1    | /*
2    |    ** $Log: st_build.c,v $
3    |    ** Revision 1.33  2004/10/05 23:18:11  millis
4    |    ** Fix Bug 366 (cannot waive in duplex games)
5    |    **
6    |    ** Revision 1.32  2004/07/25 16:13:44  millis
7    |    ** Bug fixes for Bug 91 (Duplex powers), Bug 233 (Abandoned power cannot
8    |    ** return in duplex) and Bug 206 (allow takeover of unknown abandoned
9    |    ** countries)
10   |    **
11   |    ** Revision 1.31  2004/07/13 00:29:26  millis
12   |    ** Fix bug 339, allowing build transform games to permit players changing
13   |    ** mind about builds without allowing too many.
14   |    **
15   |    ** Revision 1.30  2004/06/27 01:50:22  millis
16   |    ** Futher Intimate fixes (Bug 297) specifically to allow phased orders
17   |    ** and correct turns not processing, plus more information printed.
18   |    **
19   |    ** Revision 1.29  2004/05/23 22:48:12  millis
20   |    ** Fix for Intimate, show default disbands for controlled powers
21   |    **
22   |    ** Revision 1.28  2004/05/22 08:51:02  millis
23   |    ** Bug 297: Add Intimate Diplomacy
24   |    **
25   |    ** Revision 1.27  2004/01/04 11:34:35  millis
26   |    ** Implement Bug #262 (ExtraCentres for 1900 Steamroller)
27   |    **
28   |    ** Revision 1.26  2003/07/24 23:00:43  millis
29   |    ** Fix bug 202
30   |    **
31   |    ** Revision 1.25  2003/05/14 07:59:24  millis
32   |    ** Antoher build problem resolved (all builds were rejected).
33   |    **
34   |    ** Revision 1.24  2003/05/12 21:43:04  millis
35   |    ** Fixed bug that didn't work out correct builds.
36   |    **
37   |    ** Revision 1.23  2003/05/12 02:38:23  millis
38   |    ** Bug 118 fix, correctly handle transforms for fleets.
39   |    **
40   |    ** Revision 1.22  2003/05/10 00:46:15  millis
41   |    ** Bug 140 fix, display 'orders' when orders and 'results' when results
42   |    **
43   |    ** Revision 1.21  2003/05/04 22:39:45  millis
44   |    ** Fixed build counting in ExtraCentres() game
45   |    **
46   |    ** Revision 1.20  2003/05/03 22:45:32  millis
47   |    ** take account of ExtraCentres() if set.
48   |    **
49   |    ** Revision 1.19  2003/05/02 21:39:33  millis
50   |    ** Added handling of assumed home centres
51   |    **
52   |    ** Revision 1.18  2003/02/09 23:07:09  millis
53   |    ** Corrected order of GetUnit() call
54   |    ** Also removed superfluous blank line on order output
55   |    **
56   |    ** Revision 1.17  2003/02/05 01:10:00  millis
57   |    ** Fixed small bug with pending build unit count
58   |    **
59   |    ** Revision 1.16  2003/01/18 23:46:03  millis
60   |    ** Integrated USTV changes.
61   |    **
62   |    ** Revision 1.15  2003/01/18 15:17:28  millis
63   |    ** first intermediate checkin, with Native and Multi-province support
64   |    **
65   |    ** Revision 1.14  2002/12/12 01:46:31  millis
66   |    ** Fixed Bug 51 (Suez counting as an owned province)
67   |    **
68   |    ** Revision 1.13  2002/06/10 22:07:02  millis
69   |    ** Small fix to init_build(), that was counting gateway units as units
70   |    **
71   |    ** Revision 1.12  2002/05/17 11:34:26  miller
72   |    ** Fixed small bug for CheckOwnedOK() returning bad value
73   |    **
74   |    ** Revision 1.11  2002/05/11 09:15:34  greg
75   |    ** Minor bug fixes
76   |    ** - fixed subjectline for absence requests
77   |    ** - fixed phase length, so it's no longer hard coded for responses
78   |    ** - partial fix for unusable builds, players with only unusable builds
79   |    **    will no longer be flagged as having orders due, however players
80   |    **    with some usable builds will need to waive any unusable builds,
81   |    **    also, if one or more players have unusable builds, but no
82   |    **    player has usable builds, the build phase will process after
83   |    **    a short delay
84   |    **
85   |    ** Revision 1.10  2002/04/15 12:55:46  miller
86   |    ** Multiple changes for blind & Colonial & setup from USTV
87   |    **
88   |    ** Revision 1.9  2001/12/28 06:21:24  nzmb
89   |    ** Fixed bug causing segmentation fault in st_build.c .. there was an extra %s in line 402.
90   |    **
91   |    ** Revision 1.7  2001/10/29 23:41:34  miller
92   |    ** Fixed reoccurring chaos bug (use centre() macro not 'x' to test province)
93   |    **
94   |    ** Revision 1.6  2001/10/20 12:11:14  miller
95   |    ** Merged in changes from DEMA and USTV 
96   |    **
97   |    ** Revision 1.5.2.1  2001/10/20 00:52:49  dedo
98   |    ** Remvoe compile warnings
99   |    **
100  |    ** Revision 1.5  2001/02/26 11:27:12  miller
101  |    ** Fixed small bug on line 107, using [i] instead of [p]
102  |    **
103  |    ** Revision 1.4  2000/11/18 21:12:14  miller
104  |    ** Fixed ONECENTRE bug
105  |    **
106  |    ** Revision 1.3  2000/11/16 20:42:40  miller
107  |    ** New changes for phased move syntax check, transformations and onecentre/anycentre
108  |    **
109  |    ** Revision 1.2  1999/02/04 19:10:52  davidn
110  |    ** buildout(). Altered index of mastrpt_pr to fix crashes on USTR.
111  |    ** Array is indexed by unit[].owner, which can be 1 to NPOWER (=around 100 on the
112  |    ** standard judge). MAXPLAYER is 50.
113  |    **
114  |    ** Revision 1.1  1998/02/28 17:49:42  david
115  |    ** Initial revision
116  |    **
117  |    ** Revision 1.1  1996/10/20 12:29:45  rpaar
118  |    ** Morrolan v9.0
119  |    **
120  |  */
121  | 
122  | /*  st_build.c
123  |    **
124  |    **  Copyright 1987, Lowe.
125  |    **
126  |    **  Diplomacy is a trademark of the Avalon Hill Game Company, Baltimore,
127  |    **  Maryland, all rights reserved; used with permission.
128  |    **
129  |    **  Redistribution and use in source and binary forms are permitted
130  |    **  provided that it is for non-profit purposes, that this and the
131  |    **  above notices are preserved and that due credit is given to Mr.
132  |    **  Lowe.
133  |    **
134  |  */
135  | 
136  | /*
137  |  *  03 Dec 1999 Millis Miller  Discount blockaded centres from powers builds
138  |  */
139  | 
140  | #include <stdio.h>
141  | #include <stdlib.h>
142  | #include <string.h>
143  | 
144  | #include "dip.h"
145  | #include "functions.h"
146  | #include "porder.h"
147  | 
148  | #define PossibleHomeCentre(p1) (p1 == 'x' || \
149  | 		    (p1 >= '0' && p1 <= '9') || \
150  |                     (p1 >= 'A' && p1 <= 'Z'))
151  | 
152  | 
153  | int one_owned[NPOWER + 1];
154  | static int ExtraYearCentres(void);
155  | 
156  | int ExtraCentres(int power)
157  | {
158  |     int ret_val = ExtraYearCentres();
159  |     int i;
160  |     int found = 0;
161  | 
162  | /* As can be called externally, make sure one_owned is correct */
163  |     one_owned[power] = 0;
164  |     for (i = 1; i <= npr; i++) {
165  |         if (pr[i].owner == power &&
166  |         ((pr[i].type == dipent.pl[power]) || dipent.xflags & XF_BUILD_ANYCENTRES) &&
167  |           pr[i].blockaded == 0 ) { /* Was doing something here, no more! */
168  |            if (pr[i].owner == power && pr[i].type == dipent.pl[power]) {
169  |                one_owned[power]++;
170  | 	   }
171  |         }
172  |     }
173  | 
174  |     if (dipent.x2flags & X2F_EXTRA_HC) {
175  | 	    for (i = 0; i < MAXPLAYERS && 
176  | 			!found && 
177  | 			extra_centres[i].power_letter != '\0'; i++) {
178  |                 if (pletter[dipent.variant][power] == extra_centres[i].power_letter) {
179  | 		    found++;
180  | 		    if (one_owned[power])
181  | 			ret_val += extra_centres[i].count;
182  | 		}
183  | 	   
184  | 	    }
185  |     }
186  | 
187  |     return ret_val;
188  | }
189  | 
190  | static int ExtraYearCentres(void) 
191  | {
192  |     int current_year;
193  |     int first_year;
194  | 
195  |     if (dipent.extra_centres == 0)
196  |         return 0;
197  | 
198  |     current_year = atoi(&dipent.phase[1]);
199  |     first_year = atoi(&sphase[dipent.variant][1]);
200  | 
201  |     if ((current_year - first_year) <= dipent.extra_centres)
202  |         return (dipent.extra_centres - current_year + first_year);
203  | 
204  |     return 0;
205  | }
206  | 
207  |     
208  | 
209  | int CountHomeCentres( int p)
210  | {
211  |     int total = 0;
212  |     int i;
213  | 
214  |     for ( i = 1; i <= npr; i++)
215  |         if (pr[i].type == pletter[dipent.variant][p] )
216  |             total++;
217  | 
218  |     return total;
219  | }
220  | 
221  | int CountCentres( int p )
222  | {
223  | 
224  |     int total = 0;
225  |     int i;
226  | 
227  |     for ( i = 1; i <= npr; i++)
228  |         if (pr[i].owner ==  p )
229  |             total++;
230  | 
231  |     return total;
232  | }
233  | 
234  | 
235  | static int nu[NPOWER + 1], lu[NPOWER + 1];
236  | /* See if passed location is in conditions to be built on */
237  | int CheckOwnedOK( char type, int u, int p, int p1, int *c1)
238  | {
239  |         unsigned char *t;
240  | 
241  | 	if (pr[p1].blockaded) {
242  |             errmsg("Cannot transform wing as it is blockading %s.\n",
243  |                                 pr[p1].name);
244  |                         return 0;
245  |         }
246  | 
247  |         if (water(p1)) {
248  |                     errmsg("Cannot transform %s while %s water.\n",
249  |                                 utype(unit[u].type),
250  |                                 unit[u].type == 'F' ? "in" : "over");
251  |                     return 0;
252  |         }
253  | 
254  |         if (type == 'x') {
255  |                 errmsg("Unit type must be specified.\n");
256  |                 return 0;
257  |         }
258  |         if (type == 'A')
259  |                 *c1 = MV;
260  |         else if (type == 'W' ) {
261  |                 *c1 = MV;  /* Temporary for Wings */
262  |                 if (!(dipent.flags & F_WINGS)) {
263  |                         errmsg("This game does not allow wings.\n");
264  |                         return 0;
265  |                 }
266  | 	} else if (type == 'R') {	
267  | 		*c1 = MV;
268  | 		if (!(dipent.x2flags & X2F_ARTILLERY)) {
269  | 			errmsg("This game does not allow artillery.\n");
270  | 			return 0;
271  | 		}
272  |         } else {
273  |                 if (!(*c1))
274  |                         *c1 = XC;
275  |                 for (t = (char *) pr[p1].move; *t; t++)
276  |                         if (*++t >> 4 == *c1)
277  |                                 break;
278  |                 if (!*t) {
279  |                         errmsg("Invalid coast specified for fleet in %s.\n",
280  |                                pr[p1].name);
281  |                         return 0;
282  |                 }
283  |         }
284  | 
285  |         return 1; /* it passed ok */
286  | }
287  | /****************************************************************************/
288  | void init_build(void)
289  | {
290  | 	int i=0, p;
291  | 
292  | 
293  | 	UpdateBlockades();
294  | 
295  | 	/*  Count number of units allowed to be built.  */
296  | 
297  | 	for (p = 1; p <= NPOWER; p++) {
298  | 
299  | 	        /* Just in case it got changed, i.e. X2F_MORE_HOMES game! */
300  | 		if (PossibleHomeCentre(pr[p].type) && 
301  | 		    PossibleHomeCentre(pletter[dipent.variant][pr[p].home]))
302  | 		    pr[p].type = pletter[dipent.variant][pr[p].home];
303  | 		
304  | 		nu[p] = 0;
305  | 		lu[p] = 0;
306  | 		
307  | 		nu[p] += ExtraCentres(p);
308  | 		
309  | 		for (i = 1; i <= npr; i++) {
310  | 		    if (gateway(i)) continue; /* Gateways don't count */
311  | 		    /* Just in case it got changed, i.e. X2F_MORE_HOMES game! */
312  |                     if (PossibleHomeCentre(pr[i].type) &&
313  |                     PossibleHomeCentre(pletter[dipent.variant][pr[i].home]))
314  |                     pr[i].type = pletter[dipent.variant][pr[i].home];
315  | 
316  | 
317  | 		    if (pr[i].owner == p && 
318  | 		        pr[i].blockaded == 0 && 
319  | 			PossibleHomeCentre(pr[i].type))
320  | 				nu[p]++;
321  | 		}
322  | 
323  | 		for (i = 1; i <= nunit; i++)
324  | 			if (unit[i].owner == p && !gateway(unit[i].loc))
325  | 				nu[p]--;
326  | 		if (nu[p] < 0)
327  | 			nu[p]--;
328  | 		if (nu[p] > 0)
329  | 			nu[p]++;
330  | 
331  | 	}
332  | }
333  | 
334  | int build_syntaxcheck(char *in_text, int precheck, char *out_string)
335  | {
336  | 	char *s = in_text;
337  | 
338  | 	char type, order;
339  | 	unsigned char *t;
340  | 	int p1, c1;
341  | 	char temp_out[256];
342  | 	char *out_text = NULL;
343  | 	temp_out[0]='\0';
344  | 	if (out_string != NULL) out_text = temp_out;
345  | 
346  | 	/*
347  | 	   **  Process lines of the form:
348  | 	   **
349  | 	   **    cmd   ::= <power>: {<order>} <type> <province>
350  | 	   **    order ::= build | remove ¦ transform
351  | 	   **    type  ::= Army | Fleet | Wing
352  | 	 */
353  | 
354  | 	/* 
355  |          * See if a precheck is possible
356  | 	 * If so, see if it is an canprocess line and assume ok if so
357  |          */
358  | 
359  | 	if (precheck) 
360  | 	{
361  | 		if (canpreprocess(s))  return 0;
362  | 	}
363  | 
364  | 	s = get_order(s, &order);
365  | 	AddOrderToOrder(out_text,order);
366  | 	s = get_type(s, &type);
367  | 	s = get_prov(s, &p1, &c1);
368  | 	
369  | 	if (!p1 && order != 'w') {
370  | 		errmsg("Unrecognized province -> %s", s);
371  | 		return E_WARN;
372  | 	}
373  | 	*s = '\0'; /* End of string found, so terminate it */
374  | 
375  | 	switch (order) {
376  | 	case 'b':
377  | 		AddUnitProvinceToOrder(out_text,type, p1);
378  | 		if (type == 'x') {
379  | 			errmsg("Unit type must be specified for build.\n");
380  | 			return E_WARN;
381  | 		}
382  | 		if (pr[p1].type == 'w' || pr[p1].type == 'l') {
383  |     			errmsg("%s is not a supply centre.\n",
384  |     				pr[p1].name);
385  |     			return E_WARN;
386  |     		}
387  | 
388  | 		if (type == 'A')
389  | 			c1 = MV;
390  | 		else if (type == 'W' ) {
391  | 			c1 = MV;  /* Temporary for Wings */
392  | 			if (!(dipent.flags & F_WINGS)) {
393  | 				errmsg("This game does not allow wings.\n");
394  | 				return E_WARN;
395  | 			}
396  | 		} else if (type == 'R') {
397  |                     c1 = MV;
398  |                     if (!(dipent.x2flags & X2F_ARTILLERY)) {
399  |                         errmsg("This game does not allow artillery.\n");
400  |                         return E_WARN;
401  | 		    }
402  | 
403  | 		} else {
404  | 			if (!c1)
405  | 				c1 = XC;
406  | 			for (t = (char *) pr[p1].move; *t; t++)
407  | 				if (*++t >> 4 == c1)
408  | 					break;
409  | 			if (!*t) {
410  | 				errmsg("Invalid coast specified for fleet in %s.\n",
411  | 				       pr[p1].name);
412  | 				return E_WARN;
413  | 			}
414  | 		}
415  | 
416  | 		break;
417  | 	case 'w':
418  | 		break;
419  | 
420  | 	case 'm':
421  | 		break;
422  | 
423  | 	case 'r':
424  | 		AddUnitProvinceToOrder(out_text,type, p1);
425  | 		break;
426  | 
427  | 	case 'h':  /* Home centre definition */
428  | 	case 'n':  /* Home centre definition cancellation */
429  | 		if (!(dipent.x2flags & X2F_MORE_HOMES)) {
430  | 		     errmsg("Invalid build order encountered.\n");
431  | 		    return E_WARN;
432  | 		}
433  | 		if (pr[p1].type != 'x' && 
434  | 		    !(pr[p1].type >= '0' && pr[p1].type <= '9') && 
435  | 		    !(pr[p1].type >= 'A' && pr[p1].type <= 'Z')) {
436  | 		        errmsg("Invalid province to make home centre.\n");
437  | 			return E_WARN;
438  | 		}
439  | 		AddProvinceToOrder(out_text, p1);
440  | 		break;
441  | 
442  | 	case 't':
443  | 		
444  | 		AddUnitProvinceToOrder(out_text,type, p1);
445  |                  if (!(dipent.xflags & XF_TRANS_BUILD)) {
446  |                         errmsg("Build transformation is not enabled for this game.\n");
447  |                         return E_WARN;
448  |                 }
449  | 		if (water(p1)) {
450  |                     errmsg("Cannot transform while in/over water.\n");
451  |                     return E_WARN;
452  |                 }
453  | 		if (type == 'W' ) {
454  |                         if (!(dipent.flags & F_WINGS)) {
455  |                                 errmsg("This game does not allow wings.\n");
456  |                                 return E_WARN;
457  |                         }
458  | 		}
459  | 		if (type == 'R') {
460  |                     if (!(dipent.x2flags & X2F_ARTILLERY)) {
461  |                         errmsg("This game does not allow artillery.\n");
462  |                         return E_WARN;
463  | 		    }
464  |                 }
465  | 
466  | 
467  | 		break;
468  | 
469  | 	default:
470  | 		errmsg("Invalid build order encountered.\n");
471  | 		return E_WARN;
472  | 	}
473  | 	if (out_text != NULL) strcpy(out_string, out_text);
474  | 	return 0;
475  | }
476  | int buildin(char **s, int p)
477  | {
478  | /*  Read build orders in from input file.  */
479  | 
480  | 	char type, order;
481  | 	unsigned char *t;
482  | 	int i, j, u=0, p1, c1, p2, pow;
483  | 
484  | 	/*
485  | 	   **  Process lines of the form:
486  | 	   **
487  | 	   **    cmd   ::= <power>: {<order>} <type> <province>
488  | 	   **    order ::= build | remove ¦ transform
489  | 	   **    type  ::= Army | Fleet | Wing
490  | 	 */
491  | 
492  | 
493  | 	*s = get_order(*s, &order);
494  | 	*s = get_type(*s, &type);
495  | 	*s = get_prov(*s, &p1, &c1);
496  | 	if (!p1 && order != 'w' && order != 'u') {
497  | 		errmsg("Unrecognized province -> %s", *s);
498  | 		return E_WARN;
499  | 	}
500  | 	if (p == MASTER) {
501  | 		if (pr[p1].unit) {
502  | 			p = unit[pr[p1].unit].owner;
503  | 		} else {
504  | 			p = pr[p1].owner;
505  | 		}
506  | 	}
507  | 	if (IS_DUPLEX(dipent)) {
508  | 	    /* See if I am ordering for one of my controlled powers */
509  | 	    /* Either in its province or one of its units */
510  | 	    p2 = pr[p1].owner;
511  | 	    if (p2 == 0)
512  | 	        if (pr[p1].unit)
513  | 		    p2 = unit[pr[p1].unit].owner;
514  | 	    if (p == PowerControlledBy(p2))
515  | 	        p = p2; /* Yes, so become that power */
516  | 	}
517  | 	if (order == 'x' && !(dipent.xflags & XF_ANYDISBAND))
518  | 		order = nu[p] >= 0 ? 'b' : 'r';
519  | 
520  | 	if (!(dipent.xflags & XF_ANYDISBAND))
521  | 	/* Do not check for waive condition if a duplex (non-intimate) game 
522  | 	 * This will be checked later in the waive code itself (Bug 366) */
523  | 	if ((order == 'b' && (nu[p] <= 0  && !(dipent.xflags & XF_ANYDISBAND) )) ||
524  | 	    (!(IS_DUPLEX(dipent) && !(dipent.flags & F_INTIMATE)) && order == 'w' && (nu[p] <= 0  && !(dipent.xflags & XF_ANYDISBAND) )) ||
525  | 	    (order == 'r' && nu[p] >= 0)) {
526  | 		errmsg("%s is not permitted to %s any units.\n",
527  | 		       powers[p], order == 'r' ? "remove" : "build");
528  | 		return E_WARN;
529  | 	}
530  | 	switch (order) {
531  | 	case 'b':
532  | 		if (((dipent.xflags & XF_BUILD_ONECENTRE) ==  XF_BUILD_ONECENTRE) && one_owned[p] < 1) {
533  | 			errmsg("%s must own at least one home centre to build.\n",
534  | 			       powers[p]);
535  | 			return E_WARN;
536  | 		}
537  |                 if (pr[p1].type == 'w' || pr[p1].type == 'l') {
538  |                         errmsg("%s is not a supply centre.\n",
539  |                                 pr[p1].name);
540  |                         return E_WARN;
541  |                 }
542  | 		if (pr[p1].type != dipent.pl[p] 
543  | 		    && !(dipent.xflags & XF_BUILD_ANYCENTRES)) {
544  | 			errmsg("%s is not a home province for %s.\n",
545  | 			       pr[p1].name, powers[p]);
546  | 			return E_WARN;
547  | 		}
548  | 		if (pr[p1].owner != p) {
549  | 			errmsg("%s does not control %s.\n",
550  | 			       powers[p], pr[p1].name);
551  | 			return E_WARN;
552  | 		}
553  | 		if (type == 'x') {
554  | 			errmsg("Unit type must be specified for build.\n");
555  | 			return E_WARN;
556  | 		}
557  | 		if (pr[p1].blockaded) {
558  | 			errmsg("Cannot build in %s as it is blockaded.\n",
559  | 				pr[p1].name);
560  | 			return E_WARN;
561  | 		}
562  | 		if (type == 'A')
563  | 			c1 = MV;
564  | 		else if (type == 'W' ) {
565  | 			c1 = MV;  /* Temporary for Wings */
566  | 			if (!(dipent.flags & F_WINGS)) {
567  | 				errmsg("This game does not allow wings.\n");
568  | 				return E_WARN;
569  | 			}	
570  | 		} else if (type == 'R') {
571  |                         c1 = MV;
572  |                         if (!(dipent.x2flags & X2F_ARTILLERY)) {
573  |                             errmsg("This game does not allow artillery.\n");
574  |                             return E_WARN;
575  | 			}
576  |                 } else {
577  | 			if (!c1)
578  | 				c1 = XC;
579  | 			for (t = (char *) pr[p1].move; *t; t++)
580  | 				if (*++t >> 4 == c1)
581  | 					break;
582  | 			if (!*t) {
583  | 				errmsg("Invalid coast specified for fleet in %s.\n",
584  | 				       pr[p1].name);
585  | 				return E_WARN;
586  | 			}
587  | 		}
588  | 
589  | 		/*  FALL THROUGH  */
590  | 	case 'w':
591  | 
592  | 		if (order == 'w' && (IS_DUPLEX(dipent) && !(dipent.flags & F_INTIMATE))) {
593  | 		   /* If real duplex, need to specify power that want to waive for */
594  | 		   get_power(*s, &pow);
595  | 
596  | 		   if (!pow) {
597  | 		        pow = power(**s);
598  | 		        if (pow <= 0 || pow >= WILD_PLAYER) {
599  | 		               errmsg("Unrecognized power -> %s", *s);
600  | 		               return E_WARN;
601  | 		        }
602  | 		        *s+= 2;  /* Skip power letter and space */
603  | 		   } else {
604  | 		        *s = get_power(*s, &i);  /* Consume the power text (if there) */
605  | 		   }
606  | 		   if (!(pow == p || PowerControlledBy(pow) == p)) {
607  | 		       errmsg("Power is not controlled by you - invalid waive.\n");
608  | 		       return E_WARN;
609  | 		   } else
610  | 		   p = pow;  /* Become the power that you want to waive for */
611  | 		   /* Bug 366, check if power does have builds to waive! */
612  | 		   if (nu[p] <= 0  && !(dipent.xflags & XF_ANYDISBAND))
613  | 		    {
614  | 		        errmsg("%s is not permitted to build any units.\n",
615  | 		               powers[p]);
616  | 		        return E_WARN;
617  | 		    }
618  | 		}
619  | 
620  | 		if ((u = pr[p1].unit)) {
621  | 			if (unit[u].status != 'b' && unit[u].exists ) {
622  | 				errmsg("%s already has a unit present.\n", pr[p1].name);
623  | 				return E_WARN;
624  | 			} else {
625  | 				for (i = lu[p]; i != u && unit[i].order != u; i = unit[i].order);
626  | 				if (i == u)
627  | 					lu[p] = unit[i].order;
628  | 				else
629  | 					unit[i].order = unit[u].order;
630  | 			}
631  | 			pr[unit[u].loc].unit = 0;
632  | 
633  | 			/*
634  | 			   **  If he's building too many, the earliest built gets chucked.
635  | 			 */
636  | 
637  | 		} else if (nu[p] == 1) {
638  | 			for (u = lu[p], i = 0; unit[u].order; u = unit[u].order)
639  | 				i = u;
640  | 			if (i)
641  | 				unit[i].order = 0;
642  | 			else
643  | 				lu[p] = 0;
644  | 			pr[unit[u].loc].unit = 0;
645  | 		} else {
646  | 			nu[p]--;
647  | 			if (dipent.xflags & XF_ANYDISBAND) {
648  | 			    if (nu[p] == 1) nu[p] = -2;
649  | 			}
650  | 			u = ++nunit;
651  | 		}
652  | 
653  | 		if (dipent.xflags & XF_ANYDISBAND) {
654  | 		    /* A Dirty fix that seems to do the trick */
655  | 		    if (!u ) {
656  | 		        nu[p]--;
657  |                             if (nu[p] == 1) nu[p] = -2;
658  |                             u = ++nunit;
659  |                     }
660  | 		}
661  |  
662  | 
663  | 		pr[p1].unit = order == 'w' ? 0 : u;
664  | 		unit[u].owner = p;
665  | 		unit[u].type = type;
666  | 		unit[u].stype = 'x';
667  | 		unit[u].loc = p1;
668  | 		unit[u].coast = c1;
669  | 		unit[u].status = order;
670  | 		unit[u].order = lu[p];
671  | 		lu[p] = u;
672  | 		break;
673  | 
674  | 	case 'u':    /* Unwaive, or remove waive orders */
675  | 		if (dipent.xflags & XF_ANYDISBAND)
676  | 		for (u = 1; u <= nunit; u++) {
677  | 		   if (unit[u].owner == p && unit[u].type == 'x' ) {
678  | 			unit[u].owner = 0; /* not owned! */
679  | 			nu[p]++;
680  | 			if (nu[p] == -1)
681  | 			    nu[p] = 2;
682  | 		    }
683  | 		}
684  | 
685  | 	        break;
686  | 
687  | 
688  | 	case 'm':
689  | 		if (dipent.xflags & XF_ALTBUILD) {
690  | 		    if (!(u = pr[p1].unit) || unit[u].owner != p || !unit[u].exists) {
691  |                         errmsg("%s does not own a unit %s %s to maintain.\n",
692  |                         powers[p], mov_type(p1,u), pr[p1].name);
693  |                         return E_WARN;
694  |                     }
695  | 		    if (unit[u].status == 'd') {
696  | 			nu[p]--;
697  | 		        if (nu[p] == 1)
698  | 			    nu[p] = -2;
699  | 		    }
700  | 			
701  | 		    unit[u].order = 'm';
702  | 		    unit[u].status = 'm';
703  | 		}
704  | 		break;
705  | 
706  | 	case 'r':
707  | 		u = GetUnitIndex(p1, p); /* Will return the next unit to disband */
708  | 		if (!u || unit[u].owner != p) {
709  | 			errmsg("%s does not own a unit %s %s to remove.\n",
710  | 			powers[p], mov_type(p1,u), pr[p1].name);
711  | 			return E_WARN;
712  | 		}
713  | 		/*
714  | 		   *  If this one's already been removed, put it back.
715  | 		 */
716  | 
717  | 		if (!(dipent.xflags & XF_ANYDISBAND)) {
718  | 		    if (unit[u].status == 'd') {
719  | 			nu[p]--;
720  | 			for (i = lu[p], j = 0; i && i != u; i = unit[i].order)
721  | 				j = i;
722  | 			if (j)
723  | 				unit[j].order = unit[u].order;
724  | 			else
725  | 				lu[p] = unit[u].order;
726  | 		}
727  | 		/*
728  | 		   *  If he's removing too many, the earliest one removed comes back.
729  | 		 */
730  | 
731  | 		    if (nu[p] == -1) {
732  | 			for (i = lu[p], j = 0; unit[i].order; i = unit[i].order)
733  | 				j = i;
734  | 			if (j)
735  | 				unit[j].order = 0;
736  | 			else
737  | 				lu[p] = 0;
738  | 			unit[i].status = ':';
739  | 		    } else {
740  | 			nu[p]++;
741  | 		    }
742  | 		}
743  | 		else {
744  | 		    if (dipent.xflags & XF_ANYDISBAND) {
745  | 		    nu[p]++;
746  | 		    if (nu[p] == -1)
747  | 		        nu[p] = 2;  /* Funny threshold, value always avoids +/-1 */
748  | 		    }
749  | 		}
750  | 
751  | 		unit[u].status = 'd';
752  | 		if (!(dipent.xflags & XF_ANYDISBAND)) {
753  | 		    unit[u].order = lu[p];
754  | 		    lu[p] = u;
755  | 		}
756  | 
757  | 		break;
758  | 
759  | 	case 't':
760  | 		u = pr[p1].unit; /* Find out what unit is there */
761  | 
762  | 		if (!(dipent.xflags & XF_TRANS_BUILD)) {
763  |                         errmsg("Build transformation is not enabled for this game.\n");
764  |                         return E_WARN;
765  |                 }
766  | 
767  | 	        if (type == 'x') {
768  |                     errmsg("Unknown unit type to transform to.\n");
769  |                     return E_WARN;
770  |                 }
771  |                 if (unit[u].type == type && type != 'F') {
772  |                     errmsg("Error: Unit in %s is already of type %s.\n",
773  |                     pr[p1].name, Utype(unit[u].type));
774  |                     return E_WARN;
775  |                 }
776  |                 /* If a fleet, check that coast is different */
777  |                 if (type == 'F' && unit[u].type == 'F') {
778  |                     if (c1 == unit[u].coast) {
779  |                         errmsg("Fleet %s already on %s.\n", pr[p1].name, mtype[c1]);
780  |                         return E_WARN;
781  |                     }
782  |                 }
783  | 
784  | 		/* OK, let's see if this can be transformed */
785  | 
786  | 		switch (dipent.xflags & XF_TRANS_BANYW)
787  | 		{
788  | 			case 0: /* Can only transform on home centres */
789  | 		            if (pr[p1].type != dipent.pl[p] && pr[p1].type != 'x' ) {
790  |                                  errmsg("%s is not a home province for %s.\n",
791  |                                         pr[p1].name, powers[p]);
792  |                                 return E_WARN;
793  |                             }
794  | 	                break;
795  | 
796  | 			case XF_TRANS_BONEC: /* Need one home owned centre to transform */
797  | 			                        if (one_owned[p] < 1) {
798  |                         errmsg("%s must own at least one home centre to build.\n",
799  |                                powers[p]);
800  |                         return E_WARN;
801  |                         }
802  | 
803  | 			case XF_TRANS_BANYC:  /* Can transform on any centre */
804  |                         /* but must own the centre */
805  |                         if (pr[p1].owner != p) {
806  |                         errmsg("%s does not control %s.\n",
807  |                                powers[p], pr[p1].name);
808  |                         return E_WARN;
809  |                         }
810  | 			    break;
811  | 
812  | 			default: /*Anywhere at all */
813  | 			    break; /* Nothing to do */
814  | 		}
815  |                 u = pr[p1].unit;
816  | 
817  |  
818  |                 if (!CheckOwnedOK(type, u, p, p1, &c1)) return E_WARN;
819  | 
820  |                 /*
821  |                  *  If this one's already been maked for removal, skip it.
822  |                  */
823  | 
824  |                 if (unit[u].status == 'd' ) {
825  |                         errmsg("%s %s %s is already marked to be removed.\n",
826  |                         Utype(unit[u].type), mov_type(p1,u), pr[p1].name);
827  |                         return E_WARN;
828  |                 } else if (unit[u].status == 'b' ) {
829  |                         errmsg("%s %s %s is already marked to be built.\n",
830  |                         Utype(unit[u].type), mov_type(p1,u), pr[p1].name);
831  |                         return E_WARN;
832  |                 } else if (unit[u].type == type && unit[u].coast == c1) {
833  | 			/* Unit was marked to be transformed, cancel transform */
834  |                         unit[u].status = ' ';
835  | 			unit[u].order = ' ';
836  | 		} else {
837  |                     unit[u].status = 't';
838  |                     unit[u].order = order;
839  |                     unit[u].new_type = type;
840  |                     unit[u].new_coast = c1;
841  |                     /*lu[p] = u;*/
842  |                 }
843  | 		break;
844  | 
845  |         case 'h':  /* Home centre definition */
846  |                 if (!(dipent.x2flags & X2F_MORE_HOMES)) {
847  |                      errmsg("Invalid build order encountered.\n");
848  |                     return E_WARN;
849  |                 }
850  |                 if (pr[p1].type != 'x' &&
851  |                     !(pr[p1].type >= '0' && pr[p1].type <= '9') &&
852  |                     !(pr[p1].type >= 'A' && pr[p1].type <= 'Z')) {
853  |                         errmsg("Invalid province to make home centre.\n");
854  |                         return E_WARN;
855  |                 }
856  |                 /* OK, see if it is owned */
857  |                 if (pr[p1].owner != p) {
858  |                     errmsg("Only owned centres can be made a home centre.\n");
859  |                     return E_WARN;
860  |                 }
861  |                 if (pr[p1].type == pletter[dipent.variant][p]) {
862  |                     errmsg("Centre is already owned by %s.\n",power(p));
863  |                     return E_WARN;
864  |                 }
865  |                 if (CountHomeCentres(p) >= dipent.num_homes) {
866  |                     errmsg("Power already has enough home centres.\n");
867  |                     return E_WARN;
868  |                 }
869  | 
870  |                 if (pr[p1].type == 'x')
871  |                     pr[p1].home = p;
872  |                 else {
873  |                     if (CountCentres(power(pr[p1].type)) > 0) {
874  |                         errmsg("Centre is still used as home centre by %s.\n",
875  |                                 powers[power(pr[p1].type)]);
876  |                         return E_WARN;
877  |                    } else {
878  |                         pr[p1].home = p;
879  |                    }
880  |                 }
881  |                 break;
882  | 
883  | 
884  |         case 'n':  /* Home centre cancel */
885  |             if (!(dipent.x2flags & X2F_MORE_HOMES)) {
886  |                      errmsg("Invalid build order encountered.\n");
887  |                     return E_WARN;
888  |             }
889  |             pr[p1].home = pr[p1].type;
890  |             break;
891  | 
892  | 
893  | 	default:
894  | 		errmsg("Invalid build order encountered.\n");
895  | 		return E_WARN;
896  | 	}
897  | 	return 0;
898  | 
899  | }
900  | 
901  | void buildout(int pt)
902  | {
903  | 	int i, u, p, c1, p_index, counting_centres, u_diff[NPOWER + 1], p1, pp;
904  | 	char mastrpt_pr[NPOWER + 1];    // Used to be [MAXPLAYERS]. DAN 04/02/1999
905  |         int num_units[NPOWER +1];
906  |         int num_hc;
907  |         int pr_found;
908  |         int one_printed;
909  |         int assumed[ NPOWER + 1 ];  /* Count number of centres power is assuming this turn as home centre */
910  | 
911  | 	fprintf(rfp, "Adjustment %s for Winter of %d.  (%s.%s)\n\n",
912  | 		pt ? "orders" : "results",
913  | 		atoi(&dipent.phase[1]), dipent.name, dipent.seq);
914  | 
915  | 	for ( u = 0; u <= NPOWER; u++)
916  | 		num_units[u] = 0;   /* Initialise array */
917  | 	
918  | 	if (pt == MASTER) {
919  | 		for (u = 0; u <= NPOWER; u++)    /* Used to be < MAXPLAYERS. DAN. */
920  | 			mastrpt_pr[u] = 0;
921  | 		for (u = 1; u <= nunit; u++) {
922  | 			if (unit[u].owner <= 0)
923  | 				continue;
924  | 			if (mastrpt_pr[unit[u].owner] != 1) {
925  | 				mastrpt_pr[unit[u].owner] = 1;
926  | 				mast_rpt(unit[u].owner, 1);
927  | 			};
928  | 		};
929  | 		fprintf(rfp, "\n");
930  | 	};
931  | 
932  |         for (p1 = 1;  p1<= npr; p1++) {
933  |             pr_found = 0;
934  |             for (u = 1; u <= nunit; u++) {
935  |                 if (unit[u].loc == p1)
936  |                     pr_found = 1;
937  |             }
938  |             if (!pr_found && pr[p1].type == 'x') {
939  |                 /* Unowned centre: if we have natives, build one there */
940  |                 if (dipent.has_natives &&
941  |                         (pr[p1].owner == dipent.has_natives || !pr[p1].owner)) {
942  |                     unit[++nunit].type = 'A';
943  |                     unit[nunit].stype = 'x';
944  |                     unit[nunit].owner = dipent.has_natives;
945  |                     unit[nunit].status = 'b';
946  |                     unit[nunit].loc = p1;
947  |                 }
948  |             }
949  |          }
950  | 
951  | 	for (p = 1; p <= NPOWER; p++) { /* This loop is just to order by power */
952  |             p_index = FindPower(p);
953  | 	    one_printed = 0;
954  |             if (p_index >= dipent.n) continue; /* Not a valid power */
955  | 	    if (!(processing || pt == p || pt == MASTER || pt == PowerControlledBy(p))) continue;	
956  | 	    for (u = 1; u <= nunit; u++) {
957  | 		if (p == unit[u].owner) {
958  | 
959  | 			if (unit[u].status == 'b') {
960  | 
961  | 				num_units[unit[u].owner]++;
962  | 				fprintf(rfp, "%s: ", powers[unit[u].owner]);
963  | 				for (i = strlen(powers[p]); i < LPOWER; i++)
964  | 					putc(' ', rfp);
965  | 				fprintf(rfp, "Builds %s in %s", autype(unit[u].type),
966  | 					pr[unit[u].loc].name);
967  | 				if ((c1 = unit[u].coast) > XC)
968  | 					fprintf(rfp, " (%s).\n", mtype[c1]);
969  | 				else
970  | 					fprintf(rfp, ".\n");
971  | 				unit[u].status = ':';
972  | 				one_printed++;
973  | 
974  | 			} else if (unit[u].status == 'd' && unit[u].exists) {
975  | 				fprintf(rfp, "%s: ", powers[unit[u].owner]);
976  | 				for (i = strlen(powers[p]); i < LPOWER; i++)
977  | 					putc(' ', rfp);
978  | 				fprintf(rfp, "Removes the %s %s %s.\n",
979  | 					utype(unit[u].type),
980  | 					mov_type(unit[u].loc,u),
981  | 					pr[unit[u].loc].name);
982  | 
983  | 				unit[u].owner = 0;
984  | 				unit[u].status = ':';
985  | 				pr[unit[u].loc].unit_held = 0;
986  | 				one_printed++;
987  | 
988  | 
989  | 			} else if (unit[u].status == 'w') {
990  | 				num_units[unit[u].owner]++;
991  | 				fprintf(rfp, "%s: ", powers[unit[u].owner]);
992  | 				for (i = strlen(powers[p]); i < LPOWER; i++)
993  | 					putc(' ', rfp);
994  | 				fprintf(rfp, "Build waived.\n");
995  | 				unit[u].owner = 0;
996  | 				one_printed++;
997  | 
998  | 			} else if (unit[u].status == 't') {
999  | 				num_units[unit[u].owner]++;
1000 | 				/* Only notify when changing type */
1001 |                                         fprintf(rfp, "%s: ", powers[unit[u].owner]);
1002 |                                         for (i = strlen(powers[p]); i < LPOWER; i++)
1003 |                                                 putc(' ', rfp);
1004 |                                         fprintf(rfp, "Transform the %s %s %s to %s",
1005 |                                                 utype(unit[u].type),
1006 |                                                 mov_type(unit[u].loc,u),
1007 |                                                 pr[unit[u].loc].name,
1008 |                                                 autype(unit[u].new_type));
1009 |                                         if ((c1 = unit[u].new_coast) > XC)
1010 |                                                 fprintf(rfp, " (%s).\n", mtype[c1]);
1011 |                                         else
1012 |                                                 fprintf(rfp, ".\n");
1013 |                                         if (processing) {
1014 |                                                 unit[u].type = unit[u].new_type;
1015 |                                                 unit[u].coast = unit[u].new_coast;
1016 | 					}
1017 | 				unit[u].status = ':';
1018 | 				one_printed++;
1019 | 			} else if (unit[u].status == 'm') {
1020 | 			    num_units[unit[u].owner]++;
1021 | 				/* only notify when explictly maintaining units */
1022 | 			    if (!processing && !predict) {		
1023 | 				fprintf(rfp, "%s: ", powers[unit[u].owner]);
1024 | 				 for (i = strlen(powers[p]); i < LPOWER; i++)
1025 |                                                 putc(' ', rfp);
1026 |                                         fprintf(rfp, "Maintains the %s %s %s.\n",
1027 |                                                 utype(unit[u].type),
1028 |                                                 mov_type(unit[u].loc,u),
1029 |                                                 pr[unit[u].loc].name);
1030 | 				one_printed++;
1031 |  			    }
1032 | 				unit[u].status = ':';
1033 | 			} else if (unit[u].status == ':') {
1034 | 			    num_units[unit[u].owner]++;
1035 | 			    if (dipent.xflags & XF_ALTBUILD) {
1036 |                                 fprintf(rfp, "%s: ", powers[unit[u].owner]);
1037 |                                 for (i = strlen(powers[p]); i < LPOWER; i++)
1038 |                                                 putc(' ', rfp);
1039 |                                 fprintf(rfp, "No order for the %s %s %s", 
1040 | 				             utype(unit[u].type),
1041 | 					     mov_type(unit[u].loc,u),
1042 | 					     pr[unit[u].loc].name);
1043 |                                 if (!processing && !predict ) {
1044 |                                         more_orders++;
1045 |                                 }
1046 |                                 fprintf(rfp, " (maintain).\n");
1047 | 				one_printed++;
1048 | 			    }
1049 |                         }
1050 | 		}
1051 | 	    }
1052 | 	    if (!processing && !predict && pt == MASTER )
1053 | 		if (one_printed)
1054 |                     fprintf(rfp,"\n"); /* Extra blank for master */
1055 | 
1056 | 	}
1057 | 
1058 | 	for (p = 1; p <= NPOWER; p++) {
1059 | 		assumed[p]=0;
1060 | 		if  (processing || pt == p || pt == MASTER || PowerControlledBy(p) == pt) {
1061 | 		    p_index = FindPower(p);
1062 | 		    if (p_index >= dipent.n) continue; /* Not a valid power */
1063 |                     counting_centres = dipent.players[p_index].centers -
1064 |                                        dipent.players[p_index].centres_blockaded;
1065 |                     u_diff[p] = num_units[p] - counting_centres - ExtraCentres(p);
1066 | 
1067 | 		    if (u_diff[p] < 0) {
1068 | 			fprintf(rfp, "%s: ", powers[p]);
1069 | 			for (i = strlen(powers[p]); i < LPOWER; i++)
1070 | 				putc(' ', rfp);
1071 | 			for (i = 1; i <= npr; i++) {
1072 | 				if (pr[i].owner == p && !pr[i].unit &&
1073 | 				    (pr[i].type == dipent.pl[p] || (centre(i) &&
1074 | 				     (dipent.xflags & XF_BUILD_ANYCENTRES))))
1075 | 					break;
1076 | 			}
1077 | 			if (!(dipent.xflags & XF_ANYDISBAND)) {
1078 | 			    if (i > npr ) {
1079 | 				i = nu[p] - 1 + ExtraCentres(p);
1080 | 				if (processing)
1081 | 				    fprintf(rfp, "%d unusable build%s waived.\n", i, i == 1 ? "" : "s");
1082 | 				else
1083 | 				    fprintf(rfp, "%d unusable build%s pending.\n", i, i == 1 ? "" : "s");
1084 | 				nu[p] = 1;
1085 | 			    } else {
1086 | 				i = nu[p] - 1;
1087 | 	
1088 | 				fprintf(rfp, "%d build%s pending.\n", i, i == 1 ? "" : "s");
1089 | 			    }
1090 | 			}
1091 | 		    }
1092 | 		    if ((dipent.xflags & XF_ANYDISBAND) && u_diff[p] != 0 ) {
1093 | 		        if (!processing && !predict && !(pt == MASTER)) 
1094 | 		                err++;	
1095 | 		        if (u_diff[p] > 0) 
1096 | 		            fprintf(rfp,"%d too many units: need to remove some.\n", u_diff[p]);
1097 | 		        else
1098 | 			    fprintf(rfp,"%d too few units: need to build/maintain/waive.\n", -u_diff[p]);
1099 | 		    }
1100 | 		}	
1101 | 	}
1102 | 
1103 | 	if (dipent.xflags & XF_ALTBUILD) {
1104 | 	    if (err)
1105 | 		more_orders++; /* MUST be 100% ok for these variants */
1106 | 
1107 |         } else {
1108 |             if (!processing && (nu[pt] < -1 || nu[pt] > 1))
1109 |                 more_orders++;
1110 |         }
1111 | 
1112 | 	for (u = 1; u <= nunit; u++) {
1113 | 		if ((p = unit[u].owner) && 
1114 | 	            u_diff[p] > 0 && 
1115 | 		    pr[unit[u].loc].owner != p && 
1116 | 		    FindPower(p) < dipent.n) {
1117 | 			nu[p]++;
1118 | 			unit[u].owner = 0;
1119 | 			if (processing || pt == p || pt == MASTER || PowerControlledBy(p) == pt) {
1120 | 				fprintf(rfp, "%s: ", powers[p]);
1121 | 				for (i = strlen(powers[p]); i < LPOWER; i++)
1122 | 					putc(' ', rfp);
1123 | 				fprintf(rfp, "Defaults, removing the %s in %s%s.\n",
1124 | 					utype(unit[u].type),
1125 | 					water(unit[u].loc) ? "the " : "",
1126 | 					pr[unit[u].loc].name);
1127 | 				u_diff[p]--;
1128 | 			}
1129 | 		}
1130 | 	}
1131 | 
1132 |  /* Now see if there are centres that have become home centres */
1133 |       for (p1 = 1;  p1<= npr && (dipent.x2flags & X2F_HOMETRANSFER); p1++) {
1134 |             if (pr[p1].unit && pr[p1].unit_held &&
1135 |                 (PossibleHomeCentre(pletter[dipent.variant][pr[p1].home]) ||
1136 | 		 (!pr[p1].home && pr[p1].type == 'x')) &&
1137 |                 unit[pr[p1].unit].owner != pr[p1].home) {
1138 |                 pr[p1].home = unit[pr[p1].unit].owner;
1139 |             }
1140 |         }
1141 | 
1142 |        for (pp = 1; pp <= NPOWER; pp++) { /* This loop is just to order by power */
1143 |             p_index = FindPower(pp);
1144 |             one_printed = 0;
1145 |             if (p_index >= dipent.n) continue; /* Not a valid power */
1146 |           one_printed = 0;
1147 |           for (p1 = 1;  p1<= npr; p1++) {
1148 |             p = pr[p1].home;
1149 |             if ( pr[p1].type != pletter[dipent.variant][pr[p1].home] &&
1150 |                 PossibleHomeCentre(pletter[dipent.variant][pr[p1].home])) {
1151 |                  assumed[p]++;
1152 |                  if (pp == p && (processing || pt == p || pt == MASTER || PowerControlledBy(p) == pt)) {
1153 |                     one_printed++;
1154 |                     fprintf(rfp, "\n%s: ", powers[p]);
1155 |                                 for (i = strlen(powers[p]); i < LPOWER; i++)
1156 |                                         putc(' ', rfp);
1157 |                                 fprintf(rfp, "Assumes %s as a home centre.",
1158 |                                         pr[p1].name);
1159 |                 }
1160 |             }
1161 |           }
1162 |         }
1163 |         if (one_printed) fprintf(rfp, "\n");
1164 | 
1165 |         /* Now show pending moves for home centre declarations */
1166 |         one_printed = 0;
1167 |         for (p = 1; p <= NPOWER && (dipent.x2flags & X2F_MORE_HOMES); p++) {
1168 |             if (p != dipent.has_natives && (processing || pt == p || pt == MASTER || PowerControlledBy(p) == pt )) {
1169 |                 p_index = FindPower(p);
1170 |                 if (dipent.players[p_index].centers <=0 &&
1171 |                     dipent.players[p_index].units <= 0)
1172 |                         continue;  /* Not an alive player, so ignore */
1173 |                 num_hc = CountHomeCentres(p);
1174 |                 if ( (dipent.x2flags & X2F_MORE_HOMES) &&
1175 |                      num_hc + assumed[p] < dipent.num_homes && CountCentres(p) > 0) {
1176 |                         fprintf(rfp, "\n%s: ", powers[p]);
1177 |                         one_printed++;
1178 |                         for (i = strlen(powers[p]); i < LPOWER; i++)
1179 |                                  putc(' ', rfp);
1180 |                         fprintf(rfp, "%d more Home Centre assignment%s pending.",
1181 |                                 dipent.num_homes - num_hc - assumed[p],
1182 |                                 dipent.num_homes - num_hc - assumed[p] > 1 ? "s" : "" );
1183 |                 }
1184 |             }
1185 |         }
1186 | 	
1187 |         if (one_printed) fprintf(rfp, "\n");
1188 | 
1189 |  /* Adjust the unit_held values */
1190 |       for (p1 = 1;  p1<= npr && processing; p1++) {
1191 |             if (pr[p1].unit )
1192 |                 pr[p1].unit_held = 1;
1193 |       }
1194 | 
1195 |       if (processing && dipent.flags & F_INTIMATE)
1196 |           PrintTreasury(pt, NULL, processing, predict);
1197 | 
1198 | }	        
1199 | /****************************************************************************/