home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Xconq 7.1.0 / src / xconq-7.1.0 / curses / ccmd.c next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  30.5 KB  |  1,473 lines  |  [TEXT/R*ch]

  1. /* Commands for the curses interface to Xconq.
  2.    Copyright (C) 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996
  3.    Stanley T. Shebs.
  4.  
  5. Xconq is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.  See the file COPYING.  */
  9.  
  10. #include "conq.h"
  11. extern void update_debugging PARAMS ((void));
  12. extern void toggle_debugging PARAMS ((int *flagp));
  13. #include "cconq.h"
  14. extern int autofinish_start;
  15. extern int autofinish_count;
  16. extern int drawlinear;
  17. extern char linear_char;
  18. extern char bord_char;
  19. extern char conn_char;
  20.  
  21. /* Command table. */
  22.  
  23. typedef struct cmdtab {
  24.     char fchar;                 /* character to match against */
  25.     char *name;                 /* Full name of command */
  26.     char *argtypes;
  27.     void (*fn) PARAMS ((void));  /* pointer to command's function */
  28.     char *help;                 /* short documentation string */
  29. } CmdTab;
  30.  
  31. static void impl_build PARAMS ((Side *side, Unit *unit, int u2, int n));
  32. static void resize_map PARAMS ((int n));
  33. static void execute_named_command PARAMS ((char *cmdstr));
  34. static int execute_command_from_table PARAMS ((CmdTab *cmdtab));
  35. static int execute_named_command_from_table PARAMS ((char *cmdstr,
  36.                             CmdTab *cmdtab));
  37. static void describe_command_table PARAMS ((int arg, char *key, char *buf,
  38.                        CmdTab *cmdtab));
  39. static void cmd_error PARAMS ((char *fmt, ...));
  40.  
  41. /* Declarations of all the command functions. */
  42.  
  43. #undef DEF_CMD
  44. #define DEF_CMD(letter,name,args,FN,help) void FN PARAMS ((void));
  45.  
  46. #include "cmd.def"
  47.  
  48. #include "ccmd.def"
  49.  
  50. /* Define a table of generic commands. */
  51.  
  52. #define C(c) ((c)-0x40)
  53.  
  54. CmdTab commands[] = {
  55.  
  56. #undef DEF_CMD
  57. #define DEF_CMD(LETTER,NAME,ARGS,FN,HELP) { LETTER, NAME, ARGS, FN, HELP },
  58.  
  59. #include "cmd.def"
  60.  
  61.   { 0, NULL, NULL, NULL, NULL }
  62. };
  63.  
  64. /* Define a table of curses-specific commands. */
  65.  
  66. CmdTab ccommands[] = {
  67.  
  68. #include "ccmd.def"
  69.  
  70.   { 0, NULL, NULL, NULL, NULL }
  71. };
  72.  
  73. /* Argument string following a long-name command. */
  74.  
  75. static char *cmdargstr;
  76.  
  77. /* Search in command table and execute function if found, complaining if
  78.    the command is not recognized.  Many commands operate on the "current
  79.    unit", and all uniformly error out if there is no current unit, so put
  80.    that test here.  Also fix up the arg if the value passed is one of the
  81.    specially recognized ones. */
  82.  
  83. void
  84. execute_command()
  85. {
  86.     if (execute_command_from_table(ccommands))
  87.       return;
  88.     if (execute_command_from_table(commands))
  89.       return;
  90.     cmd_error("unknown command character '%c'", inpch);
  91. }
  92.  
  93. char tmpkey;
  94.  
  95. static int
  96. execute_command_from_table(cmdtab)
  97. CmdTab *cmdtab;
  98. {
  99.     CmdTab *cmd;
  100.     char ch = inpch;
  101.     void (*fn) PARAMS ((void));
  102.     
  103.     for (cmd = cmdtab; cmd->name != NULL; ++cmd) {
  104.     if (ch == cmd->fchar) {
  105.         fn = cmd->fn;
  106.         if (fn == NULL) {
  107.         run_warning("no command function for %s (0x%x)?",
  108.                 cmd->name, ch);
  109.         return TRUE;
  110.         }
  111.         tmpkey = ch;
  112.         (*fn)();
  113.         /* Whatever might have happened, we *did* find the command. */
  114.         return TRUE;
  115.     }
  116.     }
  117.     return FALSE;
  118. }
  119.  
  120. static void
  121. execute_named_command(cmdstr)
  122. char *cmdstr;
  123. {
  124.     char *cmdname;
  125.  
  126.     parse_long_name_command(cmdstr, &cmdname, &cmdargstr, copy_string(cmdstr)); 
  127.     if (empty_string(cmdname)) {
  128.     notify(dside, "No command.");
  129.     }
  130.     /* Look for the command name in the curses-specific table. */
  131.     if (execute_named_command_from_table(cmdname, ccommands))
  132.       return;
  133.     /* Try the generic table. */
  134.     if (execute_named_command_from_table(cmdname, commands))
  135.       return;
  136.     cmd_error("unknown command name \"%s\"", cmdstr);
  137. }
  138.  
  139. static int
  140. execute_named_command_from_table(cmdstr, cmdtab)
  141. char *cmdstr;
  142. CmdTab *cmdtab;
  143. {
  144.     CmdTab *cmd;
  145.     void (*fn) PARAMS ((void));
  146.  
  147.     for (cmd = cmdtab; cmd->name != NULL; ++cmd) {
  148.     if (strcmp(cmdstr, cmd->name) == 0) {
  149.         if ((fn = cmd->fn) == NULL) {
  150.         run_warning("no command function for %s?", cmd->name);
  151.         return TRUE;
  152.         }
  153.         tmpkey = cmd->fchar;
  154.         (*fn)();
  155.         /* Whatever might have happened, we *did* find the command. */
  156.         return TRUE;
  157.     }
  158.     }
  159.     return FALSE;
  160. }
  161.  
  162. /* Paste one-line descriptions of commands into the supplied buffer. */
  163.  
  164. void
  165. describe_commands(arg, key, buf)
  166. int arg;
  167. char *key, *buf;
  168. {
  169.     strcat(buf, "To move a unit, use [hlyubn]\n");
  170.     strcat(buf, "[HLYUBN] moves unit repeatedly in that direction\n");
  171.     strcat(buf, "To look at another unit, use survey mode ('z')\n");
  172.     strcat(buf, "and use [hlyubnHLYUBN] to move the cursor\n");
  173.     strcat(buf, "\n");
  174.     strcat(buf, "Generic commands:\n");
  175.     describe_command_table(arg, key, buf, commands);
  176.     strcat(buf, "Cconq-specific commands:\n");
  177.     describe_command_table(arg, key, buf, ccommands);
  178. }
  179.  
  180. static void
  181. describe_command_table(arg, key, buf, cmdtab)
  182. int arg;
  183. char *key, *buf;
  184. CmdTab *cmdtab;
  185. {
  186.     CmdTab *cmd;
  187.  
  188.     strcat(buf, "Single-key commands:\n\n");
  189.     for (cmd = cmdtab; cmd->name != NULL; ++cmd) {
  190.     describe_command (cmd->fchar, cmd->name, cmd->help, TRUE, buf);
  191.     }
  192.     strcat(buf, "\nLong name commands:\n\n");
  193.     for (cmd = cmdtab; cmd->name != NULL; ++cmd) {
  194.     describe_command (cmd->fchar, cmd->name, cmd->help, FALSE, buf);
  195.     }
  196. }
  197.  
  198. /* Use this macro in any command if it requires a current unit. */
  199.  
  200. #define REQUIRE_UNIT()  \
  201.   if (!in_play(curunit)) {  \
  202.     curunit = NULL;  \
  203.     cmd_error("No current unit to command!");  \
  204.     return;  \
  205.   }
  206.  
  207. Unit *lastactor = NULL;
  208.  
  209. Unit *
  210. find_next_and_look()
  211. {
  212.     Unit *nextunit;
  213.  
  214.     nextunit = find_next_actor(dside, curunit);
  215.     if (nextunit != NULL) {
  216.     make_current(nextunit);
  217.     show_cursor();
  218.     }
  219.     return nextunit;
  220. }
  221.  
  222. void
  223. do_add_player()
  224. {
  225.     request_additional_side(cmdargstr);
  226. }
  227.  
  228. void
  229. do_add_terrain()
  230. {
  231.     int u, t, dir;
  232.  
  233.     REQUIRE_UNIT();
  234.     u = curunit->type;
  235.     if (ask_direction("Add terrain to where?", &dir)) {
  236.     for_all_terrain_types(t) {
  237.         if (ut_acp_to_add_terrain(u, t) > 0
  238.         && curunit->act
  239.         && curunit->act->acp >= ut_acp_to_add_terrain(u, t)) {
  240.         if (0 <= ut_alter_range(curunit->type, t)) {
  241.             if (prep_add_terrain_action(curunit, curunit,
  242.                         curunit->x, curunit->y,
  243.                         dir, t))
  244.               ;
  245.             else
  246.               xbeep();
  247.         }
  248.         }
  249.     }
  250.     }
  251. }
  252.  
  253. /* Set which AI is to run the side's play. */
  254.  
  255. void
  256. do_ai_side()
  257. {
  258.     if (side_has_ai(dside)) {
  259.     set_side_ai(dside, NULL);
  260.     } else {
  261.     set_side_ai(dside, "mplayer");
  262.     }
  263. }
  264.  
  265. void
  266. do_attack()
  267. {
  268.     int x, y;
  269.     Unit *other;
  270.  
  271.     REQUIRE_UNIT();
  272.     if (ask_position("Attack where?", &x, &y)) {
  273.     for_all_stack(x, y, other) {
  274.         if (!unit_trusts_unit(curunit, other)) {
  275.         if (valid(check_attack_action(curunit, curunit, other, 100))) {
  276.             prep_attack_action(curunit, curunit, other, 100);
  277.             return;
  278.         }
  279.         /* (should try other types of actions?) */
  280.         }
  281.     }
  282.     cmd_error("Nothing for %s to attack at %d,%d!",
  283.           unit_handle(dside, curunit), x, y);
  284.     }
  285. }
  286.  
  287. /* Set the unit to automatic control.  */
  288.  
  289. void
  290. do_auto()
  291. {
  292.     REQUIRE_UNIT();
  293.     if (curunit->plan) {
  294.     set_unit_ai_control(dside, curunit, !curunit->plan->aicontrol, FALSE);
  295.     /* a hack */
  296.     curunit->plan->waitingfortasks = !curunit->plan->aicontrol;
  297.     }
  298. }
  299.  
  300. void
  301. do_build()
  302. {
  303.     short possibles[MAXUTYPES];
  304.     int u, u2, numtypes, ufirst;
  305.  
  306.     REQUIRE_UNIT();
  307.     u = curunit->type;
  308.     if (!can_build(curunit)) {
  309.     cmd_error("%s can't build anything!", unit_handle(dside, curunit));
  310.     return;
  311.     }
  312. #if 0
  313.     if (!u_occproduce(curunit->type) && curunit->transport != NULL) {
  314.     cmd_error("%s can't build anything while inside another unit!",
  315.           unit_handle(dside, curunit));
  316.     return;
  317.     }
  318. #endif
  319.     numtypes = 0;
  320.     for_all_unit_types(u2) {
  321.     if (uu_acp_to_create(u, u2) > 0 && type_allowed_on_side(u, dside)) {
  322.         possibles[u2] = TRUE;
  323.         ++numtypes;
  324.         ufirst = u2;
  325.     } else {
  326.         possibles[u2] = FALSE;
  327.     }
  328.     }
  329.     switch (numtypes) {
  330.       case 0:
  331.     cmd_error("Nothing to build!");
  332.     break;
  333.       case 1:
  334.     /* Only one type to build - just do it. */
  335.     impl_build(dside, curunit, ufirst, prefixarg);
  336.     break;
  337.       default:
  338.     /* Player has to choose a type to build. */
  339.     u2 = ask_unit_type("Type to build:", possibles);
  340.     if (u2 != NONUTYPE) {
  341.         impl_build(dside, curunit, u2, prefixarg);
  342.     } else {
  343.         /* should clear toplines */
  344.     }
  345.     break;
  346.     }
  347. }
  348.  
  349. static void
  350. impl_build(side, unit, u2, n)
  351. Side *side;
  352. Unit *unit;
  353. int u2, n;
  354. {
  355.     if (n < 0)
  356.       n = 99;
  357.     notify(side, "%s will build %d %s",
  358.        unit_handle(side, unit), n, u_type_name(u2));
  359.     push_build_task(unit, u2, n);
  360. }
  361.  
  362. void
  363. do_clear_plan()
  364. {
  365.     REQUIRE_UNIT();
  366.     if (curunit->plan) {
  367.     set_unit_plan_type(dside, curunit, PLAN_NONE);
  368.     }
  369. }
  370.  
  371. void
  372. do_copying()
  373. {
  374.     cur_help_node = copying_help_node;
  375.     do_help();
  376. }
  377.  
  378. void
  379. do_delay()
  380. {
  381.     Unit *oldcurunit = curunit, *nextmover;
  382.  
  383.     nextmover = find_next_and_look();
  384.  
  385.     if (nextmover == NULL) {
  386.     cmd_error("no units???");
  387.     } else if (curunit == oldcurunit) {
  388.     notify(dside, "No other units to move!");
  389.     }
  390. }
  391.  
  392. void
  393. do_detach()
  394. {
  395.     Unit *unit = curunit;
  396.  
  397.     REQUIRE_UNIT();
  398.     if (!completed(unit)) {
  399.     cmd_error("cannot detach from an incomplete unit");
  400.     return;
  401.     }
  402.     if (valid(check_transfer_part_action(unit, unit, unit->hp / 2, NULL))) {
  403.     prep_transfer_part_action(unit, unit, unit->hp / 2, NULL);
  404.     } else {
  405.     cmd_error("cannot detach right now");
  406.     }
  407. }
  408.  
  409. void
  410. do_detonate()
  411. {
  412.     Unit *unit = curunit;
  413.  
  414.     REQUIRE_UNIT();
  415.     prep_detonate_action(unit, unit, unit->x, unit->y, unit->z);
  416. }
  417.  
  418. /* Supposedly you could only get to these by typing the full command names. */
  419.  
  420. void
  421. do_dir()
  422. {
  423.     cmd_error("use the single-character commands instead");
  424. }
  425.  
  426. void
  427. do_dir_multiple()
  428. {
  429.     cmd_error("use the single-character commands instead");
  430. }
  431.  
  432. /* Get rid of a unit. */
  433.  
  434. void
  435. do_disband()
  436. {
  437.     int u;
  438.  
  439.     REQUIRE_UNIT();
  440.     u = curunit->type;
  441. #ifdef DESIGNERS
  442.     if (dside->designer) {
  443.     kill_unit(curunit, -1);
  444.     return;
  445.     }
  446. #endif /* DESIGNERS */
  447.     if (!completed(curunit)) {
  448.     kill_unit(curunit, H_UNIT_DISBANDED);
  449.     } else if (u_hp_per_disband(u) > 0) {
  450.     if (prep_disband_action(curunit, curunit)) {
  451.         /* (text should come from game design) */
  452.         notify(dside, "%s will go home.", unit_handle(dside, curunit));
  453.     } else {
  454.         /* failed, should say something */
  455.     }
  456.     } else {
  457.     cmd_error("You can't just get rid of %s!",
  458.           unit_handle(dside, curunit));
  459.     }
  460. }
  461.  
  462. void
  463. do_disembark()
  464. {
  465.     Unit *transport;
  466.  
  467.     REQUIRE_UNIT();
  468.     transport = curunit->transport;
  469.     if (transport == NULL) {
  470.     cmd_error("Not in a transport");
  471.     return;
  472.     }
  473.     if (!in_play(transport)) {
  474.     cmd_error("Transport is nonsensical?");
  475.     return;
  476.     }
  477.     /* Try moving into the transport's transport, if there is one. */
  478.     if (transport->transport != NULL
  479.         && can_occupy(curunit, transport->transport)) {
  480.     prep_enter_action(curunit, curunit, transport->transport);
  481.     /* (should be able to set up task if can't do action immedly) */
  482.     return;
  483.     }
  484.     /* Try moving into the open in the cell. */
  485.     if (can_occupy_cell(curunit, curunit->x, curunit->y)
  486.     || can_occupy_conn(curunit, curunit->x, curunit->y, curunit->z)) {
  487.     prep_move_action(curunit, curunit, curunit->x, curunit->y, curunit->z);
  488.     /* (should be able to set up task if can't do action immedly) */
  489.     return;
  490.     }
  491.     cmd_error("Can't disembark here!");
  492. }
  493.  
  494. /* Determine how far away another point is.  */
  495.  
  496. void
  497. do_distance()
  498. {
  499.     int x, y;
  500.  
  501.     if (ask_position("Distance to where?", &x, &y)) {
  502.     notify(dside, "Distance is %d cells.", distance(curx, cury, x, y));
  503.     }
  504. }
  505.  
  506. void
  507. do_distrust()
  508. {
  509.     Side *side2;
  510.  
  511.     if (cmdargstr) {
  512.     side2 = parse_side_spec(cmdargstr);
  513.     if (side2 != NULL && side2 != dside) {
  514.         set_trust(dside, side2, 0);
  515.         return;
  516.     } 
  517.     }
  518.     cmd_error("no side to distrust");
  519. }
  520.  
  521. void
  522. do_draw_willingness()
  523. {
  524.     if (prefixarg < 0)
  525.       prefixarg = 1;
  526.     set_willing_to_draw(dside, (prefixarg ? 1 : 0));
  527. }
  528.  
  529. /* What about trying to embark a unit on itself or on its previous transp? */
  530.  
  531. void
  532. do_embark()
  533. {
  534.     Unit *transport;
  535.  
  536.     REQUIRE_UNIT();
  537.     /* (should only ask if multiple transport possibilities) */
  538.     if (ask_unit("Which unit to board?", &transport)) {
  539.     if (!in_play(transport)) {
  540.         cmd_error("This transport is nonsensical?");
  541.         return;
  542.     }
  543.     if (!can_occupy(curunit, transport)) {
  544.         cmd_error("Can't occupy chosen transport");
  545.         return;
  546.     }
  547.     prep_enter_action(curunit, curunit, transport);
  548.     /* (should be able to set up task if can't do action immedly) */
  549.     } else {
  550.     xbeep();
  551.     }
  552. }
  553.  
  554. /* Command to end our activity for this turn. */
  555.  
  556. void
  557. do_end_turn()
  558. {
  559.     finish_turn(dside);
  560. }
  561.  
  562. /* Command to fire at a specified unit or location. */
  563.  
  564. void
  565. do_fire()
  566. {
  567.     int x, y;
  568.     Unit *unit2;
  569.  
  570.     REQUIRE_UNIT();
  571.     sprintf(spbuf, "Fire %s at where?", unit_handle(dside, curunit));
  572.     /* (should have some sort of range feedback) */
  573.     if (ask_position(spbuf, &x, &y)) {
  574.     if (units_visible(dside, x, y)) {
  575.         for_all_stack(x, y, unit2) {
  576.         if (unit2->side != curunit->side) {
  577.             prep_fire_at_action(curunit, curunit, unit2, -1);
  578.             return;
  579.         }
  580.         }
  581.     }
  582.     /* (should say that nothing is visible and verify firing) */
  583.     if (1) {
  584.         prep_fire_into_action(curunit, curunit, x, y, 0, -1);
  585.     } else {
  586.         xbeep();
  587.     }
  588.     }
  589. }
  590.  
  591. void
  592. do_fire_into()
  593. {
  594.     int x, y;
  595.     Unit *unit2;
  596.  
  597.     REQUIRE_UNIT();
  598.     sprintf(spbuf, "Fire %s at where?", unit_handle(dside, curunit));
  599.     /* (should have some sort of range feedback) */
  600.     if (ask_position(spbuf, &x, &y)) {
  601.     prep_fire_into_action(curunit, curunit, x, y, 0, -1);
  602.     }
  603. }
  604.  
  605. /* Toggle the action following flag. */
  606.  
  607. void
  608. do_follow_action()
  609. {
  610.     follow_action = !follow_action;
  611.     if (follow_action) {
  612.     notify(dside, "Following the action.");
  613.     } else {
  614.     notify(dside, "Not following the action.");
  615.     }
  616. }
  617.  
  618. void
  619. do_force_global_replan()
  620. {
  621.     force_global_replan(dside);
  622. }
  623.  
  624. /* Give supplies to a transport.  The argument tells how many to give. */
  625.  
  626. void
  627. do_give()
  628. {
  629.     int n = prefixarg, something = FALSE, u, m, r, gift, actual;
  630.     Unit *main;
  631.  
  632.     REQUIRE_UNIT();
  633.     u = curunit->type;
  634.     main = curunit->transport;
  635.     if (main != NULL) {
  636.     spbuf[0] = '\0';
  637.     m = main->type;
  638.     for_all_material_types(r) {
  639.         gift = (n < 0 ? (um_storage_x(m, r) - main->supply[r]) : n);
  640.         if (gift > 0) {
  641.         something = TRUE;
  642.         /* Be stingy if we're low */
  643.         if (2 * curunit->supply[r] < um_storage_x(u, r))
  644.             gift = max(1, gift/2);
  645.         actual = transfer_supply(curunit, main, r, gift);
  646.         sprintf(tmpbuf, " %d %s", actual, m_type_name(r));
  647.         strcat(spbuf, tmpbuf);
  648.         }
  649.     }
  650.     if (something) {
  651.         notify(dside, "%s gave%s.", unit_handle(dside, curunit), spbuf);
  652.     } else {
  653.         notify(dside, "%s gave nothing.", unit_handle(dside, curunit));
  654.     }
  655.     } else {
  656.     cmd_error("Can't transfer supplies here!");
  657.     }
  658. }
  659.  
  660. /* Give a unit to another side or "to" independence. */
  661.  
  662. void
  663. do_give_unit()
  664. {
  665.     int u;
  666.  
  667.     REQUIRE_UNIT();
  668.     u = curunit->type;
  669. #ifdef DESIGNERS
  670.     if (dside->designer) {
  671.     change_unit_side(curunit, side_n(prefixarg), -1, NULL);
  672.     update_unit_display(dside, curunit, TRUE);
  673.     all_see_cell(curunit->x, curunit->y);
  674.     return;
  675.     }
  676. #endif /* DESIGNERS */
  677.     if (1) { /* (should test both temporary and permanent invalidity) */
  678.     prep_change_side_action(curunit, curunit, side_n(prefixarg));
  679.     } else {
  680.     cmd_error("You can't just give away the %s!", u_type_name(u));
  681.     }
  682. }
  683.  
  684. /* Bring up help info. */
  685.  
  686. void
  687. do_help()
  688. {
  689.     /* Switch to help mode, saving current mode first. */
  690.     prevmode = mode;
  691.     mode = HELP;
  692.     show_help();
  693.     refresh();
  694. }
  695.  
  696. /* Send a short message to another side. */
  697.  
  698. void
  699. do_message()
  700. {
  701.     char *msg;
  702.     Side *side2;
  703.     SideMask sidemask;
  704.  
  705.     if (prefixarg == 0) {
  706.     /* (should ask who to send to) */
  707.     }
  708.     side2 = side_n(prefixarg);
  709.     if (ask_string("Message:", "", &msg)) {
  710.     if (empty_string(msg) || (prefixarg >= 0 && side2 == NULL)) {
  711.         notify(dside, "You keep your mouth shut.");
  712.         sidemask = NOSIDES;
  713.     } else if (prefixarg < 0) {
  714.         notify(dside, "You made the announcement \"%s\"", msg);
  715.         sidemask = ALLSIDES;
  716.     } else if (side2 != NULL) {
  717.         notify(dside, "Your message was sent.");
  718.         sidemask = add_side_to_set(side2, NOSIDES);
  719.     }
  720.     if (!empty_string(msg) && sidemask != NOSIDES)
  721.       send_message(dside, sidemask, msg);
  722.     }
  723. }
  724.  
  725. /* Set unit to move to a given location.  Designers do a teleport. */
  726.  
  727. void
  728. do_move_to()
  729. {
  730.     int x, y;
  731.  
  732.     REQUIRE_UNIT();
  733.     sprintf(spbuf, "Move %s to where?", unit_handle(dside, curunit));
  734.     if (ask_position(spbuf, &x, &y)) {
  735. #ifdef DESIGNERS
  736.     if (dside->designer) {
  737.         designer_teleport(curunit, x, y, NULL);
  738.         make_current(curunit);
  739.         return;
  740.     }
  741. #endif /* DESIGNERS */
  742.     set_move_to_task(curunit, x, y);
  743.     }
  744. }
  745.  
  746. /* Command to name or rename the current unit or a given side. */
  747.  
  748. void
  749. do_name()
  750. {
  751.     char *newname;
  752.  
  753.     REQUIRE_UNIT();
  754.     if (ask_string("New name for unit:", curunit->name, &newname)) {
  755.     if (empty_string(newname))
  756.       newname = NULL;
  757.     set_unit_name(dside, curunit, newname);
  758.     }
  759. }
  760.  
  761. void
  762. do_occupant()
  763. {
  764.     Unit *nextocc;
  765.  
  766.     if (curunit == NULL) {
  767.     make_current_at(curx, cury);
  768.     }
  769.     REQUIRE_UNIT();
  770.     nextocc = find_next_occupant(curunit);
  771.     if (nextocc != curunit)
  772.       make_current(nextocc);
  773. }
  774.  
  775. void
  776. do_other()
  777. {
  778.     char *cmd;
  779.  
  780.     if (ask_string("Command:", NULL, &cmd)) {
  781.     if (empty_string(cmd)) {
  782.         cmd_error("No command");
  783.     } else if (strcmp(cmd, "?") == 0) {
  784.         cur_help_node = commands_help_node;
  785.         do_help();
  786.     } else {
  787.         execute_named_command(cmd);
  788.     }
  789.     }
  790. }
  791.  
  792. void
  793. do_print_view()
  794. {
  795.     dump_text_view(dside, use_both_chars);
  796. }
  797.  
  798. void
  799. do_produce()
  800. {
  801.     int m, n;
  802.     Unit *unit = curunit;
  803.  
  804.     REQUIRE_UNIT();
  805.     if (!can_produce(unit)) {
  806.     cmd_error("cannot do active production");
  807.     }
  808.     n = 9999;
  809.     if (prefixarg > 0)
  810.       n = prefixarg;
  811.     /* Find the first produceable type and set up to produce it. */
  812.     for_all_material_types(m) {
  813.     if (um_acp_to_produce(unit->type, m) > 0) {
  814.         push_produce_task(unit, m, n);
  815.         return;
  816.     }
  817.     }
  818. }
  819.  
  820. /* Command to get out of a game, one way or another. */
  821.  
  822. void
  823. do_quit()
  824. {
  825.     if (endofgame || !dside->ingame) {
  826.     exit_cconq();
  827.     return;
  828.     }
  829.     /* Confirm the saving of any state. */
  830.     if (!gamestatesafe) {
  831.     if (ask_bool("Do you want to save the game?", TRUE)) {
  832.         if (all_others_willing_to_save(dside)) {
  833.         do_save();
  834.         exit_cconq();
  835.         return;
  836.         } else {
  837.         set_willing_to_save(dside, TRUE);
  838.         notify(dside, "Other sides not willing to save.");
  839.         }
  840.     }
  841.     }
  842.     if (all_others_willing_to_quit(dside)) {
  843.     if (ask_bool("Do you really want to declare a draw?", FALSE)) {
  844.         set_willing_to_draw(dside, TRUE);
  845.     } else {
  846.         notify(dside, "Not willing to draw.");
  847.     }
  848.     return;
  849.     } else {
  850.     if (ask_bool("You must resign to get out; do you want to resign?", FALSE)) {
  851.         do_resign();
  852.     } else {
  853.         notify(dside, "Not resigning.");
  854.     }
  855.     }
  856. }
  857.  
  858. /* Move the current location as close to the center of the display as
  859.    possible, and redraw everything. */
  860.  
  861. void
  862. do_recenter()
  863. {
  864.     set_view_focus(mvp, curx, cury);
  865.     center_on_focus(mvp);
  866.     set_map_viewport();
  867.     show_map();
  868.     refresh();
  869. }
  870.  
  871. /* Redraw everything using the same code as when windows need a redraw. */
  872.  
  873. void
  874. do_refresh()
  875. {
  876.     redraw();
  877. }
  878.  
  879. void
  880. do_remove_terrain()
  881. {
  882.     int t, dir;
  883.  
  884.     REQUIRE_UNIT();
  885.     if (ask_direction("Remove terrain from where?", &dir)) {
  886.       for_all_terrain_types(t) {
  887.     if (ut_acp_to_remove_terrain(curunit->type, t) > 0
  888.         && curunit->act
  889.         && curunit->act->acp >= ut_acp_to_remove_terrain(curunit->type, t)) {
  890.         if (0 <= ut_alter_range(curunit->type, t)) {
  891.         if (prep_remove_terrain_action(curunit, curunit, curunit->x, curunit->y, dir, t))
  892.           ;
  893.         else
  894.           xbeep();
  895.         }
  896.     }
  897.       }
  898.     }
  899. }
  900.  
  901. void
  902. do_reserve()
  903. {
  904.     REQUIRE_UNIT();
  905.     set_unit_asleep(dside, curunit, TRUE, TRUE);
  906. }
  907.  
  908. void
  909. do_resign()
  910. {
  911.     Side *side2;
  912.  
  913.     if (endofgame) {
  914.     cmd_error("Game is already over.");
  915.     } else if (!dside->ingame) {
  916.     cmd_error("You are already out of the game.");
  917.     } else if (ask_bool("Do you really want to resign?", FALSE)) {
  918.     side2 = NULL;
  919.     if (numsides > 2) {
  920.         side2 = ask_side("Who do you want to inherit?", NULL);
  921.         if (side2 == dside) {
  922.         cmd_error("You can't inherit your own units! (not giving to anybody)");
  923.         side2 = NULL;
  924.         }
  925.     }
  926.     resign_game(dside, side2);
  927.     }
  928. }
  929.  
  930. /* Set unit to return to a good resupply place. */
  931.  
  932. void
  933. do_return()
  934. {
  935.     REQUIRE_UNIT();
  936.     set_resupply_task(curunit, NONMTYPE);
  937. }
  938.  
  939. /* Stuff game state into a file.  By default, it goes into the current
  940.    directory.  If building a scenario, we can specify just which parts
  941.    of the game state are to be written. */
  942.  
  943. void
  944. do_save()
  945. {
  946.     char *rawcontents;
  947.     Module *module;
  948.     Obj *contents;
  949.  
  950. #ifdef DESIGNERS
  951.     if (dside->designer) {
  952.     if (ask_string("Data to write?", "everything", &rawcontents)) {
  953.         /* (should be in a designer_create_module?) */
  954.         /* need to be able to get this name from somewhere */
  955.         module = create_game_module("random.scn");
  956.         /* need something better to turn contents into a Lisp object */
  957.         contents = intern_symbol(rawcontents);
  958.         /*    interpret_content_spec(module, contents);  */
  959.         notify(dside, "Module will be written to \"%s\" ...", module->filename);
  960.         if (write_game_module(module)) {
  961.         notify(dside, "Done writing to \"%s\".", module->filename);
  962.         } else {
  963.         cmd_error("Can't open file \"%s\"!", module->filename);
  964.         }
  965.         return;
  966.     } else {
  967.         return;
  968.     }
  969.     }
  970. #endif /* DESIGNERS */
  971.     if (0 /* checkpointing not allowed */) {
  972.     if (ask_bool("You really want to save and exit?", FALSE)) {
  973.         notify(dside, "Game will be saved to \"%s\" ...", saved_game_filename());
  974.         if (write_entire_game_state(saved_game_filename())) {
  975.         close_displays();
  976.         /* this should be conditional? */
  977.         exit(0);
  978.         } else {
  979.         cmd_error("Can't open file \"%s\"!", saved_game_filename());
  980.         }
  981.     }
  982.     } else {
  983.     notify(dside, "Saving...");
  984.     if (write_entire_game_state(saved_game_filename())) {
  985.         notify(dside, "Game saved.");
  986.     } else {
  987.         cmd_error("Couldn't save to \"%s\"!", saved_game_filename());
  988.     }        
  989.     }
  990. }
  991.  
  992. void
  993. do_set_formation()
  994. {
  995.     Unit *leader;
  996.  
  997.     REQUIRE_UNIT();
  998.     sprintf(spbuf, "Which unit to follow?");
  999.     if (ask_unit(spbuf, &leader)) {
  1000.     if (!in_play(leader)) {
  1001.         cmd_error("No unit to follow!");
  1002.     } else if (leader == curunit) {
  1003.         cmd_error("Unit can't follow itself!");
  1004.     } else if (leader->side != dside /* or "trusted side"? */) {
  1005.         cmd_error("Can't follow somebody else's unit!");
  1006.     } else {
  1007.         set_formation(curunit, leader, curunit->x - leader->x, curunit->y - leader->y, 1, 1);
  1008.     }
  1009.     }
  1010. }
  1011.  
  1012. void
  1013. do_set_rate()
  1014. {
  1015.     int slow, fast;
  1016.     char *reststr;
  1017.  
  1018.     if (cmdargstr) {
  1019.     slow = strtol(cmdargstr, &reststr, 10);
  1020.     fast = strtol(reststr, &reststr, 10);
  1021.     set_play_rate(slow, fast);
  1022.     }
  1023. }
  1024.  
  1025. void
  1026. do_sleep()
  1027. {
  1028.     REQUIRE_UNIT();
  1029.     set_unit_asleep(dside, curunit, TRUE, TRUE);
  1030. }
  1031.  
  1032. void
  1033. do_standing_orders()
  1034. {
  1035.     int rslt;
  1036.  
  1037.     if (cmdargstr) {
  1038.     rslt = parse_standing_order(dside, cmdargstr);
  1039.     if (rslt < 0)
  1040.       xbeep();
  1041.     } else
  1042.       xbeep();
  1043. }
  1044.  
  1045. void
  1046. do_surrender_to()
  1047. {
  1048.     cmd_error("can't surrender to anybody yet");
  1049. }
  1050.  
  1051. /* Command to toggle between interaction modes. */
  1052.  
  1053. void
  1054. do_survey()
  1055. {
  1056.     if (mode == MOVE) {
  1057.     lastactor = curunit;
  1058.     mode = SURVEY;
  1059.     } else {
  1060.     mode = MOVE;
  1061.     /* If we weren't looking at a unit when we switched modes,
  1062.        go back to the last unit that was being moved. */
  1063.     if (curunit == NULL && in_play(lastactor)) {
  1064.         make_current(lastactor);
  1065.     }
  1066.     }
  1067.     show_map();
  1068.     refresh();
  1069. }
  1070.  
  1071. /* Take supplies from transport. */
  1072.  
  1073. void
  1074. do_take()
  1075. {
  1076.     int m, rslt;
  1077.     short amts[MAXMTYPES];
  1078.  
  1079.     REQUIRE_UNIT();
  1080.     rslt = take_supplies(curunit, NULL, amts);
  1081.     if (rslt) {
  1082.     spbuf[0] = '\0';
  1083.     for_all_material_types(m) {
  1084.         if (amts[m] > 0) {
  1085.         sprintf(tmpbuf, " %d %s", amts[m], m_type_name(m));
  1086.         strcat(spbuf, tmpbuf);
  1087.         }
  1088.     }
  1089.     notify(dside, "%s got%s.", unit_handle(dside, curunit), spbuf);
  1090.     } else {
  1091.     notify(dside, "%s got nothing.", unit_handle(dside, curunit));
  1092.     }
  1093. }
  1094.  
  1095. void
  1096. do_take_unit()
  1097. {
  1098.     cmd_error("can't take units yet");
  1099. }
  1100.  
  1101. void
  1102. do_trust()
  1103. {
  1104.     Side *side2;
  1105.  
  1106.     if (cmdargstr) {
  1107.     side2 = parse_side_spec(cmdargstr);
  1108.     if (side2 != NULL && side2 != dside) {
  1109.         set_trust(dside, side2, 1);
  1110.         return;
  1111.     } 
  1112.     }
  1113.     cmd_error("no side to trust");
  1114. }
  1115.  
  1116. /* Wake *everything* (that's ours) within the given radius.  Two commands
  1117.    actually; "top-level" units (not in a transport) vs all units. */
  1118.  
  1119. /* Wake top-level units. */
  1120.  
  1121. void
  1122. do_wake()
  1123. {
  1124.     wake_area(dside, curx, cury, prefixarg, FALSE);
  1125. }
  1126.  
  1127. /* Wake all units found. */
  1128.  
  1129. void
  1130. do_wake_all()
  1131. {
  1132.     wake_area(dside, curx, cury, prefixarg, TRUE);
  1133. }
  1134.  
  1135. /* Display the program version. */
  1136.  
  1137. void
  1138. do_version()
  1139. {
  1140.     notify(dside, "Curses Xconq version %s", version_string());
  1141.     notify(dside, "(c) %s", copyright_string());
  1142. }
  1143.  
  1144. void
  1145. do_warranty()
  1146. {
  1147.     cur_help_node = warranty_help_node;
  1148.     do_help();
  1149. }
  1150.  
  1151. /* Curses-specific commands. */
  1152.  
  1153. void
  1154. do_c_change_list_view()
  1155. {
  1156.     if (prefixarg < 0) {
  1157.     cycle_list_type();
  1158.     } else if (prefixarg == 0) {
  1159.     cycle_list_filter();
  1160.     } else if (prefixarg == 1) {
  1161.     cycle_list_order();
  1162.     }
  1163.     show_list();
  1164.     refresh();
  1165. }
  1166.  
  1167. /* Commands to change the dividing line between the right-hand and left-hand
  1168.    windows of the screen. */
  1169.  
  1170. void
  1171. do_c_grow_map()
  1172. {
  1173.     if (prefixarg < 0)
  1174.       prefixarg = 5;
  1175.     if (lw <= 5 && prefixarg > 0) {
  1176.     cmd_error("list side must be at least 5");
  1177.     return;
  1178.     }
  1179.     if (lw - prefixarg < 5)
  1180.       prefixarg = lw - 5;
  1181.     resize_map(prefixarg);
  1182. }
  1183.  
  1184. void
  1185. do_c_shrink_map()
  1186. {
  1187.     if (prefixarg < 0)
  1188.       prefixarg = 5;
  1189.     if (mw <= 10 && prefixarg > 0) {
  1190.     cmd_error("map side must be at least 10");
  1191.     return;
  1192.     }
  1193.     if (mw - prefixarg < 10)
  1194.       prefixarg = mw - 10;
  1195.     resize_map(0 - prefixarg);
  1196. }
  1197.  
  1198. static void
  1199. resize_map(n)
  1200. int n;
  1201. {
  1202.     /* Resize the left-hand-side windows. */
  1203.     mw += n;
  1204.     closeupwin->w += n;
  1205.     mapwin->w += n;
  1206.     /* Move and resize the right-hand-side windows. */
  1207.     lw -= n;
  1208.     sideswin->x += n;
  1209.     sideswin->w -= n;
  1210.     listwin->x += n;
  1211.     listwin->w -= n;
  1212.     /* Update the screen to reflect the changes. */
  1213.     set_scroll();
  1214.     redraw();
  1215. }
  1216.  
  1217. void
  1218. do_c_set_info_lines()
  1219. {
  1220.     if (prefixarg < 0)
  1221.       prefixarg = 5;
  1222.     if (prefixarg < 1)
  1223.       prefixarg = 1;
  1224.     if (prefixarg > 10)
  1225.       prefixarg = 10;
  1226.     infoh = prefixarg;
  1227.     mh = LINES - 2 - infoh - 1;
  1228.     closeupwin->h = infoh;
  1229.     mapwin->y = 2 + infoh;
  1230.     mapwin->h = mh;
  1231.     /* Update the screen to reflect the changes. */
  1232.     set_scroll();
  1233.     redraw();
  1234. }
  1235.  
  1236. void
  1237. do_c_run()
  1238. {
  1239.     int turns;
  1240.  
  1241.     turns = atoi(cmdargstr);
  1242.     notify(dside, "Running free for %d turn%s.",
  1243.        turns, (turns == 1 ? "" : "s"));
  1244.     if (turns > 0) {
  1245.     set_autofinish(dside, TRUE);
  1246.     autofinish_start = g_turn();
  1247.     autofinish_count = turns;
  1248.     }
  1249. }
  1250.  
  1251. /* Set the display of various kinds of data. */
  1252.  
  1253. void
  1254. do_c_show()
  1255. {
  1256.     int value;
  1257.     char *str, *str2, tmpbuf[BUFSIZE];
  1258.  
  1259.     if (cmdargstr) {
  1260.     str = cmdargstr;
  1261.     while (*str != '\0') {
  1262.         /* Collect the next whitespace-separated token from the
  1263.                arg string. */
  1264.         while (*str != '\0' && *str == ' ')
  1265.           ++str;
  1266.         str2 = tmpbuf;
  1267.         while (*str != '\0' && *str != ' ')
  1268.           *str2++ = *str++;
  1269.         *str2 = '\0';
  1270.         str2 = tmpbuf;
  1271.         value = TRUE;
  1272.         /* See if it is prefixed with a "-" or "no". */
  1273.         if (*str2 == '-') {
  1274.         value = FALSE;
  1275.         ++str2;
  1276.         } else if (*str2 == 'n' && *(str2+1) == 'o') {
  1277.         value = FALSE;
  1278.         str2 += 2;
  1279.         }
  1280.         if (strcmp(str2, "terrain") == 0 || strcmp(str2, "t") == 0) {
  1281.         drawterrain = value;
  1282.         } else if (strcmp(str2, "unit") == 0 || strcmp(str2, "u") == 0) {
  1283.         drawunits = value;
  1284.         } else if (strcmp(str2, "name") == 0 || strcmp(str2, "n") == 0) {
  1285.         drawnames = value;
  1286.         } else if (strcmp(str2, "people") == 0 || strcmp(str2, "p") == 0) {
  1287.         drawpeople = value;
  1288.         } else if (strcmp(str2, "one") == 0 || strcmp(str2, "1") == 0) {
  1289.         use_both_chars = !value;
  1290.         } else if (strcmp(str2, "two") == 0 || strcmp(str2, "2") == 0) {
  1291.         use_both_chars = value;
  1292.         } else if (strncmp(str2, "lin", 3) == 0) {
  1293.         drawlinear = value;
  1294.         if (value && str2[3] == '=' && str2[4] != '\0') {
  1295.             linear_char = str2[4];
  1296.         }
  1297.         } else {
  1298.         cmd_error("\"%s\" not recognized", tmpbuf);
  1299.         }
  1300.     }
  1301.     } else {
  1302.     notify(dside, "Nothing to do.");
  1303.     }
  1304.     show_map();
  1305.     refresh();
  1306. }
  1307.  
  1308. #ifdef DESIGNERS
  1309.  
  1310. static int check_designer_status PARAMS ((char *str));
  1311.  
  1312. /* The following commands are only available to designers. */
  1313.  
  1314. int curradius = 0;
  1315. int curttype = 0;
  1316. int curutype = 0;
  1317. int curfeature = 0;
  1318. int cursidenumber = 1;
  1319.  
  1320. static int
  1321. check_designer_status(str)
  1322. char *str;
  1323. {
  1324.     if (dside->designer) {
  1325.     return TRUE;
  1326.     } else {
  1327.     cmd_error("You're not a designer, can't %s!", str);
  1328.     return FALSE;
  1329.     }
  1330. }
  1331.  
  1332. void
  1333. do_design()
  1334. {
  1335.     if (!dside->designer) {
  1336.     become_designer(dside);
  1337.     } else {
  1338.     become_nondesigner(dside);
  1339.     }
  1340. }
  1341.  
  1342. void
  1343. do_gdl()
  1344. {
  1345.     if (cmdargstr)
  1346.       interp_form(NULL, read_form_from_string(cmdargstr, NULL, NULL));
  1347. }
  1348.  
  1349. void
  1350. do_c_set_unit_type()
  1351. {
  1352.     int u;
  1353.  
  1354.     if (!check_designer_status("set unit types to create"))
  1355.       return;
  1356.     u = ask_unit_type("Type of unit to create:", NULL);
  1357.     if (u != NONUTYPE) {
  1358.     curutype = u;
  1359.     if (prefixarg >= 0)
  1360.       cursidenumber = prefixarg;
  1361.     notify(dside, "will now be creating side %d %s units.",
  1362.            cursidenumber, u_type_name(u));
  1363.     }
  1364. }
  1365.  
  1366. void
  1367. do_c_add_unit()
  1368. {
  1369.     Unit *unit;
  1370.  
  1371.     if (!check_designer_status("create units"))
  1372.       return;
  1373.     unit = designer_create_unit(dside, curutype, cursidenumber, curx, cury);
  1374.     if (unit != NULL) {
  1375.     make_current(unit);
  1376.     } else {
  1377.     cmd_error("Unit creation failed!");
  1378.     }
  1379. }
  1380.  
  1381. void
  1382. do_c_set_terrain_type()
  1383. {
  1384.     int t;
  1385.  
  1386.     if (!check_designer_status("set ttypes to paint"))
  1387.       return;
  1388.     t = ask_terrain_type("Type of terrain:", NULL);
  1389.     if (t != NONTTYPE) {
  1390.     curttype = t;
  1391.     if (prefixarg >= 0)
  1392.       curradius = prefixarg;
  1393.     notify(dside, "will now be painting %d-radius %s.",
  1394.            curradius, t_type_name(t));
  1395.     }
  1396. }
  1397.  
  1398. /* Terrain painting command. */
  1399.  
  1400. void
  1401. do_c_paint_terrain()
  1402. {
  1403.     int t;
  1404.  
  1405.     /* (should ask for dir for linear types?) */
  1406.     if (!check_designer_status("paint terrain"))
  1407.       return;
  1408.     /* If command's arg is nonegative, interpret as temporary
  1409.        change of terrain type. */
  1410.     t = (prefixarg >= 0 ? prefixarg : curttype);
  1411.     paint_cell(dside, curx, cury, curradius, t);
  1412. }
  1413.  
  1414. /* (should add painting for all other layers here) */
  1415.  
  1416. #endif /* DESIGNERS */
  1417.  
  1418. #ifdef DEBUGGING
  1419.  
  1420. void
  1421. do_debug()
  1422. {
  1423. #ifndef Debug
  1424.     toggle_debugging(&Debug);
  1425. #endif
  1426. }
  1427.  
  1428. void
  1429. do_debugg()
  1430. {
  1431. #ifndef DebugG
  1432.     toggle_debugging(&DebugG);
  1433. #endif
  1434. }
  1435.  
  1436. void
  1437. do_debugm()
  1438. {
  1439. #ifndef DebugM
  1440.     toggle_debugging(&DebugM);
  1441. #endif
  1442. }
  1443.  
  1444. #endif /* DEBUGGING */
  1445.  
  1446. /* Generic command error routine just does a notify. */
  1447.  
  1448. static void
  1449. #ifdef __STDC__
  1450. cmd_error(char *fmt, ...)
  1451. #else
  1452. cmd_error(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  1453. char *fmt;
  1454. long a1, a2, a3, a4, a5, a6, a7, a8, a9;
  1455. #endif
  1456. {
  1457.     char tmpnbuf[BUFSIZE];
  1458.  
  1459. #ifdef __STDC__
  1460.     {
  1461.     va_list ap;
  1462.  
  1463.     va_start(ap, fmt);
  1464.     vsprintf(tmpnbuf, fmt, ap);
  1465.     va_end(ap);
  1466.     }
  1467. #else
  1468.     sprintf(tmpnbuf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  1469. #endif
  1470.     low_notify(dside, tmpnbuf);
  1471.     xbeep();
  1472. }
  1473.