386BSD 0.1 development
[unix-history] / usr / othersrc / games / larn / global.c
CommitLineData
12458000
WJ
1/* global.c Larn is copyrighted 1986 by Noah Morgan.
2 *
3 * raiselevel() subroutine to raise the player one level
4 * loselevel() subroutine to lower the player by one level
5 * raiseexperience(x) subroutine to increase experience points
6 * loseexperience(x) subroutine to lose experience points
7 * losehp(x) subroutine to remove hit points from the player
8 * losemhp(x) subroutine to remove max # hit points from the player
9 * raisehp(x) subroutine to gain hit points
10 * raisemhp(x) subroutine to gain maximum hit points
11 * losespells(x) subroutine to lose spells
12 * losemspells(x) subroutine to lose maximum spells
13 * raisespells(x) subroutine to gain spells
14 * raisemspells(x) subroutine to gain maximum spells
15 * recalc() function to recalculate the armor class of the player
16 * makemonst(lev) function to return monster number for a randomly selected monster
17 * positionplayer() function to be sure player is not in a wall
18 * quit() subroutine to ask if the player really wants to quit
19 */
20
21#include "header.h"
22extern int score[],srcount,dropflag;
23extern int random;/* the random number seed */
24extern short playerx,playery,lastnum;
25extern char cheat,level,monstnamelist[];
26extern char lastmonst[],*what[],*who[];
27extern char winner[];
28extern char logname[],monstlevel[];
29extern char sciv[SCORESIZE+1][26][2],*potionname[],*scrollname[];
30/*
31 ***********
32 RAISE LEVEL
33 ***********
34 raiselevel()
35
36 subroutine to raise the player one level
37 uses the skill[] array to find level boundarys
38 uses c[EXPERIENCE] c[LEVEL]
39 */
40raiselevel()
41 {
42 if (c[LEVEL] < MAXPLEVEL) raiseexperience((long)(skill[c[LEVEL]]-c[EXPERIENCE]));
43 }
44
45/*
46 ***********
47 LOOSE LEVEL
48 ***********
49 loselevel()
50
51 subroutine to lower the players character level by one
52 */
53loselevel()
54 {
55 if (c[LEVEL] > 1) loseexperience((long)(c[EXPERIENCE] - skill[c[LEVEL]-1] + 1));
56 }
57
58/*
59 ****************
60 RAISE EXPERIENCE
61 ****************
62 raiseexperience(x)
63
64 subroutine to increase experience points
65 */
66raiseexperience(x)
67 register long x;
68 {
69 register int i,tmp;
70 i=c[LEVEL]; c[EXPERIENCE]+=x;
71 while (c[EXPERIENCE] >= skill[c[LEVEL]] && (c[LEVEL] < MAXPLEVEL))
72 {
73 tmp = (c[CONSTITUTION]-c[HARDGAME])>>1;
74 c[LEVEL]++; raisemhp((int)(rnd(3)+rnd((tmp>0)?tmp:1)));
75 raisemspells((int)rund(3));
76 if (c[LEVEL] < 7-c[HARDGAME]) raisemhp((int)(c[CONSTITUTION]>>2));
77 }
78 if (c[LEVEL] != i)
79 {
80 cursors();
81 beep(); lprintf("\nWelcome to level %d",(long)c[LEVEL]); /* if we changed levels */
82 }
83 bottomline();
84 }
85
86/*
87 ****************
88 LOOSE EXPERIENCE
89 ****************
90 loseexperience(x)
91
92 subroutine to lose experience points
93 */
94loseexperience(x)
95 register long x;
96 {
97 register int i,tmp;
98 i=c[LEVEL]; c[EXPERIENCE]-=x;
99 if (c[EXPERIENCE] < 0) c[EXPERIENCE]=0;
100 while (c[EXPERIENCE] < skill[c[LEVEL]-1])
101 {
102 if (--c[LEVEL] <= 1) c[LEVEL]=1; /* down one level */
103 tmp = (c[CONSTITUTION]-c[HARDGAME])>>1; /* lose hpoints */
104 losemhp((int)rnd((tmp>0)?tmp:1)); /* lose hpoints */
105 if (c[LEVEL] < 7-c[HARDGAME]) losemhp((int)(c[CONSTITUTION]>>2));
106 losemspells((int)rund(3)); /* lose spells */
107 }
108 if (i!=c[LEVEL])
109 {
110 cursors();
111 beep(); lprintf("\nYou went down to level %d!",(long)c[LEVEL]);
112 }
113 bottomline();
114 }
115
116/*
117 ********
118 LOOSE HP
119 ********
120 losehp(x)
121 losemhp(x)
122
123 subroutine to remove hit points from the player
124 warning -- will kill player if hp goes to zero
125 */
126losehp(x)
127 register int x;
128 {
129 if ((c[HP] -= x) <= 0)
130 {
131 beep(); lprcat("\n"); nap(3000); died(lastnum);
132 }
133 }
134
135losemhp(x)
136 register int x;
137 {
138 c[HP] -= x; if (c[HP] < 1) c[HP]=1;
139 c[HPMAX] -= x; if (c[HPMAX] < 1) c[HPMAX]=1;
140 }
141
142/*
143 ********
144 RAISE HP
145 ********
146 raisehp(x)
147 raisemhp(x)
148
149 subroutine to gain maximum hit points
150 */
151raisehp(x)
152 register int x;
153 {
154 if ((c[HP] += x) > c[HPMAX]) c[HP] = c[HPMAX];
155 }
156
157raisemhp(x)
158 register int x;
159 {
160 c[HPMAX] += x; c[HP] += x;
161 }
162
163/*
164 ************
165 RAISE SPELLS
166 ************
167 raisespells(x)
168 raisemspells(x)
169
170 subroutine to gain maximum spells
171 */
172raisespells(x)
173 register int x;
174 {
175 if ((c[SPELLS] += x) > c[SPELLMAX]) c[SPELLS] = c[SPELLMAX];
176 }
177
178raisemspells(x)
179 register int x;
180 {
181 c[SPELLMAX]+=x; c[SPELLS]+=x;
182 }
183
184/*
185 ************
186 LOOSE SPELLS
187 ************
188 losespells(x)
189 losemspells(x)
190
191 subroutine to lose maximum spells
192 */
193losespells(x)
194 register int x;
195 {
196 if ((c[SPELLS] -= x) < 0) c[SPELLS]=0;
197 }
198
199losemspells(x)
200 register int x;
201 {
202 if ((c[SPELLMAX] -= x) < 0) c[SPELLMAX]=0;
203 if ((c[SPELLS] -= x) < 0) c[SPELLS]=0;
204 }
205
206/*
207 makemonst(lev)
208 int lev;
209
210 function to return monster number for a randomly selected monster
211 for the given cave level
212 */
213makemonst(lev)
214 register int lev;
215 {
216 register int tmp,x;
217 if (lev < 1) lev = 1; if (lev > 12) lev = 12;
218 tmp=WATERLORD;
219 if (lev < 5)
220 while (tmp==WATERLORD) tmp=rnd((x=monstlevel[lev-1])?x:1);
221 else while (tmp==WATERLORD)
222 tmp=rnd((x=monstlevel[lev-1]-monstlevel[lev-4])?x:1)+monstlevel[lev-4];
223
224 while (monster[tmp].genocided && tmp<MAXMONST) tmp++; /* genocided? */
225 return(tmp);
226 }
227
228/*
229 positionplayer()
230
231 function to be sure player is not in a wall
232 */
233positionplayer()
234 {
235 int try;
236 try = 2;
237 while ((item[playerx][playery] || mitem[playerx][playery]) && (try))
238 if (++playerx >= MAXX-1)
239 {
240 playerx = 1;
241 if (++playery >= MAXY-1)
242 { playery = 1; --try; }
243 }
244 if (try==0) lprcat("Failure in positionplayer\n");
245 }
246
247/*
248 recalc() function to recalculate the armor class of the player
249 */
250recalc()
251 {
252 register int i,j,k;
253 c[AC] = c[MOREDEFENSES];
254 if (c[WEAR] >= 0)
255 switch(iven[c[WEAR]])
256 {
257 case OSHIELD: c[AC] += 2 + ivenarg[c[WEAR]]; break;
258 case OLEATHER: c[AC] += 2 + ivenarg[c[WEAR]]; break;
259 case OSTUDLEATHER: c[AC] += 3 + ivenarg[c[WEAR]]; break;
260 case ORING: c[AC] += 5 + ivenarg[c[WEAR]]; break;
261 case OCHAIN: c[AC] += 6 + ivenarg[c[WEAR]]; break;
262 case OSPLINT: c[AC] += 7 + ivenarg[c[WEAR]]; break;
263 case OPLATE: c[AC] += 9 + ivenarg[c[WEAR]]; break;
264 case OPLATEARMOR: c[AC] += 10 + ivenarg[c[WEAR]]; break;
265 case OSSPLATE: c[AC] += 12 + ivenarg[c[WEAR]]; break;
266 }
267
268 if (c[SHIELD] >= 0) if (iven[c[SHIELD]] == OSHIELD) c[AC] += 2 + ivenarg[c[SHIELD]];
269 if (c[WIELD] < 0) c[WCLASS] = 0; else
270 {
271 i = ivenarg[c[WIELD]];
272 switch(iven[c[WIELD]])
273 {
274 case ODAGGER: c[WCLASS] = 3 + i; break;
275 case OBELT: c[WCLASS] = 7 + i; break;
276 case OSHIELD: c[WCLASS] = 8 + i; break;
277 case OSPEAR: c[WCLASS] = 10 + i; break;
278 case OFLAIL: c[WCLASS] = 14 + i; break;
279 case OBATTLEAXE: c[WCLASS] = 17 + i; break;
280 case OLANCE: c[WCLASS] = 19 + i; break;
281 case OLONGSWORD: c[WCLASS] = 22 + i; break;
282 case O2SWORD: c[WCLASS] = 26 + i; break;
283 case OSWORD: c[WCLASS] = 32 + i; break;
284 case OSWORDofSLASHING: c[WCLASS] = 30 + i; break;
285 case OHAMMER: c[WCLASS] = 35 + i; break;
286 default: c[WCLASS] = 0;
287 }
288 }
289 c[WCLASS] += c[MOREDAM];
290
291/* now for regeneration abilities based on rings */
292 c[REGEN]=1; c[ENERGY]=0;
293 j=0; for (k=25; k>0; k--) if (iven[k]) {j=k; k=0; }
294 for (i=0; i<=j; i++)
295 {
296 switch(iven[i])
297 {
298 case OPROTRING: c[AC] += ivenarg[i] + 1; break;
299 case ODAMRING: c[WCLASS] += ivenarg[i] + 1; break;
300 case OBELT: c[WCLASS] += ((ivenarg[i]<<1)) + 2; break;
301
302 case OREGENRING: c[REGEN] += ivenarg[i] + 1; break;
303 case ORINGOFEXTRA: c[REGEN] += 5 * (ivenarg[i]+1); break;
304 case OENERGYRING: c[ENERGY] += ivenarg[i] + 1; break;
305 }
306 }
307 }
308
309
310/*
311 quit()
312
313 subroutine to ask if the player really wants to quit
314 */
315quit()
316 {
317 register int i;
318 cursors(); strcpy(lastmonst,"");
319 lprcat("\n\nDo you really want to quit?");
320 while (1)
321 {
322 i=getchar();
323 if (i == 'y') { died(300); return; }
324 if ((i == 'n') || (i == '\33')) { lprcat(" no"); lflush(); return; }
325 lprcat("\n"); setbold(); lprcat("Yes"); resetbold(); lprcat(" or ");
326 setbold(); lprcat("No"); resetbold(); lprcat(" please? Do you want to quit? ");
327 }
328 }
329
330/*
331 function to ask --more-- then the user must enter a space
332 */
333more()
334 {
335 lprcat("\n --- press "); standout("space"); lprcat(" to continue --- ");
336 while (getchar() != ' ');
337 }
338
339/*
340 function to put something in the players inventory
341 returns 0 if success, 1 if a failure
342 */
343take(itm,arg)
344 int itm,arg;
345 {
346 register int i,limit;
347/* cursors(); */
348 if ((limit = 15+(c[LEVEL]>>1)) > 26) limit=26;
349 for (i=0; i<limit; i++)
350 if (iven[i]==0)
351 {
352 iven[i] = itm; ivenarg[i] = arg; limit=0;
353 switch(itm)
354 {
355 case OPROTRING: case ODAMRING: case OBELT: limit=1; break;
356 case ODEXRING: c[DEXTERITY] += ivenarg[i]+1; limit=1; break;
357 case OSTRRING: c[STREXTRA] += ivenarg[i]+1; limit=1; break;
358 case OCLEVERRING: c[INTELLIGENCE] += ivenarg[i]+1; limit=1; break;
359 case OHAMMER: c[DEXTERITY] += 10; c[STREXTRA]+=10;
360 c[INTELLIGENCE]-=10; limit=1; break;
361
362 case OORBOFDRAGON: c[SLAYING]++; break;
363 case OSPIRITSCARAB: c[NEGATESPIRIT]++; break;
364 case OCUBEofUNDEAD: c[CUBEofUNDEAD]++; break;
365 case ONOTHEFT: c[NOTHEFT]++; break;
366 case OSWORDofSLASHING: c[DEXTERITY] +=5; limit=1; break;
367 };
368 lprcat("\nYou pick up:"); srcount=0; show3(i);
369 if (limit) bottomline(); return(0);
370 }
371 lprcat("\nYou can't carry anything else"); return(1);
372 }
373
374/*
375 subroutine to drop an object returns 1 if something there already else 0
376 */
377drop_object(k)
378 int k;
379 {
380 int itm;
381 if ((k<0) || (k>25)) return(0);
382 itm = iven[k]; cursors();
383 if (itm==0) { lprintf("\nYou don't have item %c! ",k+'a'); return(1); }
384 if (item[playerx][playery])
385 { beep(); lprcat("\nThere's something here already"); return(1); }
386 if (playery==MAXY-1 && playerx==33) return(1); /* not in entrance */
387 item[playerx][playery] = itm;
388 iarg[playerx][playery] = ivenarg[k];
389 srcount=0; lprcat("\n You drop:"); show3(k); /* show what item you dropped*/
390 know[playerx][playery] = 0; iven[k]=0;
391 if (c[WIELD]==k) c[WIELD]= -1; if (c[WEAR]==k) c[WEAR] = -1;
392 if (c[SHIELD]==k) c[SHIELD]= -1;
393 adjustcvalues(itm,ivenarg[k]);
394 dropflag=1; /* say dropped an item so wont ask to pick it up right away */
395 return(0);
396 }
397
398/*
399 function to enchant armor player is currently wearing
400 */
401enchantarmor()
402 {
403 register int tmp;
404 if (c[WEAR]<0) { if (c[SHIELD] < 0)
405 { cursors(); beep(); lprcat("\nYou feel a sense of loss"); return; }
406 else { tmp=iven[c[SHIELD]]; if (tmp != OSCROLL) if (tmp != OPOTION) { ivenarg[c[SHIELD]]++; bottomline(); } } }
407 tmp = iven[c[WEAR]];
408 if (tmp!=OSCROLL) if (tmp!=OPOTION) { ivenarg[c[WEAR]]++; bottomline(); }
409 }
410
411/*
412 function to enchant a weapon presently being wielded
413 */
414enchweapon()
415 {
416 register int tmp;
417 if (c[WIELD]<0)
418 { cursors(); beep(); lprcat("\nYou feel a sense of loss"); return; }
419 tmp = iven[c[WIELD]];
420 if (tmp!=OSCROLL) if (tmp!=OPOTION)
421 { ivenarg[c[WIELD]]++;
422 if (tmp==OCLEVERRING) c[INTELLIGENCE]++; else
423 if (tmp==OSTRRING) c[STREXTRA]++; else
424 if (tmp==ODEXRING) c[DEXTERITY]++; bottomline(); }
425 }
426
427/*
428 routine to tell if player can carry one more thing
429 returns 1 if pockets are full, else 0
430 */
431pocketfull()
432 {
433 register int i,limit;
434 if ((limit = 15+(c[LEVEL]>>1)) > 26) limit=26;
435 for (i=0; i<limit; i++) if (iven[i]==0) return(0);
436 return(1);
437 }
438
439/*
440 function to return 1 if a monster is next to the player else returns 0
441 */
442nearbymonst()
443 {
444 register int tmp,tmp2;
445 for (tmp=playerx-1; tmp<playerx+2; tmp++)
446 for (tmp2=playery-1; tmp2<playery+2; tmp2++)
447 if (mitem[tmp][tmp2]) return(1); /* if monster nearby */
448 return(0);
449 }
450
451/*
452 function to steal an item from the players pockets
453 returns 1 if steals something else returns 0
454 */
455stealsomething()
456 {
457 register int i,j;
458 j=100;
459 while (1)
460 {
461 i=rund(26);
462 if (iven[i]) if (c[WEAR]!=i) if (c[WIELD]!=i) if (c[SHIELD]!=i)
463 {
464 srcount=0; show3(i);
465 adjustcvalues(iven[i],ivenarg[i]); iven[i]=0; return(1);
466 }
467 if (--j <= 0) return(0);
468 }
469 }
470
471/*
472 function to return 1 is player carrys nothing else return 0
473 */
474emptyhanded()
475 {
476 register int i;
477 for (i=0; i<26; i++)
478 if (iven[i]) if (i!=c[WIELD]) if (i!=c[WEAR]) if (i!=c[SHIELD]) return(0);
479 return(1);
480 }
481
482/*
483 function to create a gem on a square near the player
484 */
485creategem()
486 {
487 register int i,j;
488 switch(rnd(4))
489 {
490 case 1: i=ODIAMOND; j=50; break;
491 case 2: i=ORUBY; j=40; break;
492 case 3: i=OEMERALD; j=30; break;
493 default: i=OSAPPHIRE; j=20; break;
494 };
495 createitem(i,rnd(j)+j/10);
496 }
497
498/*
499 function to change character levels as needed when dropping an object
500 that affects these characteristics
501 */
502adjustcvalues(itm,arg)
503 int itm,arg;
504 {
505 register int flag;
506 flag=0;
507 switch(itm)
508 {
509 case ODEXRING: c[DEXTERITY] -= arg+1; flag=1; break;
510 case OSTRRING: c[STREXTRA] -= arg+1; flag=1; break;
511 case OCLEVERRING: c[INTELLIGENCE] -= arg+1; flag=1; break;
512 case OHAMMER: c[DEXTERITY] -= 10; c[STREXTRA] -= 10;
513 c[INTELLIGENCE] += 10; flag=1; break;
514 case OSWORDofSLASHING: c[DEXTERITY] -= 5; flag=1; break;
515 case OORBOFDRAGON: --c[SLAYING]; return;
516 case OSPIRITSCARAB: --c[NEGATESPIRIT]; return;
517 case OCUBEofUNDEAD: --c[CUBEofUNDEAD]; return;
518 case ONOTHEFT: --c[NOTHEFT]; return;
519 case OLANCE: c[LANCEDEATH]=0; return;
520 case OPOTION: case OSCROLL: return;
521
522 default: flag=1;
523 };
524 if (flag) bottomline();
525 }
526
527/*
528 function to read a string from token input "string"
529 returns a pointer to the string
530 */
531gettokstr(str)
532 register char *str;
533 {
534 register int i,j;
535 i=50;
536 while ((getchar() != '"') && (--i > 0));
537 i=36;
538 while (--i > 0)
539 {
540 if ((j=getchar()) != '"') *str++ = j; else i=0;
541 }
542 *str = 0;
543 i=50;
544 if (j != '"') while ((getchar() != '"') && (--i > 0)); /* if end due to too long, then find closing quote */
545 }
546
547/*
548 function to ask user for a password (no echo)
549 returns 1 if entered correctly, 0 if not
550 */
551static char gpwbuf[33];
552getpassword()
553 {
554 register int i,j;
555 register char *gpwp;
556 extern char *password;
557 scbr(); /* system("stty -echo cbreak"); */
558 gpwp = gpwbuf; lprcat("\nEnter Password: "); lflush();
559 i = strlen(password);
560 for (j=0; j<i; j++) read(0,gpwp++,1); gpwbuf[i]=0;
561 sncbr(); /* system("stty echo -cbreak"); */
562 if (strcmp(gpwbuf,password) != 0)
563 { lprcat("\nSorry\n"); lflush(); return(0); }
564 else return(1);
565 }
566
567/*
568 subroutine to get a yes or no response from the user
569 returns y or n
570 */
571getyn()
572 {
573 register int i;
574 i=0; while (i!='y' && i!='n' && i!='\33') i=getchar();
575 return(i);
576 }
577
578/*
579 function to calculate the pack weight of the player
580 returns the number of pounds the player is carrying
581 */
582packweight()
583 {
584 register int i,j,k;
585 k=c[GOLD]/1000; j=25; while ((iven[j]==0) && (j>0)) --j;
586 for (i=0; i<=j; i++)
587 switch(iven[i])
588 {
589 case 0: break;
590 case OSSPLATE: case OPLATEARMOR: k += 40; break;
591 case OPLATE: k += 35; break;
592 case OHAMMER: k += 30; break;
593 case OSPLINT: k += 26; break;
594 case OSWORDofSLASHING: case OCHAIN:
595 case OBATTLEAXE: case O2SWORD: k += 23; break;
596 case OLONGSWORD: case OSWORD:
597 case ORING: case OFLAIL: k += 20; break;
598 case OLANCE: case OSTUDLEATHER: k += 15; break;
599 case OLEATHER: case OSPEAR: k += 8; break;
600 case OORBOFDRAGON: case OBELT: k += 4; break;
601 case OSHIELD: k += 7; break;
602 case OCHEST: k += 30 + ivenarg[i]; break;
603 default: k++;
604 };
605 return(k);
606 }
607
608#ifndef MACRORND
609 /* macros to generate random numbers 1<=rnd(N)<=N 0<=rund(N)<=N-1 */
610rnd(x)
611 int x;
612 {
613 return((((randx=randx*1103515245+12345)>>7)%(x))+1);
614 }
615
616rund(x)
617 int x;
618 {
619 return((((randx=randx*1103515245+12345)>>7)%(x)) );
620 }
621#endif MACRORND