MFC: Make apps using '#define _POSIX_C_SOURCE' compile.
[dragonfly.git] / games / larn / global.c
blobffbd0a2a74da0ab588ae9f601acfa1fd21dab042
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 * 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
22 #include "header.h"
23 extern int score[],dropflag;
24 extern char *what[],*who[];
25 extern char password[],winner[];
26 extern char sciv[SCORESIZE+1][26][2];
29 ***********
30 RAISE LEVEL
31 ***********
32 raiselevel()
34 subroutine to raise the player one level
35 uses the skill[] array to find level boundarys
36 uses c[EXPERIENCE] c[LEVEL]
38 void
39 raiselevel(void)
41 if (c[LEVEL] < MAXPLEVEL) raiseexperience((long)(skill[c[LEVEL]]-c[EXPERIENCE]));
45 ***********
46 LOOSE LEVEL
47 ***********
48 loselevel()
50 subroutine to lower the players character level by one
52 void
53 loselevel(void)
55 if (c[LEVEL] > 1) loseexperience((long)(c[EXPERIENCE] - skill[c[LEVEL]-1] + 1));
59 ****************
60 RAISE EXPERIENCE
61 ****************
62 raiseexperience(x)
64 subroutine to increase experience points
66 void
67 raiseexperience(long x)
69 int i,tmp;
70 i=c[LEVEL]; c[EXPERIENCE]+=x;
71 while (c[EXPERIENCE] >= skill[c[LEVEL]] && (c[LEVEL] < MAXPLEVEL))
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));
78 if (c[LEVEL] != i)
80 cursors();
81 beep(); lprintf("\nWelcome to level %d",(long)c[LEVEL]); /* if we changed levels */
83 bottomline();
87 ****************
88 LOOSE EXPERIENCE
89 ****************
90 loseexperience(x)
92 subroutine to lose experience points
94 void
95 loseexperience(long x)
97 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])
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 */
108 if (i!=c[LEVEL])
110 cursors();
111 beep(); lprintf("\nYou went down to level %d!",(long)c[LEVEL]);
113 bottomline();
117 ********
118 LOOSE HP
119 ********
120 losehp(x)
121 losemhp(x)
123 subroutine to remove hit points from the player
124 warning -- will kill player if hp goes to zero
126 void
127 losehp(int x)
129 if ((c[HP] -= x) <= 0)
131 beep(); lprcat("\n"); nap(3000); died(lastnum);
135 void
136 losemhp(int x)
138 c[HP] -= x; if (c[HP] < 1) c[HP]=1;
139 c[HPMAX] -= x; if (c[HPMAX] < 1) c[HPMAX]=1;
143 ********
144 RAISE HP
145 ********
146 raisehp(x)
147 raisemhp(x)
149 subroutine to gain maximum hit points
151 void
152 raisehp(int x)
154 if ((c[HP] += x) > c[HPMAX]) c[HP] = c[HPMAX];
157 void
158 raisemhp(int x)
160 c[HPMAX] += x; c[HP] += x;
164 ************
165 RAISE SPELLS
166 ************
167 raisemspells(x)
169 subroutine to gain maximum spells
171 void
172 raisemspells(int x)
174 c[SPELLMAX]+=x; c[SPELLS]+=x;
178 ************
179 LOOSE SPELLS
180 ************
181 losemspells(x)
183 subroutine to lose maximum spells
185 void
186 losemspells(int x)
188 if ((c[SPELLMAX] -= x) < 0) c[SPELLMAX]=0;
189 if ((c[SPELLS] -= x) < 0) c[SPELLS]=0;
193 makemonst(lev)
194 int lev;
196 function to return monster number for a randomly selected monster
197 for the given cave level
200 makemonst(int lev)
202 int tmp,x;
203 if (lev < 1) lev = 1; if (lev > 12) lev = 12;
204 tmp=WATERLORD;
205 if (lev < 5)
206 while (tmp==WATERLORD) tmp=rnd((x=monstlevel[lev-1])?x:1);
207 else while (tmp==WATERLORD)
208 tmp=rnd((x=monstlevel[lev-1]-monstlevel[lev-4])?x:1)+monstlevel[lev-4];
210 while (monster[tmp].genocided && tmp<MAXMONST) tmp++; /* genocided? */
211 return(tmp);
215 positionplayer()
217 function to be sure player is not in a wall
219 void
220 positionplayer(void)
222 int try;
223 try = 2;
224 while ((item[playerx][playery] || mitem[playerx][playery]) && (try))
225 if (++playerx >= MAXX-1)
227 playerx = 1;
228 if (++playery >= MAXY-1)
229 { playery = 1; --try; }
231 if (try==0) lprcat("Failure in positionplayer\n");
235 recalc() function to recalculate the armor class of the player
237 void
238 recalc(void)
240 int i,j,k;
241 c[AC] = c[MOREDEFENSES];
242 if (c[WEAR] >= 0)
243 switch(iven[c[WEAR]])
245 case OSHIELD: c[AC] += 2 + ivenarg[c[WEAR]]; break;
246 case OLEATHER: c[AC] += 2 + ivenarg[c[WEAR]]; break;
247 case OSTUDLEATHER: c[AC] += 3 + ivenarg[c[WEAR]]; break;
248 case ORING: c[AC] += 5 + ivenarg[c[WEAR]]; break;
249 case OCHAIN: c[AC] += 6 + ivenarg[c[WEAR]]; break;
250 case OSPLINT: c[AC] += 7 + ivenarg[c[WEAR]]; break;
251 case OPLATE: c[AC] += 9 + ivenarg[c[WEAR]]; break;
252 case OPLATEARMOR: c[AC] += 10 + ivenarg[c[WEAR]]; break;
253 case OSSPLATE: c[AC] += 12 + ivenarg[c[WEAR]]; break;
256 if (c[SHIELD] >= 0) if (iven[c[SHIELD]] == OSHIELD) c[AC] += 2 + ivenarg[c[SHIELD]];
257 if (c[WIELD] < 0) c[WCLASS] = 0; else
259 i = ivenarg[c[WIELD]];
260 switch(iven[c[WIELD]])
262 case ODAGGER: c[WCLASS] = 3 + i; break;
263 case OBELT: c[WCLASS] = 7 + i; break;
264 case OSHIELD: c[WCLASS] = 8 + i; break;
265 case OSPEAR: c[WCLASS] = 10 + i; break;
266 case OFLAIL: c[WCLASS] = 14 + i; break;
267 case OBATTLEAXE: c[WCLASS] = 17 + i; break;
268 case OLANCE: c[WCLASS] = 19 + i; break;
269 case OLONGSWORD: c[WCLASS] = 22 + i; break;
270 case O2SWORD: c[WCLASS] = 26 + i; break;
271 case OSWORD: c[WCLASS] = 32 + i; break;
272 case OSWORDofSLASHING: c[WCLASS] = 30 + i; break;
273 case OHAMMER: c[WCLASS] = 35 + i; break;
274 default: c[WCLASS] = 0;
277 c[WCLASS] += c[MOREDAM];
279 /* now for regeneration abilities based on rings */
280 c[REGEN]=1; c[ENERGY]=0;
281 j=0; for (k=25; k>0; k--) if (iven[k]) {j=k; k=0; }
282 for (i=0; i<=j; i++)
284 switch(iven[i])
286 case OPROTRING: c[AC] += ivenarg[i] + 1; break;
287 case ODAMRING: c[WCLASS] += ivenarg[i] + 1; break;
288 case OBELT: c[WCLASS] += ((ivenarg[i]<<1)) + 2; break;
290 case OREGENRING: c[REGEN] += ivenarg[i] + 1; break;
291 case ORINGOFEXTRA: c[REGEN] += 5 * (ivenarg[i]+1); break;
292 case OENERGYRING: c[ENERGY] += ivenarg[i] + 1; break;
299 quit()
301 subroutine to ask if the player really wants to quit
303 void
304 quit(void)
306 int i;
307 cursors(); strcpy(lastmonst,"");
308 lprcat("\n\nDo you really want to quit?");
309 while (1)
311 i=getchr();
312 if (i == 'y') { died(300); return; }
313 if ((i == 'n') || (i == '\33')) { lprcat(" no"); lflush(); return; }
314 lprcat("\n"); setbold(); lprcat("Yes"); resetbold(); lprcat(" or ");
315 setbold(); lprcat("No"); resetbold(); lprcat(" please? Do you want to quit? ");
320 function to ask --more-- then the user must enter a space
322 void
323 more(void)
325 lprcat("\n --- press "); standout("space"); lprcat(" to continue --- ");
326 while (getchr() != ' ');
330 function to put something in the players inventory
331 returns 0 if success, 1 if a failure
334 take(int itm, int arg)
336 int i,limit;
337 if ((limit = 15+(c[LEVEL]>>1)) > 26) limit=26;
338 for (i=0; i<limit; i++)
339 if (iven[i]==0)
341 iven[i] = itm; ivenarg[i] = arg; limit=0;
342 switch(itm)
344 case OPROTRING: case ODAMRING: case OBELT: limit=1; break;
345 case ODEXRING: c[DEXTERITY] += ivenarg[i]+1; limit=1; break;
346 case OSTRRING: c[STREXTRA] += ivenarg[i]+1; limit=1; break;
347 case OCLEVERRING: c[INTELLIGENCE] += ivenarg[i]+1; limit=1; break;
348 case OHAMMER: c[DEXTERITY] += 10; c[STREXTRA]+=10;
349 c[INTELLIGENCE]-=10; limit=1; break;
351 case OORBOFDRAGON: c[SLAYING]++; break;
352 case OSPIRITSCARAB: c[NEGATESPIRIT]++; break;
353 case OCUBEofUNDEAD: c[CUBEofUNDEAD]++; break;
354 case ONOTHEFT: c[NOTHEFT]++; break;
355 case OSWORDofSLASHING: c[DEXTERITY] +=5; limit=1; break;
357 lprcat("\nYou pick up:"); srcount=0; show3(i);
358 if (limit) bottomline(); return(0);
360 lprcat("\nYou can't carry anything else"); return(1);
364 subroutine to drop an object returns 1 if something there already else 0
367 drop_object(int k)
369 int itm;
370 if ((k<0) || (k>25)) return(0);
371 itm = iven[k]; cursors();
372 if (itm==0) { lprintf("\nYou don't have item %c! ",k+'a'); return(1); }
373 if (item[playerx][playery])
374 { beep(); lprcat("\nThere's something here already"); return(1); }
375 if (playery==MAXY-1 && playerx==33) return(1); /* not in entrance */
376 item[playerx][playery] = itm;
377 iarg[playerx][playery] = ivenarg[k];
378 srcount=0; lprcat("\n You drop:"); show3(k); /* show what item you dropped*/
379 know[playerx][playery] = 0; iven[k]=0;
380 if (c[WIELD]==k) c[WIELD]= -1; if (c[WEAR]==k) c[WEAR] = -1;
381 if (c[SHIELD]==k) c[SHIELD]= -1;
382 adjustcvalues(itm,ivenarg[k]);
383 dropflag=1; /* say dropped an item so wont ask to pick it up right away */
384 return(0);
388 function to enchant armor player is currently wearing
390 void
391 enchantarmor(void)
393 int tmp;
394 if (c[WEAR]<0) { if (c[SHIELD] < 0)
395 { cursors(); beep(); lprcat("\nYou feel a sense of loss"); return; }
396 else { tmp=iven[c[SHIELD]]; if (tmp != OSCROLL) if (tmp != OPOTION) { ivenarg[c[SHIELD]]++; bottomline(); } } }
397 tmp = iven[c[WEAR]];
398 if (tmp!=OSCROLL) if (tmp!=OPOTION) { ivenarg[c[WEAR]]++; bottomline(); }
402 function to enchant a weapon presently being wielded
404 void
405 enchweapon(void)
407 int tmp;
408 if (c[WIELD]<0)
409 { cursors(); beep(); lprcat("\nYou feel a sense of loss"); return; }
410 tmp = iven[c[WIELD]];
411 if (tmp!=OSCROLL) if (tmp!=OPOTION)
412 { ivenarg[c[WIELD]]++;
413 if (tmp==OCLEVERRING) c[INTELLIGENCE]++; else
414 if (tmp==OSTRRING) c[STREXTRA]++; else
415 if (tmp==ODEXRING) c[DEXTERITY]++; bottomline(); }
419 routine to tell if player can carry one more thing
420 returns 1 if pockets are full, else 0
423 pocketfull(void)
425 int i,limit;
426 if ((limit = 15+(c[LEVEL]>>1)) > 26) limit=26;
427 for (i=0; i<limit; i++) if (iven[i]==0) return(0);
428 return(1);
432 function to return 1 if a monster is next to the player else returns 0
435 nearbymonst(void)
437 int tmp,tmp2;
438 for (tmp=playerx-1; tmp<playerx+2; tmp++)
439 for (tmp2=playery-1; tmp2<playery+2; tmp2++)
440 if (mitem[tmp][tmp2]) return(1); /* if monster nearby */
441 return(0);
445 function to steal an item from the players pockets
446 returns 1 if steals something else returns 0
449 stealsomething(void)
451 int i,j;
452 j=100;
453 while (1)
455 i=rund(26);
456 if (iven[i]) if (c[WEAR]!=i) if (c[WIELD]!=i) if (c[SHIELD]!=i)
458 srcount=0; show3(i);
459 adjustcvalues(iven[i],ivenarg[i]); iven[i]=0; return(1);
461 if (--j <= 0) return(0);
466 function to return 1 is player carrys nothing else return 0
469 emptyhanded(void)
471 int i;
472 for (i=0; i<26; i++)
473 if (iven[i]) if (i!=c[WIELD]) if (i!=c[WEAR]) if (i!=c[SHIELD]) return(0);
474 return(1);
478 function to create a gem on a square near the player
480 void
481 creategem(void)
483 int i,j;
484 switch(rnd(4))
486 case 1: i=ODIAMOND; j=50; break;
487 case 2: i=ORUBY; j=40; break;
488 case 3: i=OEMERALD; j=30; break;
489 default: i=OSAPPHIRE; j=20; break;
491 createitem(i,rnd(j)+j/10);
495 function to change character levels as needed when dropping an object
496 that affects these characteristics
498 void
499 adjustcvalues(int itm, int arg)
501 int flag;
502 flag=0;
503 switch(itm)
505 case ODEXRING: c[DEXTERITY] -= arg+1; flag=1; break;
506 case OSTRRING: c[STREXTRA] -= arg+1; flag=1; break;
507 case OCLEVERRING: c[INTELLIGENCE] -= arg+1; flag=1; break;
508 case OHAMMER: c[DEXTERITY] -= 10; c[STREXTRA] -= 10;
509 c[INTELLIGENCE] += 10; flag=1; break;
510 case OSWORDofSLASHING: c[DEXTERITY] -= 5; flag=1; break;
511 case OORBOFDRAGON: --c[SLAYING]; return;
512 case OSPIRITSCARAB: --c[NEGATESPIRIT]; return;
513 case OCUBEofUNDEAD: --c[CUBEofUNDEAD]; return;
514 case ONOTHEFT: --c[NOTHEFT]; return;
515 case OLANCE: c[LANCEDEATH]=0; return;
516 case OPOTION: case OSCROLL: return;
518 default: flag=1;
520 if (flag) bottomline();
524 function to ask user for a password (no echo)
525 returns 1 if entered correctly, 0 if not
527 static char gpwbuf[33];
530 getpassword(void)
532 int i,j;
533 char *gpwp;
534 scbr();
535 gpwp = gpwbuf; lprcat("\nEnter Password: "); lflush();
536 i = strlen(password);
537 for (j=0; j<i; j++) read(0,gpwp++,1); gpwbuf[i]=0;
538 sncbr();
539 if (strcmp(gpwbuf,password) != 0)
540 { lprcat("\nSorry\n"); lflush(); return(0); }
541 else return(1);
545 subroutine to get a yes or no response from the user
546 returns y or n
549 getyn(void)
551 int i;
552 i=0; while (i!='y' && i!='n' && i!='\33') i=getchr();
553 return(i);
557 function to calculate the pack weight of the player
558 returns the number of pounds the player is carrying
561 packweight(void)
563 int i,j,k;
564 k=c[GOLD]/1000; j=25; while ((iven[j]==0) && (j>0)) --j;
565 for (i=0; i<=j; i++)
566 switch(iven[i])
568 case 0: break;
569 case OSSPLATE: case OPLATEARMOR: k += 40; break;
570 case OPLATE: k += 35; break;
571 case OHAMMER: k += 30; break;
572 case OSPLINT: k += 26; break;
573 case OSWORDofSLASHING: case OCHAIN:
574 case OBATTLEAXE: case O2SWORD: k += 23; break;
575 case OLONGSWORD: case OSWORD:
576 case ORING: case OFLAIL: k += 20; break;
577 case OLANCE: case OSTUDLEATHER: k += 15; break;
578 case OLEATHER: case OSPEAR: k += 8; break;
579 case OORBOFDRAGON: case OBELT: k += 4; break;
580 case OSHIELD: k += 7; break;
581 case OCHEST: k += 30 + ivenarg[i]; break;
582 default: k++;
584 return(k);
587 #ifndef MACRORND
588 /* macros to generate random numbers 1<=rnd(N)<=N 0<=rund(N)<=N-1 */
590 rnd(int x)
592 return((random()%x)+1);
596 rund(int x)
598 return(random()%x);
600 #endif /* MACRORND */