1 /* Units in Xconq.
2 Copyright (C) 1986-1989, 1991-2000 Stanley T. Shebs.
3 Copyright (C) 2004-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 #include "conq.h"
11 #include "kernel.h"
12 #include "aiscore.h"
13 #include "aiunit.h"
14 #include "aiunit2.h"
15 #include "aitact.h"
16 #include "aioprt.h"
17
18 /* This is not a limit, just sets initial allocation of unit objects
19 and how many additional to get if more are needed. This can be
20 tweaked for more frequent but smaller allocation, or less frequent
21 but larger and possibly space-wasting allocation. */
22
23 #ifndef INITMAXUNITS
24 #define INITMAXUNITS 200
25 #endif
26
27 extern void free_used_cells(Unit *unit); /* Used in move.c */
28 extern void set_unit_image(Unit *unit); /* From ui.c */
29
30 extern int *numuimages;
31
32 static void allocate_unit_block(void);
33 static int compare_units(Unit *unit1, Unit *unit2);
34 static int compare_units_by_keys(const void *e1, const void *e2);
35 static void leave_cell_aux(Unit *unit, Unit *oldtransport);
36 static void change_cell_aux(Unit *unit, int x0, int y0, int x, int y);
37 static void kill_unit_aux(Unit *unit, int reason);
38 static void set_unit_position(Unit *unit, int x, int y, int z);
39 static void enter_cell_aux(Unit *unit, int x, int y);
40 static void eject_excess_occupants(Unit *unit);
41 static void eject_occupant(Unit *unit, Unit *occ);
42 static void insert_unit(Unit *unithead, Unit *unit);
43 static void delete_unit(Unit *unit);
44 static void check_unit(Unit *unit);
45 static int disband_unit_directly(Side *side, Unit *unit);
46 static void add_unit_to_ustack(Unit *unit, int x, int y);
47 static void add_unit_to_ustack(Unit *unit, Unit *transport);
48 static void remove_unit_from_ustack(Unit *unit);
49 static void glimpse_adjacent_terrain(Unit *unit);
50 static int budget_space_for_changed_type(Unit *unit, int newtype);
51 static int try_changing_side_of_changed_unit(Unit *unit, Side *newside,
52 int newtype, int reason);
53 static int desperately_try_changing_side_of_changed_unit(Unit *unit,
54 Side *newside,
55 int newtype,
56 int reason);
57 static void resurrect_self_unit(Unit *unit, Side *oldside, Side *newside);
58
59 /* The list of available units. */
60
61 Unit *freeunits;
62
63 /* The global linked list of all units. */
64
65 Unit *unitlist;
66
67 /* A scratch global. */
68
69 Unit *tmpunit;
70
71 /* Buffers for descriptions of units. */
72
73 /* We use several and rotate among them; this is so multiple calls in
74 a single printf will work as expected. Not elegant, but simple and
75 sufficient. */
76
77 #define NUMSHORTBUFS 3
78
79 static int curshortbuf;
80
81 static char *shortbufs[NUMSHORTBUFS] = { NULL, NULL, NULL };
82
83 static char *utypenamen;
84
85 char **shortestnames = NULL;
86
87 int longest_shortest;
88
89 char **shortestgnames = NULL;
90
91 char *actorstatebuf = NULL;
92
93 /* Total number of units in existence. */
94
95 int numunits;
96
97 /* Total number of units that are alive. */
98
99 int numliveunits;
100
101 /* Total number of live units, by type. */
102
103 int *numlivebytype;
104
105 /* The next number to use for a unit id. */
106
107 int nextid = 1;
108
109 /* A cache of completenesses. */
110
111 short *completenesses;
112
113 /* Advanced unit support. */
114
115 short default_size = 1; /* Default abstract size of unit */
116 short default_usedcells = 0; /* Number of cells being used by the unit */
117 short default_maxcells = 1; /* Default max number of cells that unit can use */
118 short default_curadvance = -1; /* Default advance being researched by new unit */
119 long default_population = 1; /* Default size of unit's population */
120
121 extern void free_used_cells(Unit *unit);
122
123 /* Can the unit be an actor? */
124
125 int
can_be_actor(Unit * unit)126 can_be_actor(Unit *unit)
127 {
128 int factor = FALSE;
129 Unit *occ = NULL;
130 int t = NONTTYPE;
131
132 assert_error(unit, "Attempted to access a null unit.");
133 if (unit->cp < 0)
134 return FALSE;
135 /* Could the unit get acp every turn? */
136 factor = (u_acp(unit->type) > 0);
137 /* Is the unit ACP-independent? ACP-indep units still need plan. */
138 if (!factor)
139 factor = acp_indep(unit);
140 /* Does an occupant give the unit ACP? */
141 if (!factor) {
142 for_all_occupants(unit, occ) {
143 if (0 < uu_occ_adds_acp(unit->type, occ->type)) {
144 factor = TRUE;
145 break;
146 }
147 }
148 }
149 /* Does the unit's terrain at night give the unit ACP? */
150 if (!factor && in_play(unit) && night_at(unit->x, unit->y)) {
151 t = terrain_at(unit->x, unit->y);
152 factor = (0 < ut_night_adds_acp(unit->type, t));
153 /* (Should also consider connectors and coatings.) */
154 }
155 return factor;
156 }
157
158 /* Grab a block of unit objects to work with. */
159
160 static void
allocate_unit_block(void)161 allocate_unit_block(void)
162 {
163 int i;
164 Unit *unitblock = (Unit *) xmalloc(INITMAXUNITS * sizeof(Unit));
165
166 for (i = 0; i < INITMAXUNITS; ++i) {
167 unitblock[i].id = -1;
168 unitblock[i].next = &unitblock[i+1];
169 }
170 unitblock[INITMAXUNITS-1].next = NULL;
171 freeunits = unitblock;
172 Dprintf("Allocated space for %d units.\n", INITMAXUNITS);
173 }
174
175 /* Init gets a first block of units, and sets up the "independent side" list,
176 since newly created units will appear on it. */
177
178 void
init_units(void)179 init_units(void)
180 {
181 unitlist = NULL;
182 allocate_unit_block();
183 init_side_unithead(indepside);
184 }
185
186 /* The primitive unit creator, called by regular creator and also used to
187 make the dummy units that sit at the heads of the per-side unit lists. */
188
189 Unit *
create_bare_unit(int type)190 create_bare_unit(int type)
191 {
192 Unit *newunit;
193
194 /* If our free list is empty, go and get some more units. */
195 if (freeunits == NULL) {
196 allocate_unit_block();
197 }
198 /* Take the first unit off the free list. */
199 newunit = freeunits;
200 freeunits = freeunits->next;
201 /* Give it a valid type... */
202 newunit->type = type;
203 /* ...but an invalid id. */
204 newunit->id = -1;
205 return newunit;
206 }
207
208 /* The regular unit creation routine. All the slots should have something
209 reasonable in them, since individual units objects see a lot of reuse. */
210
211 Unit *
create_unit(int type,int makebrains)212 create_unit(int type, int makebrains)
213 {
214 int i, m;
215 Unit *newunit;
216
217 if (numlivebytype == NULL)
218 numlivebytype = (int *) xmalloc(numutypes * sizeof(int));
219 /* Fill this in. */
220 if (completenesses == NULL) {
221 completenesses = (short *) xmalloc(numutypes * sizeof(short));
222 for_all_unit_types(i)
223 completenesses[i] = u_cp(i) / u_parts(i);
224 }
225 /* Test whether we've hit any designer-specified limits. */
226 if ((u_type_in_game_max(type) >= 0
227 && numlivebytype[type] >= u_type_in_game_max(type))
228 || (g_units_in_game_max() >= 0
229 && numliveunits >= g_units_in_game_max())) {
230 return NULL;
231 }
232 /* Allocate the unit object. Xconq will fail instead of returning null. */
233 newunit = create_bare_unit(type);
234 /* Set the master uview to NULL; it will be allocated and updated as
235 needed. */
236 newunit->uview = NULL;
237 /* Init all the slots to distinguishable values. The unit is not
238 necessarily newly allocated, so we have to hit all of its slots. */
239 /* Note that we don't check for overflow of unit ids, since it's
240 highly unlikely that a single game would ever create 2 billion
241 units. */
242 newunit->id = nextid++;
243 newunit->name = NULL;
244 /* Number == 0 means unit is unnumbered. */
245 newunit->number = 0;
246 /* If during launch, images may not be loaded yet. */
247 if (numuimages) {
248 set_unit_image(newunit);
249 }
250 /* Outside the world. */
251 newunit->x = newunit->y = -1;
252 /* At ground level. */
253 newunit->z = 0;
254 /* Units default to being independent. */
255 newunit->side = indepside;
256 newunit->origside = indepside;
257 /* Create at max hp, let others reduce if necessary. */
258 newunit->hp = newunit->hp2 = u_hp(type);
259 /* Create fully functional, let other routines set incompleteness. */
260 newunit->cp = u_cp(type);
261 /* Zero the combat experience. */
262 newunit->cxp = 0;
263 /* Zero the morale. */
264 newunit->morale = 0;
265 /* Not in a transport. */
266 newunit->transport = NULL;
267 /* Note that the space never needs to be freed. */
268 if (newunit->supply == NULL && nummtypes > 0) {
269 newunit->supply = (long *) xmalloc(nummtypes * sizeof(long));
270 }
271 /* Always zero out all the supply values. */
272 for_all_material_types(m)
273 newunit->supply[m] = 0;
274 /* Allocate cache for units last production. */
275 if (nummtypes > 0)
276 newunit->production = (short *) xmalloc(nummtypes * sizeof(short));
277 /* Always zero out all the production values. */
278 for_all_material_types(m)
279 newunit->production[m] = 0;
280 /* Will allocate tooling state when actually needed. */
281 newunit->tooling = NULL;
282 /* Will allocate opinions when actually needed. */
283 newunit->opinions = NULL;
284 if (makebrains) {
285 init_unit_actorstate(newunit, TRUE);
286 init_unit_plan(newunit);
287 } else {
288 newunit->act = NULL;
289 newunit->plan = NULL;
290 }
291 if (newunit->extras != NULL)
292 init_unit_extras(newunit);
293 newunit->occupant = NULL;
294 newunit->nexthere = NULL;
295 newunit->creation_id = 0;
296 /* Glue this unit into the list of independent units. */
297 newunit->next = newunit;
298 newunit->prev = newunit;
299 insert_unit(indepside->unithead, newunit);
300 newunit->unext = unitlist;
301 unitlist = newunit;
302 /* Init various other slots. */
303 newunit->prevx = newunit->prevy = -1;
304 newunit->transport_id = lispnil;
305 newunit->aihook = NULL;
306 /* Advanced unit support. */
307 newunit->size = default_size;
308 newunit->reach = u_reach(type);
309 newunit->usedcells = default_usedcells;
310 newunit->maxcells = default_maxcells;
311 newunit->population = default_population;
312 newunit->curadvance = default_curadvance;
313 newunit->cp_stash = 0;
314 newunit->researchdone = FALSE;
315 newunit->busy = FALSE;
316 /* Add to the global unit counts. */
317 ++numunits;
318 ++numliveunits;
319 ++(numlivebytype[type]);
320 return newunit;
321 }
322
323 void
init_unit_tooling(Unit * unit)324 init_unit_tooling(Unit *unit)
325 {
326 unit->tooling = (short *) xmalloc(numutypes * sizeof(short));
327 }
328
329 /* Set or resize the array of a unit's opinions about each side in a game. */
330
331 void
init_unit_opinions(Unit * unit,int nsides)332 init_unit_opinions(Unit *unit, int nsides)
333 {
334 int i;
335 short *temp;
336
337 temp = NULL;
338 if (u_opinion_min(unit->type) != u_opinion_max(unit->type)) {
339 if (unit->opinions != NULL && nsides > numsides) {
340 temp = unit->opinions;
341 unit->opinions = NULL;
342 }
343 if (unit->opinions == NULL)
344 unit->opinions = (short *) xmalloc(nsides * sizeof(short));
345 /* Opinions are now all neutral. */
346 if (temp != NULL) {
347 /* Copy over old opinions. */
348 for (i = 0; i < numsides; ++i)
349 unit->opinions[i] = temp[i];
350 free(temp);
351 }
352 } else {
353 if (unit->opinions != NULL)
354 free(unit->opinions);
355 unit->opinions = NULL;
356 }
357 }
358
359 /* Alter the actorstate object to be correct for this unit. Allow for
360 artificially injecting ACP, since this is useful in cases when an unit
361 is "enabled" by an occupant, but the occupant has not yet been read in
362 during game restoration. */
363
364 void
init_unit_actorstate(Unit * unit,int flagacp,int acp)365 init_unit_actorstate(Unit *unit, int flagacp, int acp)
366 {
367 if (can_be_actor(unit) || (0 < acp)) {
368 /* Might already have an actorstate, don't realloc if so;
369 but do clear an existing actorstate, since might be reusing. */
370 if (unit->act == NULL)
371 unit->act = (ActorState *) xmalloc(sizeof(ActorState));
372 else
373 memset((char *) unit->act, 0, sizeof(ActorState));
374 /* Indicate that the action points have not been set. */
375 if (flagacp)
376 unit->act->acp = unit->act->initacp = u_acp_min(unit->type) - 1;
377 /* Flag the action as undefined. */
378 unit->act->nextaction.type = ACTION_NONE;
379 } else {
380 if (unit->act != NULL)
381 free(unit->act);
382 unit->act = NULL;
383 }
384 }
385
386 /* Allocate and fill in the unit extras. This is needed whenever any
387 one of the extra properties is going to get a non-default value.
388 (Normally, the accessors for this structure return a default value
389 if one is not present in a unit.) */
390
391 void
init_unit_extras(Unit * unit)392 init_unit_extras(Unit *unit)
393 {
394 if (unit->extras == NULL)
395 unit->extras = (UnitExtras *) xmalloc(sizeof(UnitExtras));
396 /* Each slot must get the same value as the accessor would return
397 if the structure had not been allocated. */
398 unit->extras->point_value = -1;
399 unit->extras->appear = -1;
400 unit->extras->appear_var_x = -1;
401 unit->extras->appear_var_y = -1;
402 unit->extras->disappear = -1;
403 unit->extras->priority = -1;
404 unit->extras->sym = lispnil;
405 unit->extras->sides = lispnil;
406 }
407
408 /* Changing a unit's type has many effects. */
409
410 void
change_unit_type(Unit * unit,int newtype,int reason,Side * newside)411 change_unit_type(Unit *unit, int newtype, int reason, Side *newside)
412 {
413 int oldtype = unit->type, oldhp = unit->hp;
414 PastUnit *pastunit;
415 Side *oldside;
416 int oldacp = 0;
417 int oldacpuser = TRUE;
418 int fnewside = FALSE;
419 Unit *transport = NULL;
420 int m = NONMTYPE;
421
422 assert_error(unit, "Tried to change the type of a null unit.");
423 /* Don't do anything if we're "changing" to the same type. */
424 if (oldtype == newtype)
425 return;
426 /* Shorthand for unit->transport. */
427 transport = unit->transport;
428 /* Record the old ACP. */
429 if (unit->act) {
430 oldacp = unit->act->acp;
431 }
432 /* Flag if the unit did not use or did not have ACP. */
433 else {
434 oldacpuser = FALSE;
435 }
436 /* Make sure that there is enough space for new type. */
437 if (!budget_space_for_changed_type(unit, newtype))
438 return;
439 /* Update the transport as the budgeting process may have pulled the
440 unit out of the transport. */
441 transport = unit->transport;
442 /* Consume materials as necessary. */
443 if (in_play(unit)) {
444 consume_materials(unit, unit, um_consumption_per_change_type);
445 }
446 /* Remember unit and its side. */
447 oldside = unit->side;
448 pastunit = change_unit_to_past_unit(unit);
449 if (reason >= 0)
450 record_event((HistEventType)reason, ALLSIDES, pastunit->id, unit->id,
451 newtype);
452 /* Decrement viewing coverage of our old type. */
453 cover_area(unit->side, unit, transport, unit->x, unit->y, -1, -1);
454 all_see_leave(unit, unit->x, unit->y, (transport == NULL));
455 /* Do the actual change. */
456 unit->type = newtype;
457 /* Make sure the new unit is complete. */
458 unit->cp = u_cp(newtype);
459 /* Set the new hp to the same ratio of max as the unit had before.
460 Caller can tweak to something else if necessary. */
461 unit->hp = (oldhp * u_hp_max(newtype)) / u_hp_max(oldtype);
462 /* Need to guarantee a positive value though. */
463 if (unit->hp < 1)
464 unit->hp = 1;
465 unit->hp2 = unit->hp;
466 /* Alter the unit's action vector as needed. */
467 /* Set the ACP to the same ratio of max as the unit had before. */
468 /* If old unit was ACP-indep or actionless, then we give the new unit
469 a free booster in the world of ACP, if it is set up to use ACP. */
470 if (!oldacpuser || (u_acp(newtype) <= 0)) {
471 init_unit_actorstate(unit, FALSE);
472 if (unit->act)
473 unit->act->initacp = unit->act->acp = total_acp_for_turn(unit);
474 }
475 else {
476 if (oldacp > 0) {
477 unit->act->acp = (oldacp * type_acp_max(newtype)) /
478 type_acp_max(oldtype);
479 unit->act->initacp = total_acp_for_turn(unit);
480 }
481 else {
482 unit->act->initacp = unit->act->acp = new_acp_for_turn(unit);
483 }
484 }
485 /* Knock out the old nextaction. Might not be compatible. */
486 if (unit->act)
487 unit->act->nextaction.type = ACTION_NONE;
488 /* Invalidate the side's point value cache. */
489 if (unit->side)
490 unit->side->point_value_valid = FALSE;
491 /* Try changing to a new side if necessary. */
492 if (!type_allowed_on_side(newtype, unit->side))
493 fnewside = try_changing_side_of_changed_unit(unit, newside, newtype,
494 reason);
495 /* (should modify per-side counts) */
496 /* Unit will always need a new number. */
497 assign_unit_number(unit);
498 /* Unit may also need a name. */
499 /* (Old names should also be gotten rid of, if the new unit type is not
500 supposed to have names assigned to its units.) */
501 make_up_unit_name(unit);
502 /* If old type was self and new type can not be self,
503 then a new avatar must be found or else the side loses. */
504 if (unit->side->self_unit == unit) {
505 if (!u_can_be_self(newtype))
506 resurrect_self_unit(unit, unit->side, newside);
507 }
508 /* Update the cancarry vector if this is a transport. */
509 if (u_is_transport(unit->type)) {
510 update_cancarry_vector(unit->side);
511 }
512 init_unit_opinions(unit, numsides);
513 /* Redo the supply numbers. */
514 /* init_supply(unit); */
515 /* (TODO: Dump excess in the terrain or stack neighbors, or ....) */
516 for_all_material_types(m) {
517 unit->supply[m] = min(unit->supply[m], um_storage_x(newtype, m));
518 }
519 init_unit_plan(unit);
520 unit->aihook = NULL;
521 /* Advanced unit support. */
522 /* (should share with unit creation) */
523 if (u_advanced(newtype)) {
524 /* If weren't previously and advanced unit. */
525 if (!u_advanced(oldtype)) {
526 unit->size = default_size;
527 unit->reach = u_reach(newtype);
528 unit->usedcells = default_usedcells;
529 unit->maxcells = default_maxcells;
530 unit->population = default_population;
531 unit->curadvance = default_curadvance;
532 unit->cp_stash = 0;
533 }
534 /* Else we were already and advanced unit. */
535 else {
536 /* Extend reach if old reach is too little. */
537 unit->reach = max(unit->reach, u_reach(newtype));
538 /* Contract reach if old reach is too large. */
539 unit->reach = min(unit->reach, u_reach(newtype));
540 }
541 }
542 /* If the unit needs to change side but could not earlier, start trying
543 some desperate measures. */
544 if (!fnewside && !type_allowed_on_side(newtype, unit->side)) {
545 if (!desperately_try_changing_side_of_changed_unit(unit, newside,
546 newtype, reason))
547 return;
548 }
549 /* Set the unit image by first clearing the old image name.
550 'set_unit_image' will set a new image name and image for us. */
551 unit->image_name = "";
552 set_unit_image(unit);
553 /* Increment viewing coverage. */
554 cover_area(unit->side, unit, transport, -1, -1, unit->x, unit->y);
555 /* If vision range is 0, allow glimpses of adjacent cell terrain.
556 This applies to terrain only, adjacent units cannot be seen. */
557 if (u_vision_range(unit->type) == 0)
558 glimpse_adjacent_terrain(unit);
559 all_see_occupy(unit, unit->x, unit->y, (transport == NULL));
560 count_loss(oldside, oldtype, (reason == H_UNIT_WRECKED ? combat_loss
561 : other_loss));
562 count_gain(unit->side, newtype, other_gain);
563 update_side_display(unit->side, unit->side, TRUE);
564 /* Update global counts. */
565 --(numlivebytype[oldtype]);
566 ++(numlivebytype[newtype]);
567 }
568
569 /* Try to change the side of an unit that changed type, if necesary. */
570
571 static int
try_changing_side_of_changed_unit(Unit * unit,Side * newside,int newtype,int reason)572 try_changing_side_of_changed_unit(Unit *unit, Side *newside, int newtype,
573 int reason)
574 {
575 int fnewside = FALSE;
576 Unit *transport = NULL;
577
578 assert_error(unit, "Tried changing side of null unit.");
579 transport = unit->transport;
580 /* We might have to change sides. */
581 if (!type_allowed_on_side(newtype, unit->side)) {
582 /* Unit maybe joins another side. */
583 if (!fnewside && newside && type_allowed_on_side(newtype, newside)) {
584 if (!transport
585 || (transport && transport->side
586 && (trusted_side(transport->side, newside)
587 || ((indepside == transport->side)
588 && uu_can_enter_indep(newtype,
589 transport->type))))) {
590 change_unit_side(unit, newside, reason, NULL);
591 fnewside = TRUE;
592 }
593 }
594 /* Unit maybe becomes independent. */
595 if (!fnewside && type_allowed_on_side(newtype, indepside)) {
596 if (!transport
597 || (transport && transport->side
598 && (trusted_side(transport->side, indepside)
599 || (indepside == transport->side)))) {
600 change_unit_side(unit, indepside, reason, NULL);
601 fnewside = TRUE;
602 }
603 }
604 /* (If we fail here, we may get more desparate later.) */
605 }
606 return fnewside;
607 }
608
609 /* Desperately try to change the side of an unit that changed type,
610 if necesary. */
611
612 static int
desperately_try_changing_side_of_changed_unit(Unit * unit,Side * newside,int newtype,int reason)613 desperately_try_changing_side_of_changed_unit(Unit *unit, Side *newside,
614 int newtype, int reason)
615 {
616 int fnewside = FALSE, fkillunit = FALSE;
617 Unit *transport = NULL;
618
619 assert_error(unit, "Tried changing side of null unit.");
620 transport = unit->transport;
621 if (!fnewside && !type_allowed_on_side(newtype, unit->side)) {
622 /* (I have quite a few reservations about the following commented out
623 code. For one, I do not think that we should be initiating a
624 capture action from within a low-level function such as
625 'change_unit_type'. For another, we cannot easily forsee all the
626 circumstances under which 'change_unit_type' is invoked, and
627 therefore it is hard to judge whether automatic escape or capture
628 are always the correct things to try. And, this adds a lot of
629 complexity to the game, which if mistakenly abused may appear to
630 be a bug to a game designer. And finally, with the ability to
631 change unit type on capture in place, have captures invoked from
632 'change_unit_type' may lead to infinite recursion in some cases.) */
633 #if (0)
634 if (transport) {
635 /* (TODO: Implement occupant escape chance for units which
636 changed type.) */
637 if (valid(check_capture_action(unit, unit, transport))) {
638 if (A_CAPTURE_FAILED ==
639 do_capture_action(unit, unit, transport))
640 fkillunit = TRUE;
641 }
642 }
643 else
644 fkillunit = TRUE;
645 #else
646 fkillunit = TRUE;
647 #endif
648 /* Unitum delenda est. */
649 if (fkillunit) {
650 /* Give any occupants a chance to escape. */
651 rescue_occupants(unit);
652 /* Say goodbye to the unit. */
653 kill_unit(unit, H_UNIT_VANISHED);
654 Dprintf(
655 "%s killed by type change since new type %s could not belong to old side or any possible new side",
656 unit_desig(unit), u_type_name(newtype));
657 }
658 else
659 fnewside = TRUE;
660 }
661 return fnewside;
662 }
663
664 /* Try to budget some space for an unit which about to change to a new type. */
665
666 static int
budget_space_for_changed_type(Unit * unit,int newtype)667 budget_space_for_changed_type(Unit *unit, int newtype)
668 {
669 int fkillunit = FALSE;
670 Unit *transport = NULL;
671 int x = -1, y = -1;
672
673 assert_error(unit, "Attempted to change type of a null unit.");
674 transport = unit->transport;
675 x = unit->x; y = unit->y;
676 /* Kill the unit if the new type cannot sit in the old type's cell or
677 old type's transport. Note that we do not permit the unit to change
678 type one more time by being wrecked at this point. */
679 if (transport) {
680 if (!type_can_occupy_without(newtype, transport, unit)) {
681 /* Can the type occupy and survive in the same cell as its
682 transport? */
683 if (!type_can_occupy_cell(newtype, unit->x, unit->y)
684 || !type_survives_in_cell(newtype, unit->x, unit->y))
685 fkillunit = TRUE;
686 // If so, then place the unit in the cell.
687 /* (We don't worry about ACP or MP at this point. Perhaps this
688 is a bad assumption, but it makes life easier....) */
689 else {
690 leave_cell(unit); // This also frees it from the transport.
691 enter_cell(unit, x, y);
692 }
693 }
694 }
695 else {
696 if (!type_can_occupy_cell_without(newtype, unit->x, unit->y, unit)
697 || !type_survives_in_cell(newtype, unit->x, unit->y))
698 fkillunit = TRUE;
699 }
700 if (fkillunit) {
701 /* Give any occupants a chance to escape. */
702 rescue_occupants(unit);
703 /* Say goodbye to the unit. */
704 kill_unit(unit, H_UNIT_VANISHED);
705 Dprintf(
706 "%s killed by type change since new type %s could not sit in (%d, %d)",
707 unit_desig(unit), u_type_name(newtype), unit->x, unit->y);
708 }
709 return !fkillunit;
710 }
711
712 /* Test if any occupant of a given unit belongs to the given side. */
713 /* {Arbiter Function} */
714
715 int
side_owns_occupant_of_unit(Side * side,Unit * unit)716 side_owns_occupant_of_unit(Side *side, Unit *unit)
717 {
718 Unit *occ = NULL;
719
720 assert_error(side, "Attempted to access a NULL side");
721 if (unit->occupant == NULL)
722 return FALSE;
723 for_all_occupants(unit, occ) {
724 if (occ->side == side)
725 return TRUE;
726 if (occ->occupant) {
727 if (side_owns_occupant_of_unit(side, occ))
728 return TRUE;
729 }
730 }
731 return FALSE;
732 }
733
734 /* Test if the side has a seeing occupant inside a transport. */
735 /* {Arbiter Function} */
736
737 int
side_owns_viewer_in_unit(Side * side,Unit * unit)738 side_owns_viewer_in_unit(Side *side, Unit *unit)
739 {
740 Unit *occ = NULL;
741
742 assert_error(side, "Attempted to access a NULL side");
743 if (unit->occupant == NULL)
744 return FALSE;
745 for_all_occupants(unit, occ) {
746 /* (TODO: Account for transport adding vision range to occ.) */
747 if ((occ->side == side) && (0 <= u_vision_range(unit->type)))
748 return TRUE;
749 if (occ->occupant) {
750 if (side_owns_viewer_in_unit(side, occ))
751 return TRUE;
752 }
753 }
754 return FALSE;
755 }
756
757 /* Return the chance of one utype seeing another, given distance. */
758
759 int
see_chance(int u,int u2,int dist)760 see_chance(int u, int u2, int dist)
761 {
762 assert_error(is_unit_type(u), "Invalid unit type encountered");
763 assert_error(is_unit_type(u2), "Invalid unit type encountered");
764 if (u_vision_range(u) < dist)
765 return 0;
766 if (u_see_always(u2))
767 return 100;
768 switch (dist) {
769 case 0:
770 return uu_see_at(u, u2);
771 case 1:
772 return uu_see_adj(u, u2);
773 default:
774 return uu_see(u, u2);
775 }
776 return 0;
777 }
778
779 /* Return the chance of one unit seeing another. */
780 /* {Arbiter Function} */
781
782 int
see_chance(Unit * seer,Unit * tosee)783 see_chance(Unit *seer, Unit *tosee)
784 {
785 int dist = -1, chance = 0;
786 int u = NONUTYPE, u2 = NONUTYPE;
787 int t = NONTTYPE, ta = NONTTYPE;
788 int tv = UNSEEN;
789
790 assert_error(in_play(seer), "Attempted to access an out-of-play unit.");
791 assert_error(in_play(tosee), "Attempted to access an out-of-play unit.");
792 tv = terrain_view(seer->side, tosee->x, tosee->y);
793 if (UNSEEN == tv)
794 return 0;
795 t = vterrain(tv);
796 u = seer->type;
797 u2 = tosee->type;
798 /* If visibility is 0 in any terrain, then the chance of seeing is 0. */
799 /* (TODO: Implement 'ut_adds_visibility' and 'ut_multiplies_visibility'.) */
800 if (0 >= ut_visibility(u2, t))
801 return 0;
802 if (any_aux_terrain_defined()) {
803 for_all_aux_terrain_types(ta) {
804 if (aux_terrain_defined(ta)
805 && aux_terrain_at(tosee->x, tosee->y, ta)
806 && (0 >= ut_visibility(u2, ta)))
807 return 0;
808 }
809 }
810 /* (TODO: Implement 'uu_transport_adds_vision',
811 'uu_transport_multiples_vision', 'uu_occ_adds_vision', and
812 'uu_occ_multiples_vision'.) */
813 if (seer->transport && (0 == uu_occ_vision(u, seer->transport->type)))
814 return 0;
815 dist = distance(seer->x, seer->y, tosee->x, tosee->y);
816 /* Basic see-chance between 2 units, accounting for distance. */
817 chance = see_chance(u, u2, dist);
818 /* Terrain modifications to see-chance. */
819 chance = (chance * ut_visibility(u2, t)) / 100;
820 if (any_aux_terrain_defined()) {
821 for_all_aux_terrain_types(ta) {
822 if (aux_terrain_defined(ta)
823 && aux_terrain_at(tosee->x, tosee->y, ta))
824 chance = (chance * ut_visibility(u2, ta)) / 100;
825 }
826 }
827 /* Transport modifications to see-chance. */
828 /* (TODO: Implement 'uu_transport_adds_visibility',
829 'uu_transport_multiplies_visibility', 'uu_occ_adds_visibility',
830 and 'uu_occ_multiplies_visibility'.) */
831 if (seer->transport)
832 chance = (chance * uu_occ_vision(u, seer->transport->type)) / 100;
833 /* Lighting modification to see-chance. */
834 /* (TODO: Should test for twilight effects.) */
835 /* (TODO: Implement 'ut_night_adds_visibility' and
836 'ut_night_multiplies_visibility'.) */
837 if (night_at(tosee->x, tosee->y)) {
838 if (((ut_vision_night_effect(u, t) * u_vision_range(u)) / 100) < dist)
839 chance = 0;
840 }
841 return chance;
842 }
843
844 /* A unit occupies a cell by adding itself to the list of occupants.
845 It will not occupy a transport even if one is at this position
846 (other code should have taken care of this case already) If
847 something goes wrong, return false. This routine is heavily
848 used. */
849
850 int
enter_cell(Unit * unit,int x,int y)851 enter_cell(Unit *unit, int x, int y)
852 {
853 /* This is essential since some calls to enter_cell do not wrap x correctly.
854 Fixes bug that caused units to disappear when they crossed the date line,
855 and also bug that placed new units at off-world positions. */
856 x = wrapx(x);
857
858 #ifdef DEBUGGING
859 /* Not necessarily an error, but indicative of bugs elsewhere. */
860 if (unit->x >= 0 || unit->y >= 0) {
861 run_warning("unit %d occupying cell (%d, %d), was at (%d %d)",
862 unit->id, x, y, unit->x, unit->y);
863 }
864 #endif /* DEBUGGING */
865 /* Always check this one, but not necessarily fatal. */
866 if (!inside_area(x, y)) {
867 run_warning("No cell at %d,%d, %s can't enter it",
868 x, y, unit_desig(unit));
869 /* Let the unit remain off-world. */
870 return FALSE;
871 }
872 #if (0)
873 if (!type_can_occupy_cell(unit->type, x, y)) {
874 run_warning("Cell at %d,%d is too full for %s",
875 x, y, unit_desig(unit));
876 /* Let the unit remain off-world. */
877 return FALSE;
878 }
879 #endif
880 add_unit_to_ustack(unit, x, y);
881 /* Set the location slots now. */
882 enter_cell_aux(unit, x, y);
883 /* Inevitable side-effect of appearing in the new location. */
884 all_see_occupy(unit, x, y, TRUE);
885 kick_out_enemy_users(unit->side, x, y);
886 return TRUE;
887 }
888
889 int
type_survives_in_cell(int u,int x,int y)890 type_survives_in_cell(int u, int x, int y)
891 {
892 int c;
893
894 /* First check if there is a safe connection to sit on. */
895 for_all_connection_types(c) {
896 if (aux_terrain_defined(c)
897 && any_connections_at(x, y, c)
898 && type_survives_in_terrain(u, c)) {
899 return TRUE;
900 }
901 }
902 /* If not, check if the ground terrain itself is safe. */
903 if (type_survives_in_terrain(u, terrain_at(x, y))) {
904 return TRUE;
905 }
906 return FALSE;
907 }
908
909 int
type_survives_in_terrain(int u,int t)910 type_survives_in_terrain(int u, int t)
911 {
912 if (ut_vanishes_on(u, t))
913 return FALSE;
914 if (ut_wrecks_on(u, t))
915 return FALSE;
916 return TRUE;
917 }
918
919 /* Return true if the given unit type can fit onto the given cell. */
920
921 /* (should eventually account for variable-size units) */
922
923 static int *toc_numtypes;
924
925 int
type_can_occupy_cell(int u,int x,int y)926 type_can_occupy_cell(int u, int x, int y)
927 {
928 int t = terrain_at(x, y), u2, u3, numthistype = 0, fullness = 0;
929 Unit *unit2;
930
931 if (t_capacity(t) <= 0 && ut_capacity_x(u, t) <= 0) {
932 return FALSE;
933 }
934 if (toc_numtypes == NULL) {
935 toc_numtypes = (int *) xmalloc(numutypes * sizeof(int));
936 }
937 for_all_unit_types(u3) {
938 toc_numtypes[u3] = 0;
939 }
940 for_all_stack(x, y, unit2) {
941 u2 = unit2->type;
942 ++toc_numtypes[u2];
943 if (u2 == u) {
944 ++numthistype;
945 }
946 /* Only count against fullness if exclusive capacity exceeded. */
947 if (toc_numtypes[u2] > ut_capacity_x(u2, t)) {
948 fullness += ut_size(u2, t);
949 }
950 }
951 /* Unit can be in this cell if there is dedicated space. */
952 if (numthistype + 1 <= ut_capacity_x(u, t)) {
953 return TRUE;
954 }
955 /* Otherwise decide on the basis of fullness. */
956 if (fullness + ut_size(u, t) <= t_capacity(t)) {
957 return TRUE;
958 }
959 return FALSE;
960 }
961
962 /* Same as above but uses unit views instead of units. */
963
964 int
side_thinks_type_can_occupy_cell(Side * side,int u,int x,int y)965 side_thinks_type_can_occupy_cell(Side *side, int u, int x, int y)
966 {
967 int t = terrain_at(x, y), u2, u3, numthistype = 0, fullness = 0;
968 UnitView *uview2;
969
970 if (t_capacity(t) <= 0 && ut_capacity_x(u, t) <= 0) {
971 return FALSE;
972 }
973 if (toc_numtypes == NULL) {
974 toc_numtypes = (int *) xmalloc(numutypes * sizeof(int));
975 }
976 for_all_unit_types(u3) {
977 toc_numtypes[u3] = 0;
978 }
979 for_all_view_stack(side, x, y, uview2) {
980 u2 = uview2->type;
981 ++toc_numtypes[u2];
982 if (u2 == u) {
983 ++numthistype;
984 }
985 /* Only count against fullness if exclusive capacity exceeded. */
986 if (toc_numtypes[u2] > ut_capacity_x(u2, t)) {
987 fullness += ut_size(u2, t);
988 }
989 }
990 /* Unit can be in this cell if there is dedicated space. */
991 if (numthistype + 1 <= ut_capacity_x(u, t)) {
992 return TRUE;
993 }
994 /* Otherwise decide on the basis of fullness. */
995 if (fullness + ut_size(u, t) <= t_capacity(t)) {
996 return TRUE;
997 }
998 return FALSE;
999 }
1000
1001 int
type_can_occupy_empty_cell(int u,int x,int y)1002 type_can_occupy_empty_cell(int u, int x, int y)
1003 {
1004 int t = terrain_at(x, y);
1005
1006 return type_can_occupy_terrain(u, t);
1007 }
1008
1009 int
type_can_occupy_terrain(int u,int t)1010 type_can_occupy_terrain(int u, int t)
1011 {
1012 if (t_capacity(t) >= ut_size(u, t))
1013 return TRUE;
1014 if (ut_capacity_x(u, t) > 0)
1015 return TRUE;
1016 return FALSE;
1017 }
1018
1019 /* Similar, but don't count a specific given unit when calculating. */
1020 /* (should share with can_occupy_cell, make unit3 be optional arg?) */
1021
1022 int
can_occupy_cell_without(Unit * unit,int x,int y,Unit * unit3)1023 can_occupy_cell_without(Unit *unit, int x, int y, Unit *unit3)
1024 {
1025 return type_can_occupy_cell_without(unit->type, x, y, unit3);
1026 }
1027
1028 static int *tocw_numtypes;
1029
1030 int
type_can_occupy_cell_without(int u,int x,int y,Unit * unit3)1031 type_can_occupy_cell_without(int u, int x, int y, Unit *unit3)
1032 {
1033 int t = terrain_at(x, y), u2, u3, numthistype = 0, fullness = 0;
1034 Unit *unit2;
1035
1036 if (t_capacity(t) <= 0 && ut_capacity_x(u, t) <= 0) {
1037 return FALSE;
1038 }
1039 if (tocw_numtypes == NULL) {
1040 tocw_numtypes = (int *) xmalloc(numutypes * sizeof(int));
1041 }
1042 for_all_unit_types(u3) {
1043 tocw_numtypes[u3] = 0;
1044 }
1045 for_all_stack(x, y, unit2) {
1046 /* This is the only way this function differs from type_can_occupy_cell. */
1047 if (unit2 == unit3) {
1048 continue;
1049 }
1050 u2 = unit2->type;
1051 ++tocw_numtypes[u2];
1052 if (u2 == u) {
1053 ++numthistype;
1054 }
1055 /* Only count against fullness if exclusive capacity exceeded. */
1056 if (tocw_numtypes[u2] > ut_capacity_x(u2, t)) {
1057 fullness += ut_size(u2, t);
1058 }
1059 }
1060 /* Unit can be in this cell if there is dedicated space. */
1061 if (numthistype + 1 <= ut_capacity_x(u, t)) {
1062 return TRUE;
1063 }
1064 /* Otherwise decide on the basis of fullness. */
1065 if (fullness + ut_size(u, t) <= t_capacity(t)) {
1066 return TRUE;
1067 }
1068 return FALSE;
1069 }
1070
1071 /* Tests if side can put a new unit at (x, y) either in the terrain or within
1072 a friendly unit. Tests both for survival and capacity, unlike the can_occupy
1073 functions. Intended for use when creating new units rather than moving an
1074 existing unit, therefore does not test if the type can also enter the cell or
1075 one of the stack units. */
1076
1077 int
side_can_put_type_at(Side * side,int u,int x,int y)1078 side_can_put_type_at(Side *side, int u, int x, int y)
1079 {
1080 Unit *unit;
1081
1082 /* First test if the new unit can sit in the terrain. */
1083 if (type_can_occupy_cell(u, x, y)
1084 && type_survives_in_cell(u, x, y)) {
1085 return TRUE;
1086 }
1087 /* Then test if it can sit within an existing friendly unit. */
1088 for_all_stack_with_occs(x, y, unit) {
1089 if (enemy_side(unit->side, side)) {
1090 continue;
1091 }
1092 if (type_can_occupy(u, unit)) {
1093 return TRUE;
1094 }
1095 }
1096 return FALSE;
1097 }
1098
1099 /* Same as above but checks for capacity rather than actual space.
1100 Intended for path-finiding etc. where space may become available
1101 while the unit is on its way there. Does however check for actual
1102 space if immobile units are present. */
1103
1104 int
side_thinks_it_can_put_type_at(Side * side,int u,int x,int y)1105 side_thinks_it_can_put_type_at(Side *side, int u, int x, int y)
1106 {
1107 UnitView *uview;
1108
1109 /* If we don't know what's out there, everything is possible.
1110 This "blissful ignorance" rule has some weird consequences,
1111 but it is necessary to avoid cheating. */
1112 if (!terrain_visible(side, x, y)) {
1113 return TRUE;
1114 }
1115 /* First test if the side thinks the new unit can sit in the terrain. */
1116 if (side_thinks_type_can_occupy_cell(side, u, x, y)
1117 && type_survives_in_cell(u, x, y)) {
1118 return TRUE;
1119 }
1120 /* Then test if the side thinks it can sit within a friendly unit. */
1121 for_all_view_stack(side, x, y, uview) {
1122 if (enemy_side(side_n(uview->siden), side)) {
1123 continue;
1124 }
1125 if (side_thinks_type_can_occupy(side, u, uview)) {
1126 return TRUE;
1127 }
1128 }
1129 return FALSE;
1130 }
1131
1132 /* Same as above but tests for room in the absence of a particular
1133 unit (usually the creator). */
1134
1135 int
side_can_put_type_at_without(Side * side,int u,int x,int y,Unit * unit)1136 side_can_put_type_at_without(Side *side, int u, int x, int y, Unit *unit)
1137 {
1138 Unit *unit2;
1139
1140 /* First test if the new unit can sit in the terrain. */
1141 if (type_can_occupy_cell_without(u, x, y, unit)
1142 && type_survives_in_cell(u, x, y)) {
1143 return TRUE;
1144 }
1145 /* Then test if it can sit within an existing friendly unit. */
1146 for_all_stack_with_occs(x, y, unit2) {
1147 if (enemy_side(unit2->side, side)) {
1148 continue;
1149 }
1150 if (type_can_occupy_without(u, unit2, unit)) {
1151 return TRUE;
1152 }
1153 }
1154 return FALSE;
1155 }
1156
1157 int
side_thinks_it_can_put_type_at_without(Side * side,int u,int x,int y,Unit * unit)1158 side_thinks_it_can_put_type_at_without(Side *side, int u, int x, int y, Unit *unit)
1159 {
1160 UnitView *uview;
1161
1162 /* First test if the new unit can sit in the terrain. */
1163 if (type_can_occupy_cell_without(u, x, y, unit)
1164 && type_survives_in_cell(u, x, y)) {
1165 return TRUE;
1166 }
1167 /* Then test if it can sit within an existing friendly unit. */
1168 for_all_view_stack_with_occs(side, x, y, uview) {
1169 if (enemy_side(side_n(uview->siden), side)) {
1170 continue;
1171 }
1172 if (side_thinks_type_can_occupy_without(u, uview, unit)) {
1173 return TRUE;
1174 }
1175 }
1176 return FALSE;
1177 }
1178
1179 /* Recursive helper to update everybody's position. This should be one of
1180 two routines that modify actual unit positions (leaving is the other). */
1181
1182 void
enter_cell_aux(Unit * unit,int x,int y)1183 enter_cell_aux(Unit *unit, int x, int y)
1184 {
1185 int u = unit->type;
1186 Unit *occ;
1187
1188 #ifdef DEBUGGING
1189 /* Not necessarily an error, but indicative of bugs elsewhere. */
1190 if (unit->x >= 0 || unit->y >= 0) {
1191 run_warning("unit %d occupying cell (%d, %d), was at (%d %d)",
1192 unit->id, x, y, unit->x, unit->y);
1193 }
1194 #endif /* DEBUGGING */
1195 if (!in_area(x, y))
1196 run_error("trying to enter cell outside world");
1197 /* Actually set the unit position. */
1198 set_unit_position(unit, x, y, unit->z);
1199 /* Increment viewing coverage. */
1200 cover_area(unit->side, unit, unit->transport, -1, -1, x, y);
1201 /* If vision range is 0, allow glimpses of adjacent cell terrain.
1202 This applies to terrain only, adjacent units cannot be seen. */
1203 if (u_vision_range(u) == 0)
1204 glimpse_adjacent_terrain(unit);
1205 /* Do for all the occupants too, recursively. */
1206 for_all_occupants(unit, occ) {
1207 enter_cell_aux(occ, x, y);
1208 }
1209 }
1210
1211 /* Decide whether the given unit can actually be in the given transport. */
1212 /* (this still needs to account for multipart units) */
1213
1214 /* The following three functions all consider a real transport and now
1215 call the same function (type_can_occupy) to do the work. */
1216
1217 int
can_occupy(Unit * unit,Unit * transport)1218 can_occupy(Unit *unit, Unit *transport)
1219 {
1220 /* Intercept nonsensical arguments. */
1221 if (transport == unit)
1222 return FALSE;
1223 return type_can_occupy(unit->type, transport);
1224 }
1225
1226 int
type_can_occupy(int u,Unit * transport)1227 type_can_occupy(int u, Unit *transport)
1228 {
1229 int utransport = transport->type, u3, o, space = 0;
1230 int numthistype = 0, numalltypes = 0, occvolume = 0;
1231 int numfacilities = 0;
1232 int nummobiles = 0;
1233 int ucap, uucap;
1234 Unit *occ;
1235
1236 /* Don't allow occupation of incomplete transports unless the unit is
1237 of a type that can help complete or the transport self-builds. Note:
1238 this test is questionable, but keep for now after fixing self-build
1239 bug. */
1240 if (!completed(transport)
1241 && uu_acp_to_build(u, utransport) < 1
1242 && u_cp_per_self_build(utransport) < 1) {
1243 return FALSE;
1244 }
1245 ucap = u_capacity(utransport);
1246 uucap = uu_capacity_x(utransport, u);
1247 if (ucap <= 0 && uucap <= 0)
1248 return FALSE;
1249 for_all_unit_types(u3)
1250 tmp_u_array[u3] = 0;
1251 /* Compute the transport's fullness. */
1252 for_all_occupants(transport, occ) {
1253 o = occ->type;
1254 ++numalltypes;
1255 ++tmp_u_array[occ->type];
1256 if (o == u)
1257 ++numthistype;
1258 if (u_facility(o))
1259 ++numfacilities;
1260 if (mobile(o))
1261 ++nummobiles;
1262 /* Only count against fullness if exclusive capacity exceeded. */
1263 if (tmp_u_array[o] > uu_capacity_x(utransport, o)) {
1264 occvolume += uu_size(o, utransport);
1265 }
1266 }
1267
1268 /* It is not very logical that dedicated space is not counted when we
1269 consider the upper limit on the total number of occupants (either of
1270 this type or in general). However, since the code works like this,
1271 games that use dedicated space hopefully take it into account. HR. */
1272
1273 /* Can carry if dedicated space available. */
1274 if (numthistype + 1 <= uucap)
1275 return TRUE;
1276 /* Check upper limit on count of occupants of this type. */
1277 if (uu_occ_max(utransport, u) >= 0
1278 && numthistype + 1 - uucap > uu_occ_max(utransport, u))
1279 return FALSE;
1280 /* Check upper limit on number of facilities. */
1281 if (u_facility_total_max(utransport) >= 0
1282 && u_facility(u)
1283 && numfacilities + 1 > u_facility_total_max(utransport))
1284 return FALSE;
1285 /* Check upper limit on number of mobiles. */
1286 if (u_mobile_total_max(utransport) >= 0
1287 && mobile(u)
1288 && nummobiles + 1 > u_mobile_total_max(utransport))
1289 return FALSE;
1290 /* Check upper limit on count of occupants of all types. */
1291 if (u_occ_total_max(utransport) >= 0
1292 && numalltypes + 1 > u_occ_total_max(utransport))
1293 return FALSE;
1294 /* Can carry if general unit hold has room. */
1295 space = (occvolume + uu_size(u, utransport) <= ucap);
1296 return space;
1297 }
1298
1299 int
side_thinks_type_can_occupy(Side * side,int u,UnitView * transport)1300 side_thinks_type_can_occupy(Side *side, int u, UnitView *transport)
1301 {
1302 int utransport = transport->type, u3, o, space = 0;
1303 int numthistype = 0, numalltypes = 0, occvolume = 0;
1304 int numfacilities = 0;
1305 int nummobiles = 0;
1306 int ucap, uucap;
1307 UnitView *occ;
1308
1309 /* Don't allow occupation of incomplete transports unless the unit is
1310 of a type that can help complete or the transport self-builds. Note:
1311 this test is questionable, but keep for now after fixing self-build
1312 bug. */
1313 if (!transport->complete
1314 && uu_acp_to_build(u, utransport) < 1
1315 && u_cp_per_self_build(utransport) < 1) {
1316 return FALSE;
1317 }
1318 ucap = u_capacity(utransport);
1319 uucap = uu_capacity_x(utransport, u);
1320 if (ucap <= 0 && uucap <= 0)
1321 return FALSE;
1322 for_all_unit_types(u3)
1323 tmp_u_array[u3] = 0;
1324 /* Compute the transport's fullness. */
1325 for_all_occupant_views(transport, occ) {
1326 o = occ->type;
1327 ++numalltypes;
1328 ++tmp_u_array[occ->type];
1329 if (o == u)
1330 ++numthistype;
1331 if (u_facility(o))
1332 ++numfacilities;
1333 if (mobile(o))
1334 ++nummobiles;
1335 /* Only count against fullness if exclusive capacity exceeded. */
1336 if (tmp_u_array[o] > uu_capacity_x(utransport, o)) {
1337 occvolume += uu_size(o, utransport);
1338 }
1339 }
1340
1341 /* It is not very logical that dedicated space is not counted when we
1342 consider the upper limit on the total number of occupants (either of
1343 this type or in general). However, since the code works like this,
1344 games that use dedicated space hopefully take it into account. HR. */
1345
1346 /* Can carry if dedicated space available. */
1347 if (numthistype + 1 <= uucap)
1348 return TRUE;
1349 /* Check upper limit on count of occupants of this type. */
1350 if (uu_occ_max(utransport, u) >= 0
1351 && numthistype + 1 - uucap > uu_occ_max(utransport, u))
1352 return FALSE;
1353 /* Check upper limit on number of facilities. */
1354 if (u_facility_total_max(utransport) >= 0
1355 && u_facility(u)
1356 && numfacilities + 1 > u_facility_total_max(utransport))
1357 return FALSE;
1358 /* Check upper limit on number of mobiles. */
1359 if (u_mobile_total_max(utransport) >= 0
1360 && mobile(u)
1361 && nummobiles + 1 > u_mobile_total_max(utransport))
1362 return FALSE;
1363 /* Check upper limit on count of occupants of all types. */
1364 if (u_occ_total_max(utransport) >= 0
1365 && numalltypes + 1 > u_occ_total_max(utransport))
1366 return FALSE;
1367 /* Can carry if general unit hold has room. */
1368 space = (occvolume + uu_size(u, utransport) <= ucap);
1369 return space;
1370 }
1371
1372 /* This function a clone of type_can_occupy which ignores a specific
1373 unit (usually the creator) when testing for room. */
1374
1375 int
type_can_occupy_without(int u,Unit * transport,Unit * unit)1376 type_can_occupy_without(int u, Unit *transport, Unit *unit)
1377 {
1378 int utransport = transport->type, u3, o, space = 0;
1379 int numthistype = 0, numalltypes = 0, occvolume = 0;
1380 int numfacilities = 0;
1381 int nummobiles = 0;
1382 int ucap, uucap;
1383 Unit *occ;
1384
1385 /* Don't allow occupation of incomplete transports unless the unit is
1386 of a type that can help complete or the transport self-builds. Note:
1387 this test is questionable, but keep for now after fixing self-build
1388 bug. */
1389 if (!completed(transport)
1390 && uu_acp_to_build(u, utransport) < 1
1391 && u_cp_per_self_build(utransport) < 1) {
1392 return FALSE;
1393 }
1394 ucap = u_capacity(utransport);
1395 uucap = uu_capacity_x(utransport, u);
1396 if (ucap <= 0 && uucap <= 0)
1397 return FALSE;
1398 for_all_unit_types(u3)
1399 tmp_u_array[u3] = 0;
1400 /* Compute the transport's fullness. */
1401 for_all_occupants(transport, occ) {
1402 /* This is the only way this function differs from type_can_occupy. */
1403 if (occ == unit) {
1404 continue;
1405 }
1406 o = occ->type;
1407 ++numalltypes;
1408 ++tmp_u_array[occ->type];
1409 if (o == u)
1410 ++numthistype;
1411 if (u_facility(o))
1412 ++numfacilities;
1413 if (mobile(o))
1414 ++nummobiles;
1415 /* Only count against fullness if exclusive capacity exceeded. */
1416 if (tmp_u_array[o] > uu_capacity_x(utransport, o)) {
1417 occvolume += uu_size(o, utransport);
1418 }
1419 }
1420
1421 /* It is not very logical that dedicated space is not counted when we
1422 consider the upper limit on the total number of occupants (either of
1423 this type or in general). However, since the code works like this,
1424 games that use dedicated space hopefully take it into account. HR. */
1425
1426 /* Can carry if dedicated space available. */
1427 if (numthistype + 1 <= uucap)
1428 return TRUE;
1429 /* Check upper limit on count of occupants of this type. */
1430 if (uu_occ_max(utransport, u) >= 0
1431 && numthistype + 1 - uucap > uu_occ_max(utransport, u))
1432 return FALSE;
1433 /* Check upper limit on number of facilities. */
1434 if (u_facility_total_max(utransport) >= 0
1435 && u_facility(u)
1436 && numfacilities + 1 > u_facility_total_max(utransport))
1437 return FALSE;
1438 /* Check upper limit on number of mobiles. */
1439 if (u_mobile_total_max(utransport) >= 0
1440 && mobile(u)
1441 && nummobiles + 1 > u_mobile_total_max(utransport))
1442 return FALSE;
1443 /* Check upper limit on count of occupants of all types. */
1444 if (u_occ_total_max(utransport) >= 0
1445 && numalltypes + 1 > u_occ_total_max(utransport))
1446 return FALSE;
1447 /* Can carry if general unit hold has room. */
1448 space = (occvolume + uu_size(u, utransport) <= ucap);
1449 return space;
1450 }
1451
1452 int
side_thinks_type_can_occupy_without(int u,UnitView * transport,Unit * unit)1453 side_thinks_type_can_occupy_without(int u, UnitView *transport, Unit *unit)
1454 {
1455 int utransport = transport->type, u3, o, space = 0;
1456 int numthistype = 0, numalltypes = 0, occvolume = 0;
1457 int numfacilities = 0;
1458 int nummobiles = 0;
1459 int ucap, uucap;
1460 UnitView *occ;
1461
1462 /* Don't allow occupation of incomplete transports unless the unit is
1463 of a type that can help complete or the transport self-builds. Note:
1464 this test is questionable, but keep for now after fixing self-build
1465 bug. */
1466 if (!transport->complete
1467 && uu_acp_to_build(u, utransport) < 1
1468 && u_cp_per_self_build(utransport) < 1) {
1469 return FALSE;
1470 }
1471 ucap = u_capacity(utransport);
1472 uucap = uu_capacity_x(utransport, u);
1473 if (ucap <= 0 && uucap <= 0)
1474 return FALSE;
1475 for_all_unit_types(u3)
1476 tmp_u_array[u3] = 0;
1477 /* Compute the transport's fullness. */
1478 for_all_occupant_views(transport, occ) {
1479 /* This is the only way this function differs from type_can_occupy. */
1480 if (view_unit(occ) == unit) {
1481 continue;
1482 }
1483 o = occ->type;
1484 ++numalltypes;
1485 ++tmp_u_array[occ->type];
1486 if (o == u)
1487 ++numthistype;
1488 if (u_facility(o))
1489 ++numfacilities;
1490 if (mobile(o))
1491 ++nummobiles;
1492 /* Only count against fullness if exclusive capacity exceeded. */
1493 if (tmp_u_array[o] > uu_capacity_x(utransport, o)) {
1494 occvolume += uu_size(o, utransport);
1495 }
1496 }
1497
1498 /* It is not very logical that dedicated space is not counted when we
1499 consider the upper limit on the total number of occupants (either of
1500 this type or in general). However, since the code works like this,
1501 games that use dedicated space hopefully take it into account. HR. */
1502
1503 /* Can carry if dedicated space available. */
1504 if (numthistype + 1 <= uucap)
1505 return TRUE;
1506 /* Check upper limit on count of occupants of this type. */
1507 if (uu_occ_max(utransport, u) >= 0
1508 && numthistype + 1 - uucap > uu_occ_max(utransport, u))
1509 return FALSE;
1510 /* Check upper limit on number of facilities. */
1511 if (u_facility_total_max(utransport) >= 0
1512 && u_facility(u)
1513 && numfacilities + 1 > u_facility_total_max(utransport))
1514 return FALSE;
1515 /* Check upper limit on number of mobiles. */
1516 if (u_mobile_total_max(utransport) >= 0
1517 && mobile(u)
1518 && nummobiles + 1 > u_mobile_total_max(utransport))
1519 return FALSE;
1520 /* Check upper limit on count of occupants of all types. */
1521 if (u_occ_total_max(utransport) >= 0
1522 && numalltypes + 1 > u_occ_total_max(utransport))
1523 return FALSE;
1524 /* Can carry if general unit hold has room. */
1525 space = (occvolume + uu_size(u, utransport) <= ucap);
1526 return space;
1527 }
1528
1529 /* This function is special in that it considers only the type of the
1530 transport (which has not been created yet). It is a clone of
1531 type_can_occupy which assumes that no other occs exist. */
1532
1533 int
type_can_occupy_empty_type(int u,int u2)1534 type_can_occupy_empty_type(int u, int u2)
1535 {
1536 int ucap, uucap, space = 0;
1537
1538 ucap = u_capacity(u2);
1539 uucap = uu_capacity_x(u2, u);
1540 if (ucap <= 0 && uucap <= 0)
1541 return FALSE;
1542
1543 /* It is not very logical that dedicated space is not counted when we
1544 consider the upper limit on the total number of occupants (either of
1545 this type or in general). However, since the code works like this,
1546 games that use dedicated space hopefully take it into account. HR. */
1547
1548 /* Can carry if dedicated space available. */
1549 if (1 <= uucap)
1550 return TRUE;
1551 /* Check upper limit on count of occupants of this type. */
1552 if (uu_occ_max(u2, u) >= 0
1553 && 1 - uucap > uu_occ_max(u2, u))
1554 return FALSE;
1555 /* Check upper limit on number of facilities. */
1556 if (u_facility_total_max(u2) >= 0
1557 && u_facility(u)
1558 && 1 > u_facility_total_max(u2))
1559 return FALSE;
1560 /* Check upper limit on number of mobiles. */
1561 if (u_mobile_total_max(u2) >= 0
1562 && mobile(u)
1563 && 1 > u_mobile_total_max(u2))
1564 return FALSE;
1565 /* Check upper limit on count of occupants of all types. */
1566 if (u_occ_total_max(u2) >= 0
1567 && 1 > u_occ_total_max(u2))
1568 return FALSE;
1569 /* Can carry if general unit hold has room. */
1570 space = (uu_size(u, u2) <= ucap);
1571 return space;
1572 }
1573
1574 /* Tests if type can have any occupants at all. */
1575
1576 int
type_can_have_occs(int u)1577 type_can_have_occs(int u)
1578 {
1579 int u2;
1580
1581 for_all_unit_types(u2) {
1582 if (could_carry(u, u2))
1583 return TRUE;
1584 }
1585 return FALSE;
1586 }
1587
1588 /* Find out if an unit is in the correct position in a stack
1589 (cell or transport), relative to another unit. */
1590
1591 int
is_at_correct_ustack_position(Unit * unit,Unit * unit2)1592 is_at_correct_ustack_position(Unit *unit, Unit *unit2)
1593 {
1594 int u = NONUTYPE, u2 = NONUTYPE;
1595 int uso = -1, u2so = -1;
1596
1597 assert_error(unit && alive(unit),
1598 "Attempted to place a dead unit in a ustack");
1599 assert_error(unit2 && alive(unit2),
1600 "Attempted to compare an unit to a dead unit");
1601 u = unit->type;
1602 u2 = unit2->type;
1603 uso = u_stack_order(u);
1604 u2so = u_stack_order(u2);
1605 /* Enforce side ordering 1st. */
1606 if (unit->side) {
1607 if (unit2->side) {
1608 if (unit->side->id > unit2->side->id)
1609 return FALSE;
1610 if (unit->side->id < unit2->side->id)
1611 return TRUE;
1612 }
1613 else
1614 return FALSE;
1615 }
1616 else {
1617 if (unit2->side)
1618 return TRUE;
1619 }
1620 /* Enforce stack ordering 2nd. */
1621 if (uso < u2so)
1622 return FALSE;
1623 if (uso > u2so)
1624 return TRUE;
1625 /* Enforce utype ordering 3rd. */
1626 if (u > u2)
1627 return FALSE;
1628 if (u < u2)
1629 return TRUE;
1630 /* Enforce unit ID ordering 4th. */
1631 if (unit->id < unit2->id)
1632 return TRUE;
1633 return FALSE;
1634 }
1635
1636 /* Units become occupants by linking into the transport's occupant list. */
1637
1638 void
enter_transport(Unit * unit,Unit * transport)1639 enter_transport(Unit *unit, Unit *transport)
1640 {
1641 assert_error(unit && alive(unit),
1642 "Attempted to enter a dead unit into a transport");
1643 assert_error(transport && alive(transport),
1644 "Attempted to enter an unit into a dead transport");
1645 assert_error(unit != transport, "Attempted to enter an unit into itself");
1646 /* Don't enter transport if there is no room. */
1647 if (!can_occupy(unit, transport)) {
1648 /* Disband the unit if it is incomplete. */
1649 if (!completed(unit))
1650 notify(unit->side, "%s is full. New unit disbanded on creation.",
1651 transport->name);
1652 kill_unit(unit, H_UNIT_DISBANDED);
1653 return;
1654 }
1655 /* Add unit to transport's ustack. */
1656 add_unit_to_ustack(unit, transport);
1657 /* Point from the unit back to its transport. */
1658 unit->transport = transport;
1659 /* If the transport is not yet on the map (such as when patching
1660 object refs during readin), skip anything that needs the transport's
1661 location. It will be handled when the transport is placed. */
1662 if (inside_area(transport->x, transport->y)) {
1663 /* Set the passenger's coords to match the transport's. */
1664 enter_cell_aux(unit, transport->x, transport->y);
1665 /* Others might be watching. */
1666 all_see_occupy(unit, transport->x, transport->y, FALSE);
1667 }
1668 }
1669
1670 /* Unit departs from a cell by zeroing out pointer if in cell or by being
1671 removed from the list of transport occupants. */
1672
1673 /* Dead units (hp = 0) may be run through here, so don't error out. */
1674
1675 void
leave_cell(Unit * unit)1676 leave_cell(Unit *unit)
1677 {
1678 int ux = unit->x, uy = unit->y;
1679 Unit *transport = unit->transport;
1680
1681 if (ux < 0 || uy < 0) {
1682 /* Sometimes called twice */
1683 } else if (transport != NULL) {
1684 leave_transport(unit);
1685 leave_cell_aux(unit, transport);
1686 all_see_leave(unit, ux, uy, FALSE);
1687 /* not all_see_cell here because can't see inside transports */
1688 update_unit_display(transport->side, transport, TRUE);
1689 } else {
1690 remove_unit_from_ustack(unit);
1691 /* Now bash the coords. */
1692 leave_cell_aux(unit, NULL);
1693 /* Now let everybody observe that the unit is gone. */
1694 all_see_leave(unit, ux, uy, TRUE);
1695 }
1696 }
1697
1698 /* When leaving, remove view coverage, record old position, and then
1699 trash the old coordinates just in case. Catches many bugs. Do
1700 this for all the occupants as well. */
1701
1702 static void
leave_cell_aux(Unit * unit,Unit * oldtransport)1703 leave_cell_aux(Unit *unit, Unit *oldtransport)
1704 {
1705 Unit *occ;
1706
1707 if (unit->x < 0 && unit->y < 0)
1708 run_warning("unit %s has already left the cell", unit_desig(unit));
1709 /* Stash the old coords. */
1710 unit->prevx = unit->x; unit->prevy = unit->y;
1711 /* Set to a recognizable value. */
1712 unit->x = -1; unit->y = -1;
1713 /* Make any occupants leave too. */
1714 for_all_occupants(unit, occ) {
1715 leave_cell_aux(occ, unit);
1716 }
1717 /* Decrement viewing coverage around our old location. */
1718 cover_area(unit->side, unit, oldtransport, unit->prevx, unit->prevy, -1, -1);
1719 }
1720
1721 /* Disembarking unlinks from the list of passengers only, leaves the unit
1722 hanging in limbo, so should have it occupy something immediately. */
1723
1724 void
leave_transport(Unit * unit)1725 leave_transport(Unit *unit)
1726 {
1727 Unit *transport = unit->transport, *occ;
1728
1729 if (unit == transport) {
1730 run_error("Unit is trying to leave itself");
1731 }
1732 if (unit == transport->occupant) {
1733 transport->occupant = unit->nexthere;
1734 } else {
1735 for_all_occupants(transport, occ) {
1736 if (unit == occ->nexthere) {
1737 occ->nexthere = occ->nexthere->nexthere;
1738 break;
1739 }
1740 }
1741 }
1742 /* Bash the now-spurious link. */
1743 unit->transport = NULL;
1744 }
1745
1746 int
change_cell(Unit * unit,int x,int y)1747 change_cell(Unit *unit, int x, int y)
1748 {
1749 int ux = unit->x, uy = unit->y;
1750 Unit *transport = unit->transport;
1751
1752 /* Always check this one, but not necessarily fatal. */
1753 if (!inside_area(x, y)) {
1754 run_warning("No cell at %d,%d, %s can't enter it",
1755 x, y, unit_desig(unit));
1756 /* Let the unit remain off-world. */
1757 return FALSE;
1758 }
1759 if (!type_can_occupy_cell(unit->type, x, y)) {
1760 run_warning("Cell at %d,%d is too full for %s",
1761 x, y, unit_desig(unit));
1762 /* Let the unit remain off-world. */
1763 return FALSE;
1764 }
1765 if (transport != NULL) {
1766 leave_transport(unit);
1767 update_unit_display(transport->side, transport, TRUE);
1768 } else {
1769 remove_unit_from_ustack(unit);
1770 }
1771 add_unit_to_ustack(unit, x, y);
1772 change_cell_aux(unit, ux, uy, x, y);
1773 all_see_leave(unit, ux, uy, (transport == NULL));
1774 /* Inevitable side-effect of appearing in the new location. */
1775 all_see_occupy(unit, x, y, TRUE);
1776 return TRUE;
1777 }
1778
1779 void
set_unit_position(Unit * unit,int x,int y,int z)1780 set_unit_position(Unit *unit, int x, int y, int z)
1781 {
1782 int u, t, tmpz;
1783
1784 /* Actually set the unit position. */
1785 unit->x = x; unit->y = y; unit->z = z;
1786 /* Constrain the altitude according to terrain if nonzero. */
1787 if (unit->z != 0) {
1788 if ((unit->z & 1) == 0) {
1789 u = unit->type;
1790 t = terrain_at(x, y);
1791 tmpz = unit->z / 2;
1792 tmpz = min(tmpz, ut_alt_max(u, t));
1793 tmpz = max(tmpz, ut_alt_min(u, t));
1794 unit->z = tmpz * 2;
1795 } else {
1796 /* (should adjust connection type?) */
1797 }
1798 }
1799 }
1800
1801 static void
change_cell_aux(Unit * unit,int x0,int y0,int x,int y)1802 change_cell_aux(Unit *unit, int x0, int y0, int x, int y)
1803 {
1804 int u = unit->type;
1805 Unit *occ;
1806
1807 /* Stash the old coords. */
1808 unit->prevx = x0; unit->prevy = y0;
1809 set_unit_position(unit, x, y, unit->z);
1810 /* Change viewing coverage. */
1811 cover_area(unit->side, unit, unit->transport, x0, y0, x, y);
1812 /* If vision range is 0, allow glimpses of adjacent cell terrain.
1813 This applies to terrain only, adjacent units cannot be seen. */
1814 if (u_vision_range(u) == 0)
1815 glimpse_adjacent_terrain(unit);
1816 /* Do for all the occupants too, recursively. */
1817 for_all_occupants(unit, occ) {
1818 change_cell_aux(occ, x0, y0, x, y);
1819 }
1820 }
1821
1822 /* Splice the unit into the given transport's ustack. */
1823
1824 void
add_unit_to_ustack(Unit * unit,Unit * transport)1825 add_unit_to_ustack(Unit *unit, Unit *transport)
1826 {
1827 Unit *topunit = NULL, *unit2 = NULL, *prevunit = NULL, *nextunit = NULL;
1828
1829 assert_error(unit, "Attempted to add a NULL unit to a transport");
1830 assert_error(transport, "Attempted to add an unit to a NULL transport");
1831 topunit = transport->occupant;
1832 if (topunit) {
1833 /* Insert the entering unit into the occupant list at
1834 its correct position. */
1835 for_all_occupants(transport, unit2) {
1836 if (is_at_correct_ustack_position(unit, unit2)) {
1837 nextunit = unit2;
1838 if (unit2 == topunit)
1839 topunit = unit;
1840 break;
1841 }
1842 prevunit = unit2;
1843 }
1844 if (prevunit != NULL)
1845 prevunit->nexthere = unit;
1846 } else {
1847 topunit = unit;
1848 }
1849 unit->nexthere = nextunit;
1850 transport->occupant = topunit;
1851 }
1852
1853 /* Put the given unit into the cell and/or unit stack at the given
1854 location. Do not modify the unit's xyz properties, just the unit
1855 layer and links to other units. */
1856
1857 void
add_unit_to_ustack(Unit * unit,int x,int y)1858 add_unit_to_ustack(Unit *unit, int x, int y)
1859 {
1860 Unit *topunit = NULL, *unit2 = NULL, *prevunit = NULL, *nextunit = NULL;
1861
1862 assert_error(unit, "Attempted to add a NULL unit to a location");
1863 assert_error(inside_area(x, y),
1864 "Attempted to an unit outside the playing area");
1865 topunit = unit_at(x, y);
1866 if (topunit) {
1867 /* Insert the entering unit into the stack at its correct position. */
1868 for_all_stack(x, y, unit2) {
1869 if (is_at_correct_ustack_position(unit, unit2)) {
1870 nextunit = unit2;
1871 if (unit2 == topunit)
1872 topunit = unit;
1873 break;
1874 }
1875 prevunit = unit2;
1876 }
1877 if (prevunit != NULL)
1878 prevunit->nexthere = unit;
1879 } else {
1880 topunit = unit;
1881 }
1882 unit->nexthere = nextunit;
1883 set_unit_at(x, y, topunit);
1884 }
1885
1886 /* Remove the given unit from the stack at its current location. */
1887
1888 void
remove_unit_from_ustack(Unit * unit)1889 remove_unit_from_ustack(Unit *unit)
1890 {
1891 int ux = unit->x, uy = unit->y;
1892 Unit *other;
1893
1894 /* Unsplice ourselves from the list of units in this cell. */
1895 if (unit == unit_at(ux, uy)) {
1896 set_unit_at(ux, uy, unit->nexthere);
1897 } else {
1898 for_all_stack(ux, uy, other) {
1899 if (unit == other->nexthere) {
1900 other->nexthere = other->nexthere->nexthere;
1901 break;
1902 }
1903 }
1904 }
1905 /* Bash this now-spurious link. */
1906 unit->nexthere = NULL;
1907 }
1908
1909 /* Add only the terrain types of adjacent cells to the unit's side's
1910 view, don't show units or anything else. This is a workaround
1911 for units with a vision range of 0. */
1912
1913 void
glimpse_adjacent_terrain(Unit * unit)1914 glimpse_adjacent_terrain(Unit *unit)
1915 {
1916 int x = unit->x, y = unit->y, dir, x1, y1;
1917 Side *side = unit->side;
1918
1919 if (u_vision_range(unit->type) == 0
1920 && unit->transport == NULL
1921 && !g_see_all()
1922 && !g_terrain_seen()
1923 && side != NULL) {
1924 for_all_directions(dir) {
1925 if (point_in_dir(x, y, dir, &x1, &y1)) {
1926 if (terrain_view(side, x1, y1) == UNSEEN) {
1927 set_terrain_view(side, x1, y1,
1928 buildtview(terrain_at(x1, y1)));
1929 update_cell_display(side, x1, y1,
1930 UPDATE_ALWAYS | UPDATE_ADJ);
1931 }
1932 }
1933 }
1934 }
1935 }
1936
1937 /* Given an overfull unit, spew out occupants until back within limits. */
1938
1939 static int *num_each_type, *shared_each_type;
1940
1941 static void
eject_excess_occupants(Unit * unit)1942 eject_excess_occupants(Unit *unit)
1943 {
1944 int u, u2 = unit->type, overfull = TRUE, count;
1945 int numalltypes = 0, occvolume = 0;
1946 Unit *occ;
1947
1948 if (num_each_type == NULL)
1949 num_each_type = (int *) xmalloc(numutypes * sizeof(int));
1950 if (shared_each_type == NULL)
1951 shared_each_type = (int *) xmalloc(numutypes * sizeof(int));
1952 for_all_unit_types(u)
1953 num_each_type[u] = shared_each_type[u] = 0;
1954 /* Eject occupants overflowing counts in shared space. */
1955 for_all_occupants(unit, occ)
1956 ++num_each_type[occ->type];
1957 for_all_unit_types(u) {
1958 if (num_each_type[u] > uu_capacity_x(u2, u)) {
1959 shared_each_type[u] = num_each_type[u] - uu_capacity_x(u2, u);
1960 if (uu_occ_max(u2, u) >= 0
1961 && shared_each_type[u] > uu_occ_max(u2, u)) {
1962 count = shared_each_type[u] - uu_occ_max(u2, u);
1963 while (count > 0) {
1964 for_all_occupants(unit, occ) {
1965 if (occ->type == u) {
1966 eject_occupant(unit, occ);
1967 --count;
1968 break;
1969 }
1970 }
1971 }
1972 }
1973 }
1974 }
1975 /* Eject occupants over the total max count allowed. */
1976 for_all_occupants(unit, occ)
1977 ++numalltypes;
1978 if (u_occ_total_max(u2) >= 0 && numalltypes > u_occ_total_max(u2)) {
1979 count = numalltypes - u_occ_total_max(u2);
1980 while (unit->occupant != NULL) {
1981 eject_occupant(unit, unit->occupant);
1982 if (--count <= 0)
1983 break;
1984 }
1985 }
1986 /* Eject occupants overflowing volume of shared space. */
1987 while (overfull) {
1988 for_all_unit_types(u)
1989 num_each_type[u] = 0;
1990 occvolume = 0;
1991 for_all_occupants(unit, occ)
1992 ++num_each_type[occ->type];
1993 for_all_unit_types(u) {
1994 occvolume +=
1995 max(0, num_each_type[u] - uu_capacity_x(u2, u)) * uu_size(u, u2);
1996 }
1997 if (occvolume > u_capacity(u2)) {
1998 overfull = TRUE;
1999 eject_occupant(unit, unit->occupant);
2000 } else {
2001 overfull = FALSE;
2002 }
2003 }
2004 }
2005
2006 /* Given that an occupant must leave its transport, decide what happens; either
2007 move out into the open, into another unit, or vanish. */
2008
2009 void
eject_occupant(Unit * unit,Unit * occ)2010 eject_occupant(Unit *unit, Unit *occ)
2011 {
2012 if (!in_play(unit) || !in_play(occ))
2013 return;
2014 /* If the occupant is mobile and the current cell has room, let it escape
2015 but be stacked in the transport's cell. */
2016 if (mobile(occ->type)
2017 && type_survives_in_cell(occ->type, unit->x, unit->y)
2018 && type_can_occupy_cell(occ->type, unit->x, unit->y)) {
2019 leave_cell(occ);
2020 enter_cell(occ, unit->x, unit->y);
2021 return;
2022 }
2023 /* (should let occupants escape into other units in cell) */
2024 /* (should let occupants with acp escape into adj cells) */
2025 /* Evaporating the occupant is our last option. */
2026 kill_unit(occ, H_UNIT_KILLED);
2027 }
2028
2029 /* Handle the general situation of a unit changing allegiance from one side
2030 to another. This is a common internal routine, so no messages here. */
2031
2032 void
change_unit_side(Unit * unit,Side * newside,int reason,Unit * agent)2033 change_unit_side(Unit *unit, Side *newside, int reason, Unit *agent)
2034 {
2035 using namespace Xconq::AI;
2036
2037 int ux = unit->x, uy = unit->y, lostself = FALSE;
2038 Side *oldside = unit->side;
2039 Unit *occ;
2040 OpRole *oprole = NULL;
2041
2042 if (oldside == newside)
2043 return;
2044 /* Fail if the unit may not be on the new side. */
2045 if (!unit_allowed_on_side(unit, newside))
2046 return;
2047 if (reason >= 0)
2048 record_unit_side_change(unit, newside, (HistEventType)reason, agent);
2049 /* Skip screen updates if the side just lost the game. */
2050 if (reason != H_SIDE_LOST) {
2051 /* Last view of unit on its old side. */
2052 update_unit_display(oldside, unit, TRUE);
2053 }
2054 /* Don't change occupants' side if the transport changed
2055 side due to being wrecked. */
2056 if (reason != H_UNIT_WRECKED
2057 && reason != H_UNIT_WRECKED_IN_ACCIDENT) {
2058 for_all_occupants(unit, occ) {
2059 change_unit_side(occ, newside, reason, agent);
2060 }
2061 }
2062 /* Adjust view coverage. The sequencing here is to make sure that no
2063 viewing coverage gets left on or off inadvertantly. */
2064 if (alive(unit) && inside_area(ux, uy)) {
2065 /* Uncover the current viewed area. */
2066 cover_area(unit->side, unit, unit->transport, ux, uy, -1, -1);
2067 /* Actually set the side slot of the unit here. */
2068 set_unit_side(unit, newside);
2069 // Release the side's operational role for the unit, if necessary.
2070 if (oprole = find_oprole(oldside, unit->id))
2071 release_oprole(oprole);
2072 /* Check if this was a self unit. */
2073 if (oldside->self_unit == unit)
2074 lostself = TRUE;
2075 /* Always redo the unit's number. */
2076 unit->number = 0;
2077 assign_unit_number(unit);
2078 /* Update the cancarry vector if this is a transport. */
2079 if (u_is_transport(unit->type)) {
2080 update_cancarry_vector(unit->side);
2081 }
2082 /* Cover it for the new side now. */
2083 cover_area(unit->side, unit, unit->transport, -1, -1, ux, uy);
2084 /* Skip screen updates if the side just lost the game. */
2085 if (reason != H_SIDE_LOST) {
2086 /* A freebie for the unit's previous side. */
2087 see_exact(oldside, ux, uy);
2088 }
2089 }
2090 /* Handle lost self units. */
2091 if (lostself
2092 /* If we already lost the game, we don't want the fact that our
2093 former units change side being interpreted as capture.
2094 Nor do we want to call side_loses again below. */
2095 && reason != H_SIDE_LOST)
2096 resurrect_self_unit(unit, unit->side, newside);
2097 /* The new side gets to decide the unit's new plans. */
2098 init_unit_plan (unit);
2099 /* Skip screen updates if the side just lost the game. */
2100 if (reason != H_SIDE_LOST) {
2101 /* Now we see the unit as belonging to someone else. */
2102 update_unit_display(oldside, unit, TRUE);
2103 update_unit_display(newside, unit, TRUE);
2104 }
2105 }
2106
2107 /* Attempt to resurrect self as new unit. Handle the consequences of
2108 failing to do so. */
2109
2110 void
resurrect_self_unit(Unit * unit,Side * oldside,Side * newside)2111 resurrect_self_unit(Unit *unit, Side *oldside, Side *newside)
2112 {
2113 char unitname[BUFSIZE];
2114 char unitname2[BUFSIZE];
2115 char newsidename[BUFSIZE];
2116 char oldsidename[BUFSIZE];
2117 Unit *unit2 = NULL;
2118
2119 assert_error(unit, "Attempted to access a NULL unit");
2120 assert_error(oldside, "Attempted to access a NULL side");
2121 if (!newside)
2122 newside = oldside;
2123 oldside->self_unit = NULL;
2124 strncpy(unitname, short_unit_handle(unit), BUFSIZE);
2125 strncpy(newsidename, short_side_title(newside), BUFSIZE);
2126 strncpy(oldsidename, side_adjective(oldside), BUFSIZE);
2127 /* Find a new self unit if possible. */
2128 if (u_self_resurrects(unit->type)) {
2129 for_all_side_units(oldside, unit2) {
2130 if (is_active(unit2)
2131 && u_can_be_self(unit2->type)) {
2132 oldside->self_unit = unit2;
2133 strcpy(unitname2, short_unit_handle(unit2));
2134 break;
2135 }
2136 } /* for all side units */
2137 } /* if self resurrects */
2138 if (oldside->ingame) {
2139 /* Unit was given to or captured by another side. */
2140 if (oldside != newside) {
2141 notify_all(
2142 "THE %s %s %s IS NOW IN THE HANDS OF %s!",
2143 all_capitals(oldsidename),
2144 ((!mobile(unit->type) || u_advanced(unit->type))
2145 ? "CAPITAL" : "LEADER"),
2146 all_capitals(unitname),
2147 all_capitals(newsidename));
2148 }
2149 /* Unit is longer the self unit for some other reason
2150 (change-type, for example). */
2151 else {
2152 notify_all(
2153 "%s NO LONGER IS THE %s OF THE %s SIDE.",
2154 all_capitals(unitname),
2155 ((!mobile(unit->type) || u_advanced(unit->type))
2156 ? "CAPITAL" : "LEADER"),
2157 all_capitals(oldsidename));
2158 }
2159 /* Mention a new self unit, if one was found. */
2160 if (oldside->self_unit) {
2161 notify_all("THE %s LEADERSHIP RELOCATES TO %s!",
2162 all_capitals(oldsidename),
2163 all_capitals(unitname2));
2164 }
2165 /* Handle side loss if no new self unit was found and one is
2166 required. */
2167 else {
2168 if (g_self_required()) {
2169 strcpy(oldsidename, short_side_title(oldside));
2170 if (newside != oldside) {
2171 notify_all("%s HAS BEEN DEFEATED BY %s!",
2172 all_capitals(oldsidename),
2173 all_capitals(newsidename));
2174 side_loses(oldside, newside, -2);
2175 }
2176 else {
2177 notify_all("%s HAS FALLEN!", all_capitals(oldsidename));
2178 side_loses(oldside, NULL, -2);
2179 }
2180 }
2181 }
2182 }
2183 }
2184
2185 /* This is a general test as to whether the given unit can be
2186 on the given side. */
2187
2188 int
unit_allowed_on_side(Unit * unit,Side * side)2189 unit_allowed_on_side(Unit *unit, Side *side)
2190 {
2191 int u;
2192
2193 if (unit == NULL)
2194 return FALSE;
2195 u = unit->type;
2196 return new_unit_allowed_on_side(u, side);
2197 }
2198
2199 /* It is crucial to pass the unit type instead of the unit itself as
2200 argument in cases where the test must be applied before a new unit
2201 is created, to prevent the appearance of independent ghost units
2202 that never got the correct side set. Fortunately, there is no need
2203 to pass a real unit since the test only uses the type. */
2204
2205 int
new_unit_allowed_on_side(int u,Side * side)2206 new_unit_allowed_on_side(int u, Side *side)
2207 {
2208 int u2, sum;
2209
2210 /* Test general limitations on the type. */
2211 if (!type_allowed_on_side(u, side))
2212 return FALSE;
2213 /* Test specific game limits. */
2214 if (u_type_per_side_max(u) >= 0) {
2215 if (side->numunits[u] >= u_type_per_side_max(u))
2216 return FALSE;
2217 }
2218 if (g_units_per_side_max() >= 0) {
2219 sum = 0;
2220 for_all_unit_types(u2) {
2221 sum += side->numunits[u2];
2222 }
2223 if (sum >= g_units_per_side_max())
2224 return FALSE;
2225 }
2226 return TRUE;
2227 }
2228
2229 /* Inability to build a unit should not preclude its capture
2230 etc. Separate calls to has_advance_to_build have therefore been
2231 introduced everywhere in the code. */
2232
2233 int
type_allowed_on_side(int u,Side * side)2234 type_allowed_on_side(int u, Side *side)
2235 {
2236 int u2;
2237 ParamBoxSide paramboxs;
2238
2239 if (side->uavail == NULL) {
2240 side->uavail = (short *) xmalloc(numutypes * sizeof(short));
2241 for_all_unit_types(u2) {
2242 paramboxs.side = side;
2243 side->uavail[u2] =
2244 eval_boolean_expression(u_possible_sides(u2),
2245 fn_test_side_in_sideclass, TRUE,
2246 (ParamBox*)¶mboxs);
2247 }
2248 }
2249 return side->uavail[u];
2250 }
2251
2252 int
type_ever_available(int u,Side * side)2253 type_ever_available(int u, Side *side)
2254 {
2255 int u2 = NONUTYPE, u3 = NONUTYPE, m = NONMTYPE, t = NONTTYPE;
2256 int a = NONATYPE;
2257 Unit *unit;
2258
2259 if (!type_allowed_on_side(u, side))
2260 return FALSE;
2261 for_all_unit_types(u2) {
2262 if (!type_allowed_on_side(u2, side))
2263 continue;
2264 if (could_create(u2, u))
2265 return TRUE;
2266 if (could_capture(u2, u, side))
2267 return TRUE;
2268 if (could_change_type_to(u, u2))
2269 return TRUE;
2270 if (u_wrecked_type(u2) == u)
2271 return TRUE;
2272 if (u_auto_upgrade_to(u2) == u)
2273 return TRUE;
2274 for_all_unit_types(u3) {
2275 if (!type_allowed_on_side(u3, side))
2276 continue;
2277 if (uu_wrecked_type_if_killed(u3, u2) == u)
2278 return TRUE;
2279 }
2280 for_all_material_types(m) {
2281 /* (Should also check to see if utype can actually starve from
2282 need of the material.) */
2283 if (um_wrecked_type_if_starved(u2, m) == u)
2284 return TRUE;
2285 }
2286 for_all_terrain_types(t) {
2287 /* (Should also check to see if utype can actually be on
2288 the damaging terrain.) */
2289 if (ut_wrecked_type_if_attrited(u2, t) == u)
2290 return TRUE;
2291 }
2292 }
2293 for_all_advance_types(a) {
2294 /* Assume that the advance can be researched. */
2295 if (ua_needed_to_build(u, a))
2296 return TRUE;
2297 }
2298 for_all_side_units(side, unit) {
2299 if (unit->type == u)
2300 return TRUE;
2301 }
2302 return FALSE;
2303 }
2304
2305 int
num_sides_allowed(int u)2306 num_sides_allowed(int u)
2307 {
2308 int rslt;
2309 Side *side;
2310
2311 rslt = 0;
2312 for_all_sides(side) {
2313 if (type_allowed_on_side(u, side)) {
2314 ++rslt;
2315 }
2316 }
2317 return rslt;
2318 }
2319
2320 /* Return true if unit1 trusts unit2. */
2321 int
unit_trusts_unit(Unit * unit1,Unit * unit2)2322 unit_trusts_unit(Unit *unit1, Unit *unit2)
2323 {
2324 return (unit1->side == unit2->side
2325 || trusted_side(unit1->side, unit2->side));
2326 }
2327
2328 /* Put the given unit on the given side, without all the fancy
2329 effects. Important to handle independents, because this gets
2330 called during init. This is the only way that a unit's side may be
2331 altered. */
2332
2333 /* Note that this may be run on dead units, as part of clearing out a
2334 side's units, in which case we just want to relink, don't care
2335 about testing whether the type is allowed or not. */
2336
2337 void
set_unit_side(Unit * unit,Side * side)2338 set_unit_side(Unit *unit, Side *side)
2339 {
2340 int u = unit->type;
2341 Side *oldside, *newside;
2342
2343 /* Might not have anything to do. */
2344 if (unit->side == side)
2345 return;
2346 /* Subtract from the counts for the ex-side. */
2347 oldside = unit->side;
2348 if (oldside->numunits)
2349 --(oldside->numunits[u]);
2350 /* Set the unit's slot. */
2351 /* Note that indep units have a NULL side, even though there
2352 is an actual side object for independents. */
2353 unit->side = side;
2354 /* Make sure this unit is off anybody else's list. */
2355 delete_unit(unit);
2356 newside = side;
2357 insert_unit(newside->unithead, unit);
2358 /* Add to counts for the side. */
2359 if (newside->numunits)
2360 ++(newside->numunits[u]);
2361 /* Invalidate both sides' point value caches. */
2362 oldside->point_value_valid = FALSE;
2363 newside->point_value_valid = FALSE;
2364 /* Bump the tech level if owning this type helps. */
2365 if (side != NULL
2366 && side->tech[u] < u_tech_from_ownership(u)) {
2367 side->tech[u] = u_tech_from_ownership(u);
2368 /* (should update any displays of tech - how to ensure?) */
2369 }
2370 }
2371
2372 /* The origside is more of a historical record or cache, doesn't need
2373 the elaboration that unit side change does. */
2374
2375 void
set_unit_origside(Unit * unit,Side * side)2376 set_unit_origside(Unit *unit, Side *side)
2377 {
2378 unit->origside = side;
2379 }
2380
2381 void
set_unit_name(Side * side,Unit * unit,char * newname)2382 set_unit_name(Side *side, Unit *unit, char *newname)
2383 {
2384 /* Always turn 0-length names into NULL. */
2385 if (newname != NULL && strlen(newname) == 0)
2386 newname = NULL;
2387 /* Don't do anything if the name didn't actually change. */
2388 if ((unit->name == NULL && newname == NULL)
2389 || (unit->name != NULL
2390 && newname != NULL
2391 && strcmp(unit->name, newname) == 0))
2392 return;
2393 /* Record this in the history. */
2394 record_unit_name_change(unit, newname);
2395 unit->name = newname;
2396 update_unit_display(side, unit, TRUE);
2397 update_unit_display(unit->side, unit, TRUE);
2398 /* (should also send to any other side directly viewing this unit!) */
2399 }
2400
2401 /* Given an amount to add, add it to the unit's hp, being careful
2402 to check the limits. Expect the caller to update the unit's
2403 display, for instance there may be a health bar to change. */
2404
2405 void
add_to_unit_hp(Unit * unit,int hp)2406 add_to_unit_hp(Unit *unit, int hp)
2407 {
2408 int hpmax;
2409
2410 unit->hp += hp;
2411 hpmax = u_hp(unit->type);
2412 if (unit->hp > hpmax)
2413 unit->hp = hpmax;
2414 unit->hp2 += hp;
2415 if (unit->hp2 > hpmax)
2416 unit->hp2 = hpmax;
2417 }
2418
2419 void
change_morale(Unit * unit,int sign,int morchange)2420 change_morale(Unit *unit, int sign, int morchange)
2421 {
2422 int u = unit->type, oldmorale;
2423
2424 if (morchange != 0) {
2425 oldmorale = unit->morale;
2426 unit->morale += (sign * prob_fraction(morchange));
2427 if (unit->morale < 0)
2428 unit->morale = 0;
2429 if (unit->morale > u_morale_max(u))
2430 unit->morale = u_morale_max(u);
2431 if (unit->morale != oldmorale) {
2432 update_unit_display(unit->side, unit, TRUE);
2433 /* (should also send to any other side directly viewing this unit?) */
2434 }
2435 }
2436 }
2437
2438 int
disband_unit(Side * side,Unit * unit)2439 disband_unit(Side *side, Unit *unit)
2440 {
2441 int rslt;
2442
2443 #ifdef DESIGNERS
2444 if (side->designer) {
2445 return designer_disband(unit);
2446 }
2447 #endif /* DESIGNERS */
2448 if (side_can_disband(side, unit)) {
2449 rslt = disband_unit_directly(side, unit);
2450 if (rslt) {
2451 /* Nothing to do */
2452 } else if (unit->plan) {
2453 set_disband_task(unit);
2454 } else {
2455 /* In order for this to work, we would need a way to direct one
2456 sort of unit to disband another. Just fail for now. */
2457 return FALSE;
2458 }
2459 return TRUE;
2460 } else {
2461 return FALSE;
2462 }
2463 }
2464
2465 int
disband_unit_directly(Side * side,Unit * unit)2466 disband_unit_directly(Side *side, Unit *unit)
2467 {
2468 if (side_can_disband(side, unit)) {
2469 if (!completed(unit)) {
2470 /* Nothing complicated about getting rid of an incomplete unit. */
2471 kill_unit(unit, H_UNIT_DISBANDED);
2472 return TRUE;
2473 } else {
2474 return FALSE;
2475 }
2476 } else {
2477 return FALSE;
2478 }
2479 }
2480
2481 void
wreck_unit(Unit * unit,HistEventType hevttype,WreckType wrecktype,int wreckarg,Unit * agent)2482 wreck_unit(Unit *unit, HistEventType hevttype, WreckType wrecktype,
2483 int wreckarg, Unit *agent)
2484 {
2485 int wreckedutype = NONUTYPE;
2486 int u = NONUTYPE;
2487
2488 assert_error(unit, "Tried to wreck a null unit.");
2489 u = unit->type;
2490 wreckedutype = u_wrecked_type(u);
2491 /* Determine if the unit has a specialized wreck type depending on the
2492 conditions under which it wrecked. */
2493 if (wreckarg > -1) {
2494 switch (wrecktype) {
2495 case WRECK_TYPE_KILLED:
2496 assert_warning_break(is_unit_type(wreckarg),
2497 "Invalid unit type argument in unit wrecking code.");
2498 if (uu_wrecked_type_if_killed(u, wreckarg) != NONUTYPE)
2499 wreckedutype = uu_wrecked_type_if_killed(u, wreckarg);
2500 break;
2501 case WRECK_TYPE_STARVED:
2502 assert_warning_break(is_material_type(wreckarg),
2503 "Invalid material type argument in unit wrecking code.");
2504 if (um_wrecked_type_if_starved(u, wreckarg) != NONUTYPE)
2505 wreckedutype = um_wrecked_type_if_starved(u, wreckarg);
2506 break;
2507 case WRECK_TYPE_ATTRITED:
2508 assert_warning_break(is_terrain_type(wreckarg),
2509 "Invalid terrain type argument in unit wrecking code.");
2510 if (ut_wrecked_type_if_attrited(u, wreckarg) != NONUTYPE)
2511 wreckedutype = ut_wrecked_type_if_attrited(u, wreckarg);
2512 break;
2513 case WRECK_TYPE_UNSPECIFIED: case WRECK_TYPE_ACCIDENT:
2514 case WRECK_TYPE_TERRAIN: case WRECK_TYPE_SIDE_LOST:
2515 default:
2516 break;
2517 }
2518 }
2519 /* Change the unit's type and side. */
2520 change_unit_type(unit, wreckedutype, hevttype,
2521 (agent ? agent->side : NULL));
2522 /* Changing the type will kill the unit if there is no room
2523 for the new type. */
2524 if (alive(unit)) {
2525 /* Restore to default hp for the new type. */
2526 unit->hp = unit->hp2 = u_hp(unit->type);
2527 /* Get rid of occupants if now overfull. */
2528 eject_excess_occupants(unit);
2529 }
2530 }
2531
2532 /* Remove a unit from play. This is different from making it
2533 available for reallocation - only the unit flusher can do that. We
2534 remove all the passengers too, recursively. Sometimes units are
2535 "killed twice", so be sure not to run all this twice. Also count
2536 up occupant deaths, being sure not to count the unit itself as an
2537 occupant. */
2538
2539 void
kill_unit(Unit * unit,int reason)2540 kill_unit(Unit *unit, int reason)
2541 {
2542 int ux = unit->x, uy = unit->y;
2543
2544 if (alive(unit)) {
2545 leave_cell(unit);
2546 /* A freebie for the unit's side. */
2547 see_exact(unit->side, ux, uy);
2548 kill_unit_aux(unit, reason);
2549 }
2550 }
2551
2552 /* Do the self unit specific parts of killing a unit. */
2553 static void
kill_self_unit(Unit * unit,char * unitname)2554 kill_self_unit(Unit *unit, char *unitname)
2555 {
2556 resurrect_self_unit(unit, unit->side, NULL);
2557 #if (0)
2558 int u = unit->type;
2559 char sidename[BUFSIZE];
2560
2561 unit->side->self_unit = NULL;
2562 strcpy(sidename, side_adjective(unit->side));
2563 if (u_self_resurrects(u)) {
2564 /* Find a new self unit if possible. */
2565 Unit *unit2;
2566
2567 for_all_side_units(unit->side, unit2) {
2568 if (is_active(unit2)
2569 && u_can_be_self(unit2->type)) {
2570 char unitname2[BUFSIZE];
2571 unit->side->self_unit = unit2;
2572 strcpy(unitname2, short_unit_handle(unit2));
2573 if (!mobile(unit->type) || u_advanced(unit->type)) {
2574 notify_all("THE %s CAPITAL %s HAS BEEN DESTROYED!",
2575 all_capitals(sidename), all_capitals(unitname));
2576 notify_all("THE %s GOVERNMENT ESCAPES TO %s!",
2577 all_capitals(sidename), all_capitals(unitname2));
2578 } else {
2579 notify_all("THE %s LEADER %s HAS BEEN KILLED!",
2580 all_capitals(sidename), all_capitals(unitname));
2581 notify_all("THE NEW %s LEADER IS %s!",
2582 all_capitals(sidename), all_capitals(unitname2));
2583 }
2584 break;
2585 }
2586 }
2587 }
2588 /* We failed to appoint a new self-unit ... */
2589 if (unit->side->ingame
2590 && unit->side->self_unit == NULL) {
2591 if (!mobile(unit->type) || u_advanced(unit->type)) {
2592 notify_all("THE %s CAPITAL %s HAS BEEN DESTROYED!",
2593 all_capitals(sidename), all_capitals(unitname));
2594 } else {
2595 notify_all("THE %s LEADER %s HAS BEEN KILLED!",
2596 all_capitals(sidename), all_capitals(unitname));
2597 }
2598 /* ... and we really need one. */
2599 if (g_self_required()) {
2600 strcpy(sidename, short_side_title(unit->side));
2601 notify_all("%s HAS LOST THE GAME!", all_capitals(sidename));
2602 /* If the capital/leader has been killed, we lose to NULL, rather
2603 than to the killing side. */
2604 side_loses(unit->side, NULL, -2);
2605 }
2606 }
2607 #endif
2608 }
2609
2610 /* Trash it now - occupant doesn't need to leave_cell. Also record
2611 the event, and update the apropriate display. The unit here should
2612 be known to be alive. */
2613
2614 void
kill_unit_aux(Unit * unit,int reason)2615 kill_unit_aux(Unit *unit, int reason)
2616 {
2617 int u = unit->type;
2618 char unitname[BUFSIZE];
2619 Unit *occ;
2620 Side *side = unit->side;
2621
2622 /* Save this handle before the unit is killed. */
2623 strcpy(unitname, short_unit_handle(unit));
2624 /* Now kill the unit. */
2625 unit->hp = 0;
2626 /* Get rid of the unit's plan/tasks. This should be safe, because
2627 unit death should only happen during action execution and in
2628 between turns, and plans/tasks should not be in use at those times. */
2629 /* Might not be anything to dispose of. */
2630 if (unit->plan != NULL) {
2631 free_plan(unit);
2632 unit->plan = NULL;
2633 }
2634 /* Maybe enter the loss into the historical record. */
2635 if (reason >= 0)
2636 record_unit_death(unit, (HistEventType)reason);
2637 remove_unit_from_vector(unit->side->actionvector, unit, -1);
2638 if (side != NULL) {
2639 /* Invalidate the side's point value cache. */
2640 side->point_value_valid = FALSE;
2641 update_unit_display(side, unit, TRUE);
2642 }
2643 /* Kill all the occupants in turn. */
2644 for_all_occupants(unit, occ) {
2645 if (alive(occ))
2646 kill_unit_aux(occ, reason);
2647 /* We must take each occ out of the world explcitly,
2648 since 'kill_unit_aux' doesn't do that in the recursive call. */
2649 leave_cell(occ);
2650 }
2651 /* Advanced unit support. */
2652 if (u_advanced(unit->type))
2653 free_used_cells(unit);
2654 /* Update global counts. */
2655 --numliveunits;
2656 --(numlivebytype[u]);
2657 if (unit->side->self_unit == unit) {
2658 kill_self_unit(unit, unitname);
2659 }
2660 }
2661
2662 /* Free up all cells used by unit that passed away. */
2663
2664 void
free_used_cells(Unit * unit)2665 free_used_cells(Unit *unit)
2666 {
2667 int x, y;
2668
2669 for_all_cells_within_reach(unit, x, y) {
2670 if (!inside_area(x, y))
2671 continue;
2672 if (user_at(x, y) == unit->id)
2673 set_user_at(x, y, NOUSER);
2674 }
2675 unit->usedcells = 0;
2676 }
2677
2678 /* Get rid of all dead units at once.
2679
2680 (This routine is basically a garbage collector, and should not be
2681 called during a unit list traversal.) The process starts by finding
2682 the first live unit, making it the head, then linking around all in
2683 the middle. Dead units stay on the dead unit list for each side
2684 until that side has had a chance to move. Then they are finally
2685 flushed in a permanent fashion. */
2686
2687 static void flush_one_unit(Unit *unit);
2688
2689 void
flush_dead_units(void)2690 flush_dead_units(void)
2691 {
2692 Unit *unit, *prevunit, *nextunit;
2693
2694 if (unitlist == NULL)
2695 return;
2696 unit = unitlist;
2697 while (!alive(unit)) {
2698 nextunit = unit->unext;
2699 delete_unit(unit);
2700 flush_one_unit(unit);
2701 unit = nextunit;
2702 if (unit == NULL)
2703 break;
2704 }
2705 unitlist = unit;
2706 /* Since the first unit of unitlist is guaranteed live now,
2707 we know that prevunit will always be set correctly;
2708 but mollify insufficiently intelligent compilers. */
2709 prevunit = NULL;
2710 for_all_units(unit) {
2711 if (!alive(unit)) {
2712 nextunit = unit->unext;
2713 prevunit->unext = unit->unext;
2714 delete_unit(unit);
2715 flush_one_unit(unit);
2716 unit = prevunit;
2717 } else {
2718 prevunit = unit;
2719 }
2720 }
2721 }
2722
2723 /* Keep it clean - hit all links to other places. Some might not be
2724 strictly necessary, but this is not an area to take chances with. */
2725
2726 static void
flush_one_unit(Unit * unit)2727 flush_one_unit(Unit *unit)
2728 {
2729 unit->id = -1;
2730 unit->imf = NULL;
2731 unit->image_name = NULL;
2732 unit->occupant = NULL;
2733 unit->transport = NULL;
2734 unit->nexthere = NULL;
2735 unit->prev = NULL;
2736 unit->unext = NULL;
2737 /* Add it on the front of the list of available units. */
2738 unit->next = freeunits;
2739 freeunits = unit;
2740 }
2741
2742 /* Do a bubble sort.
2743 Data is generally coherent, so bubble sort not too bad if we allow
2744 early termination when everything is already in order. */
2745
2746 /* If slowness objectionable, replace with something clever, but be
2747 sure that average performance in real games is what's being improved. */
2748
2749 void
sort_units(int byidonly)2750 sort_units(int byidonly)
2751 {
2752 int flips;
2753 int passes = 0;
2754 register Unit *unit, *nextunit;
2755 Side *side;
2756
2757 for_all_sides(side) {
2758 passes = 0;
2759 flips = TRUE;
2760 while (flips) {
2761 flips = FALSE;
2762 for_all_side_units(side, unit) {
2763 if (unit->next != side->unithead
2764 && (byidonly ? ((unit->id - unit->next->id) > 0)
2765 : (compare_units(unit, unit->next) > 0))) {
2766 flips = TRUE;
2767 /* Reorder the units by fiddling with their links. */
2768 nextunit = unit->next;
2769 unit->prev->next = nextunit;
2770 nextunit->next->prev = unit;
2771 nextunit->prev = unit->prev;
2772 unit->next = nextunit->next;
2773 nextunit->next = unit;
2774 unit->prev = nextunit;
2775 }
2776 ++passes;
2777 }
2778 }
2779 }
2780 Dprintf("Sorting passes = %d\n", passes);
2781 }
2782
2783 static int
compare_units(Unit * unit1,Unit * unit2)2784 compare_units(Unit *unit1, Unit *unit2)
2785 {
2786 if (unit1->type != unit2->type)
2787 return (unit1->type - unit2->type);
2788 if (unit1->name && unit2->name == NULL)
2789 return -1;
2790 if (unit1->name == NULL && unit2->name)
2791 return 1;
2792 if (unit1->name && unit2->name)
2793 return strcmp(unit1->name, unit2->name);
2794 if (unit1->number != unit2->number)
2795 return (unit1->number - unit2->number);
2796 /* Ids impose a total ordering. */
2797 return (unit1->id - unit2->id);
2798 }
2799
2800 #if 0 /* Unused. */
2801
2802 /* Useful for the machine player to know how long it can move this
2803 piece before it should go home. Assumes can't replenish from
2804 terrain. Result may be negative, in which case it's time to go! */
2805
2806 int
2807 moves_till_low_supplies(Unit *unit)
2808 {
2809 int u = unit->type, m, moves = 1234567, tmp;
2810
2811 for_all_material_types(m) {
2812 if ((um_consumption_per_move(u, m) > 0)) {
2813 tmp = (unit->supply[m] - um_storage_x(u, m) / 2) / um_consumption_per_move(u, m);
2814 moves = min(moves, tmp);
2815 }
2816 }
2817 return moves;
2818 }
2819
2820 #endif
2821
2822 /* Short, unreadable, but greppable listing of unit. Primarily useful
2823 for debugging and warnings. We use several buffers and rotate between
2824 them so we can call this more than once in a single printf. */
2825
2826 char *
unit_desig(Unit * unit)2827 unit_desig(Unit *unit)
2828 {
2829 int i;
2830 char *shortbuf;
2831
2832 /* Allocate if not yet done so. */
2833 for (i = 0; i < NUMSHORTBUFS; ++i) {
2834 if (shortbufs[i] == NULL)
2835 shortbufs[i] = (char *)xmalloc(BUFSIZE);
2836 }
2837 /* Note that we test here, so that unit_desig(NULL) can be used
2838 to allocate any space that this routine might need later. */
2839 if (unit == NULL)
2840 return "no unit";
2841 shortbuf = shortbufs[curshortbuf];
2842 curshortbuf = (curshortbuf + 1) % NUMSHORTBUFS;
2843 if (unit->id == -1) {
2844 sprintf(shortbuf, "s%d head", side_number(unit->side));
2845 return shortbuf;
2846 } else if (is_unit_type(unit->type)) {
2847 sprintf(shortbuf, "s%d %s %d (%d,%d",
2848 side_number(unit->side), shortest_unique_name(unit->type),
2849 unit->id, unit->x, unit->y);
2850 if (unit->z != 0)
2851 tprintf(shortbuf, ",%d", unit->z);
2852 if (unit->transport)
2853 tprintf(shortbuf, ",in%d", unit->transport->id);
2854 strcat(shortbuf, ")"); /* close out the unit location */
2855 return shortbuf;
2856 } else {
2857 return "!garbage unit!";
2858 }
2859 }
2860
2861 /* Short, unreadable, but greppable listing of unit that omits anything
2862 that changes from turn to turn. */
2863
2864 char *
unit_desig_no_loc(Unit * unit)2865 unit_desig_no_loc(Unit *unit)
2866 {
2867 char *shortbuf;
2868
2869 if (unit == NULL)
2870 return "no unit";
2871 /* Allocate if not yet done so. */
2872 if (shortbufs[curshortbuf] == NULL)
2873 shortbufs[curshortbuf] = (char *)xmalloc(BUFSIZE);
2874 shortbuf = shortbufs[curshortbuf];
2875 curshortbuf = (curshortbuf + 1) % NUMSHORTBUFS;
2876 if (unit->id == -1) {
2877 sprintf(shortbuf, "s%d head", side_number(unit->side));
2878 return shortbuf;
2879 } else if (is_unit_type(unit->type)) {
2880 sprintf(shortbuf, "s%d %-3.3s %d",
2881 side_number(unit->side), shortest_unique_name(unit->type),
2882 unit->id);
2883 return shortbuf;
2884 } else {
2885 return "!garbage unit!";
2886 }
2887 }
2888
2889 /* Come up with a unit type name that fits in the given space. */
2890
2891 char *
utype_name_n(int u,int n)2892 utype_name_n(int u, int n)
2893 {
2894 char *utypename, *shortname, *rawname;
2895
2896 utypename = u_type_name(u);
2897 if (n <= 0 || strlen(utypename) <= (size_t)n) {
2898 return utypename;
2899 } else if (n == 1 && !empty_string(u_uchar(u))) {
2900 /* Use the unit char if possible. */
2901 return u_uchar(u);
2902 } else if (!empty_string(u_short_name(u))) {
2903 shortname = u_short_name(u);
2904 if (strlen(shortname) <= (size_t)n) {
2905 return shortname;
2906 } else {
2907 rawname = shortname;
2908 }
2909 } else {
2910 rawname = utypename;
2911 }
2912 /* Copy what will fit. */
2913 if (utypenamen == NULL)
2914 utypenamen = (char *)xmalloc(BUFSIZE);
2915 if (n > BUFSIZE - 1)
2916 n = BUFSIZE - 1;
2917 strncpy(utypenamen, rawname, n);
2918 utypenamen[n] = '\0';
2919 return utypenamen;
2920 }
2921
2922 char *
shortest_unique_name(int u)2923 shortest_unique_name(int u)
2924 {
2925 char namebuf[BUFSIZE], *name1;
2926 int u1, u2, i, len, allhavechars, *firstuniq, firstuniq1;
2927
2928 /* Don't try to allocate shortestnames before numutypes has been
2929 defined. This will cause crashes later on as the program
2930 mistakenly believes that all shortestnames[u] have been
2931 allocated just because shortestnames != NULL. */
2932 if (numutypes == 0)
2933 return NULL;
2934 if (shortestnames == NULL) {
2935 shortestnames = (char **) xmalloc(numutypes * sizeof(char *));
2936 firstuniq = (int *) xmalloc(numutypes * sizeof(int));
2937 /* First use game definition's single chars if possible. */
2938 allhavechars = TRUE;
2939 for_all_unit_types(u1) {
2940 firstuniq[u1] = -1;
2941 if (!empty_string(u_uchar(u1))) {
2942 namebuf[0] = (u_uchar(u1))[0];
2943 namebuf[1] = '\0';
2944 shortestnames[u1] = copy_string(namebuf);
2945 firstuniq[u1] = 0;
2946 } else {
2947 allhavechars = FALSE;
2948 }
2949 }
2950 if (!allhavechars) {
2951 /* Start with copies of full name for all types not
2952 already named. */
2953 for_all_unit_types(u1) {
2954 if (shortestnames[u1] == NULL) {
2955 shortestnames[u1] = copy_string(u_type_name(u1));
2956 firstuniq[u1] = 0;
2957 }
2958 }
2959 for_all_unit_types(u1) {
2960 if (firstuniq[u1] < 0) {
2961 name1 = shortestnames[u1];
2962 firstuniq1 = firstuniq[u1];
2963 for_all_unit_types(u2) {
2964 if (u1 != u2) {
2965 /* Look through the supposedly minimal
2966 unique substring and see if it is the
2967 same. */
2968 for (i = 0; i < firstuniq1; ++i ) {
2969 if (name1[i] != (shortestnames[u2])[i]) {
2970 break;
2971 }
2972 }
2973 /* If so, must extend the unique substring. */
2974 if (i == firstuniq1) {
2975 /* Look for the first nonmatching char. */
2976 while (name1[firstuniq1] == (shortestnames[u2])[firstuniq1]) {
2977 ++firstuniq1;
2978 }
2979 }
2980 }
2981 }
2982 firstuniq[u1] = firstuniq1;
2983 }
2984 }
2985 /* For any types where the unique short name is shorter
2986 than the seed name, truncate appropriately. */
2987 longest_shortest = 0;
2988 for_all_unit_types(u1) {
2989 if (size_t(firstuniq[u1] + 1) < strlen(shortestnames[u1])) {
2990 (shortestnames[u1])[firstuniq[u1] + 1] = '\0';
2991 }
2992 len = strlen(shortestnames[u1]);
2993 if (len > longest_shortest)
2994 longest_shortest = len;
2995 }
2996 } else {
2997 longest_shortest = 1;
2998 }
2999 if (Debug) {
3000 for_all_unit_types(u1) {
3001 Dprintf("Shortest type name: %s for %s\n",
3002 shortestnames[u1], u_type_name(u1));
3003 }
3004 }
3005 }
3006 return shortestnames[u];
3007 }
3008
3009 /* Similar to shortest_unique_name, but returns a generic name/char
3010 instead. */
3011
3012 char *
shortest_generic_name(int u)3013 shortest_generic_name(int u)
3014 {
3015 char namebuf[BUFSIZE], *name1;
3016 int u1, u2, i, allhavechars, *firstuniq, firstuniq1;
3017
3018 if (shortestgnames == NULL) {
3019 shortestgnames = (char **) xmalloc(numutypes * sizeof(char *));
3020 firstuniq = (int *) xmalloc(numutypes * sizeof(int));
3021 /* First use game definition's single chars if possible. */
3022 allhavechars = TRUE;
3023 for_all_unit_types(u1) {
3024 firstuniq[u1] = -1;
3025 if (!empty_string(u_gchar(u1))) {
3026 namebuf[0] = (u_gchar(u1))[0];
3027 namebuf[1] = '\0';
3028 shortestgnames[u1] = copy_string(namebuf);
3029 firstuniq[u1] = 0;
3030 } else if (!empty_string(u_uchar(u1))) {
3031 namebuf[0] = (u_uchar(u1))[0];
3032 namebuf[1] = '\0';
3033 shortestgnames[u1] = copy_string(namebuf);
3034 firstuniq[u1] = 0;
3035 } else {
3036 allhavechars = FALSE;
3037 }
3038 }
3039 if (!allhavechars) {
3040 /* Start with copies of full name for all types not
3041 already named. */
3042 for_all_unit_types(u1) {
3043 if (shortestgnames[u1] == NULL) {
3044 name1 = (!empty_string(u_generic_name(u1)) ? u_generic_name(u1) : u_type_name(u1));
3045 shortestgnames[u1] = copy_string(name1);
3046 firstuniq[u1] = 0;
3047 }
3048 }
3049 for_all_unit_types(u1) {
3050 if (firstuniq[u1] < 0) {
3051 name1 = shortestgnames[u1];
3052 firstuniq1 = firstuniq[u1];
3053 for_all_unit_types(u2) {
3054 if (u1 != u2) {
3055 /* Look through the supposedly minimal
3056 unique substring and see if it is the
3057 same. */
3058 for (i = 0; i < firstuniq1; ++i ) {
3059 if (name1[i] != (shortestgnames[u2])[i]) {
3060 break;
3061 }
3062 }
3063 /* If so, must extend the unique substring. */
3064 if (i == firstuniq1) {
3065 /* Look for the first nonmatching char. */
3066 while (name1[firstuniq1] == (shortestgnames[u2])[firstuniq1]) {
3067 ++firstuniq1;
3068 }
3069 }
3070 }
3071 }
3072 firstuniq[u1] = firstuniq1;
3073 }
3074 }
3075 /* For any types where the unique short name is shorter
3076 than the seed name, truncate appropriately. */
3077 for_all_unit_types(u1) {
3078 if (size_t(firstuniq[u1] + 1) < strlen(shortestgnames[u1])) {
3079 (shortestgnames[u1])[firstuniq[u1] + 1] = '\0';
3080 }
3081 }
3082 }
3083 if (Debug) {
3084 for_all_unit_types(u1) {
3085 Dprintf("Shortest generic type name: %s for %s\n",
3086 shortestgnames[u1], u_type_name(u1));
3087 }
3088 }
3089 }
3090 return shortestgnames[u];
3091 }
3092
3093 /* This formats an actorstate readably. */
3094
3095 char *
actorstate_desig(ActorState * as)3096 actorstate_desig(ActorState *as)
3097 {
3098 if (actorstatebuf == NULL)
3099 actorstatebuf = (char *)xmalloc(BUFSIZE);
3100 if (as != NULL) {
3101 sprintf(actorstatebuf, "acp %d/%d %s",
3102 as->acp, as->initacp, action_desig(&(as->nextaction)));
3103 return actorstatebuf;
3104 } else {
3105 return "no act";
3106 }
3107 }
3108
3109 /* Search for a unit with the given id number. */
3110
3111 /* This is used a lot, it should be sped up. */
3112
3113 Unit *
find_unit(int n)3114 find_unit(int n)
3115 {
3116 Unit *unit;
3117
3118 for_all_units(unit) {
3119 if (unit->id == n && alive(unit))
3120 return unit;
3121 }
3122 return NULL;
3123 }
3124
3125 /* Same, but don't by picky about liveness. */
3126
3127 Unit *
find_unit_dead_or_alive(int n)3128 find_unit_dead_or_alive(int n)
3129 {
3130 Unit *unit;
3131
3132 for_all_units(unit) {
3133 if (unit->id == n)
3134 return unit;
3135 }
3136 return NULL;
3137 }
3138
3139 /* Find a unit with the given name, either alive or dead. */
3140
3141 Unit *
find_unit_by_name(char * nm)3142 find_unit_by_name(char *nm)
3143 {
3144 Unit *unit;
3145
3146 if (nm == NULL)
3147 return NULL;
3148 for_all_units(unit) {
3149 if (unit->name != NULL && strcmp(unit->name, nm) == 0)
3150 return unit;
3151 }
3152 return NULL;
3153 }
3154
3155 /* Find a unit with the given number, either alive or dead. */
3156
3157 Unit *
find_unit_by_number(int nb)3158 find_unit_by_number(int nb)
3159 {
3160 Unit *unit;
3161
3162 for_all_units(unit) {
3163 if (unit->number == nb)
3164 return unit;
3165 }
3166 return NULL;
3167 }
3168
3169 /* Find a unit with the given symbol, either alive or dead. */
3170
3171 Unit *
find_unit_by_symbol(Obj * sym)3172 find_unit_by_symbol(Obj *sym)
3173 {
3174 Unit *unit;
3175
3176 if (sym == lispnil)
3177 return NULL;
3178 for_all_units(unit) {
3179 if (equal(unit_symbol(unit), sym))
3180 return unit;
3181 }
3182 return NULL;
3183 }
3184
3185 /* Insert the given unit after the other given unit. */
3186
3187 void
insert_unit(Unit * unithead,Unit * unit)3188 insert_unit(Unit *unithead, Unit *unit)
3189 {
3190 unit->next = unithead->next;
3191 unit->prev = unithead;
3192 unithead->next->prev = unit;
3193 unithead->next = unit;
3194 }
3195
3196 /* Delete the unit from its list. */
3197
3198 void
delete_unit(Unit * unit)3199 delete_unit(Unit *unit)
3200 {
3201 unit->next->prev = unit->prev;
3202 unit->prev->next = unit->next;
3203 }
3204
3205 #if 0 /* not used, although they seem useful... */
3206 int
3207 num_occupants(Unit *unit)
3208 {
3209 int num = 0;
3210 Unit *occ;
3211
3212 for_all_occupants(unit, occ) {
3213 num += 1;
3214 }
3215 return num;
3216 }
3217
3218 int
3219 num_units_at(int x, int y)
3220 int x, y;
3221 {
3222 int num = 0;
3223 Unit *unit;
3224
3225 if (!in_area(x, y)) {
3226 run_warning("num_units_at %d,%d??", x, y);
3227 return 0;
3228 }
3229 for_all_stack(x, y, unit) {
3230 num += 1;
3231 }
3232 return num;
3233 }
3234 #endif
3235
3236 /* Call this to doublecheck invariants on units. */
3237
3238 void
check_all_units(void)3239 check_all_units(void)
3240 {
3241 Unit *unit;
3242
3243 for_all_units(unit) {
3244 check_unit(unit);
3245 }
3246 }
3247
3248 void
check_unit(Unit * unit)3249 check_unit(Unit *unit)
3250 {
3251 if (alive(unit) && unit->transport && !alive(unit->transport)) {
3252 run_warning("%s is inside a dead transport", unit_desig(unit));
3253 }
3254 /* etc */
3255 }
3256
3257 UnitVector *
make_unit_vector(int initsize)3258 make_unit_vector(int initsize)
3259 {
3260 UnitVector *vec;
3261
3262 vec = (UnitVector *)
3263 xmalloc(sizeof(UnitVector) + initsize * sizeof(UnitVectorEntry));
3264 vec->size = initsize;
3265 vec->numunits = 0;
3266 return vec;
3267 }
3268
3269 void
clear_unit_vector(UnitVector * vec)3270 clear_unit_vector(UnitVector *vec)
3271 {
3272 vec->numunits = 0;
3273 }
3274
3275 UnitVector *
add_unit_to_vector(UnitVector * vec,Unit * unit,int flag)3276 add_unit_to_vector(UnitVector *vec, Unit *unit, int flag)
3277 {
3278 int i;
3279 UnitVector *newvec;
3280
3281 /* Can't add to something that doesn't exist! */
3282 if (vec == NULL)
3283 run_error("No actionvector!");
3284 /* (should search to see if already present) */
3285 if (vec->numunits >= vec->size) {
3286 newvec = make_unit_vector((3 * vec->size) / 2);
3287 newvec->numunits = vec->numunits;
3288 for (i = 0; i < vec->numunits; ++i) {
3289 newvec->units[i] = vec->units[i];
3290 }
3291 free(vec);
3292 vec = newvec;
3293 }
3294 ((vec->units)[vec->numunits]).unit = unit;
3295 ((vec->units)[vec->numunits]).flag = flag;
3296 ++(vec->numunits);
3297 return vec;
3298 }
3299
3300 void
remove_unit_from_vector(UnitVector * vec,Unit * unit,int pos)3301 remove_unit_from_vector(UnitVector *vec, Unit *unit, int pos)
3302 {
3303 int j;
3304
3305 /* It's probably a bug that the vector is null sometimes,
3306 but don't flip out over it. */
3307 if (vec == NULL)
3308 return;
3309 /* Search for unit in vector. */
3310 if (pos < 0) {
3311 for (j = 0; j < vec->numunits; ++j) {
3312 if (unit == vec->units[j].unit) {
3313 pos = j;
3314 break;
3315 }
3316 }
3317 }
3318 if (pos < 0)
3319 return;
3320 if (unit != vec->units[pos].unit)
3321 run_error("unit mismatch in remove_unit_from_vector, %s not at %d",
3322 unit_desig(unit), pos);
3323 for (j = pos + 1; j < vec->numunits; ++j)
3324 vec->units[j-1] = vec->units[j];
3325 --(vec->numunits);
3326 }
3327
3328 enum sortkeys tmpsortkeys[MAXSORTKEYS];
3329
3330 static int
compare_units_by_keys(CONST void * e1,CONST void * e2)3331 compare_units_by_keys(CONST void *e1, CONST void *e2)
3332 {
3333 int i;
3334 Unit *unit1 = ((UnitVectorEntry *) e1)->unit;
3335 Unit *unit2 = ((UnitVectorEntry *) e2)->unit;
3336
3337 if (unit1 == unit2)
3338 return 0;
3339 if (unit1 == NULL)
3340 return 1;
3341 if (unit2 == NULL)
3342 return -1;
3343 for (i = 0; i < MAXSORTKEYS; ++i) {
3344 switch (tmpsortkeys[i]) {
3345 case byside:
3346 if (unit1->side != unit2->side) {
3347 int s1 = side_number(unit1->side);
3348 int s2 = side_number(unit2->side);
3349
3350 /* Put independents at the end of any list. */
3351 if (s1 == 0)
3352 s1 = numsides + 1;
3353 if (s2 == 0)
3354 s2 = numsides + 1;
3355 return (s1 - s2);
3356 }
3357 break;
3358 case bytype:
3359 if (unit1->type != unit2->type) {
3360 return (unit1->type - unit2->type);
3361 }
3362 break;
3363 case byname:
3364 if (unit1->name) {
3365 if (unit2->name) {
3366 return strcmp(unit1->name, unit2->name);
3367 } else {
3368 return -1;
3369 }
3370 } else if (unit1->number > 0) {
3371 if (unit2->name) {
3372 return 1;
3373 } else if (unit2->number > 0) {
3374 return (unit1->number - unit2->number);
3375 } else {
3376 return -1;
3377 }
3378 } else if (unit2->name) {
3379 return 1;
3380 } else if (unit2->number > 0) {
3381 return 1;
3382 }
3383 break;
3384 case byactorder:
3385 /* (should sort by action priority?) */
3386 break;
3387 case bylocation:
3388 if (unit1->y != unit2->y) {
3389 return (unit2->y - unit1->y);
3390 } else if (unit1->x != unit2->x) {
3391 return (unit1->x - unit2->x);
3392 } else {
3393 /* Both units are at the same location. Sort by transport. */
3394 if (unit1->transport) {
3395 if (unit2->transport) {
3396 } else {
3397 return 1;
3398 }
3399 } else {
3400 if (unit2->transport) {
3401 return -1;
3402 } else {
3403 }
3404 }
3405 }
3406 break;
3407 case bynothing:
3408 return (unit1->id - unit2->id);
3409 default:
3410 break;
3411 }
3412 }
3413 /* Unit ids are all unique, so this is a reliable default sort key. */
3414 return (unit1->id - unit2->id);
3415 }
3416
3417 void
sort_unit_vector(UnitVector * vec)3418 sort_unit_vector(UnitVector *vec)
3419 {
3420 qsort(vec->units, vec->numunits, sizeof(UnitVectorEntry),
3421 compare_units_by_keys);
3422 }
3423
3424 #ifdef DESIGNERS
3425
3426 /* A designer can call this to create an arbitrary unit during the game. */
3427
3428 Unit *
designer_create_unit(Side * side,int u,int s,int x,int y)3429 designer_create_unit(Side *side, int u, int s, int x, int y)
3430 {
3431 Unit *newunit;
3432 Side *side2;
3433
3434 side2 = side_n(s);
3435 if (!type_can_occupy_cell(u, x, y)
3436 || !type_survives_in_cell(u, x, y)
3437 || !new_unit_allowed_on_side(u, side2)) {
3438 return NULL;
3439 }
3440 newunit = create_unit(u, TRUE);
3441 if (newunit == NULL)
3442 return NULL;
3443 if (s != 0) {
3444 side2 = side_n(s);
3445 set_unit_side(newunit, side2);
3446 set_unit_origside(newunit, side2);
3447 /* (should ensure that any changed counts are set correctly) */
3448 }
3449 init_supply(newunit);
3450 Xconq::suppress_reactions = TRUE;
3451 enter_cell(newunit, x, y);
3452 update_cell_display(side, x, y, UPDATE_ALWAYS);
3453 update_unit_display(side, newunit, TRUE);
3454 Xconq::suppress_reactions = FALSE;
3455 return newunit;
3456 }
3457
3458 /* Move a unit to a given location instantly, with all sides observing. */
3459
3460 int
designer_teleport(Unit * unit,int x,int y,Unit * other)3461 designer_teleport(Unit *unit, int x, int y, Unit *other)
3462 {
3463 int oldx = unit->x, oldy = unit->y, rslt;
3464 Side *side2;
3465
3466 Xconq::suppress_reactions = TRUE;
3467 if (other != NULL && can_occupy(unit, other)) {
3468 leave_cell(unit);
3469 enter_transport(unit, other);
3470 all_see_cell(x, y);
3471 rslt = TRUE;
3472 } else if (type_can_occupy_cell(unit->type, x, y)
3473 && type_survives_in_cell(unit->type, x, y)) {
3474 change_cell(unit, x, y);
3475 rslt = TRUE;
3476 } else {
3477 rslt = FALSE;
3478 }
3479 if (rslt) {
3480 /* Provide accurate info on affected cells. */
3481 for_all_sides(side2) {
3482 if (is_designer(side2)) {
3483 see_exact(side2, oldx, oldy);
3484 see_exact(side2, x, y);
3485 }
3486 }
3487 }
3488 Xconq::suppress_reactions = FALSE;
3489 return rslt;
3490 }
3491
3492 int
designer_change_side(Unit * unit,Side * side)3493 designer_change_side(Unit *unit, Side *side)
3494 {
3495 Side *side2;
3496
3497 change_unit_side(unit, side, -1, NULL);
3498 for_all_sides(side2) {
3499 if (1 /* side2 should see change */) {
3500 update_unit_display(side2, unit, TRUE);
3501 }
3502 }
3503 return TRUE;
3504 }
3505
3506 int
designer_disband(Unit * unit)3507 designer_disband(Unit *unit)
3508 {
3509 kill_unit(unit, -1);
3510 return TRUE;
3511 }
3512
3513 #endif /* DESIGNERS */
3514
3515 /* Unit-related functions moved here from actions.c and plan.c. */
3516
3517 //! Could u be on t?
3518
3519 int
could_be_on(int u,int t)3520 could_be_on(int u, int t)
3521 {
3522 assert_error(is_unit_type(u), "Attempted to manipulate an invalid utype");
3523 assert_error(is_terrain_type(t),
3524 "Attempted to manipulate an invalid ttype");
3525 if ((t_capacity(t) < ut_size(u, t)) && (0 >= ut_capacity_x(u, t)))
3526 return FALSE;
3527 return TRUE;
3528 }
3529
3530 /* Functions returning general abilities of a unit. */
3531
3532 int
can_develop(Unit * unit)3533 can_develop(Unit *unit)
3534 {
3535 return type_can_develop(unit->type);
3536 }
3537
3538 int
type_can_develop(int u)3539 type_can_develop(int u)
3540 {
3541 int u2;
3542
3543 for_all_unit_types(u2) {
3544 if (could_develop(u, u2))
3545 return TRUE;
3546 }
3547 return FALSE;
3548 }
3549
3550 /* This is true if the given location has some kind of material for the
3551 unit to extract. */
3552
3553 int
can_extract_at(Unit * unit,int x,int y,int * mp)3554 can_extract_at(Unit *unit, int x, int y, int *mp)
3555 {
3556 int m;
3557 Unit *unit2;
3558
3559 /* Can't do anything with an unseen location. */
3560 if (unit->side != NULL
3561 && terrain_view(unit->side, x, y) == UNSEEN)
3562 return FALSE;
3563 for_all_material_types(m) {
3564 if (um_acp_to_extract(unit->type, m) > 0) {
3565 /* Look for case of extraction from terrain. */
3566 if (any_cell_materials_defined()
3567 && cell_material_defined(m)
3568 && material_at(x, y, m) > 0) {
3569 *mp = m;
3570 return TRUE;
3571 }
3572 /* Then look for extraction from independent unit. */
3573 if (g_no_indepside_ingame()) {
3574 for_all_stack(x, y, unit2) {
3575 if (in_play(unit2)
3576 && indep(unit2)
3577 && unit2->supply[m] > 0) {
3578 *mp = m;
3579 return TRUE;
3580 }
3581 }
3582 }
3583 }
3584 }
3585 return FALSE;
3586 }
3587
3588 /* This is true if the given location has some kind of material for the
3589 unit to transfer. */
3590
3591 int
can_load_at(Unit * unit,int x,int y,int * mp)3592 can_load_at(Unit *unit, int x, int y, int *mp)
3593 {
3594 int m;
3595 Unit *unit2;
3596
3597 /* Can't do anything with an unseen location. */
3598 if (unit->side != NULL
3599 && terrain_view(unit->side, x, y) == UNSEEN)
3600 return FALSE;
3601 for_all_material_types(m) {
3602 if (um_acp_to_load(unit->type, m) > 0) {
3603 for_all_stack(x, y, unit2) {
3604 if (in_play(unit2)
3605 && unit2->side == unit->side
3606 && type_max_acp(unit2->type) == 0
3607 && um_acp_to_unload(unit2->type, m) > 0) {
3608 *mp = m;
3609 return TRUE;
3610 }
3611 }
3612 }
3613 }
3614 return FALSE;
3615 }
3616
3617 /* This tests whether the given unit is capable of doing repair. */
3618 /*!
3619 \todo Move to 'aiunit.cc' where it probably belongs.
3620 \todo Fix prototype for separate actor/agent.
3621 */
3622
3623 int
can_change_type(Unit * unit)3624 can_change_type(Unit *unit)
3625 {
3626 int u2 = NONUTYPE;
3627 int rslt = A_ANY_CANNOT_DO;
3628
3629 for_all_unit_types(u2) {
3630 if (valid(rslt = can_change_type_to(unit, unit, u2)))
3631 return rslt;
3632 }
3633 return A_ANY_CANNOT_DO;
3634 }
3635
3636 int
could_change_type(int u)3637 could_change_type(int u)
3638 {
3639 int u2;
3640
3641 if (u_auto_upgrade_to(u) != NONUTYPE)
3642 return TRUE;
3643 for_all_unit_types(u2) {
3644 if (could_change_type_to(u, u2))
3645 return TRUE;
3646 }
3647 return FALSE;
3648 }
3649
3650 int
can_change_type_to(Unit * unit,int u2)3651 can_change_type_to(Unit *unit, int u2)
3652 {
3653 return (valid(can_change_type_to(unit, unit, u2)));
3654 }
3655
3656 int
could_change_type_to(int u,int u2)3657 could_change_type_to(int u, int u2)
3658 {
3659 if (uu_change_type_to(u, u2)) {
3660 #if (0)
3661 if (u_acp_independent(u))
3662 return TRUE;
3663 if (uu_acp_to_change_type(u, u2) > 0)
3664 return TRUE;
3665 #else
3666 return TRUE;
3667 #endif
3668 }
3669 return FALSE;
3670 }
3671
3672 int
can_disband(Unit * unit)3673 can_disband(Unit *unit)
3674 {
3675 return (type_can_disband(unit->type) || !completed(unit));
3676 }
3677
3678 int
type_can_disband(int u)3679 type_can_disband(int u)
3680 {
3681 return (u_acp_to_disband(u) > 0);
3682 }
3683
3684 int
side_can_disband(Side * side,Unit * unit)3685 side_can_disband(Side *side, Unit *unit)
3686 {
3687 if (is_designer(side))
3688 return TRUE;
3689 return (side_controls_unit(side, unit)
3690 && can_disband(unit));
3691 }
3692
3693 /* This tests whether the given unit is capable of adding terrain. */
3694
3695 int
can_add_terrain(Unit * unit)3696 can_add_terrain(Unit *unit)
3697 {
3698 return type_can_add_terrain(unit->type);
3699 }
3700
3701 int
type_can_add_terrain(int u)3702 type_can_add_terrain(int u)
3703 {
3704 int t;
3705
3706 for_all_terrain_types(t) {
3707 if (ut_acp_to_add_terrain(u, t) > 0)
3708 return TRUE;
3709 }
3710 return FALSE;
3711 }
3712
3713 /* This tests whether the given unit is capable of removing terrain. */
3714
3715 int
can_remove_terrain(Unit * unit)3716 can_remove_terrain(Unit *unit)
3717 {
3718 return type_can_remove_terrain(unit->type);
3719 }
3720
3721 int
type_can_remove_terrain(int u)3722 type_can_remove_terrain(int u)
3723 {
3724 int t;
3725
3726 for_all_terrain_types(t) {
3727 if (ut_acp_to_remove_terrain(u, t) > 0)
3728 return TRUE;
3729 }
3730 return FALSE;
3731 }
3732
3733 /* Checks if there is an incomplete unit within range that we should
3734 resume building. */
3735
3736 Unit *
incomplete_build_target(Unit * unit)3737 incomplete_build_target(Unit *unit)
3738 {
3739 int x, y, u, building, range = 0;
3740 Unit *unit2, *unit3;
3741
3742 /* If there is a creation ID, then look at that unit first. */
3743 if (unit->creation_id > 0) {
3744 unit2 = find_unit(unit->creation_id);
3745 if (in_play(unit2) && !fullsized(unit2))
3746 return unit2;
3747 }
3748 /* First compute how far away we need to look for build targets. */
3749 for_all_unit_types(u) {
3750 if (could_build(unit->type, u)
3751 && side_can_build(unit->side, u)) {
3752 range = max(range, uu_build_range(unit->type, u));
3753 }
3754 }
3755 /* Then look for build targets. */
3756 for_all_cells_within_range(unit->x, unit->y, range, x, y) {
3757 if (!inside_area(x, y)) {
3758 continue;
3759 }
3760 if (!units_visible(unit->side, x, y)) {
3761 continue;
3762 }
3763 for_all_stack_with_occs(x, y, unit2) {
3764 if (in_play(unit2)
3765 && !fullsized(unit2)
3766 && unit->side == unit2->side
3767 && could_build(unit->type, unit2->type)
3768 && side_can_build(unit->side, unit2->type)
3769 && uu_build_range(unit->type, unit2->type)
3770 >= distance(unit->x, unit->y, unit2->x, unit2->y)) {
3771 /* Also check that nobody else is building this unit. */
3772 building = FALSE;
3773 for_all_side_units(unit->side, unit3) {
3774 if (could_build(unit3->type, unit2->type)
3775 && unit3->plan
3776 && unit3->plan->tasks
3777 && unit3->plan->tasks->type == TASK_BUILD
3778 && unit3->plan->tasks->args[1] == unit2->id) {
3779 building = TRUE;
3780 break;
3781 }
3782 }
3783 if (!building) {
3784 return unit2;
3785 }
3786 }
3787 }
3788 }
3789 return NULL;
3790 }
3791
3792 /* These functions test if the given utype belonging to the given side
3793 can build various classes of units. */
3794
3795 int
can_build_attackers(Side * side,int u)3796 can_build_attackers(Side *side, int u)
3797 {
3798 int u2;
3799
3800 for_all_unit_types(u2) {
3801 if (u_offensive_worth(u2) > 0
3802 && could_create(u, u2)
3803 && side_can_build(side, u2))
3804 return TRUE;
3805 }
3806 return FALSE;
3807 }
3808
3809 int
can_build_defenders(Side * side,int u)3810 can_build_defenders(Side *side, int u)
3811 {
3812 int u2;
3813
3814 for_all_unit_types(u2) {
3815 if (u_defensive_worth(u2) > 0
3816 && could_create(u, u2)
3817 && side_can_build(side, u2))
3818 return TRUE;
3819 }
3820 return FALSE;
3821 }
3822
3823 int
can_build_explorers(Side * side,int u)3824 can_build_explorers(Side *side, int u)
3825 {
3826 int u2;
3827
3828 for_all_unit_types(u2) {
3829 if (u_ai_explorer_worth(u2) > 0
3830 && could_create(u, u2)
3831 && side_can_build(side, u2))
3832 return TRUE;
3833 }
3834 return FALSE;
3835 }
3836
3837 int
can_build_colonizers(Side * side,int u)3838 can_build_colonizers(Side *side, int u)
3839 {
3840 int u2;
3841
3842 for_all_unit_types(u2) {
3843 if (u_colonizer_worth(u2) > 0
3844 && could_create(u, u2)
3845 && side_can_build(side, u2))
3846 return TRUE;
3847 }
3848 return FALSE;
3849 }
3850
3851 int
can_build_facilities(Side * side,int u)3852 can_build_facilities(Side *side, int u)
3853 {
3854 int u2;
3855
3856 for_all_unit_types(u2) {
3857 if (u_facility_worth(u2) > 0
3858 && could_create(u, u2)
3859 && side_can_build(side, u2))
3860 return TRUE;
3861 }
3862 return FALSE;
3863 }
3864
3865 /* True if the given unit is a sort that can build other units. */
3866
3867 int
can_build(Unit * unit)3868 can_build(Unit *unit)
3869 {
3870 int u2;
3871
3872 if (indep(unit)
3873 && g_indepside_can_build() != TRUE)
3874 return FALSE;
3875 for_all_unit_types(u2) {
3876 if (unit_can_build_type(unit, u2))
3877 return TRUE;
3878 }
3879 return FALSE;
3880 }
3881
3882 /* True if a unit of a given type and side can build other units. */
3883
type_can_build(int u,Side * side)3884 int type_can_build(int u, Side *side)
3885 {
3886 int u2 = NONUTYPE;
3887
3888 if ((side == indepside) && !g_indepside_can_build())
3889 return FALSE;
3890 for_all_unit_types(u2) {
3891 if (type_can_build_type(u, side, u2))
3892 return TRUE;
3893 }
3894 return FALSE;
3895 }
3896
3897 /* Tests if a unit can build a type at a specific location either directly
3898 or by moving within range. */
3899
3900 int
unit_can_build_type_at(Unit * unit,int u2,int x,int y)3901 unit_can_build_type_at(Unit *unit, int u2, int x, int y)
3902 {
3903 int dist, range, u = unit->type, resume = FALSE;
3904 Side *side = unit->side;
3905 Unit *unit2;
3906
3907 if (!in_area(x, y)){
3908 notify(side, "Cannot build outside the world.");
3909 notify(side, "Please pick a new site (or Escape to cancel).");
3910 return FALSE;
3911 }
3912 /* This should have been tested before getting this far but we check
3913 it anyway. */
3914 if (!inside_area(x, y)){
3915 notify(side, "Cannot build on the edge of the world.");
3916 notify(side, "Please pick a new site (or Escape to cancel).");
3917 return FALSE;
3918 }
3919 /* This should have been tested before getting this far but we check
3920 it anyway. */
3921 if (!type_can_build_type(u, side, u2)){
3922 notify(side, "%s cannot build %s. Wrong type.",
3923 unit_handle(side, unit), u_type_name(u2));
3924 return FALSE;
3925 }
3926 /* Check if there is an incomplete unit in the cell that we clicked
3927 on. Note: we don't want to use find_unit_to_complete here since it
3928 also checks the current build target, irrespective of its location,
3929 and searches adjacent cells for build targets. */
3930 for_all_stack_with_occs(x, y, unit2) {
3931 if (in_play(unit2)
3932 && !fullsized(unit2)
3933 && unit2->type == u2
3934 && unit2->side == unit->side) {
3935 resume = TRUE;
3936 break;
3937 }
3938 }
3939 /* Consider both build range and create range. */
3940 /* (Why? We should not be second-guessing the player. If the player
3941 wants to create with one unit and then build with another, that
3942 is his/her option. Furthermore, some units may be complete upon
3943 creation and the game designer may have neglected to set the
3944 build-range to the create-range in such cases.) */
3945 range = min(uu_create_range(u, u2), uu_build_range(u, u2));
3946 dist = distance(unit->x, unit->y, x, y);
3947 /* We are trying to build a unit in the same cell. */
3948 if (dist == 0) {
3949 /* We can always resume building a unit in the same cell. */
3950 if (resume) {
3951 return TRUE;
3952 }
3953 /* Check that there is room to create a new unit. */
3954 if (side_thinks_it_can_put_type_at(side, u2, x, y)
3955 /* There may still be room without the creator. */
3956 || (side_thinks_it_can_put_type_at_without(side, u2, x, y, unit)
3957 /* The creator may die in the process ... */
3958 && (uu_hp_to_garrison(u, u2) >= u_hp(u)
3959 /* ... or it may fit inside the created unit. */
3960 || type_can_occupy_empty_type(u, u2)))) {
3961 return TRUE;
3962 } else {
3963 notify(side, "%s cannot build %s at (%d,%d). No room.",
3964 unit_handle(side, unit), u_type_name(u2), x, y);
3965 notify(side, "Please pick a new site (or Escape to cancel).");
3966 return FALSE;
3967 }
3968 /* We are trying to build a unit elsewhere. */
3969 } else {
3970 /* If we need to create a new unit and there is no room,
3971 then we are done. */
3972 if (!resume && !side_thinks_it_can_put_type_at(side, u2, x, y)) {
3973 notify(side, "%s cannot build %s at (%d,%d). No room.",
3974 unit_handle(side, unit), u_type_name(u2), x, y);
3975 notify(side, "Please pick a new site (or Escape to cancel).");
3976 return FALSE;
3977 }
3978 /* First test if we are already within range. */
3979 if (dist <= range) {
3980 return TRUE;
3981 /* For mobile units we test if we can get within range. */
3982 } else if (mobile(u)) {
3983 /* This handy path function tests
3984 not only if we can reach a point,
3985 but also if we can get within range of that point. */
3986 if (1 /*choose_move_direction(unit, x, y, range) >= 0*/) {
3987 return TRUE;
3988 } else {
3989 notify(side,
3990 "%s cannot build %s at (%d,%d). No way there.",
3991 unit_handle(side, unit), u_type_name(u2), x, y);
3992 notify(side,
3993 "Please pick a new site (or Escape to cancel).");
3994 return FALSE;
3995 }
3996 /* Nothing else to do for immobile units. */
3997 } else {
3998 notify(side,
3999 "%s cannot build %s at (%d,%d). Too far away.",
4000 unit_handle(side, unit), u_type_name(u2), x, y);
4001 notify(side,
4002 "Please pick a new site (or Escape to cancel).");
4003 return FALSE;
4004 }
4005 }
4006 return FALSE;
4007 }
4008
4009 /* True if the given unit can build a given type of unit. */
4010
4011 int
can_build_type(Unit * unit,int u2)4012 can_build_type(Unit *unit, int u2)
4013 {
4014 int u = unit->type;
4015
4016 if (!could_create(u, u2)) {
4017 DMprintf("%s was told to build %s which it cannot create.\n",
4018 unit_desig(unit), shortest_generic_name(u2));
4019 return FALSE;
4020 }
4021 if (!could_build(u, u2)) {
4022 DMprintf("%s was told to build %s which it cannot build.\n",
4023 unit_desig(unit), shortest_generic_name(u2));
4024 return FALSE;
4025 }
4026 /* Success if the unit can start building right away. */
4027 if (side_can_build(unit->side, u2))
4028 return TRUE;
4029 return FALSE;
4030 }
4031
4032 /* Legacy call to 'can_develop_or_build_type'. */
4033
4034 int
unit_can_build_type(Unit * unit,int u2)4035 unit_can_build_type(Unit *unit, int u2)
4036 {
4037 return can_develop_or_build_type(unit, u2);
4038 }
4039
4040 /* True if the given unit can develop/build a given type of unit. */
4041
4042 int
can_develop_or_build_type(Unit * unit,int u2)4043 can_develop_or_build_type(Unit *unit, int u2)
4044 {
4045 int u = unit->type;
4046
4047 if (!could_create(u, u2)) {
4048 DMprintf("%s was told to build %s which it cannot create.\n",
4049 unit_desig(unit), shortest_generic_name(u2));
4050 return FALSE;
4051 }
4052 if (!could_build(u, u2)) {
4053 DMprintf("%s was told to build %s which it cannot build.\n",
4054 unit_desig(unit), shortest_generic_name(u2));
4055 return FALSE;
4056 }
4057 /* Success if the unit can start building right away. */
4058 if (side_can_build(unit->side, u2))
4059 return TRUE;
4060 /* Or, the unit might be able to work on development first, then
4061 will switch to building automatically when the tech is
4062 sufficient. */
4063 if (could_develop(u, u2) && side_can_develop(unit->side, u2))
4064 return TRUE;
4065 return FALSE;
4066 }
4067
4068 /* True if a unit type could develop/build a given other unit type. */
4069
4070 int
type_can_build_type(int u,Side * side,int u2)4071 type_can_build_type(int u, Side *side, int u2)
4072 {
4073 if (!could_create(u, u2)) {
4074 return FALSE;
4075 }
4076 if (!could_build(u, u2)) {
4077 return FALSE;
4078 }
4079 /* Success if the unit can start building right away. */
4080 if (side_can_build(side, u2))
4081 return TRUE;
4082 /* Or, the unit might be able to work on development first, then
4083 will switch to building automatically when the tech is
4084 sufficient. */
4085 if (could_develop(u, u2) && side_can_develop(side, u2))
4086 return TRUE;
4087 return FALSE;
4088 }
4089
4090 int
can_build_or_help(Unit * unit)4091 can_build_or_help(Unit *unit)
4092 {
4093 int u2;
4094
4095 if (indep(unit)
4096 && g_indepside_can_build() != TRUE)
4097 return FALSE;
4098 for_all_unit_types(u2) {
4099 if (could_create(unit->type, u2)
4100 || could_build(unit->type, u2)
4101 || could_develop(unit->type, u2))
4102 return TRUE;
4103 }
4104 return FALSE;
4105 }
4106
4107 int
can_research(Unit * unit)4108 can_research(Unit *unit)
4109 {
4110 /* Kind of crude, but works for now. */
4111 if (u_advanced(unit->type))
4112 return TRUE;
4113 return FALSE;
4114 }
4115
4116 int
can_produce(Unit * unit)4117 can_produce(Unit *unit)
4118 {
4119 int m;
4120
4121 for_all_material_types(m) {
4122 if (um_acp_to_produce(unit->type, m))
4123 return TRUE;
4124 }
4125 return FALSE;
4126 }
4127
4128 int
total_production(Unit * unit,int m)4129 total_production(Unit *unit, int m)
4130 {
4131 int t = terrain_at(unit->x, unit->y);
4132 int prod;
4133
4134 prod = base_production(unit, m);
4135 /* This simplified calcualtion does not include productivity limits
4136 or the probabilistic nature of terrain productivity effects. */
4137 prod *= ut_productivity(unit->type, t);
4138 prod /= 100;
4139 /* Add in the production cache for advanced units. */
4140 if (u_advanced(unit->type)) {
4141 prod += unit->production[m];
4142 }
4143 return prod;
4144 }
4145
4146 int
base_production(Unit * unit,int m)4147 base_production(Unit *unit, int m)
4148 {
4149 int u = unit->type, occprod;
4150
4151 if (unit->transport) {
4152 occprod = um_occ_production(u, m);
4153 return (occprod >= 0 ? occprod : um_base_production(u, m));
4154 } else {
4155 return um_base_production(u, m);
4156 }
4157 }
4158
4159 int
total_consumption(Unit * unit,int m)4160 total_consumption(Unit *unit, int m)
4161 {
4162 int consum;
4163
4164 consum = base_consumption(unit, m);
4165 /* Add in size-dependent consumption for advanced units. */
4166 if (u_advanced(unit->type)) {
4167 consum += unit->size * um_consumption_per_size(unit->type, m);
4168 }
4169 return consum;
4170 }
4171
4172 int
base_consumption(Unit * unit,int m)4173 base_consumption(Unit *unit, int m)
4174 {
4175 int consum;
4176
4177 consum = um_base_consumption(unit->type, m);
4178 /* Multiply in effect of being an occupant. */
4179 if (unit->transport) {
4180 consum *= um_consumption_as_occupant(unit->type, m);
4181 }
4182 return consum;
4183 }
4184
4185 /* Check how long a unit can sit where it is. */
4186
4187 int
survival_time(Unit * unit)4188 survival_time(Unit *unit)
4189 {
4190 int m, least = 99999, rate, tmp;
4191
4192 for_all_material_types(m) {
4193 rate = total_consumption(unit, m) - total_production(unit, m);
4194 if (rate > 0) {
4195 tmp = unit->supply[m];
4196 least = min(least, tmp / rate);
4197 }
4198 }
4199 return least;
4200 }
4201
4202 /* Tests if unit will not move due to being immobile or having
4203 a stationary goal. */
4204
4205 int
will_not_move(Unit * unit)4206 will_not_move(Unit *unit)
4207 {
4208 if (!mobile(unit->type))
4209 return TRUE;
4210 if (!is_active(unit))
4211 return TRUE;
4212 /* The human player may have put the unit to sleep in order
4213 to serve as a garrison or sentry. */
4214 if (unit->plan && unit->plan->asleep)
4215 return TRUE;
4216 /* The AI may have assigned the unit to occupy something. */
4217 if (unit->plan && unit->plan->maingoal
4218 && ((unit->plan->maingoal->type == GOAL_UNIT_OCCUPIED
4219 && unit->transport
4220 && unit->transport == find_unit(unit->plan->maingoal->args[0]))
4221 || (unit->plan->maingoal->type == GOAL_CELL_OCCUPIED
4222 && unit->plan->maingoal->args[0] == unit->x
4223 && unit->plan->maingoal->args[1] == unit->y))) {
4224 return TRUE;
4225 }
4226 return FALSE;
4227 }
4228
4229 int
needs_material_to_move(Unit * unit,int m)4230 needs_material_to_move(Unit *unit, int m)
4231 {
4232 if (mobile(unit->type)
4233 && um_consumption_per_move(unit->type, m) > 0) {
4234 return TRUE;
4235 }
4236 return FALSE;
4237 }
4238
4239 int
needs_material_to_survive(Unit * unit,int m)4240 needs_material_to_survive(Unit *unit, int m)
4241 {
4242 if (total_consumption(unit, m) > 0) {
4243 return TRUE;
4244 }
4245 return FALSE;
4246 }
4247
4248 /* Test if unit can move out into adjacent cells. */
4249
4250 int
can_move(Unit * unit)4251 can_move(Unit *unit)
4252 {
4253 int d, x, y;
4254
4255 for_all_directions(d) {
4256 if (interior_point_in_dir(unit->x, unit->y, d, &x, &y)) {
4257 /* (should account for world-leaving options?) */
4258 if (could_live_on(unit->type, terrain_at(x, y)))
4259 return TRUE;
4260 }
4261 }
4262 return FALSE;
4263 }
4264
4265 /* This is the maximum distance from "home" that a unit can expect to get,
4266 travelling on its most hostile terrain type. */
4267
4268 int
operating_range_worst(int u)4269 operating_range_worst(int u)
4270 {
4271 int m, t, prod, range, worstrange = area.maxdim;
4272
4273 for_all_material_types(m) {
4274 if (um_base_consumption(u, m) > 0) {
4275 for_all_terrain_types(t) {
4276 if (!terrain_always_impassable(u, t)) {
4277 prod = (um_base_production(u, m) * ut_productivity(u, t))
4278 / 100;
4279 /* (Need to consider direct withdrawals from treasury.) */
4280 if (prod < um_base_consumption(u, m)) {
4281 range = um_storage_x(u, m) /
4282 (um_base_consumption(u, m) - prod);
4283 if (range < worstrange)
4284 worstrange = range;
4285 }
4286 }
4287 }
4288 }
4289 }
4290 return worstrange;
4291 }
4292
4293 /* Worst operating range for a real unit with given supplies. */
4294
4295 int
real_operating_range_worst(Unit * unit)4296 real_operating_range_worst(Unit *unit)
4297 {
4298 int m, t, prod, range, worstrange = area.maxdim;
4299 int u = unit->type;
4300
4301 for_all_material_types(m) {
4302 if (um_base_consumption(u, m) > 0) {
4303 for_all_terrain_types(t) {
4304 if (!terrain_always_impassable(u, t)) {
4305 prod = (um_base_production(u, m) * ut_productivity(u, t))
4306 / 100;
4307 /* (Need to consider direct withdrawals from treasury.) */
4308 if (prod < um_base_consumption(u, m)) {
4309 range = unit->supply[m] /
4310 (um_base_consumption(u, m) - prod);
4311 if (range < worstrange)
4312 worstrange = range;
4313 }
4314 }
4315 }
4316 }
4317 }
4318 return worstrange;
4319 }
4320
4321 /* Same, but for best terrain. */
4322
4323 int
operating_range_best(int u)4324 operating_range_best(int u)
4325 {
4326 int m, t, prod, range, tbestrange, tbest = 0, bestrange = 0;
4327 int moves, consump;
4328
4329 for_all_terrain_types(t) {
4330 if (!terrain_always_impassable(u, t)) {
4331 tbestrange = area.maxdim;
4332 for_all_material_types(m) {
4333 consump = 0;
4334 moves = (type_max_acp(u) * type_max_speed(u)) / 100;
4335 if (um_consumption_per_move(u, m) > 0) {
4336 consump = moves * um_consumption_per_move(u, m);
4337 }
4338 if (moves <= 0)
4339 moves = 1;
4340 if (um_base_consumption(u, m) > 0) {
4341 consump = max(consump, um_base_consumption(u, m));
4342 }
4343 /* (Need to consider direct withdrawals from treasury.) */
4344 prod = (um_base_production(u, m) * ut_productivity(u, t)) / 100;
4345 if (prod > 0) {
4346 consump = max(0, consump - prod);
4347 }
4348 if (consump > 0) {
4349 range = (um_storage_x(u, m) * moves) / consump;
4350 if (range < tbestrange)
4351 tbestrange = range;
4352 }
4353 }
4354 if (tbestrange > bestrange) {
4355 bestrange = tbestrange;
4356 tbest = t;
4357 }
4358 }
4359 }
4360 return bestrange;
4361 }
4362
4363 /* Best operating range for a real unit with given supplies. */
4364
4365 int
real_operating_range_best(Unit * unit)4366 real_operating_range_best(Unit *unit)
4367 {
4368 int m, t, prod, range, tbestrange, tbest = 0, bestrange = 0;
4369 int moves, consump, tmoves = 0;
4370 int u = unit->type;
4371 int u2 = NONUTYPE;
4372 Unit *unit2 = NULL;
4373
4374 if (unit->transport && mobile(unit->transport->type)
4375 && !u_is_carrier(unit->transport->type))
4376 return real_operating_range_best(unit->transport);
4377 for_all_terrain_types(t) {
4378 if (!terrain_always_impassable(u, t)) {
4379 tbestrange = area.maxdim;
4380 for_all_material_types(m) {
4381 consump = 0;
4382 moves = (type_max_acp(u) * type_max_speed(u)) / 100;
4383 if (um_consumption_per_move(u, m) > 0) {
4384 consump = moves * um_consumption_per_move(u, m);
4385 }
4386 if (moves <= 0)
4387 moves = 1;
4388 #if (0)
4389 /* Is transport a refuelling source? */
4390 if (unit->transport
4391 && valid(can_refuel(unit->transport, unit, m)))
4392 unit2 = unit->transport;
4393 /* Account for resupplier that may pull away. */
4394 if (unit2) {
4395 u2 = unit->transport->type;
4396 if (mobile(u2) && u_is_carrier(u2)) {
4397 tmoves = (type_max_acp(u2) * type_max_speed(u2)) / 100;
4398 if (um_consumption_per_move(u, m) > 0)
4399 consump += tmoves * um_consumption_per_move(u, m);
4400 }
4401 }
4402 #endif
4403 if (um_base_consumption(u, m) > 0) {
4404 consump = max(consump, um_base_consumption(u, m));
4405 }
4406 /* (Need to consider direct withdrawals from treasury.) */
4407 prod = (um_base_production(u, m) * ut_productivity(u, t)) / 100;
4408 prod +=
4409 (um_base_production(u, m) * ut_productivity_adj(u, t)) /
4410 100;
4411 if (prod > 0) {
4412 consump = max(0, consump - prod);
4413 }
4414 if (consump > 0) {
4415 range = (unit->supply[m] * moves) / consump;
4416 if (range < tbestrange)
4417 tbestrange = range;
4418 }
4419 }
4420 if (tbestrange > bestrange) {
4421 bestrange = tbestrange;
4422 tbest = t;
4423 }
4424 }
4425 }
4426 return bestrange;
4427 }
4428
4429 /* Fill an utype array from a GDL list. */
4430
4431 void
fill_utype_array_from_lisp(int * typeary,Obj * typeobj)4432 fill_utype_array_from_lisp(int *typeary, Obj *typeobj)
4433 {
4434 int u = NONUTYPE;
4435 char *uname = NULL;
4436 Obj *rest = lispnil, *curobj = lispnil;
4437
4438 /* Sanity Checks. */
4439 assert_error(typeobj, "Attempted to access a NULL GDL form");
4440 assert_error(typeary, "Attempted to fill a NULL utype array");
4441 if (lispnil == typeobj) {
4442 run_warning("Bad unit type object encountered");
4443 return;
4444 }
4445 /* Test symbols. */
4446 if (symbolp(typeobj)) {
4447 /* If all utypes were specified, then adjust utype array accordingly. */
4448 if (match_keyword(typeobj, K_USTAR)) {
4449 for_all_unit_types(u)
4450 typeary[u] = TRUE;
4451 }
4452 /* Else if the symbol is bound, expand it. */
4453 else if (boundp(typeobj))
4454 fill_utype_array_from_lisp(typeary, eval_symbol(typeobj));
4455 /* Else, see if we can match the symbol name to an unit type name. */
4456 else
4457 fill_utype_array_from_lisp(typeary, new_string(c_string(typeobj)));
4458 }
4459 /* Test string values. */
4460 else if (stringp(typeobj)) {
4461 uname = c_string(typeobj);
4462 for_all_unit_types(u) {
4463 if (!strcmp(u_type_name(u), uname)) {
4464 typeary[u] = TRUE;
4465 break;
4466 }
4467 }
4468 if (u >= numutypes)
4469 run_warning("Bad unit type name, \"%s\" encountered", uname);
4470 }
4471 /* Test integer values. */
4472 else if (numberp(typeobj) || utypep(typeobj)) {
4473 u = c_number(typeobj);
4474 if (!is_unit_type(u))
4475 run_warning("Bad unit type number, %d, encountered", u);
4476 else
4477 typeary[u] = TRUE;
4478 }
4479 /*! \todo Handle utype objects? */
4480 /* Iterate through a list. */
4481 else if (consp(typeobj)) {
4482 /* Take care of things such as 'append'. */
4483 typeobj = eval(typeobj);
4484 /* Now go through the list. */
4485 for_all_list(typeobj, rest) {
4486 curobj = car(rest);
4487 if ((lispnil == curobj) || consp(curobj)) {
4488 run_warning("Bad unit type encountered");
4489 continue;
4490 }
4491 else {
4492 fill_utype_array_from_lisp(typeary, curobj);
4493 }
4494 }
4495 }
4496 else
4497 run_warning("Bad unit type encountered");
4498 }
4499