|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 30185 (0x75e9) Types: TextFile Names: »do.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/X/Xconq/do.c«
/* Copyright (c) 1987, 1988 Stanley T. Shebs, University of Utah. */ /* This program may be used, copied, modified, and redistributed freely */ /* for noncommercial purposes, so long as this notice remains intact. */ /* RCS $Header: do.c,v 1.1 88/06/21 12:30:06 shebs Exp $ */ /* This file contains almost all command functions. */ /* Help commands are in a separate file. */ #include "config.h" #include "misc.h" #include "dir.h" #include "period.h" #include "side.h" #include "unit.h" #include "map.h" #include "global.h" extern bool delaymove; char *grok_string(); bool reconfig; /* true when an option needs screen reconfigured */ bool remap; /* true when only main map needs redrawing */ bool reinfo; /* true when only info display needs redrawing */ bool tmparea = TRUE; /* true for area painting, false for bar painting */ /* Things will be totally scrogged if two human players in build mode... */ int tmpterr = 0; /* temporary terrain type for area operation */ int tmpdist = 0; /* temporary argument for painting */ int tmpflag; /* temporary int for area operation */ /* Move in given direction a given distance - used for both single and */ /* automatic multiple moves. */ do_dir(side, dir, n) Side *side; int dir, n; { if (side->teach) { cache_movedir(side, dir, n); } else { switch (side->mode) { case MOVE: if (side->curunit != NULL) order_movedir(side->curunit, dir, n); break; case SURVEY: move_survey(side, wrap(side->curx + n*dirx[dir]), side->cury + n*diry[dir]); break; default: case_panic("mode", side->mode); } } } /* Wake *everything* (that's ours) within the given radius. Two commands */ /* actually; lowercase is transports only, uppercase is everybody. */ do_wakeup(side, n) Side *side; int n; { if (side->teach) { cache_awake(side, 1); } else { wakeup_area(side, n, TRUE); } } /* Wake up only the main/current unit in a hex. */ do_wakemain(side, n) Side *side; int n; { if (side->teach) { cache_awake(side, 1); } else { wakeup_area(side, n, FALSE); } } /* The area wakeup. */ wake_at(x, y) int x, y; { Unit *unit = unit_at(x, y); if (unit != NULL && (unit->side == tmpside || Build)) wake_unit(unit, tmpflag); } wakeup_area(side, n, occs) Side *side; int n, occs; { tmpside = side; tmpflag = occs; apply_to_area(side->curx, side->cury, n, wake_at); } /* Put unit to sleep for a while. If we sleep it next to something that */ /* might wake it up, then adjust flags so it won't wake up on next turn. */ do_sentry(side, unit, n) Side *side; Unit *unit; int n; { if (side->teach) { cache_sentry(side, n); } else { order_sentry(unit, n); if (n > 1 && adj_enemy(unit)) unit->orders.flags &= ~(ENEMYWAKE|NEUTRALWAKE); } } /* Don't move for remainder of turn, but be awake next turn. This also */ /* hooks into terrain painting, since the space bar is big and convenient. */ do_sit(side, n) Side *side; int n; { if (side->mode == SURVEY && Build) { paint_terrain(side); } else if (side->curunit != NULL) { do_sentry(side, side->curunit, 1); } else { cmd_error(side, "No unit to operate on here!"); } } /* Set unit to move to a given location. */ x_moveto(side) Side *side; { if (grok_position(side)) { if (side->teach) { cache_moveto(side, side->reqposx, side->reqposy); } else if (Build) { leave_hex(side->requnit); occupy_hex(side->requnit, side->reqposx, side->reqposy); make_current(side, side->requnit); all_see_hex(side->curx, side->cury); } else { order_moveto(side->requnit, side->reqposx, side->reqposy); } restore_cur(side); } else { request_input(side, side->requnit, x_moveto); } } /* The command proper. */ do_moveto(side, unit, n) Side *side; Unit *unit; int n; { ask_position(side, "Move to where?"); request_input(side, unit, x_moveto); side->reqposx = side->curx; side->reqposy = side->cury; } /* Auxiliary stuff used when searching for place to return to. Note that */ /* a good refueling spot will be woken up, so it won't get too far away */ /* before unit has a chance to get there. */ /* Won't find refueling places inside other units, sigh. */ refuel_here(x, y) int x, y; { Unit *unit = unit_at(x, y); if (unit != NULL && unit->side == tmpside && can_carry(unit, tmpunit)) { wake_unit(unit, FALSE); return TRUE; } return FALSE; } /* Search for a friendly refueler within range and set course for it. */ /* Warn player and refuse to move if nothing close enough. */ do_return(side, unit, n) Side *side; Unit *unit; int n; { int x, y, u = unit->type, r, range = max(world.width, world.height); for_all_resource_types(r) { if (utypes[u].tomove[r] > 0) { range = min(range, unit->supply[r] / utypes[u].tomove[r]); } } tmpside = side; tmpunit = unit; if (search_area(unit->x, unit->y, range, refuel_here, &x, &y)) { if (unit->x != x || unit->y != y) { order_moveto(unit, x, y); unit->orders.flags = SHORTESTPATH; } else { cmd_error(side, "Already at a resupply point!"); } } else { cmd_error(side, "No resupply point in range!"); } } /* Set unit to attempt to follow a coast. Needs a starting direction, */ /* which can be computed from a position. */ x_coast(side) Side *side; { int dir; if (grok_position(side)) { if (side->curx != side->reqposx || side->cury != side->reqposy) { dir = find_dir(side->reqposx - side->curx, side->reqposy - side->cury); if (side->teach) { cache_edge(side, dir, side->reqvalue2); } else { order_edge(side->requnit, dir, side->reqvalue2); } restore_cur(side); } else { cmd_error(side, "No particular direction at own hex??"); } } else { request_input(side, side->requnit, x_coast); } } /* The command proper just sets up the interaction. */ do_coast(side, unit, n) Side *side; Unit *unit; int n; { ask_position(side, "Move in which direction?"); request_input(side, unit, x_coast); side->reqposx = side->curx; side->reqposy = side->cury; side->reqvalue2 = n; } /* Set orders to follow a leader unit. */ x_follow(side) Side *side; { Unit *leader; if (grok_position(side)) { if ((leader = unit_at(side->reqposx, side->reqposy)) != NULL && leader->side == side) { if (leader != side->requnit) { if (side->teach) { cache_follow(side, leader, side->reqvalue2); } else { order_follow(side->requnit, leader, side->reqvalue2); } } else { cmd_error(side, "Unit can't follow itself!"); } } else { cmd_error(side, "No unit to follow!"); } restore_cur(side); } else { request_input(side, side->requnit, x_follow); } } /* The command proper. */ do_follow(side, unit, n) Side *side; Unit *unit; int n; { ask_position(side, "Which unit to follow?"); request_input(side, unit, x_follow); side->reqposx = side->curx; side->reqposy = side->cury; side->reqvalue2 = n; } /* Patrolling goes back and forth between two points. First point is the */ /* current position. */ x_patrol(side) Side *side; { if (grok_position(side)) { if (side->teach) { cache_patrol(side, side->sounit->x, side->sounit->y, side->reqposx, side->reqposy, side->reqvalue2); } else { order_patrol(side->requnit, side->requnit->x, side->requnit->y, side->reqposx, side->reqposy, side->reqvalue2); } restore_cur(side); } else { request_input(side, side->requnit, x_patrol); } } /* The command proper. */ do_patrol(side, unit, n) Side *side; Unit *unit; int n; { ask_position(side, "What other endpoint for patrol?"); request_input(side, unit, x_patrol); side->reqposx = side->curx; side->reqposy = side->cury; side->reqvalue2 = n; } /* Delay a unit's move until a later time. The set flag will be recognized */ /* by the movement loops, when deciding which unit to move next. */ do_delay(side, unit, n) Side *side; Unit *unit; int n; { delaymove = TRUE; notify(side, "Delaying moving %s.", unit_handle(side, unit)); } /* Get rid of unit. Some units cannot be disbanded, but if they can, the */ /* resources go to a transport if one is there. Disbanding a transport */ /* also disbands all the occupants - oh well. */ do_disband(side, unit, n) Side *side; Unit *unit; int n; { int u = unit->type; if (utypes[u].disband || Build) { notify(side, "%s goes home.", unit_handle(side, unit)); if (unit->transport != NULL) recycle_unit(unit, unit->transport); kill_unit(unit, DISBAND); make_current(side, unit_at(side->curx, side->cury)); } else { cmd_error(side, "You can't just get rid of the %s!", utypes[u].name); } } /* Reclaim both the unit's supplies and anything used in its making, but */ /* only let a maker of the unit reclaim its ingredients. */ recycle_unit(unit, unit2) Unit *unit, *unit2; { int u = unit->type, u2 = unit2->type, r, scrap; for_all_resource_types(r) { transfer_supply(unit, unit2, r, unit->supply[r]); if (could_make(u2, u) > 0) { scrap = utypes[u].tomake[r]; unit2->supply[r] += (scrap * period.efficiency) / 100; } } } /* Give a unit to another side (possibly to neutrals). Units that won't */ /* change their sides when captured won't change voluntarily either. */ do_give_unit(side, unit, n) Side *side; Unit *unit; int n; { int u = unit->type; if (utypes[u].changeside || Build) { unit_changes_side(unit, side_n(n), CAPTURE, PRISONER); all_see_hex(unit->x, unit->y); } else { cmd_error(side, "You can't just give away the %s!", utypes[u].name); } } /* Marking is for the purpose of rearranging units within a hex. */ do_mark_unit(side, unit, n) Side *side; Unit *unit; int n; { side->markunit = unit; notify(side, "%s has been marked.", unit_handle(side, unit)); } /* This is a clever (if I do say so myself) command to examine all occupants */ /* and suboccupants, in a preorder fashion. */ do_occupant(side, unit, n) Side *side; Unit *unit; int n; { Unit *nextup; switch (side->mode) { case MOVE: cmd_error(side, "Can only look at occupants when in survey mode!"); break; case SURVEY: if (unit->occupant != NULL) { make_current(side, unit->occupant); } else if (unit->nexthere != NULL) { make_current(side, unit->nexthere); } else { nextup = unit->transport; if (nextup != NULL) { while (nextup->transport != NULL && nextup->nexthere == NULL) { nextup = nextup->transport; } if (nextup->nexthere != NULL) make_current(side, nextup->nexthere); if (nextup->transport == NULL) make_current(side, nextup); } } break; default: case_panic(side->mode, "mode"); break; } } /* This can actually do general rearrangement, but defaults to putting the */ /* unit on the first available transport in the hex. */ /* What about trying to embark a unit on itself or on its previous transp? */ do_embark(side, unit, n) Side *side; Unit *unit; int n; { Unit *mainunit = unit_at(side->curx, side->cury); Unit *transport = NULL; if (mainunit != unit) { if (side->markunit == NULL || side->markunit->x != unit->x || side->markunit->y != unit->y) { for_all_occupants(mainunit, transport) { if (can_carry(transport, unit)) break; } } else { transport = side->markunit; } if (transport != NULL) { leave_hex(unit); occupy_unit(unit, transport); } else { cmd_error(side, "No plausible transport!"); } } else { cmd_error(side, "Nothing for this unit to get into!"); } } /* Give supplies to a transport. The argument tells how many to give. */ do_give(side, unit, n) Side *side; Unit *unit; int n; { bool something = FALSE; int u = unit->type, m, r, gift, actual; Unit *main = unit->transport; if (main != NULL) { sprintf(spbuf, ""); m = main->type; for_all_resource_types(r) { gift = (n < 0 ? utypes[m].storage[r] - main->supply[r] : n); if (gift > 0) { something = TRUE; /* Be stingy if we're low */ if (2 * unit->supply[r] < utypes[u].storage[r]) gift = max(1, gift/2); actual = transfer_supply(unit, main, r, gift); sprintf(tmpbuf, " %d %s", actual, rtypes[r].name); strcat(spbuf, tmpbuf); } } if (something) { notify(side, "%s gave%s.", unit_handle(side, unit), spbuf); } else { notify(side, "%s gave nothing.", unit_handle(side, unit)); } } else { cmd_error(side, "Can't transfer supplies here!"); } } /* Take supplies from transport. Both the transport must have something */ /* left. */ do_take(side, unit, n) Side *side; Unit *unit; int n; { bool something = FALSE; int u = unit->type, m, r, need, actual; Unit *main = unit->transport; if (main != NULL) { sprintf(spbuf, ""); m = main->type; for_all_resource_types(r) { need = (n < 0 ? utypes[u].storage[r] - unit->supply[r] : n); if (need > 0) { something = TRUE; /* Be stingy if we're low */ if (2 * main->supply[r] < utypes[m].storage[r]) need = max(1, need/2); actual = transfer_supply(main, unit, r, need); sprintf(tmpbuf, " %d %s", actual, rtypes[r].name); strcat(spbuf, tmpbuf); } } if (something) { notify(side, "%s got%s.", unit_handle(side, unit), spbuf); } else { notify(side, "%s needed nothing.", unit_handle(side, unit)); } } else { cmd_error(side, "Can't transfer supplies here!"); } } /* Take the current player out of the game while letting everybody else */ /* continue on. */ x_resign(side) Side *side; { if (grok_bool(side)) resign_game(side, side->reqoside); } do_resign(side, n) Side *side; int n; { ask_bool(side, "Do you really want to give up?", FALSE); request_input(side, NULL, x_resign); side->reqoside = side_n(n); } /* Unconditional resignation - usable by everybody. */ resign_game(side, side2) Side *side, *side2; { notify_all("Those wimpy %s have given up!", plural_form(side->name)); if (side2 != NULL) { notify_all("... and they gave all their stuff to the %s!", plural_form(side2->name)); } side_loses(side, side2); } /* Leave quickly when the boss walks by. One person can kill a multi-player */ /* game, which isn't too great, but the alternatives are complicated. */ /* The stats file will be left behind, to foment argument about who would */ /* have won... This routine also includes a trapdoor for freezing/unfreezing */ /* machine players when building - mode display will invert to confirm this. */ x_exit(side) Side *side; { Unit *unit; if (grok_bool(side)) { close_displays(); printf("\nThe outcome remains undecided"); if (numhumans == 1 && side->humanp) { printf(", but you're probably the loser!\n\n", side->host); } else { printf("...\n\n"); } /* Need to kill off all units to finish up statistics */ for_all_units(unit) if (alive(unit)) kill_unit(unit, ENDOFWORLD); print_statistics(); exit(0); } if (Build) { Freeze = !Freeze; show_timemode(side); } } do_exit(side, n) Side *side; int n; { ask_bool(side, "Do you REALLY want to end the game for EVERYBODY?", FALSE); request_input(side, NULL, x_exit); } /* Stuff game state into a file. By default, it goes into the current */ /* directory. If building a scenario, will ask about each section, values */ /* of globals, and dest file before actually writing anything. */ /* No capability to write out period at present... */ x_save_1(side) Side *side; { char *sects, *fname; int sdetail = 1, udetail = 1; if ((sects = grok_string(side)) != NULL) { fname = "random.scn"; sprintf(spbuf, "------"); if (iindex('v', sects) >= 0) spbuf[0] = '+'; if (iindex('p', sects) >= 0) spbuf[1] = '+'; if (iindex('m', sects) >= 0) spbuf[2] = '+'; if (iindex('g', sects) >= 0) spbuf[3] = '+'; if (iindex('s', sects) >= 0) spbuf[4] = '+'; if (iindex('u', sects) >= 0) spbuf[5] = '+'; if (iindex('s', sects) >= 0) { sdetail = 1; if (isdigit(sects[iindex('s', sects)+1])) sdetail = sects[iindex('s', sects)+1] - '0'; } if (iindex('u', sects) >= 0) { udetail = 1; if (isdigit(sects[iindex('u', sects)+1])) udetail = sects[iindex('u', sects)+1] - '0'; } notify(side, "Mapfile with sections %s will be saved to \"%s\" ...", spbuf, fname); if (write_scenario(fname, spbuf, sdetail, udetail)) { notify(side, "Done writing to \"%s\".", fname); } else { cmd_error(side, "Can't open file \"%s\"!", fname); } } else { request_input(side, NULL, x_save_1); } } /* Make a header appropriate to a save file, write the file, and leave. */ x_save_2(side) Side *side; { if (grok_bool(side)) { notify_all("Game will be saved to \"%s\" ...", SAVEFILE); if (write_savefile(SAVEFILE)) { close_displays(); exit(0); } else { cmd_error(side, "Can't open file \"%s\"!", SAVEFILE); } } } /* The command proper just sets up different handlers, depending on */ /* whether we're building (and therefore saving a scenario/fragment), or */ /* saving as much game state as possible, for resumption later. */ do_save(side, n) Side *side; int n; { if (Build) { ask_string(side, "Sections to write?", "ms1u1"); request_input(side, NULL, x_save_1); } else { ask_bool(side, "You really want to save?", FALSE); request_input(side, NULL, x_save_2); } } /* Redraw everything using the same code as when windows need a redraw. */ do_redraw(side, n) Side *side; int n; { redraw(side); } /* Name or rename the current unit or a given side. We make a copy of the */ /* string after it's been successfully read, just in case. */ x_name(side) Side *side; { char *name; Side *side2; if ((name = grok_string(side)) == NULL) { request_input(side, side->requnit, x_name); } else if (strlen(name) == 0) { notify(side, "Name not changed."); } else if (side->requnit != NULL) { side->requnit->name = copy_string(name); } else if (side->reqoside != NULL) { side->reqoside->name = copy_string(name); for_all_sides(side2) show_all_sides(side2); } else { cmd_error(side, "Nothing to name!"); } } /* The command proper decides between unit and side naming. */ do_name(side, n) Side *side; int n; { if (side->curunit != NULL) { ask_string(side, "New name for unit:", side->curunit->name); } else { ask_string(side, "New name for yourself:", side->name); side->reqoside = side; } request_input(side, side->curunit, x_name); } /* Designate the current location as the center of action and sort all */ /* of our own units relative to it. */ do_center(side, n) Side *side; int n; { side->cx = side->curx; side->cy = side->cury; sort_units(); notify(side, "Units reordered."); } /* Hook command to set miscellaneous options. Can't do from command line */ /* because each display may want different behavior. This routine can */ /* change the display dramatically, but it should only redraw if a change */ /* has actually been made. */ /* Conversion to machine player is irreversible, so we confirm it first. */ x_options_2(side) Side *side; { if (grok_bool(side)) { side->humanp = !side->humanp; numhumans--; init_sighandlers(); } } x_options(side) Side *side; { int n = side->reqvalue2; char opt; if ((opt = grok_char(side)) != '\0') { switch (opt) { case '?': notify(side, "Change (D)isplay Mode, (G)raph, Win (H)eight,"); notify(side, "(I)nverse Video, (M)onochrome, (N)otice Buffer"); notify(side, "(R)obot, Win (W)idth"); break; case 'd': remap = TRUE; side->showmode = (side->showmode + 1) % 4; break; case 'g': reinfo = TRUE; side->graphical = !side->graphical; break; case 'h': if (n < 5 || n > world.height) { cmd_error(side, "Bad height %d!", n); } else { if (n != side->vh) reconfig = TRUE; side->vh = n; } break; case 'i': if (side->monochrome) { reconfig = TRUE; side->bonw = !side->bonw; } else { cmd_error(side, "Inverse video is only for monochrome!"); } break; case 'm': reconfig = TRUE; side->monochrome = !side->monochrome; side->bonw = FALSE; break; case 'n': if (n < 1 || n > MAXNOTES) { cmd_error(side, "Bad number of notes %d!", n); } else { if (n != side->nh) reconfig = TRUE; side->nh = n; } break; case 'r': if (side->mode == MOVE) { ask_bool(side, "Do you really want to become a machine?", FALSE); request_input(side, NULL, x_options_2); return; } else { cmd_error(side, "Must be in move mode!"); } break; case 'w': if (n < 5 || n > world.width || n > BUFSIZE) { cmd_error(side, "Bad width %d!", n); } else { if (n != side->vw) reconfig = TRUE; side->vw = n; } break; default: cmd_error(side, "unrecognized option '%c'", opt); break; } if (remap) { undraw_box(side); show_map(side); } if (reinfo) show_info(side); if (reconfig) reconfigure_display(side); } else { request_input(side, NULL, x_options); } } /* The command proper. */ do_options(side, n) Side *side; int n; { reinfo = remap = reconfig = FALSE; ask_char(side, "Options:", "dghimnrw"); request_input(side, NULL, x_options); side->reqvalue2 = n; } /* Set standing orders for a unit of a given type that enters a given city. */ /* Space for standing orders is dynamically allocated the first time we */ /* request some orders. */ x_standing_1(side) Side *side; { int type; if ((type = grok_unit_type(side)) >= 0) { if (type != NOTHING) get_standing_order(side, type); } else { request_input(side, side->requnit, x_standing_1); } } /* The command proper starts the ball rolling by prompting for the type */ /* of unit that will get standing orders. Of course, if a unit is not of */ /* a type that has occupants, standing orders are pretty useless. Also, */ /* if only one type of occupant is possible, then no need to ask. */ do_standing(side, unit, n) Side *side; Unit *unit; int n; { int u; u = ask_unit_type(side, "Type of occupant to get standing orders", utypes[unit->type].capacity); if (u < 0) { show_standing_orders(side, unit); request_input(side, unit, x_standing_1); side->sounit = unit; } else if (u == NOTHING) { cmd_error(side, "This unit never has occupants to give orders to!"); } else { show_standing_orders(side, unit); get_standing_order(side, u); } } /* A standing order is acquired by snarfing the next order and saving it */ /* rather than applying it to some unit. */ get_standing_order(side, type) Side *side; int type; { if (side->requnit->standing == NULL) { side->requnit->standing = (StandingOrder *) malloc(sizeof(StandingOrder)); } side->teach = TRUE; side->soutype = type; side->tmporder = (Order *) malloc(sizeof(Order)); notify(side, "Next input order will become the standing order."); show_timemode(side); request_command(side); } /* Survey mode allows player to look around (and change things) by moving */ /* cursor. The same command toggles in and out, so need a case statement. */ /* Players waiting their turn will be in survey mode, but can't get out. */ do_survey_mode(side, n) Side *side; int n; { switch (side->mode) { case MOVE: survey_mode(side); break; case SURVEY: if (side == curside) { move_mode(side); } else { cmd_error(side, "Not your turn yet!"); } break; default: case_panic("mode", side->mode); } } /* Change what a unit is producing. */ do_product(side, unit, n) Side *side; Unit *unit; int n; { if (!global.setproduct) { cmd_error(side, "No construction changes allowed in this game!"); } else { if (!can_produce(unit)) { cmd_error(side, "This unit can't build anything!"); } else { if (!utypes[unit->type].maker) { wake_unit(unit, FALSE); } request_new_product(unit); } } } /* Set a unit to not produce anything (yes, this really is useful). */ do_idle(side, unit, n) Side *side; Unit *unit; int n; { if (!global.setproduct) { cmd_error(side, "No production changes allowed in this scenario!"); } else { set_product(unit, NOTHING); unit->schedule = n; show_info(side); } } /* Send a short (1 line) message to another player. Some messages are */ /* recognized specially, causing various actions. */ x_message(side) Side *side; { char *msg; Side *side3; if ((msg = grok_string(side)) != NULL) { if (side->reqoside == NULL) { if (msg != NULL && strlen(msg) > 0) { notify_all("The %s announce: %s", plural_form(side->name), msg); } } else if (strcmp(msg, "briefing") == 0) { notify(side->reqoside, "Receiving a briefing from the %s...", plural_form(side->name)); reveal_side(side, side->reqoside, 100); notify(side, "You just briefed the %s on your position.", plural_form(side->reqoside->name)); } else if (strcmp(msg, "alliance") == 0) { notify(side, "You propose a formal alliance with the %s.", plural_form(side->reqoside->name)); side->attitude[side_number(side->reqoside)] = ALLY; if (side->reqoside->attitude[side_number(side)] >= ALLY) { declare_alliance(side, side->reqoside); for_all_sides(side3) redraw(side3); } else { notify(side->reqoside, "The %s propose a formal alliance.", plural_form(side->name)); } } else if (strcmp(msg, "neutral") == 0) { notify(side, "You propose neutrality with the %s.", plural_form(side->reqoside->name)); side->attitude[side_number(side->reqoside)] = NEUTRAL; if (side->reqoside->attitude[side_number(side)] == NEUTRAL) { declare_neutrality(side, side->reqoside); for_all_sides(side3) redraw(side3); } else { notify(side->reqoside, "The %s propose neutrality.", plural_form(side->name)); } } else if (strcmp(msg, "war") == 0) { notify(side, "You declare war on the %s!", plural_form(side->reqoside->name)); declare_war(side, side->reqoside); for_all_sides(side3) redraw(side3); } else if (strlen(msg) > 0) { notify(side->reqoside, "The %s say to you: %s", plural_form(side->name), msg); } else { notify(side, "You keep your mouth shut."); } } else { request_input(side, NULL, x_message); } } /* The command proper. */ do_message(side, n) Side *side; int n; { char prompt[BUFSIZE]; Side *side2; side2 = side_n(n); side->reqoside = side2; if (side != side2) { if (side2) { sprintf(prompt, "Say to the %s: ", plural_form(side2->name)); } else { sprintf(prompt, "Broadcast: "); } ask_string(side, prompt, NULL); request_input(side, NULL, x_message); } else { cmd_error(side, "You mumble to yourself."); } } /* Add a new player to the game. */ /* Should use arg to decide whether to convert machine player (or just */ /* use if available?) Also needs to decide if new player is human and */ /* which host to open, then go through side's startup seq and open disp. */ /* Issues of cached values (?) and war/alliance setup and uses of numsides. */ do_add_player(side, n) Side *side; int n; { notify(side, "Sorry, can't add new players yet!"); } /* Command to display the program version. Looks wired in, but of course */ /* this is not something that we want to be easily changeable! */ /* This will also show data about other sides. */ do_version(side, n) Side *side; int n; { notify(side, " "); notify(side, "XCONQ version %s", version); notify(side, "(c) Copyright 1987, 1988 Stanley T. Shebs, University of Utah"); notify(side, " "); if (Debug || Build) reveal_side(NULL, side, 100); } /* Create any unit anywhere. It gets the usual initial supply, and its */ /* current side is also its true side (i.e. it will never revolt). */ x_unit(side) Side *side; { int u; Unit *unit; if ((u = grok_unit_type(side)) >= 0) { if (u != NOTHING) { unit = create_unit(u, NULL); occupy_hex(unit, side->curx, side->cury); init_supply(unit); unit_changes_side(unit, side->reqoside, -1, -1); unit->trueside = unit->side; make_current(side, unit); all_see_hex(side->curx, side->cury); } } else { ask_unit_type(side, "Type of unit to create?", NULL); request_input(side, NULL, x_unit); } } /* The command function proper, which only works in Build mode. */ do_unit(side, n) Side *side; int n; { if (Build) { if (unit_at(side->curx, side->cury) == NULL) { ask_unit_type(side, "Type of unit to create?", NULL); side->reqoside = side_n(n); request_input(side, NULL, x_unit); } else { cmd_error(side, "Unit already here!"); } } else { cmd_error(side, "Not building a mapfile!"); } } /* Terrain editing alters a hexagonal area of given radius. If only one */ /* hex changed (the default), just update that alone; otherwise, go ahead */ /* and redraw everything. */ /* The command itself just sets up what will be drawn. */ do_terrain(side, terr, n) Side *side; int terr, n; { tmpterr = terr; tmpdist = min(abs(n), world.width); tmparea = (n >= 0); notify(side, "Will now paint %d hex %s of %s.", tmpdist, (tmparea ? "radius areas" : "bars"), ttypes[tmpterr].name); } /* Function to change just one hex and to echo that change. */ /* Don't need to make it show instantly, can wait. */ set_one_hex(x, y) int x, y; { set_terrain_at(x, y, tmpterr); see_exact(tmpside, x, y); draw_hex(tmpside, x, y, FALSE); } /* Painting operation is activated by the "sit" command. */ paint_terrain(side) Side *side; { int i; tmpside = side; if (tmparea) { apply_to_area(side->curx, side->cury, tmpdist, set_one_hex); } else { for (i = 0; i < tmpdist; ++i) set_one_hex(wrap(side->curx + i), side->cury); } } /* Generic command error routine - beeps display etc. */ /*VARARGS*/ cmd_error(side, control, a1, a2, a3, a4, a5, a6) Side *side; char *control, *a1, *a2, *a3, *a4, *a5, *a6; { notify(side, control, a1, a2, a3, a4, a5, a6); if (active_display(side)) beep(side); }