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 / kernel / mplayer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  93.5 KB  |  3,233 lines  |  [TEXT/R*ch]

  1. /* Implementation of the "mplayer" AI in Xconq.
  2.    Copyright (C) 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 int xmalloc_warnings;
  12.  
  13. /* Limit on the number of goals that a side may have. */
  14.  
  15. #define MAXGOALS 10
  16.  
  17. /* Limit on the number of theaters a single side may have. */
  18.  
  19. #define MAXTHEATERS 98
  20.  
  21. /* what does the game look like? */
  22. typedef enum a_game_class {
  23.     gc_none,
  24.     gc_standard,
  25.     gc_time
  26. } GameClass;
  27.  
  28. static GameClass game_class = gc_none;
  29.  
  30. /* Strategy is what a side uses to make decisions. */
  31.  
  32. typedef struct a_strategy {
  33.     int type;            /* placeholder */
  34.     int trytowin;
  35.     int creationdate;
  36.     short strengths[MAXSIDES][MAXUTYPES];  /* estimated numbers of units */
  37.     short points[MAXSIDES];    /* estimated point value */
  38.     short alstrengths[MAXSIDES][MAXUTYPES];  /* numbers in alliances */
  39.     short alpoints[MAXSIDES];    /* points in alliances */
  40.     short initial_strengths_computed;
  41.     short strengths0[MAXSIDES][MAXUTYPES];  /* initial estimated numbers of units */
  42.     short points0[MAXSIDES];    /* initial estimated point value */
  43.     short alstrengths0[MAXSIDES][MAXUTYPES];  /* initial numbers in alliances */
  44.     short alpoints0[MAXSIDES];    /* initial points in alliances */
  45.     short contacted[MAXSIDES+1];
  46.     short homefound[MAXSIDES+1];
  47.     int analyzegame;
  48.     struct a_theater *theaters;
  49.     struct a_theater **theatertable;
  50.     short numtheaters;
  51.     char *areatheaters;
  52.     struct a_theater *homefront;
  53.     struct a_theater *perimeters[NUMDIRS];
  54.     struct a_theater *midranges[NUMDIRS];
  55.     struct a_theater *remotes[NUMDIRS];
  56.     int numgoals;
  57.     struct a_goal *goals[MAXGOALS];
  58.     /* Exploration and search slots. */
  59.     int zonewidth, zoneheight;
  60.     int numzonex, numzoney;     /* dimensions of search zone array */
  61.     int numzones;
  62.     struct a_searchzone *searchzones;
  63.     short *explorertypes;
  64.     short explorersneeded;
  65.     short *terrainguess;
  66.     short cx, cy;               /* "centroid" of all our units */
  67.     short *demand;              /* worth of each utype w.r.t. strategy */
  68.     int explore_priority;
  69.     int defend_priority;
  70.     int attack_priority;
  71.     struct a_unit *unitlist[MAXUTYPES];   /* lists to help mplay efficiency */
  72.     short unitlistcount[MAXUTYPES];  /* counts of above lists */
  73.     short *actualmix;
  74.     short *expectedmix;
  75.     short *idealmix;
  76.     short *research_status;  /* specific to the "time" game */
  77.     short *research_on;      /* specific to the "time" game */
  78.     Obj *writable_state;
  79. } Strategy;
  80.  
  81. /* utype-specific research status codes for the "time" game */
  82. #define RS_RESEARCH_NEEDED 4
  83. #define RS_RESEARCH_ASSIGNED 3
  84. #define RS_UPGRADE_NEEDED 1
  85.  
  86. #define mplayer(s) ((Strategy *) (s)->ai)
  87.  
  88. /* A Theater is a sub-area that can be planned for all at once. */
  89.  
  90. /* To save space in theater layer, no more than 127 theaters may exist at once.
  91.    This should be sufficient, even a Napoleon would have trouble keeping track
  92.    of that much activity. */
  93.  
  94. typedef struct a_theater {
  95.     short id;
  96.     char *name;            /* an informative name for this theater */
  97.     short x, y;            /* center of the theater */
  98.     short xmin, ymin;        /*  */
  99.     short xmax, ymax;        /*  */
  100.     int size;            /* number of cells in the theater */
  101.     short importance;        /* 0 = shrug, 100 = critical */
  102.     Goal *maingoal;
  103.     short allied_units;        /* How many units on our side here. */
  104.     short makers;        /* Total number of makers */
  105.     short unexplored;        /* number of unseen cells in theater */
  106.     short allied_bases;        /* total number of our bases, includes towns */
  107.     short border;        /* true if this is a border theater. */
  108.     short reinforce;        /* priority on request for units. */
  109.     short numassigned[MAXUTYPES];  /* num of each type assigned to theater */
  110.     short numneeded[MAXUTYPES];  /* units we should move to theater. */
  111.     short numtotransport[MAXUTYPES];  /* types needing transportation. */
  112.     short numenemies[MAXUTYPES];
  113.     short numsuspected[MAXUTYPES];
  114.     short numsuspectedmax[MAXUTYPES];
  115.     int *people;        /* number of populated cells seen */
  116.     int enemystrengthmin;    /* estimate of enemy unit strength */
  117.     int enemystrengthmax;    /* estimate of enemy unit strength */
  118.     short units_lost;        /* How many units have we lost here. */
  119.     struct a_theater *next;
  120. } Theater;
  121.  
  122. #define for_all_theaters(s,th)  \
  123.   for ((th) = mplayer(s)->theaters; (th) != NULL; (th) = (th)->next)
  124.  
  125. #define theater_at(s,x,y)  \
  126.   (mplayer(s)->theatertable[mplayer(s)->areatheaters[(x)+area.width*(y)]])
  127.  
  128. #define set_theater_at(s,x,y,th)  \
  129.   ((mplayer(s)->areatheaters[(x)+area.width*(y)]) = (th)->id)
  130.  
  131. #define for_all_cells_in_theater(s,x,y,th)  \
  132.   for ((x) = theater->xmin; (x) < theater->xmax; ++(x))  \
  133.     for ((y) = theater->ymin; (y) < theater->ymax; ++(y))  \
  134.       if (theater_at((s), (x), (y)) == (th)
  135.  
  136. #define unit_theater(unit) ((Theater *) (unit)->aihook)
  137.  
  138. #define set_unit_theater(unit,theater) ((unit)->aihook = (char *) (theater))
  139.  
  140. #define can_see_actual_units(side, x, y) (all_see_all || cover((side), (x), (y)) > 0)
  141.  
  142. /* Local function declarations. */
  143.  
  144. static void mplayer_init PARAMS ((Side *side));
  145. static void mplayer_init_turn PARAMS ((Side *side));
  146. static void create_strategy PARAMS ((Side *side));
  147. static void reset_strategy PARAMS ((Side *side));
  148. static void analyze_the_game PARAMS ((Side *side));
  149. static void determine_subgoals PARAMS ((Side *side));
  150. static void review_theaters PARAMS ((Side *side));
  151. static void create_initial_theaters PARAMS ((Side *side));
  152. static Theater *create_theater PARAMS ((Side *side));
  153. static void remove_theater PARAMS ((Side *side, Theater *theater));
  154. static void remove_small_theaters PARAMS ((Side *side));
  155. static void compute_theater_bounds PARAMS ((Side *side));
  156. static void review_goals PARAMS ((Side *side));
  157. static void review_units PARAMS ((Side *side));
  158. static void update_side_strategy PARAMS ((Side *side));
  159. static void decide_theater_needs PARAMS ((Side *side, Theater *theater));
  160. static void update_unit_plans PARAMS ((Side *side));
  161. static void update_unit_plans_randomly PARAMS ((Side *side));
  162. static void estimate_strengths PARAMS ((Side *side));
  163. static void decide_resignation PARAMS ((Side *side));
  164. static void give_up PARAMS ((Side *side));
  165. static void add_goal PARAMS ((Side *side, Goal *goal));
  166. static Goal *has_goal PARAMS ((Side *side, GoalType goaltype));
  167. static Goal *has_unsatisfied_goal PARAMS ((Side *side, GoalType goaltype));
  168. static void mplayer_decide_plan PARAMS ((Side *side, Unit *unit));
  169. static int need_this_type_to_explore PARAMS ((Side *side, int u));
  170. /* static int compare_weights PARAMS ((struct weightelt *w1, struct weightelt *w2)); */
  171. static void assign_to_exploration PARAMS ((Side *side, Unit *unit));
  172. static void assign_explorer_to_theater PARAMS ((Side *side, Unit *unit, Theater *theater));
  173. static int need_this_type_to_build_explorers PARAMS ((Side *side, int u));
  174. static void assign_to_explorer_construction PARAMS ((Side *side, Unit *unit));
  175. static void assign_to_offense PARAMS ((Side *side, Unit *unit));
  176. static void assign_to_offense_support PARAMS ((Side *side, Unit *unit));
  177. static int type_can_build_attackers PARAMS ((Side *side, int u));
  178. static int mplayer_preferred_build_type PARAMS ((Side *side, Unit *unit, int plantype));
  179. static int select_by_weight PARAMS ((int *arr, int numvals));
  180. static int need_more_transportation PARAMS ((Side *side));
  181. static void assign_to_defense_support PARAMS ((Side *side, Unit *unit));
  182. static int assign_to_research_on PARAMS ((Side *side, Unit *unit, int u2));
  183. static int can_research_on PARAMS ((int u, int u2));
  184. static int needs_research PARAMS ((Side *side, int u));
  185. static int mplayer_planning_to_capture PARAMS ((Side *side, int u, int x, int y));
  186. static int mplayer_guide_explorer PARAMS ((Side *side, Unit *unit));
  187. static int probably_explorable PARAMS ((Side *side, int x, int y, int u));
  188. static int build_base_for_self PARAMS ((Side *side, Unit *unit));
  189. static int build_base_for_others PARAMS ((Side *side, Unit *unit));
  190. static int build_depot_for_self PARAMS ((Side *side, Unit *unit));
  191. static void mplayer_react_to_action_result PARAMS ((Side *side, Unit *unit, int rslt));
  192. static void mplayer_react_to_task_result PARAMS ((Side *side, Unit *unit, Task *task, TaskOutcome rslt));
  193. static void change_to_adjacent_theater PARAMS ((Side *side, Unit *unit));
  194. static int desired_direction_impassable PARAMS ((Unit *unit, int x, int y));
  195. static int could_be_ferried PARAMS ((Unit *unit, int x, int y));
  196. static int carryable PARAMS ((int u));
  197. static int accelerable PARAMS ((int u));
  198. static int blocked_by_enemy PARAMS ((Unit *unit, int x, int y));
  199. static void attack_blockage PARAMS ((Side *side, Unit *unit, int x, int y));
  200. static void mplayer_react_to_new_side PARAMS ((Side *side, Side *side2));
  201. static void mplayer_analyze_after_moves PARAMS ((Side *side, int numacted));
  202. static void mplayer_finish_movement PARAMS ((Side *side));
  203. static Unit *search_for_available_transport PARAMS ((Unit *unit));
  204. static void rethink_plan PARAMS ((Unit *unit));
  205. static int enemy_close_by PARAMS ((Side *side, Unit *unit, int dist, int *xp, int *yp));
  206. static void mplayer_receive_message PARAMS ((Side *side, Side *sender, char *str));
  207. static char *mplayer_at_desig PARAMS ((Side *side, int x, int y));
  208. static int mplayer_theater_at PARAMS ((Side *side, int x, int y));
  209. static int mplayer_read_strengths PARAMS ((Side *side));
  210. static Obj *mplayer_save_state PARAMS ((Side *side));
  211.  
  212. static void mplayer_react_to_unit_loss PARAMS ((Side *side, Unit *unit));
  213.  
  214. static int compare_weights PARAMS ((const void *w1, const void *w2));
  215.  
  216. /* This is the set of operations that generic code will use. */
  217.  
  218. AI_ops mplayer_ops = {
  219.     "mplayer",            /* name */
  220.     NULL,            /* to_test_compat */        
  221.     mplayer_init,        /* to_init */
  222.     mplayer_init_turn,        /* to_init_turn */
  223.     mplayer_decide_plan,    /* to_decide_plan */
  224.     mplayer_react_to_unit_loss,    /* to_react_to_unit_loss */
  225.     mplayer_react_to_action_result,    /* to_react_to_action_result */
  226.     mplayer_react_to_task_result,    /* to_react_to_task_result */
  227.     mplayer_react_to_new_side,    /* to_react_to_new_side */
  228.     mplayer_planning_to_capture,    /* planning_to_capture */
  229.     mplayer_guide_explorer,    /* to_guide_explorer */
  230.     mplayer_preferred_build_type,    /* preferred_build_type */
  231.     mplayer_analyze_after_moves,    /* to_analyze_after_moves */
  232.     mplayer_finish_movement,    /* to_finish_movement */
  233.     mplayer_receive_message,    /* to_receive_message */
  234.     mplayer_save_state,        /* to_save_state */
  235.     mplayer_theater_at,        /* region_at */
  236.     mplayer_at_desig,        /* at_desig */
  237.     -1                /* dummy */
  238. };
  239.  
  240. /* Flag to detect when shared mplayer init has been done. */
  241.  
  242. static int mplayerinited = FALSE;
  243.  
  244. static Theater *tmptheater;
  245.  
  246. static Side *anewside;
  247.  
  248. /* Determine game type from name of included modules. */
  249.  
  250. static GameClass
  251. find_game_class()
  252. {
  253.     Module *m;
  254.  
  255.     for_all_modules(m) {
  256.     if (strcmp(m->name, "time") == 0
  257.         || (m->origmodulename && strcmp(m->origmodulename, "time") == 0))
  258.       return gc_time;
  259.     }
  260.  
  261.     return gc_standard;
  262. }
  263.  
  264. static void
  265. mplayer_init(side)
  266. Side *side;
  267. {
  268.     Unit *unit;
  269.  
  270.     if (game_class == gc_none) {
  271.     game_class = find_game_class();
  272.     }
  273.  
  274.     /* (should do this only when absolutely needed - mplayer might
  275.        never actually be used) */
  276.     if (!mplayerinited) {
  277.     ai_init_shared();
  278.     mplayerinited = TRUE;
  279.     Dprintf("One mplayer AI is %d bytes.\n", sizeof(Strategy));
  280.     }
  281.     /* Make sure a strategy object exists. */
  282.     if (mplayer(side) == NULL)
  283.       create_strategy(side);
  284.     /* If the side has no units at the moment, it doesn't really need to
  285.        plan. */
  286.     if (!side_has_units(side))
  287.       return;
  288.     /* Compute an initial estimation of units on each side. */
  289.     /* (Needed for save/restore consistency, otherwise not
  290.        critical to do here.) */
  291.     estimate_strengths(side);
  292.     /* Study the scorekeepers and such, decide how to play the game. */
  293.     analyze_the_game(side);
  294.     /* Reset plans of any units that were not doing anything. */
  295.     for_all_side_units(side, unit) {
  296.         if (in_play(unit) && unit->plan && unit->plan->aicontrol) {
  297.         unit->plan->asleep = FALSE;
  298.         unit->plan->reserve = FALSE;
  299.         /* We might want to mess with the unit now, so clear all
  300.            delays. */
  301.         unit->plan->delayed = FALSE;
  302.         if (unit->plan->waitingfortasks)
  303.           --(side->numwaiting);
  304.         unit->plan->waitingfortasks = FALSE;
  305.         if (unit->plan->type == PLAN_PASSIVE) {
  306.         unit->plan->type = PLAN_NONE;
  307.         }
  308.         }
  309.     }
  310. }
  311.  
  312. /* At the beginning of each turn, make plans and review the situation. */
  313.  
  314. static void
  315. mplayer_init_turn(side)
  316. Side *side;
  317. {
  318.     int u, u2;
  319.  
  320.     /* Cases where we no longer need to run. */
  321.     if (!side->ingame)
  322.       return;
  323.     /* A side without units hasn't got anything to do but wait. */
  324.     /* (should account for possible units on controlled sides) */
  325.     if (!side_has_units(side))
  326.       return;
  327.     /* Mplayers in a hacked game will not play,
  328.        unless they're being debugged. */
  329.     if (compromised && !DebugM)
  330.       return;
  331.     update_all_progress_displays("ai turn init start", side->id);
  332.     DMprintf("%s mplayer init turn\n", side_desig(side));
  333.     /* Make sure a strategy object exists. */
  334.     if (mplayer(side) == NULL)
  335.       create_strategy(side);
  336.     /* Look over the game design we're playing with. */
  337.     analyze_the_game(side);
  338.  
  339.     /* code specific to the "time" game */
  340.     if (game_class == gc_time) {
  341.     for_all_unit_types(u) {
  342.         if (mplayer(side)->research_status[u] == RS_RESEARCH_ASSIGNED) {
  343.         u2 = mplayer(side)->research_on[u];
  344.         if (!needs_research (side, u2)) {
  345.             /* research done, start upgrading */
  346.             DMprintf("%s has completed research on %s\n",
  347.                  side_desig(side), u_type_name(u2));
  348.             mplayer(side)->research_status[u] = RS_UPGRADE_NEEDED;
  349.         }
  350.         }
  351.     }
  352.     }
  353.  
  354.     /* If this game is one that can be won, as opposed to
  355.        just dinking around, figure how to win it. */
  356.     if (mplayer(side)->trytowin) {
  357.     /* Check out the current goal tree first. */
  358.     review_goals(side);
  359.     /* Goal analysis might have triggered resignation. */
  360.     if (!side->ingame)
  361.       goto done;
  362.     /* Check out all the theaters. */
  363.     review_theaters(side);
  364.     /* Check out all of our units. */
  365.     review_units(side);
  366.     /* Decide on the new current plan. */
  367.     update_side_strategy(side);
  368.     /* Propagate this to individual unit plans. */
  369.     update_unit_plans(side);
  370.     } else {
  371.     update_unit_plans_randomly(side);
  372.     }
  373.   done:
  374.     update_all_progress_displays("", side->id);
  375.     DMprintf("%s mplayer init turn done\n", side_desig(side));
  376. }
  377.  
  378. /* Create and install an entirely new strategy object for the side. */
  379.  
  380. static void
  381. create_strategy(side)
  382. Side *side;
  383. {
  384.     Strategy *strategy = (Strategy *) xmalloc(sizeof(Strategy));
  385.  
  386.     /* Put the specific structure into a generic slot. */
  387.     side->ai = (struct a_ai *) strategy;
  388.     strategy->type = mplayertype;
  389.     /* Allocate a table of pointers to theaters, for access via small numbers
  390.        rather than full pointers. */
  391.     strategy->theatertable = (Theater **) xmalloc(127 * sizeof(Theater *));
  392.     /* Allocate a layer of indexes into the theater table. */
  393.     strategy->areatheaters = malloc_area_layer(char);
  394.     /* Allocate random things. */
  395.     /* Arrays for unit types. */
  396.     strategy->actualmix = (short *) xmalloc(numutypes * sizeof(short));
  397.     strategy->expectedmix = (short *) xmalloc(numutypes * sizeof(short));
  398.     strategy->idealmix = (short *) xmalloc(numutypes * sizeof(short));
  399.     strategy->research_status = (short *) xmalloc(numutypes * sizeof(short));
  400.     strategy->research_on     = (short *) xmalloc(numutypes * sizeof(short));
  401.     /* Arrays for terrain types. */
  402.     strategy->terrainguess = (short *) xmalloc(numttypes * sizeof(short));
  403.     strategy->writable_state = lispnil;
  404.     /* Set everything to correct initial values. */
  405.     reset_strategy(side);
  406. }
  407.  
  408. /* Put all the right initial values into the strategy, but don't allocate anything. */
  409.  
  410. static void
  411. reset_strategy(side)
  412. Side *side;
  413. {
  414.     int u, u2, t, dir;
  415.     Strategy *strategy = (Strategy *) side->ai;
  416.  
  417.     /* Remember when we did this. */
  418.     strategy->creationdate = g_turn();
  419.     /* Null out various stuff. */
  420.     strategy->numgoals = 0;
  421.     strategy->theaters = NULL;
  422.     /* Actually we start with no theaters, but it's convenient to leave entry 0
  423.        in the theater table pointing to NULL. */
  424.     strategy->numtheaters = 1;
  425.     /* Clear pointers to special-purpose theaters. */
  426.     strategy->homefront = NULL;
  427.     for_all_directions(dir) {
  428.         strategy->perimeters[dir] = NULL;
  429.         strategy->midranges[dir] = NULL;
  430.         strategy->remotes[dir] = NULL;
  431.     }
  432.     strategy->explorersneeded = 0;
  433.     /* Reset the summation of our exploration needs. */
  434.     for_all_unit_types(u) {
  435.     strategy->actualmix[u] = 0;
  436.     strategy->expectedmix[u] = 0;
  437.     strategy->idealmix[u] = 0;
  438.     strategy->research_status[u] = 0;
  439.     strategy->research_on[u] = 0;
  440.  
  441.     /* code specific to the "time" game */
  442.     if (game_class == gc_time) {
  443.         for_all_unit_types(u2) {
  444.         if (needs_research (side, u2) && can_research_on(u, u2)) {
  445.             strategy->research_status[u] = RS_RESEARCH_NEEDED;
  446.             strategy->research_on[u] = u2;
  447.             DMprintf("%s can research on %s (to level %d)\n",
  448.                  u_type_name(u), u_type_name(u2),
  449.                  u_tech_to_build(u2));
  450.         }
  451.         }
  452.     }
  453.     }
  454.     for_all_terrain_types(t) {
  455.     strategy->terrainguess[t] = 0;
  456.     }
  457.     strategy->analyzegame = TRUE;
  458.     /* Analyze the game and decide our basic goals. */
  459.     analyze_the_game(side);
  460. }
  461.  
  462. /* Look over the game design and decide what we're supposed to be doing,
  463.    if anything at all.  This just sets up toplevel goals based on the
  464.    game design, does not evaluate goals or any such. */
  465.  
  466. static void
  467. analyze_the_game(side)
  468. Side *side;
  469. {
  470.     int maybedraw, i;
  471.     Goal *goal;
  472.  
  473.     if (mplayer(side)->analyzegame) {
  474.     if (should_try_to_win(side)) {
  475.         mplayer(side)->trytowin = TRUE;
  476.         /* This is our whole purpose in the game. */
  477.         goal = create_goal(GOAL_WON_GAME, side, TRUE);
  478.         add_goal(side, goal);
  479.         /* Now figure what exactly we have to do in order to win. */
  480.         determine_subgoals(side);
  481.         /* Machine will want to keep playing as long as it thinks
  482.            it has a chance to win. */
  483.         maybedraw = FALSE;
  484.     } else {
  485.         mplayer(side)->trytowin = FALSE;
  486.         /* Since the side is not trying to win anything, it will be
  487.            pretty laidback about whether to keep the game going. */
  488.         maybedraw = TRUE;
  489.     }
  490.     /* Be trusting about game saves, at least for now. (The problem
  491.        is that a human player could escape fate by saving the game
  492.        and then either editing the saved game or just throwing it
  493.        away.) */
  494.     set_willing_to_save(side, TRUE);
  495.     set_willing_to_draw(side, maybedraw);
  496.     mplayer(side)->analyzegame = FALSE;
  497.     /* Summarize our analysis of this game. */
  498.     DMprintf("%s will try to %s this game\n",
  499.          side_desig(side),
  500.          mplayer(side)->trytowin ? "win" : "have fun in");
  501.     for (i = 0; i < mplayer(side)->numgoals; ++i) {
  502.         goal = mplayer(side)->goals[i];
  503.         DMprintf("%s has %s\n", side_desig(side), goal_desig(goal));
  504.     }
  505.     }
  506. }
  507.  
  508. static void
  509. determine_subgoals(side)
  510. Side *side;
  511. {
  512.     int numvicgoals;
  513.     Unit *unit;
  514.     Side *side2;
  515.     Scorekeeper *sk;
  516.     Goal *goal;
  517.  
  518.     /* Look at each scorekeeper and decide on appropriate goals. */
  519.     for_all_scorekeepers(sk) {
  520.         if (match_keyword(sk->body, K_LAST_SIDE_WINS)) {
  521.         /* We want to "kick butt" - *everybody* else's butt. */
  522.         for_all_sides(side2) {
  523.         if (!trusted_side(side, side2) && side2->ingame) {
  524.             /* Our goals include preventing other sides from accomplishing
  525.                theirs. */
  526.             goal = create_goal(GOAL_WON_GAME, side2, FALSE);
  527.             add_goal(side, goal);
  528.             /* (should add "search-and-destroy" as corollaries) */
  529.         }
  530.         }
  531.         /* Add goals to protect our own units. */
  532.         numvicgoals = 0;
  533.         for_all_side_units(side, unit) {
  534.         if (point_value(unit) > 0  /* (should be "n most valuable") */
  535.             && in_play(unit)
  536.             && numvicgoals < 10) {
  537.             goal = create_goal(GOAL_VICINITY_HELD, side, TRUE);
  538.             goal->args[0] = unit->x;  goal->args[1] = unit->y;
  539.             goal->args[2] = goal->args[3] = 2;
  540.             add_goal(side, goal);
  541.             ++numvicgoals;
  542.         }
  543.         }
  544.         } else {
  545.         DMprintf("Don't understand a scorekeeper!");
  546.         }
  547.     }
  548.     /* We might develop a sudden interest in exploration. */
  549.     /* (but should only be if information is really important to winning) */
  550.     if (!all_see_all) {
  551.     if (!g_terrain_seen()) {
  552.         add_goal(side, create_goal(GOAL_WORLD_KNOWN, side, TRUE));
  553.     }
  554.     /* It will be important to keep track of other sides' units
  555.        as much as possible. */
  556.     for_all_sides(side2) {
  557.         if (side != side2) {
  558.         goal = create_goal(GOAL_POSITIONS_KNOWN, side, TRUE);
  559.         goal->args[0] = (long) side2;
  560.         add_goal(side, goal);
  561.         }
  562.     }
  563.     /* Also add the general goal of knowing where indeps are. */
  564.     goal = create_goal(GOAL_POSITIONS_KNOWN, side, TRUE);
  565.     goal->args[0] = (long) NULL;
  566.     add_goal(side, goal);
  567.     }
  568. }
  569.  
  570. /* Do a combination of analyzing existing theaters and creating new ones. */
  571.  
  572. static void
  573. review_theaters(side)
  574. Side *side;
  575. {
  576.     int x, y, u, s, pop, totnumunits;
  577.     int firstcontact = FALSE;
  578.     int homefound = FALSE;
  579.     short view;
  580.     Unit *unit;
  581.     Side *firstcontactside, *homefoundside, *otherside, *side2;
  582.     Theater *theater;
  583.  
  584.     /* Create some theaters if none exist. */
  585.     if (mplayer(side)->theaters == NULL) {
  586.     create_initial_theaters(side);
  587.     }
  588.     for_all_theaters(side, theater) {
  589.     theater->allied_units = 0;
  590.     theater->makers = 0;
  591.     theater->unexplored = 0;
  592.     theater->border = FALSE;
  593.     theater->allied_bases = 0;
  594.     for_all_unit_types(u) {
  595.         theater->numassigned[u] = 0;
  596.         theater->numneeded[u] = 0;
  597.         theater->numenemies[u] = 0;
  598.         theater->numsuspected[u] = theater->numsuspectedmax[u] = 0;
  599.         theater->numtotransport[u] = 0;
  600.     }
  601.     if (people_sides_defined()) {
  602.         for (s = 0; s <= numsides; ++s)
  603.           theater->people[s] = 0;
  604.     }
  605.     theater->units_lost /= 2;
  606.     }
  607.     compute_theater_bounds(side);
  608.     /* Now look at all the units that we can. */
  609.     for_all_side_units(side, unit) {
  610.         if (in_play(unit)) {
  611.         theater = unit_theater(unit);
  612.         if (theater != NULL) {
  613.         ++(theater->allied_units);
  614.         (theater->numassigned[unit->type])++;
  615.         if (isbase(unit))
  616.           theater->allied_bases++;
  617.         }
  618.     }
  619.     }
  620.     /* (should also analyze allies etc) */
  621.     /* Now look at the whole world. */
  622.     for_all_interior_cells(x, y) {
  623.     theater = theater_at(side, x, y);
  624.     if (theater != NULL) {
  625.         if (can_see_actual_units(side, x, y)) {
  626.             for_all_stack(x, y, unit) {
  627.                 /* what about occupants? */
  628.                 if (in_play(unit)
  629.                     && !trusted_side(side, unit->side)
  630.                     && (!indep(unit)
  631.                         || u_point_value(unit->type) > 0)) {
  632.             if (enemy_side(side, unit->side))
  633.               ++(theater->numenemies[unit->type]);
  634.                     if (mplayer(side)->contacted[side_number(unit->side)] == 0) {
  635.                 mplayer(side)->contacted[side_number(unit->side)] = 1;
  636.                 if (!indep(unit)) {
  637.                 firstcontact = TRUE;
  638.                 firstcontactside = unit->side;
  639.                 }
  640.                     }
  641.                     if (mplayer(side)->homefound[side_number(unit->side)] == 0
  642.                         && !mobile(unit->type)) {
  643.                 mplayer(side)->homefound[side_number(unit->side)] = 1;
  644.                 if (!indep(unit)) {
  645.                 homefound = TRUE;
  646.                 homefoundside = unit->side;
  647.                 }
  648.                     }
  649.                 }
  650.             }
  651.         if (people_sides_defined()) {
  652.             pop = people_side_at(x, y);
  653.             if (pop != NOBODY) {
  654.             ++(theater->people[pop]);
  655.                     if (mplayer(side)->homefound[pop] == 0) {
  656.                 mplayer(side)->homefound[pop] = 1;
  657.                 if (pop != 0) {
  658.                 homefound = TRUE;
  659.                 homefoundside = side_n(pop);
  660.                 }
  661.                     }
  662.             }
  663.         }
  664.         } else {
  665.         if (terrain_view(side, x, y) == UNSEEN) {
  666.             ++(theater->unexplored);
  667.         } else {
  668.             view = unit_view(side, x, y);
  669.             if (view != EMPTY) {
  670.             side2 = side_n(vside(view));
  671.             if (side2 == NULL) {
  672.                 u = vtype(view);
  673.                 /* (should rate by value of capture) */
  674.                 if (u_point_value(u) > 0) {
  675.                 ++(theater->numsuspected[u]);
  676.                 ++(theater->numsuspectedmax[u]);
  677.                 }
  678.             } else if (enemy_side(side, side2)) {
  679.                 u = vtype(view);
  680.                 if (u_point_value(u) > 0) {
  681.                 ++(theater->numsuspected[u]);
  682.                 ++(theater->numsuspectedmax[u]);
  683.                 }
  684.             }
  685.             }
  686.             if (people_sides_defined()) {
  687.             pop = people_side_at(x, y);
  688.             if (pop != NOBODY) {
  689.                 ++(theater->people[pop]);
  690.             }
  691.             }
  692.         }
  693.         }
  694.     }
  695.     }
  696.     for_all_theaters(side, theater) {
  697.         theater->x = (theater->xmin + theater->xmax) / 2;
  698.         theater->y = (theater->ymin + theater->ymax) / 2;
  699.         theater->enemystrengthmin = theater->enemystrengthmax = 0;
  700.         for_all_unit_types(u) {
  701.         theater->enemystrengthmin +=
  702.           theater->numenemies[u] + theater->numsuspected[u];
  703.     }
  704.     theater->enemystrengthmax = theater->enemystrengthmin;
  705.     }
  706.     if (firstcontact || homefound) {
  707.         for_all_side_units(side, unit) {
  708.         if (unit->plan && unit->plan->aicontrol) {
  709.         unit->plan->maingoal = NULL;
  710.         unit->plan->formation = NULL;
  711.         unit->plan->funit = NULL;
  712.         /* Force a replan. */
  713.         unit->plan->type = PLAN_NONE;
  714.         unit->plan->asleep = FALSE;
  715.         unit->plan->reserve = FALSE;
  716.         if (unit->plan->waitingfortasks)
  717.           --(side->numwaiting);
  718.         unit->plan->waitingfortasks = FALSE;
  719.         set_unit_theater(unit, NULL);
  720.         update_unit_display(side, unit, TRUE);
  721.         }
  722.     }
  723.     }
  724.     for_all_theaters(side, theater) {
  725.     DMprintf("%s theater \"%s\" at %d,%d from %d,%d to %d,%d (size %d)\n",
  726.          side_desig(side), theater->name, theater->x, theater->y,
  727.          theater->xmin, theater->ymin, theater->xmax, theater->ymax,
  728.          theater->size);
  729.     /* Summarize what we know about the theater. */
  730.     DMprintf("%s theater \"%s\"", side_desig(side), theater->name);
  731.     if (!all_see_all && theater->unexplored > 0) {
  732.         DMprintf(" unexplored %d", theater->unexplored);
  733.     }
  734.     DMprintf(" enemy %d", theater->enemystrengthmin);
  735.     if (theater->enemystrengthmin != theater->enemystrengthmax) {
  736.         DMprintf("-%d", theater->enemystrengthmax);
  737.     }
  738.     for_all_unit_types(u) {
  739.         if (theater->numenemies[u] + theater->numsuspected[u] > 0) {
  740.             DMprintf(" %3s %d", u_type_name(u), theater->numenemies[u]);
  741.             if (theater->numsuspected[u] > 0) {
  742.             DMprintf("+%d", theater->numsuspected[u]);
  743.         }
  744.         }
  745.     }
  746.     if (people_sides_defined()) {
  747.         DMprintf(" people");
  748.         for (s = 0; s <= numsides; ++s) {
  749.         if (theater->people[s] > 0) {
  750.             DMprintf(" s%d %d", s, theater->people[s]);
  751.         }
  752.         }
  753.     }
  754.     DMprintf("\n");
  755.     totnumunits = 0;
  756.     for_all_unit_types(u) {
  757.         totnumunits +=
  758.           (theater->numassigned[u] + theater->numneeded[u] + theater->numtotransport[u]);
  759.     }
  760.     if (totnumunits > 0) {
  761.         /* Summarize the status of our own units in this theater. */
  762.         DMprintf("%s theater \"%s\" has ", side_desig(side), theater->name);
  763.         for_all_unit_types(u) {
  764.         if (theater->numassigned[u] + theater->numneeded[u] + theater->numtotransport[u] > 0) {
  765.             DMprintf(" %d %3s", theater->numassigned[u], u_type_name(u));
  766.             if (theater->numneeded[u] > 0) {
  767.                 DMprintf(" (of %d needed)", theater->numneeded[u]);
  768.             }
  769.             if (theater->numtotransport[u] > 0) {
  770.                 DMprintf(" (%d awaiting transport)", theater->numtotransport[u]);
  771.             }
  772.         }
  773.         }
  774.         DMprintf("\n");
  775.     }
  776.     }
  777.     /* Also summarize contacts. */
  778.     for_all_sides(otherside) {
  779.         if (otherside != side) {
  780.         if (mplayer(side)->contacted[otherside->id]) {
  781.         DMprintf("%s contacted s%d", side_desig(side), otherside->id);
  782.         if (mplayer(side)->homefound[otherside->id]) {
  783.             DMprintf(", home found");
  784.         }
  785.         DMprintf("\n");
  786.         }
  787.         }
  788.     }
  789. }
  790.  
  791. /* Set up the initial set of theaters. */
  792.  
  793. static void
  794. create_initial_theaters(side)
  795. Side *side;
  796. {
  797.     int x, y, dir, dist, i, j;
  798.     int xmin, ymin, xmax, ymax;
  799.     int homeradius, perimradius, midradius, xxx;
  800.     int numthx, numthy, thwid, thhgt;
  801.     Unit *unit;
  802.     Theater *homefront, *enemyarea, *theater;
  803.     Theater *gridtheaters[8][8];
  804.     Strategy *strategy = mplayer(side);
  805.     
  806.     for (i = 0; i < 8; ++i) {
  807.     for (j = 0; j < 8; ++j) {
  808.         gridtheaters[i][j] = NULL;
  809.     }
  810.     }
  811.     /* Compute bbox of initial (should also do enemy?) units. */
  812.     xmin = area.width;  ymin = area.height;  xmax = ymax = 0;
  813.     for_all_side_units(side, unit) {
  814.     if (alive(unit) /* and other preconditions? */) {
  815.         if (unit->x < xmin)
  816.           xmin = unit->x;
  817.         if (unit->y < ymin)
  818.           ymin = unit->y;
  819.         if (unit->x > xmax)
  820.           xmax = unit->x;
  821.         if (unit->y > ymax)
  822.           ymax = unit->y;
  823.     }
  824.     }
  825.     /* Most games start with each side's units grouped closely together.
  826.        If this is not the case, do something else. */
  827.     if (xmax - xmin > area.width / 4 && ymax - ymin > area.height / 4) {
  828.     /* (should do some sort of clustering of units) */
  829.     if (0 /*people_sides_defined()*/) {
  830.         homefront = create_theater(side);
  831.         homefront->name = "Home Front";
  832.         enemyarea = create_theater(side);
  833.         enemyarea->name = "Enemy Area";
  834.         for_all_interior_cells(x, y) {
  835.             if (people_side_at(x, y) == side->id) {
  836.             set_theater_at(side, x, y, homefront);
  837.             } else {
  838.             set_theater_at(side, x, y, enemyarea);
  839.             }
  840.         }
  841.     } else {
  842.         /* Divide the world up along a grid. */
  843.         numthx = (area.width  > 60 ? (area.width  > 120 ? 7 : 5) : 3);
  844.         numthy = (area.height > 60 ? (area.height > 120 ? 7 : 5) : 3);
  845.         thwid = max(8, area.width / numthx);
  846.         thhgt = max(8, area.height / numthy);
  847.         for_all_interior_cells(x, y) {
  848.         i = x / thwid;  j = y / thhgt;
  849.         if (gridtheaters[i][j] == NULL) {
  850.             theater = create_theater(side);
  851.             sprintf(spbuf, "Grid %d,%d", i, j);
  852.             theater->name = copy_string(spbuf);
  853.             theater->x = x;  theater->y = y;
  854.             gridtheaters[i][j] = theater;
  855.         } else {
  856.             theater = gridtheaters[i][j];
  857.         }
  858.         set_theater_at(side, x, y, theater);
  859.         }
  860.     }
  861.     return;
  862.     } else {
  863.     /* Always create a first theater that covers the starting area. */
  864.     homefront = create_theater(side);
  865.     homefront->name = "Home Front";
  866.     /* Calculate startxy if not already available. */
  867.     if (side->startx < 0 && side->starty < 0)
  868.       calc_start_xy(side);
  869.     homefront->x = side->startx;  homefront->y = side->starty;
  870.     strategy->homefront = homefront;
  871.     homeradius = max(5, g_radius_min());
  872.     perimradius = max(homeradius + 5, g_separation_min() - homeradius);
  873.     midradius = max(perimradius + 10, g_separation_min() * 2);
  874.     xxx = max((side->startx - perimradius), (area.width - side->startx - perimradius));
  875.     xxx /= 2;
  876.     midradius = min(midradius, perimradius + xxx);
  877.     for_all_interior_cells(x, y) {
  878.         if (people_sides_defined()
  879.         && people_side_at(x, y) == side->id) {
  880.         set_theater_at(side, x, y, homefront);
  881.         } else {
  882.         dist = distance(x, y, side->startx, side->starty);
  883.         if (dist < homeradius) {
  884.             set_theater_at(side, x, y, homefront);
  885.         } else {
  886.             dir = approx_dir(x - side->startx, y - side->starty);
  887.             if (dist < perimradius) {
  888.             if (strategy->perimeters[dir] == NULL) {
  889.                 theater = create_theater(side);
  890.                 sprintf(spbuf, "Perimeter %s", dirnames[dir]);
  891.                 theater->name = copy_string(spbuf);
  892.                 theater->x = x;  theater->y = y;
  893.                 strategy->perimeters[dir] = theater;
  894.             } else {
  895.                 theater = strategy->perimeters[dir];
  896.             }
  897.             } else if (dist < midradius) {
  898.             if (strategy->midranges[dir] == NULL) {
  899.                 theater = create_theater(side);
  900.                 sprintf(spbuf, "Midrange %s", dirnames[dir]);
  901.                 theater->name = copy_string(spbuf);
  902.                 theater->x = x;  theater->y = y;
  903.                 strategy->midranges[dir] = theater;
  904.             } else {
  905.                 theater = strategy->midranges[dir];
  906.             }
  907.             } else {
  908.             if (strategy->remotes[dir] == NULL) {
  909.                 theater = create_theater(side);
  910.                 sprintf(spbuf, "Remote %s", dirnames[dir]);
  911.                 theater->name = copy_string(spbuf);
  912.                 theater->x = x;  theater->y = y;
  913.                 strategy->remotes[dir] = theater;
  914.             } else {
  915.                 theater = strategy->remotes[dir];
  916.             }
  917.             }
  918.             set_theater_at(side, x, y, theater);
  919.             }
  920.         }
  921.     }  
  922.     }
  923.     remove_small_theaters(side);
  924.     /* Assign all units to the theater they're currently in. */
  925.     /* (how do reinforcements get handled? mplayer should get hold of perhaps) */
  926.     for_all_side_units(side, unit) {
  927.     if (in_play(unit) /* and other preconditions? */) {
  928.         set_unit_theater(unit, theater_at(side, unit->x, unit->y));
  929.     }
  930.     }
  931. }
  932.  
  933. /* Create a single theater object and link it into the list of
  934.    theaters. */
  935.  
  936. /* (should be able to re-use theaters in already in theater table) */
  937.  
  938. static Theater *
  939. create_theater(side)
  940. Side *side;
  941. {
  942.     Theater *theater = (Theater *) xmalloc(sizeof(Theater));
  943.     
  944.     if (mplayer(side)->numtheaters > MAXTHEATERS)
  945.       return NULL;
  946.     theater->id = (mplayer(side)->numtheaters)++;
  947.     theater->name = "?";
  948.     theater->maingoal = NULL;
  949.     theater->people = (int *) xmalloc ((numsides + 1) * sizeof(int));
  950.     /* (should alloc other array slots too) */
  951.     /* Connect theater into a linked list. */
  952.     theater->next = mplayer(side)->theaters;
  953.     mplayer(side)->theaters = theater;
  954.     /* Install it into the theater table also. */
  955.     mplayer(side)->theatertable[theater->id] = theater;
  956.     return theater;
  957. }
  958.  
  959. /* Clear all references to the theater and remove it from the list.
  960.    Note that the theater size must already be zero. */
  961.  
  962. static void
  963. remove_theater(side, theater)
  964. Side *side;
  965. Theater *theater;
  966. {
  967.     int dir;
  968.     Theater *prev;
  969.  
  970.     if (mplayer(side)->homefront == theater)
  971.       mplayer(side)->homefront = NULL;
  972.     for_all_directions(dir) {
  973.     if (mplayer(side)->perimeters[dir] == theater)
  974.       mplayer(side)->perimeters[dir] = NULL;
  975.     if (mplayer(side)->midranges[dir] == theater)
  976.       mplayer(side)->midranges[dir] = NULL;
  977.     if (mplayer(side)->remotes[dir] == theater)
  978.       mplayer(side)->remotes[dir] = NULL;
  979.     }
  980.     if (mplayer(side)->theaters == theater)
  981.       mplayer(side)->theaters = theater->next;
  982.     else {
  983.     prev = NULL;
  984.     for_all_theaters(side, prev) {
  985.         if (prev->next == theater) {
  986.         prev->next = theater->next;
  987.         break;
  988.         }
  989.     }
  990.     /* If prev still null, badness */
  991.     }
  992.     --(mplayer(side)->numtheaters);
  993. }
  994.  
  995. static void
  996. move_theater_cell(x, y)
  997. int x, y;
  998. {
  999.     int dir, x1, y1;
  1000.     Theater *theater2;
  1001.  
  1002.     if (theater_at(tmpside, x, y) == tmptheater) {
  1003.     for_all_directions(dir) {
  1004.         if (interior_point_in_dir(x, y, dir, &x1, &y1)) {
  1005.         theater2 = theater_at(tmpside, x1, y1);
  1006.         if (theater2 != NULL && theater2 != tmptheater) {
  1007.             set_theater_at(tmpside, x, y, theater2);
  1008.             ++(theater2->size);
  1009.             /* (should recompute bbox too) */
  1010.             --(tmptheater->size);
  1011.         }
  1012.         }
  1013.     }
  1014.     }
  1015. }
  1016.  
  1017. static void
  1018. remove_small_theaters(side)
  1019. Side *side;
  1020. {
  1021.     int domore;
  1022.     Theater *theater;
  1023.  
  1024.     compute_theater_bounds(side);
  1025.     domore = TRUE;
  1026.     while (domore) {
  1027.     domore = FALSE;
  1028.     for_all_theaters(side, theater) {
  1029.         if (between(1, theater->size, 5)) {
  1030.         tmpside = side;
  1031.         tmptheater = theater;
  1032.         apply_to_area(theater->x, theater->y, 6, move_theater_cell);
  1033.         if (theater->size == 0) {
  1034.             remove_theater(side, theater);
  1035.             /* Have to start over now. */
  1036.             domore = TRUE;
  1037.             break;
  1038.         }
  1039.         }
  1040.     }
  1041.     }
  1042.     /* Redo, many random changes to bounds. */
  1043.     compute_theater_bounds(side);
  1044. }
  1045.  
  1046. /* Compute the size and bounding box of each theater.  This should be run
  1047.    each time theaters change in size or shape. */
  1048.  
  1049. static void
  1050. compute_theater_bounds(side)
  1051. Side *side;
  1052. {
  1053.     int x, y;
  1054.     Theater *theater;
  1055.  
  1056.     for_all_theaters(side, theater) {
  1057.     theater->size = 0;
  1058.     theater->xmin = theater->ymin = -1;
  1059.     theater->xmax = theater->ymax = -1;
  1060.     }
  1061.     for_all_interior_cells(x, y) {
  1062.     theater = theater_at(side, x, y);
  1063.     if (theater != NULL) {
  1064.         ++(theater->size);
  1065.         /* Compute bounding box of theater if not already done. */
  1066.         if (theater->xmin < 0 || x < theater->xmin)
  1067.           theater->xmin = x;
  1068.         if (theater->ymin < 0 || y < theater->ymin)
  1069.           theater->ymin = y;
  1070.         if (theater->xmax < 0 || x > theater->xmax)
  1071.           theater->xmax = x;
  1072.         if (theater->ymax < 0 || y > theater->ymax)
  1073.           theater->ymax = y;
  1074.     }
  1075.     }
  1076. }
  1077.  
  1078. /* Examine the goals to see what has been accomplished and what still needs
  1079.    to be done. */
  1080.  
  1081. static void
  1082. review_goals(side)
  1083. Side *side;
  1084. {
  1085.     int i;
  1086.     Scorekeeper *sk;
  1087.     Goal *goal;
  1088.     Side *side2;
  1089.     Strategy *strategy = mplayer(side);
  1090.  
  1091.     /* First check on our friends and enemies. */
  1092.     for_all_sides(side2) {
  1093.     /* If they're not trusting us, we don't want to trust them. */
  1094.     /* (should be able to update this immediately after other side changes trust) */
  1095.     if (!trusted_side(side2, side))
  1096.       set_trust(side, side2, FALSE);
  1097.     }
  1098.     for (i = 0; i < strategy->numgoals; ++i) {
  1099.     goal = strategy->goals[i];
  1100.     DMprintf("%s has %s\n", side_desig(side), goal_desig(goal));
  1101.     }
  1102.     /* Should look at certainty of each goal and decide whether to keep or
  1103.        drop it, and mention in debug output also. */
  1104.     /* Also think about resigning. */
  1105.     if (keeping_score()) {
  1106.     for_all_scorekeepers(sk) {
  1107.         if (symbolp(sk->body)
  1108.         && match_keyword(sk->body, K_LAST_SIDE_WINS)) {
  1109.         decide_resignation(side);
  1110.         }
  1111.     }
  1112.     }
  1113. }
  1114.  
  1115. static void
  1116. estimate_strengths(side)
  1117. Side *side;
  1118. {
  1119.     int u, sn1, x, y, uview;
  1120.     Side *side1, *side2;
  1121.     Strategy *strategy = mplayer(side);
  1122.     Unit *unit;
  1123.  
  1124.     for_all_sides(side1) {
  1125.     sn1 = side_number(side1);
  1126.     for_all_unit_types(u) {
  1127.         strategy->strengths[sn1][u] = 0;
  1128.     }
  1129.     /* this lets us count even semi-trusted allies' units accurately... */
  1130.     if (side1 == side || allied_side(side, side1)) {
  1131.         for_all_side_units(side1, unit) {
  1132.         /* Note that we count off-area units, since they are reinforcements
  1133.            usually. */
  1134.         if (alive(unit) && completed(unit)) {
  1135.             ++(strategy->strengths[sn1][unit->type]);
  1136.         }
  1137.         }
  1138.     }
  1139.     }
  1140.     if (all_see_all) {
  1141.     /* If we can see everything, we can add up units accurately. */
  1142.     for_all_cells(x, y) {
  1143.         for_all_stack(x, y, unit) {
  1144.         side2 = unit->side;
  1145.         if (side2 != NULL && !(side2 == side || allied_side(side, side2))) {
  1146.             if (completed(unit)) {
  1147.                 ++(strategy->strengths[side2->id][unit->type]);
  1148.             }
  1149.         }
  1150.         }
  1151.     }
  1152.     } else {
  1153.     /* Look at the current view to get enemy strength. */
  1154.     /* This is too easily faked, and doesn't know about hiding units... */
  1155.     /* Should also discount old data. */
  1156.     for_all_cells(x, y) {
  1157.         uview = unit_view(side, x, y);
  1158.         if (uview != UNSEEN && uview != EMPTY) {
  1159.         side2 = side_n(vside(uview));
  1160.         /* Count only units on other sides. */
  1161.         if (side2 != NULL && !(side2 == side || allied_side(side, side2))) {
  1162.             ++(strategy->strengths[side2->id][vtype(uview)]);
  1163.         }
  1164.         }
  1165.     }
  1166.     }
  1167.     /* Estimate point values. */
  1168.     /* (should try to account for individual units with special point values) */
  1169.     for_all_sides(side1) {
  1170.     sn1 = side1->id;
  1171.     strategy->points[sn1] = 0;
  1172.     for_all_unit_types(u) {
  1173.         strategy->points[sn1] +=
  1174.           strategy->strengths[sn1][u] * u_point_value(u);
  1175.     }
  1176.     }
  1177.     /* Estimate point values, and how many of each type in allied group. */
  1178.     for_all_sides(side1) {
  1179.     sn1 = side1->id;
  1180.     for_all_unit_types(u) {
  1181.         strategy->alstrengths[sn1][u] = strategy->strengths[sn1][u];
  1182.         for_all_sides(side2) {
  1183.         if (side1 != side2 && allied_side(side1, side2)) {
  1184.             strategy->alstrengths[sn1][u] +=
  1185.               strategy->strengths[side2->id][u];
  1186.         }
  1187.         }
  1188.     }
  1189.     strategy->alpoints[sn1] = strategy->points[sn1];
  1190.     for_all_sides(side2) {
  1191.         if (side1 != side2 && allied_side(side1, side2)) {
  1192.         strategy->alpoints[sn1] += strategy->points[side2->id];
  1193.         }
  1194.     }
  1195.     }
  1196.     if (!strategy->initial_strengths_computed) {
  1197.     if (!mplayer_read_strengths(side)) {
  1198.         for_all_sides(side1) {
  1199.         sn1 = side1->id;
  1200.         strategy->points0[sn1] = strategy->points[sn1];
  1201.         strategy->alpoints0[sn1] = strategy->alpoints[sn1];
  1202.         for_all_unit_types(u) {
  1203.             strategy->strengths0[sn1][u] =
  1204.               strategy->strengths[sn1][u];
  1205.             strategy->alstrengths0[sn1][u] =
  1206.               strategy->alstrengths[sn1][u];
  1207.         }
  1208.         }
  1209.     }
  1210.     ai_save_state(side);
  1211.     strategy->initial_strengths_computed = TRUE;
  1212.     }
  1213.     /* If we're calling strength estimation because a new side has
  1214.        come into existence, use the current strengths as the new
  1215.        side's initial strengths. */
  1216.     if (anewside != NULL) {
  1217.     sn1 = anewside->id;
  1218.     strategy->points0[sn1] = strategy->points[sn1];
  1219.     strategy->alpoints0[sn1] = strategy->alpoints[sn1];
  1220.     for_all_unit_types(u) {
  1221.         strategy->strengths0[sn1][u] =
  1222.           strategy->strengths[sn1][u];
  1223.         strategy->alstrengths0[sn1][u] =
  1224.           strategy->alstrengths[sn1][u];
  1225.     }
  1226.     /* Have to redo the saveable state also; force this by blasting any
  1227.        existing recordable state (it should all be re-creatable from
  1228.        mplayer's internal state). */
  1229.     strategy->writable_state = lispnil;
  1230.     ai_save_state(side);
  1231.     }
  1232.     /* Dump out a detailed listing of our estimates. */
  1233.     if (DebugM) {
  1234.     for_all_sides(side1) {
  1235.         sn1 = side1->id;
  1236.         DMprintf("%s ", side_desig(side));
  1237.         DMprintf("est init streng of %s: ", side_desig(side1));
  1238.         for_all_unit_types(u) {
  1239.         DMprintf(" %d", strategy->strengths0[sn1][u]);
  1240.         }
  1241.         DMprintf(" (%d points)\n", strategy->points0[sn1]);
  1242.         DMprintf("%s ", side_desig(side));
  1243.         DMprintf("est curr streng of %s: ", side_desig(side1));
  1244.         for_all_unit_types(u) {
  1245.         DMprintf(" %d", strategy->strengths[sn1][u]);
  1246.         }
  1247.         DMprintf(" (%d points)\n", strategy->points[sn1]);
  1248.         DMprintf("%s ", side_desig(side));
  1249.         DMprintf("est init allied of %s: ", side_desig(side1));
  1250.         for_all_unit_types(u) {
  1251.         DMprintf(" %d", strategy->alstrengths0[sn1][u]);
  1252.         }
  1253.         DMprintf(" (%d points)\n", strategy->alpoints0[sn1]);
  1254.         DMprintf("%s ", side_desig(side));
  1255.         DMprintf("est curr allied of %s: ", side_desig(side1));
  1256.         for_all_unit_types(u) {
  1257.         DMprintf(" %d", strategy->alstrengths[sn1][u]);
  1258.         }
  1259.         DMprintf(" (%d points)\n", strategy->alpoints[sn1]);
  1260.     }
  1261.     }
  1262. }
  1263.  
  1264. /* Sometimes there is no point in going on, but be careful not to be too
  1265.    pessimistic.  Right now we only give up if no hope at all.  Currently
  1266.    this is only used if there is a last-side-wins scorekeeper; it would
  1267.    need to be modified considerably to be useful with scorekeepers in
  1268.    general. */
  1269.  
  1270. static void
  1271. decide_resignation(side)
  1272. Side *side;
  1273. {
  1274.     int ratio, ratio0, chance = 0, sn1;
  1275.     Side *side1;
  1276.     Strategy *strategy = mplayer(side);
  1277.  
  1278.     estimate_strengths(side);
  1279.     /* If our estimate of our own points is zero, then we're about to lose the
  1280.        game anyway, so just return and avoid screwing up ratio calcs below. */
  1281.     if (strategy->alpoints[side->id] <= 0)
  1282.       return;
  1283.     for_all_sides(side1) {
  1284.     if (side != side1 && side1->ingame && !allied_side(side, side1)) {
  1285.         sn1 = side1->id;
  1286.         /* Note that ratio calculations always scale up by 100, so that we
  1287.            can do finer comparisons without needing floating point. */
  1288.         ratio = (strategy->alpoints[sn1] * 100) / strategy->alpoints[side->id];
  1289.         /* code specific to the "time" game */
  1290.         /* the mplayer can severely underestimates its own strength */
  1291.         if (game_class == gc_time) {
  1292.         ratio /= 3;
  1293.         }
  1294.  
  1295.         if (strategy->alpoints0[side->id] > 0) {
  1296.         ratio0 = (strategy->alpoints0[sn1] * 100) / strategy->alpoints0[side->id];
  1297.         /* If we estimated 0 points for some side's initial strength,
  1298.            then our estimate is bad; assume parity. */
  1299.         if (ratio0 <= 0)
  1300.           ratio0 = 100;
  1301.         /* This formula basically calls for no resignation if ratio is no more
  1302.            than twice what it was initially, 50% chance if ratio is four times
  1303.            what it was (if we started out even, then we're outnumbered 4 to 1),
  1304.            and interpolates for ratios in between. */
  1305.         chance = (((ratio * 100) / ratio0) - 200) / 5;
  1306.         chance = max(chance, 0);
  1307.         chance = min(chance, 90);
  1308.         } else {
  1309.         /* work by absolute ratios */
  1310.         if (ratio > 400) {
  1311.             chance = ratio / 10;
  1312.         }
  1313.         chance = min(chance, 90);
  1314.         }
  1315.     }
  1316.     }
  1317.  
  1318.     /* Whether or not we actually resign, we may be willing to
  1319.        go for a draw if other players want to. */
  1320.     /* (Note that toggling this flag is not exactly poker-faced
  1321.        behavior, but I doubt human players will be able to derive
  1322.        much advantage, since they'll already have a pretty good
  1323.        idea if the AI is in trouble or not.) */
  1324.     set_willing_to_draw(side, (chance > 0));
  1325.     /* Maybe resign. */
  1326.     if (chance > 0) {
  1327.     if (probability(chance)) {
  1328.         give_up(side);
  1329.     }
  1330.     }
  1331. }
  1332.  
  1333. /* If an mplayer resigns, it tries to help its friends. */
  1334.  
  1335. static void
  1336. give_up(side)
  1337. Side *side;
  1338. {
  1339.     Side *side1;
  1340.  
  1341.     /* If there is a human player, allow the human to make the final decision. */
  1342.     /* (should have a way to delegate this also, at least for testing purposes) */
  1343.     if (side_has_display(side)) {
  1344.     notify(side, "Your AI mplayer recommends resignation");
  1345.     return;
  1346.     }
  1347.     /* (should have to give units to controlling side if there is one) */
  1348.     /* (should controlling side be able to disallow resignation?) */
  1349.     /* Try to give away all of our units to an ally. */
  1350.     for_all_sides(side1) {
  1351.     if (side != side1 && allied_side(side, side1) && side1->ingame) {
  1352.         resign_game(side, side1);
  1353.         return;
  1354.     }
  1355.     }
  1356.     /* (should give to any positively-regarded side?) */
  1357.     /* No allies left in game, let everything become independent. */
  1358.     /* (should disband all units that can be disbanded?) */
  1359.     resign_game(side, NULL);
  1360. }
  1361.  
  1362. /* Go through all our units (and allied ones?). */
  1363.  
  1364. static void
  1365. review_units(side)
  1366. Side *side;
  1367. {
  1368.     Unit *unit, *occ, *unit2;
  1369.     Plan *plan;
  1370.     Theater *oldtheater, *theater;
  1371.     int u, u2, cp, cpmin, any;
  1372.  
  1373.     /* This code is specific to the "time" game. */
  1374.     if (game_class == gc_time) {
  1375.     for_all_unit_types(u) {
  1376.         u2 = mplayer(side)->research_on[u];
  1377.         if (mplayer(side)->research_status[u] == RS_RESEARCH_ASSIGNED) {
  1378.         /* is anyone researching? */
  1379.         unit2 = NULL;
  1380.         for_all_side_units(side, unit) {
  1381.             if (unit->type==u && in_play(unit) &&
  1382.             unit->plan && unit->plan->aicontrol) {
  1383.             if (unit->plan->tasks &&
  1384.                 unit->plan->tasks->type == TASK_RESEARCH &&
  1385.                 unit->plan->tasks->args[0] == u2) 
  1386.               unit2 = unit;
  1387.             }
  1388.         }
  1389.         if (unit2 != NULL) {
  1390.             DMprintf("%s is researching for %s on %s (level %d/%d)\n",
  1391.                  unit_desig(unit2), side_desig(side),
  1392.                  u_type_name(u2),
  1393.                  side->tech[u2], u_tech_to_build(u2));
  1394.         } else {
  1395.             DMprintf("no %s is researching for %s on %s!\n",
  1396.                  u_type_name(u), side_desig(side),
  1397.                  u_type_name(u2));
  1398.             mplayer(side)->research_status[u] = RS_RESEARCH_NEEDED;
  1399.         }
  1400.         }
  1401.         if (mplayer(side)->research_status[u] == RS_RESEARCH_NEEDED
  1402.         && needs_research (side, u2)) {
  1403.         /* pick for research a unit not building; 
  1404.            if all are building, choose the one which started last */
  1405.         unit2 = NULL;
  1406.         cpmin = 9999;
  1407.         any = 0;
  1408.         for_all_side_units(side, unit) {
  1409.             if (unit->type == u
  1410.             && in_play(unit)
  1411.             && unit->plan
  1412.             && unit->plan->aicontrol) {
  1413.             any = 1;
  1414.             cp = 0;
  1415.             occ = NULL;
  1416.             if ((unit->plan->tasks != NULL
  1417.                  && unit->plan->tasks->type == TASK_BUILD))
  1418.               occ = find_unit_to_complete(unit, unit->plan->tasks);
  1419.             if (occ != NULL) {
  1420.                 cp = occ->cp - uu_creation_cp(u,occ->type);
  1421.                 if (uu_cp_per_build(u,u2) > 0)
  1422.                   cp /= uu_cp_per_build(u,u2);
  1423.             }
  1424.             if (cp < cpmin) {
  1425.                 unit2 = unit;
  1426.                 cpmin = cp;
  1427.             }
  1428.             }
  1429.         }
  1430.         if (unit2 == NULL) {
  1431.             if (any)
  1432.               DMprintf("no %s is available to research for %s on %s!\n",
  1433.                    u_type_name(u), side_desig(side),
  1434.                    u_type_name(u2));
  1435.         } else {
  1436.             if (assign_to_research_on(side, unit2, u2)) {
  1437.             mplayer(side)->research_status[u] =
  1438.               RS_RESEARCH_ASSIGNED;
  1439.             }
  1440.         }
  1441.         }
  1442.     }
  1443.     }
  1444.  
  1445.     for_all_side_units(side, unit) {
  1446.     if (in_play(unit) && unit->plan && unit->plan->aicontrol) {
  1447.  
  1448.         /* code specific to the "time" game */
  1449.         if (game_class == gc_time) {
  1450.         u = unit->type;
  1451.         u2 = mplayer(side)->research_on[u];
  1452.  
  1453.         /* should we upgrade? */
  1454.         if (mplayer(side)->research_status[u] == RS_UPGRADE_NEEDED) {
  1455.             cp = 0;
  1456.             occ = NULL;
  1457.             if ((unit->plan->tasks != NULL &&
  1458.              unit->plan->tasks->type == TASK_BUILD))
  1459.               occ = find_unit_to_complete(unit, unit->plan->tasks);
  1460.             if (occ != NULL) {
  1461.             cp = occ->cp - uu_creation_cp(u,occ->type);
  1462.             if (uu_cp_per_build(u,u2)>0)
  1463.               cp /= uu_cp_per_build(u,u2);
  1464.             }
  1465.             if (occ != NULL && occ->type==u2) {
  1466.             /* already upgrading */
  1467.             DMprintf("%s is upgrading to %s (%d/%d cp)\n",
  1468.                  unit_desig(unit), u_type_name(u2),
  1469.                  occ->cp, u_cp(occ->type));
  1470.             } else if (cp >= u_cp(u2)/4) { /* rule-of-thumb... */
  1471.             /* complete unit under construction */
  1472.             DMprintf("%s will complete %s (now %d/%d cp) before upgrading to %s\n",
  1473.                  unit_desig(unit), u_type_name(occ->type),
  1474.                  occ->cp, u_cp(occ->type), u_type_name(u2));
  1475.             } else {
  1476.             /* start upgrading */
  1477.             if (occ != NULL && !fullsized(occ)) {
  1478.                 DMprintf("%s will drop work on %s (%d/%d cp) and immediately start upgrading to %s\n",
  1479.                  unit_desig(unit), u_type_name(occ->type),
  1480.                  occ->cp, u_cp(occ->type), u_type_name(u2));
  1481.             } else {
  1482.                 DMprintf("%s will start upgrading to %s\n",
  1483.                      unit_desig(unit), u_type_name(u2));
  1484.             }
  1485.             unit->plan->type = PLAN_PASSIVE;
  1486.             clear_task_agenda(unit->plan);
  1487.             set_construction(unit, u2, 1);
  1488.             }
  1489.         }
  1490.         }
  1491.  
  1492.         plan = unit->plan;
  1493.         oldtheater = unit_theater(unit);
  1494.         /* Goal might have become satisfied. */
  1495.         if (plan->maingoal) {
  1496.         if (goal_truth(side, plan->maingoal) == 100) {
  1497.             DMprintf("%s %s satisfied, removing\n",
  1498.                  unit_desig(unit), goal_desig(plan->maingoal));
  1499.             plan->maingoal = NULL;
  1500.             /* Force a replan. */
  1501.             plan->type = PLAN_NONE;
  1502.             set_unit_theater(unit, NULL);
  1503.         }
  1504.         }
  1505.         /* Theater might have become explored enough (90% known). */
  1506.         if (plan->type == PLAN_EXPLORATORY
  1507.             && (theater = unit_theater(unit)) != NULL
  1508.             && theater->unexplored < theater->size / 10) {
  1509.             DMprintf("%s theater %s is mostly known\n",
  1510.                  unit_desig(unit), theater->name);
  1511.             plan->maingoal = NULL;
  1512.             /* Force a replan. */
  1513.             plan->type = PLAN_NONE;
  1514.             set_unit_theater(unit, NULL);
  1515.         }
  1516.         theater = unit_theater(unit);
  1517.         DMprintf("%s currently assigned to %s",
  1518.                  unit_desig(unit),
  1519.              (theater ? theater->name : "no theater"));
  1520.         if (oldtheater != theater) {
  1521.             DMprintf(" (was %s)",
  1522.              (oldtheater ? oldtheater->name : "no theater"));
  1523.         }
  1524.         DMprintf("\n");
  1525.     }
  1526.     }
  1527.     /* Could notify display about unit plan mix? */
  1528. }
  1529.  
  1530. /* Look at our current overall strategy and hack it as needed. */
  1531.  
  1532. static void
  1533. update_side_strategy(side)
  1534. Side *side;
  1535. {
  1536.     Theater *theater;
  1537.  
  1538.     Dprintf("%s updating strategy\n", side_desig(side));
  1539.     /* Add something to add/update theaters as things open up. (?) */
  1540.     for_all_theaters(side, theater) {
  1541.     decide_theater_needs(side, theater);
  1542.     }
  1543. }
  1544.  
  1545. /* Figure out how many units to request for each area. */
  1546.  
  1547. static void
  1548. decide_theater_needs(side, theater)
  1549. Side *side;
  1550. Theater *theater;
  1551. {
  1552.     if (theater->unexplored > 0) {
  1553.         /* Exploration is less important when 90% of a theater is known. */
  1554.         if (theater->unexplored > (theater->size / 10)) {
  1555.         ++(mplayer(side)->explorersneeded);
  1556.         }
  1557.     /* Should look for good exploration units. */
  1558.     theater->importance = 50;  /* should depend on context */
  1559. /*    theater->reinforce = EXPLORE_AREA;  */
  1560. #if 0
  1561.     } else if (0 /* few enemies? */) {
  1562.     if (theater->allied_makers == 0
  1563.         && theater->makers > 0
  1564.         && theater->nearby) {
  1565.         theater->reinforce = GUARD_BORDER_TOWN + 2 * theater->makers;
  1566.     } else if (theater->makers > 0) {
  1567.         theater->reinforce = (theater->border ? GUARD_BORDER_TOWN :
  1568.                   GUARD_TOWN) + 2 * theater->allied_makers;
  1569.     } else if (theater->allied_bases > 0) {
  1570.         theater->reinforce = (theater->border ? GUARD_BORDER: GUARD_BASE);
  1571.     } else if (theater->border) {
  1572.         theater->reinforce = NO_UNITS;
  1573.     } else {
  1574.         theater->reinforce = NO_UNITS;
  1575.     }
  1576.     } else {
  1577.     if (theater->allied_makers > 0) {
  1578.         theater->reinforce = DEFEND_TOWN + 5 * theater->makers;
  1579.     } else if (theater->allied_bases > 0) {
  1580.         theater->reinforce = DEFEND_BASE + theater->allied_bases;
  1581.     } else {
  1582.         theater->reinforce = 0 /* DEFEND_AREA */;
  1583.     }
  1584. #endif
  1585.     }
  1586. }
  1587.  
  1588. /* For each unit, decide what it should be doing (if anything).  This is
  1589.    when a side takes the initiative;  a unit can also request info from
  1590.    its side when it is working on its individual plan. */
  1591.  
  1592. static void
  1593. update_unit_plans(side)
  1594. Side *side;
  1595. {
  1596.     Unit *unit;
  1597.  
  1598.     for_all_side_units(side, unit) {
  1599.     if (is_active(unit) && unit->plan != NULL) {
  1600.         mplayer_decide_plan(side, unit);
  1601.     }
  1602.     }
  1603. }
  1604.  
  1605. /* Randomly change a unit's plans.  (This is really more for
  1606.    debugging, exercising plan execution code in novel ways.) */
  1607.  
  1608. static void
  1609. update_unit_plans_randomly(side)
  1610. Side *side;
  1611. {
  1612.     Unit *unit;
  1613.  
  1614.     for_all_side_units(side, unit) {
  1615.     if (is_active(unit) && unit->plan && unit->plan->aicontrol) {
  1616.         if (probability(10)) {
  1617.         DMprintf("Randomly changed %s plan %s",
  1618.              unit_desig(unit), plan_desig(unit->plan));
  1619.         unit->plan->type = xrandom((int) NUMPLANTYPES);
  1620.         DMprintf("to plan %s\n", plan_desig(unit->plan));
  1621.         }
  1622.         /* (should add/remove goals randomly) */
  1623.         if (probability(10)) {
  1624.         unit->plan->reserve = FALSE;
  1625.         }
  1626.         if (probability(10)) {
  1627.         unit->plan->asleep = FALSE;
  1628.         }
  1629.     }
  1630.     }
  1631. }
  1632.  
  1633. /* Push a new goal onto the side's list of goals. */
  1634.  
  1635. /* (this should only add goals that are not already present) */
  1636.  
  1637. static void
  1638. add_goal(side, goal)
  1639. Side *side;
  1640. Goal *goal;
  1641. {
  1642.     if (mplayer(side)->numgoals < MAXGOALS) {
  1643.     mplayer(side)->goals[(mplayer(side)->numgoals)++] = goal;
  1644.     }
  1645. }
  1646.  
  1647. static Goal *
  1648. has_goal(side, goaltype)
  1649. Side *side;
  1650. GoalType goaltype;
  1651. {
  1652.     int i;
  1653.     Goal *goal;
  1654.  
  1655.     for (i = 0; i < mplayer(side)->numgoals; ++i) {
  1656.     goal = mplayer(side)->goals[i];
  1657.     if (goal != NULL && goal->type == goaltype) {
  1658.         return goal;
  1659.     }
  1660.     }
  1661.     return NULL;
  1662. }
  1663.  
  1664. static Goal *
  1665. has_unsatisfied_goal(side, goaltype)
  1666. Side *side;
  1667. GoalType goaltype;
  1668. {
  1669.     int i;
  1670.     Goal *goal;
  1671.  
  1672.     for (i = 0; i < mplayer(side)->numgoals; ++i) {
  1673.     goal = mplayer(side)->goals[i];
  1674.     if (goal != NULL && goal->type == goaltype && goal_truth(side, goal) < 100) {
  1675.         return goal;
  1676.     }
  1677.     }
  1678.     return NULL;
  1679. }
  1680.  
  1681. /* This is for when a unit needs a plan and asks its side for one. */
  1682.  
  1683. static void
  1684. mplayer_decide_plan(side, unit)
  1685. Side *side;
  1686. Unit *unit;
  1687. {
  1688.     Plan *plan = unit->plan;
  1689.     int u = unit->type;
  1690.  
  1691.     if (plan == NULL || !plan->aicontrol)
  1692.       return;
  1693.  
  1694.     /* code specific to the "time" game */
  1695.     /* don't mess up with units researching or upgrading */
  1696.     if (game_class == gc_time) {
  1697.     if (mplayer(side)->research_status[u] == RS_UPGRADE_NEEDED
  1698.         && plan->tasks != NULL
  1699.         && plan->tasks->type == TASK_BUILD)
  1700.       return;
  1701.     if (mplayer(side)->research_status[u] == RS_RESEARCH_ASSIGNED
  1702.         && plan->tasks != NULL
  1703.         && plan->tasks->type == TASK_RESEARCH)
  1704.       return;
  1705.     }
  1706.  
  1707.     if (!mplayer(side)->trytowin) {
  1708.     plan->type = PLAN_RANDOM;
  1709.     clear_task_agenda(unit->plan);
  1710.     return;
  1711.     }
  1712.     switch (plan->type) {
  1713.       case PLAN_PASSIVE:
  1714.       case PLAN_NONE:
  1715.     if (mobile(unit->type)) {
  1716.         /* Maybe assign to exploration. */
  1717.         if (has_goal(side, GOAL_WORLD_KNOWN)) {
  1718.         if (need_this_type_to_explore(side, unit->type)) {
  1719.             /* also limit to a total percentage, in case
  1720.                exploration needs are very high */
  1721.             assign_to_exploration(side, unit);
  1722.             return;
  1723.         }
  1724.         }
  1725.         if (type_can_attack(unit->type) || type_can_fire(unit->type)) {
  1726.         /* (A more precise test would be "can attack types known to be or
  1727.             likely to be in the current game".) */
  1728.         assign_to_offense(side, unit);
  1729.         } else {
  1730.         assign_to_offense_support(side, unit);
  1731.         }
  1732.         /* when should mobile units be assigned to defense?? */
  1733.     } else {
  1734.         if (has_unsatisfied_goal(side, GOAL_VICINITY_HELD)
  1735.         && type_can_build_attackers(side, unit->type)
  1736.         ) {
  1737.             assign_to_offense_support(side, unit);
  1738.         } else if (has_goal(side, GOAL_WORLD_KNOWN)
  1739.             && need_this_type_to_build_explorers(side, unit->type)) {
  1740.         assign_to_explorer_construction(side, unit);
  1741.         } else if (type_can_build_attackers(side, unit->type)) {
  1742.             assign_to_offense_support(side, unit);
  1743.         } else {
  1744.         assign_to_defense_support(side, unit);
  1745.         }
  1746.     }
  1747.     break;
  1748.       case PLAN_OFFENSIVE:
  1749.     /* leave plan alone */
  1750.     break;
  1751.       case PLAN_EXPLORATORY:
  1752.     /* leave plan alone */
  1753.     break;
  1754.       case PLAN_DEFENSIVE:
  1755.     /* leave plan alone */
  1756.     break;
  1757.       default:
  1758.     break;
  1759.     }
  1760. }
  1761.  
  1762. static int
  1763. need_this_type_to_explore(side, u)
  1764. Side *side;
  1765. int u;
  1766. {
  1767.     int s, numcontacted = 0, numfound = 0;
  1768.  
  1769.     if (!mobile(u))
  1770.       return FALSE;
  1771.     for (s = 1; s <= numsides; ++s) {
  1772.         if (s == side->id)
  1773.           continue;
  1774.     if (mplayer(side)->contacted[s])
  1775.       ++numcontacted;
  1776.     if (mplayer(side)->homefound[s])
  1777.       ++numfound;
  1778.     }
  1779.     if (numcontacted == 0) {
  1780.     return TRUE;
  1781.     } else if (numfound == 0) {
  1782.     return probability(50);
  1783.     } else if (numfound < numsides - 1) {
  1784.     return probability(10);
  1785.     } else {
  1786.     return FALSE;
  1787.     }
  1788. }
  1789.  
  1790. struct weightelt {
  1791.     int weight;
  1792.     long data;
  1793. };
  1794.  
  1795. static int
  1796. compare_weights(w1, w2)
  1797. CONST void *w1, *w2;
  1798. {
  1799.     return (((struct weightelt *) w2)->weight - ((struct weightelt *) w1)->weight);
  1800. }
  1801.  
  1802. /* Set the unit up as an explorer and let it go. */
  1803.  
  1804. static void
  1805. assign_to_exploration(side, unit)
  1806. Side *side;
  1807. Unit *unit;
  1808. {
  1809.     int numweights = 0, weight, i, dist;
  1810.     struct weightelt weights[MAXTHEATERS];
  1811.     Theater *theater;
  1812.  
  1813.     /* Unit's goal in life will be to see that the world is all known. */
  1814.     unit->plan->type = PLAN_EXPLORATORY;
  1815.     set_unit_theater(unit, NULL);
  1816.     /* Find the theater most in need of exploration. */
  1817.     for_all_theaters(side, theater) {
  1818.         if (theater->size > 0 && theater->unexplored > 0) {
  1819.         /* Weight by percentage of theater that is unknown. */
  1820.         weight = (100 * theater->unexplored) / theater->size;
  1821.         /* Downrate theaters that are far away. */
  1822.         dist = distance(unit->x, unit->y, theater->x, theater->y)
  1823.           - isqrt(theater->size) / 2;
  1824.         if (dist < 0)
  1825.           dist = 0;
  1826.         weight /= max(1, (4 * dist) / area.maxdim);
  1827.         /* Uprate the home front by a lot. */
  1828.         if (theater == mplayer(side)->homefront)
  1829.           weight *= 4;
  1830.         /* Flatten out 10% variations. */
  1831.         weight = 10 * (weight / 10);
  1832.         weights[numweights].weight = weight;
  1833.         weights[numweights].data = theater->id;
  1834.         ++numweights;
  1835.         }
  1836.     }
  1837.     if (numweights > 0) {
  1838.         qsort(weights, numweights, sizeof(struct weightelt), compare_weights);
  1839.         /* Choose randomly among theaters of equal weight. */
  1840.         for (i = 0; i < numweights; ++i)
  1841.       if (weights[i].weight < weights[0].weight)
  1842.         break;
  1843.         theater = mplayer(side)->theatertable[weights[xrandom(i)].data];
  1844.     } else {
  1845.         theater = NULL;
  1846.     }
  1847.     assign_explorer_to_theater(side, unit, theater);
  1848. }
  1849.  
  1850. static int
  1851. probably_explorable(side, x, y, u)
  1852. Side *side;
  1853. int x, y, u;
  1854. {
  1855.     int dir, x1, y1, tview, t;
  1856.  
  1857.     for_all_directions(dir) {
  1858.     if (interior_point_in_dir(x, y, dir, &x1, &y1)) {
  1859.         tview = terrain_view(side, x, y);
  1860.         if (tview == UNSEEN)
  1861.           return TRUE;
  1862.         t = vterrain(tview);
  1863.         if (could_be_on(u, t) && could_live_on(u, t))
  1864.           return TRUE;
  1865.     }
  1866.     }
  1867.     return FALSE;
  1868. }
  1869.  
  1870. static void
  1871. assign_explorer_to_theater(side, unit, theater)
  1872. Side *side;
  1873. Unit *unit;
  1874. Theater *theater;
  1875. {
  1876.     int sq, x, y, tries = 0;
  1877.     Goal *goal;
  1878.     
  1879.     if (theater != NULL) {
  1880.     set_unit_theater(unit, theater);
  1881.     ++(theater->numassigned[unit->type]);
  1882.     goal = create_goal(GOAL_VICINITY_KNOWN, side, TRUE);
  1883.     sq = isqrt(theater->size);
  1884.     while (++tries < 100) {
  1885.         /* Select a random point within the theater. */
  1886.         x = theater->xmin;  y = theater->ymin;
  1887.         x += (xrandom(theater->xmax - theater->xmin)
  1888.           + xrandom(theater->xmax - theater->xmin)) / 2;
  1889.         y += (xrandom(theater->ymax - theater->ymin)
  1890.           + xrandom(theater->ymax - theater->ymin)) / 2;
  1891.         if (theater_at(side, x, y) == theater
  1892.         && terrain_view(side, x, y) == UNSEEN
  1893.         && probably_explorable(side, x, y, unit->type))
  1894.           break;
  1895.     }
  1896.     goal->args[0] = x;  goal->args[1] = y;
  1897.     goal->args[2] = goal->args[3] = sq / 2;
  1898.     unit->plan->maingoal = goal;
  1899.     DMprintf("%s now assigned to exploration in %s, around %d,%d\n",
  1900.          unit_desig(unit), theater->name, x, y);
  1901.     }
  1902. }
  1903.  
  1904. static int
  1905. need_this_type_to_build_explorers(side, u)
  1906. Side *side;
  1907. int u;
  1908. {
  1909.     int s, u2;
  1910.     
  1911.     for (s = 1; s <= numsides; ++s) {
  1912.     if (mplayer(side)->contacted[s])
  1913.       return FALSE;
  1914.     if (mplayer(side)->homefound[s])
  1915.       return FALSE;
  1916.     }
  1917.     for_all_unit_types(u2) {
  1918.     if (mobile(u2)
  1919.         /* should also check u2 is a useful explorer */
  1920.         && uu_acp_to_create(u, u2) > 0)
  1921.       return TRUE;
  1922.     }
  1923.     return FALSE;
  1924. }
  1925.  
  1926. /* Explorer constructors concentrate on building types that are good for
  1927.    exploration. */
  1928.  
  1929. static void
  1930. assign_to_explorer_construction(side, unit)
  1931. Side *side;
  1932. Unit *unit;
  1933. {
  1934.     /* Unit's goal in life will be to help see that the world is all known. */
  1935.     unit->plan->type = PLAN_EXPLORATORY;
  1936.     DMprintf("%s assigned to explorer construction\n", unit_desig(unit));
  1937. }
  1938.  
  1939. static void
  1940. assign_to_offense(side, unit)
  1941. Side *side;
  1942. Unit *unit;
  1943. {
  1944.     int numweights = 0, weight;
  1945.     struct weightelt weights[MAXTHEATERS];
  1946.     Goal *goal;
  1947.     Theater *homefront, *theater;
  1948.  
  1949.     unit->plan->type = PLAN_OFFENSIVE;
  1950.     clear_task_agenda(unit->plan);
  1951.     /* If our home area is being threatened, assign the unit to it. */
  1952.     homefront = mplayer(side)->homefront;
  1953.     if (homefront != NULL && homefront->enemystrengthmin > 0) {
  1954.     set_unit_theater(unit, homefront);
  1955.     goal = create_goal(GOAL_VICINITY_HELD, side, TRUE);
  1956.     goal->args[0] = homefront->x;  goal->args[1] = homefront->y;
  1957.     goal->args[2] = goal->args[3] = isqrt(homefront->size);
  1958.     unit->plan->maingoal = goal;
  1959.     DMprintf("%s assigned to offensive in the home front\n",
  1960.          unit_desig(unit));
  1961.     return;
  1962.     }
  1963.     /* If the theater the unit is currently in is being threatened, assign the unit to it. */
  1964.     /* (should just increase it weight in next calculation?) */
  1965.     theater = theater_at(side, unit->x, unit->y);
  1966.     if (theater != NULL && theater->enemystrengthmin > 0) {
  1967.     set_unit_theater(unit, theater);
  1968.     goal = create_goal(GOAL_VICINITY_HELD, side, TRUE);
  1969.     /* (should randomize?) */
  1970.     goal->args[0] = theater->x;  goal->args[1] = theater->y;
  1971.     goal->args[2] = (theater->xmax - theater->xmin) / 2;
  1972.     goal->args[3] = (theater->ymax - theater->ymin) / 2;
  1973.     unit->plan->maingoal = goal;
  1974.     DMprintf("%s assigned to offensive in the theater where it's at now\n",
  1975.          unit_desig(unit));
  1976.     return;
  1977.     }
  1978.     for_all_theaters(side, theater) {
  1979.         if (theater->enemystrengthmin > 0 || theater->unexplored > 0) {
  1980.         /* (should weight by strength relative to own units already there) */
  1981.         weight = theater->enemystrengthmax * 20;
  1982.         /* Prefer not to send unit to farther-away theaters. */
  1983.         if (distance(unit->x, unit->y, theater->x, theater->y) > area.maxdim / 2) {
  1984.         weight /= 2;
  1985.         }
  1986.         /* Prefer theaters with more unknown territory. */
  1987.         weight += (10 * theater->unexplored) / max(1, theater->size);
  1988.         weights[numweights].weight = weight;
  1989.         weights[numweights].data = theater->id;
  1990.         ++numweights;
  1991.         }
  1992.     }
  1993.     if (numweights > 0) {
  1994.         qsort(weights, numweights, sizeof(struct weightelt), compare_weights);
  1995.         theater = mplayer(side)->theatertable[weights[0].data];
  1996.     } else {
  1997.         theater = theater_at(side, unit->x, unit->y);
  1998.     }
  1999.     set_unit_theater(unit, theater);
  2000.     if (theater != NULL) {
  2001.     ++(theater->numassigned[unit->type]);
  2002.     goal = create_goal(GOAL_VICINITY_HELD, side, TRUE);
  2003.     /* (should randomize?) */
  2004.     goal->args[0] = theater->x;  goal->args[1] = theater->y;
  2005.     goal->args[2] = (theater->xmax - theater->xmin) / 2;
  2006.     goal->args[3] = (theater->ymax - theater->ymin) / 2;
  2007.     unit->plan->maingoal = goal;
  2008.     DMprintf("%s now assigned to offensive in %s",
  2009.          unit_desig(unit), theater->name);
  2010.     if (numweights > 1) {
  2011.         DMprintf(" (weight %d; runnerup was %s, weight %d)",
  2012.              weights[0].weight,
  2013.              (mplayer(side)->theatertable[weights[1].data])->name,
  2014.              weights[1].weight);
  2015.     }
  2016.     DMprintf("\n");
  2017.     } else {
  2018.     DMprintf("%s now assigned to offensive in no theater",
  2019.          unit_desig(unit));
  2020.     }
  2021. }
  2022.  
  2023. static void
  2024. assign_to_offense_support(side, unit)
  2025. Side *side;
  2026. Unit *unit;
  2027. {
  2028.     unit->plan->type = PLAN_OFFENSIVE;
  2029.     clear_task_agenda(unit->plan);
  2030. }
  2031.  
  2032. static int
  2033. type_can_build_attackers(side, u)
  2034. Side *side;
  2035. int u;
  2036. {
  2037.     int u2;
  2038.     
  2039.     for_all_unit_types(u2) {
  2040.     if (mobile(u2)
  2041.         && (type_can_attack(u2) || type_can_fire(u2))
  2042.         && uu_acp_to_create(u, u2) > 0)
  2043.       return TRUE;
  2044.     }
  2045.     return FALSE;
  2046. }
  2047.  
  2048. /* For the given side and unit and plan, calculate the right type of
  2049.    unit to build. */
  2050.  
  2051. static int
  2052. mplayer_preferred_build_type(side, unit, plantype)
  2053. Side *side;
  2054. Unit *unit;
  2055. int plantype;
  2056. {
  2057.     int u = unit->type, u2, u3, t;
  2058.     int x, y, dir, x1, y1, blockedallaround, uview, est, rslt;
  2059.     int prefs[MAXUTYPES], knownterrain[MAXTTYPES];
  2060.     int fringeterrain[MAXTTYPES], sumfringe, totfringe;
  2061.     int enemytypes[MAXUTYPES];
  2062.     int numtotransport[MAXUTYPES];
  2063.     Unit *unit2, *occ;
  2064.     Theater *theater;
  2065.  
  2066.     if (plantype == PLAN_EXPLORATORY) {
  2067.     /* Calculate the amount of each type of terrain at the edges
  2068.        of the known world. */
  2069.     for_all_terrain_types(t)
  2070.       knownterrain[t] = fringeterrain[t] = 0;
  2071.     for_all_interior_cells(x, y) {
  2072.         if (terrain_view(side, x, y) != UNSEEN) {
  2073.         ++(knownterrain[(int) terrain_at(x, y)]);
  2074.         for_all_directions(dir) {
  2075.             point_in_dir(x, y, dir, &x1, &y1);
  2076.             if (terrain_view(side, x1, y1) == UNSEEN) {
  2077.             ++(fringeterrain[(int) terrain_at(x, y)]);
  2078.             break;
  2079.             }
  2080.         }
  2081.         }
  2082.     }
  2083.     } else {
  2084.     /* should use estimated strengths instead? */
  2085.         for_all_unit_types(u2)
  2086.           enemytypes[u2] = 0;
  2087.         for_all_interior_cells(x, y) {
  2088.         if (can_see_actual_units(side, x, y)) {
  2089.         for_all_stack(x, y, unit2) {
  2090.             if (!trusted_side(side, unit2->side))
  2091.               ++enemytypes[unit2->type];
  2092.             /* (should count occ types recursively also) */
  2093.             for_all_occupants(unit2, occ) {
  2094.             ++enemytypes[occ->type];
  2095.             }
  2096.         }
  2097.         } else {
  2098.         uview = unit_view(side, x, y);
  2099.         if (uview != EMPTY) {
  2100.             if (!trusted_side(side, side_n(vside(uview))))
  2101.               ++enemytypes[vtype(uview)];
  2102.         }
  2103.         }
  2104.         }
  2105.     }
  2106.     /* Calculate a basic preference for each possible type. */
  2107.     for_all_unit_types(u2) {
  2108.     prefs[u2] = 0;
  2109.     est = est_completion_time(unit, u2);
  2110.     if (could_create(u, u2)
  2111.         /* tmp hack until mplayer can do research */
  2112.         && (u_tech_to_build(u2) > 0 ? side->tech[u2] >= u_tech_to_build(u2) : TRUE)
  2113.         && est >= 0
  2114.         && type_allowed_on_side(u2, side)) {
  2115.         if (0 /* any demand in this unit's theater */) {
  2116.         } else if (need_more_transportation(side)) {
  2117.             for_all_unit_types(u3) {
  2118.             numtotransport[u3] = 0;
  2119.             }
  2120.             for_all_theaters(side, theater) {
  2121.             for_all_unit_types(u3) {
  2122.             numtotransport[u3] += theater->numtotransport[u3];
  2123.             }
  2124.             }
  2125.             for_all_unit_types(u3) {
  2126.             if (numtotransport[u3] > 0
  2127.             && mobile(u2)
  2128.             && could_carry(u2, u3)) {
  2129.             prefs[u2] += numtotransport[u3];
  2130.             }
  2131.             }
  2132.         } else {
  2133.         /* Prefer units by overall suitability for general plan. */
  2134.         if (plantype == PLAN_EXPLORATORY) {
  2135.             /* Weight unit types by suitability for exploration around
  2136.                the edges of the known area. */
  2137.             sumfringe = totfringe = 0;
  2138.             for_all_terrain_types(t) {
  2139.             totfringe += fringeterrain[t];
  2140.             if (!terrain_always_impassable(u2, t))
  2141.               sumfringe += fringeterrain[t];
  2142.             }
  2143.             if (totfringe < 1)
  2144.               sumfringe = totfringe = 1;
  2145.             /* Scale - so 5% diffs in amt of crossable terrain
  2146.                don't affect result. */
  2147.             prefs[u2] = (20 * sumfringe) / totfringe;
  2148.             /* Prefer types that are quicker to build. */
  2149.             prefs[u2] /= max(1, est / 8);
  2150.         } else {
  2151.             /* Weight unit types by effectiveness against known enemies. */
  2152.             for_all_unit_types(u3) {
  2153.             if (enemytypes[u3] > 0) {
  2154.                 if (uu_zz_bhw(u2, u3) > 0) {
  2155.                 prefs[u2] += uu_zz_bhw(u2, u3) * enemytypes[u3];
  2156.                 }
  2157.                 if (uu_zz_bcw(u2, u3) > 0) {
  2158.                 prefs[u2] += uu_zz_bcw(u2, u3) * enemytypes[u3];
  2159.                 }
  2160.             }
  2161.             }
  2162.             /* Prefer types that are quicker to build. */
  2163.             prefs[u2] /= max(1, est / 8);
  2164.         }
  2165.         if (prefs[u2] < 1)
  2166.           prefs[u2] = 1;
  2167.         }
  2168.     }
  2169.     }
  2170.     /* Units that can't even get out of the builder get their preference
  2171.        cut.  This helps prevent the construction of large ships in Denver. */
  2172.     /* (should allow if units would have some other way to leave) */
  2173.     if (1 /* plantype == PLAN_EXPLORATORY */) {
  2174.     for_all_unit_types(u2) {
  2175.         if (prefs[u2] > 0) {
  2176.         blockedallaround = TRUE;
  2177.         for_all_directions(dir) {
  2178.             point_in_dir(unit->x, unit->y, dir, &x1, &y1);
  2179.             if (!terrain_always_impassable(u2, terrain_at(x1, y1))) {
  2180.                 blockedallaround = FALSE;
  2181.                 break;
  2182.             }
  2183. #if 0  /* should replace this with a more useful test */
  2184.             if (unit_at(x1, y1) != NULL) {
  2185.                 blockedallaround = FALSE;
  2186.                 break;
  2187.             }
  2188. #endif
  2189.         }
  2190.         if (blockedallaround)
  2191.           prefs[u2] = 0;
  2192.         }
  2193.     }
  2194.     }
  2195.     DMprintf("%s preferred build type is ", unit_desig(unit));
  2196.     /* Look for an existing incomplete occupant and prefer to build its type,
  2197.        if it is in the choices in the typelist. */
  2198.     for_all_occupants(unit, occ) {
  2199.     if (in_play(occ) && !completed(occ)) {
  2200.         if (prefs[occ->type] > 0 && flip_coin()) {
  2201.         rslt = occ->type;
  2202.         DMprintf("%s (incomplete occupant)\n", u_type_name(rslt));
  2203.         return rslt;
  2204.         }
  2205.     }
  2206.     }
  2207.     for_all_unit_types(u2)
  2208.       if (prefs[u2] < 0)
  2209.         prefs[u2] = 0;
  2210.     rslt = select_by_weight(prefs, numutypes);
  2211.     if (!is_unit_type(rslt))
  2212.       rslt = NONUTYPE;
  2213.     if (DebugM) {
  2214.     if (is_unit_type(rslt)) {
  2215.         DMprintf("%s (choices were", u_type_name(rslt));
  2216.         for_all_unit_types(u2) {
  2217.         if (prefs[u2] > 0)
  2218.           DMprintf(" %s,%d", utype_name_n(u2, 1), prefs[u2]);
  2219.         }
  2220.         DMprintf(")");
  2221.     } else {
  2222.         DMprintf("nothing (no choices)");
  2223.     }
  2224.     DMprintf("\n");
  2225.     }
  2226.     return rslt;
  2227. }
  2228.  
  2229. /* (should make this a generic routine) */
  2230.  
  2231. static int
  2232. select_by_weight(arr, numvals)
  2233. int *arr, numvals;
  2234. {
  2235.     int sum = 0, i, n;
  2236.  
  2237.     sum = 0;
  2238.     for (i = 0; i < numvals; ++i) {
  2239.     sum += arr[i];
  2240.     }
  2241.     if (sum == 0)
  2242.       return -1;
  2243.     /* We now know the range, make a random index into it. */
  2244.     n = xrandom(sum);
  2245.     /* Go through again to figure out which choice the index refs. */
  2246.     sum = 0;
  2247.     for (i = 0; i < numvals; ++i) {
  2248.     sum += arr[i];
  2249.     if (sum >= n) {
  2250.         return i;
  2251.     }
  2252.     }
  2253.     run_error("Ooh weird");
  2254.     return -1;
  2255. }
  2256.  
  2257. static int
  2258. need_more_transportation(side)
  2259. Side *side;
  2260. {
  2261.     int u3, u2, anytransport;
  2262.     Theater *theater;
  2263.  
  2264.     for_all_theaters(side, theater) {
  2265.     for_all_unit_types(u3) {
  2266.         if (theater->numtotransport[u3] > 0) {
  2267.         anytransport = FALSE;
  2268.         for_all_unit_types(u2) {
  2269.             if (theater->numassigned[u2] > 0
  2270.             && mobile(u2)
  2271.             && could_carry(u2, u3))
  2272.               anytransport = TRUE;
  2273.         }
  2274.         if (!anytransport)
  2275.           return TRUE;
  2276.         }
  2277.     }
  2278.     }
  2279.     return FALSE;
  2280. }
  2281.  
  2282. static void
  2283. assign_to_defense_support(side, unit)
  2284. Side *side;
  2285. Unit *unit;
  2286. {
  2287.     unit->plan->type = PLAN_DEFENSIVE;
  2288.     clear_task_agenda(unit->plan);
  2289. }
  2290.  
  2291. static int
  2292. can_research_on(u, u2)
  2293. int u;
  2294. int u2;
  2295. {
  2296.     int acp_res = uu_acp_to_research(u, u2);
  2297.  
  2298.     if (acp_res < 1 || acp_res > u_acp(u))
  2299.       return 0;
  2300.  
  2301.     return 1;
  2302. }
  2303.  
  2304. /* code specific to the "time" game */
  2305. static int 
  2306. needs_research (side, u)
  2307. Side *side;
  2308. int u;
  2309. {
  2310.     int u2, i;
  2311.  
  2312.     if (game_class != gc_time)
  2313.       return 0;
  2314.  
  2315.     if (side->tech[u] >= u_tech_to_build(u) ||
  2316.     u_tech_max(u)  > u_tech_to_build(u))
  2317.       return 0;
  2318.     
  2319.     i = 0;
  2320.     for_all_unit_types(u2) {
  2321.     i += uu_acp_to_create(u, u2) > 0;
  2322.     }
  2323.     if (i < 2)
  2324.       return 0;
  2325.  
  2326.     return 1;
  2327. }
  2328.  
  2329. static int
  2330. assign_to_research_on(side, unit, u2)
  2331. Side *side;
  2332. Unit *unit;
  2333. int u2;
  2334. {
  2335.     int lev = u_tech_to_build(u2);
  2336.  
  2337.     if (!can_research_on(unit->type, u2)) {
  2338.     DMprintf("%s cannot research on %s!\n",
  2339.          unit_desig(unit), u_type_name(u2));
  2340.     return 0;
  2341.     }
  2342.  
  2343.     DMprintf("%s will research for %s on %s (to level %d)\n",
  2344.          unit_desig(unit), side_desig(side), u_type_name(u2), lev);
  2345.  
  2346.     unit->plan->type = PLAN_PASSIVE;
  2347.     push_research_task(unit, u2, lev);
  2348.     return 1;
  2349. }
  2350.  
  2351. /* This is called by individual plans to see if a particular unit type at a
  2352.    particular location is scheduled to be captured. */
  2353.  
  2354. static int
  2355. mplayer_planning_to_capture(side, u, x, y)
  2356. Side *side;
  2357. int u, x, y;
  2358. {
  2359.     Task *task;
  2360.     Unit *unit;
  2361.  
  2362.     for_all_side_units(side, unit) {
  2363.     if (in_play(unit)
  2364.         && unit->plan) {
  2365.         for_all_tasks(unit->plan, task) {
  2366.         if (task->type == TASK_CAPTURE
  2367.             && task->args[0] == x && task->args[1] == y
  2368.             && (task->args[2] == NONUTYPE || task->args[2] == u))
  2369.           return TRUE;
  2370.         if (task->type == TASK_HIT_UNIT
  2371.             && task->args[0] == x && task->args[1] == y
  2372.             && (task->args[2] == NONUTYPE || task->args[2] == u)
  2373.             && uu_capture(unit->type, u) > 0)
  2374.           return TRUE;
  2375.         }
  2376.     }
  2377.     }
  2378.     return FALSE;
  2379. }
  2380.  
  2381. /* This is called when an exploring unit gets confused about what to do. */
  2382.  
  2383. static int
  2384. mplayer_guide_explorer(side, unit)
  2385. Side *side;
  2386. Unit *unit;
  2387. {
  2388.     if (probability(10) && build_base_for_self(side, unit))
  2389.       return TRUE;
  2390.     if (probability(10) && build_base_for_others(side, unit))
  2391.       return TRUE;
  2392.     return FALSE;
  2393. }
  2394.  
  2395. /* Decide for the unit whether it should build a base for its own benefit. */
  2396.  
  2397. static int
  2398. build_base_for_self(side, unit)
  2399. Side *side;
  2400. Unit *unit;
  2401. {
  2402.     int u = unit->type, u2, cando = FALSE;
  2403.  
  2404.     for_all_unit_types(u2) {
  2405.     if (uu_acp_to_create(u, u2) > 0
  2406.         && (uu_creation_cp(u, u2) >= u_cp(u2)
  2407.             || uu_acp_to_build(u, u2) > 0)
  2408.         /* (should check if any advantage to building) */
  2409.        ) {
  2410.        cando = TRUE;
  2411.        break;
  2412.     }
  2413.     }
  2414.     if (cando) {
  2415.     DMprintf("%s building %s as a base for itself\n",
  2416.              unit_desig(unit), u_type_name(u2));
  2417.     set_construction(unit, u2, 1);
  2418.     return TRUE;
  2419.     }
  2420.     return FALSE;
  2421. }
  2422.  
  2423. /* Decide for the unit whether it should build a base to help other units. */
  2424.  
  2425. static int
  2426. build_base_for_others(side, unit)
  2427. Side *side;
  2428. Unit *unit;
  2429. {
  2430.     int u = unit->type, u2, cando = FALSE;
  2431.  
  2432.     for_all_unit_types(u2) {
  2433.     if (uu_acp_to_create(u, u2) > 0
  2434.         && (uu_creation_cp(u, u2) >= u_cp(u2)
  2435.             || uu_acp_to_build(u, u2) > 0)
  2436.         /* (should check if any advantage to building) */
  2437.        ) {
  2438.        cando = TRUE;
  2439.        break;
  2440.     }
  2441.     }
  2442.     if (cando) {
  2443.     DMprintf("%s building %s as a base for others\n",
  2444.              unit_desig(unit), u_type_name(u2));
  2445.     set_construction(unit, u2, 1);
  2446.     return TRUE;
  2447.     }
  2448.     return FALSE;
  2449. }
  2450.  
  2451. static int
  2452. build_depot_for_self(side, unit)
  2453. Side *side;
  2454. Unit *unit;
  2455. {
  2456.     int u = unit->type, u2, cando = FALSE;
  2457.  
  2458.     for_all_unit_types(u2) {
  2459.     if (uu_acp_to_create(u, u2) > 0
  2460.         && (uu_creation_cp(u, u2) >= u_cp(u2)
  2461.             || uu_acp_to_build(u, u2) > 0)
  2462.         /* (should check if any advantage to building) */
  2463.        ) {
  2464.        cando = TRUE;
  2465.        break;
  2466.     }
  2467.     }
  2468.     if (cando) {
  2469.     DMprintf("%s building %s as a depot for itself\n",
  2470.              unit_desig(unit), u_type_name(u2));
  2471.     set_construction(unit, u2, 1);
  2472.     return TRUE;
  2473.     }
  2474.     return FALSE;
  2475. }
  2476.  
  2477. static void
  2478. mplayer_react_to_action_result(side, unit, rslt)
  2479. Side *side;
  2480. Unit *unit;
  2481. int rslt;
  2482. {
  2483.     if (unit->plan
  2484.     && unit->plan->supply_is_low) {
  2485.     resupply_if_low(unit);
  2486.     }
  2487. }
  2488.  
  2489. /* This is a hook that runs after each task is executed. */
  2490.  
  2491. static void
  2492. mplayer_react_to_task_result(side, unit, task, rslt)
  2493. Side *side;
  2494. Unit *unit;
  2495. Task *task;
  2496. TaskOutcome rslt;
  2497. {
  2498.     int dx, dy, x1, y1, fact;
  2499.     Unit *occ;
  2500.     Theater *theater;
  2501.  
  2502.     /* React to an apparent blockage. */
  2503.     if (rslt == TASK_FAILED
  2504.     && task != NULL
  2505.     && task->type == TASK_MOVE_TO
  2506.     && task->retrynum > 2) {
  2507.     if (desired_direction_impassable(unit, task->args[0], task->args[1])) {
  2508.         if (could_be_ferried(unit, task->args[0], task->args[1])) {
  2509.         if (unit->plan->type == PLAN_EXPLORATORY && flip_coin()) {
  2510.                   /* (could also change task within the same theater) */
  2511.             DMprintf("%s blocked while exploring, changing theaters\n",
  2512.                  unit_desig(unit));
  2513.             change_to_adjacent_theater(side, unit);
  2514.             return;
  2515.         } else if (flip_coin()) {
  2516.             DMprintf("%s blocked, will wait for transport\n",
  2517.                  unit_desig(unit));
  2518.             theater = theater_at(side, unit->x, unit->y);
  2519.             if (theater != NULL) {
  2520.             ++(theater->numtotransport[unit->type]);
  2521.             }
  2522.             unit->plan->reserve = TRUE;
  2523.             unit->plan->waitingfortransport = TRUE;
  2524.             return;
  2525.         }
  2526.         } else {
  2527.             if (unit->occupant) {
  2528.             DMprintf("%s blocked while transporting, will sit briefly\n",
  2529.                  unit_desig(unit));
  2530.             unit->plan->reserve = TRUE;
  2531.             for_all_occupants(unit, occ) {
  2532.                 wake_unit(occ, FALSE, -1, NULL);
  2533.             }
  2534.             return;
  2535.             }
  2536.         /* Another option is to transfer to another theater.
  2537.            This is especially useful when exploring. */
  2538.         if (unit->plan->type == PLAN_EXPLORATORY && flip_coin()) {
  2539.             DMprintf("%s blocked while exploring, changing theaters\n",
  2540.                  unit_desig(unit));
  2541.             change_to_adjacent_theater(side, unit);
  2542.             return;
  2543.         }
  2544.         }
  2545.         /* Try moving sideways. */
  2546.         if (probability(80)) {
  2547.         dx = task->args[0] - unit->x;  dy = task->args[1] - unit->y;
  2548.         fact = (flip_coin() ? 50 : -50);
  2549.         x1 = unit->x - ((fact * dy) / 100);  y1 = unit->y + ((fact * dx) / 100);
  2550.         if (inside_area(x1, y1))
  2551.           push_move_near_task(unit, x1, y1, 1);
  2552.         }
  2553.         return;
  2554.     } else if (blocked_by_enemy(unit, task->args[0], task->args[1])) {
  2555.         /* (should decide if allowable risk to passengers) */
  2556.         DMprintf("%s blocked by enemy\n", unit_desig(unit));
  2557.         attack_blockage(side, unit, task->args[0], task->args[1]); 
  2558.     }
  2559.     return;
  2560.     }
  2561.     /* React to inability to resupply by trying to build a base. */
  2562.     if (rslt == TASK_FAILED
  2563.     && task != NULL
  2564.     && task->type == TASK_RESUPPLY
  2565.     && task->retrynum > 2) {
  2566.         set_unit_reserve(side, unit, FALSE, FALSE);
  2567.         build_depot_for_self(side, unit);
  2568.     }
  2569. #if 0    /* I'm not sure the following is really necessary - */
  2570.     /* - if the task fails, but a good victim is to be seen nearby, then the AI will
  2571.        eventually assign a unit to attack, quite likely the one whose task just failed. */
  2572.     /* React to a target unit trying to get away; if we can still see it nearby
  2573.        somewhere, adjust to pursue. */
  2574.     if (rslt == TASK_FAILED
  2575.     && task != NULL
  2576.     && task->type == TASK_HIT_UNIT
  2577.     ) {
  2578.     int u = unit->type, tx, ty, dist, enemythere, uview, u2, s2;
  2579.     Unit *unit2, *target;
  2580.  
  2581.     tx = task->args[0];  ty = task->args[1];
  2582.     tu = task->args[2];  ts = task->args[3];
  2583.     if (can_see_actual_units(side, tx, ty)) {
  2584.         for_all_stack(tx, ty, unit2) {
  2585.                 if (unit2->side != side
  2586.             && (tu == NONUTYPE || tu == unit2->type)
  2587.             ) {
  2588.             /* A target is still there; task must have failed for some
  2589.                other reason. */
  2590.             return;
  2591.             }
  2592.         }
  2593.         /* They're gone! */
  2594.     } else {
  2595.         /* Assess old image or emptiness. */
  2596.         uview = unit_view(side, tx, ty);
  2597.         if (uview != EMPTY) {
  2598.             if (tu == NONUTYPE || tu == vtype(uview)) {
  2599.                 /* Target is still here. */
  2600.                 return;
  2601.             }
  2602.         }
  2603.         /* They're gone! */
  2604.     }
  2605.     /* If we get here, the target's location is empty. */
  2606.     return;
  2607.     }
  2608. #endif
  2609. }
  2610.  
  2611. static void
  2612. change_to_adjacent_theater(side, unit)
  2613. Side *side;
  2614. Unit *unit;
  2615. {
  2616.     int dir;
  2617.     Theater *theater;
  2618.  
  2619.     theater = unit_theater(unit);
  2620.     if (theater != NULL) {
  2621.        for_all_directions(dir) {
  2622.            if (theater == mplayer(side)->perimeters[dir]) {
  2623.                assign_explorer_to_theater(side, unit,
  2624.                    mplayer(side)->perimeters[flip_coin() ? left_dir(dir) : right_dir(dir)]);
  2625.                break;
  2626.            }
  2627.            if (theater == mplayer(side)->midranges[dir]) {
  2628.                assign_explorer_to_theater(side, unit,
  2629.                    mplayer(side)->midranges[flip_coin() ? left_dir(dir) : right_dir(dir)]);
  2630.                break;
  2631.            }
  2632.            if (theater == mplayer(side)->remotes[dir]) {
  2633.                assign_explorer_to_theater(side, unit,
  2634.                    mplayer(side)->remotes[flip_coin() ? left_dir(dir) : right_dir(dir)]);
  2635.                break;
  2636.            }
  2637.        }
  2638.     }
  2639. }
  2640.  
  2641. /* (should account for impassability because of borders, etc) */
  2642.  
  2643. static int
  2644. desired_direction_impassable(unit, x, y)
  2645. Unit *unit;
  2646. int x, y;
  2647. {
  2648.     int dirs[NUMDIRS], numdirs, i, x1, y1, t, numbaddirs = 0;
  2649.  
  2650.     numdirs = choose_move_dirs(unit, x, y, TRUE, NULL, NULL, dirs);
  2651.     for (i = 0; i < numdirs; ++i) {
  2652.     point_in_dir(unit->x, unit->y, dirs[i], &x1, &y1);
  2653.     t = terrain_at(x1, y1);
  2654.     if (terrain_always_impassable(unit->type, t))
  2655.       ++numbaddirs;
  2656.     }
  2657.     return (numbaddirs == numdirs);
  2658. }
  2659.  
  2660. static int
  2661. could_be_ferried(unit, x, y)
  2662. Unit *unit;
  2663. int x, y;
  2664. {
  2665.     int dirs[NUMDIRS], numdirs, i, x1, y1, t, u2;
  2666.  
  2667.     if (!carryable(unit->type))
  2668.       return FALSE;
  2669.     numdirs = choose_move_dirs(unit, x, y, FALSE, NULL, NULL, dirs);
  2670.     for (i = 0; i < numdirs; ++i) {
  2671.     point_in_dir(unit->x, unit->y, dirs[i], &x1, &y1);
  2672.     t = terrain_at(x1, y1);
  2673.     /* See if there is a type that can carry us through via this direction. */
  2674.     for_all_unit_types(u2) {
  2675.         if (could_carry(u2, unit->type)
  2676.             && mobile(u2)
  2677.             && !terrain_always_impassable(u2, t)
  2678.             /* should also have "and this type is avail to us" */
  2679.             ) {
  2680.             return TRUE;
  2681.         }
  2682.     }
  2683.     }
  2684.     return FALSE;
  2685. }
  2686.  
  2687. /* Note the recursion - should precalc this property. */
  2688.  
  2689. static int
  2690. carryable(u)
  2691. int u;
  2692. {
  2693.     int u2;
  2694.     
  2695.     for_all_unit_types(u2) {
  2696.     if (could_carry(u2, u)
  2697.         && (mobile(u2) /* || carryable(u2) */ ))
  2698.       return TRUE;
  2699.     }
  2700.     return FALSE;
  2701. }
  2702.  
  2703. int *accelerables = NULL;
  2704.  
  2705. static int
  2706. accelerable(u)
  2707. int u;
  2708. {
  2709.     int u1, u2;
  2710.  
  2711.     if (accelerables == NULL) {
  2712.     accelerables = (int *) xmalloc(numutypes * sizeof(int));
  2713.     for_all_unit_types(u1) {    
  2714.         for_all_unit_types(u2) {
  2715.         if (could_carry(u2, u1)
  2716.             && mobile(u2)) {
  2717.             if (u_acp(u2) * u_speed(u2) > u_acp(u1) * u_speed(u1)) {
  2718. #if 0
  2719.             sameterrain = TRUE;
  2720.             for_all_terrain_types(t) {
  2721.                 if (terrain_always_impassable(u2, t)
  2722.                 && !terrain_always_impassable(u1, t)) {
  2723.                 return FALSE;
  2724.                 }
  2725.             }
  2726. #endif
  2727.             accelerables[u1] = TRUE;
  2728.             break;
  2729.             }
  2730.         }
  2731.         }
  2732.     }
  2733.     }
  2734.     return accelerables[u];
  2735. }
  2736.  
  2737. static int
  2738. blocked_by_enemy(unit, x, y)
  2739. Unit *unit;
  2740. int x, y;
  2741. {
  2742.     int dirs[NUMDIRS], numdirs, i, x1, y1, t, numbaddirs = 0;
  2743.     Unit *unit2;
  2744.  
  2745.     numdirs = choose_move_dirs(unit, x, y, TRUE, NULL, NULL, dirs);
  2746.     for (i = 0; i < numdirs; ++i) {
  2747.     point_in_dir(unit->x, unit->y, dirs[i], &x1, &y1);
  2748.     t = terrain_at(x1, y1);
  2749.     if (terrain_always_impassable(unit->type, t)) {
  2750.         ++numbaddirs;
  2751.         continue;
  2752.     }
  2753.     unit2 = unit_at(x1, y1);
  2754.     if (in_play(unit2) && !trusted_side(unit->side, unit2->side))
  2755.       ++numbaddirs;
  2756.     }
  2757.     return (numbaddirs == numdirs);
  2758. }
  2759.  
  2760. static void
  2761. attack_blockage(side, unit, x, y)
  2762. Side *side;
  2763. Unit *unit;
  2764. int x, y;
  2765. {
  2766.     int dirs[NUMDIRS], numdirs, i, x1, y1, t;
  2767.     Unit *unit2;
  2768.  
  2769.     numdirs = choose_move_dirs(unit, x, y, TRUE, NULL, NULL, dirs);
  2770.     for (i = 0; i < numdirs; ++i) {
  2771.     point_in_dir(unit->x, unit->y, dirs[i], &x1, &y1);
  2772.     t = terrain_at(x1, y1);
  2773.     if (terrain_always_impassable(unit->type, t))
  2774.       continue;
  2775.     unit2 = unit_at(x1, y1);
  2776.     if (!trusted_side(unit->side, unit2->side)) {
  2777.         push_hit_task(unit, x1, y1);
  2778.         return;
  2779.     }
  2780.     }
  2781. }
  2782.  
  2783. static void
  2784. mplayer_react_to_new_side(side, side2)
  2785. Side *side, *side2;
  2786. {
  2787.     /* (Assumes we call this right after adding each new side) */
  2788.     int oldnumsides = numsides - 1;
  2789.     int *newpeople, s;
  2790.     Theater *theater;
  2791.  
  2792.     for_all_theaters(side, theater) {
  2793.     /* Grow any people count arrays if present. */
  2794.     if (theater->people != NULL) {
  2795.         newpeople = (int *) xmalloc ((numsides + 1) * sizeof(int));
  2796.         for (s = 0; s <= oldnumsides; ++s)
  2797.           newpeople[s] = theater->people[s];
  2798.         free(theater->people);
  2799.         theater->people = newpeople;
  2800.     }
  2801.     }
  2802.     anewside = side2;
  2803.     estimate_strengths(side);
  2804.     anewside = NULL;
  2805. }
  2806.  
  2807. static int analyze_move_count;
  2808.  
  2809. /* This runs after every few moves in run_game, so performance is
  2810.    important.  We only look for wedged units either when there is
  2811.    clear evidence of such, or every couple hundred calls, just in case. */
  2812.  
  2813. static void
  2814. mplayer_analyze_after_moves(side, numacted)
  2815. Side *side;
  2816. int numacted;
  2817. {
  2818.     Unit *unit;
  2819.  
  2820.     if (numacted == 0 && (side->numwaiting > 0 || ((++analyze_move_count % 200) == 0))) {
  2821.     for_all_side_units(side, unit) {
  2822.         if (unit->plan
  2823.         && !unit->plan->asleep
  2824.         && !unit->plan->reserve
  2825.         && unit->plan->waitingfortasks
  2826.         && unit->plan->aicontrol) {
  2827.         /* This case really ought never to occur, but it's relatively
  2828.            benign, so no need to make an actual warning for this. */
  2829.         Dprintf("AI-controlled unit %s waiting for tasks? - putting into reserve",
  2830.             unit_desig(unit));
  2831.         reserve_unit(side, unit);
  2832.         }
  2833.     }
  2834.     }
  2835. }
  2836.  
  2837. /* At the end of a turn, re-evaluate the plans of some units in case
  2838.    the situation changed. */
  2839.  
  2840. static void
  2841. mplayer_finish_movement(side)
  2842. Side *side;
  2843. {
  2844.     int u;
  2845.     Unit *unit;
  2846.     Theater *theater;
  2847.  
  2848.     for_all_theaters(side, theater) {
  2849.     for_all_unit_types(u) {
  2850.         if (theater->numtotransport[u] > 0) {
  2851.         /* Find a unit needing transport. */
  2852.         for_all_side_units(side, unit) {
  2853.             if (is_active(unit)
  2854.             && unit->plan
  2855.             && unit->plan->aicontrol
  2856.             && unit->plan->waitingfortransport
  2857.             && theater_at(side, unit->x, unit->y) == theater) {
  2858.             search_for_available_transport(unit);
  2859.             unit->plan->waitingfortransport = FALSE;
  2860.             }
  2861.         }
  2862.         break;
  2863.         }
  2864.     }
  2865.     }
  2866.     for_all_side_units(side, unit) {
  2867.     if (is_active(unit)
  2868.         && unit->plan
  2869.         && unit->plan->aicontrol) {
  2870.         rethink_plan(unit);
  2871.     }
  2872.     }
  2873. }
  2874.  
  2875. static Unit *
  2876. search_for_available_transport(unit)
  2877. Unit *unit;
  2878. {
  2879.     int dist, closestdist = area.maxdim;
  2880.     Unit *transport, *closesttransport = NULL;
  2881.     Theater *theater = unit_theater(unit);
  2882.  
  2883.     /* (more efficient to search adjacent cells first?) */
  2884.     for_all_side_units(unit->side, transport) {
  2885.     if (is_active(transport)
  2886.         && mobile(transport->type)
  2887.         && could_carry(transport->type, unit->type)
  2888.         && transport->occupant == NULL /* (should be "has room") */
  2889.         && transport->act != NULL /* not quite correct, but to fix bug */) {
  2890.         /* Don't grab at units being moved manually. */
  2891.         if (transport->plan
  2892.         && !transport->plan->aicontrol)
  2893.           continue;
  2894.         /* Maybe this one is already coming to get somebody. */
  2895.         if (transport->plan
  2896.         && transport->plan->tasks != NULL
  2897.         && transport->plan->tasks->type == TASK_PICKUP) {
  2898.         if (transport->plan->tasks->args[0] == unit->id)
  2899.           return transport;
  2900.         /* Picking up somebody else - don't hijack. */
  2901.         continue;
  2902.         }
  2903.         if (transport->plan
  2904.         && transport->plan->tasks != NULL
  2905.         && transport->plan->tasks->type == TASK_MOVE_TO
  2906.         && transport->plan->tasks->next != NULL
  2907.         && transport->plan->tasks->next->type == TASK_PICKUP) {
  2908.         if (transport->plan->tasks->next->args[0] == unit->id)
  2909.           return transport;
  2910.         /* Picking up somebody else - don't hijack. */
  2911.         continue;
  2912.         }
  2913.         dist = distance(unit->x, unit->y, transport->x, transport->y);
  2914.         if (dist < closestdist || (dist == closestdist && flip_coin())) {
  2915.         closesttransport = transport;
  2916.         closestdist = dist;
  2917.         }
  2918.         /* If transport already adjacent, no need to keep looking. */
  2919.         if (closestdist <= 1)
  2920.           break;
  2921.     }
  2922.     }
  2923.     if (closesttransport != NULL && closesttransport->plan != NULL) {
  2924.     clear_task_agenda(closesttransport->plan);
  2925.     /* (could inherit unit's goal, but not needed) */
  2926.     closesttransport->plan->maingoal = NULL;
  2927.     push_pickup_task(closesttransport, unit);
  2928.     push_move_near_task(closesttransport, unit->x, unit->y, 1);
  2929.     /* No longer count this unit as needing transport. */
  2930.     if (theater != NULL) {
  2931.         --(theater->numtotransport[unit->type]);
  2932.         set_unit_theater(closesttransport, theater);
  2933.     }
  2934.     DMprintf("%s will be picked up by closest transport %s\n",
  2935.              unit_desig(unit), unit_desig(closesttransport));
  2936.     return closesttransport;
  2937.     }
  2938.     return NULL;
  2939. }
  2940.  
  2941. /* For units with plans and that are under AI control, consider changing the
  2942.    current plan/tasks. */
  2943.  
  2944. static void
  2945. rethink_plan(unit)
  2946. Unit *unit;
  2947. {
  2948.     int dist, x1, y1;
  2949.     Task *toptask = unit->plan->tasks, *nexttask = NULL;
  2950.     Plan *plan = unit->plan;
  2951.     Unit *transport;
  2952.  
  2953.     if (toptask)
  2954.       nexttask = toptask->next;
  2955.     /* If we have a long ways to go, see if there is a transport available that
  2956.        can get us there faster.  */
  2957.     if (toptask != NULL
  2958.     && (toptask->type == TASK_HIT_UNIT
  2959.         || (toptask->type == TASK_MOVE_TO
  2960.         && nexttask != NULL
  2961.         && nexttask->type == TASK_HIT_UNIT))
  2962.         && !plan->reserve
  2963.         && !plan->asleep
  2964.         && !plan->waitingfortransport
  2965.         && (unit->transport == NULL || !mobile(unit->transport->type))
  2966.         && ((dist = distance(unit->x, unit->y,
  2967.                  toptask->args[0], toptask->args[1]))
  2968.             >= 4 * u_acp(unit->type))
  2969.         && accelerable(unit->type)
  2970.         ) {
  2971.         DMprintf("%s looking for transport to accelerate with;\n", unit_desig(unit));
  2972.         transport = search_for_available_transport(unit);
  2973.         if (transport != NULL) {
  2974.         /* push_sentry_task(unit, max(1, dist / max(1, u_acp(transport->type)))); */
  2975.         plan->reserve = TRUE;
  2976.         plan->waitingfortransport = FALSE;
  2977.         } else {
  2978.         DMprintf("  found nothing\n");
  2979.         }
  2980.     }
  2981.     if (unit->plan->type == PLAN_OFFENSIVE
  2982.         && toptask != NULL
  2983.         && toptask->type == TASK_MOVE_TO
  2984.         && distance(unit->x, unit->y, toptask->args[0], toptask->args[1])
  2985.         >= min(2, u_acp(unit->type))
  2986.         && enemy_close_by(unit->side, unit, 1 /* 2 would be better? */, &x1, &y1)
  2987.         ) {
  2988.     push_hit_task(unit, x1, y1);
  2989.     DMprintf("%s sees enemy close by, will attack it\n", unit_desig(unit));
  2990.     }
  2991.     /* (should also notice fire opportunities) */
  2992.     /* If we see somebody that could be captured and help us explore, set up
  2993.        to produce capturers. */
  2994.     if (!mobile(unit->type)
  2995.     && (unit->plan->type == PLAN_EXPLORATORY || unit->plan->type == PLAN_OFFENSIVE)
  2996.     ) {
  2997.     int range = 4, rslt, x, y;
  2998.  
  2999.     DMprintf("%s searching for useful capture within %d in order to choose build; found ",
  3000.               unit_desig(unit), range);
  3001.     tmpunit = unit;
  3002.     rslt = search_around(unit->x, unit->y, range, useful_captureable_here,
  3003.                  &x, &y, 1);
  3004.     if (rslt) {
  3005.         DMprintf("one at %d,%d\n", x, y);
  3006.         if (toptask != NULL
  3007.         && toptask->type == TASK_BUILD
  3008.         && uu_capture(toptask->args[0], tmputype)
  3009.         ) {
  3010.         /* already doing the right thing */
  3011.         } else {
  3012.         /* (should find best type that can capture quickly,
  3013.             schedule to build it) */
  3014.         }
  3015.     } else {
  3016.         DMprintf("nothing\n");
  3017.     }
  3018.     }
  3019. }
  3020.  
  3021. static int victimx, victimy, victimrating;
  3022.  
  3023. static int
  3024. enemy_close_by(side, unit, dist, xp, yp)
  3025. Side *side;
  3026. Unit *unit;
  3027. int dist, *xp, *yp;
  3028. {
  3029.     int x = unit->x, y = unit->y, dir, x1, y1;
  3030.  
  3031.     victimrating = -9999;
  3032.     tmpunit = unit;
  3033.     victim_here(x, y);
  3034.     for_all_directions(dir) {
  3035.     if (point_in_dir(x, y, dir, &x1, &y1)) {
  3036.         victim_here(x, y);
  3037.     }
  3038.     }
  3039.     if (victimrating > -9999) {
  3040.     *xp = victimx;  *yp = victimy;
  3041.     return TRUE;
  3042.     } else {
  3043.     return FALSE;
  3044.     }
  3045. }
  3046.  
  3047. static void
  3048. mplayer_react_to_unit_loss(side, unit)
  3049. Side *side;
  3050. Unit *unit;
  3051. {
  3052.     int x = unit->x, y = unit->y;
  3053.     Theater *th;
  3054.  
  3055.     if (!inside_area(x, y)) {
  3056.     x = unit->prevx;  y = unit->prevy;
  3057.     }
  3058.     if (!inside_area(x, y))
  3059.       return;
  3060.     if (mplayer(side) && (th = theater_at(side, x, y)) != NULL) {
  3061.         ++(th->units_lost);
  3062.     }
  3063. }
  3064.  
  3065. static void
  3066. mplayer_receive_message(side, sender, str)
  3067. Side *side, *sender;
  3068. char *str;
  3069. {
  3070.     /* First detect standard messages. */
  3071.     if (strcmp(str, "Eh?") == 0) {
  3072.     /* Don't respond, otherwise we might infinitely recurse. */
  3073.     } else if (allied_side(side, sender)) {
  3074.     } else {
  3075.     /* Detect insults and respond appropriately. */
  3076.     if (strstr(str, "idiot")) {
  3077.         send_message(side, add_side_to_set(sender, NOSIDES), "Loser!");
  3078.     } else {
  3079.         /* No idea what the message was, be puzzled. */
  3080.         send_message(side, add_side_to_set(sender, NOSIDES), "Eh?");
  3081.     }
  3082.     }
  3083. }
  3084.  
  3085. /* This is used by interfaces to display the theater in use at a given point. */
  3086.  
  3087. static char *
  3088. mplayer_at_desig(side, x, y)
  3089. Side *side;
  3090. int x, y;
  3091. {
  3092.     Theater *theater;
  3093.  
  3094.     if (mplayer(side) == NULL)
  3095.       return "";
  3096.     theater = theater_at(side, x, y);
  3097.     return (theater ? theater->name : "<no theater>");
  3098. }
  3099.  
  3100. static int
  3101. mplayer_theater_at(side, x, y)
  3102. Side *side;
  3103. int x, y;
  3104. {
  3105.     Theater *theater;
  3106.  
  3107.     if (mplayer(side) == NULL)
  3108.       return 0;
  3109.     theater = theater_at(side, x, y);
  3110.     return (theater ? theater->id : 0);
  3111. }
  3112.  
  3113. static int
  3114. mplayer_read_strengths(side)
  3115. Side *side;
  3116. {
  3117.     int sn1, u, found = FALSE;
  3118.     char *propname;
  3119.     Obj *props, *bdg, *rest, *sidebdg, *urest;
  3120.     Side *side1;
  3121.     Strategy *strategy = mplayer(side);
  3122.  
  3123.     props = find_at_key(side->aidata, "mplayer");
  3124.     for (; props != lispnil; props = cdr(props)) {
  3125.     bdg = car(props);
  3126.     propname = c_string(car(bdg));
  3127.     if (strcmp(propname, "strengths0") == 0) {
  3128.         found = TRUE;
  3129.         rest = cdr(bdg);
  3130.         for_all_sides(side1) {
  3131.         sn1 = side1->id;
  3132.         sidebdg = car(rest);
  3133.         urest = cadr(sidebdg);
  3134.         for_all_unit_types(u) {
  3135.             strategy->strengths0[sn1][u] = c_number(car(urest));
  3136.             urest = cdr(urest);
  3137.         }
  3138.         rest = cdr(rest);
  3139.         }
  3140.     } else if (strcmp(propname, "alstrengths0") == 0) {
  3141.         found = TRUE;
  3142.         rest = cdr(bdg);
  3143.         for_all_sides(side1) {
  3144.         sn1 = side1->id;
  3145.         sidebdg = car(rest);
  3146.         urest = cadr(sidebdg);
  3147.         for_all_unit_types(u) {
  3148.             strategy->alstrengths0[sn1][u] = c_number(car(urest));
  3149.             urest = cdr(urest);
  3150.         }
  3151.         rest = cdr(rest);
  3152.         }
  3153.     } else if (strcmp(propname, "points0") == 0) {
  3154.         found = TRUE;
  3155.         rest = cdr(bdg);
  3156.         for_all_sides(side1) {
  3157.         sn1 = side1->id;
  3158.         strategy->points0[sn1] = c_number(car(rest));
  3159.         rest = cdr(rest);
  3160.         }
  3161.     } else if (strcmp(propname, "alpoints0") == 0) {
  3162.         found = TRUE;
  3163.         rest = cdr(bdg);
  3164.         for_all_sides(side1) {
  3165.         sn1 = side1->id;
  3166.         strategy->alpoints0[sn1] = c_number(car(rest));
  3167.         rest = cdr(rest);
  3168.         }
  3169.     } else {
  3170.     }
  3171.     }
  3172.     return found;
  3173. }
  3174.  
  3175. /* Write out any state that the mplayer must preserve.  We don't actually write;
  3176.    instead we build a Lisp object and pass that back to the writing routines. */
  3177.  
  3178. static Obj *
  3179. mplayer_save_state(side)
  3180. Side *side;
  3181. {
  3182.     int sn1, u;
  3183.     Obj *rslt, *vallist, *uvallist;
  3184.     Side *side1;
  3185.     Strategy *strategy = mplayer(side);
  3186.  
  3187.     rslt = lispnil;
  3188.     /* Just return last result if it's already been computed. */
  3189.     if (strategy->writable_state != lispnil || xmalloc_warnings)
  3190.       return strategy->writable_state;
  3191.     /* We're pushing bindings onto a list, so do in reverse of desired order. */
  3192.     vallist = lispnil;
  3193.     for_all_sides(side1) {
  3194.     sn1 = side1->id;
  3195.     uvallist = lispnil;
  3196.     for_all_unit_types(u) {
  3197.         uvallist = cons(new_number(strategy->alstrengths0[sn1][u]), uvallist);
  3198.     }
  3199.     uvallist = reverse(uvallist);
  3200.     push_binding(&vallist, new_number(sn1), uvallist);
  3201.     }
  3202.     vallist = reverse(vallist);
  3203.     push_cdr_binding(&rslt, intern_symbol("alstrengths0"), vallist);
  3204.     vallist = lispnil;
  3205.     for_all_sides(side1) {
  3206.     sn1 = side1->id;
  3207.     uvallist = lispnil;
  3208.     for_all_unit_types(u) {
  3209.         uvallist = cons(new_number(strategy->strengths0[sn1][u]), uvallist);
  3210.     }
  3211.     uvallist = reverse(uvallist);
  3212.     push_binding(&vallist, new_number(sn1), uvallist);
  3213.     }
  3214.     vallist = reverse(vallist);
  3215.     push_cdr_binding(&rslt, intern_symbol("strengths0"), vallist);
  3216.     vallist = lispnil;
  3217.     for_all_sides(side1) {
  3218.     sn1 = side1->id;
  3219.     vallist = cons(new_number(strategy->alpoints0[sn1]), vallist);
  3220.     }
  3221.     vallist = reverse(vallist);
  3222.     push_cdr_binding(&rslt, intern_symbol("alpoints0"), vallist);
  3223.     vallist = lispnil;
  3224.     for_all_sides(side1) {
  3225.     sn1 = side1->id;
  3226.     vallist = cons(new_number(strategy->points0[sn1]), vallist);
  3227.     }
  3228.     vallist = reverse(vallist);
  3229.     push_cdr_binding(&rslt, intern_symbol("points0"), vallist);
  3230.     strategy->writable_state = rslt;
  3231.     return rslt;
  3232. }
  3233.