bsd-family-tree: Small sync with FreeBSD.
[dragonfly.git] / games / larn / global.c
blob7d579f634efa8e53831a08dcec380ed3554030f6
1 /* global.c Larn is copyrighted 1986 by Noah Morgan.
2 * $FreeBSD: src/games/larn/global.c,v 1.5 1999/11/16 02:57:21 billf Exp $
3 * $DragonFly: src/games/larn/global.c,v 1.5 2006/08/26 17:05:05 pavalos Exp $
5 * raiselevel() subroutine to raise the player one level
6 * loselevel() subroutine to lower the player by one level
7 * raiseexperience(x) subroutine to increase experience points
8 * loseexperience(x) subroutine to lose experience points
9 * losehp(x) subroutine to remove hit points from the player
10 * losemhp(x) subroutine to remove max # hit points from the player
11 * raisehp(x) subroutine to gain hit points
12 * raisemhp(x) subroutine to gain maximum hit points
13 * losemspells(x) subroutine to lose maximum spells
14 * raisemspells(x) subroutine to gain maximum spells
15 * makemonst(lev) function to return monster number for a randomly
16 * selected monster
17 * positionplayer() function to be sure player is not in a wall
18 * recalc() function to recalculate the armor class of the player
19 * quit() subroutine to ask if the player really wants to quit
23 #include "header.h"
24 extern int score[], dropflag;
25 extern char *what[], *who[];
26 extern char password[], winner[];
27 extern char sciv[SCORESIZE + 1][26][2];
30 raiselevel()
32 subroutine to raise the player one level
33 uses the skill[] array to find level boundarys
34 uses c[EXPERIENCE] c[LEVEL]
36 void
37 raiselevel(void)
39 if (c[LEVEL] < MAXPLEVEL)
40 raiseexperience((long)(skill[c[LEVEL]] - c[EXPERIENCE]));
44 loselevel()
46 subroutine to lower the players character level by one
48 void
49 loselevel(void)
51 if (c[LEVEL] > 1)
52 loseexperience((long)(c[EXPERIENCE] - skill[c[LEVEL] - 1] + 1));
56 raiseexperience(x)
58 subroutine to increase experience points
60 void
61 raiseexperience(long x)
63 int i, tmp;
64 i = c[LEVEL];
65 c[EXPERIENCE] += x;
66 while (c[EXPERIENCE] >= skill[c[LEVEL]] && (c[LEVEL] < MAXPLEVEL)) {
67 tmp = (c[CONSTITUTION] - c[HARDGAME]) >> 1;
68 c[LEVEL]++;
69 raisemhp((int)(rnd(3) + rnd((tmp > 0) ? tmp : 1)));
70 raisemspells((int)rund(3));
71 if (c[LEVEL] < 7 - c[HARDGAME])
72 raisemhp((int)(c[CONSTITUTION] >> 2));
74 if (c[LEVEL] != i) {
75 cursors();
76 beep();
77 lprintf("\nWelcome to level %d", (long)c[LEVEL]); /* if we changed levels */
79 bottomline();
83 loseexperience(x)
85 subroutine to lose experience points
87 void
88 loseexperience(long x)
90 int i, tmp;
91 i = c[LEVEL];
92 c[EXPERIENCE] -= x;
93 if (c[EXPERIENCE] < 0)
94 c[EXPERIENCE] = 0;
95 while (c[EXPERIENCE] < skill[c[LEVEL] - 1]) {
96 if (--c[LEVEL] <= 1) /* down one level */
97 c[LEVEL] = 1;
98 tmp = (c[CONSTITUTION] - c[HARDGAME]) >> 1; /* lose hpoints */
99 losemhp((int)rnd((tmp > 0) ? tmp : 1)); /* lose hpoints */
100 if (c[LEVEL] < 7 - c[HARDGAME])
101 losemhp((int)(c[CONSTITUTION] >> 2));
102 losemspells((int)rund(3)); /* lose spells */
104 if (i != c[LEVEL]) {
105 cursors();
106 beep();
107 lprintf("\nYou went down to level %d!", (long)c[LEVEL]);
109 bottomline();
113 losehp(x)
114 losemhp(x)
116 subroutine to remove hit points from the player
117 warning -- will kill player if hp goes to zero
119 void
120 losehp(int x)
122 if ((c[HP] -= x) <= 0) {
123 beep();
124 lprcat("\n");
125 nap(3000);
126 died(lastnum);
130 void
131 losemhp(int x)
133 c[HP] -= x;
134 if (c[HP] < 1)
135 c[HP] = 1;
136 c[HPMAX] -= x;
137 if (c[HPMAX] < 1)
138 c[HPMAX] = 1;
142 raisehp(x)
143 raisemhp(x)
145 subroutine to gain maximum hit points
147 void
148 raisehp(int x)
150 if ((c[HP] += x) > c[HPMAX])
151 c[HP] = c[HPMAX];
154 void
155 raisemhp(int x)
157 c[HPMAX] += x;
158 c[HP] += x;
162 raisemspells(x)
164 subroutine to gain maximum spells
166 void
167 raisemspells(int x)
169 c[SPELLMAX] += x;
170 c[SPELLS] += x;
174 losemspells(x)
176 subroutine to lose maximum spells
178 void
179 losemspells(int x)
181 if ((c[SPELLMAX] -= x) < 0)
182 c[SPELLMAX] = 0;
183 if ((c[SPELLS] -= x) < 0)
184 c[SPELLS] = 0;
188 makemonst(lev)
189 int lev;
191 function to return monster number for a randomly selected monster
192 for the given cave level
195 makemonst(int lev)
197 int tmp, x;
198 if (lev < 1)
199 lev = 1;
200 if (lev > 12)
201 lev = 12;
202 tmp = WATERLORD;
203 if (lev < 5)
204 while (tmp == WATERLORD)
205 tmp = rnd((x = monstlevel[lev - 1]) ? x : 1);
206 else
207 while (tmp == WATERLORD)
208 tmp = rnd((x = monstlevel[lev - 1] - monstlevel[lev - 4])
209 ? x : 1) + monstlevel[lev - 4];
211 while (tmp < MAXMONST && monster[tmp].genocided) /* genocided? */
212 tmp++;
213 return (tmp);
217 positionplayer()
219 function to be sure player is not in a wall
221 void
222 positionplayer(void)
224 int try;
225 try = 2;
226 while ((item[playerx][playery] || mitem[playerx][playery]) && (try))
227 if (++playerx >= MAXX - 1) {
228 playerx = 1;
229 if (++playery >= MAXY - 1) {
230 playery = 1;
231 --try;
234 if (try == 0)
235 lprcat("Failure in positionplayer\n");
239 recalc() function to recalculate the armor class of the player
241 void
242 recalc(void)
244 int i, j, k;
245 c[AC] = c[MOREDEFENSES];
246 if (c[WEAR] >= 0)
247 switch (iven[c[WEAR]]) {
248 case OSHIELD:
249 c[AC] += 2 + ivenarg[c[WEAR]];
250 break;
251 case OLEATHER:
252 c[AC] += 2 + ivenarg[c[WEAR]];
253 break;
254 case OSTUDLEATHER:
255 c[AC] += 3 + ivenarg[c[WEAR]];
256 break;
257 case ORING:
258 c[AC] += 5 + ivenarg[c[WEAR]];
259 break;
260 case OCHAIN:
261 c[AC] += 6 + ivenarg[c[WEAR]];
262 break;
263 case OSPLINT:
264 c[AC] += 7 + ivenarg[c[WEAR]];
265 break;
266 case OPLATE:
267 c[AC] += 9 + ivenarg[c[WEAR]];
268 break;
269 case OPLATEARMOR:
270 c[AC] += 10 + ivenarg[c[WEAR]];
271 break;
272 case OSSPLATE:
273 c[AC] += 12 + ivenarg[c[WEAR]];
274 break;
277 if (c[SHIELD] >= 0)
278 if (iven[c[SHIELD]] == OSHIELD)
279 c[AC] += 2 + ivenarg[c[SHIELD]];
280 if (c[WIELD] < 0)
281 c[WCLASS] = 0;
282 else {
283 i = ivenarg[c[WIELD]];
284 switch (iven[c[WIELD]]) {
285 case ODAGGER:
286 c[WCLASS] = 3 + i;
287 break;
288 case OBELT:
289 c[WCLASS] = 7 + i;
290 break;
291 case OSHIELD:
292 c[WCLASS] = 8 + i;
293 break;
294 case OSPEAR:
295 c[WCLASS] = 10 + i;
296 break;
297 case OFLAIL:
298 c[WCLASS] = 14 + i;
299 break;
300 case OBATTLEAXE:
301 c[WCLASS] = 17 + i;
302 break;
303 case OLANCE:
304 c[WCLASS] = 19 + i;
305 break;
306 case OLONGSWORD:
307 c[WCLASS] = 22 + i;
308 break;
309 case O2SWORD:
310 c[WCLASS] = 26 + i;
311 break;
312 case OSWORD:
313 c[WCLASS] = 32 + i;
314 break;
315 case OSWORDofSLASHING:
316 c[WCLASS] = 30 + i;
317 break;
318 case OHAMMER:
319 c[WCLASS] = 35 + i;
320 break;
321 default:
322 c[WCLASS] = 0;
325 c[WCLASS] += c[MOREDAM];
327 /* now for regeneration abilities based on rings */
328 c[REGEN] = 1;
329 c[ENERGY] = 0;
330 j = 0;
331 for (k = 25; k > 0; k--)
332 if (iven[k]) {
333 j = k;
334 k = 0;
336 for (i = 0; i <= j; i++) {
337 switch (iven[i]) {
338 case OPROTRING:
339 c[AC] += ivenarg[i] + 1;
340 break;
341 case ODAMRING:
342 c[WCLASS] += ivenarg[i] + 1;
343 break;
344 case OBELT:
345 c[WCLASS] += ((ivenarg[i] << 1)) + 2;
346 break;
348 case OREGENRING:
349 c[REGEN] += ivenarg[i] + 1;
350 break;
351 case ORINGOFEXTRA:
352 c[REGEN] += 5 * (ivenarg[i] + 1);
353 break;
354 case OENERGYRING:
355 c[ENERGY] += ivenarg[i] + 1;
356 break;
363 quit()
365 subroutine to ask if the player really wants to quit
367 void
368 quit(void)
370 int i;
371 cursors();
372 strcpy(lastmonst, "");
373 lprcat("\n\nDo you really want to quit?");
374 while (1) {
375 i = getchr();
376 if (i == 'y') {
377 died(300);
378 return;
380 if ((i == 'n') || (i == '\33')) {
381 lprcat(" no");
382 lflush();
383 return;
385 lprcat("\n");
386 setbold();
387 lprcat("Yes");
388 resetbold();
389 lprcat(" or ");
390 setbold();
391 lprcat("No");
392 resetbold();
393 lprcat(" please? Do you want to quit? ");
398 function to ask --more-- then the user must enter a space
400 void
401 more(void)
403 lprcat("\n --- press ");
404 standout("space");
405 lprcat(" to continue --- ");
406 while (getchr() != ' ')
407 ; /* nothing */
411 function to put something in the players inventory
412 returns 0 if success, 1 if a failure
415 take(int itm, int arg)
417 int i, limit;
418 if ((limit = 15 + (c[LEVEL] >> 1)) > 26)
419 limit = 26;
420 for (i = 0; i < limit; i++)
421 if (iven[i] == 0) {
422 iven[i] = itm;
423 ivenarg[i] = arg;
424 limit = 0;
425 switch (itm) {
426 case OPROTRING:
427 case ODAMRING:
428 case OBELT:
429 limit = 1;
430 break;
431 case ODEXRING:
432 c[DEXTERITY] += ivenarg[i] + 1;
433 limit = 1;
434 break;
435 case OSTRRING:
436 c[STREXTRA] += ivenarg[i] + 1;
437 limit = 1;
438 break;
439 case OCLEVERRING:
440 c[INTELLIGENCE] += ivenarg[i] + 1;
441 limit = 1;
442 break;
443 case OHAMMER:
444 c[DEXTERITY] += 10;
445 c[STREXTRA] += 10;
446 c[INTELLIGENCE] -= 10;
447 limit = 1;
448 break;
450 case OORBOFDRAGON:
451 c[SLAYING]++;
452 break;
453 case OSPIRITSCARAB:
454 c[NEGATESPIRIT]++;
455 break;
456 case OCUBEofUNDEAD:
457 c[CUBEofUNDEAD]++;
458 break;
459 case ONOTHEFT:
460 c[NOTHEFT]++;
461 break;
462 case OSWORDofSLASHING:
463 c[DEXTERITY] += 5;
464 limit = 1;
465 break;
467 lprcat("\nYou pick up:");
468 srcount = 0;
469 show3(i);
470 if (limit)
471 bottomline();
472 return (0);
474 lprcat("\nYou can't carry anything else");
475 return (1);
479 subroutine to drop an object
480 returns 1 if something there already else 0
483 drop_object(int k)
485 int itm;
486 if ((k < 0) || (k > 25))
487 return (0);
488 itm = iven[k];
489 cursors();
490 if (itm == 0) {
491 lprintf("\nYou don't have item %c! ", k + 'a');
492 return (1);
494 if (item[playerx][playery]) {
495 beep();
496 lprcat("\nThere's something here already");
497 return (1);
499 if (playery == MAXY - 1 && playerx == 33) /* not in entrance */
500 return (1);
501 item[playerx][playery] = itm;
502 iarg[playerx][playery] = ivenarg[k];
503 srcount = 0;
504 lprcat("\n You drop:");
505 show3(k); /* show what item you dropped*/
506 know[playerx][playery] = 0;
507 iven[k] = 0;
508 if (c[WIELD] == k)
509 c[WIELD] = -1;
510 if (c[WEAR] == k)
511 c[WEAR] = -1;
512 if (c[SHIELD] == k)
513 c[SHIELD] = -1;
514 adjustcvalues(itm, ivenarg[k]);
515 /* say dropped an item so wont ask to pick it up right away */
516 dropflag = 1;
517 return (0);
521 function to enchant armor player is currently wearing
523 void
524 enchantarmor(void)
526 int tmp;
527 if (c[WEAR] < 0) {
528 if (c[SHIELD] < 0) {
529 cursors();
530 beep();
531 lprcat("\nYou feel a sense of loss");
532 return;
533 } else {
534 tmp = iven[c[SHIELD]];
535 if (tmp != OSCROLL)
536 if (tmp != OPOTION) {
537 ivenarg[c[SHIELD]]++;
538 bottomline();
542 tmp = iven[c[WEAR]];
543 if (tmp != OSCROLL)
544 if (tmp != OPOTION) {
545 ivenarg[c[WEAR]]++;
546 bottomline();
551 function to enchant a weapon presently being wielded
553 void
554 enchweapon(void)
556 int tmp;
557 if (c[WIELD] < 0) {
558 cursors();
559 beep();
560 lprcat("\nYou feel a sense of loss");
561 return;
563 tmp = iven[c[WIELD]];
564 if (tmp != OSCROLL)
565 if (tmp != OPOTION) {
566 ivenarg[c[WIELD]]++;
567 if (tmp == OCLEVERRING)
568 c[INTELLIGENCE]++;
569 else if (tmp == OSTRRING)
570 c[STREXTRA]++;
571 else if (tmp == ODEXRING)
572 c[DEXTERITY]++;
573 bottomline();
578 routine to tell if player can carry one more thing
579 returns 1 if pockets are full, else 0
582 pocketfull(void)
584 int i, limit;
585 if ((limit = 15 + (c[LEVEL] >> 1)) > 26)
586 limit = 26;
587 for (i = 0; i < limit; i++)
588 if (iven[i] == 0)
589 return (0);
590 return (1);
594 function to return 1 if a monster is next to the player else returns 0
597 nearbymonst(void)
599 int tmp, tmp2;
600 for (tmp = playerx - 1; tmp < playerx + 2; tmp++)
601 for (tmp2 = playery - 1; tmp2 < playery + 2; tmp2++)
602 if (mitem[tmp][tmp2]) /* if monster nearby */
603 return (1);
604 return (0);
608 function to steal an item from the players pockets
609 returns 1 if steals something else returns 0
612 stealsomething(void)
614 int i, j;
615 j = 100;
616 while (1) {
617 i = rund(26);
618 if (iven[i])
619 if (c[WEAR] != i)
620 if (c[WIELD] != i)
621 if (c[SHIELD] != i) {
622 srcount = 0;
623 show3(i);
624 adjustcvalues(iven[i], ivenarg[i]);
625 iven[i] = 0;
626 return (1);
628 if (--j <= 0)
629 return (0);
634 function to return 1 is player carrys nothing else return 0
637 emptyhanded(void)
639 int i;
640 for (i = 0; i < 26; i++)
641 if (iven[i])
642 if (i != c[WIELD])
643 if (i != c[WEAR])
644 if (i != c[SHIELD])
645 return (0);
646 return (1);
650 function to create a gem on a square near the player
652 void
653 creategem(void)
655 int i, j;
656 switch (rnd(4)) {
657 case 1:
658 i = ODIAMOND;
659 j = 50;
660 break;
661 case 2:
662 i = ORUBY;
663 j = 40;
664 break;
665 case 3:
666 i = OEMERALD;
667 j = 30;
668 break;
669 default:
670 i = OSAPPHIRE;
671 j = 20;
672 break;
674 createitem(i, rnd(j) + j / 10);
678 function to change character levels as needed when dropping an object
679 that affects these characteristics
681 void
682 adjustcvalues(int itm, int arg)
684 int flag;
685 flag = 0;
686 switch (itm) {
687 case ODEXRING:
688 c[DEXTERITY] -= arg + 1;
689 flag = 1;
690 break;
691 case OSTRRING:
692 c[STREXTRA] -= arg + 1;
693 flag = 1;
694 break;
695 case OCLEVERRING:
696 c[INTELLIGENCE] -= arg + 1;
697 flag = 1;
698 break;
699 case OHAMMER:
700 c[DEXTERITY] -= 10;
701 c[STREXTRA] -= 10;
702 c[INTELLIGENCE] += 10;
703 flag = 1;
704 break;
705 case OSWORDofSLASHING:
706 c[DEXTERITY] -= 5;
707 flag = 1;
708 break;
709 case OORBOFDRAGON:
710 --c[SLAYING];
711 return;
712 case OSPIRITSCARAB:
713 --c[NEGATESPIRIT];
714 return;
715 case OCUBEofUNDEAD:
716 --c[CUBEofUNDEAD];
717 return;
718 case ONOTHEFT:
719 --c[NOTHEFT];
720 return;
721 case OLANCE:
722 c[LANCEDEATH] = 0;
723 return;
724 case OPOTION:
725 case OSCROLL:
726 return;
728 default:
729 flag = 1;
731 if (flag)
732 bottomline();
736 function to ask user for a password (no echo)
737 returns 1 if entered correctly, 0 if not
739 static char gpwbuf[33];
742 getpassword(void)
744 int i, j;
745 char *gpwp;
746 scbr();
747 gpwp = gpwbuf;
748 lprcat("\nEnter Password: ");
749 lflush();
750 i = strlen(password);
751 for (j = 0; j < i; j++)
752 read(0, gpwp++, 1);
753 gpwbuf[i] = 0;
754 sncbr();
755 if (strcmp(gpwbuf, password) != 0) {
756 lprcat("\nSorry\n");
757 lflush();
758 return (0);
759 } else
760 return (1);
764 subroutine to get a yes or no response from the user
765 returns y or n
768 getyn(void)
770 int i;
771 i = 0;
772 while (i != 'y' && i != 'n' && i != '\33')
773 i = getchr();
774 return (i);
778 function to calculate the pack weight of the player
779 returns the number of pounds the player is carrying
782 packweight(void)
784 int i, j, k;
785 k = c[GOLD] / 1000;
786 j = 25;
787 while ((iven[j] == 0) && (j > 0))
788 --j;
789 for (i = 0; i <= j; i++)
790 switch (iven[i]) {
791 case 0:
792 break;
793 case OSSPLATE:
794 case OPLATEARMOR:
795 k += 40;
796 break;
797 case OPLATE:
798 k += 35;
799 break;
800 case OHAMMER:
801 k += 30;
802 break;
803 case OSPLINT:
804 k += 26;
805 break;
806 case OSWORDofSLASHING:
807 case OCHAIN:
808 case OBATTLEAXE:
809 case O2SWORD:
810 k += 23;
811 break;
812 case OLONGSWORD:
813 case OSWORD:
814 case ORING:
815 case OFLAIL:
816 k += 20;
817 break;
818 case OLANCE:
819 case OSTUDLEATHER:
820 k += 15;
821 break;
822 case OLEATHER:
823 case OSPEAR:
824 k += 8;
825 break;
826 case OORBOFDRAGON:
827 case OBELT:
828 k += 4;
829 break;
830 case OSHIELD:
831 k += 7;
832 break;
833 case OCHEST:
834 k += 30 + ivenarg[i];
835 break;
836 default:
837 k++;
839 return (k);
842 #ifndef MACRORND
843 /* macros to generate random numbers 1<=rnd(N)<=N 0<=rund(N)<=N-1 */
845 rnd(int x)
847 return ((random() % x) + 1);
851 rund(int x)
853 return (random() % x);
855 #endif /* MACRORND */