1 /* omega copyright (c) 1987,1988,1989 by Laurence Raphael Brothers */
2 
3 /* this file includes main() and some top-level functions */
4 /* omega.c */
5 
6 #if !defined(MSDOS_SUPPORTED_ANTIQUE)
7 #include <signal.h>
8 #include <fcntl.h>
9 #include <time.h>
10 #include <unistd.h>
11 #include <stdlib.h>
12 /* Note: in order to avoid a memory bug I've been told about, I'm
13    explicitly initializing every global to something. */
14 #endif
15 
16 #include "glob.h"
17 
18 /* most globals originate in omega.c */
19 
20 char *Omegalib;		/* contains the path to the library files */
21 
22 #ifdef DEBUG
23 FILE *DG_debug_log; /* debug log file pointer */
24 int DG_debug_flag = 0; /* debug flag -- set by -d commandline option */
25 #endif
26 
27 /* Objects and Monsters are allocated and initialized in init.c */
28 
29 /* one of each spell */
30 #ifndef MSDOS_SUPPORTED_ANTIQUE
31 struct spell Spells[NUMSPELLS+1];
32 #else
33 struct spell Spells[NUMSPELLS+1] = {0};
34 #endif
35 
36 /* locations of city sites [0] - found, [1] - x, [2] - y */
37 #ifndef MSDOS_SUPPORTED_ANTIQUE
38 int CitySiteList[NUMCITYSITES][3];
39 #else
40 int CitySiteList[NUMCITYSITES][3] = {0};
41 #endif
42 
43 /* Currently defined in caps since it is now a variable, was a constant */
44 int LENGTH=MAXLENGTH;
45 int WIDTH=MAXWIDTH;
46 
47 long GameStatus=0L;                   /* Game Status bit vector */
48 int ScreenLength = 0;                 /* How large is level window */
49 #ifndef MSDOS_SUPPORTED_ANTIQUE
50 struct player Player;                 /* the player */
51 #else
52 struct player Player = {0};           /* the player */
53 #endif
54 #ifndef MSDOS_SUPPORTED_ANTIQUE
55 struct terrain Country[MAXWIDTH][MAXLENGTH];/* The countryside */
56 #else
57 struct terrain Country[MAXWIDTH][MAXLENGTH] = {0};/* The countryside */
58 #endif
59 #ifdef SAVE_LEVELS
60 struct level TheLevel;
61 #endif
62 struct level *City=NULL;              /* The city of Rampart */
63 struct level *TempLevel=NULL;         /* Place holder */
64 struct level *Level=NULL;             /* Pointer to current Level */
65 struct level *Dungeon=NULL;           /* Pointer to current Dungeon */
66 int Villagenum = 0;                   /* Current Village number */
67 int ScreenOffset = 0;                 /* Offset of displayed screen to level */
68 int MaxDungeonLevels = 0;             /* Deepest level allowed in dungeon */
69 int Current_Dungeon= -1;              /* What is Dungeon now */
70 int Current_Environment= E_CITY;      /* Which environment are we in */
71 int Last_Environment= E_COUNTRYSIDE;  /* Which environment were we in */
72 #ifndef MSDOS_SUPPORTED_ANTIQUE
73 int Dirs[2][9];                       /* 9 xy directions */
74 #else
75 int Dirs[2][9]=                       /* 9 xy directions */
76   { { 1,1,-1,-1,1,-1,0,0,0} , { 1,-1,1,-1,0,0,1,-1,0 } };
77 #endif
78 char Cmd='s';                         /* last player command */
79 int Command_Duration = 0;             /* how long does current command take */
80 struct monster *Arena_Monster=NULL;   /* Opponent in arena */
81 int Arena_Opponent=0;                 /* case label of opponent in l_arena()*/
82 int Arena_Victory = 0;                /* did player win in arena? */
83 int Imprisonment=0;                   /* amount of time spent in jail */
84 int Precipitation=0;                  /* Hours of rain, snow, etc */
85 int Lunarity=0;                       /* Effect of the moon on character */
86 int Phase = 0;                        /* Phase of the moon */
87 int Date = 0;                         /* Starting date */
88 int Pawndate = 0;                     /* Pawn Shop item generation date */
89 pob Pawnitems[PAWNITEMS] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
90 /* items in pawn shop */
91 int SymbolUseHour= -1;                /* holy symbol use marker */
92 int ViewHour= -1;                     /* crystal ball use marker */
93 int ZapHour= -1;                      /* staff of enchantment use marker */
94 int HelmHour= -1;                     /* helm of teleportation use marker*/
95 int Constriction=0;                   /* Dragonlord Attack State */
96 int Blessing=FALSE;                   /* Altar Blessing State */
97 int LastDay= -1;                      /* DPW date of dole */
98 int RitualHour= -1;                   /* last use of ritual magic */
99 int RitualRoom= -1;                   /* last room of ritual magic */
100 int Lawstone=0;                       /* magic stone counter */
101 int Chaostone=0;                      /* magic stone counter */
102 int Mindstone=0;                      /* magic stone counter */
103 int Searchnum = 1;                    /* number of times to search on 's' */
104 int Behavior;			      /* Player NPC behavior */
105 int Verbosity = VERBOSE;              /* verbosity level */
106 long Time = 0;                        /* turn number */
107 int Tick = 0;                         /* 10 a turn; action coordinator */
108 char Stringbuffer[STRING_BUFFER_SIZE][80];	/* last strings printed */
109 long Gymcredit = 0;                   /* credit at rampart gym */
110 int Spellsleft = 0;                   /* research allowance at college */
111 int StarGemUse = 0;                   /* last date of star gem use */
112 int HiMagicUse = 0;                   /* last date of high magic use */
113 int HiMagic = 0;                      /* current level for l_throne */
114 long Balance = 0;                     /* bank account */
115 long FixedPoints = 0;                 /* points are frozen after adepthood*/
116 int LastTownLocX=0;            /* previous position in village or city */
117 int LastTownLocY=0;            /* previous position in village or city */
118 int LastCountryLocX=0;            /* previous position in countryside */
119 int LastCountryLocY=0;            /* previous position in countryside */
120 #ifndef MSDOS_SUPPORTED_ANTIQUE
121 char Password[64];                    /* autoteller password */
122 #else
123 char Password[64] = {0};              /* autoteller password */
124 #endif
125 #ifndef MSDOS_SUPPORTED_ANTIQUE
126 char Str1[STRING_LEN],Str2[STRING_LEN],Str3[STRING_LEN],Str4[STRING_LEN];
127 #else
128 char Str1[STRING_LEN] = {0},Str2[STRING_LEN] = {0},Str3[STRING_LEN] = {0},Str4[STRING_LEN] = {0};
129 #endif
130    /* Some string space, random uses */
131 
132 pol Condoitems=NULL;                        /* Items in condo */
133 
134 /* high score names, levels, behavior */
135 #ifndef MSDOS_SUPPORTED_ANTIQUE
136 int Shadowlordbehavior,Archmagebehavior,Primebehavior,Commandantbehavior;
137 int Championbehavior,Priestbehavior[7],Hibehavior,Dukebehavior;
138 int Chaoslordbehavior,Lawlordbehavior,Justiciarbehavior;
139 char Shadowlord[80],Archmage[80],Prime[80],Commandant[80],Duke[80];
140 char Champion[80],Priest[7][80],Hiscorer[80],Hidescrip[80];
141 char Chaoslord[80],Lawlord[80],Justiciar[80];
142 int Shadowlordlevel,Archmagelevel,Primelevel,Commandantlevel,Dukelevel;
143 #else
144 int Shadowlordbehavior = 0,Archmagebehavior = 0,Primebehavior = 0,Commandantbehavior = 0;
145 int Championbehavior = 0,Priestbehavior[7] = {0},Hibehavior = 0,Dukebehavior = 0;
146 int Chaoslordbehavior = 0,Lawlordbehavior = 0,Justiciarbehavior = 0;
147 char Shadowlord[80] = {0},Archmage[80] = {0},Prime[80] = {0},Commandant[80] = {0},Duke[80] = {0};
148 char Champion[80] = {0},Priest[7][80] = {0},Hiscorer[80] = {0},Hidescrip[80] = {0};
149 char Chaoslord[80] = {0},Lawlord[80] = {0},Justiciar[80] = {0};
150 int Shadowlordlevel = 0,Archmagelevel = 0,Primelevel = 0,Commandantlevel = 0,Dukelevel = 0;
151 #endif
152 #ifndef MSDOS_SUPPORTED_ANTIQUE
153 int Championlevel,Priestlevel[7],Hilevel,Justiciarlevel;
154 #else
155 int Championlevel = 0,Priestlevel[7] = {0},Hilevel = 0,Justiciarlevel = 0;
156 #endif
157 long Hiscore = 0L;
158 int Chaoslordlevel = 0,Lawlordlevel = 0,Chaos = 0,Law = 0;
159 
160 /* New globals which used to be statics */
161 int twiddle = FALSE;
162 int saved=FALSE;
163 int onewithchaos=FALSE;
164 int club_hinthour = 0;
165 int winnings = 0;
166 int tavern_hinthour;
167 int scroll_ids[30];
168 int potion_ids[30];
169 int stick_ids[30];
170 int ring_ids[30];
171 int cloak_ids[30];
172 int boot_ids[30];
173 
174 int deepest[E_MAX + 1];
175 int level_seed[E_MAX + 1];	/* random number seed that generated level */
176 
177 /* This may be implementation dependent */
178 /* SRANDFUNCTION is defined in odefs.h */
179 /* environment is the environment about to be generated, or -1 for the first */
180 /* time, or -2 if we want to restore the random number point */
initrand(int environment,int level)181 void initrand(int environment, int level)
182 {
183   static int store;
184   int seed;
185 
186   if (environment >= 0)
187     store = RANDFUNCTION();
188   /* Pseudo Random Seed */
189   if (environment == E_RANDOM)
190     seed = (int) time((long *)NULL);
191   else if (environment == E_RESTORE)
192     seed = store;
193   else
194     seed = level_seed[environment] + 1000*level;
195   SRANDFUNCTION(seed);
196 }
197 
198 
game_restore(argc,argv)199 int game_restore(argc,argv)
200 int argc;
201 char *argv[];
202 {
203   char savestr[80];
204   int ok;
205 #ifdef DEBUG
206   if (argc == 3) {
207     if( (argv[2][0] == '-') && (argv[2][1] == 'g') )
208     {
209        DG_debug_flag++;
210        argc--;
211     }
212   }
213 #endif
214   if (argc==2) {
215     strcpy(savestr,argv[1]);
216     ok = restore_game(savestr);
217     if (! ok) {
218       endgraf();
219       printf("Try again with the right save file, luser!\n");
220       exit(0);
221     }
222     change_to_user_perms();
223     unlink(savestr);
224     change_to_game_perms();
225     return(TRUE);
226   }
227   else return(FALSE);
228 }
229 
230 
main(argc,argv)231 int main(argc,argv)
232 int argc;
233 char *argv[];
234 {
235   int continuing;
236   int count;
237 
238 
239   /* always catch ^c and hang-up signals */
240 
241 #ifdef SIGINT
242   signal(SIGINT,(void *)quit);
243 #endif
244 #ifdef SIGHUP
245   signal(SIGHUP,(void *)signalsave);
246 #endif
247 
248 #ifndef MSDOS
249   if (CATCH_SIGNALS) {
250     signal(SIGQUIT,(void *)signalexit);
251     signal(SIGILL,(void *)signalexit);
252 #ifdef DEBUG
253     if( DG_debug_flag ) {
254 #endif
255     signal(SIGTRAP,(void *)signalexit);
256     signal(SIGFPE,(void *)signalexit);
257     signal(SIGSEGV,(void *)signalexit);
258 #ifdef DEBUG
259     }
260 #endif
261 #ifdef SIGIOT
262     signal(SIGIOT,(void *)signalexit);
263 #endif
264 #ifdef SIGABRT
265     signal(SIGABRT,(void *)signalexit);
266 #endif
267 #ifdef SIGEMT
268     signal(SIGEMT,(void *)signalexit);
269 #endif
270 #ifdef SIGBUS
271     signal(SIGBUS,(void *)signalexit);
272 #endif
273 #ifdef SIGSYS
274     signal(SIGSYS,(void *)signalexit);
275 #endif
276     }
277 #endif
278 
279 #ifndef FIXED_OMEGALIB
280   if (!(Omegalib = getenv("OMEGALIB")))
281 #endif
282     Omegalib = OMEGALIB;
283 
284   /* if filecheck is 0, some necessary data files are missing */
285   if (filecheck() == 0) exit(0);
286 
287   /* all kinds of initialization */
288   init_perms();
289   initgraf();
290 #ifndef MSDOS_SUPPORTED_ANTIQUE
291   initdirs();
292 #endif
293   initrand(E_RANDOM, 0);
294   initspells();
295 
296 #ifdef DEBUG
297   /* initialize debug log file */
298   DG_debug_log = fopen( "/tmp/omega_dbg_log", "a" );
299   assert( DG_debug_log ); /* WDT :) */
300   setvbuf( DG_debug_log, NULL, _IOLBF, 0);
301   fprintf(DG_debug_log, "##############  new game started ##############\n");
302 #endif
303 
304   for (count = 0; count < STRING_BUFFER_SIZE; count++)
305     strcpy(Stringbuffer[count],"<nothing>");
306 
307 #ifdef SAVE_LEVELS
308   msdos_init();
309 #endif
310 
311   omega_title();
312   showscores();
313 
314   /* game restore attempts to restore game if there is an argument */
315   continuing = game_restore(argc,argv);
316 
317   /* monsters initialized in game_restore if game is being restored */
318   /* items initialized in game_restore if game is being restored */
319   if (! continuing) {
320     inititem(TRUE);
321     Date = random_range(360);
322     Phase = random_range(24);
323     strcpy(Password,"");
324     initplayer();
325     init_world();
326     mprint("'?' for help or commandlist, 'Q' to quit.");
327   }
328   else mprint("Your adventure continues....");
329 
330   timeprint();
331   calc_melee();
332   if (Current_Environment != E_COUNTRYSIDE)
333     showroom(Level->site[Player.x][Player.y].roomnumber);
334   else
335     terrain_check(FALSE);
336 
337   if (optionp(SHOW_COLOUR))
338     colour_on();
339   else
340     colour_off();
341 
342   screencheck(Player.y);
343 
344  /* game cycle */
345   if (!continuing)
346     time_clock(TRUE);
347   while (TRUE) {
348     if (Current_Environment == E_COUNTRYSIDE)
349       p_country_process();
350     else time_clock(FALSE);
351   }
352 }
353 
354 #ifndef MSDOS
signalexit()355 void signalexit()
356 {
357   int reply;
358   clearmsg();
359   mprint("Yikes!");
360   morewait();
361   mprint("Sorry, caught a core-dump signal.");
362   mprint("Want to try and save the game?");
363   reply = ynq();
364   if (reply=='y')
365     save(FALSE, TRUE); /* don't compress, force save */
366   else if (reply == EOF)
367     signalsave();
368   mprint("Bye!");
369   endgraf();
370   exit(0);
371 }
372 #endif
373 
374 
375 
376 
377 /* Start up game with new dungeons; start with player in city */
init_world()378 void init_world()
379 {
380   int env, i;
381 
382   City = Level = TempLevel = Dungeon = NULL;
383   for (env = 0; env <= E_MAX; env++)
384     level_seed[env] = RANDFUNCTION();
385   load_country();
386   for(i=0;i<NUMCITYSITES;i++)
387     CitySiteList[i][0] = FALSE;
388   load_city(TRUE);
389   WIDTH = 64;
390   LENGTH = 64;
391   Player.x = 62;
392   Player.y = 21;
393   Level = City;
394   Current_Environment = E_CITY;
395   print1("You pass through the massive gates of Rampart, the city.");
396 }
397 
398 /* set variable item names */
inititem(reset)399 void inititem(reset)
400 int reset;
401 {
402   int i;
403 
404   if (reset) {
405     shuffle(scroll_ids, 30);
406     shuffle(potion_ids, 20);
407     shuffle(stick_ids, 20);
408     shuffle(boot_ids, 20);
409     shuffle(cloak_ids, 20);
410     shuffle(ring_ids, 20);
411   }
412   for(i=0;i<NUMSCROLLS;i++)
413     Objects[SCROLLID+i].objstr = scrollname(i);
414   for(i=0;i<NUMPOTIONS;i++)
415     Objects[POTIONID+i].objstr = potionname(i);
416   Objects[ARTIFACTID + 10].objstr = potionname(18);
417   Objects[ARTIFACTID + 13].objstr = potionname(19);
418   for(i=0;i<NUMSTICKS;i++)
419     Objects[STICKID+i].objstr = stickname(i);
420   for(i=0;i<NUMBOOTS;i++)
421     Objects[BOOTID+i].objstr = bootname(i);
422   for(i=0;i<NUMCLOAKS;i++)
423     Objects[CLOAKID+i].objstr = cloakname(i);
424   for(i=0;i<NUMRINGS;i++)
425     Objects[RINGID+i].objstr = ringname(i);
426 }
427