1    | /*
2    |  * $Log: common.c,v $
3    |  * Revision 1.9  2004/07/27 23:04:26  millis
4    |  * Fix bug 342, no bidding phase in Intimate if no mercenaries alive
5    |  *
6    |  * Revision 1.8  2004/05/22 08:53:14  millis
7    |  * Bug 297: Add Intimate Diplomacy
8    |  *
9    |  * Revision 1.6  2003/05/02 22:23:39  millis
10   |  * Added valid_artillery_move()
11   |  *
12   |  * Revision 1.5  2003/01/13 22:38:51  millis
13   |  * merged in from ustv
14   |  *
15   |  * Revision 1.4.2.1  2003/01/13 16:04:47  millis
16   |  * ustv latest versions
17   |  *
18   |  * Revision 1.4  2002/04/15 12:55:41  miller
19   |  * Multiple changes for blind & Colonial & setup from USTV
20   |  *
21   |  * Revision 1.2.2.1  2001/10/19 23:25:18  dema
22   |  * Initialse need-order array
23   |  *
24   |  * Revision 1.2  2000/11/14 14:27:37  miller
25   |  * Added handling for Wing units
26   |  *
27   |  * Revision 1.1  1998/02/28 17:49:42  david
28   |  * Initial revision
29   |  *
30   |  * Revision 1.2  1997/01/26 16:55:29  rpaar
31   |  * Applied Kevin's year patch to remove some bugs in year handling.
32   |  *
33   |  * Revision 1.1  1996/10/20 12:29:45  rpaar
34   |  * Morrolan v9.0
35   |  */
36   | 
37   | #include <stdlib.h>
38   | 
39   | #include "dip.h"
40   | #include "porder.h"
41   | #include "functions.h"
42   | 
43   | /****************************************************************************/
44   | int valid_artillery_move(int u, int p, int *c, int *b)
45   | {
46   |     /* Return valid_move() if not an artillery unit */
47   |     /* Return 0 if artillery but can't get there */
48   |     /* return 1 if artillery and can get there */
49   | 
50   |     int ok = 0;
51   |     unsigned char *t, fc;
52   | 
53   |     ok = valid_move(u, p, c, b);
54   | 
55   |     if (unit[u].type != 'R')
56   | 	return ok;  /* Non artillery can only support in the same place */
57   | 
58   | /* Create a dummy unit */
59   | 	nunit++;
60   | 	unit[nunit].coast = MV;  /* Artillery moves as a land unit */
61   | 	
62   | 
63   |         for (t = pr[unit[u].loc].move; *t && !ok; t++) {
64   | 	    unit[nunit].loc = *t++;
65   | 	    fc = *t >> 4;
66   | 	    if (fc == MV ) {
67   | 	        ok = valid_move(nunit, p, c, b);
68   | 	    }
69   | 	}
70   | 
71   |     nunit--;  /* Delete dummy unit */
72   | 
73   |     return ok;  
74   | }
75   | 
76   | int valid_move(int u, int p, int *c, int *b)
77   | {
78   | 
79   | 	/*
80   | 	 *  Verify that the specified unit can move to the specified coast of
81   | 	 *  the specified province.
82   | 	 *
83   | 	 *  If the unit is on the XC coast, movement from any coast is okay.
84   | 	 *
85   | 	 *  If the destination coast is not specified, the destination coast is
86   | 	 *  set to the first one found that the unit can get to.
87   | 	 *
88   | 	 *  If the destination coast is CC (conditional) then the next entry in
89   | 	 *  the movement table contains the province that controls the straits.
90   | 	 *   
91   |          *  Additionally, if the unit is a wing, it can do anything!
92   | 	 */
93   | 
94   | 	unsigned char *t, fc;
95   | 	int ret;
96   | 
97   | 	*b = 0;
98   | 	if (u <= 0) return 0; /* Invalid unit index */
99   | 	if (!pr[unit[u].loc].move) 
100  | 	    return 0;  /* Province has no valid moves, so return 0 */
101  | 	for (t = pr[unit[u].loc].move; *t; t++) {
102  | 		if (*t++ == p)
103  | 		  if 
104  | 		     (((unit[u].type == 'W') || (unit[u].type == 'T') || 
105  | 			 ((unit[u].coast == (fc = (*t >> 4)) || (unit[u].coast == XC && fc))
106  | 		          && (*c == (*t & 0x0F) || !*c)))) {
107  | 			if (!*c)
108  | 				*c = (*t & 0x0F);
109  | 			if (*c == CC) {
110  | 				*b = *++t;
111  | 				*c = XC;
112  | 			}
113  | 			ret = 1;
114  | 			return ret;
115  | 		}
116  | 	}
117  | 	ret = 0;
118  | 	return ret;
119  | }
120  | 
121  | 
122  | int lookup(unsigned char *name)
123  | {
124  | 	unsigned char *s, *t;
125  | 
126  | 	/*
127  | 	 * Do a linear search on the heap for a specified province abbreviation
128  | 	 *
129  | 	 * The structure of the heap is name, 0, number, name, 0, number ...
130  | 	 */
131  | 
132  | 	t = (char *) heap;
133  | 	while (*t) {
134  | 		s = name;
135  | 		while (*t && toupper(*s) == toupper(*t)) {
136  | 			while (*++s == '.' || isspace(*s));
137  | 			while (*++t == '.' || isspace(*t));
138  | 		}
139  | 		if (!*s && !*t)
140  | 			return (int) *++t;
141  | 		while (*t++);
142  | 		t++;
143  | 	}
144  | 	return 0;
145  | }
146  | 
147  | 
148  | void init_retreats(void)
149  | {
150  | 	int i;
151  | 
152  | 	dipent.phase[5] = 'R';
153  | 
154  | 	for (i=0; i < NPOWER+1; i++)
155  | 	    need_order[i] = 0;  /* Initialise array */
156  | 	
157  | 	for (i = 1; i <= nunit; i++)
158  | 		if (unit[i].status == 'r')
159  | 			if (unit[i].owner < WILD_PLAYER)
160  | 				need_order[unit[i].owner]++;
161  | }
162  | 
163  | void init_movement(void)
164  | {
165  | 	int i;
166  | 
167  | 	dipent.phase[5] = 'M';
168  | 
169  | 	for (i=0; i < NPOWER+1; i++)
170  |             need_order[i] = 0;  /* Initialise array */                                  
171  | 
172  | 	for (i = 1; i <= nunit; i++)
173  | 		if (unit[i].owner < WILD_PLAYER)
174  | 			need_order[unit[i].owner]++;
175  | }
176  | 
177  | int HasOneMercenaryAlive(void)
178  | {
179  |     int i;
180  | 
181  |     for (i = 0; i < dipent.n; i++) {
182  |         if (dipent.players[i].controlling_power != 0 &&
183  | 	    dipent.players[i].centers > 0 )
184  | 	    return 1;
185  |     }
186  | 
187  |     return 0;  /* No-one found alive! */
188  | }
189  | void next_year(void)
190  | {
191  | 	int dipent_year = atoi(&dipent.phase[1]) + 1;
192  | 	while (dipent_year >= 10000)
193  | 		dipent_year -= 10000;
194  | 	sprintf(dipent.phase, "S%04dM", dipent_year);
195  | 	if (dipent.flags & F_INTIMATE && HasOneMercenaryAlive())
196  | 		dipent.phase[5] = 'A'; /* Intimate adjustment phase */
197  | 	else 
198  | 	    init_movement();
199  | }