Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / games / larn / global.c
blob706cffec1a48125e7c44544dd95e2608026a1b38
1 /* $NetBSD: global.c,v 1.11 2008/02/03 21:24:58 dholland Exp $ */
3 /*
4 * global.c Larn is copyrighted 1986 by Noah Morgan.
5 *
6 * raiselevel() subroutine to raise the player one level
7 * loselevel() subroutine to lower the player by one level
8 * raiseexperience(x) subroutine to increase experience points
9 * loseexperience(x) subroutine to lose experience points
10 * losehp(x) subroutine to remove hit points from the player
11 * losemhp(x) subroutine to remove max # hit points from the player
12 * raisehp(x) subroutine to gain hit points
13 * raisemhp(x) subroutine to gain maximum hit points
14 * losemspells(x) subroutine to lose maximum spells
15 * raisemspells(x) subroutine to gain maximum spells
16 * makemonst(lev) function to return monster number for a randomly
17 * selected monster
18 * positionplayer() function to be sure player is not in a wall
19 * recalc() function to recalculate the armor class of the player
20 * quit() subroutine to ask if the player really wants to quit
22 #include <sys/cdefs.h>
23 #ifndef lint
24 __RCSID("$NetBSD: global.c,v 1.11 2008/02/03 21:24:58 dholland Exp $");
25 #endif /* not lint */
27 #include <string.h>
28 #include <unistd.h>
29 #include "header.h"
30 #include "extern.h"
31 extern int score[], dropflag;
32 extern char *what[], *who[];
33 extern char winner[];
34 extern char sciv[SCORESIZE + 1][26][2];
35 extern char *password;
38 raiselevel()
40 subroutine to raise the player one level
41 uses the skill[] array to find level boundarys
42 uses c[EXPERIENCE] c[LEVEL]
44 void
45 raiselevel()
47 if (c[LEVEL] < MAXPLEVEL)
48 raiseexperience((long) (skill[c[LEVEL]] - c[EXPERIENCE]));
52 loselevel()
54 subroutine to lower the players character level by one
56 void
57 loselevel()
59 if (c[LEVEL] > 1)
60 loseexperience((long) (c[EXPERIENCE] - skill[c[LEVEL] - 1] + 1));
64 raiseexperience(x)
66 subroutine to increase experience points
68 void
69 raiseexperience(x)
70 long x;
72 int i, tmp;
73 i = c[LEVEL];
74 c[EXPERIENCE] += x;
75 while (c[EXPERIENCE] >= skill[c[LEVEL]] && (c[LEVEL] < MAXPLEVEL)) {
76 tmp = (c[CONSTITUTION] - c[HARDGAME]) >> 1;
77 c[LEVEL]++;
78 raisemhp((int) (rnd(3) + rnd((tmp > 0) ? tmp : 1)));
79 raisemspells((int) rund(3));
80 if (c[LEVEL] < 7 - c[HARDGAME])
81 raisemhp((int) (c[CONSTITUTION] >> 2));
83 if (c[LEVEL] != i) {
84 cursors();
85 beep();
86 lprintf("\nWelcome to level %ld", (long) c[LEVEL]); /* if we changed levels */
88 bottomline();
92 loseexperience(x)
94 subroutine to lose experience points
96 void
97 loseexperience(x)
98 long x;
100 int i, tmp;
101 i = c[LEVEL];
102 c[EXPERIENCE] -= x;
103 if (c[EXPERIENCE] < 0)
104 c[EXPERIENCE] = 0;
105 while (c[EXPERIENCE] < skill[c[LEVEL] - 1]) {
106 if (--c[LEVEL] <= 1)
107 c[LEVEL] = 1; /* down one level */
108 tmp = (c[CONSTITUTION] - c[HARDGAME]) >> 1; /* lose hpoints */
109 losemhp((int) rnd((tmp > 0) ? tmp : 1)); /* lose hpoints */
110 if (c[LEVEL] < 7 - c[HARDGAME])
111 losemhp((int) (c[CONSTITUTION] >> 2));
112 losemspells((int) rund(3)); /* lose spells */
114 if (i != c[LEVEL]) {
115 cursors();
116 beep();
117 lprintf("\nYou went down to level %ld!", (long) c[LEVEL]);
119 bottomline();
123 losehp(x)
124 losemhp(x)
126 subroutine to remove hit points from the player
127 warning -- will kill player if hp goes to zero
129 void
130 losehp(x)
131 int x;
133 if ((c[HP] -= x) <= 0) {
134 beep();
135 lprcat("\n");
136 nap(3000);
137 died(lastnum);
141 void
142 losemhp(x)
143 int x;
145 c[HP] -= x;
146 if (c[HP] < 1)
147 c[HP] = 1;
148 c[HPMAX] -= x;
149 if (c[HPMAX] < 1)
150 c[HPMAX] = 1;
154 raisehp(x)
155 raisemhp(x)
157 subroutine to gain maximum hit points
159 void
160 raisehp(x)
161 int x;
163 if ((c[HP] += x) > c[HPMAX])
164 c[HP] = c[HPMAX];
167 void
168 raisemhp(x)
169 int x;
171 c[HPMAX] += x;
172 c[HP] += x;
176 raisemspells(x)
178 subroutine to gain maximum spells
180 void
181 raisemspells(x)
182 int x;
184 c[SPELLMAX] += x;
185 c[SPELLS] += x;
189 losemspells(x)
191 subroutine to lose maximum spells
193 void
194 losemspells(x)
195 int x;
197 if ((c[SPELLMAX] -= x) < 0)
198 c[SPELLMAX] = 0;
199 if ((c[SPELLS] -= x) < 0)
200 c[SPELLS] = 0;
204 makemonst(lev)
205 int lev;
207 function to return monster number for a randomly selected monster
208 for the given cave level
211 makemonst(lev)
212 int lev;
214 int tmp, x;
215 if (lev < 1)
216 lev = 1;
217 if (lev > 12)
218 lev = 12;
219 tmp = WATERLORD;
220 if (lev < 5)
221 while (tmp == WATERLORD)
222 tmp = rnd((x = monstlevel[lev - 1]) ? x : 1);
223 else
224 while (tmp == WATERLORD)
225 tmp = rnd((x = monstlevel[lev - 1] - monstlevel[lev - 4]) ? x : 1) + monstlevel[lev - 4];
227 while (monster[tmp].genocided && tmp < MAXMONST)
228 tmp++; /* genocided? */
229 return (tmp);
233 positionplayer()
235 function to be sure player is not in a wall
237 void
238 positionplayer()
240 int try;
241 try = 2;
242 while ((item[playerx][playery] || mitem[playerx][playery]) && (try))
243 if (++playerx >= MAXX - 1) {
244 playerx = 1;
245 if (++playery >= MAXY - 1) {
246 playery = 1;
247 --try;
250 if (try == 0)
251 lprcat("Failure in positionplayer\n");
255 recalc() function to recalculate the armor class of the player
257 void
258 recalc()
260 int i, j, k;
261 c[AC] = c[MOREDEFENSES];
262 if (c[WEAR] >= 0)
263 switch (iven[c[WEAR]]) {
264 case OSHIELD:
265 c[AC] += 2 + ivenarg[c[WEAR]];
266 break;
267 case OLEATHER:
268 c[AC] += 2 + ivenarg[c[WEAR]];
269 break;
270 case OSTUDLEATHER:
271 c[AC] += 3 + ivenarg[c[WEAR]];
272 break;
273 case ORING:
274 c[AC] += 5 + ivenarg[c[WEAR]];
275 break;
276 case OCHAIN:
277 c[AC] += 6 + ivenarg[c[WEAR]];
278 break;
279 case OSPLINT:
280 c[AC] += 7 + ivenarg[c[WEAR]];
281 break;
282 case OPLATE:
283 c[AC] += 9 + ivenarg[c[WEAR]];
284 break;
285 case OPLATEARMOR:
286 c[AC] += 10 + ivenarg[c[WEAR]];
287 break;
288 case OSSPLATE:
289 c[AC] += 12 + ivenarg[c[WEAR]];
290 break;
293 if (c[SHIELD] >= 0)
294 if (iven[c[SHIELD]] == OSHIELD)
295 c[AC] += 2 + ivenarg[c[SHIELD]];
296 if (c[WIELD] < 0)
297 c[WCLASS] = 0;
298 else {
299 i = ivenarg[c[WIELD]];
300 switch (iven[c[WIELD]]) {
301 case ODAGGER:
302 c[WCLASS] = 3 + i;
303 break;
304 case OBELT:
305 c[WCLASS] = 7 + i;
306 break;
307 case OSHIELD:
308 c[WCLASS] = 8 + i;
309 break;
310 case OSPEAR:
311 c[WCLASS] = 10 + i;
312 break;
313 case OFLAIL:
314 c[WCLASS] = 14 + i;
315 break;
316 case OBATTLEAXE:
317 c[WCLASS] = 17 + i;
318 break;
319 case OLANCE:
320 c[WCLASS] = 19 + i;
321 break;
322 case OLONGSWORD:
323 c[WCLASS] = 22 + i;
324 break;
325 case O2SWORD:
326 c[WCLASS] = 26 + i;
327 break;
328 case OSWORD:
329 c[WCLASS] = 32 + i;
330 break;
331 case OSWORDofSLASHING:
332 c[WCLASS] = 30 + i;
333 break;
334 case OHAMMER:
335 c[WCLASS] = 35 + i;
336 break;
337 default:
338 c[WCLASS] = 0;
341 c[WCLASS] += c[MOREDAM];
343 /* now for regeneration abilities based on rings */
344 c[REGEN] = 1;
345 c[ENERGY] = 0;
346 j = 0;
347 for (k = 25; k > 0; k--)
348 if (iven[k]) {
349 j = k;
350 k = 0;
352 for (i = 0; i <= j; i++) {
353 switch (iven[i]) {
354 case OPROTRING:
355 c[AC] += ivenarg[i] + 1;
356 break;
357 case ODAMRING:
358 c[WCLASS] += ivenarg[i] + 1;
359 break;
360 case OBELT:
361 c[WCLASS] += ((ivenarg[i] << 1)) + 2;
362 break;
364 case OREGENRING:
365 c[REGEN] += ivenarg[i] + 1;
366 break;
367 case ORINGOFEXTRA:
368 c[REGEN] += 5 * (ivenarg[i] + 1);
369 break;
370 case OENERGYRING:
371 c[ENERGY] += ivenarg[i] + 1;
372 break;
379 quit()
381 subroutine to ask if the player really wants to quit
383 void
384 quit()
386 int i;
387 cursors();
388 strcpy(lastmonst, "");
389 lprcat("\n\nDo you really want to quit?");
390 while (1) {
391 i = ttgetch();
392 if (i == 'y') {
393 died(300);
394 return;
396 if ((i == 'n') || (i == '\33')) {
397 lprcat(" no");
398 lflush();
399 return;
401 lprcat("\n");
402 setbold();
403 lprcat("Yes");
404 resetbold();
405 lprcat(" or ");
406 setbold();
407 lprcat("No");
408 resetbold();
409 lprcat(" please? Do you want to quit? ");
414 function to ask --more-- then the user must enter a space
416 void
417 more()
419 lprcat("\n --- press ");
420 standout("space");
421 lprcat(" to continue --- ");
422 while (ttgetch() != ' ');
426 function to put something in the players inventory
427 returns 0 if success, 1 if a failure
430 take(int theitem, int arg)
432 int i, limit;
433 /* cursors(); */
434 if ((limit = 15 + (c[LEVEL] >> 1)) > 26)
435 limit = 26;
436 for (i = 0; i < limit; i++)
437 if (iven[i] == 0) {
438 iven[i] = theitem;
439 ivenarg[i] = arg;
440 limit = 0;
441 switch (theitem) {
442 case OPROTRING:
443 case ODAMRING:
444 case OBELT:
445 limit = 1;
446 break;
447 case ODEXRING:
448 c[DEXTERITY] += ivenarg[i] + 1;
449 limit = 1;
450 break;
451 case OSTRRING:
452 c[STREXTRA] += ivenarg[i] + 1;
453 limit = 1;
454 break;
455 case OCLEVERRING:
456 c[INTELLIGENCE] += ivenarg[i] + 1;
457 limit = 1;
458 break;
459 case OHAMMER:
460 c[DEXTERITY] += 10;
461 c[STREXTRA] += 10;
462 c[INTELLIGENCE] -= 10;
463 limit = 1;
464 break;
466 case OORBOFDRAGON:
467 c[SLAYING]++;
468 break;
469 case OSPIRITSCARAB:
470 c[NEGATESPIRIT]++;
471 break;
472 case OCUBEofUNDEAD:
473 c[CUBEofUNDEAD]++;
474 break;
475 case ONOTHEFT:
476 c[NOTHEFT]++;
477 break;
478 case OSWORDofSLASHING:
479 c[DEXTERITY] += 5;
480 limit = 1;
481 break;
483 lprcat("\nYou pick up:");
484 srcount = 0;
485 show3(i);
486 if (limit)
487 bottomline();
488 return (0);
490 lprcat("\nYou can't carry anything else");
491 return (1);
495 subroutine to drop an object
496 returns 1 if something there already else 0
499 drop_object(k)
500 int k;
502 int theitem;
503 if ((k < 0) || (k > 25))
504 return (0);
505 theitem = iven[k];
506 cursors();
507 if (theitem == 0) {
508 lprintf("\nYou don't have item %c! ", k + 'a');
509 return (1);
511 if (item[playerx][playery]) {
512 beep();
513 lprcat("\nThere's something here already");
514 return (1);
516 if (playery == MAXY - 1 && playerx == 33)
517 return (1); /* not in entrance */
518 item[playerx][playery] = theitem;
519 iarg[playerx][playery] = ivenarg[k];
520 srcount = 0;
521 lprcat("\n You drop:");
522 show3(k); /* show what item you dropped */
523 know[playerx][playery] = 0;
524 iven[k] = 0;
525 if (c[WIELD] == k)
526 c[WIELD] = -1;
527 if (c[WEAR] == k)
528 c[WEAR] = -1;
529 if (c[SHIELD] == k)
530 c[SHIELD] = -1;
531 adjustcvalues(theitem, ivenarg[k]);
532 dropflag = 1; /* say dropped an item so wont ask to pick it
533 * up right away */
534 return (0);
538 function to enchant armor player is currently wearing
540 void
541 enchantarmor()
543 int tmp;
544 if (c[WEAR] < 0) {
545 if (c[SHIELD] < 0) {
546 cursors();
547 beep();
548 lprcat("\nYou feel a sense of loss");
549 return;
550 } else {
551 tmp = iven[c[SHIELD]];
552 if (tmp != OSCROLL)
553 if (tmp != OPOTION) {
554 ivenarg[c[SHIELD]]++;
555 bottomline();
559 tmp = iven[c[WEAR]];
560 if (tmp != OSCROLL)
561 if (tmp != OPOTION) {
562 ivenarg[c[WEAR]]++;
563 bottomline();
568 function to enchant a weapon presently being wielded
570 void
571 enchweapon()
573 int tmp;
574 if (c[WIELD] < 0) {
575 cursors();
576 beep();
577 lprcat("\nYou feel a sense of loss");
578 return;
580 tmp = iven[c[WIELD]];
581 if (tmp != OSCROLL)
582 if (tmp != OPOTION) {
583 ivenarg[c[WIELD]]++;
584 if (tmp == OCLEVERRING)
585 c[INTELLIGENCE]++;
586 else if (tmp == OSTRRING)
587 c[STREXTRA]++;
588 else if (tmp == ODEXRING)
589 c[DEXTERITY]++;
590 bottomline();
595 routine to tell if player can carry one more thing
596 returns 1 if pockets are full, else 0
599 pocketfull()
601 int i, limit;
602 if ((limit = 15 + (c[LEVEL] >> 1)) > 26)
603 limit = 26;
604 for (i = 0; i < limit; i++)
605 if (iven[i] == 0)
606 return (0);
607 return (1);
611 function to return 1 if a monster is next to the player else returns 0
614 nearbymonst()
616 int tmp, tmp2;
617 for (tmp = playerx - 1; tmp < playerx + 2; tmp++)
618 for (tmp2 = playery - 1; tmp2 < playery + 2; tmp2++)
619 if (mitem[tmp][tmp2])
620 return (1); /* if monster nearby */
621 return (0);
625 function to steal an item from the players pockets
626 returns 1 if steals something else returns 0
629 stealsomething()
631 int i, j;
632 j = 100;
633 while (1) {
634 i = rund(26);
635 if (iven[i])
636 if (c[WEAR] != i)
637 if (c[WIELD] != i)
638 if (c[SHIELD] != i) {
639 srcount = 0;
640 show3(i);
641 adjustcvalues(iven[i], ivenarg[i]);
642 iven[i] = 0;
643 return (1);
645 if (--j <= 0)
646 return (0);
651 function to return 1 is player carrys nothing else return 0
654 emptyhanded()
656 int i;
657 for (i = 0; i < 26; i++)
658 if (iven[i])
659 if (i != c[WIELD])
660 if (i != c[WEAR])
661 if (i != c[SHIELD])
662 return (0);
663 return (1);
667 function to create a gem on a square near the player
669 void
670 creategem()
672 int i, j;
673 switch (rnd(4)) {
674 case 1:
675 i = ODIAMOND;
676 j = 50;
677 break;
678 case 2:
679 i = ORUBY;
680 j = 40;
681 break;
682 case 3:
683 i = OEMERALD;
684 j = 30;
685 break;
686 default:
687 i = OSAPPHIRE;
688 j = 20;
689 break;
691 createitem(i, rnd(j) + j / 10);
695 function to change character levels as needed when dropping an object
696 that affects these characteristics
698 void
699 adjustcvalues(int theitem, int arg)
701 int flag;
702 flag = 0;
703 switch (theitem) {
704 case ODEXRING:
705 c[DEXTERITY] -= arg + 1;
706 flag = 1;
707 break;
708 case OSTRRING:
709 c[STREXTRA] -= arg + 1;
710 flag = 1;
711 break;
712 case OCLEVERRING:
713 c[INTELLIGENCE] -= arg + 1;
714 flag = 1;
715 break;
716 case OHAMMER:
717 c[DEXTERITY] -= 10;
718 c[STREXTRA] -= 10;
719 c[INTELLIGENCE] += 10;
720 flag = 1;
721 break;
722 case OSWORDofSLASHING:
723 c[DEXTERITY] -= 5;
724 flag = 1;
725 break;
726 case OORBOFDRAGON:
727 --c[SLAYING];
728 return;
729 case OSPIRITSCARAB:
730 --c[NEGATESPIRIT];
731 return;
732 case OCUBEofUNDEAD:
733 --c[CUBEofUNDEAD];
734 return;
735 case ONOTHEFT:
736 --c[NOTHEFT];
737 return;
738 case OLANCE:
739 c[LANCEDEATH] = 0;
740 return;
741 case OPOTION:
742 case OSCROLL:
743 return;
745 default:
746 flag = 1;
748 if (flag)
749 bottomline();
753 function to ask user for a password (no echo)
754 returns 1 if entered correctly, 0 if not
756 static char gpwbuf[33];
758 getpassword()
760 int i, j;
761 char *gpwp;
762 scbr(); /* system("stty -echo cbreak"); */
763 gpwp = gpwbuf;
764 lprcat("\nEnter Password: ");
765 lflush();
766 i = strlen(password);
767 for (j = 0; j < i; j++)
768 *gpwp++ = ttgetch();
769 gpwbuf[i] = 0;
770 sncbr(); /* system("stty echo -cbreak"); */
771 if (strcmp(gpwbuf, password) != 0) {
772 lprcat("\nSorry\n");
773 lflush();
774 return (0);
775 } else
776 return (1);
780 subroutine to get a yes or no response from the user
781 returns y or n
784 getyn()
786 int i;
787 i = 0;
788 while (i != 'y' && i != 'n' && i != '\33')
789 i = ttgetch();
790 return (i);
794 function to calculate the pack weight of the player
795 returns the number of pounds the player is carrying
798 packweight()
800 int i, j, k;
801 k = c[GOLD] / 1000;
802 j = 25;
803 while ((iven[j] == 0) && (j > 0))
804 --j;
805 for (i = 0; i <= j; i++)
806 switch (iven[i]) {
807 case 0:
808 break;
809 case OSSPLATE:
810 case OPLATEARMOR:
811 k += 40;
812 break;
813 case OPLATE:
814 k += 35;
815 break;
816 case OHAMMER:
817 k += 30;
818 break;
819 case OSPLINT:
820 k += 26;
821 break;
822 case OSWORDofSLASHING:
823 case OCHAIN:
824 case OBATTLEAXE:
825 case O2SWORD:
826 k += 23;
827 break;
828 case OLONGSWORD:
829 case OSWORD:
830 case ORING:
831 case OFLAIL:
832 k += 20;
833 break;
834 case OLANCE:
835 case OSTUDLEATHER:
836 k += 15;
837 break;
838 case OLEATHER:
839 case OSPEAR:
840 k += 8;
841 break;
842 case OORBOFDRAGON:
843 case OBELT:
844 k += 4;
845 break;
846 case OSHIELD:
847 k += 7;
848 break;
849 case OCHEST:
850 k += 30 + ivenarg[i];
851 break;
852 default:
853 k++;
855 return (k);
858 #ifndef MACRORND
859 /* macros to generate random numbers 1<=rnd(N)<=N 0<=rund(N)<=N-1 */
861 rnd(x)
862 int x;
864 return ((((randx = randx * 1103515245 + 12345) >> 7) % (x)) + 1);
868 rund(x)
869 int x;
871 return ((((randx = randx * 1103515245 + 12345) >> 7) % (x)));
873 #endif /* MACRORND */