Mercurial > hg > early-roguelike
comparison arogue5/player.c @ 63:0ed67132cf10
Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Thu, 09 Aug 2012 22:58:48 +0000 |
parents | |
children | aeabbca6dc0b |
comparison
equal
deleted
inserted
replaced
62:0ef99244acb8 | 63:0ed67132cf10 |
---|---|
1 /* | |
2 * This file contains functions for dealing with special player abilities | |
3 * | |
4 * Advanced Rogue | |
5 * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T | |
6 * All rights reserved. | |
7 * | |
8 * See the file LICENSE.TXT for full copyright and licensing information. | |
9 */ | |
10 | |
11 #include "curses.h" | |
12 #include "rogue.h" | |
13 | |
14 | |
15 /* | |
16 * affect: | |
17 * cleric affecting undead | |
18 */ | |
19 | |
20 affect() | |
21 { | |
22 register struct linked_list *item; | |
23 register struct thing *tp; | |
24 register const char *mname; | |
25 bool see; | |
26 coord new_pos; | |
27 | |
28 if (player.t_ctype != C_CLERIC && cur_relic[HEIL_ANKH] == 0) { | |
29 msg("Only clerics can affect undead."); | |
30 return; | |
31 } | |
32 | |
33 new_pos.y = hero.y + delta.y; | |
34 new_pos.x = hero.x + delta.x; | |
35 | |
36 if (cansee(new_pos.y, new_pos.x)) see = TRUE; | |
37 else see = FALSE; | |
38 | |
39 /* Anything there? */ | |
40 if (new_pos.y < 0 || new_pos.y > LINES-3 || | |
41 new_pos.x < 0 || new_pos.x > COLS-1 || | |
42 mvwinch(mw, new_pos.y, new_pos.x) == ' ') { | |
43 msg("Nothing to affect."); | |
44 return; | |
45 } | |
46 | |
47 if ((item = find_mons(new_pos.y, new_pos.x)) == NULL) { | |
48 debug("Affect what @ %d,%d?", new_pos.y, new_pos.x); | |
49 return; | |
50 } | |
51 tp = THINGPTR(item); | |
52 mname = monsters[tp->t_index].m_name; | |
53 | |
54 if (on(player, ISINVIS) && off(*tp, CANSEE)) { | |
55 sprintf(outstring,"%s%s cannot see you", see ? "The " : "It", | |
56 see ? mname : ""); | |
57 msg(outstring); | |
58 return; | |
59 } | |
60 | |
61 if (off(*tp, TURNABLE) || on(*tp, WASTURNED)) | |
62 goto annoy; | |
63 turn_off(*tp, TURNABLE); | |
64 | |
65 /* Can cleric kill it? */ | |
66 if (pstats.s_lvl >= 3 * tp->t_stats.s_lvl) { | |
67 unsigned long test; /* For overflow check */ | |
68 | |
69 sprintf(outstring,"You have destroyed %s%s.", see ? "the " : "it", see ? mname : ""); | |
70 msg(outstring); | |
71 test = pstats.s_exp + tp->t_stats.s_exp; | |
72 | |
73 /* Be sure there is no overflow before increasing experience */ | |
74 if (test > pstats.s_exp) pstats.s_exp = test; | |
75 killed(item, FALSE, TRUE); | |
76 check_level(TRUE); | |
77 return; | |
78 } | |
79 | |
80 /* Can cleric turn it? */ | |
81 if (rnd(100) + 1 > | |
82 (100 * ((2 * tp->t_stats.s_lvl) - pstats.s_lvl)) / pstats.s_lvl) { | |
83 unsigned long test; /* Overflow test */ | |
84 | |
85 /* Make the monster flee */ | |
86 turn_on(*tp, WASTURNED); /* No more fleeing after this */ | |
87 turn_on(*tp, ISFLEE); | |
88 runto(tp, &hero); | |
89 | |
90 /* Let player know */ | |
91 sprintf(outstring,"You have turned %s%s.", see ? "the " : "it", see ? mname : ""); | |
92 msg(outstring); | |
93 | |
94 /* get points for turning monster -- but check overflow first */ | |
95 test = pstats.s_exp + tp->t_stats.s_exp/2; | |
96 if (test > pstats.s_exp) pstats.s_exp = test; | |
97 check_level(TRUE); | |
98 | |
99 /* If monster was suffocating, stop it */ | |
100 if (on(*tp, DIDSUFFOCATE)) { | |
101 turn_off(*tp, DIDSUFFOCATE); | |
102 extinguish(suffocate); | |
103 } | |
104 | |
105 /* If monster held us, stop it */ | |
106 if (on(*tp, DIDHOLD) && (--hold_count == 0)) | |
107 turn_off(player, ISHELD); | |
108 turn_off(*tp, DIDHOLD); | |
109 return; | |
110 } | |
111 | |
112 /* Otherwise -- no go */ | |
113 annoy: | |
114 sprintf(outstring,"You do not affect %s%s.", see ? "the " : "it", see ? mname : ""); | |
115 msg(outstring); | |
116 | |
117 /* Annoy monster */ | |
118 if (off(*tp, ISFLEE)) runto(tp, &hero); | |
119 } | |
120 | |
121 /* | |
122 * the magic user is going to try and cast a spell | |
123 */ | |
124 cast() | |
125 { | |
126 register int i, num_spells, spell_ability; | |
127 int which_spell; | |
128 bool nohw = FALSE; | |
129 | |
130 i = num_spells = spell_ability = which_spell = 0; | |
131 | |
132 if (player.t_ctype != C_MAGICIAN && pstats.s_intel < 16) { | |
133 msg("You are not permitted to cast spells."); | |
134 return; | |
135 } | |
136 if (cur_misc[WEAR_CLOAK] != NULL && | |
137 cur_misc[WEAR_CLOAK]->o_which == MM_R_POWERLESS) { | |
138 msg("You can't seem to cast a spell!"); | |
139 return; | |
140 } | |
141 num_spells = 0; | |
142 | |
143 /* Get the number of avilable spells */ | |
144 if (pstats.s_intel >= 16) | |
145 num_spells = pstats.s_intel - 15; | |
146 | |
147 if (player.t_ctype == C_MAGICIAN) | |
148 num_spells += pstats.s_lvl; | |
149 | |
150 if (num_spells > MAXSPELLS) | |
151 num_spells = MAXSPELLS; | |
152 | |
153 spell_ability = pstats.s_lvl * pstats.s_intel; | |
154 if (player.t_ctype != C_MAGICIAN) | |
155 spell_ability /= 2; | |
156 | |
157 /* Prompt for spells */ | |
158 msg("Which spell are you casting? (* for list): "); | |
159 | |
160 which_spell = (int) (readchar() - 'a'); | |
161 if (which_spell == (int) ESCAPE - (int) 'a') { | |
162 mpos = 0; | |
163 msg(""); | |
164 after = FALSE; | |
165 return; | |
166 } | |
167 if (which_spell >= 0 && which_spell < num_spells) nohw = TRUE; | |
168 | |
169 else if (slow_invent) { | |
170 register char c; | |
171 | |
172 for (i=0; i<num_spells; i++) { | |
173 msg(""); | |
174 mvwaddch(cw, 0, 0, '['); | |
175 waddch(cw, (char) ((int) 'a' + i)); | |
176 waddstr(cw, "] A spell of "); | |
177 if (magic_spells[i].s_type == TYP_POTION) | |
178 waddstr(cw, p_magic[magic_spells[i].s_which].mi_name); | |
179 else if (magic_spells[i].s_type == TYP_SCROLL) | |
180 waddstr(cw, s_magic[magic_spells[i].s_which].mi_name); | |
181 else if (magic_spells[i].s_type == TYP_STICK) | |
182 waddstr(cw, ws_magic[magic_spells[i].s_which].mi_name); | |
183 waddstr(cw, morestr); | |
184 draw(cw); | |
185 do { | |
186 c = readchar(); | |
187 } while (c != ' ' && c != ESCAPE); | |
188 if (c == ESCAPE) | |
189 break; | |
190 } | |
191 msg(""); | |
192 mvwaddstr(cw, 0, 0, "Which spell are you casting? "); | |
193 draw(cw); | |
194 } | |
195 else { | |
196 /* Set up for redraw */ | |
197 msg(""); | |
198 clearok(cw, TRUE); | |
199 touchwin(cw); | |
200 | |
201 /* Now display the possible spells */ | |
202 wclear(hw); | |
203 touchwin(hw); | |
204 mvwaddstr(hw, 2, 0, " Cost Spell"); | |
205 mvwaddstr(hw, 3, 0, "-----------------------------------------------"); | |
206 for (i=0; i<num_spells; i++) { | |
207 mvwaddch(hw, i+4, 0, '['); | |
208 waddch(hw, (char) ((int) 'a' + i)); | |
209 waddch(hw, ']'); | |
210 sprintf(prbuf, " %3d", magic_spells[i].s_cost); | |
211 waddstr(hw, prbuf); | |
212 waddstr(hw, " A spell of "); | |
213 if (magic_spells[i].s_type == TYP_POTION) | |
214 waddstr(hw, p_magic[magic_spells[i].s_which].mi_name); | |
215 else if (magic_spells[i].s_type == TYP_SCROLL) | |
216 waddstr(hw, s_magic[magic_spells[i].s_which].mi_name); | |
217 else if (magic_spells[i].s_type == TYP_STICK) | |
218 waddstr(hw, ws_magic[magic_spells[i].s_which].mi_name); | |
219 } | |
220 sprintf(prbuf,"[Current spell power = %d]",spell_ability - spell_power); | |
221 mvwaddstr(hw, 0, 0, prbuf); | |
222 waddstr(hw, " Which spell are you casting? "); | |
223 draw(hw); | |
224 } | |
225 | |
226 if (!nohw) { | |
227 which_spell = (int) (wgetch(hw) - 'a'); | |
228 while (which_spell < 0 || which_spell >= num_spells) { | |
229 if (which_spell == (int) ESCAPE - (int) 'a') { | |
230 after = FALSE; | |
231 return; | |
232 } | |
233 wmove(hw, 0, 0); | |
234 wclrtoeol(hw); | |
235 waddstr(hw, "Please enter one of the listed spells. "); | |
236 draw(hw); | |
237 which_spell = (int) (wgetch(hw) - 'a'); | |
238 } | |
239 } | |
240 | |
241 if ((spell_power + magic_spells[which_spell].s_cost) > spell_ability) { | |
242 msg("Your attempt fails."); | |
243 return; | |
244 } | |
245 if (nohw) | |
246 msg("Your spell is successful."); | |
247 else { | |
248 mvwaddstr(hw, 0, 0, "Your spell is successful.--More--"); | |
249 wclrtoeol(hw); | |
250 draw(hw); | |
251 wait_for(hw,' '); | |
252 } | |
253 if (magic_spells[which_spell].s_type == TYP_POTION) | |
254 quaff( magic_spells[which_spell].s_which, | |
255 magic_spells[which_spell].s_flag, | |
256 FALSE); | |
257 else if (magic_spells[which_spell].s_type == TYP_SCROLL) | |
258 read_scroll( magic_spells[which_spell].s_which, | |
259 magic_spells[which_spell].s_flag, | |
260 FALSE); | |
261 else if (magic_spells[which_spell].s_type == TYP_STICK) { | |
262 if (!do_zap( TRUE, | |
263 magic_spells[which_spell].s_which, | |
264 magic_spells[which_spell].s_flag)) { | |
265 after = FALSE; | |
266 return; | |
267 } | |
268 } | |
269 spell_power += magic_spells[which_spell].s_cost; | |
270 } | |
271 | |
272 /* Constitution bonus */ | |
273 | |
274 const_bonus() /* Hit point adjustment for changing levels */ | |
275 { | |
276 if (pstats.s_const > 6 && pstats.s_const <= 14) | |
277 return(0); | |
278 if (pstats.s_const > 14) | |
279 return(pstats.s_const-14); | |
280 if (pstats.s_const > 3) | |
281 return(-1); | |
282 return(-2); | |
283 } | |
284 | |
285 | |
286 /* Routines for thieves */ | |
287 | |
288 /* | |
289 * gsense: | |
290 * Sense gold | |
291 */ | |
292 | |
293 gsense() | |
294 { | |
295 /* Only thieves can do this */ | |
296 if (player.t_ctype != C_THIEF) { | |
297 msg("You seem to have no gold sense."); | |
298 return; | |
299 } | |
300 | |
301 if (lvl_obj != NULL) { | |
302 struct linked_list *gitem; | |
303 struct object *cur; | |
304 int gtotal = 0; | |
305 | |
306 wclear(hw); | |
307 for (gitem = lvl_obj; gitem != NULL; gitem = next(gitem)) { | |
308 cur = OBJPTR(gitem); | |
309 if (cur->o_type == GOLD) { | |
310 gtotal += cur->o_count; | |
311 mvwaddch(hw, cur->o_pos.y, cur->o_pos.x, GOLD); | |
312 } | |
313 } | |
314 if (gtotal) { | |
315 s_know[S_GFIND] = TRUE; | |
316 msg("You sense gold!"); | |
317 overlay(hw,cw); | |
318 return; | |
319 } | |
320 } | |
321 msg("You can sense no gold on this level."); | |
322 } | |
323 | |
324 /* | |
325 * the cleric asks his deity for a spell | |
326 */ | |
327 pray() | |
328 { | |
329 register int i, num_prayers, prayer_ability; | |
330 int which_prayer; | |
331 bool nohw = FALSE; | |
332 | |
333 which_prayer = num_prayers = prayer_ability = i = 0; | |
334 | |
335 if (player.t_ctype != C_CLERIC && pstats.s_wisdom < 17 && | |
336 cur_relic[HEIL_ANKH] == 0) { | |
337 msg("You are not permitted to pray."); | |
338 return; | |
339 } | |
340 if (cur_misc[WEAR_CLOAK] != NULL && | |
341 cur_misc[WEAR_CLOAK]->o_which == MM_R_POWERLESS) { | |
342 msg("You can't seem to pray!"); | |
343 return; | |
344 } | |
345 num_prayers = 0; | |
346 | |
347 /* Get the number of avilable prayers */ | |
348 if (pstats.s_wisdom > 16) | |
349 num_prayers = (pstats.s_wisdom - 15) / 2; | |
350 | |
351 if (player.t_ctype == C_CLERIC) | |
352 num_prayers += pstats.s_lvl; | |
353 | |
354 if (cur_relic[HEIL_ANKH]) num_prayers += 3; | |
355 | |
356 if (num_prayers > MAXPRAYERS) | |
357 num_prayers = MAXPRAYERS; | |
358 | |
359 prayer_ability = pstats.s_lvl * pstats.s_wisdom; | |
360 if (player.t_ctype != C_CLERIC) | |
361 prayer_ability /= 2; | |
362 | |
363 if (cur_relic[HEIL_ANKH]) prayer_ability *= 2; | |
364 | |
365 /* Prompt for prayer */ | |
366 msg("Which prayer are you offering? (* for list): "); | |
367 which_prayer = (int) (readchar() - 'a'); | |
368 if (which_prayer == (int) ESCAPE - (int) 'a') { | |
369 mpos = 0; | |
370 msg(""); | |
371 after = FALSE; | |
372 return; | |
373 } | |
374 if (which_prayer >= 0 && which_prayer < num_prayers) nohw = TRUE; | |
375 | |
376 else if (slow_invent) { | |
377 register char c; | |
378 | |
379 for (i=0; i<num_prayers; i++) { | |
380 msg(""); | |
381 mvwaddch(cw, 0, 0, '['); | |
382 waddch(cw, (char) ((int) 'a' + i)); | |
383 waddstr(cw, "] A prayer for "); | |
384 if (cleric_spells[i].s_type == TYP_POTION) | |
385 waddstr(cw, p_magic[cleric_spells[i].s_which].mi_name); | |
386 else if (cleric_spells[i].s_type == TYP_SCROLL) | |
387 waddstr(cw, s_magic[cleric_spells[i].s_which].mi_name); | |
388 else if (cleric_spells[i].s_type == TYP_STICK) | |
389 waddstr(cw, ws_magic[cleric_spells[i].s_which].mi_name); | |
390 waddstr(cw, morestr); | |
391 draw(cw); | |
392 do { | |
393 c = readchar(); | |
394 } while (c != ' ' && c != ESCAPE); | |
395 if (c == ESCAPE) | |
396 break; | |
397 } | |
398 msg(""); | |
399 mvwaddstr(cw, 0, 0, "Which prayer are you offering? "); | |
400 draw(cw); | |
401 } | |
402 else { | |
403 /* Set up for redraw */ | |
404 msg(""); | |
405 clearok(cw, TRUE); | |
406 touchwin(cw); | |
407 | |
408 /* Now display the possible prayers */ | |
409 wclear(hw); | |
410 touchwin(hw); | |
411 mvwaddstr(hw, 2, 0, " Cost Prayer"); | |
412 mvwaddstr(hw, 3, 0, "-----------------------------------------------"); | |
413 for (i=0; i<num_prayers; i++) { | |
414 mvwaddch(hw, i+4, 0, '['); | |
415 waddch(hw, (char) ((int) 'a' + i)); | |
416 waddch(hw, ']'); | |
417 sprintf(prbuf, " %3d", cleric_spells[i].s_cost); | |
418 waddstr(hw, prbuf); | |
419 waddstr(hw, " A prayer for "); | |
420 if (cleric_spells[i].s_type == TYP_POTION) | |
421 waddstr(hw, p_magic[cleric_spells[i].s_which].mi_name); | |
422 else if (cleric_spells[i].s_type == TYP_SCROLL) | |
423 waddstr(hw, s_magic[cleric_spells[i].s_which].mi_name); | |
424 else if (cleric_spells[i].s_type == TYP_STICK) | |
425 waddstr(hw, ws_magic[cleric_spells[i].s_which].mi_name); | |
426 } | |
427 sprintf(prbuf,"[Current prayer ability = %d]",prayer_ability-pray_time); | |
428 mvwaddstr(hw, 0, 0, prbuf); | |
429 waddstr(hw, " Which prayer are you offering? "); | |
430 draw(hw); | |
431 } | |
432 | |
433 if (!nohw) { | |
434 which_prayer = (int) (wgetch(hw) - 'a'); | |
435 while (which_prayer < 0 || which_prayer >= num_prayers) { | |
436 if (which_prayer == (int) ESCAPE - (int) 'a') { | |
437 after = FALSE; | |
438 return; | |
439 } | |
440 wmove(hw, 0, 0); | |
441 wclrtoeol(hw); | |
442 mvwaddstr(hw, 0, 0, "Please enter one of the listed prayers."); | |
443 draw(hw); | |
444 which_prayer = (int) (wgetch(hw) - 'a'); | |
445 } | |
446 } | |
447 | |
448 | |
449 if (cleric_spells[which_prayer].s_cost + pray_time > prayer_ability) { | |
450 msg("Your prayer fails."); | |
451 return; | |
452 } | |
453 | |
454 if (nohw) | |
455 msg("Your prayer has been granted."); | |
456 else { | |
457 mvwaddstr(hw, 0, 0, "Your prayer has been granted.--More--"); | |
458 wclrtoeol(hw); | |
459 draw(hw); | |
460 wait_for(hw,' '); | |
461 } | |
462 if (cleric_spells[which_prayer].s_type == TYP_POTION) | |
463 quaff( cleric_spells[which_prayer].s_which, | |
464 cleric_spells[which_prayer].s_flag, | |
465 FALSE); | |
466 else if (cleric_spells[which_prayer].s_type == TYP_SCROLL) | |
467 read_scroll( cleric_spells[which_prayer].s_which, | |
468 cleric_spells[which_prayer].s_flag, | |
469 FALSE); | |
470 else if (cleric_spells[which_prayer].s_type == TYP_STICK) { | |
471 if (!do_zap( TRUE, | |
472 cleric_spells[which_prayer].s_which, | |
473 cleric_spells[which_prayer].s_flag)) { | |
474 after = FALSE; | |
475 return; | |
476 } | |
477 } | |
478 pray_time += cleric_spells[which_prayer].s_cost; | |
479 } | |
480 | |
481 | |
482 | |
483 /* | |
484 * steal: | |
485 * Steal in direction given in delta | |
486 */ | |
487 | |
488 steal() | |
489 { | |
490 register struct linked_list *item; | |
491 register struct thing *tp; | |
492 register const char *mname; | |
493 coord new_pos; | |
494 int thief_bonus = -50; | |
495 bool isinvisible = FALSE; | |
496 | |
497 new_pos.y = hero.y + delta.y; | |
498 new_pos.x = hero.x + delta.x; | |
499 | |
500 if (on(player, ISBLIND)) { | |
501 msg("You can't see anything."); | |
502 return; | |
503 } | |
504 | |
505 /* Anything there? */ | |
506 if (new_pos.y < 0 || new_pos.y > LINES-3 || | |
507 new_pos.x < 0 || new_pos.x > COLS-1 || | |
508 mvwinch(mw, new_pos.y, new_pos.x) == ' ') { | |
509 msg("Nothing to steal from."); | |
510 return; | |
511 } | |
512 | |
513 if ((item = find_mons(new_pos.y, new_pos.x)) == NULL) | |
514 debug("Steal from what @ %d,%d?", new_pos.y, new_pos.x); | |
515 tp = THINGPTR(item); | |
516 if (isinvisible = invisible(tp)) mname = "creature"; | |
517 else mname = monsters[tp->t_index].m_name; | |
518 | |
519 /* Can player steal something unnoticed? */ | |
520 if (player.t_ctype == C_THIEF) thief_bonus = 10; | |
521 if (on(*tp, ISUNIQUE)) thief_bonus -= 15; | |
522 if (isinvisible) thief_bonus -= 20; | |
523 if (on(*tp, ISINWALL) && off(player, CANINWALL)) thief_bonus -= 50; | |
524 | |
525 if (rnd(100) < | |
526 (thief_bonus + 2*dex_compute() + 5*pstats.s_lvl - | |
527 5*(tp->t_stats.s_lvl - 3))) { | |
528 register struct linked_list *s_item, *pack_ptr; | |
529 int count = 0; | |
530 unsigned long test; /* Overflow check */ | |
531 | |
532 s_item = NULL; /* Start stolen goods out as nothing */ | |
533 | |
534 /* Find a good item to take */ | |
535 for (pack_ptr=tp->t_pack; pack_ptr != NULL; pack_ptr=next(pack_ptr)) | |
536 if ((OBJPTR(pack_ptr))->o_type != RELIC && | |
537 rnd(++count) == 0) | |
538 s_item = pack_ptr; | |
539 | |
540 /* | |
541 * Find anything? | |
542 * | |
543 * if we have a merchant, and his pack is empty then the | |
544 * rogue has already stolen once | |
545 */ | |
546 if (s_item == NULL) { | |
547 if (tp->t_index == NUMMONST) | |
548 msg("The %s seems to be shielding his pack from you.", mname); | |
549 else | |
550 msg("The %s apparently has nothing to steal.", mname); | |
551 return; | |
552 } | |
553 | |
554 /* Take it from monster */ | |
555 if (tp->t_pack) detach(tp->t_pack, s_item); | |
556 | |
557 /* Give it to player */ | |
558 if (add_pack(s_item, FALSE, NULL) == FALSE) { | |
559 (OBJPTR(s_item))->o_pos = hero; | |
560 fall(s_item, TRUE); | |
561 } | |
562 | |
563 /* Get points for stealing -- but first check for overflow */ | |
564 test = pstats.s_exp + tp->t_stats.s_exp/2; | |
565 if (test > pstats.s_exp) pstats.s_exp = test; | |
566 | |
567 /* | |
568 * Do adjustments if player went up a level | |
569 */ | |
570 check_level(TRUE); | |
571 } | |
572 | |
573 else { | |
574 msg("Your attempt fails."); | |
575 | |
576 /* Annoy monster (maybe) */ | |
577 if (rnd(35) >= dex_compute() + thief_bonus) { | |
578 if (tp->t_index == NUMMONST) { | |
579 if (!isinvisible) | |
580 msg("The %s looks insulted and leaves", mname); | |
581 killed(item, FALSE, FALSE); | |
582 } | |
583 else | |
584 runto(tp, &hero); | |
585 } | |
586 } | |
587 } |