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

  1. /* Copyright (c) 1987, 1988  Stanley T. Shebs. */
  2. /* This program may be used, copied, modified, and redistributed freely */
  3. /* for noncommercial purposes, so long as this notice remains intact. */
  4.  
  5. /* This file implements production decisions for the machine players. */
  6.  
  7. #include "config.h"
  8. #include "misc.h"
  9. #include "dir.h"
  10. #include "period.h"
  11. #include "side.h"
  12. #include "unit.h"
  13. #include "map.h"
  14. #include "global.h"
  15. #include "mplay.h"
  16.  
  17.  
  18. /* Decide whether a change of product is desirable. */
  19.  
  20. bool change_machine_product(unit)
  21. Unit *unit;
  22. {
  23.     int u = unit->type;
  24.  
  25.     if (Freeze) {
  26.     return FALSE;
  27.     } else if (utypes[u].maker) {
  28.     if (producing(unit)) {
  29.         if ((unit->built > 2) ||
  30.         ((utypes[u].make[unit->product] * unit->built) > 20)) {
  31.         return TRUE;
  32.         }
  33.     } else {
  34.         return TRUE;
  35.     }
  36.     }
  37.     return FALSE;
  38. }
  39.  
  40. /* Machine algorithm for deciding what a unit should build. This routine */
  41. /* must return the type of unit decided upon.  Variety of production is */
  42. /* important, as is favoring types which can leave the builder other than */
  43. /* on a transport.  Capturers of valuable units are also highly preferable. */
  44.  
  45. int machine_product(unit)
  46. Unit *unit;
  47. {
  48.     int u = unit->type, u2, u3,
  49.             type, t, d, x, y, x1, y1, d1, value, bestvalue, besttype, tmp;
  50.     int adjterr[MAXUTYPES];
  51.     int units_close[MAXUTYPES];
  52.     int demand[MAXUTYPES], total_demand, ucount[MAXUTYPES];
  53.     int Values[MAXUTYPES];
  54.     int others, total_units;
  55.     Unit *unit2;
  56.     int enemy_strength = unit->side->areas[area_index(unit->x, unit->y)].enemy_strength;
  57.     int units_lost = unit->side->areas[area_index(unit->x, unit->y)].units_lost;
  58.  
  59.     enter_procedure("machine_product");
  60.     mside = unit->side;
  61.     besttype = period.firstptype;
  62.     /* make sure we find a product if the unit can build. */
  63.     if (!could_make(u, besttype)) {
  64.       for_all_unit_types(u2)
  65.     if (could_make(u, u2))
  66.       besttype = u2;
  67.     }
  68.     bestvalue = 0;
  69. #ifdef REGIONS
  70.     for_all_unit_types(u2) {
  71.       adjterr[u2] = 0;
  72.       units_close[u2] = 0;
  73.       for_all_directions(d) {
  74.     x = wrap(unit->x + dirx[d]);  y = unit->y + diry[d];
  75.     if ((t = aref(unit_region[u2], x, y)) >= 0) {
  76.       tmp = TRUE;
  77.       for (d1 = 0; d1 < d; d1++) {
  78.         x1 = wrap(unit->x + dirx[d1]);  y1 = unit->y + diry[d1];
  79.         if (t == aref(unit_region[u2], x1, y1))
  80.           tmp = FALSE;
  81.       }
  82.       if (tmp) {
  83.         adjterr[u2] += unit_region_size[u2][t];
  84.         units_close[u2] += units_in_region[u2][t];
  85.       }
  86.     }
  87.       }
  88.     }
  89. #else
  90.     for_all_unit_types(u2) {
  91.       adjterr[u2] = 0;
  92.       units_close[u2] = 0;
  93.       for_all_directions(d) {
  94.     x = wrap(unit->x + dirx[d]);  y = unit->y + diry[d];
  95.     if (could_move(u2, terrain_at(x, y))) {
  96.       adjterr[u2] += 1;
  97.     }
  98.       }
  99.       units_close[u2] = units_nearby(x, y, 7, munit->type);
  100.     }
  101. #endif
  102.     if (!worths_known) {
  103.       for_all_unit_types(u2) {
  104.     tmp = utypes[u2].is_base;  /* really should be checking that can leave
  105.                       either by moving or on transport. Bases
  106.                       can always be made. */
  107.     if (could_make(u, u2)) {
  108.       value = side_plan(mside)->demand[u2];
  109.       if (mobile(u2)) {
  110. #ifdef REGIONS
  111.         value += adjterr[u2] * num_regions[u2] * 
  112.                  600 / unit_hexes[u2];
  113. #endif
  114.         if (adjterr[u2] > 0) tmp = TRUE;
  115.       } else tmp = TRUE;
  116.       value *= isqrt(utypes[u2].speed);
  117.       for_all_unit_types(u3)
  118.         if (bcw[u2][u3] > 100)
  119.           value += value / 8;
  120.       if (utypes[u2].is_transport && !utypes[u2].is_carrier)
  121.         value += value/4;
  122.       if (value > 0 && utypes[u2].is_carrier && base_building)
  123.         value /= 2;
  124.       if (utypes[u2].is_base) value += value;
  125.       if (value > 0)
  126.         value /= (mside->units[u2] + mside->building[u2] + 1);
  127.       others = units_nearby(unit->x, unit->y, min(utypes[u2].speed * 5, 14), u2);
  128.       if (others > 0 && value > 0) value /= others;
  129.       
  130.       /* might want to adjust by number of existing units? */
  131.       value = (value * (100 - build_time(unit, u2))) / 100;
  132.       if (build_time(unit, u2) < 10)
  133.         value += (value * (10 - build_time(unit, u2))) / 10;
  134.       if (utypes[u2].selfdestruct && value > 0) value /= 10;
  135.       if (utypes[u2].research > 0) {
  136.         if (mside->building[u2] > 0) {
  137.           if (value > 0)
  138.         value = value / 100 - 1000;
  139.           else value -= 1000;
  140.         } else for_all_unit_types(u3) {
  141.           if (utypes[u2].research_contrib[u3] && mside->counts[u3] <= 1) {
  142.         if (value > 0)
  143.           value = value / 100 - 1000;
  144.         else value -= 1000;
  145.           }
  146.         }
  147.       }
  148.       if (tmp && value > bestvalue) {
  149.         besttype = u2;
  150.         bestvalue = value;
  151.       }
  152.     }
  153.       }
  154.     } else {
  155.       total_demand = 1; /* make sure we don't divide by zero */
  156.       for_all_unit_types(u2) 
  157.     if (could_make(u, u2)) {
  158.       demand[u2] = utypes[u2].attack_worth * attack_priority +
  159.         utypes[u2].defense_worth *
  160.           (defend_priority + 5 * (enemy_strength + units_lost)) +
  161.           utypes[u2].explore_worth * explore_priority;
  162.       /* if we are under attack, build quick units. */
  163.       if (utypes[u].make[u2] < 10 && enemy_strength > 3)
  164.         demand[u2] += demand[u2] / 2;
  165.       if (utypes[u].make[u2] < 5 && enemy_strength > 3)
  166.         demand[u2] += demand[u2] / 2;
  167.       total_demand += demand[u2];
  168.       ucount[u2] = 0;
  169.       }
  170.       total_units = 100;  /* actually hundreths of units */
  171.       for_all_side_units(mside, unit2) {
  172.     if (could_make(u, unit2->type))
  173.       ucount[unit2->type] += 100;
  174.     if (unit != unit2 && producing(unit2) && !cripple(unit2)) {
  175.       ucount[unit2->product] +=
  176.         max(30, ((100 + utypes[unit2->type].make[unit2->product] - 
  177.               unit2->schedule) * 10) /
  178.         utypes[unit2->type].make[unit2->product]);
  179.     }
  180.       }
  181.       for_all_unit_types(u2)
  182.      if could_make(u, u2) {
  183.        ucount[u2] =  
  184.          region_portion(ucount[u2], u2, units_close, adjterr);
  185.        total_units += ucount[u2];
  186.      }
  187.       for_all_unit_types(u2) {
  188.     tmp = utypes[u2].is_base;  /* really should be checking that can leave
  189.                       either by moving or on transport. Bases
  190.                       can always be made. */
  191.     if (could_make(u, u2)) {
  192.       value = demand[u2] - ((3 + ucount[u2]) * total_demand) / total_units;
  193.       if (unit->product == u2) value += max(1, value / 4);
  194. /*      others = units_nearby(unit->x, unit->y,
  195.                 min(utypes[u2].speed * 5, 14), u2); */
  196. /*      if (others > 0) value /= isqrt(others); */
  197.       
  198.       /* might want to adjust by number of existing units? */
  199.       Values[u2] = value;
  200.       if (utypes[u2].research > 0) {
  201.         if (mside->building[u2] > 0) {
  202.           if (value > 0)
  203.         value = value / 100 - 1000;
  204.           else value -= 1000;
  205.         } else for_all_unit_types(u3) {
  206.           if (utypes[u2].research_contrib[u3] && mside->counts[u3] <= 1) {
  207.         if (value > 0)
  208.           value = value / 100 - 1000;
  209.         else value -= 1000;
  210.           }
  211.         }
  212.       }
  213.       if (value > bestvalue && adjterr[u2] >
  214. #ifdef REGIONS
  215.           utypes[u2].min_region_size
  216. #else
  217.         0
  218. #endif
  219.           )
  220.         {
  221.         besttype = u2;
  222.         bestvalue = value;
  223.       }
  224.     }
  225.       }
  226.       type= besttype;
  227. /*      notify(side_n(0),"%d %d | %d %d %d %d %d %d",
  228.          type, total_units, Values[0], adjterr[0], adjterr[1], 
  229.          adjterr[2], adjterr[3], adjterr[4]); 
  230. */
  231. /*      printf("\n%d: unit %s was building %s, now %s value %d\n", 
  232.          global.time, unit_desig(unit),
  233.          (unit->product == NOTHING ? "no" : utypes[unit->product].name),
  234.          (type == NOTHING ? "no" : utypes[type].name),
  235.          bestvalue); */
  236.     }
  237.     type = besttype;
  238.     /* safety check */
  239.     if (!could_make(unit->type, type)) type = NOTHING;
  240.     if (Debug) printf("%d: %s will now build %s units\n",
  241.               global.time, unit_desig(unit),
  242.               (type == NOTHING ? "no" : utypes[type].name));
  243.     exit_procedure();
  244.     return type;
  245. }
  246.  
  247. /* Take into account other units already in this region.  This will
  248. tend to increase the unit count of regions which already have more
  249. units than the portion of the land they account for. */
  250.  
  251. int region_portion(n, ut, units_close, adjterr)
  252. int n, ut, units_close[MAXUTYPES], adjterr[MAXUTYPES];
  253. {
  254.   
  255.   int result;
  256.  
  257. #ifdef REGIONS
  258.   if (unit_hexes[ut] != 0) 
  259.     result = n - (n * adjterr[ut]) / (3 * unit_hexes[ut]) +
  260.       (n * units_close[ut]) / 
  261.     (3 * max(mside->unitlistcount[ut], 1));
  262.   else 
  263. #endif /* REGIONS */
  264.   result = n + (n * units_close[ut]) /
  265.              (3 * max(mside->unitlistcount[ut], 1));
  266.   return result;
  267. }
  268.