Commit | Line | Data |
---|---|---|
19c2d5f0 KB |
1 | /* main.c */ |
2 | #include "header.h" | |
3 | #include <pwd.h> | |
4 | static char copyright[]="\nLarn is copyrighted 1986 by Noah Morgan.\n"; | |
5 | int srcount=0; /* line counter for showstr() */ | |
6 | int dropflag=0; /* if 1 then don't lookforobject() next round */ | |
7 | int rmst=80; /* random monster creation counter */ | |
8 | int userid; /* the players login user id number */ | |
9 | char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a move */ | |
10 | static char viewflag=0; | |
11 | /* if viewflag then we have done a 99 stay here and don't showcell in the main loop */ | |
12 | char restorflag=0; /* 1 means restore has been done */ | |
13 | static char cmdhelp[] = "\ | |
14 | Cmd line format: larn [-slicnh] [-o<optsifle>] [-##] [++]\n\ | |
15 | -s show the scoreboard\n\ | |
16 | -l show the logfile (wizard id only)\n\ | |
17 | -i show scoreboard with inventories of dead characters\n\ | |
18 | -c create new scoreboard (wizard id only)\n\ | |
19 | -n suppress welcome message on starting game\n\ | |
20 | -## specify level of difficulty (example: -5)\n\ | |
21 | -h print this help text\n\ | |
22 | ++ restore game from checkpoint file\n\ | |
23 | -o<optsfile> specify .larnopts filename to be used instead of \"~/.larnopts\"\n\ | |
24 | "; | |
25 | #ifdef VT100 | |
26 | static char *termtypes[] = { "vt100", "vt101", "vt102", "vt103", "vt125", | |
27 | "vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340", | |
28 | "vt341" }; | |
29 | #endif VT100 | |
30 | /* | |
31 | ************ | |
32 | MAIN PROGRAM | |
33 | ************ | |
34 | */ | |
35 | main(argc,argv) | |
36 | int argc; | |
37 | char **argv; | |
38 | { | |
39 | register int i,j; | |
40 | int hard; | |
41 | char *ptr=0,*ttype; | |
42 | struct passwd *pwe,*getpwuid(); | |
43 | ||
44 | /* | |
45 | * first task is to identify the player | |
46 | */ | |
47 | #ifndef VT100 | |
48 | init_term(); /* setup the terminal (find out what type) for termcap */ | |
49 | #endif VT100 | |
50 | if (((ptr = getlogin()) == 0) || (*ptr==0)) /* try to get login name */ | |
51 | if (pwe=getpwuid(getuid())) /* can we get it from /etc/passwd? */ | |
52 | ptr = pwe->pw_name; | |
53 | else | |
54 | if ((ptr = getenv("USER")) == 0) | |
55 | if ((ptr = getenv("LOGNAME")) == 0) | |
56 | { | |
57 | noone: write(2, "Can't find your logname. Who Are You?\n",39); | |
58 | exit(); | |
59 | } | |
60 | if (ptr==0) goto noone; | |
61 | if (strlen(ptr)==0) goto noone; | |
62 | /* | |
63 | * second task is to prepare the pathnames the player will need | |
64 | */ | |
65 | strcpy(loginname,ptr); /* save loginname of the user for logging purposes */ | |
66 | strcpy(logname,ptr); /* this will be overwritten with the players name */ | |
67 | if ((ptr = getenv("HOME")) == 0) ptr = "."; | |
68 | #ifdef SAVEINHOME | |
69 | strcpy(savefilename, ptr); | |
70 | strcat(savefilename, "/Larn.sav"); /* save file name in home directory */ | |
71 | #else | |
72 | strcat(savefilename,logname); /* prepare savefile name */ | |
73 | strcat(savefilename,".sav"); /* prepare savefile name */ | |
74 | #endif | |
75 | sprintf(optsfile, "%s/.larnopts",ptr); /* the .larnopts filename */ | |
76 | strcat(scorefile, SCORENAME); /* the larn scoreboard filename */ | |
77 | strcat(logfile, LOGFNAME); /* larn activity logging filename */ | |
78 | strcat(helpfile, HELPNAME); /* the larn on-line help file */ | |
79 | strcat(larnlevels, LEVELSNAME); /* the pre-made cave level data file */ | |
80 | strcat(fortfile, FORTSNAME); /* the fortune data file name */ | |
81 | strcat(playerids, PLAYERIDS); /* the playerid data file name */ | |
82 | strcat(holifile, HOLIFILE); /* the holiday data file name */ | |
83 | ||
84 | /* | |
85 | * now malloc the memory for the dungeon | |
86 | */ | |
87 | cell = (struct cel *)malloc(sizeof(struct cel)*(MAXLEVEL+MAXVLEVEL)*MAXX*MAXY); | |
88 | if (cell == 0) died(-285); /* malloc failure */ | |
89 | lpbuf = malloc((5* BUFBIG)>>2); /* output buffer */ | |
90 | inbuffer = malloc((5*MAXIBUF)>>2); /* output buffer */ | |
91 | if ((lpbuf==0) || (inbuffer==0)) died(-285); /* malloc() failure */ | |
92 | ||
93 | lcreat((char*)0); newgame(); /* set the initial clock */ hard= -1; | |
94 | ||
95 | #ifdef VT100 | |
96 | /* | |
97 | * check terminal type to avoid users who have not vt100 type terminals | |
98 | */ | |
99 | ttype = getenv("TERM"); | |
100 | for (j=1, i=0; i<sizeof(termtypes)/sizeof(char *); i++) | |
101 | if (strcmp(ttype,termtypes[i]) == 0) { j=0; break; } | |
102 | if (j) | |
103 | { | |
104 | lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush(); | |
105 | exit(); | |
106 | } | |
107 | #endif VT100 | |
108 | ||
109 | /* | |
110 | * now make scoreboard if it is not there (don't clear) | |
111 | */ | |
112 | /* if (access(scorefile,0) == -1) */ /* not there */ | |
113 | /* makeboard(); */ | |
114 | ||
115 | /* | |
116 | * now process the command line arguments | |
117 | */ | |
118 | for (i=1; i<argc; i++) | |
119 | { | |
120 | if (argv[i][0] == '-') | |
121 | switch(argv[i][1]) | |
122 | { | |
123 | case 's': showscores(); exit(); /* show scoreboard */ | |
124 | ||
125 | case 'l': /* show log file */ | |
126 | diedlog(); exit(); | |
127 | ||
128 | case 'i': showallscores(); exit(); /* show all scoreboard */ | |
129 | ||
130 | case 'c': /* anyone with password can create scoreboard */ | |
131 | lprcat("Preparing to initialize the scoreboard.\n"); | |
132 | if (getpassword() != 0) /*make new scoreboard*/ | |
133 | { | |
134 | makeboard(); lprc('\n'); showscores(); | |
135 | } | |
136 | exit(); | |
137 | ||
138 | case 'n': /* no welcome msg */ nowelcome=1; argv[i][0]=0; break; | |
139 | ||
140 | case '0': case '1': case '2': case '3': case '4': case '5': | |
141 | case '6': case '7': case '8': case '9': /* for hardness */ | |
142 | sscanf(&argv[i][1],"%d",&hard); | |
143 | break; | |
144 | ||
145 | case 'h': /* print out command line arguments */ | |
146 | write(1,cmdhelp,sizeof(cmdhelp)); exit(); | |
147 | ||
148 | case 'o': /* specify a .larnopts filename */ | |
149 | strncpy(optsfile,argv[i]+2,127); break; | |
150 | ||
151 | default: printf("Unknown option <%s>\n",argv[i]); exit(); | |
152 | }; | |
153 | ||
154 | if (argv[i][0] == '+') | |
155 | { | |
156 | clear(); restorflag = 1; | |
157 | if (argv[i][1] == '+') | |
158 | { | |
159 | hitflag=1; restoregame(ckpfile); /* restore checkpointed game */ | |
160 | } | |
161 | i = argc; | |
162 | } | |
163 | } | |
164 | ||
165 | readopts(); /* read the options file if there is one */ | |
166 | ||
167 | #ifdef TIMECHECK | |
168 | /* | |
169 | * this section of code checks to see if larn is allowed during working hours | |
170 | */ | |
171 | if (dayplay==0) /* check for not-during-daytime-hours */ | |
172 | if (playable()) | |
173 | { | |
174 | write(2,"Sorry, Larn can not be played during working hours.\n",52); | |
175 | exit(); | |
176 | } | |
177 | #endif TIMECHECK | |
178 | ||
179 | #ifdef UIDSCORE | |
180 | userid = geteuid(); /* obtain the user's effective id number */ | |
181 | #else UIDSCORE | |
182 | userid = getplid(logname); /* obtain the players id number */ | |
183 | #endif UIDSCORE | |
184 | if (userid < 0) { write(2,"Can't obtain playerid\n",22); exit(); } | |
185 | ||
186 | #ifdef HIDEBYLINK | |
187 | /* | |
188 | * this section of code causes the program to look like something else to ps | |
189 | */ | |
190 | if (strcmp(psname,argv[0])) /* if a different process name only */ | |
191 | { | |
192 | if ((i=access(psname,1)) < 0) | |
193 | { /* link not there */ | |
194 | if (link(argv[0],psname)>=0) | |
195 | { | |
196 | argv[0] = psname; execv(psname,argv); | |
197 | } | |
198 | } | |
199 | else | |
200 | unlink(psname); | |
201 | } | |
202 | ||
203 | for (i=1; i<argc; i++) | |
204 | { | |
205 | szero(argv[i]); /* zero the argument to avoid ps snooping */ | |
206 | } | |
207 | #endif HIDEBYLINK | |
208 | ||
209 | if (access(savefilename,0)==0) /* restore game if need to */ | |
210 | { | |
211 | clear(); restorflag = 1; | |
212 | hitflag=1; restoregame(savefilename); /* restore last game */ | |
213 | } | |
214 | sigsetup(); /* trap all needed signals */ | |
215 | sethard(hard); /* set up the desired difficulty */ | |
216 | setupvt100(); /* setup the terminal special mode */ | |
217 | if (c[HP]==0) /* create new game */ | |
218 | { | |
219 | makeplayer(); /* make the character that will play */ | |
220 | newcavelevel(0);/* make the dungeon */ | |
221 | predostuff = 1; /* tell signals that we are in the welcome screen */ | |
222 | if (nowelcome==0) welcome(); /* welcome the player to the game */ | |
223 | } | |
224 | drawscreen(); /* show the initial dungeon */ | |
225 | predostuff = 2; /* tell the trap functions that they must do a showplayer() | |
226 | from here on */ | |
227 | /* nice(1); /* games should be run niced */ | |
228 | yrepcount = hit2flag = 0; | |
229 | while (1) | |
230 | { | |
231 | if (dropflag==0) lookforobject(); /* see if there is an object here */ | |
232 | else dropflag=0; /* don't show it just dropped an item */ | |
233 | if (hitflag==0) { if (c[HASTEMONST]) movemonst(); movemonst(); } /* move the monsters */ | |
234 | if (viewflag==0) showcell(playerx,playery); else viewflag=0; /* show stuff around player */ | |
235 | if (hit3flag) flushall(); | |
236 | hitflag=hit3flag=0; nomove=1; | |
237 | bot_linex(); /* update bottom line */ | |
238 | while (nomove) | |
239 | { | |
240 | if (hit3flag) flushall(); | |
241 | nomove=0; parse(); | |
242 | } /* get commands and make moves */ | |
243 | regen(); /* regenerate hp and spells */ | |
244 | if (c[TIMESTOP]==0) | |
245 | if (--rmst <= 0) | |
246 | { rmst = 120-(level<<2); fillmonst(makemonst(level)); } | |
247 | } | |
248 | } | |
249 | \f | |
250 | /* | |
251 | showstr() | |
252 | ||
253 | show character's inventory | |
254 | */ | |
255 | showstr() | |
256 | { | |
257 | register int i,number; | |
258 | for (number=3, i=0; i<26; i++) | |
259 | if (iven[i]) number++; /* count items in inventory */ | |
260 | t_setup(number); qshowstr(); t_endup(number); | |
261 | } | |
262 | ||
263 | qshowstr() | |
264 | { | |
265 | register int i,j,k,sigsav; | |
266 | srcount=0; sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ | |
267 | if (c[GOLD]) { lprintf(".) %d gold pieces",(long)c[GOLD]); srcount++; } | |
268 | for (k=26; k>=0; k--) | |
269 | if (iven[k]) | |
270 | { for (i=22; i<84; i++) | |
271 | for (j=0; j<=k; j++) if (i==iven[j]) show3(j); k=0; } | |
272 | ||
273 | lprintf("\nElapsed time is %d. You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100)); | |
274 | more(); nosignal=sigsav; | |
275 | } | |
276 | ||
277 | /* | |
278 | * subroutine to clear screen depending on # lines to display | |
279 | */ | |
280 | t_setup(count) | |
281 | register int count; | |
282 | { | |
283 | if (count<20) /* how do we clear the screen? */ | |
284 | { | |
285 | cl_up(79,count); cursor(1,1); | |
286 | } | |
287 | else | |
288 | { | |
289 | resetscroll(); clear(); | |
290 | } | |
291 | } | |
292 | ||
293 | /* | |
294 | * subroutine to restore normal display screen depending on t_setup() | |
295 | */ | |
296 | t_endup(count) | |
297 | register int count; | |
298 | { | |
299 | if (count<18) /* how did we clear the screen? */ | |
300 | draws(0,MAXX,0,(count>MAXY) ? MAXY : count); | |
301 | else | |
302 | { | |
303 | drawscreen(); setscroll(); | |
304 | } | |
305 | } | |
306 | ||
307 | /* | |
308 | function to show the things player is wearing only | |
309 | */ | |
310 | showwear() | |
311 | { | |
312 | register int i,j,sigsav,count; | |
313 | sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ | |
314 | srcount=0; | |
315 | ||
316 | for (count=2,j=0; j<=26; j++) /* count number of items we will display */ | |
317 | if (i=iven[j]) | |
318 | switch(i) | |
319 | { | |
320 | case OLEATHER: case OPLATE: case OCHAIN: | |
321 | case ORING: case OSTUDLEATHER: case OSPLINT: | |
322 | case OPLATEARMOR: case OSSPLATE: case OSHIELD: | |
323 | count++; | |
324 | }; | |
325 | ||
326 | t_setup(count); | |
327 | ||
328 | for (i=22; i<84; i++) | |
329 | for (j=0; j<=26; j++) | |
330 | if (i==iven[j]) | |
331 | switch(i) | |
332 | { | |
333 | case OLEATHER: case OPLATE: case OCHAIN: | |
334 | case ORING: case OSTUDLEATHER: case OSPLINT: | |
335 | case OPLATEARMOR: case OSSPLATE: case OSHIELD: | |
336 | show3(j); | |
337 | }; | |
338 | more(); nosignal=sigsav; t_endup(count); | |
339 | } | |
340 | ||
341 | /* | |
342 | function to show the things player can wield only | |
343 | */ | |
344 | showwield() | |
345 | { | |
346 | register int i,j,sigsav,count; | |
347 | sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ | |
348 | srcount=0; | |
349 | ||
350 | for (count=2,j=0; j<=26; j++) /* count how many items */ | |
351 | if (i=iven[j]) | |
352 | switch(i) | |
353 | { | |
354 | case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE: | |
355 | case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT: | |
356 | case OSPIRITSCARAB: case OCUBEofUNDEAD: | |
357 | case OPOTION: case OSCROLL: break; | |
358 | default: count++; | |
359 | }; | |
360 | ||
361 | t_setup(count); | |
362 | ||
363 | for (i=22; i<84; i++) | |
364 | for (j=0; j<=26; j++) | |
365 | if (i==iven[j]) | |
366 | switch(i) | |
367 | { | |
368 | case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE: | |
369 | case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT: | |
370 | case OSPIRITSCARAB: case OCUBEofUNDEAD: | |
371 | case OPOTION: case OSCROLL: break; | |
372 | default: show3(j); | |
373 | }; | |
374 | more(); nosignal=sigsav; t_endup(count); | |
375 | } | |
376 | ||
377 | /* | |
378 | * function to show the things player can read only | |
379 | */ | |
380 | showread() | |
381 | { | |
382 | register int i,j,sigsav,count; | |
383 | sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ | |
384 | srcount=0; | |
385 | ||
386 | for (count=2,j=0; j<=26; j++) | |
387 | switch(iven[j]) | |
388 | { | |
389 | case OBOOK: case OSCROLL: count++; | |
390 | }; | |
391 | t_setup(count); | |
392 | ||
393 | for (i=22; i<84; i++) | |
394 | for (j=0; j<=26; j++) | |
395 | if (i==iven[j]) | |
396 | switch(i) | |
397 | { | |
398 | case OBOOK: case OSCROLL: show3(j); | |
399 | }; | |
400 | more(); nosignal=sigsav; t_endup(count); | |
401 | } | |
402 | ||
403 | /* | |
404 | * function to show the things player can eat only | |
405 | */ | |
406 | showeat() | |
407 | { | |
408 | register int i,j,sigsav,count; | |
409 | sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ | |
410 | srcount=0; | |
411 | ||
412 | for (count=2,j=0; j<=26; j++) | |
413 | switch(iven[j]) | |
414 | { | |
415 | case OCOOKIE: count++; | |
416 | }; | |
417 | t_setup(count); | |
418 | ||
419 | for (i=22; i<84; i++) | |
420 | for (j=0; j<=26; j++) | |
421 | if (i==iven[j]) | |
422 | switch(i) | |
423 | { | |
424 | case OCOOKIE: show3(j); | |
425 | }; | |
426 | more(); nosignal=sigsav; t_endup(count); | |
427 | } | |
428 | ||
429 | /* | |
430 | function to show the things player can quaff only | |
431 | */ | |
432 | showquaff() | |
433 | { | |
434 | register int i,j,sigsav,count; | |
435 | sigsav=nosignal; nosignal=1; /* don't allow ^c etc */ | |
436 | srcount=0; | |
437 | ||
438 | for (count=2,j=0; j<=26; j++) | |
439 | switch(iven[j]) | |
440 | { | |
441 | case OPOTION: count++; | |
442 | }; | |
443 | t_setup(count); | |
444 | ||
445 | for (i=22; i<84; i++) | |
446 | for (j=0; j<=26; j++) | |
447 | if (i==iven[j]) | |
448 | switch(i) | |
449 | { | |
450 | case OPOTION: show3(j); | |
451 | }; | |
452 | more(); nosignal=sigsav; t_endup(count); | |
453 | } | |
454 | ||
455 | show1(idx,str2) | |
456 | register int idx; | |
457 | register char *str2[]; | |
458 | { | |
459 | if (str2==0) lprintf("\n%c) %s",idx+'a',objectname[iven[idx]]); | |
460 | else if (*str2[ivenarg[idx]]==0) lprintf("\n%c) %s",idx+'a',objectname[iven[idx]]); | |
461 | else lprintf("\n%c) %s of%s",idx+'a',objectname[iven[idx]],str2[ivenarg[idx]]); | |
462 | } | |
463 | ||
464 | show3(index) | |
465 | register int index; | |
466 | { | |
467 | switch(iven[index]) | |
468 | { | |
469 | case OPOTION: show1(index,potionname); break; | |
470 | case OSCROLL: show1(index,scrollname); break; | |
471 | ||
472 | case OLARNEYE: case OBOOK: case OSPIRITSCARAB: | |
473 | case ODIAMOND: case ORUBY: case OCUBEofUNDEAD: | |
474 | case OEMERALD: case OCHEST: case OCOOKIE: | |
475 | case OSAPPHIRE: case ONOTHEFT: show1(index,(char **)0); break; | |
476 | ||
477 | default: lprintf("\n%c) %s",index+'a',objectname[iven[index]]); | |
478 | if (ivenarg[index]>0) lprintf(" + %d",(long)ivenarg[index]); | |
479 | else if (ivenarg[index]<0) lprintf(" %d",(long)ivenarg[index]); | |
480 | break; | |
481 | } | |
482 | if (c[WIELD]==index) lprcat(" (weapon in hand)"); | |
483 | if ((c[WEAR]==index) || (c[SHIELD]==index)) lprcat(" (being worn)"); | |
484 | if (++srcount>=22) { srcount=0; more(); clear(); } | |
485 | } | |
486 | ||
487 | /* | |
488 | subroutine to randomly create monsters if needed | |
489 | */ | |
490 | randmonst() | |
491 | { | |
492 | if (c[TIMESTOP]) return; /* don't make monsters if time is stopped */ | |
493 | if (--rmst <= 0) | |
494 | { | |
495 | rmst = 120 - (level<<2); fillmonst(makemonst(level)); | |
496 | } | |
497 | } | |
498 | ||
499 | \f | |
500 | /* | |
501 | parse() | |
502 | ||
503 | get and execute a command | |
504 | */ | |
505 | parse() | |
506 | { | |
507 | register int i,j,k,flag; | |
508 | while (1) | |
509 | { | |
510 | k = yylex(); | |
511 | switch(k) /* get the token from the input and switch on it */ | |
512 | { | |
513 | case 'h': moveplayer(4); return; /* west */ | |
514 | case 'H': run(4); return; /* west */ | |
515 | case 'l': moveplayer(2); return; /* east */ | |
516 | case 'L': run(2); return; /* east */ | |
517 | case 'j': moveplayer(1); return; /* south */ | |
518 | case 'J': run(1); return; /* south */ | |
519 | case 'k': moveplayer(3); return; /* north */ | |
520 | case 'K': run(3); return; /* north */ | |
521 | case 'u': moveplayer(5); return; /* northeast */ | |
522 | case 'U': run(5); return; /* northeast */ | |
523 | case 'y': moveplayer(6); return; /* northwest */ | |
524 | case 'Y': run(6); return; /* northwest */ | |
525 | case 'n': moveplayer(7); return; /* southeast */ | |
526 | case 'N': run(7); return; /* southeast */ | |
527 | case 'b': moveplayer(8); return; /* southwest */ | |
528 | case 'B': run(8); return; /* southwest */ | |
529 | ||
530 | case '.': if (yrepcount) viewflag=1; return; /* stay here */ | |
531 | ||
532 | case 'w': yrepcount=0; wield(); return; /* wield a weapon */ | |
533 | ||
534 | case 'W': yrepcount=0; wear(); return; /* wear armor */ | |
535 | ||
536 | case 'r': yrepcount=0; | |
537 | if (c[BLINDCOUNT]) { cursors(); lprcat("\nYou can't read anything when you're blind!"); } else | |
538 | if (c[TIMESTOP]==0) readscr(); return; /* to read a scroll */ | |
539 | ||
540 | case 'q': yrepcount=0; if (c[TIMESTOP]==0) quaff(); return; /* quaff a potion */ | |
541 | ||
542 | case 'd': yrepcount=0; if (c[TIMESTOP]==0) dropobj(); return; /* to drop an object */ | |
543 | ||
544 | case 'c': yrepcount=0; cast(); return; /* cast a spell */ | |
545 | ||
546 | case 'i': yrepcount=0; nomove=1; showstr(); return; /* status */ | |
547 | ||
548 | case 'e': yrepcount=0; | |
549 | if (c[TIMESTOP]==0) eatcookie(); return; /* to eat a fortune cookie */ | |
550 | ||
551 | case 'D': yrepcount=0; seemagic(0); nomove=1; return; /* list spells and scrolls */ | |
552 | ||
553 | case '?': yrepcount=0; help(); nomove=1; return; /* give the help screen*/ | |
554 | ||
555 | case 'S': clear(); lprcat("Saving . . ."); lflush(); | |
556 | savegame(savefilename); wizard=1; died(-257); /* save the game - doesn't return */ | |
557 | ||
558 | case 'Z': yrepcount=0; if (c[LEVEL]>9) { oteleport(1); return; } | |
559 | cursors(); lprcat("\nAs yet, you don't have enough experience to use teleportation"); | |
560 | return; /* teleport yourself */ | |
561 | ||
562 | case '^': /* identify traps */ flag=yrepcount=0; cursors(); | |
563 | lprc('\n'); for (j=playery-1; j<playery+2; j++) | |
564 | { | |
565 | if (j < 0) j=0; if (j >= MAXY) break; | |
566 | for (i=playerx-1; i<playerx+2; i++) | |
567 | { | |
568 | if (i < 0) i=0; if (i >= MAXX) break; | |
569 | switch(item[i][j]) | |
570 | { | |
571 | case OTRAPDOOR: case ODARTRAP: | |
572 | case OTRAPARROW: case OTELEPORTER: | |
573 | lprcat("\nIts "); lprcat(objectname[item[i][j]]); flag++; | |
574 | }; | |
575 | } | |
576 | } | |
577 | if (flag==0) lprcat("\nNo traps are visible"); | |
578 | return; | |
579 | ||
580 | #if WIZID | |
581 | case '_': /* this is the fudge player password for wizard mode*/ | |
582 | yrepcount=0; cursors(); nomove=1; | |
583 | if (userid!=wisid) | |
584 | { | |
585 | lprcat("Sorry, you are not empowered to be a wizard.\n"); | |
586 | scbr(); /* system("stty -echo cbreak"); */ | |
587 | lflush(); return; | |
588 | } | |
589 | if (getpassword()==0) | |
590 | { | |
591 | scbr(); /* system("stty -echo cbreak"); */ return; | |
592 | } | |
593 | wizard=1; scbr(); /* system("stty -echo cbreak"); */ | |
594 | for (i=0; i<6; i++) c[i]=70; iven[0]=iven[1]=0; | |
595 | take(OPROTRING,50); take(OLANCE,25); c[WIELD]=1; | |
596 | c[LANCEDEATH]=1; c[WEAR] = c[SHIELD] = -1; | |
597 | raiseexperience(6000000L); c[AWARENESS] += 25000; | |
598 | { | |
599 | register int i,j; | |
600 | for (i=0; i<MAXY; i++) | |
601 | for (j=0; j<MAXX; j++) know[j][i]=1; | |
602 | for (i=0; i<SPNUM; i++) spelknow[i]=1; | |
603 | for (i=0; i<MAXSCROLL; i++) scrollname[i][0]=' '; | |
604 | for (i=0; i<MAXPOTION; i++) potionname[i][0]=' '; | |
605 | } | |
606 | for (i=0; i<MAXSCROLL; i++) | |
607 | if (strlen(scrollname[i])>2) /* no null items */ | |
608 | { item[i][0]=OSCROLL; iarg[i][0]=i; } | |
609 | for (i=MAXX-1; i>MAXX-1-MAXPOTION; i--) | |
610 | if (strlen(potionname[i-MAXX+MAXPOTION])>2) /* no null items */ | |
611 | { item[i][0]=OPOTION; iarg[i][0]=i-MAXX+MAXPOTION; } | |
612 | for (i=1; i<MAXY; i++) | |
613 | { item[0][i]=i; iarg[0][i]=0; } | |
614 | for (i=MAXY; i<MAXY+MAXX; i++) | |
615 | { item[i-MAXY][MAXY-1]=i; iarg[i-MAXY][MAXY-1]=0; } | |
616 | for (i=MAXX+MAXY; i<MAXX+MAXY+MAXY; i++) | |
617 | { item[MAXX-1][i-MAXX-MAXY]=i; iarg[MAXX-1][i-MAXX-MAXY]=0; } | |
618 | c[GOLD]+=25000; drawscreen(); return; | |
619 | #endif | |
620 | ||
621 | case 'T': yrepcount=0; cursors(); if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else | |
622 | if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); } | |
623 | else lprcat("\nYou aren't wearing anything"); | |
624 | return; | |
625 | ||
626 | case 'g': cursors(); | |
627 | lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight()); | |
628 | case ' ': yrepcount=0; nomove=1; return; | |
629 | ||
630 | case 'v': yrepcount=0; cursors(); | |
631 | lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d",(long)VERSION,(long)SUBVERSION,(long)c[HARDGAME]); | |
632 | if (wizard) lprcat(" Wizard"); nomove=1; | |
633 | if (cheat) lprcat(" Cheater"); | |
634 | lprcat(copyright); | |
635 | return; | |
636 | ||
637 | case 'Q': yrepcount=0; quit(); nomove=1; return; /* quit */ | |
638 | ||
639 | case 'L'-64: yrepcount=0; drawscreen(); nomove=1; return; /* look */ | |
640 | ||
641 | #if WIZID | |
642 | #ifdef EXTRA | |
643 | case 'A': yrepcount=0; nomove=1; if (wizard) { diag(); return; } /* create diagnostic file */ | |
644 | return; | |
645 | #endif | |
646 | #endif | |
647 | case 'P': cursors(); | |
648 | if (outstanding_taxes>0) | |
649 | lprintf("\nYou presently owe %d gp in taxes.",(long)outstanding_taxes); | |
650 | else | |
651 | lprcat("\nYou do not owe any taxes."); | |
652 | return; | |
653 | }; | |
654 | } | |
655 | } | |
656 | ||
657 | parse2() | |
658 | { | |
659 | if (c[HASTEMONST]) movemonst(); movemonst(); /* move the monsters */ | |
660 | randmonst(); regen(); | |
661 | } | |
662 | ||
663 | run(dir) | |
664 | int dir; | |
665 | { | |
666 | register int i; | |
667 | i=1; while (i) | |
668 | { | |
669 | i=moveplayer(dir); | |
670 | if (i>0) { if (c[HASTEMONST]) movemonst(); movemonst(); randmonst(); regen(); } | |
671 | if (hitflag) i=0; | |
672 | if (i!=0) showcell(playerx,playery); | |
673 | } | |
674 | } | |
675 | ||
676 | /* | |
677 | function to wield a weapon | |
678 | */ | |
679 | wield() | |
680 | { | |
681 | register int i; | |
682 | while (1) | |
683 | { | |
684 | if ((i = whatitem("wield"))=='\33') return; | |
685 | if (i != '.') | |
686 | { | |
687 | if (i=='*') showwield(); | |
688 | else if (iven[i-'a']==0) { ydhi(i); return; } | |
689 | else if (iven[i-'a']==OPOTION) { ycwi(i); return; } | |
690 | else if (iven[i-'a']==OSCROLL) { ycwi(i); return; } | |
691 | else if ((c[SHIELD]!= -1) && (iven[i-'a']==O2SWORD)) { lprcat("\nBut one arm is busy with your shield!"); return; } | |
692 | else { c[WIELD]=i-'a'; if (iven[i-'a'] == OLANCE) c[LANCEDEATH]=1; else c[LANCEDEATH]=0; bottomline(); return; } | |
693 | } | |
694 | } | |
695 | } | |
696 | ||
697 | /* | |
698 | common routine to say you don't have an item | |
699 | */ | |
700 | ydhi(x) | |
701 | int x; | |
702 | { cursors(); lprintf("\nYou don't have item %c!",x); } | |
703 | ycwi(x) | |
704 | int x; | |
705 | { cursors(); lprintf("\nYou can't wield item %c!",x); } | |
706 | ||
707 | /* | |
708 | function to wear armor | |
709 | */ | |
710 | wear() | |
711 | { | |
712 | register int i; | |
713 | while (1) | |
714 | { | |
715 | if ((i = whatitem("wear"))=='\33') return; | |
716 | if (i != '.') | |
717 | { | |
718 | if (i=='*') showwear(); else | |
719 | switch(iven[i-'a']) | |
720 | { | |
721 | case 0: ydhi(i); return; | |
722 | case OLEATHER: case OCHAIN: case OPLATE: case OSTUDLEATHER: | |
723 | case ORING: case OSPLINT: case OPLATEARMOR: case OSSPLATE: | |
724 | if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; } | |
725 | c[WEAR]=i-'a'; bottomline(); return; | |
726 | case OSHIELD: if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; } | |
727 | if (iven[c[WIELD]]==O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; } | |
728 | c[SHIELD] = i-'a'; bottomline(); return; | |
729 | default: lprcat("\nYou can't wear that!"); | |
730 | }; | |
731 | } | |
732 | } | |
733 | } | |
734 | ||
735 | /* | |
736 | function to drop an object | |
737 | */ | |
738 | dropobj() | |
739 | { | |
740 | register int i; | |
741 | register char *p; | |
742 | long amt; | |
743 | p = &item[playerx][playery]; | |
744 | while (1) | |
745 | { | |
746 | if ((i = whatitem("drop"))=='\33') return; | |
747 | if (i=='*') showstr(); else | |
748 | { | |
749 | if (i=='.') /* drop some gold */ | |
750 | { | |
751 | if (*p) { lprcat("\nThere's something here already!"); return; } | |
752 | lprcat("\n\n"); | |
753 | cl_dn(1,23); | |
754 | lprcat("How much gold do you drop? "); | |
755 | if ((amt=readnum((long)c[GOLD])) == 0) return; | |
756 | if (amt>c[GOLD]) | |
757 | { lprcat("\nYou don't have that much!"); return; } | |
758 | if (amt<=32767) | |
759 | { *p=OGOLDPILE; i=amt; } | |
760 | else if (amt<=327670L) | |
761 | { *p=ODGOLD; i=amt/10; amt = 10*i; } | |
762 | else if (amt<=3276700L) | |
763 | { *p=OMAXGOLD; i=amt/100; amt = 100*i; } | |
764 | else if (amt<=32767000L) | |
765 | { *p=OKGOLD; i=amt/1000; amt = 1000*i; } | |
766 | else | |
767 | { *p=OKGOLD; i=32767; amt = 32767000L; } | |
768 | c[GOLD] -= amt; | |
769 | lprintf("You drop %d gold pieces",(long)amt); | |
770 | iarg[playerx][playery]=i; bottomgold(); | |
771 | know[playerx][playery]=0; dropflag=1; return; | |
772 | } | |
773 | drop_object(i-'a'); | |
774 | return; | |
775 | } | |
776 | } | |
777 | } | |
778 | ||
779 | /* | |
780 | * readscr() Subroutine to read a scroll one is carrying | |
781 | */ | |
782 | readscr() | |
783 | { | |
784 | register int i; | |
785 | while (1) | |
786 | { | |
787 | if ((i = whatitem("read"))=='\33') return; | |
788 | if (i != '.') | |
789 | { | |
790 | if (i=='*') showread(); else | |
791 | { | |
792 | if (iven[i-'a']==OSCROLL) { read_scroll(ivenarg[i-'a']); iven[i-'a']=0; return; } | |
793 | if (iven[i-'a']==OBOOK) { readbook(ivenarg[i-'a']); iven[i-'a']=0; return; } | |
794 | if (iven[i-'a']==0) { ydhi(i); return; } | |
795 | lprcat("\nThere's nothing on it to read"); return; | |
796 | } | |
797 | } | |
798 | } | |
799 | } | |
800 | ||
801 | /* | |
802 | * subroutine to eat a cookie one is carrying | |
803 | */ | |
804 | eatcookie() | |
805 | { | |
806 | register int i; | |
807 | char *p; | |
808 | while (1) | |
809 | { | |
810 | if ((i = whatitem("eat"))=='\33') return; | |
811 | if (i != '.') | |
812 | if (i=='*') showeat(); else | |
813 | { | |
814 | if (iven[i-'a']==OCOOKIE) | |
815 | { | |
816 | lprcat("\nThe cookie was delicious."); | |
817 | iven[i-'a']=0; | |
818 | if (!c[BLINDCOUNT]) | |
819 | { | |
820 | if (p=fortune(fortfile)) | |
821 | { | |
822 | lprcat(" Inside you find a scrap of paper that says:\n"); | |
823 | lprcat(p); | |
824 | } | |
825 | } | |
826 | return; | |
827 | } | |
828 | if (iven[i-'a']==0) { ydhi(i); return; } | |
829 | lprcat("\nYou can't eat that!"); return; | |
830 | } | |
831 | } | |
832 | } | |
833 | ||
834 | /* | |
835 | * subroutine to quaff a potion one is carrying | |
836 | */ | |
837 | quaff() | |
838 | { | |
839 | register int i; | |
840 | while (1) | |
841 | { | |
842 | if ((i = whatitem("quaff"))=='\33') return; | |
843 | if (i != '.') | |
844 | { | |
845 | if (i=='*') showquaff(); else | |
846 | { | |
847 | if (iven[i-'a']==OPOTION) { quaffpotion(ivenarg[i-'a']); iven[i-'a']=0; return; } | |
848 | if (iven[i-'a']==0) { ydhi(i); return; } | |
849 | lprcat("\nYou wouldn't want to quaff that, would you? "); return; | |
850 | } | |
851 | } | |
852 | } | |
853 | } | |
854 | ||
855 | /* | |
856 | function to ask what player wants to do | |
857 | */ | |
858 | whatitem(str) | |
859 | char *str; | |
860 | { | |
861 | int i; | |
862 | cursors(); lprintf("\nWhat do you want to %s [* for all] ? ",str); | |
863 | i=0; while (i>'z' || (i<'a' && i!='*' && i!='\33' && i!='.')) i=getchar(); | |
864 | if (i=='\33') lprcat(" aborted"); | |
865 | return(i); | |
866 | } | |
867 | ||
868 | /* | |
869 | subroutine to get a number from the player | |
870 | and allow * to mean return amt, else return the number entered | |
871 | */ | |
872 | unsigned long readnum(mx) | |
873 | long mx; | |
874 | { | |
875 | register int i; | |
876 | register unsigned long amt=0; | |
877 | sncbr(); | |
878 | if ((i=getchar()) == '*') amt = mx; /* allow him to say * for all gold */ | |
879 | else | |
880 | while (i != '\n') | |
881 | { | |
882 | if (i=='\033') { scbr(); lprcat(" aborted"); return(0); } | |
883 | if ((i <= '9') && (i >= '0') && (amt<99999999)) | |
884 | amt = amt*10+i-'0'; | |
885 | i = getchar(); | |
886 | } | |
887 | scbr(); return(amt); | |
888 | } | |
889 | ||
890 | #ifdef HIDEBYLINK | |
891 | /* | |
892 | * routine to zero every byte in a string | |
893 | */ | |
894 | szero(str) | |
895 | register char *str; | |
896 | { | |
897 | while (*str) | |
898 | *str++ = 0; | |
899 | } | |
900 | #endif HIDEBYLINK | |
901 | ||
902 | #ifdef TIMECHECK | |
903 | /* | |
904 | * routine to check the time of day and return 1 if its during work hours | |
905 | * checks the file ".holidays" for forms like "mmm dd comment..." | |
906 | */ | |
907 | int playable() | |
908 | { | |
909 | long g_time,time(); | |
910 | int hour,day,year; | |
911 | char *date,*month,*p; | |
912 | ||
913 | time(&g_time); /* get the time and date */ | |
914 | date = ctime(&g_time); /* format: Fri Jul 4 00:27:56 EDT 1986 */ | |
915 | year = atoi(date+20); | |
916 | hour = (date[11]-'0')*10 + date[12]-'0'; | |
917 | day = (date[8]!=' ') ? ((date[8]-'0')*10 + date[9]-'0') : (date[9]-'0'); | |
918 | month = date+4; date[7]=0; /* point to and NULL terminate month */ | |
919 | ||
920 | if (((hour>=8 && hour<17)) /* 8AM - 5PM */ | |
921 | && strncmp("Sat",date,3)!=0 /* not a Saturday */ | |
922 | && strncmp("Sun",date,3)!=0) /* not a Sunday */ | |
923 | { | |
924 | /* now check for a .holidays datafile */ | |
925 | lflush(); | |
926 | if (lopen(holifile) >= 0) | |
927 | for ( ; ; ) | |
928 | { | |
929 | if ((p=lgetw())==0) break; | |
930 | if (strlen(p)<6) continue; | |
931 | if ((strncmp(p,month,3)==0) && (day==atoi(p+4)) && (year==atoi(p+7))) | |
932 | return(0); /* a holiday */ | |
933 | } | |
934 | lrclose(); lcreat((char*)0); | |
935 | return(1); | |
936 | } | |
937 | return(0); | |
938 | } | |
939 | #endif TIMECHECK |