Mercurial > hg > early-roguelike
comparison arogue7/options.c @ 125:adfa37e67084
Import Advanced Rogue 7.7 from the Roguelike Restoration Project (r1490)
| author | John "Elwin" Edwards |
|---|---|
| date | Fri, 08 May 2015 15:24:40 -0400 |
| parents | |
| children | b786053d2f37 |
comparison
equal
deleted
inserted
replaced
| 124:d10fc4a065ac | 125:adfa37e67084 |
|---|---|
| 1 /* | |
| 2 * options.c - This file has all the code for the option command | |
| 3 * | |
| 4 * Advanced Rogue | |
| 5 * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T | |
| 6 * All rights reserved. | |
| 7 * | |
| 8 * Based on "Rogue: Exploring the Dungeons of Doom" | |
| 9 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
| 10 * All rights reserved. | |
| 11 * | |
| 12 * See the file LICENSE.TXT for full copyright and licensing information. | |
| 13 */ | |
| 14 | |
| 15 /* | |
| 16 * This file has all the code for the option command. | |
| 17 * I would rather this command were not necessary, but | |
| 18 * it is the only way to keep the wolves off of my back. | |
| 19 * | |
| 20 */ | |
| 21 | |
| 22 #include "curses.h" | |
| 23 #include <ctype.h> | |
| 24 #include "rogue.h" | |
| 25 | |
| 26 #define NUM_OPTS (sizeof optlist / sizeof (OPTION)) | |
| 27 | |
| 28 | |
| 29 /* | |
| 30 * description of an option and what to do with it | |
| 31 */ | |
| 32 struct optstruct { | |
| 33 char *o_name; /* option name */ | |
| 34 char *o_prompt; /* prompt for interactive entry */ | |
| 35 int *o_opt; /* pointer to thing to set */ | |
| 36 int (*o_putfunc)(); /* function to print value */ | |
| 37 int (*o_getfunc)(); /* function to get value interactively */ | |
| 38 }; | |
| 39 | |
| 40 typedef struct optstruct OPTION; | |
| 41 | |
| 42 int put_bool(), | |
| 43 get_bool(), | |
| 44 put_str(), | |
| 45 get_str(), | |
| 46 put_abil(), | |
| 47 get_abil(), | |
| 48 get_quest(), | |
| 49 put_quest(); | |
| 50 | |
| 51 OPTION optlist[] = { | |
| 52 {"terse", "Terse output: ", | |
| 53 (int *) &terse, put_bool, get_bool }, | |
| 54 {"flush", "Flush typeahead during battle: ", | |
| 55 (int *) &fight_flush, put_bool, get_bool }, | |
| 56 {"jump", "Show position only at end of run: ", | |
| 57 (int *) &jump, put_bool, get_bool }, | |
| 58 {"step", "Do inventories one line at a time: ", | |
| 59 (int *) &slow_invent, put_bool, get_bool }, | |
| 60 {"askme", "Ask me about unidentified things: ", | |
| 61 (int *) &askme, put_bool, get_bool }, | |
| 62 {"pickup", "Pick things up automatically: ", | |
| 63 (int *) &auto_pickup, put_bool, get_bool }, | |
| 64 {"overlay", "Overlay menu: ", | |
| 65 (int *) &menu_overlay, put_bool, get_bool }, | |
| 66 {"name", "Name: ", | |
| 67 (int *) whoami, put_str, get_str }, | |
| 68 {"file", "Save file: ", | |
| 69 (int *) file_name, put_str, get_str }, | |
| 70 {"score", "Score file: ", | |
| 71 (int *) score_file, put_str, get_str }, | |
| 72 {"class", "Character class: ", | |
| 73 (int *)&char_type, put_abil, get_abil }, | |
| 74 {"quest", "Quest item: ", | |
| 75 (int *) &quest_item, put_quest, get_quest } | |
| 76 }; | |
| 77 | |
| 78 /* | |
| 79 * The ability field is read-only | |
| 80 */ | |
| 81 get_abil(abil, win) | |
| 82 int *abil; | |
| 83 WINDOW *win; | |
| 84 { | |
| 85 register int oy, ox; | |
| 86 | |
| 87 getyx(win, oy, ox); | |
| 88 put_abil(abil, win); | |
| 89 get_ro(win, oy, ox); | |
| 90 } | |
| 91 | |
| 92 /* | |
| 93 * The quest field is read-only | |
| 94 */ | |
| 95 get_quest(quest, win) | |
| 96 int *quest; | |
| 97 WINDOW *win; | |
| 98 { | |
| 99 register int oy, ox; | |
| 100 | |
| 101 getyx(win, oy, ox); | |
| 102 waddstr(win, rel_magic[*quest].mi_name); | |
| 103 get_ro(win, oy, ox); | |
| 104 } | |
| 105 | |
| 106 /* | |
| 107 * get_ro: | |
| 108 * "Get" a read-only value. | |
| 109 */ | |
| 110 | |
| 111 get_ro(win, oy, ox) | |
| 112 WINDOW *win; | |
| 113 register int oy, ox; | |
| 114 { | |
| 115 register int ny, nx; | |
| 116 register bool op_bad; | |
| 117 | |
| 118 op_bad = TRUE; | |
| 119 getyx(win, ny, nx); | |
| 120 while(op_bad) | |
| 121 { | |
| 122 wmove(win, oy, ox); | |
| 123 draw(win); | |
| 124 switch (wgetch(win)) | |
| 125 { | |
| 126 case '\n': | |
| 127 case '\r': | |
| 128 op_bad = FALSE; | |
| 129 break; | |
| 130 case '\033': | |
| 131 case '\007': | |
| 132 return QUIT; | |
| 133 case '-': | |
| 134 return MINUS; | |
| 135 default: | |
| 136 mvwaddstr(win, ny, nx + 5, "(no change allowed)"); | |
| 137 } | |
| 138 } | |
| 139 wmove(win, ny, nx + 5); | |
| 140 wclrtoeol(win); | |
| 141 wmove(win, ny, nx); | |
| 142 waddch(win, '\n'); | |
| 143 return NORM; | |
| 144 } | |
| 145 | |
| 146 /* | |
| 147 * allow changing a boolean option and print it out | |
| 148 */ | |
| 149 | |
| 150 get_bool(bp, win) | |
| 151 bool *bp; | |
| 152 WINDOW *win; | |
| 153 { | |
| 154 register int oy, ox; | |
| 155 register bool op_bad; | |
| 156 | |
| 157 op_bad = TRUE; | |
| 158 getyx(win, oy, ox); | |
| 159 waddstr(win, *bp ? "True" : "False"); | |
| 160 while(op_bad) | |
| 161 { | |
| 162 wmove(win, oy, ox); | |
| 163 draw(win); | |
| 164 switch (wgetch(win)) | |
| 165 { | |
| 166 case 't': | |
| 167 case 'T': | |
| 168 *bp = TRUE; | |
| 169 op_bad = FALSE; | |
| 170 break; | |
| 171 case 'f': | |
| 172 case 'F': | |
| 173 *bp = FALSE; | |
| 174 op_bad = FALSE; | |
| 175 break; | |
| 176 case '\n': | |
| 177 case '\r': | |
| 178 op_bad = FALSE; | |
| 179 break; | |
| 180 case '\033': | |
| 181 case '\007': | |
| 182 return QUIT; | |
| 183 case '-': | |
| 184 return MINUS; | |
| 185 default: | |
| 186 mvwaddstr(win, oy, ox + 10, "(T or F)"); | |
| 187 } | |
| 188 } | |
| 189 wmove(win, oy, ox); | |
| 190 wclrtoeol(win); | |
| 191 waddstr(win, *bp ? "True" : "False"); | |
| 192 waddch(win, '\n'); | |
| 193 return NORM; | |
| 194 } | |
| 195 | |
| 196 | |
| 197 /* | |
| 198 * set a string option | |
| 199 */ | |
| 200 get_str(opt, win) | |
| 201 register char *opt; | |
| 202 WINDOW *win; | |
| 203 { | |
| 204 register char *sp; | |
| 205 register int c, oy, ox; | |
| 206 char buf[LINELEN]; | |
| 207 | |
| 208 draw(win); | |
| 209 getyx(win, oy, ox); | |
| 210 /* | |
| 211 * loop reading in the string, and put it in a temporary buffer | |
| 212 */ | |
| 213 for (sp = buf; | |
| 214 (c = wgetch(win)) != '\n' && | |
| 215 c != '\r' && | |
| 216 c != '\033' && | |
| 217 c != '\007' && | |
| 218 sp < &buf[LINELEN-1]; | |
| 219 wclrtoeol(win), draw(win)) | |
| 220 { | |
| 221 if (c == -1) | |
| 222 continue; | |
| 223 else if (c == md_erasechar()) /* process erase character */ | |
| 224 { | |
| 225 if (sp > buf) | |
| 226 { | |
| 227 register int i; | |
| 228 | |
| 229 sp--; | |
| 230 for (i = strlen(unctrl(*sp)); i; i--) | |
| 231 waddch(win, '\b'); | |
| 232 } | |
| 233 continue; | |
| 234 } | |
| 235 else if (c == md_killchar()) /* process kill character */ | |
| 236 { | |
| 237 sp = buf; | |
| 238 wmove(win, oy, ox); | |
| 239 continue; | |
| 240 } | |
| 241 else if (sp == buf) | |
| 242 if (c == '-' && win == hw) /* To move back a line in hw */ | |
| 243 break; | |
| 244 else if (c == '~') | |
| 245 { | |
| 246 strcpy(buf, home); | |
| 247 waddstr(win, home); | |
| 248 sp += strlen(home); | |
| 249 continue; | |
| 250 } | |
| 251 *sp++ = c; | |
| 252 waddstr(win, unctrl(c)); | |
| 253 } | |
| 254 *sp = '\0'; | |
| 255 if (sp > buf) /* only change option if something has been typed */ | |
| 256 strucpy(opt, buf, strlen(buf)); | |
| 257 wmove(win, oy, ox); | |
| 258 waddstr(win, opt); | |
| 259 waddch(win, '\n'); | |
| 260 draw(win); | |
| 261 if (win == msgw) | |
| 262 mpos += (int)(sp - buf); | |
| 263 if (c == '-') | |
| 264 return MINUS; | |
| 265 else if (c == '\033' || c == '\007') | |
| 266 return QUIT; | |
| 267 else | |
| 268 return NORM; | |
| 269 } | |
| 270 | |
| 271 | |
| 272 | |
| 273 /* | |
| 274 * print and then set options from the terminal | |
| 275 */ | |
| 276 option() | |
| 277 { | |
| 278 register OPTION *op; | |
| 279 register int retval; | |
| 280 | |
| 281 wclear(hw); | |
| 282 touchwin(hw); | |
| 283 /* | |
| 284 * Display current values of options | |
| 285 */ | |
| 286 for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++) | |
| 287 { | |
| 288 waddstr(hw, op->o_prompt); | |
| 289 (*op->o_putfunc)(op->o_opt, hw); | |
| 290 waddch(hw, '\n'); | |
| 291 } | |
| 292 /* | |
| 293 * Set values | |
| 294 */ | |
| 295 wmove(hw, 0, 0); | |
| 296 for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++) | |
| 297 { | |
| 298 waddstr(hw, op->o_prompt); | |
| 299 if ((retval = (*op->o_getfunc)(op->o_opt, hw))) | |
| 300 if (retval == QUIT) | |
| 301 break; | |
| 302 else if (op > optlist) { /* MINUS */ | |
| 303 wmove(hw, (int)(op - optlist) - 1, 0); | |
| 304 op -= 2; | |
| 305 } | |
| 306 else /* trying to back up beyond the top */ | |
| 307 { | |
| 308 putchar('\007'); | |
| 309 wmove(hw, 0, 0); | |
| 310 op--; | |
| 311 } | |
| 312 } | |
| 313 /* | |
| 314 * Switch back to original screen | |
| 315 */ | |
| 316 mvwaddstr(hw, lines-1, 0, spacemsg); | |
| 317 draw(hw); | |
| 318 wait_for(' '); | |
| 319 clearok(cw, TRUE); | |
| 320 touchwin(cw); | |
| 321 after = FALSE; | |
| 322 } | |
| 323 | |
| 324 /* | |
| 325 * parse options from string, usually taken from the environment. | |
| 326 * the string is a series of comma seperated values, with booleans | |
| 327 * being stated as "name" (true) or "noname" (false), and strings | |
| 328 * being "name=....", with the string being defined up to a comma | |
| 329 * or the end of the entire option string. | |
| 330 */ | |
| 331 | |
| 332 parse_opts(str) | |
| 333 register char *str; | |
| 334 { | |
| 335 register char *sp; | |
| 336 register OPTION *op; | |
| 337 register int len; | |
| 338 | |
| 339 while (*str) | |
| 340 { | |
| 341 /* | |
| 342 * Get option name | |
| 343 */ | |
| 344 for (sp = str; isalpha(*sp); sp++) | |
| 345 continue; | |
| 346 len = (int)(sp - str); | |
| 347 /* | |
| 348 * Look it up and deal with it | |
| 349 */ | |
| 350 for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++) | |
| 351 if (EQSTR(str, op->o_name, len)) | |
| 352 { | |
| 353 if (op->o_putfunc == put_bool) /* if option is a boolean */ | |
| 354 *(bool *)op->o_opt = TRUE; | |
| 355 else /* string option */ | |
| 356 { | |
| 357 register char *start; | |
| 358 char value[LINELEN]; | |
| 359 | |
| 360 /* | |
| 361 * Skip to start of string value | |
| 362 */ | |
| 363 for (str = sp + 1; *str == '='; str++) | |
| 364 continue; | |
| 365 if (*str == '~') | |
| 366 { | |
| 367 strcpy((char *) value, home); | |
| 368 start = (char *) value + strlen(home); | |
| 369 while (*++str == '/') | |
| 370 continue; | |
| 371 } | |
| 372 else | |
| 373 start = (char *) value; | |
| 374 /* | |
| 375 * Skip to end of string value | |
| 376 */ | |
| 377 for (sp = str + 1; *sp && *sp != ','; sp++) | |
| 378 continue; | |
| 379 strucpy(start, str, sp - str); | |
| 380 | |
| 381 /* Put the value into the option field */ | |
| 382 if (op->o_putfunc != put_abil) | |
| 383 strcpy((char *)op->o_opt, (char *)value); | |
| 384 | |
| 385 else if (*op->o_opt == -1) { /* Only init ability once */ | |
