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 | }