comparison urogue/options.c @ 256:c495a4f288c6

Import UltraRogue from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 31 Jan 2017 19:56:04 -0500
parents
children ac42afd962e4
comparison
equal deleted inserted replaced
253:d9badb9c0179 256:c495a4f288c6
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 /* description of an option and what to do with it */
27 static OPTION optlist[] =
28 {
29 {"jump","Show position only at end of run (jump): ", &jump,put_bool,get_bool},
30 {"inven","Style of inventories (inven): ", &inv_type, put_inv, get_inv},
31 {"askme","Ask me about unidentified things (askme): ",&askme,put_bool,get_bool},
32 {"doorstop","Stop running when adjacent (doorstop): ",&doorstop,put_bool,get_bool},
33 {"name", "Name (name): ", &whoami, put_str, get_str},
34 {"fruit", "Fruit (fruit): ", &fruit, put_str, get_str},
35 {"file", "Save file (file): ", &file_name, put_str, get_str},
36 {"score", "Score file (score): ", &score_file, put_str, get_str},
37 {"class", "Character class (class): ",&char_type, put_abil, get_abil}
38 };
39
40 /*
41 option()
42 print and then set options from the terminal
43 */
44
45 void
46 option(void)
47 {
48 OPTION *op;
49 int retval;
50
51 wclear(hw);
52 touchwin(hw);
53
54 /* Display current values of options */
55
56 for (op = optlist; op < &optlist[NUM_OPTS]; op++)
57 {
58 waddstr(hw, op->o_prompt);
59 (*op->o_putfunc)(&op->o_opt, hw);
60 waddch(hw, '\n');
61 }
62
63 /* Set values */
64
65 wmove(hw, 0, 0);
66
67 for (op = optlist; op < &optlist[NUM_OPTS]; op++)
68 {
69 waddstr(hw, op->o_prompt);
70
71 retval = (*op->o_getfunc)(&op->o_opt, hw);
72
73 if (retval)
74 if (retval == QUIT)
75 break;
76 else if (op > optlist) /* MINUS */
77 {
78 wmove(hw, (int)(op - optlist) - 1, 0);
79 op -= 2;
80 }
81 else /* trying to back up beyond the top */
82 {
83 putchar('\007');
84 wmove(hw, 0, 0);
85 op--;
86 }
87 }
88
89 /* Switch back to original screen */
90
91 mvwaddstr(hw, LINES - 1, 0, spacemsg);
92 wrefresh(hw);
93 wait_for(' ');
94 clearok(cw, TRUE);
95 touchwin(cw);
96 }
97
98 /*
99 put_bool()
100 put out a boolean
101 */
102
103 void
104 put_bool(opt_arg *opt, WINDOW *win)
105 {
106 waddstr(win, *opt->iarg ? "True" : "False");
107 }
108
109 /*
110 put_str()
111 put out a string
112 */
113
114 void
115 put_str(opt_arg *opt, WINDOW *win)
116 {
117 waddstr(win, opt->str);
118 }
119
120 /*
121 put_abil()
122 print the character type
123 */
124
125 void
126 put_abil(opt_arg *opt, WINDOW *win)
127 {
128 char *abil;
129
130 switch(*opt->iarg)
131 {
132 case C_FIGHTER:
133 abil = "Fighter";
134 break;
135 case C_MAGICIAN:
136 abil = "Magic User";
137 break;
138 case C_CLERIC:
139 abil = "Cleric";
140 break;
141 case C_THIEF:
142 abil = "Thief";
143 break;
144 case C_PALADIN:
145 abil = "Paladin";
146 break;
147 case C_RANGER:
148 abil = "Ranger";
149 break;
150 case C_ILLUSION:
151 abil = "Illusionist";
152 break;
153 case C_ASSASIN:
154 abil = "Assasin";
155 break;
156 case C_NINJA:
157 abil = "Ninja";
158 break;
159 case C_DRUID:
160 abil = "Druid";
161 break;
162 default:
163 abil = "(unknown)";
164 }
165 waddstr(win, abil);
166 }
167
168
169 /*
170 get_bool()
171 allow changing a boolean option and print it out
172 */
173
174 int
175 get_bool(opt_arg *opt, WINDOW *win)
176 {
177 int oy, ox;
178 int op_bad;
179
180 op_bad = TRUE;
181 getyx(win, oy, ox);
182 waddstr(win, *opt->iarg ? "True" : "False");
183
184 while(op_bad)
185 {
186 wmove(win, oy, ox);
187 wrefresh(win);
188
189 switch (readcharw(win))
190 {
191 case 't':
192 case 'T':
193 *opt->iarg = TRUE;
194 op_bad = FALSE;
195 break;
196
197 case 'f':
198 case 'F':
199 *opt->iarg = FALSE;
200 op_bad = FALSE;
201 break;
202
203 case '\n':
204 case '\r':
205 op_bad = FALSE;
206 break;
207
208 case '\033':
209 case '\007':
210 return QUIT;
211
212 case '-':
213 return MINUS;
214
215 default:
216 mvwaddstr(win, oy, ox + 10, "(T or F)");
217 }
218 }
219
220 wmove(win, oy, ox);
221 wclrtoeol(win);
222 waddstr(win, *opt->iarg ? "True" : "False");
223 waddch(win, '\n');
224
225 return(NORM);
226 }
227
228 /*
229 get_str()
230 set a string option
231 */
232
233 int
234 get_str(opt_arg *opt, WINDOW *win)
235 {
236 return( get_string(opt->str, win) );
237 }
238
239 /*
240 get_abil()
241 The ability field is read-only
242 */
243
244 int
245 get_abil(opt_arg *opt, WINDOW *win)
246 {
247 int oy, ox, ny, nx;
248 int op_bad;
249
250 op_bad = TRUE;
251 getyx(win, oy, ox);
252 put_abil(opt, win);
253 getyx(win, ny, nx);
254
255 while(op_bad)
256 {
257 wmove(win, oy, ox);
258 wrefresh(win);
259
260 switch(readcharw(win))
261 {
262 case '\n':
263 case '\r':
264 op_bad = FALSE;
265 break;
266
267 case '\033':
268 case '\007':
269 return(QUIT);
270
271 case '-':
272 return(MINUS);
273
274 default:
275 mvwaddstr(win, ny, nx + 5, "(no change allowed)");
276 }
277 }
278
279 wmove(win, ny, nx + 5);
280 wclrtoeol(win);
281 wmove(win, ny, nx);
282 waddch(win, '\n');
283
284 return(NORM);
285 }
286
287
288 /*
289 parse_opts()
290 parse options from string, usually taken from the environment. the
291 string is a series of comma seperated values, with booleans being
292 stated as "name" (true) or "noname" (false), and strings being
293 "name=....", with the string being defined up to a comma or the
294 end of the entire option string.
295 */
296
297 void
298 parse_opts(char *str)
299 {
300 char *sp;
301 const OPTION *op;
302 size_t len;
303
304 while (*str)
305 {
306 for (sp = str; isalpha(*sp); sp++)
307 continue;
308
309 len = sp - str;
310
311 /* Look it up and deal with it */
312
313 for (op = optlist; op < &optlist[NUM_OPTS]; op++)
314 if (EQSTR(str, op->o_name, len))
315 {
316 if (op->o_putfunc == put_bool)
317 *op->o_opt.iarg = TRUE;
318 else /* string option */
319 {
320 char *start;
321 char value[80];
322
323 /* Skip to start of string value */
324
325 for (str = sp + 1; *str == '='; str++)
326 continue;
327
328 start = (char *) value;
329
330 /* Skip to end of string value */
331
332 for (sp = str + 1; *sp && *sp != ','; sp++)
333 continue;
334
335 strncpy(start, str, sp - str);
336
337 /* Put the value into the option field */
338
339 if (op->o_putfunc != put_abil &&
340 op->o_putfunc != put_inv)
341 strcpy(op->o_opt.str, value);
342
343 if (op->o_putfunc == put_inv)
344 {
345 int *opt = op->o_opt.iarg;
346
347 len = strlen(value);
348
349 if (isupper(value[0]))
350 value[0] = (char) tolower(value[0]);
351 if (EQSTR(value, "overwrite",len))
352 *opt = INV_OVER;
353 if (EQSTR(value, "slow", len))
354 *opt = INV_SLOW;
355 if (EQSTR(value, "clear", len))
356 *opt = INV_CLEAR;
357 }
358 else if (*op->o_opt.iarg == -1)
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, "fighter", len))
367 *opt = C_FIGHTER;
368 else if (EQSTR(value, "magic", min(len, 5)))
369 *opt = C_MAGICIAN;
370 else if (EQSTR(value, "illus", min(len, 5)))
371 *opt = C_ILLUSION;
372 else if (EQSTR(value, "cleric", len))
373 *opt = C_CLERIC;
374 else if (EQSTR(value, "thief", len))
375 *opt = C_THIEF;
376 else if (EQSTR(value, "paladin", len))
377 *opt = C_PALADIN;
378 else if (EQSTR(value, "ranger", len))
379 *opt = C_RANGER;
380 else if (EQSTR(value, "assasin", len))
381 *opt = C_ASSASIN;
382 else if (EQSTR(value, "druid", len))
383 *opt = C_DRUID;
384 else if (EQSTR(value, "ninja", len))
385 *opt = C_NINJA;
386 }
387 }
388 break;
389 }
390 else if (op->o_putfunc == put_bool
391 && EQSTR(str, "no", 2) &&
392 EQSTR(str + 2, op->o_name, len - 2))
393 {
394 *op->o_opt.iarg = FALSE;
395 break;
396 }
397
398 /* skip to start of next option name */
399
400 while (*sp && !isalpha(*sp))
401 sp++;
402
403 str = sp;
404 }
405 }
406
407 /*
408 put_inv()
409 print the inventory type
410 */
411
412 void
413 put_inv(opt_arg *opt, WINDOW *win)
414 {
415 char *style;
416
417 switch(*opt->iarg)
418 {
419 case INV_OVER:
420 style = "Overwrite";
421 break;
422
423 case INV_SLOW:
424 style = "Slow";
425 break;
426
427 case INV_CLEAR:
428 style = "Clear Screen";
429 break;
430
431 default:
432 style = "(unknown)";
433 }
434
435 waddstr(win, style);
436 }
437
438 /*
439 get_inv()
440 The inventory field.
441 */
442
443 int
444 get_inv(opt_arg *opt, WINDOW *win)
445 {
446 int oy, ox, ny, nx;
447 int op_bad;
448
449 op_bad = TRUE;
450 getyx(win, oy, ox);
451 put_inv(opt, win);
452 getyx(win, ny, nx);
453
454 while(op_bad)
455 {
456 wmove(win, oy, ox);
457 wrefresh(win);
458
459 switch(readcharw(win))
460 {
461 case '\n':
462 case '\r':
463 op_bad = FALSE;
464 break;
465
466 case '\033':
467 case '\007':
468 return(QUIT);
469
470 case '-':
471 return(MINUS);
472
473 case 'O':
474 case 'o':
475 *opt->iarg = INV_OVER;
476 op_bad = FALSE;
477 break;
478
479 case 'S':
480 case 's':
481 *opt->iarg = INV_SLOW;
482 op_bad = FALSE;
483 break;
484
485 case 'C':
486 case 'c':
487 *opt->iarg = INV_CLEAR;
488 op_bad = FALSE;
489 break;
490
491 default:
492 mvwaddstr(win, ny, nx + 5, "(Use: o, s, or c)");
493 }
494 }
495
496 wmove(win, oy, ox);
497 wclrtoeol(win);
498
499 switch(*opt->iarg)
500 {
501 case INV_SLOW:
502 waddstr(win, "Slow\n");
503 break;
504
505 case INV_CLEAR:
506 waddstr(win, "Clear Screen\n");
507 break;
508
509 case INV_OVER:
510 waddstr(win, "Overwrite\n");
511 break;
512
513 default:
514 waddstr(win, "Unknown\n");
515 break;
516 }
517
518 return(NORM);
519 }