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*)&paramboxs);
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