Use toupper(c) rather than homegrown code.
[vms-empire.git] / util.c
1 /*
2  *    Copyright (C) 1987, 1988 Chuck Simmons
3  * 
4  * See the file COPYING, distributed with empire, for restriction
5  * and warranty information.
6  */
7
8 /*
9 util.c -- various utility routines.
10 */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <curses.h>     /* Ugh...shouldn't be needed here */
15 #include <ctype.h>
16 #include <signal.h>
17 #include "empire.h"
18 #include "extern.h"
19
20 #include <sys/types.h>
21 #include <unistd.h>
22 #include <ctype.h>
23
24 /*
25 Report a bug.
26 */
27
28 void
29 assert(char *expression, char *file, int line)
30 {
31         char buf[STRSIZE];
32
33         (void) move (lines, 0);
34         close_disp ();
35
36         (void) sprintf (buf, "assert failed: file %s line %d: %s",
37                         file, line, expression);
38
39         kill(getpid(), SIGSEGV);        /* core dump */
40 }
41
42 /*
43 End the game by cleaning up the display.
44 */
45
46 void
47 empend(void)
48 {
49         close_disp ();
50         exit (0);
51 }
52
53
54 /*
55 Here is a little routine to perform consistency checking on the
56 database.  I'm finding that my database is becoming inconsistent,
57 and I've no idea why.  Possibly this will help.
58
59 We perform the following functions:
60
61 1)  Make sure no list contains loops.
62
63 2)  Make sure every object is in either the free list with 0 hits,
64 or it is in the correct object list and a location list with non-zero hits,
65 and an appropriate owner.
66
67 3)  Make sure every city is on the map.
68
69 4)  Make sure every object is in the correct location and that
70 objects on the map have non-zero hits.
71
72 5)  Make sure every object in a cargo list has a ship pointer.
73
74 6)  Make sure every object with a ship pointer is in that ship's
75 cargo list.
76 */
77
78 static int in_free[LIST_SIZE]; /* TRUE if object in free list */
79 static int in_obj[LIST_SIZE]; /* TRUE if object in obj list */
80 static int in_loc[LIST_SIZE]; /* TRUE if object in a loc list */
81 static int in_cargo[LIST_SIZE]; /* TRUE if object in a cargo list */
82
83 void
84 check(void) {
85         void check_cargo(), check_obj(), check_obj_cargo();
86         
87         long i, j;
88         piece_info_t *p;
89         
90         /* nothing in any list yet */
91         for (i = 0; i < LIST_SIZE; i++) {
92                 in_free[i] = 0;
93                 in_obj[i] = 0;
94                 in_loc[i] = 0;
95                 in_cargo[i] = 0;
96         }
97                 
98         /* Mark all objects in free list.  Make sure objects in free list
99         have zero hits. */
100         
101         for (p = free_list; p != NULL; p = p->piece_link.next) {
102                 i = p - object;
103                 ASSERT (!in_free[i]);
104                 in_free[i] = 1;
105                 ASSERT (p->hits == 0);
106                 if (p->piece_link.prev)
107                         ASSERT (p->piece_link.prev->piece_link.next == p);
108         }
109         
110         /* Mark all objects in the map.
111         Check that cities are in corect location.
112         Check that objects are in correct location,
113         have a good owner, and good hits. */
114         
115         for (i = 0; i < MAP_SIZE; i++) {
116                 if (map[i].cityp) ASSERT (map[i].cityp->loc == i);
117                 
118                 for (p = map[i].objp; p != NULL; p = p->loc_link.next) {
119                         ASSERT (p->loc == i);
120                         ASSERT (p->hits > 0);
121                         ASSERT (p->owner == USER || p->owner == COMP);
122                                 
123                         j = p - object;
124                         ASSERT (!in_loc[j]);
125                         in_loc[j] = 1;
126                         
127                         if (p->loc_link.prev)
128                                 ASSERT (p->loc_link.prev->loc_link.next == p);
129                 }
130         }
131
132         /* make sure all cities are on map */
133
134         for (i = 0; i < NUM_CITY; i++)
135                 ASSERT (map[city[i].loc].cityp == &(city[i]));
136
137         /* Scan object lists. */
138         
139         check_obj (comp_obj, COMP);
140         check_obj (user_obj, USER);
141         
142         /* Scan cargo lists. */
143         
144         check_cargo (user_obj[TRANSPORT], ARMY);
145         check_cargo (comp_obj[TRANSPORT], ARMY);
146         check_cargo (user_obj[CARRIER], FIGHTER);
147         check_cargo (comp_obj[CARRIER], FIGHTER);
148         
149         /* Make sure all objects with ship pointers are in cargo. */
150
151         check_obj_cargo (comp_obj);
152         check_obj_cargo (user_obj);
153         
154         /* Make sure every object is either free or in loc and obj list. */
155
156         for (i = 0; i < LIST_SIZE; i++)
157                 ASSERT (in_free[i] != (in_loc[i] && in_obj[i]));
158 }
159
160 /*
161 Check object lists.  We look for:
162
163 1)  Loops and bad prev pointers.
164
165 2)  Dead objects.
166
167 3)  Invalid types.
168
169 4)  Invalid owners.
170 */
171
172 void
173 check_obj(piece_info_t **list, int owner)
174 {
175         long i, j;
176         piece_info_t *p;
177         
178         for (i = 0; i < NUM_OBJECTS; i++)
179         for (p = list[i]; p != NULL; p = p->piece_link.next) {
180                 ASSERT (p->owner == owner);
181                 ASSERT (p->type == i);
182                 ASSERT (p->hits > 0);
183                 
184                 j = p - object;
185                 ASSERT (!in_obj[j]);
186                 in_obj[j] = 1;
187         
188                 if (p->piece_link.prev)
189                         ASSERT (p->piece_link.prev->piece_link.next == p);
190         }
191 }
192
193 /*
194 Check cargo lists.  We assume object lists are valid.
195 as we will place bits in the 'in_cargo' array that are used by
196 'check_obj'.
197
198 Check for:
199
200 1)  Number of items in list is same as cargo count.
201
202 2)  Type of cargo is correct.
203
204 3)  Location of cargo matches location of ship.
205
206 4)  Ship pointer of cargo points to correct ship.
207
208 5)  There are no loops in cargo list and prev ptrs are correct.
209
210 6)  All cargo is alive.
211 */
212
213 void
214 check_cargo(piece_info_t *list, int cargo_type)
215 {
216         piece_info_t *p, *q;
217         long j, count;
218         
219         for (p = list; p != NULL; p = p->piece_link.next) {
220                 count = 0;
221                 for (q = p->cargo; q != NULL; q = q->cargo_link.next) {
222                         count += 1; /* count items in list */
223                         ASSERT (q->type == cargo_type);
224                         ASSERT (q->owner == p->owner);
225                         ASSERT (q->hits > 0);
226                         ASSERT (q->ship == p);
227                         ASSERT (q->loc == p->loc);
228                         
229                         j = q - object;
230                         ASSERT (!in_cargo[j]);
231                         in_cargo[j] = 1;
232
233                         if (p->cargo_link.prev)
234                                 ASSERT (p->cargo_link.prev->cargo_link.next == p);
235                 }
236                 ASSERT (count == p->count);
237         }
238 }
239
240 /*
241 Scan through object lists making sure every object with a ship
242 pointer appears in a cargo list.  We assume object and cargo
243 lists are valid.
244 */
245
246 void
247 check_obj_cargo(piece_info_t **list)
248 {
249         piece_info_t *p;
250         long i;
251
252         for (i = 0; i < NUM_OBJECTS; i++)
253         for (p = list[i]; p != NULL; p = p->piece_link.next) {
254                 if (p->ship) ASSERT (in_cargo[p-object]);
255         }
256 }