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