]> thyrsus.com Git - vms-empire.git/commitdiff
Initial revision
authorEric S. Raymond <esr@thyrsus.com>
Thu, 29 Mar 1990 21:27:44 +0000 (21:27 +0000)
committerEric S. Raymond <esr@thyrsus.com>
Thu, 29 Mar 1990 21:27:44 +0000 (21:27 +0000)
util.c [new file with mode: 0644]

diff --git a/util.c b/util.c
new file mode 100644 (file)
index 0000000..60d32d7
--- /dev/null
+++ b/util.c
@@ -0,0 +1,411 @@
+/* $Id$  - (c) Copyright 1987, 1988 Chuck Simmons */
+
+/*
+ *    Copyright (C) 1987, 1988 Chuck Simmons
+ * 
+ * See the file COPYING, distributed with empire, for restriction
+ * and warranty information.
+ */
+
+/*
+util.c -- various utility routines.
+*/
+
+#include <curses.h>
+#include <ctype.h>
+#include "empire.h"
+#include "extern.h"
+
+
+/*
+Convert a string to uppercase.
+Shirley this is defined elsewhere?
+*/
+
+#include <ctype.h>
+
+void
+tupper (str)
+char   *str;
+{
+       while (*str) {
+               if (islower (*str)) *str = upper (*str);
+               str++;
+       }
+}
+
+/*
+Convert a character to uppercase (if it is lowercase)
+*/
+
+char
+upper (c)
+char c;
+{
+       if (islower (c))
+               return toupper (c);
+       else return c;
+}
+
+/*
+Clear the end of a specified line starting at the specified column.
+*/
+
+void
+clreol(linep, colp)
+int linep, colp;
+{
+       (void) move (linep, colp);
+       (void) clrtoeol();
+}
+
+/*
+Initialize the terminal.
+*/
+
+void
+ttinit()
+{
+       (void) initscr();
+       (void) noecho();
+       (void) crmode();
+       lines = LINES;
+       cols = COLS;
+       if (lines > MAP_HEIGHT + NUMTOPS + 1)
+               lines = MAP_HEIGHT + NUMTOPS + 1;
+       if (cols > MAP_WIDTH + NUMSIDES)
+               cols = MAP_WIDTH + NUMSIDES;
+}
+
+
+/*
+Clear the screen.  We must also kill information maintained about the
+display.
+*/
+
+void
+clear_screen () {
+       (void) clear ();
+       (void) refresh ();
+       kill_display ();
+}
+
+/*
+Redraw the screen.
+*/
+
+void
+redraw () {
+       (void) clearok (curscr, TRUE);
+       (void) refresh ();
+}
+
+/*
+Wait a little bit to give user a chance to see a message.  We refresh
+the screen and pause for a few milliseconds.
+*/
+
+void
+delay () {
+       (void) refresh ();
+       (void) napms (delay_time); /* pause a bit */
+}
+
+
+/*
+Clean up the display.  This routine gets called as we leave the game.
+*/
+
+void
+close_disp()
+{
+       (void) move (LINES - 1, 0);
+       (void) clrtoeol ();
+       (void) refresh ();
+       (void) endwin ();
+}
+
+/*
+Position the cursor and output a string.
+*/
+
+void
+/* VARARGS3 */
+pos_str (row, col, str, a, b, c, d, e, f, g, h)
+int row, col;
+char *str;
+int a, b, c, d, e, f, g, h;
+{
+       (void) move (row, col);
+       addprintf (str, a, b, c, d, e, f, g, h);
+}
+
+void
+/* VARARGS1 */
+addprintf (str, a, b, c, d, e, f, g, h)
+char *str;
+int a, b, c, d, e, f, g, h;
+{
+       char junkbuf[STRSIZE];
+       
+       (void) sprintf (junkbuf, str, a, b, c, d, e, f, g, h);
+       (void) addstr (junkbuf);
+}
+
+/*
+Report a bug.
+*/
+
+void
+assert (expression, file, line)
+char *expression;
+char *file;
+int line;
+{
+       char buf[STRSIZE];
+       int a;
+
+       (void) move (lines, 0);
+       close_disp ();
+
+       (void) sprintf (buf, "assert failed: file %s line %d: %s",
+                       file, line, expression);
+
+       a = 1; /* keep lint quiet */
+       a /= 0; /* force a core dump */
+       a = a; /* keep lint quiet */
+}
+
+/*
+End the game by cleaning up the display.
+*/
+
+void
+empend ()
+{
+       close_disp ();
+       exit (0);
+}
+
+/*
+ * 03a 01Apr88 aml .Hacked movement algorithms for computer.
+ * 02b 01Jun87 aml .First round of bug fixes.
+ * 02a 01Jan87 aml .Translated to C.
+ * 01b 27May85 cal .Fixed round number update bug. Made truename simple.
+ * 01a 01Sep83 cal .Taken from a Decus tape
+ */
+
+void
+ver ()
+{
+        (void) addstr ("EMPIRE, Version 5.00 site Amdahl 1-Apr-1988");
+}
+
+/*
+Here is a little routine to perform consistency checking on the
+database.  I'm finding that my database is becoming inconsistent,
+and I've no idea why.  Possibly this will help.
+
+We perform the following functions:
+
+1)  Make sure no list contains loops.
+
+2)  Make sure every object is in either the free list with 0 hits,
+or it is in the correct object list and a location list with non-zero hits,
+and an appropriate owner.
+
+3)  Make sure every city is on the map.
+
+4)  Make sure every object is in the correct location and that
+objects on the map have non-zero hits.
+
+5)  Make sure every object in a cargo list has a ship pointer.
+
+6)  Make sure every object with a ship pointer is in that ship's
+cargo list.
+*/
+
+static int in_free[LIST_SIZE]; /* TRUE if object in free list */
+static int in_obj[LIST_SIZE]; /* TRUE if object in obj list */
+static int in_loc[LIST_SIZE]; /* TRUE if object in a loc list */
+static int in_cargo[LIST_SIZE]; /* TRUE if object in a cargo list */
+
+void
+check () {
+       void check_cargo(), check_obj(), check_obj_cargo();
+       
+       long i, j;
+       piece_info_t *p;
+       
+       /* nothing in any list yet */
+       for (i = 0; i < LIST_SIZE; i++) {
+               in_free[i] = 0;
+               in_obj[i] = 0;
+               in_loc[i] = 0;
+               in_cargo[i] = 0;
+       }
+               
+       /* Mark all objects in free list.  Make sure objects in free list
+       have zero hits. */
+       
+       for (p = free_list; p != NULL; p = p->piece_link.next) {
+               i = p - object;
+               ASSERT (!in_free[i]);
+               in_free[i] = 1;
+               ASSERT (p->hits == 0);
+               if (p->piece_link.prev)
+                       ASSERT (p->piece_link.prev->piece_link.next == p);
+       }
+       
+       /* Mark all objects in the map.
+       Check that cities are in corect location.
+       Check that objects are in correct location,
+       have a good owner, and good hits. */
+       
+       for (i = 0; i < MAP_SIZE; i++) {
+               if (map[i].cityp) ASSERT (map[i].cityp->loc == i);
+               
+               for (p = map[i].objp; p != NULL; p = p->loc_link.next) {
+                       ASSERT (p->loc == i);
+                       ASSERT (p->hits > 0);
+                       ASSERT (p->owner == USER || p->owner == COMP);
+                               
+                       j = p - object;
+                       ASSERT (!in_loc[j]);
+                       in_loc[j] = 1;
+                       
+                       if (p->loc_link.prev)
+                               ASSERT (p->loc_link.prev->loc_link.next == p);
+               }
+       }
+
+       /* make sure all cities are on map */
+
+       for (i = 0; i < NUM_CITY; i++)
+               ASSERT (map[city[i].loc].cityp == &(city[i]));
+
+       /* Scan object lists. */
+       
+       check_obj (comp_obj, COMP);
+       check_obj (user_obj, USER);
+       
+       /* Scan cargo lists. */
+       
+       check_cargo (user_obj[TRANSPORT], ARMY);
+       check_cargo (comp_obj[TRANSPORT], ARMY);
+       check_cargo (user_obj[CARRIER], FIGHTER);
+       check_cargo (comp_obj[CARRIER], FIGHTER);
+       
+       /* Make sure all objects with ship pointers are in cargo. */
+
+       check_obj_cargo (comp_obj);
+       check_obj_cargo (user_obj);
+       
+       /* Make sure every object is either free or in loc and obj list. */
+
+       for (i = 0; i < LIST_SIZE; i++)
+               ASSERT (in_free[i] != (in_loc[i] && in_obj[i]));
+}
+
+/*
+Check object lists.  We look for:
+
+1)  Loops and bad prev pointers.
+
+2)  Dead objects.
+
+3)  Invalid types.
+
+4)  Invalid owners.
+*/
+
+void
+check_obj (list, owner)
+piece_info_t **list;
+int owner;
+{
+       long i, j;
+       piece_info_t *p;
+       
+       for (i = 0; i < NUM_OBJECTS; i++)
+       for (p = list[i]; p != NULL; p = p->piece_link.next) {
+               ASSERT (p->owner == owner);
+               ASSERT (p->type == i);
+               ASSERT (p->hits > 0);
+               
+               j = p - object;
+               ASSERT (!in_obj[j]);
+               in_obj[j] = 1;
+       
+               if (p->piece_link.prev)
+                       ASSERT (p->piece_link.prev->piece_link.next == p);
+       }
+}
+
+/*
+Check cargo lists.  We assume object lists are valid.
+as we will place bits in the 'in_cargo' array that are used by
+'check_obj'.
+
+Check for:
+
+1)  Number of items in list is same as cargo count.
+
+2)  Type of cargo is correct.
+
+3)  Location of cargo matches location of ship.
+
+4)  Ship pointer of cargo points to correct ship.
+
+5)  There are no loops in cargo list and prev ptrs are correct.
+
+6)  All cargo is alive.
+*/
+
+void
+check_cargo (list, cargo_type)
+piece_info_t *list;
+int cargo_type;
+{
+       piece_info_t *p, *q;
+       long j, count;
+       
+       for (p = list; p != NULL; p = p->piece_link.next) {
+               count = 0;
+               for (q = p->cargo; q != NULL; q = q->cargo_link.next) {
+                       count += 1; /* count items in list */
+                       ASSERT (q->type == cargo_type);
+                       ASSERT (q->owner == p->owner);
+                       ASSERT (q->hits > 0);
+                       ASSERT (q->ship == p);
+                       ASSERT (q->loc == p->loc);
+                       
+                       j = q - object;
+                       ASSERT (!in_cargo[j]);
+                       in_cargo[j] = 1;
+
+                       if (p->cargo_link.prev)
+                               ASSERT (p->cargo_link.prev->cargo_link.next == p);
+                }
+               ASSERT (count == p->count);
+        }
+}
+
+/*
+Scan through object lists making sure every object with a ship
+pointer appears in a cargo list.  We assume object and cargo
+lists are valid.
+*/
+
+void
+check_obj_cargo (list)
+piece_info_t **list;
+{
+       piece_info_t *p;
+       long i;
+
+       for (i = 0; i < NUM_OBJECTS; i++)
+       for (p = list[i]; p != NULL; p = p->piece_link.next) {
+               if (p->ship) ASSERT (in_cargo[p-object]);
+       }
+}