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 / phases.c < prev    next >
C/C++ Source or Header  |  1992-03-10  |  24KB  |  809 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 includes all turn phases except init, movement, and endgame. */
  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.  
  16. /* Should probably be in period.h */
  17.  
  18. #define will_garrison(u1, u2) (utypes[u1].guard[u2] > 0)
  19.  
  20. bool anyrevolt = FALSE;
  21. bool anysurrender = FALSE;
  22. bool anyaccident = FALSE;
  23. bool anyattrition = FALSE;
  24.  
  25. /* Spying phase reveals other sides' secrets.  This phase also automatically */
  26. /* updates allies's view of each other's units; not every turn, but fairly */
  27. /* regularly (can do briefing at any time, of course).  Spying will reveal */
  28. /* hex even if never seen before (dubious). */
  29.  
  30. spy_phase()
  31. {
  32.     Side *side, *other;
  33.  
  34.     routine("Spy Phase");
  35.     enter_procedure("spy_phase");
  36.     if (Debug) printf("Entering spy phase\n");
  37.     for_all_sides(side) {
  38.     if (probability(period.spychance)) {
  39.         other = side_n(RANDOM(numsides));
  40.         if (other != NULL && !other->lost && !allied_side(side, other)) {
  41.         if (period.spychance < 20) {
  42.             notify(side, "You found out some of the %s dispositions!!",
  43.                other->name);
  44.         }
  45.         reveal_side(other, side, period.spyquality);
  46.         }
  47.     }
  48.     for_all_sides(other) {
  49.         if (allied_side(other, side) && side != other) {
  50.         reveal_side(side, other, 100);
  51.         }
  52.     }
  53.     }
  54.     exit_procedure();
  55. }
  56.  
  57. /* The disaster phase handles revolts, surrenders, accidents, and attrition. */
  58. /* Note that accidents and attrition happen even if unit changes sides. */
  59. /* Also, revolts happen first, so something that revolts may subsequently */
  60. /* surrender to nearby unit. */
  61.  
  62. disaster_phase()
  63. {
  64.     Unit *unit;
  65.     Side *loop_side;
  66.  
  67.     routine("disaster_phase");
  68.     enter_procedure("disaster_phase");
  69.     if (Debug) printf("Entering disaster phase\n");
  70.     {
  71.     int u, t;
  72.  
  73.     for_all_unit_types(u) {
  74.         if (utypes[u].revolt > 0) anyrevolt = TRUE;
  75.         if (utypes[u].surrender > 0) anysurrender = TRUE;
  76.         for_all_terrain_types(t) {
  77.         if (utypes[u].accident[t] > 0) anyaccident = TRUE;
  78.         if (utypes[u].attrition[t] > 0) anyattrition = TRUE;
  79.         }
  80.     }
  81.     }
  82.     if (anyrevolt) {
  83.     for_all_units(loop_side, unit) if (alive(unit)) unit_revolt(unit);
  84.     }
  85.     if (anysurrender) {
  86.     for_all_units(loop_side, unit) if (alive(unit)) unit_surrender(unit);
  87.     }
  88.     if (anyaccident) {
  89.     for_all_units(loop_side, unit) if (alive(unit)) unit_accident(unit);
  90.     }
  91.     if (anyattrition) {
  92.     for_all_units(loop_side, unit) if (alive(unit)) unit_attrition(unit);
  93.     }
  94.     exit_procedure();
  95. }
  96.  
  97. /* A unit revolts by going back to its "true side" (which is usually set at */
  98. /* unit creation time).  The base revolt chance is worst case if morale is */
  99. /* variable; a unit at maximum (nonzero) morale will never revolt. */
  100.  
  101. unit_revolt(unit)
  102. Unit *unit;
  103. {
  104.     int u = unit->type, ux = unit->x, uy = unit->y, chance;
  105.     Side *oldside = unit->side;
  106.  
  107.     enter_procedure("unit_revolt");
  108.     if (utypes[unit->type].revolt > 0) {
  109.     chance = utypes[u].revolt;
  110. /*    maxmor = utypes[u].maxmorale;
  111.   if (maxmor > 0) chance = (chance * (maxmor - unit->morale)) / maxmor; */
  112.     if (unit->trueside != oldside && RANDOM(10000) < chance) {
  113.         notify(oldside, "%s revolts!", unit_handle(oldside, unit));
  114.         unit_changes_side(unit, unit->trueside, CAPTURE, DISASTER);
  115.         see_exact(oldside, ux, uy);
  116.         draw_hex(oldside, ux, uy, TRUE);
  117.         all_see_hex(ux, uy);
  118.     }
  119.     }
  120.     exit_procedure();
  121. }
  122.  
  123. /* Units may also surrender to adjacent enemy units, but only to a type */
  124. /* that is both visible and capable of capturing the unit surrendering. */
  125. /* Neutrals have to be treated differently, since they don't have a view */
  126. /* to work from.  We sort of compute the view "on the fly". */
  127.  
  128. unit_surrender(unit)
  129. Unit *unit;
  130. {
  131.     bool surrounded = TRUE;
  132.     int u = unit->type, chance, d, x, y;
  133.     viewdata view;
  134.     Unit *unit2, *eunit = NULL;
  135.     Side *us = unit->side, *es;
  136.  
  137.     enter_procedure("unit_surrender");
  138.     if (utypes[u].surrender > 0 || utypes[u].siege > 0) {
  139.     chance = 0;
  140.     for_all_directions(d) {
  141.         x = wrap(unit->x + dirx[d]);  y = limit(unit->y + diry[d]);
  142.         if (neutral(unit)) {
  143.         if (((unit2 = unit_at(x, y)) != NULL) &&
  144.             (probability(utypes[unit2->type].visibility)) &&
  145.             (could_capture(unit2->type, u))) {
  146.             chance += utypes[u].surrender;
  147.             eunit = unit2;
  148.         } else {
  149.             surrounded = FALSE;
  150.         }
  151.         } else {
  152.         view = side_view(us, x, y);
  153.         if (view == EMPTY || view == UNSEEN) {
  154.             surrounded = FALSE;
  155.         } else {
  156.             es = side_n(vside(view));
  157.             if (enemy_side(us, es) && could_capture(vtype(view), u)) {
  158.             chance += utypes[u].surrender;
  159.             if (unit_at(x, y)) eunit = unit_at(x, y);
  160.             }
  161.         }
  162.         }
  163.     }
  164.     if (surrounded && eunit) chance += utypes[u].siege;
  165.     if (RANDOM(10000) < chance) {
  166.         if (eunit) {
  167.         notify(eunit->side, "%s has surrendered to you!",
  168.                unit_handle(eunit->side, unit));
  169.         notify(us, "%s has surrendered to the %s!",
  170.                unit_handle(us, unit), plural_form(eunit->side->name));
  171.         capture_unit(eunit, unit);
  172.         }
  173.     }
  174.     }
  175.     exit_procedure();
  176. }
  177.  
  178. /* Accidents will happen!... Kill off any occupants of course. */
  179.  
  180. unit_accident(unit)
  181. Unit *unit;
  182. {
  183.     int u = unit->type;
  184.     Side *us = unit->side;
  185.  
  186.     enter_procedure("unit_accident");
  187.     if (RANDOM(10000) < utypes[u].accident[terrain_at(unit->x, unit->y)]) {
  188.     if (strlen(utypes[u].accidentmsg) > 0)
  189.         notify(us, "%s %s!", unit_handle(us, unit), utypes[u].accidentmsg);
  190.     kill_unit(unit, DISASTER);
  191.     }
  192.     exit_procedure();
  193. }
  194.  
  195. /* Attrition only takes out a few hp at a time, but can be deadly... */
  196. /* Occupants lost only if unit lost (do we care?) */
  197.  
  198. unit_attrition(unit)
  199. Unit *unit;
  200. {
  201.     int u = unit->type;
  202.     Side *us = unit->side;
  203.  
  204.     enter_procedure("unit_attrition");
  205.     if (RANDOM(10000) < utypes[u].attrition[terrain_at(unit->x, unit->y)]) {
  206.     if (unit->hp <= utypes[u].attdamage) {
  207.         notify(us, "%s dies from attrition!", unit_handle(us, unit));
  208.         kill_unit(unit, DISASTER);
  209.     } else {
  210.         if (strlen(utypes[u].attritionmsg) > 0) {
  211.         notify(us, "%s %s!",
  212.                unit_handle(us, unit), utypes[u].attritionmsg);
  213.         }
  214.         unit->hp -= utypes[u].attdamage;
  215.     }
  216.     }
  217.     exit_procedure();
  218. }
  219.  
  220. /* Repair always proceds each turn, as long as the repairing unit is not */
  221. /* crippled.  A unit can repair itself, its transport, and its occupants. */
  222.  
  223. /* Another activity of units is to build other units.  The code here has to */
  224. /* be a little tricky because players need to get opportunities to cancel */
  225. /* and to idle units, plus not get asked about units that don't usually */
  226. /* produce things. */
  227.  
  228. /* The order of repair vs building means scarce supplies used on existing */
  229. /* units first. */
  230.  
  231. build_phase()
  232. {
  233.     Unit *unit, *occ;
  234.     Side *side;
  235.  
  236.     routine("build_phase");
  237.     enter_procedure("build_phase");
  238.     if (Debug) printf("Entering build phase\n");
  239.     for_all_units(side, unit) { 
  240.       if (alive(unit) && !cripple(unit)) {
  241.     repair_unit(unit, unit);
  242.     for_all_occupants(unit, occ) repair_unit(unit, occ);
  243.     if (unit->transport != NULL) repair_unit(unit, unit->transport);
  244.     work_on_new_unit(unit);
  245.       }
  246.     }
  247.     exit_procedure();
  248. }
  249.  
  250. /* One arbitrary unit repairs another only if actually needed.  Rate is */
  251. /* always less than 1 hp/turn; this is a practical limit on max hp values */
  252. /* if reasonably rapid repair is desired.  If unit being repaired was badly */
  253. /* damaged (crippled), then we'll use up same resources as needed for */
  254. /* construction, and if a resource type is missing, then repairs will not */
  255. /* proced at all. */
  256.  
  257. repair_unit(unit, unit2)
  258.      Unit *unit, *unit2;
  259. {
  260.   int u = unit->type, u2 = unit2->type, r;
  261.   
  262.   enter_procedure("repair_unit");
  263.   if ((unit2->hp < utypes[u2].hp) && could_repair(u, u2)) {
  264.     int rpchance = utypes[u].repair[u2], count, hprp = 0;
  265.  
  266.     for (count = 0; count < period.repairscale; count++) {
  267.       if (rpchance == 1 || RANDOM(rpchance) == 0) {
  268.     if (cripple(unit2)) {
  269.       for_all_resource_types(r) {
  270.         if (unit->supply[r] < utypes[u2].tomake[r]) {
  271.           if (Debug)
  272.         printf("Unit not repaired for lack of supplies");
  273.           break;
  274.         }
  275.       }
  276.       /* Will underestimate because of rounding down. */
  277.       for_all_resource_types(r) {
  278.         unit->supply[r] -= utypes[u2].tomake[r] / utypes[u2].hp;
  279.       }
  280.     }
  281.     hprp++;
  282.       }
  283.     }
  284.     if (Debug)
  285.       printf("unit %d repaired %d. chance was 1 in %d. %d/%d\n",
  286.          u, u2, utypes[u].repair[u2], hprp, period.repairscale);
  287.     unit2->hp += hprp;
  288.     if (unit2->hp > utypes[u2].hp)
  289.       unit2->hp = utypes[u2].hp;
  290.   }
  291.   exit_procedure();
  292. }
  293.  
  294. /* Machine players need opportunities to change their production. */
  295. /* Neutrals never produce (what could they do with the results?). */
  296. /* Construction may be constrained by lack of resources, so don't count */
  297. /* down on schedule or use up building materials unless we actually have */
  298. /* enough. */
  299.  
  300. work_on_new_unit(unit)
  301. Unit *unit;
  302. {
  303.     int u = unit->type, r, mk, rmk, use;
  304.  
  305.     enter_procedure("work_on_new_unit");
  306.     if (!neutral(unit)) {
  307.     if (producing(unit)) {
  308.         mk = utypes[u].make[unit->product];
  309.         for_all_resource_types(r) {
  310.         if ((rmk = utypes[unit->product].tomake[r]) > 0) {
  311.             use = (rmk / mk) + (unit->schedule <= (rmk % mk) ? 1 : 0);
  312.             if (unit->supply[r] < use) return;
  313.             unit->supply[r] -= use;
  314.         }
  315.         }
  316.         unit->schedule--;
  317.         if (unit->schedule <= 0) {
  318.             int  product = unit->product;
  319.  
  320.         /* this monkey business is necessary to prevent an
  321.            occupying builder from giving a warning message */
  322.         if (!utypes[u].maker)
  323.           set_product(unit, NOTHING);
  324.  
  325.         if (complete_new_unit(unit, product)) {
  326.             if (utypes[u].maker) {
  327.                 if (unit->next_product != unit->product)
  328.               set_product(unit, unit->next_product);
  329.             set_schedule(unit);
  330.             }
  331.         } else {
  332.             if (!utypes[u].maker) /* oops, we zeroed the product */
  333.                 set_product(unit, product);
  334.             unit->schedule++;
  335.         }
  336.         }
  337.     } else {
  338.         if (unit->schedule > 0) unit->schedule--;
  339.     }
  340.     }
  341.     exit_procedure();
  342. }
  343.  
  344. /* When one unit produces another, it may be that one can occupy the other, */
  345. /* in either direction.  So we have to make sure that both ways work. */
  346. /* Also the builder may become the garrison, so we have to get it out of */
  347. /* the way before deciding about fiddling around. */
  348. /* Morale of new unit is slightly more than morale of building unit. */
  349. /* Returns success of the whole process. */
  350.  
  351. complete_new_unit(unit, type)
  352. Unit *unit;
  353. int type;
  354. {
  355.     bool success = FALSE;
  356.     int ux = unit->x, uy = unit->y, u = unit->type;
  357.     Unit *mainunit, *newunit;
  358.     Side *us = unit->side;
  359.  
  360.     enter_procedure("complete_new_unit");
  361.     if (will_garrison(unit->type, type)) leave_hex(unit);
  362.     if ((newunit = create_unit(type, (char *) NULL)) != NULL) {
  363.     mainunit = unit_at(ux, uy);
  364.     if (mainunit == NULL) {
  365.         if (could_occupy(type, terrain_at(ux, uy))) {
  366.         assign_unit_to_side(newunit, us);
  367.         occupy_hex(newunit, ux, uy);
  368.         success = TRUE;
  369.         } else {
  370.         notify(us, "%s can't go here!", unit_handle(us, newunit));
  371.         kill_unit(newunit, DISASTER);
  372.         }
  373.     } else if (could_carry(mainunit->type, type)) {
  374.         if (can_carry(mainunit, newunit)) {
  375.         assign_unit_to_side(newunit, us);
  376.         occupy_hex(newunit, ux, uy);
  377.         success = TRUE;
  378.         } else {
  379.         notify(us, "%s will delay completion of %s until it has room.",
  380.                unit_handle(us, unit), utypes[type].name);
  381.         kill_unit(newunit, DISASTER);
  382.         }
  383.     } else if (could_carry(type, mainunit->type)) {
  384.         if (could_occupy(type, terrain_at(ux, uy))) {
  385.         assign_unit_to_side(newunit, us);
  386.         /* Redundant code.  Eliminates messages complaining */
  387.         /* about units building as occupants. */
  388.         if (!utypes[u].maker) {
  389.           set_product(mainunit, NOTHING);
  390.         } else {
  391.           set_schedule(mainunit);
  392.         }
  393.         occupy_hex(newunit, ux, uy);
  394.         success = TRUE;
  395.         } else {
  396.         notify(us, "%s can't go here!", unit_handle(us, newunit));
  397.         kill_unit(newunit, DISASTER);
  398.         }
  399.     } else {
  400.         notify(us, "Idiots! - %s can't build a %s while in a %s!",
  401.            unit_handle(us, unit),
  402.            utypes[type].name, utypes[mainunit->type].name);
  403.         kill_unit(newunit, DISASTER);
  404.     }
  405.     }
  406.     if (will_garrison(unit->type, type)) {
  407.       unit->prevx = -1;
  408.       occupy_hex(unit, ux, uy);
  409.     }
  410.     if (success) {
  411.     if (utypes[type].named) newunit->name = make_unit_name(newunit);
  412. /*    newunit->morale = min(newunit->morale, unit->morale + 1); */
  413.     unit->built++;
  414.     (us->balance[type][PRODUCED])++;
  415.     (us->units[type])++;
  416.     if (will_garrison(unit->type, type)) {
  417.         Unit    *occ;
  418.         extern char killbuf[]; /* from attack.c */
  419.         extern int occdeath[]; /* from unit.c */
  420.  
  421.         /* Put the new unit exactly in place of its garrison. */
  422.         if (newunit->transport == unit) {
  423.         /* Get the garrisoning unit out of the way. */
  424.         leave_hex(unit);
  425.         if (unit->transport == NULL) {
  426.             occupy_hex(newunit, ux, uy);
  427.         } else {
  428.             occupy_unit(newunit, unit->transport);
  429.         }
  430.         }
  431.  
  432.         do { /* this screwy loop handles the fact that the linked
  433.             list is being changed while we're scanning it.
  434.             The real solution would be to write a special loop,
  435.             but I'm lazy */
  436.             for_all_occupants(unit, occ) {
  437.             if (can_carry(newunit, occ)) {
  438.                 leave_hex(occ);
  439.                 occupy_unit(occ, newunit);
  440.             break;
  441.             }
  442.         }
  443.         } while (occ!=NULL && can_carry(newunit, occ));
  444.  
  445.         /* Now we can kill the garrison and its other occupants. */
  446.         /* (or should occupants be put into the new unit?) */
  447.         kill_unit(unit, GARRISON);
  448.         summarize_units(killbuf, occdeath);
  449.         if (*killbuf)
  450.           notify(unit->side, "%s destroyed during garrison operation",
  451.              killbuf);
  452.     }
  453.     update_state(us, type);
  454.     if (!humanside(unit->side) && change_machine_product(unit)) 
  455.       request_new_product(unit);
  456.     if (Debug)
  457.       printf("%s is completed\n", unit_handle((Side *)NULL, newunit));
  458.     }
  459.     exit_procedure();
  460.     return success;
  461. }
  462.  
  463. /* The main routine does production, distribution, and discarding in order. */
  464.  
  465. supply_phase()
  466. {
  467.     int u, r, t, amt, dist, x, y, x1, y1, x2, y2;
  468.     Unit *unit, *ounit;
  469.     Side *loop_side;
  470.  
  471.     routine("supply_phase");
  472.     enter_procedure("supply_phase");
  473.     if (Debug) printf("Entering supply phase\n");
  474.     /* Make new resources but don't clip to storage capacity yet */
  475.     for_all_units(loop_side, unit) {
  476.     u = unit->type;
  477.     for_all_resource_types(r) {
  478.         t = terrain_at(unit->x, unit->y);
  479.         amt = (utypes[u].produce[r] * utypes[u].productivity[t]) / 100 +
  480.           (probability((utypes[u].produce[r] * 
  481.                 utypes[u].productivity[t]) % 100) ? 1 : 0);
  482.         if (cripple(unit))
  483.         amt = (amt * unit->hp) / (utypes[u].crippled + 1);
  484.         unit->supply[r] += amt;
  485.     }
  486.     }
  487.     /* Move stuff around - hopefully will get rid of any excess */
  488.     for_all_units(loop_side, unit)
  489.       if (!neutral(unit)) {
  490.         u = unit->type;
  491.     for_all_resource_types(r) {
  492.             dist = utypes[u].outlength[r];
  493.         y1 = unit->y - dist;
  494.         y2 = unit->y + dist;
  495.         for (y = y1; y <= y2; ++y) {
  496.         if (between(0, y, world.height-1)) {
  497.             x1 = unit->x - (y < unit->y ? (y - y1) : dist);
  498.             x2 = unit->x + (y > unit->y ? (y2 - y) : dist);
  499.             for (x = x1; x <= x2; ++x) {
  500.             ounit = unit_at(wrap(x), y);
  501.             if (ounit != NULL && alive(ounit) &&
  502.                 ounit->side == unit->side) {
  503.               try_transfer(unit, ounit, r);
  504.             }
  505.             }
  506.         }
  507.         }
  508.     }
  509.     }
  510.     /* Throw away any excess */
  511.     for_all_units(loop_side, unit) {
  512.     u = unit->type;
  513.     for_all_resource_types(r) {
  514.         unit->supply[r] = min(unit->supply[r], utypes[u].storage[r]);
  515.     }
  516.     }
  517.     exit_procedure();
  518. }
  519.  
  520. /* Give away supplies, but save enough to stay alive for a couple turns. */
  521. try_transfer(from, to, r)
  522. Unit *from, *to;
  523. int r;
  524. {
  525.   int save_amount;  /* Hang on to this much at least. */
  526.   int u = from->type;
  527.   
  528.   save_amount = max(utypes[u].consume[r] * 3,
  529.             2 * utypes[u].speed * utypes[u].tomove[r]);
  530.   save_amount = min(save_amount, from->supply[r]);
  531.   from->supply[r] -= save_amount;
  532.   try_transfer_auxR(from, to, r);
  533.   from->supply[r] += save_amount;
  534. }
  535.  
  536. /* The middle subphase of supply uses this routine to move supplies around */
  537. /* between units far apart or on the same hex. Try to do reasonable */
  538. /* things with the resources.  Producers are much more willing to */
  539. /* give away supplies that consumers. */
  540.  
  541. #if 1
  542.  
  543. try_transfer_auxR(from, to, r)
  544. Unit *from, *to;
  545. int r;
  546. {
  547.   Unit    *occ;
  548.  
  549.   try_transfer_aux(from, to, r);
  550.  
  551.   for_all_occupants(to, occ)
  552.     try_transfer_auxR(from, occ, r);
  553. }
  554.  
  555. /* the Carrier factor */
  556. #define CFACTOR 4
  557.  
  558. try_transfer_aux(from, to, r)
  559. Unit *from, *to;
  560. int r;
  561. {
  562.   struct utype    *ftp = &utypes[from->type], *ttp = &utypes[to->type];
  563.   int    fprate, tprate; /* production rate */
  564.   int    xfr;
  565.  
  566.   if (from == to || to->supply[r] >= ttp->storage[r] ||
  567.       utypes[to->type].inlength[r] < distance(from->x, from->y, to->x, to->y))
  568.     return;
  569.  
  570.   fprate = ftp->produce[r]*ftp->productivity[terrain_at(from->x, from->y)]/100
  571.     - ftp->consume[r];
  572.   tprate = ttp->produce[r]*ttp->productivity[terrain_at(to->x, to->y)]/100
  573.     - ttp->consume[r];
  574.  
  575.   if (fprate>0) {
  576.     if (tprate>0) {
  577.       /* both are producers */
  578.       float    ttf; /* time to full */
  579.  
  580.       if (ttp->storage[r]*CFACTOR < from->supply[r]) { /* a carrier */
  581.     xfr = ttp->storage[r] - to->supply[r];
  582.     if (can_satisfy_need(from, r, xfr)) {
  583.       transfer_supply(from, to, r, xfr);
  584.       return;
  585.     }
  586.       }
  587.  
  588.       ttf = ( (ftp->storage[r] + ttp->storage[r]) -
  589.           (from->supply[r] + to->supply[r])) / (fprate + tprate);
  590.       xfr = ttp->storage[r] - tprate*ttf - to->supply[r];
  591.       if (xfr<=0)
  592.     return;
  593.       if (can_satisfy_need(from, r, xfr)) {
  594.     transfer_supply(from, to, r, xfr);
  595.     return;
  596.       }
  597.  
  598.       xfr = from->supply[r] - ftp->storage[r]/2;
  599.       if (xfr>0 && can_satisfy_need(from, r, xfr)) {
  600.     transfer_supply(from, to, r, xfr);
  601.     return;
  602.       }
  603.  
  604.       xfr = from->supply[r] - ftp->storage[r];
  605.       if (xfr > 0) {
  606.     transfer_supply(from, to, r, xfr);
  607.     return;
  608.       }
  609.     } else {
  610.       /* source is a producer, dest is a consumer */
  611.       xfr = ttp->storage[r] - to->supply[r];
  612.       if ((from->supply[r]-xfr)*2 > ftp->storage[r] &&
  613.       can_satisfy_need(from, r, xfr)) {
  614.     transfer_supply(from, to, r, xfr);
  615.     return;
  616.       }
  617.  
  618.       xfr = from->supply[r]- ftp->storage[r]/2;
  619.       if (xfr>0 &&
  620.       can_satisfy_need(from, r, xfr)) {
  621.     transfer_supply(from, to, r, xfr);
  622.     return;
  623.       }
  624.  
  625.       xfr = (ttp->speed * ttp->tomove[r] + ttp->consume[r]) * 3 -
  626.     to->supply[r];
  627.       if (xfr>0 && can_satisfy_need(from, r, xfr)) {
  628.     transfer_supply(from, to, r, xfr);
  629.     return;
  630.       }
  631.     }
  632.   } else if (fprate==0) {
  633.     /* source is a transmitter */
  634.     if (tprate>0) /* dest is a producer */
  635.       return; /* sod off */
  636.     else if (tprate<0) { /* dest is a consumer */
  637.       xfr = min(from->supply[r], ttp->storage[r] - to->supply[r]);
  638.       if (xfr>0)
  639.     transfer_supply(from, to, r, xfr); /* fill up the dest */
  640.     } else { /* dest is transmitter too */
  641.       if (ttp->storage[r]*CFACTOR < ftp->storage[r]) {
  642.     /* source is a carrier, fill up the smaller one */
  643.     xfr = min(from->supply[r], ttp->storage[r] - to->supply[r]);
  644.     if (xfr>0)
  645.       transfer_supply(from, to, r, xfr); /* fill up the dest */
  646.       } /* else don't transfer */
  647.     }
  648.   } else {
  649.     /* source is a consumer */
  650.     if (tprate>0) /* dest is a producer */
  651.       return; /* sod off */
  652.     else if (tprate<0) { /* dest is a consumer */
  653.       if (ttp->storage[r]*CFACTOR < ftp->storage[r]) {
  654.     /* source is a carrier, fill up the smaller one */
  655.     xfr = min(from->supply[r], ttp->storage[r] - to->supply[r]);
  656.     if (xfr>0)
  657.       transfer_supply(from, to, r, xfr); /* fill up the dest */
  658.       } /* else don't transfer */
  659.     } /* else dest is a transmitter, sod off */
  660.   }
  661.   return;
  662. }
  663.  
  664. #else
  665.  
  666. try_transfer_aux(from, to, r)
  667. Unit *from, *to;
  668. int r;
  669. {
  670.     int nd, ut = from->type, rate;
  671.     Unit *occ;
  672.  
  673.     if (from != to && utypes[to->type].inlength[r] >=
  674.                       distance(from->x, from->y, to->x, to->y)) {
  675.     if ((nd = utypes[to->type].storage[r] - to->supply[r]) > 0) {
  676.       if ((utypes[ut].produce[r] - utypes[ut].consume[r] > 0) ||
  677.           survival_time(to) < 3 ||
  678.           (utypes[ut].storage[r] * 4 >=
  679.            utypes[to->type].storage[r])) {
  680.         if (can_satisfy_need(from, r, nd)) {
  681.           transfer_supply(from, to, r, nd);
  682.         } else if (can_satisfy_need(from, r, max(1, nd/2))) {
  683.           transfer_supply(from, to, r, max(1, nd/2));
  684.         } else if (from->supply[r] > utypes[ut].storage[r]) {
  685.           transfer_supply(from, to, r,
  686.                   (from->supply[r] - utypes[ut].storage[r]));
  687.         }
  688.       } else if ((from->supply[r] /
  689.               (((rate = utypes[ut].speed * utypes[ut].tomove[r] * 3)
  690.             > 0) ? rate : 1)) > 
  691.              (to->supply[r] /
  692.               (((rate = utypes[to->type].speed *
  693.              utypes[to->type].tomove[r] * 3) > 0) ? rate : 1))) {
  694.         transfer_supply(from, to, r, min(nd, (8 + from->supply[r]) / 9));
  695.       } 
  696.     }
  697.  
  698.       
  699.     }
  700.     for_all_occupants(to, occ)
  701.       try_transfer_aux(from, occ, r);
  702. }
  703.  
  704. #endif
  705.  
  706. /* This estimates what can be spared.  Note that total transfer of requested */
  707. /* amount is not a good idea, since the supplies might be essential to the */
  708. /* unit that has them first.  If we're more than half full, or the request */
  709. /* is less than 1/5 of our supply, then we can spare it. */
  710.  
  711. can_satisfy_need(unit, r, need)
  712. Unit *unit;
  713. int r, need;
  714. {
  715.     return ((((2 * unit->supply[r]) > (utypes[unit->type].storage[r])) &&
  716.          (((unit->supply[r] * 4) / 5) > need)) ||
  717.         (need < (utypes[unit->type].storage[r] / 5)));
  718. }
  719.  
  720. /* Move supply from one unit to another.  Don't move more than is possible; */
  721. /* check both from and to amounts and capacities. */
  722.  
  723. transfer_supply(from, to, r, amount)
  724. Unit *from, *to;
  725. int r, amount;
  726. {
  727.     amount = min(amount, from->supply[r]);
  728.     amount = min(amount, utypes[to->type].storage[r] - to->supply[r]);
  729.     from->supply[r] -= amount;
  730.     to->supply[r] += amount;
  731.     if (Debug) {
  732.       printf("%s receives %d %s ", unit_handle((Side *) NULL, to),
  733.          amount, rtypes[r].name);
  734.       printf("from %s\n", unit_handle((Side *) NULL, from));
  735.     }
  736.     return amount;
  737. }
  738.  
  739. /* Handle constant consumption, which is a post process to movement. */
  740. /* Don't care about current side in this phase.  This is also a handy */
  741. /* place to count up all of a side's resources, for use by win/lose tests. */
  742.  
  743. consumption_phase()
  744. {
  745.     int r;
  746.     Unit *unit;
  747.     Side *side;
  748.  
  749.     routine("consumption_phase");
  750.     enter_procedure("consumption_phase");
  751.     if (Debug) printf("Entering consumption phase\n");
  752.     for_all_sides(side) {
  753.     for_all_resource_types(r) {
  754.         side->resources[r] = 0;
  755.     }
  756.     }
  757.     for_all_units(side, unit)
  758.       if (alive(unit)) unit_consumes(unit);
  759.     exit_procedure();
  760. }
  761.  
  762. /* Consume the constant overhead part of supply consumption. */
  763. /* Usage by movement is subtracted from overhead first. */
  764. /* Finally, credit side with the unit's remaining supplies. */
  765.  
  766. unit_consumes(unit)
  767. Unit *unit;
  768. {
  769.     int u = unit->type, r, usedup;
  770.     
  771.     for_all_resource_types(r) {
  772.     if (utypes[u].consume[r] > 0  && (unit->transport == NULL ||
  773.                       utypes[u].consume_as_occupant)) {
  774.         usedup = unit->actualmoves * utypes[u].tomove[r];
  775.         if (usedup < utypes[u].consume[r])
  776.         unit->supply[r] -= (utypes[u].consume[r] - usedup);
  777.         if (unit->supply[r] <= 0 && !in_supply(unit)) {
  778.         exhaust_supply(unit);
  779.         return;
  780.         }
  781.     }
  782.     if (!neutral(unit)) unit->side->resources[r] += unit->supply[r];
  783.     }
  784. }
  785.  
  786. /* What happens to a unit that runs out of a supply.  If it can survive */
  787. /* on no supplies, then there may be a few turns of grace, depending on */
  788. /* how the dice roll... */
  789.  
  790. exhaust_supply(unit)
  791. Unit *unit;
  792. {
  793.     if (probability(100 - utypes[unit->type].survival)) {
  794.     notify(unit->side, "%s %s!",
  795.            unit_handle(unit->side, unit), utypes[unit->type].starvemsg);
  796.     kill_unit(unit, STARVATION);
  797.     }
  798. }
  799.  
  800. /* Check if the unit has ready access to a source of supplies. */
  801.  
  802. in_supply(unit)
  803. Unit *unit;
  804. {
  805.     if (unit->transport != NULL) return TRUE;
  806.     /* needs to be more sophisticated and account for supply lines */
  807.     return FALSE;
  808. }
  809.