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