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 / mplay.c < prev    next >
C/C++ Source or Header  |  1992-03-08  |  27KB  |  934 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 the main machine strategy.  Not much room for fancy */
  6. /* tricks, just solid basic play.  The code emphasizes avoidance of mistakes */
  7. /* instead of strategic brilliance, so machine behavior is akin to bulldozer */
  8. /* plodding.  Nevertheless, bulldozers can be very effective when they */
  9. /* outnumber the human players... */
  10.  
  11. /* It is also very important to prevent infinite loops, so no action of the */
  12. /* machine player is 100% certain. */
  13.  
  14. #include "config.h"
  15. #include "misc.h"
  16. #include "dir.h"
  17. #include "period.h"
  18. #include "side.h"
  19. #include "unit.h"
  20. #include "map.h"
  21. #include "global.h"
  22. #include "mplay.h"
  23.  
  24.  
  25. int max_range = 10;  /* dummy value to start to prevent debugging crashes. */
  26.  
  27. /* At the beginning of each turn, can make plans and review the situation. */
  28. /* This should be frequent at first, but rather expensive to do always, */
  29. /* so only some chance of doing it on a random turn.  This routine can be */
  30. /* for human players too if they want to use the machines strategy for building */
  31. /* so we have to check that some things are not done for the human. */
  32.  
  33. init_machine_turn(side)
  34. Side *side;
  35. {
  36.     Unit *unit;
  37.     int x, y;
  38.  
  39.     if (side->lost) return;
  40. /*    if ((global.time < 20 && probability(30)) || probability(10)) make_strategy(side);
  41.     if ((global.time < 20 && probability(30)) || probability(15)) review_groups(side);  */
  42.     make_unitlists(side);
  43.     if (global.time > 20 || probability(25)) decide_resignation(side);
  44.     if (Cheat && !humanside(side)) {
  45.       for_all_hexes(x, y) 
  46.     see_exact(side, x, y);
  47.     }
  48.     /* Completely reset the areas periodically, so that units tend not to want to go too far. */
  49.     if (global.time % 4 == 0)
  50.       for_all_side_units(side, unit)
  51.     unit->area = area_index(unit->x, unit->y);
  52.     update_areas(side);
  53.     find_border_areas(side);
  54.     determine_unit_request(side);
  55.     assign_units(side);
  56.     make_unitlists(side);
  57.     defend_priority = 50;
  58.     explore_priority = max(75 - global.time, 0);
  59.     attack_priority = max(0, 50 - explore_priority);
  60. }
  61.  
  62.  
  63.  
  64. /* Strategy is based on a study of the entire world map, looking for */
  65. /* duties and opportunities. */
  66.  
  67. make_strategy(side)
  68. Side *side;
  69. {
  70. }
  71.  
  72. /* Decides if unit has nothing covering it. */
  73.  
  74. defended(side, x, y)
  75. Side *side;
  76. int x, y;
  77. {
  78. }
  79.  
  80. /* Sometimes there is no point in going on, but be careful not to be too */
  81. /* pessimistic.  Right now we only give up if no hope at all. */
  82.  
  83. decide_resignation(side)
  84. Side *side;
  85. {
  86.     int u, u2, sn1, inrunning = FALSE, opposed, own, chance = 0;
  87.     Side *side1, *side2;
  88.     Plan *plan = side_plan(side);
  89.     Unit *unit;
  90.  
  91.     if (humanside(side))
  92.       return;
  93.     enter_procedure("decide resignation");
  94.     if (global.numconds == 0) {
  95.       for_all_sides(side1) {
  96.     sn1 = side_number(side1);
  97.     for_all_unit_types(u) {
  98.       plan->allies[sn1][u] = plan->estimate[sn1][u];
  99.       for_all_sides(side2) {
  100.         if (side1 != side2 && allied_side(side1, side2)) {
  101.           plan->allies[sn1][u] +=
  102.         plan->estimate[side_number(side2)][u];
  103.         }
  104.       }
  105.     }
  106.       }  
  107.       for_all_unit_types(u) {
  108.         own = plan->allies[side_number(side)][u];
  109.         for_all_unit_types(u2) {
  110.         if (could_make(u, u2) && mobile(u2))
  111.             inrunning = TRUE;
  112.         for_all_sides(side1) {
  113.             if (enemy_side(side, side1)) {
  114.             opposed = plan->allies[side_number(side1)][u2];
  115.             if (own > 0 && opposed > 0) {
  116.                 if (could_capture(u, u2) && mobile(u))
  117.                 inrunning = TRUE;
  118.                 if (could_hit(u, u2) && mobile(u))
  119.                 inrunning = TRUE;
  120.             }
  121.             }
  122.         }
  123.         }
  124.     }
  125.     /* should use chance for doubtful situations, like relative strength */
  126.     if (!inrunning || probability(chance)) 
  127.       resign_game(side, (Side *) NULL);  
  128.     } else {
  129.       if (!active_display(side)) {
  130.     chance = 0;
  131.     for_all_side_units(side, unit)
  132.       /* don't resign unless you have less than twenty units and */
  133.       /* those can't build bases (should be anything) and can't */
  134.       /* make */
  135.       if (chance++ > 20 || utypes[unit->type].can_make ||
  136.           utypes[unit->type].maker || utypes[unit->type].can_capture)
  137.         return;
  138.     /* Try to give away all of our units to an ally */
  139.     for_all_sides(side1) {
  140.       if (side != side1 && allied_side(side, side1)) {
  141.         resign_game(side, side1);
  142.         }
  143.       resign_game(side, (Side *) NULL);
  144.     }
  145.       }}    
  146.           
  147.     exit_procedure();
  148.  
  149. }
  150.  
  151. /* Decide on and make a move or set orders for a machine player. */
  152.  
  153. machine_move(unit)
  154. Unit *unit;
  155. {
  156.  
  157.   routine("Machine Move");
  158.   munit = unit;
  159.   mside = unit->side;
  160.   if (unit->move_turn != global.time) {
  161.     unit->move_turn = global.time;
  162.     unit->move_tries = 0;
  163.   } else unit->move_tries++;
  164.       
  165.   if (unit->move_tries++ > utypes[unit->type].speed * 2) {
  166.     unit->movesleft = 0;
  167.     order_sentry(unit,1);
  168.     return;
  169.   }
  170.   bestworth = 1000000; /* very good, until we actually evaluate */
  171.   if (probability(5)) {
  172.         mside->cx = unit->x;  mside->cy = unit->y;
  173.       }
  174.   route_max_distance = 0;
  175.   if (Freeze) {
  176.     order_sentry(unit, 1);
  177.   } else {
  178.     if (unit->goal == LOAD && probability(fullness(unit))) {
  179.       if (unit->gx == 0 && unit->gy == 0) 
  180.     unit->goal = DRIFT;
  181.       else unit->goal = APPROACH;
  182.     }
  183.     if (istransport(unit) && probability(20 - fullness(unit)))
  184.       unit->goal = LOAD;
  185.     if (unit->goal == NOGOAL) unit->goal = DRIFT;
  186.     wake_neighbors(unit);
  187.     /* this can cause problems if unit is carrying some other sides
  188.        units.  As such, occupant_can_capture_neighbor does not return 
  189.        true for occupants of other sided. */
  190.     if (occupant_can_capture_neighbor(unit)) {
  191. /*      delaymove = TRUE; */
  192. /*      mside->movunit = NULL;*/ /* set in occupant_can_capture_neighbor */
  193.       return;
  194.     }
  195. /*    if (should_capture_maker(unit)) return;
  196.       if (should_build_base(unit)) return;
  197.       if (should_capture_base(unit)) return;
  198.       if (should_transport_someone(unit)) return;
  199. */
  200.     if (should_build_base(unit)) return; 
  201.     if (follow_plan(unit)) return;
  202.     if (no_possible_moves(unit)) {
  203.       order_sentry(unit,1);
  204.       return;
  205.     }
  206.     if (maybe_return_home(unit)) return;
  207.     if (unit->area != area_index(unit->x, unit->y))
  208.       get_unit_to_area(unit);
  209.     else {
  210.       if (mside->areas[unit->area].safe_area && probability(80)) {
  211.     order_sentry(unit, 2);
  212.     return;
  213.       }
  214.       if (probability(50) && short_term(unit)) return;
  215.       search_for_best_move(unit);
  216.     }
  217.   }
  218.   routine("Not Machine Move");
  219. }
  220.  
  221. /* Set up goals for units that need them. */
  222. /* Goals should differ according to unit's role in group... */
  223.  
  224. decide_goal(unit)
  225. Unit *unit;
  226. {
  227. }
  228.  
  229. bool find_base(unit, pred, extra)
  230. Unit *unit;
  231. bool (*pred)();
  232. int extra;
  233. {
  234.   int range;
  235.   int ox, oy, ux = unit->x, uy = unit->y;
  236.  
  237.   enter_procedure("find base");
  238.   route_max_distance = range = range_left(unit) + extra;
  239.   if ((range * range < mside->numunits) ? 
  240.       (search_area(ux, uy, range, pred, &ox, &oy, 1))  :
  241.       (find_closest_unit(ux, uy, range, pred, &ox, &oy))) {
  242. /*    order_moveto(unit, ox, oy); */
  243.     if (munit->move_tries < 3)
  244.       unit->orders.flags |= SHORTESTPATH;
  245.     unit->orders.flags &=
  246.       ~(ENEMYWAKE|NEUTRALWAKE|SUPPLYWAKE|ATTACKUNIT);
  247.     if (Debug) printf("will resupply at %d,%d\n", ox, oy);
  248.     exit_procedure();
  249.     return TRUE;
  250.   }
  251.   exit_procedure();
  252.   return FALSE;
  253. }
  254.  
  255. /* See if we're in a bad way, either on supply or hits, and get to safety */
  256. /* if possible.  If not, then move on to other actions. */
  257. /* Can't be 100% though, there might be some problem preventing move */
  258.  
  259. maybe_return_home(unit)
  260. Unit *unit;
  261. {
  262.     int u = unit->type;
  263.  
  264.     enter_procedure("maybe return home 1");
  265.  
  266.     if (Debug) printf("%s low supplies %d moves %d wakup %d - ", unit_desig(unit),
  267.               low_supplies(unit), moves_till_low_supplies(unit),
  268.               unit->wakeup_reason);
  269.     unit->priority = 1000000;
  270.     if ((low_supplies(unit) || munit->move_tries > 6 ||
  271.      (moves_till_low_supplies(unit) < min(3, unit->movesleft) &&
  272.       unit->wakeup_reason != WAKEENEMY))  &&
  273.     !can_capture_neighbor(unit)
  274.     && probability(100)) {
  275.  
  276.       if (Debug) printf("%s should get supplies ? - ", unit_desig(unit));
  277.       if (producing(unit) && survival_time(unit) > unit->schedule) {
  278.     order_sentry(unit, 1);
  279.     exit_procedure();
  280.     return TRUE;
  281.       }
  282.       if (Debug) printf("%s should get supplies - ", unit_desig(unit));
  283.       if (find_base(unit,good_haven_p, 0)) {
  284.     exit_procedure();
  285.     return TRUE;
  286.       } else if (find_base(unit,haven_p, 0)) {
  287.     exit_procedure();
  288.     return TRUE;
  289.       } else if (unit->transport != NULL) {
  290.     order_sentry(unit, 1);
  291.       } else if (survive_to_build_base(unit) && unit->transport == NULL) {
  292.     if (Debug) printf("going to build something\n");
  293.     set_product(unit, machine_product(unit));
  294.     set_schedule(unit);
  295.     order_sentry(unit, unit->schedule+1);
  296.     exit_procedure();
  297.     return TRUE;
  298.       } else if (find_base(unit,haven_p, 1)) {
  299.     exit_procedure();
  300.     return TRUE;
  301.       } else if (Debug) printf("but can't\n");
  302.       
  303.     }
  304.     if ((cripple(unit) && probability(98)) ||
  305.     probability(100 - ((100 * unit->hp) / utypes[u].hp))) {
  306.     /* note that crippled units cannot repair themselves */
  307.     if (Debug) printf("%s badly damaged - ", unit_desig(unit));
  308.     if (unit->transport && could_repair(u, unit->transport->type)) {
  309.         if (Debug) printf("%s will repair\n", unit_desig(unit->transport));
  310.         order_sentry(unit, 1);
  311.         exit_procedure();
  312.         return TRUE;
  313.     } else {
  314.         if (find_base(unit, shop_p, 0)) {
  315.             exit_procedure();
  316.         return TRUE;
  317.         } else {
  318.         if (Debug) printf("but no place to repair\n");
  319.         }
  320.     }
  321.     }
  322.     if (out_of_ammo(unit) >= 0 && probability(80)) {
  323.     if (Debug) printf("%s should reload - ", unit_desig(unit));
  324.     if (find_base(unit, haven_p, 0)) {
  325.         exit_procedure();
  326.         return TRUE;
  327.     } else {
  328.       if (survive_to_build_base(unit) && 
  329.           unit->transport == NULL && probability(90)) {
  330.         if (Debug) printf("going to build something\n");
  331.         set_product(unit, machine_product(unit));
  332.         set_schedule(unit);
  333.         order_sentry(unit, unit->schedule+1);
  334.       }
  335.       else if (Debug) printf("but can't\n");
  336.     }
  337.     }
  338.     exit_procedure();
  339.     return FALSE;
  340. }
  341.  
  342. /* Return the distance that we can go by shortest path before running out */
  343. /* of important supplies.  Will return at least 1, since we can *always* */
  344. /* move one hex to safety.  This is a worst-case routine, too complicated */
  345. /* to worry about units getting refreshed by terrain or whatever. */
  346.  
  347. range_left(unit)
  348. Unit *unit;
  349. {
  350.     int u = unit->type, r, least = 12345;
  351.  
  352.     for_all_resource_types(r) {
  353.     if (utypes[u].tomove[r] > 0) {
  354.       least = min(least, unit->supply[r] / utypes[u].tomove[r]);
  355.     }
  356.     if (utypes[u].consume[r] > 0)
  357.         least = min(least,
  358.             (utypes[unit->type].speed * unit->supply[r]) / utypes[u].consume[r]);
  359.     }
  360.     return (least == 12345 ? 1 : least);
  361. }
  362.  
  363. /* Try to get to the given destination using the router in preference
  364. to the order_moveto command */
  365.  
  366. route_to(unit, x, y)
  367. Unit *unit;
  368. int x,y;
  369. {
  370.   Mplan *plan;
  371.   int maxdist = moves_till_low_supplies(unit);
  372.   Unit *dest_unit = unit_at(x,y);
  373.  
  374.   if (dest_unit != NULL && isbase(dest_unit))
  375.     maxdist = range_left(unit);
  376.   if (route_max_distance > maxdist)
  377.     maxdist = route_max_distance;
  378.   plan = find_route(munit->type, maxdist,
  379.             munit->x, munit->y, x, y);
  380.   if (plan != NULL) {
  381.     unit->priority = bestworth;
  382.     free_plan(unit->plan);
  383.     unit->plan = plan;
  384.     /* Find the last plan step that we want to use */
  385.     while (maxdist-- > 1 && plan != NULL)
  386.       plan = plan->next;
  387.     if (plan != NULL) {
  388.       free_plan(plan->next);
  389.       plan->next = NULL;
  390.     }
  391. /*    printf("Using plan ");
  392.     printf("unit %d type %d (x,y) (%d,%d), to (%d,%d)\n",
  393.        unit->id, unit->type, unit->x, unit->y, x, y); */
  394.   } else {
  395.  /*    printf("Could not find plan.  Ordering move to %d.\n",
  396.        route_max_distance); 
  397.     printf("unit %d type %d (x,y) (%d,%d), to (%d,%d)\n",
  398.        unit->id, unit->type, unit->x, unit->y, x, y); */
  399.     order_moveto(unit, x, y);
  400.   }
  401. }
  402.   
  403.  
  404. /* Do short-range planning.  Only thing here is intended to be for defenders */
  405. /* protecting a small area (5 moves is arb, should derive from defense */
  406. /* group area). */
  407.  
  408. short_term(unit)
  409. Unit *unit;
  410. {
  411.     int u = unit->type, range;
  412.  
  413.     if (!mobile(unit->type)) {
  414.     order_sentry(unit, 100);
  415.     return TRUE;
  416.     }
  417.     switch (unit->goal) {
  418.     case DRIFT:
  419.     range = max(9, min(5 * utypes[u].speed,
  420.                 moves_till_low_supplies(unit)));
  421.     if (probability(90)) {
  422.         find_worths(range);
  423.         if (bestworth >= 0) {
  424.         if (Debug) printf("drifting to %d,%d (worth %d)\n",
  425.                   bestx, besty, bestworth);
  426.         if (unit->transport != NULL &&
  427.             moves_till_low_supplies(unit) < 8)
  428.           do_take(mside, unit, -1);
  429.         route_to(unit, bestx, besty);
  430.         unit->orders.flags &= ~SHORTESTPATH;
  431.         return TRUE;
  432.         }
  433.     }
  434.     break;
  435.     case LOAD:
  436.     case APPROACH:
  437.     case HITTARGET:
  438.     case CAPTARGET:
  439.     break;
  440.     default:
  441.         case_panic("unit goal", munit->goal);
  442.     break;
  443.     }
  444.     return FALSE;
  445. }
  446.  
  447. /* Search for most favorable odds anywhere in the area, but only for */
  448. /* the remaining moves in this turn.  Multi-turn tactics is elsewhere. */
  449.  
  450. search_for_best_move(unit)
  451. Unit *unit;
  452. {
  453.     int ux = unit->x, uy = unit->y,
  454.         range = min(moves_till_low_supplies(unit), AREA_SIZE+2), goal;
  455.  
  456.     enter_procedure("search_for_best_move");
  457.     if (!mobile(unit->type)) {
  458.     order_sentry(unit, 100);
  459.     exit_procedure();
  460.     return;
  461.     }
  462.     if (utypes[unit->type].produce[0] > 0
  463.     && mside->areas[area_index(ux, uy)].enemy_strength == 0)
  464.       range = min(range * 3, AREA_SIZE * 2);
  465.     if (Debug) printf("%d: %s ", global.time, unit_desig(unit));
  466.     find_worths(range);
  467.     if (bestworth >= 0) {
  468.           if (unit->transport != NULL && mobile(unit->transport->type) &&
  469.         bestworth >= EXPLORE_VAL) {
  470.         if (Debug) printf("moving to %d,%d (worth %d)\n",
  471.                   bestx, besty, bestworth);
  472.         if (unit->transport != NULL &&
  473.         moves_till_low_supplies(unit) < 2)
  474.           do_take(mside, unit, -1);
  475.         route_to(unit, bestx, besty);
  476.         unit->orders.flags &= ~SHORTESTPATH;
  477.     } else if (unit->transport != NULL && mobile(unit->transport->type) &&
  478.         /* force unit to try to leave transport occasionally */
  479.         probability(30)) {
  480.         if (Debug) printf("sleeping on transport\n");
  481.         order_sentry(unit, 1);
  482.     } else if ((bestworth < 3000 ||
  483.             (moves_till_low_supplies(unit)) < distance(ux, uy, bestx, besty))
  484.            && survive_to_build_base(unit) &&
  485.            !base_nearby(unit, 2*utypes[unit->type].speed) &&
  486.            (utypes[unit->type].occproduce || (unit->transport == NULL))
  487.            && probability(40)) {
  488.           if (Debug) printf("going to build something\n");
  489.           set_product(unit, machine_product(unit));
  490.           set_schedule(unit);
  491.           order_sentry(unit, unit->schedule+1);
  492.         }
  493.     else if ((ux == bestx && uy == besty) || !can_move(unit)) {
  494.         if (Debug) printf("staying put\n");
  495.         order_sentry(unit, 1);
  496.     } else if (probability(90)) {
  497.         if (Debug) printf("moving to %d,%d (worth %d)\n",
  498.                   bestx, besty, bestworth);
  499.         if (unit->transport != NULL &&
  500.         moves_till_low_supplies(unit) < 2)
  501.           do_take(mside, unit, -1);
  502.         route_to(unit, bestx, besty);
  503.         unit->orders.flags &= ~SHORTESTPATH;
  504.     } else {
  505.         if (unit->transport != NULL)
  506.           do_embark(mside, unit, RANDOM(5));
  507.         if (Debug) printf("hanging around\n");
  508.     }
  509.     } else {
  510.     goal = unit->goal;
  511.     /* jam alternative sometimes... */
  512.     if (probability(95)) goal = DRIFT;
  513.     switch (goal) {
  514.     case DRIFT:
  515.         if (can_produce(unit) && survive_to_build_base(unit) &&
  516.         (utypes[unit->type].occproduce || (unit->transport == NULL)) &&
  517.         probability(90)) {
  518.         if (Debug) printf("going to build something\n");
  519.         set_product(unit, machine_product(unit));
  520.         set_schedule(unit);
  521.         order_sentry(unit, unit->schedule+1);
  522.         } else if (unit->transport != NULL && do_embark(mside, unit, 1)) {
  523.         break;
  524.         } else if (probability(90)) {
  525.         if (Debug) printf("going in random direction\n");
  526.         order_movedir(unit, random_dir(), RANDOM(3)+1);
  527.         } else {
  528.         if (Debug) printf("hanging around\n");
  529.         order_sentry(unit, RANDOM(4)+1);
  530.         }
  531.         break;
  532.     case LOAD:
  533.         if (unit->occupant != NULL) {
  534.         if (Debug) printf("starting off to goal\n");
  535.         unit->goal = APPROACH;
  536.         route_to(unit, unit->gx, unit->gy);
  537.         } else {
  538.         if (bestworth >= 0) {
  539.             if (Debug) printf("loading at %d,%d (worth %d)\n",
  540.                       bestworth, bestx, besty);
  541.             route_to(unit, bestx, besty);
  542.             unit->orders.flags &= ~SHORTESTPATH;
  543.         } else {
  544.             if (Debug) printf("moving slowly about\n");
  545.             order_movedir(unit, random_dir(), 1);
  546.         }
  547.         }
  548.         break;
  549.     case APPROACH:
  550.         if (survive_to_build_base(unit) && !base_nearby(unit, 8) &&
  551.         (utypes[unit->type].occproduce || (unit->transport == NULL))
  552.         && probability(90) && unit->wakeup_reason != WAKEENEMY
  553.         && bestworth < 1000) {
  554.           if (Debug) printf("going to build something\n");
  555.           set_product(unit, machine_product(unit));
  556.           set_schedule(unit);
  557.           order_sentry(unit, unit->schedule+1);
  558.           break;
  559.         }
  560.         if (unit->transport != NULL && do_embark(mside, unit, 1))
  561.           break;
  562.     case HITTARGET:
  563.     case CAPTARGET:
  564.         if (unit->transport != NULL) {
  565.           if (!can_move(unit)) {
  566.             if (Debug) printf("waiting to get off\n");
  567.             order_sentry(unit, 2);
  568.         } else {
  569.             if (Debug) printf("leaving for %d,%d\n",
  570.                       unit->gx, unit->gy);
  571.             route_to(unit, unit->gx, unit->gy);
  572.         }
  573.         } else {
  574.         if (Debug) printf("approaching %d,%d\n", unit->gx, unit->gy);
  575.         route_to(unit, unit->gx, unit->gy);
  576.         }
  577.         break;
  578.     default:
  579.             case_panic("unit goal", munit->goal);
  580.         break;
  581.     }
  582.     }
  583.     exit_procedure();
  584. }
  585.  
  586. find_worths(range)
  587. int range;
  588. {
  589.   int ux = munit->x, uy = munit->y;
  590.  
  591.     bestworth = -10000;
  592. #ifdef REGIONS
  593.     munit_regions = regions_around(munit->type, ux, uy, FALSE);
  594. #endif
  595.     max_range = range;
  596.     apply_to_area(ux, uy, range, evaluate_hex);
  597.     apply_to_area(ux, uy, range, maximize_worth);
  598. }
  599.  
  600. /* Given a position nearby the unit, evaluate it with respect to goals, */
  601. /* general characteristics, and so forth.  -10000 is very bad, 0 is OK, */
  602. /* 10000 or so is best possible. */
  603.  
  604. /* Should downrate hexes within reach of enemy retaliation. */
  605. /* Should downrate hexes requiring supply consumption to enter/occupy. */
  606.  
  607. extern int printing;
  608.  
  609. evaluate_hex(x, y)
  610. int x, y;
  611. {
  612.     bool adjhex, ownhex, reachable;
  613.     int etype, dist, worth = 0;
  614.     viewdata view;
  615.     int terr = terrain_at(x, y);
  616.     Side *es;
  617.     Unit *eunit;
  618.  
  619.     if (!between(1, y, world.height-2))
  620.       return -10000;
  621.  
  622.     enter_procedure("evaluate hex"); 
  623. printing = FALSE;
  624.     view = side_view(mside, x, y);
  625.     dist = distance(munit->x, munit->y, x, y);
  626.     adjhex = (dist == 1);
  627.     ownhex = (dist == 0);
  628.     /* it would be cheating if we didn't check that we knew what
  629.        the view was before we decided it was unreachable. */
  630.        
  631.     reachable =
  632. #ifdef REGIONS
  633.       (view == UNSEEN ||
  634.          (munit_regions & regions_around(munit->type, x, y, TRUE)) != 0);
  635. #else
  636.        TRUE;
  637. #endif
  638.  
  639.     
  640.     if (view == EMPTY && !reachable) {
  641.       /* don't bother with empty hexes we can't reach without a transport. */
  642.       aset(localworth, x, y, -1000);
  643.       exit_procedure();
  644.       return;
  645.     }
  646.     if (y <= 0 || y >= world.height-1) {
  647.     worth = -10000;
  648.     } else {
  649.     switch (munit->goal) {
  650.     case DRIFT:
  651.         if (ownhex) {
  652.         worth = -1;
  653.         } else if (view == UNSEEN) {
  654.         worth = EXPLORE_VAL + 200 /dist + 
  655.           ((dist < munit->movesleft - 1) ? 5 * dist : -20) +
  656.           ((dist < max_range - 1 ) ? 5 * dist : 0);
  657.         } else if (view == EMPTY) {
  658. #ifdef PREVVIEW
  659.         worth = PATROL_VAL + side_view_age(mside, x, y);
  660. #else
  661.         worth = PATROL_VAL;
  662. #endif
  663.         if (impassable(munit, x, y)) worth -= 900;
  664.         } else {
  665.         es = side_n(vside(view));
  666.         etype = vtype(view);
  667.         if (es == NULL) {
  668.             if (could_capture(munit->type, etype)
  669.             || (occupant_could_capture(munit,etype) && !adjhex)) {
  670.             worth = CAPTURE_OTHER + bcw[munit->type][etype] / dist;
  671.             } else {
  672.             worth = -10000;
  673.             }
  674.         } else if (enemy_side(mside, es)) {
  675.             worth = attack_worth(munit, etype);
  676.             if (worth > 0)
  677.               worth = FAVORABLE_COMBAT + 80 * attack_worth(munit, etype);
  678.             else worth = UNFAVORABLE_COMBAT + 80 * attack_worth(munit, etype);
  679.             worth += threat(mside, etype, x, y);
  680.             if (dist > range_left(munit) / 2)
  681.               worth /= dist;
  682.             worth += 100;
  683.             if (could_capture(munit->type, etype)
  684.             || occupant_could_capture(munit,etype)) {
  685.             worth += CAPTURE_OTHER + bcw[munit->type][etype] / dist;
  686.               }
  687.         } else {
  688.           if ((eunit = unit_at(x, y)) != NULL) {
  689.             if (can_carry(eunit, munit) &&
  690.             mobile(eunit->type)) {
  691.               worth = MEET_TRANSPORT;
  692.               worth += 100/dist;
  693.             } else worth = -10000;
  694.           }
  695.         }
  696.         }
  697.         break;
  698.     case LOAD:
  699.         if (ownhex || view == UNSEEN || view == EMPTY) {
  700.         worth = -1;
  701.         } else {
  702.         es = side_n(vside(view));
  703.         if (allied_side(mside, es)) {
  704.             if ((eunit = unit_at(x, y)) != NULL &&
  705.             can_carry(munit, eunit)) {
  706.                 worth = MEET_TRANSPORT;
  707.                 worth += 100/dist;
  708.                 worth += 50;
  709.             } else worth = -10000;
  710.         } else {
  711.             worth = -10000;
  712.         }
  713.         }
  714.         break;
  715.     case APPROACH:
  716.     case HITTARGET:
  717.     case CAPTARGET:
  718.         if (ownhex) {
  719.         worth = -100;
  720.         } else if (view == UNSEEN) {
  721.         worth = EXPLORE_VAL + 200 /dist + 
  722.           ((dist < munit->movesleft - 1) ? 5 * dist : -20) +
  723.           ((dist < max_range - 1 ) ? 5 * dist : 0);
  724.         } else if (view == EMPTY) {
  725.             if (impassable(munit, x, y)) worth -= 900;
  726. #ifdef PREVVIEW
  727.         else worth = PATROL_VAL + side_view_age(mside, x, y);
  728. #else
  729.         else worth = PATROL_VAL;
  730. #endif
  731.         } else {
  732.         es = side_n(vside(view));
  733.         etype = vtype(view);
  734.         if (es == NULL) {
  735.             if (could_capture(munit->type, etype) ||
  736.             (!adjhex && occupant_could_capture(munit,etype))) {
  737.             worth = CAPTURE_OTHER + bcw[munit->type][etype] / dist;
  738.             } else {
  739.             worth = -10000;
  740.             }
  741.         } else if (!allied_side(mside, es)) {
  742.             worth = attack_worth(munit, etype);
  743.             if (worth > 0)
  744.               worth = FAVORABLE_COMBAT + 80 * attack_worth(munit, etype);
  745.             else worth = UNFAVORABLE_COMBAT + 80 * attack_worth(munit, etype);
  746.             worth += threat(mside, etype, x, y);
  747.             if (dist > range_left(munit) / 2)
  748.               worth /= dist;
  749.             worth += 100;
  750.             if (could_capture(munit->type, etype)
  751.             || occupant_could_capture(munit,etype)) {
  752.             worth += CAPTURE_OTHER + bcw[munit->type][etype] / dist;
  753.               }
  754.         } else {
  755.           /* must be ally */
  756.           if ((eunit = unit_at(x, y)) != NULL) {
  757.             if (can_carry(eunit, munit) &&
  758.             mobile(eunit->type)) {
  759.               worth = MEET_TRANSPORT + 100/dist;
  760.             }
  761.           } else worth = -10000;
  762.         }
  763.         }
  764.         break;
  765.     default:
  766.         case_panic("unit goal", munit->goal);
  767.         break;
  768.     }
  769.     }
  770.     if ((munit->gx > 0 || munit->gy > 0) && (worth < 3000) &&
  771.     (distance(x, y, munit->gx, munit->gy) <
  772.      distance(munit->x, munit->y, munit->gx, munit->gy))  &&
  773.     view == EMPTY) {
  774.     worth += HEAD_FOR_GOAL - 5 * distance(x, y, munit->gx, munit->gy);
  775.     }
  776.     if ((view != EMPTY) && (view != UNSEEN) && !ownhex) {
  777.       es = side_n(vside(view));
  778.       etype = vtype(view);
  779.       if (!allied_side(mside,es) && (could_capture(munit->type, etype) ||
  780.                      occupant_could_capture(munit,etype))) {
  781.     worth += 4000 / dist;
  782.       }
  783.     }
  784.     /* try to count this hex less if other units could get to it more easily */
  785.  
  786. /*    if (worth > 1000) {
  787.       nearer_units = units_nearby(x, y, dist - 1, munit->type);
  788.       if (nearer_units > 0)
  789.     worth = worth / 2 + worth / (nearer_units + 1);
  790.     } */
  791.     worth -= 100;
  792.     worth += utypes[munit->type].productivity[terr];
  793.     if (printing)
  794.       notify(mside,"final worth %d", worth);
  795.     aset(localworth, x, y, worth);
  796.     exit_procedure(); 
  797.     return worth;  /* debugging cludge */
  798. }
  799.  
  800. /* Scan evaluated area looking for best overall hex. */
  801.  
  802.  
  803. maximize_worth(x, y)
  804. int x, y;
  805. {
  806.     int worth;
  807.  
  808.     worth = aref(localworth, x, y);
  809.     if (worth >= 0) {
  810.     if (worth > bestworth) {
  811.         bestworth = worth;  bestx = x;  besty = y;
  812.     } else if (worth == bestworth && flip_coin()) {
  813.         bestworth = worth;  bestx = x;  besty = y;
  814.     }
  815.     }
  816. }
  817.  
  818. /* This is a heuristic estimation of the value of one unit type hitting */
  819. /* on another.  Should take cost of production into account as well as the */
  820. /* chance and significance of any effect. */
  821.  
  822. attack_worth(unit, etype)
  823. Unit *unit;
  824. int etype;
  825. {
  826.     int utype = unit->type, worth;
  827.  
  828.     worth = bhw[utype][etype];
  829.     if (utypes[utype].damage[etype] >= utypes[etype].hp)
  830.     worth *= 2;
  831.     if (utypes[etype].damage[utype] >= unit->hp)
  832.     worth /= (could_capture(utype, etype) ? 1 : 4);
  833.     if (could_capture(utype, etype)) worth *= 4;
  834.     return worth;
  835. }
  836.  
  837.  
  838. /* Support functions. */
  839.  
  840. /* True if unit is in immediate danger of being captured. */
  841. /* Needs check on capturer transport being seen. */
  842.  
  843. might_be_captured(unit)
  844. Unit *unit;
  845. {
  846.     int d, x, y;
  847.     Unit *unit2;
  848.  
  849.     for_all_directions(d) {
  850.     x = wrap(unit->x + dirx[d]);  y = unit->y + diry[d];
  851.     if (((unit2 = unit_at(x, y)) != NULL) &&
  852.         (enemy_side(unit->side, unit2->side)) &&
  853.         (could_capture(unit2->type, unit->type))) return TRUE;
  854.     }
  855.     return FALSE;
  856. }
  857.  
  858. /* Return true if the given unit type at given position is threatened. */
  859.  
  860. threat(side, u, x0, y0)
  861. Side *side;
  862. int u, x0, y0;
  863. {
  864.     int d, x, y, thr = 0;
  865.     Side *side2;
  866.     viewdata view;
  867.  
  868.     for_all_directions(d) {
  869.     x = wrap(x0 + dirx[d]);  y = y0 + diry[d];
  870.     view = side_view(side, x, y);
  871.     if (view != UNSEEN && view != EMPTY) {
  872.         side2 = side_n(vside(view));
  873.         if (allied_side(side, side2)) {
  874.         if (could_capture(u, vtype(view))) thr += 1000;
  875.         if (bhw[u][vtype(view)] > 0) thr += 100;
  876.         }
  877.     }
  878.     }
  879.     return thr;
  880. }
  881.  
  882. /* Returns the type of attack to plan for.  (Should balance relative */
  883. /* effectiveness of each type of attack.) */
  884.  
  885. attack_type(e)
  886. int e;
  887. {
  888.     int u;
  889.  
  890.     if (utypes[e].surrender > 0 || utypes[e].siege > 0) return BESIEGE;
  891.     for_all_unit_types(u) if (could_capture(u, e)) return CAPTARGET;
  892.     return HITTARGET;
  893. }
  894.  
  895. bool should_build_base(unit)
  896. Unit *unit;
  897. {
  898.   if (Debug) printf("Should build base survive %d base near %d wakeup %d \n",
  899.             survive_to_build_base(unit), base_nearby(unit,1),
  900.             unit->wakeup_reason);
  901.   if ((exact_survive_to_build_base(unit))
  902.       && unit->transport == NULL &&
  903.       !any_base_nearby(unit,1) && probability(90) &&
  904.       unit->wakeup_reason != WAKEENEMY) {
  905.     if (Debug) printf("going to build something\n");
  906.     set_product(unit, machine_product(unit));
  907.     set_schedule(unit);
  908.     order_sentry(unit, unit->schedule+1);
  909.     return TRUE;
  910.   }
  911.   if ((survive_to_build_base(unit) && probability(20))
  912.       && unit->transport == NULL &&
  913.       !any_base_nearby(unit,1) && probability(90) &&
  914.       !neutral_base_nearby(unit, 5) &&
  915.       unit->wakeup_reason != WAKEENEMY) {
  916.     if (Debug) printf("going to build something\n");
  917.     set_product(unit, machine_product(unit));
  918.     set_schedule(unit);
  919.     order_sentry(unit, unit->schedule+1);
  920.     return TRUE;
  921.   }       
  922.   else return FALSE;
  923. }
  924.  
  925.  
  926. get_unit_to_area(unit)
  927. Unit *unit;
  928. {
  929.   unit->goal = APPROACH;
  930.   unit->gx = area_info[unit->area].x;
  931.   unit->gy = area_info[unit->area].y;
  932.   search_for_best_move(unit);
  933. }
  934.