/* * XEvil(TM) Copyright (C) 1994,2000 Steve Hardt and Michael Judge * http://www.xevil.com * satan@xevil.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program, the file "gpl.txt"; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA, or visit http://www.gnu.org. */ // "utils.h" Misc. utilities. to be included by ALL files. #ifndef UTILS_H #define UTILS_H #if X11 #ifndef NO_PRAGMAS #pragma interface #endif #endif #if WIN32 #define Boolean BOOL #define False FALSE #define True TRUE // Uncomment this to enable modeless dialogs for XEvil. //#define MODELESS_DIALOGS #endif // math.h #ifdef MATH_CLASS_HACK // Lame-ass AIX math.h has a function called class() #define class fakeclass #endif #if X11 #ifndef MATH_H_IS_CC extern "C" { #endif #include #ifndef MATH_H_IS_CC } #endif #endif #ifdef MATH_CLASS_HACK #undef class #endif #if WIN32 #include #endif // For some odd-ball linux machines, needed before #ifdef IO_COOKIE_HACK #define _IO_cookie_io_functions_t int #endif extern "C" { #include #include // For exit(). #include // For seed to srandom and clock(). #if X11 #include // for clock_t and gettimeofday(). #include #include #endif #if WIN32 #include #endif } #include #include // for u_char, u_int, etc. #include #include // Defines #ifndef MSEC_PER_CLOCK #define MSEC_PER_CLOCK (1.0e3 / CLOCKS_PER_SEC) #endif #ifndef max #define max(a,b) (ab ? b : a) #endif #if X11 typedef char Boolean; #endif typedef int ColorNum; #if X11 typedef struct timeval CMN_TIME; #endif #if WIN32 // milliseconds typedef int CMN_TIME; #endif // So we can do "new charP[n]". typedef char *charP; typedef const char* constCharP; // Network stuff. #if X11 #define CMN_SOCKET int #define CMN_PORT u_short #endif #if WIN32 #define CMN_SOCKET SOCKET #define CMN_PORT USHORT #endif #if X11 #include #endif typedef struct sockaddr CMN_SOCKADDR; typedef struct sockaddr_in CMN_SOCKADDR_IN; #ifdef RANDOM_NEEDS_PROTOTYPES extern "C" { long random(); void srandom(int); } #endif class InStream; typedef InStream *InStreamP; class OutStream; typedef OutStream *OutStreamP; typedef int GameStyleType; // Possible values of GameStyleType. enum {SCENARIOS,LEVELS_ONLY,KILL,DUEL,EXTENDED,TRAINING,LEVELS}; // Data Structures class Timer { public: Timer() {remaining = maxx = 0;} // Starts out ready. Timer(int t) {assert (t >= 0); maxx = t; remaining = 0;} Boolean ready() {return remaining == 0;} int get_remaining() {return remaining;} void set() {remaining = maxx;} void set(int time) {remaining = time;} void set_max(int m) {maxx = m; remaining = 0;} void reset() {remaining = 0;} void clock() {if (remaining) remaining--;} private: int remaining; int maxx; }; class Utils { public: static void seed_random(); /* REQUIRES: Must be called at startup. */ /* EFFECTS: Seed the random number generator based on the current time. */ static Boolean coin_flip(); /* EFFECTS: Randomly returns True or False; */ static int choose(int x); /* EFFECTS: Randomly return a number from 0 to x-1. */ static int weighted_choose(int n,int* weights); /* REQUIRES: weights is an array of length n. Each weight is >= 0. */ /* EFFECTS: Randomly choose a number from 0 to n-1. Probabitly of returning m is weights[m]/sum(weights). */ static void insertion_sort(int arry[],int numElements); static void random_list(int arry[],int numElements); /* EFFECTS: Fills arry the first numElements of arry with the numbers in {0..(numElements-1)} in a random order. */ static int minimum(int v1,int v2) {return v1 <= v2 ? v1 : v2;} static int maximum(int v1,int v2) {return v1 >= v2 ? v1 : v2;} static int minimum(int arry[],int size); /* EFFECTS: Return the minimum value in the array arry of size size. */ static int minimum(int arry[],Boolean oks[],int size); /* EFFECTS: Return the minimum value in arry which is ok or -1 if none. */ static Boolean inList(int key,const int list[],int size); /* EFFECTS: Returns whether key is in list list of size size. */ static void freeif(char *&str); /* MODIFIES: str */ /* EFFECTS: Free memory of str if non-NULL. Set str to NULL. */ static char *strdup(const char *str); /* EFFECTS: Copy str, allocating new memory. If str is NULL, return NULL. */ static int strlen(const char* cs) {assert(cs); return ::strlen(cs);} /* REQUIRES: cs is non-NULL */ static int strcmp(const char* str1,const char* str2) {return ::strcmp(str1,str2);} /* EFFECTS: Wrapper for C library strcmp(). Return 0 if strings are the same. */ static char* strchr(const char* cs,int c) {return ::strchr(cs,c);} static char* strrchr(const char* cs,int c) {return ::strrchr(cs,c);} static char* strstr(const char* cs,const char* ct) {return ::strstr(cs,ct);} static void strcpy(char* s,const char* ct) {::strcpy(s,ct);} static void strncpy(char* s,const char* ct,int n) {::strncpy(s,ct,(size_t)n);} static void strcat(char* s,const char* ct) {::strcat(s,ct);} static int atoi(const char*); static const char* getenv(const char*); static int mod(int n,int m) {return (n >= 0) ? (n % m) : (-(-n % m) + m) % m;} /* EFFECTS: Return (n % m), allowing n to be negative. */ static int div(int n,int m) {if (n >= 0) return (n / m); else if (-n % m == 0) return (n / m); else return (n / m) - 1;} /* EFFECTS: Return (n / m), adjust for negative n. */ static int ceil_div(int n,int m); /* EFFECTS: Integer division, rounding up. */ static Boolean string_equals_ignore_case(char *str1,char *str2); /* EFFECTS: Does str1 equal str2 ignoring case. */ static void string_read(InStreamP,char *buffer,int bufLen); /* EFFECTS: Read character string from InStream, put results in buffer. buffer will be null-terminated, even if the string read in is truncated. String will be completely read in from the InStream no matter what. */ static char* string_read(InStreamP in); /* EFFECTS: Read char string from in, return newly allocated string with entire message. Use delete to free string when done. Return empty string if error, never returns NULL. */ static int get_string_write_length(const char *msg); /* EFFECTS: The amount of bytes necessary to write msg to an output stream. */ static void string_write(OutStreamP,const char *msg); /* EFFECTS: Write msg to the output stream. */ static const char* arg_value_check(int& n,int argc,char** argv, const char* name); /* MODIFIES: n */ /* EFFECTS: Helper for parsing command line arguments that are of the form "-name value". Check element n of argv against the supplied name. If match found, return value, else NULL. If a match is found, n will be incremented to skip over the value in the command line list. */ static Boolean arg_name_check(int n,int argc,char** argv, const char* name); /* EFFECTS: Helper for parsing Boolean command line switches, of the form "-name". Check element n of argv against the supplied name. */ // Make X11 versions of these when we need them. #if WIN32 static Boolean is_dir(const char* fName); /* EFFECTS: Return True if fName exists on the filesystem and is a directory. Will work whether fName ends in '\' or not. */ static Boolean mkdir(const char* fName); /* EFFECTS: Create a new directory. Return whether successful. Will only create the last component of fName as a new directory. */ /* NOTE: We could make a version that will make all the new directories necessary for fName. */ #endif static const char* game_style_to_string(GameStyleType); /* EFFECTS: Convert GameStyleType to string, return "Unknown" if unknown or invalid GameStyleType. */ /* NOTE: Is here because the GameStyleType enumeration is here. */ static char* get_OS_info(); /* EFFECTS: Return a platform-dependent string describing the current operating system. Caller must free returned value with delete. */ private: static void string_read_body(InStreamP,u_short len,char *buffer,int bufLen); }; /* A generic untyped growable list. */ typedef void *voidP; class PtrList { public: PtrList(); /* EFFECTS: Create PtrList of zero initial allocation. */ /* NOTE: Guaranteed not to allocate/free any memory if no elements are ever added. */ PtrList(int); /* EFFECTS: Create PtrList of given initial allocation. */ /* NOTE: Guaranteed not to allocate/free any memory if this constructor is called with zero, and no elements are ever added. */ PtrList(void *); PtrList(void *,void *); PtrList(void *,void *,void *); PtrList(void *,void *,void *,void *); PtrList(void *,void *,void *,void *,void *); /* EFFECTS: Create a PtrList with length and allocation equal to the number of arguments. Initialize with the given elements. */ ~PtrList(); /* NOTE: Does not delete the elements pointed to by the list. */ PtrList(const PtrList &) {assert(0);} void operator = (const PtrList &) {assert(0);} //////// PTRLIST IO NOT TESTED ///////// PtrList(InStreamP); /* EFFECTS: Create a list from a stream. */ static int get_write_length(int len); /* EFFECTS: write_length of any list of the given length. */ int get_write_length() const {return get_write_length(len);} /* EFFECTS: write_length of this list */ void write(OutStreamP) const; /* EFFECTS: Write to stream. */ void add(void *); /* EFFECTS: Append new value to the end of list. */ void *get(int) const; /* EFFECTS: I'll give you one guess. */ Boolean contains(void *el) const; /* EFFECTS: Is el in the list, using == for comparison. */ int index(void *el) const; /* EFFECTS: Return the index of the first occurance of el in the list or -1 if not found. Use == for comparison. */ /* NOTE: Simple linear search. */ void add_unique(void *el) {if (!contains(el)) add(el);} /* EFFECTS: Add el to the list if it is not there already. Use == for comparison. */ void set(int i,void *val); /* EFFECTS: Set indexed element to new value. */ /* REQUIRES: i < length() */ int length() const {return len;} /* EFFECTS: Number of elements added to list. */ void del(int i); /* EFFECTS: Delete element i, copy the last element of the list to element i. */ /* NOTE: Be careful when iterating and deleting elements as del() moves elements around. */ void clear() {len = 0;} /* EFFECTS: Empty the list. */ void append(const PtrList &other); /* EFFECTS: Add all elements of other to the list. Does not check for duplicates. */ void fill(int n,void *val = NULL); /* EFFECTS: Append val to the list n times. Useful for initializing a List. */ void set_and_fill(int i,void *val,void *fill = NULL); /* EFFECTS: Set element i to val. Grow the list as necessary, filling in the newly created empty element with "fill". */ private: void commonConstructor(int); void increaseSize(); int len; int allc; void **data; }; // Iterator over an IDictionary. class IDictIterator { public: virtual ~IDictIterator(); virtual void* next(void*& key) = 0; /* MODIFIES: key */ /* EFFECTS: Return the next value in the iteration or NULL if done. Sets key to be the key corresponding to value. */ }; // A key-value lookup system. class IDictionary { public: virtual ~IDictionary(); virtual void* get(void* key) = 0; /* EFFECTS: Return the value assoicated with key, or NULL if none. */ virtual void *getAtIndex(int index) = 0; /* REQUIRES: 0 <= index < size() */ /* EFFECTS: Return the value stored at the given index. */ virtual int length() = 0; /* EFFECTS: Return the number of associations in the dictionary. */ virtual IDictIterator* iterate() = 0; /* REQUIRES: Don't add new assocations or delete the IDictionary before you are done with the IDictIterator. You may change the value of an existing association, however. */ /* EFFECTS: Return an iterator for the values of the Dictionary. */ virtual void* put(void* key,void* value) = 0; /* REQUIRES: Neither key nor value are NULL */ /* EFFECTS: Put (key,value) association into the dictionary. Return the previous value stored at key if any, else return NULL. */ }; IDictionary* HashTable_factory(int startAlloc = -1, int (*hashFntn)(void *key,int length) = 0); /* EFFECTS: Create a HashTable implementation of IDictionary. */ // Print out debug info. class DebugInfo { public: static void initialize(); /* EFFECTS: Call once at startup. */ static Boolean on() {return _on;} /* EFFECTS: Is printing debug info turned on. */ static void turn_on() {_on = True;} /* EFFECTS: Enable printing out debug info. */ static void print(const char *); /* EFFECTS: Print the debug message to the appropriate place if debugging is on. */ private: static Boolean _on; }; #endif //UTILS_H