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