home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Xconq 7.1.0 / src / xconq-7.1.0 / kernel / run.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  86.4 KB  |  3,452 lines  |  [TEXT/R*ch]

  1. /* The main simulation-running code in Xconq.
  2.    Copyright (C) 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996
  3.    Stanley T. Shebs.
  4.  
  5. Xconq is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.  See the file COPYING.  */
  9.  
  10. /* This is the main simulation-running code. */
  11.  
  12. #include "conq.h"
  13. extern void all_see_cell_weather PARAMS ((int x, int y));
  14. extern int stop_apply;
  15. extern int execute_standing_order PARAMS ((Unit *unit, int addtask));
  16. extern void add_to_unit_hp PARAMS ((Unit *unit, int hp));
  17. extern void try_sharing PARAMS ((Unit *from, Unit *to, int m));
  18.  
  19. static void run_turn_start PARAMS ((void));
  20. static void run_restored_turn_start PARAMS ((void));
  21. static void add_new_sides_to_game PARAMS ((void));
  22. static void init_movement PARAMS ((void));
  23. static void init_actionvectors PARAMS ((void));
  24. static void run_tech_leakage PARAMS ((void));
  25. static void cache_init_tech_levels PARAMS ((void));
  26. static void run_tooling_attrition PARAMS ((void));
  27. static void reset_all_reserves PARAMS ((void));
  28. static void compute_moves PARAMS ((void));
  29. static void compose_actionvectors PARAMS ((void));
  30. static int move_some_units PARAMS ((int lim));
  31. static int side_move_some_units PARAMS ((Side *side, int lim));
  32. static int unit_still_acting PARAMS ((Unit *unit, int checkwaiting));
  33. static int move_one_unit_multiple PARAMS ((Unit *unit, int lim));
  34. static void finish_movement PARAMS ((void));
  35. static void test_agreements PARAMS ((void));
  36. static void compute_sun PARAMS ((void));
  37. static void run_sun PARAMS ((void));
  38. static void compute_season PARAMS ((void));
  39. static void run_environment PARAMS ((void));
  40. static void mix_winds PARAMS ((void));
  41. static void run_spies PARAMS ((void));
  42. static void run_random_events PARAMS ((void));
  43. static int init_accidents PARAMS ((void));
  44. static void run_accidents PARAMS ((void));
  45. static int init_attrition PARAMS ((void));
  46. static void run_attrition PARAMS ((void));
  47. static int init_revolts PARAMS ((void));
  48. static void run_revolts PARAMS ((void));
  49. static void unit_revolt PARAMS ((Unit *unit));
  50. static int init_surrenders PARAMS ((void));
  51. static void run_surrenders PARAMS ((void));
  52. static void unit_surrender PARAMS ((Unit *unit));
  53. static void maybe_surrender_to PARAMS ((Unit *unit, Unit *unit2));
  54. static int excess_left PARAMS ((int x, int y));
  55. static void try_transfer_to_cell PARAMS ((int x, int y));
  56. static int sharable_left PARAMS ((int x, int y));
  57. static void try_sharing_with_cell PARAMS ((int x, int y));
  58. static void run_economy PARAMS ((void));
  59. static int base_production PARAMS ((Unit *unit, int m));
  60. static void try_transfer PARAMS ((Unit *from, Unit *to, int r));
  61. static void try_transfer_aux PARAMS ((Unit *from, Unit *to, int r));
  62. static int can_satisfy_need PARAMS ((Unit *unit, int r, int need));
  63. static void run_turn_end PARAMS ((void));
  64. static void run_people_consumption PARAMS ((void));
  65. static void run_cell_consumption PARAMS ((void));
  66. static void run_unit_base_consumption PARAMS ((void));
  67. static void unit_consumes PARAMS ((Unit *unit));
  68. static int in_supply PARAMS ((Unit *unit, int m));
  69. static void run_self_builds PARAMS ((void));
  70. static void run_environment_effects PARAMS ((void));
  71. static void damage_unit_with_temperature PARAMS ((Unit *unit, int n));
  72. static void run_people_side_changes PARAMS ((void));
  73. static void update_cell_display_all_sides PARAMS ((int x, int y, int rightnow));
  74. static void run_appearances PARAMS ((void));
  75. static void run_disappearances PARAMS ((void));
  76. static void run_hp_recovery PARAMS ((void));
  77. static void run_auto_repair PARAMS ((void));
  78. static void auto_repair_from_here PARAMS ((int x, int y));
  79. static void auto_repair_unit PARAMS ((Unit *unit, Unit *unit2));
  80. static int season_effect PARAMS ((int u));
  81. static void run_detonation_accidents PARAMS ((void));
  82. static void run_people_limits PARAMS ((void));
  83. static void maybe_detonate_accidently PARAMS ((Unit *unit));
  84. static void spy_on_location PARAMS ((int x, int y));
  85.  
  86. /* The number of the current turn within a year. */
  87.  
  88. int curyearpart = -1;
  89.  
  90. /* The season name for the current turn. */
  91.  
  92. char *curseasonname = NULL;
  93.  
  94. /* Priority of sides that are now moving. */
  95.  
  96. int curpriority;
  97.  
  98. /* Priority of units that are now moving. */
  99.  
  100. int curunitpriority;
  101.  
  102. /* The table of all types of random events. */
  103.  
  104. struct randomeventtype {
  105.     int key;
  106.     int (*initfn) PARAMS ((void));
  107.     void (*fn) PARAMS ((void));
  108. } randomeventmethods[] = {
  109.     { K_ACCIDENTS_IN_TERRAIN, init_accidents, run_accidents },
  110.     { K_ATTRITION_IN_TERRAIN, init_attrition, run_attrition },
  111.     { K_UNITS_REVOLT, init_revolts, run_revolts },
  112.     { K_UNITS_SURRENDER, init_surrenders, run_surrenders },
  113.     { 0, NULL, NULL }
  114. };
  115.  
  116. int numrandomevents;
  117.  
  118. int randomeventindices[10]; /* this must be >= number of diff methods */
  119.  
  120. int maintimeout = -1;
  121.  
  122. int paused = FALSE;
  123.  
  124. /* State variables. */
  125. /* (I don't think all of these are strictly necessary) */
  126.  
  127. /* This becomes TRUE the first time run_game is executed. */
  128.  
  129. int gameinited = FALSE;
  130.  
  131. /* This is true only before the game actually starts. */
  132.  
  133. int beforestart = TRUE;
  134.  
  135. /* This is true only at the beginning of a turn. */
  136.  
  137. int at_turn_start = FALSE;
  138.  
  139. /* This is true after the game is over. */
  140.  
  141. int endofgame = FALSE;
  142.  
  143. /* How often to do saves while playing. */
  144.  
  145. int checkpointinterval = 0;
  146.  
  147. /* This is set FALSE whenever the game state changes, and TRUE whenever
  148.    the game has been saved. */
  149.  
  150. int gamestatesafe = TRUE;
  151.  
  152. /* This is TRUE after the designer has been mucking around, or if
  153.    networked versions are found to be inconsistent. */
  154.  
  155. int compromised = FALSE;
  156.  
  157. /* The number of new sides that have been requested to be added. */
  158.  
  159. int new_sides_requested;
  160.  
  161. char **players_requested;
  162.  
  163. /* True whenever the game has both day and night. */
  164.  
  165. int daynight = FALSE;
  166.  
  167. /* The location of the sun, as a position relative to the area.  The
  168.    actual values may be far outside the area. */
  169.  
  170. int sunx, suny;
  171.  
  172. /* The sun's previous location. */
  173.  
  174. int lastsunx = -1, lastsuny = -1;
  175.  
  176. /* The time at which the game actually starts. */
  177.  
  178. time_t game_start_in_real_time;
  179.  
  180. /* The point in the turn at which players can actually do things. */
  181.  
  182. time_t turn_play_start_in_real_time;
  183.  
  184. int planexecs;
  185.  
  186. int taskexecs;
  187.  
  188. /* The rate at which AIs play when acting more slowly (so as
  189.    not to overwhelm human players), expressed as plan executions
  190.    per minute.  0 means "as fast as possible". */
  191.  
  192. int slow_play_rate = 240;
  193.  
  194. /* The rate at which AIs play when acting more quickly (such
  195.    as when all humans are done with their moves). */
  196.  
  197. int fast_play_rate = 0;
  198.  
  199. /* The current rate at which AIs are playing. */
  200.  
  201. int current_play_rate;
  202.  
  203. /* Flags indicating whether various sets of calculations need to be done. */
  204.  
  205. int any_tooling_attrition = -1;
  206.  
  207. int any_self_builds = -1;
  208.  
  209. int any_appearances = -1;
  210.  
  211. int any_people_side_changes = -1;
  212.  
  213. int *any_people_surrenders = NULL;
  214.  
  215. int any_hp_recovery = -1;
  216.  
  217. int any_auto_repair = -1;
  218.  
  219. int any_tech_leakage = -1;
  220.  
  221. int any_detonation_accidents = -1;
  222.  
  223. int any_unit_production = -1;
  224.  
  225. int any_terrain_production = -1;
  226.  
  227. int any_people_production = -1;
  228.  
  229. int any_people_consumption = -1;
  230.  
  231. int any_cell_consumption = -1;
  232.  
  233. int any_unit_base_consumption = -1;
  234.  
  235. int any_people_max = -1;
  236.  
  237. int any_spying = -1;
  238.  
  239. int any_disappearances = -1;
  240.  
  241. static short *will_be_auto_repaired;
  242.  
  243. static short *auto_repair_range_max;
  244.  
  245. /* This function does a (small, usually) amount of simulation, then returns.
  246.    It can be run multiple times at any time, will not go "too far".
  247.    It returns the number of actions that were actually performed. Other
  248.    important state changes (such a side finishing its turn or the turn
  249.    ending) are also counted as actions, so that this function's callers
  250.    will know that something was done. */
  251.  
  252. int
  253. run_game(maxactions)
  254. int maxactions;
  255. {
  256.     int numacted, runtime;
  257.     time_t rungamestart, rungameend;
  258.     Side *side;
  259.  
  260.     gameinited = TRUE;
  261.     time(&rungamestart);
  262.     numacted = 0;
  263.     if (beforestart) {
  264.     /* If we haven't started yet, see if it's time. */
  265.     test_for_game_start();
  266.     Dprintf("run_game: tested for game start.\n");
  267.     } else if (endofgame) {
  268.     /* Nothing to do except wait for users to do exit commands. */
  269.         Dprintf("run_game: at end of game.\n");
  270.     } else if (paused) {
  271.     /* Don't do anything if we're paused. */
  272.         Dprintf("run_game: paused.\n");
  273.     } else {
  274.     if (at_turn_start) {
  275.         if (midturnrestore)
  276.           run_restored_turn_start();
  277.         else
  278.           run_turn_start();
  279.         check_all_units();
  280.         compose_actionvectors();
  281.         init_movement();
  282.         update_all_progress_displays("", -1);
  283.         /* Game might have been ended by new turn init. */
  284.         if (endofgame) {
  285.             Dprintf("run_game: game ended by new turn init.\n");
  286.             return 0;
  287.         }
  288.         /* (should adjust this by recorded elapsed turn time) */
  289.         time(&turn_play_start_in_real_time);
  290.         at_turn_start = FALSE;
  291.         /* Count turn start as an action. */
  292.         ++numacted;
  293.     }
  294.     for_all_sides(side) {
  295.         /* If this is running in realtime, update all clock displays. */
  296.         if (side->ingame && side_has_display(side) && realtime_game()) {
  297.         update_clock_display(side, TRUE);
  298.         }
  299.         /* Non-participating sides are automatically "finished". */
  300.         if (side->ingame
  301.             && !side->finishedturn
  302.         && !side_has_ai(side)
  303.         && !side_has_display(side)) {
  304.         Dprintf("run_game: %s finished - no AI or display.\n",
  305.             side_desig(side));
  306.         finish_turn(side);
  307.         /* Count this as an action. */
  308.         ++numacted;
  309.         }
  310.     }
  311.     /* If all sides are done acting, end the turn.  This won't be true
  312.        right at the start of a turn. */
  313.     if (all_sides_finished() || exceeded_rt_per_turn()) {
  314.         run_turn_end();
  315.         Dprintf("run_game: at turn end.\n");
  316.         at_turn_start = TRUE;
  317.         /* Count this as an action. */
  318.         ++numacted;
  319.     } else {
  320.         /* Move some units around. */
  321.         numacted += move_some_units(maxactions);
  322.         /* Possibly finish some sides' turns. */
  323.         for_all_sides(side) {
  324.         if (!side->finishedturn) {
  325.             if (side_has_ai(side)) {
  326.             ai_analyze_after_moves(side, numacted);
  327.             }
  328.             /* Display and/or AI might have vanished? */
  329.             if (!side_has_ai(side) && !side_has_display(side)) {
  330.                 Dprintf("run_game: %s finished - AI and/or display gone.\n",
  331.                 side_desig(side));
  332.             finish_turn(side);
  333.             /* Count this as an action. */
  334.             ++numacted;
  335.             }
  336.             /* See if any sides auto-finish. */
  337.             if (!units_still_acting(side)
  338.             && side->autofinish
  339. #ifdef DESIGNERS
  340.             && !side->designer
  341. #endif /* DESIGNERS */
  342.             ) {
  343.                 Dprintf("run_game: %s auto-finishes.\n", side_desig(side));
  344.             finish_turn(side);
  345.             /* Count this as an action. */
  346.             ++numacted;
  347.             }
  348.         }
  349.         }
  350.         if (Debug) {
  351.             Dprintf("run_game: %d/%d actions.", numacted, maxactions);
  352.         if (planexecs > 0)
  353.           Dprintf(" (%d plan execs)", planexecs);
  354.         if (taskexecs > 0)
  355.           Dprintf(" (%d task execs)", taskexecs);
  356.         /* (also number of units considered?) */
  357.             Dprintf("\n");
  358.         }
  359.     }
  360.     check_realtime();
  361.     test_for_game_end();
  362.     }
  363.     time(&rungameend);
  364.     runtime = idifftime(rungameend, rungamestart);
  365.     if (runtime > 0)
  366.       Dprintf("run_game: took %d seconds\n", runtime);
  367.     return numacted;
  368. }
  369.  
  370. /* See if game is ready to get underway for real.  Note that displays will
  371.    work before the game has started, but game time doesn't move. */
  372.  
  373. void
  374. test_for_game_start()
  375. {
  376.     int anydisplays = FALSE;
  377.     Side *side;
  378.  
  379.     /* We must have at least one unit on a side that is being displayed
  380.        before the game can start for real. */
  381.     for_all_sides(side) {
  382.     if (side_has_display(side)) {
  383.         anydisplays = TRUE;
  384.     }
  385.     if (side_has_units(side) && side_has_display(side)) {
  386.         /* Now we're really ready to roll. */
  387.         beforestart = FALSE;
  388.         at_turn_start = TRUE;
  389.         if (midturnrestore) {
  390.         record_event(H_GAME_RESTARTED, ALLSIDES);
  391.         } else {
  392.         record_event(H_GAME_STARTED, ALLSIDES);
  393.         set_g_elapsed_time(0);
  394.         }
  395.         /* Record the game as starting NOW in real time. */
  396.         time(&game_start_in_real_time);
  397.         /* Adjust by any recorded elapsed time. */
  398.         game_start_in_real_time -= g_elapsed_time();
  399.         /* No need to look at any more sides, just get on with the game. */
  400.         return;
  401.     }
  402.     }
  403.     if (!anydisplays) {
  404.     init_warning("No sides have a display");
  405.     }
  406. }
  407.  
  408. /* This routine looks to see if the game is completely over. */
  409.  
  410. void
  411. test_for_game_end()
  412. {
  413.     Side *side;
  414.  
  415.     /* Declare a draw if everybody is amenable. */
  416.     if (all_others_willing_to_quit(NULL)) {
  417.         /* (should remove all sides first?) */
  418.     end_the_game();
  419.     }
  420.     for_all_sides(side) {
  421.         /* If we have an active side being displayed, we're not done yet. */
  422.     if (side->ingame && side_has_display(side))
  423.       return;
  424.     /* (If no displayed sides have units, turns will whiz by) */
  425.     }
  426.     end_the_game();
  427. }
  428.  
  429. /* This is true when all participating sides have finished their turn. */
  430.  
  431. int
  432. all_sides_finished()
  433. {
  434.     Side *side;
  435.  
  436.     for_all_sides(side) {
  437.     if (side->ingame
  438.         && !side->finishedturn) {
  439.         return FALSE;
  440.     }
  441.     }
  442.     return TRUE;
  443. }
  444.  
  445. /* This is true when AIs should move more slowly. */
  446.  
  447. int
  448. all_human_only_sides_finished()
  449. {
  450.     Side *side;
  451.  
  452.     for_all_sides(side) {
  453.     if (side->ingame
  454.         && side_has_display(side)
  455.         && !side_has_ai(side)
  456.         && !side->finishedturn) {
  457.         return FALSE;
  458.     }
  459.     }
  460.     return TRUE;
  461. }
  462.  
  463. /* Call this from interfaces to check on realtime details without actually
  464.    going into run_game.  Will call back to interface if necessary. */
  465.  
  466. void
  467. check_realtime()
  468. {
  469.     Side *side;
  470.  
  471.     if (!realtime_game())
  472.       return;
  473.     if (exceeded_rt_for_game())
  474.       end_the_game();
  475.     if (g_rt_per_side() > 0) {
  476.     for_all_sides(side) {
  477.         if (side->ingame && side->totaltimeused > g_rt_per_side()) {
  478.         remove_side_from_game(side);
  479.         }
  480.     }
  481.     }
  482. }
  483.  
  484. int
  485. exceeded_rt_for_game()
  486. {
  487.     time_t now;
  488.  
  489.     if (g_rt_for_game() <= 0)
  490.       return FALSE;
  491.     time(&now);
  492.     /* Note that the game start time is already adjusted for any
  493.        elapsed time recorded when the game was last saved. */
  494.     return (idifftime(now, game_start_in_real_time) > g_rt_for_game());
  495. }
  496.  
  497. int
  498. exceeded_rt_per_turn()
  499. {
  500.     time_t now;
  501.  
  502.     if (g_rt_per_turn() <= 0)
  503.       return FALSE;
  504.     time(&now);
  505.     return (idifftime(now, turn_play_start_in_real_time) > g_rt_per_turn());
  506. }
  507.  
  508. /* This returns true if the given side is still wanting to do stuff. */
  509.  
  510. int
  511. units_still_acting(side)
  512. Side *side;
  513. {
  514.     int curactor;
  515.     Unit *unit;
  516.  
  517.     if (!side->ingame)
  518.       return FALSE;
  519.     for (curactor = 0; curactor < side->actionvector->numunits; ++curactor) {
  520.     unit = (side->actionvector->units)[curactor].unit;
  521.     if (unit_still_acting(unit, FALSE) && side_controls_unit(side, unit)) {
  522.         return TRUE;
  523.     }
  524.     }
  525.     return FALSE;
  526. }
  527.  
  528. /* Do everything that would happen before movement in a turn. */
  529.  
  530. static void
  531. run_turn_start()
  532. {
  533.     int curturn;
  534.     time_t turncalcstart, turncalcend;
  535.     Side *side;
  536.  
  537.     /* Increment the turn number. */
  538.     curturn = g_turn();
  539.     ++curturn;
  540.     set_g_turn(curturn);
  541.     /* See if we've hit the preset end of the game. */
  542.     if (curturn > g_last_turn() && !probability(g_extra_turn())) {
  543.     end_the_game();
  544.     /* The game is over, don't bother with the other calcs. */
  545.     return;
  546.     }
  547.     add_new_sides_to_game();
  548.     time(&turncalcstart);
  549.     update_all_progress_displays("turn start calcs", -1);
  550.     compute_season();
  551.     Dprintf("##### TURN %d (%s) #####\n",
  552.         curturn, absolute_date_string(curturn));
  553.     for_all_sides(side) {
  554.     side->finishedturn = FALSE;
  555.     update_turn_display(side, TRUE);
  556.     if (realtime_game()) {
  557.         update_clock_display(side, TRUE);
  558.     }
  559.     }
  560.     run_sun();
  561.     run_environment();
  562.     run_economy();
  563.     run_hp_recovery();
  564.     run_auto_repair();
  565.     run_self_builds();
  566.     run_appearances();
  567.     run_random_events();
  568.     run_detonation_accidents();
  569.     sort_units();
  570.     init_actionvectors();
  571.     compute_moves();
  572.     run_spies();
  573.     run_tech_leakage();
  574.     run_tooling_attrition();
  575.     cache_init_tech_levels();
  576.     reset_all_reserves();
  577.     gamestatesafe = FALSE;
  578.     if ((checkpointinterval > 0) && (curturn % checkpointinterval == 0)) {
  579.     write_entire_game_state(checkpoint_filename());
  580.     }
  581.     time(&turncalcend);
  582.     Dprintf("%d seconds to calc at turn start\n",
  583.         idifftime(turncalcend, turncalcstart));
  584. }
  585.  
  586. /* Do computations to start the first turn of a restored game. */
  587.  
  588. static void
  589. run_restored_turn_start()
  590. {
  591.     Side *side;
  592.  
  593.     Dprintf("##### TURN %d (%s) #####\n",
  594.         g_turn(), absolute_date_string(g_turn()));
  595.     for_all_sides(side) {
  596.     update_turn_display(side, TRUE);
  597.     if (realtime_game()) {
  598.         update_clock_display(side, TRUE);
  599.     }
  600.     }
  601.     compute_sun();
  602.     sort_units();
  603.     init_actionvectors();
  604.     /* We're done with restore-specific tweaks, turn the flag off. */
  605.     midturnrestore = FALSE;
  606. }
  607.  
  608. static void
  609. init_actionvectors()
  610. {
  611.     Side *side;
  612.  
  613.     for_all_sides_plus_indep(side) {
  614.     if (side->actionvector == NULL)
  615.       side->actionvector = make_unit_vector(max(numunits, 100));
  616.     clear_unit_vector(side->actionvector);
  617.     }
  618. }
  619.  
  620. /* Interfaces should call this to have another side added to the current
  621.    game.  The actual addition happens during turn setup, so as not to
  622.    risk confusing list traversals or AI calculations. */
  623.  
  624. /* (should take a player spec as arg?) */
  625.  
  626. int
  627. request_additional_side(playerspec)
  628. char *playerspec;
  629. {
  630.     if (numsides + new_sides_requested + 1 <= g_sides_max()) {
  631.     if (players_requested == NULL)
  632.       players_requested = (char **) xmalloc(MAXSIDES * sizeof(char *));
  633.     if (empty_string(playerspec))
  634.       playerspec = ",ai";
  635.     players_requested[new_sides_requested++] = copy_string(playerspec);
  636.     notify_all("Will add a new side (player \"%s\") at the start of the next turn",
  637.            playerspec);
  638.     return TRUE;
  639.     } else {
  640.     notify_all("Additional side requested, but not possible to add");
  641.     return FALSE;
  642.     }
  643. }
  644.  
  645. /* Add the requested number of new sides into an ongoing game. */
  646.  
  647. static void
  648. add_new_sides_to_game()
  649. {
  650.     int i;
  651.     Side *side, *side2;
  652.     Player *player;
  653.     Unit *unit;
  654.  
  655.     if (new_sides_requested > 0) {
  656.     for (i = 0; i < new_sides_requested; ++i) {
  657.         if (numsides >= g_sides_max())
  658.           break;
  659.         /* Grow side-referencing objects. */
  660.         for_all_units(unit) {
  661.         if (unit->opinions != NULL) {
  662.             init_unit_opinions(unit, numsides + 1);
  663.         }
  664.         }
  665.         side = make_up_a_side();
  666.         player = add_player();
  667.         parse_player_spec(player, players_requested[i]);
  668.         player->side = side;
  669.         side->player = player;
  670.         /* Set the player's advantage to be the side's advantage, if not
  671.            already set. */
  672.         if (player->advantage == 0) {
  673.         player->advantage = side->advantage;
  674.         }
  675.         run_synth_methods();
  676.         init_doctrine(side);
  677.         init_self_unit(side);
  678.         if (g_use_side_priority()) {
  679.         int maxpri = 0;
  680.  
  681.         for_all_sides(side2) {
  682.             if (side2->priority > maxpri)
  683.               maxpri = side2->priority;
  684.         }
  685.         side->priority = maxpri + 1;
  686.         /* If the indepside's priority was set automatically to be
  687.            one up from regular sides', bump it up to be past the new
  688.            side's priority also. */
  689.         if (indepside->priority == side->priority)
  690.           ++(indepside->priority);
  691.         }
  692.         /* Count all of the new side's units as initial gain. */
  693.         for_all_side_units(side, unit) {
  694.         count_gain(side, unit->type, initial_gain);
  695.         }
  696.         if (side_wants_ai(side)) {
  697.         init_ai(side);
  698.         }
  699.         for_all_sides(side2) {
  700.         /* Give all other AIs a chance to re-evaluate the situation. */
  701.         if (side_has_ai(side2) && side2 != side) {
  702.             ai_react_to_new_side(side2, side);
  703.         }
  704.         /* Add the new side to displays. */
  705.         update_side_display(side2, side, TRUE);
  706.         notify(side2, "A new side %s (played by %s) is in the game.",
  707.                side_desig(side), player_desig(player));
  708.         }
  709.     }
  710.     if (i > 0) {
  711.         /* Recalculate all view info for all sides; simpler than
  712.            trying to figure out what's really changed. */
  713.         reset_coverage();
  714.         reset_all_views();
  715.         compute_all_feature_centroids();
  716.         /* Redraw everything that's displayed. */
  717.         update_everything();
  718.     }
  719.     if (i < new_sides_requested) {
  720.         notify_all("Cannot create %d of the requested new sides",
  721.                new_sides_requested - i);
  722.     }
  723.     }
  724.     /* We've handled everything we're going to, reset the counter. */
  725.     new_sides_requested = 0;
  726. }
  727.  
  728. /* Parse the syntax "[username][,ai][/config][@display][+advantage]". */
  729.  
  730. void
  731. parse_player_spec(player, spec)
  732. Player *player;
  733. char *spec;
  734. {
  735.     int commapos, slashpos, atpos, pluspos;
  736.  
  737.     if (spec != NULL && strcmp(spec, "*") != 0) {
  738.     /* Extract (destructively) a trailing advantage specification. */
  739.     pluspos = iindex('+', spec);
  740.     if (pluspos >= 0) {
  741.         player->advantage = max(1, atoi(&(spec[pluspos + 1])));
  742.         spec[pluspos] = '\0';
  743.     }
  744.     /* Extract a displayname if given. */
  745.     atpos = iindex('@', spec);
  746.     if (atpos >= 0) {
  747.         player->displayname = copy_string(spec + atpos + 1);
  748.         spec[atpos] = '\0';
  749.     }
  750.     /* Extract a configuration name if given. */
  751.     slashpos = iindex('/', spec);
  752.     if (slashpos >= 0) {
  753.         player->configname = copy_string(spec + slashpos + 1);
  754.         spec[slashpos] = '\0';
  755.     }
  756.     /* Extract an AI type if given. */
  757.     commapos = iindex(',', spec);
  758.     if (commapos >= 0) {
  759.         player->aitypename = copy_string(spec + commapos + 1);
  760.         spec[commapos] = '\0';
  761.     }
  762.     /* Just a plain old string left. */
  763.     if (strlen(spec) > 0) {
  764.         if (atpos >= 0) {
  765.         /* Display given separately, so this is a name. */
  766.         player->name = copy_string(spec);
  767.         } else {
  768.         player->displayname = copy_string(spec);
  769.         }
  770.     }
  771.     }
  772.     canonicalize_player(player);
  773. }
  774.  
  775. static void
  776. init_movement()
  777. {
  778.     int i;
  779.     Side *side, *side2;
  780.  
  781.     i = 1;
  782.     curpriority = 9999;
  783.     curunitpriority = 0;
  784.     /* In the absence of any idea about how to handle actions by independent units,
  785.        force their turn to be finished immediately. */
  786.     indepside->finishedturn = TRUE;
  787.     for_all_sides(side) {
  788.     if (side->ingame) {
  789.         /* Record that this side was active during at least one turn. */
  790.         side->everingame = TRUE;
  791.         /* No units are waiting for orders initially. */
  792.         side->numwaiting = 0;
  793.     }
  794.     side->turnstarttime = time(0);
  795.     /* Didn't really do input, but useful to pretend so. */
  796.     side->lasttime = time(0);
  797.     /* Calculate side priorities; do here so future versions can
  798.        set priorities dynamically. */
  799.     if (g_use_side_priority()) {
  800.         if (side->priority < 0) {
  801.         side->priority = i++;
  802.         }
  803.     }
  804.     if (side_has_ai(side))
  805.       ai_init_turn(side);
  806.     side->busy = FALSE;
  807.     if (side_has_display(side))
  808.       update_action_display(side, TRUE);
  809.     }
  810.     /* Set independent units to move after units on sides. */
  811.     if (g_use_side_priority()) {
  812.     if (indepside->priority < 0) {
  813.         indepside->priority = i;
  814.     }
  815.     for_all_sides_plus_indep(side) {
  816.         if (!side->finishedturn && side->priority < curpriority)
  817.           curpriority = side->priority;
  818.     }
  819.     }
  820.     /* Inform sides with displays that all units are ready to act. */
  821.     for_all_sides(side) {
  822.     if (side_has_display(side)) {
  823.         for_all_sides(side2) {
  824.         update_side_display(side, side2, TRUE);
  825.         }
  826.     }
  827.     }
  828. }
  829.  
  830. /* Compute the leakage of technology from one side to another. */
  831.  
  832. static void
  833. run_tech_leakage()
  834. {
  835.     int u;
  836.     Side *side, *side2;
  837.  
  838.     if (any_tech_leakage < 0) {
  839.     any_tech_leakage = FALSE;
  840.     for_all_unit_types(u) {
  841.         if (u_tech_leakage(u) > 0) {
  842.         any_tech_leakage = TRUE;
  843.         break;
  844.         }
  845.     }
  846.     }
  847.     if (!any_tech_leakage)
  848.       return;
  849.     Dprintf("Running tech leakage\n");
  850.     for_all_sides(side) {
  851.     for_all_sides(side2) {
  852.         if (side != side2 /* and some contact between sides */) {
  853.         for_all_unit_types(u) {
  854.             if (side->tech[u] < side2->tech[u]
  855.             && u_tech_leakage(u) > 0) {
  856.             side->tech[u] += prob_fraction(u_tech_leakage(u));
  857.             }
  858.         }
  859.         }
  860.     }
  861.     }
  862. }
  863.  
  864. /* Remember each side's tech levels before it does any research actions
  865.    during the turn.  This can be used to keep tech level from going up too
  866.    fast if the player has lots of units doing research. */
  867.  
  868. static void
  869. cache_init_tech_levels()
  870. {
  871.     int u;
  872.     Side *side;
  873.  
  874.     if (using_tech_levels()) {
  875.     for_all_sides(side) {
  876.         for_all_unit_types(u) {
  877.         side->inittech[u] = side->tech[u];
  878.         }
  879.     }
  880.     }
  881. }
  882.  
  883. /* Reduce some units' construction tooling randomly. */
  884.  
  885. static void
  886. run_tooling_attrition()
  887. {
  888.     int u, u2, att;
  889.     Unit *unit;
  890.  
  891.     /* Test whether tooling attrition is ever possible. */
  892.     if (any_tooling_attrition < 0) {
  893.     any_tooling_attrition = FALSE;
  894.     for_all_unit_types(u) {
  895.         for_all_unit_types(u2) {
  896.         if (uu_tp_attrition(u, u2) > 0) {
  897.             any_tooling_attrition = TRUE;
  898.             break;
  899.         }
  900.         }
  901.         if (any_tooling_attrition)
  902.           break;
  903.     }
  904.     }
  905.     if (!any_tooling_attrition)
  906.       return;
  907.     for_all_units(unit) {
  908.     if (is_active(unit) && unit->tooling != NULL) {
  909.         for_all_unit_types(u2) {
  910.         att = uu_tp_attrition(unit->type, u2);
  911.         if (att > 0) {
  912.             unit->tooling[u2] -= prob_fraction(att);
  913.         }
  914.         if (unit->tooling[u2] < 0) unit->tooling[u2] = 0;
  915.         }
  916.     }
  917.     }
  918. }
  919.  
  920. static void
  921. reset_all_reserves()
  922. {
  923.     Unit *unit;
  924.  
  925.     for_all_units(unit) {
  926.     if (unit->plan != NULL) {
  927.         unit->plan->reserve = FALSE;
  928.     }
  929.     }
  930. }
  931.  
  932. /* Compute moves and actions for all the units at once, put everybody that
  933.    can do anything into a list. */
  934.  
  935. static void
  936. compute_moves()
  937. {
  938.     int curturn = g_turn();
  939.     Unit *unit;
  940.     Side *side;
  941.  
  942.     for_all_sides(side) {
  943.     side->numacting = 0;
  944.     side->numfinished = 0;
  945.     for_all_side_units(side, unit) {
  946.         if (unit->act) {
  947.         /* Unit acp is set to -1 to indicate uninitialization,
  948.            but acp is computed by adding to the previous acp,
  949.            so when starting a new game (as opposed to
  950.            restoring an old one), acp should be inited to
  951.            zero.  (This could maybe be done better.) */
  952.         if (curturn == 1)
  953.           unit->act->acp = 0;
  954.         compute_acp(unit);
  955.         update_unit_acp_display(side, unit, FALSE);
  956.         }
  957.     }
  958.     }
  959. }
  960.  
  961. static void
  962. compose_actionvectors()
  963. {
  964.     int priority;
  965.     Unit *unit;
  966.     Side *side;
  967.  
  968.     for_all_sides_plus_indep(side) {
  969.     for_all_side_units(side, unit) {
  970.         if (unit->act && unit->act->initacp > 0) {
  971.         priority = unit_priority(unit);
  972.         if (between(curunitpriority, priority, curunitpriority + 99)) {
  973.             side->actionvector = add_unit_to_vector(side->actionvector, unit, 0);
  974.             /* Clear all delay flags. */
  975.             if (unit->plan)
  976.               unit->plan->delayed = FALSE;
  977.         }
  978.         }
  979.         if (unit->plan) {
  980.         unit->plan->execs_this_turn = 0;
  981.         }
  982.     }
  983.     /* (should sort vector by unit priority) */
  984.     Dprintf("Action vector for %s has %d units, at priority %d\n",
  985.         side_desig(side), side->actionvector->numunits, curunitpriority);
  986.     }
  987. }
  988.  
  989. int
  990. unit_priority(unit)
  991. Unit *unit;
  992. {
  993.     /* (should look for individual unit priority hook also) */
  994.     return u_action_priority(unit->type);
  995. }
  996.  
  997. /* Compute the action points available to the unit this turn. */
  998.  
  999. void
  1000. compute_acp(unit)
  1001. Unit *unit;
  1002. {
  1003.     int u = unit->type, t, acp, tempeff, maxacp, minacp, err;
  1004.     Unit *occ;
  1005.  
  1006.     /* Units still under construction or off-area can't do anything. */
  1007.     if (!completed(unit) || !inside_area(unit->x, unit->y)) {
  1008.     unit->act->initacp = unit->act->acp = unit->act->actualactions = 0;
  1009.     return;
  1010.     }
  1011.     /* First compute how many action points are available. */
  1012.     /* Start with basic acp, normal or damaged as appropriate. */
  1013.     /* (Should fix - small multi-part unit would be considered damaged) */
  1014.     if (unit->hp < u_hp_max(u) && u_acp_damage_effect(u) != lispnil) {
  1015.     acp = damaged_acp(unit, u_acp_damage_effect(u));
  1016.     } else {
  1017.     acp = u_acp(u);
  1018.     }
  1019.     /* Adjust for occupants. */
  1020.     for_all_occupants(unit, occ) {
  1021.     if (is_active(occ)) {
  1022.         acp = (acp * uu_acp_occ_effect(occ->type, u)) / 100;
  1023.     }
  1024.     }
  1025.     /* Adjust for night time. */
  1026.     if (night_at(unit->x, unit->y)) {
  1027.         /* (should account for unit being on a road at night, etc) */
  1028.     t = terrain_at(unit->x, unit->y);
  1029.         acp = (acp * ut_acp_night_effect(u, t)) / 100;
  1030.     }
  1031.     /* Adjust for temperature. */
  1032.     if (temperatures_defined() && u_acp_temp_effect(u) != lispnil) {
  1033.     err = interpolate_in_list(temperature_at(unit->x, unit->y), u_acp_temp_effect(u), &tempeff);
  1034.     if (err == 0) {
  1035.         acp = (acp * tempeff) / 100;
  1036.     } else {
  1037.         /* (should complain?) */
  1038.     }
  1039.     }
  1040.     /* Adjust for season. */
  1041.     if (u_acp_season_effect(u) != lispnil) {
  1042.         acp = (acp * season_effect(u)) / 100;
  1043.     }
  1044.     /* Clip to upper and lower acp-per-turn limits. */
  1045.     acp = max(acp, u_acp_turn_min(u));
  1046.     if (u_acp_turn_max(u) >= 0)
  1047.       acp = min(acp, u_acp_turn_max(u));
  1048.     /* Increment the unit's available acp by the acp we get for this turn. */
  1049.     unit->act->initacp = unit->act->acp + acp;
  1050.     /* Now clip the unit's accumulated acp to its limits. */
  1051.     minacp = u_acp_min(u);
  1052.     unit->act->initacp = max(unit->act->initacp, minacp);
  1053.     maxacp = (u_acp_max(u) < 0 ? acp : u_acp_max(u));
  1054.     unit->act->initacp = min(unit->act->initacp, maxacp);
  1055.     /* Current acp is now the initial acp. */
  1056.     unit->act->acp = unit->act->initacp;
  1057.     /* Zero the counts of what actually got done. */
  1058.     unit->act->actualactions = unit->act->actualmoves = 0;
  1059. }
  1060.  
  1061. /* Compute and return the acp of a damaged unit, using a list of (hp acp) pairs
  1062.    and interpolating between them. */
  1063.  
  1064. int
  1065. damaged_acp(unit, effect)
  1066. Unit *unit;
  1067. Obj *effect;
  1068. {
  1069.     int u, err, rslt;
  1070.  
  1071.     u = unit->type;
  1072.     err = interpolate_in_list_ext(unit->hp, effect, 0, 0, 0, 0, u_hp(u), u_acp(u), &rslt);
  1073.     if (err != 0) {
  1074.     run_warning("cannot get damaged acp for %s at hp %d, using %d",
  1075.             u_type_name(u), u_acp(u));
  1076.     rslt = u_acp(u);
  1077.     }
  1078.     return rslt;
  1079. }
  1080.  
  1081. static void
  1082. compute_season()
  1083. {
  1084.     Obj *names, *rest, *elt;
  1085.  
  1086.     curseasonname = NULL;
  1087.     if (world.yearlength > 1) {
  1088.     curyearpart = (g_turn() + g_initial_year_part()) % world.yearlength;
  1089.     /* Determine the name of the season, if defined. */
  1090.     names = g_season_names();
  1091.     if (names != NULL && names != lispnil && consp(names)) {
  1092.         for (rest = names; rest != lispnil; rest = cdr(rest)) {
  1093.         elt = car(rest);
  1094.         if (consp(elt)
  1095.             && numberp(car(elt))
  1096.             && numberp(cadr(elt))
  1097.             && between(c_number(car(elt)), curyearpart, c_number(cadr(elt)))
  1098.             && stringp(car(cddr(elt))))
  1099.           curseasonname = c_string(car(cddr(elt)));
  1100.         }
  1101.     }
  1102.     } else {
  1103.     curyearpart = 0;
  1104.     }
  1105. }
  1106.  
  1107. static int
  1108. season_effect(u)
  1109. int u;
  1110. {
  1111.     int err, rslt;
  1112.  
  1113.     if (curyearpart < 0)
  1114.       compute_season();
  1115.     err = interpolate_in_list(curyearpart, u_acp_season_effect(u), &rslt);
  1116.     if (err != 0) {
  1117.     rslt = 100;
  1118.     }
  1119.     return rslt;
  1120. }
  1121.  
  1122. /* Do some number of actions. */
  1123.  
  1124. static int
  1125. move_some_units(lim)
  1126. int lim;
  1127. {
  1128.     int num = 0, sidenum;
  1129.     Side *side;
  1130.  
  1131.     for_all_sides_plus_indep(side) {
  1132.     if ((g_use_side_priority() ?
  1133.          curpriority == side->priority :
  1134.          TRUE)) {
  1135.         sidenum = side_move_some_units(side, lim);
  1136.         num = max(num, sidenum);
  1137.     }
  1138.     }
  1139.     return num;
  1140. }
  1141.  
  1142. /* Do some number of actions. */
  1143.  
  1144. static int
  1145. side_move_some_units(side, lim)
  1146. Side *side;
  1147. int lim;
  1148. {
  1149.     int num, foundanytomove, curactor, numdelayed;
  1150.     Unit *unit;
  1151.  
  1152.     num = 0;
  1153.   tryagain:
  1154.     foundanytomove = FALSE;
  1155.     numdelayed = 0;
  1156.     for (curactor = 0; curactor < side->actionvector->numunits; ++curactor) {
  1157.     unit = (side->actionvector->units)[curactor].unit;
  1158.     if (unit->plan && unit->plan->delayed) {
  1159.         ++numdelayed;
  1160.         continue;
  1161.     }
  1162.     current_play_rate = slow_play_rate;
  1163.     /* AIs should play as fast as possible if turns are sequential or if the
  1164.        human players are all done. */
  1165.     if (g_use_side_priority() || all_human_only_sides_finished()) {
  1166.         current_play_rate = fast_play_rate;
  1167.     }
  1168.     /* If the unit is keeping formation, then give it a chance to
  1169.        adjust its position, even if it's not "still acting". */
  1170.     if (is_active(unit)
  1171.         && (unit->side ?
  1172.         (unit->side->ingame && !unit->side->finishedturn) : TRUE)
  1173.         && (unit->act && unit->act->acp > 0)
  1174.         && (unit->plan && unit->plan->formation)) {
  1175.         num += move_one_unit_multiple(unit, lim - num);
  1176.         foundanytomove = TRUE;
  1177.     }
  1178.     if (unit->side
  1179.         && unit->side->orders
  1180.         && unit->plan
  1181.         && unit->plan->tasks == NULL
  1182.         && execute_standing_order(unit, FALSE)) {
  1183.         /* We're not waiting because standing order execution will
  1184.            shortly be allowed to fill in a task for real. */
  1185.         unit->plan->waitingfortasks = FALSE;
  1186.         num += move_one_unit_multiple(unit, lim - num);
  1187.         foundanytomove = TRUE;
  1188.     }
  1189.     if (unit_still_acting(unit, TRUE)) {
  1190.         num += move_one_unit_multiple(unit, lim - num);
  1191.         foundanytomove = TRUE;
  1192.     }
  1193.     if (unit_still_acting(unit, FALSE)) {
  1194.         foundanytomove = TRUE;
  1195.     }
  1196.     if (num >= lim) 
  1197.       return num;
  1198.     }
  1199.     if (!foundanytomove && numdelayed > 0) {
  1200.     for (curactor = 0; curactor < side->actionvector->numunits; ++curactor) {
  1201.         unit = (side->actionvector->units)[curactor].unit;
  1202.         if (unit->plan)
  1203.           unit->plan->delayed = FALSE;
  1204.     }
  1205.     goto tryagain;
  1206.     }
  1207.     if (!foundanytomove && 0 /* not at max priority */) {
  1208.     /* should recompose action vector for new priority? */
  1209.     }
  1210.     return num;
  1211. }
  1212.  
  1213. static int
  1214. unit_still_acting(unit, checkwaiting)
  1215. Unit *unit;
  1216. int checkwaiting;
  1217. {
  1218.     return (is_active(unit)
  1219.         && (unit->side
  1220.         && unit->side->ingame
  1221.         && !unit->side->finishedturn)
  1222.         && (unit->act
  1223.         && unit->act->acp > 0)
  1224.         && ((unit->plan
  1225.         && !unit->plan->asleep
  1226.         && !unit->plan->reserve
  1227.         && (checkwaiting ? !unit->plan->waitingfortasks : TRUE))
  1228.         || has_pending_action(unit)));
  1229. }
  1230.  
  1231. /* Do a single unit's actions, up to the given limit or until it runs
  1232.    out of things it wants to do (or something happens to it). */
  1233.  
  1234. int lastexecution = 0;
  1235.  
  1236. static int
  1237. move_one_unit_multiple(unit, lim)
  1238. Unit *unit;
  1239. int lim;
  1240. {
  1241.     int num = 0, buzz = 0, acp1;
  1242.     int rslt;
  1243.  
  1244.     if (unit->act == NULL || unit->act->initacp < 1)
  1245.       return 0;
  1246.     acp1 = unit->act->acp;
  1247.     while (is_active(unit)
  1248.        && (unit->act
  1249.            && unit->act->acp > u_acp_min(unit->type))
  1250.        && ((unit->plan
  1251.         && !unit->plan->asleep
  1252.         && !unit->plan->reserve
  1253.         && !unit->plan->delayed)
  1254.            || has_pending_action(unit))
  1255.        && num < lim
  1256.        && buzz < lim) {
  1257.     if (has_pending_action(unit)) {
  1258.         /* Execute the action directly. */
  1259.         rslt = execute_action(unit, &(unit->act->nextaction));
  1260.         /* Clear the action.  Note that the unit might have changed
  1261.            to a non-acting type, so we have to check for act struct. */
  1262.         if (unit->act)
  1263.           unit->act->nextaction.type = ACTION_NONE;
  1264.         /* In any case, the game state is irrevocably altered. */
  1265.         gamestatesafe = FALSE;
  1266.         ++num;
  1267.     } else if (unit->plan) {
  1268.         if (unit->side
  1269.         && unit->side->orders
  1270.         && unit->plan->tasks == NULL
  1271.         && execute_standing_order(unit, TRUE)) {
  1272.         execute_plan(unit, 1);
  1273.         gamestatesafe = FALSE;
  1274.         ++buzz;
  1275.         }
  1276.         if (unit->plan->formation && move_into_formation(unit)) {
  1277.         execute_plan(unit, 1);
  1278.         gamestatesafe = FALSE;
  1279.         ++buzz;
  1280.         }
  1281.         if (unit->plan->waitingfortasks
  1282.         || unit->plan->asleep
  1283.         || unit->plan->reserve
  1284.         || unit->plan->delayed)
  1285.           break;
  1286.         if (unit->side
  1287.         && side_has_ai(unit->side)
  1288.         && current_play_rate > 0
  1289.         && !n_ms_elapsed(60000 / current_play_rate)
  1290.         )
  1291.           break;
  1292.         execute_plan(unit, 1);
  1293.         record_ms();
  1294.         gamestatesafe = FALSE;
  1295.         ++buzz;
  1296.     } else {
  1297.         run_warning("Planless \"%s\" was asked to act", unit_desig(unit));
  1298.         ++buzz;
  1299.     }
  1300.     /* This should never happen. */
  1301.     if (unit->act && unit->act->acp == acp1 && num > 1) {
  1302.         /* Blast the action. */
  1303.         unit->act->nextaction.type = ACTION_NONE;
  1304.         /* Blast the plan. */
  1305.         if (unit->plan)
  1306.           unit->plan->type = PLAN_NONE;
  1307.         if (unit->plan && probability(5))
  1308.           unit->plan->asleep = TRUE;
  1309.         run_warning("%s was confused, resetting plans", unit_desig(unit));
  1310.     }
  1311.     }
  1312.     return num;
  1313. }
  1314.  
  1315. /* This explicitly finishes out a side's activity for the turn. */
  1316.  
  1317. void
  1318. finish_turn(side)
  1319. Side *side;
  1320. {
  1321.     int nextpriority;
  1322.     Side *side2, *side3;
  1323.  
  1324.     /* Flag the side as being done for this turn. */
  1325.     side->finishedturn = TRUE;
  1326.     /* Stop counting down our time consumption. */
  1327.     side->totaltimeused += (time(0) - side->turnstarttime);
  1328.     if (g_use_side_priority()) {
  1329.     nextpriority = 9999;
  1330.     for_all_sides_plus_indep(side2) {
  1331.         if (!side2->finishedturn
  1332. /*        && side2->priority > curpriority */
  1333.         && side2->priority < nextpriority) {
  1334.         nextpriority = side2->priority;
  1335.         }
  1336.         if (!side2->finishedturn && side2->priority < curpriority)
  1337.           run_warning("%s not finished, but priority is %d, less than current %d",
  1338.               side_desig(side2), side2->priority, curpriority);
  1339.     }
  1340.     if (nextpriority > curpriority)
  1341.       curpriority = nextpriority;
  1342.     }
  1343.     /* Clue everybody in. */
  1344.     if (g_use_side_priority()) {
  1345.     /* Several sides may change, if current priority changes. */
  1346.     for_all_sides(side2) {
  1347.         for_all_sides(side3) {
  1348.         update_side_display(side2, side3, TRUE);
  1349.         }
  1350.     }
  1351.     } else {
  1352.     /* Only the turn-finishing side changes. */
  1353.     for_all_sides(side2) {
  1354.         update_side_display(side2, side, TRUE);
  1355.     }
  1356.     }
  1357.     Dprintf("%s finished its turn.\n", side_desig(side));
  1358. }
  1359.  
  1360. void
  1361. set_play_rate(slow, fast)
  1362. int slow, fast;
  1363. {
  1364.     if (slow < 0 || fast < 0 || fast < slow) {
  1365.     run_warning("Bad play rates slow=%d fast=%d, ignoring", slow, fast);
  1366.     return;
  1367.     }
  1368.     slow_play_rate = slow;
  1369.     fast_play_rate = fast;
  1370. }
  1371.  
  1372. /* Take care of details that no longer require any interaction, at least
  1373.    none that can't wait until the next turn. */
  1374.  
  1375. static void
  1376. finish_movement()
  1377. {
  1378.     int lostacp;
  1379.     Unit *unit;
  1380.     Side *side, *side2;
  1381.  
  1382.     for_all_sides (side) {
  1383.     if (Debug) {
  1384.         lostacp = 0;
  1385.         for_all_side_units(side, unit) {
  1386.         if (is_active(unit) && unit->act && unit->act->acp > 0) {
  1387.             lostacp += unit->act->acp;
  1388.         }
  1389.         }
  1390.         if (lostacp > 0) {
  1391.         Dprintf("%s forfeited %d acp overall.\n",
  1392.             side_desig(side), lostacp);
  1393.         }
  1394.     }
  1395.     if (side_has_ai(side)) {
  1396.         ai_finish_movement(side);
  1397.     }
  1398.     }
  1399.     for_all_sides(side)  {
  1400.     for_all_sides(side2) {
  1401.         update_side_display(side, side2, TRUE);
  1402.     }
  1403.     }
  1404. }
  1405.  
  1406. /* See how any agreements' terms are holding up. */
  1407.  
  1408. static void
  1409. test_agreements()
  1410. {
  1411.     Agreement *ag;
  1412.  
  1413.     for_all_agreements(ag) {
  1414.     if (ag->state == in_force) {
  1415.         /* what? */
  1416.     }
  1417.     }
  1418. }
  1419.  
  1420. /* Compute sun-related data. */
  1421.  
  1422. static void
  1423. compute_sun()
  1424. {
  1425.     int curtime, highest;
  1426.  
  1427.     switch (world.daylength) {
  1428.       case 0:
  1429.     /* Sun is at a fixed position. */
  1430.     daynight = TRUE;
  1431.     /* (should be possible to set explicitly somehow? implicitly from lat/long?) */
  1432.     sunx = area.width / 2;  suny = area.halfheight;
  1433.     break;
  1434.       case 1:
  1435.     /* No sun effects at all, every place uniformly lit. */
  1436.           daynight = FALSE;
  1437.     break;
  1438.       default:
  1439.     /* Normal days and nights. */
  1440.     daynight = TRUE;
  1441.     /* If world has a appropriate circumference, the sun moves over
  1442.        it at a regular pace. */
  1443.     if (world.circumference >= area.width) {
  1444.         lastsunx = sunx;  lastsuny = suny;
  1445.         curtime = (g_turn() * 100 + g_initial_day_part()) % (world.daylength * 100);
  1446.         sunx = (curtime * world.circumference) / (world.daylength * 100) + area.width / 2;
  1447.         /* Adjust for the world's axialtilt.  The approximation is basically a triangle
  1448.            wave instead of a more correct sinusoid. */
  1449.         highest = ((world.circumference / 4) * world.axialtilt) / 90;
  1450.         if (curtime < ((world.daylength * 100) / 2))
  1451.           suny = area.halfheight - highest + (curtime * 2 * highest) / ((world.daylength * 100) / 2);
  1452.         else
  1453.           suny = area.halfheight + highest - ((curtime - ((world.daylength * 100) / 2)) * 2 * highest) / ((world.daylength * 100) / 2);
  1454.         suny -= area.latitude;
  1455.     }
  1456.     break;
  1457.     }
  1458.     if (daynight) {
  1459.     Dprintf("Sun is now at %d,%d\n", sunx, suny);
  1460.     }
  1461. }
  1462. /* Compute the position of the sun for this turn. */
  1463.  
  1464. static void
  1465. run_sun()
  1466. {
  1467.     int x, y;
  1468.     Side *side;
  1469.  
  1470.     compute_sun();
  1471.     if (world.daylength > 1 && world.circumference >= area.width) {
  1472.     /* Update the appearance of any cells whose lighting has changed. */
  1473.     /* Note that we do this from top to bottom, purely for esthetic
  1474.        reasons. */
  1475.     for (y = area.height - 1; y >= 0; --y) {
  1476.         for (x = 0; x < area.width; ++x) {
  1477.         if (in_area(x, y)) {
  1478.             if (lighting(x, y, sunx, suny) != lighting(x, y, lastsunx, lastsuny)) {
  1479.             for_all_sides(side) {
  1480.                 update_cell_display(side, x, y, FALSE);
  1481.             }
  1482.             }
  1483.             }
  1484.         }
  1485.     }
  1486.     }
  1487. }
  1488.  
  1489. int any_annual_temp_change = -1;
  1490.  
  1491. static int num_key_points;
  1492.  
  1493. struct a_key_point {
  1494.     int x, y;
  1495.     int temp;
  1496. } *key_points;
  1497.  
  1498. void calc_key_point_temps PARAMS ((int yearpart));
  1499.  
  1500. int interpolate_temperature PARAMS ((int x, int y));
  1501.  
  1502. void
  1503. calc_key_point_temps(yearpart)
  1504. int yearpart;
  1505. {
  1506.     int i, err, rslt;
  1507.     Obj *lis, *item, *loc;
  1508.  
  1509.     num_key_points = length(g_temp_year());
  1510.     if (num_key_points > 0 && key_points == NULL) {
  1511.     key_points =
  1512.       (struct a_key_point *) xmalloc(num_key_points * sizeof(struct a_key_point));
  1513.     }
  1514.     i = 0;
  1515.     for (lis = g_temp_year(); lis != lispnil; lis = cdr(lis)) {
  1516.     item = car(lis);
  1517.     loc = car(item);
  1518.     if (consp(loc)) {
  1519.         key_points[i].x = c_number(car(loc));
  1520.         key_points[i].y = c_number(car(cdr(loc)));
  1521.     }
  1522.     err = interpolate_in_list(yearpart, cdr(item), &rslt);
  1523.     if (err != 0) {
  1524.         /* (should complain) */
  1525.         rslt = 0;
  1526.     }
  1527.     key_points[i].temp = rslt;
  1528.     ++i;
  1529.     }
  1530. }
  1531.  
  1532. int
  1533. interpolate_temperature(x, y)
  1534. int x, y;
  1535. {
  1536.     int d0, d1, t0, t1, i, besti, nextbesti, d;
  1537.  
  1538.     if (num_key_points == 1) {
  1539.     return key_points[0].temp;
  1540.     } else if (num_key_points == 2) {
  1541.     d0 = distance(x, y, key_points[0].x, key_points[0].y);
  1542.     t0 = key_points[0].temp;
  1543.     d1 = distance(x, y, key_points[1].x, key_points[1].y);
  1544.     t1 = key_points[1].temp;
  1545.     return ((t0 * d1 + t1 * d0) / (d0 + d1));
  1546.     } else if (num_key_points > 2) {
  1547.     besti = 0;
  1548.     nextbesti = -1;
  1549.     d0 = distance(x, y, key_points[besti].x, key_points[besti].y);
  1550.     for (i = 2; i < num_key_points; ++i) {
  1551.         d = distance(x, y, key_points[i].x, key_points[i].y);
  1552.         if (d < d0) {
  1553.         nextbesti = besti;
  1554.         d1 = d0;
  1555.         besti = i;
  1556.         d0 = distance(x, y, key_points[besti].x, key_points[besti].y);
  1557.         } else if ((nextbesti < 0 || d < d1) && i != besti) {
  1558.         nextbesti = i;
  1559.         d1 = distance(x, y, key_points[nextbesti].x, key_points[nextbesti].y);
  1560.         }
  1561.     }
  1562.     d1 = distance(x, y, key_points[nextbesti].x, key_points[nextbesti].y);
  1563.     t0 = key_points[besti].temp;
  1564.     t1 = key_points[nextbesti].temp;
  1565.     return ((t0 * d1 + t1 * d0) / (d0 + d1));
  1566.     } else {
  1567.     run_error("???");
  1568.     return 0;
  1569.     }
  1570. }
  1571.  
  1572. /* Compute environment changes. */
  1573.  
  1574. static void
  1575. run_environment()
  1576. {
  1577.     int yrlen = world.yearlength, x, y, dir, t, celltemp;
  1578.     int anychanges = FALSE;
  1579.  
  1580.     if (mintemp == maxtemp && !any_wind_variation_in_layer)
  1581.       return;
  1582.     if (mintemp != maxtemp && !temperatures_defined()) {
  1583.         allocate_area_temperatures();
  1584.         allocate_area_scratch(3);
  1585.     }
  1586.     if (any_annual_temp_change < 0) {
  1587.     any_annual_temp_change = FALSE;
  1588.     if (yrlen > 0 && g_temp_year() != lispnil) {
  1589.         any_annual_temp_change = TRUE;
  1590.     }
  1591.     }
  1592.     if (any_annual_temp_change) {
  1593.     calc_key_point_temps(curyearpart);
  1594.     }
  1595.     if (any_wind_variation_in_layer && !winds_defined()) {
  1596.         allocate_area_winds();
  1597.         allocate_area_scratch(2);
  1598.     }
  1599.     /* The tmp1 record will record where any changes occur. */
  1600.     for_all_cells(x, y) {
  1601.     set_tmp1_at(x, y, FALSE);
  1602.     }
  1603.     if (mintemp != maxtemp) {
  1604.     /* Compute the average temperature at each point in the world. */
  1605.     for (y = area.height - 1; y >= 0; --y) {
  1606.         for (x = 0; x < area.width; ++x) {
  1607.         if (!in_area(x, y))
  1608.           continue;
  1609.         /* Save the prev temp. */
  1610.         set_tmp2_at(x, y, temperature_at(x, y));
  1611.         t = terrain_at(x, y);
  1612.         if (any_annual_temp_change)
  1613.           celltemp = interpolate_temperature(x, y);
  1614.         else
  1615.           celltemp = t_temp_avg(t);
  1616.         /* Add in a random variation if specified. */
  1617.         if (t_temp_variability(t) > 0) {
  1618.             celltemp += (xrandom(t_temp_variability(t))
  1619.                  - t_temp_variability(t)/2);
  1620.         }
  1621.         /* Higher elevations can be much colder. */
  1622.         /* (In this pos, will influence lowlands via moderation -
  1623.            realistic?) */
  1624.         if (elevations_defined()
  1625.             && g_temp_floor_elev() != 0
  1626.             && elev_at(x, y) < g_temp_floor_elev()) {
  1627.             celltemp -=
  1628.               ((celltemp - g_temp_floor()) * elev_at(x, y))
  1629.             / g_temp_floor_elev();
  1630.         }
  1631.         /* Clip to terrain type's limits. */
  1632.         if (celltemp < t_temp_min(t))
  1633.           celltemp = t_temp_min(t);
  1634.         if (celltemp > t_temp_max(t))
  1635.           celltemp = t_temp_max(t);
  1636.         /* Record the (unmoderated) temperature of the cell. */
  1637.         set_temperature_at(x, y, celltemp);
  1638.         }
  1639.     }
  1640.     /* Sometimes the scale of the world is such that neighboring cells
  1641.        influence each other's temperatures. */
  1642.     if (g_temp_mod_range() > 0) {
  1643.         /* only doing a range of 1... */
  1644.         for_all_interior_cells(x, y) {
  1645.         set_tmp3_at(x, y, temperature_at(x, y));
  1646.         for_all_directions(dir) {
  1647.             set_tmp3_at(x, y,
  1648.                 (tmp3_at(x, y)
  1649.                  + temperature_at(x+dirx[dir], y+diry[dir])));
  1650.         }
  1651.         }
  1652.         for_all_interior_cells(x, y) {
  1653.         celltemp = tmp3_at(x, y) / (NUMDIRS + 1);
  1654.         t = terrain_at(x, y);
  1655.         /* Clip to terrain type's limits. */
  1656.         if (celltemp < t_temp_min(t))
  1657.           celltemp = t_temp_min(t);
  1658.         if (celltemp > t_temp_max(t))
  1659.           celltemp = t_temp_max(t);
  1660.         set_temperature_at(x, y, celltemp);
  1661.         }
  1662.     }
  1663.      for_all_cells(x, y) {
  1664.         if (temperature_at(x, y) != tmp2_at(x, y))
  1665.           set_tmp1_at(x, y, TRUE);
  1666.         anychanges = TRUE;
  1667.     }
  1668.     }
  1669.     /* Do wind changes. */
  1670.     if (any_wind_variation_in_layer) {
  1671.     /* Save the previous state. */
  1672.     for_all_interior_cells(x, y) {
  1673.         set_tmp2_at(x, y, raw_wind_at(x, y));
  1674.     }
  1675.     for_all_interior_cells(x, y) {
  1676.         int winddir = wind_dir_at(x, y);
  1677.         int windforce = wind_force_at(x, y);
  1678.         int t = terrain_at(x, y);
  1679.         int anychange;
  1680.  
  1681.         anychange = FALSE;
  1682.         if (probability(t_wind_variability(t))) {
  1683.         winddir = (flip_coin() ? right_dir(winddir) : left_dir(winddir));
  1684.         anychange = TRUE;
  1685.         }
  1686.         if (probability(t_wind_force_variability(t))) {    
  1687.         windforce += (flip_coin() ? 1 : -1);
  1688.         windforce = max(windforce, t_wind_force_min(t));
  1689.         windforce = min(windforce, t_wind_force_max(t));
  1690.         anychange = TRUE;
  1691.         }
  1692.         if (anychange) {
  1693.         set_wind_at(x, y, winddir, windforce);
  1694.         }
  1695.     }
  1696.     if (g_wind_mix_range() > 0) {
  1697.         mix_winds();
  1698.     }
  1699.     for_all_cells(x, y) {
  1700.         if (raw_wind_at(x, y) != tmp2_at(x, y))
  1701.           set_tmp1_at(x, y, TRUE);
  1702.         anychanges = TRUE;
  1703.     }
  1704.     }
  1705.     /* See if any displays should change and report if so. */
  1706.     if (anychanges) {
  1707.     for_all_cells(x, y) {
  1708.         if (tmp1_at(x, y)) {
  1709.         all_see_cell_weather(x, y);
  1710.         }
  1711.     }
  1712.     }
  1713. }
  1714.  
  1715. static void
  1716. mix_winds()
  1717. {
  1718.     int num, i, x, y, dir, x1, y1, wdir, wforce, sumx, sumy, n, t;
  1719.  
  1720.     num = (area.width * area.height) / 6;
  1721.  
  1722.     for (i = 0; i < num; ++i) {
  1723.     random_point(&x, &y);
  1724.     wdir = wind_dir_at(x, y);
  1725.     wforce = wind_force_at(x, y);
  1726.     sumx = dirx[wdir] * wforce;  sumy = diry[wdir] * wforce;
  1727.     n = 1;
  1728.     for_all_directions(dir) {
  1729.         if (point_in_dir(x, y, dir, &x1, &y1)) {
  1730.         wdir = wind_dir_at(x1, y1);
  1731.         wforce = wind_force_at(x1, y1);
  1732.         sumx += dirx[wdir] * wforce;  sumy += diry[wdir] * wforce;
  1733.         ++n;
  1734.         }
  1735.     }
  1736.     sumx = sumx / n;  sumy = sumy / n;
  1737.     wdir = approx_dir(sumx, sumy);
  1738.     wforce = distance(0, 0, sumx, sumy);
  1739.     t = terrain_at(x, y);
  1740.     wforce = max(wforce, t_wind_force_min(t));
  1741.     wforce = min(wforce, t_wind_force_max(t));
  1742.     if (wforce < 0)
  1743.       wforce = 0;
  1744.     set_wind_at(x, y, wdir, wforce);
  1745.     }
  1746. }
  1747.  
  1748. /* Update all sides with all weather changes that have happened at
  1749.    the given location. */
  1750.  
  1751. void
  1752. all_see_cell_weather(x, y)
  1753. int x, y;
  1754. {
  1755.     int oldview;
  1756.     Side *side;
  1757.  
  1758.     for_all_sides(side) {
  1759.     if (g_see_weather_always()
  1760.         ? (terrain_view(side, x, y) != UNSEEN)
  1761.         : (cover(side, x, y) > 0)) {
  1762.         oldview = temperature_view(side, x, y);
  1763.         if (oldview != temperature_at(x, y)) {
  1764.         set_temperature_view(side, x, y, temperature_at(x, y));
  1765.         update_cell_display(side, x, y, 34);
  1766.         }
  1767.         /* (should update cloud view here too) */
  1768.         oldview = wind_view(side, x, y);
  1769.         if (oldview != raw_wind_at(x, y)) {
  1770.         set_wind_view(side, x, y, raw_wind_at(x, y));
  1771.         update_cell_display(side, x, y, 35);
  1772.         }
  1773.     }
  1774.     }
  1775. }
  1776.  
  1777. /* Given that the spying unit is going to get info about other units at this
  1778.    location, figure out just what it is going to see. */
  1779.  
  1780. static void
  1781. spy_on_location(x, y)
  1782. int x, y;
  1783. {
  1784.     int qual;
  1785.     Unit *unit2, *occ;
  1786.  
  1787.     for_all_stack(x, y, unit2) {
  1788.         if (unit2->side != tmpunit->side) {
  1789.             qual = uu_spy_quality(tmpunit->type, unit2->type);
  1790.             if (probability(qual)) {
  1791.                 /* Spy got something, report it. */
  1792.                 /* (should be more worked-out, dunno exactly how) */
  1793.                 see_exact(tmpunit->side, x, y);
  1794.                 for_all_occupants(unit2, occ) {
  1795.                     /* (should get info about occupants) */
  1796.                 }
  1797.             }
  1798.         }
  1799.     }
  1800. }
  1801.  
  1802. /* Certain kinds of units can do spying for the side they're on. */
  1803.  
  1804. static void
  1805. run_spies()
  1806. {
  1807.     int chance;
  1808.     Unit *unit;
  1809.  
  1810.     if (any_spying < 0) {
  1811.     int u;
  1812.  
  1813.     any_spying = FALSE;
  1814.     for_all_unit_types(u) {
  1815.         if (u_spy_chance(u) > 0) {
  1816.         any_spying = TRUE;
  1817.         break;
  1818.         }
  1819.     }
  1820.     if (all_see_all)
  1821.       any_spying = FALSE;  /* override */
  1822.     }
  1823.     if (!any_spying)
  1824.       return;
  1825.     Dprintf("Running spies\n");
  1826.     for_all_units(unit) {
  1827.     if (is_active(unit)) {
  1828.         chance = u_spy_chance(unit->type);
  1829.         if (chance > 0) {
  1830.         if (xrandom(10000) < chance) {
  1831.             /* Spying is successful, decide how much was seen. */
  1832.             tmpunit = unit;
  1833.             apply_to_area(unit->x, unit->y, u_spy_range(unit->type),
  1834.                   spy_on_location);
  1835.         }
  1836.         }
  1837.     }
  1838.     }
  1839. }
  1840.  
  1841. /* Figure out ahead of time which random event methods to run. */
  1842.  
  1843. void
  1844. init_random_events()
  1845. {
  1846.     int i, k;
  1847.     Obj *randomeventlist, *rest, *evttype;
  1848.  
  1849.     numrandomevents = 0;
  1850.     randomeventlist = g_random_events();
  1851.     if (randomeventlist == NULL || randomeventlist == lispnil)
  1852.       return;
  1853.     for (rest = randomeventlist; rest != lispnil; rest = cdr(rest)) {
  1854.     evttype = car(rest);
  1855.     if (symbolp(evttype)) {
  1856.         k = keyword_code(c_string(evttype));
  1857.         for (i = 0; randomeventmethods[i].key != 0; ++i) {
  1858.         if (k == randomeventmethods[i].key
  1859.             && randomeventmethods[i].fn != NULL
  1860.             && (randomeventmethods[i].initfn == NULL
  1861.             || (*(randomeventmethods[i].initfn))())) {
  1862.             randomeventindices[numrandomevents++] = i;
  1863.         }
  1864.         }
  1865.     }
  1866.     }
  1867. }
  1868.  
  1869. /* Run the current cache of random event methods. */
  1870.  
  1871. static void
  1872. run_random_events()
  1873. {
  1874.     int i;
  1875.  
  1876.     if (numrandomevents > 0) {
  1877.     Dprintf("Running random events\n");
  1878.     for (i = 0; i < numrandomevents; ++i) {
  1879.         (*(randomeventmethods[randomeventindices[i]].fn))();
  1880.     }
  1881.     }
  1882. }
  1883.  
  1884. /* Test whether accidents can happen in this game. */
  1885.  
  1886. static int
  1887. init_accidents()
  1888. {
  1889.     int u, t;
  1890.     
  1891.     for_all_unit_types(u) {
  1892.         for_all_terrain_types(t) {
  1893.             if (ut_accident_vanish(u, t) > 0
  1894.         || ut_accident_hit(u, t) > 0)
  1895.           return TRUE;
  1896.         }
  1897.     }
  1898.     return FALSE;
  1899. }
  1900.  
  1901. /* Test each unit that is out in the open to see if a terrain-related
  1902.    accident happens to it.  Accidents can either kill the unit instantly or
  1903.    just damage it. */
  1904.  
  1905. static void
  1906. run_accidents()
  1907. {
  1908.     int t;
  1909.     Unit *unit;
  1910.  
  1911.     for_all_units(unit) {
  1912.     if (in_play(unit) && unit->transport == NULL) {
  1913.         t = terrain_at(unit->x, unit->y);
  1914.         if (xrandom(10000) < ut_accident_vanish(unit->type, t)) {
  1915.             /* Kill the unit outright. */
  1916.         kill_unit(unit, H_UNIT_VANISHED);
  1917.         /* should make a hevt */
  1918.         } else if (xrandom(10000) < ut_accident_hit(unit->type, t)) {
  1919.         /* Damage the unit. */
  1920.         unit->hp2 -= ut_accident_damage(unit->type, t);
  1921.         /* (should be able to pass reason to damage_unit) */
  1922.         damage_unit(unit, accident_dmg);
  1923.         }
  1924.     }
  1925.     }
  1926. }
  1927.  
  1928. /* Test whether attrition can ever happen in this game. */
  1929.  
  1930. static int
  1931. init_attrition()
  1932. {
  1933.     int u, t;
  1934.     
  1935.     for_all_unit_types(u) {
  1936.         for_all_terrain_types(t) {
  1937.             if (ut_attrition(u, t) > 0)
  1938.           return TRUE;
  1939.         }
  1940.     }
  1941.     return FALSE;
  1942. }
  1943.  
  1944. /* Attrition only takes out a few hp at a time, but can be deadly... */
  1945.  
  1946. static void
  1947. run_attrition()
  1948. {
  1949.     int u, dmg;
  1950.     Unit *unit;
  1951.  
  1952.     for_all_units(unit) {
  1953.     if (in_play(unit)) {
  1954.         u = unit->type;
  1955.         dmg = prob_fraction(ut_attrition(u, terrain_at(unit->x, unit->y)));
  1956.         /* This is like hit_unit but doesn't have other effects. */
  1957.         unit->hp2 -= dmg;
  1958.         /* (should be able to pass reason to damage_unit) */
  1959.         damage_unit(unit, accident_dmg);
  1960.     }
  1961.     }
  1962. }
  1963.  
  1964. /* Test whether revolts can ever happen in this game. */
  1965.  
  1966. static int
  1967. init_revolts()
  1968. {
  1969.     int u;
  1970.  
  1971.     for_all_unit_types(u) {
  1972.     if (u_revolt(u) > 0)
  1973.       return TRUE;
  1974.     }
  1975.     return FALSE;
  1976. }
  1977.  
  1978. /* Check each unit to see whether it revolts spontaneously.  While
  1979.    surrender is influenced by nearby units, revolt takes only the
  1980.    overall state of the world into account. */
  1981.  
  1982. static void
  1983. run_revolts()
  1984. {
  1985.     Unit *unit;
  1986.  
  1987.     for_all_units(unit) {
  1988.     if (in_play(unit) && u_revolt(unit->type) > 0) {
  1989.         unit_revolt(unit);
  1990.     }
  1991.     }
  1992. }
  1993.  
  1994. static void
  1995. unit_revolt(unit)
  1996. Unit *unit;
  1997. {
  1998.     int u = unit->type, ux = unit->x, uy = unit->y, chance, count;
  1999.     Side *oldside = unit->side, *newside;
  2000.  
  2001.     chance = u_revolt(u);
  2002.     if (0 /* affected by politics */) {
  2003.     }
  2004.     if (xrandom(10000) < chance) {
  2005.     if (0 /* leanings towards various sides */) {
  2006.         /* (should want to change to best-liked side) */
  2007.     } else {
  2008.         count = 0;
  2009.         while (count++ < 200) {
  2010.         newside = side_n(xrandom(numsides + 1));
  2011.         if (unit_allowed_on_side(unit, newside)
  2012.             && newside != oldside) {
  2013.             break;
  2014.         }
  2015.         }
  2016.     }
  2017.     /* Might not have been much of a revolt. :-) */
  2018.     if (newside == oldside)
  2019.       return;
  2020.     change_unit_side(unit, newside, H_UNIT_REVOLTED, NULL);
  2021.     see_exact(oldside, ux, uy);
  2022.     update_cell_display(oldside, ux, uy, TRUE);
  2023.     all_see_cell(ux, uy);
  2024.     }
  2025. }
  2026.  
  2027. /* Test whether surrenders can happen in this game. */
  2028.  
  2029. int *surrender_ranges;
  2030.  
  2031. static int
  2032. init_surrenders()
  2033. {
  2034.     int u1, u2, u3, range, rslt = FALSE;
  2035.     
  2036.     for_all_unit_types(u1) {
  2037.         for_all_unit_types(u2) {
  2038.             if (uu_surrender_chance(u1, u2) > 0) {
  2039.         rslt = TRUE;
  2040.         if (surrender_ranges == NULL)
  2041.           surrender_ranges = (int *) xmalloc(MAXUTYPES * sizeof(int));
  2042.         for_all_unit_types(u3) surrender_ranges[u3] = -1;
  2043.         range = uu_surrender_range(u1, u2);
  2044.         surrender_ranges[u1] = max(range, surrender_ranges[u1]);
  2045.             }
  2046.         }
  2047.     }
  2048.     return rslt;
  2049. }
  2050.  
  2051. static void
  2052. run_surrenders()
  2053. {
  2054.     Unit *unit;
  2055.  
  2056.     for_all_units(unit) {
  2057.     if (in_play(unit)) {
  2058.         unit_surrender(unit);
  2059.     }
  2060.     }
  2061. }
  2062.  
  2063. /* Units may surrender to enemy units that are visible nearby.
  2064.    Independents have to be treated specially, since they don't have a view
  2065.    to work from.  We sort of compute the view "on the fly". */
  2066.  
  2067. static void
  2068. unit_surrender(unit)
  2069. Unit *unit;
  2070. {
  2071.     int u = unit->type, dir, x1, y1, range /*, surrounded = TRUE */;
  2072.     Unit *unit2;
  2073.  
  2074.     range = surrender_ranges[u];
  2075.     if (range < 0) {
  2076.     /* This unit won't surrender, nothing to do. */
  2077.     } else if (range > 1) {
  2078.     /* (should write general case) */
  2079.     } else {
  2080.     /* Range is 0 or 1; check other units in this cell. */
  2081.     for_all_stack(unit->x, unit->y, unit2) {
  2082.         if (in_play(unit2)
  2083.         && unit2->side != unit->side
  2084.         && uu_surrender_chance(u, unit2->type) > 0
  2085.         && visible_to(unit, unit2)) {
  2086.         maybe_surrender_to(unit, unit2);
  2087.         }
  2088.     }
  2089.     /* Check on adjacent units. */
  2090.         if (range == 1) {
  2091.       for_all_directions(dir) {
  2092.         if (interior_point_in_dir(unit->x, unit->y, dir, &x1, &y1)) {
  2093.         for_all_stack(unit->x, unit->y, unit2) {
  2094.             if (in_play(unit2)
  2095.             && unit2->side != unit->side
  2096.             && uu_surrender_chance(u, unit2->type) > 0
  2097.             && visible_to(unit, unit2)) {
  2098.             maybe_surrender_to(unit, unit2);
  2099.             }
  2100.         }
  2101.         }
  2102.       }
  2103.     }
  2104.     }
  2105. }
  2106.  
  2107. /* Calculate whether one unit is visible to another, even if the other is independent. */
  2108.  
  2109. int
  2110. visible_to(unit, unit2)
  2111. Unit *unit, *unit2;
  2112. {
  2113.     int uview;
  2114.  
  2115.     if (all_see_all) {
  2116.     return TRUE;
  2117.     } else if (unit->side != NULL) {
  2118.         uview = unit_view(unit->side, unit2->x, unit2->y);
  2119.     return (uview != EMPTY && vtype(uview) == unit2->type);
  2120.     } else {
  2121.     /* (should be more careful to check see-chances) */
  2122.         if (distance(unit->x, unit->y, unit2->x, unit2->y) <= u_vision_range(unit->type))
  2123.           return TRUE;
  2124.         else
  2125.           return FALSE;
  2126.     }
  2127. }
  2128.  
  2129. static void
  2130. maybe_surrender_to(unit, unit2)
  2131. Unit *unit, *unit2;
  2132. {
  2133.     int chance;
  2134.  
  2135.     chance = uu_surrender_chance(unit->type, unit2->type);
  2136.     if (xrandom(10000) < chance) {
  2137.     /* (should be able to indicate that this was surrender, not capture */
  2138.     capture_unit(unit, unit2);
  2139.     }
  2140. }
  2141.  
  2142. int tmpexcess;
  2143.  
  2144. /* We've "found what we were searching for" when the excess to distribute
  2145.    is gone. */
  2146.  
  2147. static int
  2148. excess_left(x, y)
  2149. int x, y;
  2150. {
  2151.     return (tmpexcess > 0);
  2152. }
  2153.  
  2154. static void
  2155. try_transfer_to_cell(x, y)
  2156. int x, y;
  2157. {
  2158.     Unit *unit2, *occ;
  2159.  
  2160.     if (tmpexcess <= 0)
  2161.       return;
  2162.     for_all_stack(x, y, unit2) {
  2163.     if (in_play(unit2) && unit2->side == tmpunit->side) {
  2164.         try_transfer(tmpunit, unit2, tmpmtype);
  2165.     }
  2166.     }
  2167.     for_all_stack(x, y, unit2) {
  2168.     if (in_play(unit2) && unit2->side == tmpunit->side) {
  2169.         for_all_occupants(unit2, occ) {
  2170.         if (in_play(occ) && occ->side == tmpunit->side) {
  2171.             try_transfer(tmpunit, occ, tmpmtype);
  2172.         }
  2173.         }
  2174.     }
  2175.     }
  2176. }
  2177.  
  2178. static int
  2179. sharable_left(x, y)
  2180. int x, y;
  2181. {
  2182.     return tmpunit->supply[tmpmtype] > (um_storage_x(tmpunit->type, tmpmtype) / 2);
  2183. }
  2184.  
  2185. static void
  2186. try_sharing_with_cell(x, y)
  2187. int x, y;
  2188. {
  2189.     Unit *unit2, *occ;
  2190.  
  2191.     if (!sharable_left(x, y))
  2192.       return;
  2193.     for_all_stack(x, y, unit2) {
  2194.     if (in_play(unit2) && unit2->side == tmpunit->side) {
  2195.         try_sharing(tmpunit, unit2, tmpmtype);
  2196.     }
  2197.     }
  2198.     for_all_stack(x, y, unit2) {
  2199.     if (in_play(unit2) && unit2->side == tmpunit->side) {
  2200.         for_all_occupants(unit2, occ) {
  2201.         if (in_play(occ) && occ->side == tmpunit->side) {
  2202.             try_sharing(tmpunit, occ, tmpmtype);
  2203.         }
  2204.         }
  2205.     }
  2206.     }
  2207. }
  2208.  
  2209. /* The main routine does production, distribution, and discarding in order. */
  2210.  
  2211. static void
  2212. run_economy()
  2213. {
  2214.     int u, m, t, amt, dist, x, y, x1, y1, m1, m2;
  2215.     int prod, ptivity, stor, oldamt, newamt;
  2216.     int ttotals[MAXMTYPES], utotals[MAXMTYPES];
  2217.     Unit *unit;
  2218.     
  2219.     if (nummtypes == 0)
  2220.       return;
  2221.     if (any_unit_production < 0) {
  2222.     any_unit_production = FALSE;
  2223.     for_all_unit_types(u) {
  2224.         for_all_material_types(m) {
  2225.         if (max(um_base_production(u, m),
  2226.             um_occ_production(u, m)) > 0) {
  2227.             any_unit_production = TRUE;
  2228.             break;
  2229.         }
  2230.         }
  2231.     }
  2232.     }
  2233.     if (any_terrain_production < 0) {
  2234.     any_terrain_production = FALSE;
  2235.     for_all_terrain_types(t) {
  2236.         for_all_material_types(m) {
  2237.         if (tm_production(t, m) > 0) {
  2238.             any_terrain_production = TRUE;
  2239.             break;
  2240.         }
  2241.         }
  2242.     }
  2243.     }
  2244.     if (any_people_production < 0) {
  2245.     any_people_production = FALSE;
  2246.     for_all_material_types(m1) {
  2247.         if (m_people(m1) > 0) {
  2248.         for_all_material_types(m2) {
  2249.             if (mm_people_production(m1, m2) > 0) {
  2250.             any_people_production = TRUE;
  2251.             break;
  2252.             }
  2253.         }
  2254.         }
  2255.     }
  2256.     }
  2257.     if (!any_unit_production
  2258.     && !any_terrain_production
  2259.     && !any_people_production)
  2260.       return;
  2261.     /* (should find other reasons not to run this) */
  2262.     Dprintf("Running economy\n");
  2263.     for_all_material_types(m)
  2264.       ttotals[m] = utotals[m] = 0;
  2265.     /* Make new materials but don't clip to storage capacities yet. */
  2266.     if ((any_terrain_production || any_people_production)
  2267.     && any_cell_materials_defined()) {
  2268.     for_all_material_types(m) {
  2269.         if (cell_material_defined(m)) {
  2270.         for_all_cells(x, y) {
  2271.             if (any_terrain_production) {
  2272.             t = terrain_at(x, y);
  2273.             prod = tm_production(t, m);
  2274.             if (prod > 0) {
  2275.                 oldamt = material_at(x, y, m);
  2276.                 newamt = oldamt + prod;
  2277.                 set_material_at(x, y, m, newamt);
  2278.                 if (Debug) {
  2279.                 stor = tm_storage_x(t, m);
  2280.                 if (newamt > stor)
  2281.                   ttotals[m] += (newamt - stor);
  2282.                 }
  2283.             }
  2284.             }
  2285.             if (any_people_production) {
  2286.             for_all_material_types(m1) {
  2287.                 if (m_people(m1) > 0) {
  2288.                 prod = mm_people_production(m1, m);
  2289.                 if (prod > 0) {
  2290.                     oldamt = material_at(x, y, m);
  2291.                     newamt = oldamt + prod;
  2292.                     set_material_at(x, y, m, newamt);
  2293.                     if (Debug) {
  2294.                     stor = tm_storage_x(t, m);
  2295.                     if (newamt > stor)
  2296.                       ttotals[m] += (newamt - stor);
  2297.                     }
  2298.                 }
  2299.                 }
  2300.             }
  2301.             }
  2302.         }
  2303.         }
  2304.     }
  2305.     }
  2306.     if (any_unit_production) {
  2307.     for_all_units(unit) {
  2308.         if (in_play(unit) && completed(unit)) {
  2309.         u = unit->type;
  2310.         for_all_material_types(m) {
  2311.             t = terrain_at(unit->x, unit->y);
  2312.             prod = base_production(unit, m);
  2313.             if (prod > 0) {
  2314.             ptivity = ut_productivity(u, t);
  2315.             /* Note that we've switched to hundredths. */
  2316.             ptivity = max(ptivity, um_productivity_min(u, m));
  2317.             ptivity = min(ptivity, um_productivity_max(u, m));
  2318.             amt = prob_fraction(prod * ptivity);
  2319.             unit->supply[m] += amt;
  2320.             if (Debug && unit->supply[m] > um_storage_x(u, m))
  2321.               utotals[m] += (unit->supply[m] - um_storage_x(u, m));
  2322.             }
  2323.         }
  2324.         }
  2325.     }
  2326.     }
  2327.     Dprintf("Overflow is:");
  2328.     Dprintf("  (for terrain)");
  2329.     for_all_material_types(m) Dprintf(" %d", ttotals[m]);
  2330.     Dprintf("  (for units)");
  2331.     for_all_material_types(m) Dprintf(" %d", utotals[m]);
  2332.     Dprintf("\n");
  2333.     /* Move stuff around - try to get rid of any excess. */
  2334.     /* (should also do cell-cell, cell-unit, unit-cell xfers) */
  2335.     for_all_units(unit) {
  2336.     if (in_play(unit) && !indep(unit)) {
  2337.         u = unit->type;
  2338.         for_all_material_types(m) {
  2339.         stor = um_storage_x(u, m);
  2340.         if (unit->supply[m] > stor) {
  2341.             dist = um_outlength(u, m);
  2342.             if (dist >= 0) {
  2343.                 tmpunit = unit;
  2344.                 tmpmtype = m;
  2345.                 tmpexcess = unit->supply[m] - stor;
  2346.             search_and_apply(unit->x, unit->y, dist, excess_left,
  2347.                      &x1, &y1, 1,
  2348.                      try_transfer_to_cell, 999999);
  2349.             }
  2350.         }
  2351.         }
  2352.     }
  2353.     }
  2354.     /* Throw away excess that can't be stored anywhere. */
  2355.     for_all_material_types(m)
  2356.       ttotals[m] = utotals[m] = 0;
  2357.     if (any_cell_materials_defined()) {
  2358.     for_all_material_types(m) {
  2359.         if (cell_material_defined(m)) {
  2360.         for_all_cells(x, y) {
  2361.             t = terrain_at(x, y);
  2362.             stor = tm_storage_x(t, m);
  2363.             oldamt = material_at(x, y, m);
  2364.             newamt = min(oldamt, stor);
  2365.             set_material_at(x, y, m, newamt);
  2366.             if (Debug && newamt < oldamt)
  2367.               ttotals[m] += (oldamt - newamt);
  2368.         }
  2369.         }
  2370.     }
  2371.     }
  2372.     for_all_units(unit) {
  2373.     u = unit->type;
  2374.     for_all_material_types(m) {
  2375.         stor = um_storage_x(u, m);
  2376.         oldamt = unit->supply[m];
  2377.         newamt = min(oldamt, stor);
  2378.         unit->supply[m] = newamt;
  2379.         if (Debug && newamt < oldamt)
  2380.           utotals[m] += (oldamt - newamt);
  2381.     }
  2382.     }
  2383.     Dprintf("Discarded ");
  2384.     Dprintf("  (for terrain)");
  2385.     for_all_material_types(m) Dprintf(" %d", ttotals[m]);
  2386.     Dprintf("  (for units)");
  2387.     for_all_material_types(m) Dprintf(" %d", utotals[m]);
  2388.     Dprintf("\n");
  2389.     /* This next phase is for sharing of scarcer supplies. */
  2390.     for_all_units(unit) {
  2391.     if (in_play(unit) && !indep(unit)) {
  2392.         u = unit->type;
  2393.         for_all_material_types(m) {
  2394.         dist = um_outlength(u, m);
  2395.         if (dist >= 0) {
  2396.             tmpunit = unit;
  2397.             tmpmtype = m;
  2398.             search_and_apply(unit->x, unit->y, dist, sharable_left,
  2399.                      &x1, &y1, 1,
  2400.                      try_sharing_with_cell, 999999);
  2401.         }
  2402.         }
  2403.     }
  2404.     }
  2405.     /* Finally, reset supply alarms. */
  2406.     for_all_units(unit) {
  2407.     if (in_play(unit) && unit->plan != NULL) {
  2408.         /* (should probably be a subr) */
  2409.         if (unit->plan->supply_is_low
  2410.         && !past_halfway_point(unit)) {
  2411.         unit->plan->supply_alarm = TRUE;
  2412.         unit->plan->supply_is_low = FALSE;
  2413.             update_unit_display(unit->side, unit, TRUE); 
  2414.         }
  2415.     }
  2416.     }
  2417. }
  2418.  
  2419. static int
  2420. base_production(unit, m)
  2421. Unit *unit;
  2422. int m;
  2423. {
  2424.     int u = unit->type, occprod;
  2425.  
  2426.     if (unit->transport) {
  2427.     occprod = um_occ_production(u, m);
  2428.     return (occprod >= 0 ? occprod : um_base_production(u, m));
  2429.     } else {
  2430.     return um_base_production(u, m);
  2431.     }
  2432. }
  2433.  
  2434. /* Give away supplies, but save enough to stay alive for a couple turns. */
  2435.  
  2436. static void
  2437. try_transfer(from, to, m)
  2438. Unit *from, *to;
  2439. int m;
  2440. {
  2441.     int oldsupply = from->supply[m];
  2442.  
  2443.     try_transfer_aux(from, to, m);
  2444.     tmpexcess -= (oldsupply - from->supply[m]);
  2445. }
  2446.  
  2447. /* Note that this may be called on newly-completed units during a turn. */
  2448.  
  2449. void
  2450. try_sharing(from, to, m)
  2451. Unit *from, *to;
  2452. int m;
  2453. {
  2454.     try_transfer_aux(from, to, m);
  2455. }
  2456.  
  2457. /* Material redistribution uses this routine to move supplies around
  2458.    between units far apart or on the same cell. Try to do reasonable
  2459.    things with the materials.  Net producers are much more willing to
  2460.    give away supplies than net consumers. */
  2461.  
  2462. static void
  2463. try_transfer_aux(from, to, m)
  2464. Unit *from, *to;
  2465. int m;
  2466. {
  2467.     int nd, u = from->type, u2 = to->type, fromrate, torate;
  2468.  
  2469.     if (from != to &&
  2470.     um_inlength(u2, m) >= distance(from->x, from->y, to->x, to->y)) {
  2471.     if (completed(to)) {
  2472.         /* Try for the transfer only if we're below capacity. */
  2473.         nd = um_storage_x(u2, m) - to->supply[m];
  2474.         if (nd  > 0) {
  2475.         if ((um_base_production(u, m) > um_base_consumption(u, m))
  2476.             || (survival_time(to) < 3)
  2477.             || (um_storage_x(u, m) * 4 >= um_storage_x(u2, m))) {
  2478.             if (can_satisfy_need(from, m, nd)) {
  2479.             transfer_supply(from, to, m, nd);
  2480.             } else if (can_satisfy_need(from, m, max(1, nd/2))) {
  2481.             transfer_supply(from, to, m, max(1, nd/2));
  2482.             } else if (from->supply[m] > um_storage_x(u, m)) {
  2483.             transfer_supply(from, to, m,
  2484.                     (from->supply[m]
  2485.                      - um_storage_x(u, m)));
  2486.             }
  2487.         } else {
  2488.             fromrate = u_speed(u) * um_consumption_per_move(u, m) * 3;
  2489.             fromrate = max(1, fromrate);
  2490.             torate = u_speed(u2) * um_consumption_per_move(u2, m) * 3;
  2491.             torate = max(1, torate);
  2492.             if ((from->supply[m] / fromrate)
  2493.             > (to->supply[m] / torate)) {
  2494.             transfer_supply(from, to, m,
  2495.                     min(nd, (8 + from->supply[m]) / 9));
  2496.             }
  2497.         }
  2498.         }
  2499.     } else {
  2500.         /* Incomplete units don't need supply, but they are a
  2501.            handy overflow mepository. */
  2502.         if (from->supply[m] > um_storage_x(u, m)
  2503.         && to->supply[m] < um_storage_x(u2, m)) {
  2504.         /* Calculate the limit on how much we can transfer usefully. */
  2505.         nd = min(um_storage_x(u2, m) - to->supply[m],
  2506.              from->supply[m] - um_storage_x(u, m));
  2507.         transfer_supply(from, to, m, nd);
  2508.         }
  2509.     }
  2510.     }
  2511. }
  2512.  
  2513. /* This estimates if a need can be met.  Note that total transfer of
  2514.    requested amount is not a good idea, since the supplies might be
  2515.    essential to the unit that has them first.  If we're more than half
  2516.    full, or the request is very small, then we can spare it. */
  2517.  
  2518. /* (should replace with doctrine/plan controls, check underlying terrain) */
  2519.  
  2520. static int
  2521. can_satisfy_need(unit, m, need)
  2522. Unit *unit;
  2523. int m, need;
  2524. {
  2525.     int supp = unit->supply[m];
  2526.     int stor = um_storage_x(unit->type, m);
  2527.  
  2528.     return (((2 * supp > stor) && (need < ((supp * 4) / 5)))
  2529.         || (need < stor / 5));
  2530. }
  2531.  
  2532. /* Do everything associated with the end of a turn. */
  2533.  
  2534. static void
  2535. run_turn_end()
  2536. {
  2537.     finish_movement();
  2538.     run_people_consumption();
  2539.     run_cell_consumption();
  2540.     run_unit_base_consumption();
  2541.     run_environment_effects();
  2542.     run_people_side_changes();
  2543.     /* This should come after other people-related computations,
  2544.        since this only constrains generic overcrowding. */
  2545.     run_people_limits();
  2546.     flush_dead_units();
  2547.     check_post_turn_scores();
  2548.     test_agreements();
  2549.     run_disappearances();
  2550. #ifdef DEBUGGING
  2551.     if (Debug)
  2552.       report_malloc();
  2553. #endif /* DEBUGGING */
  2554. }
  2555.  
  2556. /* Handle consumption by people. */
  2557.  
  2558. static void
  2559. run_people_consumption()
  2560. {
  2561.     int x, y, m1, m2, t, consum, oldamt, newamt, newtype;
  2562.  
  2563.     /* Precompute whether any people consumption ever happens. */
  2564.     if (any_people_consumption < 0) {
  2565.     int mm1, mm2;
  2566.  
  2567.     any_people_consumption = FALSE;
  2568.     for_all_material_types(mm1) {
  2569.         for_all_material_types(mm2) {
  2570.             if (mm_people_consumption(mm1, mm2) > 0) {
  2571.             any_people_consumption = TRUE;
  2572.             break;
  2573.             }
  2574.         }
  2575.         if (any_people_consumption)
  2576.           break;
  2577.     }
  2578.     Dprintf("Have consumption by people.\n");
  2579.     }
  2580.     if (!any_people_consumption)
  2581.       return;
  2582.     Dprintf("Running people consumption\n");
  2583.     if (any_cell_materials_defined()) {
  2584.     for_all_material_types(m1) {
  2585.         if (cell_material_defined(m1)) {
  2586.         for_all_material_types(m2) {
  2587.             if (cell_material_defined(m2)) {
  2588.             consum = mm_people_consumption(m1, m2);
  2589.             if (consum > 0) {
  2590.                 for_all_cells(x, y) {
  2591.                 oldamt = material_at(x, y, m2);
  2592.                 newamt = oldamt - consum;
  2593.                 if (newamt < 0) {
  2594.                     newamt = 0;
  2595.                     /* Check for exhaustion. */
  2596.                     /* (should share with cell consumption) */
  2597.                     t = terrain_at(x, y);
  2598.                     if (probability(tm_change_on_exhaust(t, m2)) &&
  2599.                     tm_exhaust_type(t, m2) != NONTTYPE) {
  2600.                     newtype = tm_exhaust_type(t, m2);
  2601.                     /* Change the terrain's type. */
  2602.                     change_terrain_type(x, y, newtype);
  2603.                     }
  2604.                 }
  2605.                 set_material_at(x, y, m2, newamt);
  2606.                 }
  2607.             }
  2608.             }
  2609.         }
  2610.         }
  2611.     }
  2612.     }
  2613. }
  2614.  
  2615. /* Handle consumption by terrain. */
  2616.  
  2617. static void
  2618. run_cell_consumption()
  2619. {
  2620.     int x, y, t, m, consum, oldamt, newamt, willchange, newtype;
  2621.  
  2622.     /* Precompute whether any cell base consumption ever happens. */
  2623.     if (any_cell_consumption < 0) {
  2624.     int t2, m2;
  2625.  
  2626.     any_cell_consumption = FALSE;
  2627.     for_all_terrain_types(t2) {
  2628.         for_all_material_types(m2) {
  2629.             if (tm_consumption(t2, m2) > 0) {
  2630.             any_cell_consumption = TRUE;
  2631.             break;
  2632.             }
  2633.         }
  2634.         if (any_cell_consumption)
  2635.           break;
  2636.     }
  2637.     Dprintf("Have consumption by cells.\n");
  2638.     }
  2639.     if (!any_cell_consumption)
  2640.       return;
  2641.     Dprintf("Running cell consumption\n");
  2642.     if (any_cell_materials_defined()) {
  2643.     for_all_cells(x, y) {
  2644.         t = terrain_at(x, y);
  2645.         willchange = FALSE;
  2646.         for_all_material_types(m) {
  2647.         if (cell_material_defined(m)) {
  2648.             consum = tm_consumption(t, m);
  2649.             oldamt = material_at(x, y, m);
  2650.             newamt = oldamt - consum;
  2651.             if (newamt < 0) {
  2652.             newamt = 0;
  2653.             /* Check for exhaustion. */
  2654.             if (!willchange &&
  2655.                 probability(tm_change_on_exhaust(t, m)) &&
  2656.                 tm_exhaust_type(t, m) != NONTTYPE) {
  2657.                 willchange = TRUE;
  2658.                 newtype = tm_exhaust_type(t, m);
  2659.             }
  2660.             }
  2661.             set_material_at(x, y, m, newamt);
  2662.         }
  2663.         }
  2664.         if (willchange) {
  2665.             /* Change the terrain's type. */
  2666.             change_terrain_type(x, y, newtype);
  2667.         }
  2668.     }
  2669.     }
  2670. }
  2671.  
  2672. /* Handle base consumption by units. */
  2673.  
  2674. static void
  2675. run_unit_base_consumption()
  2676. {
  2677.     Unit *unit;
  2678.  
  2679.     /* Precompute whether any base consumption ever happens. */
  2680.     if (any_unit_base_consumption < 0) {
  2681.     int u, m;
  2682.  
  2683.     any_unit_base_consumption = FALSE;
  2684.     for_all_unit_types(u) {
  2685.         for_all_material_types(m) {
  2686.             if (um_base_consumption(u, m) > 0) {
  2687.             any_unit_base_consumption = TRUE;
  2688.             break;
  2689.             }
  2690.         }
  2691.         if (any_unit_base_consumption)
  2692.           break;
  2693.     }
  2694.     Dprintf("Have consumption by units.\n");
  2695.     }
  2696.     if (!any_unit_base_consumption)
  2697.       return;
  2698.     Dprintf("Running unit consumption\n");
  2699.     for_all_units(unit) {
  2700.     if (is_active(unit)) {
  2701.         unit_consumes(unit);
  2702.     }
  2703.     }
  2704. }
  2705.  
  2706. /* Consume the constant overhead part of supply consumption. */
  2707. /* Usage by movement is subtracted from overhead first. */
  2708.  
  2709. static void
  2710. unit_consumes(unit)
  2711. Unit *unit;
  2712. {
  2713.     int u = unit->type, m, usedup, consump, tempeff, checkstarve = FALSE;
  2714.     Obj *effect;
  2715.  
  2716.     if (alive(unit)) {    
  2717.     for_all_material_types(m) {
  2718.         if (um_base_consumption(u, m) > 0 &&
  2719.         !(unit->transport != NULL
  2720.           && um_consumption_as_occupant(u, m) == 0)) {
  2721.         /* Calculate what was already consumed by movement. */
  2722.         usedup = 0;
  2723.         if (unit->act != NULL)
  2724.           usedup = unit->act->actualmoves * um_consumption_per_move(u, m);
  2725.         consump = um_base_consumption(u, m);
  2726.         /* If being transported, modify the base consumption. */
  2727.         if (unit->transport != NULL)
  2728.           consump = (consump * um_consumption_as_occupant(u, m)) / 100;
  2729.         /* Modify consumption if temperature effects. */
  2730.         effect = u_consume_temp_effect(u);
  2731. #if 0        /* (should think about this code a bit more) */
  2732.         if (temperatures_defined() && effect != lispnil) {
  2733.             tempeff = interpolate_in_list(temperature_at(unit->x, unit->y), effect, FALSE, 999);
  2734.             consump = (consump * tempeff) / 100;
  2735.         }
  2736. #endif
  2737.         /* Subtract consumption that was not already used up in movement. */
  2738.         if (usedup < consump)
  2739.           unit->supply[m] -= (consump - usedup);
  2740.         /* Don't let supply go below zero. */
  2741.         if (unit->supply[m] <= 0) {
  2742.             unit->supply[m] = 0;
  2743.             checkstarve = TRUE;
  2744.         }
  2745.         }
  2746.     }
  2747.     }
  2748.     if (checkstarve)
  2749.       maybe_starve(unit, TRUE);
  2750.     if (alive(unit)
  2751.         && unit->plan
  2752.         && !unit->plan->supply_is_low
  2753.         && past_halfway_point(unit)
  2754.         ) {
  2755.         unit->plan->supply_is_low = TRUE;
  2756.         update_unit_display(unit->side, unit, TRUE); 
  2757.     }
  2758. }
  2759.  
  2760. /* What happens to a unit that runs out of supplies.  If it can survive
  2761.    on nothing, then there may be a few turns of grace, depending on
  2762.    how the dice roll... */
  2763.  
  2764. void
  2765. maybe_starve(unit, partial)
  2766. Unit *unit;
  2767. int partial;
  2768. {
  2769.     int u = unit->type, m, starv, oneloss, hploss = 0;
  2770.  
  2771.     for_all_material_types(m) {
  2772.     if (unit->supply[m] <= 0 && !in_supply(unit, m)) {
  2773.         starv = um_hp_per_starve(u, m);
  2774.         if (starv > 0) {
  2775.         oneloss = prob_fraction(starv);
  2776.         hploss = max(hploss, oneloss);
  2777.         }
  2778.     }
  2779.     }
  2780.     if (hploss > 0) {
  2781.     if (hploss >= unit->hp) {
  2782.         /* (should let occupants try to escape first) */
  2783.         kill_unit(unit, H_UNIT_STARVED);
  2784.     } else if (partial) {
  2785.         unit->hp -= hploss;
  2786.         unit->hp2 -= hploss;
  2787.         /* (should do other hp loss consequences) */
  2788.         /* (use generic damage routine?) */
  2789.     }
  2790.     }
  2791. }
  2792.  
  2793. /* Check if the unit has ready access to a source of supplies. */
  2794.  
  2795. /* (should be more sophisticated and account for supply lines etc) */
  2796.  
  2797. static int
  2798. in_supply(unit, m)
  2799. Unit *unit;
  2800. int m;
  2801. {
  2802.     if (unit->transport != NULL) {
  2803.         if (unit->transport->supply[m] > 0)
  2804.       return TRUE;
  2805.     }
  2806.     return FALSE;
  2807. }
  2808.  
  2809. /* Some types of units can become completed and grow to full size
  2810.    automatically when they get to a certain point. */
  2811.  
  2812. static void
  2813. run_self_builds()
  2814. {
  2815.     int u, cpper;
  2816.     Unit *unit;
  2817.  
  2818.     if (any_self_builds < 0) {
  2819.     any_self_builds = FALSE;
  2820.     for_all_unit_types(u) {
  2821.         if (u_cp_per_self_build(u) > 0) {
  2822.         any_self_builds = TRUE;
  2823.         break;
  2824.         }
  2825.     }
  2826.     }
  2827.     if (!any_self_builds)
  2828.       return;
  2829.     Dprintf("Running self builds\n");
  2830.     for_all_units(unit) {
  2831.     u = unit->type;
  2832.     if (in_play(unit)
  2833.         && !fullsized(unit)
  2834.         && (cpper = u_cp_per_self_build(u)) > 0
  2835.         && unit->cp >= u_cp_to_self_build(u)) {
  2836.         unit->cp += cpper;
  2837.         if (unit->cp > u_cp(u)) unit->cp = u_cp(u);
  2838.         if (completed(unit)) {
  2839.         make_unit_complete(unit);
  2840.         } else {
  2841.             /* Let the player know that progress was made. */
  2842.         update_unit_display(unit->side, unit, TRUE);
  2843.         }
  2844.     }
  2845.     }
  2846. }
  2847.  
  2848. static void
  2849. run_environment_effects()
  2850. {
  2851.     int err, dmg;
  2852.     Unit *unit;
  2853.     Obj *attrition;
  2854.  
  2855.     if (!temperatures_defined())
  2856.       return;
  2857.     /* (should check if temperature attrition ever non-nil) */
  2858.     Dprintf("Running environmental effects\n");
  2859.     for_all_units(unit) {
  2860.     if (is_active(unit)) {
  2861.         attrition = u_temp_attrition(unit->type);
  2862.         if (attrition != lispnil) {
  2863.         err = interpolate_in_list(temperature_at(unit->x, unit->y), attrition, &dmg);
  2864.         if (err != 0) {
  2865.             dmg = 0;
  2866.         }
  2867.         damage_unit_with_temperature(unit, dmg);
  2868.         }
  2869.         /* (should check for storm damage here?) */
  2870.     }
  2871.     }
  2872. }
  2873.  
  2874. static void
  2875. damage_unit_with_temperature(unit, dmg)
  2876. Unit *unit;
  2877. int dmg;
  2878. {
  2879.     int n;
  2880.  
  2881.     n = prob_fraction(dmg);
  2882.     if (n >= unit->hp) {
  2883.     notify(unit->side, "%s dies from excessive temperatures",
  2884.            unit_handle(unit->side, unit));
  2885.     /* should have a different hevt type - this will be recorded as a combat death */
  2886.     kill_unit(unit, H_UNIT_DIED_FROM_TEMPERATURE);
  2887.     } else if (n > 0) {
  2888.     notify(unit->side, "%s loses %d HP due to excessive temperatures",
  2889.         unit_handle(unit->side, unit), n);
  2890.     unit->hp -= n;
  2891.     unit->hp2 -= n;
  2892.     update_unit_display(unit->side, unit, TRUE);
  2893.     }
  2894. }
  2895.  
  2896. static void
  2897. run_people_side_changes()
  2898. {
  2899.     int x, y, u, t;
  2900.     Unit *unit;
  2901.  
  2902.     if (!people_sides_defined())
  2903.       return;
  2904.     if (any_people_side_changes < 0) {
  2905.     any_people_surrenders = (int *) xmalloc(numutypes * sizeof(int));
  2906.     any_people_side_changes = FALSE;
  2907.     for_all_unit_types(u) {
  2908.         for_all_terrain_types(t) {
  2909.         if (ut_people_surrender(u, t) > 0) {
  2910.             any_people_side_changes = TRUE;
  2911.             any_people_surrenders[u] = TRUE;
  2912.             break;
  2913.         }
  2914.         }
  2915.     }
  2916.     }
  2917.     if (!any_people_side_changes)
  2918.       return;
  2919.     for_all_cells(x, y) {
  2920.     if (unit_at(x, y) != NULL) {
  2921.         for_all_stack(x, y, unit) {
  2922.         /* The people here may change sides. */
  2923.             u = unit->type;
  2924.         if (any_people_surrenders[u]
  2925.             && probability(people_surrender_chance(u, x, y))) {
  2926.             change_people_side_around(x, y, u, unit->side);
  2927.         }
  2928.         }
  2929.     } else {
  2930.         /* Unoccupied cells might see population revert. */
  2931.         /* (this would need multiple-loyalty pops) */
  2932.     }
  2933.     }
  2934. }
  2935.  
  2936. int
  2937. people_surrender_chance(u, x, y)
  2938. int u, x, y;
  2939. {
  2940.     int m, chance, peop;
  2941.  
  2942.     chance = ut_people_surrender(u, terrain_at(x, y));
  2943.     /* Modify the basic chance according to people types, if present. */
  2944.     if (any_cell_materials_defined()) {
  2945.     for_all_material_types(m) {
  2946.         if (m_people(m) > 0
  2947.         && cell_material_defined(m)) {
  2948.         peop = material_at(x, y, m);
  2949.         if (peop > 0) {
  2950.             chance = (chance * um_people_surrender(u, m)) / 100;
  2951.         }
  2952.         }
  2953.     }
  2954.     }
  2955.     return chance;
  2956. }
  2957.  
  2958. void
  2959. change_people_side_around(x, y, u, side)
  2960. int x, y, u;
  2961. Side *side;
  2962. {
  2963.     int pop = people_side_at(x, y), s = side_number(side), dir, x1, y1;
  2964.     Side *oldside;
  2965.  
  2966.     if (pop != NOBODY
  2967.         && pop != s
  2968.         && !trusted_side(side, side_n(pop))) {
  2969.         oldside = side_n(pop);
  2970.     set_people_side_at(x, y, s);
  2971.     update_cell_display_all_sides(x, y, TRUE);
  2972.     for_all_directions(dir) {
  2973.         if (interior_point_in_dir(x, y, dir, &x1, &y1)) {
  2974.         update_cell_display_all_sides(x1, y1, TRUE);
  2975.         }
  2976.     }
  2977.     /* Previous side loses its free coverage. */
  2978.     if (oldside) {
  2979.         add_cover(oldside, x, y, -1);
  2980.         /* Update coverage display. */
  2981.         update_cell_display(oldside, x, y, 36);
  2982.     }
  2983.     }
  2984.     /* (should add ability to change adjacent cells also) */
  2985. }
  2986.  
  2987. /* See if the numbers of individuals in a cell exceeds the max, and migrate or
  2988.    remove so as to bring the numbers back in line. */
  2989.  
  2990. static void
  2991. run_people_limits()
  2992. {
  2993.     int m, t, x, y, num, ratio, amt, newamt;
  2994.     
  2995.     if (any_people_max < 0) {
  2996.     any_people_max = FALSE;
  2997.     for_all_terrain_types(t) {
  2998.         if (t_people_max(t) >= 0) {
  2999.         any_people_max = TRUE;
  3000.         break;
  3001.         }
  3002.     }
  3003.     }
  3004.     if (!any_people_max)
  3005.       return;
  3006.     if (!any_cell_materials_defined())
  3007.       return;
  3008.     for_all_cells(x, y) {
  3009.     t = terrain_at(x, y);
  3010.     if (t_people_max(t) >= 0) {
  3011.         num = num_people_at(x, y);
  3012.         if (num > t_people_max(t)) {
  3013.         /* Too many people here, trim them down. */
  3014.         /* Compute the ratio of limit to actual number.
  3015.            (Note that actual number is guaranteed to be nonzero.) */
  3016.         ratio = (t_people_max(t) * 100) / num;
  3017.         for_all_material_types(m) {
  3018.             if (m_people(m) > 0
  3019.             && cell_material_defined(m)) {
  3020.             amt = material_at(x, y, m);
  3021.             if (amt > 0) {
  3022.                 newamt = (amt * ratio) / 100;
  3023.                 set_material_at(x, y, m, newamt);
  3024.                 /* (should update sides?) */
  3025.             }
  3026.             }
  3027.         }
  3028.         }
  3029.     }
  3030.     }
  3031. }
  3032.  
  3033. /* (generic routine) */
  3034.  
  3035. int
  3036. num_people_at(x, y)
  3037. int x, y;
  3038. {
  3039.     int m, num;
  3040.  
  3041.     num = 0;
  3042.     for_all_material_types(m) {
  3043.     if (cell_material_defined(m)) {
  3044.         num += material_at(x, y, m) * m_people(m);
  3045.     }
  3046.     }
  3047.     return num;
  3048. }
  3049.  
  3050. static void
  3051. update_cell_display_all_sides(x, y, rightnow)
  3052. int x, y, rightnow;
  3053. {
  3054.     Side *side;
  3055.  
  3056.     for_all_sides(side) {
  3057.     /* (Testing for unit visibility is not quite right, but close
  3058.        enough for now.) */
  3059.     if (side->ingame && units_visible(side, x, y)) {
  3060.         update_cell_display(side, x, y, rightnow);
  3061.     }
  3062.     }
  3063. }
  3064.  
  3065. /* See if it's time for any scheduled arrivals to appear. */
  3066.  
  3067. static void
  3068. run_appearances()
  3069. {
  3070.     int curturn, nx, ny, nw, nh, nx1, ny1;
  3071.     Unit *unit, *transport;
  3072.  
  3073.     if (any_appearances < 0) {
  3074.         any_appearances = FALSE;
  3075.     for_all_units(unit) {
  3076.         if (unit->cp < 0 && unit_appear_turn(unit) >= 0) {
  3077.         any_appearances = TRUE;
  3078.         break;
  3079.         }
  3080.     }
  3081.     }
  3082.     if (!any_appearances)
  3083.       return;
  3084.     Dprintf("Running appearances\n");
  3085.     curturn = g_turn();
  3086.     for_all_units(unit) {
  3087.         /* See if now time for a unit to appear. */
  3088.         if (unit->cp < 0 && unit_appear_turn(unit) >= 0) {
  3089.         if (unit_appear_turn(unit) <= curturn) {
  3090.         /* Set the unit to its correct cp. */
  3091.         unit->cp = (- unit->cp);
  3092.         /* Get the base location at which it will appear. */
  3093.         nx = (- unit->prevx);  ny = (- unit->prevy);
  3094.         if (unit_appear_x(unit) >= 0 && unit_appear_y(unit) >= 0) {
  3095.             /* Appear at a random location around nx,ny. */
  3096.             nw = unit_appear_x(unit);  nh = unit_appear_y(unit);
  3097.             if (random_point_in_area(nx, ny, nw, nh, &nx1, &ny1)) {
  3098.             nx = nx1;  ny = ny1;
  3099.             }
  3100.         }
  3101.         /* Do the usual steps to place the unit. */
  3102.         /* (should be able to retry with diff loc if nw or nh > 0) */
  3103.         if (inside_area(nx, ny)) {
  3104.             if (can_occupy_cell(unit, nx, ny)) {
  3105.             enter_cell(unit, nx, ny);
  3106.             } else {
  3107.             /* Search this cell for units to enter. */
  3108.             for_all_stack(nx, ny, transport) {
  3109.                 if (unit->side == transport->side
  3110.                 && can_occupy(unit, transport)) {
  3111.                 enter_transport(unit, transport);
  3112.                 break;
  3113.                 }
  3114.             }
  3115.             /* We've got a problem, make the unit wait for next turn;
  3116.                since the appearance turn test is "<=", will just try again. */
  3117.             unit->cp = (- unit->cp);
  3118.             }
  3119.         } else {
  3120.             /* loc of reinforcement is messed up */
  3121.         }
  3122.         init_unit_actorstate(unit, FALSE);
  3123.         init_unit_plan(unit);
  3124.         }
  3125.         }
  3126.     }
  3127. }
  3128.  
  3129. static void
  3130. run_disappearances()
  3131. {
  3132.     int curturn;
  3133.     Unit *unit;
  3134.  
  3135.     if (any_disappearances < 0) {
  3136.         any_disappearances = FALSE;
  3137.     for_all_units(unit) {
  3138.         if (unit_disappear_turn(unit) >= 0) {
  3139.         any_disappearances = TRUE;
  3140.         break;
  3141.         }
  3142.     }
  3143.     }
  3144.     if (!any_disappearances)
  3145.       return;
  3146.     Dprintf("Running disappearances\n");
  3147.     curturn = g_turn();
  3148.     for_all_units(unit) {
  3149.         /* See if now time for a unit to disappear. */
  3150.         if (in_play(unit) && unit_disappear_turn(unit) >= 0) {
  3151.         if (unit_disappear_turn(unit) <= curturn) {
  3152.         /* (should eject occupants first if possible) */
  3153.         kill_unit(unit, H_UNIT_LEFT_WORLD);
  3154.         }
  3155.     }
  3156.     }
  3157. }
  3158.  
  3159. /* Some types of units recover lost hp spontaneously. */
  3160.  
  3161. static void
  3162. run_hp_recovery()
  3163. {
  3164.     int u, hprecovery, hpmax, oldhp;
  3165.     Unit *unit;
  3166.  
  3167.     if (any_hp_recovery < 0) {
  3168.     any_hp_recovery = FALSE;
  3169.         for_all_unit_types(u) {
  3170.         if (u_hp_recovery(u) > 0) {
  3171.         any_hp_recovery = TRUE;
  3172.         break;
  3173.         }
  3174.     }
  3175.     }
  3176.     if (!any_hp_recovery)
  3177.       return;
  3178.     Dprintf("Running hp recovery\n");
  3179.     for_all_units(unit) {
  3180.     if (is_active(unit)) {
  3181.         u = unit->type;
  3182.         hprecovery = u_hp_recovery(u);
  3183.         hpmax = u_hp(u);
  3184.         /* (should only do for one part of multi-part unit?) */
  3185.         if (hprecovery > 0 && unit->hp < hpmax) {
  3186.         oldhp = unit->hp;
  3187.         add_to_unit_hp(unit, prob_fraction(hprecovery));
  3188.         /* Inform the player if the unit's hp changed. */
  3189.         if (unit->hp != oldhp) {
  3190.             update_unit_display(unit->side, unit, TRUE);
  3191.         }
  3192.         }
  3193.     }
  3194.     }
  3195. }
  3196.  
  3197. /* Some types of units can repair others without doing actions. */
  3198.  
  3199. static void
  3200. run_auto_repair()
  3201. {
  3202.     int u1, u2, u, hpmax, oldhp;
  3203.     Unit *unit, *occ;
  3204.  
  3205.     if (any_auto_repair < 0) {
  3206.     any_auto_repair = FALSE;
  3207.         for_all_unit_types(u1) {
  3208.         for_all_unit_types(u2) {
  3209.         if (uu_auto_repair(u2, u1) > 0) {
  3210.             any_auto_repair = TRUE;
  3211.             break;
  3212.         }
  3213.         }
  3214.     }
  3215.     }
  3216.     if (!any_auto_repair)
  3217.       return;
  3218.     if (will_be_auto_repaired == NULL) {
  3219.     will_be_auto_repaired =
  3220.       (short *) xmalloc(numutypes * sizeof(short));
  3221.     auto_repair_range_max =
  3222.       (short *) xmalloc(numutypes * sizeof(short));
  3223.         for_all_unit_types(u1) {
  3224.         will_be_auto_repaired[u1] = FALSE;
  3225.         auto_repair_range_max[u1] = -1;
  3226.         for_all_unit_types(u2) {
  3227.         if (uu_auto_repair(u2, u1) > 0) {
  3228.             will_be_auto_repaired[u1] = TRUE;
  3229.             auto_repair_range_max[u1] =
  3230.               max(auto_repair_range_max[u1], uu_auto_repair_range(u2, u1));
  3231.         }
  3232.         }
  3233.     }
  3234.     }
  3235.     Dprintf("Running auto repair\n");
  3236.     for_all_units(unit) {
  3237.     if (is_active(unit)) {
  3238.         u = unit->type;
  3239.         hpmax = u_hp(u);
  3240.         /* (should only do for one part of multi-part unit?) */
  3241.         if (unit->hp < u_hp(u) && will_be_auto_repaired[u]) {
  3242.         oldhp = unit->hp;
  3243.         if (auto_repair_range_max[u] < 0) {
  3244.             if (unit->transport && uu_auto_repair(unit->transport->type, u) > 0) {
  3245.             auto_repair_unit(unit->transport, unit);
  3246.             } else {
  3247.             for_all_occupants(unit, occ) {
  3248.                 if (is_active(occ) && uu_auto_repair(occ->type, u) > 0) {
  3249.                 auto_repair_unit(occ, unit);
  3250.                 }
  3251.             }
  3252.             }
  3253.         } else {
  3254.             tmpunit = unit;
  3255.             apply_to_area(unit->x, unit->y, auto_repair_range_max[u], auto_repair_from_here);
  3256.         }
  3257.         /* Inform the player if the unit's hp changed. */
  3258.         if (unit->hp != oldhp) {
  3259.             update_unit_display(unit->side, unit, TRUE);
  3260.         }
  3261.         }
  3262.     }
  3263.     }
  3264. }
  3265.  
  3266. /* Try to auto-repair using anything found at the given location. */
  3267.  
  3268. static void
  3269. auto_repair_from_here(x, y)
  3270. int x, y;
  3271. {
  3272.     int dist;
  3273.     Unit *unit2;
  3274.  
  3275.     /* Skip out if we're all repaired. */
  3276.     if (tmpunit->hp == u_hp(tmpunit->type)) {
  3277.     stop_apply = TRUE;
  3278.     return;
  3279.     }
  3280.     for_all_stack(x, y, unit2) {
  3281.     if (unit2 != tmpunit
  3282.         && trusted_side(unit2->side, tmpunit->side)
  3283.         && uu_auto_repair(unit2->type, tmpunit->type) > 0) {
  3284.         dist = distance(tmpunit->x, tmpunit->y, unit2->x, unit2->y);
  3285.         if (dist <= uu_auto_repair_range(unit2->type, tmpunit->type)) {
  3286.         auto_repair_unit(unit2, tmpunit);
  3287.         }
  3288.     }
  3289.     }
  3290. }
  3291.  
  3292. /* Do the actual auto-repair. */
  3293.  
  3294. static void
  3295. auto_repair_unit(unit, unit2)
  3296. Unit *unit, *unit2;
  3297. {
  3298.     int u = unit->type, u2 = unit2->type, m, repair;
  3299.  
  3300.     /* Check the basic restrictions on repair. */
  3301.     if (unit->hp < uu_hp_to_repair(u, u2))
  3302.       return;
  3303.     for_all_material_types(m) {
  3304.     if (unit->supply[m] < um_to_repair(u, m))
  3305.       return;
  3306.     }
  3307.     repair = uu_auto_repair(u, u2);
  3308.     add_to_unit_hp(unit2, prob_fraction(repair));
  3309. }
  3310.  
  3311. void
  3312. add_to_unit_hp(unit, hp)
  3313. Unit *unit;
  3314. int hp;
  3315. {
  3316.     int hpmax;
  3317.  
  3318.     unit->hp += hp;
  3319.     hpmax = u_hp(unit->type);
  3320.     if (unit->hp > hpmax)
  3321.       unit->hp = hpmax;
  3322.     unit->hp2 += hp;
  3323.     if (unit->hp2 > hpmax)
  3324.       unit->hp2 = hpmax;
  3325. }
  3326.  
  3327. static void
  3328. run_detonation_accidents()
  3329. {
  3330.     int u, t, x, y, z, chance;
  3331.     Unit *unit;
  3332.  
  3333.     if (any_detonation_accidents < 0) {
  3334.     any_detonation_accidents = FALSE;
  3335.     for_all_unit_types(u) {
  3336.         for_all_terrain_types(t) {
  3337.         if (ut_detonation_accident(u, t) > 0) {
  3338.             any_detonation_accidents = TRUE;
  3339.             break;
  3340.         }
  3341.         }
  3342.     }
  3343.     }
  3344.     if (!any_detonation_accidents)
  3345.       return;
  3346.     for_all_units(unit) {
  3347.     if (in_play(unit) && completed(unit)) {
  3348.         x = unit->x;  y = unit->y;  z = unit->z;
  3349.         t = terrain_at(x, y);
  3350.         chance = ut_detonation_accident(unit->type, t);
  3351.         if (chance > 0) {
  3352.             maybe_detonate_accidently(unit);
  3353.         }
  3354.     }
  3355.     }
  3356. }
  3357.  
  3358. static void
  3359. maybe_detonate_accidently(unit)
  3360. Unit *unit;
  3361. {
  3362.     int x = unit->x, y = unit->y, chance, t;
  3363.     extern int max_u_detonate_effect_range;
  3364.  
  3365.     t = terrain_at(x, y);
  3366.     chance = ut_detonation_accident(unit->type, t);
  3367.     if (xrandom(10000) < chance) {
  3368.     /* Detonate the unit right where it is. */
  3369.     detonate_unit(unit, x, y, unit->z);
  3370.     reckon_damage_around(x, y, max_u_detonate_effect_range);
  3371.     }
  3372. }
  3373.  
  3374. /* Resignation, possibly giving away any remaining units. */
  3375.  
  3376. void
  3377. resign_game(side, side2)
  3378. Side *side, *side2;
  3379. {
  3380.     /* Nothing to do if we're not in the game. */
  3381.     if (!side->ingame)
  3382.       return;
  3383.     notify_all_of_resignation(side, side2);
  3384.     side_loses(side, side2, -1);
  3385. }
  3386.  
  3387. /* This is true if there is any kind of realtime limit on the game. */
  3388.  
  3389. int
  3390. realtime_game()
  3391. {
  3392.     return (g_rt_for_game() > 0
  3393.             || g_rt_per_side() > 0
  3394.             || g_rt_per_turn() > 0);
  3395. }
  3396.  
  3397. /* Pass NULL to see if all sides are now willing to save the game. */
  3398.  
  3399. int
  3400. all_others_willing_to_save(side)
  3401. Side *side;
  3402. {
  3403.     Side *side2;
  3404.  
  3405.     for_all_sides(side2) {
  3406.     if (side != side2 && !side2->willingtosave)
  3407.       return FALSE; 
  3408.     }
  3409.     return TRUE;
  3410. }
  3411.  
  3412. /* Pass NULL to see if all sides are now willing to declare a draw. */
  3413.  
  3414. int
  3415. all_others_willing_to_quit(side)
  3416. Side *side;
  3417. {
  3418.     Side *side2;
  3419.  
  3420.     for_all_sides(side2) {
  3421.     if (side != side2 && !side2->willingtodraw)
  3422.       return FALSE; 
  3423.     }
  3424.     return TRUE;
  3425. }
  3426.  
  3427. /* This forces an end to the game directly. */
  3428.  
  3429. void
  3430. end_the_game()
  3431. {
  3432.     Side *side;
  3433.  
  3434.     Dprintf("The game is over.\n");
  3435.     /* Make sure everybody sees this. */
  3436.     notify_all("END OF THE GAME!");
  3437.     record_event(H_GAME_ENDED, ALLSIDES);
  3438.     /* Set the global that indicates the game is over for everybody. */
  3439.     endofgame = TRUE;
  3440.     end_history();
  3441.     record_into_scorefile();
  3442.     dump_statistics();
  3443.     /* Done with internal state change, now echo onto displays. */
  3444.     for_all_sides(side) {
  3445.         /* (should there be any other effects on sides, like final scoring?) */
  3446.         if (side_has_display(side)) {
  3447.             update_turn_display(side, TRUE);
  3448.             update_side_display(side, side, TRUE);
  3449.         }
  3450.     }
  3451. }
  3452.