Annotation of early-roguelike/urogue/options.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: options.c - This file has all the code for the option command
3:
4: UltraRogue: The Ultimate Adventure in the Dungeons of Doom
5: Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
6: All rights reserved.
7:
8: Based on "Advanced Rogue"
9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
10: All rights reserved.
11:
12: Based on "Rogue: Exploring the Dungeons of Doom"
13: Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
14: All rights reserved.
15:
16: See the file LICENSE.TXT for full copyright and licensing information.
17: */
18:
19: #include <string.h>
20: #include <ctype.h>
21: #include "rogue.h"
22:
23: #define NUM_OPTS (sizeof optlist / sizeof (OPTION))
24: #define EQSTR(a, b, c) (strncmp(a, b, c) == 0)
25:
26: int get_restr(opt_arg *opt, WINDOW *win);
27: int get_score(opt_arg *opt, WINDOW *win);
28:
29: /* description of an option and what to do with it */
30: static OPTION optlist[] =
31: {
32: {"jump","Show position only at end of run (jump): ", { &jump },
33: put_bool, get_bool},
34: {"inven","Style of inventories (inven): ", { &inv_type },
35: put_inv, get_inv},
36: {"askme","Ask me about unidentified things (askme): ", { &askme},
37: put_bool, get_bool},
38: {"doorstop","Stop running when adjacent (doorstop): ", { &doorstop },
39: put_bool, get_bool},
40: {"name", "Name (name): ", { &whoami }, put_str, get_restr},
41: {"fruit", "Fruit (fruit): ", { &fruit }, put_str, get_str},
42: {"file", "Save file (file): ", { &file_name }, put_str, get_restr},
43: {"score", "Score file (score): ", { &score_file }, put_str, get_score},
44: {"class", "Character class (class): ", { &char_type }, put_abil, get_abil}
45: };
46:
47: /*
48: option()
49: print and then set options from the terminal
50: */
51:
52: void
53: option(void)
54: {
55: OPTION *op;
56: int retval;
57:
58: wclear(hw);
59: touchwin(hw);
60:
61: /* Display current values of options */
62:
63: for (op = optlist; op < &optlist[NUM_OPTS]; op++)
64: {
65: waddstr(hw, op->o_prompt);
66: (*op->o_putfunc)(&op->o_opt, hw);
67: waddch(hw, '\n');
68: }
69:
70: /* Set values */
71:
72: wmove(hw, 0, 0);
73:
74: for (op = optlist; op < &optlist[NUM_OPTS]; op++)
75: {
76: waddstr(hw, op->o_prompt);
77:
78: retval = (*op->o_getfunc)(&op->o_opt, hw);
79:
80: if (retval)
81: if (retval == QUIT)
82: break;
83: else if (op > optlist) /* MINUS */
84: {
85: wmove(hw, (int)(op - optlist) - 1, 0);
86: op -= 2;
87: }
88: else /* trying to back up beyond the top */
89: {
90: putchar('\007');
91: wmove(hw, 0, 0);
92: op--;
93: }
94: }
95:
96: /* Switch back to original screen */
97:
98: mvwaddstr(hw, LINES - 1, 0, spacemsg);
99: wrefresh(hw);
100: wait_for(' ');
101: clearok(cw, TRUE);
102: touchwin(cw);
103: }
104:
105: /*
106: put_bool()
107: put out a boolean
108: */
109:
110: void
111: put_bool(opt_arg *opt, WINDOW *win)
112: {
113: waddstr(win, *opt->iarg ? "True" : "False");
114: }
115:
116: /*
117: put_str()
118: put out a string
119: */
120:
121: void
122: put_str(opt_arg *opt, WINDOW *win)
123: {
124: waddstr(win, opt->str);
125: }
126:
127: /*
128: put_abil()
129: print the character type
130: */
131:
132: void
133: put_abil(opt_arg *opt, WINDOW *win)
134: {
135: char *abil;
136:
137: switch(*opt->iarg)
138: {
139: case C_FIGHTER:
140: abil = "Fighter";
141: break;
142: case C_MAGICIAN:
143: abil = "Magic User";
144: break;
145: case C_CLERIC:
146: abil = "Cleric";
147: break;
148: case C_THIEF:
149: abil = "Thief";
150: break;
151: case C_PALADIN:
152: abil = "Paladin";
153: break;
154: case C_RANGER:
155: abil = "Ranger";
156: break;
157: case C_ILLUSION:
158: abil = "Illusionist";
159: break;
160: case C_ASSASIN:
161: abil = "Assasin";
162: break;
163: case C_NINJA:
164: abil = "Ninja";
165: break;
166: case C_DRUID:
167: abil = "Druid";
168: break;
169: default:
170: abil = "(unknown)";
171: }
172: waddstr(win, abil);
173: }
174:
175:
176: /*
177: get_bool()
178: allow changing a boolean option and print it out
179: */
180:
181: int
182: get_bool(opt_arg *opt, WINDOW *win)
183: {
184: int oy, ox;
185: int op_bad;
186:
187: op_bad = TRUE;
188: getyx(win, oy, ox);
189: waddstr(win, *opt->iarg ? "True" : "False");
190:
191: while(op_bad)
192: {
193: wmove(win, oy, ox);
194: wrefresh(win);
195:
196: switch (readcharw(win))
197: {
198: case 't':
199: case 'T':
200: *opt->iarg = TRUE;
201: op_bad = FALSE;
202: break;
203:
204: case 'f':
205: case 'F':
206: *opt->iarg = FALSE;
207: op_bad = FALSE;
208: break;
209:
210: case '\n':
211: case '\r':
212: op_bad = FALSE;
213: break;
214:
215: case '\033':
216: case '\007':
217: return QUIT;
218:
219: case '-':
220: return MINUS;
221:
222: default:
223: mvwaddstr(win, oy, ox + 10, "(T or F)");
224: }
225: }
226:
227: wmove(win, oy, ox);
228: wclrtoeol(win);
229: waddstr(win, *opt->iarg ? "True" : "False");
230: waddch(win, '\n');
231:
232: return(NORM);
233: }
234:
235: /*
236: get_str()
237: set a string option
238: */
239:
240: int
241: get_str(opt_arg *opt, WINDOW *win)
242: {
243: return( get_string(opt->str, win) );
244: }
245:
246: /*
247: get_abil()
248: The ability field is read-only
249: */
250:
251: int
252: get_abil(opt_arg *opt, WINDOW *win)
253: {
254: int oy, ox, ny, nx;
255: int op_bad;
256:
257: op_bad = TRUE;
258: getyx(win, oy, ox);
259: put_abil(opt, win);
260: getyx(win, ny, nx);
261:
262: while(op_bad)
263: {
264: wmove(win, oy, ox);
265: wrefresh(win);
266:
267: switch(readcharw(win))
268: {
269: case '\n':
270: case '\r':
271: op_bad = FALSE;
272: break;
273:
274: case '\033':
275: case '\007':
276: return(QUIT);
277:
278: case '-':
279: return(MINUS);
280:
281: default:
282: mvwaddstr(win, ny, nx + 5, "(no change allowed)");
283: }
284: }
285:
286: wmove(win, ny, nx + 5);
287: wclrtoeol(win);
288: wmove(win, ny, nx);
289: waddch(win, '\n');
290:
291: return(NORM);
292: }
293:
294:
295: /*
296: parse_opts()
297: parse options from string, usually taken from the environment. the
298: string is a series of comma seperated values, with booleans being
299: stated as "name" (true) or "noname" (false), and strings being
300: "name=....", with the string being defined up to a comma or the
301: end of the entire option string.
302: */
303:
304: void
305: parse_opts(char *str)
306: {
307: char *sp;
308: const OPTION *op;
309: size_t len;
310:
311: while (*str)
312: {
313: for (sp = str; isalpha(*sp); sp++)
314: continue;
315:
316: len = sp - str;
317:
318: /* Look it up and deal with it */
319:
320: for (op = optlist; op < &optlist[NUM_OPTS]; op++)
321: {
322: if (EQSTR(str, op->o_name, len))
323: {
324: if (op->o_putfunc == put_bool)
325: *op->o_opt.iarg = TRUE;
326: else /* string option */
327: {
328: char *start;
329: char value[80];
330:
331: /* Skip to start of string value */
332:
333: for (str = sp + 1; *str == '='; str++)
334: continue;
335:
336: start = (char *) value;
337:
338: /* Skip to end of string value */
339:
340: for (sp = str + 1; *sp && *sp != ','; sp++)
341: continue;
342:
343: strncpy(start, str, sp - str);
344:
345: /* Some options can't be changed. */
346: if (use_savedir &&
347: (op->o_opt.str == whoami ||
348: op->o_opt.str == file_name ||
349: op->o_opt.str == score_file))
350: break;
351:
352: /* Put the value into the option field */
353:
354: if (op->o_putfunc != put_abil &&
355: op->o_putfunc != put_inv)
356: strcpy(op->o_opt.str, value);
357:
358: if (op->o_putfunc == put_inv)
359: {
360: int *opt = op->o_opt.iarg;
361:
362: len = strlen(value);
363:
364: if (isupper(value[0]))
365: value[0] = (char) tolower(value[0]);
366: if (EQSTR(value, "overwrite",len))
367: *opt = INV_OVER;
368: if (EQSTR(value, "slow", len))
369: *opt = INV_SLOW;
370: if (EQSTR(value, "clear", len))
371: *opt = INV_CLEAR;
372: }
373: else if (*op->o_opt.iarg == -1)
374: {
375: int *opt = op->o_opt.iarg;
376:
377: len = strlen(value);
378:
379: if (isupper(value[0]))
380: value[0] = (char) tolower(value[0]);
381: if (EQSTR(value, "fighter", len))
382: *opt = C_FIGHTER;
383: else if (EQSTR(value, "magic", min(len, 5)))
384: *opt = C_MAGICIAN;
385: else if (EQSTR(value, "illus", min(len, 5)))
386: *opt = C_ILLUSION;
387: else if (EQSTR(value, "cleric", len))
388: *opt = C_CLERIC;
389: else if (EQSTR(value, "thief", len))
390: *opt = C_THIEF;
391: else if (EQSTR(value, "paladin", len))
392: *opt = C_PALADIN;
393: else if (EQSTR(value, "ranger", len))
394: *opt = C_RANGER;
395: else if (EQSTR(value, "assasin", len))
396: *opt = C_ASSASIN;
397: else if (EQSTR(value, "druid", len))
398: *opt = C_DRUID;
399: else if (EQSTR(value, "ninja", len))
400: *opt = C_NINJA;
401: }
402: }
403: break;
404: }
405: else if (op->o_putfunc == put_bool
406: && EQSTR(str, "no", 2) &&
407: EQSTR(str + 2, op->o_name, len - 2))
408: {
409: *op->o_opt.iarg = FALSE;
410: break;
411: }
412: }
413:
414: /* skip to start of next option name */
415:
416: while (*sp && !isalpha(*sp))
417: sp++;
418:
419: str = sp;
420: }
421: }
422:
423: /*
424: put_inv()
425: print the inventory type
426: */
427:
428: void
429: put_inv(opt_arg *opt, WINDOW *win)
430: {
431: char *style;
432:
433: switch(*opt->iarg)
434: {
435: case INV_OVER:
436: style = "Overwrite";
437: break;
438:
439: case INV_SLOW:
440: style = "Slow";
441: break;
442:
443: case INV_CLEAR:
444: style = "Clear Screen";
445: break;
446:
447: default:
448: style = "(unknown)";
449: }
450:
451: waddstr(win, style);
452: }
453:
454: /*
455: get_inv()
456: The inventory field.
457: */
458:
459: int
460: get_inv(opt_arg *opt, WINDOW *win)
461: {
462: int oy, ox, ny, nx;
463: int op_bad;
464:
465: op_bad = TRUE;
466: getyx(win, oy, ox);
467: put_inv(opt, win);
468: getyx(win, ny, nx);
469:
470: while(op_bad)
471: {
472: wmove(win, oy, ox);
473: wrefresh(win);
474:
475: switch(readcharw(win))
476: {
477: case '\n':
478: case '\r':
479: op_bad = FALSE;
480: break;
481:
482: case '\033':
483: case '\007':
484: return(QUIT);
485:
486: case '-':
487: return(MINUS);
488:
489: case 'O':
490: case 'o':
491: *opt->iarg = INV_OVER;
492: op_bad = FALSE;
493: break;
494:
495: case 'S':
496: case 's':
497: *opt->iarg = INV_SLOW;
498: op_bad = FALSE;
499: break;
500:
501: case 'C':
502: case 'c':
503: *opt->iarg = INV_CLEAR;
504: op_bad = FALSE;
505: break;
506:
507: default:
508: mvwaddstr(win, ny, nx + 5, "(Use: o, s, or c)");
509: }
510: }
511:
512: wmove(win, oy, ox);
513: wclrtoeol(win);
514:
515: switch(*opt->iarg)
516: {
517: case INV_SLOW:
518: waddstr(win, "Slow\n");
519: break;
520:
521: case INV_CLEAR:
522: waddstr(win, "Clear Screen\n");
523: break;
524:
525: case INV_OVER:
526: waddstr(win, "Overwrite\n");
527: break;
528:
529: default:
530: waddstr(win, "Unknown\n");
531: break;
532: }
533:
534: return(NORM);
535: }
536:
537: /*
538: * get_restr()
539: *
540: * Gets strings that cannot be changed when use_savedir is set.
541: * get_abil() can't be repurposed to do this without ugliness.
542: *
543: */
544: int
545: get_restr(opt_arg *opt, WINDOW *win)
546: {
547: int oy, ox, ny, nx;
548: int keep_up;
549:
550: keep_up = TRUE;
551: getyx(win, oy, ox);
552: put_str(opt, win);
553:
554: if (!use_savedir) {
555: wmove(win, oy, ox);
556: return get_str(opt, win);
557: }
558:
559: getyx(win, ny, nx);
560: while(keep_up)
561: {
562: wmove(win, oy, ox);
563: wrefresh(win);
564:
565: switch(readcharw(win))
566: {
567: case '\n':
568: case '\r':
569: keep_up = FALSE;
570: break;
571:
572: case '\033':
573: case '\007':
574: return(QUIT);
575:
576: case '-':
577: return(MINUS);
578:
579: default:
580: mvwaddstr(win, ny, nx + 5, "(no change allowed)");
581: }
582: }
583:
584: wmove(win, ny, nx + 5);
585: wclrtoeol(win);
586: wmove(win, ny, nx);
587: waddch(win, '\n');
588:
589: return(NORM);
590: }
591:
592: int
593: get_score(opt_arg *opt, WINDOW *win)
594: {
595: char old_score_file[2*LINELEN];
596: int status;
597:
598: if (use_savedir)
599: return get_restr(opt, win);
600:
601: strncpy(old_score_file, opt->str, 2*LINELEN);
602: old_score_file[2*LINELEN - 1] = '\0';
603: status = get_str(opt, win);
604: if (status == NORM && strcmp(old_score_file, opt->str)) {
605: fclose(fd_score);
606: fd_score = fopen(score_file, "r+");
607: if (fd_score == NULL)
608: fd_score = fopen(score_file, "a+");
609: }
610: return status;
611: }
CVSweb