1 /* Implementations of Xconq actions.
2    Copyright (C) 1987-1989, 1991-2000 Stanley T. Shebs.
3    Copyright (C) 2005 Eric A. McDonald.
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 /*! \file kernel/actions.c
11  * \brief Implementations of Xconq actions.
12  *
13  * The general theory of actions is that interface or AI code calls, for
14  * an action foo, the routine prep_foo_action, which just records the action
15  * for later execution.  The action loop in run_game eventually calls
16  * do_foo_action, which first calls check_foo_action to confirm that the
17  * action will succeed.  If check_foo_action does not find any errors, then
18  * the action cannot fail.  The main body of do_foo_action then implements
19  * the effects of the action.  Interfaces may call check_foo_action freely,
20  * but should never call do_foo_action directly.
21  *
22  * action.def is used to declare the actions as extern int, as well
23  * as defining the action default function array, actiondefns.  A macro,
24  * ACTION_DEF is redefined to use different portions of it's arguments
25  * to define the different types of information to this module.
26  *
27  * Each action has an acting unit, which is the unit that schedules the action
28  * and supplies the ACP to perform the action. Each action also has an "actee",
29  * a unit that actually performs the action (extractor, builder, creator, etc).
30  * The two units are currently always identical, but the theoretical possibility
31  * of splitting the work in this way is supported by two separate unit arguments
32  * in all action functions. It is the status, position, capabilities and available
33  * supplies of the "actee" that determines if, how and to what extent the action
34  * can be performed, but the action is also limited by the ACPs that are available
35  * to the acting unit. Note that the "actee" is called so for historical reasons - a
36  * better name would be "actor" since it in most cases is the active unit. One
37  * exception is the materials transfer code, where the "actee" is the donor (not
38  * necessarily active) of the transferred materials. Another example is the
39  * disband action where the "actee" is the unit being disbanded. Other parameters
40  * may be defined.
41  *
42  * \note We can't declare all the action functions as static
43  * because some of them are in other files, but don't
44  * let them be visible to all files.
45  *
46  * \note <P>The DEF_ACTION macro and it's like can't be documented directly
47  * with Doxygen, as it doesn't support overlaid macros, or macro substitiution
48  * in comments.  So where a single definition file is used for several purposes,
49  * the documentation has to be manually included each time, which kind of
50  * defeats the purpose of having the definions in a single file.  One
51  * possibility would be to use a pre-processor like m4 to create a set
52  * of documentation includes, like action_function.doc to be included.
53  * It's probably not worthwile for external function declarations, since
54  * they'll be documented where they are defined, but it might be nice for
55  * things like enumerations or fixed data structures.
56  */
57 
58 #include "conq.h"
59 #include "kernel.h"
60 
61 extern int at_turn_start;
62 
63 static int creator_always_dies_on_creation(int u, int new_u);
64 static void set_created_unit_props(Unit *newunit, Unit *creator, Side *side);
65 //! Checks that are common to both explicit and auto-repair.
66 static int can_any_repair_common(Unit *actor, Unit *repairer, Unit *repairee);
67 static int give_away(Unit *unit, int m, int amt);
68 static void notify_action(Unit *unit, Action *action);
69 static void play_action_movies(Unit *unit, Action *action);
70 static void adjust_tech_crossover(Side *side, int u);
71 static void adjust_tooling_crossover(Unit *unit, int u2);
72 static void distribute_material(Unit *unit, int m, int amt);
73 static void notify_tech(Side *side, int u, int oldtech, int newtech);
74 static void notify_tp(Side *side, Unit *unit, int u2, int oldtp, int newtp);
75 static int extract_one_round(Unit *extractor, int x, int y, int m, int amount);
76 
77 #undef  DEF_ACTION
78 
79 #define DEF_ACTION(name,code,args,prepfn,netprepfn,DOFN,checkfn,ARGDECL,doc)  \
80     extern int DOFN ARGDECL;
81 
82 #include "action.def"
83 
84 #undef  DEF_ACTION
85 #define DEF_ACTION(NAME,CODE,ARGS,prepfn,netprepfn,dofn,checkfn,argdecl,doc)  \
86     { CODE, NAME, ARGS },
87 
88 /*! \brief Action function table.
89  *
90  * The table of all the action functions declared above.  It uses
91  * CODE_DEF_ACTION and action.def above to generate an "extern int"
92  * declaration for every action (prep, do, and * check).  Below it
93  * generates a table with 3 entries for each function, a code number
94  * (CODe), the name of the function (NAME), and the extended
95  * declaration list for the function (ARGS).
96  */
97 ActionDefn actiondefns[] = {
98 
99 #include "action.def"
100 
101     { (ActionType)-1, NULL, NULL }
102 };
103 
104 /*! \brief Retreat flag.
105  *
106  * This is used to indicate that a move is a retreat; for normal
107  * movement it will always be false.
108  */
109 int retreating;
110 
111 /*! \brief Type of Unit from which a Unit is retreating.
112  *
113  * This is a specific type of Unit that the retreater is running away from.
114  */
115 int retreating_from = NONUTYPE;
116 
117 /*! \brief Action description buffer.
118  *
119  * This is used to compose a description of what a Unit is doing.
120  */
121 char *actiondesigbuf = NULL;
122 
123 extern Action *latest_action;
124 
125 /* Cache variables. */
126 int *cache__type_max_night_acp_from_any_terrains = NULL;
127 int *cache__type_max_acp_from_any_occs = NULL;
128 int *cache__type_max_acp = NULL;
129 
130 int
could_take_from_treasury(int u,int m)131 could_take_from_treasury(int u, int m)
132 {
133     assert_error(is_unit_type(u), "Attempted to manipulate an invalid utype");
134     assert_error(is_material_type(m),
135                  "Attempted to manipulate an invalid mtype");
136     return (um_takes_from_treasury(u, m) && m_treasury(m)
137 	    && (0 < g_treasury_size()));
138 }
139 
140 int
could_take_from_treasury(int u,Side * side,int m)141 could_take_from_treasury(int u, Side *side, int m)
142 {
143     assert_error(is_unit_type(u), "Attempted to manipulate an invalid utype");
144     assert_error(side, "Attempted to access a NULL side");
145     assert_error(is_material_type(m),
146                  "Attempted to manipulate an invalid mtype");
147     return ((side == indepside) && !g_indepside_has_treasury() ? FALSE
148 	    : could_take_from_treasury(u, m));
149 }
150 
151 int
could_take_directly_from_treasury(int u,int m)152 could_take_directly_from_treasury(int u, int m)
153 {
154     assert_error(is_unit_type(u), "Attempted to manipulate an invalid utype");
155     assert_error(is_material_type(m),
156                  "Attempted to manipulate an invalid mtype");
157     return (!um_storage_x(u, m) && could_take_from_treasury(u, m));
158 }
159 
160 int
could_take_directly_from_treasury(int u,Side * side,int m)161 could_take_directly_from_treasury(int u, Side *side, int m)
162 {
163     assert_error(is_unit_type(u), "Attempted to manipulate an invalid utype");
164     assert_error(side, "Attempted to access a NULL side");
165     assert_error(is_material_type(m),
166                  "Attempted to manipulate an invalid mtype");
167     return ((side == indepside) && !g_indepside_has_treasury() ? FALSE
168 	    : could_take_directly_from_treasury(u, m));
169 }
170 
171 int
could_give_to_treasury(int u,int m)172 could_give_to_treasury(int u, int m)
173 {
174     assert_error(is_unit_type(u), "Attempted to manipulate an invalid utype");
175     assert_error(is_material_type(m),
176                  "Attempted to manipulate an invalid mtype");
177     return (um_gives_to_treasury(u, m) && m_treasury(m)
178 	    && (0 < g_treasury_size()));
179 }
180 
181 int
could_give_to_treasury(int u,Side * side,int m)182 could_give_to_treasury(int u, Side *side, int m)
183 {
184     assert_error(is_unit_type(u), "Attempted to manipulate an invalid utype");
185     assert_error(side, "Attempted to access a NULL side");
186     assert_error(is_material_type(m),
187                  "Attempted to manipulate an invalid mtype");
188     return ((side == indepside) && !g_indepside_has_treasury() ? FALSE
189 	    : could_give_to_treasury(u, m));
190 }
191 
192 int
could_give_directly_to_treasury(int u,int m)193 could_give_directly_to_treasury(int u, int m)
194 {
195     assert_error(is_unit_type(u), "Attempted to manipulate an invalid utype");
196     assert_error(is_material_type(m),
197                  "Attempted to manipulate an invalid mtype");
198     return (!um_storage_x(u, m) && could_give_to_treasury(u, m));
199 }
200 
201 int
could_give_directly_to_treasury(int u,Side * side,int m)202 could_give_directly_to_treasury(int u, Side *side, int m)
203 {
204     assert_error(is_unit_type(u), "Attempted to manipulate an invalid utype");
205     assert_error(side, "Attempted to access a NULL side");
206     assert_error(is_material_type(m),
207                  "Attempted to manipulate an invalid mtype");
208     return ((side == indepside) && !g_indepside_has_treasury() ? FALSE
209 	    : could_give_directly_to_treasury(u, m));
210 }
211 
212 void
get_materials_availability(Unit * actor,Unit * agent,long * p_mavail,long * p_mavailmax,int flags)213 get_materials_availability(
214     Unit *actor, Unit *agent, long *p_mavail, long *p_mavailmax, int flags)
215 {
216     int u2 = NONUTYPE;
217     Side *side = NULL, *side2 = NULL, *tside = NULL;
218     int m = NONMTYPE;
219 
220     assert_error(in_play(actor),
221 		 "Materials Check: Attempted to access an out-of-play actor");
222     assert_error(in_play(agent),
223 		 "Materials Check: Attempted to access an out-of-play agent");
224     assert_error(p_mavail,
225 		 "Materials Check: Attempted to access a NULL materials array");
226     assert_error(p_mavailmax,
227 		 "Materials Check: Attempted to access a NULL materials array");
228     // Useful info.
229     u2 = agent->type;
230     side = actor->side;
231     side2 = agent->side;
232     // Process flags.
233     tside = (flags & MReq_AGENT_TREASURY ? side2 : side);
234     // Fill out the materials arrays.
235     for_all_material_types(m) {
236 	if (could_take_directly_from_treasury(u2, tside, m)) {
237 	    p_mavail[m] = tside->treasury[m];
238 	    p_mavailmax[m] = g_treasury_size();
239 	}
240 	else if (could_take_from_treasury(u2, tside, m)) {
241 	    p_mavail[m] =
242 		min(agent->supply[m] + tside->treasury[m], um_storage_x(u2, m));
243 	    p_mavailmax[m] = um_storage_x(u2, m);
244 	}
245 	else {
246 	    p_mavail[m] = agent->supply[m];
247 	    p_mavailmax[m] = um_storage_x(u2, m);
248 	}
249     }
250 }
251 
252 int
can_meet_materials_requirement(long * p_mreq,long * p_mavail,long * p_mavailmax)253 can_meet_materials_requirement(
254     long *p_mreq, long *p_mavail, long *p_mavailmax)
255 {
256     int m = NONMTYPE;
257 
258     assert_error(p_mreq,
259 		 "Materials Check: Attempted to access a NULL materials array");
260     assert_error(p_mavail,
261 		 "Materials Check: Attempted to access a NULL materials array");
262     assert_error(p_mavailmax,
263 		 "Materials Check: Attempted to access a NULL materials array");
264     // For each material, see if requirement can be met by availabilities.
265     for_all_material_types(m) {
266 	// If requirement > what can ever be available...
267 	if (p_mreq[m] > p_mavailmax[m])
268 	    return A_ANY_CANNOT_DO;
269 	// If requirement > what is currently available...
270 	if (p_mreq[m] > p_mavail[m])
271 	    return A_ANY_NO_MATERIAL;
272     }
273     return A_ANY_OK;
274 }
275 
276 int
can_meet_materials_requirement(Unit * actor,Unit * agent,int (* getter)(int u,int m),int u3,int mult)277 can_meet_materials_requirement(
278     Unit *actor, Unit *agent, int (*getter)(int u, int m), int u3, int mult)
279 {
280     int rslt = A_ANY_OK;
281     int u2 = NONUTYPE;
282     int m = NONMTYPE;
283     Side *side = NULL;
284     long amtreq = 0, aamtavail = 0, tamtavail = 0, astorcap = 0;
285 
286     assert_error(in_play(actor), "Attempted to access an out-of-play unit");
287     assert_error(in_play(agent), "Attempted to access an out-of-play unit");
288     assert_error(getter, "Attempted to use a NULL getter function");
289     u2 = agent->type;
290     side = actor->side;
291     for_all_material_types(m) {
292 	/* Get amount requested. */
293 	amtreq = getter(is_unit_type(u3) ? u3 : u2, m) * mult;
294 	/* If none requested, then no further processing for material. */
295 	if (!amtreq)
296 	  continue;
297 	/* Get amount available in agent. */
298 	aamtavail = agent->supply[m];
299 	/* Check if agent supply can satisfy request. */
300 	if (aamtavail >= amtreq)
301 	  continue;
302 	/* Get agent's storage capacity for material. */
303 	astorcap = um_storage_x(u2, m);
304 	/* Can agent take from treasury? */
305 	if (side_has_treasury(side, m) && um_takes_from_treasury(u2, m)) {
306 	    tamtavail = side->treasury[m];
307 	    /* Does agent use treasury directly? */
308 	    if (!um_storage_x(u2, m)) {
309 		/* Check if request exceeds treasury size. */
310 		if (amtreq > g_treasury_size())
311 		  return A_ANY_CANNOT_DO;
312 		/* Check if side treasury can satisfy request. */
313 		if (amtreq > tamtavail)
314 		  return A_ANY_NO_MATERIAL;
315 	    }
316 	    /* Else, agent only uses what is needed from treasury. */
317 	    else {
318 		/* Check if request exceeds agent capacity. */
319 		if (amtreq > astorcap)
320 		  return A_ANY_CANNOT_DO;
321 		/* Check if request exceeds agent + treasury amounts. */
322 		if (amtreq > (aamtavail + tamtavail))
323 		  return A_ANY_NO_MATERIAL;
324 	    }
325 	}
326 	/* Else, agent cannot use from treasury, but needs more material. */
327 	else {
328 	    /* Check if request exceeds agent capacity. */
329 	    if (amtreq > astorcap)
330 	      return A_ANY_CANNOT_DO;
331 	    else
332 	      return A_ANY_NO_MATERIAL;
333 	}
334     }
335     return rslt;
336 }
337 
338 int
consume_materials(Unit * actor,Unit * consumer,int (* getter)(int u,int m),int u3,int mult)339 consume_materials(
340     Unit *actor, Unit *consumer, int (*getter)(int u, int m), int u3, int mult)
341 {
342     int rslt = A_ANY_OK;
343     int u2 = NONUTYPE;
344     int m = NONMTYPE;
345     Side *side = NULL;
346     long amtreq = 0, camtavail = 0, tamtavail = 0, cstorcap = 0, tsize = 0;
347 
348     assert_error(in_play(actor), "Attempted to access an out-of-play unit");
349     assert_error(in_play(consumer),
350 		 "Attempted to access an out-of-play unit");
351     assert_error(getter, "Attempted to use a NULL getter function");
352     u2 = consumer->type;
353     side = actor->side;
354     /* Check before diving in. */
355     if (!valid(rslt = can_meet_materials_requirement(actor, consumer, getter)))
356       return rslt;
357     for_all_material_types(m) {
358 	/* Get amount requested. */
359 	amtreq = getter(is_unit_type(u3) ? u3 : u2, m) * mult;
360 	/* If none requested, then no further processing for material. */
361 	if (!amtreq)
362 	  continue;
363 	/* Get amount available in consumer. */
364 	camtavail = consumer->supply[m];
365 	/* Get consumer's storage capacity for material. */
366 	cstorcap = um_storage_x(u2, m);
367 	/* Get treasury amount, if any. */
368 	if (side_has_treasury(side, m) && um_takes_from_treasury(u2, m))
369 	  tamtavail = side->treasury[m];
370 	else
371 	  tamtavail = 0;
372 	/* Get treasury's size. */
373 	if (side_has_treasury(side, m) && um_gives_to_treasury(u2, m))
374 	  tsize = g_treasury_size();
375 	else
376 	  tsize = 0;
377 	/* If request is positive. */
378 	if (0 < amtreq) {
379 	    /* Consume consumer supply. */
380 	    if (amtreq <= camtavail) {
381 		consumer->supply[m] -= amtreq;
382 		continue;
383 	    }
384 	    else {
385 		amtreq -= camtavail;
386 		consumer->supply[m] = 0;
387 	    }
388 	    /* Consume treasury supply. */
389 	    side->treasury[m] -= amtreq;
390 	}
391 	/* Else request is negative. */
392 	else {
393 	    /* Produce consumer supply, if possible. */
394 	    if (-amtreq <= (cstorcap - camtavail)) {
395 		consumer->supply[m] -= amtreq;
396 		continue;
397 	    }
398 	    else {
399 		amtreq += (cstorcap - camtavail);
400 		consumer->supply[m] = cstorcap;
401 	    }
402 	    /* Produce treasury supply, if possible. */
403 	    if (0 < tsize) {
404 		side->treasury[m] = min(-amtreq + tamtavail, tsize);
405 		amtreq = tsize - (-amtreq + tamtavail);
406 		/* (TODO: Try something with any remaining excess?) */
407 	    }
408 	}
409     }
410     return rslt;
411 }
412 
413 //! Does unit has enough of each material needed to act?
414 
415 int
has_supply_to_act(Unit * unit)416 has_supply_to_act(Unit *unit)
417 {
418     int m = NONMTYPE;
419 
420     for_all_material_types(m) {
421 	if (unit->supply[m] < um_to_act(unit->type, m))
422 	  return FALSE;
423     }
424     return TRUE;
425 }
426 
427 /* Unit/utype status/analysis functions. */
428 
429 /*! \todo Eventually assert activeness instead of just returning an error. */
430 
431 int
can_act(Unit * actor,Unit * agent)432 can_act(Unit *actor, Unit *agent)
433 {
434     int rslt = A_ANY_OK;
435 
436     // Only active units can act.
437     if (!is_active(actor))
438       return A_ANY_ERROR;
439     if (!is_active(agent))
440       return A_ANY_ERROR;
441     /* Does agent have enough material to act? */
442     if (!has_supply_to_act(agent))
443       return A_ANY_NO_MATERIAL;
444     return rslt;
445 }
446 
447 int
has_enough_tooling(Unit * constructor,int u2)448 has_enough_tooling(Unit *constructor, int u2)
449 {
450     assert_error(is_active(constructor),
451 		 "Toolup Check: Attempted to access an inactive constructor");
452     assert_error(is_unit_type(u2),
453 		 "Toolup Check: Encountered invalid unit type");
454     return ((constructor->tooling ? constructor->tooling[u2] : 0)
455 	    >= uu_tp_to_build(constructor->type, u2));
456 }
457 
458 int
could_toolup_for(int u,int u2)459 could_toolup_for(int u, int u2)
460 {
461     assert_error(is_unit_type(u),
462 		 "Toolup Check: Encountered invalid unit type");
463     assert_error(is_unit_type(u2),
464 		 "Toolup Check: Encountered invalid unit type");
465     return (uu_toolup_for(u, u2) && (0 < uu_tp_per_toolup(u, u2))
466 	    && (uu_tp_max(u, u2) >= uu_tp_to_build(u, u2)));
467 }
468 
469 int
could_toolup_for_any(int u)470 could_toolup_for_any(int u)
471 {
472     int u2 = NONUTYPE;
473 
474     assert_error(is_unit_type(u),
475 		 "Toolup Check: Encountered invalid unit type");
476     for_all_unit_types(u2) {
477 	if (could_toolup_for(u, u2))
478 	    return TRUE;
479     }
480     return FALSE;
481 }
482 
483 int
can_toolup_for(Unit * actor,Unit * constructor,int u3)484 can_toolup_for(Unit *actor, Unit *constructor, int u3)
485 {
486     static long *p_mavail, *p_mavailmax, *p_mreq;
487 
488     int rslt = A_ANY_OK;
489     int u = NONUTYPE, u2 = NONUTYPE;
490     Side *side = NULL;
491     int acpcost = 0, tpt = 0;
492     int m = NONMTYPE;
493 
494     assert_error(is_active(actor),
495                  "Toolup Check: Attempted to manipulate an inactive actor");
496     assert_error(is_active(constructor),
497 "Toolup Check: Attempted to manipulate an inactive constructor");
498     assert_error(is_unit_type(u3),
499                  "Toolup Check: Encountered invalid unit type to toolup for");
500     // Can the creator act?
501     if (!valid(rslt = can_act(actor, constructor)))
502       return rslt;
503     // Some useful info.
504     u = actor->type;
505     u2 = constructor->type;
506     side = actor->side;
507     tpt = uu_tp_per_toolup(u2, u3);
508     // Maybe we are already tooled up or don't have any tooling up to do?
509     if (has_enough_tooling(constructor, u3))
510 	return A_ANY_OK;
511     // Could the constructor's utype toolup for the requested utype?
512     if (!could_toolup_for(u2, u3))
513 	return A_ANY_CANNOT_DO;
514     // Initialize materials arrays, if necessary.
515     if (!p_mavail)
516         p_mavail = (long *)xmalloc(nummtypes * sizeof(long));
517     if (!p_mavailmax)
518         p_mavailmax = (long *)xmalloc(nummtypes * sizeof(long));
519     if (!p_mreq)
520         p_mreq = (long *)xmalloc(nummtypes * sizeof(long));
521     // Possibly check against ACP.
522     if (!u_acp_independent(u2)
523 	&& (0 < (acpcost = uu_acp_to_toolup(u2, u3)))) {
524         // Can the ACP source ever provide enough ACP?
525         if (!can_have_enough_acp(actor, acpcost))
526             return A_ANY_CANNOT_DO;
527         // Does the ACP source have enough ACP to support toolup?
528         if (!has_enough_acp(actor, acpcost))
529             return A_ANY_NO_ACP;
530     }
531     // Check if utype is allowed, and if needed tech & advances exist.
532     if (!side_can_build(side, u3))
533         return A_ANY_CANNOT_DO;
534     // Compare materials availability and requirements.
535     get_materials_availability(actor, constructor, p_mavail, p_mavailmax);
536     for_all_material_types(m) {
537         p_mreq[m] =
538             max(um_to_toolup(u2, m),
539                 um_consumption_per_tooledup(u3, m)
540                 + um_consumption_per_toolup(u2, m)
541 		+ tpt * um_consumption_per_tp(u2, m));
542     }
543     if (!valid(
544             rslt =
545                 can_meet_materials_requirement(p_mreq, p_mavail, p_mavailmax)))
546         return rslt;
547     return A_ANY_OK;
548 }
549 
550 //! Materials requirement for build or create-as-build action.
551 
552 static int
materials_req_for_build(int u2,int u3,int m,int cp)553 materials_req_for_build(int u2, int u3, int m, int cp)
554 {
555     assert_error(is_unit_type(u2),
556 		 "Construct Check: Encountered invalid constructor unit type");
557     assert_error(is_unit_type(u3),
558 		 "Construct Check: Encountered invalid constructee unit type");
559     assert_error(is_material_type(m),
560 "Construct Check: Encountered invalid construction material type");
561     return max(um_to_build(u2, m),
562 	       (um_consumption_per_cp(u3, m) * cp)
563 		+ um_consumption_per_built(u3, m)
564 		+ um_consumption_per_build(u2, m));
565 }
566 
567 int
could_create(int u,int u2)568 could_create(int u, int u2)
569 {
570     assert_error(is_unit_type(u),
571 		 "Create Check: Encountered invalid creator unit type");
572     assert_error(is_unit_type(u2),
573 		 "Create Check: Encountered invalid creation unit type");
574     if (uu_create_as_build(u, u2)) {
575 	if (!uu_build(u, u2) || (0 > uu_cp_per_build(u, u2)))
576 	    return FALSE;
577     }
578     else {
579 	if (!uu_create(u, u2) || (0 > uu_creation_cp(u, u2)))
580 	    return FALSE;
581     }
582     if ((0 < uu_tp_to_build(u, u2)) && !could_toolup_for(u, u2))
583 	return FALSE;
584     return TRUE;
585 }
586 
587 int
could_create_any(int u)588 could_create_any(int u)
589 {
590     int u2 = NONUTYPE;
591 
592     assert_error(is_unit_type(u),
593 		 "Create Check: Encountered invalid creator unit type");
594     for_all_unit_types(u2) {
595 	if (could_create(u, u2))
596 	    return TRUE;
597     }
598     return FALSE;
599 }
600 
601 int
can_create_common(Unit * actor,Unit * creator,int u3,int x,int y)602 can_create_common(Unit *actor, Unit *creator, int u3, int x, int y)
603 {
604     static long *p_mavail, *p_mavailmax, *p_mreq;
605 
606     int rslt = A_ANY_OK;
607     int u = NONUTYPE, u2 = NONUTYPE;
608     Side *side = NULL;
609     int acpcost = 0, cp = -1;
610     int m = NONMTYPE;
611     int cab = FALSE;
612 
613     assert_error(is_active(actor),
614 		 "Create Check: Attempted to manipulate an inactive actor");
615     assert_error(is_active(creator),
616 		 "Create Check: Attempted to manipulate an inactive creator");
617     assert_error(is_unit_type(u3),
618 		 "Create Check: Encountered invalid unit type to create");
619     if (!inside_area(x, y))
620 	return A_MOVE_CANNOT_LEAVE_WORLD;
621     // Can the creator act?
622     if (!valid(rslt = can_act(actor, creator)))
623       return rslt;
624     u = actor->type;
625     u2 = creator->type;
626     side = actor->side;
627     cab = uu_create_as_build(u2, u3);
628     // Can the creator's utype create the requested utype?
629     if (!could_create(u2, u3))
630 	return A_ANY_CANNOT_DO;
631     // Initialize materials arrays, if necessary.
632     if (!p_mavail)
633 	p_mavail = (long *)xmalloc(nummtypes * sizeof(long));
634     if (!p_mavailmax)
635 	p_mavailmax = (long *)xmalloc(nummtypes * sizeof(long));
636     if (!p_mreq)
637 	p_mreq = (long *)xmalloc(nummtypes * sizeof(long));
638     // Is the distance within creation range?
639     if (distance(creator->x, creator->y, x, y)
640 	> (cab ? uu_build_range(u2, u3) : uu_create_range(u2, u3)))
641 	return A_ANY_TOO_FAR;
642     // Possibly check against ACP.
643     if (!u_acp_independent(u2)
644 	&& (0 < (cab ? uu_acp_to_build(u2, u3) : uu_acp_to_create(u2, u3)))) {
645 	// Can the ACP source ever provide enough ACP?
646 	acpcost = (cab ? uu_acp_to_build(u2, u3) : uu_acp_to_create(u2, u3));
647 	if (!can_have_enough_acp(actor, acpcost))
648 	    return A_ANY_CANNOT_DO;
649 	// Does the ACP source have enough ACP to support creation?
650 	if (!has_enough_acp(actor, acpcost))
651 	    return A_ANY_NO_ACP;
652     }
653     // Check if utype is allowed, and if needed tech & advances exist.
654     if (!side_can_build(side, u3))
655 	return A_ANY_CANNOT_DO;
656     // Check if we hit a limit on the number of units.
657     if (!new_unit_allowed_on_side(u3, side))
658 	return A_ANY_CANNOT_DO;
659     // Check the tooling.
660     if (!valid(can_toolup_for(actor, creator, u3)))
661 	return A_ANY_CANNOT_DO;
662     if (!has_enough_tooling(creator, u3))
663 	return A_CONSTRUCT_NO_TOOLING;
664     // If creator is in transport, can creator build from within the transport?
665     if (creator->transport
666         && !uu_occ_can_build(creator->transport->type, u2))
667 	return A_ANY_CANNOT_DO;
668     // Compare materials availability and requirements.
669     cp = min((cab ? uu_cp_per_build(u2, u3) : uu_creation_cp(u2, u3)),
670 	     u_cp(u3));
671     get_materials_availability(actor, creator, p_mavail, p_mavailmax);
672     for_all_material_types(m) {
673 	if (cab)
674 	    p_mreq[m] = materials_req_for_build(u2, u3, m, cp);
675 	else
676 	    p_mreq[m] =
677 		max(um_to_create(u2, m),
678 		    um_consumption_per_cp(u3, m) * cp
679 		    + um_consumption_on_creation(u3, m)
680 		    + um_consumption_per_create(u2, m));
681     }
682     if (!valid(
683 	    rslt =
684 		can_meet_materials_requirement(p_mreq, p_mavail, p_mavailmax)))
685 	return rslt;
686     return A_ANY_OK;
687 }
688 
689 int
could_build(int u,int u2)690 could_build(int u, int u2)
691 {
692     assert_error(is_unit_type(u),
693 		 "Build Check: Encountered invalid builder unit type");
694     assert_error(is_unit_type(u2),
695 		 "Build Check: Encountered invalid buildee unit type");
696     return (uu_build(u, u2) && (0 < uu_cp_per_build(u, u2))
697 	    && (!uu_tp_to_build(u, u2) || could_toolup_for(u, u2)));
698 }
699 
700 int
could_build_any(int u)701 could_build_any(int u)
702 {
703     int u2 = NONUTYPE;
704 
705     assert_error(is_unit_type(u),
706 		 "Build Check: Encountered invalid builder unit type");
707     for_all_unit_types(u2) {
708 	if (could_build(u, u2))
709 	    return TRUE;
710     }
711     return FALSE;
712 }
713 
714 int
can_build(Unit * actor,Unit * builder,int u3)715 can_build(Unit *actor, Unit *builder, int u3)
716 {
717     int rslt = A_ANY_OK;
718     int u = NONUTYPE, u2 = NONUTYPE;
719 
720     assert_error(is_active(actor),
721 		 "Build Check: Attempted to access an inactive actor");
722     assert_error(is_active(builder),
723 		 "Build Check: Attempted to access an inactive builder");
724     assert_error(is_unit_type(u3),
725 		 "Build Check: Encountered an invalid buildee unit type");
726     u = actor->type;
727     u2 = builder->type;
728     if (!valid(rslt = can_act(actor, builder)))
729 	return rslt;
730     if (!could_build(u2, u3))
731 	return A_ANY_CANNOT_DO;
732     if (!valid(can_toolup_for(actor, builder, u3)))
733 	return A_ANY_CANNOT_DO;
734     if (!has_enough_tooling(builder, u3))
735 	return A_CONSTRUCT_NO_TOOLING;
736     return rslt;
737 }
738 
739 int
can_build(Unit * actor,Unit * builder,Unit * buildee)740 can_build(Unit *actor, Unit *builder, Unit *buildee)
741 {
742     static long *p_mavail, *p_mavailmax, *p_mreq;
743 
744     int rslt = A_ANY_OK;
745     int acp = 0, cp = -1;
746     int u = NONUTYPE, u2 = NONUTYPE, u3 = NONUTYPE;
747     int m = NONMTYPE;
748     Unit *transport = NULL;
749 
750     assert_error(is_active(actor),
751 		 "Build Check: Attempted to access an inactive actor");
752     assert_error(is_active(builder),
753 		 "Build Check: Attempted to access an inactive builder");
754     assert_error(in_play(buildee),
755 		 "Build Check: Attempted to access an out-of-play buildee");
756     u = actor->type;
757     u2 = builder->type;
758     u3 = buildee->type;
759     transport = builder->transport;
760     if (!valid(rslt = can_build(actor, builder, u3)))
761       return rslt;
762     // Can builder build while inside transport?
763     // Note that an exception is made, if building on the transport itself.
764     if (transport && (transport != buildee)
765         && !uu_occ_can_build(transport->type, u2))
766 	return A_ANY_CANNOT_DO;
767     // Initialize materials arrays, if necessary.
768     if (!p_mavail)
769         p_mavail = (long *)xmalloc(nummtypes * sizeof(long));
770     if (!p_mavailmax)
771         p_mavailmax = (long *)xmalloc(nummtypes * sizeof(long));
772     if (!p_mreq)
773         p_mreq = (long *)xmalloc(nummtypes * sizeof(long));
774     // Check if necessary ACP is available to build.
775     if (!u_acp_independent(u2) && (0 < uu_acp_to_build(u2, u3))) {
776 	acp = uu_acp_to_build(u2, u3);
777 	if (!can_have_enough_acp(actor, acp))
778 	    return A_ANY_CANNOT_DO;
779 	if (!has_enough_acp(actor, acp))
780 	    return A_ANY_NO_ACP;
781     }
782     // Compare materials availability and requirements.
783     cp = min(uu_cp_per_build(u2, u3), completenesses[u3] - buildee->cp);
784     get_materials_availability(actor, builder, p_mavail, p_mavailmax);
785     for_all_material_types(m)
786 	p_mreq[m] = materials_req_for_build(u2, u3, m, cp);
787     if (!valid(
788             rslt =
789                 can_meet_materials_requirement(p_mreq, p_mavail, p_mavailmax)))
790         return rslt;
791     return rslt;
792 }
793 
794 static int
can_any_repair_common(Unit * actor,Unit * repairer,Unit * repairee)795 can_any_repair_common(Unit *actor, Unit *repairer, Unit *repairee)
796 {
797     static long *p_mavail, *p_mavailmax, *p_mreq;
798 
799     int rslt = A_ANY_OK;
800     int u = NONUTYPE, u2 = NONUTYPE, u3 = NONUTYPE;
801     int m = NONMTYPE;
802 
803     assert_error(is_active(actor),
804 		 "Repair Check: Attempted to manipulate inactive actor");
805     assert_error(is_active(repairer),
806 		 "Repair Check: Attempted to manipulate inactive repairer");
807     assert_error(in_play(repairer),
808 		 "Repair Check: Attempted to manipulate out-of-play repairee");
809     // Check if we are attempting to repair an enemy?
810     if (enemy_side(repairer->side, repairee->side))
811 	return A_ANY_CANNOT_DO;
812     // Check if we meet basic action requirements.
813     if (!valid(rslt = can_act(actor, repairer)))
814 	return rslt;
815     // Useful info.
816     u = actor->type;
817     u2 = repairer->type;
818     u3 = repairee->type;
819     // Initialize materials arrays, if necessary.
820     if (!p_mavail)
821 	p_mavail = (long *)xmalloc(nummtypes * sizeof(long));
822     if (!p_mavailmax)
823 	p_mavailmax = (long *)xmalloc(nummtypes * sizeof(long));
824     if (!p_mreq)
825 	p_mreq = (long *)xmalloc(nummtypes * sizeof(long));
826     // Compare materials availability and requirements.
827     get_materials_availability(actor, repairer, p_mavail, p_mavailmax);
828     for_all_material_types(m) {
829 	p_mreq[m] =
830 	    max(um_to_repair(u2, m),
831 		um_consumption_per_repaired(u3, m)
832 		+ um_consumption_per_repair(u2, m));
833     }
834     if (!valid(
835             rslt =
836                 can_meet_materials_requirement(p_mreq, p_mavail, p_mavailmax)))
837         return rslt;
838     return A_ANY_OK;
839 }
840 
841 int
could_auto_repair(int u,int u2)842 could_auto_repair(int u, int u2)
843 {
844     assert_error(is_unit_type(u),
845 		 "Repair Check: Encountered an invalid repairer unit type");
846     assert_error(is_unit_type(u2),
847 		 "Repair Check: Encountered an invalid repairee unit type");
848     if (0 < uu_auto_repair(u, u2))
849 	return TRUE;
850     return FALSE;
851 }
852 
853 int
can_auto_repair(Unit * repairer,Unit * repairee)854 can_auto_repair(Unit *repairer, Unit *repairee)
855 {
856     int rslt = A_ANY_OK;
857     int u2 = NONUTYPE, u3 = NONUTYPE;
858     int recovery = FALSE;
859     int dist = -1;
860 
861     if (!is_active(repairer))
862 	return A_ANY_ERROR;
863     assert_error(in_play(repairee),
864 		 "Repair Check: Attempted to manipulate out-of-play repairee");
865     // Useful info.
866     u2 = repairer->type;
867     u3 = repairee->type;
868     dist = distance(repairer->x, repairer->y, repairee->x, repairee->y);
869     // Check if there is any repair to perform.
870     // Note: We check against full HP rather than doctrine level here,
871     //	because, technically, anything less than full HP means that
872     //	repair could be performed.
873     if (repairee->hp >= u_hp(u3))
874 	return A_ANY_OK;
875     // Could we use hp-recovery mechanism?
876     if ((repairer == repairee) && (0 < u_hp_recovery(u2)))
877 	recovery = TRUE;
878     // Could we auto-repair?
879     if (!could_auto_repair(u2, u3) && !recovery)
880 	return A_ANY_CANNOT_DO;
881     // Can we use hp-recovery mechanism?
882     if (recovery) {
883 	if (repairee->hp < u_hp_to_recover(u2))
884 	    // TODO: Should return A_REPAIR_TOO_DAMAGED.
885 	    return A_ANY_NO_MATERIAL;
886 	return A_ANY_OK;
887     }
888     // Are we in range for auto-repair?
889     if (dist > uu_auto_repair_range(u2, u3))
890 	return A_ANY_TOO_FAR;
891     // Additional checks.
892     if (!valid(rslt = can_any_repair_common(repairer, repairer, repairee)))
893 	return rslt;
894     return rslt;
895 }
896 
897 int
could_repair(int u,int u2)898 could_repair(int u, int u2)
899 {
900     assert_error(is_unit_type(u),
901 		 "Repair Check: Encountered an invalid repairer unit type");
902     assert_error(is_unit_type(u2),
903 		 "Repair Check: Encountered an invalid repairee unit type");
904     if (uu_repair(u, u2) && (0 < uu_hp_per_repair(u, u2)))
905 	return TRUE;
906     return FALSE;
907 }
908 
909 int
can_repair(Unit * actor,Unit * repairer,int u3)910 can_repair(Unit *actor, Unit *repairer, int u3)
911 {
912     int rslt = A_ANY_OK;
913     int u = NONUTYPE, u2 = NONUTYPE;
914 
915     assert_error(is_active(actor),
916 		 "Repair Check: Attempted to manipulate inactive actor");
917     assert_error(is_active(repairer),
918 		 "Repair Check: Attempted to manipulate inactive repairer");
919     assert_error(is_unit_type(u3),
920 		 "Repair Check: Encountered an invalid repairee unit type");
921     u = actor->type;
922     u2 = repairer->type;
923     // Check if we meet basic action requirements.
924     if (!valid(rslt = can_act(actor, repairer)))
925 	return rslt;
926     // Could we explicitly repair?
927     if (!could_repair(u2, u3))
928 	return A_ANY_CANNOT_DO;
929     return rslt;
930 }
931 
932 int
can_repair(Unit * actor,Unit * repairer,Unit * repairee)933 can_repair(Unit *actor, Unit *repairer, Unit *repairee)
934 {
935     int rslt = A_ANY_OK;
936     int u = NONUTYPE, u2 = NONUTYPE, u3 = NONUTYPE;
937     int acp = -1, dist = -1;
938 
939     assert_error(is_active(actor),
940 		 "Repair Check: Attempted to manipulate inactive actor");
941     assert_error(is_active(repairer),
942 		 "Repair Check: Attempted to manipulate inactive repairer");
943     assert_error(in_play(repairer),
944 		 "Repair Check: Attempted to manipulate out-of-play repairee");
945     // Additional checks.
946     if (!valid(rslt = can_any_repair_common(repairer, repairer, repairee)))
947 	return rslt;
948     // Useful info.
949     u = actor->type;
950     u2 = repairer->type;
951     u3 = repairee->type;
952     dist = distance(repairer->x, repairer->y, repairee->x, repairee->y);
953     // Check if there is any repair to perform.
954     // Note: We check against full HP rather than doctrine level here,
955     //	because, technically, anything less than full HP means that
956     //	repair could be performed.
957     if (repairee->hp >= u_hp(u3))
958 	return A_ANY_OK;
959     if (!valid(rslt = can_repair(actor, repairer, u3)))
960 	return rslt;
961     if (dist > uu_repair_range(u2, u3))
962 	return A_ANY_TOO_FAR;
963     // Check if necessary ACP is available for explicit repair.
964     if (!u_acp_independent(u2) && (0 < uu_acp_to_repair(u2, u3))) {
965 	acp = uu_acp_to_repair(u2, u3);
966 	if (!can_have_enough_acp(actor, acp))
967 	    return A_ANY_CANNOT_DO;
968 	if (!has_enough_acp(actor, acp))
969 	    return A_ANY_NO_ACP;
970     }
971     return rslt;
972 }
973 
974 int
can_change_type_to(int u,int u2,Side * side)975 can_change_type_to(int u, int u2, Side *side)
976 {
977     int rslt = A_ANY_OK;
978     int a = NONATYPE;
979 
980     assert_error(is_unit_type(u), "Attempted to reference an invalid utype");
981     assert_error(is_unit_type(u2),
982 		 "Attempted to change type to an invalid utype");
983     assert_error(side, "Attempted to access a NULL side");
984     /* Check if a manual change-type or auto-upgrade is ever possible. */
985     if (!could_change_type_to(u, u2) && !could_auto_upgrade_to(u, u2))
986       return A_ANY_CANNOT_DO;
987     /* Check if the turn number is high enough. */
988     if (g_turn() < uu_turn_to_change_type(u, u2))
989       /* (Should return A_ANY_PREMATURE.) */
990       return A_ANY_NO_MATERIAL;
991     /* Check if the unit's new type can be on the side. */
992     if (!type_allowed_on_side(u2, side))
993       return A_ANY_CANNOT_DO;
994     /* Check if the unit could ever have anough CXP. */
995     if (u_cxp_max(u) < uu_cxp_to_change_type(u, u2))
996       return A_ANY_CANNOT_DO;
997     /* Check if there could ever be ebough tech. */
998     if (u_tech_max(u2) < u_tech_to_change_type_to(u2))
999       return A_ANY_CANNOT_DO;
1000     /* Check if the side has enough tech. */
1001     if (side->tech[u2] < u_tech_to_change_type_to(u2))
1002       /* (Should return A_ANY_NO_TECH.) */
1003       return A_ANY_NO_MATERIAL;
1004     /* Check that the side has any advances necessary for the change. */
1005     for_all_advance_types(a) {
1006         if (!ua_to_change_type(u, a))
1007           continue;
1008         if (!has_advance(side, a))
1009           /* (Should return A_ANY_NO_ADVANCE.) */
1010           return A_ANY_NO_MATERIAL;
1011     }
1012     return rslt;
1013 }
1014 
1015 //! Can given unit change into given utype?
1016 
1017 int
can_change_type_to(Unit * actor,Unit * morpher,int u3)1018 can_change_type_to(Unit *actor, Unit *morpher, int u3)
1019 {
1020     int rslt = A_ANY_OK;
1021     int u = NONUTYPE, u2 = NONUTYPE, u4 = NONUTYPE;
1022     int acp = 0;
1023     Unit *occ = NULL;
1024 
1025     assert_error(in_play(actor), "Attempted to manipulate an out-of-play unit");
1026     assert_error(in_play(morpher),
1027 		 "Attempted to manipulate an out-of-play unit");
1028     assert_error(is_unit_type(u3),
1029 		 "Attempted to change type into an invalid utype");
1030     if (!valid(rslt = can_act(actor, morpher)))
1031       return rslt;
1032     u = actor->type;
1033     u2 = morpher->type;
1034     /* Is manual change-type valid? */
1035     if (!at_turn_start && !uu_change_type_to(u2, u3))
1036       return A_ANY_CANNOT_DO;
1037     /* Is auto-upgrade valid? */
1038     if (at_turn_start && (u3 != u_auto_upgrade_to(u2)))
1039       return A_ANY_CANNOT_DO;
1040     /* Go through utype-based and side-based tests. */
1041     if (!valid(rslt = can_change_type_to(u2, u3, actor->side)))
1042       return rslt;
1043     acp = uu_acp_to_change_type(u2, u3);
1044 #if (0)
1045     /* Check if the unit can even perform the action. */
1046     if (!at_turn_start && !u_acp_independent(u) && (acp < 1))
1047       return A_ANY_CANNOT_DO;
1048 #endif
1049     /* Check if the actor actually has enough ACP to make the
1050        change-type happen. Give a free pass for automated happenings at the
1051        the turn start. */
1052     if (!at_turn_start && !u_acp_independent(u) && !has_enough_acp(actor, acp))
1053       return A_ANY_NO_ACP;
1054     /* Check that the unit has grown enough. */
1055     if (morpher->size < uu_size_to_change_type(u2, u3))
1056       /* (Should return A_ANY_TOO_SMALL.) */
1057       return A_ANY_NO_MATERIAL;
1058     /* Check that the unit has the necessary CXP for the change. */
1059     if (morpher->cxp < uu_cxp_to_change_type(u2, u3))
1060       /* (Should return A_ANY_NO_CXP.) */
1061       return A_ANY_NO_MATERIAL;
1062     /* Check that the unit has any materials necessary for the change. */
1063     if (!valid(rslt =
1064 		can_meet_materials_requirement(actor, morpher,
1065 					       um_to_change_type)))
1066       return rslt;
1067     if (!valid(rslt =
1068 		can_meet_materials_requirement(actor, morpher,
1069 					       um_consumption_per_change_type)))
1070       return rslt;
1071     /* Check that the unit has any occupants necessary for the change. */
1072     for_all_unit_types(u4)
1073       tmp_u_array[u4] = uu_occs_to_change_type(u2, u4);
1074     for_all_occupants(morpher, occ) {
1075         u4 = occ->type;
1076         if (!uu_occs_to_change_type(u2, u4))
1077           continue;
1078         --(tmp_u_array[u4]);
1079     }
1080     for_all_unit_types(u4) {
1081         if (tmp_u_array[u4])
1082           /* (Should return A_ANY_NO_OCCS.) */
1083           return A_ANY_NO_MATERIAL;
1084     }
1085     return rslt;
1086 }
1087 
1088 /*! \brief Action Initialization.
1089  *
1090  * Do any action-related initialization.
1091  * Currently it doesn't do anything.
1092  */
1093 void
init_actions(void)1094 init_actions(void)
1095 {
1096 }
1097 
1098 /*! \brief Prepare for No Action.
1099  *
1100  * Just a placeholder action, so not much to do here.
1101  *
1102  * \see do_none_action, check_none_action
1103  *
1104  * \param unit is the pointer to the \Unit initiating action.
1105  * \param actee is the pointer to the \Unit which performs the action.
1106  * \return
1107  *   - TRUE if action is queed.
1108  *   - FALSE if
1109  *     - \Unit pointer to unit is NULL,
1110  *     - \Unit action pointer is NULL, or
1111  *     - \Unit pointer to actee is NULL
1112  */
1113 int
prep_none_action(Unit * unit,Unit * actee)1114 prep_none_action(Unit *unit, Unit *actee)
1115 {
1116     if (unit == NULL || unit->act == NULL || actee == NULL) {
1117 	return FALSE;
1118     }
1119     unit->act->nextaction.type = ACTION_NONE;
1120     unit->act->nextaction.actee = actee->id;
1121     return TRUE;
1122 }
1123 
1124 /*! \brief Do No Action.
1125  *
1126  * Perform no action action. :-)
1127  *
1128  * \see prep_none_action, check_none_action.
1129  *
1130  * \param unit is the pointer to the \Unit initiating the action.
1131  * \param actee is the pointer to the \Unit which performs the action.
1132  * \return A_ANY_DONE always.
1133  */
1134 int
do_none_action(Unit * unit,Unit * actee)1135 do_none_action(Unit *unit, Unit *actee)
1136 {
1137     return A_ANY_DONE;
1138 }
1139 
1140 /*! \brief Check for No Action.
1141  *
1142  * Check to see if no action is possible.
1143  *
1144  * \see prep_none_action, do_none_action.
1145  *
1146  * \param unit is the pointer to the \Unit initiating the action.
1147  * \param actee is the pointer to the \Unit which performs the action
1148  * \return A_ANY_DONE always.
1149  */
1150 int
check_none_action(Unit * unit,Unit * actee)1151 check_none_action(Unit *unit, Unit *actee)
1152 {
1153     return A_ANY_DONE;
1154 }
1155 
1156 /* Material actions. */
1157 
1158 /* Explicit material production. */
1159 
1160 /*! \brief Prepare for Material Production Action.
1161  *
1162  * Produce materials from unit.  The unit supplies the ACP
1163  * for the action, and stores the action arguments.  The
1164  * producer stores the available material.
1165  * - Sets the next action type to ACTION_PRODUCE.
1166  * - Sets the type and amount of production.
1167  * - Set producer to the actee.
1168  * Fails if either of the pointers to \Unit is NULL, or tha ction is NULL.
1169  *
1170  * \see do_produce_action, check_produce_action.
1171  *
1172  * \param unit is the pointer to the \Unit initiating the action.
1173  * \param producer is the pointer to the \Unit extracting the material.
1174  * \param m is material type.
1175  * \param amount is amount of material to produce.
1176  * \return
1177  *    - TRUE if action is queed.
1178  *    - FALSE if
1179  *      - unit pointer is NULL,
1180  *      - unit action pointer is NULL, or
1181  *      - producer pointer is NULL.
1182  */
1183 int
prep_produce_action(Unit * unit,Unit * producer,int m,int amount)1184 prep_produce_action(Unit *unit, Unit *producer, int m, int amount)
1185 {
1186     if (unit == NULL || unit->act == NULL || producer == NULL) {
1187 	return FALSE;
1188     }
1189     unit->act->nextaction.type = ACTION_PRODUCE;
1190     unit->act->nextaction.args[0] = m;
1191     unit->act->nextaction.args[1] = amount;
1192     unit->act->nextaction.actee = producer->id;
1193     return TRUE;
1194 }
1195 
1196 /*! \brief Do Material Production Action.
1197  *
1198  * Produce materials from a unit.  The producer unit stores as much material
1199  * internally as possible, then distributes it ot units around it.
1200  * - Sets the production amount to the quantity asked for, or the
1201  *    maximum that can be produced, whichever is less.
1202  * - Clips the amount stored to the storeage maximum.
1203  * - If there is an excess amount, passes it around, if possible.
1204  * - Uses up ACP for production.
1205  *
1206  * \see prep_produce_action, check_produce_action, um_material_per_production,
1207  *      um_storate_x, distribute_material, use_up_acp,
1208  *      um_acp_to_produce.
1209  *
1210  * \GDL
1211  *    - <a href="xcdesign_246.html#GDL_ref_acp-to-produce">acp-to-produce</a>
1212  *    - <a href="xcdesign_246.html#GDL_ref_material-per-production">material-per-production</a>
1213  *    - <a href="xcdesign_246.html#GDL_ref_material-to-produce">material-to-produce</a>
1214  *    - <a href="xcdesign_204.html#GDL_ref_unit-storage-x">unit-storage-x</a>
1215  *    - <a href="xcdesign_182.html#GDL_ref_unit-type">unit-type</a>
1216  *
1217  * \param unit is the pointer to the \Unit initiating the action.
1218  * \param producer is the pointer to the \Unit which extracts the material.
1219  * \param m is the material type.
1220  * \param amount is the amount of material to produce.
1221  * \return A_ANY_DONE always.
1222  */
1223 int
do_produce_action(Unit * unit,Unit * producer,int m,int amount)1224 do_produce_action(Unit *unit, Unit *producer, int m, int amount)
1225 {
1226     int amt;	/* amount of material produced */
1227     int excess; /* amount of material that can't be stored by producer */
1228     int space; /* max amount of material that can be added to the supply */
1229 
1230     /* Note: it is very important that the transactions below are made in the
1231     correct order to avoid both numeric overflow in the producer's supply and
1232     the latter being depleted before all excess has been passed around. */
1233     amt = min(amount, um_material_per_production(producer->type, m));
1234     space = um_storage_x(producer->type, m) - producer->supply[m];
1235 
1236     /* First fill up the producer as far as there is room. */
1237     producer->supply[m] += min(amt, space);
1238     /* Compute the excess we couldn't store. */
1239     excess = amt - space;
1240     /* Try to give away the same amount to make room for the excess. */
1241     if (excess > 0) {
1242     	/* But first clip it to available supplies. */
1243     	excess = min(excess, producer->supply[m]);
1244     	producer->supply[m] -= excess;
1245 	distribute_material(producer, m, excess);
1246     }
1247     /* Then try to fill up the producer again with the remaining excess. */
1248     space = um_storage_x(producer->type, m) - producer->supply[m];
1249     /* The check for available space is redundant now, but will be needed
1250     in the future when distribute_material has been improved. */
1251     producer->supply[m] += min(excess, space);
1252     use_up_acp(unit, um_acp_to_produce(producer->type, m));
1253     return A_ANY_DONE;
1254 }
1255 
1256 /*! \brief Check for Material Production Action.
1257  *
1258  * Produce materials from Unit.
1259  * Validate:
1260  *    - unit is in play
1261  *    - producer is in play.
1262  *    - material type is valid.
1263  *    - producer needs at least 1 acp to produce material
1264  *    - unit must be able to have enough acp to produce at some point
1265  *      in the future.
1266  *    - unit has enough acp to produce the material
1267  *    - all needed supplies to produce the material
1268  *      are available.
1269  *    .
1270  * \see prep_produce_action, do_produce_action, in_play,
1271  *      is_material_type, um_acp_to_produce, can_have_enough_acp,
1272  *      um_material_per_production, has_enough_acp, for_all_material_types,
1273  *      um_to_produce.
1274  *
1275  * \GDL
1276  *    - <a href="xcdesign_246.html#GDL_ref_acp-to-produce">acp-to-produce</a>
1277  *    - <a href="xcdesign_246.html#GDL_ref_material-per-production">material-per-production</a>
1278  *    - <a href="xcdesign_246.html#GDL_ref_material-to-produce">material-to-produce</a>
1279  *    - <a href="xcdesign_182.html#GDL_ref_unit-type">unit-type</a>
1280  *
1281  * \param unit is the pointer to the \Unit initiating the action.
1282  * \param producer is the pointer to the \Unit that extracts the material.
1283  * \param m is material type?
1284  * \param amount is amount of material produced?
1285  * \return
1286  *   - A_ANY_ERROR if
1287  *     - unit is not in play
1288  *     - producer is not in play
1289  *     - the material type is unknown
1290  *     .
1291  *   - A_ANY_CANNOT_DO if
1292  *     - ACP of unit is less than 1
1293  *     - if the unit cannot ever have enough ACP for the extraction
1294  *     - if the material production per turn is less than 1
1295  *     .
1296  *   - A_ANY_NO_ACP if the unit doesn't have enough ACP
1297  *   - A_ANY_NO_MATERIAL if any required materials are not available.
1298  *   - A_ANY_OK if the unit can produce the material.
1299  */
1300 int
check_produce_action(Unit * unit,Unit * producer,int m,int amount)1301 check_produce_action(Unit *unit, Unit *producer, int m, int amount)
1302 {
1303     int acp;			/* ACP used in production of material */
1304     int supply;		/* iteration - material needed as supplies to produce material */
1305 
1306     if (!in_play(unit)) {
1307 	return A_ANY_ERROR;
1308     }
1309     if (!in_play(producer)) {
1310 	return A_ANY_ERROR;
1311     }
1312     if (!is_material_type(m)) {
1313 	return A_ANY_ERROR;
1314     }
1315     acp = um_acp_to_produce(producer->type, m);
1316     if (acp < 1) {
1317 	return A_ANY_CANNOT_DO;
1318     }
1319     if (!can_have_enough_acp(unit, acp)) {
1320 	return A_ANY_CANNOT_DO;
1321     }
1322     if (um_material_per_production(producer->type, m) < 1) {
1323 	return A_ANY_CANNOT_DO;
1324     }
1325     if (!has_enough_acp(unit, acp)) {
1326 	return A_ANY_NO_ACP;
1327     }
1328     /* Check that the unit has any required supplies. */
1329     for_all_material_types(supply) {
1330 	if (producer->supply[supply] < um_to_produce(producer->type, supply)) {
1331 	    return A_ANY_NO_MATERIAL;
1332 	}
1333     }
1334     return A_ANY_OK;
1335 }
1336 
1337 /* Extraction of material from terrain. */
1338 
1339 /*! \brief Prepare for Terrain Extraction Action.
1340  *
1341  * Prepare to extract material from a cell.  The unit supplies the ACP
1342  * for the extraction process and stores the parameters for the extaction
1343  * action.  The extractor is the unit which recieves the material.
1344  *
1345  * \see do_extract_action, check_extract_action.
1346  *
1347  * \param unit is the pointer to the \Unit initiating the action.
1348  * \param extractor is the pointer to the \Unit doing the extraction.
1349  * \param x is the x co-ordinate of the cell.
1350  * \param y is the y co-ordinate of the cell.
1351  * \param m is the material to extract from the cell.
1352  * \param amount is the quantify of material to extract from the cell.
1353  * \return
1354  *    - true action is queed.
1355  *    -false if
1356  *      - unit pointer is NULL,
1357  *      - unit action pointer is NULL, or
1358  *      - extractor pointer is NULL
1359  */
1360 int
prep_extract_action(Unit * unit,Unit * extractor,int x,int y,int m,int amount)1361 prep_extract_action(Unit *unit, Unit *extractor, int x, int y, int m, int amount)
1362 {
1363     if (unit == NULL || unit->act == NULL || extractor == NULL) {
1364 	return FALSE;
1365     }
1366     unit->act->nextaction.type = ACTION_EXTRACT;
1367     unit->act->nextaction.args[0] = x;
1368     unit->act->nextaction.args[1] = y;
1369     unit->act->nextaction.args[2] = m;
1370     unit->act->nextaction.args[3] = amount;
1371     unit->act->nextaction.actee = extractor->id;
1372     return TRUE;
1373 }
1374 
1375 /*! \brief Do Terrain Material Extraction Action.
1376  *
1377  * Extract material from the cell or other \Units in the cell.
1378  * - Calculate material production.
1379  *   - if cell produces material and has at least amount units of material
1380  *      - reduce materials at cell by amount.
1381  *      - if remaining amount is zero and the probability of changing
1382  *           on exhaustion is met, and the terrain on exhaustion has
1383  *           a value, change the terrain.
1384  *   - else try to supply from \Units in cell.
1385  * - clip to amount requested.
1386  * - distribute excess to other \Units.
1387  * - reduce ACP of the unit \Unit.
1388  *
1389  * \see prep_extract_action, check_extract_action, any_cell_materials_defined,
1390  *      cell_material_defined, material_at, set_material_at, terrain_at,
1391  *      probabability, tm_change_on_exhaust, tm_exhaust_type,
1392  *      change_terrain_type, for_all_stack, um_storage_x, distribute_material,
1393  *      use_up_acp, um_acp_to_extract.
1394  *
1395  * \GDL
1396  *    - <a href="xcdesign_247.html#GDL_ref_acp-to-extract">acp-to-extract</a>
1397  *    - <a href="xcdesign_263.html#GDL_ref_change-on-exhaustion-chance">change-on-exhaustion-chance</a>
1398  *    - <a href="xcdesign_263.html#GDL_ref_terrain-exhaustion-type">terrain-exhaustion-type</a>
1399  *    - <a href="xcdesign_204.html#GDL_ref_unit-storage-x">unit-storage-x</a>
1400  *    - <a href="xcdesign_182.html#GDL_ref_unit-type">unit-type</a>
1401  *
1402  * \param unit is the pointer to the \Unit initiating the action.
1403  * \param extractor is the pointer to the \Unit extracting the material.
1404  * \param x is the cell x location.
1405  * \param y is the cell y location.
1406  * \param m is the material needed.
1407  * \param amount is the quanity to produce.
1408  * \return A_ANY_DONE.
1409  */
1410 int
do_extract_action(Unit * unit,Unit * extractor,int x,int y,int m,int amount)1411 do_extract_action(Unit *unit, Unit *extractor, int x, int y, int m, int amount)
1412 {
1413     int found = 0;		/* Amount of material actually extracted. */
1414     int excess;         	/* Amount of material that can't be stored in extractor. */
1415     int space; 		/* Free space in the supply. */
1416 
1417     /* Do one attempt at extracting the amount. */
1418     found = extract_one_round(extractor, x, y, m, amount);
1419     /* Compute the excess we couldn't extract. */
1420     excess = amount - found;
1421     /* Compute the remaining storage space. */
1422     space = um_storage_x(extractor->type, m) - extractor->supply[m];
1423     /* If we ran out of space, we try to make room for more. */
1424     if (space == 0
1425         && excess > 0) {
1426     	/* But first clip to availble storage space. */
1427     	excess = min(excess, extractor->supply[m]);
1428 	extractor->supply[m] -= excess;
1429 	distribute_material(extractor, m, excess);
1430     }
1431     /* Do one more attempt at extracting the remaining amount. */
1432     found += extract_one_round(extractor, x, y, m, excess);
1433 
1434     use_up_acp(unit, um_acp_to_extract(extractor->type, m));
1435     if (found < amount) {
1436     	/* Should never happen since materials were checked by check_extract_action. */
1437     	run_warning("%s unable to extract %d %s at (%d, %d).",
1438 		short_unit_handle(extractor), amount, m_type_name(m), x, y);
1439 	return A_ANY_ERROR;
1440     } else {
1441 	return A_ANY_DONE;
1442     }
1443 }
1444 
1445 int
extract_one_round(Unit * extractor,int x,int y,int m,int amount)1446 extract_one_round(Unit *extractor, int x, int y, int m, int amount)
1447 {
1448     int oldamt;		/* Amount of material in terrain before adjustment */
1449     int amt;			/* Amount of material removed. */
1450     int newamt;		/* New amount of material in terrain after extraction. */
1451     int space; 		/* Max amount of material that can be added to the supply */
1452     int found = 0;		/* Amount of material actually extracted. */
1453     int t;              		/* Rerrain of cell */
1454     int newt;		/* New terrain type of cell if all materials extracted */
1455     Unit *unit2;		/* Iteration - pointer to next unit in stack of units. */
1456 
1457     /* First compute the available storage space. */
1458     space = um_storage_x(extractor->type, m) - extractor->supply[m];
1459 
1460     /* Get what we can get from the terrain. */
1461     if (any_cell_materials_defined()
1462 	  && cell_material_defined(m)
1463 	  && material_at(x, y, m) > 0) {
1464 	oldamt = material_at(x, y, m);
1465 	amt = min(amount, oldamt);
1466 	/* First fill up the extractor as far as there is room. */
1467 	extractor->supply[m] += min(amt, space);
1468 	newamt = oldamt - min(amt, space);
1469 	found += min(amt, space);
1470 	space -= min(amt, space);
1471 	set_material_at(x, y, m, newamt);
1472 	/* (should do with a common routine) */
1473 	t = terrain_at(x, y);
1474 	if (newamt == 0
1475 	      && probability(tm_change_on_exhaust(t, m))
1476 	      && tm_exhaust_type(t, m) != NONTTYPE) {
1477 	    newt = tm_exhaust_type(t, m);
1478 	    /* Change the terrain's type. */
1479 	    change_terrain_type(x, y, newt);
1480 	}
1481     }
1482     /* If there was not enough material in the terrain we proceed
1483     to plunder any owner-less independent units in the stack. */
1484     if (amount - found > 0
1485     	&& space > 0
1486     	&& g_no_indepside_ingame()) {
1487 	for_all_stack(x, y, unit2) {
1488 	    /* If we don't need more or ran out of space we are done. */
1489 	    if (amount - found == 0 || space == 0) {
1490 	    	break;
1491 	    }
1492 	    if (in_play(unit2)
1493 	        && indep(unit2)
1494 	        && unit2->supply[m] >= 0) {
1495 		oldamt = unit2->supply[m];
1496 		amt = min(amount - found, oldamt);
1497 		/* First fill up the extractor as far as there is room. */
1498 		extractor->supply[m] += min(amt, space);
1499 		found += min(amt, space);
1500 		newamt = oldamt - min(amt, space);
1501 		unit2->supply[m] = newamt;
1502 		space -= min(amt, space);
1503 	    }
1504 	}
1505     }
1506     return found;
1507 }
1508 
1509 /*! \brief Check for Terrain Material Estraction Action.
1510  *
1511  * This checks to see if an extract operation is possible.
1512  * It verifies:
1513  * - the unit is in play,
1514  * - the extractor is in play,
1515  * - the material type is valid,
1516  * - the unit is capable of extracting material (no negative ACP balance)
1517  * - the unit has enough available ACP,
1518  * - the extractor has any supplies needed for extraction.
1519  * It then checks to see if material can be produced from the cell,
1520  * else from any other independent \Units also in the cell.
1521  *
1522  * \see prep_extract_action, do_extract_action, in_play, is_material_type,
1523  *      um_acp_to_extract, can_have_enough_acp, has_enough_acp,
1524  *      for_all_material_types, um_to_extract, any_cell_materials_defined,
1525  *      cell_material_defined, material_at, for_all_stack, indep.
1526  *
1527  * \GDL
1528  *    - <a href="xcdesign_247.html#GDL_ref_acp-to-extract">u-acp-to-extract</a>
1529  *    - <a href="xcdesign_263.html#GDL_ref_change-on-exhaustion-chance">change-on-exhaustion-chance</a>
1530  *    - <a href="xcdesign_182.html#GDL_ref_unit-type">unit-type</a>
1531  *
1532  * \param unit is the pointer to the \Unit initiating the action.
1533  * \param extractor is the pointer to the \Unit on which the action is preformed,
1534  * \param x is the x co-ordinate of the  cell,
1535  * \param y is the y co-ordinate of the cell,
1536  * \param m is the material to be produced,
1537  * \param amount is the quanity to be produced.
1538  * \return
1539  *    - A_ANY_ERROR if
1540  *      - the unit is not in play,
1541  *      - the extractor is not in play,
1542  *      - the material type is not valid.
1543  *    - A_ANY_CANNOT_DO if
1544  *      - the ACP is negative,
1545  *      - the unit can never have enough ACP.
1546  *    - A_ANY_NO_ACP if the unit doesn't have enough ACP.
1547  *    - A_ANY_NO_MATERIAL if the cell doesn't have the material.
1548  *    - A_ANY_OK if the material is available.
1549  *    - A_EXTRACT_NO_SOURCE if no material could be extracted.
1550  */
1551 int
check_extract_action(Unit * unit,Unit * extractor,int x,int y,int m,int amount)1552 check_extract_action(Unit *unit, Unit *extractor, int x, int y, int m, int amount)
1553 {
1554     int acp;			/* ACP for extraction. */
1555     int supply;		/* supply needed for extraction. */
1556     int found;		/* materials found when looking around. */
1557     Unit *stack_unit;	/* interation - pointer to next stack unit. */
1558 
1559     if (!in_play(unit)) {
1560 	return A_ANY_ERROR;
1561     }
1562     if (!in_play(extractor)) {
1563 	return A_ANY_ERROR;
1564     }
1565     if (!is_material_type(m)) {
1566 	return A_ANY_ERROR;
1567     }
1568     acp = um_acp_to_extract(extractor->type, m);
1569     if (acp < 1) {
1570 	return A_ANY_CANNOT_DO;
1571     }
1572     if (!can_have_enough_acp(unit, acp)) {
1573 	return A_ANY_CANNOT_DO;
1574     }
1575     if (!has_enough_acp(unit, acp)) {
1576 	return A_ANY_NO_ACP;
1577     }
1578     /* Check that the unit has any required supplies. */
1579     for_all_material_types(supply) {
1580 	if (extractor->supply[supply] < um_to_extract(extractor->type, supply)) {
1581 	    return A_ANY_NO_MATERIAL;
1582 	}
1583     }
1584     /* Look for case of extraction from terrain. */
1585     found = 0;
1586     if (any_cell_materials_defined()
1587 	&& cell_material_defined(m)
1588 	/* amount is currently always 1 (see do_collect_task) so this is in fact
1589 	a check for material_at(x, y, m) > 0. However, we keep support
1590 	for n in case the task code is modified in the future. */
1591 	&& material_at(x, y, m) > 0) {
1592     	found += material_at(x, y, m);
1593     }
1594     /* Then look for extraction from independent unit provided that there
1595     is no independent side that owns these units. This breaks the one game
1596     that uses explicit extraction, ancient-days, but prevents the absurd
1597     case where a unit is using units belonging to another side (indepside)
1598     to resupply itself. Possible fix for ancient-days: let berry bushes etc.
1599     be independent, set no-indepside-ingame to true, and let live animals
1600     belong to a third side. */
1601     if (g_no_indepside_ingame()) {
1602 	    for_all_stack(x, y, stack_unit) {
1603 		if (in_play(stack_unit)
1604 		    && indep(stack_unit)
1605 		    && stack_unit->supply[m] > 0) {
1606     			found += stack_unit->supply[m];
1607 		}
1608 	    }
1609     }
1610     if (found >= amount) {
1611     	return A_ANY_OK;
1612     }
1613     return A_EXTRACT_NO_SOURCE;
1614 }
1615 
1616 /* Transfer action. */
1617 
1618 /* This action transfers material from one unit to another. */
1619 
1620 /*! \brief Prepare for Material Transfer Action.
1621  *
1622  * This routine sets up a material transfer from one \Unit to another.
1623  * The unit \Unit supplies the ACP for the action, and stores the parameters
1624  * for the action.  The from Unit supplies the material to the to Unit.
1625  *
1626  * \see do_transfer_action, check_transfer_action.
1627  *
1628  * \param unit is the pointer to the \Unit initiating the action.
1629  * \param from is the \Unit the materisl comes from.
1630  * \param m is the material being transferred.
1631  * \param amount is the quanity of material being transferred.
1632  * \param to is the \Unit receiving the transfer.
1633  * \return
1634  *   - TRUE if action is queed.
1635  *   - FALSE if
1636  *     - unit pointer is NULL,
1637  *     - unit action pointer is NULL,
1638  *     - from pointer is NULL, or
1639  *     - to pointer is NULL.
1640  */
1641 int
prep_transfer_action(Unit * unit,Unit * from,int m,int amount,Unit * to)1642 prep_transfer_action(Unit *unit, Unit *from, int m, int amount, Unit *to)
1643 {
1644     if (unit == NULL || unit->act == NULL || from == NULL || to == NULL) {
1645 	return FALSE;
1646     }
1647     unit->act->nextaction.type = ACTION_TRANSFER;
1648     unit->act->nextaction.args[0] = m;
1649     unit->act->nextaction.args[1] = amount;
1650     unit->act->nextaction.args[2] = to->id;
1651     unit->act->nextaction.actee = from->id;
1652     return TRUE;
1653 }
1654 
1655 /*! \brief Do Material Transfer Action.
1656  *
1657  * This routine transfers material from one \Unit to another.
1658  * Transfer goes from the to Unit to the from Unit if the
1659  * quanity transferred is negative.  The actual quantity transfered is
1660  * calculated by transfer_supply.  The ACP for the transer
1661  * is used buy the unit Unit, even if no materis is transfered.
1662  * Transfers always use 1 ACP.
1663  *
1664  * \todo Add return code specifying that only a partial amount of
1665  *       material was transferred.
1666  *
1667  * \see prep_transfer_action, check_transfer_action, transfer_supply.
1668  *
1669  * \GDL
1670  *    - <a href="xcdesign_248.html#GDL_ref_acp-to-unload">acp-to-unload</a>
1671  *
1672  * \param unit is the pointer to the \Unit initiating the action.
1673  * \param from is the pointer to the \Unit supplying the material
1674  *        (for positive transfers).
1675  * \param m is the material being transferred.
1676  * \param amount is the quanity of material being transferred.
1677  * \param to is the pointer to the \Unit receiving the transfer
1678  *        (for positive transfers).
1679  * \return
1680  *   - A_ANY_ERROR if no material was transferred.
1681  *   - A_ANY_DONE if at least one unit of material was transferred.
1682  */
1683 int
do_transfer_action(Unit * unit,Unit * from,int m,int amount,Unit * to)1684 do_transfer_action(Unit *unit, Unit *from, int m, int amount, Unit *to)
1685 {
1686     int actual; /* Actual amount of material transferred */
1687 
1688     if (amount > 0) {
1689     	actual = transfer_supply(from, to, m, amount);
1690     	use_up_acp(unit, um_acp_to_unload(from->type, m));
1691     } else {
1692     	actual = transfer_supply(to, from, m, -amount);
1693     	use_up_acp(unit, um_acp_to_unload(to->type, m));
1694     }
1695     if (actual == amount) {
1696 	return A_ANY_DONE;
1697     } else if (actual == 0) {
1698 	return A_ANY_ERROR;
1699     } else {
1700     	/* (should be able to say that action did not do all that was requested) */
1701 	return A_ANY_DONE;
1702     }
1703 }
1704 
1705 /*! \brief Check for Material Transfer Action.
1706  *
1707  * This routine makes sure that a transfer is possible.
1708  * It verifies
1709  *  - that unit, <I>to</I>, and <I>from</I> \Units are in play.
1710  *  - that the material tor transfer is a valid material,
1711  *  - that the quantify of material to transfer is non-zero.
1712  *  - that the <I>from</I> \Unit can unload material (ACP 1 or more),
1713  *  - that the <I>to</I> \Unit may load material(ACP 1 or more),
1714  *  - that the unit can ever have enough ACP to transfer the material,
1715  *  - that the \Unit suppling the material has the supplies needed to
1716  *    transfer the material,
1717  *  - that the \Unit receivng the material has the storage for the
1718  *    transferred material. and
1719  *  - that the unit has enough ACP to transfer the material.
1720  *
1721  * \see prep_transfer_action, do_transfer_action, in_play, is_material_type,
1722  *      um_acp_to_unload, um_acp_to_load, can_have_enough_acp,
1723  *      um_storage_x, has_enough_acp.
1724  *
1725  * \GDL
1726  *    - <a href="xcdesign_248.html#GDL_ref_acp-to-load">acp-to-load</a>
1727  *    - <a href="xcdesign_248.html#GDL_ref_acp-to-unload">acp-to-unload</a>
1728  *    - <a href="xcdesign_182.html#GDL_ref_unit-type">unit-type</a>
1729  *
1730  * \param unit is the pointer to the \Unit initiating the action.
1731  * \param from is the pointer to the \Unit supplying the material (if
1732  *        amount is positive).
1733  * \param m is the material being transferred.
1734  * \param amount is the quanity of material being transferred.
1735  * \param to is the pointer to the \Unit receiving the transfer (if
1736  *        amount is positive).
1737  * \return
1738  *   - A_ANY_ERROR if
1739  *     - the unit is not in play,
1740  *     - the <I>to</I> \Unit is not in play,
1741  *     - the material type is invalid,
1742  *     - the quanity of material to produce is zero (negative is ok),
1743  *     - the <I>from</I> \Unit is not in play,
1744  *     - the appropriate \Unit (depending on quantity positive or negative) does
1745  *       not have enough supplies of other materials on hand, or
1746  *     - the appropriate \Unit does not have enough storage capacity.
1747  *   - A_ANY_CANNOT_DO if
1748  *     - the <I>from</I> \Unit cannot unload material (ACP to unload less than 1),
1749  *     - the <I>to</I> \Unit has a NULL action pointer or cannot load material
1750  *       (ACP to load less than 1), or
1751  *     - the unit can never have enought ACP to do the transfer.
1752  *   - A_ANY_NO_ACP if the unit doesn't have enought ACP.
1753  *   - A_ANY_DONE if at least one unit of material can be transferred.
1754  */
1755 int
check_transfer_action(Unit * unit,Unit * from,int m,int amount,Unit * to)1756 check_transfer_action(Unit *unit, Unit *from, int m, int amount, Unit *to)
1757 {
1758     if (!in_play(unit)) {
1759 	return A_ANY_ERROR;
1760     }
1761     if (!in_play(from)) {
1762 	return A_ANY_ERROR;
1763     }
1764     if (!is_material_type(m)) {
1765 	return A_ANY_ERROR;
1766     }
1767     if (amount == 0) {
1768 	return A_ANY_ERROR;
1769     }
1770     if (!in_play(to)) {
1771 	return A_ANY_ERROR;
1772     }
1773     if (amount > 0) {
1774 	if (um_acp_to_unload(from->type, m) < 1) {
1775 	    return A_ANY_CANNOT_DO;
1776 	}
1777 	if (to->act && um_acp_to_load(to->type, m) < 1) {
1778 	    return A_ANY_CANNOT_DO;
1779 	}
1780 	/* We check only the acp needed for the unload action since um_acp_to_load
1781 	is used strictly as a permission flag (never causes acps to be consumed). */
1782 	if (!can_have_enough_acp(unit, um_acp_to_unload(from->type, m))) {
1783 	    return A_ANY_CANNOT_DO;
1784 	}
1785 	if (from->supply[m] <= 0) {
1786 	    return A_ANY_ERROR;
1787 	}
1788 	if (um_storage_x(to->type, m) == 0) {
1789 	    return A_ANY_ERROR;
1790 	}
1791     } else {
1792 	if (um_acp_to_load(from->type, m) < 1) {
1793 	    return A_ANY_CANNOT_DO;
1794 	}
1795 	if (to->act && um_acp_to_unload(to->type, m) < 1) {
1796 	    return A_ANY_CANNOT_DO;
1797 	}
1798 	/* We check only the acp needed for the unload action since um_acp_to_load
1799 	is used strictly as a permission flag (never causes acps to be consumed). */
1800 	if (!can_have_enough_acp(unit, um_acp_to_unload(to->type, m))) {
1801 	    return A_ANY_CANNOT_DO;
1802 	}
1803 	if (to->supply[m] <= 0) {
1804 	    return A_ANY_ERROR;
1805 	}
1806 	if (um_storage_x(from->type, m) == 0) {
1807 	    return A_ANY_ERROR;
1808 	}
1809     }
1810     if (!has_enough_acp(unit, 1)) {
1811 	return A_ANY_NO_ACP;
1812     }
1813     return A_ANY_OK;
1814 }
1815 
1816 /*! \brief Transfer Supply.
1817  *
1818  * Move supply from one \Unit to another.  Don't move more than is
1819  * possible; check both from and to amounts and capacities.  This
1820  * routine will also transfer to the side's treasury if necessary can
1821  * handle overflow. This is a utility routine.
1822  * - Calculate the min amount to transfer based on the available
1823  *   supply and the maximum that can be loaded in the to \Unit.
1824  * - if there is a treasury for the material, and the receiving
1825  *   \Unit can transfer material to the treasury, then transfer any
1826  *   excess production from the from \Unit to the treasure
1827  * - reduce the material supply of the from \Unit,
1828  * - increase the  material supply of the to \Unit.
1829  * - update to and from \Unit supply display for the sides involved.
1830  * - if the treasury was modified, update the treasury supply display.
1831  * - print debug message, if it's enabled.
1832  *
1833  * \see do_transfer_material, um_unload_max, um_load_max, UM_storage_x,
1834  *      side_has_treasury, um_gives_to_treasury, update_unit_display,
1835  *      update_side_display.
1836  *
1837  * \GDL
1838  *    - <a href="xcdesign_248.html#GDL_ref_load-max">load-max</a>
1839  *    - <a href="xcdesign_262.html#GDL_ref_gives-to-treasury">gives-to-treasury</a>
1840  *    - <a href="xcdesign_161.html#GDL_ref_treasury">treasury</a>
1841  *    - <a href="xcdesign_182.html#GDL_ref_unit-type">unit-type</a>
1842  *    - <a href="xcdesign_248.html#GDL_ref_unload-max">unload-max</a>
1843  *
1844  * \param from is the pointer to the \Unit supplying the material.
1845  * \param to is the pointer to the \Unit receiving the material.
1846  * \param m is the material type to transfer.
1847  * \param amount is the amount of material to transfer.
1848  * \return the amount to transfer.
1849  */
1850 int
transfer_supply(Unit * from,Unit * to,int m,int amount)1851 transfer_supply(Unit *from, Unit *to, int m, int amount)
1852 {
1853     int amt2;					/* material amount */
1854     int origfrom = from->supply[m];	/* Material originally in from unit */
1855     int origto = to->supply[m];		/* Material originally in to Unit */
1856 
1857     /* Constrain the amount of supply that may be unloaded. */
1858     amount = min(amount, origfrom);
1859     if (um_unload_max(from->type, m) >= 0) {
1860 	amount = min(amount, um_unload_max(from->type, m));
1861     }
1862     /* Now constrain the amount of material that can be loaded */
1863     if (um_load_max(to->type, m) >= 0) {
1864 	amount = min(amount, um_load_max(to->type, m));
1865     }
1866     /* amount is now the material that is possible to transfer,
1867      * now figure out the amount that can actually be put into
1868      * the 'to' Unit. */
1869     amt2 = min(amount, um_storage_x(to->type, m) - origto);
1870 
1871 #if 0 /* Using the treasury to dump overflow is rather dubious.
1872 	Presumably, we are doing the transfer action because we
1873 	want 'to' to get the stuff, not because we want to fill up the
1874 	treasury. Better to keep the material in 'from', and do a
1875 	second transfer action if necessary. */
1876 
1877     /* Transfer overflow to side's treasury if it exists.  If it
1878      * doesn't, reduce the amount transferred to the amount that
1879      * the 'to' unit can hold. */
1880     if (side_has_treasury(to->side, m)
1881         && um_gives_to_treasury(to->type, m)) {
1882 	/* Make sure the treasury does not overflow. */
1883 	to->side->treasury[m] += min(g_treasury_size() - to->side->treasury[m], amount - amt2);
1884     } else {
1885 	amount = amt2;
1886     }
1887   /* Also dubious if from->supply should be decremented with
1888   more than is actually moved to either 'to' or treasury. */
1889     from->supply[m] -= amount;
1890 
1891 #else
1892 
1893     from->supply[m] -= amt2;
1894 
1895 #endif
1896 
1897     to->supply[m] += amt2;
1898 
1899     /* Make sure any displays of supply levels see the transfer. */
1900     update_unit_display(from->side, from, TRUE);
1901     update_unit_display(to->side, to, TRUE);
1902 
1903 #if 0		/* Not needed if we don't transfer overflow to treasury. */
1904 
1905     if (amount != amt2) {
1906 	update_side_display(from->side, from->side, TRUE);
1907 	update_side_display(to->side, to->side, TRUE);
1908     }
1909 
1910 #endif
1911 
1912     Dprintf("%s (had %d) transfers %d %s to %s (had %d)\n",
1913 	    unit_desig(from), origfrom, amt2, m_type_name(m),
1914 	    unit_desig(to), origto);
1915     return amt2;
1916 }
1917 
1918 /* Develop action. */
1919 
1920 
1921 /*! \brief Prepare for technical Development Action.
1922  *
1923  * Setup a Develop action.
1924  * In order to build a specific unit type, a side may first have to develop
1925  * the tech level needed for that unit. This is achieved by the develop action.
1926  * \note Technical development is different from advances and advanced
1927  * units.
1928  * \see do_devop_action, do_check_action.
1929  * \param unit is the pointer to the \Unit initiating the action.
1930  * \param developer is the pointer to the \Unit doing the development.
1931  * \param new_u is the new Unit type being developed.
1932  * \return
1933  *   - TRUE action is queed.
1934  *   - FALSE if
1935  *     - unit is null pointer,
1936  *     - unit action is a null pointer, or
1937  *     - developer is null pointer.
1938  */
1939 int
prep_develop_action(Unit * unit,Unit * developer,int new_u)1940 prep_develop_action(Unit *unit, Unit *developer, int new_u)
1941 {
1942     if (unit == NULL || unit->act == NULL || developer == NULL) {
1943 	return FALSE;
1944     }
1945     unit->act->nextaction.type = ACTION_DEVELOP;
1946     unit->act->nextaction.args[0] = new_u;
1947     unit->act->nextaction.actee = developer->id;
1948     return TRUE;
1949 }
1950 
1951 /*! \brief Do Technical Development Action.
1952  *
1953  * Develop the tech level needed for building \new_u, if not already available.
1954  * -# calculate contribution to tech by the developer \Unit.  Use the value
1955  *    of uu_tech_per_develop divided by 100, plus a random value of zero or
1956  *    one.
1957  * -# Caclulate limit on tech change for the side
1958  * -# If tech change exceeds limit, reset to limit
1959  * -# If tech level changes,
1960  *   - notify side of tech change.
1961  *   - update vector of buildable Units.
1962  * -# Adjust the tech levels of related Units
1963  * -# Uuse up the ACP of the \Unit.
1964  *
1965  * \note Technical development is different from advances and advanced
1966  * units.
1967  *
1968  * \see prep_develop_action, prob_fraction, uu_tech_per_develop,
1969  *      u_tech_per_turn_max, update_canbuild_vector, adjust_tech_crossover,
1970  *      use_up_acp, uu_acp_to_develop.
1971  *
1972  * \GDL
1973  *    - <a href="xcdesign_241.html#GDL_ref_acp-to-develop">acp-to-develop</a>
1974  *    - <a href="xcdesign_157.html#GDL_ref_init-tech">init-tech</a>
1975  *    - <a href="xcdesign_157.html#GDL_ref_tech">tech</a>
1976  *    - <a href="xcdesign_241.html#GDL_ref_tech-per-develop">tech-per-develop</a>
1977  *    - <a href="xcdesign_241.html#GDL_ref_tech-per-turn-max">tech-per-turn-max</a>
1978  *    - <a href="xcdesign_182.html#GDL_ref_unit-type">unit-type</a>
1979  *
1980  * \param unit is the pointer to the \Unit initiating the action.
1981  * \param developer is the pointer to the \Unit acted upon.
1982  * \param new_u is the Unit type of the increasing tech Unit.
1983  * \return A_ANY_DONE.
1984  */
1985 int
do_develop_action(Unit * unit,Unit * developer,int new_u)1986 do_develop_action(Unit *unit, Unit *developer, int new_u)
1987 {
1988     int oldtech;	/* Side's starting tech level */
1989     int lim;		/* limit on tech development */
1990     Side *side;	/* Developer's side */
1991 
1992     side = developer->side;
1993     /* Save the initial tech level */
1994     oldtech = side->tech[new_u];
1995     side->tech[new_u] += prob_fraction(uu_tech_per_develop(developer->type, new_u));
1996     /* Silently apply the per-side-per-turn limit on tech gains. */
1997     lim =  side->inittech[new_u] + u_tech_per_turn_max(new_u);
1998     if (side->tech[new_u] > lim) {
1999 	side->tech[new_u] = lim;
2000     }
2001     if (side->tech[new_u] != oldtech) {
2002 	/* (should do generic side display update?) */
2003 	notify_tech(side, new_u, oldtech, side->tech[new_u]);
2004 	/* Update info for side_can_build. */
2005 	update_canbuild_vector(side);
2006     }
2007     /* Adjust the tech levels of any related unit types. */
2008     adjust_tech_crossover(side, new_u);
2009     use_up_acp(unit, uu_acp_to_develop(developer->type, new_u));
2010     return A_ANY_DONE;
2011 }
2012 
2013 /*! \brief Check for Technical Development Action.
2014  *
2015  * Check to see is tech development action is possible.  Tech development is
2016  * on a unit basis, as opposed to advances, which may depend on each other.
2017  * \note Technical development is different from advances and advanced
2018  * units.
2019  * <P>
2020  * - Validate \Units acted on.
2021  *   - unit must be in play,
2022  *   - developer must be in play, and
2023  *   - newunt must be a Unit type.
2024  * - Check to see if the side is an independent side, and independents are
2025  *    allowed to develop.
2026  * - the developer must be able to develop the new unit type
2027  * - unit must be able to have enough acp for the developer to develop the
2028  *    new unit type
2029  * - the side's tech level must not be at the side's maximum value already
2030  * - the unit must have enough acp for the developer to develop the new unit
2031  *    type
2032  * - the developer must have all materials needed to develop the new unit type
2033  *
2034  * \see prep_develop_action, do_develop_action, in_play, is_unit_type,
2035  *      g_indepside_can_develop, could_develop, can_have_enough_acp,
2036  *      uu_acp_to_develop, u_tech_max, for_all_material_types.
2037  *
2038  * \GDL
2039  *    - <a href="xcdesign_241.html#GDL_ref_acp-to-develop">acp-to-develop</a>
2040  *    - <a href="xcdesign_157.html#GDL_ref_init-tech">init-tech</a>
2041  *    - <a href="xcdesign_157.html#GDL_ref_tech">tech</a>
2042  *    - <a href="xcdesign_182.html#GDL_ref_unit-type">unit-type</a>
2043  *
2044  * \param unit is the pointer to the \Unit initiating the action.
2045  * \param developer is the pointer to the \Unit which does the development
2046  * \param new_u is the new Unit type to be developed.
2047  * \return
2048  *   - A_ANY_ERROR if
2049  *     - unit is not in play,
2050  *     - developer is not in play,
2051  *     - new_u in not a valid Unit type,
2052  *     - the side is independent, and not allowed technical development, or
2053  *     - the side has reached it's maximum tech level.
2054  *   - A_ANY_CANNOT_DO if
2055  *      - the developer cannot develop the new unit type, or
2056  *      - the unit can never have enough ACP to develop the new Unit type.
2057  *   - A_ANY_NO_ACP if the unit does not currently have enough acp to develop
2058  *     the new unit type.
2059  *   - A_ANY_OK if the do_develop_action can be done.
2060  */
2061 int
check_develop_action(Unit * unit,Unit * developer,int new_u)2062 check_develop_action(Unit *unit, Unit *developer, int new_u)
2063 {
2064     int m;		/* material type */
2065     Side *side;	/* unit's side */
2066 
2067     if (!in_play(unit)) {
2068       return A_ANY_ERROR;
2069     }
2070     if (!in_play(developer)) {
2071       return A_ANY_ERROR;
2072     }
2073     if (!is_unit_type(new_u)) {
2074       return A_ANY_ERROR;
2075     }
2076     side = unit->side;
2077     /* Independent units might not do develop. */
2078     if (side == indepside && g_indepside_can_develop() == FALSE) {
2079       return A_ANY_ERROR;
2080     }
2081     /* This unit must be of a type that can develop the given type. */
2082     if (!could_develop(developer->type, new_u)) {
2083       return A_ANY_CANNOT_DO;
2084     }
2085     if (!can_have_enough_acp(unit, uu_acp_to_develop(developer->type, new_u))) {
2086       return A_ANY_CANNOT_DO;
2087     }
2088     /* Max tech level means there's nothing more to learn. */
2089     if (side->tech[new_u] >= u_tech_max(new_u)) {
2090       return A_ANY_ERROR;
2091     }
2092     if (!has_enough_acp(unit, uu_acp_to_develop(developer->type, new_u))) {
2093       return A_ANY_NO_ACP;
2094     }
2095     /* Check that the unit has any required supplies. */
2096     for_all_material_types(m) {
2097 	if (developer->supply[m] < um_to_develop(developer->type, m)) {
2098 	  return A_ANY_NO_MATERIAL;
2099 	}
2100     }
2101     return A_ANY_OK;
2102 }
2103 
2104 /*!
2105  * \brief Adjuxt for Tchnical Development Crossover.
2106  *
2107  * For all Unit types, bring their tech level up to match the crossovers
2108  * from the given Unit type.
2109  * - for all Unit types ( for all sides, presumably? )
2110  *   - if the Unit type isn't the Unit type being developed
2111  *     - calculate the crosstech value
2112  *     - if the crosstech value increaes the tech level of the other \Unit
2113  *       - change the tech level of the other \Unit.
2114  *     - if the other uunit's tech level increases
2115  *       - notify the \Side of a tech increase for the Unit.
2116  *       - update the can build vector for the side.
2117  *
2118  * \see do_develop_action, for_all_unit_types, uu_tech_crossover, u_tech_max,
2119  *      notify_tech, update_canbuild_vector.
2120  *
2121  *  \GDL
2122  *    - <a href="xcdesign_157.html#GDL_ref_tech">tech</a>
2123  *    - <a href="xcdesign_190.html#GDL_ref_tech-crossover">tech-crossover</a>
2124  *    - <a href="xcdesign_190.html#GDL_ref_tech-max">tech-max</a>
2125  *
2126  * \param side is the pointer to \Side with the technical development.
2127  * \param new_u is the new Unit type being developed.
2128  */
2129 void
adjust_tech_crossover(Side * side,int new_u)2130 adjust_tech_crossover(Side *side, int new_u)
2131 {
2132     int other_u;	/* other unit type (iteration variable) */
2133     int oldtech;        /* initial tech level of the other unit */
2134     int crosstech;	/* crossover technical development of unit */
2135 
2136     for_all_unit_types(other_u) {
2137 	if (other_u != new_u) {
2138 	    oldtech = side->tech[other_u];
2139 	    /* Compute the crossover as a ratio of max tech levels for
2140                each type. */
2141 	    crosstech =
2142 	      ((side->tech[new_u] * uu_tech_crossover(new_u, other_u) * u_tech_max(other_u)) /
2143 	       (u_tech_max(new_u) * 100));
2144 	    if (crosstech > side->tech[other_u]) {
2145 		side->tech[other_u] = crosstech;
2146 	    }
2147 	    if (side->tech[other_u] != oldtech) {
2148 		/* (should do generic side display update?) */
2149 		notify_tech(side, other_u, oldtech, side->tech[other_u]);
2150 		/* Update info for side_can_build. */
2151 		update_canbuild_vector(side);
2152 	    }
2153 	}
2154     }
2155 }
2156 
2157 /*! \brief Notify of Technical Advance.
2158  *
2159  * Notify the given side of any notable changes in technological
2160  * ability.
2161  * For the given Unit, chck and notify the \Side if technology development allows
2162  * the side to see a new Unit type, own a new Unit type, use a new Unit type, or
2163  * build a new Unit type.
2164  *
2165  * \todo move to nlang.c?
2166  *
2167  * \see do_develop_action, adjust_tech_crossover, u_tech_to_see, u_tech_to_own,
2168  *      u_tech_to_use, u_tech_to_build, notify.
2169  *
2170  * \GDL
2171  *    - <a href="xcdesign_190.html#GDL_ref_tech-to-build">tech-to-build</a>
2172  *    - <a href="xcdesign.html#GDL_ref_tech-to_own">tech-to_own</a>
2173  *    - <a href="xcdesign_190.html#GDL_ref_tech-to-see">tech-to-see</a>
2174  *    - <a href="xcdesign_190.html#GDL_ref_tech-to-use">tech-to-use</a>
2175  *
2176  * \param side is the pointer to the \Side owning the Unit.
2177  * \param u is the Unit type.
2178  * \param oldtech is the old technical level for the Unit.
2179  * \param newtech is the new technical level for the Unit.
2180  */
2181 void
notify_tech(Side * side,int u,int oldtech,int newtech)2182 notify_tech(Side *side, int u, int oldtech, int newtech)
2183 {
2184     if (oldtech < u_tech_to_see(u)
2185 	&& newtech >= u_tech_to_see(u)) {
2186 	notify(side, "You now have the technology to see %s units",
2187 	       u_type_name(u));
2188     }
2189     if (oldtech < u_tech_to_own(u)
2190 	&& newtech >= u_tech_to_own(u)) {
2191 	notify(side, "You now have the technology to own %s units",
2192 	       u_type_name(u));
2193     }
2194     if (oldtech < u_tech_to_use(u)
2195 	&& newtech >= u_tech_to_use(u)) {
2196 	notify(side, "You now have the technology to use %s units",
2197 	       u_type_name(u));
2198     }
2199     if (oldtech < u_tech_to_build(u)
2200 	&& newtech >= u_tech_to_build(u)) {
2201 	notify(side, "You now have the technology to build new %s units",
2202 	       u_type_name(u));
2203     }
2204     if ((oldtech < u_tech_to_change_type_to(u))
2205 	&& (newtech >= u_tech_to_change_type_to(u))) {
2206 	notify(side, "You now have the technology to change type to %s units",
2207 	       u_type_name(u));
2208     }
2209 }
2210 
2211 /* Toolup action. */
2212 
2213 /*! \brief Prepare for Toolup Action.
2214  *
2215  * Before a \Unit can build another, it may need to take some time to
2216  * prepare by "tooling up". This is to simulate the amount of time
2217  * it takes to build the first of a Unit.
2218  * \see do_toolup_action, check_toolup_action.
2219  * \param unit is the pointer to the \Unit initiating the action.
2220  * \param constructor is a pointer to the \Unit which builds the new Unit.
2221  * \param u3 is the type of Unit being built.
2222  * \return
2223  *   - TRUE if action is successfully queued.
2224  */
2225 
2226 int
prep_toolup_action(Unit * actor,Unit * constructor,int u3)2227 prep_toolup_action(Unit *actor, Unit *constructor, int u3)
2228 {
2229     assert_error(is_active(actor),
2230 		 "Toolup Prep: Attempted to access an inactive actor");
2231     assert_error(is_active(constructor),
2232 		 "Toolup Prep: Attempted to access an inactive constructor");
2233     assert_error(is_unit_type(u3),
2234 		 "Toolup Prep: Encountered an invalid unit type to toolup for");
2235     actor->act->nextaction.type = ACTION_TOOL_UP;
2236     actor->act->nextaction.args[0] = u3;
2237     actor->act->nextaction.actee = constructor->id;
2238     return TRUE;
2239 }
2240 
2241 /*! \brief Do Toolup Action.
2242  *
2243  * Do the tooup action.
2244  * - If builder tooling pointer is NULL, initialize tooling for it.
2245  * - Get current tooling points (tp), add in the builder \Unit tooling points,
2246  *    and clip to the max tooling points for creating the new Unit type.
2247  * - If the number of tooling points changes (can go negative?),
2248  *    notify the side.
2249  * - Adjust the tooling on all other Units, via a crossover array.
2250  * - update Unit display for the side.
2251  * - use up ACP for the unit \Unit
2252  *
2253  * \see prep_toolup_action, check_tooup_action, init_unit_tooling,
2254  *      uu_tp_per_toolup, uu_tp_max, notify_tp, adjust_tooling_crossover,
2255  *      update_unit_display, use_up_acp, uu_acp_to_toolup.
2256  *
2257  * \param actor is the pointer to the \Unit initiating the action.
2258  * \param constructor is pointer to the \Unit which is building the New unit.
2259  * \param u3 is the Unit type for which to tool up.
2260  * \return A_ANY_DONE always.
2261  */
2262 
2263 int
do_toolup_action(Unit * actor,Unit * constructor,int u3)2264 do_toolup_action(Unit *actor, Unit *constructor, int u3)
2265 {
2266     int oldtp = -1, tp = -1;
2267     Side *side = NULL;
2268     int u2 = NONUTYPE;
2269 
2270     assert_error(is_active(actor),
2271 		 "Create Action: Attempted to manipulate an inactive actor");
2272     assert_error(is_active(constructor),
2273 "Create Action: Attempted to manipulate an inactive constructor");
2274     assert_error(is_unit_type(u3),
2275 		 "Create Action: Encountered an invalid unit type");
2276     u2 = constructor->type;
2277     side = actor->side;
2278     // Initialize the constructor's tooling array, if necessary.
2279     if (!constructor->tooling)
2280 	init_unit_tooling(constructor);
2281     // Increase the tooling, clipping to its max.
2282     oldtp = tp = constructor->tooling[u3];
2283     tp = min(tp + uu_tp_per_toolup(u2, u3), uu_tp_max(u2, u3));
2284     constructor->tooling[u3] = tp;
2285     if (constructor->tooling[u3] != oldtp)
2286 	notify_tp(side, constructor, u3, oldtp, constructor->tooling[u3]);
2287     // Adjust any related toolings.
2288     adjust_tooling_crossover(constructor, u3);
2289     update_unit_display(side, constructor, TRUE);
2290     // Consume resources for this toolup.
2291     consume_materials(actor, constructor, um_consumption_per_tooledup, u3);
2292     consume_materials(actor, constructor, um_consumption_per_toolup);
2293     use_up_acp(actor, uu_acp_to_toolup(u2, u3));
2294     return A_ANY_DONE;
2295 }
2296 
2297 /*! \brief Check Toolup Action.
2298  *
2299  * Check to see if a toolup action may be performed.
2300  *
2301  * \see prep_toolup_action, do_toolup_action. in_play, is_unit_type,
2302  *      uu_acp_to_toolup, can_have_enough_acp, uu_tp_max,
2303  *      has_enough_acp.
2304  *
2305  * \param actor is the pointer to the \Unit initiating the action.
2306  * \param constructor is pointer to \Unit which will do the tool up for the
2307  *        new unit.
2308  * \param u3 is the type of Unit for which to toolup.
2309  * \return
2310  *    - A_ANY_ERROR if
2311  *      - unit is not in play,
2312  *      - builder is not in play,
2313  *      - new_u is not a Unit type, or
2314  *      - tooling points equal or exceed the number needed to toolup for the
2315  *        new Unit type.
2316  *    - A_ANY_CANNOT_DO if
2317  *      - the builder \Unit cannot toolup for the required Unit type
2318  *        (acp less than 1), or
2319  *      - the unit \Unit can never have enough acp to produce the Unit type.
2320  *    - A_ANY_NO_ACP if the unit \Unit doesn't have enough acp to toolup this turn.
2321  *    - A_ANY_OK if the toolup is possible.
2322  */
2323 
2324 int
check_toolup_action(Unit * actor,Unit * constructor,int u3)2325 check_toolup_action(Unit *actor, Unit *constructor, int u3)
2326 {
2327     int rslt = A_ANY_OK;
2328 
2329     if (!valid(rslt = can_toolup_for(actor, constructor, u3)))
2330 	return rslt;
2331     return A_ANY_OK;
2332 }
2333 
2334 /*! \brief Adjust Tooling Startup Crossover.
2335  *
2336  * For all Unit types, adjust any toolup crossover from the Unit toolup.
2337  * - If the \Unit tooling pointer is NULL, return
2338  * - For all Unit types
2339  *   - for each Unit type not the same as the calling Unit's type,
2340  *     - calculate crossover toolup points.
2341  *     - if crossover value increases,
2342  *       - set new toolup point value.
2343  *       - notify side of Unit change.
2344  *
2345  * \see do_toolup_action, for_all_unit_types, uu_tp_crossover, uu_tp_max,
2346  *      notify_tp.
2347  *
2348  * \param unit is a pointer to the \Unit perfroming the toolup
2349  * \param u is the type of Unit that was tooled up.
2350  */
2351 
2352 void
adjust_tooling_crossover(Unit * constructor,int u2)2353 adjust_tooling_crossover(Unit *constructor, int u2)
2354 {
2355     int u = NONUTYPE, u3 = NONUTYPE;
2356     int uucross = -1, oldtp = -1;
2357     short int *tooling = NULL;
2358 
2359     assert_error(is_active(constructor),
2360 "Toolup Action: Attempted to manipulate an out-of-play constructor");
2361     assert_error(is_unit_type(u2),
2362 		 "Toolup Action: Encountered an invalid unit type");
2363     u = constructor->type;
2364     // Perhaps nothing to cross over with.
2365     if (!constructor->tooling)
2366 	return;
2367     tooling = constructor->tooling;
2368     // Look through other utypes and find any to share tooling with.
2369     for_all_unit_types(u3) {
2370 	if (u3 == u2)
2371 	    continue;
2372 	uucross = uu_tp_crossover(u2, u3);
2373 	// Clobber any toolings which cannot be shared.
2374 	if (0 >= uucross) {
2375 	    tooling[u3] = 0;
2376 	    continue;
2377 	}
2378 	oldtp = tooling[u3];
2379 	// Calculate the crossover as a ratio of max levels.
2380 	tooling[u3] = (tooling[u2] * uucross * uu_tp_max(u, u3))
2381 		       / (uu_tp_max(u, u2) * 100);
2382 	if (tooling[u3] != oldtp)
2383 	    notify_tp(constructor->side, constructor, u3, oldtp, tooling[u3]);
2384     }
2385 }
2386 
2387 /*! \brief Notify of Tooling Startup Change.
2388  *
2389  * Notify the given \Side of any notable changes in tooling.
2390  * If toolup points moved from not buildable to buildable, notify side.
2391  *
2392  * \todo move to nlang.c?
2393  *
2394  * \see do_toolup_action, adjust_toolup_crossover, notify.
2395  *
2396  *  \GDL
2397  *    - <a href="xcdesign_242.html#GDL_ref_tp-to-build"></a>
2398  *    - <a href="xcdesign_182.html#GDL_ref_unit-type">unit-type</a>
2399  *
2400  * \param side is a pointer to the \Side.
2401  * \param unit is a pointer to the \Unit.
2402  * \param u is the type of the Unit.
2403  * \param oldtp is the old toolup points.
2404  * \param newtp is the new toolup points.
2405  *
2406  */
2407 void
notify_tp(Side * side,Unit * unit,int u,int oldtp,int newtp)2408 notify_tp(Side *side, Unit *unit, int u, int oldtp, int newtp)
2409 {
2410     if (oldtp < uu_tp_to_build(unit->type, u)
2411 	&& newtp >= uu_tp_to_build(unit->type, u)) {
2412 	notify(side, "%s is now tooled to build %s units",
2413 	       unit_handle(side, unit), u_type_name(u));
2414     }
2415 }
2416 
2417 //! Consume materials needed by a build or create-as-build action.
2418 
2419 static void
consume_materials_for_build(Unit * actor,Unit * constructor,int u3,int cp)2420 consume_materials_for_build(Unit *actor, Unit *constructor, int u3, int cp)
2421 {
2422     assert_error(is_active(actor),
2423 		 "Construct Action: Attempted to access an inactive actor");
2424     assert_error(is_active(constructor),
2425 "Construct Action: Attempted to access an inactive constructor");
2426     assert_error(is_unit_type(u3),
2427 "Construct Action: Encountered an invalid unit type to construct");
2428     consume_materials(actor, constructor, um_consumption_per_cp, u3, cp);
2429     consume_materials(actor, constructor, um_consumption_per_built, u3);
2430     consume_materials(actor, constructor, um_consumption_per_build);
2431 }
2432 
2433 static void
do_create_action_common_1(Unit * actor,Unit * creator,Unit * creation)2434 do_create_action_common_1(Unit *actor, Unit *creator, Unit *creation)
2435 {
2436     int u2 = NONUTYPE, u3 = NONUTYPE;
2437     int cab = FALSE;
2438     int cp = -1;
2439 
2440     assert_error(is_active(actor),
2441 		 "Create Action: Attempted to manipulate inactive actor");
2442     assert_error(is_active(creator),
2443 		 "Create Action: Attempted to manipulate inactive creator");
2444     assert_error(creation,
2445 		 "Create Action: Attempted to manipulate null creation");
2446     u2 = creator->type;
2447     u3 = creation->type;
2448     cab = uu_create_as_build(u2, u3);
2449     cp = min((cab ? uu_cp_per_build(u2, u3) : uu_creation_cp(u2, u3)),
2450 	     u_cp(u3));
2451     // Consume resources for this create.
2452     if (cab) {
2453 	consume_materials_for_build(actor, creator, u3, cp);
2454 	use_up_acp(actor, uu_acp_to_build(u2, u3));
2455     }
2456     else {
2457 	consume_materials(actor, creator, um_consumption_per_cp, u3, cp);
2458 	consume_materials(actor, creator, um_consumption_on_creation, u3);
2459 	consume_materials(actor, creator, um_consumption_per_create);
2460 	use_up_acp(actor, uu_acp_to_create(u2, u3));
2461     }
2462     // Fill in various properties.
2463     set_created_unit_props(creation, creator, actor->side);
2464     // Give the creator a handle to the new unit.
2465     creator->creation_id = creation->id;
2466     // Transfer the creator's stash of CPs to newunit if permitted.
2467     if (uu_builder_can_reuse_cp(creator->type, u3)) {
2468 	creation->cp += min(creator->cp_stash, u_cp(u3) - creation->cp);
2469 	creator->cp_stash -=
2470 	    min(creator->cp_stash, u_cp(u3) - creation->cp);
2471     }
2472 }
2473 
2474 static void
do_create_action_common_2(Unit * actor,Unit * creator,Unit * creation)2475 do_create_action_common_2(Unit *actor, Unit *creator, Unit *creation)
2476 {
2477     int u3 = NONUTYPE;
2478 
2479     assert_error(actor,
2480 		 "Create Action: Attempted to manipulate NULL actor");
2481     assert_error(creator,
2482 		 "Create Action: Attempted to manipulate NULL creator");
2483     assert_error(in_play(creation),
2484 		 "Create Action: Attempted to manipulate out-of-play creation");
2485     u3 = creation->type;
2486     // Unit might have started out complete.
2487     if (completed(creation)) {
2488 	if (uu_constructor_absorbed_by(creator->type, u3))
2489 	    garrison_unit(creator, creation);
2490 	make_unit_complete(creation);
2491     }
2492     else
2493 	record_event(H_UNIT_CREATED,
2494 		     add_side_to_set(actor->side, NOSIDES),
2495 		     side_number(actor->side), creation->id);
2496     // Add creation to actor's side's tally of units.
2497     if (alive(actor))
2498 	count_gain(actor->side, u3, build_gain);
2499 }
2500 
2501 /* Create-in action. */
2502 
2503 /*! \brief Prepare for Create In Unit Action.
2504  *
2505  * This action creates the (incomplete) unit.
2506  * \see do_create_in_action, check_create_in_action.
2507  * \param unit is the pointer to the \Unit initiating the action.
2508  * \param creator is the pointer to the \Unit which creates the new Unit.
2509  * \param new_u the the type of \Unit to create.
2510  * \param dest is the pointer to the \Unit in which to create the new Unit.
2511  * \return
2512  *   - TRUE if action is queued.
2513  *   - FALSE if
2514  *     - the unit pointer is NULL,
2515  *     - the unit action pointer is NULL,
2516  *     - the creator pointer is NULL, or
2517  *     - the dest pointer is NULL.
2518  */
2519 int
prep_create_in_action(Unit * unit,Unit * creator,int new_u,Unit * dest)2520 prep_create_in_action(Unit *unit, Unit *creator, int new_u, Unit *dest)
2521 {
2522     if (unit == NULL || unit->act == NULL || creator == NULL || dest == NULL) {
2523 	return FALSE;
2524     }
2525     unit->act->nextaction.type = ACTION_CREATE_IN;
2526     unit->act->nextaction.args[0] = new_u;
2527     unit->act->nextaction.args[1] = dest->id;
2528     unit->act->nextaction.actee = creator->id;
2529     return TRUE;
2530 }
2531 
2532 /*! \brief Do Create In Unit Action.
2533  *
2534  * This action creates a \Unit "in" another Unit.
2535  * - If the Unit being created is advanced
2536  *   - Figure out if the destination unit is the creator's transport
2537  *   - If the destination unit is the creator's transport
2538  *     - increment destination unit's size by 1.
2539  *     - garrison (destroy) the creator
2540  *     - update the Unit display
2541  *     - use up ACPs
2542  *     - return
2543  * - (If we fell through above code) create the new \Unit.
2544  * - If the pointer to the new \Unit is not NULL
2545  *    - Fill in new \Unit properties.
2546  *    - if creation points can be passed to the new \Unit
2547  *      - stuff new \Unit with as much as it can hold or is avalible,
2548  *      - move balances to the correct places.
2549  *    - Put the new \Unit in the transport (dest)
2550  *    - If \Unit created complete
2551  *      - garrison \Unit in transport
2552  *      - make \Unit complete
2553  *    - Else
2554  *      - record the creation event.
2555  *    - If creator is alive
2556  *      - count the gain in \Units (scorekeeping?)
2557  *      - for all materials (supplies)
2558  *        - calculate the amount of material consumed in createing new \Unit
2559  *        - if consumption greater than supply
2560  *          - figure out amount lacking
2561  *          - reduce supply by amount consumed
2562  *          - if lacking supply from unit2
2563  *            - remove need amount from treasury.
2564  *          - if not in treasury
2565  *            - generate run time warning (but still return good status).
2566  *    - use ACP needed to create new \Unit.
2567  *    - return
2568  * - else return error (no memory for new \Unit?)
2569  *
2570  * \todo Add crosscheck to make sure that an advanced unit
2571  *       does not exceed it's maximum size.
2572  *
2573  * \see prep_create_in_action, check_create_in_action, u_advanced,
2574  *      update_unit_display, garrison_unit, use_up_acp, create_unit,
2575  *      set_created_unit_props, uu_builder_can_reuse_cp, enter_transport,
2576  *      make_unit_complete, completed, record_event, add_sid_to_set, alive,
2577  *      count_gain, for_all_material_types, um_consumption_on_creation
2578  *      side_has_treasury, um_takes_from_treasury, run_warning,
2579  *      use_up_acp, uu_acp_to_create.
2580  *
2581  * \param unit is the pointer to the \Unit initiating the action.
2582  * \param creator is pointer to \Unit performing the creation.
2583  * \param new_u is the new Unit type.
2584  * \param dest is the \Unit to create the new Unit in.
2585  * \return
2586  *   - A_ANY_ERROR if the new \Unit could not be created.
2587  *   - A_ANY_DONE otherwise.
2588  */
2589 
2590 int
do_create_in_action(Unit * actor,Unit * creator,int u3,Unit * transport)2591 do_create_in_action(Unit *actor, Unit *creator, int u3, Unit *transport)
2592 {
2593     Unit *creation = NULL;
2594     int u2 = NONUTYPE;
2595 
2596     assert_error(is_active(actor),
2597 		 "Create Action: Attempted to manipulate inactive actor");
2598     assert_error(is_active(creator),
2599 		 "Create Action: Attempted to manipulate inactive creator");
2600     assert_error(in_play(transport),
2601 "Create Action: Attempted to manipulate out-of-play transport");
2602     // Useful info.
2603     u2 = creator->type;
2604     // Special Case.
2605     // Merge "creator" into its transport to increase transport's size.
2606     // Transport must be advanced unit.
2607     if (u_advanced(u3)
2608     	&& creator->transport && (creator->transport == transport)
2609     	&& (transport->type == u3)) {
2610 	// TODO: Should test whether this kidn of joining is allowed.
2611 	// TODO: Be more flexible with how much size is added.
2612 	transport->size += 1;
2613 	update_unit_display(transport->side, transport, TRUE);
2614 	garrison_unit(creator, transport);
2615 	use_up_acp(actor, uu_acp_to_create(u2, u3));
2616 	return A_ANY_DONE;
2617     }
2618     // Create the new unit.
2619     creation = create_unit(u3, FALSE);
2620     // If creation succeeded...
2621     if (creation) {
2622 	do_create_action_common_1(actor, creator, creation);
2623 	// Put the new unit inside the designated transport.
2624 	enter_transport(creation, transport);
2625 	do_create_action_common_2(actor, creator, creation);
2626 	return A_ANY_DONE;
2627     }
2628     // Else, we failed to create the unit.
2629     // Perhaps we have reached the side limit on units?
2630     else
2631 	return A_ANY_ERROR;
2632 }
2633 
2634 /*! \brief Check for Create in Unit Action
2635  *
2636  * Check to see if it's possible to create a \Unit in another Unit.
2637  *
2638  * \see prep_create_in_action, do_create_in_action, in_play,
2639  *      u_advanced, unit_at, type_can_occupy.
2640  *
2641  * \return
2642  *   - the return value from can_create_common, if it is not
2643  *     A_ANY_OK;
2644  *   - A_ANY_ERROR if
2645  *     - destination \Unit is not in play, or
2646  *     - the new \Unit cannot be created in the destination Unit;
2647  *   - A_ANY_OK otherwise.
2648  */
2649 int
check_create_in_action(Unit * actor,Unit * creator,int uc,Unit * transport)2650 check_create_in_action(Unit *actor, Unit *creator, int uc, Unit *transport)
2651 {
2652     int rslt = A_ANY_OK;
2653 
2654     // Is transport unit in play?
2655     if (!in_play(transport))
2656 	return A_ANY_ERROR;
2657     // If common checks are not passed, then get out.
2658     if (!valid(
2659 	    rslt =
2660 		can_create_common(
2661 		    actor, creator, uc, transport->x, transport->y)))
2662 	return rslt;
2663     // Special Feature: Can we add a colonizer to an existing city?
2664     if (u_advanced(uc)
2665     	&& creator->transport && (creator->transport == transport)
2666     	&& (transport->type == uc))
2667 	return A_ANY_OK;
2668     // Can the new utype fit in the transport?
2669     if (!type_can_occupy(uc, transport))
2670 	return A_ANY_ERROR;
2671     return A_ANY_OK;
2672 }
2673 
2674 /*! \brief Set Created Unit Properties.
2675  *
2676  * Set the properties of the newly created unit.
2677  * Set various values:
2678  *   - hp and hp2 to 1,
2679  *   - cp to creation cp table value,
2680  *   - the pointer to the original \Side,
2681  *   - assign a unique unit number
2682  *   - set all the initial supplies, and
2683  *   - if morale is used, set the morale.
2684  *
2685  * \todo Possibly should set the unit's morale from a global
2686  *       side morale value if there isn't a specific value
2687  *       for the unit.
2688  * \see uu_creation_cp, set_unit_origside, assign_unit_number,
2689  *      for_all_material_types, max, um_created_supply, min,
2690  *      UM_storage_x, u_morale_max, uu_createion_morale,
2691  * \param newunit is a pointer to the new \Unit.
2692  * \param creator_u is the unit type of the creating unit.
2693  * \param side is the pointer to the creating \Side.
2694  * \param creator_mor is the creating unit's morale.
2695  */
2696 static void
set_created_unit_props(Unit * newunit,Unit * creator,Side * side)2697 set_created_unit_props(Unit *newunit, Unit *creator, Side *side)
2698 {
2699     int u2 = NONUTYPE, u3 = NONUTYPE;
2700     int m = NONMTYPE;
2701     int amt;
2702     int mfrac;
2703     int mor;
2704 
2705     u2 = creator->type;
2706     u3 = newunit->type;
2707     newunit->hp = newunit->hp2 = 1;
2708     newunit->cp =
2709 	(uu_create_as_build(u2, u3) ? uu_cp_per_build(u2, u3)
2710 				    : uu_creation_cp(u2, u3));
2711     set_unit_side(newunit, side);
2712     set_unit_origside(newunit, side);
2713     /* Always number the unit when first created. */
2714     assign_unit_number(newunit);
2715     /* Set all supplies to their just-created levels. */
2716     for_all_material_types(m) {
2717         amt = newunit->supply[m];
2718         amt = max(amt, um_created_supply(newunit->type, m));
2719         /* Clip to capacity. */
2720         amt = min(amt, um_storage_x(newunit->type, m));
2721         newunit->supply[m] = amt;
2722     }
2723     /* Set the created unit's morale as a ratio to the creator's morale. */
2724     if (u_morale_max(newunit->type) > 0) {
2725         if (u_morale_max(creator->type) > 0) {
2726             mfrac = (creator->morale * 100) / u_morale_max(creator->type);
2727             mor = (uu_creation_morale(creator->type, newunit->type) * mfrac)
2728 		  / 100;
2729             /* Scale to new unit's morale range. */
2730             newunit->morale = (mor * u_morale_max(newunit->type)) / 100;
2731         } else {
2732             /* (should get from global side morale or some such?) */
2733             newunit->morale = u_morale_max(newunit->type);
2734         }
2735     }
2736 }
2737 
2738 /* Create-at action. */
2739 
2740 /* Create a new unit of a given type, out in the open at a given location. */
2741 
2742 /*! \brief Prepare for Create Unit at Location.
2743  *
2744  * Prepare to create a unit in the open at the given location.
2745  * \param unit is the pointer to the \Unit initiating the action.
2746  * \param creator is a pointer to the \Unit creating the new Unit.
2747  * \param new_u is the Unit type of the unit being created.
2748  * \param x is the cell x co-ordinate.
2749  * \param y is the cell y co-ordinate.
2750  * \param z is the altitude of the unit.
2751  * \return
2752  *   - TRUE if action is queued.
2753  *   - FALSE if
2754  *     - Acting \Unit pointer is NULL,
2755  *     - Acting \Unit action pointer is NULL, or
2756  *     - Creating \Unit is NULL;
2757  */
2758 int
prep_create_at_action(Unit * unit,Unit * creator,int new_u,int x,int y,int z)2759 prep_create_at_action(Unit *unit, Unit *creator, int new_u, int x, int y, int z)
2760 {
2761     if (unit == NULL || unit->act == NULL || creator == NULL) {
2762 	return FALSE;
2763     }
2764     unit->act->nextaction.type = ACTION_CREATE_AT;
2765     unit->act->nextaction.args[0] = new_u;
2766     unit->act->nextaction.args[1] = x;
2767     unit->act->nextaction.args[2] = y;
2768     unit->act->nextaction.args[3] = z;
2769     unit->act->nextaction.actee = creator->id;
2770     return TRUE;
2771 }
2772 
2773 /*! \brief Do Create Unit at Location.
2774  *
2775  * Create the unit at the given location.
2776  * - Try to allocate a new \Unit.
2777  * - If allocated,
2778  *    - Set the default properties of the \Unit.
2779  *    - If the \Unit can reuse creation points, adjust the new unit's and creator's
2780  *      creation points.
2781  *    - If the new unit can occupy the cell
2782  *      - enter the cell with the new \Unit.
2783  *      .
2784  *    - else if there is space in cell and the creating \Unit can transport
2785  *      the new unit
2786  *      - make the creating \Unit leave the cell
2787  *      - make the new \Unit enter the cell
2788  *      - make the creator \Unit eter the new unit as an occupant.
2789  *      .
2790  *    - else there was an error.
2791  *    - if the new \Unit is completed on creation
2792  *      - destroy creating \Unit, if neccessary.  This is for things
2793  *        like creatinn a city from a colonizer that is "used up" in
2794  *        the process of creating the new Unit.
2795  *      - complete the new \Unit.
2796  *      .
2797  *    - else record the creation event.
2798  *    - if the creating unit is still alive (not destroyed by creating the new unit)
2799  *      - record any score gain from creating unit.
2800  *      - use supplies for creation (local and/or treasury).
2801  *      .
2802  *    - use up creation ACP from the unit.
2803  *    .
2804  *  - else ran out of memory
2805  *  .
2806  * \see create_unit, set_created_unit_props, uu_builder_can_reuse_cp,
2807  *      mn, u_cp, can_occupy_cell, enter_cell, can_occupy_cell_without,
2808  *      can_occupy, leave_cell, enter_transport, run_error, completed,
2809  *      garrison_unit, make_unit_complete, recod_event, add_side_to_set,
2810  *      side_number, alive, count_gain, for_all_material_types,
2811  *      um_consumption_on_creation, side_has_treasury,
2812  *      run_warning, use_up_acp.
2813  * \param actor is the pointer to the \Unit initiating the action.
2814  * \param creator is a pointer to the \Unit doing the creation.
2815  * \param u3 is the Unit type to be created.
2816  * \param x is the creation location's x co-ordiate.
2817  * \param y is the creation location's y co-ordinate.
2818  * \param z is the creation location's altitude.
2819  * \return
2820  *   - A_ANY_ERROR if no memory for \Unit creation.
2821  *   - A_ANY_OK if unit created.
2822  */
2823 
2824 int
do_create_at_action(Unit * actor,Unit * creator,int u3,int x,int y,int z)2825 do_create_at_action(Unit *actor, Unit *creator, int u3, int x, int y, int z)
2826 {
2827     int u2 = NONUTYPE;
2828     int t = NONTTYPE;
2829     Unit *creation = NULL;
2830 
2831     assert_error(is_active(actor),
2832 		 "Create Action: Attempted to manipulate inactive unit");
2833     assert_error(is_active(creator),
2834 		 "Create Action: Attempted to manipulate inactive unit");
2835     assert_error(is_unit_type(u3),
2836 		 "Create Action: Encountered invalid unit type for new unit");
2837     assert_error(inside_area(x, y),
2838 		 "Create Action: Attempted to place new unit outside of world");
2839     u2 = creator->type;
2840     // TODO: Handle any ZOC violations as appropriate.
2841     // Create the new unit.
2842     creation = create_unit(u3, FALSE);
2843     if (creation) {
2844 	do_create_action_common_1(actor, creator, creation);
2845 	// Put the unit where there is room for it.
2846 	t = terrain_at(x, y);
2847     	// If there is room in the cell...
2848 	if (type_can_occupy_cell(u3, x, y)
2849     	    && type_survives_in_cell(u3, x, y)) {
2850 	    enter_cell(creation, x, y);
2851 	}
2852 	// Else if the creator occupies its construction work...
2853 	else if (can_occupy_cell_without(creation, x, y, creator)
2854 		 && type_survives_in_cell(u3, x, y)
2855 		 && can_occupy(creator, creation)) {
2856 		leave_cell(creator);
2857 		enter_cell(creation, x, y);
2858 		enter_transport(creator, creation);
2859 	}
2860 	// Else if the creator is going to die.
2861 	else if (can_occupy_cell_without(creation, x, y, creator)
2862 		 && type_survives_in_cell(u3, x, y)
2863 		 && creator_always_dies_on_creation(creator->type, u3)) {
2864 		leave_cell(creator);
2865 		enter_cell(creation, x, y);
2866 	}
2867 	// This should never happen.
2868 	//  If it does, then 'check_create_at_action' has made a mistake.
2869 	else
2870 	    run_error(
2871 		"Create Action: Tried to place creation where it cannot be");
2872 	// TODO: Adjust altitude.
2873 	do_create_action_common_2(actor, creator, creation);
2874 	return A_ANY_DONE;
2875     }
2876     // Else, we failed to create the unit.
2877     // Perhaps we have reached the side limit on units?
2878     else {
2879         return A_ANY_ERROR;
2880     }
2881 }
2882 
2883 /*! \brief Check for Create Unit at Location.
2884  *
2885  * Check to see if a \Unit may be created at cell(x,y) at altitude z.
2886  * \see inside_area, type_can_occupy_cell,
2887  *      type_can_occupy_enpty_type, type_can_occupy_cell_without,
2888  *      terrain_at, ut_vanished_on, ut_wrecks_on,
2889  *      type_can_sit_on_conn.
2890  * \param actor is the pointer to the \Unit initiating the action.
2891  * \param creator is thepointer to the \Unit creating the Unit.
2892  * \param u3 is the type of Unit being created.
2893  * \param x is the location's x co-ordinate.
2894  * \param y is the location's y co-ordinate.
2895  * \param z is the altitude of the new \Unit.
2896  * \return
2897  *   - result of can_create_common, if not A_ANY_OK
2898  *   - A_ANY_ERROR if
2899  *     - the creation location is not in the world,
2900  *     - the new Unit can't occupy the desired cell, or the creator can't
2901  *       occupy the new Unit.
2902  *     - the Unit vanishes or wrecks in the cell, or can't sit
2903  *       on the connection.
2904  *   - A_ANY_OK if it's ok to create the unit.
2905  */
2906 
2907 int
check_create_at_action(Unit * actor,Unit * creator,int u3,int x,int y,int z)2908 check_create_at_action(
2909     Unit *actor, Unit *creator, int u3, int x, int y, int z)
2910 {
2911     int rslt = A_ANY_OK;
2912     int u2 = NONUTYPE;
2913     int t = NONTTYPE;
2914 
2915     // If not inside the playing area, then error.
2916     if (!inside_area(x, y))
2917         return A_ANY_ERROR;
2918     // TODO: Check altitude.
2919     // If common checks are not passed, then error.
2920     if (!valid(rslt = can_create_common(actor, creator, u3, x, y)))
2921         return rslt;
2922     // Useful info.
2923     u2 = creator->type;
2924     // Check that the desired cell has room for the unit.
2925     t = terrain_at(x, y);
2926     // If there is room in the cell.
2927     if (type_can_occupy_cell(u3, x, y)
2928     	&& type_survives_in_cell(u3, x, y))
2929     	return A_ANY_OK;
2930     // Else if in same cell, and creator dies or occupies its construction work.
2931     if ((x == creator->x) && (y == creator->y)
2932 	&& type_can_occupy_cell_without(u3, x, y, creator)
2933     	&& type_survives_in_cell(u3, x, y)
2934     	&& (type_can_occupy_empty_type(u2, u3)
2935 	    || creator_always_dies_on_creation(u2, u3)))
2936     	return A_ANY_OK;
2937     // Else, there is no room.
2938     return A_ANY_ERROR;
2939 }
2940 
2941 /* Tests if a creator always dies on creation. Note that the creator may die
2942 even if this test returns false, if its actual hp is less than hp-max. */
2943 
2944 int
creator_always_dies_on_creation(int u,int new_u)2945 creator_always_dies_on_creation(int u, int new_u)
2946 {
2947 	if (uu_hp_to_garrison(u, new_u) >= u_hp_max(u)
2948 	    && uu_creation_cp(u, new_u) >= u_cp(new_u)) {
2949 		return TRUE;
2950 	}
2951 	return FALSE;
2952 }
2953 
2954 /* Build action. */
2955 
2956 /*! \brief Prepare to Build Unit in Unit.
2957  *
2958  * Sets up build operation.
2959  * \bug Shouldn't newunit be checked for NULL as well?  If it is
2960  *      NULL, then newunit->id will probably not work as intended.
2961  * \param unit is the \Unit initiating the action.
2962  * \param builder is the \Unit building the new Unit.
2963  * \param newunit is the new Unit to build.
2964  * \return
2965  *   - FALSE if
2966  *     - unit pointer to unit is NULL,
2967  *     - pointer to unit action is NULL, or
2968  *     - builder pointer to actee is NULL;
2969  *   - TRUE otherwise.
2970  */
2971 int
prep_build_action(Unit * unit,Unit * builder,Unit * newunit)2972 prep_build_action(Unit *unit, Unit *builder, Unit *newunit)
2973 {
2974     if (unit == NULL || unit->act == NULL || builder == NULL) {
2975 	return FALSE;
2976     }
2977     unit->act->nextaction.type = ACTION_BUILD;
2978     unit->act->nextaction.args[0] = newunit->id;
2979     unit->act->nextaction.actee = builder->id;
2980     return TRUE;
2981 }
2982 
2983 /*! \brief Do Build Unit in Unit Action.
2984  *
2985  * Build a unit.
2986  * - for all materials
2987  *   - reduce the supply of the building \Unit by the proportional amount based
2988  *     on construction points.
2989  * - increase constrution points for the unit for this build
2990  * - if \Unit completed,
2991  *   - get rid of building \Unit, if neccessary
2992  *   - make \Unit complete,
2993  *   - update Unit display,
2994  *   - use up ACP.
2995  * - else
2996  *   - update Unit display
2997  *   - use up ACP
2998  * \see for_all_material_types, side_has_treasury, um_takes_from_treasury
2999  *      run_warning, uu_cp_per_build, completed, garrison_unit,
3000  *      make_unit_complete, update_unit_display, use_up_acp.
3001  * \param unit is the pointer to the \Unit initiating the action.
3002  * \param builder is the pointer to \Unit building the new Unit.
3003  * \param newunit is the pointer to \Unit being built.
3004  * \return
3005  *   - A_BUILD_COMPLETED if new \Unit is completed.
3006  *   - A_ANY_DONE if build done.
3007  */
3008 
3009 int
do_build_action(Unit * unit,Unit * builder,Unit * newunit)3010 do_build_action(Unit *unit, Unit *builder, Unit *newunit)
3011 {
3012     int rslt = A_ANY_DONE;
3013     int cp = -1;
3014     int u2 = NONUTYPE, u3 = NONUTYPE;
3015 
3016     assert_error(is_active(unit),
3017 		 "Build Action: Attempted to manipulate inactive unit");
3018     assert_error(is_active(builder),
3019 		 "Build Action: Attempted to manipulate inactive unit");
3020     assert_error(in_play(newunit),
3021 		 "Build Action: Attempted to manipulate out-of-play unit");
3022     u2 = builder->type;
3023     u3 = newunit->type;
3024     // Calculate CP gained for this build.
3025     cp = min(uu_cp_per_build(u2, u3), completenesses[u3] - newunit->cp);
3026     // Consume resources for this build.
3027     consume_materials_for_build(unit, builder, u3, cp);
3028     use_up_acp(unit, uu_acp_to_build(u2, u3));
3029     // Increment the new unit's CP.
3030     newunit->cp += cp;
3031     // Handle completeness.
3032     if (completed(newunit)) {
3033 	if (uu_constructor_absorbed_by(u2, u3))
3034 	    garrison_unit(builder, newunit);
3035         make_unit_complete(newunit);
3036 	// TODO: Implement consumption-to-complete.
3037 	// TODO: Implement addition of default occs.
3038 	rslt = A_BUILD_COMPLETED;
3039     }
3040     update_unit_display(newunit->side, newunit, TRUE);
3041     return rslt;
3042 }
3043 
3044 /*! \brief Garrison Unit.
3045  *
3046  * This name is somewhat confusing.  It uses the uu_hp_to_garrison table
3047  * to determine if the unit should be removed.  It is used to remove a
3048  * building Unit upon creating a new Unit.  An example would be a
3049  * colonizer/settler/engineer disappearing when a villiage/town/city is
3050  * built.  It is also sometimes used when a unit captures a unit, such as
3051  * an army capturing a city, and being destroyed in the process of
3052  * capturing the city.
3053  * - If the hit points to create/capture (hp_to_garrison) is greater than
3054  * the remaining hit points of the building \Unit
3055  *   - remove the new \Unit from the cell,
3056  *   - if the new \Unit is being transported by the building/capturing Unit
3057  *     - force the new \Unit out of the building/capturing Unit.
3058  *     - if the there is a transport availble (not currently implemented)
3059  *       - put the new \Unit in the transport
3060  *     - else
3061  *       - put the new \Unit in the cell.
3062  *   - if the new \Unit is being transported, but not by the
3063  *     building/capturing Unit
3064  *     - set the alternate transport local variable to the transporting \Unit.
3065  *   - for all occupants of the building/capturing \Unit
3066  *     - if the occupant of the building \Unit can occupy the new
3067  *       Unit
3068  *       - remove the occupant from the new \Unit.
3069  *       - update the Unit display.
3070  *       - add the occupant to the new \Unit.
3071  *     - else if the alternate transport can hold the occupant
3072  *       - remove the ocupant from the building/capuring \Unit.
3073  *       - update the Unit display.
3074  *       - add the occupant to the alternate transport.
3075  *     - else if the occupant can enter the cell
3076  *       - remove the occupant from the building/capturing \Unit.
3077  *       - update the Unit display.
3078  *       - add the occupant to the cell.
3079  *     - By default, leave the occupant in the building/capturing \Unit to be
3080  *       destroyed with the building/capturing Unit.
3081  *   - Set the temporary event data 1 to the id of the new \Unit.
3082  *   - Kill the building/capturing Unit.
3083  * - else reduce the building/capturing hp and hp2 by the hp to garrison
3084  *   amount. \note if this occurs before damage is calculated, hp and hp2
3085  *   may be different.
3086  * \todo Add code to handle the garrison \Unit being put in a transport?
3087  * \todo Add code to handle sub-occupants of doomed occupants?
3088  * \todo Add code to post event for garrisoning damage?
3089  * \see uu_hp_to_garrison, leave_cell, leave_trasnport, enter_transport,
3090  *      can_occupy, update_unit_display, kill_unit.
3091  *  \param builder is a pointer to the \Unit building/capturing the unit.
3092  *  \param newunit is a pointer to the \Unit being built/captured.
3093  */
3094 void
garrison_unit(Unit * builder,Unit * newunit)3095 garrison_unit(Unit *builder, Unit *newunit)
3096 {
3097     int x = builder->x;		/* x co-ordinate of builder */
3098     int y = builder->y;		/* y co-ordinate of builder */
3099     Unit *transport = NULL;	/* pointer to transport unit */
3100     Unit *occ;			/* pointer to occupant unit */
3101     Unit *nextocc;		   	/* pointer to next occupant unit */
3102 
3103     /* Maybe get rid of the building unit if it is to be the garrison. */
3104     if (uu_hp_to_garrison(builder->type, newunit->type) >= builder->hp) {
3105 	/* But first get the about-to-be-killed garrisoning unit
3106 	   disconnected from everything. */
3107 	leave_cell(builder);
3108 	/* Put new unit in place of the garrisoning one, if it was an
3109            occupant. */
3110 	if (newunit->transport == builder) {
3111 	    leave_transport(newunit);
3112 	    enter_cell(newunit, x, y);
3113 	}
3114 	if (newunit->transport != NULL && newunit->transport != builder)
3115 	  transport = newunit->transport;
3116 	/* for_all_occupants will not work here,
3117 	   since leave_transport changes occ->nexthere */
3118 	for (occ = builder->occupant; occ != NULL; occ = nextocc) {
3119 	    nextocc = occ->nexthere;
3120 	    /* Move the other occupants anywhere we can find. */
3121 	    if (can_occupy(occ, newunit)) {
3122 		// leave_cell won't work here,
3123 		//  since "builder" already left cell */
3124 		leave_transport(occ);
3125 		update_unit_display(builder->side, builder, TRUE);
3126 		enter_transport(occ, newunit);
3127 	    } else if (transport != NULL && can_occupy(occ, transport)) {
3128 		leave_transport(occ);
3129 		update_unit_display(builder->side, builder, TRUE);
3130 		enter_transport(occ, transport);
3131 	    } else if (type_can_occupy_cell(occ->type, x, y)
3132 		       && type_survives_in_cell(occ->type, x, y)) {
3133 	    	// We test for type_survives_in_cell here,
3134 		//   since we call enter_cell directly,
3135 		//   and thus bypass the unit-wrecking code in do_move_action.
3136 		leave_transport(occ);
3137 		update_unit_display(builder->side, builder, TRUE);
3138 		enter_cell(occ, x, y);
3139 	    }
3140 	    /* Otherwise the occupant has to die along with the garrison. */
3141 	    /* (should also do something with sub-occs of doomed occs?) */
3142 	}
3143 	/* Now we can get rid of the garrisoning unit without scrambling
3144 	   anything else. */
3145 	tmphevtdata1 = newunit->id;
3146 	kill_unit(builder, H_UNIT_GARRISONED);
3147     } else {
3148 	/* Note that if this all happens before damage is reckoned,
3149 	   hp and hp2 might be different. */
3150 	builder->hp -= uu_hp_to_garrison(builder->type, newunit->type);
3151 	builder->hp2 -= uu_hp_to_garrison(builder->type, newunit->type);
3152 	/* (should record loss of hp as garrison event?) */
3153     }
3154 }
3155 
3156 /*! \brief Check for Build Unit in Unit Action.
3157  *
3158  * Check to see if a Unit can continue to be built.
3159  * \see prep_build_action, do_build_action, in_play, uu_acp_to_build,
3160  *      can_have_enough_acp, uu_cp_per_build, uu_tp_to_build,
3161  *	fillsized, dostamce. uu_build_range, completed, uu_occ_can_build,
3162  *	has_enough_acp, um_to_build.
3163  * \param actor is the pointer to the \Unit initiating the action.
3164  * \param builder is the pointer to \Unit building the new Unit.
3165  * \param buildee is the pointer to \Unit being built.
3166  */
3167 
3168 int
check_build_action(Unit * actor,Unit * builder,Unit * buildee)3169 check_build_action(Unit *actor, Unit *builder, Unit *buildee)
3170 {
3171     int rslt = A_ANY_OK;
3172     int u3 = NONUTYPE;
3173 
3174     if (!in_play(buildee))
3175 	return A_ANY_ERROR;
3176     u3 = buildee->type;
3177     if (!valid(rslt = can_build(actor, builder, buildee)))
3178       return rslt;
3179     if (fullsized(buildee))
3180 	return A_ANY_ERROR;
3181     return A_ANY_OK;
3182 }
3183 
3184 /*!
3185  * \brief Complete Unit.
3186  *
3187  * Do all the little things to make a fully operational unit.
3188  *   - if a unit has multiple parts ( fleet or army, for example),
3189  *     it is not created at full size, but at a size of 1, so
3190  *     construction points and hit points are set appropriately.
3191  *   - Give the unit a name.
3192  *   - set the view coverage area of the unit.
3193  *   - if unit creation cuases a change in control of the cell,
3194  *     remove enemy units.
3195  *   - handle material supplied, created, and/or shared for created
3196  *     unit.
3197  *   - initialize action state.
3198  *
3199  * \see max, u_cp, u_parts, u_hp, make_up_unit_name, cover_area,
3200  * Kick_out_enemy_users, for_all_material_types, um_completed_supply,
3201  * um_storage_x, try_sharing, init_unit_actorstate, init_unit_plan,
3202  * set_unit_acp_for_turn, make_unit_vector, clear_unit_vector,
3203  * add_unit_to_vector, for_all_sides, trusted_side, add_side_to_set,
3204  * record_event, side_number, see_all_cell, printf
3205  * \param unit is the unit to be completed.
3206  */
3207 
3208 void
make_unit_complete(Unit * unit)3209 make_unit_complete(Unit *unit)
3210 {
3211     int u = NONUTYPE, u2 = NONUTYPE;
3212     int m = NONMTYPE;
3213     SideMask observers;
3214     Side *side = NULL, *side2 = NULL;
3215     int i = 0, imax = -1;
3216     Unit *unit2 = NULL;
3217 
3218     assert_error(in_play(unit),
3219 		 "Complete Action: Attempted to access an out-of-play unit");
3220     u = unit->type;
3221     side = unit->side;
3222     /* Make this a "complete" but not a "fullsized" unit. */
3223     unit->cp = max(unit->cp, u_cp(u) / u_parts(u));
3224     unit->hp = unit->hp2 = u_hp(u) / u_parts(u);
3225     /* Christen our new unit. Its serial number (if it is a type that has
3226        one) was assigned just after its creation. */
3227     make_up_unit_name(unit);
3228     /* It also starts viewing its surroundings. */
3229     cover_area(side, unit, unit->transport, -1, -1, unit->x, unit->y);
3230     /* Kick out enemy users if we control this cell. */
3231     kick_out_enemy_users(side, unit->x, unit->y);
3232     /* Update the cancarry vector if this is a transport. */
3233     if (u_is_transport(u))
3234     	update_cancarry_vector(side);
3235     /* Set all the supplies up to their unit-just-completed levels. */
3236     for_all_material_types(m) {
3237 	unit->supply[m] = max(unit->supply[m], um_completed_supply(u, m));
3238 	unit->supply[m] = min(unit->supply[m], um_storage_x(u, m));
3239     }
3240     // Add any incomplete or complete occs that come as "part of the package".
3241     // TODO: Warn on occupancy failures.
3242     // TODO: Notify on creation failures.
3243     for_all_unit_types(u2) {
3244 	if (!uu_complete_occs_on_completion(u, u2)
3245 	    && !uu_incomplete_occs_on_completion(u, u2))
3246 	    continue;
3247 	if (!type_can_occupy(u2, unit)) {
3248 	    run_warning(
3249 "Cannot fit any implicitly created %s units into newly completed %s",
3250 			u_type_name(u2), medium_long_unit_handle(unit));
3251 	    continue;
3252 	}
3253 	if (0 < (imax = uu_complete_occs_on_completion(u, u2))) {
3254 	    // TODO: Handle dice specs or probabilities.
3255 	    for (i = 0; i < imax; ++i) {
3256 		if (!type_can_occupy(u2, unit)) {
3257 		    run_warning(
3258 "Cannot fit any more implictly created %s units into newly completed %s",
3259 				u_type_name(u2), medium_long_unit_handle(unit));
3260 		    break;
3261 		}
3262 		if (!(unit2 = create_unit(u2, FALSE))) {
3263 		    notify(side,
3264 "Failed to implicitly create %s unit in newly completed %s",
3265 			   u_type_name(u2), medium_long_unit_handle(unit));
3266 		    break;
3267 		}
3268 		set_created_unit_props(unit2, unit, side);
3269 		unit2->cp = u_cp(u2);
3270 		enter_transport(unit2, unit);
3271 		make_unit_complete(unit2);
3272 		record_event(
3273 		    H_UNIT_CREATED, add_side_to_set(side, NOSIDES),
3274 		    side_number(side), unit2->id);
3275 		count_gain(side, u2, build_gain);
3276 	    }
3277 	}
3278 	if (0 < (imax = uu_incomplete_occs_on_completion(u, u2))) {
3279 	    // TODO: Handle dice specs or probabilities.
3280 	    for (i = 0; i < imax; ++i) {
3281 		if (!type_can_occupy(u2, unit)) {
3282 		    run_warning(
3283 "Cannot fit any more implictly created %s units into newly completed %s",
3284 				u_type_name(u2), medium_long_unit_handle(unit));
3285 		    break;
3286 		}
3287 		if (!(unit2 = create_unit(u2, FALSE))) {
3288 		    notify(side,
3289 "Failed to implicitly create %s unit in newly completed %s",
3290 			   u_type_name(u2), medium_long_unit_handle(unit));
3291 		    break;
3292 		}
3293 		set_created_unit_props(unit2, unit, side);
3294 		unit2->cp = 0;
3295 		if (completed(unit2))
3296 		    make_unit_complete(unit2);
3297 		enter_transport(unit2, unit);
3298 		record_event(
3299 		    H_UNIT_CREATED, add_side_to_set(side, NOSIDES),
3300 		    side_number(side), unit2->id);
3301 		count_gain(side, u2, build_gain);
3302 	    }
3303 	}
3304     }
3305 #if (1)
3306     /* The new unit may not need any materials due to being assigned
3307 	a stationary goal. Let the economy code decide wheter or not to fill
3308 	it up with materials. */
3309     /* Also see if anybody here is willing to share to make up any
3310        deficiencies before the end of the turn. */
3311     for_all_material_types(m) {
3312 	if (unit->transport)
3313 	  try_sharing(unit->transport, unit, m);
3314     }
3315 #endif
3316     init_unit_actorstate(unit, FALSE);
3317     init_unit_plan(unit);
3318     /* Put this unit into action immediately, at full acp. */
3319     if (unit->act) {
3320 	set_unit_acp_for_turn(unit);
3321 	if (unit->act->initacp > 0) {
3322 	   /* Make_unit_complete may be called by advanced units at
3323 	      turn 0 before compose_actionvectors has been called! */
3324 	   if (unit->side->actionvector == NULL) {
3325 		unit->side->actionvector = make_unit_vector(max(numunits, 100));
3326 		clear_unit_vector(unit->side->actionvector);
3327 	   }
3328 	   unit->side->actionvector =
3329 	    add_unit_to_vector(unit->side->actionvector, unit, 0);
3330 	}
3331     }
3332     /* Inform all sides that should know about the completion. */
3333     observers = NOSIDES;
3334     for_all_sides(side2) {
3335 	if (side2 == unit->side
3336 	    || trusted_side(unit->side, side2)
3337 	    /* (or add all sides if g_see_all?) */
3338 	    ) {
3339 	    observers = add_side_to_set(unit->side, observers);
3340 	}
3341     }
3342     record_event(H_UNIT_COMPLETED, observers, side_number(unit->side),
3343 		 unit->id);
3344     /* Make sure the image of the newly completed unit
3345 	(and its name) is drawn. */
3346     all_see_cell(unit->x, unit->y);
3347     /* (should add to any per-side tallies) */
3348     Dprintf("%s is completed\n", unit_desig(unit));
3349 }
3350 
3351 /* Repair action. */
3352 
3353 /*!
3354  * \brief Prepare for Unit Repair Action.
3355  */
3356 
3357 int
prep_repair_action(Unit * actor,Unit * repairer,Unit * repairee)3358 prep_repair_action(Unit *actor, Unit *repairer, Unit *repairee)
3359 {
3360     if (!is_active(actor) || !is_active(repairer) || !in_play(repairee))
3361 	return FALSE;
3362     if (!repairer->act)
3363 	return FALSE;
3364     repairer->act->nextaction.type = ACTION_REPAIR;
3365     repairer->act->nextaction.args[0] = repairee->id;
3366     repairer->act->nextaction.actee = repairer->id;
3367     return TRUE;
3368 }
3369 
3370 /*!
3371  * \brief Do Repair Unit Action.
3372  *
3373  * Use a unit to repair another unit.
3374  *   - Calculate amount of hitpoints that can be repaired.
3375  *   - Adjust the repaired unit's hitpoints.
3376  *   - Use up any materials required.
3377  *   - Use up any ACP needed.
3378  * \see uu_repair, add_to_unit_hp, prob_fraction,
3379  *      for_all_material_types, um_comsumption_per_repair,
3380  *      use_up_acp, uu_acp_to_repair.
3381  * \return A_ANY_DONE always.
3382  */
3383 
3384 int
do_repair_action(Unit * acpsrc,Unit * repairer,Unit * repairee)3385 do_repair_action(Unit *acpsrc, Unit *repairer, Unit *repairee)
3386 {
3387     int u2 = NONUTYPE, u3 = NONUTYPE;
3388 
3389     assert_error(is_active(acpsrc),
3390 		 "Repair Action: Attempted to manipulate an inactive unit");
3391     assert_error(is_active(repairer),
3392 		 "Repair Action: Attempted to manipulate an inactive unit");
3393     assert_error(in_play(repairee),
3394 		 "Repair Action: Attempted to manipulate an out-of-play unit");
3395     // Useful info.
3396     u2 = repairer->type;
3397     u3 = repairee->type;
3398     // If at turn start, then we consider auto-repair mechanisms.
3399     if (at_turn_start) {
3400 	// Hp-recovery mechanism.
3401 	if ((repairer == repairee)
3402 	    && (0 < u_hp_recovery(u2))
3403 	    && (repairee->hp >= u_hp_to_recover(u2))) {
3404 	    add_to_unit_hp(repairee, prob_fraction(u_hp_recovery(u2)));
3405 	}
3406 	// Auto-repair mechanism.
3407 	if (0 < uu_auto_repair(u2, u3)) {
3408 	    add_to_unit_hp(repairee, prob_fraction(uu_auto_repair(u2, u3)));
3409 	    consume_materials(acpsrc, repairer, um_consumption_per_repair);
3410 	    consume_materials(acpsrc, repairer, um_consumption_per_repaired,
3411 			      u3);
3412 	}
3413     }
3414     // Else during turn, then we consider explicit repair.
3415     else {
3416 	add_to_unit_hp(repairee, prob_fraction(uu_hp_per_repair(u2, u3)));
3417 	consume_materials(acpsrc, repairer, um_consumption_per_repair);
3418 	consume_materials(acpsrc, repairer, um_consumption_per_repaired, u3);
3419 	use_up_acp(acpsrc, uu_acp_to_repair(u2, u3));
3420     }
3421     return A_ANY_DONE;
3422 }
3423 
3424 /*!
3425  * \brief Check for Repair Unit Action.
3426  *
3427  * Check to see if the repair action can be done.
3428  * Validate:
3429  *   - All units are in play.
3430  *   - The repairng unit can repair the repaired unit.
3431  *   - Sufficient materials are on hand to do the repair.
3432  *   - the unit has enought ACP to do the repair this turn.
3433  * \see in_play, uu_acp_to_repair, can_have_enough_acp, uu_hp_to_repair,
3434  *      for_all_material_types, um_to_repair, um_consumption_per_repair,
3435  *      has_enough_acp.
3436  */
3437 
3438 int
check_repair_action(Unit * actor,Unit * repairer,Unit * repairee)3439 check_repair_action(Unit *actor, Unit *repairer, Unit *repairee)
3440 {
3441     int rslt = A_ANY_OK;
3442 
3443     // Is the repairee in play?
3444     if (!in_play(repairee))
3445 	return A_ANY_ERROR;
3446     // Can explicit repair occur during turn?
3447     if (!at_turn_start && !valid(rslt = can_repair(actor, repairer, repairee)))
3448 	return rslt;
3449     // Can auto-repair occur at turn start?
3450     if (at_turn_start
3451 	&& !valid(rslt = can_auto_repair(repairer, repairee)))
3452 	return rslt;
3453     return A_ANY_OK;
3454 }
3455 
3456 /* Disband action. */
3457 
3458 /*!
3459  * \brief Prepare for Unit Disband Action.
3460  *
3461  * Set up to do a disband action.
3462  * The disband action destroys a unit in an "orderly" fashion, and can be
3463  * undertaken voluntarily.
3464  * \param unit is a pointer to the \Unit initiating the action.
3465  * \param disbanded is a pointer to the unit being disbanded.
3466  * \return
3467  *    - true if the action is queued;
3468  *    - false if
3469  *      - unit pointer is NULL,
3470  *      - the unit action pointer is NULL, or
3471  *      - the disbanded pointer is NULL.
3472  */
3473 int
prep_disband_action(Unit * unit,Unit * disbanded)3474 prep_disband_action(Unit *unit, Unit *disbanded)
3475 {
3476     if (unit == NULL || unit->act == NULL || disbanded == NULL)
3477       return FALSE;
3478     unit->act->nextaction.type = ACTION_DISBAND;
3479     unit->act->nextaction.actee = disbanded->id;
3480     return TRUE;
3481 }
3482 
3483 /*!
3484  * \brief Do Unit Disband Action.
3485  *
3486  * Disband the unit by:
3487  *   - distributing as much of it's supplies as possble,
3488  *   - if it has more hit points than needed to disband, recover
3489  *     as much of it's disbanding materials as possible,
3490  *   - kill the unit, and
3491  *   - use it's ACP.
3492  * \see for_all_material_types, um_supply_per_disband, distribute_material.
3493  *      hp_per_disband, for_all_material_types, um_recycleable,
3494  *      distribute_material, kill_unit, use_up_acp, u_acp_to_disband.
3495  *
3496  * \GDL
3497  *    - <A href="xcdesign.html#GDL_ref_acp-to-disband">acp-to-disband</A>
3498  *    .
3499  * \param unit is a pointer to the \Unit initiating the action.
3500  * \param disbanded is a pointer to the unit being disbanded.
3501  * \return A_ANY_OK always.
3502  */
3503 int
do_disband_action(Unit * unit,Unit * disbanded)3504 do_disband_action(Unit *unit, Unit *disbanded)
3505 {
3506     int m, amt, disb;
3507 
3508     /* Recover some percentage of the unit's supply. */
3509     for_all_material_types(m) {
3510     	if (um_supply_per_disband(disbanded->type, m) > 0 && disbanded->supply[m] > 0) {
3511     	    amt = (disbanded->supply[m] * um_supply_per_disband(disbanded->type, m)) / 100;
3512     	    /* Unit always loses the amount, whether or not distributed. */
3513     	    disbanded->supply[m] -= amt;
3514     	    distribute_material(disbanded, m, amt);
3515     	}
3516     }
3517     /* Remove hit points or kill the unit directly. */
3518     disb = u_hp_per_disband(disbanded->type);
3519     if (disb < disbanded->hp) {
3520 	disbanded->hp -= disb;
3521 	disbanded->hp2 = disbanded->hp;
3522     } else {
3523     	/* Pass around whatever we can get out of the unit itself. */
3524     	for_all_material_types(m) {
3525     	    if (um_recycleable(disbanded->type, m) > 0) {
3526     	    	distribute_material(disbanded, m, um_recycleable(disbanded->type, m));
3527     	    }
3528     	}
3529 	kill_unit(disbanded, H_UNIT_DISBANDED);
3530     }
3531     use_up_acp(unit, u_acp_to_disband(disbanded->type));
3532     return A_ANY_DONE;
3533 }
3534 
3535 /*
3536  * \brief Distribute Material to Units.
3537  *
3538  * \todo The adjacent distribution code and the ranged distribution
3539  * code are not the same.  Question: why not?  FIXME in general: why is
3540  * the algorithm here so different from run_economy?  Should
3541  * perhaps merge some of the code or at least ideas.  But I'm not
3542  * sure run_economy is quite right either in terms of making sure
3543  * that it transfers supplies rather than losing them due to
3544  * being full.
3545  * <P> Stanley M. Sutton comment.
3546  * <P> To be really accurate, this should be iterative, and
3547  * prioritorized.  If all units in range are full, the algorithym
3548  * should check to see if the full units can transfer supplies
3549  * to non-full units within their range, and so on.
3550  * Since this could use an appreciable amount of ACP if there are ACP
3551  * costs involved, it should really be solved by a global optimization
3552  * algorithm that can figure out the best way to disribute all supplies
3553  * to be distruted with the minimum outlay of ACP, perhaps limited by
3554  * available ACP, a doctrine, a plan, or a player settable value as a
3555  * percentage of the turn's available ACP, or a player setable maximem
3556  * number.
3557  * <P>Should we distribute material to other cccupants on the
3558  * same transport before checking the stack?
3559  * <P>Should we check for units inside transports on the same
3560  * cell?
3561  * \parm unit is the \Unit distributing material.
3562  * \param m is the type of material being distributed.
3563  * \param amt is the amount of material being distributed.
3564  * \see give_away, for_all_stack, unit_trusts_unit, for_all_directions,
3565  *      interior_point_in_dir,
3566  * Given a unit and a quantity of material, pass it out to nearby units.
3567  */
3568 
3569 void
distribute_material(Unit * unit,int m,int amt)3570 distribute_material(Unit *unit, int m, int amt)
3571 {
3572     int dir, x1, y1, dist;
3573     Unit *unit2;
3574 
3575     /* Distribute to transport first. */
3576     if (unit->transport != NULL) {
3577 	amt = give_away(unit->transport, m, amt);
3578 	if (unit->transport->transport != NULL) {
3579 		amt = give_away(unit->transport->transport, m, amt);
3580     	}
3581     }
3582     /* Then to any unit in the cell. */
3583     for_all_stack_with_occs(unit->x, unit->y, unit2) {
3584     	if (amt <= 0) {
3585     		break;
3586     	}
3587 	if (unit2 != unit && unit_trusts_unit(unit, unit2)) {
3588 		amt = give_away(unit2, m, amt);
3589     	}
3590     }
3591     /* Then to any unit in an adjacent cell. */
3592     for_all_directions(dir) {
3593 	if (amt <= 0) {
3594 		break;
3595 	}
3596 	if (interior_point_in_dir(unit->x, unit->y, dir, &x1, &y1)) {
3597 		for_all_stack(x1, y1, unit2) {
3598 			if (amt <= 0) {
3599 				break;
3600 			}
3601 			if (unit_trusts_unit(unit, unit2)) {
3602 				amt = give_away(unit2, m, amt);
3603 			}
3604 		}
3605 	}
3606     }
3607     /* Then to any unit within range.  This in addition to the above
3608      * code for adjacent cells because the latter does not check in-length
3609      * and out-length.
3610      */
3611 	for_all_cells_within_range(unit->x, unit->y,
3612 				   um_outlength (unit->type, m), x1, y1) {
3613 	    if (amt <= 0) {
3614 		break;
3615 	    }
3616 	    if (!inside_area(x1, y1)) {
3617 		continue;
3618 	    }
3619 	    if (!terrain_visible(unit->side, x1, y1)) {
3620 		continue;
3621 	    }
3622 	    dist = distance(unit->x, unit->y, x1, y1);
3623 	    /* Include all occupants like try_transfer_to_cell does for
3624 	       run_economy.  */
3625 	    for_all_stack_with_occs(x1, y1, unit2) {
3626 		if (amt <= 0) {
3627 			goto done;
3628 		}
3629 		if (is_active(unit2)
3630 		    && unit_trusts_unit(unit, unit2)
3631 		    && um_inlength (unit2->type, m) >= dist) {
3632 		    amt = give_away (unit2, m, amt);
3633 		}
3634 	    }
3635 	}
3636  done:;
3637 }
3638 
3639 /* Give as much as possible of the given material to the unit,
3640    return the amount left to give away. */
3641 
3642 static int
give_away(Unit * unit,int m,int amt)3643 give_away(Unit *unit, int m, int amt)
3644 {
3645     int space, add;
3646 
3647     /* We can't give away a negative amount. */
3648     if (amt <= 0) {
3649     	return amt;
3650     }
3651     space = um_storage_x(unit->type, m) - unit->supply[m];
3652     add = (amt < space ? amt : space);
3653     unit->supply[m] += add;
3654     amt -= add;
3655     if (add > 0)
3656       update_unit_display(unit->side, unit, TRUE);
3657     return amt;
3658 }
3659 
3660 int
check_disband_action(Unit * unit,Unit * disbanded)3661 check_disband_action(Unit *unit, Unit *disbanded)
3662 {
3663     int acp;
3664 
3665     if (!in_play(unit))
3666       return A_ANY_ERROR;
3667     if (!in_play(disbanded))
3668       return A_ANY_ERROR;
3669     acp = u_acp_to_disband(disbanded->type);
3670     if (acp < 1)
3671       return A_ANY_CANNOT_DO;
3672     if (u_hp_per_disband(disbanded->type) <= 0)
3673       return A_ANY_CANNOT_DO;
3674     if (!has_enough_acp(unit, acp))
3675       return A_ANY_NO_ACP;
3676     return A_ANY_OK;
3677 }
3678 
3679 /* Transfer-part action. */
3680 
3681 /* Create a new unit that is similar to the original one, and give it
3682    some of the parts of the original unit. */
3683 /* (New unit in same cell if possible or else in random adjacent cell.) */
3684 
3685 int
prep_transfer_part_action(Unit * unit,Unit * unit2,int parts,Unit * unit3)3686 prep_transfer_part_action(Unit *unit, Unit *unit2, int parts, Unit *unit3)
3687 {
3688     if (unit == NULL || unit->act == NULL || unit2 == NULL)
3689       return FALSE;
3690     unit->act->nextaction.type = ACTION_TRANSFER_PART;
3691     unit->act->nextaction.args[0] = parts;
3692     unit->act->nextaction.args[1] = (unit3 ? unit3->id : 0);
3693     unit->act->nextaction.actee = unit2->id;
3694     return TRUE;
3695 }
3696 
3697 int
do_transfer_part_action(Unit * unit,Unit * unit2,int parts,Unit * unit3)3698 do_transfer_part_action(Unit *unit, Unit *unit2, int parts, Unit *unit3)
3699 {
3700     int u2 = unit2->type, acp, part_hp;
3701 
3702     part_hp = u_hp(u2) / u_parts(u2);
3703     if (unit3 == NULL) {
3704 	/* Create a new unit with parts from unit2. */
3705 	unit3 = create_unit(u2, TRUE);
3706 	if (unit3 != NULL) {
3707 	    unit3->hp = parts * part_hp;
3708 	    /* (Cap the hp now -
3709 		occupancy calcs below might use unit parts to determine
3710 		available capacity) */
3711 	    unit3->hp = min(unit3->hp, u_hp(unit3->type));
3712 	    unit3->hp2 = unit3->hp;
3713 	    set_unit_side(unit3, unit->side);
3714 	    set_unit_origside(unit3, unit->origside);
3715 	    /* Always number the unit when first created. */
3716 	    assign_unit_number(unit3);
3717 	    /* (should fill in more slots of new unit, such as supply?) */
3718 	    if (type_can_occupy_cell(unit3->type, unit2->x, unit2->y)
3719 		&& type_survives_in_cell(unit3->type, unit2->x, unit2->y)) {
3720 	    	/* Calling type_survives_in_cell is redundant since unit3 is
3721 		    the same type as unit2, which is already in the cell,
3722 		    but we do it anyway for consistency. */
3723 		enter_cell(unit3, unit2->x, unit2->y);
3724 	    } else {
3725 	    	/* (should add code to enter something else here) */
3726 		/* This should never happen. */
3727 		run_warning(
3728 "transfer_part complications, leaving unit offworld");
3729 	    }
3730 	} else {
3731 	    /* We have a problem. */
3732 	    return A_ANY_ERROR;
3733 	}
3734     } else {
3735 	/* Increase the unit3's hp by what's in this unit, and cap it. */
3736 	add_to_unit_hp(unit3, parts * part_hp);
3737     }
3738     /* Tweak parts in unit2 also. */
3739     if (parts * part_hp >= unit2->hp) {
3740 	/* (should transfer occs, supply, etc to unit3) */
3741 	kill_unit(unit2, H_UNIT_MERGED);
3742     } else {
3743 	unit2->hp -= parts * part_hp;
3744 	unit2->hp2 = unit2->hp;
3745     }
3746     if (alive(unit2))
3747       update_unit_display(unit2->side, unit2, TRUE);
3748     update_unit_display(unit3->side, unit3, TRUE);
3749     acp = u_acp_to_transfer_part(u2);
3750     use_up_acp(unit, acp);
3751     return A_ANY_DONE;
3752 }
3753 
3754 int
check_transfer_part_action(Unit * unit,Unit * unit2,int parts,Unit * unit3)3755 check_transfer_part_action(Unit *unit, Unit *unit2, int parts, Unit *unit3)
3756 {
3757     int u2, acp;
3758 
3759     if (!in_play(unit))
3760       return A_ANY_ERROR;
3761     if (!in_play(unit2))
3762       return A_ANY_ERROR;
3763     if (parts <= 0)
3764       return A_ANY_ERROR;
3765     /* unit3 can be NULL, which implies an unit it to be detached. */
3766     u2 = unit2->type;
3767     /* If unit3 is not NULL, then we need to check to make sure that it
3768 	is compatible with the donor unit. */
3769     if (unit3 &&
3770 	((u_parts(unit3->type) <= 0)
3771 	 || !uu_can_transfer_parts_to(u2, unit3->type)))
3772       return A_ANY_CANNOT_DO;
3773     acp = u_acp_to_transfer_part(u2);
3774     /* Check if type is allowed and if needed tech & advances exist. */
3775     if (!side_can_build(unit->side, u2))
3776       return A_ANY_CANNOT_DO;
3777     /* Check if we hit a limit on the number of units. */
3778     if (!new_unit_allowed_on_side(u2, unit->side))
3779       return A_ANY_CANNOT_DO;
3780     if (!can_have_enough_acp(unit, acp))
3781       return A_ANY_CANNOT_DO;
3782     if (u_parts(u2) <= 1)
3783       return A_ANY_ERROR;
3784     if (!has_enough_acp(unit, acp))
3785       return A_ANY_NO_ACP;
3786     return A_ANY_OK;
3787 }
3788 
3789 /* Change-type action. */
3790 
3791 int
prep_change_type_action(Unit * unit,Unit * unit2,int u3)3792 prep_change_type_action(Unit *unit, Unit *unit2, int u3)
3793 {
3794     if (unit == NULL || unit->act == NULL || unit2 == NULL)
3795       return FALSE;
3796     unit->act->nextaction.type = ACTION_CHANGE_TYPE;
3797     unit->act->nextaction.args[0] = u3;
3798     unit->act->nextaction.actee = unit2->id;
3799     return TRUE;
3800 }
3801 
3802 /* Actually change the type of a unit. */
3803 
3804 int
do_change_type_action(Unit * unit,Unit * unit2,int u3)3805 do_change_type_action(Unit *unit, Unit *unit2, int u3)
3806 {
3807     int u, u2;
3808     int acpdebt = 0;
3809 
3810     u = unit->type;  u2 = unit2->type;
3811     acpdebt = uu_acp_to_change_type(u2, u3);
3812     change_unit_type(unit2, u3, H_UNIT_TYPE_CHANGED, NULL);
3813     update_unit_display(unit2->side, unit2, TRUE);
3814     if (!acp_indep(unit) && unit->act) {
3815 	if (type_acp_max(u) > 0)
3816 	  acpdebt = (acpdebt * type_acp_max(u3)) / type_acp_max(u);
3817 	else
3818 	  acpdebt = 0;
3819 	use_up_acp(unit, min(acpdebt, unit->act->acp - u_acp_min(u3)));
3820     }
3821     return A_ANY_DONE;
3822 }
3823 
3824 //! Check the 'change-type' action.
3825 /*!
3826     Arbiter Function.
3827 */
3828 
3829 int
check_change_type_action(Unit * unit,Unit * unit2,int u3)3830 check_change_type_action(Unit *unit, Unit *unit2, int u3)
3831 {
3832     int rslt = A_ANY_OK;
3833 
3834     assert_return(in_play(unit), A_ANY_ERROR);
3835     assert_return(in_play(unit2), A_ANY_ERROR);
3836     assert_return(is_unit_type(u3), A_ANY_ERROR);
3837     if (!valid(rslt = can_change_type_to(unit, unit2, u3)))
3838       return rslt;
3839     return A_ANY_OK;
3840 }
3841 
3842 /* Change-side action. */
3843 
3844 /* Tell a unit to change to a given side. */
3845 
3846 /* (what about occs, garrisons, plans?) */
3847 
3848 int
prep_change_side_action(Unit * unit,Unit * unit2,Side * side)3849 prep_change_side_action(Unit *unit, Unit *unit2, Side *side)
3850 {
3851     if (unit == NULL || unit->act == NULL || unit2 == NULL)
3852       return FALSE;
3853     unit->act->nextaction.type = ACTION_CHANGE_SIDE;
3854     unit->act->nextaction.args[0] = side_number(side);
3855     unit->act->nextaction.actee = unit2->id;
3856     return TRUE;
3857 }
3858 
3859 int
do_change_side_action(Unit * unit,Unit * unit2,Side * side)3860 do_change_side_action(Unit *unit, Unit *unit2, Side *side)
3861 {
3862     int rslt;
3863 
3864     if (side_controls_unit(unit->side, unit2)) {
3865 	/* If we own it, we can just change it. */
3866 	change_unit_side(unit2, side, H_UNIT_ACQUIRED, NULL);
3867 	rslt = A_ANY_DONE;
3868     } else {
3869 	rslt = A_ANY_ERROR;
3870     }
3871     use_up_acp(unit, u_acp_to_change_side(unit2->type));
3872     return rslt;
3873 }
3874 
3875 int
check_change_side_action(Unit * unit,Unit * unit2,Side * side)3876 check_change_side_action(Unit *unit, Unit *unit2, Side *side)
3877 {
3878     int u, u2, acp;
3879 
3880     if (!in_play(unit))
3881       return A_ANY_ERROR;
3882     if (!in_play(unit2))
3883       return A_ANY_ERROR;
3884     if (!side_in_play(side))
3885       return A_ANY_ERROR;
3886     if (unit2->side == side)
3887       return A_ANY_ERROR;
3888     if (!unit_allowed_on_side(unit2, side))
3889       return A_ANY_ERROR;
3890     u = unit->type;  u2 = unit2->type;
3891     acp = u_acp_to_change_side(u2);
3892     if (acp < 1)
3893       return A_ANY_CANNOT_DO;
3894     if (!can_have_enough_acp(unit, acp))
3895       return A_ANY_CANNOT_DO;
3896     if (!has_enough_acp(unit, acp))
3897       return A_ANY_NO_ACP;
3898     return A_ANY_OK;
3899 }
3900 
3901 /* Alter-terrain action. */
3902 
3903 /* Change the terrain in the cell to something else. */
3904 
3905 /* We don't need to ensure that the unit can exist on the new terrain
3906    type, because the designer is presumed to have set things up sensibly,
3907    because the unit might be in an appropriate transport, or because
3908    there is some actual use in such a bizarre shtick. */
3909 
3910 /* What if engineers dig hole underneath enemy unit?  Should this be
3911    possible, or should there be a "can-dig-under-enemy" parm?  */
3912 
3913 int
prep_alter_cell_action(Unit * unit,Unit * unit2,int x,int y,int t)3914 prep_alter_cell_action(Unit *unit, Unit *unit2, int x, int y, int t)
3915 {
3916     if (unit == NULL || unit->act == NULL || unit2 == NULL)
3917       return FALSE;
3918     unit->act->nextaction.type = ACTION_ALTER_TERRAIN;
3919     unit->act->nextaction.args[0] = x;
3920     unit->act->nextaction.args[1] = y;
3921     unit->act->nextaction.args[2] = t;
3922     unit->act->nextaction.actee = unit2->id;
3923     return TRUE;
3924 }
3925 
3926 int
do_alter_cell_action(Unit * unit,Unit * unit2,int x,int y,int t)3927 do_alter_cell_action(Unit *unit, Unit *unit2, int x, int y, int t)
3928 {
3929     int u, u2, oldt, acpr, acpa, m, amt, excess, space;
3930 
3931     u = unit->type;  u2 = unit2->type;
3932     oldt = terrain_at(x, y);
3933     /* Change the terrain to the new type. */
3934     change_terrain_type(x, y, t);
3935     for_all_material_types(m) {
3936 	amt = tm_material_per_remove_terrain(oldt, m) - tm_consumption_per_add_terrain(t, m);
3937 	space = um_storage_x(unit2->type, m) - unit2->supply[m];
3938     	/* First fill up unit2 as far as there is room. */
3939 	unit2->supply[m] += min(amt, space);
3940 	/* Compute the excess we couldn't store. */
3941 	excess = amt - space;
3942 	/* Try to give away the same amount to make room for the excess. */
3943 	if (excess > 0) {
3944 	    /* But first clip it to available supplies. */
3945 	    excess = min(excess, unit2->supply[m]);
3946 	    unit2->supply[m] -= excess;
3947 	    distribute_material(unit2, m, excess);
3948 	}
3949     }
3950     /* Then try to fill up unit2 again with the remaining excess. */
3951     space = um_storage_x(unit2->type, m) - unit2->supply[m];
3952     /* The check for available space is redundant now, but will be needed
3953     in the future when distribute_material has been improved. */
3954     unit2->supply[m] += min(excess, space);
3955 
3956     /* Note that we still charge acp even if terrain type doesn't change. */
3957     acpr = ut_acp_to_remove_terrain(u2, oldt);
3958     acpa = ut_acp_to_add_terrain(u2, t);
3959     use_up_acp(unit, acpr + acpa);
3960     return A_ANY_DONE;
3961 }
3962 
3963 int
check_alter_cell_action(Unit * unit,Unit * unit2,int x,int y,int t)3964 check_alter_cell_action(Unit *unit, Unit *unit2, int x, int y, int t)
3965 {
3966     int u, u2, m, oldt, acpr, acpa;
3967 
3968     if (!in_play(unit))
3969       return A_ANY_ERROR;
3970     if (!in_play(unit2))
3971       return A_ANY_ERROR;
3972     if (!in_area(x, y))
3973       return A_ANY_ERROR;
3974     if (!is_terrain_type(t))
3975       return A_ANY_ERROR;
3976     if (!t_is_cell(t))
3977       return A_ANY_ERROR;
3978     u = unit->type;  u2 = unit2->type;
3979     oldt = terrain_at(x, y);
3980     acpr = ut_acp_to_remove_terrain(u2, oldt);
3981     acpa = ut_acp_to_add_terrain(u2, t);
3982     if (acpr < 1 || acpa < 1)
3983       return A_ANY_CANNOT_DO;
3984     if (!can_have_enough_acp(unit, acpr + acpa))
3985       return A_ANY_CANNOT_DO;
3986     if (distance(unit2->x, unit2->y, x, y) > ut_alter_range(u2, t))
3987       return A_ANY_ERROR;
3988     if (!has_enough_acp(unit, acpr + acpa))
3989       return A_ANY_NO_ACP;
3990     /* We have to have a minimum level of supply to be able to do the
3991        action. */
3992     for_all_material_types(m) {
3993 	if (unit2->supply[m] < um_to_remove_terrain(u2, m))
3994 	  return A_ANY_NO_MATERIAL;
3995 	if (unit2->supply[m] < um_to_add_terrain(u2, m))
3996 	  return A_ANY_NO_MATERIAL;
3997 	if (unit2->supply[m] < (tm_consumption_per_add_terrain(t, m) - tm_material_per_remove_terrain(oldt, m)))
3998 	  return A_ANY_NO_MATERIAL;
3999     }
4000     return A_ANY_OK;
4001 }
4002 
4003 /* Add-terrain action. */
4004 
4005 /* Add terrain; border, connection, or coating. */
4006 
4007 int
prep_add_terrain_action(Unit * unit,Unit * unit2,int x,int y,int dir,int t)4008 prep_add_terrain_action(Unit *unit, Unit *unit2, int x, int y, int dir, int t)
4009 {
4010     if (unit == NULL || unit->act == NULL || unit2 == NULL)
4011       return FALSE;
4012     unit->act->nextaction.type = ACTION_ADD_TERRAIN;
4013     unit->act->nextaction.args[0] = x;
4014     unit->act->nextaction.args[1] = y;
4015     unit->act->nextaction.args[2] = dir;
4016     unit->act->nextaction.args[3] = t;
4017     unit->act->nextaction.actee = unit2->id;
4018     return TRUE;
4019 }
4020 
4021 int
do_add_terrain_action(Unit * unit,Unit * unit2,int x,int y,int dir,int t)4022 do_add_terrain_action(Unit *unit, Unit *unit2, int x, int y, int dir, int t)
4023 {
4024     int u = unit->type, oldval, newval, m, amt;
4025     Side *side;
4026 
4027     switch (t_subtype(t)) {
4028       case cellsubtype:
4029       	/* Will never happen. */
4030       	break;
4031       case bordersubtype:
4032       	oldval = border_at(x, y, dir, t);
4033       	newval = TRUE;
4034 	set_border_at(x, y, dir, t, newval);
4035       	break;
4036       case connectionsubtype:
4037       	oldval = connection_at(x, y, dir, t);
4038       	newval = TRUE;
4039 	set_connection_at(x, y, dir, t, newval);
4040       	break;
4041       case coatingsubtype:
4042     	oldval = aux_terrain_at(x, y, t);
4043       	/* Interpret "dir" as depth of coating to add. */
4044     	newval = min(oldval + dir, tt_coat_max(terrain_at(x, y), t));
4045     	set_aux_terrain_at(x, y, t, newval);
4046       	break;
4047     }
4048     /* Consume any material necessary to the action. */
4049     for_all_material_types(m) {
4050 	amt = tm_consumption_per_add_terrain(t, m);
4051         if (side_has_treasury(unit2->side, m)
4052 	    && um_takes_from_treasury(unit2->type, m)
4053 	    && (amt > unit2->supply[m])) {
4054 	    amt -= unit2->supply[m];
4055 	    unit2->supply[m] = 0;
4056 	    unit2->side->treasury[m] -= amt;
4057 	} else
4058 	    unit2->supply[m] -= amt;
4059     }
4060     /* Let everybody see what has happened. */
4061     for_all_sides(side) {
4062 	if (active_display(side)) {
4063 	    if (terrain_visible(side, x, y))
4064 	      update_cell_display(side, x, y, UPDATE_ALWAYS | UPDATE_ADJ);
4065     	}
4066     }
4067     use_up_acp(unit, (newval != oldval ? ut_acp_to_add_terrain(u, t) : 1));
4068     return A_ANY_DONE;
4069 }
4070 
4071 int
check_add_terrain_action(Unit * unit,Unit * unit2,int x,int y,int dir,int t)4072 check_add_terrain_action(Unit *unit, Unit *unit2, int x, int y, int dir, int t)
4073 {
4074     int u, u2, m, acp, treas;
4075 
4076     if (!in_play(unit))
4077       return A_ANY_ERROR;
4078     if (!in_play(unit2))
4079       return A_ANY_ERROR;
4080     if (!inside_area(x, y))
4081       return A_ANY_ERROR;
4082     if (!between(0, dir, NUMDIRS - 1))
4083       return A_ANY_ERROR;
4084     if (!is_terrain_type(t))
4085       return A_ANY_ERROR;
4086     if (t_is_cell(t))
4087       return A_ANY_ERROR;
4088     u = unit->type;  u2 = unit2->type;
4089     acp = ut_acp_to_add_terrain(u2, t);
4090     if (acp < 1)
4091       return A_ANY_CANNOT_DO;
4092      if (!can_have_enough_acp(unit, acp))
4093        return A_ANY_CANNOT_DO;
4094    if (distance(unit->x, unit->y, x, y) > ut_alter_range(u2, t))
4095       return A_ANY_TOO_FAR;
4096     if (!has_enough_acp(unit, acp))
4097       return A_ANY_NO_ACP;
4098     /* We have to have certain amounts supply to be able to do the action. */
4099     for_all_material_types(m) {
4100 	if (unit2->supply[m] < um_to_add_terrain(u2, m))
4101 	  return A_ANY_NO_MATERIAL;
4102         if (side_has_treasury(unit2->side, m)
4103 	    && um_takes_from_treasury(u2, m))
4104 	    treas = unit2->side->treasury[m];
4105         else
4106 	    treas = 0;
4107 	if ((unit2->supply[m] + treas) < tm_consumption_per_add_terrain(t, m))
4108 	  return A_ANY_NO_MATERIAL;
4109     }
4110     return A_ANY_OK;
4111 }
4112 
4113 /* Remove-terrain action. */
4114 
4115 /* Remove a border, connection, or coating. */
4116 
4117 int
prep_remove_terrain_action(Unit * unit,Unit * unit2,int x,int y,int dir,int t)4118 prep_remove_terrain_action(Unit *unit, Unit *unit2, int x, int y, int dir, int t)
4119 {
4120     if (unit == NULL || unit->act == NULL || unit2 == NULL)
4121       return FALSE;
4122     unit->act->nextaction.type = ACTION_REMOVE_TERRAIN;
4123     unit->act->nextaction.args[0] = x;
4124     unit->act->nextaction.args[1] = y;
4125     unit->act->nextaction.args[2] = dir;
4126     unit->act->nextaction.args[3] = t;
4127     unit->act->nextaction.actee = unit2->id;
4128     return TRUE;
4129 }
4130 
4131 int
do_remove_terrain_action(Unit * unit,Unit * unit2,int x,int y,int dir,int t)4132 do_remove_terrain_action(Unit *unit, Unit *unit2, int x, int y, int dir, int t)
4133 {
4134     int u = unit->type, oldval, newval, m, amt, excess, space;
4135     Side *side;
4136 
4137     switch (t_subtype(t)) {
4138       case cellsubtype:
4139       	/* Will never happen. */
4140       	break;
4141       case bordersubtype:
4142 	oldval = border_at(x, y, dir, t);
4143 	newval = FALSE;
4144 	set_border_at(x, y, dir, t, newval);
4145       	break;
4146       case connectionsubtype:
4147 	oldval = connection_at(x, y, dir, t);
4148 	newval = FALSE;
4149 	set_connection_at(x, y, dir, t, newval);
4150       	break;
4151       case coatingsubtype:
4152     	oldval = aux_terrain_at(x, y, t);
4153        	/* Interpret "dir" as depth of coating to remove. */
4154    	newval = max(oldval - dir, 0);
4155    	/* If newval drops below the min coating depth, coating will vanish. */
4156     	if (newval < tt_coat_min(terrain_at(x, y), t))
4157     	  newval = 0;
4158     	set_aux_terrain_at(x, y, t, newval);
4159       	break;
4160     }
4161     for_all_material_types(m) {
4162 	amt = tm_material_per_remove_terrain(t, m);
4163 	space = um_storage_x(unit2->type, m) - unit2->supply[m];
4164     	/* First fill up unit2 as far as there is room. */
4165 	unit2->supply[m] += min(amt, space);
4166 	/* Compute the excess we couldn't store. */
4167 	excess = amt - space;
4168 	/* Try to give away the same amount to make room for the excess. */
4169 	if (excess > 0) {
4170 	    /* But first clip it to available supplies. */
4171 	    excess = min(excess, unit2->supply[m]);
4172 	    unit2->supply[m] -= excess;
4173 	    distribute_material(unit2, m, excess);
4174 	}
4175     }
4176     /* Then try to fill up unit2 again with the remaining excess. */
4177     space = um_storage_x(unit2->type, m) - unit2->supply[m];
4178     /* The check for available space is redundant now, but will be needed
4179     in the future when distribute_material has been improved. */
4180     unit2->supply[m] += min(excess, space);
4181 
4182     /* Let everybody see what has happened. */
4183     for_all_sides(side) {
4184 	if (active_display(side)) {
4185 	    if (terrain_visible(side, x, y))
4186 	      update_cell_display(side, x, y, UPDATE_ALWAYS | UPDATE_ADJ);
4187     	}
4188     }
4189     use_up_acp(unit, (newval != oldval ? ut_acp_to_remove_terrain(u, t) : 1));
4190     return A_ANY_DONE;
4191 }
4192 
4193 int
check_remove_terrain_action(Unit * unit,Unit * unit2,int x,int y,int dir,int t)4194 check_remove_terrain_action(Unit *unit, Unit *unit2, int x, int y, int dir, int t)
4195 {
4196     int u, u2, m, acp;
4197 
4198     if (!in_play(unit))
4199       return A_ANY_ERROR;
4200     if (!in_play(unit2))
4201       return A_ANY_ERROR;
4202     if (!inside_area(x, y))
4203       return A_ANY_ERROR;
4204     if (!between(0, dir, NUMDIRS - 1))
4205       return A_ANY_ERROR;
4206     if (!is_terrain_type(t))
4207       return A_ANY_ERROR;
4208     if (t_is_cell(t))
4209       return A_ANY_ERROR;
4210     u = unit->type;  u2 = unit2->type;
4211     acp = ut_acp_to_remove_terrain(u2, t);
4212     if (acp < 1)
4213       return A_ANY_CANNOT_DO;
4214     if (!can_have_enough_acp(unit, acp))
4215       return A_ANY_CANNOT_DO;
4216     if (distance(unit->x, unit->y, x, y) > ut_alter_range(u2, t))
4217       return A_ANY_TOO_FAR;
4218     if (!has_enough_acp(unit, acp))
4219       return A_ANY_NO_ACP;
4220     /* We have to have a minimum level of supply to be able to do the
4221        action. */
4222     for_all_material_types(m) {
4223 	if (unit2->supply[m] < um_to_remove_terrain(u2, m))
4224 	  return A_ANY_NO_MATERIAL;
4225     }
4226     return A_ANY_OK;
4227 }
4228 
4229 //! Should action movies be played?
4230 /*! \note Stupid hack. */
4231 
4232 int
should_play_movies(void)4233 should_play_movies(void)
4234 {
4235     Side *side = NULL;
4236 
4237     for_all_sides(side) {
4238 	if (side == indepside)
4239 	  continue;
4240 	if (!side_has_ai(side))
4241 	  return TRUE;
4242     }
4243     return FALSE;
4244 }
4245 
4246 /* Execute a given action on a given unit. */
4247 
4248 /* (assumes unit can act in the first place - valid?) */
4249 
4250 int
execute_action(Unit * unit,Action * action)4251 execute_action(Unit *unit, Action *action)
4252 {
4253     char *argtypestr;
4254     int u = unit->type, rslt = A_ANY_ERROR, n, i, a[4];
4255     Unit *unit2, *aunits[4];
4256     Side *asides[4];
4257     extern int numsoundplays;
4258 
4259     Dprintf("%s doing %s with %d acp left\n",
4260 	    unit_desig(unit), action_desig(action), unit->act->acp);
4261 
4262     if (!alive(unit) || !unit->act || unit->act->acp < u_acp_min(u))
4263       return A_ANY_ERROR;
4264 
4265     argtypestr = actiondefns[(int) action->type].argtypes;
4266     n = strlen(argtypestr);
4267     for (i = 0; i < n; ++i) {
4268 	switch (argtypestr[i]) {
4269 	  case 'n':
4270 	  case 'u':
4271 	  case 'm':
4272 	  case 't':
4273 	  case 'x':
4274 	  case 'y':
4275 	  case 'z':
4276 	  case 'd':
4277 	    a[i] = action->args[i];
4278 	    break;
4279 	  case 'U':
4280 	    aunits[i] = find_unit(action->args[i]);
4281 	    /* It may be that the argunit cannot be found - perhaps the
4282 	       unit died before the action could be applied to it.  In any
4283 	       case, let the per-action code handle the case. */
4284 	    break;
4285 	  case 'S':
4286 	    asides[i] = side_n(action->args[i]);
4287 	    if (asides[i] == NULL)
4288 	      asides[i] = indepside;
4289 	    break;
4290 	  default:
4291 	    case_panic("action argument type", argtypestr[i]);
4292 	    break;
4293 	}
4294     }
4295     if (action->actee == 0) {
4296 	unit2 = unit;
4297     } else {
4298 	unit2 = find_unit(action->actee);
4299     }
4300     if (unit2 == NULL) {
4301 	return A_ANY_ERROR;
4302     }
4303     switch (actiondefns[(int) action->type].typecode) {
4304       case ACTION_NONE:
4305 	rslt = check_none_action(unit, unit2);
4306 	break;
4307       case ACTION_MOVE:
4308 	rslt = check_move_action(unit, unit2, a[0], a[1], a[2]);
4309 	break;
4310       case ACTION_ENTER:
4311 	rslt = check_enter_action(unit, unit2, aunits[0]);
4312 	break;
4313       case ACTION_ATTACK:
4314 	rslt = check_attack_action(unit, unit2, aunits[0], a[1]);
4315 	break;
4316       case ACTION_OVERRUN:
4317 	rslt = check_overrun_action(unit, unit2, a[0], a[1], a[2], a[3]);
4318 	break;
4319       case ACTION_FIRE_AT:
4320 	rslt = check_fire_at_action(unit, unit2, aunits[0], a[1]);
4321 	break;
4322       case ACTION_FIRE_INTO:
4323 	rslt = check_fire_into_action(unit, unit2, a[0], a[1], a[2], a[3]);
4324 	break;
4325       case ACTION_CAPTURE:
4326 	rslt = check_capture_action(unit, unit2, aunits[0]);
4327 	break;
4328       case ACTION_DETONATE:
4329 	rslt = check_detonate_action(unit, unit2, a[0], a[1], a[2]);
4330 	break;
4331       case ACTION_PRODUCE:
4332 	rslt = check_produce_action(unit, unit2, a[0], a[1]);
4333 	break;
4334       case ACTION_EXTRACT:
4335 	rslt = check_extract_action(unit, unit2, a[0], a[1], a[2], a[3]);
4336 	break;
4337       case ACTION_TRANSFER:
4338 	rslt = check_transfer_action(unit, unit2, a[0], a[1], aunits[2]);
4339 	break;
4340       case ACTION_DEVELOP:
4341 	rslt = check_develop_action(unit, unit2, a[0]);
4342 	break;
4343       case ACTION_TOOL_UP:
4344 	rslt = check_toolup_action(unit, unit2, a[0]);
4345 	break;
4346       case ACTION_CREATE_IN:
4347 	rslt = check_create_in_action(unit, unit2, a[0], aunits[1]);
4348 	break;
4349       case ACTION_CREATE_AT:
4350 	rslt = check_create_at_action(unit, unit2, a[0], a[1], a[2], a[3]);
4351 	break;
4352       case ACTION_BUILD:
4353 	rslt = check_build_action(unit, unit2, aunits[0]);
4354 	break;
4355       case ACTION_REPAIR:
4356 	rslt = check_repair_action(unit, unit2, aunits[0]);
4357 	break;
4358       case ACTION_DISBAND:
4359 	rslt = check_disband_action(unit, unit2);
4360 	break;
4361       case ACTION_TRANSFER_PART:
4362 	rslt = check_transfer_part_action(unit, unit2, a[0], aunits[1]);
4363 	break;
4364       case ACTION_CHANGE_TYPE:
4365 	rslt = check_change_type_action(unit, unit2, a[0]);
4366 	break;
4367       case ACTION_CHANGE_SIDE:
4368 	rslt = check_change_side_action(unit, unit2, asides[0]);
4369 	break;
4370       case ACTION_ALTER_TERRAIN:
4371 	rslt = check_alter_cell_action(unit, unit2, a[0], a[1], a[2]);
4372 	break;
4373       case ACTION_ADD_TERRAIN:
4374 	rslt = check_add_terrain_action(unit, unit2, a[0], a[1], a[2], a[3]);
4375 	break;
4376       case ACTION_REMOVE_TERRAIN:
4377 	rslt = check_remove_terrain_action(unit, unit2, a[0], a[1], a[2], a[3]);
4378 	break;
4379       case NUMACTIONTYPES:
4380 	/* should be error */
4381 	break;
4382     }
4383     numsoundplays = 0; /* kind of a hack */
4384     if (!valid(rslt)) {
4385 	if (unit->plan) {
4386 	    unit->plan->lastaction = *action;
4387 	    unit->plan->lastresult = rslt;
4388 	}
4389 	Dprintf("%s action %s can't be done, result is %s\n",
4390 		unit_desig(unit), action_desig(action), hevtdefns[rslt].name);
4391 	return rslt;
4392     }
4393     if (g_action_notices() != lispnil)
4394       notify_action(unit, action);
4395     if (g_action_movies() != lispnil)
4396       play_action_movies(unit, action);
4397     switch (actiondefns[(int) action->type].typecode) {
4398       case ACTION_NONE:
4399 	rslt = do_none_action(unit, unit2);
4400 	break;
4401       case ACTION_MOVE:
4402 	rslt = do_move_action(unit, unit2, a[0], a[1], a[2]);
4403 	break;
4404       case ACTION_ENTER:
4405 	rslt = do_enter_action(unit, unit2, aunits[0]);
4406 	break;
4407       case ACTION_ATTACK:
4408 	rslt = do_attack_action(unit, unit2, aunits[0], a[1]);
4409 	break;
4410       case ACTION_OVERRUN:
4411 	rslt = do_overrun_action(unit, unit2, a[0], a[1], a[2], a[3]);
4412 	break;
4413       case ACTION_FIRE_AT:
4414 	rslt = do_fire_at_action(unit, unit2, aunits[0], a[1]);
4415 	break;
4416       case ACTION_FIRE_INTO:
4417 	rslt = do_fire_into_action(unit, unit2, a[0], a[1], a[2], a[3]);
4418 	break;
4419       case ACTION_CAPTURE:
4420 	rslt = do_capture_action(unit, unit2, aunits[0]);
4421 	break;
4422       case ACTION_DETONATE:
4423 	rslt = do_detonate_action(unit, unit2, a[0], a[1], a[2]);
4424 	break;
4425       case ACTION_PRODUCE:
4426 	rslt = do_produce_action(unit, unit2, a[0], a[1]);
4427 	break;
4428       case ACTION_EXTRACT:
4429 	rslt = do_extract_action(unit, unit2, a[0], a[1], a[2], a[3]);
4430 	break;
4431       case ACTION_TRANSFER:
4432 	rslt = do_transfer_action(unit, unit2, a[0], a[1], aunits[2]);
4433 	break;
4434       case ACTION_DEVELOP:
4435 	rslt = do_develop_action(unit, unit2, a[0]);
4436 	break;
4437       case ACTION_TOOL_UP:
4438 	rslt = do_toolup_action(unit, unit2, a[0]);
4439 	break;
4440       case ACTION_CREATE_IN:
4441 	rslt = do_create_in_action(unit, unit2, a[0], aunits[1]);
4442 	break;
4443       case ACTION_CREATE_AT:
4444 	rslt = do_create_at_action(unit, unit2, a[0], a[1], a[2], a[3]);
4445 	break;
4446       case ACTION_BUILD:
4447 	rslt = do_build_action(unit, unit2, aunits[0]);
4448 	break;
4449       case ACTION_REPAIR:
4450 	rslt = do_repair_action(unit, unit2, aunits[0]);
4451 	break;
4452       case ACTION_DISBAND:
4453 	rslt = do_disband_action(unit, unit2);
4454 	break;
4455       case ACTION_TRANSFER_PART:
4456 	rslt = do_transfer_part_action(unit, unit2, a[0], aunits[1]);
4457 	break;
4458       case ACTION_CHANGE_TYPE:
4459 	rslt = do_change_type_action(unit, unit2, a[0]);
4460 	break;
4461       case ACTION_CHANGE_SIDE:
4462 	rslt = do_change_side_action(unit, unit2, asides[0]);
4463 	break;
4464       case ACTION_ALTER_TERRAIN:
4465 	rslt = do_alter_cell_action(unit, unit2, a[0], a[1], a[2]);
4466 	break;
4467       case ACTION_ADD_TERRAIN:
4468 	rslt = do_add_terrain_action(unit, unit2, a[0], a[1], a[2], a[3]);
4469 	break;
4470       case ACTION_REMOVE_TERRAIN:
4471 	rslt = do_remove_terrain_action(unit, unit2, a[0], a[1], a[2], a[3]);
4472 	break;
4473       case NUMACTIONTYPES:
4474 	/* should be error */
4475 	break;
4476     }
4477     /* The action may have been blasted if the unit was wrecked,
4478     so we use latest_action instead. */
4479     Dprintf("%s action %s result is %s, %d acp left\n",
4480 	    unit_desig(unit), action_desig(latest_action), hevtdefns[rslt].name,
4481 	    (unit->act ? unit->act->acp : -9999));
4482     /* Not sure what to do if the action was blasted, so we also test
4483     that it still exists. In reality act and plan are blasted together,
4484     so this test may be redundant. Note: using latest_action will not
4485     work here since it changes all the time. */
4486     if (unit->plan
4487         && unit->act) {
4488 	unit->plan->lastaction = *action;
4489 	unit->plan->lastresult = rslt;
4490     }
4491     /* Report the result to the unit's owner. */
4492     if (unit->side && side_has_display(unit->side)) {
4493 	update_action_result_display(unit->side, unit, rslt, TRUE);
4494     }
4495     /* Show other sides that some action has occurred. */
4496     update_side_display_all_sides(unit->side, TRUE);
4497 #if 0 /* doesn't do anything yet */
4498     /* If of a type that might be spotted if it does anything, check
4499        each side to see if they notice.  Note that the type is from
4500        *before* the action, not after (some actions may cause type
4501        changes). */
4502     if (u_spot_action(u)
4503 	&& !g_see_all()
4504 	&& !u_see_always(u)
4505 	&& in_area(unit->x, unit->y)) {
4506 	Side *side2;
4507 	for_all_sides(side2) {
4508 	    if (cover(side2, unit->x, unit->y) > 0) {
4509 		/* (should call some sort of "glimpsing" routine) */
4510 	    }
4511 	}
4512     }
4513 #endif
4514     /* Check on any scorekeepers that run after each action.  Note
4515        that one or more sides may be out of the game after this
4516        returns. */
4517     if (any_post_action_scores)
4518       check_post_action_scores();
4519     /* Return success/failure so caller can use. */
4520     return rslt;
4521 }
4522 
4523 static int pattern_matches_action(Obj *pattern, Unit *unit, Action *action);
4524 static void action_desc_from_list(Side *side, Obj *lis, Unit *unit, Action *action, char *buf);
4525 
4526 static void
notify_action(Unit * unit,Action * action)4527 notify_action(Unit *unit, Action *action)
4528 {
4529     int found = FALSE;
4530     char *atypename, abuf[BUFSIZE];
4531     Obj *rest, *head, *pat, *msgdesc;
4532 
4533     atypename = actiondefns[(int) action->type].name;
4534     for_all_list(g_action_notices(), rest) {
4535 	head = car(rest);
4536 	if (!consp(head)) {
4537 	    run_warning("Non-list in action-notices");
4538 	    continue;
4539 	}
4540 	pat = car(head);
4541 	if (symbolp(pat) && strcmp(c_string(pat), atypename) == 0) {
4542 	    found = TRUE;
4543 	    break;
4544 	}
4545 	if (consp(pat)
4546 	    && symbolp(car(pat))
4547 	    && strcmp(c_string(car(pat)), atypename) == 0
4548 	    && pattern_matches_action(cdr(pat), unit, action)) {
4549 	    found = TRUE;
4550 	    break;
4551 	}
4552     }
4553     /* If we have a match, do something with it. */
4554     if (found) {
4555 	msgdesc = cadr(head);
4556 	if (stringp(msgdesc)) {
4557 	    strcpy(abuf, c_string(msgdesc));
4558 	} else {
4559 	    action_desc_from_list(unit->side, msgdesc, unit, action, abuf);
4560 	}
4561 	notify(unit->side, "%s", abuf);
4562     }
4563 }
4564 
4565 static int
pattern_matches_action(Obj * parms,Unit * unit,Action * action)4566 pattern_matches_action(Obj *parms, Unit *unit, Action *action)
4567 {
4568     Obj *head;
4569     Unit *actee;
4570 
4571     head = car(parms);
4572     if (!(symbolp(head) && strcmp(c_string(head), u_type_name(unit->type)) == 0)
4573 	 || match_keyword(head, K_USTAR)
4574 	 || (symbolp(head)
4575 	     && boundp(head)
4576 	     && ((symbolp(symbol_value(head))
4577 	          && strcmp(c_string(symbol_value(head)), u_type_name(unit->type)) == 0)
4578 	         || (numberp(symbol_value(head))
4579 	             && c_number(symbol_value(head)) == unit->type))))
4580       return FALSE;
4581     parms = cdr(parms);
4582     head = car(parms);
4583     if (action->actee == unit->id)
4584       actee = unit;
4585     else
4586       actee = find_unit(action->actee);
4587     if (!(symbolp(head) && strcmp(c_string(head), u_type_name(actee->type)) == 0)
4588 	 || match_keyword(head, K_USTAR)
4589 	 || (symbolp(head)
4590 	     && boundp(head)
4591 	     && ((symbolp(symbol_value(head))
4592 	          && strcmp(c_string(symbol_value(head)), u_type_name(actee->type)) == 0)
4593 	         || (numberp(symbol_value(head))
4594 	             && c_number(symbol_value(head)) == actee->type))))
4595       return FALSE;
4596     /* (should test result also) */
4597     return TRUE;
4598 }
4599 
4600 static void
action_desc_from_list(Side * side,Obj * lis,Unit * unit,Action * action,char * buf)4601 action_desc_from_list(Side *side, Obj *lis, Unit *unit, Action *action,
4602 		      char *buf)
4603 {
4604     int n;
4605     char *symname;
4606     Obj *rest, *item;
4607     Unit *actee;
4608 
4609     buf[0] = '\0';
4610     for_all_list(lis, rest) {
4611 	item = car(rest);
4612 	if (stringp(item)) {
4613 	    strcat(buf, c_string(item));
4614 	} else if (symbolp(item)) {
4615 	    symname = c_string(item);
4616 	    if (strcmp(symname, "unit") == 0) {
4617 		sprintf(buf+strlen(buf), "%s", unit_handle(side, unit));
4618 	    } else if (strcmp(symname, "actee") == 0) {
4619 		if (action->actee == unit->id)
4620 		  actee = unit;
4621 		else
4622 		  actee = find_unit(action->actee);
4623 		sprintf(buf+strlen(buf), "%s", unit_handle(side, actee));
4624 	    } else {
4625 		sprintf(buf+strlen(buf), " ??%s?? ", symname);
4626 	    }
4627 	} else if (numberp(item)) {
4628 	    n = c_number(item);
4629 	    if (0 /* special processing */) {
4630 	    } else {
4631 		sprintf(buf+strlen(buf), "%d", n);
4632 	    }
4633 	} else {
4634 	    strcat(buf, " ????? ");
4635 	}
4636     }
4637 }
4638 
4639 static void
play_action_movies(Unit * unit,Action * action)4640 play_action_movies(Unit *unit, Action *action)
4641 {
4642     int found = FALSE;
4643     char *soundname;
4644     Obj *rest, *head, *parms, *msgdesc;
4645 
4646     if (!should_play_movies())
4647       return;
4648     for_all_list(g_action_movies(), rest) {
4649 	head = car(rest);
4650 	if (consp(head)
4651 	    && symbolp(car(head))
4652 	    && strcmp(c_string(car(head)),
4653 		      actiondefns[(int) action->type].name) == 0) {
4654 	    found = TRUE;
4655 	    break;
4656 	}
4657 	if (consp(head)
4658 	    && consp(car(head))
4659 	    && symbolp(car(car(head)))
4660 	    && strcmp(c_string(car(car(head))),
4661 		      actiondefns[(int) action->type].name) == 0) {
4662 	    parms = cdr(car(head));
4663 	    if (parms == lispnil) {
4664 		found = TRUE;
4665 		break;
4666 	    }
4667 	    if (((symbolp(car(parms))
4668 		   && strcmp(c_string(car(parms)),
4669 			     u_type_name(unit->type)) == 0)
4670 		  || match_keyword(car(parms), K_USTAR)
4671 		  || (symbolp(car(parms))
4672 		      && boundp(car(parms))
4673 		      && ((symbolp(symbol_value(car(parms)))
4674 		          && strcmp(c_string(symbol_value(car(parms))),
4675 				    u_type_name(unit->type)) == 0)
4676 		          || (numberp(symbol_value(car(parms)))
4677 		              && c_number(symbol_value(car(parms)))
4678 			      == unit->type)))
4679 		  )) {
4680 		found = TRUE;
4681 		break;
4682 	    }
4683 	    /* (should be able to match on particular action parms also) */
4684 	}
4685     }
4686     /* If we have a match, do something with it. */
4687     if (found) {
4688 	msgdesc = cadr(head);
4689 	if (stringp(msgdesc)) {
4690 	    notify(unit->side, "%s", c_string(msgdesc));
4691 	} else if (consp(msgdesc)
4692 		   && symbolp(car(msgdesc))
4693 		   && strcmp(c_string(car(msgdesc)), "sound") == 0
4694 		   && stringp(cadr(msgdesc))) {
4695 	    soundname = c_string(cadr(msgdesc));
4696 	    /* (should not be passing ptrs to schedule_movie) */
4697 	    schedule_movie(unit->side, "sound", soundname);
4698 	    play_movies(add_side_to_set(unit->side, NOSIDES));
4699 	} else {
4700 	}
4701     }
4702 }
4703 
4704 /* Basic check that unit has sufficient acp to do an action. */
4705 
4706 int
can_have_enough_acp(Unit * unit,int acp)4707 can_have_enough_acp(Unit *unit, int acp)
4708 {
4709     if (!type_can_have_enough_acp(unit->type, acp)) {
4710 	if (acp < new_acp_for_turn(unit))
4711 	  return TRUE;
4712     }
4713     else
4714       return TRUE;
4715     return FALSE;
4716 }
4717 
4718 int
type_can_have_enough_acp(int u,int acp)4719 type_can_have_enough_acp(int u, int acp)
4720 {
4721     int maxacp, minacp;
4722 
4723     /* Acp-independent units always have enough acp. */
4724     if (u_acp_independent(u))
4725     	return TRUE;
4726     /* Else determine the basic ACP for the unit. */
4727     maxacp = u_acp(u);
4728     if (u_acp_turn_max(u) >= 0)
4729       maxacp = min(maxacp, u_acp_turn_max(u));
4730     maxacp = (u_acp_max(u) < 0 ? maxacp : u_acp_max(u));
4731     minacp = u_acp_min(u);
4732     return (maxacp + u_free_acp(u) - acp >= minacp);
4733 }
4734 
4735 int
has_enough_acp(Unit * unit,int acp)4736 has_enough_acp(Unit *unit, int acp)
4737 {
4738     int u = unit->type;
4739 
4740     /* ACP-indep units always have enough ACP. */
4741     if (acp_indep(unit))
4742       return TRUE;
4743     /* If the ACP required is 0, then allow the action. */
4744     if (!acp)
4745       return TRUE;
4746     /* If an unit cannot act, then it cannot have enough ACP. */
4747     if (!unit->act)
4748       return FALSE;
4749     return ((unit->act->acp + u_free_acp(u) - acp) >= u_acp_min(unit->type));
4750 }
4751 
4752 /* What is the maximum ACP that can be gained from being on any terrain
4753    at night? */
4754 int
type_max_night_acp_from_any_terrains(int u)4755 type_max_night_acp_from_any_terrains(int u)
4756 {
4757     int t = NONTTYPE, u3 = NONUTYPE;
4758     int acp = 0, maxacp = 0;
4759 
4760     if (!cache__type_max_night_acp_from_any_terrains) {
4761 	cache__type_max_night_acp_from_any_terrains =
4762 	  (int *)xmalloc(numutypes * sizeof(int));
4763 	for_all_unit_types(u3) {
4764 	    for_all_terrain_types(t) {
4765 		if (t_is_cell(t) /* || connector || coating */) {
4766 		    acp = ut_night_adds_acp(u3, t);
4767 		    maxacp = max(acp, maxacp);
4768 		}
4769 	    }
4770 	    cache__type_max_night_acp_from_any_terrains[u3] = maxacp;
4771 	}
4772     }
4773     return cache__type_max_night_acp_from_any_terrains[u];
4774 }
4775 
4776 /* What is the maximum ACP that can be gained from having any occupant? */
4777 /* (To do this calculation truthfully, we need to use a knapsack algorithm,
4778     because it may be that some combination of occ types yields the best
4779     results. Nonetheless, the function, in its current form, at least tells
4780     us whether or not any occ type will boost the ACP.) */
4781 int
type_max_acp_from_any_occs(int u)4782 type_max_acp_from_any_occs(int u)
4783 {
4784     int u2 = NONUTYPE, u3 = NONUTYPE;
4785     int acp = 0, maxacp = 0;
4786 
4787     if (!cache__type_max_acp_from_any_occs) {
4788 	cache__type_max_acp_from_any_occs = (int *)xmalloc(numutypes *
4789 							   sizeof(int));
4790 	for_all_unit_types(u3) {
4791 	    for_all_unit_types(u2) {
4792 		acp = uu_occ_adds_acp(u3, u2);
4793 		if (acp) {
4794 		    if (type_can_occupy_empty_type(u2, u3))
4795 			maxacp = max(acp, maxacp);
4796 		}
4797 	    }
4798 	    cache__type_max_acp_from_any_occs[u3] = maxacp;
4799 	}
4800     }
4801     return cache__type_max_acp_from_any_occs[u];
4802 }
4803 
4804 /* What is the maximum ACP that an unit type can have? */
4805 int
type_max_acp(int u)4806 type_max_acp(int u)
4807 {
4808     int u3 = NONUTYPE;
4809     int acp = 0;
4810 
4811     if (!cache__type_max_acp) {
4812 	cache__type_max_acp = (int *)xmalloc(numutypes * sizeof(int));
4813 	for_all_unit_types(u3) {
4814 	    if (u_acp_max(u3) >= 0) {
4815 		cache__type_max_acp[u3] = u_acp_max(u3);
4816 		continue;
4817 	    }
4818 	    acp = u_acp(u3);
4819 	    acp += type_max_night_acp_from_any_terrains(u3);
4820 	    acp += type_max_acp_from_any_occs(u3);
4821 	    /* (Should consider multiplicative effects.) */
4822 	    cache__type_max_acp[u3] = acp;
4823 	}
4824     }
4825     return cache__type_max_acp[u];
4826 }
4827 
4828 //! Make the consumed acp disappear, but not go below the minimum possible.
4829 /*! \note u_free_acp does not need to be explicitly considered here. */
4830 
4831 void
use_up_acp(Unit * unit,int acp)4832 use_up_acp(Unit *unit, int acp)
4833 {
4834     int oldacp, newacp, acpmin;
4835 
4836     /* This can sometimes be called on dead or non-acting units,
4837        so check first. */
4838     if (alive(unit) && !u_acp_independent(unit->type) && unit->act && acp > 0) {
4839     	oldacp = unit->act->acp;
4840 	newacp = oldacp - acp;
4841 	acpmin = u_acp_min(unit->type);
4842 	unit->act->acp = max(newacp, acpmin);
4843 	/* Maybe modify the unit's display. */
4844 	if (oldacp != unit->act->acp) {
4845 	    update_unit_acp_display(unit->side, unit, TRUE);
4846 	}
4847     }
4848 }
4849 
4850 /* The following is generic code. */
4851 
4852 int
construction_possible(int u2)4853 construction_possible(int u2)
4854 {
4855     int u;
4856 
4857     for_all_unit_types(u) {
4858 	if (could_create(u, u2)
4859 	    && uu_tp_max(u, u2) >= uu_tp_to_build(u, u2))
4860 	  return TRUE;
4861     }
4862     return FALSE;
4863 }
4864 
4865 int
any_construction_possible(void)4866 any_construction_possible(void)
4867 {
4868     int u, u2;
4869     static int any_construction = -1;
4870 
4871     if (any_construction < 0) {
4872 	any_construction = FALSE;
4873 	for_all_unit_types(u) {
4874 	    for_all_unit_types(u2) {
4875 		if (could_create(u, u2)) {
4876 		    any_construction = TRUE;
4877 		    return any_construction;
4878 		}
4879 	    }
4880 	}
4881     }
4882     return any_construction;
4883 }
4884 
4885 /* Test if the given mtype ever is stored in individual units. */
4886 
4887 int
storage_possible(int m)4888 storage_possible(int m)
4889 {
4890 	int	u;
4891 	Side	*side;
4892 
4893 	/* Test if any utype can store the mtype AND does not
4894 	always give it to a treasury. */
4895 	for_all_unit_types(u) {
4896 		/* Skip utypes that cannot store m. */
4897 		if (!um_storage_x(u, m))
4898 		    continue;
4899 		/* This utype will give m to a treasury if it exists,
4900 		but might not give ALL in backdrop model 1. */
4901 		if (um_gives_to_treasury(u, m)
4902 		    && (g_backdrop_model() != 1)) {
4903 			/* Test if all sides that can have this unit also
4904 			have a treasury that will recieve m. */
4905 			for_all_sides(side) {
4906 				if (side_has_treasury(side, m))
4907 				    continue;
4908 				if (!type_allowed_on_side(u, side))
4909 				    continue;
4910 				/* We found a side that can have this utype
4911 				and lacks a treasury for m. */
4912 				return TRUE;
4913 			}
4914 		/* We found a utype that can store m and does not give it
4915 		to a treasury even if it exists. */
4916 		} else return TRUE;
4917 	}
4918 	return FALSE;
4919 }
4920 
4921 /* Test if any mtype is ever stored in individual units. */
4922 
4923 int
any_storage_possible(void)4924 any_storage_possible(void)
4925 {
4926 	int m;
4927 
4928 	for_all_material_types(m) {
4929 		if (storage_possible(m)) {
4930 			return TRUE;
4931 		}
4932 	}
4933 	return FALSE;
4934 }
4935 
4936 /* Compose a legible description of a given action. */
4937 
4938 char *
action_desig(Action * act)4939 action_desig(Action *act)
4940 {
4941     int i, slen;
4942     char ch, *str;
4943 
4944     if (act == NULL)
4945       return "?null action?";
4946     if (act->type == ACTION_NONE)
4947       return "[]";
4948     if (actiondesigbuf == NULL)
4949       actiondesigbuf = (char *)xmalloc(BUFSIZE);
4950     str = actiondesigbuf;
4951     sprintf(str, "[%s", actiondefns[act->type].name);
4952     slen = strlen(actiondefns[act->type].argtypes);
4953     for (i = 0; i < slen; ++i) {
4954 	ch = (actiondefns[act->type].argtypes)[i];
4955 	switch (ch) {
4956 	  case 'U':
4957 	    tprintf(str, " \"%s\"",
4958 		    unit_desig(find_unit(act->args[i])));
4959 	    break;
4960 	  default:
4961 	    tprintf(str, " %d", act->args[i]);
4962 	}
4963     }
4964     if (act->actee != 0) {
4965 	tprintf(str, " (#%d)", act->actee);
4966     }
4967     strcat(str, "]");
4968     return actiondesigbuf;
4969 }
4970