+static char keyTable[KT_numKeys+1];
+
+static char *hostStr;
+static int paused = 0;
+
+static sigjmp_buf close_env;
+
+
+ExtFunc void MapKeys(char *newKeys)
+{
+ int i, k, ch;
+ char used[256];
+ int errs = 0;
+
+ /* XXX assumptions about ASCII encoding here */
+ for (i = k = 0; newKeys[i] && k < KT_numKeys; i++,k++) {
+ if (newKeys[i] == '^' && newKeys[i+1])
+ keyTable[k] = toupper(newKeys[++i]) - ('A' - 1);
+ else
+ keyTable[k] = newKeys[i];
+ }
+ memset(used, 0, sizeof(used));
+ for (k = 0; k < KT_numKeys; k++) {
+ ch = (unsigned char) keyTable[k];
+ if (used[ch]) {
+ if (iscntrl(ch) && ch < ' ')
+ sprintf(scratch, "Ctrl-%c", ch + ('A' - 1));
+ else if (isprint(ch))
+ sprintf(scratch, "\"%c\"", ch);
+ else
+ sprintf(scratch, "0x%X", ch);
+ if (!errs)
+ fprintf(stderr, "Duplicate key mappings:\n");
+ errs++;
+ fprintf(stderr, " %s mapped to both %s and %s\n",
+ scratch, keyNames[used[ch]-1], keyNames[k]);
+ }
+ used[ch] = k + 1;
+ }
+ if (errs)
+ exit(1);
+} //MapKeys
+
+ExtFunc void WriteConf(void)
+{
+ FILE *file_out;
+
+ file_out = fopen(CONFIG_FILE, "w");
+ if (file_out == NULL)
+ die("Error writing config file");
+
+ fprintf(file_out, "### NETRIS %s Config file ###\n\n", version_string);
+
+ fclose(file_out);
+ fprintf(stderr, "Wrote new game configuration to %s\n", CONFIG_FILE);
+} //WriteConf
+
+ExtFunc void HandleOption(char tag, char *value)
+{
+ switch (tag) {
+ case 'a': //ascii
+ if (value && !strcasecmp(value, "0")) Game.ascii = 0;
+ else Game.ascii = 1;
+ break;
+ case 'c': //connect
+ initConn = 1;
+ hostStr = value;
+ break;
+ case 'p': //port
+ port = atoi(value);
+ break;
+ case 'i': //speed (of level 1)
+ Game.initspeed = atof(value) * 1e6;
+ break;
+ case 'l': //level
+ if ((Players[0].score.level = atof(value)) < 1)
+ Players[0].score.level = 1;
+ if (Players[0].score.level > 15)
+ Players[0].score.level = 15;
+ break;
+ case 't': //team
+ Players[0].team = atoi(value);
+ break;
+ case 1: //spy
+ {
+ int i;
+ i = atof(value);
+ Players[i / 10].spy = i % 10;
+ }
+ break;
+ case 'r': //robot
+ robotEnable = 1;
+ Players[0].flags |= SCF_usingRobot;
+ InitRobot(value);
+ break;
+ case 'F': //fair robot
+ fairRobot = 1;
+ Players[0].flags |= SCF_fairRobot;
+ break;
+ case 'd': //drop mode
+ if (value && !strcasecmp(value, "0")) Players[0].dropmode &= 254;
+ else Players[0].dropmode |= 1;
+ break;
+ case 'D': //instadrop
+ if (value && !strcasecmp(value, "0")) Players[0].dropmode &= 253;
+ else Players[0].dropmode |= 2;
+ break;
+ case 'C': //color
+ if (value && !strcasecmp(value, "1")) Game.color = 1;
+ else Game.color = 0;
+ break;
+ case 'S': //slowterm
+ if (value && !strcasecmp(value, "1")) Game.standout = 1;
+ else Game.standout = 0;
+ break;
+ case 'k': //keys
+ MapKeys(value); break;
+ case 'H': //info
+ DistInfo(); exit(0);
+ case 'R': //rules
+ Rules(); exit(0);
+ case 'h': //help
+ Usage(); exit(0);
+ default:
+ Usage(); exit(1);
+ }
+} //HandleParam
+
+ExtFunc void ReadConf(char *filename)
+{
+ FILE *file_in;
+ char buf[513];
+ int i;
+ char *ch;
+ char tag[81], value[81];
+
+ file_in = fopen(filename, "r");
+ if (file_in) {
+ while (fgets(buf, 512, file_in) != NULL) {
+ if ((ch = strchr(buf, '#')))
+ *ch = '\0'; // truncate string from # char
+ for (i = strlen(buf)-1; i >= 0; i--)
+ if (buf[i] == ' ' || buf[i] == '\n' || buf[i] == '\t' || buf[i] == 13)
+ buf[i] = '\0';
+ else break;
+
+ sscanf(buf, "%80[^= \t] = %80[^\n]", tag, value);
+ for (i = 0; options[i].name; i++){
+ if (!strcasecmp(options[i].name, tag)) {
+ HandleOption(options[i].val, value);
+ break;
+ }
+ }
+ }
+ fclose(file_in);
+ } //read file
+ else {
+ fprintf(stderr, "Unable to open config file %s.\n", filename);
+ } //defaults
+
+} //ReadConf