home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xconq55.zip / xc5.5 / mutil.c < prev    next >
C/C++ Source or Header  |  1992-03-08  |  30KB  |  1,197 lines

  1. /* Copyright (c) 1987, 1988  Stanley T. Shebs. */
  2. /* This program may be used, copied, modified, and redistributed freely */
  3. /* for noncommercial purposes, so long as this notice remains intact. */
  4.  
  5. /* This file implements auxilary functions for the machine players. */
  6.  
  7. #include "config.h"
  8. #include "misc.h"
  9. #include "dir.h"
  10. #include "period.h"
  11. #include "side.h"
  12. #include "unit.h"
  13. #include "map.h"
  14. #include "global.h"
  15. #include "mplay.h"
  16.  
  17.  
  18.  
  19. Mplan *freeplans = NULL; /* Will be initialize to plan list first time */
  20.              /* plan is created. */
  21. int route_max_distance;
  22.  
  23.  
  24. /* Short unreadable but greppable listing of unit. */
  25.  
  26. char *unit_desig(unit)
  27. Unit *unit;
  28. {
  29.   enter_procedure("unit_desig");
  30.     sprintf(shortbuf, "s%d %d %c (%d,%d)",
  31.         side_number(unit->side), unit->number, utypes[unit->type].uchar,
  32.         unit->x, unit->y);
  33.   exit_procedure();
  34.     return shortbuf;
  35. }
  36.  
  37. /* Count how many units on our side of the given type are within the */
  38. /* specified distance. */
  39.  
  40. int units_nearby(x, y, dist, type)
  41. int x, y;
  42. {
  43.   Unit *unit;
  44.   int ux, uy;
  45.  
  46. /*  enter_procedure("units nearby"); */
  47.   unit_count = 0;
  48.   for (unit = mside->unitlist[type]; unit != NULL; unit = unit->mlist) {
  49.     ux = unit->x;
  50.     uy = unit->y;
  51.     if (alive(unit) && distance(x, y, ux, uy) <= dist)
  52.       unit_count++;
  53.   }
  54. /*  exit_procedure(); */
  55.   return unit_count;
  56. }
  57.  
  58. /* Can this unit build a base without dying. */
  59.  
  60. bool survive_to_build_base(unit)
  61. Unit *unit;
  62. {
  63.   return (base_builder(unit) &&
  64.       survival_time(unit) > build_time(unit, base_builder(unit)));
  65. }
  66.  
  67. /* Is this the last chance for a unit to build a base without dying. */
  68.  
  69. bool exact_survive_to_build_base(unit)
  70. Unit *unit;
  71. {
  72.   return (base_builder(unit) &&
  73.       survival_time(unit) == (1 + build_time(unit, base_builder(unit))));
  74. }
  75.  
  76. /* Is there a machine base here. */
  77.  
  78. base_here(x, y)
  79. int x, y;
  80. {
  81.     Unit *unit = unit_at(x, y);
  82.  
  83.     return (unit != NULL && unit->side == mside && isbase(unit)) ;
  84.  
  85. }
  86.  
  87. /* Is there anybodies base here. */
  88.  
  89. any_base_here(x, y)
  90. int x, y;
  91. {
  92.     int utype = vtype(side_view(mside, x, y));
  93.  
  94.     return (utype != EMPTY && utype != UNSEEN &&
  95.         utypes[utype].is_base);
  96.  
  97. }
  98.  
  99. /* Is there anybodies base here. */
  100.  
  101. neutral_base_here(x, y)
  102. int x, y;
  103. {
  104.     viewdata view = side_view(mside, x, y);
  105.     int utype = vtype(view);
  106.  
  107.     return (utype != EMPTY && utype != UNSEEN &&
  108.         utypes[utype].is_base && vside_neutral(view));
  109.  
  110. }
  111.  
  112. /* Is there a base within the given range.  Generally range is small. */
  113.  
  114. bool base_nearby(unit,range)
  115. Unit *unit;
  116. int range;
  117. {
  118.   int x,y;
  119.   
  120.   mside = unit->side;
  121.   return search_area(unit->x, unit->y, range, base_here, &x, &y, 1);
  122. }
  123.  
  124. /* Is there a base within the given range.  Generally range is small. */
  125.  
  126. bool any_base_nearby(unit,range)
  127. Unit *unit;
  128. int range;
  129. {
  130.   int x,y;
  131.   
  132.   mside = unit->side;
  133.   return search_area(unit->x, unit->y, range, any_base_here, &x, &y, 1);
  134. }
  135.  
  136. /* Is there a neutral base within the given range.  Generally range is small. */
  137.  
  138. bool neutral_base_nearby(unit,range)
  139. Unit *unit;
  140. int range;
  141. {
  142.   int x,y;
  143.   
  144.   mside = unit->side;
  145.   return search_area(unit->x, unit->y, range, neutral_base_here, &x, &y, 1);
  146. }
  147.  
  148.  
  149. bool occupant_could_capture(unit,etype)
  150. Unit *unit;
  151. int etype;
  152. {
  153.   Unit *occ;
  154.  
  155.   for_all_occupants(unit,occ)
  156.     if could_capture(occ->type, etype)
  157.       return TRUE;
  158.   return FALSE;
  159. }
  160.  
  161. /* Check to see if there is anyone around to capture. */
  162.  
  163. bool can_capture_neighbor(unit)
  164. Unit *unit;
  165. {
  166.   int d, x, y;
  167.   viewdata view;
  168.   Side *side2;
  169.  
  170.   for_all_directions(d) {
  171.     x = wrap(unit->x + dirx[d]);  y = limit(unit->y + diry[d]);
  172.     view = side_view(unit->side, x, y);
  173.     if (view != UNSEEN && view != EMPTY) {
  174.       side2 = side_n(vside(view));
  175.       if (!allied_side(unit->side, side2)) {
  176.     if (could_capture(unit->type, vtype(view))) {
  177.       mside->movunit = unit;
  178.       mside->last_unit = unit;
  179.       return TRUE;
  180.     }
  181.       }
  182.     }
  183.   }
  184.   return FALSE;
  185. }
  186.  
  187. /* check if our first occupant can capture something.  Doesn't look at
  188. other occupants. */
  189.  
  190. bool occupant_can_capture_neighbor(unit)
  191. Unit *unit;
  192. {
  193.   Unit *occ = unit->occupant;
  194.  
  195.   if (occ != NULL && occ->movesleft > 0 && occ->side == unit->side) {
  196.     if (can_capture_neighbor(occ)) {
  197.       mside->movunit = occ;
  198.       mside->last_unit = occ;
  199.       return TRUE;
  200.     }
  201.   }
  202.   return FALSE;
  203. }
  204.  
  205. /* Find the closes unit, first prefering bases, and then transports. */
  206.  
  207. bool find_closest_unit(x0, y0, maxdist, pred, rxp, ryp)
  208. int x0, y0, maxdist, (*pred)(), *rxp, *ryp;
  209. {
  210.     Unit *unit;
  211.     int ut, dist;
  212.     bool found = FALSE;
  213.     
  214.     enter_procedure("find_closest_unit");
  215.     for_all_unit_types(ut) {
  216.       if (utypes[ut].is_base)
  217.     for (unit = mside->unitlist[ut]; unit != NULL; unit = unit->mlist) {
  218.       if (alive(unit) && (dist = distance(x0, y0, unit->x, unit->y)) <= maxdist) {
  219.         if ((*pred)(unit->x, unit->y)) {
  220.           maxdist = dist - 1;
  221.           found = TRUE;
  222.           *rxp = unit->x;  *ryp = unit->y;
  223.         }
  224.       }
  225.     }
  226.     }
  227.     if (found) {
  228.       exit_procedure();
  229.       return TRUE;
  230.     }
  231.     for_all_unit_types(ut) {
  232.       if (!utypes[ut].is_base && utypes[ut].is_transport)
  233.     for (unit = mside->unitlist[ut]; unit != NULL; unit = unit->mlist) {
  234.       if (alive(unit) && distance(x0, y0, unit->x, unit->y) <= maxdist) {
  235.         if ((*pred)(unit->x, unit->y)) {
  236.           *rxp = unit->x;  *ryp = unit->y;
  237.           maxdist = dist - 1;
  238.           found = TRUE;
  239.         }
  240.       }
  241.     }
  242.     }
  243.     if (found) {
  244.       exit_procedure();
  245.       return TRUE;
  246.     }
  247.     for_all_unit_types(ut) {
  248.       if (!utypes[ut].is_base && !utypes[ut].is_transport)
  249.     for (unit = mside->unitlist[ut]; unit != NULL; unit = unit->mlist) {
  250.       if (alive(unit) && distance(x0, y0, unit->x, unit->y) <= maxdist) {
  251.         if ((*pred)(unit->x, unit->y)) {
  252.           *rxp = unit->x;  *ryp = unit->y;
  253.           maxdist = dist - 1;
  254.           found = TRUE;
  255.         }
  256.       }
  257.     }
  258.     }
  259.     if (found) {
  260.       exit_procedure();
  261.       return TRUE;
  262.     }
  263.     exit_procedure();
  264.     return FALSE;
  265. }
  266.  
  267.  
  268. /* Return percentage of capacity. */
  269.  
  270. int fullness(unit)
  271. Unit *unit;
  272. {
  273.     int u = unit->type, o, cap = 0, num = 0, vol = 0;
  274.     Unit *occ;
  275.  
  276.     for_all_unit_types(o) cap += utypes[u].capacity[o];
  277.     for_all_occupants(unit, occ) {
  278.     num++;
  279.     vol += utypes[occ->type].volume;
  280.     }
  281.     return (cap > 0) ? max(((utypes[u].holdvolume > 0) ? (100 * vol) / utypes[u].holdvolume : 100),
  282.             (100 * num) / cap) : 100;
  283.  
  284. }
  285.  
  286. /* True if the given unit is a sort that can build other units. */
  287.  
  288. bool can_produce(unit)
  289. Unit *unit;
  290. {
  291.     int p;
  292.  
  293.     for_all_unit_types(p) {
  294.     if (could_make(unit->type, p)) return TRUE;
  295.     }
  296.     return FALSE;
  297. }
  298.  
  299. /* Test if unit can move out into adjacent hexes. */
  300.  
  301. can_move(unit)
  302. Unit *unit;
  303. {
  304.     int d, x, y;
  305.  
  306.     for_all_directions(d) {
  307.     x = wrap(unit->x + dirx[d]);  y = limit(unit->y + diry[d]);
  308.     if (could_move(unit->type, terrain_at(x, y))) return TRUE;
  309.     }
  310.     return FALSE;
  311. }
  312.  
  313. /* Returns the type of missing supplies. Not great routine if first */
  314. /* resource is a type of ammo. */
  315.  
  316. out_of_ammo(unit)
  317. Unit *unit;
  318. {
  319.     int u = unit->type, r;
  320.  
  321.     for_all_resource_types(r) {
  322.     if (utypes[u].hitswith[r] > 0 && unit->supply[r] <= 0)
  323.         return r;
  324.     }
  325.     return (-1);
  326. }
  327.  
  328. /* Someplace that we can definitely get supplies at. */
  329.  
  330. good_haven_p(x, y)
  331. int x, y;
  332. {
  333.     Unit *unit = unit_at(x, y);
  334.     int r;
  335.     Mplan *plan;
  336.  
  337.     if (unit != NULL) {
  338.       if (allied_side(mside, unit->side) && alive(unit) &&
  339.       can_carry(unit, munit) && !might_be_captured(unit)) {
  340.     for_all_resource_types(r)
  341.       /* could also add in distance calculation to see how much we */
  342.       /* really need. */
  343.       if (unit->supply[r] <
  344.           (utypes[munit->type].storage[r])) {
  345.         return FALSE;
  346.       }
  347.     if ((plan = find_route(munit->type, route_max_distance,
  348.                    munit->x, munit->y, x, y)) != NULL) {
  349.       free_plan(munit->plan);
  350.       munit->plan = plan;
  351.       return TRUE;
  352.     }
  353.       }
  354.     } 
  355.     return FALSE;
  356. }
  357.  
  358. /* See if the location has a unit that can take us in for refueling */
  359. /* (where's the check for refueling ability?) */
  360.  
  361. haven_p(x, y)
  362. int x, y;
  363. {
  364.     Unit *unit = unit_at(x, y);
  365.     Mplan *plan;
  366.  
  367.     if (unit != NULL &&
  368.     allied_side(mside, unit->side) && alive(unit) &&
  369.     can_carry(unit, munit) && !might_be_captured(unit) &&
  370.     (plan = find_route(munit->type, route_max_distance,
  371.                munit->x, munit->y, x, y)) != NULL) {
  372.           free_plan(munit->plan);
  373.       munit->plan = plan;
  374.       return TRUE;
  375.     }
  376.     else return FALSE;
  377. }
  378.  
  379. /* See if the location has a unit that can repair us */
  380.  
  381. shop_p(x, y)
  382. int x, y;
  383. {
  384.     Unit *unit = unit_at(x, y);
  385.     Mplan *plan;
  386.  
  387.    if (unit != NULL && allied_side(munit->side, unit->side) && alive(unit) &&
  388.        can_carry(unit, munit) && could_repair(unit->type, munit->type) &&
  389.        !might_be_captured(unit) &&
  390.        (plan = find_route(munit->type, route_max_distance,
  391.               munit->x, munit->y, x, y)) != NULL) {
  392.           free_plan(munit->plan);
  393.       munit->plan = plan;
  394.       return TRUE;
  395.     }
  396.     else return FALSE;
  397. }
  398.  
  399. /* Check how long a unit can sit where it is */
  400.  
  401. int survival_time(unit)
  402. Unit *unit;
  403. {
  404.     int u = unit->type, r, least = 12345, rate;
  405.     int t = terrain_at(unit->x, unit->y);
  406.  
  407.  
  408.     for_all_resource_types(r) {
  409.       rate = (utypes[u].consume[r] -
  410.            (utypes[u].produce[r] * utypes[u].productivity[t]) / 100);
  411.       if (rate > 0)
  412.     least = min(least, (unit->supply[r] + unit->actualmoves * utypes[u].tomove[r]) / rate);
  413.     }
  414.     return (least);
  415. }
  416.  
  417. #ifdef REGIONS
  418. long regions_around(u, x, y, center)
  419. int u, x, y;
  420. bool center;
  421. {
  422.   int d, nx, ny;
  423.   long result = 0;
  424.  
  425.   for_all_directions(d) {
  426.     nx = wrap(x + dirx[d]);  ny = y + diry[d];
  427.     if (aref(unit_region[u], nx, ny) >= 0)
  428.       result |= 1 << (aref(unit_region[u], nx, ny) % sizeof(long));
  429.   }
  430.   if (center && aref(unit_region[u], x, y) > 0)
  431.     result |= 1 << (aref(unit_region[u], x, y) % sizeof(long));
  432.   return result;
  433. }
  434. #endif
  435.  
  436. void init_plans()
  437. {
  438.     int i;
  439.     Mplan *plans;
  440.  
  441.     plans = (Mplan *) malloc(INITMAXUNITS * sizeof(Mplan));
  442.     freeplans = plans;
  443.     for (i = 0; i < INITMAXUNITS; ++i) {
  444.       plans[i].next = &plans[i+1];
  445.     }
  446.     plans[INITMAXUNITS-1].next = NULL;
  447. }
  448.  
  449. void free_plan(plan)
  450. Mplan *plan;
  451. {
  452.   Mplan *next;
  453.  
  454.   while (plan != NULL) {
  455.     next = plan->next;
  456.     plan->next = freeplans;
  457.     freeplans = plan;
  458.     plan = next;
  459.   }
  460. }
  461.  
  462. Mplan *make_plan_step(type, x, y, priority)
  463. int type, x, y, priority;
  464. {
  465.   Mplan *plan;
  466.   
  467.   if (freeplans == NULL) init_plans();
  468.   plan = freeplans;
  469.   freeplans = plan->next;
  470.   plan->next = NULL;
  471.   plan->type = type;
  472.   plan->x = x;
  473.   plan->y = y;
  474.   return plan;
  475. }
  476.   
  477. /* should be using A* rather than this I think.? */
  478.  
  479. unsigned char mark = 255;
  480. int counter = 0;
  481. Mplan *find_route_aux(ut, maxdist, curdist, fromdir, sx, sy, fx, fy, tx, ty, flags)
  482. int ut, fx, fy, tx, ty, flags;
  483. {
  484.   int d, i, x, y, td;
  485.   viewdata view;
  486.   int baddirs = (fromdir<0) ? 0 : ((1 << fromdir) |
  487.                    (1 << ((fromdir + 1) % 6)) |
  488.                    (1 << ((fromdir - 1 + 6) % 6)));
  489.   int distleft = distance(fx, fy, tx, ty);
  490.   Mplan *resulting_plan;
  491.  
  492.   if (!(flags & SAMEPATH)) {
  493.     baddirs = 0;
  494.     mark++;
  495.     if (mark == 0) {
  496.       for_all_hexes(x,y)
  497.     markloc(x,y);
  498.       mark++;
  499.     }
  500.   }
  501.   flags |= SAMEPATH; /* add samepath flag */
  502.   markloc(fx, fy);
  503.   set_fromdir(fx, fy, fromdir);
  504.   if (curdist + distleft > maxdist) {
  505.     return NULL;
  506.   }
  507.   set_dist(fx, fy, curdist);
  508.   curdist++;
  509.   if (fx == tx && fy == ty)
  510.     return make_plan_for_route(sx, sy, tx, ty);
  511.   
  512.   d = fromdir;
  513.   do {
  514.     d = (d + 1) % 6;
  515.     x = wrap(fx + dirx[d]);
  516.     y = fy + diry[d];
  517.   } while (distance(x, y, tx, ty) >= distleft);
  518.  
  519.   td = (d + 5) % 6;
  520.   if (distance(wrap(fx + dirx[td]), fy + diry[td], tx, ty) < distleft) 
  521.     d = td;
  522.   i = 0;
  523.  
  524.   x = wrap(fx + dirx[d]);
  525.   y = fy + diry[d];
  526.   if ((flags & EXPLORE_PATH) && UNSEEN == side_view(mside, x, y)) {
  527.     return make_plan_for_route(sx, sy, fx, fy);
  528.   }
  529.  
  530.   while (i <= 3) {
  531.     x = wrap(fx + dirx[td = (d + i + 6) % 6]);
  532.     y = fy + diry[td];
  533.     view = side_view(mside, x, y);
  534.     if ( (x == tx && y == ty) ||
  535.     (between(1, y, world.height-2) &&
  536.      (!markedloc(x, y)  /*||
  537.                   get_dist(x, y) > curdist */) &&
  538.      ((view == EMPTY) || view == UNSEEN ||
  539.       (allied_side(side_n(vside(view)),mside) &&
  540.        could_carry(vtype(view), ut))) &&
  541.      (baddirs & (1 << td)) == 0 &&
  542.      could_move(ut, terrain_at(x, y))
  543.      )) {
  544.       resulting_plan = find_route_aux(ut, maxdist, curdist,
  545.                   opposite_dir(td),
  546.                   sx, sy, x, y, tx, ty,
  547.                   flags);
  548.       if (resulting_plan != NULL)
  549.     return resulting_plan;
  550.     }
  551.     x = wrap(fx + dirx[td = (d - i + 6) % 6]);
  552.     y = fy + diry[td];
  553.     view = side_view(mside, x, y);
  554.     if ((x == tx && y == ty) ||
  555.     (between(1, y, world.height-2) &&
  556.      between(1, i, 2) && 
  557.      (!markedloc(x, y) /* ||
  558.                   get_dist(x, y) > curdist*/) &&
  559.      (view == EMPTY) &&
  560.      (baddirs & (1 << td)) == 0 &&
  561.      could_move(ut, terrain_at(x, y))
  562.      )) {
  563.       resulting_plan = find_route_aux(ut, maxdist, curdist,
  564.                   opposite_dir(td),
  565.                   sx, sy, x, y, tx, ty,
  566.                   flags);
  567.       if (resulting_plan != NULL)
  568.     return resulting_plan;
  569.     }
  570.     i++;
  571.   }
  572.   return NULL;
  573. }
  574.                  
  575. Mplan *make_plan_for_route(sx, sy, tx, ty)
  576. int sx, sy, tx, ty;
  577. {
  578.   Mplan *plan = NULL, *new;
  579.   int x = tx, y = ty, d;
  580.  
  581.   while (x != sx || y != sy) {
  582.     new = make_plan_step(PMOVE, x, y, bestworth);
  583.     new->next = plan;
  584.     plan = new;
  585.     d = get_fromdir(x, y);
  586.     x = wrap(x + dirx[d]);
  587.     y = y + diry[d];
  588.   }
  589.   return plan;
  590. }  
  591.  
  592. Mplan *find_route(ut, maxdist, fx, fy, tx, ty)
  593. int ut, maxdist, fx, fy, tx, ty;
  594. {
  595.   int mindist = distance(fx, fy, tx, ty), i, flags;
  596.   Mplan *route;
  597.  
  598.   if (Debug)
  599.     notify(mside, "finding route for %s (%d %d) to (%d %d)",
  600.        utypes[ut].name, fx, fy, tx, ty);
  601.  
  602.   flags=0;
  603. #ifdef REGIONS
  604.   if ((regions_around(ut, tx, ty, TRUE) &
  605.        regions_around(ut, fx, fy, FALSE)) == 0)
  606.     {
  607.     int d, x, y;
  608.     Unit *base;
  609.     bool basefound = FALSE;
  610.     for_all_directions(d) {
  611.     x = wrap(fx + dirx[d]);  y = limit(fy + diry[d]);
  612.     if ((base = unit_at(x, y)) != NULL &&
  613.         could_carry(base->type, ut))
  614.       basefound = TRUE;
  615.     }
  616.     if (!basefound) {
  617.       return NULL;
  618.     }
  619.   }
  620. #endif
  621.   if (UNSEEN == side_view(mside, tx, ty))
  622.     flags = EXPLORE_PATH;
  623.   
  624.   for (i = 0; (mindist + i*i) <= maxdist; i++) {
  625.     route = find_route_aux(ut, min(maxdist, ((i+1)*(i+1)+mindist)),
  626.                0, -1, fx, fy,
  627.                fx, fy, tx, ty, flags);
  628.     if (route != NULL)
  629.       return route;
  630.   }
  631.   return NULL;
  632. }
  633.  
  634. /* Follow plan unless we have some reason to change.  Right now we
  635. assume the plan will only last for one turn, so we are the only ones
  636. likely to have seen something relavent. */
  637.  
  638. bool follow_plan(unit)
  639. Unit *unit;
  640. {
  641.   int x, y;
  642.   viewdata view;
  643.   Side *es;
  644.   Mplan *plan = unit->plan;
  645.   
  646.   if (plan == NULL) return FALSE;
  647.   find_worths(utypes[unit->type].seerange);
  648.   x = plan->x;
  649.   y = plan->y;
  650.   if (bestworth > unit->priority &&
  651.       (bestx != x || besty != y)) {
  652.     notify(mside, "Cancelling plan, better plan found. %d over %d", bestworth,
  653.        unit->priority);
  654.     free_plan(unit->plan);
  655.     unit->plan = NULL;
  656.     return FALSE;
  657.   }
  658.   if (distance(unit->x, unit->y, x, y) > 1) {
  659.     notify(mside, "Cancelling plan, something wrong.");
  660. /* fix this.  The other unit can move between when we give the order and the order is followed. */
  661.     free_plan(unit->plan);
  662.     unit->plan = NULL;
  663.     return FALSE;
  664.   }
  665.   view = side_view(mside, x, y); 
  666.  
  667.   if (view == EMPTY &&
  668.       !could_move(unit->type, terrain_at(x, y))) {
  669.     notify(mside, "Cancelling plan, bad terrain.");
  670.     /* fix this.  The other unit can move between when we give the order and the order is followed. */
  671.     free_plan(unit->plan);
  672.     unit->plan = NULL;
  673.     return FALSE;
  674.   }
  675.  
  676.   /* code here is not good.  Have to make sure we are really looking
  677.      at next hex on path */
  678.  
  679.   if (view != EMPTY) { 
  680.     es = side_n(vside(view));
  681.     if (!allied_side(mside, es)) {
  682.       if (plan->next != NULL) {
  683.     /* Something is in our way and it in not our target, replan. */
  684.     notify(mside, "Cancelling plan, path is blocked.");
  685.     free_plan(plan);
  686.     unit->plan = NULL;
  687.     munit->move_tries++;
  688.     return FALSE;
  689.       } else if (occupant_can_capture_neighbor(unit)) {
  690.     /* capture attempt.  Other code will make this unit hang out
  691.        for a turn until the occupant can do its job. */
  692.     free_plan(plan);
  693.     unit->plan = NULL;
  694.     munit->move_tries++;
  695.     return FALSE;
  696.       }
  697.     } else if (!(can_carry(unit_at(x, y), unit) ||
  698.          can_carry(unit, unit_at(x, y)))) {
  699.       /* An allied unit is in our way. */
  700.     notify(mside, "Can plan of %s, path blocked by ally %s at (%d,%d).",
  701.        utypes[unit->type].name,
  702.        utypes[unit_at(x, y)->type].name,
  703.        x, y);
  704.       free_plan(plan);
  705.       unit->plan = NULL;
  706. /*    if (active_display(mside)) get_input(); */
  707.     munit->move_tries++;
  708.       return FALSE;
  709.     }
  710.   }
  711.   order_moveto(unit, x, y);
  712.   unit->plan = plan->next;
  713.   plan->next = NULL;
  714.   free_plan(plan);
  715.   return TRUE;
  716. }
  717.  
  718.  
  719. /* Optimize a plan to account for base building and running out of
  720. supplies. */
  721.  
  722. optimize_plan(unit)
  723. Unit *unit;
  724. {
  725.   int ut = unit->type;
  726.   Utype *utype = utypes + ut;
  727.   int consumed[MAXRTYPES]; /* amount consumed in turn under consideration */
  728.   int supply[MAXRTYPES];
  729.   Mplan *step, *prevstep, *savestep;
  730.   int r, movesleft = unit->movesleft; 
  731.  
  732. /* ways to use resources, 
  733.    1 movement.  
  734.    2 consumption.  
  735.    3 building things.  
  736.    4 repairing things.  We'll skip this at least 
  737.    5 attacking things.  This won't matter in this routine.  */
  738.  
  739.   for_all_resource_types(r) {
  740.     supply[r] = unit->supply[r];
  741.     consumed[r] = unit->actualmoves * utype->tomove[r];
  742.   }
  743.  
  744.   /* now simulate plan */
  745.   step = unit->plan;
  746.   prevstep = NULL;
  747.   while (step != NULL) {
  748.     if (movesleft <= 0) {
  749.       for_all_resource_types(r) {
  750.      if (utype->consume[r] > consumed[r])
  751.       supply[r] -= utype->consume[r] - consumed[r];
  752.      consumed[r] = 0;
  753.     supply[r] += (utype->produce[r] * utype->productivity[terrain_at(step->x, step->y)]) / 100;
  754.       }
  755.       movesleft = utype->speed;
  756.     }  
  757.   }
  758. }
  759.  
  760. make_unitlists(side)
  761. Side *side;
  762. {
  763.   Unit *unit;
  764.   int ut, i;
  765.   Side *loop_side;
  766.  
  767.     side->numunits = 0;
  768.     for_all_unit_types(ut) {
  769.       side->unitlist[ut] = NULL;
  770.       side->unitlistcount[ut] = 0;
  771.     }
  772.     for_all_unit_types(ut) 
  773. #ifdef REGIONS      
  774.       for (i = 0; i < num_regions[ut]; i++)
  775.     units_in_region[ut][i] = 0;
  776. #endif
  777.    for_all_units(loop_side, unit) {
  778.       if (side == unit->side && !humanside(side)) {
  779.     if (!producing(unit) && probability(10))
  780.       wake_unit(unit, FALSE, WAKEOWNER, (Unit *) NULL);
  781.       }
  782.       if (allied_side(unit->side, side)) {
  783.     side->numunits++;
  784.     ut = unit->type;
  785.     side->unitlistcount[ut]++;
  786.     unit->mlist = side->unitlist[ut];
  787.     side->unitlist[ut] = unit;
  788. #ifdef REGIONS
  789.     if (unit->side == side &&
  790.         (i = aref(unit_region[ut], unit->x, unit->y)) >= 0)
  791.       units_in_region[ut][i]++;
  792. #endif
  793.       }
  794.     }
  795. }
  796.  
  797. void update_areas(side)
  798. Side *side;
  799. {
  800.   int x, y, num, ut;
  801.   viewdata view;
  802.   Unit *unit;
  803.   Side *loop_side;
  804.  
  805.   for (num = 0; num < areas_wide * areas_high; num++) {
  806.     area_info[num].allied_units = 0;
  807.     area_info[num].allied_makers = 0;
  808.     area_info[num].neutral_makers = 0;
  809.     area_info[num].makers = 0;
  810.     area_info[num].unexplored = 0;
  811.     area_info[num].border = FALSE;
  812.     area_info[num].allied_bases = 0;
  813.     for_all_unit_types(ut) {
  814.       area_info[num].units[ut] = NULL;
  815.       area_info[num].requested_units[ut] = 0;
  816.     }
  817.     if (Cheat)
  818.       side->areas[num].enemy_strength = 0;
  819.     else side->areas[num].enemy_strength /= 2;
  820.     side->areas[num].units_lost /= 2;
  821.     side->areas[num].enemy_seen_recently = 0;
  822.   }
  823.   for_all_units (loop_side, unit) {
  824.     num = area_index(unit->x, unit->y);
  825.     if (allied_side(unit->side, side)) {
  826.       area_info[num].allied_units++;
  827.       unit->nextinarea = area_info[num].units[unit->type];
  828.       area_info[num].units[unit->type] = unit;
  829.       if (utypes[unit->type].maker)
  830.     area_info[num].allied_makers++;
  831.       if (isbase(unit))
  832.     area_info[num].allied_bases++;
  833.     }
  834.     if (utypes[unit->type].maker) {
  835.           area_info[num].makers++;
  836.     if (unit->side == NULL)
  837.       area_info[num].neutral_makers++;
  838.       }
  839.     if (Cheat && enemy_side(unit->side, side)) {
  840.       side->areas[num].enemy_strength += unit_strength(unit->type);
  841.     }
  842.   }
  843.   for_all_interior_hexes(x, y) {
  844.     num = area_index(x, y);
  845.     view = side_view(side, x, y);
  846.     if (view == UNSEEN)
  847.       area_info[num].unexplored++;
  848.     else {
  849.       if (view == EMPTY && side_view_age(side, x, y) < 4)
  850.     view = side_prevview(side, x, y);
  851.       if (view != EMPTY && view != UNSEEN) {
  852.     ut = vtype(view);
  853.     if (enemy_side(side_n(vside(view)), side))
  854.       side->areas[num].enemy_seen_recently += unit_strength(ut);
  855.       }
  856.     }
  857.   }
  858.   for (num = 0; num < areas_wide * areas_high; num++) {
  859.     side->areas[num].enemy_strength +=
  860.       side->areas[num].enemy_seen_recently;
  861.   }
  862. }
  863.  
  864. int unit_strength(ut)
  865. int ut;
  866. {
  867.   return ((ave_build_time[ut]) ? ave_build_time[ut] : 10);
  868. }
  869.  
  870. find_border_areas(side)
  871. Side *side;
  872. {
  873.   
  874.   int num, x, y, i;
  875.   bool safe;
  876.  
  877.   for (num = 0; num < areas_wide * areas_high; num++) {
  878.     if (area_info[num].allied_bases == 0 ||
  879.     area_info[num].unexplored > 0 ||
  880.     area_info[num].allied_makers != area_info[num].makers ||
  881.     side->areas[num].enemy_strength > 5) {
  882.           area_info[num].border = TRUE;
  883.       side->areas[num].safe_area = FALSE;
  884.     }
  885.     else {
  886.       area_info[num].nearby = TRUE;
  887.       area_info[num].border = FALSE;
  888.       safe = area_info[num].allied_units > 15;
  889.       for_all_directions(i) {
  890.     x = wrap(area_info[num].x + dirx[i] * AREA_SIZE);
  891.     y = interior(area_info[num].y + diry[i] * AREA_SIZE);
  892.     area_info[area_index(x,y)].nearby = TRUE;
  893.     if (area_info[area_index(x,y)].allied_bases < 2) {
  894.       area_info[num].border = TRUE;
  895.       safe = FALSE;
  896.     }
  897.       }
  898.       side->areas[num].safe_area = safe;
  899.     }
  900.   }
  901. }
  902.  
  903. /* Figure out how many units to request for each area. */
  904.  
  905. determine_unit_request(side)
  906. Side *side;
  907. {
  908.  
  909.   int num;
  910.  
  911.     for (num = 0; num < areas_wide * areas_high; num++) {
  912.       if (side->areas[num].enemy_strength < 5) {
  913.     if (area_info[num].allied_makers == 0 &&
  914.         area_info[num].makers > 0 &&
  915.         area_info[num].nearby) 
  916.       area_info[num].unit_request =
  917.          GUARD_BORDER_TOWN + 2 * area_info[num].makers;
  918.     else if (area_info[num].makers > 0) 
  919.       area_info[num].unit_request =
  920.           (area_info[num].border ? GUARD_BORDER_TOWN :
  921.            GUARD_TOWN) + 2 * area_info[num].allied_makers;
  922.     else if (area_info[num].allied_bases > 0)
  923.       area_info[num].unit_request =
  924.           (area_info[num].border ? GUARD_BORDER: 
  925.            GUARD_BASE);
  926.     else if (area_info[num].border)
  927.       area_info[num].unit_request = NO_UNITS;
  928.     else area_info[num].unit_request = NO_UNITS;
  929.       } else  {
  930.     if (area_info[num].allied_makers > 0) 
  931.       area_info[num].unit_request =
  932.         DEFEND_TOWN + 5 * area_info[num].makers;
  933.     else if (area_info[num].allied_bases > 0)
  934.       area_info[num].unit_request =
  935.         DEFEND_BASE + area_info[num].allied_bases;
  936.     else area_info[num].unit_request = DEFEND_AREA;
  937.       }
  938.     }
  939. }
  940.  
  941. assign_units(side)
  942. Side *side;
  943. {
  944.   int total_units, num, total_requests, i, u, priority, d;
  945.   Unit *unit, *prev;
  946.  
  947.   total_units = 0;
  948.   for_all_side_units(side, unit) 
  949.     if (mobile(unit->type))
  950.       total_units += unit_strength(unit->type);
  951.  
  952.   for (i = 0; i < NUMTOPAREAS; i++) {
  953.     top_areas[i] = NULL;
  954.     }
  955.   total_requests = 0;
  956.   for (num = 0; num < areas_wide * areas_high; num++) {
  957.     total_requests += area_info[num].unit_request;
  958.   }
  959.  
  960.   /* Figure out how many units to request of each type. */
  961.   if (total_requests>0) {
  962.     for (num = 0; num < areas_wide * areas_high; num++) {
  963.       /*    printf("area %d (%d %d), request %d allied makers %d enemy_strength %d \n", num, area_info[num].x, area_info[num].y,
  964.         area_info[num].unit_request, area_info[num].allied_makers,
  965.         side->areas[num].enemy_strength); */
  966.       for_all_unit_types(u) {
  967.     if (mobile(u)) {
  968.       area_info[num].requested_units[u] =
  969.         ((area_info[num].unit_request) * (side->unitlistcount[u]) +
  970.          total_requests - total_requests/4) 
  971.           / total_requests;
  972.       area_info[num].num_units[u] = 0;
  973.       /*    if (area_info[num].requested_units[u] > 0)
  974.         printf("area %d requested %d %s\n", num,
  975.         area_info[num].requested_units[u], utypes[u].name);  */
  976.     } else area_info[num].requested_units[u] = 0;
  977.       }
  978.     }
  979.   }
  980.  
  981.   /* Allocate units to locations where they are already going if they */
  982.   /* are really needed there.  If not, then allocate them to the */
  983.   /* current location. */
  984.   /* Figure out how many units are already allocated. */
  985.   for_all_unit_types(u) {
  986.     if (!mobile(u)) { /* No need to allocate. */
  987.       side->unitlist[u] = NULL;
  988.     } else {
  989.       for (priority = 1; priority <= 2; priority++) {
  990.     allocate_as_is(side, u, priority);
  991.       }
  992.       /* Mark all remaining units as unselected.  We will try to
  993.      assign them to the nearest and highest priority task */
  994.       for (unit = side->unitlist[u]; unit != NULL; unit = unit->mlist) {
  995.     unit->selection_status = 10000;
  996.       }
  997.       /* This loop looks for high priority units that are not
  998.      at their destinations.  All units being placed are guaranteed
  999.      not to be placed in the area they currently are in. */
  1000.       for (num = 0; num < areas_wide * areas_high; num++)
  1001.     if (needs_units(1, side, num, u) || needs_units(2, side, num, u)) {
  1002.       prev = NULL;
  1003.       /* Send unit to priority 2 locations only if the distance is */
  1004.       /* half as far as the nearest priority 1 location. */
  1005.       i = (needs_units(1, side, num, u)) ? 2 : 1;
  1006.       for (unit = side->unitlist[u]; unit != NULL; unit = unit->mlist) {
  1007.         d = distance(unit->x, unit->y, area_info[num].x, area_info[num].y) / i;
  1008.         if (d < unit->selection_status) {
  1009.           if (unit->selection_status < 10000) {
  1010.         area_info[unit->area].num_units[u]--;
  1011.           }
  1012.           unit->area = num;
  1013.           unit->selection_status = d;
  1014.           area_info[num].num_units[u]++;
  1015.           /* delete the unit immediately if it is close. no need */
  1016.           /* to check any further */
  1017.           if (d < AREA_SIZE) {
  1018.         if (prev == NULL)
  1019.           side->unitlist[u] = unit->mlist;
  1020.         else prev->mlist = unit->mlist;
  1021.           } else prev = unit;
  1022.         } else prev = unit;
  1023.       }
  1024.     }
  1025.       for (unit = side->unitlist[u]; unit != NULL; unit = unit->mlist) {
  1026.     prev = NULL;
  1027.     if (unit->selection_status < 10000) {
  1028.       if (prev == NULL)
  1029.         side->unitlist[u] = unit->mlist;
  1030.       else prev->mlist = unit->mlist;
  1031.     } else prev = unit;
  1032.       }
  1033.  
  1034.       /* Now allocate all other units alreay in the correct locations. */
  1035.       allocate_as_is(side, u, 3);
  1036.  
  1037.       for (num = 0; num < areas_wide * areas_high; num++)
  1038.     if (needs_units(3, side, num, u)) {
  1039.       prev = NULL;
  1040.       for (unit = side->unitlist[u]; unit != NULL; unit = unit->mlist) {
  1041.         d = distance(unit->x, unit->y, area_info[num].x, area_info[num].y);
  1042.         if (d < unit->selection_status) {
  1043.           if (unit->selection_status < 10000) {
  1044.         area_info[unit->area].num_units[u]--;
  1045.           }
  1046.           unit->area = num;
  1047.           unit->selection_status = d;
  1048.           area_info[num].num_units[u]++;
  1049.           if (d < AREA_SIZE) {
  1050.         if (prev == NULL)
  1051.           side->unitlist[u] = unit->mlist;
  1052.         else prev->mlist = unit->mlist;
  1053.           } else prev = unit;
  1054.         } else prev = unit;
  1055.       }
  1056.     }
  1057. /* No needed, unit lists redone from start */
  1058. /*      for (unit = side->unitlist[u]; unit != NULL; unit = unit->mlist) {
  1059.     prev = NULL;
  1060.     if (unit->selection_status < 10000) {
  1061.       if (prev == NULL)
  1062.         side->unitlist[u] = unit->mlist;
  1063.       else prev->mlist = unit->mlist;
  1064.     } else prev = unit;
  1065.       } */
  1066.     }
  1067.   }
  1068.   /* Allocate remaining units. */
  1069.  
  1070. /* Unit allocation. */
  1071.  
  1072. /* Allocate all units in war zones to that zone, unless they are */
  1073.  /* moving to another war zone.  
  1074.  
  1075.     Allocate units to other zones up to some fraction, provided that
  1076.     they have already been allocated to that area.
  1077.  
  1078.     Allocate the other units to the neediest area nearby.  War zones
  1079.     already have most of the units in them, so distance is not too
  1080.     important. 
  1081. */
  1082.  
  1083.  
  1084.   
  1085. }
  1086.  
  1087. /* Are units for this area a top priority. */
  1088.  
  1089. bool needs_units(priority, side, area, utype)
  1090. int priority;
  1091. Side *side;
  1092. int area, utype;
  1093. {
  1094.   switch (priority) {
  1095.   case 1:
  1096.     if (side->areas[area].enemy_strength < 4 ||
  1097.     area_info[area].allied_bases == 0)
  1098.       return FALSE;
  1099.     else if (area_info[area].requested_units[utype] >
  1100.          area_info[area].num_units[utype])
  1101.       return TRUE;
  1102.     else return FALSE;
  1103.     break;
  1104.   case 2:
  1105.     if (side->areas[area].enemy_strength < 4 ||
  1106.     area_info[area].allied_makers == 0)
  1107.       return FALSE;
  1108.     else if (area_info[area].requested_units[utype] / 2 >
  1109.          area_info[area].num_units[utype])
  1110.       return TRUE;
  1111.     else return FALSE;
  1112.     break;
  1113.   case 3: 
  1114.     if (area_info[area].requested_units[utype] >
  1115.     area_info[area].num_units[utype])
  1116.       return TRUE;
  1117.     else return FALSE;
  1118.     break;
  1119.   default:
  1120.     return TRUE;
  1121.     break;
  1122.   }
  1123. }
  1124.  
  1125. allocate_as_is(side, u, priority)
  1126. Side *side;
  1127. int u, priority;
  1128. {
  1129.   Unit *unit, *prev;
  1130.   int num;
  1131.  
  1132.   prev = NULL;
  1133.   for (unit = side->unitlist[u]; unit != NULL; unit = unit->mlist) {
  1134.     num = area_index(unit->x, unit->y);
  1135.     if (unit->area >= 0 && needs_units(priority, side, unit->area, u)) {
  1136.       area_info[unit->area].num_units[u]++;
  1137.       if (prev == NULL)
  1138.     side->unitlist[u] = unit->mlist;
  1139.       else prev->mlist = unit->mlist;
  1140.     } else if (needs_units(priority, side, num, u)) {
  1141.       unit->area = num;
  1142.       area_info[num].num_units[u]++;
  1143.       if (prev == NULL)
  1144.     side->unitlist[u] = unit->mlist;
  1145.       else prev->mlist = unit->mlist;
  1146.     } else prev = unit;      
  1147.   }
  1148. }
  1149.  
  1150. bool area_needs_capturer(x, y)
  1151. int x, y;
  1152. {
  1153.   int num = area_index(x, y);
  1154.  
  1155.   if (area_info[num].makers < area_info[num].allied_makers &&
  1156.       (mside->areas[num].capturers_approaching == 0 ||
  1157.        mside->areas[num].capture_time - global.time > 10))
  1158.     return TRUE;
  1159.   else return FALSE;
  1160. }
  1161.  
  1162. /* Check for any makers this unit should be capturing. */
  1163.  
  1164. bool should_capture_maker(unit)
  1165. Unit *unit;
  1166. {
  1167.   int x, y;
  1168.   if (search_area(unit->x, unit->y, 25, area_needs_capturer, &x, &y, AREA_SIZE))
  1169.     {
  1170.     }
  1171.   return FALSE;
  1172. }
  1173.  
  1174. bool no_possible_moves(unit)
  1175. Unit *unit;
  1176. {
  1177.   int fx = unit->x, fy = unit->y, ut = unit->type;
  1178.   int d, x, y;
  1179.   viewdata view;
  1180.   Side *side = unit->side;
  1181.  
  1182.   for_all_directions(d) {
  1183.     x = wrap(fx + dirx[d]);  y = limit(fy + diry[d]);
  1184.     view = side_view(side, x, y);
  1185.     if (view == EMPTY) {
  1186.       if (could_move(ut, terrain_at(x, y)))
  1187.     return FALSE;
  1188.     } else if (enemy_side(side_n(vside(view)) , side)
  1189.            && could_hit(ut, vtype(view))) {
  1190.       return FALSE;
  1191.     } else if (could_carry(vtype(view), ut) &&
  1192.            allied_side(side_n(vside(view)), side))
  1193.       return FALSE;
  1194.   }
  1195.   return TRUE;
  1196. }
  1197.