am-utils: Convert info page to "man 7 am-utils"
[dragonfly.git] / games / larn / global.c
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 $
4  *
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
20  *
21  */
22
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];
28
29 /*
30         raiselevel()
31
32         subroutine to raise the player one level
33         uses the skill[] array to find level boundarys
34         uses c[EXPERIENCE]  c[LEVEL]
35  */
36 void
37 raiselevel(void)
38 {
39         if (c[LEVEL] < MAXPLEVEL)
40                 raiseexperience((long)(skill[c[LEVEL]] - c[EXPERIENCE]));
41 }
42
43 /*
44     loselevel()
45
46         subroutine to lower the players character level by one
47  */
48 void
49 loselevel(void)
50 {
51         if (c[LEVEL] > 1)
52                 loseexperience((long)(c[EXPERIENCE] - skill[c[LEVEL] - 1] + 1));
53 }
54
55 /*
56         raiseexperience(x)
57
58         subroutine to increase experience points
59  */
60 void
61 raiseexperience(long x)
62 {
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));
73         }
74         if (c[LEVEL] != i) {
75                 cursors();
76                 beep();
77                 lprintf("\nWelcome to level %d", (long)c[LEVEL]);       /* if we changed levels */
78         }
79         bottomline();
80 }
81
82 /*
83         loseexperience(x)
84
85         subroutine to lose experience points
86  */
87 void
88 loseexperience(long x)
89 {
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 */
103         }
104         if (i != c[LEVEL]) {
105                 cursors();
106                 beep();
107                 lprintf("\nYou went down to level %d!", (long)c[LEVEL]);
108         }
109         bottomline();
110 }
111
112 /*
113         losehp(x)
114         losemhp(x)
115
116         subroutine to remove hit points from the player
117         warning -- will kill player if hp goes to zero
118  */
119 void
120 losehp(int x)
121 {
122         if ((c[HP] -= x) <= 0) {
123                 beep();
124                 lprcat("\n");
125                 nap(3000);
126                 died(lastnum);
127         }
128 }
129
130 void
131 losemhp(int x)
132 {
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;
139 }
140
141 /*
142         raisehp(x)
143         raisemhp(x)
144
145         subroutine to gain maximum hit points
146  */
147 void
148 raisehp(int x)
149 {
150         if ((c[HP] += x) > c[HPMAX])
151                 c[HP] = c[HPMAX];
152 }
153
154 void
155 raisemhp(int x)
156 {
157         c[HPMAX] += x;
158         c[HP] += x;
159 }
160
161 /*
162         raisemspells(x)
163
164         subroutine to gain maximum spells
165  */
166 void
167 raisemspells(int x)
168 {
169         c[SPELLMAX] += x;
170         c[SPELLS] += x;
171 }
172
173 /*
174         losemspells(x)
175
176         subroutine to lose maximum spells
177  */
178 void
179 losemspells(int x)
180 {
181         if ((c[SPELLMAX] -= x) < 0)
182                 c[SPELLMAX] = 0;
183         if ((c[SPELLS] -= x) < 0)
184                 c[SPELLS] = 0;
185 }
186
187 /*
188         makemonst(lev)
189                 int lev;
190
191         function to return monster number for a randomly selected monster
192                 for the given cave level
193  */
194 int
195 makemonst(int lev)
196 {
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];
210
211         while (monster[tmp].genocided && tmp < MAXMONST)        /* genocided? */
212                 tmp++;
213         return (tmp);
214 }
215
216 /*
217         positionplayer()
218
219         function to be sure player is not in a wall
220  */
221 void
222 positionplayer(void)
223 {
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;
232                         }
233                 }
234         if (try == 0)
235                 lprcat("Failure in positionplayer\n");
236 }
237
238 /*
239         recalc()        function to recalculate the armor class of the player
240  */
241 void
242 recalc(void)
243 {
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;
275                 }
276
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;
323                 }
324         }
325         c[WCLASS] += c[MOREDAM];
326
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;
335                 }
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;
347
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;
357                 }
358         }
359 }
360
361
362 /*
363         quit()
364
365         subroutine to ask if the player really wants to quit
366  */
367 void
368 quit(void)
369 {
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;
379                 }
380                 if ((i == 'n') || (i == '\33')) {
381                         lprcat(" no");
382                         lflush();
383                         return;
384                 }
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? ");
394         }
395 }
396
397 /*
398         function to ask --more-- then the user must enter a space
399  */
400 void
401 more(void)
402 {
403         lprcat("\n  --- press ");
404         standout("space");
405         lprcat(" to continue --- ");
406         while (getchr() != ' ')
407                 ; /* nothing */
408 }
409
410 /*
411         function to put something in the players inventory
412         returns 0 if success, 1 if a failure
413  */
414 int
415 take(int itm, int arg)
416 {
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;
449
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;
466                         }
467                         lprcat("\nYou pick up:");
468                         srcount = 0;
469                         show3(i);
470                         if (limit)
471                                 bottomline();
472                         return (0);
473                 }
474         lprcat("\nYou can't carry anything else");
475         return (1);
476 }
477
478 /*
479         subroutine to drop an object
480         returns 1 if something there already else 0
481  */
482 int
483 drop_object(int k)
484 {
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);
493         }
494         if (item[playerx][playery]) {
495                 beep();
496                 lprcat("\nThere's something here already");
497                 return (1);
498         }
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);
518 }
519
520 /*
521         function to enchant armor player is currently wearing
522  */
523 void
524 enchantarmor(void)
525 {
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();
539                                 }
540                 }
541         }
542         tmp = iven[c[WEAR]];
543         if (tmp != OSCROLL)
544                 if (tmp != OPOTION) {
545                         ivenarg[c[WEAR]]++;
546                         bottomline();
547                 }
548 }
549
550 /*
551         function to enchant a weapon presently being wielded
552  */
553 void
554 enchweapon(void)
555 {
556         int tmp;
557         if (c[WIELD] < 0) {
558                 cursors();
559                 beep();
560                 lprcat("\nYou feel a sense of loss");
561                 return;
562         }
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();
574                 }
575 }
576
577 /*
578         routine to tell if player can carry one more thing
579         returns 1 if pockets are full, else 0
580  */
581 int
582 pocketfull(void)
583 {
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);
591 }
592
593 /*
594         function to return 1 if a monster is next to the player else returns 0
595  */
596 int
597 nearbymonst(void)
598 {
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);
605 }
606
607 /*
608         function to steal an item from the players pockets
609         returns 1 if steals something else returns 0
610  */
611 int
612 stealsomething(void)
613 {
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);
627                                         }
628                 if (--j <= 0)
629                         return (0);
630         }
631 }
632
633 /*
634         function to return 1 is player carrys nothing else return 0
635  */
636 int
637 emptyhanded(void)
638 {
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);
647 }
648
649 /*
650         function to create a gem on a square near the player
651  */
652 void
653 creategem(void)
654 {
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;
673         }
674         createitem(i, rnd(j) + j / 10);
675 }
676
677 /*
678         function to change character levels as needed when dropping an object
679         that affects these characteristics
680  */
681 void
682 adjustcvalues(int itm, int arg)
683 {
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;
727
728         default:
729                 flag = 1;
730         }
731         if (flag)
732                 bottomline();
733 }
734
735 /*
736         function to ask user for a password (no echo)
737         returns 1 if entered correctly, 0 if not
738  */
739 static char gpwbuf[33];
740
741 int
742 getpassword(void)
743 {
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);
761 }
762
763 /*
764         subroutine to get a yes or no response from the user
765         returns y or n
766  */
767 int
768 getyn(void)
769 {
770         int i;
771         i = 0;
772         while (i != 'y' && i != 'n' && i != '\33')
773                 i = getchr();
774         return (i);
775 }
776
777 /*
778         function to calculate the pack weight of the player
779         returns the number of pounds the player is carrying
780  */
781 int
782 packweight(void)
783 {
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++;
838                 }
839         return (k);
840 }
841
842 #ifndef MACRORND
843 /* macros to generate random numbers   1<=rnd(N)<=N   0<=rund(N)<=N-1 */
844 int
845 rnd(int x)
846 {
847         return ((random() % x) + 1);
848 }
849
850 int
851 rund(int x)
852 {
853         return (random() % x);
854 }
855 #endif /* MACRORND */