root/trunk/src/cmd0.c

Revision 930, 14.4 kB (checked in by takkaria, 4 months ago)

Clear up yet more warnings and whitespace issues.

  • Property svn:eol-style set to native
Line 
1 /*
2  * File: cmd0.c
3  * Purpose: Deal with command processing.
4  *
5  * Copyright (c) 2007 Andrew Sidwell, Ben Harrison
6  *
7  * This work is free software; you can redistribute it and/or modify it
8  * under the terms of either:
9  *
10  * a) the GNU General Public License as published by the Free Software
11  *    Foundation, version 2, or
12  *
13  * b) the "Angband licence":
14  *    This software may be copied and distributed for educational, research,
15  *    and not for profit purposes provided that this copyright and statement
16  *    are included in all such copies.  Other copyrights may also apply.
17  */
18 #include "angband.h"
19 #include "wizard.h"
20 #include "cmds.h"
21 #include "ui-menu.h"
22
23
24 /*
25  * This file contains (several) big lists of commands, so that they can be
26  * easily maniuplated for e.g. help displays, or if a port wants to provide a
27  * native menu containing a command list.
28  *
29  * Consider a two-paned layout for the command menus. XXX
30  *
31  * This file still needs some clearing up. XXX
32  */
33
34 /*** Big list of commands ***/
35
36 /* Useful typedef */
37 typedef void do_cmd_type(void);
38
39
40 /* Forward declare these, because they're really defined later */
41 static do_cmd_type do_cmd_wizard, do_cmd_try_debug,
42             do_cmd_quit, do_cmd_mouseclick, do_cmd_port,
43             do_cmd_xxx_options, do_cmd_menu, do_cmd_monlist;
44
45 #ifdef ALLOW_BORG
46 static do_cmd_type do_cmd_try_borg;
47 #endif
48
49 /*
50  * Holds a generic command.
51  */
52 typedef struct
53 {
54         const char *desc;
55         unsigned char key;
56         do_cmd_type *hook;
57 } command_type;
58
59
60 /* Magic use */
61 static command_type cmd_magic[] =
62 {
63         { "Gain new spells or prayers", 'G', do_cmd_study },
64         { "Browse a book",              'b', do_cmd_browse },
65         { "Cast a spell",               'm', do_cmd_cast },
66         { "Pray a prayer",              'p', do_cmd_pray }
67 };
68
69 /* General actions */
70 static command_type cmd_action[] =
71 {
72         { "Search for traps/doors",     's', do_cmd_search },
73         { "Disarm a trap or chest",     'D', do_cmd_disarm },
74         { "Rest for a while",           'R', do_cmd_rest },
75         { "Look around",                'l', do_cmd_look },
76         { "Target monster or location", '*', do_cmd_target },
77         { "Dig a tunnel",               'T', do_cmd_tunnel },
78         { "Go up staircase",            '<', do_cmd_go_up },
79         { "Go down staircase",          '>', do_cmd_go_down },
80         { "Toggle search mode",         'S', do_cmd_toggle_search },
81         { "Open a door or a chest",     'o', do_cmd_open },
82         { "Close a door",               'c', do_cmd_close },
83         { "Jam a door shut",            'j', do_cmd_spike },
84         { "Bash a door open",           'B', do_cmd_bash }
85 };
86
87 /* Item use commands */
88 static command_type cmd_item_use[] =
89 {
90         { "Read a scroll",            'r', do_cmd_read_scroll },
91         { "Quaff a potion",           'q', do_cmd_quaff_potion },
92         { "Use a staff",              'u', do_cmd_use_staff },
93         { "Aim a wand",               'a', do_cmd_aim_wand },
94         { "Zap a rod",                'z', do_cmd_zap_rod },
95         { "Activate an object",       'A', do_cmd_activate },
96         { "Eat some food",            'E', do_cmd_eat_food },
97         { "Fuel your light source",   'F', do_cmd_refill },
98         { "Fire your missile weapon", 'f', do_cmd_fire },
99         { "Throw an item",            'v', do_cmd_throw }
100 };
101
102 /* Item management commands */
103 static command_type cmd_item_manage[]  =
104 {
105         { "Display equipment listing", 'e', do_cmd_equip },
106         { "Display inventory listing", 'i', do_cmd_inven },
107         { "Pick up objects",           'g', do_cmd_pickup },
108         { "Wear/wield an item",        'w', do_cmd_wield },
109         { "Take/unwield off an item"'t', do_cmd_takeoff },
110         { "Drop an item",              'd', do_cmd_drop },
111         { "Destroy an item",           'k', do_cmd_destroy },
112         { "Mark an item as squelch",   'K', do_cmd_mark_squelch },
113         { "Examine an item",           'I', do_cmd_observe },
114         { "Inscribe an object",        '{', do_cmd_inscribe },
115         { "Uninscribe an object",      '}', do_cmd_uninscribe }
116 };
117
118 /* Information access commands */
119 static command_type cmd_info[] =
120 {
121         { "Full dungeon map",             'M', do_cmd_view_map },
122         { "Display visible monster list", '[', do_cmd_monlist },
123         { "Locate player on map",         'L', do_cmd_locate },
124         { "Help",                         '?', do_cmd_help },
125         { "Identify symbol",              '/', do_cmd_query_symbol },
126         { "Character description",        'C', do_cmd_change_name },
127         { "Check knowledge",              '~', do_cmd_knowledge },
128         { "Repeat level feeling",   KTRL('F'), do_cmd_feeling },
129         { "Show previous message",  KTRL('O'), do_cmd_message_one },
130         { "Show previous messages", KTRL('P'), do_cmd_messages }
131 };
132
133 /* Utility/assorted commands */
134 static command_type cmd_util[] =
135 {
136         { "Interact with options",        '=', do_cmd_xxx_options },
137         { "Port-specific preferences",    '!', do_cmd_port },
138
139         { "Save and don't quit",  KTRL('S'), do_cmd_save_game },
140         { "Save and quit",        KTRL('X'), do_cmd_quit },
141         { "Quit (commit suicide)",      'Q', do_cmd_suicide },
142         { "Redraw the screen",    KTRL('R'), do_cmd_redraw },
143
144         { "Load \"screen dump\"",       '(', do_cmd_load_screen },
145         { "Save \"screen dump\"",       ')', do_cmd_save_screen }
146 };
147
148 /* Commands that shouldn't be shown to the user */ 
149 static command_type cmd_hidden[] =
150 {
151         { "Take notes",               ':', do_cmd_note },
152         { "Version info",             'V', do_cmd_version },
153         { "Load a single pref line"'"', do_cmd_pref },
154         { "Mouse click",           '\xff', do_cmd_mouseclick },
155         { "Enter a store",            '_', do_cmd_store },
156         { "Toggle windows",     KTRL('E'), toggle_inven_equip }, /* XXX */
157         { "Alter a grid",             '+', do_cmd_alter },
158         { "Walk",                     ';', do_cmd_walk },
159         { "Jump into a trap",         '-', do_cmd_jump },
160         { "Start running",            '.', do_cmd_run },
161         { "Stand still",              ',', do_cmd_hold },
162         { "Check knowledge",          '|', do_cmd_knowledge },
163         { "Display menu of actions", '\n', do_cmd_menu },
164         { "Display menu of actions", '\r', do_cmd_menu },
165
166         { "Toggle wizard mode",  KTRL('W'), do_cmd_wizard },
167
168 #ifdef ALLOW_DEBUG
169         { "Debug mode commands", KTRL('A'), do_cmd_try_debug },
170 #endif
171 #ifdef ALLOW_BORG
172         { "Borg commands",       KTRL('Z'), do_cmd_try_borg }
173 #endif
174 };
175
176
177
178 /*
179  * A categorised list of all the command lists.
180  */
181 typedef struct
182 {
183         const char *name;
184         command_type *list;
185         size_t len;
186 } command_list;
187
188 static command_list cmds_all[] =
189 {
190         { "Use magic/Pray",  cmd_magic,       N_ELEMENTS(cmd_magic) },
191         { "Action commands", cmd_action,      N_ELEMENTS(cmd_action) },
192         { "Use item",        cmd_item_use,    N_ELEMENTS(cmd_item_use) },
193         { "Manage items",    cmd_item_manage, N_ELEMENTS(cmd_item_manage) },
194         { "Information",     cmd_info,        N_ELEMENTS(cmd_info) },
195         { "Utility",         cmd_util,        N_ELEMENTS(cmd_util) },
196         { "Hidden",          cmd_hidden,      N_ELEMENTS(cmd_hidden) }
197 };
198
199
200
201
202
203 /*
204  * Toggle wizard mode
205  */
206 static void do_cmd_wizard(void)
207 {
208         /* Verify first time */
209         if (!(p_ptr->noscore & NOSCORE_WIZARD))
210         {
211                 /* Mention effects */
212                 msg_print("You are about to enter 'wizard' mode for the very first time!");
213                 msg_print("This is a form of cheating, and your game will not be scored!");
214                 message_flush();
215
216                 /* Verify request */
217                 if (!get_check("Are you sure you want to enter wizard mode? "))
218                         return;
219
220                 /* Mark savefile */
221                 p_ptr->noscore |= NOSCORE_WIZARD;
222         }
223
224         /* Toggle mode */
225         if (p_ptr->wizard)
226         {
227                 p_ptr->wizard = FALSE;
228                 msg_print("Wizard mode off.");
229         }
230         else
231         {
232                 p_ptr->wizard = TRUE;
233                 msg_print("Wizard mode on.");
234         }
235
236         /* Update monsters */
237         p_ptr->update |= (PU_MONSTERS);
238
239         /* Redraw "title" */
240         p_ptr->redraw |= (PR_TITLE);
241 }
242
243
244
245
246 #ifdef ALLOW_DEBUG
247
248 /*
249  * Verify use of "debug" mode
250  */
251 static void do_cmd_try_debug(void)
252 {
253         /* Ask first time */
254         if (!(p_ptr->noscore & NOSCORE_DEBUG))
255         {
256                 /* Mention effects */
257                 msg_print("You are about to use the dangerous, unsupported, debug commands!");
258                 msg_print("Your machine may crash, and your savefile may become corrupted!");
259                 message_flush();
260
261                 /* Verify request */
262                 if (!get_check("Are you sure you want to use the debug commands? "))
263                         return;
264
265                 /* Mark savefile */
266                 p_ptr->noscore |= NOSCORE_DEBUG;
267         }
268
269         /* Okay */
270         do_cmd_debug();
271 }
272
273 #endif /* ALLOW_DEBUG */
274
275
276
277 #ifdef ALLOW_BORG
278
279 /*
280  * Verify use of "borg" mode
281  */
282 static bool do_cmd_try_borg(void)
283 {
284         /* Ask first time */
285         if (!(p_ptr->noscore & NOSCORE_BORG))
286         {
287                 /* Mention effects */
288                 msg_print("You are about to use the dangerous, unsupported, borg commands!");
289                 msg_print("Your machine may crash, and your savefile may become corrupted!");
290                 message_flush();
291
292                 /* Verify request */
293                 if (!get_check("Are you sure you want to use the borg commands? "))
294                         return;
295
296                 /* Mark savefile */
297                 p_ptr->noscore |= NOSCORE_BORG;
298         }
299
300         /* Okay */
301         do_cmd_borg();
302 }
303
304 #endif /* ALLOW_BORG */
305
306
307 /*
308  * Quit the game.
309  */
310 static void do_cmd_quit(void)
311 {
312         /* Stop playing */
313         p_ptr->playing = FALSE;
314
315         /* Leaving */
316         p_ptr->leaving = TRUE;
317 }
318
319
320 /*
321  * Handle a mouseclick, using the horrible hack that is '\xff'.
322  */
323 static void do_cmd_mouseclick(void)
324 {
325         int x, y;
326
327         if (!mouse_movement) return;
328
329         y = KEY_GRID_Y(p_ptr->command_cmd_ex);
330         x = KEY_GRID_X(p_ptr->command_cmd_ex);
331
332         /* Check for a valid location */
333         if (!in_bounds_fully(y, x)) return;
334
335         /* XXX We could try various things here like going up/down stairs */
336         if ((p_ptr->py == y) && (p_ptr->px == x) /* && (p_ptr->command_cmd_ex.mousebutton) */)
337         {
338                 do_cmd_rest();
339         }
340         else /* if (p_ptr->command_cmd_ex.mousebutton == 1) */
341         {
342                 if (p_ptr->timed[TMD_CONFUSED])
343                 {
344                         do_cmd_walk();
345                 }
346                 else
347                 {
348                         do_cmd_pathfind(y, x);
349                 }
350         }
351         /*
352         else if (p_ptr->command_cmd_ex.mousebutton == 2)
353         {
354                 target_set_location(y, x);
355                 msg_print("Target set.");
356         }
357         */
358 }
359
360
361 /*
362  * Port-specific options
363  *
364  * Should be moved to the options screen. XXX
365  */
366 static void do_cmd_port(void)
367 {
368         (void)Term_user(0);
369 }
370
371
372 /*
373  * Display the options and redraw afterward.
374  */
375 static void do_cmd_xxx_options(void)
376 {
377         do_cmd_options();
378         do_cmd_redraw();
379 }
380
381
382 /*
383  * Display the main-screen monster list.
384  */
385 static void do_cmd_monlist(void)
386 {
387         /* Save the screen and display the list */
388         screen_save();
389         display_monlist();
390
391         /* Wait */
392         anykey();
393
394         /* Return */
395         screen_load();
396 }
397
398
399 /*
400  * Invoked when the command isn't recognised.
401  */
402 static void do_cmd_unknown(void)
403 {
404         prt("Type '?' for help.", 0, 0);
405 }
406
407
408
409
410 /* List indexed by char */
411 do_cmd_type *converted_list[UCHAR_MAX+1];
412
413
414 /*** Menu functions ***/
415
416 /* Display an entry on a command menu */
417 static void cmd_sub_entry(menu_type *menu, int oid, bool cursor, int row, int col, int width)
418 {
419         byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE);
420         const command_type *commands = menu->menu_data;
421
422         (void)width;
423
424         /* Write the description */
425         Term_putstr(col, row, -1, attr, commands[oid].desc);
426
427         /* Include keypress */
428         Term_addch(attr, ' ');
429         Term_addch(attr, '(');
430
431         /* KTRL()ing a control character does not alter it at all */
432         if (KTRL(commands[oid].key) == commands[oid].key)
433         {
434                 Term_addch(attr, '^');
435                 Term_addch(attr, UN_KTRL(commands[oid].key));
436         }
437         else
438         {
439                 Term_addch(attr, commands[oid].key);
440         }
441
442         Term_addch(attr, ')');
443 }
444
445
446 /* Handle user input from a command menu */
447 static bool cmd_sub_action(char cmd, void *db, int oid)
448 {
449         (void)db;
450         (void)oid;
451
452         /* Only handle enter */
453         if (cmd == '\n' || cmd == '\r')
454                 return TRUE;
455         else
456                 return FALSE;
457 }
458
459 /*
460  * Display a list of commands.
461  */
462 static bool cmd_menu(command_list *list, void *selection_p)
463 {
464         menu_type menu;
465         menu_iter commands_menu = { NULL, NULL, cmd_sub_entry, cmd_sub_action };
466         region area = { 23, 4, 37, 13 };
467
468         ui_event_data evt;
469         int cursor = 0;
470         command_type *selection = selection_p;
471
472         /* Set up the menu */
473         WIPE(&menu, menu);
474         menu.cmd_keys = "\x8B\x8C\n\r";
475         menu.count = list->len;
476         menu.menu_data = list->list;
477         menu_init(&menu, MN_SKIN_SCROLL, &commands_menu, &area);
478
479         /* Set up the screen */
480         screen_save();
481         window_make(21, 3, 62, 17);
482
483         /* Select an entry */
484         evt = menu_select(&menu, &cursor, 0);
485
486         /* Load de screen */
487         screen_load();
488
489         if (evt.type == EVT_SELECT)
490         {
491                 *selection = list->list[evt.index];
492         }
493
494         if (evt.type == EVT_ESCAPE)
495         {
496                 return FALSE;
497         }
498         else
499         {
500                 return TRUE;
501         }
502 }
503
504
505
506 static bool cmd_list_action(char cmd, void *db, int oid)
507 {
508         if (cmd == '\n' || cmd == '\r' || cmd == '\xff')
509         {
510                 return cmd_menu(&cmds_all[oid], db);
511         }
512         else
513         {
514                 return FALSE;
515         }
516 }
517
518 static void cmd_list_entry(menu_type *menu, int oid, bool cursor, int row, int col, int width)
519 {
520         byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE);
521         (void)menu;
522         (void)width;
523         Term_putstr(col, row, -1, attr, cmds_all[oid].name);
524 }
525
526 /*
527  * Display a list of command types, allowing the user to select one.
528  */
529 static void do_cmd_menu(void)
530 {
531         menu_type menu;
532         menu_iter commands_menu = { NULL, NULL, cmd_list_entry, cmd_list_action };
533         region area = { 21, 5, 37, 6 };
534
535         ui_event_data evt;
536         int cursor = 0;
537         command_type chosen_command = { NULL, 0, NULL };
538
539         /* Set up the menu */
540         WIPE(&menu, menu);
541         menu.cmd_keys = "\x8B\x8C\n\r";
542         menu.count = N_ELEMENTS(cmds_all) - 1;
543         menu.menu_data = &chosen_command;
544         menu_init(&menu, MN_SKIN_SCROLL, &commands_menu, &area);
545
546         /* Set up the screen */
547         screen_save();
548         window_make(19, 4, 58, 11);
549
550         /* Select an entry */
551         evt = menu_select(&menu, &cursor, 0);
552
553         /* Load de screen */
554         screen_load();
555
556         /* If a command was chosen, do it. */
557         if (chosen_command.hook)
558         {
559                 chosen_command.hook();
560         }
561 }
562
563
564 /*** Exported functions ***/
565
566 /*
567  * Initialise the command list.
568  */
569 void cmd_init(void)
570 {
571         size_t i, j;
572
573         /* Go through all the lists of commands */
574         for (j = 0; j < N_ELEMENTS(cmds_all); j++)
575         {
576                 command_type *commands = cmds_all[j].list;
577
578                 /* Fill everything in */
579                 for (i = 0; i < cmds_all[j].len; i++)
580                 {
581                         unsigned char key = commands[i].key;
582
583                         /* Note: at present converted_list is UCHAR_MAX + 1
584                            large, so 'key' is always a valid index. */
585                         converted_list[key] = commands[i].hook;
586                 }
587         }
588
589         /* Fill in the rest */
590         for (i = 0; i < N_ELEMENTS(converted_list); i++)
591         {
592                 switch (i)
593                 {
594                         /* Ignore */
595                         case ESCAPE:
596                         case ' ':
597                         case '\a':
598                         {
599                                 break;
600                         }
601
602                         default:
603                         {
604                                 if (!converted_list[i])
605                                         converted_list[i] = do_cmd_unknown;
606                         }
607                 }               
608         }
609 }
610
611
612 /*
613  * Parse and execute the current command
614  * Give "Warning" on illegal commands.
615  */
616 void process_command(bool no_request)
617 {
618         if (!no_request)
619                 request_command();
620
621         /* Handle repeating the last command */
622         repeat_check();
623
624         /* Handle resize events XXX */
625         if (p_ptr->command_cmd_ex.type == EVT_RESIZE)
626         {
627                 do_cmd_redraw();
628         }
629         else
630         {
631                 /* Within these boundaries, the cast to unsigned char will have the desired effect */
632                 assert(p_ptr->command_cmd >= CHAR_MIN && p_ptr->command_cmd <= CHAR_MAX);
633
634                 /* Execute the command */
635                 if (converted_list[(unsigned char) p_ptr->command_cmd])
636                         converted_list[(unsigned char) p_ptr->command_cmd]();
637         }
638 }
Note: See TracBrowser for help on using the browser.