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 / ai.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  20.2 KB  |  866 lines  |  [TEXT/R*ch]

  1. /* Functions common to all AIs.
  2.    Copyright (C) 1992, 1993, 1994, 1995, 1996 Stanley T. Shebs.
  3.  
  4. Xconq is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.  See the file COPYING.  */
  8.  
  9. #include "conq.h"
  10.  
  11. /* The number of AI types defined.  Increment for each new AI type
  12.    that is compiled in. */
  13.  
  14. #define numaitypes 2
  15.  
  16. /* Declarations of all AI types. */
  17.  
  18. extern AI_ops mplayer_ops;
  19.  
  20. AI_ops **all_ai_ops;
  21.  
  22. void
  23. init_ai_types()
  24. {
  25.     /* Fill in the table of pointers to AI types. */
  26.     all_ai_ops = (AI_ops **) xmalloc(numaitypes * sizeof(AI_ops *));
  27.     all_ai_ops[0] = (AI_ops *) xmalloc(sizeof(AI_ops));
  28.     all_ai_ops[1] = &mplayer_ops;
  29. }
  30.  
  31. void
  32. init_ai(side)
  33. Side *side;
  34. {
  35.     int i;
  36.     char *typename;
  37.     int (*test) PARAMS ((void));
  38.     void (*fn) PARAMS ((Side *side));
  39.  
  40.     if (side_wants_ai(side)) {
  41.     if (strcmp(side->player->aitypename, "ai") == 0) {
  42.         /* (should use the "best" default for this game and side) */
  43.         side->player->aitypename = "mplayer";
  44.     }
  45.     for (i = 0; i < numaitypes; ++i) {
  46.         typename = (all_ai_ops[i])->name;
  47.         if (typename != NULL
  48.         && strcmp(typename, side->player->aitypename) == 0) {
  49.         test = (all_ai_ops[i])->to_test_compat;
  50.         if (test == NULL || (*test)()) {
  51.             side->aitype = i;
  52.             fn = (all_ai_ops[i])->to_init;
  53.             if (fn)
  54.               (*fn)(side);
  55.         } else {
  56.             /* desired aitype not avail - should complain */
  57.         }
  58.         }
  59.     }
  60.     if (!side_has_ai(side)) {
  61.         init_warning("could not make an AI (type %s) for %s",
  62.              side->player->aitypename, side_desig(side));
  63.     }
  64.     }
  65. }
  66.  
  67. /* Change the AI running a side.  This has to clean up if the AI is
  68.    being turned off. */
  69.  
  70. void
  71. set_side_ai(side, typename)
  72. Side *side;
  73. char *typename;
  74. {
  75.     Unit *unit;
  76.  
  77.     if (!empty_string(typename) && strcmp(typename, "ai") == 0) {
  78.     /* (should use the "best" default for this game and side) */
  79.     typename = "mplayer";
  80.     }
  81.     side->player->aitypename = typename;
  82.     for_all_side_units(side, unit) {
  83.     unit->aihook = NULL;
  84.     if (unit->plan && unit->plan->aicontrol) {
  85.         unit->plan->type = PLAN_NONE;
  86.         unit->plan->maingoal = NULL;
  87.         unit->plan->formation = NULL;
  88.         unit->plan->funit = NULL;
  89.         clear_task_agenda(unit->plan);
  90.         if (typename == NULL) {
  91.         unit->plan->asleep = FALSE;
  92.         unit->plan->reserve = FALSE;
  93.         /* Don't touch delay, let action looping clear it eventually. */
  94.         unit->plan->aicontrol = FALSE;
  95.         } else {
  96.         unit->plan->aicontrol = TRUE;
  97.         }
  98.     }
  99.     /* Still let units finish their currently buffered action. */
  100.     }
  101.     if (typename == NULL) {
  102.     /* (should just deactivate) */
  103.     side->ai = NULL;
  104.     /* Clear out everything that was set up by the AI. */
  105.     } else {
  106.     init_ai(side);
  107.     }
  108. }
  109.  
  110. void
  111. ai_init_turn(side)
  112. Side *side;
  113. {
  114.     void (*fn) PARAMS ((Side *side));
  115.  
  116.     fn = (all_ai_ops[side->aitype])->to_init_turn;
  117.     if (fn)
  118.       (*fn)(side);
  119. }
  120.  
  121. void
  122. ai_decide_plan(side, unit)
  123. Side *side;
  124. Unit *unit;
  125. {
  126.     void (*fn) PARAMS ((Side *side, Unit *unit));
  127.  
  128.     fn = ((all_ai_ops[side->aitype])->to_decide_plan);
  129.     if (fn)
  130.       (*fn)(side, unit);
  131. }
  132.  
  133. void
  134. ai_react_to_unit_loss(side, unit)
  135. Side *side;
  136. Unit *unit;
  137. {
  138.     void (*fn) PARAMS ((Side *side, Unit *unit));
  139.  
  140.     fn = ((all_ai_ops[side->aitype])->to_react_to_unit_loss);
  141.     if (fn)
  142.       (*fn)(side, unit);
  143. }
  144.  
  145. /* Forward an action result to the appropriate AI routine. */
  146.  
  147. void
  148. ai_react_to_action_result(side, unit, rslt)
  149. Side *side;
  150. Unit *unit;
  151. int rslt;
  152. {
  153.     void (*fn) PARAMS ((Side *side, Unit *unit, int rslt));
  154.  
  155.     fn = ((all_ai_ops[side->aitype])->to_react_to_action_result);
  156.     if (fn)
  157.       (*fn)(side, unit, rslt);
  158. }
  159.  
  160. /* Forward a task result to the appropriate AI routine. */
  161.  
  162. void
  163. ai_react_to_task_result(side, unit, task, rslt)
  164. Side *side;
  165. Unit *unit;
  166. Task *task;
  167. TaskOutcome rslt;
  168. {
  169.     void (*fn) PARAMS ((Side *side, Unit *unit, Task *task, TaskOutcome rslt));
  170.  
  171.     fn = ((all_ai_ops[side->aitype])->to_react_to_task_result);
  172.     if (fn)
  173.       (*fn)(side, unit, task, rslt);
  174. }
  175.  
  176. void
  177. ai_react_to_new_side(side, side2)
  178. Side *side, *side2;
  179. {
  180.     void (*fn) PARAMS ((Side *side, Side *side2));
  181.  
  182.     fn = ((all_ai_ops[side->aitype])->to_react_to_new_side);
  183.     if (fn)
  184.       (*fn)(side, side2);
  185. }
  186.  
  187. int
  188. ai_planning_to_capture(side, u, x, y)
  189. Side *side;
  190. int u, x, y;
  191. {
  192.     int (*fn) PARAMS ((Side *side, int u, int x, int y));
  193.  
  194.     fn = ((all_ai_ops[side->aitype])->planning_to_capture);
  195.     if (fn)
  196.       return (*fn)(side, u, x, y);
  197.     else
  198.       return FALSE;
  199. }
  200.  
  201. int
  202. ai_guide_explorer(side, unit)
  203. Side *side;
  204. Unit *unit;
  205. {
  206.     int (*fn) PARAMS ((Side *side, Unit *unit));
  207.  
  208.     fn = ((all_ai_ops[side->aitype])->to_guide_explorer);
  209.     if (fn)
  210.       return (*fn)(side, unit);
  211.     else
  212.       return FALSE;
  213. }
  214.  
  215. int
  216. ai_preferred_build_type(side, unit, plantype)
  217. Side *side;
  218. Unit *unit;
  219. int plantype;
  220. {
  221.     int (*fn) PARAMS ((Side *side, Unit *unit, int plantype));
  222.  
  223.     fn = ((all_ai_ops[side->aitype])->preferred_build_type);
  224.     if (fn)
  225.       return (*fn)(side, unit, plantype);
  226.     else
  227.       return NONUTYPE;
  228. }
  229.  
  230. void
  231. ai_analyze_after_moves(side, numacted)
  232. Side *side;
  233. int numacted;
  234. {
  235.     void (*fn) PARAMS ((Side *side, int numacted));
  236.  
  237.     fn = ((all_ai_ops[side->aitype])->to_analyze_after_moves);
  238.     if (fn)
  239.       (*fn)(side, numacted);
  240. }
  241.  
  242. void
  243. ai_finish_movement(side)
  244. Side *side;
  245. {
  246.     void (*fn) PARAMS ((Side *side));
  247.  
  248.     fn = ((all_ai_ops[side->aitype])->to_finish_movement);
  249.     if (fn)
  250.       (*fn)(side);
  251. }
  252.  
  253. /* Forward a textual message to the appropriate AI routine. */
  254.  
  255. void
  256. ai_receive_message(side, sender, str)
  257. Side *side, *sender;
  258. char *str;
  259. {
  260.     void (*fn) PARAMS ((Side *side, Side *sender, char *str));
  261.  
  262.     fn = ((all_ai_ops[side->aitype])->to_receive_message);
  263.     if (fn)
  264.       (*fn)(side, sender, str);
  265. }
  266.  
  267. void
  268. ai_save_state(side)
  269. Side *side;
  270. {
  271.     Obj *(*fn) PARAMS ((Side *side)), *state = lispnil;
  272.  
  273.     fn = ((all_ai_ops[side->aitype])->to_save_state);
  274.     if (fn)
  275.       state = (*fn)(side);
  276.     /* Don't bother if there's no AI state to mess with. */
  277.     if (side->aidata == lispnil && state == lispnil)
  278.       return;
  279.     side->aidata = replace_at_key(side->aidata, side->player->aitypename, state);
  280. }
  281.  
  282. int
  283. ai_region_at(side, x, y)
  284. Side *side;
  285. int x, y;
  286. {
  287.     int (*fn) PARAMS ((Side *side, int x, int y));
  288.  
  289.     fn = ((all_ai_ops[side->aitype])->region_at);
  290.     if (fn)
  291.       return (*fn)(side, x, y);
  292.     else
  293.       return 0;
  294. }
  295.  
  296. char *
  297. ai_at_desig(side, x, y)
  298. Side *side;
  299. int x, y;
  300. {
  301.     char *(*fn) PARAMS ((Side *side, int x, int y));
  302.  
  303.     fn = ((all_ai_ops[side->aitype])->at_desig);
  304.     if (fn)
  305.       return (*fn)(side, x, y);
  306.     else
  307.       return NULL;
  308. }
  309.  
  310. /* (should go elsewhere eventually?) */
  311.  
  312. /* Goal handling. */
  313.  
  314. GoalDefn goaldefns[] = {
  315.  
  316. #undef  DEF_GOAL
  317. #define DEF_GOAL(NAME,code,ARGTYPES) { NAME, ARGTYPES },
  318.  
  319. #include "goal.def"
  320.  
  321.     { NULL, NULL }
  322. };
  323.  
  324.  
  325. /* General handling of goals. */
  326.  
  327. Goal *
  328. create_goal(type, side, tf)
  329. GoalType type;
  330. Side *side;
  331. int tf;
  332. {
  333.     Goal *goal = (Goal *) xmalloc(sizeof(Goal));
  334.  
  335.     goal->type = type;
  336.     goal->side = side;
  337.     goal->tf = tf;
  338.     return goal;
  339. }
  340.  
  341. int
  342. cell_unknown(x, y)
  343. int x, y;
  344. {
  345.     return (!all_see_all && !tmpside->see_all && terrain_view(tmpside, x, y) == UNSEEN);
  346. }
  347.  
  348. int
  349. enemies_present(x, y)
  350. int x, y;
  351. {
  352.     if (units_visible(tmpside, x, y)) {
  353.         return (unit_at(x, y) != NULL && !trusted_side(tmpside, unit_at(x, y)->side));
  354.     } else if (terrain_view(tmpside, x, y) != UNSEEN) {
  355.         return (vside(unit_view(tmpside, x, y)) != side_number(tmpside));
  356.     } else {
  357.         return FALSE;
  358.     }
  359. }
  360.  
  361. /* Test a goal to see if it is true for side, as specified. */
  362.  
  363. int
  364. goal_truth(side, goal)
  365. Side *side;
  366. Goal *goal;
  367. {
  368.     int x, y;
  369.     Side *side2 = NULL;
  370.  
  371.     if (goal == NULL) return 0;
  372.     switch (goal->type) {
  373.       case GOAL_WON_GAME:
  374.     side2 = goal->side;
  375.     return (side2 ? (side_won(side2) ? 100 : -100) : 0);
  376.       case GOAL_LOST_GAME:
  377.     side2 = goal->side;
  378.     return (side2 ? (side_lost(side2) ? 100 : -100) : 0);
  379.       case GOAL_POSITIONS_KNOWN:
  380.     /* what if no enemies present? then this is undefined? */
  381.     /* should goals have preconditions or prerequisites? */
  382.     return 0;
  383.       case GOAL_WORLD_KNOWN:
  384.     tmpside = side;
  385.     for_all_interior_cells(x, y) {
  386.         if (cell_unknown(x, y)) return -100;
  387.     }
  388.     return 100;
  389.       case GOAL_VICINITY_KNOWN:
  390.     tmpside = side;
  391.     if (search_around(goal->args[0], goal->args[1], goal->args[2],
  392.               cell_unknown, &x, &y, 1)) {
  393.         return -100;
  394.     } else {
  395.         return 100;
  396.     }
  397.       case GOAL_VICINITY_HELD:
  398.           tmpside = side;
  399.     if (search_around(goal->args[0], goal->args[1], goal->args[2],
  400.               enemies_present, &x, &y, 1)) {
  401.         return -100;
  402.     } else {
  403.         return 100;
  404.     }
  405.       case GOAL_CELL_OCCUPIED:
  406.     return 0;
  407.       case GOAL_HAS_UNIT_TYPE:
  408.     return 0;
  409.       case GOAL_HAS_UNIT_TYPE_NEAR:
  410.     return 0;
  411.       case GOAL_HAS_MATERIAL_TYPE:
  412.     return 0;
  413.       default:
  414.     case_panic("goal type", goal->type);
  415.     return 0;
  416.     }
  417. }
  418.  
  419. /* (might eventually want another evaluator that guesses at another
  420.    side's goals) */
  421.  
  422. char *goalbuf = NULL;
  423.  
  424. char *
  425. goal_desig(goal)
  426. Goal *goal;
  427. {
  428.     int numargs, i, arg;
  429.     char *argtypes;
  430.  
  431.     if (goal == NULL)
  432.       return "<null goal>";
  433.     if (goalbuf == NULL)
  434.       goalbuf = xmalloc(BUFSIZE);
  435.     sprintf(goalbuf, "<goal s%d %s%s",
  436.         side_number(goal->side), (goal->tf ? "" : "not "),
  437.         goaldefns[goal->type].name);
  438.     argtypes = goaldefns[goal->type].argtypes;
  439.     numargs = strlen(argtypes);
  440.     for (i = 0; i < numargs; ++i) {
  441.     arg = goal->args[i];
  442.     switch (argtypes[i]) {
  443.       case 'h':
  444.         tprintf(goalbuf, "%d", arg);
  445.         break;
  446.       case 'm':
  447.         if (is_material_type(arg))
  448.           tprintf(goalbuf, " %s", m_type_name(arg));
  449.         else
  450.           tprintf(goalbuf, " m%d?", arg);
  451.         break;
  452.       case 'S':
  453.         tprintf(goalbuf, " `%s'", side_desig(side_n(arg)));
  454.         break;
  455.       case 'u':
  456.         if (is_unit_type(arg))
  457.           tprintf(goalbuf, " %s", u_type_name(arg));
  458.         else
  459.           tprintf(goalbuf, " m%d?", arg);
  460.         break;
  461.       case 'U':
  462.         tprintf(goalbuf, " `%s'", unit_desig(find_unit(arg)));
  463.         break;
  464.       case 'w':
  465.         tprintf(goalbuf, " %dx", arg);
  466.         break;
  467.       case 'x':
  468.         tprintf(goalbuf, " %d,", arg);
  469.         break;
  470.       case 'y':
  471.         tprintf(goalbuf, "%d", arg);
  472.         break;
  473.       default:
  474.         tprintf(goalbuf, " %d", arg);
  475.         break;
  476.     }
  477.     }
  478.     strcat(goalbuf, ">");
  479.     return goalbuf;
  480. }
  481.  
  482.  
  483. /* General collections of numbers used by all machine players. */
  484.  
  485. /* Init used by all machine players.  Precompute useful information
  486.    relating to unit types in general, and that usually gets referenced
  487.    in inner loops. */
  488.  
  489. void
  490. ai_init_shared()
  491. {
  492.     int u, u1, u2, t, m1, numbuilders, tmp;
  493.     
  494.     /* Need 3 scratch layers for routefinding. */
  495.     allocate_area_scratch(3);
  496.  
  497.     /* Recognize unit types that are bases */
  498.     for_all_unit_types(u1) {
  499.     set_u_is_base(u1, FALSE);
  500.     tmp = FALSE;
  501.     for_all_material_types(m1) {
  502.         if (um_base_production(u1, m1) > 0) {
  503.         tmp = TRUE;
  504.         break;
  505.         }
  506.     }
  507.     if (tmp) {
  508.         for_all_unit_types(u2) {
  509.         if ((u1 != u2) && could_carry(u1,u2)) {
  510.             set_u_is_base(u1, TRUE);
  511.             continue;
  512.         }
  513.         }
  514.     }
  515.     }
  516.     /* Note that is_base_builder is set to the type of base that can */
  517.     /* be built.  That means that unit zero can not be a base which */
  518.     /* can be built. */
  519.     for_all_unit_types(u1) {
  520.     set_u_is_transport(u1, FALSE);
  521.     set_u_is_carrier(u1, FALSE);
  522.     set_u_is_base_builder(u1, FALSE);
  523.     set_u_can_make(u1, FALSE);
  524.     set_u_can_capture(u1, FALSE);
  525.     numbuilders = 0;
  526. /*    ave_build_time[u1] = 0;  */
  527.     for_all_unit_types(u2) {
  528.         if (u_is_base(u2) &&
  529.         could_create(u1, u2) &&
  530.         1 /* can be made quickly? */) {
  531.         set_u_is_base_builder(u1, u2);
  532.         }
  533.         if (u_speed(u1) > 0 && could_carry(u1, u2)) {
  534.         set_u_is_transport(u1, TRUE);
  535.         }
  536.         if (could_create(u2, u1)) {
  537.         numbuilders++;
  538. /*        ave_build_time[u1] += uu_make(u2,u1);  */
  539.         set_u_can_make(u2, TRUE);
  540.         }
  541.         if (uu_capture(u1, u2) > 0 || uu_indep_capture(u1, u2) > 0) {
  542.         set_u_can_capture(u1, TRUE);
  543.         }
  544.     }
  545. /*    if (numbuilders > 0)
  546.       ave_build_time[u1] /= numbuilders;  */
  547.     }
  548.     /* a carrier is a unit that is a mobile base, but that cannot
  549.        move a passenger anywhere the passenger could not go itself. */
  550.     for_all_unit_types(u1) {
  551.     if (u_is_transport(u1)) {
  552.         set_u_is_carrier(u1, TRUE);
  553.         for_all_unit_types(u2) {
  554.         if (could_carry(u1, u2)) {
  555.             for_all_terrain_types(t) {
  556.             if (could_be_on(u1, t) && !could_be_on(u2, t))
  557.               set_u_is_carrier(u1, FALSE);
  558.             }
  559.         }
  560.         }
  561.     }
  562.     }
  563.     for_all_unit_types(u) {
  564.     set_u_bw(u, basic_worth(u));
  565.     }
  566.     for_all_unit_types(u) {
  567.     for_all_unit_types(u2) {
  568.         set_uu_bhw(u, u2, basic_hit_worth(u, u2));
  569.         set_uu_bfw(u, u2, basic_fire_worth(u, u2));
  570.         set_uu_bcw(u, u2, basic_capture_worth(u, u2));
  571.         set_uu_btw(u, u2, basic_transport_worth(u, u2));
  572.     }
  573.     }
  574.     /* Tell how things rated. */
  575.     if (DebugM)
  576.       display_assessment();
  577. }
  578.  
  579. int basic_transport_worth PARAMS ((int u1, int u2));
  580. void set_uu_btw PARAMS ((int u1, int u2, int v));
  581.  
  582. #define DICE(N,NUMDICE,SPOTS,OFFSET)  \
  583.   (((N) >> 14 == 0 || (N) >> 14 == 3) ?  \
  584.    (NUMDICE = 0, SPOTS = 0, OFFSET = (N)) :  \
  585.    (NUMDICE = ((N) >> 11) & 0x07, SPOTS = ((N) >> 7) & 0x0f, OFFSET = (N) & 0x7f))
  586.  
  587. /* A crude estimate of the worth of having one type of unit. */
  588.  
  589. int
  590. basic_worth(u)
  591. int u;
  592. {
  593.     int worth = 0, u2, r, range;
  594.   
  595.     worth += u_hp(u) * 10;
  596.     for_all_unit_types(u2) {
  597.     if (could_create(u, u2))
  598.       worth += (u_bw(u2) * (50)) / 1 /* uu_make(u, u2) */;
  599.     /* (should account for shared capacity) */
  600.     if (could_carry(u, u2))
  601.       worth += (1 + u_speed(u)) * uu_capacity_x(u, u2) *
  602.         (u_is_base(u) ? 10 : 1) * u_bw(u2) / 30;
  603.     }
  604.     range = 12345;
  605.     for_all_material_types(r) {
  606.     worth += um_base_production(u, r) * (u_is_base(u) ? 4 : 1);
  607.     if (um_consumption_per_move(u, r) > 0)
  608.       range = min(range, um_storage_x(u, r) / max(1, um_consumption_per_move(u, r)));
  609.     if (um_base_consumption(u, r) > 0) 
  610.       range =
  611.         min(range, u_speed(u) * um_storage_x(u, r) / max(1, um_base_consumption(u, r)));
  612.     }
  613.     worth += u_speed(u) * u_hp(u);
  614.     worth += (range == 12345 ? area.maxdim : range)
  615.       * u_hp(u) / max(1, 10 - u_speed(u));
  616.     for_all_unit_types(u2) {
  617.     worth += (worth * uu_capture(u, u2)) / 150;
  618.     }
  619.     worth = isqrt(worth);
  620.     DMprintf("unit type %s worth %d \n ", u_type_name(u), worth);
  621.     return worth;
  622. }
  623.  
  624. /* A basic estimate of the payoff of one unit type attacking another type
  625.    directly.  This is "context-free", does not account for overall goals etc. */
  626.  
  627. /* (should account for number of attacks possible in one turn) */
  628.  
  629. int
  630. basic_hit_worth(u, e)
  631. int u, e;
  632. {
  633.     int dam, numdice, numspots, offset, avgdamage, worth = 0, anti = 0;
  634.  
  635.     if (uu_acp_to_attack(u, e) < 1)
  636.       return -9999;
  637.     dam = uu_damage(u, e);
  638.     DICE(dam, numdice, numspots, offset);
  639.     avgdamage = offset + (numdice * numspots) / 2;
  640.     if (avgdamage > u_hp(e))
  641.       avgdamage = u_hp(e);
  642.     worth = (uu_hit(u, e) * avgdamage) / u_hp(e);
  643.     if (1 /* strength of counterattack */) {
  644.     dam = uu_damage(e, u);
  645.     DICE(dam, numdice, numspots, offset);
  646.     avgdamage = offset + (numdice * numspots) / 2;
  647.     if (avgdamage > u_hp(u))
  648.       avgdamage = u_hp(u);
  649.     anti = (uu_hit(e, u) * avgdamage) / u_hp(u);
  650.     }
  651.     return worth - (anti * 9) / 10;
  652. }
  653.  
  654. int
  655. basic_fire_worth(u, e)
  656. int u, e;
  657. {
  658.     int hitchance, dam, numdice, numspots, offset, avgdamage, worth = 0;
  659.  
  660.     if (u_acp_to_fire(u) < 1)
  661.       return -9999;
  662.     if (uu_fire_hit(u, e) != -1)
  663.       hitchance = uu_fire_hit(u, e);
  664.     else
  665.       hitchance = uu_hit(u, e);
  666.     if (uu_fire_damage(u, e) != -1)
  667.       dam = uu_fire_damage(u, e);
  668.     else
  669.       dam = uu_damage(u, e);
  670.     DICE(dam, numdice, numspots, offset);
  671.     avgdamage = offset + (numdice * numspots) / 2;
  672.     if (avgdamage > u_hp(e))
  673.       avgdamage = u_hp(e);
  674.     worth = (hitchance * avgdamage) / u_hp(e);
  675.     return worth;
  676. }
  677.  
  678. /* A crude estimate of the payoff of one unit type trying to capture. */
  679.  
  680. int
  681. basic_capture_worth(u, e)
  682. int u, e;
  683. {
  684.     int worth1 = 0, worth2 = 0;
  685.  
  686.     if (uu_acp_to_capture(u, e) < 1 && uu_acp_to_attack(u, e) < 1)
  687.       return -9999;
  688.     if (uu_capture(u, e) > 0) {
  689.     worth1 = uu_capture(u, e) * u_acp(u) /* divided by acp/attack */;
  690.     }
  691.     if (uu_indep_capture(u, e) > 0) {
  692.     worth2 = uu_indep_capture(u, e) * u_acp(u) /* divided by acp/attack */;
  693.     }
  694.     return max(worth1, worth2);
  695. }
  696.  
  697. int
  698. basic_transport_worth(u, u2)
  699. int u, u2;
  700. {
  701.     int worth = 0;
  702.  
  703.     if (could_carry(u, u2)) {
  704.     worth += 1;
  705.     }
  706.     return worth;
  707. }
  708.  
  709. /* Some notion of the unit's "strength"? */
  710.  
  711. int
  712. unit_strength(u)
  713. int u;
  714. {
  715.     return 1;
  716. }
  717.  
  718. /* Display the results of our calculations. */
  719.  
  720. void
  721. display_assessment()
  722. {
  723.     int t, u, u2;
  724.  
  725.     DMprintf("\nUnit Attributes:\n");
  726.     for_all_unit_types(u) {
  727.     DMprintf(" %-3.3s : base %d, transport %d, carrier %d, worth %d\n",
  728.            shortest_unique_name(u), u_is_base(u),
  729.            u_is_transport(u), u_is_carrier(u), u_bw(u));
  730.     DMprintf("    Operate between ranges %d and %d\n", operating_range_worst(u), operating_range_best(u));
  731.     }
  732.     DMprintf("\nUnit vs Unit Combat:\n");
  733.     for_all_unit_types(u) {
  734.     DMprintf(" %-3.3s:", shortest_unique_name(u));
  735.     for_all_unit_types(u2)
  736.       DMprintf("%5d", uu_zz_bhw(u, u2));
  737.     DMprintf("\n");
  738.     }
  739.     DMprintf("\nUnit vs Unit Fire:\n");
  740.     for_all_unit_types(u) {
  741.     DMprintf(" %-3.3s:", shortest_unique_name(u));
  742.     for_all_unit_types(u2)
  743.       DMprintf("%5d", uu_zz_bfw(u, u2));
  744.     DMprintf("\n");
  745.     }
  746.     DMprintf("\nUnit vs Unit Capture:\n");
  747.     for_all_unit_types(u) {
  748.     DMprintf(" %-3.3s:", shortest_unique_name(u));
  749.     for_all_unit_types(u2)
  750.       DMprintf(" %4d", uu_zz_bcw(u, u2));
  751.     DMprintf("\n");
  752.     }
  753.     DMprintf("\nUnit vs Unit Transport:\n");
  754.     for_all_unit_types(u) {
  755.     DMprintf(" %-3.3s:", shortest_unique_name(u));
  756.     for_all_unit_types(u2)
  757.       DMprintf(" %4d", uu_zz_btw(u, u2));
  758.     DMprintf("\n");
  759.     }
  760.     DMprintf("\n");
  761. }
  762.  
  763. int
  764. is_base_for(u1, u2)
  765. int u1, u2;
  766. {
  767.     return (u_speed(u1) == 0
  768.         && (uu_capacity_x(u2, u1) > 0
  769.         || (uu_size(u2, u1) <= u_capacity(u1))));
  770. }
  771.  
  772. int
  773. is_carrier_for(u1, u2)
  774. int u1, u2;
  775. {
  776.     return (u_speed(u1) > 0
  777.         && (uu_capacity_x(u2, u1) > 0
  778.         || (uu_size(u2, u1) <= u_capacity(u1))));
  779. }
  780.  
  781. /* Since *.def parameters don't have setters usually, we have to supply
  782.    some here.  These are very sensitive to how the parameters are organized,
  783.    and they don't do any checking, so you have to careful about using them. */
  784.  
  785. void set_u_is_base(u, n) int u, n; {  utypes[u].is_base = n;  }
  786. void set_u_is_transport(u, n) int u, n; {  utypes[u].is_transport = n;  }
  787. void set_u_is_carrier(u, n) int u, n; {  utypes[u].is_carrier = n;  }
  788. void set_u_is_base_builder(u, n) int u, n; {  utypes[u].is_base_builder = n;  }
  789. void set_u_can_make(u, n) int u, n; {  utypes[u].can_make = n;  }
  790. void set_u_can_capture(u, n) int u, n; {  utypes[u].can_capture = n;  }
  791. void set_u_bw(u, n) int u, n; {  utypes[u].bw = n;  }
  792.  
  793. int bhwtab = -1;
  794. int bfwtab = -1;
  795. int bcwtab = -1;
  796. int btwtab = -1;
  797.  
  798. void
  799. set_uu_bhw(u1, u2, v)
  800. int u1, u2, v;
  801. {
  802.     if (bhwtab < 0) {
  803.     for (bhwtab = 0; tabledefns[bhwtab].name != NULL; ++bhwtab) {
  804.         if (strcmp("zz-basic-hit-worth", tabledefns[bhwtab].name) == 0) {
  805.         allocate_table(bhwtab, FALSE);
  806.         break;
  807.         }
  808.     }
  809.     }
  810.     if (tabledefns[bhwtab].table == NULL)
  811.       run_error("no bhw table allocated");
  812.     (*(tabledefns[bhwtab].table))[numutypes * u1 + u2] = v;
  813. }
  814.  
  815. void
  816. set_uu_bfw(u1, u2, v)
  817. int u1, u2, v;
  818. {
  819.     if (bfwtab < 0) {
  820.     for (bfwtab = 0; tabledefns[bfwtab].name != NULL; ++bfwtab) {
  821.         if (strcmp("zz-basic-fire-worth", tabledefns[bfwtab].name) == 0) {
  822.         allocate_table(bfwtab, FALSE);
  823.         break;
  824.         }
  825.     }
  826.     }
  827.     if (tabledefns[bfwtab].table == NULL)
  828.       run_error("no bfw table allocated");
  829.     (*(tabledefns[bfwtab].table))[numutypes * u1 + u2] = v;
  830. }
  831.  
  832. void
  833. set_uu_bcw(u1, u2, v)
  834. int u1, u2, v;
  835. {
  836.     if (bcwtab < 0) {
  837.     for (bcwtab = 0; tabledefns[bcwtab].name != NULL; ++bcwtab) {
  838.         if (strcmp("zz-basic-capture-worth", tabledefns[bcwtab].name) == 0) {
  839.         allocate_table(bcwtab, FALSE);
  840.         break;
  841.         }
  842.     }
  843.     }
  844.     if (tabledefns[bcwtab].table == NULL)
  845.       run_error("no bcw table allocated");
  846.     (*(tabledefns[bcwtab].table))[numutypes * u1 + u2] = v;
  847. }
  848.  
  849.  
  850. void
  851. set_uu_btw(u1, u2, v)
  852. int u1, u2, v;
  853. {
  854.     if (btwtab < 0) {
  855.     for (btwtab = 0; tabledefns[btwtab].name != NULL; ++btwtab) {
  856.         if (strcmp("zz-basic-transport-worth", tabledefns[btwtab].name) == 0) {
  857.         allocate_table(btwtab, FALSE);
  858.         break;
  859.         }
  860.     }
  861.     }
  862.     if (tabledefns[btwtab].table == NULL)
  863.       run_error("no btw table allocated");
  864.     (*(tabledefns[btwtab].table))[numutypes * u1 + u2] = v;
  865. }
  866.