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