| | 14 | static bool repeat_prev_allowed = FALSE; |
| | 15 | |
| | 16 | enum cmd_arg_type { |
| | 17 | arg_STRING, |
| | 18 | arg_CHOICE, |
| | 19 | arg_NUMBER, |
| | 20 | arg_ITEM, |
| | 21 | arg_DIRECTION, |
| | 22 | arg_TARGET, |
| | 23 | arg_POINT, |
| | 24 | arg_END |
| | 25 | }; |
| | 26 | |
| | 27 | /* A simple list of commands and their handling functions. */ |
| | 28 | static struct |
| | 29 | { |
| | 30 | cmd_code cmd; |
| | 31 | enum cmd_arg_type arg_type[3]; |
| | 32 | cmd_handler_fn fn; |
| | 33 | bool repeat_allowed; |
| | 34 | } game_cmds[] = |
| | 35 | { |
| | 36 | { CMD_LOADFILE, { arg_END }, NULL, FALSE }, |
| | 37 | { CMD_NEWGAME, { arg_END }, NULL, FALSE }, |
| | 38 | |
| | 39 | { CMD_BIRTH_RESET, { arg_END }, NULL, FALSE }, |
| | 40 | { CMD_CHOOSE_SEX, { arg_CHOICE, arg_END }, NULL, FALSE }, |
| | 41 | { CMD_CHOOSE_RACE, { arg_CHOICE, arg_END }, NULL, FALSE }, |
| | 42 | { CMD_CHOOSE_CLASS, { arg_CHOICE, arg_END }, NULL, FALSE }, |
| | 43 | { CMD_BUY_STAT, { arg_CHOICE, arg_END }, NULL, FALSE }, |
| | 44 | { CMD_SELL_STAT, { arg_CHOICE, arg_END }, NULL, FALSE }, |
| | 45 | { CMD_RESET_STATS, { arg_END }, NULL, FALSE }, |
| | 46 | { CMD_ROLL_STATS, { arg_END }, NULL, FALSE }, |
| | 47 | { CMD_PREV_STATS, { arg_END }, NULL, FALSE }, |
| | 48 | { CMD_NAME_CHOICE, { arg_STRING, arg_END }, NULL, FALSE }, |
| | 49 | { CMD_ACCEPT_CHARACTER, { arg_END }, NULL, FALSE }, |
| | 50 | |
| | 51 | { CMD_GO_UP, { arg_END }, do_cmd_go_up, FALSE }, |
| | 52 | { CMD_GO_DOWN, { arg_END }, do_cmd_go_down, FALSE }, |
| | 53 | { CMD_SEARCH, { arg_END }, do_cmd_search, TRUE }, |
| | 54 | { CMD_TOGGLE_SEARCH, { arg_END }, do_cmd_toggle_search, FALSE }, |
| | 55 | { CMD_WALK, { arg_DIRECTION, arg_END }, do_cmd_walk, TRUE }, |
| | 56 | { CMD_RUN, { arg_DIRECTION, arg_END }, do_cmd_run, FALSE }, |
| | 57 | { CMD_JUMP, { arg_DIRECTION, arg_END }, do_cmd_jump, FALSE }, |
| | 58 | { CMD_OPEN, { arg_DIRECTION, arg_END }, do_cmd_open, TRUE }, |
| | 59 | { CMD_CLOSE, { arg_DIRECTION, arg_END }, do_cmd_close, TRUE }, |
| | 60 | { CMD_TUNNEL, { arg_DIRECTION, arg_END }, do_cmd_tunnel, TRUE }, |
| | 61 | { CMD_HOLD, { arg_END }, do_cmd_hold, TRUE }, |
| | 62 | { CMD_DISARM, { arg_DIRECTION, arg_END }, do_cmd_disarm, TRUE }, |
| | 63 | { CMD_BASH, { arg_DIRECTION, arg_END }, do_cmd_bash, TRUE }, |
| | 64 | { CMD_ALTER, { arg_DIRECTION, arg_END }, do_cmd_alter, TRUE }, |
| | 65 | { CMD_JAM, { arg_DIRECTION, arg_END }, do_cmd_spike, FALSE }, |
| | 66 | { CMD_REST, { arg_CHOICE, arg_END }, do_cmd_rest, FALSE }, |
| | 67 | { CMD_PATHFIND, { arg_POINT, arg_END }, do_cmd_pathfind, FALSE }, |
| | 68 | { CMD_PICKUP, { arg_ITEM, arg_END }, do_cmd_pickup, FALSE }, |
| | 69 | { CMD_WIELD, { arg_ITEM, arg_END }, do_cmd_wield, FALSE }, |
| | 70 | { CMD_TAKEOFF, { arg_ITEM, arg_END }, do_cmd_takeoff, FALSE }, |
| | 71 | { CMD_DROP, { arg_ITEM, arg_END }, do_cmd_drop, FALSE }, |
| | 72 | { CMD_UNINSCRIBE, { arg_ITEM, arg_END }, do_cmd_uninscribe, FALSE }, |
| | 73 | { CMD_EAT, { arg_ITEM, arg_END }, do_cmd_use, FALSE }, |
| | 74 | { CMD_QUAFF, { arg_ITEM, arg_TARGET, arg_END }, do_cmd_use, FALSE }, |
| | 75 | { CMD_USE_ROD, { arg_ITEM, arg_TARGET, arg_END }, do_cmd_use, FALSE }, |
| | 76 | { CMD_USE_STAFF, { arg_ITEM }, do_cmd_use, FALSE }, |
| | 77 | { CMD_USE_WAND, { arg_ITEM, arg_TARGET, arg_END }, do_cmd_use, FALSE }, |
| | 78 | { CMD_READ_SCROLL, { arg_ITEM, arg_TARGET, arg_END }, do_cmd_use, FALSE }, |
| | 79 | { CMD_ACTIVATE, { arg_ITEM, arg_TARGET, arg_END }, do_cmd_use, FALSE }, |
| | 80 | { CMD_REFILL, { arg_ITEM, arg_END }, do_cmd_refill, FALSE }, |
| | 81 | { CMD_FIRE, { arg_ITEM, arg_TARGET, arg_END }, do_cmd_fire, FALSE }, |
| | 82 | { CMD_THROW, { arg_ITEM, arg_TARGET, arg_END }, do_cmd_throw, FALSE }, |
| | 83 | { CMD_DESTROY, { arg_ITEM, arg_NUMBER, arg_END }, do_cmd_destroy, FALSE }, |
| | 84 | { CMD_ENTER_STORE, { arg_END }, do_cmd_store, FALSE }, |
| | 85 | { CMD_INSCRIBE, { arg_ITEM, arg_STRING, arg_END }, do_cmd_inscribe, FALSE }, |
| | 86 | { CMD_STUDY_SPELL, { arg_CHOICE, arg_END }, do_cmd_study_spell, FALSE }, |
| | 87 | { CMD_STUDY_BOOK, { arg_ITEM, arg_END }, do_cmd_study_book, FALSE }, |
| | 88 | { CMD_CAST, { arg_CHOICE, arg_TARGET, arg_END }, do_cmd_cast, FALSE }, |
| | 89 | { CMD_SELL, { arg_ITEM, arg_NUMBER, arg_END }, do_cmd_sell, FALSE }, |
| | 90 | { CMD_STASH, { arg_ITEM, arg_NUMBER, arg_END }, do_cmd_stash, FALSE }, |
| | 91 | { CMD_BUY, { arg_ITEM, arg_NUMBER, arg_END }, do_cmd_buy, FALSE }, |
| | 92 | { CMD_RETRIEVE, { arg_ITEM, arg_NUMBER, arg_END }, do_cmd_retrieve, FALSE } |
| | 93 | , |
| | 94 | { CMD_SUICIDE, { arg_END }, do_cmd_suicide, FALSE }, |
| | 95 | { CMD_SAVE, { arg_END }, do_cmd_save_game, FALSE }, |
| | 96 | { CMD_QUIT, { arg_END }, do_cmd_quit, FALSE }, |
| | 97 | { CMD_HELP, { arg_END }, NULL, FALSE }, |
| | 98 | { CMD_REPEAT, { arg_END }, NULL, FALSE }, |
| | 99 | }; |
| | 100 | |
| | 101 | |
| 102 | | break; |
| 103 | | } |
| 104 | | |
| 105 | | /* These take one integer argument - a "choice" */ |
| 106 | | case CMD_BIRTH_RESET: |
| 107 | | case CMD_CHOOSE_SEX: |
| 108 | | case CMD_CHOOSE_RACE: |
| 109 | | case CMD_CHOOSE_CLASS: |
| 110 | | case CMD_BUY_STAT: |
| 111 | | case CMD_SELL_STAT: |
| 112 | | case CMD_RESET_STATS: |
| 113 | | case CMD_REST: |
| 114 | | case CMD_STUDY_SPELL: |
| 115 | | { |
| 116 | | cmd.args[0].choice = va_arg(vp, int); |
| 117 | | break; |
| 118 | | } |
| 119 | | |
| 120 | | /* These take a string argument. */ |
| 121 | | case CMD_NAME_CHOICE: |
| 122 | | { |
| 123 | | /* Take a copy, it'll last longer. */ |
| 124 | | /* XXX Should we free this automatically when the slot |
| 125 | | in the queue gets reused, or just continue to let |
| 126 | | the command processor worry about it? */ |
| 127 | | cmd.args[0].string = string_make(va_arg(vp, const char *)); |
| 128 | | break; |
| 129 | | } |
| 130 | | |
| 131 | | /* These take a direction as an argument. */ |
| 132 | | case CMD_WALK: |
| 133 | | case CMD_RUN: |
| 134 | | case CMD_JUMP: |
| 135 | | case CMD_OPEN: |
| 136 | | case CMD_CLOSE: |
| 137 | | case CMD_TUNNEL: |
| 138 | | case CMD_DISARM: |
| 139 | | case CMD_BASH: |
| 140 | | case CMD_ALTER: |
| 141 | | case CMD_JAM: |
| 142 | | { |
| 143 | | cmd.args[0].direction = va_arg(vp, int); |
| 144 | | |
| 145 | | /* Direction hasn't been specified, so we ask for one. */ |
| 146 | | if (cmd.args[0].direction == DIR_UNKNOWN) |
| 147 | | { |
| 148 | | /* |
| 149 | | * If no direction supplied, abort the command. |
| 150 | | * XXX Eventually replace the get_rep_dir call |
| 151 | | * with something more generalised. |
| 152 | | */ |
| 153 | | if (!get_rep_dir(&cmd.args[0].direction)) |
| 154 | | return 1; |
| 155 | | } |
| 156 | | |
| 157 | | break; |
| 158 | | } |
| 159 | | |
| 160 | | /* These take a point (y, x) on the map as an argument. */ |
| 161 | | case CMD_PATHFIND: |
| 162 | | { |
| 163 | | cmd.args[0].point.y = va_arg(vp, int); |
| 164 | | cmd.args[0].point.x = va_arg(vp, int); |
| 165 | | break; |
| 166 | | } |
| 167 | | |
| 168 | | /* These take an item number. */ |
| 169 | | case CMD_UNINSCRIBE: |
| 170 | | case CMD_WIELD: |
| 171 | | case CMD_TAKEOFF: |
| 172 | | case CMD_REFILL: |
| 173 | | case CMD_STUDY_BOOK: |
| 174 | | /* Note that if the effects change for the following, they |
| 175 | | might need to take a target as well, as below. */ |
| 176 | | case CMD_USE_STAFF: |
| 177 | | case CMD_EAT: |
| 178 | | { |
| 179 | | cmd.args[0].item = va_arg(vp, int); |
| 180 | | break; |
| 181 | | } |
| 182 | | |
| 183 | | /* |
| 184 | | * These take an item number and a "target" as arguments, |
| 185 | | * though a target isn't always actually needed, so we'll |
| 186 | | * only prompt for it via callback |
| 187 | | * if the item being used needs it. |
| 188 | | */ |
| 189 | | case CMD_USE_WAND: |
| 190 | | case CMD_USE_ROD: |
| 191 | | case CMD_QUAFF: |
| 192 | | case CMD_ACTIVATE: |
| 193 | | case CMD_READ_SCROLL: |
| 194 | | case CMD_FIRE: |
| 195 | | case CMD_THROW: |
| 196 | | { |
| 197 | | cmd.args[0].item = va_arg(vp, int); |
| 198 | | cmd.args[1].direction = va_arg(vp, int); |
| 199 | | |
| 200 | | if (cmd.args[1].direction == DIR_UNKNOWN && |
| 201 | | obj_needs_aim(object_from_item_idx(cmd.args[0].choice))) |
| 202 | | { |
| 203 | | if (!get_aim_dir(&cmd.args[1].direction)) |
| 204 | | return 1; |
| 205 | | } |
| 206 | | |
| 207 | | break; |
| 208 | | } |
| 209 | | |
| 210 | | /* This takes a choice and a direction. */ |
| 211 | | case CMD_CAST: |
| 212 | | { |
| 213 | | cmd.args[0].choice = va_arg(vp, int); |
| 214 | | cmd.args[1].direction = va_arg(vp, int); |
| 215 | | |
| 216 | | if (cmd.args[1].direction == DIR_UNKNOWN && |
| 217 | | spell_needs_aim(cp_ptr->spell_book, cmd.args[0].choice)) |
| 218 | | { |
| 219 | | if (!get_aim_dir(&cmd.args[1].direction)) |
| 220 | | return 1; |
| 221 | | } |
| 222 | | |
| 223 | | break; |
| 224 | | } |
| 225 | | |
| 226 | | /* These take an item number and a number of those items to process. */ |
| 227 | | case CMD_DROP: |
| 228 | | case CMD_DESTROY: |
| 229 | | case CMD_SELL: |
| 230 | | case CMD_BUY: |
| 231 | | case CMD_STASH: |
| 232 | | case CMD_RETRIEVE: |
| 233 | | { |
| 234 | | /* TODO: Number should probably be replaced by 'repeat'ing */ |
| 235 | | cmd.args[0].item = va_arg(vp, int); |
| 236 | | cmd.args[1].number = va_arg(vp, int); |
| 237 | | break; |
| 238 | | } |
| 239 | | |
| 240 | | /* Takes an item number and a string to inscribe. */ |
| 241 | | case CMD_INSCRIBE: |
| 242 | | { |
| 243 | | cmd.args[0].item = va_arg(vp, int); |
| 244 | | cmd.args[1].string = string_make(va_arg(vp, const char *)); |
| 245 | | break; |
| | 196 | case arg_CHOICE: |
| | 197 | { |
| | 198 | cmd.args[j].choice = va_arg(vp, int); |
| | 199 | break; |
| | 200 | } |
| | 201 | |
| | 202 | case arg_STRING: |
| | 203 | { |
| | 204 | cmd.args[j].string = string_make(va_arg(vp, const char *)); |
| | 205 | break; |
| | 206 | } |
| | 207 | |
| | 208 | case arg_DIRECTION: |
| | 209 | case arg_TARGET: |
| | 210 | { |
| | 211 | cmd.args[j].direction = va_arg(vp, int); |
| | 212 | break; |
| | 213 | } |
| | 214 | |
| | 215 | case arg_POINT: |
| | 216 | { |
| | 217 | cmd.args[j].point.y = va_arg(vp, int); |
| | 218 | cmd.args[j].point.x = va_arg(vp, int); |
| | 219 | break; |
| | 220 | } |
| | 221 | |
| | 222 | case arg_ITEM: |
| | 223 | { |
| | 224 | cmd.args[j].item = va_arg(vp, int); |
| | 225 | break; |
| | 226 | } |
| | 227 | |
| | 228 | case arg_NUMBER: |
| | 229 | { |
| | 230 | cmd.args[j].number = va_arg(vp, int); |
| | 231 | break; |
| | 232 | } |
| | 233 | |
| | 234 | case arg_END: |
| | 235 | { |
| | 236 | break; |
| | 237 | } |
| 255 | | |
| 256 | | /* A simple list of commands and their handling functions. */ |
| 257 | | static struct |
| 258 | | { |
| 259 | | cmd_code cmd; |
| 260 | | cmd_handler_fn fn; |
| 261 | | bool repeat_allowed; |
| 262 | | } game_cmds[] = |
| 263 | | { |
| 264 | | { CMD_GO_UP, do_cmd_go_up, FALSE }, |
| 265 | | { CMD_GO_DOWN, do_cmd_go_down, FALSE }, |
| 266 | | { CMD_SEARCH, do_cmd_search, TRUE }, |
| 267 | | { CMD_TOGGLE_SEARCH, do_cmd_toggle_search, FALSE }, |
| 268 | | { CMD_WALK, do_cmd_walk, TRUE }, |
| 269 | | { CMD_RUN, do_cmd_run, FALSE }, |
| 270 | | { CMD_JUMP, do_cmd_jump, FALSE }, |
| 271 | | { CMD_OPEN, do_cmd_open, TRUE }, |
| 272 | | { CMD_CLOSE, do_cmd_close, TRUE }, |
| 273 | | { CMD_TUNNEL, do_cmd_tunnel, TRUE }, |
| 274 | | { CMD_HOLD, do_cmd_hold, TRUE }, |
| 275 | | { CMD_DISARM, do_cmd_disarm, TRUE }, |
| 276 | | { CMD_BASH, do_cmd_bash, TRUE }, |
| 277 | | { CMD_ALTER, do_cmd_alter, TRUE }, |
| 278 | | { CMD_JAM, do_cmd_spike, FALSE }, |
| 279 | | { CMD_REST, do_cmd_rest, FALSE }, |
| 280 | | { CMD_PATHFIND, do_cmd_pathfind, FALSE }, |
| 281 | | { CMD_PICKUP, do_cmd_pickup, FALSE }, |
| 282 | | { CMD_SUICIDE, do_cmd_suicide, FALSE }, |
| 283 | | { CMD_SAVE, do_cmd_save_game, FALSE }, |
| 284 | | { CMD_QUIT, do_cmd_quit, FALSE }, |
| 285 | | { CMD_WIELD, do_cmd_wield, FALSE }, |
| 286 | | { CMD_TAKEOFF, do_cmd_takeoff, FALSE }, |
| 287 | | { CMD_DROP, do_cmd_drop, FALSE }, |
| 288 | | { CMD_UNINSCRIBE, do_cmd_uninscribe, FALSE }, |
| 289 | | { CMD_EAT, do_cmd_use, FALSE }, |
| 290 | | { CMD_QUAFF, do_cmd_use, FALSE }, |
| 291 | | { CMD_USE_ROD, do_cmd_use, FALSE }, |
| 292 | | { CMD_USE_STAFF, do_cmd_use, FALSE }, |
| 293 | | { CMD_USE_WAND, do_cmd_use, FALSE }, |
| 294 | | { CMD_READ_SCROLL, do_cmd_use, FALSE }, |
| 295 | | { CMD_ACTIVATE, do_cmd_use, FALSE }, |
| 296 | | { CMD_REFILL, do_cmd_refill, FALSE }, |
| 297 | | { CMD_FIRE, do_cmd_fire, FALSE }, |
| 298 | | { CMD_THROW, do_cmd_throw, FALSE }, |
| 299 | | { CMD_DESTROY, do_cmd_destroy, FALSE }, |
| 300 | | { CMD_ENTER_STORE, do_cmd_store, FALSE }, |
| 301 | | { CMD_INSCRIBE, do_cmd_inscribe, FALSE }, |
| 302 | | { CMD_STUDY_SPELL, do_cmd_study_spell, FALSE }, |
| 303 | | { CMD_STUDY_BOOK, do_cmd_study_book, FALSE }, |
| 304 | | { CMD_CAST, do_cmd_cast, FALSE }, |
| 305 | | { CMD_SELL, do_cmd_sell, FALSE }, |
| 306 | | { CMD_STASH, do_cmd_stash, FALSE }, |
| 307 | | { CMD_BUY, do_cmd_buy, FALSE }, |
| 308 | | { CMD_RETRIEVE, do_cmd_retrieve, FALSE }, |
| 309 | | }; |