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
23 extern int score
[],dropflag
;
24 extern char *what
[],*who
[];
25 extern char password
[],winner
[];
26 extern char sciv
[SCORESIZE
+1][26][2];
34 subroutine to raise the player one level
35 uses the skill[] array to find level boundarys
36 uses c[EXPERIENCE] c[LEVEL]
41 if (c
[LEVEL
] < MAXPLEVEL
) raiseexperience((long)(skill
[c
[LEVEL
]]-c
[EXPERIENCE
]));
50 subroutine to lower the players character level by one
55 if (c
[LEVEL
] > 1) loseexperience((long)(c
[EXPERIENCE
] - skill
[c
[LEVEL
]-1] + 1));
64 subroutine to increase experience points
67 raiseexperience(long x
)
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));
81 beep(); lprintf("\nWelcome to level %d",(long)c
[LEVEL
]); /* if we changed levels */
92 subroutine to lose experience points
95 loseexperience(long x
)
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 */
111 beep(); lprintf("\nYou went down to level %d!",(long)c
[LEVEL
]);
123 subroutine to remove hit points from the player
124 warning -- will kill player if hp goes to zero
129 if ((c
[HP
] -= x
) <= 0)
131 beep(); lprcat("\n"); nap(3000); died(lastnum
);
138 c
[HP
] -= x
; if (c
[HP
] < 1) c
[HP
]=1;
139 c
[HPMAX
] -= x
; if (c
[HPMAX
] < 1) c
[HPMAX
]=1;
149 subroutine to gain maximum hit points
154 if ((c
[HP
] += x
) > c
[HPMAX
]) c
[HP
] = c
[HPMAX
];
160 c
[HPMAX
] += x
; c
[HP
] += x
;
169 subroutine to gain maximum spells
174 c
[SPELLMAX
]+=x
; c
[SPELLS
]+=x
;
183 subroutine to lose maximum spells
188 if ((c
[SPELLMAX
] -= x
) < 0) c
[SPELLMAX
]=0;
189 if ((c
[SPELLS
] -= x
) < 0) c
[SPELLS
]=0;
196 function to return monster number for a randomly selected monster
197 for the given cave level
203 if (lev
< 1) lev
= 1; if (lev
> 12) lev
= 12;
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? */
217 function to be sure player is not in a wall
224 while ((item
[playerx
][playery
] || mitem
[playerx
][playery
]) && (try))
225 if (++playerx
>= MAXX
-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
241 c
[AC
] = c
[MOREDEFENSES
];
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; }
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;
301 subroutine to ask if the player really wants to quit
307 cursors(); strcpy(lastmonst
,"");
308 lprcat("\n\nDo you really want to quit?");
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
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
)
337 if ((limit
= 15+(c
[LEVEL
]>>1)) > 26) limit
=26;
338 for (i
=0; i
<limit
; i
++)
341 iven
[i
] = itm
; ivenarg
[i
] = arg
; limit
=0;
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
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 */
388 function to enchant armor player is currently wearing
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(); } } }
398 if (tmp
!=OSCROLL
) if (tmp
!=OPOTION
) { ivenarg
[c
[WEAR
]]++; bottomline(); }
402 function to enchant a weapon presently being wielded
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
426 if ((limit
= 15+(c
[LEVEL
]>>1)) > 26) limit
=26;
427 for (i
=0; i
<limit
; i
++) if (iven
[i
]==0) return(0);
432 function to return 1 if a monster is next to the player else returns 0
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 */
445 function to steal an item from the players pockets
446 returns 1 if steals something else returns 0
456 if (iven
[i
]) if (c
[WEAR
]!=i
) if (c
[WIELD
]!=i
) if (c
[SHIELD
]!=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
473 if (iven
[i
]) if (i
!=c
[WIELD
]) if (i
!=c
[WEAR
]) if (i
!=c
[SHIELD
]) return(0);
478 function to create a gem on a square near the player
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
499 adjustcvalues(int itm
, int arg
)
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;
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];
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;
539 if (strcmp(gpwbuf
,password
) != 0)
540 { lprcat("\nSorry\n"); lflush(); return(0); }
545 subroutine to get a yes or no response from the user
552 i
=0; while (i
!='y' && i
!='n' && i
!='\33') i
=getchr();
557 function to calculate the pack weight of the player
558 returns the number of pounds the player is carrying
564 k
=c
[GOLD
]/1000; j
=25; while ((iven
[j
]==0) && (j
>0)) --j
;
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;
588 /* macros to generate random numbers 1<=rnd(N)<=N 0<=rund(N)<=N-1 */
592 return((random()%x
)+1);
600 #endif /* MACRORND */