Blindfold removal fix
[slashemextended.git] / src / spell.c
blob2394b653707d7ad0823b5cf9e9649a12b0d1ce58
1 /* SCCS Id: @(#)spell.c 3.4 2003/01/17 */
2 /* Copyright (c) M. Stephenson 1988 */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
6 #include "edog.h"
8 /* Are now ints */
9 static NEARDATA int delay; /* moves left for this spell */
10 static NEARDATA int end_delay; /* when to stop studying */
11 static NEARDATA struct obj *book; /* last/current book being xscribed */
13 /* spellmenu arguments; 0 thru n-1 used as spl_book[] index when swapping */
14 #define SPELLMENU_CAST (-2)
15 #define SPELLMENU_VIEW (-1)
17 #define KEEN 10000 /* memory increase reading the book */
18 #define DUNADAN_KEEN 5000 /* memory increase reading the book */
19 #define CAST_BOOST 500 /* memory increase for successful casting */
20 #define DUNADAN_CAST_BOOST 250 /* memory increase for successful casting */
21 #define MAX_KNOW 200000 /* Absolute Max timeout */
22 #define MAX_CAN_STUDY 190000 /* Can study while timeout is less than */
24 #define MAX_STUDY_TIME 300 /* Max time for one study session */
25 #define MAX_SPELL_STUDY 30 /* Uses before spellbook crumbles */
27 #define spellknow(spell) spl_book[spell].sp_know
28 #define spellmemorize(spell) spl_book[spell].sp_memorize
30 static NEARDATA const char revivables[] = { ALLOW_FLOOROBJ, FOOD_CLASS, 0 };
32 static const char all_count[] = { ALLOW_COUNT, ALL_CLASSES, 0 };
33 static const char allnoncount[] = { ALL_CLASSES, 0 };
35 #define spellev(spell) spl_book[spell].sp_lev
36 #define spellid(spell) spl_book[spell].sp_id
37 #define spellname(spell) OBJ_NAME(objects[spellid(spell)])
38 #define spellet(spell) \
39 ((char)((spell < 26) ? ('a' + spell) : \
40 (spell < 52) ? ('A' + spell - 26) : \
41 (spell < 78) ? ('0' + spell - 52) : \
42 (spell < 104) ? ('a' + spell - 78) : \
43 (spell < 130) ? ('A' + spell - 104) : \
44 (spell < 156) ? ('0' + spell - 130) : 0 ))
46 STATIC_DCL int spell_let_to_idx(CHAR_P);
47 STATIC_DCL boolean cursed_book(struct obj *bp);
48 STATIC_DCL boolean confused_book(struct obj *);
49 STATIC_DCL void deadbook(struct obj *);
50 STATIC_PTR int learn(void);
51 STATIC_DCL void do_reset_learn(void);
52 STATIC_DCL boolean getspell(int *, BOOLEAN_P);
53 STATIC_DCL boolean dospellmenu(const char *,int,int *, int);
54 STATIC_DCL int percent_success(int);
55 STATIC_DCL void cast_protection(void);
56 STATIC_DCL void cast_reflection(void);
57 STATIC_DCL void spell_backfire(int);
58 STATIC_DCL const char *spelltypemnemonic(int);
59 static int spell_dash(void);
60 STATIC_DCL void boostknow(int, int);
61 STATIC_DCL void drainknow(int, int);
62 STATIC_DCL void incrnknow(int, BOOLEAN_P);
64 boolean
65 spell_known(int sbook_id)
67 int i;
69 i = 0;
70 while (spl_book[i].sp_id != NO_SPELL && i < MAXSPELL) {
71 if (spl_book[i].sp_id == sbook_id) return(TRUE);
72 i++;
74 return(FALSE);
79 /* The roles[] table lists the role-specific values for tuning
80 * percent_success().
82 * Reasoning:
83 * splcaster, special:
84 * Arc are aware of magic through historical research
85 * Bar abhor magic (Conan finds it "interferes with his animal instincts")
86 * Cav are ignorant to magic
87 * Hea are very aware of healing magic through medical research
88 * Kni are moderately aware of healing from Paladin training
89 * Mon use magic to attack and defend in lieu of weapons and armor
90 * Pri are very aware of healing magic through theological research
91 * Ran avoid magic, preferring to fight unseen and unheard
92 * Rog are moderately aware of magic through trickery
93 * Sam have limited magical awareness, prefering meditation to conjuring
94 * Tou are aware of magic from all the great films they have seen
95 * Val have limited magical awareness, prefering fighting
96 * Wiz are trained mages
98 * The arms penalty is lessened for trained fighters Bar, Kni, Ran,
99 * Sam, Val -
100 * the penalty is its metal interference, not encumbrance.
101 * The `spelspec' is a single spell which is fundamentally easier
102 * for that role to cast.
104 * spelspec, spelsbon:
105 * Arc map masters (SPE_MAGIC_MAPPING)
106 * Bar fugue/berserker (SPE_HASTE_SELF)
107 * Cav born to dig (SPE_DIG)
108 * Hea to heal (SPE_CURE_SICKNESS)
109 * Kni to turn back evil (SPE_TURN_UNDEAD)
110 * Mon to preserve their abilities (SPE_RESTORE_ABILITY)
111 * Pri to bless (SPE_REMOVE_CURSE)
112 * Ran to hide (SPE_INVISIBILITY)
113 * Rog to find loot (SPE_DETECT_TREASURE)
114 * Sam to be At One (SPE_CLAIRVOYANCE)
115 * Tou to smile (SPE_CHARM_MONSTER)
116 * Val control lightning (SPE_LIGHTNING)
117 * Wiz all really, but SPE_MAGIC_MISSILE is their party trick
118 * Yeo guard doors (SPE_KNOCK)
120 * See percent_success() below for more comments.
122 * uarmbon, uarmsbon, uarmhbon, uarmgbon, uarmfbon:
123 * Fighters find body armour & shield a little less limiting.
124 * Headgear, Gauntlets and Footwear are not role-specific (but
125 * still have an effect, except helm of brilliance, which is designed
126 * to permit magic-use).
129 #define uarmhbon 3 /* Metal helmets interfere with the mind */
130 #define uarmgbon 5 /* Casting channels through the hands */
131 #define uarmfbon 1 /* All metal interferes to some degree */
133 /* since the spellbook itself doesn't blow up, don't say just "explodes" */
134 static const char explodes[] = "radiates explosive energy";
136 /* convert an alnum into a number in the range 0..61, or -1 if not an alnum */
137 STATIC_OVL int
138 spell_let_to_idx(ilet)
139 char ilet;
141 int indx;
143 indx = ilet - 'a';
144 if (indx >= 0 && indx < 26) return indx;
145 indx = ilet - 'A';
146 if (indx >= 0 && indx < 26) return indx + 26;
147 indx = ilet - '0';
148 if (indx >= 0 && indx < 10) return indx + 52;
149 return -1;
152 STATIC_PTR void
153 undo_barfloodC(x, y, roomcnt)
154 int x, y;
155 void * roomcnt;
157 if (levl[x][y].typ != IRONBARS)
158 return;
160 (*(int *)roomcnt)++;
162 /* Get rid of bars at x, y */
163 levl[x][y].typ = ROOM;
164 blockorunblock_point(x,y);
165 newsym(x,y);
168 /* TRUE: book should be destroyed by caller */
169 STATIC_OVL boolean
170 cursed_book(bp)
171 struct obj *bp;
173 int lev = objects[bp->otyp].oc_level;
175 switch(rn2(lev)) {
176 case 0:
177 You_feel("a wrenching sensation.");
178 if (PlayerHearsSoundEffects) pline(issoviet ? "Tam net nikakoy zashchity. Tam net nikakoy nadezhdy. Yedinstvennoye, chto yest'? Uverennost' v tom, chto vy, igrok, budet umeret' uzhasnoy i muchitel'noy smert'yu." : "SCHRING!");
179 tele(); /* teleport him */
180 break;
181 case 1:
182 You_feel("threatened.");
183 aggravate();
184 break;
185 case 2:
186 /* [Tom] lowered this (used to be 100,250) */
187 make_blinded(Blinded + rn1(50,25),TRUE);
188 break;
189 case 3:
190 take_gold();
191 break;
192 case 4:
193 pline("These runes were just too much to comprehend.");
194 make_confused(HConfusion + rn1(7,16),FALSE);
195 break;
196 case 5:
197 pline_The("book was coated with contact poison!");
198 if (uarmg) {
199 if (uarmg->oerodeproof || (Race_if(PM_CHIQUAI) && rn2(4)) || (uarmg->oartifact && rn2(4)) || (objects[uarmg->otyp].oc_material == MT_GREEN_STEEL && rn2(2)) || !is_corrodeable(uarmg)) {
200 Your("gloves seem unaffected.");
201 } else if (uarmg->oeroded2 < MAX_ERODE) {
202 if (uarmg->greased) {
203 grease_protect(uarmg, "gloves", &youmonst);
204 } else if (!rn2(2) || !(uarmf && uarmf->oartifact == ART_LUISA_S_IRRESISTIBLE_CHARM) ) {
205 Your("gloves corrode%s!",
206 uarmg->oeroded2+1 == MAX_ERODE ?
207 " completely" : uarmg->oeroded2 ?
208 " further" : "");
209 uarmg->oeroded2++;
211 } else
212 Your("gloves %s completely corroded.",
213 Blind ? "feel" : "look");
214 break;
216 /* temp disable in_use; death should not destroy the book */
217 bp->in_use = FALSE;
218 losestr(StrongPoison_resistance ? 1 : Poison_resistance ? rno(3) : rnd(5), TRUE);
219 losehp(rnd(Poison_resistance ? 6 : 10),
220 "contact-poisoned spellbook", KILLED_BY_AN);
221 bp->in_use = TRUE;
222 break;
223 case 6:
224 if(Antimagic && !Race_if(PM_KUTAR) && rn2(StrongAntimagic ? 20 : 5) ) {
225 shieldeff(u.ux, u.uy);
226 pline_The("book %s, but you are unharmed!", explodes);
227 } else {
228 pline("As you read the book, it %s in your %s!",
229 explodes, body_part(FACE));
230 losehp(2*rnd(10)+5, "exploding rune", KILLED_BY_AN);
232 return TRUE;
233 default:
234 rndcurse();
235 break;
237 return (bp->spe < 0) ? TRUE : FALSE;
240 /* study while confused: returns TRUE if the book is destroyed */
241 STATIC_OVL boolean
242 confused_book(spellbook)
243 struct obj *spellbook;
245 boolean gone = FALSE;
247 if (!rn2(50) && spellbook->otyp != SPE_BOOK_OF_THE_DEAD) {
248 spellbook->in_use = TRUE; /* in case called from learn */
249 pline("Being confused you have difficulties in controlling your actions.");
250 display_nhwindow(WIN_MESSAGE, FALSE);
251 You("accidentally tear the spellbook to pieces.");
252 if (!objects[spellbook->otyp].oc_name_known &&
253 !objects[spellbook->otyp].oc_uname)
254 docall(spellbook);
255 if (carried(spellbook)) useup(spellbook);
256 else useupf(spellbook, 1L);
257 gone = TRUE;
258 } else {
259 You("find yourself reading the %s line over and over again.",
260 spellbook == book ? "next" : "first");
262 return gone;
265 STATIC_PTR void
266 do_lockfloodg(x, y, poolcnt)
267 int x, y;
268 void * poolcnt;
270 register struct monst *mtmp;
271 register struct trap *ttmp;
272 int randomamount = 0;
273 int randomx, randomy;
274 if (!rn2(25)) randomamount += rnz(2);
275 if (!rn2(125)) randomamount += rnz(5);
276 if (!rn2(625)) randomamount += rnz(20);
277 if (!rn2(3125)) randomamount += rnz(50);
278 if (isaquarian) {
279 if (!rn2(25)) randomamount += rnz(2);
280 if (!rn2(125)) randomamount += rnz(5);
281 if (!rn2(625)) randomamount += rnz(20);
282 if (!rn2(3125)) randomamount += rnz(50);
284 if (rn2(5)) randomamount = 0;
286 while (randomamount) {
287 randomamount--;
288 randomx = rn1(COLNO-3,2);
289 randomy = rn2(ROWNO);
290 if (isok(randomx, randomy) && ((levl[randomx][randomy].wall_info & W_NONDIGGABLE) == 0) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR || (levl[randomx][randomy].typ == DOOR && levl[randomx][randomy].doormask == D_NODOOR) ) ) {
292 if (rn2(3)) doorlockX(randomx, randomy, TRUE);
293 else {
294 if (levl[randomx][randomy].typ != DOOR) levl[randomx][randomy].typ = STONE;
295 else levl[randomx][randomy].typ = CROSSWALL;
296 blockorunblock_point(randomx,randomy);
297 if (!(levl[randomx][randomy].wall_info & W_EASYGROWTH)) levl[randomx][randomy].wall_info |= W_HARDGROWTH;
298 del_engr_at(randomx, randomy);
300 if ((mtmp = m_at(randomx, randomy)) != 0) {
301 (void) minliquid(mtmp);
302 } else {
303 newsym(randomx,randomy);
309 if (rn2(3)) doorlockX(x, y, TRUE);
311 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
312 (sobj_at(BOULDER, x, y)) || (levl[x][y].wall_info & W_NONDIGGABLE) != 0 || (levl[x][y].typ != CORR && levl[x][y].typ != ROOM && (levl[x][y].typ != DOOR || levl[x][y].doormask != D_NODOOR) ))
313 return;
315 (*(int *)poolcnt)++;
317 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
318 /* Put a wall at x, y */
319 if (levl[x][y].typ != DOOR) levl[x][y].typ = STONE;
320 else levl[x][y].typ = CROSSWALL;
321 blockorunblock_point(x,y);
322 if (!(levl[x][y].wall_info & W_EASYGROWTH)) levl[x][y].wall_info |= W_HARDGROWTH;
323 del_engr_at(x, y);
325 if ((mtmp = m_at(x, y)) != 0) {
326 (void) minliquid(mtmp);
327 } else {
328 newsym(x,y);
330 } else if ((x == u.ux) && (y == u.uy)) {
331 (*(int *)poolcnt)--;
336 STATIC_PTR void
337 do_treefloodg(x, y, poolcnt)
338 int x, y;
339 void * poolcnt;
341 register struct monst *mtmp;
342 register struct trap *ttmp;
343 int randomamount = 0;
344 int randomx, randomy;
345 if (!rn2(25)) randomamount += rnz(2);
346 if (!rn2(125)) randomamount += rnz(5);
347 if (!rn2(625)) randomamount += rnz(20);
348 if (!rn2(3125)) randomamount += rnz(50);
349 if (isaquarian) {
350 if (!rn2(25)) randomamount += rnz(2);
351 if (!rn2(125)) randomamount += rnz(5);
352 if (!rn2(625)) randomamount += rnz(20);
353 if (!rn2(3125)) randomamount += rnz(50);
355 if (rn2(5)) randomamount = 0;
357 while (randomamount) {
358 randomamount--;
359 randomx = rn1(COLNO-3,2);
360 randomy = rn2(ROWNO);
361 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
362 levl[randomx][randomy].typ = TREE;
363 blockorunblock_point(randomx,randomy);
364 if (!(levl[randomx][randomy].wall_info & W_EASYGROWTH)) levl[randomx][randomy].wall_info |= W_HARDGROWTH;
365 del_engr_at(randomx, randomy);
367 if ((mtmp = m_at(randomx, randomy)) != 0) {
368 (void) minliquid(mtmp);
369 } else {
370 newsym(randomx,randomy);
375 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
376 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
377 return;
379 (*(int *)poolcnt)++;
381 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
382 /* Put a pool at x, y */
383 levl[x][y].typ = TREE;
384 blockorunblock_point(x,y);
385 if (!(levl[x][y].wall_info & W_EASYGROWTH)) levl[x][y].wall_info |= W_HARDGROWTH;
386 del_engr_at(x, y);
388 if ((mtmp = m_at(x, y)) != 0) {
389 (void) minliquid(mtmp);
390 } else {
391 newsym(x,y);
393 } else if ((x == u.ux) && (y == u.uy)) {
394 (*(int *)poolcnt)--;
399 STATIC_PTR void
400 do_gravefloodg(x, y, poolcnt)
401 int x, y;
402 void * poolcnt;
404 register struct monst *mtmp;
405 register struct trap *ttmp;
406 int randomamount = 0;
407 int randomx, randomy;
408 if (!rn2(25)) randomamount += rnz(2);
409 if (!rn2(125)) randomamount += rnz(5);
410 if (!rn2(625)) randomamount += rnz(20);
411 if (!rn2(3125)) randomamount += rnz(50);
412 if (isaquarian) {
413 if (!rn2(25)) randomamount += rnz(2);
414 if (!rn2(125)) randomamount += rnz(5);
415 if (!rn2(625)) randomamount += rnz(20);
416 if (!rn2(3125)) randomamount += rnz(50);
418 if (rn2(5)) randomamount = 0;
420 while (randomamount) {
421 randomamount--;
422 randomx = rn1(COLNO-3,2);
423 randomy = rn2(ROWNO);
424 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
425 levl[randomx][randomy].typ = GRAVEWALL;
426 blockorunblock_point(randomx,randomy);
427 if (!(levl[randomx][randomy].wall_info & W_EASYGROWTH)) levl[randomx][randomy].wall_info |= W_HARDGROWTH;
428 del_engr_at(randomx, randomy);
430 if ((mtmp = m_at(randomx, randomy)) != 0) {
431 (void) minliquid(mtmp);
432 } else {
433 newsym(randomx,randomy);
438 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
439 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
440 return;
442 (*(int *)poolcnt)++;
444 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
445 /* Put a pool at x, y */
446 levl[x][y].typ = GRAVEWALL;
447 blockorunblock_point(x,y);
448 if (!(levl[x][y].wall_info & W_EASYGROWTH)) levl[x][y].wall_info |= W_HARDGROWTH;
449 del_engr_at(x, y);
451 if ((mtmp = m_at(x, y)) != 0) {
452 (void) minliquid(mtmp);
453 } else {
454 newsym(x,y);
456 } else if ((x == u.ux) && (y == u.uy)) {
457 (*(int *)poolcnt)--;
462 STATIC_PTR void
463 do_tunnelfloodg(x, y, poolcnt)
464 int x, y;
465 void * poolcnt;
467 register struct monst *mtmp;
468 register struct trap *ttmp;
469 int randomamount = 0;
470 int randomx, randomy;
471 if (!rn2(25)) randomamount += rnz(2);
472 if (!rn2(125)) randomamount += rnz(5);
473 if (!rn2(625)) randomamount += rnz(20);
474 if (!rn2(3125)) randomamount += rnz(50);
475 if (isaquarian) {
476 if (!rn2(25)) randomamount += rnz(2);
477 if (!rn2(125)) randomamount += rnz(5);
478 if (!rn2(625)) randomamount += rnz(20);
479 if (!rn2(3125)) randomamount += rnz(50);
481 if (rn2(5)) randomamount = 0;
483 while (randomamount) {
484 randomamount--;
485 randomx = rn1(COLNO-3,2);
486 randomy = rn2(ROWNO);
487 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
488 levl[randomx][randomy].typ = TUNNELWALL;
489 blockorunblock_point(randomx,randomy);
490 if (!(levl[randomx][randomy].wall_info & W_EASYGROWTH)) levl[randomx][randomy].wall_info |= W_HARDGROWTH;
491 del_engr_at(randomx, randomy);
493 if ((mtmp = m_at(randomx, randomy)) != 0) {
494 (void) minliquid(mtmp);
495 } else {
496 newsym(randomx,randomy);
501 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
502 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
503 return;
505 (*(int *)poolcnt)++;
507 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
508 /* Put a pool at x, y */
509 levl[x][y].typ = TUNNELWALL;
510 blockorunblock_point(x,y);
511 if (!(levl[x][y].wall_info & W_EASYGROWTH)) levl[x][y].wall_info |= W_HARDGROWTH;
512 del_engr_at(x, y);
514 if ((mtmp = m_at(x, y)) != 0) {
515 (void) minliquid(mtmp);
516 } else {
517 newsym(x,y);
519 } else if ((x == u.ux) && (y == u.uy)) {
520 (*(int *)poolcnt)--;
525 STATIC_PTR void
526 do_farmfloodg(x, y, poolcnt)
527 int x, y;
528 void * poolcnt;
530 register struct monst *mtmp;
531 register struct trap *ttmp;
532 int randomamount = 0;
533 int randomx, randomy;
534 if (!rn2(25)) randomamount += rnz(2);
535 if (!rn2(125)) randomamount += rnz(5);
536 if (!rn2(625)) randomamount += rnz(20);
537 if (!rn2(3125)) randomamount += rnz(50);
538 if (isaquarian) {
539 if (!rn2(25)) randomamount += rnz(2);
540 if (!rn2(125)) randomamount += rnz(5);
541 if (!rn2(625)) randomamount += rnz(20);
542 if (!rn2(3125)) randomamount += rnz(50);
544 if (rn2(5)) randomamount = 0;
546 while (randomamount) {
547 randomamount--;
548 randomx = rn1(COLNO-3,2);
549 randomy = rn2(ROWNO);
550 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
551 levl[randomx][randomy].typ = FARMLAND;
552 blockorunblock_point(randomx,randomy);
553 if (!(levl[randomx][randomy].wall_info & W_EASYGROWTH)) levl[randomx][randomy].wall_info |= W_HARDGROWTH;
554 del_engr_at(randomx, randomy);
556 if ((mtmp = m_at(randomx, randomy)) != 0) {
557 (void) minliquid(mtmp);
558 } else {
559 newsym(randomx,randomy);
564 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
565 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
566 return;
568 (*(int *)poolcnt)++;
570 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
571 /* Put a pool at x, y */
572 levl[x][y].typ = FARMLAND;
573 blockorunblock_point(x,y);
574 if (!(levl[x][y].wall_info & W_EASYGROWTH)) levl[x][y].wall_info |= W_HARDGROWTH;
575 del_engr_at(x, y);
577 if ((mtmp = m_at(x, y)) != 0) {
578 (void) minliquid(mtmp);
579 } else {
580 newsym(x,y);
582 } else if ((x == u.ux) && (y == u.uy)) {
583 (*(int *)poolcnt)--;
588 STATIC_PTR void
589 do_mountainfloodg(x, y, poolcnt)
590 int x, y;
591 void * poolcnt;
593 register struct monst *mtmp;
594 register struct trap *ttmp;
595 int randomamount = 0;
596 int randomx, randomy;
597 if (!rn2(25)) randomamount += rnz(2);
598 if (!rn2(125)) randomamount += rnz(5);
599 if (!rn2(625)) randomamount += rnz(20);
600 if (!rn2(3125)) randomamount += rnz(50);
601 if (isaquarian) {
602 if (!rn2(25)) randomamount += rnz(2);
603 if (!rn2(125)) randomamount += rnz(5);
604 if (!rn2(625)) randomamount += rnz(20);
605 if (!rn2(3125)) randomamount += rnz(50);
607 if (rn2(5)) randomamount = 0;
609 while (randomamount) {
610 randomamount--;
611 randomx = rn1(COLNO-3,2);
612 randomy = rn2(ROWNO);
613 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
614 levl[randomx][randomy].typ = MOUNTAIN;
615 blockorunblock_point(randomx,randomy);
616 if (!(levl[randomx][randomy].wall_info & W_EASYGROWTH)) levl[randomx][randomy].wall_info |= W_HARDGROWTH;
617 del_engr_at(randomx, randomy);
619 if ((mtmp = m_at(randomx, randomy)) != 0) {
620 (void) minliquid(mtmp);
621 } else {
622 newsym(randomx,randomy);
627 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
628 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
629 return;
631 (*(int *)poolcnt)++;
633 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
634 /* Put a pool at x, y */
635 levl[x][y].typ = MOUNTAIN;
636 blockorunblock_point(x,y);
637 if (!(levl[x][y].wall_info & W_EASYGROWTH)) levl[x][y].wall_info |= W_HARDGROWTH;
638 del_engr_at(x, y);
640 if ((mtmp = m_at(x, y)) != 0) {
641 (void) minliquid(mtmp);
642 } else {
643 newsym(x,y);
645 } else if ((x == u.ux) && (y == u.uy)) {
646 (*(int *)poolcnt)--;
651 STATIC_PTR void
652 do_watertunnelfloodg(x, y, poolcnt)
653 int x, y;
654 void * poolcnt;
656 register struct monst *mtmp;
657 register struct trap *ttmp;
658 int randomamount = 0;
659 int randomx, randomy;
660 if (!rn2(25)) randomamount += rnz(2);
661 if (!rn2(125)) randomamount += rnz(5);
662 if (!rn2(625)) randomamount += rnz(20);
663 if (!rn2(3125)) randomamount += rnz(50);
664 if (isaquarian) {
665 if (!rn2(25)) randomamount += rnz(2);
666 if (!rn2(125)) randomamount += rnz(5);
667 if (!rn2(625)) randomamount += rnz(20);
668 if (!rn2(3125)) randomamount += rnz(50);
670 if (rn2(5)) randomamount = 0;
672 while (randomamount) {
673 randomamount--;
674 randomx = rn1(COLNO-3,2);
675 randomy = rn2(ROWNO);
676 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
677 levl[randomx][randomy].typ = WATERTUNNEL;
678 blockorunblock_point(randomx,randomy);
679 if (!(levl[randomx][randomy].wall_info & W_EASYGROWTH)) levl[randomx][randomy].wall_info |= W_HARDGROWTH;
680 del_engr_at(randomx, randomy);
682 if ((mtmp = m_at(randomx, randomy)) != 0) {
683 (void) minliquid(mtmp);
684 } else {
685 newsym(randomx,randomy);
690 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
691 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
692 return;
694 (*(int *)poolcnt)++;
696 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
697 /* Put a pool at x, y */
698 levl[x][y].typ = WATERTUNNEL;
699 blockorunblock_point(x,y);
700 if (!(levl[x][y].wall_info & W_EASYGROWTH)) levl[x][y].wall_info |= W_HARDGROWTH;
701 del_engr_at(x, y);
703 if ((mtmp = m_at(x, y)) != 0) {
704 (void) minliquid(mtmp);
705 } else {
706 newsym(x,y);
708 } else if ((x == u.ux) && (y == u.uy)) {
709 (*(int *)poolcnt)--;
714 STATIC_PTR void
715 do_icefloodg(x, y, poolcnt)
716 int x, y;
717 void * poolcnt;
719 register struct monst *mtmp;
720 register struct trap *ttmp;
721 int randomamount = 0;
722 int randomx, randomy;
723 if (!rn2(25)) randomamount += rnz(2);
724 if (!rn2(125)) randomamount += rnz(5);
725 if (!rn2(625)) randomamount += rnz(20);
726 if (!rn2(3125)) randomamount += rnz(50);
727 if (isaquarian) {
728 if (!rn2(25)) randomamount += rnz(2);
729 if (!rn2(125)) randomamount += rnz(5);
730 if (!rn2(625)) randomamount += rnz(20);
731 if (!rn2(3125)) randomamount += rnz(50);
733 if (rn2(5)) randomamount = 0;
735 while (randomamount) {
736 randomamount--;
737 randomx = rn1(COLNO-3,2);
738 randomy = rn2(ROWNO);
739 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
740 levl[randomx][randomy].typ = ICE;
741 del_engr_at(randomx, randomy);
743 if ((mtmp = m_at(randomx, randomy)) != 0) {
744 (void) minliquid(mtmp);
745 } else {
746 newsym(randomx,randomy);
751 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
752 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
753 return;
755 (*(int *)poolcnt)++;
757 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
758 /* Put a pool at x, y */
759 levl[x][y].typ = ICE;
760 del_engr_at(x, y);
762 if ((mtmp = m_at(x, y)) != 0) {
763 (void) minliquid(mtmp);
764 } else {
765 newsym(x,y);
767 } else if ((x == u.ux) && (y == u.uy)) {
768 (*(int *)poolcnt)--;
773 STATIC_PTR void
774 do_crystalwaterfloodg(x, y, poolcnt)
775 int x, y;
776 void * poolcnt;
778 register struct monst *mtmp;
779 register struct trap *ttmp;
780 int randomamount = 0;
781 int randomx, randomy;
782 if (!rn2(25)) randomamount += rnz(2);
783 if (!rn2(125)) randomamount += rnz(5);
784 if (!rn2(625)) randomamount += rnz(20);
785 if (!rn2(3125)) randomamount += rnz(50);
786 if (isaquarian) {
787 if (!rn2(25)) randomamount += rnz(2);
788 if (!rn2(125)) randomamount += rnz(5);
789 if (!rn2(625)) randomamount += rnz(20);
790 if (!rn2(3125)) randomamount += rnz(50);
792 if (rn2(5)) randomamount = 0;
794 while (randomamount) {
795 randomamount--;
796 randomx = rn1(COLNO-3,2);
797 randomy = rn2(ROWNO);
798 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
799 levl[randomx][randomy].typ = CRYSTALWATER;
800 del_engr_at(randomx, randomy);
802 if ((mtmp = m_at(randomx, randomy)) != 0) {
803 (void) minliquid(mtmp);
804 } else {
805 newsym(randomx,randomy);
810 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
811 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
812 return;
814 (*(int *)poolcnt)++;
816 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
817 /* Put a pool at x, y */
818 levl[x][y].typ = CRYSTALWATER;
819 del_engr_at(x, y);
821 if ((mtmp = m_at(x, y)) != 0) {
822 (void) minliquid(mtmp);
823 } else {
824 newsym(x,y);
826 } else if ((x == u.ux) && (y == u.uy)) {
827 (*(int *)poolcnt)--;
833 STATIC_PTR void
834 do_moorfloodg(x, y, poolcnt)
835 int x, y;
836 void * poolcnt;
838 register struct monst *mtmp;
839 register struct trap *ttmp;
840 int randomamount = 0;
841 int randomx, randomy;
842 if (!rn2(25)) randomamount += rnz(2);
843 if (!rn2(125)) randomamount += rnz(5);
844 if (!rn2(625)) randomamount += rnz(20);
845 if (!rn2(3125)) randomamount += rnz(50);
846 if (isaquarian) {
847 if (!rn2(25)) randomamount += rnz(2);
848 if (!rn2(125)) randomamount += rnz(5);
849 if (!rn2(625)) randomamount += rnz(20);
850 if (!rn2(3125)) randomamount += rnz(50);
852 if (rn2(5)) randomamount = 0;
854 while (randomamount) {
855 randomamount--;
856 randomx = rn1(COLNO-3,2);
857 randomy = rn2(ROWNO);
858 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
859 levl[randomx][randomy].typ = MOORLAND;
860 del_engr_at(randomx, randomy);
862 if ((mtmp = m_at(randomx, randomy)) != 0) {
863 (void) minliquid(mtmp);
864 } else {
865 newsym(randomx,randomy);
870 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
871 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
872 return;
874 (*(int *)poolcnt)++;
876 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
877 /* Put a pool at x, y */
878 levl[x][y].typ = MOORLAND;
879 del_engr_at(x, y);
881 if ((mtmp = m_at(x, y)) != 0) {
882 (void) minliquid(mtmp);
883 } else {
884 newsym(x,y);
886 } else if ((x == u.ux) && (y == u.uy)) {
887 (*(int *)poolcnt)--;
892 STATIC_PTR void
893 do_urinefloodg(x, y, poolcnt)
894 int x, y;
895 void * poolcnt;
897 register struct monst *mtmp;
898 register struct trap *ttmp;
899 int randomamount = 0;
900 int randomx, randomy;
901 if (!rn2(25)) randomamount += rnz(2);
902 if (!rn2(125)) randomamount += rnz(5);
903 if (!rn2(625)) randomamount += rnz(20);
904 if (!rn2(3125)) randomamount += rnz(50);
905 if (isaquarian) {
906 if (!rn2(25)) randomamount += rnz(2);
907 if (!rn2(125)) randomamount += rnz(5);
908 if (!rn2(625)) randomamount += rnz(20);
909 if (!rn2(3125)) randomamount += rnz(50);
911 if (rn2(5)) randomamount = 0;
913 while (randomamount) {
914 randomamount--;
915 randomx = rn1(COLNO-3,2);
916 randomy = rn2(ROWNO);
917 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
918 levl[randomx][randomy].typ = URINELAKE;
919 del_engr_at(randomx, randomy);
921 if ((mtmp = m_at(randomx, randomy)) != 0) {
922 (void) minliquid(mtmp);
923 } else {
924 newsym(randomx,randomy);
929 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
930 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
931 return;
933 (*(int *)poolcnt)++;
935 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
936 /* Put a pool at x, y */
937 levl[x][y].typ = URINELAKE;
938 del_engr_at(x, y);
940 if ((mtmp = m_at(x, y)) != 0) {
941 (void) minliquid(mtmp);
942 } else {
943 newsym(x,y);
945 } else if ((x == u.ux) && (y == u.uy)) {
946 (*(int *)poolcnt)--;
951 STATIC_PTR void
952 do_shiftingsandfloodg(x, y, poolcnt)
953 int x, y;
954 void * poolcnt;
956 register struct monst *mtmp;
957 register struct trap *ttmp;
958 int randomamount = 0;
959 int randomx, randomy;
960 if (!rn2(25)) randomamount += rnz(2);
961 if (!rn2(125)) randomamount += rnz(5);
962 if (!rn2(625)) randomamount += rnz(20);
963 if (!rn2(3125)) randomamount += rnz(50);
964 if (isaquarian) {
965 if (!rn2(25)) randomamount += rnz(2);
966 if (!rn2(125)) randomamount += rnz(5);
967 if (!rn2(625)) randomamount += rnz(20);
968 if (!rn2(3125)) randomamount += rnz(50);
970 if (rn2(5)) randomamount = 0;
972 while (randomamount) {
973 randomamount--;
974 randomx = rn1(COLNO-3,2);
975 randomy = rn2(ROWNO);
976 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
977 levl[randomx][randomy].typ = SHIFTINGSAND;
978 del_engr_at(randomx, randomy);
980 if ((mtmp = m_at(randomx, randomy)) != 0) {
981 (void) minliquid(mtmp);
982 } else {
983 newsym(randomx,randomy);
988 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
989 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
990 return;
992 (*(int *)poolcnt)++;
994 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
995 /* Put a pool at x, y */
996 levl[x][y].typ = SHIFTINGSAND;
997 del_engr_at(x, y);
999 if ((mtmp = m_at(x, y)) != 0) {
1000 (void) minliquid(mtmp);
1001 } else {
1002 newsym(x,y);
1004 } else if ((x == u.ux) && (y == u.uy)) {
1005 (*(int *)poolcnt)--;
1010 STATIC_PTR void
1011 do_styxfloodg(x, y, poolcnt)
1012 int x, y;
1013 void * poolcnt;
1015 register struct monst *mtmp;
1016 register struct trap *ttmp;
1017 int randomamount = 0;
1018 int randomx, randomy;
1019 if (!rn2(25)) randomamount += rnz(2);
1020 if (!rn2(125)) randomamount += rnz(5);
1021 if (!rn2(625)) randomamount += rnz(20);
1022 if (!rn2(3125)) randomamount += rnz(50);
1023 if (isaquarian) {
1024 if (!rn2(25)) randomamount += rnz(2);
1025 if (!rn2(125)) randomamount += rnz(5);
1026 if (!rn2(625)) randomamount += rnz(20);
1027 if (!rn2(3125)) randomamount += rnz(50);
1029 if (rn2(5)) randomamount = 0;
1031 while (randomamount) {
1032 randomamount--;
1033 randomx = rn1(COLNO-3,2);
1034 randomy = rn2(ROWNO);
1035 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1036 levl[randomx][randomy].typ = STYXRIVER;
1037 del_engr_at(randomx, randomy);
1039 if ((mtmp = m_at(randomx, randomy)) != 0) {
1040 (void) minliquid(mtmp);
1041 } else {
1042 newsym(randomx,randomy);
1047 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1048 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1049 return;
1051 (*(int *)poolcnt)++;
1053 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1054 /* Put a pool at x, y */
1055 levl[x][y].typ = STYXRIVER;
1056 del_engr_at(x, y);
1058 if ((mtmp = m_at(x, y)) != 0) {
1059 (void) minliquid(mtmp);
1060 } else {
1061 newsym(x,y);
1063 } else if ((x == u.ux) && (y == u.uy)) {
1064 (*(int *)poolcnt)--;
1069 STATIC_PTR void
1070 do_snowfloodg(x, y, poolcnt)
1071 int x, y;
1072 void * poolcnt;
1074 register struct monst *mtmp;
1075 register struct trap *ttmp;
1076 int randomamount = 0;
1077 int randomx, randomy;
1078 if (!rn2(25)) randomamount += rnz(2);
1079 if (!rn2(125)) randomamount += rnz(5);
1080 if (!rn2(625)) randomamount += rnz(20);
1081 if (!rn2(3125)) randomamount += rnz(50);
1082 if (isaquarian) {
1083 if (!rn2(25)) randomamount += rnz(2);
1084 if (!rn2(125)) randomamount += rnz(5);
1085 if (!rn2(625)) randomamount += rnz(20);
1086 if (!rn2(3125)) randomamount += rnz(50);
1088 if (rn2(5)) randomamount = 0;
1090 while (randomamount) {
1091 randomamount--;
1092 randomx = rn1(COLNO-3,2);
1093 randomy = rn2(ROWNO);
1094 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1095 levl[randomx][randomy].typ = SNOW;
1096 del_engr_at(randomx, randomy);
1098 if ((mtmp = m_at(randomx, randomy)) != 0) {
1099 (void) minliquid(mtmp);
1100 } else {
1101 newsym(randomx,randomy);
1106 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1107 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1108 return;
1110 (*(int *)poolcnt)++;
1112 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1113 /* Put a pool at x, y */
1114 levl[x][y].typ = SNOW;
1115 del_engr_at(x, y);
1117 if ((mtmp = m_at(x, y)) != 0) {
1118 (void) minliquid(mtmp);
1119 } else {
1120 newsym(x,y);
1122 } else if ((x == u.ux) && (y == u.uy)) {
1123 (*(int *)poolcnt)--;
1128 STATIC_PTR void
1129 do_ashfloodg(x, y, poolcnt)
1130 int x, y;
1131 void * poolcnt;
1133 register struct monst *mtmp;
1134 register struct trap *ttmp;
1135 int randomamount = 0;
1136 int randomx, randomy;
1137 if (!rn2(25)) randomamount += rnz(2);
1138 if (!rn2(125)) randomamount += rnz(5);
1139 if (!rn2(625)) randomamount += rnz(20);
1140 if (!rn2(3125)) randomamount += rnz(50);
1141 if (isaquarian) {
1142 if (!rn2(25)) randomamount += rnz(2);
1143 if (!rn2(125)) randomamount += rnz(5);
1144 if (!rn2(625)) randomamount += rnz(20);
1145 if (!rn2(3125)) randomamount += rnz(50);
1147 if (rn2(5)) randomamount = 0;
1149 while (randomamount) {
1150 randomamount--;
1151 randomx = rn1(COLNO-3,2);
1152 randomy = rn2(ROWNO);
1153 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1154 levl[randomx][randomy].typ = ASH;
1155 del_engr_at(randomx, randomy);
1157 if ((mtmp = m_at(randomx, randomy)) != 0) {
1158 (void) minliquid(mtmp);
1159 } else {
1160 newsym(randomx,randomy);
1165 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1166 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1167 return;
1169 (*(int *)poolcnt)++;
1171 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1172 /* Put a pool at x, y */
1173 levl[x][y].typ = ASH;
1174 del_engr_at(x, y);
1176 if ((mtmp = m_at(x, y)) != 0) {
1177 (void) minliquid(mtmp);
1178 } else {
1179 newsym(x,y);
1181 } else if ((x == u.ux) && (y == u.uy)) {
1182 (*(int *)poolcnt)--;
1187 STATIC_PTR void
1188 do_sandfloodg(x, y, poolcnt)
1189 int x, y;
1190 void * poolcnt;
1192 register struct monst *mtmp;
1193 register struct trap *ttmp;
1194 int randomamount = 0;
1195 int randomx, randomy;
1196 if (!rn2(25)) randomamount += rnz(2);
1197 if (!rn2(125)) randomamount += rnz(5);
1198 if (!rn2(625)) randomamount += rnz(20);
1199 if (!rn2(3125)) randomamount += rnz(50);
1200 if (isaquarian) {
1201 if (!rn2(25)) randomamount += rnz(2);
1202 if (!rn2(125)) randomamount += rnz(5);
1203 if (!rn2(625)) randomamount += rnz(20);
1204 if (!rn2(3125)) randomamount += rnz(50);
1206 if (rn2(5)) randomamount = 0;
1208 while (randomamount) {
1209 randomamount--;
1210 randomx = rn1(COLNO-3,2);
1211 randomy = rn2(ROWNO);
1212 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1213 levl[randomx][randomy].typ = SAND;
1214 del_engr_at(randomx, randomy);
1216 if ((mtmp = m_at(randomx, randomy)) != 0) {
1217 (void) minliquid(mtmp);
1218 } else {
1219 newsym(randomx,randomy);
1224 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1225 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1226 return;
1228 (*(int *)poolcnt)++;
1230 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1231 /* Put a pool at x, y */
1232 levl[x][y].typ = SAND;
1233 del_engr_at(x, y);
1235 if ((mtmp = m_at(x, y)) != 0) {
1236 (void) minliquid(mtmp);
1237 } else {
1238 newsym(x,y);
1240 } else if ((x == u.ux) && (y == u.uy)) {
1241 (*(int *)poolcnt)--;
1246 STATIC_PTR void
1247 do_pavementfloodg(x, y, poolcnt)
1248 int x, y;
1249 void * poolcnt;
1251 register struct monst *mtmp;
1252 register struct trap *ttmp;
1253 int randomamount = 0;
1254 int randomx, randomy;
1255 if (!rn2(25)) randomamount += rnz(2);
1256 if (!rn2(125)) randomamount += rnz(5);
1257 if (!rn2(625)) randomamount += rnz(20);
1258 if (!rn2(3125)) randomamount += rnz(50);
1259 if (isaquarian) {
1260 if (!rn2(25)) randomamount += rnz(2);
1261 if (!rn2(125)) randomamount += rnz(5);
1262 if (!rn2(625)) randomamount += rnz(20);
1263 if (!rn2(3125)) randomamount += rnz(50);
1265 if (rn2(5)) randomamount = 0;
1267 while (randomamount) {
1268 randomamount--;
1269 randomx = rn1(COLNO-3,2);
1270 randomy = rn2(ROWNO);
1271 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1272 levl[randomx][randomy].typ = PAVEDFLOOR;
1273 del_engr_at(randomx, randomy);
1275 if ((mtmp = m_at(randomx, randomy)) != 0) {
1276 (void) minliquid(mtmp);
1277 } else {
1278 newsym(randomx,randomy);
1283 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1284 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1285 return;
1287 (*(int *)poolcnt)++;
1289 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1290 /* Put a pool at x, y */
1291 levl[x][y].typ = PAVEDFLOOR;
1292 del_engr_at(x, y);
1294 if ((mtmp = m_at(x, y)) != 0) {
1295 (void) minliquid(mtmp);
1296 } else {
1297 newsym(x,y);
1299 } else if ((x == u.ux) && (y == u.uy)) {
1300 (*(int *)poolcnt)--;
1305 STATIC_PTR void
1306 do_highwayfloodg(x, y, poolcnt)
1307 int x, y;
1308 void * poolcnt;
1310 register struct monst *mtmp;
1311 register struct trap *ttmp;
1312 int randomamount = 0;
1313 int randomx, randomy;
1314 if (!rn2(25)) randomamount += rnz(2);
1315 if (!rn2(125)) randomamount += rnz(5);
1316 if (!rn2(625)) randomamount += rnz(20);
1317 if (!rn2(3125)) randomamount += rnz(50);
1318 if (isaquarian) {
1319 if (!rn2(25)) randomamount += rnz(2);
1320 if (!rn2(125)) randomamount += rnz(5);
1321 if (!rn2(625)) randomamount += rnz(20);
1322 if (!rn2(3125)) randomamount += rnz(50);
1324 if (rn2(5)) randomamount = 0;
1326 while (randomamount) {
1327 randomamount--;
1328 randomx = rn1(COLNO-3,2);
1329 randomy = rn2(ROWNO);
1330 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1331 levl[randomx][randomy].typ = HIGHWAY;
1332 del_engr_at(randomx, randomy);
1334 if ((mtmp = m_at(randomx, randomy)) != 0) {
1335 (void) minliquid(mtmp);
1336 } else {
1337 newsym(randomx,randomy);
1342 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1343 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1344 return;
1346 (*(int *)poolcnt)++;
1348 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1349 /* Put a pool at x, y */
1350 levl[x][y].typ = HIGHWAY;
1351 del_engr_at(x, y);
1353 if ((mtmp = m_at(x, y)) != 0) {
1354 (void) minliquid(mtmp);
1355 } else {
1356 newsym(x,y);
1358 } else if ((x == u.ux) && (y == u.uy)) {
1359 (*(int *)poolcnt)--;
1364 STATIC_PTR void
1365 do_grassfloodg(x, y, poolcnt)
1366 int x, y;
1367 void * poolcnt;
1369 register struct monst *mtmp;
1370 register struct trap *ttmp;
1371 int randomamount = 0;
1372 int randomx, randomy;
1373 if (!rn2(25)) randomamount += rnz(2);
1374 if (!rn2(125)) randomamount += rnz(5);
1375 if (!rn2(625)) randomamount += rnz(20);
1376 if (!rn2(3125)) randomamount += rnz(50);
1377 if (isaquarian) {
1378 if (!rn2(25)) randomamount += rnz(2);
1379 if (!rn2(125)) randomamount += rnz(5);
1380 if (!rn2(625)) randomamount += rnz(20);
1381 if (!rn2(3125)) randomamount += rnz(50);
1383 if (rn2(5)) randomamount = 0;
1385 while (randomamount) {
1386 randomamount--;
1387 randomx = rn1(COLNO-3,2);
1388 randomy = rn2(ROWNO);
1389 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1390 levl[randomx][randomy].typ = GRASSLAND;
1391 del_engr_at(randomx, randomy);
1393 if ((mtmp = m_at(randomx, randomy)) != 0) {
1394 (void) minliquid(mtmp);
1395 } else {
1396 newsym(randomx,randomy);
1401 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1402 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1403 return;
1405 (*(int *)poolcnt)++;
1407 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1408 /* Put a pool at x, y */
1409 levl[x][y].typ = GRASSLAND;
1410 del_engr_at(x, y);
1412 if ((mtmp = m_at(x, y)) != 0) {
1413 (void) minliquid(mtmp);
1414 } else {
1415 newsym(x,y);
1417 } else if ((x == u.ux) && (y == u.uy)) {
1418 (*(int *)poolcnt)--;
1423 STATIC_PTR void
1424 do_nethermistfloodg(x, y, poolcnt)
1425 int x, y;
1426 void * poolcnt;
1428 register struct monst *mtmp;
1429 register struct trap *ttmp;
1430 int randomamount = 0;
1431 int randomx, randomy;
1432 if (!rn2(25)) randomamount += rnz(2);
1433 if (!rn2(125)) randomamount += rnz(5);
1434 if (!rn2(625)) randomamount += rnz(20);
1435 if (!rn2(3125)) randomamount += rnz(50);
1436 if (isaquarian) {
1437 if (!rn2(25)) randomamount += rnz(2);
1438 if (!rn2(125)) randomamount += rnz(5);
1439 if (!rn2(625)) randomamount += rnz(20);
1440 if (!rn2(3125)) randomamount += rnz(50);
1442 if (rn2(5)) randomamount = 0;
1444 while (randomamount) {
1445 randomamount--;
1446 randomx = rn1(COLNO-3,2);
1447 randomy = rn2(ROWNO);
1448 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1449 levl[randomx][randomy].typ = NETHERMIST;
1450 del_engr_at(randomx, randomy);
1452 if ((mtmp = m_at(randomx, randomy)) != 0) {
1453 (void) minliquid(mtmp);
1454 } else {
1455 newsym(randomx,randomy);
1460 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1461 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1462 return;
1464 (*(int *)poolcnt)++;
1466 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1467 /* Put a pool at x, y */
1468 levl[x][y].typ = NETHERMIST;
1469 del_engr_at(x, y);
1471 if ((mtmp = m_at(x, y)) != 0) {
1472 (void) minliquid(mtmp);
1473 } else {
1474 newsym(x,y);
1476 } else if ((x == u.ux) && (y == u.uy)) {
1477 (*(int *)poolcnt)--;
1482 STATIC_PTR void
1483 do_stalactitefloodg(x, y, poolcnt)
1484 int x, y;
1485 void * poolcnt;
1487 register struct monst *mtmp;
1488 register struct trap *ttmp;
1489 int randomamount = 0;
1490 int randomx, randomy;
1491 if (!rn2(25)) randomamount += rnz(2);
1492 if (!rn2(125)) randomamount += rnz(5);
1493 if (!rn2(625)) randomamount += rnz(20);
1494 if (!rn2(3125)) randomamount += rnz(50);
1495 if (isaquarian) {
1496 if (!rn2(25)) randomamount += rnz(2);
1497 if (!rn2(125)) randomamount += rnz(5);
1498 if (!rn2(625)) randomamount += rnz(20);
1499 if (!rn2(3125)) randomamount += rnz(50);
1501 if (rn2(5)) randomamount = 0;
1503 while (randomamount) {
1504 randomamount--;
1505 randomx = rn1(COLNO-3,2);
1506 randomy = rn2(ROWNO);
1507 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1508 levl[randomx][randomy].typ = STALACTITE;
1509 del_engr_at(randomx, randomy);
1511 if ((mtmp = m_at(randomx, randomy)) != 0) {
1512 (void) minliquid(mtmp);
1513 } else {
1514 newsym(randomx,randomy);
1519 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1520 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1521 return;
1523 (*(int *)poolcnt)++;
1525 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1526 /* Put a pool at x, y */
1527 levl[x][y].typ = STALACTITE;
1528 del_engr_at(x, y);
1530 if ((mtmp = m_at(x, y)) != 0) {
1531 (void) minliquid(mtmp);
1532 } else {
1533 newsym(x,y);
1535 } else if ((x == u.ux) && (y == u.uy)) {
1536 (*(int *)poolcnt)--;
1541 STATIC_PTR void
1542 do_cryptfloodg(x, y, poolcnt)
1543 int x, y;
1544 void * poolcnt;
1546 register struct monst *mtmp;
1547 register struct trap *ttmp;
1548 int randomamount = 0;
1549 int randomx, randomy;
1550 if (!rn2(25)) randomamount += rnz(2);
1551 if (!rn2(125)) randomamount += rnz(5);
1552 if (!rn2(625)) randomamount += rnz(20);
1553 if (!rn2(3125)) randomamount += rnz(50);
1554 if (isaquarian) {
1555 if (!rn2(25)) randomamount += rnz(2);
1556 if (!rn2(125)) randomamount += rnz(5);
1557 if (!rn2(625)) randomamount += rnz(20);
1558 if (!rn2(3125)) randomamount += rnz(50);
1560 if (rn2(5)) randomamount = 0;
1562 while (randomamount) {
1563 randomamount--;
1564 randomx = rn1(COLNO-3,2);
1565 randomy = rn2(ROWNO);
1566 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1567 levl[randomx][randomy].typ = CRYPTFLOOR;
1568 del_engr_at(randomx, randomy);
1570 if ((mtmp = m_at(randomx, randomy)) != 0) {
1571 (void) minliquid(mtmp);
1572 } else {
1573 newsym(randomx,randomy);
1578 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1579 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1580 return;
1582 (*(int *)poolcnt)++;
1584 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1585 /* Put a pool at x, y */
1586 levl[x][y].typ = CRYPTFLOOR;
1587 del_engr_at(x, y);
1589 if ((mtmp = m_at(x, y)) != 0) {
1590 (void) minliquid(mtmp);
1591 } else {
1592 newsym(x,y);
1594 } else if ((x == u.ux) && (y == u.uy)) {
1595 (*(int *)poolcnt)--;
1600 STATIC_PTR void
1601 do_bubblefloodg(x, y, poolcnt)
1602 int x, y;
1603 void * poolcnt;
1605 register struct monst *mtmp;
1606 register struct trap *ttmp;
1607 int randomamount = 0;
1608 int randomx, randomy;
1609 if (!rn2(25)) randomamount += rnz(2);
1610 if (!rn2(125)) randomamount += rnz(5);
1611 if (!rn2(625)) randomamount += rnz(20);
1612 if (!rn2(3125)) randomamount += rnz(50);
1613 if (isaquarian) {
1614 if (!rn2(25)) randomamount += rnz(2);
1615 if (!rn2(125)) randomamount += rnz(5);
1616 if (!rn2(625)) randomamount += rnz(20);
1617 if (!rn2(3125)) randomamount += rnz(50);
1619 if (rn2(5)) randomamount = 0;
1621 while (randomamount) {
1622 randomamount--;
1623 randomx = rn1(COLNO-3,2);
1624 randomy = rn2(ROWNO);
1625 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1626 levl[randomx][randomy].typ = BUBBLES;
1627 blockorunblock_point(randomx,randomy);
1628 del_engr_at(randomx, randomy);
1630 if ((mtmp = m_at(randomx, randomy)) != 0) {
1631 (void) minliquid(mtmp);
1632 } else {
1633 newsym(randomx,randomy);
1638 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1639 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1640 return;
1642 (*(int *)poolcnt)++;
1644 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1645 /* Put a pool at x, y */
1646 levl[x][y].typ = BUBBLES;
1647 blockorunblock_point(x,y);
1648 del_engr_at(x, y);
1650 if ((mtmp = m_at(x, y)) != 0) {
1651 (void) minliquid(mtmp);
1652 } else {
1653 newsym(x,y);
1655 } else if ((x == u.ux) && (y == u.uy)) {
1656 (*(int *)poolcnt)--;
1661 STATIC_PTR void
1662 do_raincloudfloodg(x, y, poolcnt)
1663 int x, y;
1664 void * poolcnt;
1666 register struct monst *mtmp;
1667 register struct trap *ttmp;
1668 int randomamount = 0;
1669 int randomx, randomy;
1670 if (!rn2(25)) randomamount += rnz(2);
1671 if (!rn2(125)) randomamount += rnz(5);
1672 if (!rn2(625)) randomamount += rnz(20);
1673 if (!rn2(3125)) randomamount += rnz(50);
1674 if (isaquarian) {
1675 if (!rn2(25)) randomamount += rnz(2);
1676 if (!rn2(125)) randomamount += rnz(5);
1677 if (!rn2(625)) randomamount += rnz(20);
1678 if (!rn2(3125)) randomamount += rnz(50);
1680 if (rn2(5)) randomamount = 0;
1682 while (randomamount) {
1683 randomamount--;
1684 randomx = rn1(COLNO-3,2);
1685 randomy = rn2(ROWNO);
1686 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1687 levl[randomx][randomy].typ = RAINCLOUD;
1688 blockorunblock_point(randomx,randomy);
1689 del_engr_at(randomx, randomy);
1691 if ((mtmp = m_at(randomx, randomy)) != 0) {
1692 (void) minliquid(mtmp);
1693 } else {
1694 newsym(randomx,randomy);
1699 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1700 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1701 return;
1703 (*(int *)poolcnt)++;
1705 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1706 /* Put a pool at x, y */
1707 levl[x][y].typ = RAINCLOUD;
1708 blockorunblock_point(x,y);
1709 del_engr_at(x, y);
1711 if ((mtmp = m_at(x, y)) != 0) {
1712 (void) minliquid(mtmp);
1713 } else {
1714 newsym(x,y);
1716 } else if ((x == u.ux) && (y == u.uy)) {
1717 (*(int *)poolcnt)--;
1722 STATIC_PTR void
1723 do_cloudfloodg(x, y, poolcnt)
1724 int x, y;
1725 void * poolcnt;
1727 register struct monst *mtmp;
1728 register struct trap *ttmp;
1729 int randomamount = 0;
1730 int randomx, randomy;
1731 if (!rn2(25)) randomamount += rnz(2);
1732 if (!rn2(125)) randomamount += rnz(5);
1733 if (!rn2(625)) randomamount += rnz(20);
1734 if (!rn2(3125)) randomamount += rnz(50);
1735 if (isaquarian) {
1736 if (!rn2(25)) randomamount += rnz(2);
1737 if (!rn2(125)) randomamount += rnz(5);
1738 if (!rn2(625)) randomamount += rnz(20);
1739 if (!rn2(3125)) randomamount += rnz(50);
1741 if (rn2(5)) randomamount = 0;
1743 while (randomamount) {
1744 randomamount--;
1745 randomx = rn1(COLNO-3,2);
1746 randomy = rn2(ROWNO);
1747 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1748 levl[randomx][randomy].typ = CLOUD;
1749 blockorunblock_point(randomx,randomy);
1750 del_engr_at(randomx, randomy);
1752 if ((mtmp = m_at(randomx, randomy)) != 0) {
1753 (void) minliquid(mtmp);
1754 } else {
1755 newsym(randomx,randomy);
1760 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1761 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1762 return;
1764 (*(int *)poolcnt)++;
1766 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1767 /* Put a pool at x, y */
1768 levl[x][y].typ = CLOUD;
1769 blockorunblock_point(x,y);
1770 del_engr_at(x, y);
1772 if ((mtmp = m_at(x, y)) != 0) {
1773 (void) minliquid(mtmp);
1774 } else {
1775 newsym(x,y);
1777 } else if ((x == u.ux) && (y == u.uy)) {
1778 (*(int *)poolcnt)--;
1783 STATIC_PTR void
1784 do_terrainfloodg(x, y, poolcnt)
1785 int x, y;
1786 void * poolcnt;
1788 register struct monst *mtmp;
1789 register struct trap *ttmp;
1790 int randomamount = 0;
1791 int randomx, randomy;
1792 if (!rn2(25)) randomamount += rnz(2);
1793 if (!rn2(125)) randomamount += rnz(5);
1794 if (!rn2(625)) randomamount += rnz(20);
1795 if (!rn2(3125)) randomamount += rnz(50);
1796 if (isaquarian) {
1797 if (!rn2(25)) randomamount += rnz(2);
1798 if (!rn2(125)) randomamount += rnz(5);
1799 if (!rn2(625)) randomamount += rnz(20);
1800 if (!rn2(3125)) randomamount += rnz(50);
1802 if (rn2(7)) randomamount = 0;
1804 while (randomamount) {
1805 randomamount--;
1806 randomx = rn1(COLNO-3,2);
1807 randomy = rn2(ROWNO);
1808 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1809 levl[randomx][randomy].typ = randomwalltype();
1810 blockorunblock_point(randomx,randomy);
1811 if (!(levl[randomx][randomy].wall_info & W_EASYGROWTH)) levl[randomx][randomy].wall_info |= W_HARDGROWTH;
1812 del_engr_at(randomx, randomy);
1814 if ((mtmp = m_at(randomx, randomy)) != 0) {
1815 (void) minliquid(mtmp);
1816 } else {
1817 newsym(randomx,randomy);
1822 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1823 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1824 return;
1826 (*(int *)poolcnt)++;
1828 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1829 /* Put a pool at x, y */
1830 levl[x][y].typ = randomwalltype();
1831 blockorunblock_point(x,y);
1832 if (!(levl[x][y].wall_info & W_EASYGROWTH)) levl[x][y].wall_info |= W_HARDGROWTH;
1833 del_engr_at(x, y);
1835 if ((mtmp = m_at(x, y)) != 0) {
1836 (void) minliquid(mtmp);
1837 } else {
1838 newsym(x,y);
1840 } else if ((x == u.ux) && (y == u.uy)) {
1841 (*(int *)poolcnt)--;
1846 STATIC_PTR void
1847 do_barfloodg(x, y, poolcnt)
1848 int x, y;
1849 void * poolcnt;
1851 register struct monst *mtmp;
1852 register struct trap *ttmp;
1853 int randomamount = 0;
1854 int randomx, randomy;
1855 if (!rn2(25)) randomamount += rnz(2);
1856 if (!rn2(125)) randomamount += rnz(5);
1857 if (!rn2(625)) randomamount += rnz(20);
1858 if (!rn2(3125)) randomamount += rnz(50);
1859 if (isaquarian) {
1860 if (!rn2(25)) randomamount += rnz(2);
1861 if (!rn2(125)) randomamount += rnz(5);
1862 if (!rn2(625)) randomamount += rnz(20);
1863 if (!rn2(3125)) randomamount += rnz(50);
1865 if (rn2(5)) randomamount = 0;
1867 while (randomamount) {
1868 randomamount--;
1869 randomx = rn1(COLNO-3,2);
1870 randomy = rn2(ROWNO);
1871 if (isok(randomx, randomy) && (levl[randomx][randomy].typ == ROOM || levl[randomx][randomy].typ == CORR) ) {
1872 levl[randomx][randomy].typ = IRONBARS;
1873 blockorunblock_point(randomx,randomy);
1874 del_engr_at(randomx, randomy);
1876 if ((mtmp = m_at(randomx, randomy)) != 0) {
1877 (void) minliquid(mtmp);
1878 } else {
1879 newsym(randomx,randomy);
1884 if ((rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1885 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y) )
1886 return;
1888 (*(int *)poolcnt)++;
1890 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1891 /* Put a pool at x, y */
1892 levl[x][y].typ = IRONBARS;
1893 blockorunblock_point(x,y);
1894 del_engr_at(x, y);
1896 if ((mtmp = m_at(x, y)) != 0) {
1897 (void) minliquid(mtmp);
1898 } else {
1899 newsym(x,y);
1901 } else if ((x == u.ux) && (y == u.uy)) {
1902 (*(int *)poolcnt)--;
1907 STATIC_PTR void
1908 do_lavafloodg(x, y, poolcnt)
1909 int x, y;
1910 void * poolcnt;
1912 register struct monst *mtmp;
1913 register struct trap *ttmp;
1915 if (/*nexttodoor(x, y) || */(rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1916 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y))
1917 return;
1919 (*(int *)poolcnt)++;
1921 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1922 /* Put a pool at x, y */
1923 levl[x][y].typ = LAVAPOOL;
1924 del_engr_at(x, y);
1926 if ((mtmp = m_at(x, y)) != 0) {
1927 (void) minliquid(mtmp);
1928 } else {
1929 newsym(x,y);
1931 } else if ((x == u.ux) && (y == u.uy)) {
1932 (*(int *)poolcnt)--;
1937 STATIC_PTR void
1938 do_floodg(x, y, poolcnt)
1939 int x, y;
1940 void * poolcnt;
1942 register struct monst *mtmp;
1943 register struct trap *ttmp;
1945 if (/*nexttodoor(x, y) || */(rn2(1 + distmin(u.ux, u.uy, x, y))) ||
1946 (sobj_at(BOULDER, x, y)) || (levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y))
1947 return;
1949 (*(int *)poolcnt)++;
1951 if (!((*(int *)poolcnt) && (x == u.ux) && (y == u.uy))) {
1952 /* Put a pool at x, y */
1953 levl[x][y].typ = POOL;
1954 del_engr_at(x, y);
1955 water_damage(level.objects[x][y], FALSE, TRUE);
1957 if ((mtmp = m_at(x, y)) != 0) {
1958 (void) minliquid(mtmp);
1959 } else {
1960 newsym(x,y);
1962 } else if ((x == u.ux) && (y == u.uy)) {
1963 (*(int *)poolcnt)--;
1968 /* special effects for The Book of the Dead */
1969 STATIC_OVL void
1970 deadbook(book2)
1971 struct obj *book2;
1973 struct monst *mtmp, *mtmp2;
1974 coord mm;
1976 You("turn the pages of the Book of the Dead...");
1977 makeknown(SPE_BOOK_OF_THE_DEAD);
1979 if (!u.bellimbued) {
1980 pline("But nothing happens. You faintly recall that this book will be an enigma to you until you finally imbue a certain 'silver bell'.");
1981 return;
1984 /* KMH -- Need ->known to avoid "_a_ Book of the Dead" */
1985 book2->known = 1;
1986 if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
1987 register struct obj *otmp;
1988 register boolean arti1_primed = FALSE, arti2_primed = FALSE,
1989 arti_cursed = FALSE;
1991 /* If your book becomes prime cursed or worse, the game should still be winnable --Amy */
1992 if(book2->cursed && rn2(2)) {
1993 pline_The("runes appear scrambled. You can't read them!");
1994 return;
1997 if(!u.uhave.bell || !u.uhave.menorah) {
1998 pline("A chill runs down your %s.", body_part(SPINE));
1999 if(!u.uhave.bell) You_hear("a faint chime...");
2000 if(!u.uhave.menorah) pline("Vlad's doppelganger is amused.");
2001 return;
2004 for(otmp = invent; otmp; otmp = otmp->nobj) {
2005 if(otmp->otyp == CANDELABRUM_OF_INVOCATION &&
2006 otmp->spe == 7 && otmp->lamplit) {
2007 if(!otmp->cursed || !issoviet) arti1_primed = TRUE;
2008 else arti_cursed = TRUE;
2010 if(otmp->otyp == BELL_OF_OPENING &&
2011 (moves - otmp->age) < 50L) { /* you rang it recently */
2012 if(!otmp->cursed || !issoviet) arti2_primed = TRUE;
2013 else arti_cursed = TRUE;
2017 if(arti_cursed && issoviet) { /* Nyah-nyah! --Amy */
2018 pline_The("invocation fails!");
2019 pline("At least one of your artifacts is cursed...");
2020 pline("Teper' vy bol'she ne mozhete pobezhdat' v igre, vy sovershenno glupyy igrok. Vy nikogda ne smozhete podnyat' proklyatiye, i on nikogda ne budet rabotat', poka kniga proklyata kha-kha-kha-kha-kha-kha BWAR KHAR KHAR!");
2021 } else if(arti1_primed && arti2_primed) {
2022 unsigned soon = (unsigned) d(2,6); /* time til next intervene() */
2024 /* successful invocation */
2025 mkinvokearea();
2026 u.uevent.invoked = 1;
2027 /* in case you haven't killed the Wizard yet, behave as if
2028 you just did */
2029 u.uevent.udemigod = 1; /* wizdead() */
2030 if (!u.udg_cnt || u.udg_cnt > soon) u.udg_cnt = soon;
2031 } else { /* at least one artifact not prepared properly */
2032 You("have a feeling that %s is amiss...", something);
2033 goto raise_dead;
2035 return;
2038 /* when not an invocation situation */
2039 if (book2->cursed) {
2040 raise_dead:
2042 You("raised the dead!");
2043 /* first maybe place a dangerous adversary */
2044 if (!rn2(3) && ((mtmp = makemon(&mons[PM_MASTER_LICH],
2045 u.ux, u.uy, NO_MINVENT)) != 0 ||
2046 (mtmp = makemon(&mons[PM_NALFESHNEE],
2047 u.ux, u.uy, NO_MINVENT)) != 0)) {
2048 mtmp->mpeaceful = 0;
2049 mtmp->mfrenzied = 1;
2050 set_malign(mtmp);
2052 /* next handle the affect on things you're carrying */
2053 (void) unturn_dead(&youmonst);
2054 /* last place some monsters around you */
2055 mm.x = u.ux;
2056 mm.y = u.uy;
2057 mkundead(&mm, TRUE, NO_MINVENT|MM_ANGRY|MM_FRENZIED, TRUE);
2058 badeffect();
2059 aggravate();
2060 } else if(book2->blessed) {
2061 for(mtmp = fmon; mtmp; mtmp = mtmp2) {
2062 mtmp2 = mtmp->nmon; /* tamedog() changes chain */
2063 if (DEADMONSTER(mtmp)) continue;
2065 if ((is_undead(mtmp->data) || mtmp->egotype_undead) && !mtmp->mfrenzied && cansee(mtmp->mx, mtmp->my)) {
2066 mtmp->mpeaceful = TRUE;
2067 if(sgn(mtmp->data->maligntyp) == sgn(u.ualign.type)
2068 && distu(mtmp->mx, mtmp->my) < 4)
2069 if (mtmp->mtame) {
2070 if (mtmp->mtame < 20)
2071 mtmp->mtame++;
2072 } else
2073 (void) tamedog(mtmp, (struct obj *)0, FALSE);
2074 else monflee(mtmp, rnd(10), FALSE, TRUE);
2077 /* Amy edit: infinite command undead would be way overpowered */
2078 unbless(book2);
2079 } else {
2080 switch(rn2(3)) {
2081 case 0:
2082 Your("ancestors are annoyed with you!");
2083 break;
2084 case 1:
2085 pline_The("headstones in the cemetery begin to move!");
2086 break;
2087 default:
2088 pline("Oh my! Your name appears in the book!");
2091 return;
2094 STATIC_PTR int
2095 learn()
2097 int i;
2098 short booktype;
2099 char splname[BUFSZ];
2100 boolean costly = TRUE;
2102 if (!book || !(carried(book) ||
2103 (book->where == OBJ_FLOOR &&
2104 book->ox == u.ux && book->oy == u.uy))) {
2105 /* maybe it was stolen or polymorphed? */
2106 do_reset_learn();
2107 return(0);
2109 /* JDS: lenses give 50% faster reading; 33% smaller read time */
2110 if (delay < end_delay && ublindf && ublindf->otyp == LENSES && rn2(2))
2111 delay++;
2112 if (delay < end_delay && ublindf && ublindf->otyp == RADIOGLASSES && rn2(2))
2113 delay++;
2114 if (delay < end_delay && ublindf && ublindf->otyp == SHIELD_PATE_GLASSES && rn2(2))
2115 delay++;
2116 if (delay < end_delay && ublindf && ublindf->otyp == BOSS_VISOR && rn2(2))
2117 delay++;
2119 if (Confusion && (book->otyp != SPE_BOOK_OF_THE_DEAD) && !(Conf_resist && rn2(StrongConf_resist ? 25 : 5)) && !rn2((Role_if(PM_LIBRARIAN) || Role_if(PM_PSYKER)) ? 500 : 50) ) { /* became confused while learning */
2121 (void) confused_book(book);
2122 book = 0; /* no longer studying */
2123 if ((delay - end_delay) < 0) {
2124 if (!issoviet) {
2126 register int actualdelay;
2127 actualdelay = rno(-(delay - end_delay));
2128 if (!isstunfish && (actualdelay > 0)) actualdelay = isqrt(actualdelay); /* a lot of reduction --Amy */
2130 nomul(-(actualdelay), "reading a confusing book", TRUE); /* remaining delay is uninterrupted */
2131 } else { /* soviet mode */
2132 nomul((delay - end_delay), "reading a confusing book", TRUE);
2133 pline("Vy tol'ko chto podpisal svoy smertnyy prigovor, potomu chto sovetskaya ne zabotitsya o igrovoy balans. Ne dazhe nebol'shoye nemnogo.");
2137 delay = end_delay;
2138 return(0);
2140 if (delay < end_delay) { /* not if (delay++), so at end delay == 0 */
2141 delay++;
2142 if (delay) return(1); /* still busy, Amy edit: to me it looks like the original code is not working correctly,
2143 * since "delay" can become 0 here and if you get interrupted, you lose a charge again! */
2145 exercise(A_WIS, TRUE); /* you're studying. */
2146 booktype = book->otyp;
2147 if(booktype == SPE_BOOK_OF_THE_DEAD) {
2148 deadbook(book);
2149 return(0);
2152 if(booktype == SPE_BLADE_ANGER) {
2153 impossible("player trying to read spellbook of blade anger");
2154 return 0;
2156 if(booktype == SPE_BEAMSWORD) {
2157 impossible("player trying to read spellbook of beamsword");
2158 return 0;
2160 if(booktype == SPE_DRAINING_ARROW) {
2161 impossible("player trying to read spellbook of draining arrow");
2162 return 0;
2164 if(booktype == SPE_MENSTRUATION) {
2165 impossible("player trying to read spellbook of menstruation");
2166 return 0;
2169 sprintf(splname, objects[booktype].oc_name_known ?
2170 "\"%s\"" : "the \"%s\" spell",
2171 OBJ_NAME(objects[booktype]) );
2172 for (i = 0; i < MAXSPELL; i++) {
2173 if (spellid(i) == booktype) {
2174 if (book->spestudied > MAX_SPELL_STUDY) {
2175 pline("This spellbook is too faint to be read anymore.");
2176 book->otyp = booktype = SPE_BLANK_PAPER;
2177 } else if (spellknow(i) <= MAX_CAN_STUDY) {
2178 Your("knowledge of that spell is keener.");
2180 if (book->oartifact == ART_SECRET_BOOK_OF_VENOM) {
2181 You("gain the secret knowledge of venom mixing!");
2182 learntech_or_leveltech(T_VENOM_MIXING, FROMOUTSIDE, 1);
2185 if (book->oartifact == ART_DOLCEVAIN) {
2186 u.thornspell += rnz(1000);
2187 You("grow a thorny hide!");
2190 if (book->oartifact == ART_KING_IN_YELLOW) {
2191 int kiypm;
2192 kiypm = dprince(rn2((int)A_LAWFUL+2) - 1);
2193 if (kiypm >= PM_ORCUS && kiypm <= PM_DEMOGORGON) u.conclusiocount++;
2194 if (kiypm && (kiypm != NON_PM)) {
2195 (void) makemon(&mons[kiypm], u.ux, u.uy, MM_ANGRY|MM_FRENZIED);
2196 pline("An angry demon is summoned!");
2200 if (book->oartifact == ART_IWA_ERWI) {
2201 int iwaerwi;
2202 if (rn2(2)) {
2203 if (objects[SPE_DEFUSING].oc_level < 8) objects[SPE_DEFUSING].oc_level++;
2204 } else {
2205 if (objects[SPE_DEFUSING].oc_level > 1) objects[SPE_DEFUSING].oc_level--;
2208 for (iwaerwi = 0; iwaerwi < MAXSPELL && spellid(iwaerwi) != NO_SPELL; iwaerwi++) {
2209 if (spellid(iwaerwi) == SPE_DEFUSING) {
2210 spl_book[iwaerwi].sp_lev = objects[SPE_DEFUSING].oc_level;
2214 pline("The level of the defusing spell has changed!");
2217 use_skill(P_MEMORIZATION, spellev(i));
2218 if (!rn2(3)) u.uenmax++;
2219 u.cnd_spellbookcount++;
2220 incrnknow(i, FALSE);
2221 if (book->oartifact == ART_YOU_CAN_HURT) {
2222 losehp( (u.uhpmax / 2) + 2, "being hurt by a spellbook", KILLED_BY);
2223 boostknow(i, 50000);
2224 You("can hurt, but the spell will last for a generous time.");
2226 if (book->oartifact == ART_BACKLASHPROTECT) {
2227 boostknow(i, 40000);
2228 pline_The("spell has a lot of memory now.");
2230 if (book->oartifact == ART_HEALING_RAIN_OBTAINED) {
2231 wonderspell(SPE_HEALING_RAIN);
2233 if (book->oartifact == ART_MULTIPLY_ME) {
2234 boostknow(i, Role_if(PM_OCCULT_MASTER) ? 40000 : 10000);
2235 pline_The("spell memory bonus was multiplied!");
2237 if (book->oartifact == ART_PAGAN_POETRY) {
2238 u.superspecialspell = booktype;
2239 pline_The("spell is your super special spell now.");
2241 if (book->oartifact == ART_LESSEE_DAT && Role_if(PM_ELECTRIC_MAGE)) {
2242 if (P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_ISRESTRICTED) {
2243 unrestrict_weapon_skill(P_ELEMENTAL_SPELL);
2244 pline("You can now learn the elemental spells skill.");
2245 } else if (P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_UNSKILLED) {
2246 unrestrict_weapon_skill(P_ELEMENTAL_SPELL);
2247 P_MAX_SKILL(P_ELEMENTAL_SPELL) = P_BASIC;
2248 pline("You can now learn the elemental spells skill.");
2249 } else if (rn2(2) && P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_BASIC) {
2250 P_MAX_SKILL(P_ELEMENTAL_SPELL) = P_SKILLED;
2251 pline("Your knowledge of the elemental spells skill increases.");
2252 } else if (!rn2(4) && P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_SKILLED) {
2253 P_MAX_SKILL(P_ELEMENTAL_SPELL) = P_EXPERT;
2254 pline("Your knowledge of the elemental spells skill increases.");
2255 } else if (!rn2(10) && P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_EXPERT) {
2256 P_MAX_SKILL(P_ELEMENTAL_SPELL) = P_MASTER;
2257 pline("Your knowledge of the elemental spells skill increases.");
2258 } else if (!rn2(100) && P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_MASTER) {
2259 P_MAX_SKILL(P_ELEMENTAL_SPELL) = P_GRAND_MASTER;
2260 pline("Your knowledge of the elemental spells skill increases.");
2261 } else if (!rn2(200) && P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_GRAND_MASTER) {
2262 P_MAX_SKILL(P_ELEMENTAL_SPELL) = P_SUPREME_MASTER;
2263 pline("Your knowledge of the elemental spells skill increases.");
2266 if (u.emynluincomplete) boostknow(i, 1000);
2267 if (uarmc && uarmc->oartifact == ART_READ_UP_ON_IT) boostknow(i, 20000);
2268 if (uarmg && itemhasappearance(uarmg, APP_RUNIC_GLOVES) && !rn2(2) ) incrnknow(i, FALSE);
2269 if (Role_if(PM_MAHOU_SHOUJO)) incrnknow(i, FALSE);
2270 book->spestudied++;
2272 if (!PlayerCannotUseSkills && P_SKILL(P_MEMORIZATION) >= P_BASIC) {
2274 char nervbuf[QBUFSZ];
2275 char thisisannoying = 0;
2277 if (!u.youhavememorized) {
2278 u.youhavememorized = TRUE;
2279 if (!iflags.memorizationknown) pline("You have the memorization skill, which allows you to gain extra spell memory for newly learned spells. Whenever you learn a spell, you are asked whether you want to use the skill to boost the new spell's memory. In the case of doubt you should ALWAYS ANSWER YES. If you answer no, you just throw the bonus away. (Exception is if you want a forgotten spell, but you only ever need one of those normally.)");
2282 if (!iflags.memorizationknown) sprintf(nervbuf, "Memorize this spell to add more spell memory? In the case of doubt you should always answer yes, unless you want the bonus to go to waste.");
2283 else sprintf(nervbuf, "Memorize this spell to add more spell memory?");
2284 thisisannoying = yn_function(nervbuf, ynqchars, 'y');
2285 if (thisisannoying != 'n') {
2287 int memoboost = 0;
2288 switch (P_SKILL(P_MEMORIZATION)) {
2289 case P_BASIC: memoboost = 2; break;
2290 case P_SKILLED: memoboost = 4; break;
2291 case P_EXPERT: memoboost = 6; break;
2292 case P_MASTER: memoboost = 8; break;
2293 case P_GRAND_MASTER: memoboost = 10; break;
2294 case P_SUPREME_MASTER: memoboost = 12; break;
2296 boostknow(i, memoboost * 1000);
2297 spl_book[i].sp_memorize = TRUE;
2298 pline("Spell memory increased! You gained %d%% extra spell memory.", memoboost * 10);
2299 } else {
2300 spl_book[i].sp_memorize = FALSE;
2301 pline("You decided to throw away the spell memory bonus. The spell was set to non-memorization mode. If you did that by mistake, you should open the spell menu and turn memorization for this spell back on so that it properly benefits from memorization skill.");
2306 if (end_delay) {
2307 boostknow(i, end_delay * ((book->spe > 0) ? 20 : 10));
2309 use_skill(spell_skilltype(book->otyp), end_delay / ((book->spe > 0) ? 10 : 20));
2311 exercise(A_WIS, TRUE); /* extra study */
2312 } else { /* MAX_CAN_STUDY < spellknow(i) <= MAX_SPELL_STUDY */
2313 You("know %s quite well already.", splname);
2314 costly = FALSE;
2316 /* make book become known even when spell is already
2317 known, in case amnesia made you forget the book */
2318 makeknown((int)booktype);
2319 break;
2320 } else if (spellid(i) == NO_SPELL) {
2321 spl_book[i].sp_id = booktype;
2322 spl_book[i].sp_lev = objects[booktype].oc_level;
2323 spl_book[i].sp_memorize = TRUE;
2324 use_skill(P_MEMORIZATION, spellev(i));
2325 if (!rn2(3)) u.uenmax++;
2326 u.cnd_spellbookcount++;
2327 incrnknow(i, TRUE);
2328 if (u.emynluincomplete) boostknow(i, 1000);
2329 if (uarmc && uarmc->oartifact == ART_READ_UP_ON_IT) boostknow(i, 20000);
2330 if (uarmg && itemhasappearance(uarmg, APP_RUNIC_GLOVES) && !rn2(2) ) incrnknow(i, TRUE);
2331 if (Role_if(PM_MAHOU_SHOUJO)) incrnknow(i, TRUE);
2332 book->spestudied++;
2333 You("have keen knowledge of the spell.");
2334 You(i > 0 ? "add %s to your repertoire." : "learn %s.",
2335 splname);
2336 if (book->oartifact == ART_SECRET_BOOK_OF_VENOM) {
2337 You("gain the secret knowledge of venom mixing!");
2338 learntech_or_leveltech(T_VENOM_MIXING, FROMOUTSIDE, 1);
2340 if (book->oartifact == ART_DOLCEVAIN) {
2341 u.thornspell += rnz(1000);
2342 You("grow a thorny hide!");
2344 if (book->oartifact == ART_KING_IN_YELLOW) {
2345 int kiypm;
2346 kiypm = dprince(rn2((int)A_LAWFUL+2) - 1);
2347 if (kiypm >= PM_ORCUS && kiypm <= PM_DEMOGORGON) u.conclusiocount++;
2348 if (kiypm && (kiypm != NON_PM)) {
2349 (void) makemon(&mons[kiypm], u.ux, u.uy, MM_ANGRY|MM_FRENZIED);
2350 pline("An angry demon is summoned!");
2353 if (book->oartifact == ART_YOU_CAN_HURT) {
2354 losehp( (u.uhpmax / 2) + 2, "being hurt by a spellbook", KILLED_BY);
2355 boostknow(i, 50000);
2356 You("can hurt, but the spell will last for a generous time.");
2358 if (book->oartifact == ART_HEALING_RAIN_OBTAINED) {
2359 wonderspell(SPE_HEALING_RAIN);
2361 if (book->oartifact == ART_BACKLASHPROTECT) {
2362 boostknow(i, 40000);
2363 pline_The("spell has a lot of memory now.");
2365 if (book->oartifact == ART_MULTIPLY_ME) {
2366 boostknow(i, Role_if(PM_OCCULT_MASTER) ? 40000 : 10000);
2367 pline_The("spell memory bonus was multiplied!");
2369 if (book->oartifact == ART_PAGAN_POETRY) {
2370 u.superspecialspell = booktype;
2371 pline_The("spell is your super special spell now.");
2374 if (book->oartifact == ART_LESSEE_DAT && Role_if(PM_ELECTRIC_MAGE)) {
2375 if (P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_ISRESTRICTED) {
2376 unrestrict_weapon_skill(P_ELEMENTAL_SPELL);
2377 pline("You can now learn the elemental spells skill.");
2378 } else if (P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_UNSKILLED) {
2379 unrestrict_weapon_skill(P_ELEMENTAL_SPELL);
2380 P_MAX_SKILL(P_ELEMENTAL_SPELL) = P_BASIC;
2381 pline("You can now learn the elemental spells skill.");
2382 } else if (rn2(2) && P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_BASIC) {
2383 P_MAX_SKILL(P_ELEMENTAL_SPELL) = P_SKILLED;
2384 pline("Your knowledge of the elemental spells skill increases.");
2385 } else if (!rn2(4) && P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_SKILLED) {
2386 P_MAX_SKILL(P_ELEMENTAL_SPELL) = P_EXPERT;
2387 pline("Your knowledge of the elemental spells skill increases.");
2388 } else if (!rn2(10) && P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_EXPERT) {
2389 P_MAX_SKILL(P_ELEMENTAL_SPELL) = P_MASTER;
2390 pline("Your knowledge of the elemental spells skill increases.");
2391 } else if (!rn2(100) && P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_MASTER) {
2392 P_MAX_SKILL(P_ELEMENTAL_SPELL) = P_GRAND_MASTER;
2393 pline("Your knowledge of the elemental spells skill increases.");
2394 } else if (!rn2(200) && P_MAX_SKILL(P_ELEMENTAL_SPELL) == P_GRAND_MASTER) {
2395 P_MAX_SKILL(P_ELEMENTAL_SPELL) = P_SUPREME_MASTER;
2396 pline("Your knowledge of the elemental spells skill increases.");
2400 if (book->oartifact == ART_IWA_ERWI) {
2401 int iwaerwi;
2402 if (rn2(2)) {
2403 if (objects[SPE_DEFUSING].oc_level < 8) objects[SPE_DEFUSING].oc_level++;
2404 } else {
2405 if (objects[SPE_DEFUSING].oc_level > 1) objects[SPE_DEFUSING].oc_level--;
2407 for (iwaerwi = 0; iwaerwi < MAXSPELL && spellid(iwaerwi) != NO_SPELL; iwaerwi++) {
2408 if (spellid(iwaerwi) == SPE_DEFUSING) {
2409 spl_book[iwaerwi].sp_lev = objects[SPE_DEFUSING].oc_level;
2412 pline("The level of the defusing spell has changed!");
2414 if (booktype == SPE_FORBIDDEN_KNOWLEDGE) {
2415 u.ugangr += 15;
2416 if (flags.soundok) You_hear("a thunderous growling and rumbling...");
2417 if (PlayerHearsSoundEffects) pline(issoviet ? "Pozdravlyayu, teper' vashe bozhestvo ochen' zol. Pochemu ty ne molish'sya? Eto mozhet byt' prosto privesti svoyu zhizn' do kontsa, a zatem vy mozhete svernut' luchshe, nesovetskimi kharakter nakonets-to! SDELAY ETO SEYCHAS!" : "Grrrrrrr! Grummel! Wummmmmm!");
2420 makeknown((int)booktype);
2421 if (booktype == SPE_AMNESIA) {
2422 You_feel("dizzy!");
2423 forget(ALL_MAP, FALSE);
2426 if (!PlayerCannotUseSkills && P_SKILL(P_MEMORIZATION) >= P_BASIC) {
2428 char nervbuf[QBUFSZ];
2429 char thisisannoying = 0;
2431 if (!u.youhavememorized) {
2432 u.youhavememorized = TRUE;
2433 if (!iflags.memorizationknown) pline("You have the memorization skill, which allows you to gain extra spell memory for newly learned spells. Whenever you learn a spell, you are asked whether you want to use the skill to boost the new spell's memory. In the case of doubt you should ALWAYS ANSWER YES. If you answer no, you just throw the bonus away. (Exception is if you want a forgotten spell, but you only ever need one of those normally.)");
2436 if (!iflags.memorizationknown) sprintf(nervbuf, "Memorize this spell to add more spell memory? In the case of doubt you should always answer yes, unless you want the bonus to go to waste.");
2437 else sprintf(nervbuf, "Memorize this spell to add more spell memory?");
2438 thisisannoying = yn_function(nervbuf, ynqchars, 'y');
2439 if (thisisannoying != 'n') {
2441 int memoboost = 0;
2442 switch (P_SKILL(P_MEMORIZATION)) {
2443 case P_BASIC: memoboost = 2; break;
2444 case P_SKILLED: memoboost = 4; break;
2445 case P_EXPERT: memoboost = 6; break;
2446 case P_MASTER: memoboost = 8; break;
2447 case P_GRAND_MASTER: memoboost = 10; break;
2448 case P_SUPREME_MASTER: memoboost = 12; break;
2450 boostknow(i, memoboost * 1000);
2451 spl_book[i].sp_memorize = TRUE;
2452 pline("Spell memory increased! You gained %d%% extra spell memory.", memoboost * 10);
2453 } else {
2454 spl_book[i].sp_memorize = FALSE;
2455 pline("You decided to throw away the spell memory bonus. The spell was set to non-memorization mode. If you did that by mistake, you should open the spell menu and turn memorization for this spell back on so that it properly benefits from memorization skill.");
2460 break;
2463 if (i == MAXSPELL) impossible("Too many spells memorized!");
2465 if ( (book->cursed || book->spe < 1) && !(uimplant && uimplant->oartifact == ART_DOMPFINATION) && !Role_if(PM_LIBRARIAN) && !Role_if(PM_PSYKER) && !(booktype == SPE_BOOK_OF_THE_DEAD) ) { /* maybe a demon cursed it */
2466 if (cursed_book(book)) {
2467 if (carried(book)) useup(book);
2468 else useupf(book, 1L);
2469 pline_The("book falls apart.");
2470 book = 0;
2471 return 0;
2474 if (costly) check_unpaid(book);
2475 book = 0;
2476 return(0);
2480 study_book(spellbook)
2481 register struct obj *spellbook;
2483 register int booktype = spellbook->otyp;
2484 register boolean confused = ((Confusion != 0) && !(Conf_resist && (StrongConf_resist ? rn2(3) : !rn2(3)) ));
2485 boolean too_hard = FALSE;
2487 if (delay && !confused && spellbook == book &&
2488 /* handle the sequence: start reading, get interrupted,
2489 have book become erased somehow, resume reading it */
2490 booktype != SPE_BLANK_PAPER) {
2491 You("continue your efforts to memorize the spell.");
2492 if (AutoDestruct || u.uprops[AUTO_DESTRUCT].extrinsic || (uarmf && uarmf->oartifact == ART_KHOR_S_REQUIRED_IDEA) || have_autodestructstone() || (uchain && uchain->oartifact == ART_SIYID) ) learn();
2493 } else {
2494 /* KMH -- Simplified this code */
2495 if (booktype == SPE_BLANK_PAPER) {
2496 pline("This spellbook is all blank.");
2497 makeknown(booktype);
2498 return(1);
2501 if (ACURR(A_INT) == 1 && !rn2(4)) {
2503 check_unpaid_usage(spellbook, TRUE);
2504 pline("%s", generate_garbage_string());
2507 const char *line;
2508 char buflin[BUFSZ];
2509 if (rn2(2)) line = getrumor(-1, buflin, TRUE);
2510 else line = getrumor(0, buflin, TRUE);
2511 if (!*line) line = "Slash'EM rumors file closed for renovation.";
2512 pline("%s", line);
2515 pline("%s", generate_garbage_string());
2517 consume_obj_charge(spellbook, FALSE); /* even if you have good devices skill --Amy */
2519 if (!rn2(2)) pline("%s", generate_garbage_string());
2520 if (!rn2(5)) {
2521 badeffect();
2522 pline("%s", generate_garbage_string());
2524 spellbook->in_use = FALSE;
2526 return(1);
2529 if (spellbook->spe > 0 && confused && rn2((Role_if(PM_LIBRARIAN) || Role_if(PM_PSYKER)) ? 2 : 10) ) {
2530 check_unpaid_usage(spellbook, TRUE);
2532 int nochargechange = 10;
2533 if (!(PlayerCannotUseSkills)) {
2534 switch (P_SKILL(P_DEVICES)) {
2535 default: break;
2536 case P_BASIC: nochargechange = 9; break;
2537 case P_SKILLED: nochargechange = 8; break;
2538 case P_EXPERT: nochargechange = 7; break;
2539 case P_MASTER: nochargechange = 6; break;
2540 case P_GRAND_MASTER: nochargechange = 5; break;
2541 case P_SUPREME_MASTER: nochargechange = 4; break;
2545 if (nochargechange >= rnd(10)) consume_obj_charge(spellbook, FALSE);
2547 use_skill(P_DEVICES,1);
2548 if (Race_if(PM_FAWN)) {
2549 use_skill(P_DEVICES,1);
2551 if (Race_if(PM_SATRE)) {
2552 use_skill(P_DEVICES,1);
2553 use_skill(P_DEVICES,1);
2556 pline_The("words on the page seem to glow faintly purple.");
2557 You_cant("quite make them out.");
2558 return 1;
2559 } else if (spellbook->spe == 0) spellbook->spe--;
2561 switch (objects[booktype].oc_level) {
2562 case 1:
2563 case 2:
2564 delay = -objects[booktype].oc_delay;
2565 break;
2566 case 3:
2567 case 4:
2568 delay = -(objects[booktype].oc_level - 1) *
2569 objects[booktype].oc_delay;
2570 break;
2571 case 5:
2572 case 6:
2573 delay = -objects[booktype].oc_level *
2574 objects[booktype].oc_delay;
2575 break;
2576 case 7:
2577 delay = -8 * objects[booktype].oc_delay;
2578 break;
2579 case 8:
2580 delay = -12 * objects[booktype].oc_delay;
2581 break;
2582 default:
2583 impossible("Unknown spellbook level %d, book %d;",
2584 objects[booktype].oc_level, booktype);
2585 return 0;
2588 /* Memorization skill by Amy: reduces the time required to read a spellbook, but not below 1 (obviously) */
2589 if (!PlayerCannotUseSkills && (delay < -1) && P_SKILL(P_MEMORIZATION) >= P_BASIC) {
2591 int memreduction = 100;
2593 switch (P_SKILL(P_MEMORIZATION)) {
2594 case P_BASIC: memreduction = 80; break;
2595 case P_SKILLED: memreduction = 60; break;
2596 case P_EXPERT: memreduction = 40; break;
2597 case P_MASTER: memreduction = 20; break;
2598 case P_GRAND_MASTER: memreduction = 10; break;
2599 case P_SUPREME_MASTER: memreduction = 5; break;
2602 delay *= memreduction;
2603 delay /= 100;
2604 if (delay > -1) delay = -1; /* fail safe */
2608 if (StrongBlind_resistance && delay < -1) {
2609 delay /= 2;
2610 if (delay > -1) delay = -1; /* fail safe */
2613 /* Books are often wiser than their readers (Rus.) */
2614 spellbook->in_use = TRUE;
2615 if (!spellbook->blessed &&
2616 spellbook->otyp != SPE_BOOK_OF_THE_DEAD) {
2617 if ( ((spellbook->cursed && rn2(4)) || (spellbook->spe < 1 && rn2(3)) ) && !Role_if(PM_LIBRARIAN) && !Role_if(PM_PSYKER) && booktype != SPE_BOOK_OF_THE_DEAD ) {
2618 too_hard = TRUE;
2619 } else {
2620 /* uncursed - chance to fail */
2621 int read_ability = ACURR(A_INT) + 4 + GushLevel/2
2622 - 2*objects[booktype].oc_level
2623 + ((ublindf && (ublindf->otyp == LENSES || ublindf->otyp == RADIOGLASSES || ublindf->otyp == SHIELD_PATE_GLASSES || ublindf->otyp == BOSS_VISOR)) ? 2 : 0);
2624 /* only wizards know if a spell is too difficult */
2625 /* Amy edit: others may randomly know it sometimes */
2626 if ((Role_if(PM_WIZARD) || !rn2(4)) && read_ability < 20 &&
2627 !confused && ((spellbook->spe < 1) || spellbook->cursed)) {
2628 char qbuf[QBUFSZ];
2629 sprintf(qbuf,
2630 "This spellbook is %sdifficult to comprehend. Continue?",
2631 (read_ability < 5 ? "extremely" : read_ability < 12 ? "very " : ""));
2632 if (yn(qbuf) != 'y') {
2633 spellbook->in_use = FALSE;
2634 return(1);
2637 /* its up to random luck now */
2638 if (rnd(20) > read_ability) {
2639 too_hard = TRUE;
2644 if ( (too_hard || rn2(2)) && !(booktype == SPE_BOOK_OF_THE_DEAD) && ( (spellbook->cursed && !Role_if(PM_LIBRARIAN) && !Role_if(PM_PSYKER) ) || ((spellbook->spe < 1) && !(booktype == SPE_BOOK_OF_THE_DEAD) ) )) {
2645 boolean gone = cursed_book(spellbook);
2647 if (delay < 0) {
2648 if (!issoviet) {
2650 register int actualdelay;
2651 actualdelay = rno(-(delay));
2652 if (!isstunfish && (actualdelay > 1)) actualdelay = isqrt(actualdelay); /* a lot of reduction */
2654 nomul(-(actualdelay), "reading a cursed book", TRUE); /* study time */
2655 } else { /* soviet mode */
2656 nomul((delay), "reading a cursed book", TRUE);
2657 pline("Vy tol'ko chto podpisal svoy smertnyy prigovor, potomu chto sovetskaya ne zabotitsya o igrovoy balans. Ne dazhe nebol'shoye nemnogo.");
2661 delay = 0;
2662 if(gone || (spellbook->spe < 0) || !rn2(5)) {
2663 if (!gone && !(booktype == SPE_BOOK_OF_THE_DEAD)) pline_The("spellbook crumbles to dust!");
2664 else if (!(booktype == SPE_BOOK_OF_THE_DEAD)) pline_The("spellbook has been destroyed.");
2665 if (!objects[spellbook->otyp].oc_name_known &&
2666 !objects[spellbook->otyp].oc_uname)
2667 docall(spellbook);
2668 if (carried(spellbook)) useup(spellbook);
2669 else useupf(spellbook, 1L);
2670 } else
2671 spellbook->in_use = FALSE;
2672 return(1);
2673 } else if (confused && !(Conf_resist && rn2(StrongConf_resist ? 25 : 5)) && !rn2((Role_if(PM_LIBRARIAN) || Role_if(PM_PSYKER)) ? 250 : 50) && spellbook->otyp != SPE_BOOK_OF_THE_DEAD) {
2674 if (!confused_book(spellbook)) {
2675 spellbook->in_use = FALSE;
2677 if (delay < 0) {
2678 if (!issoviet) {
2679 register int actualdelay;
2680 actualdelay = rno(-(delay));
2681 if (actualdelay > 1) actualdelay = isqrt(actualdelay); /* a lot of reduction */
2683 nomul(-(actualdelay), "reading a book while confused", TRUE);
2685 } else { /* soviet mode */
2686 nomul((delay), "reading a book while confused", TRUE);
2687 pline("Vy tol'ko chto podpisal svoy smertnyy prigovor, potomu chto sovetskaya ne zabotitsya o igrovoy balans. Ne dazhe nebol'shoye nemnogo.");
2690 delay = 0;
2691 return(1);
2693 spellbook->in_use = FALSE;
2695 /* The glowing words make studying easier */
2696 if (spellbook->otyp != SPE_BOOK_OF_THE_DEAD) {
2697 delay *= 2;
2698 if (spellbook->spe > 0) {
2699 check_unpaid_usage(spellbook, TRUE);
2701 int nochargechange = 10;
2702 if (!(PlayerCannotUseSkills)) {
2703 switch (P_SKILL(P_DEVICES)) {
2704 default: break;
2705 case P_BASIC: nochargechange = 9; break;
2706 case P_SKILLED: nochargechange = 8; break;
2707 case P_EXPERT: nochargechange = 7; break;
2708 case P_MASTER: nochargechange = 6; break;
2709 case P_GRAND_MASTER: nochargechange = 5; break;
2710 case P_SUPREME_MASTER: nochargechange = 4; break;
2714 if (nochargechange >= rnd(10)) consume_obj_charge(spellbook, FALSE);
2716 use_skill(P_DEVICES,1);
2717 if (Race_if(PM_FAWN)) {
2718 use_skill(P_DEVICES,1);
2720 if (Race_if(PM_SATRE)) {
2721 use_skill(P_DEVICES,1);
2722 use_skill(P_DEVICES,1);
2724 if (Role_if(PM_LIBRARIAN)) {
2725 use_skill(P_DEVICES,1);
2728 pline_The("words on the page seem to glow faintly.");
2729 if (!too_hard)
2730 delay /= 3;
2733 end_delay = 0; /* Changed if multi != 0 */
2735 #ifdef DEBUG
2736 pline("Delay: %i", delay);
2737 #endif
2738 if (multi) {
2739 /* Count == practice reading :) */
2740 char qbuf[QBUFSZ];
2742 if (multi + 1 > MAX_STUDY_TIME) multi = MAX_STUDY_TIME - 1;
2743 sprintf(qbuf, "Study for at least %i turns?", (multi+1));
2744 if (ynq(qbuf) != 'y') {
2745 multi = 0;
2746 return(1);
2748 if ((--multi) > (-delay)) end_delay = multi + delay;
2749 multi = 0;
2750 #ifdef DEBUG
2751 pline("end_delay: %i", end_delay);
2752 #endif
2755 You("begin to %s the runes.",
2756 spellbook->otyp == SPE_BOOK_OF_THE_DEAD ? "recite" :
2757 "memorize");
2760 book = spellbook;
2761 set_occupation(learn, "studying", 0);
2762 return(1);
2765 /* a spellbook has been destroyed or the character has changed levels;
2766 the stored address for the current book is no longer valid */
2767 void
2768 book_disappears(obj)
2769 struct obj *obj;
2771 if (obj == book) book = (struct obj *)0;
2774 /* renaming an object usually results in it having a different address;
2775 so the sequence start reading, get interrupted, name the book, resume
2776 reading would read the "new" book from scratch */
2777 void
2778 book_substitution(old_obj, new_obj)
2779 struct obj *old_obj, *new_obj;
2781 if (old_obj == book) book = new_obj;
2784 static void
2785 do_reset_learn()
2787 stop_occupation();
2790 /* called from moveloop() */
2791 void
2792 age_spells()
2794 int i;
2795 if (Keen_memory && !rn2(StrongKeen_memory ? 3 : 5)) /* sync this with cyan spells, see below! --Amy */
2796 return;
2798 if (uarm && uarm->oartifact == ART_COPE_OF_THE_ELDRITCH_KNIGH && rn2(2)) return;
2800 if (uarms && uarms->oartifact == ART_UNUSUAL_ENCH && !rn2(5)) return;
2802 /* the spell color trap that causes your memory to decrease when casting shouldn't be too awfully harsh... --Amy
2803 * ATTENTION: cyan spells reduces memory when casting, please keep that synchronized!!! */
2804 if (SpellColorCyan && rn2(10))
2805 return;
2808 * The time relative to the hero (a pass through move
2809 * loop) causes all spell knowledge to be decremented.
2810 * The hero's speed, rest status, conscious status etc.
2811 * does not alter the loss of memory.
2813 for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++)
2814 if (spellknow(i) ) {
2816 if (!(uarmc && itemhasappearance(uarmc, APP_GUILD_CLOAK) ) && !tech_inuse(T_SPELL_SPAM) ) {
2818 /* 10000 turns is nothing compared to the length of the game; have it last longer, please! --Amy */
2819 if (spellmemorize(i) && !rn2(2)) continue;
2821 /* higher spell retention means your char is more of a caster and should therefore benefit --Amy */
2822 if (spellmemorize(i) && (rnd(urole.spelrete + 100) > 100) ) continue;
2824 /* higher intelligence was doing nothing??? come on! --Amy */
2825 if (spellmemorize(i) && ACURR(A_INT) > 14) {
2826 int intelsave = ACURR(A_INT) - 14;
2827 if (intelsave > rn2(66)) continue;
2830 /* Memorization skill by Amy: if the spell is set to memorization mode, have a skill-based chance here
2831 * that on any given turn the spell memory will not decrease.
2832 * cyan spells uses the same calculation below, any changes need to go into that function as well */
2834 if (!PlayerCannotUseSkills && spellmemorize(i) && P_SKILL(P_MEMORIZATION) >= P_BASIC) {
2836 int savememochance = 0;
2838 switch (P_SKILL(P_MEMORIZATION)) {
2839 case P_BASIC: savememochance = 1; break;
2840 case P_SKILLED: savememochance = 2; break;
2841 case P_EXPERT: savememochance = 3; break;
2842 case P_MASTER: savememochance = 4; break;
2843 case P_GRAND_MASTER: savememochance = 5; break;
2844 case P_SUPREME_MASTER: savememochance = 6; break;
2847 if (savememochance > rn2(10)) continue;
2851 if (!PlayerCannotUseSkills && spellmemorize(i) && P_SKILL(spell_skilltype(spellid(i))) >= P_BASIC) {
2853 int savememochance = 0;
2855 switch (P_SKILL(spell_skilltype(spellid(i)))) {
2856 case P_BASIC: savememochance = 1; break;
2857 case P_SKILLED: savememochance = 2; break;
2858 case P_EXPERT: savememochance = 3; break;
2859 case P_MASTER: savememochance = 4; break;
2860 case P_GRAND_MASTER: savememochance = 5; break;
2861 case P_SUPREME_MASTER: savememochance = 6; break;
2864 if (savememochance > rn2(20)) continue;
2868 decrnknow(i);
2871 if (SpellForgetting || u.uprops[SPELL_FORGETTING].extrinsic || have_spellforgettingstone()) {
2872 if (spellknow(i)) decrnknow(i);
2873 if (spellknow(i)) decrnknow(i);
2874 if (spellknow(i)) decrnknow(i);
2875 if (spellknow(i)) decrnknow(i);
2876 if (spellknow(i)) decrnknow(i);
2877 if (spellknow(i)) decrnknow(i);
2878 if (spellknow(i)) decrnknow(i);
2879 if (spellknow(i)) decrnknow(i);
2880 if (spellknow(i)) decrnknow(i);
2883 /* In Soviet Russia, people do not use magic very often, and so they definitely don't need any of those
2884 * completely superfluous messages telling them about spell memory. They already trashed the actual spell
2885 * memory display in the menu, so why the heck would they suddenly want to get messages about it? Hell no,
2886 * they prefer to suddenly discover their cure sickness spell was forgotten just as they're about to
2887 * cure that green slime effect on level 66 of Gehennom, after investing 500 hours into their character. --Amy */
2889 if (!issoviet && !SpellColorCyan && !(SpellForgetting || u.uprops[SPELL_FORGETTING].extrinsic || have_spellforgettingstone()) && !(SpellLoss || u.uprops[SPELLS_LOST].extrinsic || have_spelllossstone()) && spellknow(i) == 1000) pline("Your %s spell is beginning to fade from your memory.", spellname(i));
2890 if (!issoviet && !SpellColorCyan && !(SpellForgetting || u.uprops[SPELL_FORGETTING].extrinsic || have_spellforgettingstone()) && !(SpellLoss || u.uprops[SPELLS_LOST].extrinsic || have_spelllossstone()) && spellknow(i) == 100) pline("You are about to forget the %s spell.", spellname(i));
2891 if (!issoviet && !SpellColorCyan && !(SpellForgetting || u.uprops[SPELL_FORGETTING].extrinsic || have_spellforgettingstone()) && !(SpellLoss || u.uprops[SPELLS_LOST].extrinsic || have_spelllossstone()) && spellknow(i) == 0) pline("You no longer know how to cast the %s spell.", spellname(i));
2893 if (spellknow(i) && uarmc && itemhasappearance(uarmc, APP_FORGETFUL_CLOAK) ) {
2894 decrnknow(i);
2895 if (!issoviet && !SpellColorCyan && !(SpellForgetting || u.uprops[SPELL_FORGETTING].extrinsic || have_spellforgettingstone()) && !(SpellLoss || u.uprops[SPELLS_LOST].extrinsic || have_spelllossstone()) && spellknow(i) == 1000) pline("Your %s spell is beginning to fade from your memory.", spellname(i));
2896 if (!issoviet && !SpellColorCyan && !(SpellForgetting || u.uprops[SPELL_FORGETTING].extrinsic || have_spellforgettingstone()) && !(SpellLoss || u.uprops[SPELLS_LOST].extrinsic || have_spelllossstone()) && spellknow(i) == 100) pline("You are about to forget the %s spell.", spellname(i));
2897 if (!issoviet && !SpellColorCyan && !(SpellForgetting || u.uprops[SPELL_FORGETTING].extrinsic || have_spellforgettingstone()) && !(SpellLoss || u.uprops[SPELLS_LOST].extrinsic || have_spelllossstone()) && spellknow(i) == 0) pline("You no longer know how to cast the %s spell.", spellname(i));
2901 if (spellknow(i) && RngeForgetting) {
2902 decrnknow(i);
2903 if (!issoviet && !SpellColorCyan && !(SpellForgetting || u.uprops[SPELL_FORGETTING].extrinsic || have_spellforgettingstone()) && !(SpellLoss || u.uprops[SPELLS_LOST].extrinsic || have_spelllossstone()) && spellknow(i) == 1000) pline("Your %s spell is beginning to fade from your memory.", spellname(i));
2904 if (!issoviet && !SpellColorCyan && !(SpellForgetting || u.uprops[SPELL_FORGETTING].extrinsic || have_spellforgettingstone()) && !(SpellLoss || u.uprops[SPELLS_LOST].extrinsic || have_spelllossstone()) && spellknow(i) == 100) pline("You are about to forget the %s spell.", spellname(i));
2905 if (!issoviet && !SpellColorCyan && !(SpellForgetting || u.uprops[SPELL_FORGETTING].extrinsic || have_spellforgettingstone()) && !(SpellLoss || u.uprops[SPELLS_LOST].extrinsic || have_spelllossstone()) && spellknow(i) == 0) pline("You no longer know how to cast the %s spell.", spellname(i));
2910 return;
2914 * Return TRUE if a spell was picked, with the spell index in the return
2915 * parameter. Otherwise return FALSE.
2917 STATIC_OVL boolean
2918 getspell(spell_no, goldspellpossible)
2919 int *spell_no;
2920 boolean goldspellpossible;
2922 int nspells, idx, n, thisone, choicenumber;
2923 char ilet, lets[BUFSZ], qbuf[QBUFSZ];
2925 if (spellid(0) == NO_SPELL) {
2926 You("don't know any spells right now.");
2927 return FALSE;
2930 if ((Goldspells || u.uprops[GOLDSPELLS].extrinsic || have_goldspellstone()) && goldspellpossible && rn2(10)) {
2932 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
2933 continue;
2934 if (n) {
2935 thisone = -1;
2936 choicenumber = 0;
2937 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++) {
2938 if (!choicenumber || (!rn2(choicenumber + 1)) ) {
2939 thisone = n;
2941 choicenumber++;
2944 if (choicenumber > 0 && thisone >= 0) {
2945 pline("You cast %s.", spellname(thisone));
2946 spelleffects(thisone, FALSE);
2947 if (SpellColorPlatinum && u.uen < 0) {
2948 u.uenmax -= (0 - u.uen);
2949 if (u.uenmax < 0) {
2950 u.uhpmax -= (0 - u.uenmax);
2951 if (u.uhpmax < 1) u.uhpmax = 1;
2952 if (Upolyd) {
2953 u.mhmax -= (0 - u.uenmax);
2954 if (u.mhmax < 1) u.mhmax = 1;
2956 losehp((0 - u.uenmax) * 10, "overcasting a spell", KILLED_BY);
2957 u.uenmax = 0;
2959 u.uen = 0;
2960 if (u.uenmax < 0) u.uenmax = 0;
2962 TimerunBug += 1; /* ugh, ugly hack --Amy */
2963 return FALSE;
2966 /* we somehow didn't choose a spell */
2967 pline("You fail to cast a spell.");
2968 TimerunBug += 1; /* ugh, ugly hack --Amy */
2969 return FALSE;
2972 if (flags.menu_style == MENU_TRADITIONAL) {
2973 /* we know there is at least 1 known spell */
2974 for (nspells = 1; nspells < MAXSPELL
2975 && spellid(nspells) != NO_SPELL; nspells++)
2976 continue;
2978 if (nspells == 1) strcpy(lets, "a");
2979 else if (nspells < 27) sprintf(lets, "a-%c", 'a' + nspells - 1);
2980 else if (nspells == 27) sprintf(lets, "a-z A");
2981 else if (nspells < 53)
2982 sprintf(lets, "a-z A-%c", 'A' + nspells - 27);
2983 else if (nspells == 53) sprintf(lets, "a-z A-Z 0");
2984 else if (nspells < 78)
2985 sprintf(lets, "a-z A-Z 0-%c", '0' + nspells - 53);
2986 else sprintf(lets, "a-z A-Z 0-9");
2988 for(;;) {
2989 sprintf(qbuf, "Cast which spell? [%s ?]", lets);
2990 if ((ilet = yn_function(qbuf, (char *)0, '\0')) == '?')
2991 break;
2993 if (index(quitchars, ilet))
2994 return FALSE;
2996 idx = spell_let_to_idx(ilet);
2997 if (idx >= 0 && idx < nspells) {
2998 *spell_no = idx;
2999 return TRUE;
3000 } else
3001 You("don't know that spell.");
3004 if (SpellColorPink) return dospellmenu("Your spells are pink.", SPELLMENU_CAST, spell_no, 0);
3005 else if (SpellColorBrightCyan) return dospellmenu("Your spells are bright cyan.", SPELLMENU_CAST, spell_no, 0);
3006 else if (SpellColorCyan) return dospellmenu("Your spells are cyan.", SPELLMENU_CAST, spell_no, 0);
3007 else if (SpellColorBlack) return dospellmenu("Your spells are black.", SPELLMENU_CAST, spell_no, 0);
3008 else if (SpellColorOrange) return dospellmenu("Your spells are orange.", SPELLMENU_CAST, spell_no, 0);
3009 else if (SpellColorRed) return dospellmenu("Your spells are red.", SPELLMENU_CAST, spell_no, 0);
3010 else if (SpellColorPlatinum) return dospellmenu("Your spells are platinum.", SPELLMENU_CAST, spell_no, 0);
3011 else if (SpellColorSilver) return dospellmenu("Your spells are silver.", SPELLMENU_CAST, spell_no, 0);
3012 else if (SpellColorMetal) return dospellmenu("Your spells are metal.", SPELLMENU_CAST, spell_no, 0);
3013 else if (SpellColorGreen) return dospellmenu("Your spells are green.", SPELLMENU_CAST, spell_no, 0);
3014 else if (SpellColorBlue) return dospellmenu("Your spells are blue.", SPELLMENU_CAST, spell_no, 0);
3015 else if (SpellColorGray) return dospellmenu("Your spells are completely gray.", SPELLMENU_CAST, spell_no, 0);
3016 else if (SpellColorBrown) return dospellmenu("Your spells are brown.", SPELLMENU_CAST, spell_no, 0);
3017 else if (SpellColorWhite) return dospellmenu("Your spells are white.", SPELLMENU_CAST, spell_no, 0);
3018 else if (SpellColorViolet) return dospellmenu("Your spells are violet.", SPELLMENU_CAST, spell_no, 0);
3019 else if (SpellColorYellow) return dospellmenu("Your spells are yellow.", SPELLMENU_CAST, spell_no, 0);
3020 else return dospellmenu("Choose which spell to cast", SPELLMENU_CAST, spell_no, 0);
3024 /* the 'Z' command -- cast a spell */
3026 docast()
3028 int spell_no;
3030 int whatreturn;
3032 /* Amy note: use autismweaponcheck and not uwep here!!! after all, this is a *negative* effect */
3034 if (u.antimagicshell || (uarmh && uarmh->otyp == HELM_OF_ANTI_MAGIC) || (RngeAntimagicA && (moves % 10 == 0)) || (RngeAntimagicB && (moves % 5 == 0)) || (RngeAntimagicC && (moves % 2 == 0)) || (RngeAntimagicD) || (uarmc && uarmc->oartifact == ART_SHELLY && (moves % 3 == 0)) || (uarmc && uarmc->oartifact == ART_BLACK_VEIL_OF_BLACKNESS) || (uarmc && uarmc->oartifact == ART_ARABELLA_S_WAND_BOOSTER) || (uarmu && uarmu->oartifact == ART_ANTIMAGIC_SHELL) || autismweaponcheck(ART_LONG_SWORD_OF_ETERNITY) || autismweaponcheck(ART_HEAVY_CROSSBOW_OF_ETERNITY) || (uarmu && uarmu->oartifact == ART_ANTIMAGIC_FIELD) || (Role_if(PM_UNBELIEVER) && !(uwep && uwep->oartifact == ART_MAGE_STAFF_OF_ETERNITY) ) || autismweaponcheck(ART_ARK_OF_THE_COVENANT) || (uarmc && uarmc->oartifact == ART_SPELL_WARDED_WRAPPINGS_OF_) || autismweaponcheck(ART_ANTIMAGICBANE) ) {
3036 pline("Your anti-magic shell prevents spellcasting.");
3037 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3038 return 0;
3041 if (getspell(&spell_no, TRUE)) {
3043 /* Spellbinder allows you to cast several spells in one turn, but not the same spell twice --Amy */
3045 if (u.spellbinder) {
3046 if ((spell_no == u.spellbinder1) || (spell_no == u.spellbinder2) || (spell_no == u.spellbinder3) || (spell_no == u.spellbinder4) || (spell_no == u.spellbinder5) || (spell_no == u.spellbinder6) || (spell_no == u.spellbinder7)) {
3047 pline("You already bound the same spell in this turn, and therefore it fails!");
3048 return 0;
3050 if (u.spellbinder1 == -1) u.spellbinder1 = spell_no;
3051 else if (u.spellbinder2 == -1) u.spellbinder2 = spell_no;
3052 else if (u.spellbinder3 == -1) u.spellbinder3 = spell_no;
3053 else if (u.spellbinder4 == -1) u.spellbinder4 = spell_no;
3054 else if (u.spellbinder5 == -1) u.spellbinder5 = spell_no;
3055 else if (u.spellbinder6 == -1) u.spellbinder6 = spell_no;
3056 else if (u.spellbinder7 == -1) u.spellbinder7 = spell_no;
3059 whatreturn = spelleffects(spell_no, FALSE);
3061 if (SpellColorPlatinum && u.uen < 0) {
3062 u.uenmax -= (0 - u.uen);
3063 if (u.uenmax < 0) {
3064 u.uhpmax -= (0 - u.uenmax);
3065 if (u.uhpmax < 1) u.uhpmax = 1;
3066 if (Upolyd) {
3067 u.mhmax -= (0 - u.uenmax);
3068 if (u.mhmax < 1) u.mhmax = 1;
3070 losehp((0 - u.uenmax) * 10, "overcasting a spell", KILLED_BY);
3071 u.uenmax = 0;
3073 u.uen = 0;
3074 if (u.uenmax < 0) u.uenmax = 0;
3076 else if (u.uen < 0) {
3077 int manafiredamage = abs(u.uen);
3078 u.uen = 0;
3079 losehp(manafiredamage, "mana fire", KILLED_BY);
3080 You("took %d points of damage from mana fire.", manafiredamage);
3083 return whatreturn;
3085 return 0;
3088 void
3089 castinertiaspell()
3091 char buf[BUFSZ];
3092 char c;
3093 boolean willcastinertiaspell = FALSE;
3095 pline("You control the %s spell flow.", spellname(u.inertiacontrolspellno));
3097 if (flags.inertiaconfirm) {
3098 getlin ("Cast it? [y/yes/no/q/quit]",buf);
3099 (void) lcase (buf);
3100 if (!(strcmp (buf, "yes")) || !(strcmp (buf, "y")) || !(strcmp (buf, "ye")) || !(strcmp (buf, "ys"))) willcastinertiaspell = TRUE;
3101 if (!(strcmp (buf, "q")) || !(strcmp (buf, "quit"))) {
3102 You("ended inertia control prematurely.");
3103 u.inertiacontrol = 0;
3104 u.inertiacontrolspell = -1;
3105 u.inertiacontrolspellno = -1;
3106 return;
3108 } else {
3109 c = yn_function("Cast it?", ynqchars, 'n');
3110 if (c == 'y') willcastinertiaspell = TRUE;
3111 else if (c == 'q') {
3112 You("ended inertia control prematurely.");
3113 u.inertiacontrol = 0;
3114 u.inertiacontrolspell = -1;
3115 u.inertiacontrolspellno = -1;
3116 return;
3120 if (willcastinertiaspell) {
3122 if (spellid(u.inertiacontrolspellno) != u.inertiacontrolspell) {
3123 pline("The inertia controlled spell is no longer in place, and therefore cannot be auto-casted!");
3124 u.inertiacontrol = 0;
3125 u.inertiacontrolspell = -1;
3126 u.inertiacontrolspellno = -1;
3127 return;
3129 spelleffects(u.inertiacontrolspellno, FALSE);
3131 if (SpellColorPlatinum && u.uen < 0) {
3132 u.uenmax -= (0 - u.uen);
3133 if (u.uenmax < 0) {
3134 u.uhpmax -= (0 - u.uenmax);
3135 if (u.uhpmax < 1) u.uhpmax = 1;
3136 if (Upolyd) {
3137 u.mhmax -= (0 - u.uenmax);
3138 if (u.mhmax < 1) u.mhmax = 1;
3140 losehp((0 - u.uenmax) * 10, "overcasting a spell", KILLED_BY);
3141 u.uenmax = 0;
3143 u.uen = 0;
3144 if (u.uenmax < 0) u.uenmax = 0;
3150 STATIC_OVL const char*
3151 spelltypemnemonic(int skill)
3153 switch (skill) {
3154 case P_ATTACK_SPELL:
3155 return " attack";
3156 case P_HEALING_SPELL:
3157 return " healing";
3158 case P_DIVINATION_SPELL:
3159 return " divine";
3160 case P_ENCHANTMENT_SPELL:
3161 return " enchant";
3162 case P_PROTECTION_SPELL:
3163 return " protect";
3164 case P_BODY_SPELL:
3165 return " body";
3166 case P_OCCULT_SPELL:
3167 return " occult";
3168 case P_ELEMENTAL_SPELL:
3169 return "elemental";
3170 case P_CHAOS_SPELL:
3171 return " chaos";
3172 case P_MATTER_SPELL:
3173 return " matter";
3174 default:
3175 impossible("Unknown spell skill, %d;", skill);
3176 return "";
3181 spell_skilltype(booktype)
3182 int booktype;
3184 return (objects[booktype].oc_skill);
3187 STATIC_OVL void
3188 cast_protection()
3190 int loglev = 0;
3191 int l = GushLevel;
3192 int natac = u.uac - u.uspellprot;
3193 int gain;
3195 /* loglev=log2(u.ulevel)+1 (1..5) */
3196 while (l) {
3197 loglev++;
3198 l /= 2;
3201 /* The more u.uspellprot you already have, the less you get,
3202 * and the better your natural ac, the less you get.
3204 * LEVEL AC SPELLPROT from sucessive SPE_PROTECTION casts
3205 * 1 10 0, 1, 2, 3, 4
3206 * 1 0 0, 1, 2, 3
3207 * 1 -10 0, 1, 2
3208 * 2-3 10 0, 2, 4, 5, 6, 7, 8
3209 * 2-3 0 0, 2, 4, 5, 6
3210 * 2-3 -10 0, 2, 3, 4
3211 * 4-7 10 0, 3, 6, 8, 9, 10, 11, 12
3212 * 4-7 0 0, 3, 5, 7, 8, 9
3213 * 4-7 -10 0, 3, 5, 6
3214 * 7-15 -10 0, 3, 5, 6
3215 * 8-15 10 0, 4, 7, 10, 12, 13, 14, 15, 16
3216 * 8-15 0 0, 4, 7, 9, 10, 11, 12
3217 * 8-15 -10 0, 4, 6, 7, 8
3218 * 16-30 10 0, 5, 9, 12, 14, 16, 17, 18, 19, 20
3219 * 16-30 0 0, 5, 9, 11, 13, 14, 15
3220 * 16-30 -10 0, 5, 8, 9, 10
3222 gain = loglev - (int)u.uspellprot / (4 - min(3,(10 - natac)/10));
3223 if (Race_if(PM_MAYMES)) gain *= 2;
3225 if (gain > 0) {
3226 if (!Blind) {
3227 const char *hgolden = hcolor(NH_GOLDEN);
3229 if (u.uspellprot)
3230 pline_The("%s haze around you becomes more dense.",
3231 hgolden);
3232 else
3233 pline_The("%s around you begins to shimmer with %s haze.",
3234 /*[ what about being inside solid rock while polyd? ]*/
3235 (Underwater || Is_waterlevel(&u.uz)) ? "water" : "air",
3236 an(hgolden));
3238 u.uspellprot += gain;
3239 u.uspmtime =
3240 (!(PlayerCannotUseSkills) && P_SKILL(spell_skilltype(SPE_PROTECTION)) >= P_EXPERT) ? 20 : 10;
3242 if (Race_if(PM_MAYMES)) {
3243 u.uspmtime *= 2;
3246 if (!u.usptime)
3247 u.usptime = u.uspmtime;
3249 find_ac();
3250 } else {
3251 Your("skin feels warm for a moment.");
3255 STATIC_OVL void
3256 cast_reflection()
3258 if (HReflecting) {
3259 if (!Blind)
3260 pline("The shimmering globe around you becomes slightly brighter.");
3261 else
3262 You_feel("slightly more smooth.");
3263 } else {
3264 if (!Blind)
3265 pline("A shimmering globe appears around you!");
3266 else
3267 You_feel("smooth.");
3269 incr_itimeout(&HReflecting, rn1(10, HReflecting ? 4 : 30));
3273 /* attempting to cast a forgotten spell will cause disorientation */
3274 STATIC_OVL void
3275 spell_backfire(spell)
3276 int spell;
3278 long duration = (long)((spellev(spell) + 1) * 3); /* 6..24 */
3280 /* prior to 3.4.1, the only effect was confusion; it still predominates */
3281 if (!obsidianprotection()) switch (rn2(17)) {
3282 case 0:
3283 case 1:
3284 case 2:
3285 case 3: make_confused(HConfusion + duration, FALSE); /* 40% */
3286 break;
3287 case 4:
3288 case 5:
3289 case 6: make_confused(HConfusion + (2L * duration / 3L), FALSE); /* 30% */
3290 make_stunned(HStun + (duration / 3L), FALSE);
3291 break;
3292 case 7:
3293 case 8: make_stunned(HStun + (2L * duration / 3L), FALSE); /* 20% */
3294 make_confused(HConfusion + (duration / 3L), FALSE);
3295 break;
3296 case 9: make_stunned(HStun + duration, FALSE); /* 10% */
3297 break;
3298 case 10: make_numbed(HNumbed + duration, FALSE); /* 10% */
3299 break;
3300 case 11: make_frozen(HFrozen + duration, FALSE); /* 10% */
3301 break;
3302 case 12: make_burned(HBurned + duration, FALSE); /* 10% */
3303 break;
3304 case 13: make_feared(HFeared + duration, FALSE); /* 10% */
3305 break;
3306 case 14: make_blinded(Blinded + duration, FALSE); /* 10% */
3307 break;
3308 case 15: make_hallucinated(HHallucination + duration, FALSE, 0L); /* 10% */
3309 break;
3310 case 16: make_dimmed(HDimmed + duration, FALSE); /* 10% */
3311 break;
3313 return;
3317 spelleffects(spell, atme)
3318 int spell;
3319 boolean atme;
3321 int energy, damage, chance, n, intell;
3322 int hungr;
3323 int skill, role_skill;
3324 boolean confused = ((Confusion != 0) && !(Conf_resist && (StrongConf_resist ? rn2(3) : !rn2(3)) ) );
3325 struct obj *pseudo;
3326 struct obj *otmp;
3327 int confusionchance = 0;
3330 * Find the skill the hero has in a spell type category.
3331 * See spell_skilltype for categories.
3333 skill = spell_skilltype(spellid(spell));
3334 role_skill = P_SKILL(skill);
3335 if (PlayerCannotUseSkills) role_skill = P_ISRESTRICTED;
3338 * Spell casting no longer affects knowledge of the spell. A
3339 * decrement of spell knowledge is done every turn.
3341 if (spellknow(spell) <= 0) {
3343 /* overhaul by Amy: forgotten spells are no longer free, they cost Pw now and can fail or backfire
3344 * higher-level spells cost less mana to cast, THIS IS NOT AN ERROR, it's because those will also generally
3345 * have a higher fail rate, because I want there to be no easy answer for the question of "which is the best
3346 * spell to turn into a forgotten spell?" - low-level ones will have a low fail rate but cost much Pw,
3347 * high-level ones will have a high fail rate (unless you're a pretty good spellcaster) but cost little Pw */
3348 int forgottencost;
3349 forgottencost = ((9 - spellev(spell)) * 5);
3350 if (u.uhave.amulet && u.amuletcompletelyimbued && !u.freeplaymode) {
3351 You_feel("the amulet draining your energy away.");
3352 forgottencost += rnd(2*forgottencost);
3354 if (u.uen < forgottencost) {
3355 u.uen = 0;
3356 pline("You are exhausted, and fail to invoke the forgotten spell due to the amulet draining all your energy away.");
3357 return(1);
3360 if (u.uen < forgottencost) {
3361 You("don't have enough energy to cast that spell. The required amount was %d.", forgottencost);
3362 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3363 return(0);
3365 u.uen -= forgottencost;
3367 Your("knowledge of this spell is twisted.");
3369 if (rnd(100) > (percent_success(spell))) {
3370 pline("The attempt to invoke the forgotten spell failed.");
3371 if (!rn2(10)) {
3372 pline("In fact, you've screwed up badly enough for it to backfire...");
3373 badeffect();
3375 return(1);
3378 pline("It invokes nightmarish images in your mind...");
3379 u.cnd_forgottenspellcount++;
3380 spell_backfire(spell);
3381 if (!rn2(25)) {
3382 badeffect();
3384 return(1);
3385 } else if (spellknow(spell) <= 100) {
3386 You("strain to recall the spell.");
3387 } else if (spellknow(spell) <= 1000) {
3388 Your("knowledge of this spell is growing faint.");
3390 energy = manacost(spellid(spell));
3391 if (SpellColorYellow) energy *= 2;
3392 if (SpellColorWhite) energy *= 4;
3394 if (WinceState) {
3395 energy *= 6;
3396 energy /= 5;
3397 energy++;
3398 if (StrongWinceState) {
3399 energy *= 6;
3400 energy /= 5;
3401 energy++;
3404 if (u.martialstyle == MARTIALSTYLE_MUAYTHAI) {
3405 energy *= 11;
3406 energy /= 10;
3408 if (ACURR(A_WIS) == 2) {
3409 energy *= 11;
3410 energy /= 10;
3412 if (ACURR(A_WIS) == 1) {
3413 energy *= 12;
3414 energy /= 10;
3417 /* inertia control and spellbinder make spells a bit more expensive... --Amy */
3418 if (u.inertiacontrol) {
3419 energy *= 5;
3420 energy /= 4;
3422 if (u.spellbinder) {
3423 energy *= 5;
3424 energy /= 4;
3426 /* if you have both active, it's even more expensive */
3427 if (u.spellbinder && u.inertiacontrol) {
3428 energy *= 4;
3429 energy /= 3;
3432 /* only being easier to cast is not good enough for the "special spell", since you can't have a failure rate
3433 * lower than 0%. Reduce cost of casting the special spell to 80%! --Amy */
3434 if (spellid(spell) == urole.spelspec) { if (rn2(10)) energy += 1; energy *= 4; energy /= 5; }
3435 if (spellid(spell) == u.superspecialspell) { if (rn2(10)) energy += 1; energy *= 4; energy /= 5; }
3437 if (tech_inuse(T_SPELL_SPAM) && rn2(10)) {
3438 energy += 1; energy *= 9; energy /= 10;
3441 /* slight mana cost decrease if you're very skilled, to make skill matter more --Amy */
3442 if (role_skill == P_SKILLED) { if (rn2(10)) energy += 1; energy *= 19; energy /= 20;}
3443 if (role_skill == P_EXPERT) { if (rn2(10)) energy += 1; energy *= 18; energy /= 20;}
3444 if (role_skill == P_MASTER) { if (rn2(10)) energy += 1; energy *= 17; energy /= 20;}
3445 if (role_skill == P_GRAND_MASTER) { if (rn2(10)) energy += 1; energy *= 16; energy /= 20;}
3446 if (role_skill == P_SUPREME_MASTER) { if (rn2(10)) energy += 1; energy *= 15; energy /= 20;}
3448 if (Role_if(PM_MAHOU_SHOUJO) && energy > 1) { /* Casting any sort of magic uses half power for them */
3449 if (rn2(10)) energy += 1;
3450 energy /= 2;
3453 if (uarmh && uarmh->oartifact == ART_FULLY_WORKING_AT_HALF_MAXI) {
3454 if (rn2(10)) energy += 1;
3455 energy /= 2;
3458 if (uwep && uwep->oartifact == ART_MANA_METER_BOOSTER) {
3459 if (rn2(10)) energy += 1;
3460 energy *= 9;
3461 energy /= 10;
3464 if (uarmc && uarmc->oartifact == ART_ZIRATHA_S_CASTING_LEGEND) {
3465 if (rn2(10)) energy += 1;
3466 energy *= 9;
3467 energy /= 10;
3470 if (uarmg && itemhasappearance(uarmg, APP_UNCANNY_GLOVES)) {
3471 energy *= 11;
3472 energy /= 10;
3475 if (uleft && uleft->oartifact == ART_HENRIETTA_S_MAGICAL_AID) {
3476 if (rn2(10)) energy += 1;
3477 energy *= 4;
3478 energy /= 5;
3481 if (Race_if(PM_BACTERIA)) {
3482 if (rn2(10)) energy += 1;
3483 energy *= 4;
3484 energy /= 5;
3487 if (Upolyd && dmgtype(youmonst.data, AD_SPEL) ) {
3488 if (rn2(10)) energy += 1;
3489 energy *= 19;
3490 energy /= 20;
3492 if (Upolyd && dmgtype(youmonst.data, AD_CLRC) ) {
3493 if (rn2(10)) energy += 1;
3494 energy *= 19;
3495 energy /= 20;
3497 if (Upolyd && dmgtype(youmonst.data, AD_CAST) ) {
3498 if (rn2(10)) energy += 1;
3499 energy *= 9;
3500 energy /= 10;
3503 if (uarmc && uarmc->oartifact == ART_GAGARIN_S_TRANSLATOR) {
3504 if (rn2(10)) energy += 1;
3505 energy *= 9;
3506 energy /= 10;
3509 if (uright && uright->oartifact == ART_HENRIETTA_S_MAGICAL_AID) {
3510 if (rn2(10)) energy += 1;
3511 energy *= 4;
3512 energy /= 5;
3514 if (Role_if(PM_ELEMENTALIST) && skill == P_ELEMENTAL_SPELL) {
3515 if (rn2(10)) energy += 1;
3516 energy *= 3;
3517 energy /= 4;
3520 if ((uarmg && itemhasappearance(uarmg, APP_OCCULTISM_GLOVES)) && skill == P_OCCULT_SPELL) {
3521 if (rn2(10)) energy += 1;
3522 energy *= 4;
3523 energy /= 5;
3526 if (Race_if(PM_MANSTER) && energy > 1) {
3527 if (rn2(10)) energy += 1;
3528 energy *= 2;
3529 energy /= 3;
3532 if (powerfulimplants() && uimplant && uimplant->oartifact == ART_DOMPFINATION) {
3533 if (rn2(10)) energy += 1;
3534 energy *= 9;
3535 energy /= 10;
3538 if (Role_if(PM_MAHOU_SHOUJO) && (energy > 1) && uarmc && itemhasappearance(uarmc, APP_WEEB_CLOAK) ) {
3539 if (rn2(10)) energy += 1;
3540 energy *= 9;
3541 energy /= 10;
3544 /* Fail safe. Spellcasting should never become too inexpensive. --Amy */
3545 if (energy < 2) energy = rn2(10) ? 2 : 1;
3547 if (u.uhunger <= 10 && spellid(spell) != SPE_DETECT_FOOD && spellid(spell) != SPE_SATISFY_HUNGER && spellid(spell) != SPE_KEEP_SATIATION) {
3548 You("are too hungry to cast that spell.");
3549 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3550 return(0);
3551 } else if (ACURR(A_STR) < 4 && !(Role_if(PM_CELLAR_CHILD) && uwep && (weapon_type(uwep) == P_QUARTERSTAFF)) ) {
3552 You("lack the strength to cast spells.");
3553 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3554 return(0);
3555 } else if(check_capacity(
3556 "Your concentration falters while carrying so much stuff.")) {
3557 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3558 return (1);
3559 } else if (!freehandX() && !(uwep && uwep->oartifact == ART_MAGE_STAFF_OF_ETERNITY) && !(Role_if(PM_CELLAR_CHILD) && uwep && (weapon_type(uwep) == P_QUARTERSTAFF)) ) {
3560 Your("arms are not free to cast!");
3561 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3562 return (0);
3563 } else if (u.spellcooldown > 0) {
3564 pline("Spell cooldown. Wait %d more turns.", u.spellcooldown);
3565 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3566 return (0);
3567 } else if ((Muteness || u.uprops[MUTENESS].extrinsic || have_mutenessstone() || (uarmh && uarmh->oartifact == ART_CLELIA_S_TONGUE_BREAKER) ) && rn2(10)) {
3568 pline("You're muted, and fail to cast the spell!");
3569 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3570 u.uen -= rnd(20); /* arbitrary; you're supposed to still be able to cast a little sometimes --Amy */
3571 if (u.uen < 0) u.uen = 0;
3572 return (0);
3573 } else if (tech_inuse(T_SILENT_OCEAN)) {
3574 pline("The silent ocean prevents you from spellcasting.");
3575 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3576 return (0);
3577 } else if (isevilvariant && (Strangled || is_silent(youmonst.data) || !has_head(youmonst.data) || youmonst.data->msound == MS_BUZZ || youmonst.data->msound == MS_BURBLE || youmonst.data->msound == MS_GURGLE || youmonst.data->msound == MS_MUTE)) {
3578 pline("You're unable to chant any magical formula!");
3579 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3580 return (0);
3583 /* Casting any sort of magic as a mahou shoujo or naga does not cause hunger */
3584 /* Amy edit: but if you're satiated, you always use the standard amount of nutrition. That way, hungerless casting
3585 * does not rob you of the ability to get out of satiated status by repeatedly casting spells. */
3587 if ((!Role_if(PM_MAHOU_SHOUJO) && !Race_if(PM_HUMANLIKE_NAGA) && (spellid(spell) != SPE_DETECT_FOOD) && (spellid(spell) != SPE_SATISFY_HUNGER) && (spellid(spell) != SPE_KEEP_SATIATION) ) || u.uhunger > 2500 ) {
3588 hungr = energy * 2;
3590 /* If hero is a wizard, their current intelligence
3591 * (bonuses + temporary + current)
3592 * affects hunger reduction in casting a spell.
3593 * 1. int = 17-18 no reduction
3594 * 2. int = 16 1/4 hungr
3595 * 3. int = 15 1/2 hungr
3596 * 4. int = 1-14 normal reduction
3597 * The reason for this is:
3598 * a) Intelligence affects the amount of exertion
3599 * in thinking.
3600 * b) Wizards have spent their life at magic and
3601 * understand quite well how to cast spells.
3603 intell = acurr(A_INT);
3604 if (!Role_if(PM_WIZARD)) intell = 10;
3605 if (u.uhunger > 2500) intell = 10;
3606 switch (intell) {
3607 case 25: case 24: case 23: case 22:
3608 case 21: case 20: case 19: case 18:
3609 case 17: hungr = 0; break;
3610 case 16: hungr /= 4; break;
3611 case 15: hungr /= 2; break;
3614 /* if you're supposed to get hungry, then it shouldn't be reduced to zero --Amy */
3615 if (hungr < 1) hungr = 1;
3617 else
3618 hungr = 0;
3619 /* don't put player (quite) into fainting from
3620 * casting a spell, particularly since they might
3621 * not even be hungry at the beginning; however,
3622 * this is low enough that they must eat before
3623 * casting anything else except detect food
3626 if (u.uhave.amulet && u.amuletcompletelyimbued && !u.freeplaymode) {
3627 /* casting while you have the fully imbued amulet always causes extra hunger no matter what --Amy
3628 * but a non-imbued one doesn't increase hunger cost */
3629 hungr += rnd(2*energy);
3632 if (hungr > u.uhunger-3)
3633 hungr = u.uhunger-3;
3634 if (energy > u.uen) {
3635 if (SpellColorPlatinum) {
3636 You("overcast the spell. Magic reaction hurts you!");
3637 goto castanyway;
3640 if (role_skill >= P_SKILLED || Race_if(PM_BACTERIA)) You("don't have enough energy to cast that spell.");
3641 else You("don't have enough energy to cast that spell. The required amount was %d.",energy);
3642 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3643 /* WAC/ALI Experts can override with HP/hunger loss */
3644 if ((role_skill >= P_SKILLED || Race_if(PM_BACTERIA)) && (u.uhpmax > (energy / 5)) && (yn("Continue? Doing so may damage your maximum health.") == 'y')) {
3645 energy -= u.uen;
3646 hungr += energy * 2;
3647 if (hungr > u.uhunger - 1)
3648 hungr = u.uhunger - 1;
3650 if (energy > 4 && (!Race_if(PM_BACTERIA) || !rn2(2))) {
3651 /* otherwise, skilled godmode at 0% fail equals instawin. --Amy */
3652 pline("Your maximum health was reduced by %d.", energy / 5);
3653 u.uhpmax -= (energy / 5);
3654 if (u.uhpmax < 1) {
3655 u.uhpmax = 1;
3656 u.youaredead = 1;
3657 done(DIED);
3658 u.youaredead = 0;
3660 u.uhp -= (energy / 5);
3661 if (u.uhp < 1) {
3662 u.youaredead = 1;
3663 done(DIED);
3664 u.youaredead = 0;
3666 } else if (energy < 5 && (!Race_if(PM_BACTERIA) || !rn2(2))) {
3667 pline("Your maximum health was reduced by 1.");
3668 u.uhpmax -= 1;
3669 if (u.uhpmax < 1) {
3670 u.uhpmax = 1;
3671 u.youaredead = 1;
3672 done(DIED);
3673 u.youaredead = 0;
3675 u.uhp -= 1;
3676 if (u.uhp < 1) {
3677 u.youaredead = 1;
3678 done(DIED);
3679 u.youaredead = 0;
3682 flags.botl = TRUE;
3684 losehp(energy,"spellcasting exhaustion", KILLED_BY);
3685 if (role_skill < P_EXPERT) exercise(A_WIS, FALSE);
3686 energy = u.uen;
3687 } else {
3688 if (role_skill >= P_SKILLED || Race_if(PM_BACTERIA)) pline("The required amount was %d.",energy);
3689 return 0;
3693 castanyway:
3695 /* come on, you should be able to cast using less nutrition if your skill is higher! --Amy */
3697 if ((hungr > 0) && (u.uhunger <= 2500)) { /* But only if you're not satiated (see above) */
3699 if (!PlayerCannotUseSkills) {
3700 if ( role_skill == P_BASIC) {hungr *= 85; hungr /= 100;}
3701 if ( role_skill == P_SKILLED) {hungr *= 70; hungr /= 100;}
3702 if ( role_skill == P_EXPERT) {hungr *= 55; hungr /= 100;}
3703 if ( role_skill == P_MASTER) {hungr *= 40; hungr /= 100;}
3704 if ( role_skill == P_GRAND_MASTER) {hungr *= 25; hungr /= 100;}
3705 if ( role_skill == P_SUPREME_MASTER) {hungr *= 10; hungr /= 100;}
3708 /* casting it often (and thereby keeping it in memory) should also reduce hunger... */
3709 if ( spellknow(spell) >= 10000) {hungr *= 9; hungr /= 10;}
3710 if ( spellknow(spell) >= 20000) {hungr *= 9; hungr /= 10;}
3711 if ( spellknow(spell) >= 30000) {hungr *= 9; hungr /= 10;}
3712 if ( spellknow(spell) >= 40000) {hungr *= 9; hungr /= 10;}
3713 if ( spellknow(spell) >= 50000) {hungr *= 9; hungr /= 10;}
3714 if ( spellknow(spell) >= 60000) {hungr *= 9; hungr /= 10;}
3715 if ( spellknow(spell) >= 70000) {hungr *= 9; hungr /= 10;}
3717 if (uarmh && uarmh->oartifact == ART_APOTHEOSIS_VEIL) hungr /= 2;
3719 /* higher XL should help, reducing it to 40% of the normal value at max XL --Amy */
3720 if (u.ulevel > 10) {
3721 hungr *= (100 - ((u.ulevel - 10) * 3));
3722 hungr /= 100;
3725 if (boost_power_value()) {
3726 hungr *= (100 - (boost_power_value() * 3) );
3727 hungr /= 100;
3730 if (hungr < 1) hungr = 1;
3733 if (SpellColorBlue) hungr += 100;
3735 if (hungr < 0) hungr = 0; /* fail safe */
3737 morehungry(hungr);
3739 if (SpellColorGray) {
3741 You("chant the magical formula...");
3742 nomul(-2, "casting a completely gray spell", TRUE);
3746 if (spellid(spell) == SPE_PARTICLE_CANNON) {
3748 nomul(-6, "shooting the particle cannon", FALSE);
3752 if (MiscastBug || u.uprops[MISCAST_BUG].extrinsic || have_miscastingstone()) {
3753 badeffect();
3756 if (SpellColorRed && !rn2(3)) {
3758 int lcount = rnd(monster_difficulty() ) + 1;
3760 if (!obsidianprotection()) switch (rn2(11)) {
3761 case 0: make_sick(Sick ? Sick/2L + 1L : (long)rn1(ACURR(A_CON),20),
3762 "red spell sickness", TRUE, SICK_NONVOMITABLE);
3763 break;
3764 case 1: make_blinded(Blinded + lcount, TRUE);
3765 break;
3766 case 2: if (!Confusion)
3767 You("suddenly feel %s.", FunnyHallu ? "trippy" : "confused");
3768 make_confused(HConfusion + lcount, TRUE);
3769 break;
3770 case 3: make_stunned(HStun + lcount, TRUE);
3771 break;
3772 case 4: make_numbed(HNumbed + lcount, TRUE);
3773 break;
3774 case 5: make_frozen(HFrozen + lcount, TRUE);
3775 break;
3776 case 6: make_burned(HBurned + lcount, TRUE);
3777 break;
3778 case 7: (void) adjattrib(rn2(A_MAX), -1, FALSE, TRUE);
3779 break;
3780 case 8: (void) make_hallucinated(HHallucination + lcount, TRUE, 0L);
3781 break;
3782 case 9: make_feared(HFeared + lcount, TRUE);
3783 break;
3784 case 10: make_dimmed(HDimmed + lcount, TRUE);
3785 break;
3790 if (SpellColorBrown && !(t_at(u.ux, u.uy)) ) {
3791 register struct trap *shittrap;
3792 shittrap = maketrap(u.ux, u.uy, SHIT_TRAP, 0, FALSE);
3793 if (shittrap && !(shittrap->hiddentrap)) {
3794 shittrap->tseen = 1;
3798 if (SpellCooldownBug || u.uprops[SPELL_COOLDOWN_BUG].extrinsic || have_spellcooldownstone()) {
3799 if (!u.spellcooldown) {
3800 u.spellcooldown = SpellCooldownXtra ? rnz(100) : rnz(10);
3801 Your("spellcasting has been put on a timer of %d turns.", u.spellcooldown);
3805 if (SpellColorPink) {
3806 pline("%s", fauxmessage());
3807 u.cnd_plineamount++;
3810 if (SpellColorViolet) pushplayer(TRUE);
3812 if (SpellColorGreen) {
3813 register int zx, zy;
3814 for(zx = 0; zx < COLNO; zx++) for(zy = 0; zy < ROWNO; zy++) {
3815 /* Zonk all memory of this location. */
3816 levl[zx][zy].seenv = 0;
3817 levl[zx][zy].waslit = 0;
3818 clear_memory_glyph(zx, zy, S_stone);
3821 docrt();
3822 vision_recalc(0);
3826 chance = percent_success(spell);
3827 if (confused) {
3828 pline("You try to cast a spell in confusion.");
3830 /* Amy addition: very high skill may allow you to get spells off even while confused */
3831 if (!PlayerCannotUseSkills) {
3832 confusionchance = 0;
3833 if ( role_skill == P_SKILLED) confusionchance = 25;
3834 if ( role_skill == P_EXPERT) confusionchance = 50;
3835 if ( role_skill == P_MASTER) confusionchance = 75;
3836 if ( role_skill == P_GRAND_MASTER) confusionchance = 90;
3837 if ( role_skill == P_SUPREME_MASTER) confusionchance = 100;
3841 if (isevilvariant && youmonst.data->msound == MS_JAPANESE) {
3842 if (strstri(spellname(spell), "r") != 0) {
3844 register int confusedcost;
3846 pline("You can't spell the letter 'r', and therefore fail to cast the spell correctly.");
3847 u.cnd_spellfailcount++;
3848 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3849 if (!rn2(100)) { /* evil patch idea by Amy: failure effect */
3850 pline("In fact, you cast the spell incorrectly in a way that causes bad stuff to happen...");
3851 badeffect();
3853 if (SpellColorSilver) u.seesilverspell = 0;
3855 if (FailuresAreCostly) confusedcost = energy;
3856 else confusedcost = ((energy * 50 / ((role_skill == P_SUPREME_MASTER) ? 240 : (role_skill == P_GRAND_MASTER) ? 220 : (role_skill == P_MASTER) ? 200 : (role_skill == P_EXPERT) ? 180 : (role_skill == P_SKILLED) ? 160 : (role_skill == P_BASIC) ? 140 : 120)) + 1);
3858 u.uen -= confusedcost;
3860 if (SpellColorOrange) losehp(confusedcost, "casting an orange spell while confused", KILLED_BY);
3862 flags.botl = 1;
3864 return (1);
3868 if ( (confused && spellid(spell) != SPE_CURE_CONFUSION && spellid(spell) != SPE_CURE_RANDOM_STATUS && (confusionchance < rnd(100)) && (!StrongConf_resist || !rn2(3)) && rn2(Conf_resist ? 5 : 10) ) || (rnd(100) > chance)) {
3870 register int confusedcost;
3872 if (!issoviet) pline("You fail to cast the spell correctly.");
3873 else pline("HA HA HA HA HA, tip bloka l'da sdelal vy ne zaklinaniye!");
3874 u.cnd_spellfailcount++;
3875 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3876 if (!rn2(100)) { /* evil patch idea by Amy: failure effect */
3877 pline("In fact, you cast the spell incorrectly in a way that causes bad stuff to happen...");
3878 badeffect();
3881 if (SpellColorSilver) u.seesilverspell = 0;
3883 #ifdef ALLEG_FX
3884 if (iflags.usealleg) alleg_aura(u.ux, u.uy, P_ATTACK_SPELL-1);
3885 #endif
3887 /* Higher spellcasting skills mean failure takes less mana. --Amy */
3889 if (FailuresAreCostly) confusedcost = energy;
3890 else confusedcost = ((energy * 50 / ((role_skill == P_SUPREME_MASTER) ? 240 : (role_skill == P_GRAND_MASTER) ? 220 : (role_skill == P_MASTER) ? 200 : (role_skill == P_EXPERT) ? 180 : (role_skill == P_SKILLED) ? 160 : (role_skill == P_BASIC) ? 140 : 120)) + 1);
3892 u.uen -= confusedcost;
3894 if (SpellColorOrange) losehp(confusedcost, "casting an orange spell while confused", KILLED_BY);
3896 flags.botl = 1;
3897 return(1);
3900 if (u.tremblingamount) {
3901 int tremblechance = (u.tremblingamount * 5 / 2);
3902 if (rn2(100) < rnd(tremblechance)) {
3904 int confusedcost;
3906 You("screw up while casting the spell...");
3907 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3908 u.cnd_spellfailcount++;
3910 if (!rn2(10)) {
3911 pline("In fact, you screwed up so badly that bad stuff happens...");
3912 badeffect();
3915 if (SpellColorSilver) u.seesilverspell = 0;
3917 if (FailuresAreCostly) confusedcost = energy;
3918 else confusedcost = ((energy * 50 / ((role_skill == P_SUPREME_MASTER) ? 240 : (role_skill == P_GRAND_MASTER) ? 220 : (role_skill == P_MASTER) ? 200 : (role_skill == P_EXPERT) ? 180 : (role_skill == P_SKILLED) ? 160 : (role_skill == P_BASIC) ? 140 : 120)) + 1);
3920 u.uen -= confusedcost;
3922 if (SpellColorOrange) losehp(confusedcost, "casting an orange spell while trembling", KILLED_BY);
3924 flags.botl = 1;
3925 return(1);
3930 /* Players could cheat if they had just barely enough mana for casting a spell without the increased drain.
3931 * They'd just need to keep trying until the extra mana costs are randomly very low.
3932 * Prevent players from abusing this by calculating the extra drain _after_ the other checks. --Amy */
3933 if (u.uhave.amulet && u.amuletcompletelyimbued && !u.freeplaymode) {
3934 You_feel("the amulet draining your energy away.");
3935 energy += rnd(2*energy);
3938 u.uen -= energy;
3940 if (SpellColorOrange) losehp(energy, "casting an orange spell with too little health", KILLED_BY);
3942 if (SpellColorSilver) u.seesilverspell = 1;
3944 /* And if the amulet drained it below zero, set it to zero and just make the spell fail now. */
3945 if (u.uhave.amulet && !u.freeplaymode && u.amuletcompletelyimbued && u.uen < 0) {
3946 pline("You are exhausted, and fail to cast the spell due to the amulet draining all your energy away.");
3947 u.cnd_spellfailcount++;
3948 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
3949 u.uen = 0;
3950 if (SpellColorSilver) u.seesilverspell = 0;
3951 return(1);
3954 u.cnd_spellcastcount++;
3956 if (uarmg && uarmg->oartifact == ART_WHOOSHZHOOSH) {
3957 incr_itimeout(&HFast, rn1(15, 5));
3960 u.umemorizationturns += spellev(spell);
3961 if (u.umemorizationturns >= 100) {
3962 u.umemorizationturns -= 100;
3963 use_skill(P_MEMORIZATION, 1);
3966 /* if your INT is low, have a very slight chance of increasing it --Amy */
3967 if (ABASE(A_INT) < 10) {
3968 int intellchance = 500;
3969 switch (ABASE(A_INT)) {
3970 case 1: intellchance = 300; break;
3971 case 2: intellchance = 400; break;
3972 case 3: intellchance = 500; break;
3973 case 4: intellchance = 600; break;
3974 case 5: intellchance = 700; break;
3975 case 6: intellchance = 800; break;
3976 case 7: intellchance = 900; break;
3977 case 8: intellchance = 1000; break;
3978 case 9: intellchance = 1000; break;
3979 default: intellchance = 1000; break;
3982 /* make it depend on spell level... */
3983 intellchance *= 16;
3984 intellchance /= (8 + spellev(spell));
3986 if (!rn2(intellchance)) (void) adjattrib(A_INT, 1, FALSE, TRUE);
3989 if (uwep && is_lightsaber(uwep) && (uwep->lamplit || Role_if(PM_SHADOW_JEDI)) ) {
3990 u.unimanturns++;
3992 if (spellev(spell) > rn2(8)) {
3993 mightbooststat(A_INT);
3996 if (u.unimanturns >= 3) {
3997 u.unimanturns = 0;
3998 use_skill(P_NIMAN, 1);
4001 if (uwep && tech_inuse(T_ENERGY_TRANSFER)) {
4002 uwep->age += energy;
4003 if (uwep->otyp == ORANGE_LIGHTSABER) uwep->age += (energy * rnd(2));
4004 if (uwep->oartifact == ART_DESANN_S_WRATH) uwep->age += (energy * rnd(2));
4005 pline("Your lightsaber is charged a bit.");
4009 if (uwep && uwep->oartifact == ART_NEVERMAN) {
4010 u.unimanturns++;
4012 if (spellev(spell) > rn2(8)) {
4013 mightbooststat(A_INT);
4016 if (u.unimanturns >= 3) {
4017 u.unimanturns = 0;
4018 use_skill(P_NIMAN, 1);
4022 if (Role_if(PM_MAHOU_SHOUJO)) { /* Casting any sort of magic causes all monsters on a level to
4023 become alert of your location, due to mahou shoujo always announcing their attacks. */
4025 wake_nearby();
4026 verbalize("%s!",spellname(spell) );
4030 if (Race_if(PM_RELEASIER)) {
4031 verbalize("%s", !rn2(3) ? "Kjear! Hahahahaha!" : !rn2(2) ? "Aa-hu!" : "Hiarwigo!");
4034 if (SpellColorBrightCyan) {
4035 u.aggravation = 1;
4036 u.lamefarmer = 1;
4037 adjalign(-5);
4038 reset_rndmonst(NON_PM);
4039 (void) makemon((struct permonst *)0, 0, 0, MM_ANGRY|MM_FRENZIED);
4040 u.aggravation = 0;
4041 u.lamefarmer = 0;
4045 /* you can't hold perfectly still while performing the casting motion; occasionally scuff engraving --Amy
4046 * but less than if you tried to use melee attacks */
4047 if (!rn2(5)) u_wipe_engr(1);
4049 flags.botl = 1;
4050 exercise(A_WIS, TRUE);
4052 /* pseudo is a temporary "false" object containing the spell stats. */
4053 pseudo = mksobj(spellid(spell), FALSE, 2, FALSE);
4054 if (!pseudo) {
4055 pline("The spell failed spontaneously!");
4056 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
4057 return(1);
4059 if (pseudo->otyp == GOLD_PIECE) pseudo->otyp = spellid(spell); /* minimalist fix */
4060 pseudo->blessed = pseudo->cursed = 0;
4061 pseudo->quan = 20L; /* do not let useup get it */
4063 /* WAC -- If skilled enough, will act like a blessed version */
4064 if (role_skill >= P_SKILLED && issoviet) { /* made it depend on skill level --Amy */
4065 if (!rn2(10) && role_skill == P_SKILLED) pseudo->blessed = 1;
4066 if (!rn2(8) && role_skill == P_EXPERT) pseudo->blessed = 1;
4067 if (!rn2(6) && role_skill == P_MASTER) pseudo->blessed = 1;
4068 if (!rn2(5) && role_skill == P_GRAND_MASTER) pseudo->blessed = 1;
4069 if (!rn2(4) && role_skill == P_SUPREME_MASTER) pseudo->blessed = 1;
4072 #ifdef ALLEG_FX
4073 if (iflags.usealleg) alleg_aura(u.ux, u.uy, skill);
4074 #endif
4075 switch(pseudo->otyp) {
4077 * At first spells act as expected. As the hero increases in skill
4078 * with the appropriate spell type, some spells increase in their
4079 * effects, e.g. more damage, further distance, and so on, without
4080 * additional cost to the spellcaster.
4082 case SPE_MAGIC_MISSILE:
4083 case SPE_FIREBALL:
4084 case SPE_CONE_OF_COLD:
4085 case SPE_LIGHTNING:
4086 case SPE_ACID_STREAM:
4087 case SPE_SOLAR_BEAM:
4088 case SPE_PSYBEAM:
4089 case SPE_POISON_BLAST:
4090 if (tech_inuse(T_SIGIL_TEMPEST)) {
4091 weffects(pseudo);
4092 break;
4093 } /* else fall through... */
4094 /* these spells are all duplicates of wand effects */
4095 case SPE_FORCE_BOLT:
4096 case SPE_MAGIC_BOLT:
4097 case SPE_WATER_BOLT:
4098 case SPE_MULTIBEAM:
4099 case SPE_CALL_THE_ELEMENTS:
4100 case SPE_MANA_BOLT:
4101 case SPE_ULTRA_P:
4102 case SPE_SNIPER_BEAM:
4103 case SPE_BLINDING_RAY:
4104 case SPE_ENERGY_BOLT:
4105 case SPE_GRAVITY_BEAM:
4106 case SPE_BUBBLEBEAM:
4107 case SPE_DREAM_EATER:
4108 case SPE_GOOD_NIGHT:
4109 case SPE_INFERNO:
4110 case SPE_ICE_BEAM:
4111 case SPE_THUNDER:
4112 case SPE_SLUDGE:
4113 case SPE_TOXIC:
4114 case SPE_NETHER_BEAM:
4115 case SPE_AURORA_BEAM:
4116 case SPE_CHLOROFORM:
4117 case SPE_SLEEP:
4118 case SPE_KNOCK:
4119 case SPE_LOCK_MANIPULATION:
4120 case SPE_SLOW_MONSTER:
4121 case SPE_RANDOM_SPEED:
4122 case SPE_INERTIA:
4123 case SPE_CLONE_MONSTER:
4124 case SPE_WIZARD_LOCK:
4125 case SPE_DIG:
4126 case SPE_VOLT_ROCK:
4127 case SPE_GIANT_FOOT:
4128 case SPE_BUBBLING_HOLE:
4129 case SPE_GEYSER:
4130 case SPE_NERVE_POISON:
4131 case SPE_BLOOD_STREAM:
4132 case SPE_SHINING_WAVE:
4133 case SPE_ARMOR_SMASH:
4134 case SPE_STRANGLING:
4135 case SPE_PARTICLE_CANNON:
4136 case SPE_BATTERING_RAM:
4137 case SPE_WATER_FLAME:
4138 case SPE_TURN_UNDEAD:
4139 case SPE_POLYMORPH:
4140 case SPE_CHAOS_BOLT:
4141 case SPE_HELLISH_BOLT:
4142 case SPE_HORRIFY:
4143 case SPE_MUTATION:
4144 case SPE_TELEPORT_AWAY:
4145 case SPE_CANCELLATION:
4146 case SPE_VANISHING:
4147 case SPE_FINGER_OF_DEATH:
4148 case SPE_LIGHT_AREA:
4149 case SPE_DARKNESS:
4150 case SPE_DETECT_UNSEEN:
4151 case SPE_HEALING:
4152 case SPE_EXTRA_HEALING:
4153 case SPE_FULL_HEALING:
4154 case SPE_DRAIN_LIFE:
4155 case SPE_TIME:
4156 case SPE_STONE_TO_FLESH:
4157 case SPE_FINGER:
4158 case SPE_MAKE_VISIBLE:
4159 case SPE_STUN_MONSTER:
4160 case SPE_DISINTEGRATION:
4161 case SPE_DISINTEGRATION_BEAM:
4162 case SPE_CHROMATIC_BEAM:
4163 case SPE_CONVERGE_BREATH:
4164 case SPE_ELEMENTAL_BEAM:
4165 case SPE_NATURE_BEAM:
4166 case SPE_PETRIFY:
4167 case SPE_WIND:
4168 case SPE_FIRE_BOLT:
4169 case SPE_DEFENSIVE_FIREBALL:
4170 case SPE_HYPER_BEAM:
4171 case SPE_PARALYSIS:
4173 if (pseudo->otyp == SPE_ULTRA_P) {
4175 if(!Levitation) {
4176 HLevitation = 1;
4177 float_up();
4178 HLevitation = 0;
4181 incr_itimeout(&HLevitation, rn1(30, 10));
4182 spoteffects(FALSE); /* for sinks */
4185 if (pseudo->otyp == SPE_DEFENSIVE_FIREBALL) {
4186 boolean fireballfail = FALSE;
4187 int i, j, bd = 1;
4188 struct monst *mtmp;
4189 for (i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) {
4190 if (!isok(u.ux + i, u.uy + j)) continue;
4191 if ((mtmp = m_at(u.ux + i, u.uy + j)) != 0) {
4192 if (!mtmp->mpeaceful && !mtmp->mtame) {
4193 fireballfail = TRUE;
4198 if (fireballfail) {
4199 You("are interrupted!");
4200 break;
4204 if (pseudo->otyp == SPE_BATTERING_RAM) {
4205 if (u.battertimer) {
4206 You("need to wait %d more turns to ready the ram. Battering ram can be used again at turn %ld.", u.battertimer, (moves + u.battertimer));
4207 break;
4208 } else {
4209 u.battertimer = 2;
4213 if (pseudo->otyp == SPE_PARTICLE_CANNON) {
4214 if (u.gaugetimer) {
4215 You("need to wait %d more turns to refill your gauge. The particle cannon can be used again at turn %ld.", u.gaugetimer, (moves + u.gaugetimer));
4216 break;
4217 } else {
4218 u.gaugetimer = 50;
4222 if (pseudo->otyp == SPE_CONVERGE_BREATH) {
4223 if (u.gaugetimer) {
4224 You("need to wait %d more turns to refill your gauge. Converge breath can be used again at turn %ld.", u.gaugetimer, (moves + u.gaugetimer));
4225 break;
4226 } else {
4227 u.gaugetimer = 50;
4231 if (practicantterror && pseudo && pseudo->otyp == SPE_FINGER_OF_DEATH && !u.pract_fodzap) {
4232 pline("%s thunders: 'Well wait, I'll shut down your evil spellcasting. Also, for actually casting an unforgivable curse, you have to pay 25000 zorkmids. If you keep misbehaving like that I'll show you some unforgivable curses, I tell you...'", noroelaname());
4233 Muteness += rnz(5000);
4234 fineforpracticant(25000, 0, 0);
4235 u.pract_fodzap = TRUE;
4238 if (pseudo->otyp == SPE_BLOOD_STREAM) {
4240 if (Upolyd && u.mh < 5) {
4241 losehp(10000, "forcibly bleeding out", KILLED_BY);
4242 } else if (!Upolyd && u.uhp < 5) {
4243 losehp(10000, "forcibly bleeding out", KILLED_BY);
4245 if (rn2(2)) {
4246 if (Upolyd) u.mh -= ((u.mh / 5) + 1);
4247 else u.uhp -= ((u.uhp / 5) + 1);
4248 } else {
4249 if (Upolyd) {
4250 u.mh -= ((u.mhmax / 5) + 1);
4251 if (u.mh < 0) losehp(10000, "forcibly bleeding out", KILLED_BY);
4252 } else {
4253 u.uhp -= ((u.uhpmax / 5) + 1);
4254 if (u.uhp < 0) losehp(10000, "forcibly bleeding out", KILLED_BY);
4259 if (!(objects[pseudo->otyp].oc_dir == NODIR)) {
4260 if (atme) u.dx = u.dy = u.dz = 0;
4261 else
4262 magicalenergychoice:
4263 if (!getdir((char *)0)) {
4264 /* getdir cancelled, re-use previous direction */
4266 /* Amy edit: this is absolute bullshit behavior, because it's very easy to mistype. It should
4267 * NEVER direct the zap at yourself unless you specifically told it so, but the vanilla behavior
4268 * means that knowing finger of death means death to interface screw can happen at any time.
4269 * I've made magic resistance work too, see zap.c, but those that don't have magic resistance
4270 * shall not be screwed over either. Screw you, programmers. And while you're at it,
4271 * read up on game design and specifically interface design! :P --Amy */
4273 if (yn("Do you really want to input no direction?") == 'y')
4274 pline_The("magical energy is released!");
4275 else {
4276 goto magicalenergychoice;
4279 if (u.dx == 0 && u.dy == 0) {
4280 You("would have hit yourself, but to reduce YASD potential the blast goes in a random direction.");
4281 u.dz = 0;
4282 confdir();
4285 if(!u.dx && !u.dy && !u.dz) {
4286 if ((damage = zapyourself(pseudo, TRUE)) != 0) {
4287 char buf[BUFSZ];
4288 sprintf(buf, "zapped %sself with a spell", uhim());
4289 losehp(damage, buf, NO_KILLER_PREFIX);
4291 } else weffects(pseudo);
4292 } else weffects(pseudo);
4293 update_inventory(); /* spell may modify inventory */
4294 if (pseudo->otyp == SPE_TELEPORT_AWAY || pseudo->otyp == SPE_POLYMORPH || pseudo->otyp == SPE_MUTATION || pseudo->otyp == SPE_CANCELLATION) {
4295 if (!rn2(5)) {
4296 pline("The magical energy goes out of control!");
4297 badeffect();
4300 if (pseudo->otyp == SPE_VANISHING) {
4301 if (!rn2(50)) {
4302 pline("The magical energy goes out of control!");
4303 badeffect();
4306 if (pseudo->otyp == SPE_WATER_BOLT) {
4307 make_confused(HConfusion + 5, TRUE);
4308 make_stunned(HStun + 5, TRUE);
4309 if (!rn2(20)) {
4310 pline("The spell backfires!");
4311 badeffect();
4313 if (!(InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone())) (void) doredraw();
4315 if (pseudo->otyp == SPE_WIND) {
4316 pushplayer(TRUE);
4317 pline("The winds hurt you!");
4318 losehp(rnd(10), "winds", KILLED_BY);
4319 if (In_sokoban(&u.uz) && !playercancheatinsoko()) {
4320 change_luck(-1);
4321 pline("You cheater!");
4322 if (evilfriday) u.ugangr++;
4325 if (pseudo->otyp == SPE_CHAOS_BOLT) {
4326 if (!rn2(3)) {
4327 pline("The magical energy goes out of control!");
4328 make_hallucinated(HHallucination + rnd(20), FALSE, 0L);
4329 if (!rn2(10)) set_itimeout(&HeavyHallu, HHallucination);
4330 if (!rn2(2)) u.halresdeactivated = rnz(50);
4333 if (pseudo->otyp == SPE_HELLISH_BOLT) {
4334 if (!rn2(2)) {
4335 pline("The magical energy goes out of control!");
4336 make_hallucinated(HHallucination + rnd(100), FALSE, 0L);
4337 if (!rn2(5)) set_itimeout(&HeavyHallu, HHallucination);
4338 if (rn2(3)) u.halresdeactivated = rnz(200);
4341 break;
4342 /* these are all duplicates of scroll effects */
4343 case SPE_REMOVE_CURSE:
4344 case SPE_CONFUSE_MONSTER:
4345 case SPE_DETECT_FOOD:
4346 case SPE_CAUSE_FEAR:
4347 #if 0
4348 /* high skill yields effect equivalent to blessed scroll */
4349 if (role_skill >= P_SKILLED) pseudo->blessed = 1;
4350 #endif
4351 /* fall through */
4352 case SPE_CHARM_MONSTER:
4353 case SPE_MAGIC_MAPPING:
4354 case SPE_CREATE_MONSTER:
4355 case SPE_IDENTIFY:
4356 case SPE_DESTROY_ARMOR:
4357 case SPE_COMMAND_UNDEAD:
4358 case SPE_SUMMON_UNDEAD:
4359 if (rn2(5) || !issoviet) pseudo->blessed = 0;
4360 (void) seffects(pseudo);
4361 break;
4362 case SPE_CHARGING:
4363 pseudo->blessed = 0;
4364 (void) seffects(pseudo);
4365 break;
4367 case SPE_ENCHANT_WEAPON:
4368 case SPE_ENCHANT_ARMOR:
4369 if (role_skill >= P_SUPREME_MASTER) n = 7;
4370 else if (role_skill >= P_GRAND_MASTER) n = 8;
4371 else if (role_skill >= P_MASTER) n = 9;
4372 else if (role_skill >= P_EXPERT) n = 10;
4373 else if (role_skill >= P_SKILLED) n = 11;
4374 else if (role_skill >= P_BASIC) n = 12;
4375 else n = 14; /* Unskilled or restricted */
4376 if (!rn2(n)) {
4377 pseudo->blessed = 0;
4378 (void) seffects(pseudo);
4379 if (u.uenmax > 0) {
4380 u.uenmax -= 1;
4381 pline("The strain from casting such a powerful spell drains your maximum mana.");
4382 } else {
4383 pline("Casting such a powerful spell from hitpoints causes strong backlash.");
4384 badeffect(); badeffect(); badeffect(); badeffect(); badeffect();
4386 } else
4387 Your("enchantment failed!");
4388 break;
4390 case SPE_ENTRAPPING:
4392 trap_detectX((struct obj *)0);
4393 exercise(A_WIS, TRUE);
4395 if (!rn2(10)) {
4396 pline("The spell backlashes!");
4397 badeffect();
4400 break;
4401 /* these are all duplicates of potion effects */
4402 case SPE_HASTE_SELF:
4403 case SPE_DETECT_TREASURE:
4404 case SPE_DETECT_MONSTERS:
4405 case SPE_LEVITATION:
4406 case SPE_RESTORE_ABILITY:
4407 case SPE_BANISHING_FEAR:
4408 #if 0
4409 /* high skill yields effect equivalent to blessed potion */
4410 if (role_skill >= P_SKILLED) pseudo->blessed = 1;
4411 #endif
4412 /* fall through */
4413 case SPE_INVISIBILITY:
4414 if (rn2(5) || !issoviet) pseudo->blessed = 0;
4415 (void) peffects(pseudo);
4416 break;
4417 case SPE_CURE_BLINDNESS:
4418 if (HeavyBlind) break;
4419 if (Blinded > (rn1(Role_if(PM_HEALER) ? 200 : 100, 20))) {
4420 int effreduction = rnd(Blinded / 2);
4421 if (effreduction > 0) {
4422 u.ucreamed -= effreduction;
4423 if ((int)(u.ucreamed) < 0) u.ucreamed = 0; /* fail safe */
4424 Blinded -= effreduction;
4425 Your("blindness counter is reduced.");
4427 if (!Role_if(PM_HEALER) && !rn2(500)) {
4428 pline("The spell backlashes!");
4429 badeffect();
4431 } else {
4432 healup(0, 0, FALSE, TRUE);
4434 break;
4435 case SPE_AMNESIA:
4436 You_feel("dizzy!");
4437 forget(1 + rn2(5), FALSE);
4438 break;
4439 case SPE_AGGRAVATE_MONSTER:
4440 You_feel("that monsters are aware of your presence.");
4441 if (PlayerHearsSoundEffects) pline(issoviet ? "Dazhe sovetskaya Pyat' Lo obostryayetsya v vashem nizkom igrovom masterstve." : "Woaaaaaah!");
4442 aggravate();
4443 break;
4444 case SPE_CURSE_ITEMS:
4445 You_feel("as if you need some help.");
4446 if (PlayerHearsSoundEffects) pline(issoviet ? "Vashe der'mo tol'ko chto proklinal." : "Woaaaaaa-AAAH!");
4447 rndcurse();
4448 break;
4450 case SPE_ORE_MINING:
4453 int i, j;
4454 boolean alreadydone = 0;
4455 for (i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
4456 if (!isok(u.ux + i, u.uy + j)) continue;
4457 if (alreadydone) continue;
4458 if (levl[u.ux + i][u.uy + j].typ == STALACTITE) {
4459 levl[u.ux + i][u.uy + j].typ = CORR;
4461 if (!rn2(3)) { /* 80% chance of glass, 20% of precious gems */
4462 if (rn2(5)) mksobj_at(rnd_class(JADE+1, LUCKSTONE-1), u.ux + i, u.uy + j, TRUE, FALSE, FALSE);
4463 else mksobj_at(rnd_class(DILITHIUM_CRYSTAL, JADE), u.ux + i, u.uy + j, TRUE, FALSE, FALSE);
4464 pline("A stalactite turns into gems!");
4465 alreadydone = TRUE;
4467 if (practicantterror && !u.pract_oremining) {
4468 pline("%s booms: 'Didn't you hear? Mining my ore is forbidden! That's 1000 zorkmids, and you still have one minute to get away from my ore, got it?'", noroelaname());
4469 fineforpracticant(1000, 0, 0);
4470 u.pract_oremining = TRUE;
4473 break;
4474 } else {
4475 pline("A stalactite shatters!");
4476 alreadydone = TRUE;
4477 break;
4480 alreadydone = TRUE; /* why the HELL does the break statement not go out of the loop */
4481 break; /* only raze one stalactite if there are several --Amy */
4487 manloop:
4489 if (!(InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone())) (void)doredraw();
4491 break;
4493 case SPE_BOILER_KABOOM:
4496 int i, j;
4497 for (i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
4499 if (!isok(u.ux + i, u.uy + j)) continue;
4500 if (levl[u.ux + i][u.uy + j].typ == RAINCLOUD) {
4502 levl[u.ux + i][u.uy + j].typ = CORR;
4503 explode(u.ux + i, u.uy + j, ZT_FIRE, rnd(boosted_ulevel(1) * 3), WAND_CLASS, EXPL_FIERY);
4511 if (!(InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone())) (void)doredraw();
4513 break;
4515 case SPE_DEFOG:
4518 boolean defogged = 0;
4519 int i, j;
4520 for (i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
4522 if (!isok(u.ux + i, u.uy + j)) continue;
4523 if (levl[u.ux + i][u.uy + j].typ == NETHERMIST) {
4525 levl[u.ux + i][u.uy + j].typ = CORR;
4526 adjalign(-10);
4527 u.alignlim--;
4528 defogged = 1;
4534 if (defogged) pline("It is not foggy any longer.");
4535 else {
4536 pline("Nothing happens.");
4537 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
4538 pline("Oh wait, actually something bad happens...");
4539 badeffect();
4545 if (!(InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone())) (void)doredraw();
4547 break;
4549 case SPE_SWAP_POSITION:
4551 u.swappositioncount = 4;
4552 pline("The next monster you move into will be displaced.");
4554 break;
4556 case SPE_SHUFFLE_MONSTER:
4559 int hasshuffled = 0;
4561 register struct monst *nexusmon, *nextmon;
4563 for(nexusmon = fmon; nexusmon; nexusmon = nextmon) {
4564 nextmon = nexusmon->nmon; /* trap might kill mon */
4565 if (DEADMONSTER(nexusmon)) continue;
4566 if (u.usteed && nexusmon == u.usteed) continue;
4568 if (!monnear(nexusmon, u.ux, u.uy)) continue;
4569 if (nexusmon->mtrapped) {
4570 /* no longer in previous trap (affects mintrap) */
4571 nexusmon->mtrapped = 0;
4572 fill_pit(nexusmon->mx, nexusmon->my);
4575 if (pushmonster(nexusmon)) hasshuffled++;
4576 if (pushmonster(nexusmon)) hasshuffled++;
4580 if (hasshuffled && !(InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone())) doredraw();
4582 if (!hasshuffled) pline("No monsters were shuffled!");
4583 else if (hasshuffled <= 2) pline("A monster was shuffled!");
4584 else pline("Several monsters were shuffled!");
4588 break;
4590 case SPE_PET_SYRINGE:
4594 register struct monst *nexusmon, *nextmon;
4595 const char *verb;
4596 int healamount;
4598 for(nexusmon = fmon; nexusmon; nexusmon = nextmon) {
4599 nextmon = nexusmon->nmon; /* trap might kill mon */
4600 if (DEADMONSTER(nexusmon)) continue;
4602 if (!monnear(nexusmon, u.ux, u.uy)) continue;
4603 if (!nexusmon->mtame) continue;
4605 healamount = d(15, 10 + spell_damage_bonus(SPE_PET_SYRINGE) );
4606 nexusmon->mhp += healamount;
4608 if (nexusmon->mhp > nexusmon->mhpmax) nexusmon->mhp = nexusmon->mhpmax;
4610 if (nexusmon->bleedout && nexusmon->bleedout <= healamount) {
4611 nexusmon->bleedout = 0;
4612 pline("%s's bleeding stops.", Monnam(nexusmon));
4613 } else if (nexusmon->bleedout) {
4614 nexusmon->bleedout -= healamount;
4615 if (nexusmon->bleedout < 0) nexusmon->bleedout = 0; /* should never happen */
4616 pline("%s's bleeding diminishes.", Monnam(nexusmon));
4619 abuse_dog(nexusmon);
4621 pline("%s received the syringe and is healthy again.", Monnam(nexusmon));
4622 verb = growl_sound(nexusmon);
4623 pline("%s %s.", Monnam(nexusmon), vtense((char *)0, verb));
4629 break;
4631 case SPE_BUC_KNOWLEDGE:
4633 if (CannotSelectItemsInPrompts) break;
4634 pline("Choose an item for BUC identification.");
4635 bucchoice:
4636 otmp = getobj(allnoncount, "know the BUC of");
4637 if (!otmp) {
4638 if (yn("Really exit with no object selected?") == 'y')
4639 pline("You just wasted the opportunity to determine an item's BUC.");
4640 else goto bucchoice;
4641 pline("You decide not to determine an item's BUC after all.");
4642 break;
4644 if (otmp) {
4645 if (!otmp->bknown && (u.bucskill < 2 || !rn2(u.bucskill)) ) {
4646 u.bucskill++;
4647 if (u.bucskill > 250) u.bucskill = 250;
4650 otmp->bknown = TRUE;
4651 if (otmp->blessed || otmp->cursed) pline("Your %s flashes %s.", doname(otmp), hcolor(otmp->blessed ? NH_AMBER : NH_BLACK));
4654 break;
4656 case SPE_PREACHING:
4658 You("preach some religious sermon.");
4659 adjalign(5);
4661 break;
4663 case SPE_RESIST_PARALYSIS:
4665 if(!(HDiscount_action & INTRINSIC)) {
4666 You("gain paralysis resistance!");
4667 incr_itimeout(&HDiscount_action, HDiscount_action ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
4668 } else {
4669 pline("%s", nothing_happens); /* Already have as intrinsic */
4670 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
4671 pline("Oh wait, actually something bad happens...");
4672 badeffect();
4676 break;
4678 case SPE_KEEP_SATIATION:
4680 if(!(HFull_nutrient & INTRINSIC)) {
4681 Your("nutrition consumption slows down!");
4682 incr_itimeout(&HFull_nutrient, HFull_nutrient ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
4683 } else {
4684 pline("%s", nothing_happens); /* Already have as intrinsic */
4685 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
4686 pline("Oh wait, actually something bad happens...");
4687 badeffect();
4691 break;
4693 case SPE_LIGHT:
4694 if (isok(u.ux, u.uy)) {
4695 levl[u.ux][u.uy].lit = TRUE;
4696 pline("A light shines on your location.");
4698 if (isok(u.ux, u.uy + 1)) {
4699 levl[u.ux][u.uy + 1].lit = TRUE;
4701 if (isok(u.ux, u.uy - 1)) {
4702 levl[u.ux][u.uy - 1].lit = TRUE;
4704 if (isok(u.ux + 1, u.uy)) {
4705 levl[u.ux + 1][u.uy].lit = TRUE;
4707 if (isok(u.ux - 1, u.uy)) {
4708 levl[u.ux - 1][u.uy].lit = TRUE;
4710 break;
4712 case SPE_TECH_BOOST:
4714 if(!(HTechnicality & INTRINSIC)) {
4715 Your("techniques become stronger!");
4716 incr_itimeout(&HTechnicality, HTechnicality ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
4717 } else {
4718 pline("%s", nothing_happens); /* Already have as intrinsic */
4719 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
4720 pline("Oh wait, actually something bad happens...");
4721 badeffect();
4725 break;
4727 case SPE_MAGIC_CONTROL:
4729 if(!(HControlMagic & INTRINSIC)) {
4730 You("feel more capable of controlling your magic!");
4731 incr_itimeout(&HControlMagic, HControlMagic ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
4732 } else {
4733 pline("%s", nothing_happens); /* Already have as intrinsic */
4734 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
4735 pline("Oh wait, actually something bad happens...");
4736 badeffect();
4740 break;
4742 case SPE_ASTRAL_VIEW:
4744 if(!(HAstral_vision & INTRINSIC)) {
4745 You("can see through walls!");
4746 incr_itimeout(&HAstral_vision, HAstral_vision ? 1 : (5 + spell_damage_bonus(spellid(spell)) ) );
4747 } else {
4748 pline("%s", nothing_happens); /* Already have as intrinsic */
4749 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
4750 pline("Oh wait, actually something bad happens...");
4751 badeffect();
4755 break;
4757 case SPE_CAROTINE_INJECTION:
4759 if (u.uhp < 6) {
4760 You("don't have enough health to cast this!");
4761 break;
4763 if (Upolyd && u.mh < 6) {
4764 You("don't have enough health to cast this!");
4765 break;
4768 pline("Ow!");
4769 losehp(5, "carotine injection", KILLED_BY);
4771 if(!(HBlind_resistance & INTRINSIC)) {
4772 You("feel able to see freely!");
4773 incr_itimeout(&HBlind_resistance, HBlind_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rnd(100) + spell_damage_bonus(spellid(spell))*20));
4774 } else {
4775 pline("%s", nothing_happens); /* Already have as intrinsic */
4776 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
4777 pline("Oh wait, actually something bad happens...");
4778 badeffect();
4782 break;
4784 case SPE_DOWNER_TRIP:
4786 u.uprops[DEAC_FEAR_RES].intrinsic += rnz(250);
4787 make_feared(HFeared + rnz(250), TRUE);
4789 if(!(HHalluc_resistance & INTRINSIC)) {
4790 You("feel like you're on a bad trip that lacks fleecy colors!");
4791 incr_itimeout(&HHalluc_resistance, HHalluc_resistance ? (rnd(100) + spell_damage_bonus(spellid(spell))) : (rnd(200) + spell_damage_bonus(spellid(spell))*50));
4792 } else {
4793 pline("%s", nothing_happens); /* Already have as intrinsic */
4794 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
4795 pline("Oh wait, actually something bad happens...");
4796 badeffect();
4800 break;
4802 case SPE_CONTINGENCY:
4804 u.contingencyturns = 50 + (spell_damage_bonus(spellid(spell)) * 3);
4805 You("sign up a contract with the reaper.");
4807 break;
4809 case SPE_RANDOM_DETECTION:
4811 switch (rnd(4)) {
4812 case 1:
4813 trap_detectX((struct obj *)0);
4814 break;
4815 case 2:
4816 You("fail to detect anything.");
4817 break;
4818 case 3:
4819 object_detect(pseudo, 0);
4820 break;
4821 case 4:
4822 monster_detect(pseudo, 0);
4823 break;
4826 exercise(A_WIS, TRUE);
4828 if (!rn2(5)) {
4829 pline("The spell backlashes!");
4830 badeffect();
4833 break;
4835 case SPE_AULE_SMITHING:
4837 if (CannotSelectItemsInPrompts) break;
4838 pline("Choose an item for erosionproofing.");
4839 aulechoice:
4840 otmp = getobj(allnoncount, "fooproof");
4841 if (!otmp) {
4842 if (yn("Really exit with no object selected?") == 'y')
4843 pline("You just wasted the opportunity to fooproof an item.");
4844 else goto aulechoice;
4845 pline("You decide not to erosionproof any item after all.");
4846 break;
4848 if (otmp) {
4849 otmp->oerodeproof = TRUE;
4850 pline("Success! Your item is erosionproof now.");
4851 if (otmp && objects[(otmp)->otyp].oc_material == MT_CELESTIUM && !stack_too_big(otmp)) {
4852 if (!otmp->cursed) bless(otmp);
4853 else uncurse(otmp, FALSE);
4857 break;
4859 case SPE_HORSE_HOP:
4860 u.horsehopturns = 50 + rnd(50 + (spell_damage_bonus(spellid(spell)) * 5) );
4861 pline("You can jump while riding!");
4863 break;
4865 case SPE_LINE_LOSS:
4869 register struct monst *nexusmon, *nextmon;
4871 for(nexusmon = fmon; nexusmon; nexusmon = nextmon) {
4872 nextmon = nexusmon->nmon; /* trap might kill mon */
4873 if (DEADMONSTER(nexusmon)) continue;
4875 if (!sensemon(nexusmon) && !canseemon(nexusmon)) continue;
4877 nexusmon->mhp--;
4878 if (nexusmon->mhp <= 0) {
4879 xkilled(nexusmon, 0);
4880 pline("%s lost the last line and dies!", Monnam(nexusmon));
4882 else {
4883 pline("%s loses a line!", Monnam(nexusmon));
4884 wakeup(nexusmon); /* monster becomes hostile */
4891 break;
4893 case SPE_TACTICAL_NUKE:
4895 if (Upolyd) losehp((u.mhmax / 10) + 1, "tactical nuke", KILLED_BY_AN);
4896 else losehp((u.uhpmax / 10) + 1, "tactical nuke", KILLED_BY_AN);
4897 pline("Rrrrroommmmmm - the nuke hits you and all monsters in view.");
4901 register struct monst *nexusmon, *nextmon;
4903 for(nexusmon = fmon; nexusmon; nexusmon = nextmon) {
4904 nextmon = nexusmon->nmon; /* trap might kill mon */
4905 if (DEADMONSTER(nexusmon)) continue;
4907 if (!sensemon(nexusmon) && !canseemon(nexusmon)) continue;
4909 nexusmon->mhp -= ((nexusmon->mhp / 10) + 1);
4910 if (nexusmon->mhp <= 0) {
4911 xkilled(nexusmon, 0);
4912 pline("%s dies to the nuke!", Monnam(nexusmon));
4914 else {
4915 pline("%s is hurt by the nuke!", Monnam(nexusmon));
4916 wakeup(nexusmon); /* monster becomes hostile */
4923 break;
4925 case SPE_RAGNAROK:
4927 if (u.ragnarokspelltimeout) {
4928 pline("Nothing happens.");
4929 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
4930 pline("Oh wait, actually something bad happens...");
4931 badeffect();
4933 break;
4935 ragnarok(TRUE);
4936 if (evilfriday) evilragnarok(TRUE,level_difficulty());
4937 u.ragnarokspelltimeout += 1000; /* can't use it again for a while */
4939 break;
4941 case SPE_IMPACT_GUNFIRE:
4943 if (u.gaugetimer) {
4944 You("need to wait %d more turns to refill your gauge. Impact Gunfire can be used again at turn %ld.", u.gaugetimer, (moves + u.gaugetimer));
4945 break;
4946 } else {
4947 u.gaugetimer = 50;
4951 register struct obj *opbullet;
4952 int opbonus = 0;
4953 int opdamage = 0;
4954 int ctx, cty;
4955 int i;
4956 ctx = u.ux, cty = u.uy;
4958 coord cc;
4959 struct monst *psychmonst;
4961 opbullet = carrying(PISTOL_BULLET);
4962 if (!opbullet) opbullet = carrying(SILVER_PISTOL_BULLET);
4963 if (!opbullet) opbullet = carrying(LEAD_PISTOL_BULLET);
4964 if (!opbullet) opbullet = carrying(ANTIMATTER_PISTOL_BULLET);
4965 if (!opbullet) {
4966 pline("There are no pistol bullets, and therefore you can't shoot!");
4967 break;
4970 opdamage = d(8, 12) + (spell_damage_bonus(spellid(spell)) * 6);
4972 if (opbullet) {
4973 if (opbullet->spe > 0) opbonus = opbullet->spe;
4975 if (opbullet->quan > 1) {
4976 opbullet->quan--;
4977 opbullet->owt = weight(opbullet);
4979 else useup(opbullet);
4983 if (opdamage > 1) opdamage = rnd(opdamage);
4984 opdamage += (opbonus * rnd(25));
4986 if (!getdir((char *)0)) return(0);
4987 if (!u.dx && !u.dy) {
4988 You("can't direct that at yourself.");
4989 break;
4992 for(i = 0; i < 8; i++) {
4993 if (!isok(ctx + u.dx, cty + u.dy)) break;
4994 if (levl[ctx + u.dx][cty + u.dy].typ < POOL) break;
4996 ctx += u.dx;
4997 cty += u.dy;
4999 psychmonst = m_at(ctx, cty);
5001 if (psychmonst) {
5002 pline("Pouchschieau! Your projectile blasts %s!", mon_nam(psychmonst));
5003 if (noncorporeal(psychmonst->data)) { /* ghosts are hard to hit... */
5004 if (opdamage > 1) opdamage /= 2;
5005 pline("%s resists the attack!", Monnam(psychmonst));
5006 /* but isn't immune --Amy */
5008 psychmonst->mhp -= opdamage;
5009 if (psychmonst->mhp < 1) {
5010 pline("%s is blown to bits.", Monnam(psychmonst));
5011 xkilled(psychmonst,0);
5012 } else {
5013 wakeup(psychmonst); /* make them hostile */
5014 if (psychmonst->mcanmove) {
5015 psychmonst->mcanmove = 0;
5016 psychmonst->mfrozen = 2;
5017 pline("%s is paralyzed.", Monnam(psychmonst));
5020 break;
5027 break;
5029 case SPE_ONE_POINT_SHOOT:
5031 if (u.gaugetimer) {
5032 You("need to wait %d more turns to refill your gauge. One Point Shoot can be used again at turn %ld.", u.gaugetimer, (moves + u.gaugetimer));
5033 break;
5034 } else {
5035 u.gaugetimer = 50;
5039 register struct obj *opbullet;
5040 int opbonus = 0;
5041 int opdamage = 0;
5043 coord cc;
5044 struct monst *psychmonst;
5046 opbullet = carrying(PISTOL_BULLET);
5047 if (!opbullet) opbullet = carrying(SILVER_PISTOL_BULLET);
5048 if (!opbullet) opbullet = carrying(LEAD_PISTOL_BULLET);
5049 if (!opbullet) opbullet = carrying(ANTIMATTER_PISTOL_BULLET);
5050 if (!opbullet) {
5051 pline("There are no pistol bullets, and therefore you can't shoot!");
5052 break;
5055 opdamage = d(6, 12) + (spell_damage_bonus(spellid(spell)) * 5);
5057 pline("Select the target monster");
5058 cc.x = u.ux;
5059 cc.y = u.uy;
5060 getpos(&cc, TRUE, "the spot to shoot");
5061 if (cc.x == -10) break; /* user pressed esc */
5062 psychmonst = m_at(cc.x, cc.y);
5064 if (!psychmonst || (!canseemon(psychmonst) && !canspotmon(psychmonst))) {
5065 You("don't see a monster there!");
5066 break;
5069 /* there should be a valid target now, so use up a bullet */
5070 if (opbullet) {
5071 if (opbullet->spe > 0) opbonus = opbullet->spe;
5073 if (opbullet->quan > 1) {
5074 opbullet->quan--;
5075 opbullet->owt = weight(opbullet);
5077 else useup(opbullet);
5081 if (opdamage > 1) opdamage = rnd(opdamage);
5082 opdamage += (opbonus * rnd(20));
5084 if (psychmonst) {
5086 pline("PEW PEW PEW! %s is shot by your gun!", Monnam(psychmonst));
5087 if (noncorporeal(psychmonst->data)) { /* ghosts are hard to hit... */
5088 if (opdamage > 1) opdamage /= 2;
5089 pline("%s resists the attack!", Monnam(psychmonst));
5090 /* but isn't immune --Amy */
5092 psychmonst->mhp -= opdamage;
5093 if (psychmonst->mhp < 1) {
5094 pline("%s resonates and breaks up.", Monnam(psychmonst));
5095 xkilled(psychmonst,0);
5096 } else wakeup(psychmonst); /* make them hostile */
5102 break;
5104 case SPE_RETURN:
5106 if (u.returntimer) {
5107 u.returntimer = 0;
5108 pline_The("air around you gradually loses power.");
5109 break; /* be lenient, damage Pw only if you're not already returning --Amy */
5112 u.uenmax -= rnd(3);
5113 if (u.uenmax < 0) u.uenmax = 0;
5114 if (u.uen > u.uenmax) u.uen = u.uenmax;
5116 setupreturn(0);
5118 break;
5120 case SPE_GROUND_STOMP:
5122 if (Confusion) {
5123 You("are unable to use ground stomp while confused.");
5124 break;
5127 You("smash something the ground."); /* This is NOT a misspelling!!! --Amy */
5131 register struct monst *nexusmon, *nextmon;
5133 for(nexusmon = fmon; nexusmon; nexusmon = nextmon) {
5134 nextmon = nexusmon->nmon; /* trap might kill mon */
5135 if (DEADMONSTER(nexusmon)) continue;
5136 if (!monnear(nexusmon, u.ux, u.uy)) continue;
5138 if (!sensemon(nexusmon) && !canseemon(nexusmon)) continue;
5140 nexusmon->mhp -= (d(10, 10 + (spell_damage_bonus(spellid(spell)) * 5) ) + rnd(boosted_ulevel(1) * 5));
5141 if (nexusmon->mhp <= 0) {
5142 xkilled(nexusmon, 0);
5143 pline("%s is crushed flat!", Monnam(nexusmon));
5145 else {
5146 pline("%s is hit by debris!", Monnam(nexusmon));
5147 wakeup(nexusmon); /* monster becomes hostile */
5154 make_confused(HConfusion + rn1(50,75), FALSE);
5155 set_itimeout(&HeavyConfusion, HConfusion);
5156 u.uprops[DEAC_CONF_RES].intrinsic += rn1(50,75);
5158 break;
5160 case SPE_DIRECTIVE:
5164 int successrate = 0;
5166 if (!(PlayerCannotUseSkills) && P_SKILL(P_OCCULT_SPELL) >= P_UNSKILLED) {
5168 switch (P_SKILL(P_OCCULT_SPELL)) {
5169 case P_BASIC: successrate = 25; break;
5170 case P_SKILLED: successrate = 40; break;
5171 case P_EXPERT: successrate = 50; break;
5172 case P_MASTER: successrate = 60; break;
5173 case P_GRAND_MASTER: successrate = 80; break;
5174 case P_SUPREME_MASTER: successrate = 100; break;
5175 default: successrate = 10; break;
5180 if (!successrate) {
5181 pline("Unfortunately, no one seems to follow any directives you're giving.");
5182 break;
5185 if (!PlayerCannotUseSkills && P_SKILL(P_RIDING) >= P_SKILLED && rnd(75) <= successrate) {
5187 pline("Currently your steed has %d%% chance of being targetted by monsters.", u.steedhitchance);
5188 if (yn("Change it?") == 'y') {
5190 int lowerbound, higherbound;
5191 lowerbound = 25;
5192 higherbound = 25;
5194 switch (P_SKILL(P_RIDING)) {
5195 case P_SKILLED:
5196 lowerbound = 20;
5197 higherbound = 33;
5198 break;
5199 case P_EXPERT:
5200 lowerbound = 10;
5201 higherbound = 50;
5202 break;
5203 case P_MASTER:
5204 lowerbound = 5;
5205 higherbound = 75;
5206 break;
5207 case P_GRAND_MASTER:
5208 lowerbound = 3;
5209 higherbound = 90;
5210 break;
5211 case P_SUPREME_MASTER:
5212 lowerbound = 1;
5213 higherbound = 100;
5214 break;
5215 default:
5216 lowerbound = 25;
5217 higherbound = 25;
5218 break;
5221 pline("You can set the chance to values between %d%% and %d%% (inclusive).", lowerbound, higherbound);
5222 if (lowerbound <= 1 && yn("Set the chance to 1%%?") == 'y') {
5223 u.steedhitchance = 1;
5224 pline("The chance that attacks target your steed is 1%% now.");
5225 } else if (lowerbound <= 3 && yn("Set the chance to 3%%?") == 'y') {
5226 u.steedhitchance = 3;
5227 pline("The chance that attacks target your steed is 3%% now.");
5228 } else if (lowerbound <= 5 && yn("Set the chance to 5%%?") == 'y') {
5229 u.steedhitchance = 5;
5230 pline("The chance that attacks target your steed is 5%% now.");
5231 } else if (lowerbound <= 10 && yn("Set the chance to 10%%?") == 'y') {
5232 u.steedhitchance = 10;
5233 pline("The chance that attacks target your steed is 10%% now.");
5234 } else if (lowerbound <= 20 && yn("Set the chance to 20%%?") == 'y') {
5235 u.steedhitchance = 20;
5236 pline("The chance that attacks target your steed is 20%% now.");
5237 } else if (yn("Set the chance to 25%%?") == 'y') {
5238 u.steedhitchance = 25;
5239 pline("The chance that attacks target your steed is 25%% now.");
5240 } else if (higherbound >= 33 && yn("Set the chance to 33%%?") == 'y') {
5241 u.steedhitchance = 33;
5242 pline("The chance that attacks target your steed is 33%% now.");
5243 } else if (higherbound >= 50 && yn("Set the chance to 50%%?") == 'y') {
5244 u.steedhitchance = 50;
5245 pline("The chance that attacks target your steed is 50%% now.");
5246 } else if (higherbound >= 75 && yn("Set the chance to 75%%?") == 'y') {
5247 u.steedhitchance = 75;
5248 pline("The chance that attacks target your steed is 75%% now.");
5249 } else if (higherbound >= 90 && yn("Set the chance to 90%%?") == 'y') {
5250 u.steedhitchance = 90;
5251 pline("The chance that attacks target your steed is 90%% now.");
5252 } else if (higherbound >= 100 && yn("Set the chance to 100%%?") == 'y') {
5253 u.steedhitchance = 100;
5254 pline("The chance that attacks target your steed is 100%% now.");
5255 } else pline("The chance that attacks target your steed remains %d%%.", u.steedhitchance);
5261 if (rnd(20) <= successrate) {
5263 pline("Currently your pets can%s pick up items.", u.petcollectitems ? "" : "'t");
5264 if (yn("Change it?") == 'y') {
5265 if (u.petcollectitems) u.petcollectitems = 0;
5266 else u.petcollectitems = 1;
5267 pline("Your pets can%s pick up items now.", u.petcollectitems ? "" : "'t");
5272 if (rnd(45) <= successrate) {
5274 pline("Currently your pets can%s attack%s monsters.", (u.petattackenemies > 0) ? "" : "'t", u.petattackenemies == 2 ? " both hostile and peaceful" : u.petattackenemies == 1 ? " only hostile" : u.petattackenemies == -1 ? " or be attacked by" : "");
5275 if (yn("Change it?") == 'y') {
5276 pline("You got the following options: make the pet attack everything, make it attack only hostile monsters, or prevent it from attacking anything (with the choice that it may or may not still be attacked by hostiles).");
5277 if (yn("Do you want your pets to attack everything?") == 'y') {
5278 u.petattackenemies = 2;
5279 pline("Your pets can attack all monsters now.");
5280 } else if (yn("Do you want your pets to only attack hostile creatures?") == 'y') {
5281 u.petattackenemies = 1;
5282 pline("Your pets can attack hostile monsters now, but will leave peaceful ones alone.");
5283 } else if (yn("Do you want your pets to not attack any monsters, but still be attacked by them?") == 'y') {
5284 u.petattackenemies = 0;
5285 pline("Your pets can't attack monsters now.");
5286 } else if (yn("Do you want your pets to not attack any monsters, and also not be attacked by them anymore?") == 'y') {
5287 u.petattackenemies = -1;
5288 pline("Your pets can't attack monsters now and also won't be attacked by monsters.");
5294 if (rnd(75) <= successrate) {
5296 pline("Currently your pets can%s eat food off the floor.", u.petcaneat ? "" : "'t");
5297 if (yn("Change it?") == 'y') {
5298 if (u.petcaneat) u.petcaneat = 0;
5299 else u.petcaneat = 1;
5300 pline("Your pets can%s eat food off the floor now.", u.petcaneat ? "" : "'t");
5305 if (rnd(120) <= successrate) {
5307 pline("Currently your pets can%s try to follow you.", u.petcanfollow ? "" : "'t");
5308 if (yn("Change it?") == 'y') {
5309 if (u.petcanfollow) u.petcanfollow = 0;
5310 else u.petcanfollow = 1;
5311 pline("Your pets can%s try to follow you now.", u.petcanfollow ? "" : "'t");
5318 break;
5320 case SPE_POWDER_SPRAY:
5322 You("spray the powder.");
5326 register struct monst *nexusmon, *nextmon;
5328 for(nexusmon = fmon; nexusmon; nexusmon = nextmon) {
5329 nextmon = nexusmon->nmon; /* trap might kill mon */
5330 if (DEADMONSTER(nexusmon)) continue;
5332 if (!monnear(nexusmon, u.ux, u.uy)) continue;
5333 if (resist(nexusmon, SPBOOK_CLASS, 0, NOTELL)) continue;
5334 if (resists_poison(nexusmon) && !player_will_pierce_resistance()) continue;
5336 nexusmon->mhp -= rn1(10, 6);
5337 if (!rn2(500) && !resists_poison(nexusmon)) {
5338 pline("The poison was deadly...");
5339 nexusmon->mhp = -1;
5340 xkilled(nexusmon, 0);
5341 } else if (nexusmon->mhp <= 0) {
5342 xkilled(nexusmon, 0);
5343 pline("%s is poisoned to death!", Monnam(nexusmon));
5345 else {
5346 pline("%s is poisoned!", Monnam(nexusmon));
5347 wakeup(nexusmon); /* monster becomes hostile */
5353 break;
5355 case SPE_FIREWORKS:
5357 throwstorm(pseudo, 2 + spell_damage_bonus(SPE_FIREWORKS), 2, 2);
5359 break;
5361 case SPE_AIMBOT_LIGHTNING:
5364 coord cc;
5365 int dirx, diry;
5367 pline("Select the target square");
5368 cc.x = u.ux;
5369 cc.y = u.uy;
5370 getpos(&cc, TRUE, "the spot to aim lightning from");
5371 if (cc.x == -10) break; /* user pressed esc */
5373 if (!couldsee(cc.x, cc.y)) {
5374 You("can't see the location, and therefore nothing happens!");
5375 break;
5378 dirx = rn2(3) - 1;
5379 diry = rn2(3) - 1;
5380 if (dirx == 0 && diry == 0) { /* fail safe; yeah I know this biases it towards diagonal :P --Amy */
5381 dirx = rn2(2) ? 1 : -1;
5382 diry = rn2(2) ? 1 : -1;
5384 if (dirx != 0 || diry != 0) {
5385 buzz(15, 8 + (spell_damage_bonus(SPE_AIMBOT_LIGHTNING) * rnd(2)), cc.x, cc.y, dirx, diry);
5390 break;
5392 case SPE_ENHANCE_BREATH:
5394 u.breathenhancetimer = 100 + (spell_damage_bonus(SPE_ENHANCE_BREATH) * 10);
5395 Your("breath is magically enhanced!");
5397 break;
5399 case SPE_GOUGE_DICK:
5401 if (!u.uswallow) {
5402 pline("This spell has no effect if you're not engulfed.");
5403 break;
5405 pline("You ram into %s with your %spenis.", mon_nam(u.ustuck), flags.female ? "nonexistant " : "");
5406 if (u.ustuck->mpeaceful && !(u.ustuck->mtame)) u.ustuck->mpeaceful = 0; /* monster becomes hostile */
5407 u.ustuck->mhp -= d(flags.female ? 2 : 5, 5 + spell_damage_bonus(SPE_GOUGE_DICK) + rno(boosted_ulevel(1)));
5408 u.ustuck->mcanmove = 0;
5409 u.ustuck->mfrozen = rn1(5,5);
5410 u.ustuck->mstrategy &= ~STRAT_WAITFORU;
5412 if (u.ustuck->mhp <= 0) {
5413 xkilled(u.ustuck, 0);
5414 pline("The monster that engulfed you is stabbed to death!");
5416 else pline("%s is severely hurt!", Monnam(u.ustuck));
5418 break;
5420 case SPE_BODYFLUID_STRENGTHENING:
5422 u.bodyfluideffect = 10 + spell_damage_bonus(SPE_BODYFLUID_STRENGTHENING);
5423 Your("body is covered with protective acid!");
5425 break;
5427 case SPE_PURIFICATION:
5430 int i, j;
5431 for (i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
5432 if (!isok(u.ux + i, u.uy + j)) continue;
5433 if (i == 0 && j == 0) continue; /* don't target the square you're on --Amy */
5434 if (levl[u.ux + i][u.uy + j].typ == STYXRIVER) {
5435 levl[u.ux + i][u.uy + j].typ = MOAT;
5436 Norep("A styx river turns into a moat!");
5441 if (!(InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone())) (void)doredraw();
5443 break;
5445 case SPE_ADD_SPELL_MEMORY:
5447 if (spellid(0) == NO_SPELL) { /* should never happen, but I put it here just in case --Amy */
5448 You("don't know any spells, and therefore you cannot add spell memory to them either.");
5449 break;
5452 pline("Choose a spell to add spell memory.");
5453 addspmagain:
5454 if (!addsomespellmemory()) {
5455 if (yn("Really exit with no spell selected?") == 'y')
5456 pline("You just wasted the opportunity to add memory to a spell.");
5457 else goto addspmagain;
5460 break;
5462 case SPE_NEXUSPORT:
5464 switch (rnd(7)) {
5466 case 1:
5467 case 2:
5468 case 3:
5469 pline("You are teleported by nexus forces!");
5470 teleX();
5471 break;
5472 case 4:
5473 case 5:
5474 pline("You are pushed around by nexus forces!");
5475 phase_door(0);
5476 break;
5477 case 6:
5479 if (!playerlevelportdisabled() ) {
5480 make_stunned(HStun + 2, FALSE); /* to suppress teleport control that you might have */
5482 if (!u.levelporting) {
5483 u.levelporting = 1;
5484 nomul(-2, "being levelported", FALSE); /* because it's not called until you get another turn... */
5487 break;
5488 case 7:
5490 nexus_swap();
5492 if (!rn2(3)) {
5494 int reducedstat = rn2(A_MAX);
5495 if(ABASE(reducedstat) <= ATTRABSMIN(reducedstat)) {
5496 pline("Your health was damaged!");
5497 u.uhpmax -= rnd(5);
5498 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
5499 if (u.uhp < 1) {
5500 u.youaredead = 1;
5501 killer = "nexus scrambling";
5502 killer_format = KILLED_BY;
5503 done(DIED);
5504 u.youaredead = 0;
5507 } else {
5508 ABASE(reducedstat) -= 1;
5509 AMAX(reducedstat) -= 1;
5510 flags.botl = 1;
5511 pline("Your attributes were damaged!");
5515 break;
5519 if (!rn2(5)) {
5520 pline("The spell backfires!");
5521 badeffect();
5524 break;
5526 case SPE_ANTI_TELEPORTATION:
5528 u.antitelespelltimeout = rnd(100 + (spell_damage_bonus(SPE_ANTI_TELEPORTATION) * 10));
5529 You("erect an anti-teleportation barrier!");
5531 break;
5533 case SPE_FUMBLING:
5534 if (!Fumbling) pline("You start fumbling.");
5535 HFumbling = FROMOUTSIDE | rnd(5);
5536 set_itimeout(&HFumbling, 2);
5537 u.fumbleduration += rnz(1000);
5538 break;
5539 case SPE_REMOVE_BLESSING:
5542 if (FunnyHallu)
5543 You_feel("the power of the Force against you!");
5544 else
5545 You_feel("like you need some help.");
5546 if (PlayerHearsSoundEffects) pline(issoviet ? "Vashe der'mo tol'ko chto proklinal." : "Woaaaaaa-AAAH!");
5548 register struct obj *obj, *obj2;
5549 for (obj = invent; obj; obj = obj2) {
5550 obj2 = obj->nobj;
5551 if (obj->blessed && !stack_too_big(obj) ) unbless(obj);
5555 break;
5556 case SPE_CORRODE_METAL:
5559 pline("You are covered by %s particles!",NH_GREEN);
5561 register struct obj *obj, *obj2;
5562 for (obj = invent; obj; obj = obj2) {
5563 obj2 = obj->nobj;
5564 rust_dmg(obj, xname(obj), 3, TRUE, &youmonst);
5568 break;
5569 case SPE_DETECT_ARMOR_ENCHANTMENT:
5572 pline("You detect the enchantment status of your armor!");
5574 register struct obj *obj, *obj2;
5575 for (obj = invent; obj; obj = obj2) {
5576 obj2 = obj->nobj;
5578 if (obj->oclass == ARMOR_CLASS && !obj->known && (obj->shirtmessage % 3 == 0) ) {
5579 obj->known = TRUE;
5580 break;
5586 break;
5588 case SPE_METAL_GUARD:
5590 if (u.metalguard) pline("%s", nothing_happens);
5591 else {
5592 u.metalguard = TRUE;
5593 You("activate your metal guard!");
5596 break;
5598 case SPE_MAGIC_WHISTLING:
5601 register struct monst *whismtmp, *whisnextmon;
5603 You("try to whistle your pets here...");
5605 for(whismtmp = fmon; whismtmp; whismtmp = whisnextmon) {
5606 whisnextmon = whismtmp->nmon; /* trap might kill mon */
5607 if (DEADMONSTER(whismtmp)) continue;
5608 if (evilfriday && level.flags.noteleport) continue;
5609 if (whismtmp == u.usteed) continue;
5610 if (whismtmp->mtame) {
5611 if (whismtmp->mtrapped) {
5612 /* no longer in previous trap (affects mintrap) */
5613 whismtmp->mtrapped = 0;
5614 fill_pit(whismtmp->mx, whismtmp->my);
5616 mnexto(whismtmp);
5617 if (mintrap(whismtmp) == 2) change_luck(-1);
5621 break;
5623 case SPE_GAIN_SPACT:
5625 if (u.uhpmax < 101) {
5626 pline("You don't have enough health to control the powers of this spell!");
5627 break;
5629 if (Upolyd && u.mhmax < 101) {
5630 pline("You don't have enough health to control the powers of this spell!");
5631 break;
5634 u.uhpmax -= rnd(100);
5635 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
5636 if (Upolyd) {
5637 u.mhmax -= rnd(100);
5638 if (u.mh > u.mhmax) u.mh = u.mhmax;
5642 int wondertech = rnd(MAXTECH-1);
5643 learntech_or_leveltech(wondertech, FROMOUTSIDE, 1);
5644 You("learn how to perform a new technique!");
5648 break;
5650 case SPE_ATTUNE_MAGIC:
5652 if (rn2(3)) {
5653 pline("Your mana increases.");
5654 u.uenmax++;
5655 } else switch (rnd(30)) {
5657 case 1:
5658 HTeleport_control += 2;
5659 tele();
5660 break;
5661 case 2:
5664 register struct obj *acqo;
5666 acqo = mkobj_at(SPBOOK_CLASS, u.ux, u.uy, FALSE, FALSE);
5667 if (acqo) {
5668 acqo->bknown = acqo->known = TRUE;
5669 pline("A book appeared at your %s!", makeplural(body_part(FOOT)));
5670 } else {
5671 pline("Nothing happens...");
5672 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
5673 pline("Oh wait, actually something bad happens...");
5674 badeffect();
5678 break;
5679 case 3:
5680 (void) monster_detect((struct obj *)0, 0);
5681 exercise(A_WIS, TRUE);
5682 break;
5683 case 4:
5684 trap_detect((struct obj *)0);
5685 break;
5686 case 5:
5687 object_detect((struct obj *)0, 0);
5688 break;
5689 case 6:
5691 boolean havegifts = u.ugifts;
5693 if (!havegifts) u.ugifts++;
5695 register struct obj *acqo;
5697 acqo = mk_artifact((struct obj *)0, !rn2(3) ? A_CHAOTIC : rn2(2) ? A_NEUTRAL : A_LAWFUL, TRUE);
5698 if (acqo) {
5699 dropy(acqo);
5700 int acqoskill = get_obj_skill(acqo, TRUE);
5702 if (P_MAX_SKILL(acqoskill) == P_ISRESTRICTED) {
5703 unrestrict_weapon_skill(acqoskill);
5704 } else if (P_MAX_SKILL(acqoskill) == P_UNSKILLED) {
5705 unrestrict_weapon_skill(acqoskill);
5706 P_MAX_SKILL(acqoskill) = P_BASIC;
5707 } else if (rn2(2) && P_MAX_SKILL(acqoskill) == P_BASIC) {
5708 P_MAX_SKILL(acqoskill) = P_SKILLED;
5709 } else if (!rn2(4) && P_MAX_SKILL(acqoskill) == P_SKILLED) {
5710 P_MAX_SKILL(acqoskill) = P_EXPERT;
5711 } else if (!rn2(10) && P_MAX_SKILL(acqoskill) == P_EXPERT) {
5712 P_MAX_SKILL(acqoskill) = P_MASTER;
5713 } else if (!rn2(100) && P_MAX_SKILL(acqoskill) == P_MASTER) {
5714 P_MAX_SKILL(acqoskill) = P_GRAND_MASTER;
5715 } else if (!rn2(200) && P_MAX_SKILL(acqoskill) == P_GRAND_MASTER) {
5716 P_MAX_SKILL(acqoskill) = P_SUPREME_MASTER;
5718 if (Race_if(PM_RUSMOT)) {
5719 if (P_MAX_SKILL(acqoskill) == P_ISRESTRICTED) {
5720 unrestrict_weapon_skill(acqoskill);
5721 } else if (P_MAX_SKILL(acqoskill) == P_UNSKILLED) {
5722 unrestrict_weapon_skill(acqoskill);
5723 P_MAX_SKILL(acqoskill) = P_BASIC;
5724 } else if (rn2(2) && P_MAX_SKILL(acqoskill) == P_BASIC) {
5725 P_MAX_SKILL(acqoskill) = P_SKILLED;
5726 } else if (!rn2(4) && P_MAX_SKILL(acqoskill) == P_SKILLED) {
5727 P_MAX_SKILL(acqoskill) = P_EXPERT;
5728 } else if (!rn2(10) && P_MAX_SKILL(acqoskill) == P_EXPERT) {
5729 P_MAX_SKILL(acqoskill) = P_MASTER;
5730 } else if (!rn2(100) && P_MAX_SKILL(acqoskill) == P_MASTER) {
5731 P_MAX_SKILL(acqoskill) = P_GRAND_MASTER;
5732 } else if (!rn2(200) && P_MAX_SKILL(acqoskill) == P_GRAND_MASTER) {
5733 P_MAX_SKILL(acqoskill) = P_SUPREME_MASTER;
5737 discover_artifact(acqo->oartifact);
5739 if (!havegifts) u.ugifts--;
5740 pline("An artifact appeared beneath you!");
5744 else pline("Opportunity knocked, but nobody was home. Bummer.");
5748 break;
5749 case 7:
5750 pline("The RNG decides to curse-weld an item to you.");
5751 bad_artifact_xtra();
5752 break;
5753 case 8:
5755 int aggroamount = rnd(6);
5756 if (isfriday) aggroamount *= 2;
5757 u.aggravation = 1;
5758 reset_rndmonst(NON_PM);
5759 while (aggroamount) {
5760 u.cnd_aggravateamount++;
5761 makemon((struct permonst *)0, u.ux, u.uy, MM_ANGRY|MM_FRENZIED);
5762 aggroamount--;
5763 if (aggroamount < 0) aggroamount = 0;
5765 u.aggravation = 0;
5766 pline("Several monsters come out of a portal.");
5770 break;
5771 case 9:
5772 pline("Your body suddenly becomes all stiff!");
5773 if (isstunfish) nomul(-rnz(15), "paralyzed by a pentagram", TRUE);
5774 else nomul(-rnd(15), "paralyzed by a pentagram", TRUE);
5775 break;
5776 case 10:
5778 pline("The dungeon is getting more chaotic!");
5780 int madepoolPEP = 0;
5781 do_clear_areaX(u.ux, u.uy, 12, do_terrainfloodg, (void *)&madepoolPEP);
5784 break;
5785 case 11:
5786 You_feel("powered up!");
5787 u.uenmax += rnd(5);
5788 u.uen = u.uenmax;
5789 break;
5790 case 12:
5791 pline("Suddenly, you gain a new companion!");
5792 (void) make_familiar((struct obj *)0, u.ux, u.uy, FALSE, FALSE);
5793 break;
5794 case 13:
5797 if (Aggravate_monster) {
5798 u.aggravation = 1;
5799 reset_rndmonst(NON_PM);
5802 coord dd;
5803 coord cc;
5804 int cx,cy;
5805 int i;
5806 int randsp, randmnst, randmnsx;
5807 struct permonst *randmonstforspawn;
5808 int monstercolor;
5810 cx = rn2(COLNO);
5811 cy = rn2(ROWNO);
5813 if (!rn2(4)) {
5815 randsp = (rn2(14) + 2);
5816 if (!rn2(10)) randsp *= 2;
5817 if (!rn2(100)) randsp *= 3;
5818 if (!rn2(1000)) randsp *= 5;
5819 if (!rn2(10000)) randsp *= 10;
5820 randmnst = (rn2(187) + 1);
5821 randmnsx = (rn2(100) + 1);
5823 pline("You suddenly feel a surge of tension!");
5825 for (i = 0; i < randsp; i++) {
5826 /* This function will fill the map with a random amount of monsters of one class. --Amy */
5828 if (!enexto(&dd, u.ux, u.uy, (struct permonst *)0) ) continue;
5830 if (randmnst < 6)
5831 (void) makemon(mkclass(S_ANT,0), cx, cy, MM_ADJACENTOK);
5832 else if (randmnst < 9)
5833 (void) makemon(mkclass(S_BLOB,0), cx, cy, MM_ADJACENTOK);
5834 else if (randmnst < 11)
5835 (void) makemon(mkclass(S_COCKATRICE,0), cx, cy, MM_ADJACENTOK);
5836 else if (randmnst < 15)
5837 (void) makemon(mkclass(S_DOG,0), cx, cy, MM_ADJACENTOK);
5838 else if (randmnst < 18)
5839 (void) makemon(mkclass(S_EYE,0), cx, cy, MM_ADJACENTOK);
5840 else if (randmnst < 22)
5841 (void) makemon(mkclass(S_FELINE,0), cx, cy, MM_ADJACENTOK);
5842 else if (randmnst < 24)
5843 (void) makemon(mkclass(S_GREMLIN,0), cx, cy, MM_ADJACENTOK);
5844 else if (randmnst < 29)
5845 (void) makemon(mkclass(S_HUMANOID,0), cx, cy, MM_ADJACENTOK);
5846 else if (randmnst < 33)
5847 (void) makemon(mkclass(S_IMP,0), cx, cy, MM_ADJACENTOK);
5848 else if (randmnst < 36)
5849 (void) makemon(mkclass(S_JELLY,0), cx, cy, MM_ADJACENTOK);
5850 else if (randmnst < 41)
5851 (void) makemon(mkclass(S_KOBOLD,0), cx, cy, MM_ADJACENTOK);
5852 else if (randmnst < 44)
5853 (void) makemon(mkclass(S_LEPRECHAUN,0), cx, cy, MM_ADJACENTOK);
5854 else if (randmnst < 47)
5855 (void) makemon(mkclass(S_MIMIC,0), cx, cy, MM_ADJACENTOK);
5856 else if (randmnst < 50)
5857 (void) makemon(mkclass(S_NYMPH,0), cx, cy, MM_ADJACENTOK);
5858 else if (randmnst < 54)
5859 (void) makemon(mkclass(S_ORC,0), cx, cy, MM_ADJACENTOK);
5860 else if (randmnst < 55)
5861 (void) makemon(mkclass(S_PIERCER,0), cx, cy, MM_ADJACENTOK);
5862 else if (randmnst < 58)
5863 (void) makemon(mkclass(S_QUADRUPED,0), cx, cy, MM_ADJACENTOK);
5864 else if (randmnst < 62)
5865 (void) makemon(mkclass(S_RODENT,0), cx, cy, MM_ADJACENTOK);
5866 else if (randmnst < 65)
5867 (void) makemon(mkclass(S_SPIDER,0), cx, cy, MM_ADJACENTOK);
5868 else if (randmnst < 66)
5869 (void) makemon(mkclass(S_TRAPPER,0), cx, cy, MM_ADJACENTOK);
5870 else if (randmnst < 69)
5871 (void) makemon(mkclass(S_UNICORN,0), cx, cy, MM_ADJACENTOK);
5872 else if (randmnst < 71)
5873 (void) makemon(mkclass(S_VORTEX,0), cx, cy, MM_ADJACENTOK);
5874 else if (randmnst < 73)
5875 (void) makemon(mkclass(S_WORM,0), cx, cy, MM_ADJACENTOK);
5876 else if (randmnst < 75)
5877 (void) makemon(mkclass(S_XAN,0), cx, cy, MM_ADJACENTOK);
5878 else if (randmnst < 76)
5879 (void) makemon(mkclass(S_LIGHT,0), cx, cy, MM_ADJACENTOK);
5880 else if (randmnst < 77)
5881 (void) makemon(mkclass(S_ZOUTHERN,0), cx, cy, MM_ADJACENTOK);
5882 else if (randmnst < 78)
5883 (void) makemon(mkclass(S_ANGEL,0), cx, cy, MM_ADJACENTOK);
5884 else if (randmnst < 81)
5885 (void) makemon(mkclass(S_BAT,0), cx, cy, MM_ADJACENTOK);
5886 else if (randmnst < 83)
5887 (void) makemon(mkclass(S_CENTAUR,0), cx, cy, MM_ADJACENTOK);
5888 else if (randmnst < 86)
5889 (void) makemon(mkclass(S_DRAGON,0), cx, cy, MM_ADJACENTOK);
5890 else if (randmnst < 89)
5891 (void) makemon(mkclass(S_ELEMENTAL,0), cx, cy, MM_ADJACENTOK);
5892 else if (randmnst < 94)
5893 (void) makemon(mkclass(S_FUNGUS,0), cx, cy, MM_ADJACENTOK);
5894 else if (randmnst < 99)
5895 (void) makemon(mkclass(S_GNOME,0), cx, cy, MM_ADJACENTOK);
5896 else if (randmnst < 102)
5897 (void) makemon(mkclass(S_GIANT,0), cx, cy, MM_ADJACENTOK);
5898 else if (randmnst < 103)
5899 (void) makemon(mkclass(S_JABBERWOCK,0), cx, cy, MM_ADJACENTOK);
5900 else if (randmnst < 104)
5901 (void) makemon(mkclass(S_KOP,0), cx, cy, MM_ADJACENTOK);
5902 else if (randmnst < 105)
5903 (void) makemon(mkclass(S_LICH,0), cx, cy, MM_ADJACENTOK);
5904 else if (randmnst < 108)
5905 (void) makemon(mkclass(S_MUMMY,0), cx, cy, MM_ADJACENTOK);
5906 else if (randmnst < 110)
5907 (void) makemon(mkclass(S_NAGA,0), cx, cy, MM_ADJACENTOK);
5908 else if (randmnst < 113)
5909 (void) makemon(mkclass(S_OGRE,0), cx, cy, MM_ADJACENTOK);
5910 else if (randmnst < 115)
5911 (void) makemon(mkclass(S_PUDDING,0), cx, cy, MM_ADJACENTOK);
5912 else if (randmnst < 116)
5913 (void) makemon(mkclass(S_QUANTMECH,0), cx, cy, MM_ADJACENTOK);
5914 else if (randmnst < 118)
5915 (void) makemon(mkclass(S_RUSTMONST,0), cx, cy, MM_ADJACENTOK);
5916 else if (randmnst < 121)
5917 (void) makemon(mkclass(S_SNAKE,0), cx, cy, MM_ADJACENTOK);
5918 else if (randmnst < 123)
5919 (void) makemon(mkclass(S_TROLL,0), cx, cy, MM_ADJACENTOK);
5920 else if (randmnst < 124)
5921 (void) makemon(mkclass(S_UMBER,0), cx, cy, MM_ADJACENTOK);
5922 else if (randmnst < 125)
5923 (void) makemon(mkclass(S_VAMPIRE,0), cx, cy, MM_ADJACENTOK);
5924 else if (randmnst < 127)
5925 (void) makemon(mkclass(S_WRAITH,0), cx, cy, MM_ADJACENTOK);
5926 else if (randmnst < 128)
5927 (void) makemon(mkclass(S_XORN,0), cx, cy, MM_ADJACENTOK);
5928 else if (randmnst < 130)
5929 (void) makemon(mkclass(S_YETI,0), cx, cy, MM_ADJACENTOK);
5930 else if (randmnst < 135)
5931 (void) makemon(mkclass(S_ZOMBIE,0), cx, cy, MM_ADJACENTOK);
5932 else if (randmnst < 145)
5933 (void) makemon(mkclass(S_HUMAN,0), cx, cy, MM_ADJACENTOK);
5934 else if (randmnst < 147)
5935 (void) makemon(mkclass(S_GHOST,0), cx, cy, MM_ADJACENTOK);
5936 else if (randmnst < 149)
5937 (void) makemon(mkclass(S_GOLEM,0), cx, cy, MM_ADJACENTOK);
5938 else if (randmnst < 152)
5939 (void) makemon(mkclass(S_DEMON,0), cx, cy, MM_ADJACENTOK);
5940 else if (randmnst < 155)
5941 (void) makemon(mkclass(S_EEL,0), cx, cy, MM_ADJACENTOK);
5942 else if (randmnst < 160)
5943 (void) makemon(mkclass(S_LIZARD,0), cx, cy, MM_ADJACENTOK);
5944 else if (randmnst < 162)
5945 (void) makemon(mkclass(S_BAD_FOOD,0), cx, cy, MM_ADJACENTOK);
5946 else if (randmnst < 165)
5947 (void) makemon(mkclass(S_BAD_COINS,0), cx, cy, MM_ADJACENTOK);
5948 else if (randmnst < 166) {
5949 if (randmnsx < 96)
5950 (void) makemon(mkclass(S_HUMAN,0), cx, cy, MM_ADJACENTOK);
5951 else
5952 (void) makemon(mkclass(S_NEMESE,0), cx, cy, MM_ADJACENTOK);
5954 else if (randmnst < 171)
5955 (void) makemon(mkclass(S_GRUE,0), cx, cy, MM_ADJACENTOK);
5956 else if (randmnst < 176)
5957 (void) makemon(mkclass(S_WALLMONST,0), cx, cy, MM_ADJACENTOK);
5958 else if (randmnst < 180)
5959 (void) makemon(mkclass(S_RUBMONST,0), cx, cy, MM_ADJACENTOK);
5960 else if (randmnst < 181) {
5961 if (randmnsx < 99)
5962 (void) makemon(mkclass(S_HUMAN,0), cx, cy, MM_ADJACENTOK);
5963 else
5964 (void) makemon(mkclass(S_ARCHFIEND,0), cx, cy, MM_ADJACENTOK);
5966 else if (randmnst < 186)
5967 (void) makemon(mkclass(S_TURRET,0), cx, cy, MM_ADJACENTOK);
5968 else if (randmnst < 187)
5969 (void) makemon(mkclass(S_FLYFISH,0), cx, cy, MM_ADJACENTOK);
5970 else
5971 (void) makemon((struct permonst *)0, cx, cy, MM_ADJACENTOK);
5977 else if (!rn2(3)) {
5979 randsp = (rn2(14) + 2);
5980 if (!rn2(10)) randsp *= 2;
5981 if (!rn2(100)) randsp *= 3;
5982 if (!rn2(1000)) randsp *= 5;
5983 if (!rn2(10000)) randsp *= 10;
5984 randmonstforspawn = rndmonst();
5986 You_feel("the arrival of monsters!");
5988 for (i = 0; i < randsp; i++) {
5990 if (!enexto(&cc, u.ux, u.uy, (struct permonst *)0) ) continue;
5992 (void) makemon(randmonstforspawn, cx, cy, MM_ADJACENTOK);
5997 else if (!rn2(2)) {
5999 randsp = (rn2(14) + 2);
6000 if (!rn2(10)) randsp *= 2;
6001 if (!rn2(100)) randsp *= 3;
6002 if (!rn2(1000)) randsp *= 5;
6003 if (!rn2(10000)) randsp *= 10;
6004 monstercolor = rnd(15);
6006 You_feel("a colorful sensation!");
6008 for (i = 0; i < randsp; i++) {
6010 if (!enexto(&cc, u.ux, u.uy, (struct permonst *)0) ) continue;
6012 (void) makemon(colormon(monstercolor), cx, cy, MM_ADJACENTOK);
6017 else {
6019 randsp = (rn2(14) + 2);
6020 if (!rn2(10)) randsp *= 2;
6021 if (!rn2(100)) randsp *= 3;
6022 if (!rn2(1000)) randsp *= 5;
6023 if (!rn2(10000)) randsp *= 10;
6024 monstercolor = rnd(434);
6026 You_feel("that a group has arrived!");
6028 for (i = 0; i < randsp; i++) {
6030 if (!enexto(&cc, u.ux, u.uy, (struct permonst *)0) ) continue;
6032 (void) makemon(specialtensmon(monstercolor), cx, cy, MM_ADJACENTOK);
6037 u.aggravation = 0;
6040 break;
6041 case 14:
6043 if (u.uhunger < 1500) {
6044 pline("Your %s fills.", body_part(STOMACH));
6045 u.uhunger = 1500;
6046 u.uhs = 1; /* NOT_HUNGRY */
6047 flags.botl = 1;
6048 } else {
6049 pline("Nothing happens...");
6050 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
6051 pline("Oh wait, actually something bad happens...");
6052 badeffect();
6055 break;
6056 case 15:
6057 if (u.ualign.record < -1) {
6058 adjalign(-(u.ualign.record / 2));
6059 You_feel("partially absolved.");
6060 } else {
6061 u.alignlim++;
6062 adjalign(10);
6063 You_feel("appropriately %s.", align_str(u.ualign.type));
6065 break;
6066 case 16:
6069 int nastytrapdur = (Role_if(PM_GRADUATE) ? 6 : Role_if(PM_GEEK) ? 12 : 24);
6070 if (!nastytrapdur) nastytrapdur = 24; /* fail safe */
6071 int blackngdur = (Role_if(PM_GRADUATE) ? 2000 : Role_if(PM_GEEK) ? 1000 : 500);
6072 if (!blackngdur ) blackngdur = 500; /* fail safe */
6074 pline("Your mana increases.");
6075 u.uenmax++;
6076 /* nasty trap effect - no extra message because, well, nastiness! --Amy */
6077 randomnastytrapeffect(rnz(nastytrapdur * (monster_difficulty() + 1)), (blackngdur - (monster_difficulty() * 3)));
6080 break;
6081 case 17:
6083 int i = rn2(A_MAX);
6084 adjattrib(i, 1, 0, TRUE);
6085 adjattrib(i, 1, 0, TRUE);
6086 adjattrib(i, 1, 0, TRUE);
6087 adjattrib(i, 1, 0, TRUE);
6088 adjattrib(i, 1, 0, TRUE);
6090 break;
6091 case 18:
6092 Your("intrinsics change.");
6093 intrinsicgainorloss(0);
6094 break;
6095 case 19:
6097 struct obj *pseudogram;
6098 pseudogram = mksobj(SCR_ITEM_GENOCIDE, FALSE, 2, FALSE);
6099 if (!pseudogram) {
6100 pline("Nothing happens...");
6101 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
6102 pline("Oh wait, actually something bad happens...");
6103 badeffect();
6105 break;
6107 if (pseudogram->otyp == GOLD_PIECE) pseudogram->otyp = SCR_ITEM_GENOCIDE;
6108 (void) seffects(pseudogram);
6109 obfree(pseudogram, (struct obj *)0); /* now, get rid of it */
6113 break;
6114 case 20:
6115 doubleskilltraining();
6116 break;
6117 case 21:
6118 if (!(HAggravate_monster & INTRINSIC) && !(HAggravate_monster & TIMEOUT)) {
6120 int maxtrainingamount = 0;
6121 int skillnumber = 0;
6122 int actualskillselection = 0;
6123 int amountofpossibleskills = 1;
6124 int i;
6126 for (i = 0; i < P_NUM_SKILLS; i++) {
6127 if (P_SKILL(i) != P_ISRESTRICTED) continue;
6129 if (P_ADVANCE(i) > 0 && P_ADVANCE(i) >= maxtrainingamount) {
6130 if (P_ADVANCE(i) > maxtrainingamount) {
6131 amountofpossibleskills = 1;
6132 skillnumber = i;
6133 maxtrainingamount = P_ADVANCE(i);
6134 } else if (!rn2(amountofpossibleskills + 1)) {
6135 amountofpossibleskills++;
6136 skillnumber = i;
6137 } else {
6138 amountofpossibleskills++;
6143 if (skillnumber > 0 && maxtrainingamount > 0) {
6144 unrestrict_weapon_skill(skillnumber);
6146 register int maxcap = P_BASIC;
6147 if (!rn2(2)) {
6148 maxcap = P_SKILLED;
6149 if (!rn2(2)) {
6150 maxcap = P_EXPERT;
6151 if (maxtrainingamount >= 20 && !rn2(2)) {
6152 maxcap = P_MASTER;
6153 if (maxtrainingamount >= 160 && !rn2(2)) {
6154 maxcap = P_GRAND_MASTER;
6155 if (maxtrainingamount >= 540 && !rn2(2)) {
6156 maxcap = P_SUPREME_MASTER;
6163 P_MAX_SKILL(skillnumber) = maxcap;
6164 pline("You can now learn the %s skill, with a new cap of %s.", wpskillname(skillnumber), maxcap == P_SUPREME_MASTER ? "supreme master" : maxcap == P_GRAND_MASTER ? "grand master" : maxcap == P_MASTER ? "master" : maxcap == P_EXPERT ? "expert" : maxcap == P_SKILLED ? "skilled" : "basic");
6165 } else {
6166 pline("Nothing happens...");
6167 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
6168 pline("Oh wait, actually something bad happens...");
6169 badeffect();
6175 if (HAggravate_monster & INTRINSIC) {
6176 HAggravate_monster &= ~INTRINSIC;
6177 You_feel("more acceptable!");
6179 if (HAggravate_monster & TIMEOUT) {
6180 HAggravate_monster &= ~TIMEOUT;
6181 You_feel("more acceptable!");
6183 break;
6184 case 22:
6186 u.aggravation = 1;
6187 reset_rndmonst(NON_PM);
6188 int attempts = 0;
6189 register struct permonst *ptrZ;
6190 newbossPENT:
6191 do {
6193 ptrZ = rndmonst();
6194 attempts++;
6195 if (attempts && (attempts % 10000 == 0)) u.mondiffhack++;
6196 if (!rn2(2000)) reset_rndmonst(NON_PM);
6198 } while ( (!ptrZ || (ptrZ && !(ptrZ->geno & G_UNIQ))) && attempts < 50000);
6200 if (ptrZ && ptrZ->geno & G_UNIQ) {
6201 if (wizard) pline("monster generation: %s", ptrZ->mname);
6202 (void) makemon(ptrZ, u.ux, u.uy, MM_ANGRY);
6204 else if (rn2(50)) {
6205 attempts = 0;
6206 goto newbossPENT;
6209 u.mondiffhack = 0;
6211 if (!rn2(10) ) {
6212 attempts = 0;
6213 goto newbossPENT;
6215 pline("Boss monsters appear from nowhere!");
6218 u.aggravation = 0;
6220 break;
6221 case 23:
6222 if (!rn2(6400)) {
6223 ragnarok(TRUE);
6224 if (evilfriday) evilragnarok(TRUE,level_difficulty());
6228 u.aggravation = 1;
6229 u.heavyaggravation = 1;
6230 DifficultyIncreased += 1;
6231 HighlevelStatus += 1;
6232 EntireLevelMode += 1;
6234 (void) makemon(mkclass(S_NEMESE,0), u.ux, u.uy, MM_ANGRY|MM_FRENZIED);
6236 u.aggravation = 0;
6237 u.heavyaggravation = 0;
6239 break;
6240 case 24:
6241 wonderspell(-1);
6242 break;
6243 case 25:
6246 int tryct = 0;
6247 int x, y;
6248 boolean canbeinawall = FALSE;
6249 if (!rn2(Passes_walls ? 5 : 25)) canbeinawall = TRUE;
6250 register struct trap *ttmp;
6251 for (tryct = 0; tryct < 2000; tryct++) {
6252 x = rn1(COLNO-3,2);
6253 y = rn2(ROWNO);
6255 if (isok(x, y) && ((levl[x][y].typ > DBWALL) || canbeinawall) && !(t_at(x, y)) ) {
6256 ttmp = maketrap(x, y, rndtrap(), 0, TRUE);
6257 if (ttmp) {
6258 ttmp->tseen = 0;
6259 ttmp->hiddentrap = 1;
6261 if (!rn2(5)) break;
6265 You_feel("in grave danger...");
6267 break;
6268 case 26:
6269 badeffect();
6270 break;
6271 case 27:
6272 if (!uinsymbiosis) {
6273 getrandomsymbiote(FALSE, FALSE);
6274 pline("Suddenly you have a symbiote!");
6275 } else {
6276 u.usymbiote.mhpmax += rnd(10);
6277 maybe_evolve_symbiote();
6278 if (u.usymbiote.mhpmax > 500) u.usymbiote.mhpmax = 500;
6279 flags.botl = TRUE;
6280 Your("symbiote seems much stronger now.");
6282 break;
6283 case 28:
6284 decontaminate(100);
6285 You_feel("decontaminated.");
6286 break;
6287 case 29:
6288 pline("Wow! This makes you feel good!");
6290 int i, ii, lim;
6291 i = rn2(A_MAX);
6292 for (ii = 0; ii < A_MAX; ii++) {
6293 lim = AMAX(i);
6294 if (i == A_STR && u.uhs >= 3) --lim; /* WEAK */
6295 if (ABASE(i) < lim) {
6296 ABASE(i) = lim;
6297 flags.botl = 1;
6298 break;
6300 if(++i >= A_MAX) i = 0;
6304 break;
6305 case 30:
6306 boostknownskillcap();
6307 break;
6308 default:
6309 impossible("undefined pentagram effect");
6310 break;
6315 if (!rn2(7)) badeffect();
6317 break;
6319 case SPE_THRONE_GAMBLE:
6321 if (rnd(6) > 4) {
6322 switch (rnd(32)) {
6323 case 1:
6324 (void) adjattrib(rn2(A_MAX), -rno(5), FALSE, TRUE);
6325 losehp(rnd(10), "cursed throne", KILLED_BY_AN);
6326 break;
6327 case 2:
6328 (void) adjattrib(rn2(A_MAX), 1, FALSE, TRUE);
6329 break;
6330 case 3:
6331 pline("A%s electric shock shoots through your body!",
6332 (Shock_resistance) ? "n" : " massive");
6333 if (!ShockImmunity) losehp(StrongShock_resistance ? rnd(2) : Shock_resistance ? rnd(6) : rnd(30),
6334 "electric chair", KILLED_BY_AN);
6335 exercise(A_CON, FALSE);
6336 break;
6337 case 4:
6338 You_feel("much, much better!");
6339 if (Upolyd) {
6340 if (u.mh >= (u.mhmax - 5)) u.mhmax += 4;
6341 u.mh = u.mhmax;
6343 if(u.uhp >= (u.uhpmax - 5)) u.uhpmax += 4;
6344 u.uhp = u.uhpmax;
6345 if (uinsymbiosis) {
6346 u.usymbiote.mhpmax += 4;
6347 maybe_evolve_symbiote();
6348 if (u.usymbiote.mhpmax > 500) u.usymbiote.mhpmax = 500;
6350 make_blinded(0L,TRUE);
6351 make_sick(0L, (char *) 0, FALSE, SICK_ALL);
6352 heal_legs();
6353 flags.botl = 1;
6354 break;
6355 case 5:
6356 take_gold();
6357 break;
6358 case 6:
6360 /* no wishes --Amy */
6361 You_feel("your luck is changing.");
6362 change_luck(5);
6364 break;
6365 case 7:
6367 register int cnt = rnd(10);
6369 if (Aggravate_monster) {
6370 u.aggravation = 1;
6371 reset_rndmonst(NON_PM);
6374 pline("A voice echoes:");
6375 verbalize("Thy audience hath been summoned, %s!",
6376 flags.female ? "Dame" : "Sire");
6377 while(cnt--)
6378 (void) makemon(courtmon(), u.ux, u.uy, NO_MM_FLAGS);
6380 u.aggravation = 0;
6382 break;
6384 case 8:
6385 pline("A voice echoes:");
6386 verbalize("By thy Imperious order, %s...",
6387 flags.female ? "Dame" : "Sire");
6388 do_genocide(5); /* REALLY|ONTHRONE, see do_genocide() */
6389 break;
6390 case 9:
6391 pline("A voice echoes:");
6392 verbalize("A curse upon thee for sitting upon this most holy throne!");
6393 if (Luck > 0) {
6394 make_blinded(Blinded + rn1(100,250),TRUE);
6395 } else rndcurse();
6396 break;
6397 case 10:
6398 if (Luck < 0 || (HSee_invisible & INTRINSIC)) {
6399 if (level.flags.nommap) {
6400 pline(
6401 "A terrible drone fills your head!");
6402 make_confused(HConfusion + rnd(30),
6403 FALSE);
6404 } else {
6405 pline("An image forms in your mind.");
6406 do_mapping();
6408 } else {
6409 Your("vision becomes clear.");
6410 HSee_invisible |= FROMOUTSIDE;
6411 newsym(u.ux, u.uy);
6413 break;
6414 case 11:
6415 if (Luck < 0) {
6416 You_feel("threatened.");
6417 aggravate();
6418 } else {
6420 You_feel("a wrenching sensation.");
6421 if (PlayerHearsSoundEffects) pline(issoviet ? "Tam net nikakoy zashchity. Tam net nikakoy nadezhdy. Yedinstvennoye, chto yest'? Uverennost' v tom, chto vy, igrok, budet umeret' uzhasnoy i muchitel'noy smert'yu." : "SCHRING!");
6422 tele(); /* teleport him */
6424 break;
6425 case 12:
6426 You("are granted an insight!");
6427 if (invent) {
6428 /* rn2(5) agrees w/seffects() */
6429 identify_pack(rn2(5), 0, 0);
6431 break;
6432 case 13:
6433 Your("mind turns into a pretzel!");
6434 make_confused(HConfusion + rn1(7,16),FALSE);
6435 break;
6436 case 14:
6437 You("are granted some new skills!"); /* new effect that unrestricts skills --Amy */
6438 unrestrictskillchoice();
6440 break;
6441 case 15:
6442 pline("A voice echoes:");
6443 verbalize("Thou be cursed!");
6444 attrcurse();
6445 break;
6446 case 16:
6447 pline("A voice echoes:");
6448 verbalize("Thou shall be punished!");
6449 punishx();
6450 break;
6451 case 17:
6452 You_feel("like someone has touched your forehead...");
6454 int skillimprove = randomgoodskill();
6456 if (P_MAX_SKILL(skillimprove) == P_ISRESTRICTED) {
6457 unrestrict_weapon_skill(skillimprove);
6458 pline("You can now learn the %s skill.", wpskillname(skillimprove));
6459 } else if (P_MAX_SKILL(skillimprove) == P_UNSKILLED) {
6460 unrestrict_weapon_skill(skillimprove);
6461 P_MAX_SKILL(skillimprove) = P_BASIC;
6462 pline("You can now learn the %s skill.", wpskillname(skillimprove));
6463 } else if (rn2(2) && P_MAX_SKILL(skillimprove) == P_BASIC) {
6464 P_MAX_SKILL(skillimprove) = P_SKILLED;
6465 pline("Your knowledge of the %s skill increases.", wpskillname(skillimprove));
6466 } else if (!rn2(4) && P_MAX_SKILL(skillimprove) == P_SKILLED) {
6467 P_MAX_SKILL(skillimprove) = P_EXPERT;
6468 pline("Your knowledge of the %s skill increases.", wpskillname(skillimprove));
6469 } else if (!rn2(10) && P_MAX_SKILL(skillimprove) == P_EXPERT) {
6470 P_MAX_SKILL(skillimprove) = P_MASTER;
6471 pline("Your knowledge of the %s skill increases.", wpskillname(skillimprove));
6472 } else if (!rn2(100) && P_MAX_SKILL(skillimprove) == P_MASTER) {
6473 P_MAX_SKILL(skillimprove) = P_GRAND_MASTER;
6474 pline("Your knowledge of the %s skill increases.", wpskillname(skillimprove));
6475 } else if (!rn2(200) && P_MAX_SKILL(skillimprove) == P_GRAND_MASTER) {
6476 P_MAX_SKILL(skillimprove) = P_SUPREME_MASTER;
6477 pline("Your knowledge of the %s skill increases.", wpskillname(skillimprove));
6478 } else gainlevelmaybe();
6480 if (Race_if(PM_RUSMOT)) {
6481 if (P_MAX_SKILL(skillimprove) == P_ISRESTRICTED) {
6482 unrestrict_weapon_skill(skillimprove);
6483 pline("You can now learn the %s skill.", wpskillname(skillimprove));
6484 } else if (P_MAX_SKILL(skillimprove) == P_UNSKILLED) {
6485 unrestrict_weapon_skill(skillimprove);
6486 P_MAX_SKILL(skillimprove) = P_BASIC;
6487 pline("You can now learn the %s skill.", wpskillname(skillimprove));
6488 } else if (rn2(2) && P_MAX_SKILL(skillimprove) == P_BASIC) {
6489 P_MAX_SKILL(skillimprove) = P_SKILLED;
6490 pline("Your knowledge of the %s skill increases.", wpskillname(skillimprove));
6491 } else if (!rn2(4) && P_MAX_SKILL(skillimprove) == P_SKILLED) {
6492 P_MAX_SKILL(skillimprove) = P_EXPERT;
6493 pline("Your knowledge of the %s skill increases.", wpskillname(skillimprove));
6494 } else if (!rn2(10) && P_MAX_SKILL(skillimprove) == P_EXPERT) {
6495 P_MAX_SKILL(skillimprove) = P_MASTER;
6496 pline("Your knowledge of the %s skill increases.", wpskillname(skillimprove));
6497 } else if (!rn2(100) && P_MAX_SKILL(skillimprove) == P_MASTER) {
6498 P_MAX_SKILL(skillimprove) = P_GRAND_MASTER;
6499 pline("Your knowledge of the %s skill increases.", wpskillname(skillimprove));
6500 } else if (!rn2(200) && P_MAX_SKILL(skillimprove) == P_GRAND_MASTER) {
6501 P_MAX_SKILL(skillimprove) = P_SUPREME_MASTER;
6502 pline("Your knowledge of the %s skill increases.", wpskillname(skillimprove));
6506 gainlevelmaybe();
6508 break;
6509 case 18:
6510 {register int cnt = rnd(10);
6511 struct permonst *randmonstforspawn = rndmonst();
6513 if (Aggravate_monster) {
6514 u.aggravation = 1;
6515 reset_rndmonst(NON_PM);
6518 while(cnt--)
6519 (void) makemon(randmonstforspawn, u.ux, u.uy, NO_MM_FLAGS);
6521 u.aggravation = 0;
6523 pline("A voice echoes:");
6524 verbalize("Leave me alone, stupid %s", randmonstforspawn->mname);
6525 break;
6527 case 19:
6528 {register int cnt = rnd(10);
6529 int randmonstforspawn = rnd(68);
6530 if (randmonstforspawn == 35) randmonstforspawn = 53;
6532 if (Aggravate_monster) {
6533 u.aggravation = 1;
6534 reset_rndmonst(NON_PM);
6537 while(cnt--)
6538 (void) makemon(mkclass(randmonstforspawn,0), u.ux, u.uy, NO_MM_FLAGS);
6540 u.aggravation = 0;
6542 pline("A voice echoes:");
6543 verbalize("Oh, please help me! A horrible %s stole my sword! I'm nothing without it.", monexplain[randmonstforspawn]);
6544 break;
6546 case 20:
6548 if (CannotSelectItemsInPrompts) break;
6549 pline("You may fully identify an object!");
6550 register struct obj *idobj;
6552 secureidchoice:
6553 idobj = getobj(allnoncount, "secure identify");
6555 if (!idobj) {
6556 if (yn("Really exit with no object selected?") == 'y')
6557 pline("You just wasted the opportunity to secure identify your objects.");
6558 else goto secureidchoice;
6559 pline("A feeling of loss comes over you.");
6560 break;
6562 if (idobj) {
6563 makeknown(idobj->otyp);
6564 if (idobj->oartifact) discover_artifact((int)idobj->oartifact);
6565 idobj->known = idobj->dknown = idobj->bknown = idobj->rknown = 1;
6566 if (idobj->otyp == EGG && idobj->corpsenm != NON_PM)
6567 learn_egg_type(idobj->corpsenm);
6568 prinv((char *)0, idobj, 0L);
6571 break;
6572 case 21:
6574 int nastytrapdur = (Role_if(PM_GRADUATE) ? 6 : Role_if(PM_GEEK) ? 12 : 24);
6575 if (!nastytrapdur) nastytrapdur = 24; /* fail safe */
6576 int blackngdur = (Role_if(PM_GRADUATE) ? 2000 : Role_if(PM_GEEK) ? 1000 : 500);
6577 if (!blackngdur ) blackngdur = 500; /* fail safe */
6578 randomnastytrapeffect(rnz(nastytrapdur * (monster_difficulty() + 1)), (blackngdur - (monster_difficulty() * 3)));
6579 You_feel("uncomfortable.");
6581 break;
6582 case 22:
6583 morehungry(500);
6584 pline("Whoops... suddenly you feel hungry.");
6585 break;
6586 case 23:
6587 pline("Suddenly you feel a healing touch!");
6588 reducesanity(100);
6589 break;
6590 case 24:
6591 poisoned("throne", rn2(6) /* A_STR ... A_CHA*/, "poisoned throne", 30);
6592 break;
6593 case 25:
6595 int thronegold = rnd(200);
6596 u.ugold += thronegold;
6597 pline("Some coins come loose! You pick up %d zorkmids.", thronegold);
6599 break;
6600 case 26:
6603 if (Aggravate_monster) {
6604 u.aggravation = 1;
6605 reset_rndmonst(NON_PM);
6608 pline("A voice echoes:");
6609 verbalize("Thou hath been summoned to appear before royalty, %s!", playeraliasname);
6610 (void) makemon(specialtensmon(rn2(2) ? 105 : 106), u.ux, u.uy, MM_ANGRY); /* M2_LORD, M2_PRINCE */
6612 u.aggravation = 0;
6615 break;
6616 case 27:
6617 badeffect();
6618 break;
6619 case 28:
6620 u.uhp++;
6621 u.uhpmax++;
6622 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
6623 You_feel("a health boost!");
6624 break;
6625 case 29:
6626 pline("A pretty ethereal woman appears and offers: 'For only 10000 zorkmids, I will give you a very rare trinket!");
6627 if (u.ugold < 10000) {
6628 pline("But you don't have enough money! Frustrated, she places a terrible curse on you and disappears.");
6629 randomfeminismtrap(rnz( (level_difficulty() + 2) * rnd(50)));
6631 else {
6632 char femhandlebuf[BUFSZ];
6633 getlin ("Do you want to buy her goods? [y/yes/no]",femhandlebuf);
6634 (void) lcase (femhandlebuf);
6635 if (!(strcmp (femhandlebuf, "yes")) || !(strcmp (femhandlebuf, "y")) || !(strcmp (femhandlebuf, "ye")) || !(strcmp (femhandlebuf, "ys"))) {
6636 u.ugold -= 10000;
6637 register struct obj *acqo;
6638 acqo = mksobj(makegreatitem(), TRUE, TRUE, FALSE);
6639 if (acqo) {
6640 dropy(acqo);
6641 verbalize("Thanks a lot! You'll find your prize on the ground.");
6642 } else {
6643 verbalize("Oh sorry, I must have misplaced it. Here you have your money back. Maybe next time I'll have something for you.");
6644 u.ugold += 10000;
6646 } else {
6647 verbalize("You will regret that decision!");
6648 randomfeminismtrap(rnz( (level_difficulty() + 2) * rnd(50)));
6652 break;
6653 case 30:
6654 pline("A shady merchant appears and offers: 'Sale! Sale! I'm selling you this useful item for 2000 zorkmids!");
6655 if (u.ugold < 2000) {
6656 pline("But you don't have enough money! The merchant disappears.");
6658 else {
6659 char femhandlebuf[BUFSZ];
6660 getlin ("Do you want to buy his item? [y/yes/no]",femhandlebuf);
6661 (void) lcase (femhandlebuf);
6662 if (!(strcmp (femhandlebuf, "yes")) || !(strcmp (femhandlebuf, "y")) || !(strcmp (femhandlebuf, "ye")) || !(strcmp (femhandlebuf, "ys"))) {
6663 u.ugold -= 2000;
6664 register struct obj *acqo;
6665 acqo = mksobj(usefulitem(), TRUE, TRUE, FALSE);
6666 if (acqo) {
6667 dropy(acqo);
6668 verbalize("Thank you! I've dropped the item at your feet.");
6669 } else {
6670 verbalize("Nyah-nyah, thanks for the money, sucker!");
6672 } else {
6673 verbalize("Are you sure? Well, it's your decision. I'll find someone else to sell it to, then.");
6676 break;
6677 case 31:
6679 struct obj *stupidstone;
6680 stupidstone = mksobj_at(rnd_class(RIGHT_MOUSE_BUTTON_STONE,NASTY_STONE), u.ux, u.uy, TRUE, FALSE, FALSE);
6681 if (stupidstone) {
6682 stupidstone->quan = 1L;
6683 stupidstone->owt = weight(stupidstone);
6684 if (!Blind) stupidstone->dknown = 1;
6685 if (stupidstone) {
6686 pline("%s lands in your knapsack!", Doname2(stupidstone));
6687 (void) pickup_object(stupidstone, 1L, TRUE, TRUE);
6691 break;
6692 case 32:
6693 (void) mksobj_at(rnd_class(DILITHIUM_CRYSTAL, ROCK), u.ux, u.uy, TRUE, TRUE, FALSE);
6694 pline("Some stones come loose!");
6695 break;
6697 default: impossible("throne effect");
6698 break;
6700 } else {
6701 if (is_prince(youmonst.data))
6702 You_feel("very comfortable here.");
6703 else
6704 You_feel("somehow out of place...");
6707 if (!rn2(7)) badeffect();
6709 break;
6711 case SPE_COMBAT_COMMAND:
6713 verbalize(!rn2(3) ? "Bohhh!" : rn2(2) ? "Wouuh!" : "Bohhohh!");
6714 if (u.combatcommand) u.combatcommand += rnd(10);
6715 else u.combatcommand = (rn1(50, 50) + spell_damage_bonus(spellid(spell)) * 5 );
6717 break;
6719 case SPE_DEFUSING:
6721 if(!(HDefusing & INTRINSIC)) {
6722 You("can disarm traps more effectively!");
6723 incr_itimeout(&HDefusing, HDefusing ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
6724 } else {
6725 pline("%s", nothing_happens); /* Already have as intrinsic */
6726 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
6727 pline("Oh wait, actually something bad happens...");
6728 badeffect();
6732 break;
6734 case SPE_REDEMPTION:
6737 register struct obj *redeemobj;
6738 for (redeemobj = fobj; redeemobj; redeemobj = redeemobj->nobj) {
6739 if (redeemobj->otyp == CORPSE) {
6740 if (redeemobj->timed) {
6741 (void) stop_timer(MOLDY_CORPSE, (void *)redeemobj);
6742 (void) stop_timer(REVIVE_MON, (void *)redeemobj);
6744 if (!(redeemobj->timed)) {
6745 (void) start_timer(250, TIMER_OBJECT, ROT_CORPSE, (void *)redeemobj);
6746 pline("A corpse has been redeemed!");
6753 break;
6755 case SPE_MAGIC_SHIELD:
6757 u.magicshield += (u.magicshield ? rnd(10) : 40 + (spell_damage_bonus(spellid(spell)) * 10) );
6758 pline("You activate your magic shield!");
6760 break;
6762 case SPE_BERSERK:
6764 if (u.berserktime) {
6765 pline("Bad idea - you are already berserk! Things turn into an unrecognizable blur.");
6766 make_hallucinated(HHallucination + rnd(50) + HStun + HConfusion, FALSE, 0L);
6767 set_itimeout(&HeavyHallu, HHallucination);
6768 break;
6771 u.berserktime = 7 + spell_damage_bonus(spellid(spell));
6772 pline("Raaaaaargh! You fly into a berserk rage!");
6774 break;
6776 case SPE_RAIN_CLOUD:
6778 int i, j;
6779 struct monst *rainedmon;
6780 for (i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
6781 if (!isok(u.ux + i, u.uy + j)) continue;
6782 if (levl[u.ux + i][u.uy + j].typ == LAVAPOOL) {
6783 levl[u.ux + i][u.uy + j].typ = WATER;
6784 pline("The lava turns into water!");
6786 if ( (rainedmon = m_at(u.ux + i, u.uy + j)) != 0) {
6787 if (dmgtype(rainedmon->data, AD_FIRE) || dmgtype(rainedmon->data, AD_BURN) || dmgtype(rainedmon->data, AD_LAVA)) {
6789 rainedmon->mhp -= rnd(20 + (spell_damage_bonus(spellid(spell)) * 3) );
6790 pline("%s is damaged by the raindrops!", Monnam(rainedmon));
6791 if (rainedmon->mhp <= 0) {
6792 pline("%s is killed!", Monnam(rainedmon));
6793 xkilled(rainedmon, 0);
6801 if (!inertiaprotection()) {
6802 u.uprops[DEAC_FAST].intrinsic += (( rnd(10) + rnd(monster_difficulty() + 1) ) * 3);
6803 pline(u.inertia ? "You slow down even more due to the rain." : "You slow down greatly due to the rain.");
6804 u.inertia += (rnd(10) + rnd(monster_difficulty() + 1));
6807 if (!(InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone())) (void)doredraw();
6809 break;
6811 case SPE_DRY_UP_FOUNTAIN:
6813 int i, j;
6814 for (i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
6815 if (!isok(u.ux + i, u.uy + j)) continue;
6816 if (levl[u.ux + i][u.uy + j].typ == FOUNTAIN) {
6817 levl[u.ux + i][u.uy + j].typ = CORR;
6818 levl[u.ux + i][u.uy + j].looted = 0;
6819 levl[u.ux + i][u.uy + j].blessedftn = 0;
6820 pline("The fountain dries up!");
6821 level.flags.nfountains--;
6826 if (!(InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone())) (void)doredraw();
6828 break;
6830 case SPE_TAKE_SELFIE:
6832 pline("You take a selfie.");
6833 nomul(-(2 + rn2(4)), "taking a selfie", TRUE);
6835 if (!rn2(5)) {
6836 make_blinded(Blinded + rnd(50), FALSE);
6837 pline("You are blinded by the flash!");
6840 break;
6842 case SPE_VAPORIZE:
6844 int i, j;
6845 struct monst *rainedmon;
6847 if (Is_waterlevel(&u.uz)) {
6848 pline("The water foams violently for a moment.");
6849 break;
6852 for (i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
6853 if (!isok(u.ux + i, u.uy + j)) continue;
6854 if (levl[u.ux + i][u.uy + j].typ == WATER || levl[u.ux + i][u.uy + j].typ == POOL || levl[u.ux + i][u.uy + j].typ == MOAT) {
6855 levl[u.ux + i][u.uy + j].typ = ROOM;
6856 pline("The water evaporizes!");
6857 if ( (rainedmon = m_at(u.ux + i, u.uy + j)) != 0) {
6858 rainedmon->mhp /= 2;
6859 if (rainedmon->mpeaceful && !(rainedmon->mtame)) {
6860 rainedmon->mpeaceful = 0;
6861 pline("%s gets angry.", Monnam(rainedmon));
6863 pline("%s is damaged by the vapors!", Monnam(rainedmon));
6864 if (!rn2(3)) {
6865 rainedmon->mcanmove = 0;
6866 rainedmon->mfrozen = rnd(20);
6867 rainedmon->mstrategy &= ~STRAT_WAITFORU;
6868 pline("%s is paralyzed!", Monnam(rainedmon));
6870 if (rainedmon->mhp <= 0) {
6871 pline("%s is killed!", Monnam(rainedmon));
6872 xkilled(rainedmon, 0);
6879 pline("The vapors burn you!");
6880 make_burned(HBurned + rnd(200), FALSE);
6881 set_itimeout(&HeavyBurned, HBurned);
6883 if (!(InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone())) (void)doredraw();
6885 break;
6887 case SPE_NEXUS_FIELD:
6889 register struct monst *nexusmon, *nextmon;
6891 for(nexusmon = fmon; nexusmon; nexusmon = nextmon) {
6892 nextmon = nexusmon->nmon; /* trap might kill mon */
6893 if (DEADMONSTER(nexusmon)) continue;
6894 if (nexusmon == u.usteed) continue;
6895 if (resist(nexusmon, SPBOOK_CLASS, 0, NOTELL)) continue;
6897 if (!monnear(nexusmon, u.ux, u.uy)) continue;
6898 if (nexusmon->mtrapped) {
6899 /* no longer in previous trap (affects mintrap) */
6900 nexusmon->mtrapped = 0;
6901 fill_pit(nexusmon->mx, nexusmon->my);
6903 pline("%s is beamed away!", Monnam(nexusmon));
6904 wakeup(nexusmon); /* monster becomes hostile */
6905 rloc(nexusmon, FALSE);
6909 if (!rn2(10)) {
6910 register int statloss = rn2(A_MAX);
6912 ABASE(statloss) -= rnd(2);
6913 if (ABASE(statloss) < ATTRABSMIN(statloss)) ABASE(statloss) = ATTRABSMIN(statloss);
6914 AMAX(statloss) = ABASE(statloss);
6915 pline("You are hit by nexus forces!");
6916 poisontell(statloss);
6920 break;
6922 case SPE_TUNNELIZATION:
6924 register struct monst *nexusmon, *nextmon;
6926 for(nexusmon = fmon; nexusmon; nexusmon = nextmon) {
6927 nextmon = nexusmon->nmon; /* trap might kill mon */
6928 if (DEADMONSTER(nexusmon)) continue;
6929 if (levl[nexusmon->mx][nexusmon->my].typ >= STONE && levl[nexusmon->mx][nexusmon->my].typ <= ROCKWALL) {
6930 if ((levl[nexusmon->mx][nexusmon->my].wall_info & W_NONDIGGABLE) == 0 && !(*in_rooms(nexusmon->mx,nexusmon->my,SHOPBASE))) {
6931 levl[nexusmon->mx][nexusmon->my].typ = CORR;
6932 blockorunblock_point(nexusmon->mx,nexusmon->my);
6933 if (!(levl[nexusmon->mx][nexusmon->my].wall_info & W_HARDGROWTH)) levl[nexusmon->mx][nexusmon->my].wall_info |= W_EASYGROWTH;
6934 newsym(nexusmon->mx,nexusmon->my);
6937 pline("%s wails out in pain!", Monnam(nexusmon));
6938 nexusmon->mhp -= rnz(nexusmon->mhp / 2);
6939 if (nexusmon->mhp <= 0) {
6940 xkilled(nexusmon, 0);
6941 pline("%s is killed!", Monnam(nexusmon));
6942 } else wakeup(nexusmon); /* monster becomes hostile */
6943 adjalign(-10);
6948 pline("You feel bad for tunneling, and are also blinded by heaps of earth flying around.");
6949 adjalign(-2);
6950 if (rn2(5)) u.tunnelized += rnd(20);
6951 else u.tunnelized += rnd(100);
6952 make_blinded(Blinded + u.tunnelized, FALSE);
6953 set_itimeout(&HeavyBlind, Blinded);
6954 if (!(InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone())) (void)doredraw();
6956 break;
6958 case SPE_APPLY_NAIL_POLISH:
6960 if (u.nailpolish >= 10) {
6961 pline("All of your nails are polished already! Nothing happens.");
6962 break;
6964 pline("You begin applying nail polish.");
6965 u.nailpolish++;
6966 nomul(-(rnd(4)), "applying nail polish", TRUE);
6967 nomovemsg = "You finish polishing your nails.";
6969 break;
6971 case SPE_ENCHANT:
6973 if (!uwep) {
6974 pline("You are not holding a weapon!");
6975 break;
6978 /* enchanting again while it's already active sets a new timeout and does not add to the old one --Amy */
6979 u.enchantspell = (5 + spell_damage_bonus(spellid(spell)));
6980 pline("You enchant your weapon.");
6982 break;
6984 case SPE_FROST:
6986 register struct monst *frostmon, *nxtmon;
6988 for(frostmon = fmon; frostmon; frostmon = nxtmon) {
6989 nxtmon = frostmon->nmon; /* trap might kill mon */
6990 if (DEADMONSTER(frostmon)) continue;
6991 if (resist(frostmon, SPBOOK_CLASS, 0, NOTELL)) continue;
6993 if (!monnear(frostmon, u.ux, u.uy)) continue;
6994 mon_adjust_speed(frostmon, -1, (struct obj *)0);
6995 m_dowear(frostmon, FALSE); /* might want speed boots */
7000 break;
7002 case SPE_THUNDER_WAVE:
7004 register struct monst *frostmon, *nxtmon;
7006 for(frostmon = fmon; frostmon; frostmon = nxtmon) {
7007 nxtmon = frostmon->nmon; /* trap might kill mon */
7008 if (DEADMONSTER(frostmon)) continue;
7009 if (!monnear(frostmon, u.ux, u.uy)) continue;
7011 if (frostmon->mpeaceful && !frostmon->mtame) {
7012 pline("%s gets angry.", Monnam(frostmon) );
7013 frostmon->mpeaceful = 0; /* monster becomes hostile */
7016 if (!resists_elec(frostmon) && !(dmgtype(frostmon->data, AD_PLYS)) && !resist(frostmon, SPBOOK_CLASS, 0, NOTELL) && !rn2(10)) {
7018 if (canseemon(frostmon) ) {
7019 pline("%s is paralyzed! It might be unable to move!", Monnam(frostmon) );
7021 frostmon->mcanmove = 0;
7022 frostmon->mfrozen = rnd(5);
7023 frostmon->mstrategy &= ~STRAT_WAITFORU;
7027 if (!resists_elec(frostmon)) {
7029 frostmon->mhp -= rnd(10 + (spell_damage_bonus(spellid(spell)) * 2) );
7030 pline("%s is shocked!", Monnam(frostmon));
7031 if (frostmon->mhp <= 0) {
7032 pline("%s is killed!", Monnam(frostmon));
7033 xkilled(frostmon, 0);
7041 break;
7043 case SPE_POWER_FAILURE:
7046 int i, j, bd = 2;
7047 struct monst *mtmp;
7049 for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) {
7050 if (!isok(u.ux + i, u.uy + j)) continue;
7051 if ((mtmp = m_at(u.ux + i, u.uy + j)) != 0) {
7052 if (dmgtype(mtmp->data, AD_ELEC) || dmgtype(mtmp->data, AD_MALK)) {
7053 wakeup(mtmp);
7054 mtmp->mhp -= rnd(40 + (spell_damage_bonus(spellid(spell)) * 10) );
7055 pline("%s's power is down!", Monnam(mtmp));
7056 if (rn2(3) && !mtmp->mstun) {
7057 mtmp->mstun = TRUE;
7058 pline("%s is numbed!", Monnam(mtmp));
7060 if (rn2(3) && !mtmp->mblinded) {
7061 mtmp->mblinded = rnd(10);
7062 pline("%s is blinded!", Monnam(mtmp));
7064 if (mtmp->mhp <= 0) {
7065 pline("%s is killed!", Monnam(mtmp));
7066 xkilled(mtmp, 0);
7073 for (i = -2; i <= 2; i++) for(j = -2; j <= 2; j++) {
7074 if (!isok(u.ux + i, u.uy + j)) continue;
7075 if (levl[u.ux + i][u.uy + j].typ == IRONBARS && !rn2(1000) ) {
7076 levl[u.ux + i][u.uy + j].typ = CLOUD;
7077 pline("The iron bars break apart and leave behind a cloud!");
7083 u.powerfailure += rnd(100);
7084 if (!(InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone())) (void)doredraw();
7086 break;
7088 case SPE_ANGER_PEACEFUL_MONSTER:
7090 register struct monst *frostmon, *nxtmon;
7092 for(frostmon = fmon; frostmon; frostmon = nxtmon) {
7093 nxtmon = frostmon->nmon; /* trap might kill mon */
7094 if (DEADMONSTER(frostmon)) continue;
7095 if (!monnear(frostmon, u.ux, u.uy)) continue;
7097 wakeup(frostmon);
7101 break;
7103 case SPE_CURE_MONSTER:
7105 register struct monst *frostmon, *nxtmon;
7107 for(frostmon = fmon; frostmon; frostmon = nxtmon) {
7108 nxtmon = frostmon->nmon; /* trap might kill mon */
7109 if (DEADMONSTER(frostmon)) continue;
7110 if (!monnear(frostmon, u.ux, u.uy)) continue;
7111 if (rn2(2)) continue;
7112 frostmon->mfrozen = 0;
7113 frostmon->msleeping = 0;
7114 frostmon->masleep = 0;
7115 frostmon->mcanmove = 1;
7116 frostmon->mflee = 0;
7117 frostmon->mcansee = 1;
7118 frostmon->mblinded = 0;
7119 frostmon->mstun = 0;
7120 frostmon->mconf = 0;
7121 pline("%s is cured.", Monnam(frostmon));
7124 if (u.usteed && rn2(2)) {
7125 u.usteed->mfrozen = 0;
7126 u.usteed->msleeping = 0;
7127 u.usteed->masleep = 0;
7128 u.usteed->mcanmove = 1;
7129 u.usteed->mflee = 0;
7130 u.usteed->mcansee = 1;
7131 u.usteed->mblinded = 0;
7132 u.usteed->mstun = 0;
7133 u.usteed->mconf = 0;
7134 pline("%s is cured.", Monnam(u.usteed));
7139 break;
7141 case SPE_THORNS:
7143 pline("You throw up a thorny skin!");
7144 u.thornspell = 10 + (spell_damage_bonus(spellid(spell)) * 2);
7145 /* casting it repeatedly will not give you a longer duration --Amy */
7147 break;
7149 case SPE_MANA_BATTERY:
7152 register struct obj *mbobj, *mbobj2;
7153 for (mbobj = invent; mbobj; mbobj = mbobj2) {
7154 mbobj2 = mbobj->nobj;
7156 if (mbobj->oclass == WAND_CLASS) {
7157 if (mbobj->spe > 1) u.uen += (mbobj->spe * 10);
7158 if (u.uen > u.uenmax) u.uen = u.uenmax;
7159 delobj(mbobj);
7164 pline("Your wands are consumed to restore your mana.");
7166 break;
7168 case SPE_UNTAME_MONSTER:
7170 register struct monst *frostmon, *nxtmon;
7172 for(frostmon = fmon; frostmon; frostmon = nxtmon) {
7173 nxtmon = frostmon->nmon; /* trap might kill mon */
7174 if (DEADMONSTER(frostmon)) continue;
7175 if (!monnear(frostmon, u.ux, u.uy)) continue;
7177 if (frostmon->mtame) frostmon->mtame = 0;
7181 break;
7183 case SPE_CODE_EDITING:
7186 register struct obj *codeobj, *nextobj;
7187 for (codeobj = fobj; codeobj; codeobj = nextobj) {
7188 nextobj = codeobj->nobj;
7189 if (codeobj->otyp != CORPSE) continue;
7190 if (codeobj->where != OBJ_FLOOR) continue;
7191 if (obj_resists(codeobj, 0, 50)) continue; /* no easy removal of rider corpses! --Amy */
7192 explode(codeobj->ox, codeobj->oy, ZT_SPELL(ZT_FIRE), mons[codeobj->corpsenm].mlevel * rnz(5), SCROLL_CLASS, EXPL_FIERY);
7193 pline("Boom!");
7194 if (codeobj) delobj(codeobj);
7198 break;
7200 case SPE_ELEMENTAL_MINION:
7203 pline("You sacrifice some of your %s to create an elemental being.", body_part(BLOOD));
7204 u.uhpmax -= rnd(5);
7205 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
7206 if (u.uhp < 1) {
7207 u.youaredead = 1;
7208 killer = "summoning an elemental with too little health";
7209 killer_format = KILLED_BY;
7210 done(DIED);
7211 u.youaredead = 0;
7213 if (Upolyd) {
7214 u.mhmax -= rnd(5);
7215 if (u.mh > u.mhmax) u.mh = u.mhmax;
7218 /* make good shit, after all you pay with max health for this spell */
7219 u.aggravation = 1;
7220 if (!rn2(3)) u.heavyaggravation = 1;
7221 if (!rn2(20)) DifficultyIncreased += 1;
7222 if (!rn2(20)) HighlevelStatus += 1;
7224 register struct monst *elemental;
7225 elemental = makemon(mkclass(S_ELEMENTAL,0), u.ux, u.uy, MM_NOSPECIALS);
7226 if (elemental) {
7227 if (!resist(elemental, SPBOOK_CLASS, 0, NOTELL)) {
7228 elemental = tamedog(elemental, (struct obj *) 0, FALSE);
7229 if (elemental) You("dominate %s!", mon_nam(elemental));
7230 } else if (!resist(elemental, SPBOOK_CLASS, 0, NOTELL)) {
7231 elemental = tamedog(elemental, (struct obj *) 0, FALSE);
7232 if (elemental) You("dominate %s!", mon_nam(elemental));
7233 } else if (!resist(elemental, SPBOOK_CLASS, 0, TELL)) {
7234 elemental = tamedog(elemental, (struct obj *) 0, FALSE);
7235 if (elemental) You("dominate %s!", mon_nam(elemental));
7236 } else if ((rnd(30 - ACURR(A_CHA))) < 4) {
7237 elemental = tamedog(elemental, (struct obj *) 0, FALSE);
7238 if (elemental) You("dominate %s!", mon_nam(elemental));
7242 u.aggravation = 0;
7243 u.heavyaggravation = 0;
7244 if (DifficultyIncreased > 0) DifficultyIncreased--;
7245 if (HighlevelStatus > 0) HighlevelStatus--;
7249 break;
7251 case SPE_HYPERSPACE_SUMMON:
7254 pline("You sacrifice some of your %s and magical energy to create vortices.", body_part(BLOOD));
7255 u.uhpmax -= rno(8);
7256 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
7257 if (u.uhp < 1) {
7258 u.youaredead = 1;
7259 killer = "summoning vortices with too little health";
7260 killer_format = KILLED_BY;
7261 done(DIED);
7262 u.youaredead = 0;
7264 if (Upolyd) {
7265 u.mhmax -= rno(8);
7266 if (u.mh > u.mhmax) u.mh = u.mhmax;
7268 if (!rn2(2)) {
7269 u.uenmax -= rno(8);
7270 if (u.uenmax < 0) u.uenmax = 0;
7271 if (u.uen > u.uenmax) u.uen = u.uenmax;
7274 int ammount = 1;
7275 if (spell_damage_bonus(spellid(spell)) > 0) ammount += spell_damage_bonus(spellid(spell));
7277 /* make good shit, after all you pay with max health and pw for this spell */
7278 u.aggravation = 1;
7279 if (!rn2(2)) u.heavyaggravation = 1;
7280 if (!rn2(7)) DifficultyIncreased += 1;
7281 if (!rn2(7)) HighlevelStatus += 1;
7283 register struct monst *vortex;
7284 while (ammount > 0) {
7285 vortex = makemon(mkclass(S_VORTEX,0), u.ux, u.uy, MM_NOSPECIALS);
7286 if (vortex) {
7287 if (!resist(vortex, SPBOOK_CLASS, 0, NOTELL)) {
7288 vortex = tamedog(vortex, (struct obj *) 0, FALSE);
7289 if (vortex) You("dominate %s!", mon_nam(vortex));
7290 } else if (!resist(vortex, SPBOOK_CLASS, 0, NOTELL)) {
7291 vortex = tamedog(vortex, (struct obj *) 0, FALSE);
7292 if (vortex) You("dominate %s!", mon_nam(vortex));
7293 } else if (!resist(vortex, SPBOOK_CLASS, 0, NOTELL)) {
7294 vortex = tamedog(vortex, (struct obj *) 0, FALSE);
7295 if (vortex) You("dominate %s!", mon_nam(vortex));
7296 } else if (!resist(vortex, SPBOOK_CLASS, 0, NOTELL)) {
7297 vortex = tamedog(vortex, (struct obj *) 0, FALSE);
7298 if (vortex) You("dominate %s!", mon_nam(vortex));
7299 } else if (!resist(vortex, SPBOOK_CLASS, 0, TELL)) {
7300 vortex = tamedog(vortex, (struct obj *) 0, FALSE);
7301 if (vortex) You("dominate %s!", mon_nam(vortex));
7302 } else if ((rnd(30 - ACURR(A_CHA))) < 4) {
7303 vortex = tamedog(vortex, (struct obj *) 0, FALSE);
7304 if (vortex) You("dominate %s!", mon_nam(vortex));
7305 } else if ((rnd(30 - ACURR(A_CHA))) < 4) {
7306 vortex = tamedog(vortex, (struct obj *) 0, FALSE);
7307 if (vortex) You("dominate %s!", mon_nam(vortex));
7311 ammount--;
7314 u.aggravation = 0;
7315 u.heavyaggravation = 0;
7316 if (DifficultyIncreased > 0) DifficultyIncreased--;
7317 if (HighlevelStatus > 0) HighlevelStatus--;
7321 break;
7323 case SPE_KNOW_ENCHANTMENT:
7326 pline("You detect the enchantment status of your inventory!");
7328 register struct obj *obj, *obj2;
7329 for (obj = invent; obj; obj = obj2) {
7330 obj2 = obj->nobj;
7332 if (obj->shirtmessage % 4 == 0 && !obj->known) {
7333 obj->known = TRUE;
7334 break;
7340 break;
7342 case SPE_DISSOLVE_FOOD:
7345 pline("Your food dissolves!");
7347 register struct obj *obj, *obj2;
7348 for (obj = invent; obj; obj = obj2) {
7349 obj2 = obj->nobj;
7351 if (obj->oclass == FOOD_CLASS) useupall(obj);
7356 break;
7358 case SPE_MIMICRY:
7359 pline("You start to disguise.");
7361 youmonst.m_ap_type = M_AP_OBJECT;
7362 youmonst.mappearance = FunnyHallu ? ORANGE : GOLD_PIECE;
7363 newsym(u.ux,u.uy);
7365 break;
7367 case SPE_WHISPERS_FROM_BEYOND:
7369 ABASE(A_INT) -= rnd(2);
7370 if (ABASE(A_INT) < ATTRABSMIN(A_INT)) {
7371 u.youaredead = 1;
7372 Your("last thought fades away.");
7373 killer = "brainlessness";
7374 killer_format = KILLED_BY;
7375 done(DIED);
7377 /* player still alive somehow? kill them again :P */
7379 pline("Unfortunately your brain is still gone.");
7380 killer = "brainlessness";
7381 killer_format = KILLED_BY;
7382 done(DIED);
7383 u.youaredead = 0;
7385 /* if you're still alive then you're either in wizard mode, or you deserve to be able to go on playing. */
7387 ABASE(A_INT) = ATTRABSMIN(A_INT);
7388 You_feel("like a scarecrow.");
7390 AMAX(A_INT) = ABASE(A_INT);
7392 ABASE(A_WIS) -= rnd(2);
7393 if (ABASE(A_WIS) < ATTRABSMIN(A_WIS)) {
7395 u.youaredead = 1;
7396 You("turn into an unthinkable vegetable and die.");
7397 killer = "being turned into a vegetable";
7398 killer_format = KILLED_BY;
7399 done(DIED);
7400 u.youaredead = 0;
7402 /* player still alive somehow? well then, you can go on playing */
7404 ABASE(A_WIS) = ATTRABSMIN(A_WIS);
7406 AMAX(A_WIS) = ABASE(A_WIS);
7408 increasesanity(rnd(1000));
7410 /* It is not a mistake that INT loss kills you twice while WIS loss only does so once. --Amy */
7412 /* now identify the stuff because otherwise players could just hangup cheat past the bad effects... gah... */
7413 identify_pack(0, 0, 0);
7414 identify_pack(0, 0, 0);
7415 if (rn2(2)) identify_pack(0, 0, 0);
7416 if (!rn2(5)) identify_pack(0, 0, 0);
7417 whisperchoice:
7418 if (!CannotSelectItemsInPrompts) {
7419 otmp = getobj(allnoncount, "secure identify");
7421 if (!otmp) {
7422 if (yn("Really exit with no object selected?") == 'y')
7423 pline("You just wasted the opportunity to secure identify your objects.");
7424 else goto whisperchoice;
7425 pline("A feeling of loss comes over you.");
7426 break;
7428 if (otmp) {
7429 makeknown(otmp->otyp);
7430 if (otmp->oartifact) discover_artifact((int)otmp->oartifact);
7431 otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
7432 if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
7433 learn_egg_type(otmp->corpsenm);
7434 prinv((char *)0, otmp, 0L);
7438 break;
7440 case SPE_STASIS:
7441 u.stasistime = rnd(100);
7442 nomul(-(u.stasistime), "frozen in stasis", FALSE);
7443 pline("You freeze completely.");
7445 break;
7447 case SPE_CRYOGENICS:
7449 cryogenics();
7451 break;
7453 case SPE_TERROR:
7455 if (!rn2(20)) {
7457 pline("The spell effect backlashes!");
7459 if (!obsidianprotection()) switch (rn2(17)) {
7460 case 0:
7461 case 1:
7462 case 2:
7463 case 3: make_confused(HConfusion + 12, FALSE); /* 40% */
7464 break;
7465 case 4:
7466 case 5:
7467 case 6: make_confused(HConfusion + (2L * 12 / 3L), FALSE); /* 30% */
7468 make_stunned(HStun + (12 / 3L), FALSE);
7469 break;
7470 case 7:
7471 case 8: make_stunned(HStun + (2L * 12 / 3L), FALSE); /* 20% */
7472 make_confused(HConfusion + (12 / 3L), FALSE);
7473 break;
7474 case 9: make_stunned(HStun + 12, FALSE); /* 10% */
7475 break;
7476 case 10: make_numbed(HNumbed + 12, FALSE); /* 10% */
7477 break;
7478 case 11: make_frozen(HFrozen + 12, FALSE); /* 10% */
7479 break;
7480 case 12: make_burned(HBurned + 12, FALSE); /* 10% */
7481 break;
7482 case 13: make_feared(HFeared + 12, FALSE); /* 10% */
7483 break;
7484 case 14: make_blinded(Blinded + 12, FALSE); /* 10% */
7485 break;
7486 case 15: make_hallucinated(HHallucination + 12, FALSE, 0L); /* 10% */
7487 break;
7488 case 16: make_dimmed(HDimmed + 12, FALSE); /* 10% */
7489 break;
7495 register struct monst *fleemon;
7497 for(fleemon = fmon; fleemon; fleemon = fleemon->nmon) {
7498 if (DEADMONSTER(fleemon)) continue;
7499 wakeup(fleemon); /* monster becomes hostile */
7500 if (!resist(fleemon, SPBOOK_CLASS, 0, NOTELL))
7501 monflee(fleemon, rnd(50), FALSE, FALSE);
7503 You_hear("horrified screaming close by.");
7506 break;
7508 case SPE_SYMHEAL:
7509 if (uinsymbiosis) {
7510 int healamount;
7511 healamount = (rnd(10) + 4 + (spell_damage_bonus(spellid(spell)) * 2) + rndrnz(boosted_ulevel(1)));
7512 if (healamount > 1) healamount /= 2;
7513 Your("symbiote seems healthier!");
7514 u.usymbiote.mhp += healamount;
7515 if (u.usymbiote.mhp > u.usymbiote.mhpmax) u.usymbiote.mhp = u.usymbiote.mhpmax;
7518 break;
7520 case SPE_PHASE_DOOR:
7521 phase_door(0);
7522 if (!rn2(20)) {
7523 pline("The spell backlashes!");
7524 badeffect();
7527 break;
7529 case SPE_TELEPORT_SELF:
7530 tele();
7531 if (!rn2(10)) {
7532 pline("The spell backlashes!");
7533 badeffect();
7536 break;
7538 case SPE_MEDIUM_HEALING:
7540 int healamount = d(2, 10) + 5 + (!rn2(3) ? 0 : rndrnz(boosted_ulevel(1)) );
7541 if (healamount > 1 && !rn2(2)) healamount /= 2;
7543 healup(healamount, 0, FALSE, FALSE);
7545 You_feel("healthier!");
7547 if (u.usteed) {
7548 u.usteed->mhp += rnd(12);
7549 if (u.usteed->mhp > u.usteed->mhpmax) u.usteed->mhp = u.usteed->mhpmax;
7550 pline("%s looks healthier.", Monnam(u.usteed));
7556 break;
7558 case SPE_STRONG_HEALING:
7560 int healamount = d(5, 10) + 10 + (rn2(3) ? 0 : rnz(boosted_ulevel(2)) );
7561 if (healamount > 1 && !rn2(2)) healamount /= 2;
7563 healup(healamount, 0, FALSE, FALSE);
7565 You_feel("much more healthy!");
7567 if (u.usteed) {
7568 u.usteed->mhp += d(5, 5);
7569 if (u.usteed->mhp > u.usteed->mhpmax) u.usteed->mhp = u.usteed->mhpmax;
7570 pline("%s looks healthier.", Monnam(u.usteed));
7576 break;
7578 case SPE_SUPER_HEALING:
7580 int healamount = d(13, 10) + 13 + (rn2(2) ? 0 : rnz(boosted_ulevel(4)) );
7581 if (healamount > 1 && !rn2(2)) healamount /= 2;
7583 healup(healamount, 0, FALSE, FALSE);
7585 You_feel("healthy again!");
7587 if (u.usteed) {
7588 u.usteed->mhp += d(5, 13);
7589 if (u.usteed->mhp > u.usteed->mhpmax) u.usteed->mhp = u.usteed->mhpmax;
7590 pline("%s looks healthier.", Monnam(u.usteed));
7596 break;
7598 case SPE_HEALING_RAIN:
7601 struct monst *hrmon;
7603 int healamount = d(2, 10) + 5 + (!rn2(3) ? 0 : rndrnz(boosted_ulevel(1)) );
7604 if (healamount > 1 && !rn2(2)) healamount /= 2;
7606 healup(healamount, 0, FALSE, FALSE);
7608 You_feel("healthier!");
7610 if (u.usteed) {
7611 u.usteed->mhp += rnd(12);
7612 if (u.usteed->mhp > u.usteed->mhpmax) u.usteed->mhp = u.usteed->mhpmax;
7613 pline("%s looks healthier.", Monnam(u.usteed));
7617 for (hrmon = fmon; hrmon; hrmon = hrmon->nmon) {
7618 if (DEADMONSTER(hrmon)) continue;
7619 if (distu(hrmon->mx,hrmon->my) > 9) continue;
7620 if (!hrmon->mtame) continue;
7622 hrmon->mhp += rnd(12);
7623 if (hrmon->mhp > hrmon->mhpmax) hrmon->mhp = hrmon->mhpmax;
7624 pline("%s looks healthier.", Monnam(hrmon));
7630 break;
7632 case SPE_RELOCATION:
7633 if (u.uhave.amulet && !u.freeplaymode && u.amuletcompletelyimbued) {
7634 pline("The amulet prevents you from using that spell.");
7635 break;
7637 if (In_endgame(&u.uz)) {
7638 pline("That sort of magic doesn't work on the Planes.");
7639 break;
7642 badeffect();
7643 badeffect();
7644 badeffect();
7645 badeffect();
7646 badeffect();
7647 u.uenmax -= 5;
7648 if (u.uenmax < 0) u.uenmax = 0;
7649 if (u.uen > u.uenmax) u.uen = u.uenmax;
7651 (void) safe_teleds_normalterrain(FALSE);
7653 break;
7655 case SPE_BURROW:
7656 u.burrowed = 100;
7657 u.utrap = 100;
7658 u.utraptype = TT_INFLOOR;
7659 pline("You are burrowed into the floor, and gain armor class.");
7661 break;
7663 case SPE_SWITCHEROO:
7666 int NastinessProblemSave = NastinessProblem;
7668 pline("Click! The red status light goes out while the green light starts shining brightly!");
7670 cure_nasty_traps();
7672 NastinessProblem = NastinessProblemSave;
7674 pline("But then the green light goes out again and the red one lights up...");
7676 NastinessProblem += 10000;
7677 badeffect();
7678 badeffect();
7679 badeffect();
7680 badeffect();
7681 badeffect();
7682 badeffect();
7683 badeffect();
7685 break;
7689 case SPE_GAIN_CORRUPTION:
7691 pline("Okay, if that's really what you want... you feel corrupted.");
7692 if (FunnyHallu) pline("At least this isn't ADOM, where having too many corruptions would instakill you!");
7694 getnastytrapintrinsic();
7696 break;
7698 case SPE_COMMAND_DEMON:
7701 int soundresist = 0;
7702 int i, j, bd = 1;
7703 struct monst *mtmp;
7705 for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) {
7706 if (!isok(u.ux + i, u.uy + j)) continue;
7707 if ((mtmp = m_at(u.ux + i, u.uy + j)) != 0 && (is_demon(mtmp->data))) {
7709 soundresist = 0;
7710 switch (mtmp->data->msound) {
7711 default: break;
7712 case MS_FART_NORMAL: soundresist = 2; break;
7713 case MS_FART_QUIET: soundresist = 2; break;
7714 case MS_FART_LOUD: soundresist = 3; break;
7715 case MS_CONVERT: soundresist = 3; break;
7716 case MS_STENCH: soundresist = 5; break;
7717 case MS_HCALIEN: soundresist = 10; break;
7720 if (!rn2(2) && (!soundresist || (!rn2(soundresist)) ) && !resist(mtmp, SPBOOK_CLASS, 0, NOTELL) && !resist(mtmp, SPBOOK_CLASS, 0, NOTELL)) {
7721 (void) tamedog(mtmp, (struct obj *) 0, FALSE);
7722 u.uenmax--;
7723 if (u.uenmax < 0) u.uenmax = 0;
7724 if (u.uen > u.uenmax) u.uen = u.uenmax;
7725 flags.botl = TRUE;
7727 else if (!rn2(15) && !((rnd(30 - ACURR(A_CHA))) < 4) && !mtmp->mfrenzied && !mtmp->mtame) {
7728 pline("Instead of being tamed, %s enters a state of frenzy!", mon_nam(mtmp));
7729 mtmp->mpeaceful = 0;
7730 mtmp->mfrenzied = 1;
7736 if (!rn2(10)) {
7737 pline("The spell backfires!");
7738 badeffect();
7741 break;
7743 case SPE_SELFDESTRUCT:
7746 int i, j, bd = 3;
7747 struct monst *mtmp;
7749 u.youaredead = 1;
7751 pline("%s used SELFDESTRUCT!", playeraliasname);
7753 for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) {
7754 if (!isok(u.ux + i, u.uy + j)) continue;
7755 if ((mtmp = m_at(u.ux + i, u.uy + j)) != 0) {
7756 mtmp->mhp -= rnd(u.uhpmax * 5);
7757 pline("%s is hit by the explosion!", Monnam(mtmp));
7758 if (mtmp->mhp <= 0) {
7759 pline("%s is killed!", Monnam(mtmp));
7760 xkilled(mtmp, 0);
7761 } else wakeup(mtmp); /* monster becomes hostile */
7766 killer = "selfdestructing";
7767 killer_format = KILLED_BY;
7768 done(DIED);
7769 u.youaredead = 0;
7770 /* No, being polymorphed does not save you. If it did, this spell would be rendered overpowered. --Amy */
7774 break;
7776 case SPE_FINAL_EXPLOSION:
7779 int i, j, bd = 5;
7780 struct monst *mtmp;
7782 u.youaredead = 1;
7783 pline("%s used EXPLOSION!", playeraliasname);
7785 for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) {
7786 if (!isok(u.ux + i, u.uy + j)) continue;
7787 if ((mtmp = m_at(u.ux + i, u.uy + j)) != 0) {
7788 mtmp->mhp -= rnd(u.uhpmax * 10);
7789 pline("%s is hit by the explosion!", Monnam(mtmp));
7790 if (mtmp->mhp <= 0) {
7791 pline("%s is killed!", Monnam(mtmp));
7792 xkilled(mtmp, 0);
7793 } else wakeup(mtmp); /* monster becomes hostile */
7798 killer = "exploding";
7799 killer_format = KILLED_BY;
7800 done(DIED);
7801 u.youaredead = 0;
7802 /* No, being polymorphed does not save you. If it did, this spell would be rendered overpowered. --Amy */
7806 break;
7808 case SPE_EARTHQUAKE:
7809 pline_The("entire dungeon is shaking around you!");
7810 do_earthquake((GushLevel - 1) / 3 + 1);
7811 if (!rn2(3)) {
7812 int disableamount = rnd(3);
7813 while (disableamount) {
7814 deacrandomintrinsic(rnz( (monster_difficulty() * 10) + 1));
7815 disableamount--;
7816 if (disableamount < 0) disableamount = 0;
7820 break;
7822 case SPE_LYCANTHROPY:
7824 if (u.ulycn != NON_PM) {
7825 pline("You are already lycanthropic!");
7826 break;
7830 int attempts = 0;
7831 int monstZ;
7832 do {
7834 monstZ = rn2(NUMMONS);
7835 attempts++;
7837 } while (!(is_were(&mons[monstZ])) || (mons[monstZ].mlet == S_HUMAN) && attempts < 50000);
7839 if (is_were(&mons[monstZ]) && !(mons[monstZ].mlet == S_HUMAN) ) {
7840 u.ulycn = monstZ;
7841 pline("You feel feverish.");
7842 u.cnd_lycanthropecount++;
7847 break;
7849 case SPE_BUC_RANDOMIZATION:
7851 { register struct obj *objC;
7852 if (FunnyHallu)
7853 You_feel("the power of the Force against you!");
7854 else
7855 You_feel("like you need some help.");
7856 if (PlayerHearsSoundEffects) pline(issoviet ? "Vashe der'mo tol'ko chto proklinal." : "Woaaaaaa-AAAH!");
7858 for (objC = invent; objC; objC = objC->nobj) {
7859 long wornmask;
7860 #ifdef GOLDOBJ
7861 /* gold isn't subject to cursing and blessing */
7862 if (objC->oclass == COIN_CLASS) continue;
7863 #endif
7864 wornmask = (objC->owornmask & ~(W_BALL|W_ART|W_ARTI));
7865 if (wornmask) {
7866 /* handle a couple of special cases; we don't
7867 allow auxiliary weapon slots to be used to
7868 artificially increase number of worn items */
7869 if (objC == uswapwep) {
7870 if (!u.twoweap) wornmask = 0L;
7871 } else if (objC == uquiver) {
7872 if (objC->oclass == WEAPON_CLASS) {
7873 /* mergeable weapon test covers ammo,
7874 missiles, spears, daggers & knives */
7875 if (!objects[objC->otyp].oc_merge)
7876 wornmask = 0L;
7877 } else if (objC->oclass == GEM_CLASS) {
7878 /* possibly ought to check whether
7879 alternate weapon is a sling... */
7880 if (!uslinging()) wornmask = 0L;
7881 } else {
7882 /* weptools don't merge and aren't
7883 reasonable quivered weapons */
7884 wornmask = 0L;
7888 if ((wornmask ||
7889 objC->otyp == LOADSTONE ||
7890 objC->otyp == LOADBOULDER ||
7891 objC->otyp == STARLIGHTSTONE ||
7892 objC->otyp == LUCKSTONE ||
7893 objC->otyp == HEALTHSTONE ||
7894 objC->otyp == MANASTONE ||
7895 objC->otyp == SLEEPSTONE ||
7896 objC->otyp == STONE_OF_MAGIC_RESISTANCE ||
7897 is_nastygraystone(objC) ||
7898 is_feminismstone(objC) ||
7899 (objC->otyp == LEATHER_LEASH && objC->leashmon) || (objC->otyp == INKA_LEASH && objC->leashmon) || (objC->otyp == ADAMANT_LEASH && objC->leashmon) ) && !stack_too_big(objC) && !rn2(5) ) {
7900 blessorcurse(objC, 2);
7904 update_inventory();
7906 break;
7909 case SPE_MESSAGE:
7911 pline("%s", fauxmessage());
7912 u.cnd_plineamount++;
7913 if (!rn2(3)) {
7914 pline("%s", fauxmessage());
7915 u.cnd_plineamount++;
7918 break;
7920 case SPE_RUMOR:
7923 const char *line;
7924 char buflin[BUFSZ];
7925 if (rn2(2)) line = getrumor(-1, buflin, TRUE);
7926 else line = getrumor(0, buflin, TRUE);
7927 if (!*line) line = "Slash'EM rumors file closed for renovation.";
7928 pline("%s", line);
7931 break;
7933 case SPE_TRAP_DISARMING:
7935 You_feel("out of the danger zone.");
7937 int rtrap;
7938 struct trap *ttmp;
7940 int i, j;
7942 for (i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
7944 if ((ttmp = t_at(u.ux + i, u.uy + j)) != 0) {
7945 if (ttmp->ttyp == MAGIC_PORTAL) continue;
7946 deltrap(ttmp);
7952 pline("You are hit by the magical reaction from casting this very powerful spell.");
7953 u.uenmax -= rnd(5);
7954 badeffect();
7955 (void) doredraw();
7957 break;
7959 case SPE_WISHING:
7961 if (u.uhpmax < 501) {
7962 pline("You don't have enough health to control the powers of this spell!");
7963 break;
7965 if (Upolyd && u.mhmax < 501) {
7966 pline("You don't have enough health to control the powers of this spell!");
7967 break;
7969 if (u.uenmax < 501) {
7970 pline("You don't have enough mana to control the powers of this spell!");
7971 break;
7974 if (ABASE(A_STR) < 6 || ABASE(A_DEX) < 6 || ABASE(A_INT) < 6 || ABASE(A_WIS) < 6 || ABASE(A_CON) < 6 || ABASE(A_CHA) < 6) {
7975 pline("You don't have the stats required to power this mighty spell!");
7976 break;
7979 u.uhpmax -= rnd(500);
7980 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
7981 if (Upolyd) {
7982 u.mhmax -= rnd(500);
7983 if (u.mh > u.mhmax) u.mh = u.mhmax;
7985 u.uenmax -= rnd(500);
7986 if (u.uen > u.uenmax) u.uen = u.uenmax;
7988 ABASE(A_STR) -= rnd(5);
7989 if (ABASE(A_STR) < ATTRABSMIN(A_STR)) ABASE(A_STR) = ATTRABSMIN(A_STR);
7990 AMAX(A_STR) = ABASE(A_STR);
7992 ABASE(A_DEX) -= rnd(5);
7993 if (ABASE(A_DEX) < ATTRABSMIN(A_DEX)) ABASE(A_DEX) = ATTRABSMIN(A_DEX);
7994 AMAX(A_DEX) = ABASE(A_DEX);
7996 ABASE(A_INT) -= rnd(5);
7997 if (ABASE(A_INT) < ATTRABSMIN(A_INT)) ABASE(A_INT) = ATTRABSMIN(A_INT);
7998 AMAX(A_INT) = ABASE(A_INT);
8000 ABASE(A_WIS) -= rnd(5);
8001 if (ABASE(A_WIS) < ATTRABSMIN(A_WIS)) ABASE(A_WIS) = ATTRABSMIN(A_WIS);
8002 AMAX(A_WIS) = ABASE(A_WIS);
8004 ABASE(A_CON) -= rnd(5);
8005 if (ABASE(A_CON) < ATTRABSMIN(A_CON)) ABASE(A_CON) = ATTRABSMIN(A_CON);
8006 AMAX(A_CON) = ABASE(A_CON);
8008 ABASE(A_CHA) -= rnd(5);
8009 if (ABASE(A_CHA) < ATTRABSMIN(A_CHA)) ABASE(A_CHA) = ATTRABSMIN(A_CHA);
8010 AMAX(A_CHA) = ABASE(A_CHA);
8012 makewish(TRUE);
8014 break;
8016 case SPE_ACQUIREMENT:
8018 if (u.uhpmax < 101) {
8019 pline("You don't have enough health to control the powers of this spell!");
8020 break;
8022 if (Upolyd && u.mhmax < 101) {
8023 pline("You don't have enough health to control the powers of this spell!");
8024 break;
8026 if (u.uenmax < 101) {
8027 pline("You don't have enough mana to control the powers of this spell!");
8028 break;
8031 if (ABASE(A_STR) < 4 || ABASE(A_DEX) < 4 || ABASE(A_INT) < 4 || ABASE(A_WIS) < 4 || ABASE(A_CON) < 4 || ABASE(A_CHA) < 4) {
8032 pline("You don't have the stats required to power this mighty spell!");
8033 break;
8036 u.uhpmax -= rnd(33);
8037 if (rn2(2)) u.uhpmax -= rnd(33);
8038 if (!rn2(4)) u.uhpmax -= rnd(33);
8039 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
8040 if (Upolyd) {
8041 u.mhmax -= rnd(33);
8042 if (rn2(2)) u.mhmax -= rnd(33);
8043 if (!rn2(4)) u.mhmax -= rnd(33);
8044 if (u.mh > u.mhmax) u.mh = u.mhmax;
8046 u.uenmax -= rnd(33);
8047 if (rn2(2)) u.uenmax -= rnd(33);
8048 if (!rn2(4)) u.uenmax -= rnd(33);
8049 if (u.uen > u.uenmax) u.uen = u.uenmax;
8051 if (!rn2(2)) {
8052 ABASE(A_STR) -= 1;
8053 if (ABASE(A_STR) < ATTRABSMIN(A_STR)) ABASE(A_STR) = ATTRABSMIN(A_STR);
8054 AMAX(A_STR) = ABASE(A_STR);
8057 if (!rn2(2)) {
8058 ABASE(A_DEX) -= 1;
8059 if (ABASE(A_DEX) < ATTRABSMIN(A_DEX)) ABASE(A_DEX) = ATTRABSMIN(A_DEX);
8060 AMAX(A_DEX) = ABASE(A_DEX);
8063 if (!rn2(2)) {
8064 ABASE(A_INT) -= 1;
8065 if (ABASE(A_INT) < ATTRABSMIN(A_INT)) ABASE(A_INT) = ATTRABSMIN(A_INT);
8066 AMAX(A_INT) = ABASE(A_INT);
8069 if (!rn2(2)) {
8070 ABASE(A_WIS) -= 1;
8071 if (ABASE(A_WIS) < ATTRABSMIN(A_WIS)) ABASE(A_WIS) = ATTRABSMIN(A_WIS);
8072 AMAX(A_WIS) = ABASE(A_WIS);
8075 if (!rn2(2)) {
8076 ABASE(A_CON) -= 1;
8077 if (ABASE(A_CON) < ATTRABSMIN(A_CON)) ABASE(A_CON) = ATTRABSMIN(A_CON);
8078 AMAX(A_CON) = ABASE(A_CON);
8081 if (!rn2(2)) {
8082 ABASE(A_CHA) -= 1;
8083 if (ABASE(A_CHA) < ATTRABSMIN(A_CHA)) ABASE(A_CHA) = ATTRABSMIN(A_CHA);
8084 AMAX(A_CHA) = ABASE(A_CHA);
8087 acquireitem();
8089 break;
8091 case SPE_MASS_HEALING:
8093 register struct monst *mtmp, *mtmp2;
8095 for (mtmp = fmon; mtmp; mtmp = mtmp2) {
8096 mtmp2 = mtmp->nmon;
8097 if (mtmp == &youmonst) continue;
8098 if (DEADMONSTER(mtmp)) continue;
8099 if (!mtmp->mtame) {
8100 if (!Hallucination && (!mtmp->mpeaceful || !rn2(2)))
8101 continue;
8103 if (!canspotmon(mtmp)) continue; /*you can't see it and can't sense it*/
8105 mtmp->mhp += rnd(50);
8106 if (mtmp->mhp > mtmp->mhpmax) {
8107 mtmp->mhp = mtmp->mhpmax;
8109 if (mtmp->bleedout) {
8110 mtmp->bleedout -= rnd(50);
8111 if (mtmp->bleedout < 0) mtmp->bleedout = 0;
8113 pline("%s is healed.", Monnam(mtmp));
8117 int healamount = (d(6,8) + rndrnz(boosted_ulevel(1)) );
8118 if (healamount > 1) healamount /= 2;
8120 healup(healamount,0,0,0);
8122 break;
8124 case SPE_TIME_SHIFT:
8125 pline("Time goes forward...");
8126 monstermoves += 5;
8127 moves += 5;
8129 break;
8131 case SPE_CHEMISTRY:
8132 You("call upon your chemical knowledge. Nothing happens.");
8133 break;
8134 case SPE_CURE_SICKNESS:
8136 if ((Sick || Slimed) && !Role_if(PM_HEALER)) {
8137 if (u.uenmax > 0) {
8138 u.uenmax--;
8139 if (u.uen > u.uenmax) u.uen = u.uenmax;
8140 } else {
8141 You("don't have enough power for this spell.");
8142 break;
8146 if (Sick) You("are no longer ill.");
8147 if (Slimed) {
8148 pline_The("slime disappears!");
8149 Slimed = 0;
8150 /* flags.botl = 1; -- healup() handles this */
8152 healup(0, 0, TRUE, FALSE);
8153 break;
8154 case SPE_CURE_HALLUCINATION:
8155 if (HeavyHallu) break;
8156 if (HHallucination > (rn1(Role_if(PM_HEALER) ? 200 : 100, 20))) {
8157 int effreduction = rnd(HHallucination / 2);
8158 if (effreduction > 0) {
8159 HHallucination -= effreduction;
8160 Your("hallucination counter is reduced.");
8162 if (!Role_if(PM_HEALER) && !rn2(500)) {
8163 pline("The spell backlashes!");
8164 badeffect();
8166 } else {
8167 make_hallucinated(0L,TRUE,0L);
8169 break;
8170 case SPE_CURE_CONFUSION:
8171 if (HeavyConfusion) break;
8172 if (HConfusion > (rn1(Role_if(PM_HEALER) ? 200 : 100, 20))) {
8173 int effreduction = rnd(HConfusion / 2);
8174 if (effreduction > 0) {
8175 HConfusion -= effreduction;
8176 Your("confusion counter is reduced.");
8178 if (!Role_if(PM_HEALER) && !rn2(500)) {
8179 pline("The spell backlashes!");
8180 badeffect();
8182 } else {
8183 make_confused(0L,TRUE);
8185 break;
8186 case SPE_CURE_STUN:
8187 if (HeavyStunned) break;
8188 if (HStun > (rn1(Role_if(PM_HEALER) ? 200 : 100, 20))) {
8189 int effreduction = rnd(HStun / 2);
8190 if (effreduction > 0) {
8191 HStun -= effreduction;
8192 Your("stun counter is reduced.");
8194 if (!Role_if(PM_HEALER) && !rn2(500)) {
8195 pline("The spell backlashes!");
8196 badeffect();
8198 } else {
8199 make_stunned(0L,TRUE);
8201 break;
8202 case SPE_CURE_DIM:
8203 if (HeavyDimmed) break;
8204 if (HDimmed > (rn1(Role_if(PM_HEALER) ? 200 : 100, 20))) {
8205 int effreduction = rnd(HDimmed / 2);
8206 if (effreduction > 0) {
8207 HDimmed -= effreduction;
8208 Your("dimness counter is reduced.");
8210 if (!Role_if(PM_HEALER) && !rn2(500)) {
8211 pline("The spell backlashes!");
8212 badeffect();
8214 } else {
8215 make_dimmed(0L,TRUE);
8217 break;
8218 case SPE_CURE_BURN:
8219 if (HeavyBurned) break;
8220 if (HBurned > (rn1(Role_if(PM_HEALER) ? 200 : 100, 20))) {
8221 int effreduction = rnd(HBurned / 2);
8222 if (effreduction > 0) {
8223 HBurned -= effreduction;
8224 Your("burn counter is reduced.");
8226 if (!Role_if(PM_HEALER) && !rn2(500)) {
8227 pline("The spell backlashes!");
8228 badeffect();
8230 } else {
8231 make_burned(0L,TRUE);
8233 break;
8234 case SPE_CURE_FREEZE:
8235 if (HeavyFrozen) break;
8236 if (HFrozen > (rn1(Role_if(PM_HEALER) ? 200 : 100, 20))) {
8237 int effreduction = rnd(HFrozen / 2);
8238 if (effreduction > 0) {
8239 HFrozen -= effreduction;
8240 Your("freeze counter is reduced.");
8242 if (!Role_if(PM_HEALER) && !rn2(500)) {
8243 pline("The spell backlashes!");
8244 badeffect();
8246 } else {
8247 make_frozen(0L,TRUE);
8249 break;
8250 case SPE_CURE_NUMBNESS:
8251 if (HeavyNumbed) break;
8252 if (HNumbed > (rn1(Role_if(PM_HEALER) ? 200 : 100, 20))) {
8253 int effreduction = rnd(HNumbed / 2);
8254 if (effreduction > 0) {
8255 HNumbed -= effreduction;
8256 Your("numbness counter is reduced.");
8258 if (!Role_if(PM_HEALER) && !rn2(500)) {
8259 pline("The spell backlashes!");
8260 badeffect();
8262 } else {
8263 make_numbed(0L,TRUE);
8265 break;
8266 case SPE_CURE_RANDOM_STATUS:
8267 switch (rnd(10)) {
8268 case 1:
8269 if ((Sick || Slimed) && !Role_if(PM_HEALER) && !rn2(5)) {
8270 if (u.uenmax > 0) {
8271 u.uenmax--;
8272 if (u.uen > u.uenmax) u.uen = u.uenmax;
8273 } else {
8274 You("don't have enough power for this spell.");
8275 break;
8279 if (Sick) You("are no longer ill.");
8280 if (Slimed) {
8281 pline_The("slime disappears!");
8282 Slimed = 0;
8284 healup(0, 0, TRUE, FALSE);
8285 break;
8286 case 2:
8287 if (HeavyHallu) break;
8288 if (HHallucination > (rn1(Role_if(PM_HEALER) ? 600 : 300, 20))) {
8289 int effreduction = rnd(HHallucination / 2);
8290 if (effreduction > 0) {
8291 HHallucination -= effreduction;
8292 Your("hallucination counter is reduced.");
8294 } else {
8295 make_hallucinated(0L,TRUE,0L);
8297 break;
8298 case 3:
8299 if (HeavyConfusion) break;
8300 if (HConfusion > (rn1(Role_if(PM_HEALER) ? 600 : 300, 20))) {
8301 int effreduction = rnd(HConfusion / 2);
8302 if (effreduction > 0) {
8303 HConfusion -= effreduction;
8304 Your("confusion counter is reduced.");
8306 } else {
8307 make_confused(0L,TRUE);
8309 break;
8310 case 4:
8311 if (HeavyStunned) break;
8312 if (HStun > (rn1(Role_if(PM_HEALER) ? 600 : 300, 20))) {
8313 int effreduction = rnd(HStun / 2);
8314 if (effreduction > 0) {
8315 HStun -= effreduction;
8316 Your("stun counter is reduced.");
8318 } else {
8319 make_stunned(0L,TRUE);
8321 break;
8322 case 5:
8323 if (HeavyBurned) break;
8324 if (HBurned > (rn1(Role_if(PM_HEALER) ? 600 : 300, 20))) {
8325 int effreduction = rnd(HBurned / 2);
8326 if (effreduction > 0) {
8327 HBurned -= effreduction;
8328 Your("burn counter is reduced.");
8330 } else {
8331 make_burned(0L,TRUE);
8333 break;
8334 case 6:
8335 if (HeavyFrozen) break;
8336 if (HFrozen > (rn1(Role_if(PM_HEALER) ? 600 : 300, 20))) {
8337 int effreduction = rnd(HFrozen / 2);
8338 if (effreduction > 0) {
8339 HFrozen -= effreduction;
8340 Your("freeze counter is reduced.");
8342 } else {
8343 make_frozen(0L,TRUE);
8345 break;
8346 case 7:
8347 if (HeavyNumbed) break;
8348 if (HNumbed > (rn1(Role_if(PM_HEALER) ? 600 : 300, 20))) {
8349 int effreduction = rnd(HNumbed / 2);
8350 if (effreduction > 0) {
8351 HNumbed -= effreduction;
8352 Your("numbness counter is reduced.");
8354 } else {
8355 make_numbed(0L,TRUE);
8357 break;
8358 case 8:
8359 if (HeavyBlind) break;
8360 if (Blinded > (rn1(Role_if(PM_HEALER) ? 600 : 300, 20))) {
8361 int effreduction = rnd(Blinded / 2);
8362 if (effreduction > 0) {
8363 u.ucreamed -= effreduction;
8364 if ((int)(u.ucreamed) < 0) u.ucreamed = 0; /* fail safe */
8365 Blinded -= effreduction;
8366 Your("blindness counter is reduced.");
8368 } else {
8369 make_blinded(0L,FALSE);
8371 break;
8372 case 9:
8373 if (HeavyFeared) break;
8374 if (HFeared > (rn1(Role_if(PM_HEALER) ? 600 : 300, 20))) {
8375 int effreduction = rnd(HFeared / 2);
8376 if (effreduction > 0) {
8377 HFeared -= effreduction;
8378 Your("fear counter is reduced.");
8380 } else {
8381 make_feared(0L, TRUE);
8383 break;
8384 case 10:
8385 if (HeavyDimmed) break;
8386 if (HDimmed > (rn1(Role_if(PM_HEALER) ? 600 : 300, 20))) {
8387 int effreduction = rnd(HDimmed / 2);
8388 if (effreduction > 0) {
8389 HDimmed -= effreduction;
8390 Your("dimness counter is reduced.");
8392 } else {
8393 make_dimmed(0L,TRUE);
8395 break;
8397 break;
8399 case SPE_STINKING_CLOUD:
8400 { coord cc;
8401 pline("Where do you want to center the cloud?");
8402 cc.x = u.ux;
8403 cc.y = u.uy;
8404 if (getpos(&cc, TRUE, "the desired position") < 0) {
8405 pline("%s", Never_mind);
8406 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
8407 pline("Oh wait, actually I do mind...");
8408 badeffect();
8410 break;
8412 if (!cansee(cc.x, cc.y) || distu(cc.x, cc.y) >= 32) {
8413 You("smell rotten eggs.");
8414 break;
8416 (void) create_gas_cloud(cc.x, cc.y, 2, 5);
8417 break;
8419 break;
8420 case SPE_FIXING:
8421 You_feel("revitalized.");
8423 if ((Sick || Slimed) && !Role_if(PM_HEALER)) {
8424 if (u.uenmax > 0) {
8425 u.uenmax--;
8426 if (u.uen > u.uenmax) u.uen = u.uenmax;
8427 } else {
8428 You("don't have enough power for this spell.");
8429 break;
8433 if (Stoned) {
8434 fix_petrification();
8436 if (!rn2(2)) {
8437 if (u.uhpmax < 2) {
8438 u.youaredead = 1;
8439 killer = "dissolving completely";
8440 killer_format = KILLED_BY;
8441 done(DIED);
8442 u.youaredead = 0;
8443 } else {
8444 u.uhpmax--;
8445 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
8446 flags.botl = TRUE;
8447 if (Upolyd) {
8448 if (u.mhmax > 1) u.mhmax--;
8449 if (u.mh > u.mhmax) u.mh = u.mhmax;
8452 Your("health was damaged.");
8453 } else {
8454 u.negativeprotection += rnd(3);
8455 MCReduction += rn1(2500, 2500);
8456 Your("body was damaged.");
8460 if (Slimed) {
8461 pline("The slime disappears.");
8462 Slimed =0;
8465 make_sick(0L, (char *) 0, FALSE, SICK_ALL);
8466 make_blinded(0L,FALSE);
8467 make_stunned(0L,TRUE);
8468 make_confused(0L,TRUE);
8469 (void) make_hallucinated(0L,FALSE,0L);
8470 make_numbed(0L,TRUE);
8471 make_feared(0L,TRUE);
8472 make_frozen(0L,TRUE);
8473 make_burned(0L,TRUE);
8474 make_dimmed(0L,TRUE);
8476 break;
8478 case SPE_FIRE:
8480 if (Underwater)
8481 pline_The("water around you vaporizes violently!");
8482 else {
8483 pline_The("air around you erupts in a tower of flame!");
8484 burn_away_slime();
8486 explode(u.ux, u.uy, ZT_SPELL(ZT_FIRE), 3 + (spell_damage_bonus(spellid(spell)) / 2), SCROLL_CLASS, EXPL_FIERY);
8488 break;
8490 case SPE_RUSSIAN_ROULETTE:
8492 if (rn2(10)) {
8493 pline("Click!");
8494 badeffect();
8496 } else if (rn2(10)) {
8497 pline("Click! You feel vitalized.");
8498 u.uhpmax++;
8499 if (Upolyd) u.mhmax++;
8500 if (uinsymbiosis) {
8501 u.usymbiote.mhpmax++;
8502 maybe_evolve_symbiote();
8503 if (u.usymbiote.mhpmax > 500) u.usymbiote.mhpmax = 500;
8506 } else {
8507 pline("BANG! You suffer from extreme blood loss!");
8508 u.uhp -= rnd(50);
8509 u.uhpmax -= rnd(50);
8510 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
8511 if (u.uhp < 1) {
8512 u.youaredead = 1;
8513 killer = "playing russian roulette";
8514 killer_format = KILLED_BY;
8515 done(DIED);
8516 u.youaredead = 0;
8518 if (Upolyd) {
8519 u.mh -= rnd(50);
8520 u.mhmax -= rnd(50);
8521 if (u.mh > u.mhmax) u.mh = u.mhmax;
8522 if (u.mh < 1) {
8523 u.youaredead = 1;
8524 killer = "playing russian roulette";
8525 killer_format = KILLED_BY;
8526 done(DIED);
8527 u.youaredead = 0;
8530 u.uenmax -= rnd(30);
8531 if (u.uenmax < 0) u.uenmax = 0;
8532 if (u.uen > u.uenmax) u.uen = u.uenmax;
8536 break;
8538 case SPE_ACID_INGESTION:
8539 pline("Sulfuric acid forms in your mouth...");
8541 /* bullshit downside by Amy - we don't want petrification to be THAT trivial to cure... */
8543 if (!rn2(2)) {
8544 if (u.uhpmax < 2) {
8545 u.youaredead = 1;
8546 killer = "dissolving completely";
8547 killer_format = KILLED_BY;
8548 done(DIED);
8549 u.youaredead = 0;
8550 } else {
8551 u.uhpmax--;
8552 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
8553 flags.botl = TRUE;
8554 if (Upolyd) {
8555 if (u.mhmax > 1) u.mhmax--;
8556 if (u.mh > u.mhmax) u.mh = u.mhmax;
8559 Your("health was damaged.");
8560 } else {
8561 u.negativeprotection += rnd(3);
8562 MCReduction += rn1(2500, 2500);
8563 Your("body was damaged.");
8566 if (Acid_resistance && (StrongAcid_resistance || AcidImmunity || rn2(10)) ) {
8567 pline("This tastes %s.", FunnyHallu ? "tangy" : "sour");
8568 } else {
8569 pline("This burns a lot!");
8570 losehp(d(2, 8), "ingesting acid", KILLED_BY);
8572 if (Stoned) fix_petrification();
8574 break;
8576 case SPE_INDUCE_VOMITING:
8577 pline("You put your %s into your mouth...", body_part(FINGER));
8579 You_feel("like you're going to throw up.");
8580 make_vomiting(Vomiting+20, TRUE);
8581 if (Sick && Sick < 100)
8582 set_itimeout(&Sick, (Sick * 2) + 10); /* higher chance to survive long enough --Amy */
8584 break;
8586 case SPE_REBOOT:
8587 You("decide to reboot.");
8588 if (PlayerHearsSoundEffects) pline(issoviet ? "Eto poshel na khuy vverkh. No chto zhe vy ozhidali? Igra, v kotoruyu vy mozhete legko vyigrat'? Durak!" : "DUEUEDUET!");
8589 if (!Race_if(PM_UNGENOMOLD)) newman();
8590 else polyself(FALSE);
8592 break;
8594 case SPE_FORGOTTEN_SPELL:
8595 Your("knowledge of this spell is twisted.");
8596 pline("It invokes nightmarish images in your mind...");
8598 int duration = rn1(25,25);
8600 if (!obsidianprotection()) switch (rn2(17)) {
8601 case 0:
8602 case 1:
8603 case 2:
8604 case 3: make_confused(HConfusion + duration, FALSE); /* 40% */
8605 break;
8606 case 4:
8607 case 5:
8608 case 6: make_confused(HConfusion + (2L * duration / 3L), FALSE); /* 30% */
8609 make_stunned(HStun + (duration / 3L), FALSE);
8610 break;
8611 case 7:
8612 case 8: make_stunned(HStun + (2L * duration / 3L), FALSE); /* 20% */
8613 make_confused(HConfusion + (duration / 3L), FALSE);
8614 break;
8615 case 9: make_stunned(HStun + duration, FALSE); /* 10% */
8616 break;
8617 case 10: make_numbed(HNumbed + duration, FALSE); /* 10% */
8618 break;
8619 case 11: make_frozen(HFrozen + duration, FALSE); /* 10% */
8620 break;
8621 case 12: make_burned(HBurned + duration, FALSE); /* 10% */
8622 break;
8623 case 13: make_feared(HFeared + duration, FALSE); /* 10% */
8624 break;
8625 case 14: make_blinded(Blinded + duration, FALSE); /* 10% */
8626 break;
8627 case 15: make_hallucinated(HHallucination + duration, FALSE, 0L); /* 10% */
8628 break;
8629 case 16: make_dimmed(HDimmed + duration, FALSE); /* 10% */
8630 break;
8633 if (!rn2(25)) {
8634 badeffect();
8636 break;
8638 case SPE_TIME_STOP:
8639 pline((Role_if(PM_SAMURAI) || Role_if(PM_NINJA)) ? "Jikan ga teishi shimashita." : "Time has stopped.");
8640 if (rn2(3)) TimeStopped += (rnd(3) + 1);
8641 else TimeStopped += rnd(3 + spell_damage_bonus(spellid(spell)) );
8642 break;
8643 case SPE_LEVELPORT:
8644 if (!playerlevelportdisabled()) {
8645 level_tele();
8646 pline("From your strain of casting such a powerful spell, the magical energy backlashes on you.");
8647 badeffect();
8649 else pline("Hmm... that level teleport spell didn't do anything.");
8651 break;
8652 case SPE_WARPING:
8653 if (((u.uhave.amulet) && !u.freeplaymode) || CannotTeleport || (u.usteed && mon_has_amulet(u.usteed))) { pline("You shudder for a moment."); break;}
8655 if (playerlevelportdisabled()) {
8656 pline("You're unable to warp!");
8657 break;
8660 banishplayer();
8662 if (rn2(2)) {
8663 pline("From your strain of casting such a powerful spell, the magical energy backlashes on you.");
8664 badeffect();
8667 break;
8668 case SPE_TRAP_CREATION:
8670 You_feel("endangered!!");
8672 int rtrap;
8673 int i, j, bd = 1;
8674 register struct trap *ttmp;
8675 boolean canbeinawall = FALSE;
8676 if (!rn2(Passes_walls ? 5 : 25)) canbeinawall = TRUE;
8678 for (i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) {
8679 if (!isok(u.ux + i, u.uy + j)) continue;
8680 if ((levl[u.ux + i][u.uy + j].typ <= DBWALL) && !canbeinawall) continue;
8681 if (t_at(u.ux + i, u.uy + j)) continue;
8683 rtrap = rndtrap();
8685 ttmp = maketrap(u.ux + i, u.uy + j, rtrap, 100, FALSE);
8686 if (ttmp && !rn2(10)) ttmp->hiddentrap = TRUE;
8690 if (rn2(10)) {
8691 makerandomtrap(FALSE);
8692 if (!rn2(2)) makerandomtrap(FALSE);
8693 if (!rn2(4)) makerandomtrap(FALSE);
8694 if (!rn2(8)) makerandomtrap(FALSE);
8695 if (!rn2(16)) makerandomtrap(FALSE);
8696 if (!rn2(32)) makerandomtrap(FALSE);
8697 if (!rn2(64)) makerandomtrap(FALSE);
8698 if (!rn2(128)) makerandomtrap(FALSE);
8699 if (!rn2(256)) makerandomtrap(FALSE);
8700 } else {
8701 makeinvisotrap();
8702 if (!rn2(2)) makeinvisotrap();
8703 if (!rn2(4)) makeinvisotrap();
8704 if (!rn2(8)) makeinvisotrap();
8705 if (!rn2(16)) makeinvisotrap();
8706 if (!rn2(32)) makeinvisotrap();
8707 if (!rn2(64)) makeinvisotrap();
8708 if (!rn2(128)) makeinvisotrap();
8709 if (!rn2(256)) makeinvisotrap();
8711 badeffect();
8713 break;
8715 case SPE_STUN_SELF:
8716 if(!Stunned)
8717 pline("You stagger a bit...");
8718 make_stunned(HStun + rnd(25), FALSE);
8719 break;
8720 case SPE_CONFUSE_SELF:
8721 if(!Confusion)
8722 You_feel("somewhat dizzy.");
8723 make_confused(HConfusion + rnd(25), FALSE);
8724 break;
8725 case SPE_BLIND_SELF:
8726 if (!Blind && !u.usleep) pline("It suddenly gets dark.");
8727 make_blinded(Blinded + rnd(25), FALSE);
8728 if (!Blind && !u.usleep) Your("%s", vision_clears);
8729 break;
8731 case SPE_AIR_CURRENT:
8732 if (FunnyHallu)
8733 You_hear("air current noises, and a remark by Amy about how sexy they are.");
8734 else
8735 You_hear("air current noises.");
8737 pushplayer(TRUE);
8738 if (In_sokoban(&u.uz) && !playercancheatinsoko()) {
8739 change_luck(-1);
8740 pline("You cheater!");
8741 if (evilfriday) u.ugangr++;
8744 break;
8746 case SPE_DASHING:
8748 dashingchoice:
8749 if (!getdir((char *)0)) {
8750 if (yn("Do you really want to input no direction?") == 'y')
8751 break;
8752 else {
8753 goto dashingchoice;
8755 break;
8757 if (!u.dx && !u.dy) {
8758 You("stretch.");
8759 break;
8762 spell_dash();
8764 break;
8766 case SPE_MELTDOWN:
8767 You("melt!");
8768 u.uhpmax -= rnd(3);
8769 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
8770 if (u.uhp < 1) {
8771 u.youaredead = 1;
8772 killer = "melting down";
8773 killer_format = KILLED_BY;
8774 done(DIED);
8775 u.youaredead = 0;
8777 if (Upolyd) {
8778 u.mhmax -= rnd(3);
8779 if (u.mh > u.mhmax) u.mh = u.mhmax;
8782 u.uenmax -= rnd(3);
8783 if (u.uen > u.uenmax) u.uen = u.uenmax;
8785 int maderoom = 0;
8786 do_clear_areaX(u.ux, u.uy, 1, undo_barfloodC, (void *)&maderoom);
8787 if (maderoom) {
8788 You("have a sense of freedom.");
8791 break;
8793 case SPE_FLOOD:
8795 int madepoolX = 0;
8796 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_floodg, (void *)&madepoolX);
8797 if (madepoolX) pline("Watery pits appear in the dungeon!");
8798 if (rn2(2)) {
8799 u.uenmax -= rnd(3);
8800 if (u.uenmax < 0) u.uenmax = 0;
8801 if (u.uen > u.uenmax) u.uen = u.uenmax;
8802 pline("Casting this spell is straining for your maximum mana supply.");
8806 break;
8808 case SPE_LAVA:
8810 int madepool = 0;
8811 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_lavafloodg, (void *)&madepool);
8812 if (madepool) pline("Lava pools are created!");
8813 if (rn2(2)) {
8814 u.uenmax -= rnd(3);
8815 if (u.uenmax < 0) u.uenmax = 0;
8816 if (u.uen > u.uenmax) u.uen = u.uenmax;
8817 pline("Casting this spell is straining for your maximum mana supply.");
8822 break;
8824 case SPE_IRON_PRISON:
8826 int madepoolQ = 0;
8827 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_barfloodg, (void *)&madepoolQ);
8828 if (madepoolQ) pline("Iron bars appear from thin air!");
8829 if (rn2(2)) {
8830 u.uenmax -= rnd(4);
8831 if (u.uenmax < 0) u.uenmax = 0;
8832 if (u.uen > u.uenmax) u.uen = u.uenmax;
8833 pline("Casting this spell is straining for your maximum mana supply.");
8838 break;
8840 case SPE_CLOUDS:
8842 int madepoolQ = 0;
8843 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_cloudfloodg, (void *)&madepoolQ);
8844 if (madepoolQ) pline("Clouds everywhere!");
8845 if (!rn2(3)) {
8846 u.uenmax -= 1;
8847 if (u.uenmax < 0) u.uenmax = 0;
8848 if (u.uen > u.uenmax) u.uen = u.uenmax;
8849 pline("Casting this spell is straining for your maximum mana supply.");
8854 break;
8856 case SPE_ICE:
8858 int madepoolQ = 0;
8859 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_icefloodg, (void *)&madepoolQ);
8860 if (madepoolQ) pline("The landscape is winterized!");
8861 if (rn2(2)) {
8862 u.uenmax -= rnd(2);
8863 if (u.uenmax < 0) u.uenmax = 0;
8864 if (u.uen > u.uenmax) u.uen = u.uenmax;
8865 pline("Casting this spell is straining for your maximum mana supply.");
8870 break;
8872 case SPE_LOCKOUT:
8874 int madepoolQ = 0;
8875 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_lockfloodg, (void *)&madepoolQ);
8876 if (madepoolQ) pline("The area is walled off!");
8877 if (rn2(2)) {
8878 u.uenmax -= rnd(5);
8879 if (u.uenmax < 0) u.uenmax = 0;
8880 if (u.uen > u.uenmax) u.uen = u.uenmax;
8881 pline("Casting this spell is straining for your maximum mana supply.");
8886 break;
8888 case SPE_GROW_TREES:
8890 int madepoolQ = 0;
8891 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_treefloodg, (void *)&madepoolQ);
8892 if (madepoolQ) pline("Trees start to grow rapidly!");
8893 if (rn2(2)) {
8894 u.uenmax -= rnd(4);
8895 if (u.uenmax < 0) u.uenmax = 0;
8896 if (u.uen > u.uenmax) u.uen = u.uenmax;
8897 pline("Casting this spell is straining for your maximum mana supply.");
8902 break;
8904 case SPE_GRAVE:
8906 int madepoolQ = 0;
8907 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_gravefloodg, (void *)&madepoolQ);
8908 if (madepoolQ) pline("Hans Walt erects grave walls!");
8909 if (rn2(2)) {
8910 u.uenmax -= rnd(7);
8911 if (u.uenmax < 0) u.uenmax = 0;
8912 if (u.uen > u.uenmax) u.uen = u.uenmax;
8913 pline("Casting this spell is straining for your maximum mana supply.");
8918 break;
8920 case SPE_TUNNELS:
8922 int madepoolQ = 0;
8923 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_tunnelfloodg, (void *)&madepoolQ);
8924 if (madepoolQ) pline("Lots of tunnels are built!");
8925 if (rn2(2)) {
8926 u.uenmax -= rnd(4);
8927 if (u.uenmax < 0) u.uenmax = 0;
8928 if (u.uen > u.uenmax) u.uen = u.uenmax;
8929 pline("Casting this spell is straining for your maximum mana supply.");
8934 break;
8936 case SPE_FARMING:
8938 int madepoolQ = 0;
8939 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_farmfloodg, (void *)&madepoolQ);
8940 if (madepoolQ) pline("Farmland appears.");
8941 if (!rn2(3)) {
8942 u.uenmax -= rnd(3);
8943 if (u.uenmax < 0) u.uenmax = 0;
8944 if (u.uen > u.uenmax) u.uen = u.uenmax;
8945 pline("Casting this spell is straining for your maximum mana supply.");
8950 break;
8952 case SPE_MOUNTAINS:
8954 int madepoolQ = 0;
8955 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_mountainfloodg, (void *)&madepoolQ);
8956 if (madepoolQ) pline("An underground mountain! Wow!");
8957 if (rn2(2)) {
8958 u.uenmax -= rnd(7);
8959 if (u.uenmax < 0) u.uenmax = 0;
8960 if (u.uen > u.uenmax) u.uen = u.uenmax;
8961 pline("Casting this spell is straining for your maximum mana supply.");
8966 break;
8968 case SPE_DIVING:
8970 int madepoolQ = 0;
8971 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_watertunnelfloodg, (void *)&madepoolQ);
8972 if (madepoolQ) pline("Flooded tunnels have been built!");
8973 if (rn2(2)) {
8974 u.uenmax -= rnd(3);
8975 if (u.uenmax < 0) u.uenmax = 0;
8976 if (u.uen > u.uenmax) u.uen = u.uenmax;
8977 pline("Casting this spell is straining for your maximum mana supply.");
8982 break;
8984 case SPE_CRYSTALLIZATION:
8986 int madepoolQ = 0;
8987 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_crystalwaterfloodg, (void *)&madepoolQ);
8988 if (madepoolQ) pline("There's water on the ceiling!");
8989 if (rn2(2)) {
8990 u.uenmax -= rnd(2);
8991 if (u.uenmax < 0) u.uenmax = 0;
8992 if (u.uen > u.uenmax) u.uen = u.uenmax;
8993 pline("Casting this spell is straining for your maximum mana supply.");
8998 break;
9000 case SPE_MOORLAND:
9002 int madepoolQ = 0;
9003 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_moorfloodg, (void *)&madepoolQ);
9004 if (madepoolQ) pline("The floor becomes swampy.");
9005 if (!rn2(4)) {
9006 u.uenmax -= rnd(2);
9007 if (u.uenmax < 0) u.uenmax = 0;
9008 if (u.uen > u.uenmax) u.uen = u.uenmax;
9009 pline("Casting this spell is straining for your maximum mana supply.");
9014 break;
9016 case SPE_URINE:
9018 int madepoolQ = 0;
9019 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_urinefloodg, (void *)&madepoolQ);
9020 if (madepoolQ) pline("Mira does her thing!");
9021 if (!rn2(5)) {
9022 u.uenmax -= rnd(2);
9023 if (u.uenmax < 0) u.uenmax = 0;
9024 if (u.uen > u.uenmax) u.uen = u.uenmax;
9025 pline("Casting this spell is straining for your maximum mana supply.");
9030 break;
9032 case SPE_QUICKSAND:
9034 int madepoolQ = 0;
9035 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_shiftingsandfloodg, (void *)&madepoolQ);
9036 if (madepoolQ) pline("Deadly sandholes appear!");
9037 if (rn2(2)) {
9038 u.uenmax -= rnd(3);
9039 if (u.uenmax < 0) u.uenmax = 0;
9040 if (u.uen > u.uenmax) u.uen = u.uenmax;
9041 pline("Casting this spell is straining for your maximum mana supply.");
9046 break;
9048 case SPE_STYX:
9050 int madepoolQ = 0;
9051 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_styxfloodg, (void *)&madepoolQ);
9052 if (madepoolQ) pline("You're in the styx!");
9053 if (rn2(2)) {
9054 u.uenmax -= rnd(2);
9055 if (u.uenmax < 0) u.uenmax = 0;
9056 if (u.uen > u.uenmax) u.uen = u.uenmax;
9057 pline("Casting this spell is straining for your maximum mana supply.");
9062 break;
9064 case SPE_SNOW:
9066 int madepoolQ = 0;
9067 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_snowfloodg, (void *)&madepoolQ);
9068 if (madepoolQ) pline("Winter is coming!");
9069 if (!rn2(4)) {
9070 u.uenmax -= rnd(2);
9071 if (u.uenmax < 0) u.uenmax = 0;
9072 if (u.uen > u.uenmax) u.uen = u.uenmax;
9073 pline("Casting this spell is straining for your maximum mana supply.");
9078 break;
9080 case SPE_ASH:
9082 int madepoolQ = 0;
9083 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_ashfloodg, (void *)&madepoolQ);
9084 if (madepoolQ) pline("Ash terrain appears!");
9085 if (rn2(2)) {
9086 u.uenmax -= rnd(3);
9087 if (u.uenmax < 0) u.uenmax = 0;
9088 if (u.uen > u.uenmax) u.uen = u.uenmax;
9089 pline("Casting this spell is straining for your maximum mana supply.");
9094 break;
9096 case SPE_SAND:
9098 int madepoolQ = 0;
9099 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_sandfloodg, (void *)&madepoolQ);
9100 if (madepoolQ) pline("Sandy deserts!");
9101 if (rn2(2)) {
9102 u.uenmax -= rnd(2);
9103 if (u.uenmax < 0) u.uenmax = 0;
9104 if (u.uen > u.uenmax) u.uen = u.uenmax;
9105 pline("Casting this spell is straining for your maximum mana supply.");
9110 break;
9112 case SPE_PAVING:
9114 int madepoolQ = 0;
9115 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_pavementfloodg, (void *)&madepoolQ);
9116 if (madepoolQ) pline("Whoa, there's a paved road!");
9117 if (!rn2(5)) {
9118 u.uenmax -= rnd(2);
9119 if (u.uenmax < 0) u.uenmax = 0;
9120 if (u.uen > u.uenmax) u.uen = u.uenmax;
9121 pline("Casting this spell is straining for your maximum mana supply.");
9126 break;
9128 case SPE_HIGHWAY:
9130 int madepoolQ = 0;
9131 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_highwayfloodg, (void *)&madepoolQ);
9132 if (madepoolQ) pline("You build a highway to the left!");
9133 if (rn2(2)) {
9134 u.uenmax -= rnd(6);
9135 if (u.uenmax < 0) u.uenmax = 0;
9136 if (u.uen > u.uenmax) u.uen = u.uenmax;
9137 pline("Casting this spell is straining for your maximum mana supply.");
9142 break;
9144 case SPE_GRASSLAND:
9146 int madepoolQ = 0;
9147 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_grassfloodg, (void *)&madepoolQ);
9148 if (madepoolQ) pline("Grass is growing!");
9149 if (!rn2(4)) {
9150 u.uenmax -= rnd(2);
9151 if (u.uenmax < 0) u.uenmax = 0;
9152 if (u.uen > u.uenmax) u.uen = u.uenmax;
9153 pline("Casting this spell is straining for your maximum mana supply.");
9158 break;
9160 case SPE_NETHER_MIST:
9162 int madepoolQ = 0;
9163 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_nethermistfloodg, (void *)&madepoolQ);
9164 if (madepoolQ) pline("Purple mist appears!");
9165 if (!rn2(4)) {
9166 u.uenmax -= rnd(2);
9167 if (u.uenmax < 0) u.uenmax = 0;
9168 if (u.uen > u.uenmax) u.uen = u.uenmax;
9169 pline("Casting this spell is straining for your maximum mana supply.");
9174 break;
9176 case SPE_STALACTITE:
9178 int madepoolQ = 0;
9179 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_stalactitefloodg, (void *)&madepoolQ);
9180 if (madepoolQ) pline("Stalactites shoot from the ceiling!");
9181 if (!rn2(3)) {
9182 u.uenmax -= rnd(2);
9183 if (u.uenmax < 0) u.uenmax = 0;
9184 if (u.uen > u.uenmax) u.uen = u.uenmax;
9185 pline("Casting this spell is straining for your maximum mana supply.");
9190 break;
9192 case SPE_CRYPT:
9194 int madepoolQ = 0;
9195 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_cryptfloodg, (void *)&madepoolQ);
9196 if (madepoolQ) pline("You entered the crypts!");
9197 if (!rn2(5)) {
9198 u.uenmax -= rnd(2);
9199 if (u.uenmax < 0) u.uenmax = 0;
9200 if (u.uen > u.uenmax) u.uen = u.uenmax;
9201 pline("Casting this spell is straining for your maximum mana supply.");
9206 break;
9208 case SPE_BUBBLE_BOBBLE:
9210 int madepoolQ = 0;
9211 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_bubblefloodg, (void *)&madepoolQ);
9212 if (madepoolQ) pline("Floating bubbles!");
9213 if (rn2(2)) {
9214 u.uenmax -= rnd(2);
9215 if (u.uenmax < 0) u.uenmax = 0;
9216 if (u.uen > u.uenmax) u.uen = u.uenmax;
9217 pline("Casting this spell is straining for your maximum mana supply.");
9222 break;
9224 case SPE_RAIN:
9226 int madepoolQ = 0;
9227 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_raincloudfloodg, (void *)&madepoolQ);
9228 if (madepoolQ) pline("There's rain clouds now!");
9229 if (rn2(2)) {
9230 u.uenmax -= rnd(2);
9231 if (u.uenmax < 0) u.uenmax = 0;
9232 if (u.uen > u.uenmax) u.uen = u.uenmax;
9233 pline("Casting this spell is straining for your maximum mana supply.");
9238 break;
9240 case SPE_CHAOS_TERRAIN:
9243 int madepoolQ = 0;
9244 do_clear_areaX(u.ux, u.uy, 5 + rnd(5), do_terrainfloodg, (void *)&madepoolQ);
9245 if (madepoolQ) pline("Chaotic terrain is generated!");
9246 if (rn2(2)) {
9247 u.uenmax -= rnd(4);
9248 if (u.uenmax < 0) u.uenmax = 0;
9249 if (u.uen > u.uenmax) u.uen = u.uenmax;
9250 pline("Casting this spell is straining for your maximum mana supply.");
9255 break;
9257 case SPE_BOMBING:
9260 int attempts = 0;
9261 register struct permonst *ptrZ;
9263 do {
9264 ptrZ = rndmonst();
9265 attempts++;
9266 if (attempts && (attempts % 10000 == 0)) u.mondiffhack++;
9268 } while ( (!ptrZ || (ptrZ && !(attacktype(ptrZ, AT_EXPL)))) && attempts < 50000);
9270 if (ptrZ && attacktype(ptrZ, AT_EXPL)) {
9272 register struct monst *bomber;
9274 /* note by Amy: I can't, for the life of me, remember that converting a permonst to number is done via monsndx.
9275 * Therefore I'm leaving a note here that I can grep for the next 200 times I forget that permonst monster number
9276 * is done via monsndx! And since I STILL keep forgetting it and NOT find it, I'll leave some more breadcrumbs:
9277 * monster index to number is done via the monsndx function
9278 * monster number is done via that monsndx function */
9279 int monnumber = monsndx(ptrZ);
9281 bomber = make_helper(monnumber, u.ux, u.uy);
9282 if (!bomber) break;
9283 bomber->mtame = 10;
9284 bomber->isspell = bomber->uexp = TRUE;
9288 u.mondiffhack = 0;
9292 break;
9294 case SPE_ANTI_MAGIC_SHELL:
9295 pline("You produce an anti-magic shell.");
9296 u.antimagicshell += rnd(100 + (spell_damage_bonus(spellid(spell)) * 5) );
9297 /* can't cast it with the shell active, so no need to check for that :D --Amy */
9299 break;
9301 case SPE_POSSESSION:
9303 if (CannotSelectItemsInPrompts) break;
9304 register struct obj *poss;
9305 possessionchoice:
9306 poss = getobj((const char *)revivables, "possess");
9307 if (!poss) {
9308 if (yn("Really exit with no object selected?") == 'y')
9309 pline("You just wasted the opportunity to possess a corpse.");
9310 else goto possessionchoice;
9311 pline("Your possession attempt fails.");
9312 break;
9314 if (poss->otyp != CORPSE) {
9315 pline("That cannot be possessed.");
9316 break;
9318 if (obj_resists(poss, 0, 50)) {
9319 pline("Your attempt to possess such a powerful monster fails.");
9320 break;
9322 u.wormpolymorph = poss->corpsenm;
9323 if (!rn2(5)) {
9324 u.wormpolymorph = rn2(NUMMONS);
9325 pline("Your possession attempt goes out of control!");
9327 if (poss) delobj(poss);
9328 polyself(FALSE);
9329 if (!rn2(3)) {
9330 pline("The raw power goes out of control!");
9331 badeffect();
9332 u.uenmax -= rnd(5);
9333 if (u.uen > u.uenmax) u.uen = u.uenmax;
9335 if (!rn2(10)) NastinessProblem += rnd(1000);
9339 break;
9341 case SPE_POLYFORM:
9343 do {
9344 u.wormpolymorph = rn2(NUMMONS);
9345 } while(( (notake(&mons[u.wormpolymorph]) && rn2(4) ) || ((mons[u.wormpolymorph].mlet == S_BAT) && rn2(2)) || ((mons[u.wormpolymorph].mlet == S_EYE) && rn2(2) ) || ((mons[u.wormpolymorph].mmove == 1) && rn2(4) ) || ((mons[u.wormpolymorph].mmove == 2) && rn2(3) ) || ((mons[u.wormpolymorph].mmove == 3) && rn2(2) ) || ((mons[u.wormpolymorph].mmove == 4) && !rn2(3) ) || ( (mons[u.wormpolymorph].mlevel < 10) && ((mons[u.wormpolymorph].mlevel + 1) < rnd(u.ulevel)) ) || (!haseyes(&mons[u.wormpolymorph]) && rn2(2) ) || ( is_nonmoving(&mons[u.wormpolymorph]) && rn2(5) ) || ( is_eel(&mons[u.wormpolymorph]) && rn2(5) ) || ( is_nonmoving(&mons[u.wormpolymorph]) && rn2(20) ) || (is_jonadabmonster(&mons[u.wormpolymorph]) && rn2(20)) || ( uncommon2(&mons[u.wormpolymorph]) && !rn2(4) ) || ( uncommon3(&mons[u.wormpolymorph]) && !rn2(3) ) || ( uncommon5(&mons[u.wormpolymorph]) && !rn2(2) ) || ( uncommon7(&mons[u.wormpolymorph]) && rn2(3) ) || ( uncommon10(&mons[u.wormpolymorph]) && rn2(5) ) || ( is_eel(&mons[u.wormpolymorph]) && rn2(20) ) ) );
9347 pline("You feel polyform.");
9348 polyself(FALSE);
9349 if (!rn2(10)) {
9350 pline("The magical energy goes out of control!");
9351 badeffect();
9352 if (!rn2(3)) {
9353 badeffect();
9354 if (!rn2(3)) {
9355 badeffect();
9356 if (!rn2(3)) {
9357 badeffect();
9358 if (!rn2(3)) {
9359 badeffect();
9365 if (u.mtimedone && !rn2(2) && Upolyd && mons[u.umonnum].mlevel) {
9366 u.mtimedone /= mons[u.umonnum].mlevel;
9367 if (u.mtimedone < 5) u.mtimedone = 5;
9370 break;
9372 case SPE_FIRE_GOLEM:
9374 register struct obj *golemfuel;
9375 register struct monst *firegolem;
9377 golemfuel = carrying(TORCH);
9379 if (!golemfuel) {
9380 pline("You need a torch to create the golem from!");
9381 break;
9384 if (golemfuel->lamplit) { /* we don't want timer-related segfault panics --Amy */
9385 pline("You need a torch that isn't lit! Turn off all lit torches first!");
9386 break;
9389 if (golemfuel) {
9390 if (golemfuel->quan > 1) {
9391 golemfuel->quan--;
9392 golemfuel->owt = weight(golemfuel);
9394 else useup(golemfuel);
9397 firegolem = make_helper(PM_SUMMONED_FIRE_GOLEM, u.ux, u.uy);
9398 if (!firegolem) break;
9399 firegolem->mtame = 5;
9400 firegolem->isspell = firegolem->uexp = TRUE;
9404 break;
9406 case SPE_TOTEM_SUMMONING:
9408 register struct obj *poss;
9409 register struct monst *posmon;
9411 if (!Upolyd && u.uhp < 101) {
9412 pline("Totem summoning requires you to have at least 101 HP.");
9413 break;
9416 if (Upolyd && u.mh < 101) {
9417 pline("Totem summoning requires you to have at least 101 HP.");
9418 break;
9421 totemsummonchoice:
9422 if (CannotSelectItemsInPrompts) break;
9423 poss = getobj((const char *)revivables, "revive");
9424 if (!poss) {
9425 if (yn("Really exit with no object selected?") == 'y')
9426 pline("You just wasted the opportunity to summon from a totem.");
9427 else goto totemsummonchoice;
9428 pline("Your totem summoning attempt fails.");
9429 break;
9431 if (poss->otyp != CORPSE) {
9432 pline("That cannot be revived.");
9433 break;
9435 if (obj_resists(poss, 0, 50)) {
9436 pline("Your attempt to summon such a powerful monster fails.");
9437 break;
9439 posmon = revive(poss);
9441 if (posmon) {
9442 if (Is_blackmarket(&u.uz))
9443 setmangry(posmon);
9444 else
9445 if (posmon->isshk)
9446 make_happy_shk(posmon, FALSE);
9447 else if (!resist(posmon, SPBOOK_CLASS, 0, NOTELL))
9448 (void) tamedog(posmon, (struct obj *) 0, FALSE);
9449 else if (((rnd(30 - ACURR(A_CHA))) < 4) && !resist(posmon, SPBOOK_CLASS, 0, NOTELL))
9450 (void) tamedog(posmon, (struct obj *) 0, FALSE);
9451 else if (((rnd(30 - ACURR(A_CHA))) < 4) && !resist(posmon, SPBOOK_CLASS, 0, NOTELL))
9452 (void) tamedog(posmon, (struct obj *) 0, FALSE);
9454 if (Upolyd) u.mh -= rnd(100);
9455 else u.uhp -= rnd(100);
9457 if (!rn2(3)) {
9458 pline("The summoning power goes out of control!");
9459 badeffect();
9460 create_critters(rnz(10), (struct permonst *)0);
9461 u.uenmax -= rnd(10);
9462 if (u.uen > u.uenmax) u.uen = u.uenmax;
9467 break;
9469 case SPE_STERILIZE:
9471 You_feel("an anti-sexual aura.");
9473 u.sterilized = 10 + (spell_damage_bonus(spellid(spell)) * 4);
9475 break;
9477 case SPE_DISRUPTION_SHIELD:
9479 You("activate your mana shield.");
9481 u.disruptionshield = 30 + (spell_damage_bonus(spellid(spell)) * 7);
9483 break;
9485 case SPE_HOLY_SHIELD:
9487 You("activate your holy shield.");
9489 u.holyshield = 20 + (spell_damage_bonus(spellid(spell)) * 3);
9491 break;
9493 case SPE_AVALANCHE:
9495 register struct trap *avaltrap;
9496 avaltrap = maketrap(u.ux, u.uy, COLLAPSE_TRAP, 0, FALSE);
9497 if (!avaltrap) pline("For some reason, the avalanche does not go off!");
9499 if (avaltrap && avaltrap->ttyp == COLLAPSE_TRAP) {
9500 dotrap(avaltrap, 0);
9502 pline("You are severely hurt and unable to move due to being buried!");
9504 u.uhpmax -= rnd(5);
9505 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
9506 if (u.uhp < 1) {
9507 u.youaredead = 1;
9508 killer = "an avalanche";
9509 killer_format = KILLED_BY;
9510 done(DIED);
9511 u.youaredead = 0;
9513 if (Upolyd) {
9514 u.mhmax -= rnd(5);
9515 if (u.mh > u.mhmax) u.mh = u.mhmax;
9516 if (u.mh < 1) {
9517 u.youaredead = 1;
9518 killer = "an avalanche";
9519 killer_format = KILLED_BY;
9520 done(DIED);
9521 u.youaredead = 0;
9524 u.uenmax -= rnd(5);
9525 if (u.uenmax < 0) u.uenmax = 0;
9526 if (u.uen > u.uenmax) u.uen = u.uenmax;
9528 if (isstunfish) {
9529 if (StrongFree_action) {
9530 nomul(-(rnz(3)), "buried by an avalanche", TRUE);
9531 nomovemsg = "You finally dig yourself out of the debris.";
9532 } else if (Free_action) {
9533 nomul(-(rnz(5)), "buried by an avalanche", TRUE);
9534 nomovemsg = "You finally dig yourself out of the debris.";
9535 } else {
9536 nomul(-(rnz(10)), "buried by an avalanche", TRUE);
9537 nomovemsg = "You finally dig yourself out of the debris.";
9539 } else {
9540 if (StrongFree_action) {
9541 nomul(-(rnd(3)), "buried by an avalanche", TRUE);
9542 nomovemsg = "You finally dig yourself out of the debris.";
9543 } else if (Free_action) {
9544 nomul(-(rnd(5)), "buried by an avalanche", TRUE);
9545 nomovemsg = "You finally dig yourself out of the debris.";
9546 } else {
9547 nomul(-(rnd(10)), "buried by an avalanche", TRUE);
9548 nomovemsg = "You finally dig yourself out of the debris.";
9555 break;
9557 case SPE_DEMEMORIZE:
9559 if (spellid(0) == NO_SPELL) { /* should never happen, but I put it here just in case --Amy */
9560 You("don't know any spells, and therefore you cannot dememorize them either.");
9561 break;
9564 pline("Choose a spell to dememorize.");
9565 dememostart:
9566 if (!dememorizespell()) {
9567 if (yn("Really exit with no spell selected?") == 'y')
9568 pline("You just wasted the opportunity to dememorize a spell.");
9569 else goto dememostart;
9572 break;
9574 case SPE_INERTIA_CONTROL:
9576 if (spellid(0) == NO_SPELL) {
9577 You("don't know any spells, and therefore inertia control fails.");
9578 break;
9581 pline("Choose a spell to control.");
9582 controlagain:
9583 if (!inertiacontrolspell()) {
9584 if (yn("Really exit with no spell selected?") == 'y')
9585 pline("You just wasted the opportunity to control a spell.");
9586 else goto controlagain;
9589 break;
9591 case SPE_SPELLBINDER:
9593 if (u.spellbinder) {
9594 pline("Spellbinder can't be used to bind itself.");
9595 break;
9599 register int spellbindings = 2;
9601 if (!(PlayerCannotUseSkills) && P_SKILL(P_OCCULT_SPELL) >= P_SKILLED) {
9603 switch (P_SKILL(P_OCCULT_SPELL)) {
9604 case P_SKILLED: spellbindings = 3; break;
9605 case P_EXPERT: spellbindings = 4; break;
9606 case P_MASTER: spellbindings = 5; break;
9607 case P_GRAND_MASTER: spellbindings = 6; break;
9608 case P_SUPREME_MASTER: spellbindings = 7; break;
9609 default: break;
9614 u.spellbinder = spellbindings;
9615 u.spellbinder1 = -1;
9616 u.spellbinder2 = -1;
9617 u.spellbinder3 = -1;
9618 u.spellbinder4 = -1;
9619 u.spellbinder5 = -1;
9620 u.spellbinder6 = -1;
9621 u.spellbinder7 = -1;
9623 pline("You may cast %d more spells.", u.spellbinder);
9625 while (u.spellbinder) {
9626 docast();
9627 u.spellbinder--;
9632 break;
9634 case SPE_TRACKER:
9637 register struct monst *nexusmon;
9638 boolean teleportdone = FALSE;
9640 if ((level.flags.noteleport || Race_if(PM_STABILISATOR) || u.antitelespelltimeout) && !Race_if(PM_RODNEYAN) ) {
9641 pline("A mysterious force prevents you from teleporting!");
9642 break;
9645 if ( ( (u.uhave.amulet && !u.freeplaymode && (u.amuletcompletelyimbued || !rn2(3))) || CannotTeleport || On_W_tower_level(&u.uz) || (u.usteed && mon_has_amulet(u.usteed)) ) ) {
9646 You_feel("disoriented for a moment.");
9647 break;
9650 for(nexusmon = fmon; nexusmon; nexusmon = nexusmon->nmon) {
9651 if (nexusmon) break;
9654 if (!nexusmon) {
9655 pline("No valid target for tracking. Sorry.");
9656 break;
9659 int i, j, bd = 1;
9661 for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) {
9662 if (!isok(nexusmon->mx + i, nexusmon->my + j)) continue;
9664 if (teleok(nexusmon->mx + i, nexusmon->my + j, FALSE)) {
9665 teleportdone = TRUE;
9666 teleds(nexusmon->mx + i, nexusmon->my + j, FALSE);
9667 if (!rn2(10)) {
9668 pline("The spell backlashes!");
9669 badeffect();
9671 break;
9674 if (!teleportdone) pline("Tracking target is unreachable. Sorry.");
9678 break;
9680 case SPE_GEOLYSIS:
9682 pline("You sacrifice some of your %s and become able to eat through solid rock.", body_part(BLOOD));
9683 u.uhpmax -= rnd(2);
9684 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
9685 if (u.uhp < 1) {
9686 u.youaredead = 1;
9687 killer = "invoking geolysis with too little health";
9688 killer_format = KILLED_BY;
9689 done(DIED);
9690 u.youaredead = 0;
9692 if (Upolyd) {
9693 u.mhmax -= rnd(2);
9694 if (u.mh > u.mhmax) u.mh = u.mhmax;
9697 /* re-casting it will restart the countdown rather than add to the duration --Amy */
9698 u.geolysis = 15 + (spell_damage_bonus(spellid(spell)) * 5);
9700 break;
9702 case SPE_DRIPPING_TREAD:
9704 pline("You sacrifice some of your %s and start dripping elements.", body_part(BLOOD));
9705 u.uhpmax -= rnd(3);
9706 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
9707 if (u.uhp < 1) {
9708 u.youaredead = 1;
9709 killer = "dripping the elements with too little health";
9710 killer_format = KILLED_BY;
9711 done(DIED);
9712 u.youaredead = 0;
9714 if (Upolyd) {
9715 u.mhmax -= rnd(3);
9716 if (u.mh > u.mhmax) u.mh = u.mhmax;
9718 u.drippingtreadtype = rnd(4);
9719 /* 1 = water, 2 = lava, 3 = ice, 4 = clouds */
9721 if (!(PlayerCannotUseSkills) && P_SKILL(P_ELEMENTAL_SPELL) >= P_SKILLED) {
9722 pline("Choose a terrain type to generate. You can create water, lava, ice or clouds.");
9723 if (yn("Generate water?") == 'y') {
9724 u.drippingtreadtype = 1;
9726 else if (yn("Generate lava?") == 'y') {
9727 u.drippingtreadtype = 2;
9729 else if (yn("Generate ice?") == 'y') {
9730 u.drippingtreadtype = 3;
9732 else {
9733 u.drippingtreadtype = 4;
9738 if (u.drippingtreadtype == 1) pline("Generating water.");
9739 if (u.drippingtreadtype == 2) pline("Generating lava.");
9740 if (u.drippingtreadtype == 3) pline("Generating ice.");
9741 if (u.drippingtreadtype == 4) pline("Generating clouds.");
9743 /* re-casting it will restart the countdown rather than add to the duration --Amy */
9744 u.drippingtread = 20 + (spell_damage_bonus(spellid(spell)) * 3);
9746 break;
9748 case SPE_POISON_BRAND:
9750 if (!uwep) {
9751 pline("You are not holding a weapon!");
9752 break;
9754 if (uwep && !is_poisonable(uwep)) {
9755 pline("Your weapon cannot be poisoned!");
9756 break;
9758 if (uwep) {
9759 if (!stack_too_big(uwep)) {
9760 uwep->opoisoned = TRUE;
9761 pline("Your weapon was poisoned.");
9762 } else pline("Unfortunately your wielded stack of weapons was too big, and so the poisoning failed.");
9764 pline("The poison spills over you!");
9766 if (!rn2(StrongPoison_resistance ? 10 : Poison_resistance ? 5 : 3)) {
9767 int typ = rn2(A_MAX);
9768 poisontell(typ);
9769 (void) adjattrib(typ, Poison_resistance ? -1 : -rno(5), TRUE, TRUE);
9771 if (!Poison_resistance) {
9772 losehp(rnd(10), "poisoning a weapon", KILLED_BY);
9777 break;
9779 case SPE_STEAM_VENOM:
9781 if (Underwater)
9782 pline_The("water around you vaporizes violently!");
9783 else {
9784 pline_The("air around you explodes in a cloud of noxious gas!");
9786 explode(u.ux, u.uy, ZT_SPELL(ZT_POISON_GAS), 24 + (spell_damage_bonus(spellid(spell)) * 2), SCROLL_CLASS, EXPL_NOXIOUS);
9788 break;
9790 case SPE_CREATE_FAMILIAR:
9791 u.lamefarmer = TRUE;
9792 if (!rn2(5)) (void) make_familiar((struct obj *)0, u.ux, u.uy, FALSE, FALSE);
9793 else if (!rn2(2)) {
9794 pline("The summoned monster does not seem to be friendly!");
9795 (void) makemon((struct permonst *)0, u.ux, u.uy, MM_NOSPECIALS);
9796 } else if (rn2(4)) {
9797 pline("The spell fizzled out!");
9798 } else {
9799 pline("The spell backfired!");
9800 badeffect();
9802 u.ublesscnt += 50;
9803 adjalign(-3);
9804 break;
9805 case SPE_CLAIRVOYANCE:
9806 if (!BClairvoyant)
9807 do_vicinity_mapX();
9808 /* at present, only one thing blocks clairvoyance */
9809 else if (uarmh && uarmh->otyp == CORNUTHAUM)
9810 You("sense a pointy hat on top of your %s.",
9811 body_part(HEAD));
9812 break;
9813 case SPE_PROTECTION:
9814 cast_protection();
9815 break;
9817 case SPE_FORCIBLE_MOVE:
9819 if (!jump(-5)) {
9820 pline("%s", nothing_happens);
9821 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9822 pline("Oh wait, actually something bad happens...");
9823 badeffect();
9827 break;
9829 case SPE_JUMPING:
9830 if (!jump(max(role_skill,1))) {
9831 pline("%s", nothing_happens);
9832 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9833 pline("Oh wait, actually something bad happens...");
9834 badeffect();
9837 break;
9839 case SPE_LOOT_IMPROVEMENT:
9840 if(!(HMagicFindBonus & INTRINSIC)) {
9841 You_feel("able to find magical items!");
9842 incr_itimeout(&HMagicFindBonus, HMagicFindBonus ? rnd(5) : (10 + spell_damage_bonus(spellid(spell))) );
9843 } else {
9844 pline("%s", nothing_happens); /* Already have as intrinsic */
9845 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9846 pline("Oh wait, actually something bad happens...");
9847 badeffect();
9850 break;
9852 case SPE_MYSTERY_PROTECTION:
9853 if(!(HMysteryResist & INTRINSIC)) {
9854 You_feel("protected from mysterious magic.");
9855 incr_itimeout(&HMysteryResist, HMysteryResist ? (rnd(3) + spell_damage_bonus(spellid(spell))) : (rn1(33, 15) + spell_damage_bonus(spellid(spell))*3));
9856 } else {
9857 pline("%s", nothing_happens); /* Already have as intrinsic */
9858 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9859 pline("Oh wait, actually something bad happens...");
9860 badeffect();
9863 break;
9865 case SPE_RESIST_POISON:
9866 if(!(HPoison_resistance & INTRINSIC)) {
9867 You_feel("healthy ..... for the moment at least.");
9868 incr_itimeout(&HPoison_resistance, HPoison_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
9869 } else {
9870 pline("%s", nothing_happens); /* Already have as intrinsic */
9871 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9872 pline("Oh wait, actually something bad happens...");
9873 badeffect();
9876 break;
9877 case SPE_ANTI_DISINTEGRATION:
9878 if(!(HDisint_resistance & INTRINSIC)) {
9879 You_feel("quite firm for a while.");
9880 incr_itimeout(&HDisint_resistance, HDisint_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
9881 } else {
9882 pline("%s", nothing_happens); /* Already have as intrinsic */
9883 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9884 pline("Oh wait, actually something bad happens...");
9885 badeffect();
9888 break;
9889 case SPE_MAGICTORCH:
9890 if(!(HSight_bonus & INTRINSIC)) {
9891 You("can see in the dark!");
9892 incr_itimeout(&HSight_bonus, rn1(20, 10) + spell_damage_bonus(spellid(spell))*20);
9893 } else {
9894 pline("%s", nothing_happens); /* Already have as intrinsic */
9895 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9896 pline("Oh wait, actually something bad happens...");
9897 badeffect();
9900 break;
9901 case SPE_DISPLACEMENT:
9902 if(!(HDisplaced & INTRINSIC)) {
9903 pline("Your image is displaced!");
9904 incr_itimeout(&HDisplaced, HDisplaced ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(200, 100) + spell_damage_bonus(spellid(spell))*20));
9905 } else {
9906 pline("%s", nothing_happens); /* Already have as intrinsic */
9907 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9908 pline("Oh wait, actually something bad happens...");
9909 badeffect();
9912 break;
9913 case SPE_TRUE_SIGHT:
9914 if(!(HSee_invisible & INTRINSIC)) {
9915 pline("You can see invisible things!");
9916 incr_itimeout(&HSee_invisible, HSee_invisible ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(50, 25) + spell_damage_bonus(spellid(spell))*5));
9917 } else {
9918 pline("%s", nothing_happens); /* Already have as intrinsic */
9919 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9920 pline("Oh wait, actually something bad happens...");
9921 badeffect();
9924 break;
9925 case SPE_CONFLICT:
9926 if(!(HConflict & INTRINSIC)) {
9927 pline("You start generating conflict!");
9928 incr_itimeout(&HConflict, HConflict ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(20, 10) + spell_damage_bonus(spellid(spell))*3));
9929 } else {
9930 pline("%s", nothing_happens); /* Already have as intrinsic */
9931 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9932 pline("Oh wait, actually something bad happens...");
9933 badeffect();
9936 break;
9937 case SPE_ESP:
9938 if(!(HTelepat & INTRINSIC)) {
9939 You_feel("a strange mental acuity.");
9940 incr_itimeout(&HTelepat, HTelepat ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
9941 } else {
9942 pline("%s", nothing_happens); /* Already have as intrinsic */
9943 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9944 pline("Oh wait, actually something bad happens...");
9945 badeffect();
9948 break;
9949 case SPE_RADAR:
9950 if(!(HWarning & INTRINSIC)) {
9951 pline("You turn on your radar.");
9952 incr_itimeout(&HWarning, HWarning ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
9953 } else {
9954 pline("%s", nothing_happens); /* Already have as intrinsic */
9955 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9956 pline("Oh wait, actually something bad happens...");
9957 badeffect();
9960 break;
9961 case SPE_REGENERATION:
9962 if(!(HRegeneration & INTRINSIC)) {
9963 pline("You direct your internal energy to closing your wounds.");
9964 incr_itimeout(&HRegeneration, HRegeneration ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
9965 } else {
9966 pline("%s", nothing_happens); /* Already have as intrinsic */
9967 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9968 pline("Oh wait, actually something bad happens...");
9969 badeffect();
9972 break;
9973 case SPE_SEARCHING:
9974 if(!(HSearching & INTRINSIC)) {
9975 pline("You start searching.");
9976 incr_itimeout(&HSearching, HSearching ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
9977 } else {
9978 pline("%s", nothing_happens); /* Already have as intrinsic */
9979 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9980 pline("Oh wait, actually something bad happens...");
9981 badeffect();
9984 break;
9985 case SPE_FREE_ACTION:
9986 if(!(HFree_action & INTRINSIC)) {
9987 pline("You are resistant to paralysis.");
9988 incr_itimeout(&HFree_action, HFree_action ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
9989 } else {
9990 pline("%s", nothing_happens); /* Already have as intrinsic */
9991 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
9992 pline("Oh wait, actually something bad happens...");
9993 badeffect();
9996 break;
9997 case SPE_STEALTH:
9998 if(!(HStealth & INTRINSIC)) {
9999 pline("You start moving silently.");
10000 incr_itimeout(&HStealth, HStealth ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10001 } else {
10002 pline("%s", nothing_happens); /* Already have as intrinsic */
10003 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10004 pline("Oh wait, actually something bad happens...");
10005 badeffect();
10008 break;
10009 case SPE_INFRAVISION:
10010 if(!(HInfravision & INTRINSIC)) {
10011 pline("Your %s are suddenly very sensitive!", makeplural(body_part(EYE)));
10012 incr_itimeout(&HInfravision, HInfravision ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10013 } else {
10014 pline("%s", nothing_happens); /* Already have as intrinsic */
10015 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10016 pline("Oh wait, actually something bad happens...");
10017 badeffect();
10020 break;
10021 case SPE_COAGULATION:
10022 if(!(HDiminishedBleeding & INTRINSIC)) {
10023 pline("Your %s is boiling!", body_part(BLOOD));
10024 incr_itimeout(&HDiminishedBleeding, HDiminishedBleeding ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10025 } else {
10026 pline("%s", nothing_happens); /* Already have as intrinsic */
10027 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10028 pline("Oh wait, actually something bad happens...");
10029 badeffect();
10032 break;
10033 case SPE_CURE_PARALYSIS:
10034 if (multi < 0) {
10035 multi = -1;
10036 TimeStopped = 0; /* filthy exploit exploiter */
10037 You("magically regain consciousness!");
10038 } else You("weren't paralyzed to begin with, so there was nothing to cure.");
10039 break;
10040 case SPE_SMELL_MONSTER:
10041 if(!(HScentView & INTRINSIC)) {
10042 pline("Your %s is suddenly very sensitive!", body_part(NOSE));
10043 incr_itimeout(&HScentView, HScentView ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10044 } else {
10045 pline("%s", nothing_happens); /* Already have as intrinsic */
10046 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10047 pline("Oh wait, actually something bad happens...");
10048 badeffect();
10051 break;
10052 case SPE_ECHOLOCATION:
10053 pline("Your ears are suddenly very sensitive!");
10054 if (u.echolocationspell) u.echolocationspell += (rnd(5) + spell_damage_bonus(spellid(spell)));
10055 else u.echolocationspell += (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10);
10056 break;
10057 case SPE_BOTOX_RESIST:
10058 if(!(HSick_resistance & INTRINSIC)) {
10059 You_feel("resistant to sickness.");
10060 incr_itimeout(&HSick_resistance, HSick_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10061 } else {
10062 pline("%s", nothing_happens); /* Already have as intrinsic */
10063 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10064 pline("Oh wait, actually something bad happens...");
10065 badeffect();
10068 break;
10069 case SPE_DRAGON_BLOOD:
10070 if(!(HDrain_resistance & INTRINSIC)) {
10071 You_feel("resistant to level drainage.");
10072 incr_itimeout(&HDrain_resistance, HDrain_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10073 } else {
10074 pline("%s", nothing_happens); /* Already have as intrinsic */
10075 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10076 pline("Oh wait, actually something bad happens...");
10077 badeffect();
10080 break;
10081 case SPE_ANTI_MAGIC_FIELD:
10082 if(!(HAntimagic & INTRINSIC)) {
10083 You_feel("resistant to magic.");
10084 incr_itimeout(&HAntimagic, HAntimagic ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10085 } else {
10086 pline("%s", nothing_happens); /* Already have as intrinsic */
10087 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10088 pline("Oh wait, actually something bad happens...");
10089 badeffect();
10092 break;
10094 case SPE_NO_EFFECT:
10096 pline("%s", nothing_happens);
10097 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10098 pline("Oh wait, actually something bad happens...");
10099 badeffect();
10102 break;
10104 case SPE_CURE_WOUNDED_LEGS:
10106 if (Wounded_legs) pline("A warm glow spreads through your %s!", makeplural(body_part(LEG)));
10108 if (HWounded_legs > 0) {
10109 HWounded_legs -= rn1(20, 20);
10110 if (HWounded_legs < 0) HWounded_legs = 0; /* fail safe */
10113 break;
10115 case SPE_CURE_GLIB:
10117 if (Glib) {
10118 pline("You clean your %s.", makeplural(body_part(HAND)));
10119 if (Glib > (rn1(Role_if(PM_HEALER) ? 200 : 100, 20))) {
10120 int effreduction = rnd(Glib / 2);
10121 if (effreduction > 0) {
10122 Glib -= effreduction;
10123 Your("glib counter is reduced.");
10125 if (!Role_if(PM_HEALER) && !rn2(500)) {
10126 pline("The spell backlashes!");
10127 badeffect();
10129 } else {
10130 Glib = 0;
10134 break;
10136 case SPE_CUTTING:
10138 switch (rnd(7)) {
10140 case 1: pline("You put the knife to your lower %s and cut...", body_part(ARM)); break;
10141 case 2: pline("You use a sharp object to cut open your belly..."); break;
10142 case 3: pline("You slide your body along a rough surface and sustain terrible skin rashes."); break;
10143 case 4: pline("You rip your butt open with a metallic edge."); break;
10144 case 5: pline("You scratch up and down your %s with a sexy leather pump until it starts bleeding.", body_part(LEG)); break;
10145 case 6: pline("You slit your %s full length with a sharp-edged zipper.", body_part(LEG)); break;
10146 case 7: pline("You prick yourself with a needle."); break;
10149 if (!rn2(20)) losehp(d(10,8), "cutting", KILLED_BY);
10150 else if (!rn2(5)) losehp(d(6,8), "cutting", KILLED_BY);
10151 else losehp(d(4,6), "cutting", KILLED_BY);
10153 break;
10155 case SPE_UNLEVITATE:
10157 if (Levitation) pline("You try to unlevitate.");
10158 ELevitation &= ~W_ARTI;
10159 HLevitation &= ~(I_SPECIAL|TIMEOUT);
10161 break;
10163 case SPE_WORLD_FALL:
10165 You("scream \"EYGOORTS-TOGAAL, JEZEHH!\"");
10167 int num;
10168 register struct monst *wfm, *wfm2;
10169 num = 0;
10170 int wflvl = (u.ulevel / 2);
10171 if (wflvl < 1) wflvl = 1;
10173 for (wfm = fmon; wfm; wfm = wfm2) {
10174 wfm2 = wfm->nmon;
10175 if ( ((wfm->m_lev < wflvl) || (!rn2(4) && wfm->m_lev < (2 * wflvl))) && wfm->mnum != quest_info(MS_NEMESIS) && !(wfm->data->geno & G_UNIQ) ) {
10176 mondead(wfm);
10177 num++;
10180 pline("Eliminated %d monster%s.", num, plur(num));
10183 pline("Casting such a powerful spell taxes your maximum health, and also causes massive backlash...");
10185 u.uhpmax -= rnd(25);
10186 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
10187 if (u.uhp < 1) {
10188 u.youaredead = 1;
10189 killer = "invoking world fall with too little health";
10190 killer_format = KILLED_BY;
10191 done(DIED);
10192 u.youaredead = 0;
10194 if (Upolyd) {
10195 u.mhmax -= rnd(25);
10196 if (u.mh > u.mhmax) u.mh = u.mhmax;
10199 badeffect();
10200 badeffect();
10201 badeffect();
10202 badeffect();
10203 badeffect();
10204 badeffect();
10205 badeffect();
10206 NastinessProblem += rnz(1000 * (monster_difficulty() + 1));
10208 break;
10210 case SPE_GENOCIDE:
10212 if (role_skill >= P_SUPREME_MASTER) n = 13;
10213 else if (role_skill >= P_GRAND_MASTER) n = 15;
10214 else if (role_skill >= P_MASTER) n = 16;
10215 else if (role_skill >= P_EXPERT) n = 18;
10216 else if (role_skill >= P_SKILLED) n = 20;
10217 else if (role_skill >= P_BASIC) n = 22;
10218 else n = 25; /* Unskilled or restricted */
10219 if (!rn2(n)) {
10220 do_genocide(1); /* REALLY, see do_genocide() */
10221 } else
10222 Your("genocide failed!");
10223 break;
10225 case SPE_GAIN_LEVEL:
10227 if (role_skill >= P_SUPREME_MASTER) n = 38;
10228 else if (role_skill >= P_GRAND_MASTER) n = 40;
10229 else if (role_skill >= P_MASTER) n = 42;
10230 else if (role_skill >= P_EXPERT) n = 44;
10231 else if (role_skill >= P_SKILLED) n = 46;
10232 else if (role_skill >= P_BASIC) n = 48;
10233 else n = 50; /* Unskilled or restricted */
10234 if (!rn2(n)) {
10235 gainlevelmaybe();
10236 u.usanity += rnz(1000); /* doesn't give bad effects --Amy */
10237 flags.botl = TRUE;
10238 } else
10239 pline("Too bad - it didn't work!");
10240 break;
10242 case SPE_DETECT_WATER:
10244 water_detectX();
10246 break;
10248 case SPE_SATISFY_HUNGER:
10250 pline("Your stomach is filled a bit.");
10251 lesshungry(100);
10253 break;
10255 case SPE_BACKFIRE:
10257 badeffect();
10259 break;
10261 case SPE_MAP_LEVEL:
10263 if (level.flags.nommap) {
10265 pline("Whoops, something blocks the spell's power and causes it to backfire.");
10266 badeffect();
10267 break;
10271 if (role_skill >= P_SUPREME_MASTER) n = 4;
10272 else if (role_skill >= P_GRAND_MASTER) n = 5;
10273 else if (role_skill >= P_MASTER) n = 7;
10274 else if (role_skill >= P_EXPERT) n = 9;
10275 else if (role_skill >= P_SKILLED) n = 11;
10276 else if (role_skill >= P_BASIC) n = 13;
10277 else n = 15; /* Unskilled or restricted */
10278 if (!rn2(n)) {
10279 struct trap *t;
10280 long save_Hconf = HConfusion,
10281 save_Hhallu = HHallucination;
10283 HConfusion = HHallucination = 0L;
10284 for (t = ftrap; t != 0; t = t->ntrap) {
10285 if (!rn2(2)) continue;
10286 /* easier trap difficulty check compared to other detection methods because map level is powerful --Amy */
10287 if (!t->hiddentrap && (t->trapdiff < rnd(150)) ) t->tseen = 1;
10288 map_trap(t, TRUE);
10290 do_mappingY();
10291 HConfusion = save_Hconf;
10292 HHallucination = save_Hhallu;
10293 You_feel("knowledgable!");
10294 object_detect(pseudo, 0);
10296 if (!rn2(3)) {
10297 pline("The spell backlashes!");
10298 badeffect();
10301 } else
10302 pline("The map refuses to reveal its secrets.");
10303 break;
10305 case SPE_GODMODE:
10306 if (rn2(3)) incr_itimeout(&Invulnerable, rnd(5) );
10307 else incr_itimeout(&Invulnerable, rnd(5 + spell_damage_bonus(spellid(spell)) ) );
10308 You_feel("invincible!");
10309 break;
10310 case SPE_ACIDSHIELD:
10311 if(!(HAcid_resistance & INTRINSIC)) {
10312 You("are resistant to acid now. Your items, however, are not.");
10313 incr_itimeout(&HAcid_resistance, HAcid_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10314 } else {
10315 pline("%s", nothing_happens); /* Already have as intrinsic */
10316 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10317 pline("Oh wait, actually something bad happens...");
10318 badeffect();
10321 break;
10322 case SPE_RESIST_PETRIFICATION:
10323 if(!(HStone_resistance & INTRINSIC)) {
10324 You_feel("more limber. Let's eat some cockatrice meat!");
10325 incr_itimeout(&HStone_resistance, HStone_resistance ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(40, 20) + spell_damage_bonus(spellid(spell))*4));
10326 } else {
10327 pline("%s", nothing_happens); /* Already have as intrinsic */
10328 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10329 pline("Oh wait, actually something bad happens...");
10330 badeffect();
10333 break;
10334 case SPE_RESIST_SLEEP:
10335 if(!(HSleep_resistance & INTRINSIC)) {
10336 if (FunnyHallu)
10337 pline("Too much coffee!");
10338 else
10339 You("no longer feel tired.");
10340 incr_itimeout(&HSleep_resistance, HSleep_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10341 } else {
10342 pline("%s", nothing_happens); /* Already have as intrinsic */
10343 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10344 pline("Oh wait, actually something bad happens...");
10345 badeffect();
10348 break;
10349 case SPE_FLYING:
10350 if(!(HFlying & INTRINSIC)) {
10351 You("start flying!");
10352 incr_itimeout(&HFlying, HFlying ? (rnd(4) + spell_damage_bonus(spellid(spell))) : (rn1(20, 25) + spell_damage_bonus(spellid(spell))*20));
10353 } else {
10354 pline("%s", nothing_happens); /* Already have as intrinsic */
10355 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10356 pline("Oh wait, actually something bad happens...");
10357 badeffect();
10360 break;
10361 case SPE_ENDURE_COLD:
10362 if(!(HCold_resistance & INTRINSIC)) {
10363 You_feel("warmer.");
10364 incr_itimeout(&HCold_resistance, HCold_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10365 } else {
10366 pline("%s", nothing_happens); /* Already have as intrinsic */
10367 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10368 pline("Oh wait, actually something bad happens...");
10369 badeffect();
10372 break;
10373 case SPE_RESIST_STUN:
10374 if(!(HStun_resist & INTRINSIC)) {
10375 You_feel("resistant to stun.");
10376 incr_itimeout(&HStun_resist, HStun_resist ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10377 } else {
10378 pline("%s", nothing_happens); /* Already have as intrinsic */
10379 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10380 pline("Oh wait, actually something bad happens...");
10381 badeffect();
10384 break;
10385 case SPE_RESIST_CONFUSION:
10386 if(!(HConf_resist & INTRINSIC)) {
10387 You_feel("resistant to confusion.");
10388 incr_itimeout(&HConf_resist, HConf_resist ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10389 } else {
10390 pline("%s", nothing_happens); /* Already have as intrinsic */
10391 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10392 pline("Oh wait, actually something bad happens...");
10393 badeffect();
10396 break;
10397 case SPE_RESIST_CONTAMINATION:
10398 if(!(HCont_resist & INTRINSIC)) {
10399 You_feel("resistant to contamination.");
10400 incr_itimeout(&HCont_resist, HCont_resist ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10401 } else {
10402 pline("%s", nothing_happens); /* Already have as intrinsic */
10403 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10404 pline("Oh wait, actually something bad happens...");
10405 badeffect();
10408 break;
10409 case SPE_ENDURE_HEAT:
10410 if(!(HFire_resistance & INTRINSIC)) {
10411 if (FunnyHallu)
10412 pline("Excellent! You feel, like, totally cool!");
10413 else
10414 You_feel("colder.");
10415 incr_itimeout(&HFire_resistance, HFire_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10416 } else {
10417 pline("%s", nothing_happens); /* Already have as intrinsic */
10418 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10419 pline("Oh wait, actually something bad happens...");
10420 badeffect();
10423 break;
10424 case SPE_INSULATE:
10425 if(!(HShock_resistance & INTRINSIC)) {
10426 if (FunnyHallu)
10427 pline("Bummer! You've been grounded!");
10428 else
10429 You("are not at all shocked by this feeling.");
10430 incr_itimeout(&HShock_resistance, HShock_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10431 } else {
10432 pline("%s", nothing_happens); /* Already have as intrinsic */
10433 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10434 pline("Oh wait, actually something bad happens...");
10435 badeffect();
10438 break;
10440 case SPE_HOLD_AIR:
10441 if(!(HMagical_breathing & INTRINSIC)) {
10442 You("hold your breath.");
10443 incr_itimeout(&HMagical_breathing, HMagical_breathing ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(40, 20) + spell_damage_bonus(spellid(spell))*10));
10444 } else {
10445 pline("%s", nothing_happens); /* Already have as intrinsic */
10446 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10447 pline("Oh wait, actually something bad happens...");
10448 badeffect();
10451 break;
10453 case SPE_SWIMMING:
10454 if(!(HSwimming & INTRINSIC)) {
10455 You("grow water wings.");
10456 incr_itimeout(&HSwimming, HSwimming ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10457 } else {
10458 pline("%s", nothing_happens); /* Already have as intrinsic */
10459 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10460 pline("Oh wait, actually something bad happens...");
10461 badeffect();
10464 break;
10466 case SPE_RESIST_RANDOM_ELEMENT:
10467 switch (rnd(9)) {
10468 case 1:
10469 if(!(HShock_resistance & INTRINSIC)) {
10470 if (FunnyHallu)
10471 pline("Bummer! You've been grounded!");
10472 else
10473 You("are not at all shocked by this feeling.");
10474 incr_itimeout(&HShock_resistance, HShock_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10475 } else {
10476 pline("%s", nothing_happens); /* Already have as intrinsic */
10477 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10478 pline("Oh wait, actually something bad happens...");
10479 badeffect();
10482 break;
10483 case 2:
10484 if(!(HFire_resistance & INTRINSIC)) {
10485 if (FunnyHallu)
10486 pline("Excellent! You feel, like, totally cool!");
10487 else
10488 You_feel("colder.");
10489 incr_itimeout(&HFire_resistance, HFire_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10490 } else {
10491 pline("%s", nothing_happens); /* Already have as intrinsic */
10492 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10493 pline("Oh wait, actually something bad happens...");
10494 badeffect();
10497 break;
10498 case 3:
10499 if(!(HCold_resistance & INTRINSIC)) {
10500 You_feel("warmer.");
10501 incr_itimeout(&HCold_resistance, HCold_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10502 } else {
10503 pline("%s", nothing_happens); /* Already have as intrinsic */
10504 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10505 pline("Oh wait, actually something bad happens...");
10506 badeffect();
10509 break;
10510 case 4:
10511 if(!(HSleep_resistance & INTRINSIC)) {
10512 if (FunnyHallu)
10513 pline("Too much coffee!");
10514 else
10515 You("no longer feel tired.");
10516 incr_itimeout(&HSleep_resistance, HSleep_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10517 } else {
10518 pline("%s", nothing_happens); /* Already have as intrinsic */
10519 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10520 pline("Oh wait, actually something bad happens...");
10521 badeffect();
10524 break;
10525 case 5:
10526 if(!(HStone_resistance & INTRINSIC)) {
10527 You_feel("more limber. Let's eat some cockatrice meat!");
10528 incr_itimeout(&HStone_resistance, HStone_resistance ? (rnd(5) + spell_damage_bonus(spellid(spell))) : (rn1(40, 20) + spell_damage_bonus(spellid(spell))*4));
10529 } else {
10530 pline("%s", nothing_happens); /* Already have as intrinsic */
10531 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10532 pline("Oh wait, actually something bad happens...");
10533 badeffect();
10536 break;
10537 case 6:
10538 if(!(HAcid_resistance & INTRINSIC)) {
10539 You("are resistant to acid now. Your items, however, are not.");
10540 incr_itimeout(&HAcid_resistance, HAcid_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10541 } else {
10542 pline("%s", nothing_happens); /* Already have as intrinsic */
10543 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10544 pline("Oh wait, actually something bad happens...");
10545 badeffect();
10548 break;
10549 case 7:
10550 if(!(HSick_resistance & INTRINSIC)) {
10551 You_feel("resistant to sickness.");
10552 incr_itimeout(&HSick_resistance, HSick_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10553 } else {
10554 pline("%s", nothing_happens); /* Already have as intrinsic */
10555 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10556 pline("Oh wait, actually something bad happens...");
10557 badeffect();
10560 break;
10561 case 8:
10562 if(!(HPoison_resistance & INTRINSIC)) {
10563 You_feel("healthy ..... for the moment at least.");
10564 incr_itimeout(&HPoison_resistance, HPoison_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10565 } else {
10566 pline("%s", nothing_happens); /* Already have as intrinsic */
10567 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10568 pline("Oh wait, actually something bad happens...");
10569 badeffect();
10572 break;
10573 case 9:
10574 if(!(HDisint_resistance & INTRINSIC)) {
10575 You_feel("quite firm for a while.");
10576 incr_itimeout(&HDisint_resistance, HDisint_resistance ? (rnd(10) + spell_damage_bonus(spellid(spell))) : (rn1(100, 50) + spell_damage_bonus(spellid(spell))*10));
10577 } else {
10578 pline("%s", nothing_happens); /* Already have as intrinsic */
10579 if (FailureEffects || u.uprops[FAILURE_EFFECTS].extrinsic || have_failurestone()) {
10580 pline("Oh wait, actually something bad happens...");
10581 badeffect();
10584 break;
10587 break;
10589 case SPE_FORBIDDEN_KNOWLEDGE:
10590 if(!(HHalf_spell_damage & INTRINSIC)) {
10591 if (FunnyHallu)
10592 pline("Let the casting commence!");
10593 else
10594 You_feel("a sense of spell knowledge.");
10595 incr_itimeout(&HHalf_spell_damage, rn1(500, 250) + spell_damage_bonus(spellid(spell))*50);
10597 if(!(HHalf_physical_damage & INTRINSIC)) {
10598 if (FunnyHallu)
10599 You_feel("like a tough motherfucker!");
10600 else
10601 You("are resistant to normal damage.");
10602 incr_itimeout(&HHalf_physical_damage, rn1(500, 250) + spell_damage_bonus(spellid(spell))*50);
10604 u.ugangr++;
10606 break;
10608 case SPE_ALTER_REALITY:
10610 alter_reality(0);
10612 break;
10614 case SPE_ENLIGHTEN:
10615 You_feel("self-knowledgeable...");
10616 display_nhwindow(WIN_MESSAGE, FALSE);
10617 enlightenment(FALSE, FALSE);
10618 pline("The feeling subsides.");
10619 exercise(A_WIS, TRUE);
10620 break;
10622 /* WAC -- new spells */
10623 case SPE_FLAME_SPHERE:
10624 case SPE_FREEZE_SPHERE:
10625 { register int cnt = 1;
10626 struct monst *mtmp;
10628 u.lamefarmer = TRUE;
10630 if (rn2(3) && role_skill >= P_SKILLED) cnt += rnd(role_skill - P_BASIC);
10631 while(cnt--) {
10632 mtmp = make_helper((pseudo->otyp == SPE_FLAME_SPHERE) ?
10633 PM_SUMMONED_FLAMING_SPHERE : PM_SUMMONED_FREEZING_SPHERE, u.ux, u.uy);
10634 if (!mtmp) continue;
10635 mtmp->mtame = 10;
10636 mtmp->mhpmax = mtmp->mhp = 1;
10637 mtmp->isspell = mtmp->uexp = TRUE;
10638 } /* end while... */
10640 u.lamefarmer = FALSE;
10642 break;
10645 case SPE_SHOCKING_SPHERE:
10646 { register int cnt = 1;
10647 struct monst *mtmp;
10649 u.lamefarmer = TRUE;
10651 if (rn2(3) && role_skill >= P_SKILLED) cnt += rnd(role_skill - P_BASIC);
10652 while(cnt--) {
10653 mtmp = make_helper(PM_SUMMONED_SHOCKING_SPHERE, u.ux, u.uy);
10654 if (!mtmp) continue;
10655 mtmp->mtame = 10;
10656 mtmp->mhpmax = mtmp->mhp = 1;
10657 mtmp->isspell = mtmp->uexp = TRUE;
10658 } /* end while... */
10660 u.lamefarmer = FALSE;
10662 break;
10665 case SPE_ACID_SPHERE:
10666 { register int cnt = 1;
10667 struct monst *mtmp;
10669 u.lamefarmer = TRUE;
10671 if (rn2(3) && role_skill >= P_SKILLED) cnt += rnd(role_skill - P_BASIC);
10672 while(cnt--) {
10673 mtmp = make_helper(PM_SUMMONED_ACID_SPHERE, u.ux, u.uy);
10674 if (!mtmp) continue;
10675 mtmp->mtame = 10;
10676 mtmp->mhpmax = mtmp->mhp = 1;
10677 mtmp->isspell = mtmp->uexp = TRUE;
10678 } /* end while... */
10680 u.lamefarmer = FALSE;
10682 break;
10686 /* KMH -- new spells */
10687 case SPE_PASSWALL:
10688 if (!Passes_walls)
10689 You_feel("ethereal.");
10690 incr_itimeout(&HPasses_walls, rn1(10, 5));
10692 /* way too uber, needs nerf --Amy */
10693 if (!rn2(5)) badeffect();
10695 break;
10697 case SPE_DETECT_FOOT:
10699 pline("Your nose tingles, and you smell feet!");
10700 if (nolimbs(youmonst.data) || slithy(youmonst.data)) {
10701 pline("You aren't sure where the feet might be, though.");
10702 } else {
10703 pline("You see here a %s on the end of your %s.",body_part(FOOT),body_part(LEG));
10704 /* Come on sporkhack devteam, this spell could be useful. Let's see if I can make it do something. --Amy */
10705 pline("Urgh - your head spins from the vile stench!");
10706 make_confused(HConfusion + d(10,10), FALSE);
10707 turn_allmonsters(); /* This even works on Demogorgon. */
10708 badeffect();
10710 break;
10711 case SPE_REFLECTION:
10712 cast_reflection();
10713 break;
10714 case SPE_REPAIR_ARMOR:
10715 /* removes one level of erosion (both types) for a random piece of armor */
10716 if (CannotSelectItemsInPrompts) break;
10717 repairarmorchoice:
10718 otmp = getobj(allnoncount, "magically enchant");
10719 /*otmp = some_armor(&youmonst);*/
10720 if (otmp) {
10721 if (!(otmp->owornmask & W_ARMOR) ) { /* bug discovered by Heliokopis - did Sporkhack never fix this? */
10723 pline("You have a feeling of loss.");
10724 } else if (greatest_erosion(otmp) > 0) {
10725 if (!Blind) {
10726 pline("Your %s glows faintly golden for a moment.",xname(otmp));
10728 if (otmp->oeroded > 0) { otmp->oeroded--; }
10729 if (otmp->oeroded2 > 0) { otmp->oeroded2--; }
10730 if (otmp && objects[(otmp)->otyp].oc_material == MT_CELESTIUM && !stack_too_big(otmp)) {
10731 if (!otmp->cursed) bless(otmp);
10732 else uncurse(otmp, FALSE);
10734 } else {
10735 if (!Blind) {
10736 pline("Your %s glows briefly, but looks as new as ever.",xname(otmp));
10739 } else {
10740 if (yn("Really exit with no object selected?") == 'y')
10741 pline("You just wasted the opportunity to enchant your armor.");
10742 else goto repairarmorchoice;
10743 /* the player can probably feel this, so no need for a !Blind check :) */
10744 pline("Your embarrassing skin rash clears up slightly.");
10746 break;
10748 case SPE_REROLL_ARTIFACT:
10750 if (CannotSelectItemsInPrompts) break;
10751 pline("You may choose an artifact in your inventory to reroll. It may not be a worn one though.");
10752 rerollartifactchoice:
10753 otmp = getobj(allnoncount, "reroll");
10754 if (!otmp) {
10755 if (yn("Really exit with no object selected?") == 'y')
10756 pline("You just wasted the opportunity to reroll an artifact.");
10757 else goto rerollartifactchoice;
10758 pline("You decide not to reroll anything.");
10759 break;
10761 if (!otmp->oartifact) {
10762 pline("That is not an artifact, and can therefore not be rerolled!");
10763 break;
10765 if (otmp->owornmask) {
10766 pline("You cannot reroll an artifact that you're wearing!");
10767 break;
10769 if (!(otmp->oclass == WEAPON_CLASS || otmp->oclass == ARMOR_CLASS || otmp->oclass == RING_CLASS || otmp->oclass == AMULET_CLASS || otmp->oclass == IMPLANT_CLASS)) {
10770 pline("You can only reroll weapons, armors, rings, implants or amulets!");
10771 break;
10774 switch (otmp->oclass) {
10775 case WEAPON_CLASS:
10779 int wpntype; /* 1 = launcher, 2 = ammo, 3 = melee */
10780 if (is_launcher(otmp)) wpntype = 1;
10781 else if (is_ammo(otmp) || is_missile(otmp)) wpntype = 2;
10782 else wpntype = 3;
10783 reroll:
10784 otmp->otyp = rnd_class(ORCISH_DAGGER,HAWAIIAN_SHIRT-1);
10785 if (wpntype == 1 && !is_launcher(otmp)) goto reroll;
10786 if (wpntype == 2 && !is_ammo(otmp) && !is_missile(otmp)) goto reroll;
10787 if (wpntype == 3 && (is_launcher(otmp) || is_ammo(otmp) || is_missile(otmp))) goto reroll;
10790 break;
10791 case ARMOR_CLASS:
10795 int armortype;
10796 /* 1 = shield, 2 = helmet, 3 = boots, 4 = gloves, 5 = cloak, 6 = shirt, 7 = suit */
10797 if (is_shield(otmp)) armortype = 1;
10798 else if (is_helmet(otmp)) armortype = 2;
10799 else if (is_boots(otmp)) armortype = 3;
10800 else if (is_gloves(otmp)) armortype = 4;
10801 else if (is_cloak(otmp)) armortype = 5;
10802 else if (is_shirt(otmp)) armortype = 6;
10803 else armortype = 7;
10804 rerollX:
10805 otmp->otyp = rnd_class(HAWAIIAN_SHIRT,LEVITATION_BOOTS);
10806 if (armortype == 1 && !is_shield(otmp)) goto rerollX;
10807 if (armortype == 2 && !is_helmet(otmp)) goto rerollX;
10808 if (armortype == 3 && !is_boots(otmp)) goto rerollX;
10809 if (armortype == 4 && !is_gloves(otmp)) goto rerollX;
10810 if (armortype == 5 && !is_cloak(otmp)) goto rerollX;
10811 if (armortype == 6 && !is_shirt(otmp)) goto rerollX;
10812 if (armortype == 7 && !is_suit(otmp)) goto rerollX;
10815 break;
10816 case RING_CLASS:
10817 otmp->otyp = rnd_class(RIN_ADORNMENT,RIN_TELEPORT_CONTROL);
10818 break;
10819 case AMULET_CLASS:
10820 otmp->otyp = rnd_class(AMULET_OF_CHANGE,AMULET_OF_VULNERABILITY);
10821 break;
10822 case IMPLANT_CLASS:
10823 otmp->otyp = rnd_class(IMPLANT_OF_ABSORPTION,IMPLANT_OF_VIRTUE);
10824 break;
10826 pline("Your artifact was rerolled to another base item!");
10828 pline("The strain of casting such a powerful spell damages your maximum health and mana.");
10830 u.uhpmax -= rnd(10);
10831 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
10832 if (u.uhp < 1) {
10833 u.youaredead = 1;
10834 killer = "the strain of casting reroll artifact";
10835 killer_format = KILLED_BY;
10836 done(DIED);
10837 u.youaredead = 0;
10839 if (Upolyd) {
10840 u.mhmax -= rnd(10);
10841 if (u.mh > u.mhmax) u.mh = u.mhmax;
10844 u.uenmax -= rnd(10);
10845 if (u.uen > u.uenmax) u.uen = u.uenmax;
10847 break;
10849 case SPE_REPAIR_WEAPON:
10850 /* removes one level of erosion (both types) for your wielded weapon */
10851 if (uwep && stack_too_big(uwep)) {
10852 pline("The repair failed due to the stack being too big.");
10853 break;
10855 if(uwep && (uwep->oclass == WEAPON_CLASS || uwep->oclass == BALL_CLASS || uwep->oclass == GEM_CLASS || uwep->oclass == CHAIN_CLASS || uwep->oclass == VENOM_CLASS || is_weptool(uwep))) {
10856 if (greatest_erosion(uwep) > 0) {
10857 if (!Blind) {
10858 pline("Your %s glows faintly golden for a moment.",xname(uwep));
10860 if (uwep->oeroded > 0) { uwep->oeroded--; }
10861 if (uwep->oeroded2 > 0) { uwep->oeroded2--; }
10862 } else {
10863 if (!Blind) {
10864 pline("Your %s glows briefly, but looks as new as ever.",xname(uwep));
10868 break;
10869 } else {
10870 pline("You don't wield a weapon!");
10873 break;
10875 case SPE_CHARACTER_RECURSION:
10877 if (yn("WARNING!!! This spell will ***PERMANENTLY*** transform your character into another one, and remove ALL of your items and spells. Are you SURE you really want this?") == 'y') {
10879 while (invent) {
10880 register struct obj *otmp, *otmp2;
10881 for (otmp = invent; otmp; otmp = otmp2) {
10882 otmp2 = otmp->nobj;
10884 if (evades_destruction(otmp) ) dropx(otmp);
10885 else {
10886 delete_contents(otmp);
10887 useup(otmp);}
10891 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++) {
10892 spellid(n) = NO_SPELL;
10895 if (Aggravate_monster) {
10896 u.aggravation = 1;
10897 reset_rndmonst(NON_PM);
10900 (void) makemon(mkclass(S_HUMAN,0), u.ux, u.uy, NO_MM_FLAGS);
10901 (void) makemon(mkclass(S_HUMANOID,0), u.ux, u.uy, NO_MM_FLAGS);
10902 (void) makemon(mkclass(S_DEMON,0), u.ux, u.uy, NO_MM_FLAGS);
10903 (void) makemon(mkclass(S_GNOME,0), u.ux, u.uy, NO_MM_FLAGS);
10904 (void) makemon(mkclass(S_OGRE,0), u.ux, u.uy, NO_MM_FLAGS);
10905 (void) makemon(mkclass(S_GIANT,0), u.ux, u.uy, NO_MM_FLAGS);
10906 (void) makemon(mkclass(S_KOP,0), u.ux, u.uy, NO_MM_FLAGS);
10907 (void) makemon(mkclass(S_ORC,0), u.ux, u.uy, NO_MM_FLAGS);
10909 u.aggravation = 0;
10911 (void) safe_teleds_normalterrain(FALSE);
10913 recursioneffect();
10917 break;
10919 default:
10920 /*impossible("Unknown spell %d attempted.", spell);*/
10921 pline("You attempted to cast a spell %d that either doesn't exist in this game, or it has been genocided.", spell);
10922 obfree(pseudo, (struct obj *)0);
10923 return(0);
10926 /* gain skill for successful cast */
10927 use_skill(skill, spellev(spell));
10928 if (rn2(2)) use_skill(skill, spellev(spell)); /* let's make gaining spellcasting skill a little bit easier --Amy */
10929 if (!rn2(50)) use_skill(skill, (spellev(spell) * 10) ); /* jackpot! */
10931 /* WAC successful casting increases solidity of knowledge */
10933 if (!SpellColorCyan && !(pseudo && pseudo->otyp == SPE_ADD_SPELL_MEMORY) ) {
10935 int castboost = Race_if(PM_DUNADAN) ? DUNADAN_CAST_BOOST : CAST_BOOST;
10936 int baseboost = castboost; /* because multiplicative bonuses shouldn't exponentially increase it --Amy */
10937 boolean canboostmore = TRUE;
10939 if (pseudo) {
10940 switch (pseudo->otyp) {
10942 case SPE_ALTER_REALITY:
10943 case SPE_REBOOT:
10944 case SPE_CLONE_MONSTER:
10945 case SPE_THRONE_GAMBLE:
10946 case SPE_GAIN_LEVEL:
10947 case SPE_ATTUNE_MAGIC:
10948 case SPE_REROLL_ARTIFACT:
10949 case SPE_CHARGING:
10950 case SPE_RELOCATION:
10951 case SPE_AULE_SMITHING:
10952 case SPE_REPAIR_WEAPON:
10953 case SPE_REPAIR_ARMOR:
10954 case SPE_PASSWALL:
10955 canboostmore = FALSE; break;
10957 default: break;
10961 if (canboostmore) {
10963 if (irisartiboost()) {
10965 castboost += (baseboost * irisartiboost() / 100);
10969 /* if a spell is down to low memory, then casting it successfully saves it from being immediately forgotten */
10970 if (spellknow(spell) < 5000) {
10971 if (spellknow(spell) < 100) {
10972 castboost += (baseboost * 75 / 100);
10973 } else if (spellknow(spell) < 1000) {
10974 castboost += (baseboost * 50 / 100);
10975 } else if (spellknow(spell) < 2000) {
10976 castboost += (baseboost * 40 / 100);
10977 } else if (spellknow(spell) < 3000) {
10978 castboost += (baseboost * 30 / 100);
10979 } else if (spellknow(spell) < 4000) {
10980 castboost += (baseboost * 20 / 100);
10981 } else if (spellknow(spell) < 5000) {
10982 castboost += (baseboost * 10 / 100);
10986 if (Spellboost) castboost += (baseboost * 10 / 100);
10987 if (StrongSpellboost) castboost += (baseboost * 10 / 100);
10988 if (tech_inuse(T_SPELL_SPAM)) castboost += (baseboost * 10 / 100);
10990 if (!PlayerCannotUseSkills) {
10992 switch (P_SKILL(P_MEMORIZATION)) {
10993 case P_BASIC: castboost += (baseboost * 5 / 100); break;
10994 case P_SKILLED: castboost += (baseboost * 10 / 100); break;
10995 case P_EXPERT: castboost += (baseboost * 15 / 100); break;
10996 case P_MASTER: castboost += (baseboost * 20 / 100); break;
10997 case P_GRAND_MASTER: castboost += (baseboost * 25 / 100); break;
10998 case P_SUPREME_MASTER: castboost += (baseboost * 30 / 100); break;
11002 if (spellev(spell) >= 2 && !rn2(2)) {
11003 castboost += (baseboost * 10 / 100);
11005 if (spellev(spell) >= 3 && !rn2(2)) {
11006 castboost += (baseboost * 9 / 100);
11008 if (spellev(spell) >= 4 && !rn2(2)) {
11009 castboost += (baseboost * 8 / 100);
11011 if (spellev(spell) >= 5 && !rn2(2)) {
11012 castboost += (baseboost * 7 / 100);
11014 if (spellev(spell) >= 6 && !rn2(2)) {
11015 castboost += (baseboost * 6 / 100);
11017 if (spellev(spell) >= 7 && !rn2(2)) {
11018 castboost += (baseboost * 5 / 100);
11020 if (spellev(spell) >= 8 && !rn2(2)) {
11021 castboost += (baseboost * 4 / 100);
11025 boostknow(spell, castboost);
11026 if (((rnd(spellev(spell) + 5)) > 5) && canboostmore) boostknow(spell, castboost); /* higher-level spells boost more --Amy */
11027 if (!rn2(52 - (spellev(spell) * 2) ) && canboostmore && !Race_if(PM_DUNADAN) ) { /* jackpot! */
11028 boostknow(spell, (castboost * 5) );
11029 boostknow(spell, (castboost * spellev(spell) ) );
11032 if (Role_if(PM_MAHOU_SHOUJO)) boostknow(spell, castboost);
11033 if (Role_if(PM_PSYKER)) boostknow(spell, castboost);
11037 if (!(iflags.memorizationknown) && !(spl_book[spell].sp_memorize)) {
11038 if (yn("You just cast a dememorized spell! If this means that you want to continue using that spell later, you might want to set it back to memorization mode so that its spell memory lasts longer. Press y now to set the spell back to memorization mode, or n to keep it dememorized.") == 'y') {
11039 spl_book[spell].sp_memorize = TRUE;
11040 pline("Spell memorization was activated!");
11044 if (SpellColorCyan) {
11045 boolean cyanwillgodown = TRUE;
11047 /* keep this synchronized with age_spells(), please --Amy */
11049 if (Keen_memory && !rn2(StrongKeen_memory ? 3 : 5)) cyanwillgodown = FALSE;
11050 if (uarm && uarm->oartifact == ART_COPE_OF_THE_ELDRITCH_KNIGH && rn2(2)) cyanwillgodown = FALSE;
11051 if (uarmc && itemhasappearance(uarmc, APP_GUILD_CLOAK) ) cyanwillgodown = FALSE;
11052 if (tech_inuse(T_SPELL_SPAM)) cyanwillgodown = FALSE;
11053 if (uarms && uarms->oartifact == ART_UNUSUAL_ENCH && !rn2(5)) cyanwillgodown = FALSE;
11054 if (rnd(urole.spelrete + 100) > 100) cyanwillgodown = FALSE;
11056 if (!rn2(2) && spellmemorize(spell)) cyanwillgodown = FALSE;
11058 if (spellmemorize(spell) && ACURR(A_INT) > 14) {
11059 int intelsave = ACURR(A_INT) - 14;
11060 if (intelsave > rn2(66)) cyanwillgodown = FALSE;
11063 if (!PlayerCannotUseSkills && spellmemorize(spell) && P_SKILL(P_MEMORIZATION) >= P_BASIC) {
11065 int savememochance = 0;
11067 switch (P_SKILL(P_MEMORIZATION)) {
11068 case P_BASIC: savememochance = 1; break;
11069 case P_SKILLED: savememochance = 2; break;
11070 case P_EXPERT: savememochance = 3; break;
11071 case P_MASTER: savememochance = 4; break;
11072 case P_GRAND_MASTER: savememochance = 5; break;
11073 case P_SUPREME_MASTER: savememochance = 6; break;
11076 if (savememochance > rn2(10)) cyanwillgodown = FALSE;
11080 if (!PlayerCannotUseSkills && spellmemorize(spell) && P_SKILL(spell_skilltype(spellid(spell))) >= P_BASIC) {
11082 int savememochance = 0;
11084 switch (P_SKILL(spell_skilltype(spellid(spell)))) {
11085 case P_BASIC: savememochance = 1; break;
11086 case P_SKILLED: savememochance = 2; break;
11087 case P_EXPERT: savememochance = 3; break;
11088 case P_MASTER: savememochance = 4; break;
11089 case P_GRAND_MASTER: savememochance = 5; break;
11090 case P_SUPREME_MASTER: savememochance = 6; break;
11093 if (savememochance > rn2(20)) cyanwillgodown = FALSE;
11097 if (cyanwillgodown) {
11098 drainknow(spell, rnd(100));
11099 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11103 if (pseudo && pseudo->otyp == SPE_REBOOT && !rn2(10) ) {
11105 drainknow(spell, (rnd(20000)));
11106 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11110 if (pseudo && ((pseudo->otyp == SPE_ALTER_REALITY) || (pseudo->otyp == SPE_CLONE_MONSTER) ) ) {
11112 drainknow(spell, (rnd(20000)));
11113 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11117 if (pseudo && (pseudo->otyp == SPE_THRONE_GAMBLE) && !rn2(6) ) {
11119 drainknow(spell, (rnd(100000)));
11120 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11124 if (pseudo && (pseudo->otyp == SPE_GAIN_LEVEL) && !rn2(200) ) {
11126 drainknow(spell, (rnd(50000)));
11127 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11131 if (pseudo && (pseudo->otyp == SPE_ATTUNE_MAGIC) && !rn2(6) ) {
11133 drainknow(spell, (rnd(100000)));
11134 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11138 if (pseudo && (pseudo->otyp == SPE_REROLL_ARTIFACT) && !rn2(5) ) {
11140 drainknow(spell, (rnd(100000)));
11141 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11145 if (pseudo && (pseudo->otyp == SPE_CHARGING) && !rn2(role_skill == P_SUPREME_MASTER ? 9 : role_skill == P_GRAND_MASTER ? 8 : role_skill == P_MASTER ? 7 : role_skill == P_EXPERT ? 6 : role_skill == P_SKILLED ? 5 : 4) ) {
11147 drainknow(spell, (rnd(100000)));
11148 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11152 if (pseudo && (pseudo->otyp == SPE_RELOCATION) && !rn2(role_skill == P_SUPREME_MASTER ? 9 : role_skill == P_GRAND_MASTER ? 8 : role_skill == P_MASTER ? 7 : role_skill == P_EXPERT ? 6 : role_skill == P_SKILLED ? 5 : 4) ) {
11154 drainknow(spell, (rnd(10000)));
11155 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11159 if (pseudo && pseudo->otyp == SPE_ADD_SPELL_MEMORY) {
11161 drainknow(spell, 500);
11162 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11166 if (pseudo && (pseudo->otyp == SPE_AULE_SMITHING) && !rn2(role_skill == P_SUPREME_MASTER ? 9 : role_skill == P_GRAND_MASTER ? 8 : role_skill == P_MASTER ? 7 : role_skill == P_EXPERT ? 6 : role_skill == P_SKILLED ? 5 : 4) ) {
11168 drainknow(spell, (rnd(100000)));
11169 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11173 if (pseudo && ((pseudo->otyp == SPE_REPAIR_WEAPON) || (pseudo->otyp == SPE_REPAIR_ARMOR)) && !rn2(role_skill == P_SUPREME_MASTER ? 15 : role_skill == P_GRAND_MASTER ? 14 : role_skill == P_MASTER ? 13 : role_skill == P_EXPERT ? 12 : role_skill == P_SKILLED ? 11 : 10) ) {
11175 drainknow(spell, (rnd(25000)));
11176 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11180 if (pseudo && (pseudo->otyp == SPE_PASSWALL) && !rn2(role_skill == P_SUPREME_MASTER ? 30 : role_skill == P_GRAND_MASTER ? 25 : role_skill == P_MASTER ? 24 : role_skill == P_EXPERT ? 23 : role_skill == P_SKILLED ? 22 : 20) ) {
11182 drainknow(spell, (rnd(10000)));
11183 if (spellknow(spell) < 0) spl_book[spell].sp_know = 0;
11187 if ((spell_skilltype(spellid(spell)) == P_OCCULT_SPELL) && !(uarmg && uarmg->oartifact == ART_FATHIEN_ELDER_S_SECRET_POW) ) { /* dangerous realm... */
11188 if (PlayerCannotUseSkills) {
11189 if (!rn2(5)) badeffect();
11190 } else switch (role_skill) {
11191 default:
11192 case P_ISRESTRICTED:
11193 case P_UNSKILLED:
11194 if (!rn2(Role_if(PM_OCCULT_MASTER) ? 12 : 5)) {
11195 pline("You fail to control the occult powers and are hit with backlash!");
11196 badeffect();
11198 break;
11199 case P_BASIC:
11200 if (!rn2(Role_if(PM_OCCULT_MASTER) ? 14 : 6)) {
11201 pline("You fail to control the occult powers and are hit with backlash!");
11202 badeffect();
11204 break;
11205 case P_SKILLED:
11206 if (!rn2(Role_if(PM_OCCULT_MASTER) ? 16 : 7)) {
11207 pline("You fail to control the occult powers and are hit with backlash!");
11208 badeffect();
11210 break;
11211 case P_EXPERT:
11212 if (!rn2(Role_if(PM_OCCULT_MASTER) ? 20 : 8)) {
11213 pline("You fail to control the occult powers and are hit with backlash!");
11214 badeffect();
11216 break;
11217 case P_MASTER:
11218 if (!rn2(Role_if(PM_OCCULT_MASTER) ? 22 : 9)) {
11219 pline("You fail to control the occult powers and are hit with backlash!");
11220 badeffect();
11222 break;
11223 case P_GRAND_MASTER:
11224 if (!rn2(Role_if(PM_OCCULT_MASTER) ? 25 : 10)) {
11225 pline("You fail to control the occult powers and are hit with backlash!");
11226 badeffect();
11228 break;
11229 case P_SUPREME_MASTER:
11230 if (!rn2(Role_if(PM_OCCULT_MASTER) ? 30 : 11)) {
11231 pline("You fail to control the occult powers and are hit with backlash!");
11232 badeffect();
11234 break;
11238 /* charging is way too overpowered, let's add another "bullshit downside" --Amy */
11239 if (pseudo && (pseudo->otyp == SPE_CHARGING) && !rn2(role_skill == P_SUPREME_MASTER ? 16 : role_skill == P_GRAND_MASTER ? 15 : role_skill == P_MASTER ? 13 : role_skill == P_EXPERT ? 12 : role_skill == P_SKILLED ? 11 : 10) ) {
11241 badeffect();
11245 /* particle cannon and one point shoot need "gauge"; since this isn't Elona, we don't have an actual gauge meter,
11246 * so I decided that it just takes 50 turns to reload --Amy */
11247 if (pseudo && (pseudo->otyp == SPE_PARTICLE_CANNON)) {
11248 pline("The particle cannon can be used again at turn %ld.", (moves + u.gaugetimer));
11250 if (pseudo && (pseudo->otyp == SPE_CONVERGE_BREATH)) {
11251 pline("Converge Breath can be used again at turn %ld.", (moves + u.gaugetimer));
11253 if (pseudo && (pseudo->otyp == SPE_IMPACT_GUNFIRE)) {
11254 pline("Impact Gunfire can be used again at turn %ld.", (moves + u.gaugetimer));
11256 if (pseudo && (pseudo->otyp == SPE_ONE_POINT_SHOOT)) {
11257 pline("One Point Shoot can be used again at turn %ld.", (moves + u.gaugetimer));
11259 if (pseudo && (pseudo->otyp == SPE_BATTERING_RAM)) {
11260 pline("Battering Ram can be used again at turn %ld.", (moves + u.battertimer));
11262 if (pseudo && (pseudo->otyp == SPE_BUBBLING_HOLE)) {
11263 nomul(-2, "recovering from the bubbling hole", TRUE);
11266 obfree(pseudo, (struct obj *)0); /* now, get rid of it */
11267 return(1);
11270 /* #spelldelete command: allows the player to erase the bottommost spell outright, but only if it's a forgotten one */
11272 dodeletespell()
11274 int n;
11275 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
11276 continue;
11277 if (n) {
11279 n--; /* fix off-by-one error */
11280 if (spellid(n) == NO_SPELL) {
11281 impossible("ERROR: dodeletespell() trying to erase empty spell?");
11282 return 0;
11285 if (spellknow(n) > 0) {
11286 pline("This doesn't work as long as your bottommost spell still has memory left.");
11287 } else {
11288 pline("Your bottommost spell is %s, which has no memory left.", spellname(n));
11289 if (yn("Erase it from the list?") == 'y') {
11290 spellid(n) = NO_SPELL;
11291 /* no need to nullify spell memory because it's already zero */
11292 pline("Done! The spell has been removed from your list.");
11295 } else pline("It seems that you have no known spells in the first place.");
11297 /* shouldn't cost a turn, regardless of result */
11298 return 0;
11301 void
11302 losespells()
11304 boolean confused = (Confusion != 0);
11305 int n, nzap, i;
11306 int thisone, thisonetwo, choicenumber;
11308 if (Keen_memory && rn2(StrongKeen_memory ? 20 : 4)) return;
11309 if (Role_if(PM_MASTERMIND) && mastermindsave()) return;
11311 /* have no spells? well then... magic vacuum :P --Amy */
11312 if (spellid(0) == NO_SPELL) {
11313 make_magicvacuum((HMagicVacuum & TIMEOUT) + rnd(10) + rnd(monster_difficulty() * 100) );
11316 /* reduce memory of one known spell that still has memory left --Amy */
11317 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
11318 continue;
11319 if (n) {
11320 thisone = -1;
11321 choicenumber = 0;
11322 for (n = 0; ((n < MAXSPELL) && spellid(n) != NO_SPELL); n++) {
11323 if ((!choicenumber || (!rn2(choicenumber + 1)) ) && (spellknow(n) > 0)) {
11324 thisone = n;
11326 if (spellknow(n) > 0) choicenumber++;
11329 if (choicenumber > 0 && thisone >= 0 && (spellknow(thisone) > 0)) {
11330 if (rn2(10)) {
11331 spellknow(thisone) = rn2(spellknow(thisone));
11332 } else {
11333 spellknow(thisone) = 0;
11338 /* maybe also reduce spell memory a bit more, to make the amnesia effect matter --Amy */
11339 if (!rn2(5)) spellmemoryloss(level_difficulty() + 1);
11341 book = 0;
11342 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
11343 continue;
11344 if (n) {
11345 nzap = rn2(isfriday ? 20 : 50) ? 1 : (rnd(n) + confused);
11347 if (n > urole.spelrete) {
11348 int retention = urole.spelrete;
11349 if (retention < 1) {
11350 impossible("player's spell retention isn't positive??");
11351 retention = 1;
11353 int highamount = n;
11354 while (highamount > retention) {
11355 nzap++;
11356 highamount -= rnd(retention);
11360 if (nzap > n) nzap = n;
11361 for (i = n - nzap; i < n; i++) {
11362 spellid(i) = NO_SPELL;
11363 exercise(A_WIS, FALSE); /* ouch! */
11367 /* now if you have too many forgotten spells, remove them --Amy */
11368 removeagain:
11369 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
11370 continue;
11371 if (n > 4) {
11372 thisone = -1;
11373 thisonetwo = -1;
11374 choicenumber = 0;
11375 for (n = 0; ((n < MAXSPELL) && spellid(n) != NO_SPELL); n++) {
11376 if (spellknow(n) <= 0) {
11377 thisone = n;
11378 choicenumber++;
11382 if (choicenumber > 5 && thisone >= 0 && spellknow(thisone) <= 0) {
11384 spellknow(thisone) = 0; /* make sure the spell memory is deleted! */
11385 spellid(thisone) = NO_SPELL;
11387 for (n = thisone; n < MAXSPELL; n++) {
11388 if (spellid(n) != NO_SPELL) thisonetwo = n;
11390 if (thisonetwo >= 0 && spellid(thisonetwo) != NO_SPELL) { /* move last known spell to the one we've erased */
11391 spellknow(thisone) = spellknow(thisonetwo);
11392 spellid(thisone) = spellid(thisonetwo);
11393 spellev(thisone) = spellev(thisonetwo);
11394 spellname(thisone) = spellname(thisonetwo);
11396 spellknow(thisonetwo) = 0; /* make sure the spell memory is deleted! */
11397 spellid(thisonetwo) = NO_SPELL;
11401 if (choicenumber > 6) goto removeagain;
11408 /* for bad effects: spell zonking similar to the amnesia effect */
11409 void
11410 evilspellforget()
11412 int n;
11413 int thisone, thisonetwo, choicenumber;
11415 /* reduce memory of one known spell that still has memory left --Amy */
11416 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
11417 continue;
11418 if (n) {
11419 thisone = -1;
11420 choicenumber = 0;
11421 for (n = 0; ((n < MAXSPELL) && spellid(n) != NO_SPELL); n++) {
11422 if ((!choicenumber || (!rn2(choicenumber + 1)) ) && (spellknow(n) > 0)) {
11423 thisone = n;
11425 if (spellknow(n) > 0) choicenumber++;
11428 if (choicenumber > 0 && thisone >= 0 && (spellknow(thisone) > 0)) {
11429 if (rn2(10)) {
11430 spellknow(thisone) = rn2(spellknow(thisone));
11431 pline("You forget a lot of %s spell knowledge!", spellname(thisone));
11432 } else {
11433 spellknow(thisone) = 0;
11434 pline("You forget all usage of the %s spell!", spellname(thisone));
11439 /* now if you have too many forgotten spells, remove them --Amy */
11440 removeagain:
11441 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
11442 continue;
11443 if (n > 4) {
11444 thisone = -1;
11445 thisonetwo = -1;
11446 choicenumber = 0;
11447 for (n = 0; ((n < MAXSPELL) && spellid(n) != NO_SPELL); n++) {
11448 if (spellknow(n) <= 0) {
11449 thisone = n;
11450 choicenumber++;
11454 if (choicenumber > 5 && thisone >= 0 && spellknow(thisone) <= 0) {
11456 spellknow(thisone) = 0; /* make sure the spell memory is deleted! */
11457 spellid(thisone) = NO_SPELL;
11459 for (n = thisone; n < MAXSPELL; n++) {
11460 if (spellid(n) != NO_SPELL) thisonetwo = n;
11462 if (thisonetwo >= 0 && spellid(thisonetwo) != NO_SPELL) { /* move last known spell to the one we've erased */
11463 spellknow(thisone) = spellknow(thisonetwo);
11464 spellid(thisone) = spellid(thisonetwo);
11465 spellev(thisone) = spellev(thisonetwo);
11466 spellname(thisone) = spellname(thisonetwo);
11468 spellknow(thisonetwo) = 0; /* make sure the spell memory is deleted! */
11469 spellid(thisonetwo) = NO_SPELL;
11473 if (choicenumber > 6) goto removeagain;
11479 /* having too many forgotten spells just clogs up the interface, so we'll occasionally remove one --Amy */
11480 void
11481 removeforgottenspell()
11483 int n, thisone, thisonetwo, choicenumber;
11485 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
11486 continue;
11487 if (n > 4) {
11488 thisone = -1;
11489 thisonetwo = -1;
11490 choicenumber = 0;
11491 for (n = 0; ((n < MAXSPELL) && spellid(n) != NO_SPELL); n++) {
11492 if (spellknow(n) <= 0) {
11493 thisone = n;
11494 choicenumber++;
11498 if (choicenumber > 5 && thisone >= 0 && spellknow(thisone) <= 0) {
11500 pline("You completely forgot the %s spell.", spellname(thisone));
11501 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
11502 spellknow(thisone) = 0; /* make sure the spell memory is deleted! */
11503 spellid(thisone) = NO_SPELL;
11505 for (n = thisone; n < MAXSPELL; n++) {
11506 if (spellid(n) != NO_SPELL) thisonetwo = n;
11508 if (thisonetwo >= 0 && spellid(thisonetwo) != NO_SPELL) { /* move last known spell to the one we've erased */
11509 spellknow(thisone) = spellknow(thisonetwo);
11510 spellid(thisone) = spellid(thisonetwo);
11511 spellev(thisone) = spellev(thisonetwo);
11512 spellname(thisone) = spellname(thisonetwo);
11514 spellknow(thisonetwo) = 0; /* make sure the spell memory is deleted! */
11515 spellid(thisonetwo) = NO_SPELL;
11524 void
11525 spellmemoryloss(lossamount)
11526 int lossamount;
11528 int n, thisone, choicenumber, spell, nzap;
11530 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
11531 continue;
11532 if (n) {
11533 thisone = -1;
11534 choicenumber = 0;
11535 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++) {
11536 if ((spellknow(n) > 0) && (!choicenumber || (!rn2(choicenumber + 1))) ) {
11537 thisone = n;
11539 if (spellknow(n) > 0) choicenumber++;
11542 /* sometimes we're mean and reduce it by more, depending on how many spells you have... --Amy */
11543 if (!rn2(3) && choicenumber > 1) {
11544 lossamount *= (50 + rno(choicenumber));
11545 lossamount /= 50;
11547 lossamount *= rnd(5);
11549 if (choicenumber > 0 && thisone >= 0) {
11550 drainknow(thisone, (lossamount * 100));
11551 if (spellknow(thisone) < 0) {
11552 spl_book[thisone].sp_know = 0;
11553 pline("You lose all knowledge of the %s spell!", spellname(thisone));
11555 else pline("Your knowledge of the %s spell is reduced!", spellname(thisone));
11560 book = 0;
11561 nzap = 0;
11562 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
11563 continue;
11565 if (n > urole.spelrete) {
11566 int retention = urole.spelrete;
11567 if (retention < 1) {
11568 impossible("player's spell retention isn't positive??");
11569 retention = 1;
11571 int highamount = n;
11572 while (highamount > retention) {
11573 nzap++;
11574 highamount -= rnd(retention);
11578 if (n && nzap > 0) pline("Some of your spells got erased!");
11580 morezapping:
11582 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
11583 continue;
11585 if (n >= 0 && spellid(n) == NO_SPELL) n--;
11587 if (nzap > n) nzap = n;
11588 if (n && nzap > 0) {
11590 while (nzap > 0) {
11592 if (spellknow(n) > 0) drainknow(n, 10000);
11593 if (spellknow(n) < 0) spellknow(n) = 0;
11595 if (spellknow(n) <= 0) {
11596 spl_book[n].sp_know = 0;
11597 spellid(n) = NO_SPELL;
11598 exercise(A_WIS, FALSE); /* ouch! */
11599 nzap--;
11600 n--;
11601 goto morezapping;
11603 nzap--;
11609 /* halve memory of a randomly selected spell with nonzero memory --Amy */
11610 void
11611 spellmemoryhalve()
11613 int n, thisone, choicenumber, spell, nzap;
11615 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
11616 continue;
11617 if (n) {
11618 thisone = -1;
11619 choicenumber = 0;
11620 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++) {
11621 if ((spellknow(n) > 0) && (!choicenumber || (!rn2(choicenumber + 1))) ) {
11622 thisone = n;
11624 if (spellknow(n) > 0) choicenumber++;
11627 if (choicenumber > 0 && thisone >= 0) {
11628 spl_book[thisone].sp_know /= 2;
11629 if (spellknow(thisone) < 0) {
11630 spl_book[thisone].sp_know = 0;
11631 pline("You lose all knowledge of the %s spell!", spellname(thisone));
11633 else pline("Your knowledge of the %s spell is cut in half!", spellname(thisone));
11640 /* the '+' command -- view known spells */
11642 dovspell()
11644 char qbuf[QBUFSZ];
11645 int splnum, othnum;
11646 struct spell spl_tmp;
11648 if (MenuIsBugged) {
11649 pline("The spell menu command is currently unavailable!");
11650 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
11651 return 0;
11654 int dememonum = 0;
11655 int i;
11657 char spellcolorbuf[BUFSZ];
11659 if (SpellColorPink) sprintf(spellcolorbuf, "Your spells are pink.");
11660 else if (SpellColorBrightCyan) sprintf(spellcolorbuf, "Your spells are bright cyan.");
11661 else if (SpellColorCyan) sprintf(spellcolorbuf, "Your spells are cyan.");
11662 else if (SpellColorBlack) sprintf(spellcolorbuf, "Your spells are black.");
11663 else if (SpellColorOrange) sprintf(spellcolorbuf, "Your spells are orange.");
11664 else if (SpellColorRed) sprintf(spellcolorbuf, "Your spells are red.");
11665 else if (SpellColorPlatinum) sprintf(spellcolorbuf, "Your spells are platinum.");
11666 else if (SpellColorSilver) sprintf(spellcolorbuf, "Your spells are silver.");
11667 else if (SpellColorMetal) sprintf(spellcolorbuf, "Your spells are metal.");
11668 else if (SpellColorGreen) sprintf(spellcolorbuf, "Your spells are green.");
11669 else if (SpellColorBlue) sprintf(spellcolorbuf, "Your spells are blue.");
11670 else if (SpellColorGray) sprintf(spellcolorbuf, "Your spells are completely gray.");
11671 else if (SpellColorBrown) sprintf(spellcolorbuf, "Your spells are brown.");
11672 else if (SpellColorWhite) sprintf(spellcolorbuf, "Your spells are white.");
11673 else if (SpellColorViolet) sprintf(spellcolorbuf, "Your spells are violet.");
11674 else if (SpellColorYellow) sprintf(spellcolorbuf, "Your spells are yellow.");
11675 else sprintf(spellcolorbuf, "Currently known spells");
11677 if (spellid(0) == NO_SPELL)
11678 You("don't know any spells right now.");
11679 else {
11680 while (dospellmenu( spellcolorbuf, SPELLMENU_VIEW, &splnum, 0)) {
11681 sprintf(qbuf, "Reordering spells; swap '%s' with",
11682 (SpellLoss || u.uprops[SPELLS_LOST].extrinsic || have_spelllossstone()) ? "spell" : spellname(splnum));
11683 if (!dospellmenu(qbuf, splnum, &othnum, 0)) break;
11685 spl_tmp = spl_book[splnum];
11686 spl_book[splnum] = spl_book[othnum];
11687 spl_book[othnum] = spl_tmp;
11691 dememonum = 0;
11692 for (i = 0; i < MAXSPELL; i++) {
11693 if (spellid(i) == NO_SPELL) break;
11694 if (spellmemorize(i)) continue;
11695 dememonum++;
11697 if (iflags.memorizationknown) dememonum = 0;
11699 if (dememonum >= 10) pline("You set a very large amount of spells to dememorization mode. A common misconception of players unfamiliar with the memorization system is that dememorizing some spells would magically make the memorized spells last longer. That is NOT the case. The spells are independent from each other. Every spell set to memorization mode gets a 10%% reduction in spell decay rate per memorization skill level (i.e. spell memory persists longer), so if you want to keep casting those spells, you should set them back to memorization mode. You can do that by opening the spell menu (with the + key) and pressing ? twice, which brings you to the memorization menu.");
11700 else if (dememonum >= 5) pline("You set many spells to dememorization mode (indicated by a - next to the spell level). All those spells aren't getting the spell memory bonus from memorization skill, which is highly impractical unless you WANT to forget those spells for some bizarre reason. It's advisable to have only a single spell set to dememorization mode, i.e. the one you want to turn into a forgotten spell. You can change it in the spell menu (hit + to open it and ? twice to navigate to the memorization menu).");
11701 else if (dememonum >= 2) pline("You set several spells to dememorization mode (indicated by a - next to the spell level), which means that those spells currently don't benefit from increased spell memory. If you want your spells to benefit from the memorization skill, you should open the spell menu (+ key by default) and navigate to the memorization menu by pressing ? twice, then setting the spells in question back to memorization mode.");
11703 return 0;
11706 STATIC_OVL boolean
11707 dospellmenu(prompt, splaction, spell_no, specialmenutype)
11708 const char *prompt;
11709 int splaction; /* SPELLMENU_CAST, SPELLMENU_VIEW, or spl_book[] index */
11710 int *spell_no;
11711 /* specialmenutype: 0 = show spells, 1 = describe spells, 2 = memorize spells */
11712 int specialmenutype;
11714 winid tmpwin;
11715 int i, n, how;
11716 char buf[BUFSZ];
11717 menu_item *selected;
11718 anything any;
11719 boolean describe;
11721 tmpwin = create_nhwindow(NHW_MENU);
11722 start_menu(tmpwin);
11723 any.a_void = 0; /* zero out all bits */
11726 * The correct spacing of the columns depends on the
11727 * following that (1) the font is monospaced and (2)
11728 * that selection letters are pre-pended to the given
11729 * string and are of the form "a - ".
11731 * To do it right would require that we implement columns
11732 * in the window-ports (say via a tab character).
11734 if (!iflags.menu_tab_sep)
11735 sprintf(buf, "%-20s Level Pw %-10s Fail Memory", " Name", " Category");
11736 else
11737 sprintf(buf, "Name\tLevel\tPw\t Category\tFail");
11738 if (flags.menu_style == MENU_TRADITIONAL)
11739 strcat(buf, iflags.menu_tab_sep ? "\tKey" : " Key");
11740 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, buf, MENU_UNSELECTED);
11741 if (!SpellLoss && !u.uprops[SPELLS_LOST].extrinsic && !have_spelllossstone()) {for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) {
11742 sprintf(buf, iflags.menu_tab_sep ?
11743 "%s\t%-d%s\t%s%s %d\t%-d%%" : "%-20s %2d%s%s %3d %-8s %4d%%"
11744 " %3d%%",
11745 spellname(i), spellev(i),
11746 ((spellknow(i) > 1000) || SpellColorCyan) ? " " : (spellknow(i) ? "!" : "*"),
11747 spellmemorize(i) ? "+" : "-",
11748 manacost(spellid(i)),
11749 spelltypemnemonic(spell_skilltype(spellid(i))),
11750 SpellColorBlack ? 0 : (100 - percent_success(i)),
11752 /* "Spell memory percentage no longer shows up in menu - Very little reason to have this considering the timeout is so long to begin with, and spellbooks are much more common." In Soviet Russia, people aren't a fan of games with good interfaces, and rather like it if there's as little information conveyed to the player as possible. The next things they'll remove are those obsolete things displayed on the bottom status line, like HP, AC and experience level; there's very little reason to display them either. Ah wait, they might just borrow the spell loss trap and display loss trap code from Slash'EM Extended and make their effect permanent - that gets rid of all the useless information displays at once, and players will be forever grateful! --Amy */
11754 SpellColorCyan ? 100 : issoviet ? 0 : (spellknow(i) * 100 + (KEEN-1)) / KEEN);
11755 if (flags.menu_style == MENU_TRADITIONAL)
11756 sprintf(eos(buf), iflags.menu_tab_sep ?
11757 "\t%c" : "%4c ", spellet(i) ? spellet(i) : ' ');
11759 any.a_int = i+1; /* must be non-zero */
11760 add_menu(tmpwin, NO_GLYPH, &any,
11761 0, 0, ATR_NONE, buf,
11762 (i == splaction) ? MENU_SELECTED : MENU_UNSELECTED);
11765 else {for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) {
11766 sprintf(buf, iflags.menu_tab_sep ?
11767 "\t%c" : "%4c ", spellet(i) ? spellet(i) : ' ');
11768 any.a_int = i+1; /* must be non-zero */
11769 add_menu(tmpwin, NO_GLYPH, &any,
11770 0, 0, ATR_NONE, buf,
11771 (i == splaction) ? MENU_SELECTED : MENU_UNSELECTED);
11776 if (splaction == SPELLMENU_VIEW) {
11777 if (specialmenutype == 0) {
11778 any.a_int = -1; /* must be non-zero */
11779 add_menu(tmpwin, NO_GLYPH, &any,
11780 '?', 0, ATR_NONE, "Describe a spell instead",
11781 MENU_UNSELECTED);
11783 else if (specialmenutype == 1) {
11784 any.a_int = -1; /* must be non-zero */
11785 add_menu(tmpwin, NO_GLYPH, &any,
11786 '?', 0, ATR_NONE, "Memorize a spell instead",
11787 MENU_UNSELECTED);
11789 else if (specialmenutype == 2) {
11790 any.a_int = -1; /* must be non-zero */
11791 add_menu(tmpwin, NO_GLYPH, &any,
11792 '?', 0, ATR_NONE, "View spells instead",
11793 MENU_UNSELECTED);
11797 end_menu(tmpwin, prompt);
11799 how = PICK_ONE;
11800 /*if (splaction == SPELLMENU_VIEW && spellid(1) == NO_SPELL)
11801 how = PICK_NONE;*/ /* only one spell => nothing to swap with */ /* Amy edit: blah, we have the ? option now */
11802 n = select_menu(tmpwin, how, &selected);
11803 destroy_nhwindow(tmpwin);
11804 if (n > 0 && selected[0].item.a_int == -1) {
11806 char spellcolorbuf[BUFSZ];
11808 if (SpellColorPink) sprintf(spellcolorbuf, "Your spells are pink.");
11809 else if (SpellColorBrightCyan) sprintf(spellcolorbuf, "Your spells are bright cyan.");
11810 else if (SpellColorCyan) sprintf(spellcolorbuf, "Your spells are cyan.");
11811 else if (SpellColorBlack) sprintf(spellcolorbuf, "Your spells are black.");
11812 else if (SpellColorOrange) sprintf(spellcolorbuf, "Your spells are orange.");
11813 else if (SpellColorRed) sprintf(spellcolorbuf, "Your spells are red.");
11814 else if (SpellColorPlatinum) sprintf(spellcolorbuf, "Your spells are platinum.");
11815 else if (SpellColorSilver) sprintf(spellcolorbuf, "Your spells are silver.");
11816 else if (SpellColorMetal) sprintf(spellcolorbuf, "Your spells are metal.");
11817 else if (SpellColorGreen) sprintf(spellcolorbuf, "Your spells are green.");
11818 else if (SpellColorBlue) sprintf(spellcolorbuf, "Your spells are blue.");
11819 else if (SpellColorGray) sprintf(spellcolorbuf, "Your spells are completely gray.");
11820 else if (SpellColorBrown) sprintf(spellcolorbuf, "Your spells are brown.");
11821 else if (SpellColorWhite) sprintf(spellcolorbuf, "Your spells are white.");
11822 else if (SpellColorViolet) sprintf(spellcolorbuf, "Your spells are violet.");
11823 else if (SpellColorYellow) sprintf(spellcolorbuf, "Your spells are yellow.");
11824 else if (specialmenutype == 0) sprintf(spellcolorbuf, "Choose a spell to describe");
11825 else if (specialmenutype == 1) sprintf(spellcolorbuf, "Choose a spell to (de-)memorize");
11826 else if (specialmenutype == 2) sprintf(spellcolorbuf, "Currently known spells");
11827 else sprintf(spellcolorbuf, "Bug: unknown spell menu title");
11829 return dospellmenu(spellcolorbuf, splaction, spell_no, (specialmenutype == 2) ? 0 : (specialmenutype + 1));
11831 if (n > 0 && splaction == SPELLMENU_VIEW && specialmenutype == 1) { /* describe */
11833 register struct obj *pseudo;
11835 pseudo = mksobj(spellid(selected[0].item.a_int - 1), FALSE, 2, FALSE);
11836 if (!pseudo) {
11837 impossible("bugged pseudo object for spell description.");
11838 return dospellmenu(prompt, splaction, spell_no, specialmenutype);
11840 if (pseudo->otyp == GOLD_PIECE) pseudo->otyp = spellid(selected[0].item.a_int - 1); /* minimalist fix */
11841 pseudo->blessed = pseudo->cursed = 0;
11842 pseudo->quan = 20L; /* do not let useup get it */
11844 if (SpellLoss || u.uprops[SPELLS_LOST].extrinsic || have_spelllossstone()) {
11845 /* you cheater! you're not supposed to see what the spells are :P */
11846 return dospellmenu(prompt, splaction, spell_no, specialmenutype);
11849 (void) itemactions(pseudo, TRUE, TRUE);
11850 obfree(pseudo, (struct obj *)0); /* now, get rid of it */
11851 return dospellmenu(prompt, splaction, spell_no, specialmenutype);
11853 if (n > 0 && splaction == SPELLMENU_VIEW && specialmenutype == 2) { /* memorize */
11855 spl_book[selected[0].item.a_int - 1].sp_memorize = !spl_book[selected[0].item.a_int - 1].sp_memorize;
11857 char spellcolorbuf[BUFSZ];
11859 if (SpellLoss || u.uprops[SPELLS_LOST].extrinsic || have_spelllossstone()) sprintf(spellcolorbuf, "Memorization setting changed."); /* no, you don't get to see what it is now :P */
11860 else if (spl_book[selected[0].item.a_int - 1].sp_memorize) sprintf(spellcolorbuf, "Spell set to memorization mode!");
11861 else sprintf(spellcolorbuf, "Memorization for this spell deactivated.");
11863 return dospellmenu(spellcolorbuf, splaction, spell_no, specialmenutype);
11865 if (n > 0) {
11866 *spell_no = selected[0].item.a_int - 1;
11867 /* menu selection for `PICK_ONE' does not
11868 de-select any preselected entry */
11869 if (n > 1 && *spell_no == splaction)
11870 *spell_no = selected[1].item.a_int - 1;
11871 free((void *)selected);
11872 /* default selection of preselected spell means that
11873 user chose not to swap it with anything */
11874 if (*spell_no == splaction) return FALSE;
11875 return TRUE;
11876 } else if (splaction >= 0) {
11877 /* explicit de-selection of preselected spell means that
11878 user is still swapping but not for the current spell */
11879 *spell_no = splaction;
11880 return TRUE;
11882 return FALSE;
11885 #ifdef DUMP_LOG
11886 void
11887 dump_spells()
11889 int i, n;
11890 char buf[BUFSZ];
11892 if (spellid(0) == NO_SPELL) {
11893 dump("", "You didn't know any spells.");
11894 dump("", "");
11895 return;
11897 dump("", "Spells known in the end");
11899 sprintf(buf, "%-20s Level Pw %-10s Fail Memory", " Name", " Category");
11900 dump(" ",buf);
11901 for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) {
11902 sprintf(buf, "%c - %-19s %2d%s%s %3d %-8s %4d%% %3d%%",
11903 spellet(i), spellname(i), spellev(i),
11904 ((spellknow(i) > 1000) || SpellColorCyan) ? " " : (spellknow(i) ? "!" : "*"),
11905 spellmemorize(i) ? "+" : "-",
11906 manacost(spellid(i)),
11907 spelltypemnemonic(spell_skilltype(spellid(i))),
11908 SpellColorBlack ? 0 : (100 - percent_success(i)),
11909 SpellColorCyan ? 100 : issoviet ? 0 : (spellknow(i) * 100 + (KEEN-1)) / KEEN);
11910 /* In Soviet Russia, people don't want to know how much spell memory they have left. --Amy */
11911 dump(" ", buf);
11913 dump("","");
11915 } /* dump_spells */
11916 #endif
11918 /* Integer square root function without using floating point. */
11920 isqrt(val)
11921 int val;
11923 int rt = 0;
11924 int odd = 1;
11925 while(val >= odd) {
11926 val = val-odd;
11927 odd = odd+2;
11928 rt = rt + 1;
11930 return rt;
11934 STATIC_OVL int
11935 percent_success(spell)
11936 int spell;
11938 /* Intrinsic and learned ability are combined to calculate
11939 * the probability of player's success at cast a given spell.
11941 int chance, splcaster, special, statused;
11942 int difficulty;
11943 int skill;
11944 int armorpenalties = 15;
11945 int shieldpenalties = 15;
11947 if (!(PlayerCannotUseSkills)) {
11948 switch (P_SKILL(P_BODY_ARMOR)) {
11949 case P_BASIC: armorpenalties = 13; break;
11950 case P_SKILLED: armorpenalties = 11; break;
11951 case P_EXPERT: armorpenalties = 9; break;
11952 case P_MASTER: armorpenalties = 7; break;
11953 case P_GRAND_MASTER: armorpenalties = 5; break;
11954 case P_SUPREME_MASTER: armorpenalties = 3; break;
11959 if (!(PlayerCannotUseSkills)) {
11960 switch (P_SKILL(P_SHIELD)) {
11961 case P_BASIC: shieldpenalties = 13; break;
11962 case P_SKILLED: shieldpenalties = 11; break;
11963 case P_EXPERT: shieldpenalties = 9; break;
11964 case P_MASTER: shieldpenalties = 7; break;
11965 case P_GRAND_MASTER: shieldpenalties = 5; break;
11966 case P_SUPREME_MASTER: shieldpenalties = 3; break;
11971 splcaster = urole.spelbase;
11972 special = urole.spelheal;
11973 statused = ACURR(urole.spelstat);
11975 /* Calculate armor penalties */
11976 if (uarm && !SpellColorMetal && !(uarm->blessed && !issoviet) && !(uarm->otyp >= ELVEN_TOGA && uarm->otyp <= ROBE_OF_WEAKNESS) && !(uarm->oartifact == ART_HA_MONK) && !(uarm->oartifact == ART_BOBAIS) && !(uarm->oartifact == ART_AMMY_S_RETRIBUTION) )
11977 splcaster += (issoviet ? 2 : 1);
11979 /* Robes are body armour in SLASH'EM */
11980 if (uarm && !SpellColorMetal && (is_metallic(uarm) || is_filmitem(uarm)) && !is_etheritem(uarm) && !is_meteosteelitem(uarm)) {
11982 /* Amy grepping target: "materialeffect" */
11983 /* baseline = 15, used by iron, alumen and sinnum */
11984 switch (objects[(uarm)->otyp].oc_material) {
11985 default: break;
11986 case MT_METAL: armorpenalties *= 16; armorpenalties /= 15; break;
11987 case MT_STEEL: armorpenalties *= 16; armorpenalties /= 15; break;
11988 case MT_GREEN_STEEL: armorpenalties *= 12; armorpenalties /= 15; break;
11989 case MT_MERCURIAL: armorpenalties *= 3; armorpenalties /= 15; break;
11990 case MT_BRONZE: armorpenalties *= 21; armorpenalties /= 15; break;
11991 case MT_TITANIUM: armorpenalties *= 18; armorpenalties /= 15; break;
11992 case MT_COPPER: armorpenalties *= 17; armorpenalties /= 15; break;
11993 case MT_COBALT: armorpenalties *= 16; armorpenalties /= 15; break;
11994 case MT_SILVER: armorpenalties *= 17; armorpenalties /= 15; break;
11995 case MT_GOLD: armorpenalties *= 8; armorpenalties /= 15; break;
11996 case MT_TINSEL: armorpenalties *= 10; armorpenalties /= 15; break;
11997 case MT_PLATINUM: armorpenalties *= 18; armorpenalties /= 15; break;
11998 case MT_FILM: armorpenalties *= 18; armorpenalties /= 15; break;
11999 case MT_ALLOY: armorpenalties *= 18; armorpenalties /= 15; break;
12000 case MT_MITHRIL: armorpenalties *= 13; armorpenalties /= 15; break;
12001 case MT_VIVA: armorpenalties *= 12; armorpenalties /= 15; break;
12002 case MT_POURPOOR: armorpenalties *= 20; armorpenalties /= 15; break;
12003 case MT_LEAD: armorpenalties *= 25; armorpenalties /= 15; break;
12004 case MT_CHROME: armorpenalties *= 11; armorpenalties /= 15; break;
12006 if (Race_if(PM_BOVER)) armorpenalties *= 3;
12008 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12009 armorpenalties *= 4;
12010 armorpenalties /= 5;
12013 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) armorpenalties /= 2;
12014 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) armorpenalties /= 2;
12016 if (uarm && uarm->blessed && !issoviet) armorpenalties /= 2;
12018 splcaster += (urole.spelarmr * armorpenalties / (issoviet ? 12 : 30));
12020 if (SpellColorMetal && (!uarm || !is_metallic(uarm))) {
12022 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12023 armorpenalties *= 4;
12024 armorpenalties /= 5;
12027 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) armorpenalties /= 2;
12028 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) armorpenalties /= 2;
12030 if (uarm && uarm->blessed && !issoviet) armorpenalties /= 2;
12032 splcaster += (urole.spelarmr * armorpenalties / (issoviet ? 12 : 30));
12035 if (uarmc && !SpellColorMetal && (is_metallic(uarmc) || is_filmitem(uarmc)) && !is_etheritem(uarmc) && !is_meteosteelitem(uarmc)) {
12037 switch (objects[(uarmc)->otyp].oc_material) {
12038 default: break;
12039 case MT_METAL: armorpenalties *= 16; armorpenalties /= 15; break;
12040 case MT_STEEL: armorpenalties *= 16; armorpenalties /= 15; break;
12041 case MT_GREEN_STEEL: armorpenalties *= 12; armorpenalties /= 15; break;
12042 case MT_MERCURIAL: armorpenalties *= 3; armorpenalties /= 15; break;
12043 case MT_BRONZE: armorpenalties *= 21; armorpenalties /= 15; break;
12044 case MT_TITANIUM: armorpenalties *= 18; armorpenalties /= 15; break;
12045 case MT_COPPER: armorpenalties *= 17; armorpenalties /= 15; break;
12046 case MT_COBALT: armorpenalties *= 16; armorpenalties /= 15; break;
12047 case MT_SILVER: armorpenalties *= 17; armorpenalties /= 15; break;
12048 case MT_GOLD: armorpenalties *= 8; armorpenalties /= 15; break;
12049 case MT_TINSEL: armorpenalties *= 10; armorpenalties /= 15; break;
12050 case MT_PLATINUM: armorpenalties *= 18; armorpenalties /= 15; break;
12051 case MT_FILM: armorpenalties *= 18; armorpenalties /= 15; break;
12052 case MT_ALLOY: armorpenalties *= 18; armorpenalties /= 15; break;
12053 case MT_MITHRIL: armorpenalties *= 13; armorpenalties /= 15; break;
12054 case MT_VIVA: armorpenalties *= 12; armorpenalties /= 15; break;
12055 case MT_POURPOOR: armorpenalties *= 20; armorpenalties /= 15; break;
12056 case MT_LEAD: armorpenalties *= 25; armorpenalties /= 15; break;
12057 case MT_CHROME: armorpenalties *= 11; armorpenalties /= 15; break;
12059 if (Race_if(PM_BOVER)) armorpenalties *= 3;
12061 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12062 armorpenalties *= 4;
12063 armorpenalties /= 5;
12066 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) armorpenalties /= 2;
12067 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) armorpenalties /= 2;
12069 if (uarmc && uarmc->blessed && !issoviet) armorpenalties /= 2;
12071 splcaster += (urole.spelarmr * armorpenalties / (issoviet ? 36 : 50));
12073 if (SpellColorMetal && (!uarmc || !is_metallic(uarmc))) {
12075 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12076 armorpenalties *= 4;
12077 armorpenalties /= 5;
12080 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) armorpenalties /= 2;
12081 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) armorpenalties /= 2;
12083 if (uarmc && uarmc->blessed && !issoviet) armorpenalties /= 2;
12085 splcaster += (urole.spelarmr * armorpenalties / (issoviet ? 36 : 50));
12089 if (uarmu && !SpellColorMetal && (is_metallic(uarmu) || is_filmitem(uarmu)) && !is_etheritem(uarmu) && !is_meteosteelitem(uarmu)) {
12091 switch (objects[(uarmu)->otyp].oc_material) {
12092 default: break;
12093 case MT_METAL: armorpenalties *= 16; armorpenalties /= 15; break;
12094 case MT_STEEL: armorpenalties *= 16; armorpenalties /= 15; break;
12095 case MT_GREEN_STEEL: armorpenalties *= 12; armorpenalties /= 15; break;
12096 case MT_MERCURIAL: armorpenalties *= 3; armorpenalties /= 15; break;
12097 case MT_BRONZE: armorpenalties *= 21; armorpenalties /= 15; break;
12098 case MT_TITANIUM: armorpenalties *= 18; armorpenalties /= 15; break;
12099 case MT_COPPER: armorpenalties *= 17; armorpenalties /= 15; break;
12100 case MT_COBALT: armorpenalties *= 16; armorpenalties /= 15; break;
12101 case MT_SILVER: armorpenalties *= 17; armorpenalties /= 15; break;
12102 case MT_GOLD: armorpenalties *= 8; armorpenalties /= 15; break;
12103 case MT_TINSEL: armorpenalties *= 10; armorpenalties /= 15; break;
12104 case MT_PLATINUM: armorpenalties *= 18; armorpenalties /= 15; break;
12105 case MT_FILM: armorpenalties *= 18; armorpenalties /= 15; break;
12106 case MT_ALLOY: armorpenalties *= 18; armorpenalties /= 15; break;
12107 case MT_MITHRIL: armorpenalties *= 13; armorpenalties /= 15; break;
12108 case MT_VIVA: armorpenalties *= 12; armorpenalties /= 15; break;
12109 case MT_POURPOOR: armorpenalties *= 20; armorpenalties /= 15; break;
12110 case MT_LEAD: armorpenalties *= 25; armorpenalties /= 15; break;
12111 case MT_CHROME: armorpenalties *= 11; armorpenalties /= 15; break;
12113 if (Race_if(PM_BOVER)) armorpenalties *= 3;
12115 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12116 armorpenalties *= 4;
12117 armorpenalties /= 5;
12120 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) armorpenalties /= 2;
12121 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) armorpenalties /= 2;
12123 if (uarmu && uarmu->blessed && !issoviet) armorpenalties /= 2;
12125 splcaster += (urole.spelarmr * armorpenalties / (issoviet ? 72 : 100));
12127 if (SpellColorMetal && (!uarmu || !is_metallic(uarmu))) {
12129 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12130 armorpenalties *= 4;
12131 armorpenalties /= 5;
12134 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) armorpenalties /= 2;
12135 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) armorpenalties /= 2;
12137 if (uarmu && uarmu->blessed && !issoviet) armorpenalties /= 2;
12139 splcaster += (urole.spelarmr * armorpenalties / (issoviet ? 72 : 100));
12143 if (uarms && !SpellColorMetal) {
12144 if (!is_metallic(uarms) || is_etheritem(uarms) || is_meteosteelitem(uarms)) shieldpenalties /= 3;
12146 switch (objects[(uarms)->otyp].oc_material) {
12147 default: break;
12148 case MT_METAL: shieldpenalties *= 16; shieldpenalties /= 15; break;
12149 case MT_STEEL: shieldpenalties *= 16; shieldpenalties /= 15; break;
12150 case MT_GREEN_STEEL: shieldpenalties *= 12; shieldpenalties /= 15; break;
12151 case MT_MERCURIAL: shieldpenalties *= 3; shieldpenalties /= 15; break;
12152 case MT_BRONZE: shieldpenalties *= 21; shieldpenalties /= 15; break;
12153 case MT_TITANIUM: shieldpenalties *= 18; shieldpenalties /= 15; break;
12154 case MT_COPPER: shieldpenalties *= 17; shieldpenalties /= 15; break;
12155 case MT_COBALT: shieldpenalties *= 16; shieldpenalties /= 15; break;
12156 case MT_SILVER: shieldpenalties *= 17; shieldpenalties /= 15; break;
12157 case MT_GOLD: shieldpenalties *= 8; shieldpenalties /= 15; break;
12158 case MT_TINSEL: shieldpenalties *= 10; shieldpenalties /= 15; break;
12159 case MT_PLATINUM: shieldpenalties *= 18; shieldpenalties /= 15; break;
12160 case MT_FILM: shieldpenalties *= 18; shieldpenalties /= 15; break;
12161 case MT_ALLOY: shieldpenalties *= 18; shieldpenalties /= 15; break;
12162 case MT_MITHRIL: shieldpenalties *= 13; shieldpenalties /= 15; break;
12163 case MT_VIVA: shieldpenalties *= 12; shieldpenalties /= 15; break;
12164 case MT_POURPOOR: shieldpenalties *= 20; shieldpenalties /= 15; break;
12165 case MT_LEAD: shieldpenalties *= 25; shieldpenalties /= 15; break;
12166 case MT_CHROME: shieldpenalties *= 11; shieldpenalties /= 15; break;
12168 if (Race_if(PM_BOVER)) shieldpenalties *= 3;
12170 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12171 shieldpenalties *= 4;
12172 shieldpenalties /= 5;
12175 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) shieldpenalties /= 2;
12176 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) shieldpenalties /= 2;
12178 if (uarms && uarms->blessed && !issoviet) shieldpenalties /= 2;
12180 splcaster += (urole.spelshld * shieldpenalties / (issoviet ? 12 : 30));
12182 if (SpellColorMetal && (!uarms || !is_metallic(uarms))) {
12184 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12185 shieldpenalties *= 4;
12186 shieldpenalties /= 5;
12189 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) shieldpenalties /= 2;
12190 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) shieldpenalties /= 2;
12192 if (uarms && uarms->blessed && !issoviet) shieldpenalties /= 2;
12194 splcaster += (urole.spelshld * shieldpenalties / (issoviet ? 12 : 30));
12198 if (uarmh && !SpellColorMetal && (is_metallic(uarmh) || is_filmitem(uarmh)) && !is_etheritem(uarmh) && !is_meteosteelitem(uarmh) && uarmh->otyp != HELM_OF_BRILLIANCE) {
12200 switch (objects[(uarmh)->otyp].oc_material) {
12201 default: break;
12202 case MT_METAL: armorpenalties *= 16; armorpenalties /= 15; break;
12203 case MT_STEEL: armorpenalties *= 16; armorpenalties /= 15; break;
12204 case MT_GREEN_STEEL: armorpenalties *= 12; armorpenalties /= 15; break;
12205 case MT_MERCURIAL: armorpenalties *= 3; armorpenalties /= 15; break;
12206 case MT_BRONZE: armorpenalties *= 21; armorpenalties /= 15; break;
12207 case MT_TITANIUM: armorpenalties *= 18; armorpenalties /= 15; break;
12208 case MT_COPPER: armorpenalties *= 17; armorpenalties /= 15; break;
12209 case MT_COBALT: armorpenalties *= 16; armorpenalties /= 15; break;
12210 case MT_SILVER: armorpenalties *= 17; armorpenalties /= 15; break;
12211 case MT_GOLD: armorpenalties *= 8; armorpenalties /= 15; break;
12212 case MT_TINSEL: armorpenalties *= 10; armorpenalties /= 15; break;
12213 case MT_PLATINUM: armorpenalties *= 18; armorpenalties /= 15; break;
12214 case MT_FILM: armorpenalties *= 18; armorpenalties /= 15; break;
12215 case MT_ALLOY: armorpenalties *= 18; armorpenalties /= 15; break;
12216 case MT_MITHRIL: armorpenalties *= 13; armorpenalties /= 15; break;
12217 case MT_VIVA: armorpenalties *= 12; armorpenalties /= 15; break;
12218 case MT_POURPOOR: armorpenalties *= 20; armorpenalties /= 15; break;
12219 case MT_LEAD: armorpenalties *= 25; armorpenalties /= 15; break;
12220 case MT_CHROME: armorpenalties *= 11; armorpenalties /= 15; break;
12222 if (Race_if(PM_BOVER)) armorpenalties *= 3;
12224 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12225 armorpenalties *= 4;
12226 armorpenalties /= 5;
12229 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) armorpenalties /= 2;
12230 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) armorpenalties /= 2;
12232 if (uarmh && uarmh->blessed && !issoviet) armorpenalties /= 2;
12234 splcaster += (uarmhbon * armorpenalties / (issoviet ? 10 : 20));
12236 if (SpellColorMetal && (!uarmh || !is_metallic(uarmh))) {
12238 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12239 armorpenalties *= 4;
12240 armorpenalties /= 5;
12243 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) armorpenalties /= 2;
12244 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) armorpenalties /= 2;
12246 if (uarmh && uarmh->blessed && !issoviet) armorpenalties /= 2;
12248 splcaster += (uarmhbon * armorpenalties / (issoviet ? 10 : 20));
12252 if (uarmg && !SpellColorMetal && (is_metallic(uarmg) || is_filmitem(uarmg)) && !is_etheritem(uarmg) && !is_meteosteelitem(uarmg)) {
12254 switch (objects[(uarmg)->otyp].oc_material) {
12255 default: break;
12256 case MT_METAL: armorpenalties *= 16; armorpenalties /= 15; break;
12257 case MT_STEEL: armorpenalties *= 16; armorpenalties /= 15; break;
12258 case MT_GREEN_STEEL: armorpenalties *= 12; armorpenalties /= 15; break;
12259 case MT_MERCURIAL: armorpenalties *= 3; armorpenalties /= 15; break;
12260 case MT_BRONZE: armorpenalties *= 21; armorpenalties /= 15; break;
12261 case MT_TITANIUM: armorpenalties *= 18; armorpenalties /= 15; break;
12262 case MT_COPPER: armorpenalties *= 17; armorpenalties /= 15; break;
12263 case MT_COBALT: armorpenalties *= 16; armorpenalties /= 15; break;
12264 case MT_SILVER: armorpenalties *= 17; armorpenalties /= 15; break;
12265 case MT_GOLD: armorpenalties *= 8; armorpenalties /= 15; break;
12266 case MT_TINSEL: armorpenalties *= 10; armorpenalties /= 15; break;
12267 case MT_PLATINUM: armorpenalties *= 18; armorpenalties /= 15; break;
12268 case MT_FILM: armorpenalties *= 18; armorpenalties /= 15; break;
12269 case MT_ALLOY: armorpenalties *= 18; armorpenalties /= 15; break;
12270 case MT_MITHRIL: armorpenalties *= 13; armorpenalties /= 15; break;
12271 case MT_VIVA: armorpenalties *= 12; armorpenalties /= 15; break;
12272 case MT_POURPOOR: armorpenalties *= 20; armorpenalties /= 15; break;
12273 case MT_LEAD: armorpenalties *= 25; armorpenalties /= 15; break;
12274 case MT_CHROME: armorpenalties *= 11; armorpenalties /= 15; break;
12276 if (Race_if(PM_BOVER)) armorpenalties *= 3;
12278 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12279 armorpenalties *= 4;
12280 armorpenalties /= 5;
12283 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) armorpenalties /= 2;
12284 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) armorpenalties /= 2;
12286 if (uarmg && uarmg->blessed && !issoviet) armorpenalties /= 2;
12288 splcaster += (uarmgbon * armorpenalties / (issoviet ? 10 : 20));
12290 if (SpellColorMetal && (!uarmg || !is_metallic(uarmg))) {
12292 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12293 armorpenalties *= 4;
12294 armorpenalties /= 5;
12297 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) armorpenalties /= 2;
12298 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) armorpenalties /= 2;
12300 if (uarmg && uarmg->blessed && !issoviet) armorpenalties /= 2;
12302 splcaster += (uarmgbon * armorpenalties / (issoviet ? 10 : 20));
12306 if (uarmf && !SpellColorMetal && (is_metallic(uarmf) || is_filmitem(uarmf)) && !is_etheritem(uarmf) && !is_meteosteelitem(uarmf)) {
12308 switch (objects[(uarmf)->otyp].oc_material) {
12309 default: break;
12310 case MT_METAL: armorpenalties *= 16; armorpenalties /= 15; break;
12311 case MT_STEEL: armorpenalties *= 16; armorpenalties /= 15; break;
12312 case MT_GREEN_STEEL: armorpenalties *= 12; armorpenalties /= 15; break;
12313 case MT_MERCURIAL: armorpenalties *= 3; armorpenalties /= 15; break;
12314 case MT_BRONZE: armorpenalties *= 21; armorpenalties /= 15; break;
12315 case MT_TITANIUM: armorpenalties *= 18; armorpenalties /= 15; break;
12316 case MT_COPPER: armorpenalties *= 17; armorpenalties /= 15; break;
12317 case MT_COBALT: armorpenalties *= 16; armorpenalties /= 15; break;
12318 case MT_SILVER: armorpenalties *= 17; armorpenalties /= 15; break;
12319 case MT_GOLD: armorpenalties *= 8; armorpenalties /= 15; break;
12320 case MT_TINSEL: armorpenalties *= 10; armorpenalties /= 15; break;
12321 case MT_PLATINUM: armorpenalties *= 18; armorpenalties /= 15; break;
12322 case MT_FILM: armorpenalties *= 18; armorpenalties /= 15; break;
12323 case MT_ALLOY: armorpenalties *= 18; armorpenalties /= 15; break;
12324 case MT_MITHRIL: armorpenalties *= 13; armorpenalties /= 15; break;
12325 case MT_VIVA: armorpenalties *= 12; armorpenalties /= 15; break;
12326 case MT_POURPOOR: armorpenalties *= 20; armorpenalties /= 15; break;
12327 case MT_LEAD: armorpenalties *= 25; armorpenalties /= 15; break;
12328 case MT_CHROME: armorpenalties *= 11; armorpenalties /= 15; break;
12330 if (Race_if(PM_BOVER)) armorpenalties *= 3;
12332 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12333 armorpenalties *= 4;
12334 armorpenalties /= 5;
12337 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) armorpenalties /= 2;
12338 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) armorpenalties /= 2;
12340 if (uarmf && uarmf->blessed && !issoviet) armorpenalties /= 2;
12342 splcaster += (uarmfbon * armorpenalties / (issoviet ? 10 : 20));
12345 if (SpellColorMetal && (!uarmf || !is_metallic(uarmf))) {
12347 if (uwep && (weapon_type(uwep) == P_QUARTERSTAFF || weapon_type(uwep) == P_ORB)) {
12348 armorpenalties *= 4;
12349 armorpenalties /= 5;
12352 if (uarmg && itemhasappearance(uarmg, APP_VELVET_GLOVES) ) armorpenalties /= 2;
12353 if (uarmh && uarmh->oartifact == ART_METAL_NEGATER) armorpenalties /= 2;
12355 if (uarmf && uarmf->blessed && !issoviet) armorpenalties /= 2;
12357 splcaster += (uarmfbon * armorpenalties / (issoviet ? 10 : 20));
12361 if (spellid(spell) == urole.spelspec)
12362 splcaster += urole.spelsbon;
12364 if (spellid(spell) == u.superspecialspell)
12365 splcaster -= 5;
12367 /* `healing spell' bonus */
12368 if (spell_skilltype(spellid(spell)) == P_HEALING_SPELL)
12369 splcaster += special;
12371 if (uarm && uarm->otyp == ROBE_OF_POWER) splcaster -= 3;
12372 if (uarm && uarm->otyp == ROBE_OF_SPELL_POWER) splcaster -= 3;
12373 if (uarmg && uarmg->oartifact == ART_GAUNTLETS_OF_SPELL_POWER) splcaster -= 3;
12374 if (uarm && uarm->oartifact == ART_SPIDERSILK) splcaster -= 3;
12375 if (uarm && uarm->oartifact == ART_WEB_OF_LOLTH) splcaster -= 3;
12376 if (uarm && uarm->oartifact == ART_WEB_OF_HOHOTH) splcaster -= 3;
12377 if (uwep && uwep->oartifact == ART_ARYFAERN_KERYM) splcaster -= 3;
12379 if (Role_if(PM_PALADIN)) splcaster -= 3; /* it is assumed some of their power is granted by the Lord of Light himself */
12382 /* Calculate learned ability */
12384 /* Players basic likelihood of being able to cast any spell
12385 * is based of their `magic' statistic. (Int or Wis)
12387 chance = 11 * statused / 2;
12390 * High level spells are harder. Easier for higher level casters.
12391 * The difficulty is based on the hero's level and their skill level
12392 * in that spell type.
12394 skill = P_SKILL(spell_skilltype(spellid(spell)));
12395 if (PlayerCannotUseSkills) skill = P_ISRESTRICTED;
12397 /* come on, you should be able to cast better if your skill is higher! --Amy */
12398 if (!Race_if(PM_BABYLONIAN)) {
12399 if ( skill == P_BASIC) splcaster -= 3;
12400 if ( skill == P_SKILLED) splcaster -= 6;
12401 if ( skill == P_EXPERT) splcaster -= 9;
12402 if ( skill == P_MASTER) splcaster -= 12;
12403 if ( skill == P_GRAND_MASTER) splcaster -= 15;
12404 if ( skill == P_SUPREME_MASTER) splcaster -= 18;
12407 /* casting it often (and thereby keeping it in memory) should also improve chances...
12408 * Amy note: 700% is the cap where it stops getting better, this is intentional */
12409 if ( spellknow(spell) >= 20000) splcaster -= 1;
12410 if (( spellknow(spell) >= 23333) && (spellev(spell) < 5) ) splcaster -= 1;
12411 if (( spellknow(spell) >= 26666) && (spellev(spell) < 6) ) splcaster -= 1;
12412 if (( spellknow(spell) >= 30000) && (spellev(spell) < 7) ) splcaster -= 1;
12413 if (( spellknow(spell) >= 33333) && (spellev(spell) < 8) ) splcaster -= 1;
12414 if ( spellknow(spell) >= 36666) splcaster -= 1;
12415 if (( spellknow(spell) >= 40000) && (spellev(spell) < 5) ) splcaster -= 1;
12416 if (( spellknow(spell) >= 43333) && (spellev(spell) < 6) ) splcaster -= 1;
12417 if (( spellknow(spell) >= 46666) && (spellev(spell) < 7) ) splcaster -= 1;
12418 if (( spellknow(spell) >= 50000) && (spellev(spell) < 8) ) splcaster -= 1;
12419 if ( spellknow(spell) >= 53333) splcaster -= 1;
12420 if (( spellknow(spell) >= 56666) && (spellev(spell) < 5) ) splcaster -= 1;
12421 if (( spellknow(spell) >= 60000) && (spellev(spell) < 6) ) splcaster -= 1;
12422 if (( spellknow(spell) >= 63333) && (spellev(spell) < 7) ) splcaster -= 1;
12423 if (( spellknow(spell) >= 66666) && (spellev(spell) < 8) ) splcaster -= 1;
12424 if ( spellknow(spell) >= 69000) splcaster -= 1;
12426 skill = max(skill,P_UNSKILLED) - 1; /* unskilled => 0 */
12427 difficulty= (spellev(spell)-1) * 3 - ((skill * 6) + (u.ulevel/3) + 1);
12429 splcaster += 5;
12431 if (splcaster < 0) {
12432 splcaster /= 5;
12433 if (splcaster > 0) splcaster = 0; /* fail safe */
12434 if (splcaster < -10) splcaster = -10; /* absolute limit */
12436 if (splcaster > 50) splcaster = 50;
12438 if (difficulty > 0) {
12439 /* Player is too low level or unskilled. */
12440 chance -= isqrt(900 * difficulty + 2000);
12441 } else {
12442 /* Player is above level. Learning continues, but the
12443 * law of diminishing returns sets in quickly for
12444 * low-level spells. That is, a player quickly gains
12445 * no advantage for raising level.
12447 int learning = 15 * -difficulty / spellev(spell);
12448 chance += learning > 20 ? 20 : learning;
12451 /* Clamp the chance: >18 stat and advanced learning only help
12452 * to a limit, while chances below "hopeless" only raise the
12453 * specter of overflowing 16-bit ints (and permit wearing a
12454 * shield to raise the chances :-).
12456 if (chance < 0) chance = 0;
12457 if (chance > 120) chance = 120;
12459 /* Wearing anything but a light shield makes it very awkward
12460 * to cast a spell. The penalty is not quite so bad for the
12461 * player's class-specific spell.
12463 /* if (uarms && weight(uarms) > (int) objects[SMALL_SHIELD].oc_weight) {
12464 if (spellid(spell) == urole.spelspec) {
12465 chance /= 2;
12466 } else {
12467 chance /= 3;
12471 /* Finally, chance (based on player intell/wisdom and level) is
12472 * combined with ability (based on player intrinsics and
12473 * encumbrances). No matter how intelligent/wise and advanced
12474 * a player is, intrinsics and encumbrance can prevent casting;
12475 * and no matter how able, learning is always required.
12477 chance = chance * (30-splcaster) / 10;
12479 if ( (CasterProblem || u.uprops[CASTER_PROBLEM].extrinsic || have_antimagicstone() || (uarm && uarm->oartifact == ART_ROBE_OF_THE_ARCHMAGI) || (uarmc && uarmc->oartifact == ART_HERETICAL_FIGURE) || (uarm && uarm->oartifact == ART_SHIVANHUNTER_S_UNUSED_PRIZ) ) && chance > 0) {
12481 chance = (chance * u.uhp / u.uhpmax);
12485 switch (spellev(spell)) {
12487 case 1:
12488 case 2:
12489 case 3:
12490 case 4:
12491 default:
12492 break;
12493 case 5:
12494 chance -= 10;
12495 break;
12496 case 6:
12497 chance -= 32;
12498 break;
12499 case 7:
12500 chance -= 70;
12501 break;
12502 case 8:
12503 chance -= 125;
12504 break;
12508 if (SpellColorBlack) {
12510 switch (spellev(spell)) {
12512 case 1:
12513 chance -= 10;
12514 break;
12515 case 2:
12516 chance -= 25;
12517 break;
12518 case 3:
12519 chance -= 50;
12520 break;
12521 case 4:
12522 chance -= 100;
12523 break;
12524 case 5:
12525 chance -= 150;
12526 break;
12527 case 6:
12528 chance -= 200;
12529 break;
12530 case 7:
12531 chance -= 250;
12532 break;
12533 case 8:
12534 chance -= 300;
12535 break;
12541 if (Race_if(PM_TONBERRY)) {
12542 switch (spellev(spell)) {
12543 case 1:
12544 chance -= 10;
12545 break;
12546 case 2:
12547 chance -= 20;
12548 break;
12549 case 3:
12550 chance -= 30;
12551 break;
12552 case 4:
12553 chance -= 40;
12554 break;
12555 case 5:
12556 chance -= 50;
12557 break;
12558 case 6:
12559 chance -= 60;
12560 break;
12561 case 7:
12562 chance -= 70;
12563 break;
12564 case 8:
12565 chance -= 80;
12566 break;
12571 if (issoviet) chance -= 30;
12572 if (Role_if(PM_NOOB_MODE_BARB)) chance -= 50;
12573 if (u.martialstyle == MARTIALSTYLE_MUAYTHAI) chance -= 20;
12575 if (Race_if(PM_PLAYER_SKELETON)) chance -= 50;
12577 if (spell_skilltype(spellid(spell)) == P_CHAOS_SPELL) { /* more difficult! */
12579 switch (spellev(spell)) {
12581 case 1:
12582 chance -= 5;
12583 if (!Role_if(PM_CHAOS_SORCEROR)) chance -= 5;
12584 break;
12585 case 2:
12586 chance -= 10;
12587 if (!Role_if(PM_CHAOS_SORCEROR)) chance -= 10;
12588 break;
12589 case 3:
12590 chance -= 15;
12591 if (!Role_if(PM_CHAOS_SORCEROR)) chance -= 15;
12592 break;
12593 case 4:
12594 chance -= 25;
12595 if (!Role_if(PM_CHAOS_SORCEROR)) chance -= 25;
12596 break;
12597 case 5:
12598 chance -= 40;
12599 if (!Role_if(PM_CHAOS_SORCEROR)) chance -= 40;
12600 break;
12601 case 6:
12602 chance -= 58;
12603 if (!Role_if(PM_CHAOS_SORCEROR)) chance -= 60;
12604 break;
12605 case 7:
12606 chance -= 70;
12607 if (!Role_if(PM_CHAOS_SORCEROR)) chance -= 80;
12608 break;
12609 case 8:
12610 chance -= 75;
12611 if (!Role_if(PM_CHAOS_SORCEROR)) chance -= 100;
12612 break;
12618 if (uarmg && itemhasappearance(uarmg, APP_UNCANNY_GLOVES)) chance -= 10;
12620 if (uarmh && uarmh->oartifact == ART_WAITING_FOR_MELEE) chance -= 15;
12621 if (uarm && uarm->oartifact == ART_DRAGON_PLATE) chance -= 20;
12622 if (uarmf && uarmf->oartifact == ART_THICKER_THAN_THE_HEAD) chance -= 20;
12623 if (uarm && uarm->oartifact == ART_MADE_OF_IRON) chance -= 20;
12624 if (StrongMagicVacuum) chance -= 50;
12626 if (Race_if(PM_PLAYER_GOLEM)) {
12627 chance -= 25;
12628 if (spellev(spell) > 1) chance -= ((spellev(spell) - 1) * 5);
12631 if (uarm && uarm->oartifact == ART_ROFLCOPTER_WEB) chance += 10;
12632 if (uarm && uarm->otyp == ROBE_OF_SPELL_POWER) chance += 20;
12633 if (Role_if(PM_CELLAR_CHILD) && uarm && uarm->otyp == MAGE_PLATE_MAIL) chance += 20;
12634 if (uarmh && uarmh->oartifact == ART_ZERO_PERCENT_FAILURE) chance += 10;
12635 if (uarmc && uarmc->oartifact == ART_HENRIETTA_S_HEAVY_CASTER) chance += 15;
12636 if (uarmf && uarmf->oartifact == ART_SUNALI_S_SUMMONING_STORM) chance += 15;
12637 if (uwep && uwep->otyp == OLDEST_STAFF) chance += 10;
12638 if (uleft && uleft->oartifact == ART_HENRIETTA_S_MAGICAL_AID) chance += 50;
12639 if (uright && uright->oartifact == ART_HENRIETTA_S_MAGICAL_AID) chance += 50;
12640 if (uarmu && uarmu->oartifact == ART_KEITH_S_UNDEROOS) chance += 50;
12641 if (Role_if(PM_ARCHEOLOGIST) && uamul && uamul->oartifact == ART_ARCHEOLOGIST_SONG) chance += 10;
12642 if (uarmh && itemhasappearance(uarmh, APP_KNOWLEDGEABLE_HELMET) ) chance += 10;
12643 if (uarmc && itemhasappearance(uarmc, APP_SCIENCE_CLOAK) ) chance += 10;
12644 if (u.tiksrvzllatdown) chance += 10;
12645 if (uarmf && uarmf->oartifact == ART_JONADAB_S_EVERYDAY_WEAR) chance += 5;
12646 if (uarmf && uarmf->oartifact == ART_DON_T_FALL_INTO_THE_ABYSS) chance += 10;
12647 if (uwep && uwep->oartifact == ART_BAOBHAN_MOUNTAIN) chance += 10;
12648 if (uwep && uwep->oartifact == ART_ORIGIN_OF_CASTING) chance += 20;
12649 if (uwep && uwep->oartifact == ART_HELIOKOPIS_S_PLAYSTYLE) chance += 20;
12650 if (uarmg && uarmg->oartifact == ART_FLOEMMELFLOEMMELFLOEMMELFL) chance += 5;
12651 if (uarmc && uarmc->oartifact == ART_CASTEASY) chance += 5;
12652 if (uwep && uwep->oartifact == ART_INFASPEL) chance += 5;
12653 if (uarmg && uarmg->oartifact == ART_HOGWILD_WIZ) chance += 10;
12654 if (bmwride(ART_ZIN_BA)) chance += 10;
12655 if (uarmg && uarmg->oartifact == ART_WAND_INTO_SPELL) chance += 10;
12656 if (uarmc && uarmc->oartifact == ART_SHROUD) chance += 10;
12657 if (have_magicrystal()) chance += 5;
12658 if (uarmh && uarmh->oartifact == ART_ALL_THE_BETTER_SPELLING) chance += 5;
12659 if (uarm && uarm->oartifact == ART_KAMAKURA_BORI) chance += 20;
12660 if (uarmh && uarmh->oartifact == ART_DREHTURN) chance += 10;
12662 if (spell_skilltype(spellid(spell)) == P_HEALING_SPELL) {
12663 if (uwep && uwep->oartifact == ART_CELESTIAL_SCEPTRE) chance += 50;
12666 /* higher spell skill should do SOMEthing --Amy */
12667 skill = P_SKILL(spell_skilltype(spellid(spell)));
12668 if (PlayerCannotUseSkills) skill = P_ISRESTRICTED;
12670 if (!Race_if(PM_BABYLONIAN)) {
12671 if (skill >= P_BASIC) chance++;
12672 if (skill >= P_SKILLED) chance++;
12673 if (skill >= P_EXPERT) chance++;
12674 if (skill >= P_MASTER) chance += 5;
12675 if (skill >= P_GRAND_MASTER) chance += 5;
12676 if (skill >= P_SUPREME_MASTER) chance += 5;
12679 if (uarm && objects[(uarm)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12680 if (uarmu && objects[(uarmu)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12681 if (uarmc && objects[(uarmc)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12682 if (uarmf && objects[(uarmf)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12683 if (uarmg && objects[(uarmg)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12684 if (uarmh && objects[(uarmh)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12685 if (uarms && objects[(uarms)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12686 if (uwep && objects[(uwep)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12687 if (u.twoweap && uswapwep && objects[(uswapwep)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12688 if (uamul && objects[(uamul)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12689 if (uleft && objects[(uleft)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12690 if (uright && objects[(uright)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12691 if (uimplant && objects[(uimplant)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12692 if (ublindf && objects[(ublindf)->otyp].oc_material == MT_CELESTIUM) chance += 2;
12694 if (Race_if(PM_PLAYER_FAIRY)) {
12695 chance += 33;
12697 if (uwep && is_metallic(uwep) && !is_etheritem(uwep) && !is_meteosteelitem(uwep)) {
12699 switch (objects[(uwep)->otyp].oc_material) {
12700 default: chance -= 20; break;
12701 case MT_METAL: chance -= 22; break;
12702 case MT_STEEL: chance -= 22; break;
12703 case MT_GREEN_STEEL: chance -= 16; break;
12704 case MT_MERCURIAL: chance -= 4; break;
12705 case MT_BRONZE: chance -= 28; break;
12706 case MT_TITANIUM: chance -= 26; break;
12707 case MT_COPPER: chance -= 24; break;
12708 case MT_COBALT: chance -= 22; break;
12709 case MT_SILVER: chance -= 24; break;
12710 case MT_GOLD: chance -= 10; break;
12711 case MT_TINSEL: chance -= 12; break;
12712 case MT_PLATINUM: chance -= 26; break;
12713 case MT_FILM: chance -= 26; break;
12714 case MT_ALLOY: chance -= 26; break;
12715 case MT_MITHRIL: chance -= 18; break;
12716 case MT_VIVA: chance -= 16; break;
12717 case MT_POURPOOR: chance -= 30; break;
12718 case MT_LEAD: chance -= 40; break;
12719 case MT_CHROME: chance -= 14; break;
12723 if (u.twoweap && uswapwep && is_metallic(uswapwep) && !is_etheritem(uswapwep) && !is_meteosteelitem(uswapwep)) {
12725 switch (objects[(uswapwep)->otyp].oc_material) {
12726 default: chance -= 20; break;
12727 case MT_METAL: chance -= 22; break;
12728 case MT_STEEL: chance -= 22; break;
12729 case MT_GREEN_STEEL: chance -= 16; break;
12730 case MT_MERCURIAL: chance -= 4; break;
12731 case MT_BRONZE: chance -= 28; break;
12732 case MT_TITANIUM: chance -= 26; break;
12733 case MT_COPPER: chance -= 24; break;
12734 case MT_COBALT: chance -= 22; break;
12735 case MT_SILVER: chance -= 24; break;
12736 case MT_GOLD: chance -= 10; break;
12737 case MT_TINSEL: chance -= 12; break;
12738 case MT_PLATINUM: chance -= 26; break;
12739 case MT_FILM: chance -= 26; break;
12740 case MT_ALLOY: chance -= 26; break;
12741 case MT_MITHRIL: chance -= 18; break;
12742 case MT_VIVA: chance -= 16; break;
12743 case MT_POURPOOR: chance -= 30; break;
12744 case MT_LEAD: chance -= 40; break;
12745 case MT_CHROME: chance -= 14; break;
12749 if (uarm && is_metallic(uarm) && !is_etheritem(uarm) && !is_meteosteelitem(uarm)) {
12751 switch (objects[(uarm)->otyp].oc_material) {
12752 default: chance -= 20; break;
12753 case MT_METAL: chance -= 22; break;
12754 case MT_STEEL: chance -= 22; break;
12755 case MT_GREEN_STEEL: chance -= 16; break;
12756 case MT_MERCURIAL: chance -= 4; break;
12757 case MT_BRONZE: chance -= 28; break;
12758 case MT_TITANIUM: chance -= 26; break;
12759 case MT_COPPER: chance -= 24; break;
12760 case MT_COBALT: chance -= 22; break;
12761 case MT_SILVER: chance -= 24; break;
12762 case MT_GOLD: chance -= 10; break;
12763 case MT_TINSEL: chance -= 12; break;
12764 case MT_PLATINUM: chance -= 26; break;
12765 case MT_FILM: chance -= 26; break;
12766 case MT_ALLOY: chance -= 26; break;
12767 case MT_MITHRIL: chance -= 18; break;
12768 case MT_VIVA: chance -= 16; break;
12769 case MT_POURPOOR: chance -= 30; break;
12770 case MT_LEAD: chance -= 40; break;
12771 case MT_CHROME: chance -= 14; break;
12775 if (uarmc && is_metallic(uarmc) && !is_etheritem(uarmc) && !is_meteosteelitem(uarmc)) {
12777 switch (objects[(uarmc)->otyp].oc_material) {
12778 default: chance -= 20; break;
12779 case MT_METAL: chance -= 22; break;
12780 case MT_STEEL: chance -= 22; break;
12781 case MT_GREEN_STEEL: chance -= 16; break;
12782 case MT_MERCURIAL: chance -= 4; break;
12783 case MT_BRONZE: chance -= 28; break;
12784 case MT_TITANIUM: chance -= 26; break;
12785 case MT_COPPER: chance -= 24; break;
12786 case MT_COBALT: chance -= 22; break;
12787 case MT_SILVER: chance -= 24; break;
12788 case MT_GOLD: chance -= 10; break;
12789 case MT_TINSEL: chance -= 12; break;
12790 case MT_PLATINUM: chance -= 26; break;
12791 case MT_FILM: chance -= 26; break;
12792 case MT_ALLOY: chance -= 26; break;
12793 case MT_MITHRIL: chance -= 18; break;
12794 case MT_VIVA: chance -= 16; break;
12795 case MT_POURPOOR: chance -= 30; break;
12796 case MT_LEAD: chance -= 40; break;
12797 case MT_CHROME: chance -= 14; break;
12801 if (uarmh && is_metallic(uarmh) && !is_etheritem(uarmh) && !is_meteosteelitem(uarmh)) {
12803 switch (objects[(uarmh)->otyp].oc_material) {
12804 default: chance -= 20; break;
12805 case MT_METAL: chance -= 22; break;
12806 case MT_STEEL: chance -= 22; break;
12807 case MT_GREEN_STEEL: chance -= 16; break;
12808 case MT_MERCURIAL: chance -= 4; break;
12809 case MT_BRONZE: chance -= 28; break;
12810 case MT_TITANIUM: chance -= 26; break;
12811 case MT_COPPER: chance -= 24; break;
12812 case MT_COBALT: chance -= 22; break;
12813 case MT_SILVER: chance -= 24; break;
12814 case MT_GOLD: chance -= 10; break;
12815 case MT_TINSEL: chance -= 12; break;
12816 case MT_PLATINUM: chance -= 26; break;
12817 case MT_FILM: chance -= 26; break;
12818 case MT_ALLOY: chance -= 26; break;
12819 case MT_MITHRIL: chance -= 18; break;
12820 case MT_VIVA: chance -= 16; break;
12821 case MT_POURPOOR: chance -= 30; break;
12822 case MT_LEAD: chance -= 40; break;
12823 case MT_CHROME: chance -= 14; break;
12827 if (uarms && is_metallic(uarms) && !is_etheritem(uarms) && !is_meteosteelitem(uarms)) {
12829 switch (objects[(uarms)->otyp].oc_material) {
12830 default: chance -= 20; break;
12831 case MT_METAL: chance -= 22; break;
12832 case MT_STEEL: chance -= 22; break;
12833 case MT_GREEN_STEEL: chance -= 16; break;
12834 case MT_MERCURIAL: chance -= 4; break;
12835 case MT_BRONZE: chance -= 28; break;
12836 case MT_TITANIUM: chance -= 26; break;
12837 case MT_COPPER: chance -= 24; break;
12838 case MT_COBALT: chance -= 22; break;
12839 case MT_SILVER: chance -= 24; break;
12840 case MT_GOLD: chance -= 10; break;
12841 case MT_TINSEL: chance -= 12; break;
12842 case MT_PLATINUM: chance -= 26; break;
12843 case MT_FILM: chance -= 26; break;
12844 case MT_ALLOY: chance -= 26; break;
12845 case MT_MITHRIL: chance -= 18; break;
12846 case MT_VIVA: chance -= 16; break;
12847 case MT_POURPOOR: chance -= 30; break;
12848 case MT_LEAD: chance -= 40; break;
12849 case MT_CHROME: chance -= 14; break;
12853 if (uarmg && is_metallic(uarmg) && !is_etheritem(uarmg) && !is_meteosteelitem(uarmg)) {
12855 switch (objects[(uarmg)->otyp].oc_material) {
12856 default: chance -= 20; break;
12857 case MT_METAL: chance -= 22; break;
12858 case MT_STEEL: chance -= 22; break;
12859 case MT_GREEN_STEEL: chance -= 16; break;
12860 case MT_MERCURIAL: chance -= 4; break;
12861 case MT_BRONZE: chance -= 28; break;
12862 case MT_TITANIUM: chance -= 26; break;
12863 case MT_COPPER: chance -= 24; break;
12864 case MT_COBALT: chance -= 22; break;
12865 case MT_SILVER: chance -= 24; break;
12866 case MT_GOLD: chance -= 10; break;
12867 case MT_TINSEL: chance -= 12; break;
12868 case MT_PLATINUM: chance -= 26; break;
12869 case MT_FILM: chance -= 26; break;
12870 case MT_ALLOY: chance -= 26; break;
12871 case MT_MITHRIL: chance -= 18; break;
12872 case MT_VIVA: chance -= 16; break;
12873 case MT_POURPOOR: chance -= 30; break;
12874 case MT_LEAD: chance -= 40; break;
12875 case MT_CHROME: chance -= 14; break;
12879 if (uarmf && is_metallic(uarmf) && !is_etheritem(uarmf) && !is_meteosteelitem(uarmf)) {
12881 switch (objects[(uarmf)->otyp].oc_material) {
12882 default: chance -= 20; break;
12883 case MT_METAL: chance -= 22; break;
12884 case MT_STEEL: chance -= 22; break;
12885 case MT_GREEN_STEEL: chance -= 16; break;
12886 case MT_MERCURIAL: chance -= 4; break;
12887 case MT_BRONZE: chance -= 28; break;
12888 case MT_TITANIUM: chance -= 26; break;
12889 case MT_COPPER: chance -= 24; break;
12890 case MT_COBALT: chance -= 22; break;
12891 case MT_SILVER: chance -= 24; break;
12892 case MT_GOLD: chance -= 10; break;
12893 case MT_TINSEL: chance -= 12; break;
12894 case MT_PLATINUM: chance -= 26; break;
12895 case MT_FILM: chance -= 26; break;
12896 case MT_ALLOY: chance -= 26; break;
12897 case MT_MITHRIL: chance -= 18; break;
12898 case MT_VIVA: chance -= 16; break;
12899 case MT_POURPOOR: chance -= 30; break;
12900 case MT_LEAD: chance -= 40; break;
12901 case MT_CHROME: chance -= 14; break;
12905 if (uarmu && is_metallic(uarmu) && !is_etheritem(uarmu) && !is_meteosteelitem(uarmu)) {
12907 switch (objects[(uarmu)->otyp].oc_material) {
12908 default: chance -= 20; break;
12909 case MT_METAL: chance -= 22; break;
12910 case MT_STEEL: chance -= 22; break;
12911 case MT_GREEN_STEEL: chance -= 16; break;
12912 case MT_MERCURIAL: chance -= 4; break;
12913 case MT_BRONZE: chance -= 28; break;
12914 case MT_TITANIUM: chance -= 26; break;
12915 case MT_COPPER: chance -= 24; break;
12916 case MT_COBALT: chance -= 22; break;
12917 case MT_SILVER: chance -= 24; break;
12918 case MT_GOLD: chance -= 10; break;
12919 case MT_TINSEL: chance -= 12; break;
12920 case MT_PLATINUM: chance -= 26; break;
12921 case MT_FILM: chance -= 26; break;
12922 case MT_ALLOY: chance -= 26; break;
12923 case MT_MITHRIL: chance -= 18; break;
12924 case MT_VIVA: chance -= 16; break;
12925 case MT_POURPOOR: chance -= 30; break;
12926 case MT_LEAD: chance -= 40; break;
12927 case MT_CHROME: chance -= 14; break;
12931 if (uamul && is_metallic(uamul) && !is_etheritem(uamul) && !is_meteosteelitem(uamul)) {
12933 switch (objects[(uamul)->otyp].oc_material) {
12934 default: chance -= 20; break;
12935 case MT_METAL: chance -= 22; break;
12936 case MT_STEEL: chance -= 22; break;
12937 case MT_GREEN_STEEL: chance -= 16; break;
12938 case MT_MERCURIAL: chance -= 4; break;
12939 case MT_BRONZE: chance -= 28; break;
12940 case MT_TITANIUM: chance -= 26; break;
12941 case MT_COPPER: chance -= 24; break;
12942 case MT_COBALT: chance -= 22; break;
12943 case MT_SILVER: chance -= 24; break;
12944 case MT_GOLD: chance -= 10; break;
12945 case MT_TINSEL: chance -= 12; break;
12946 case MT_PLATINUM: chance -= 26; break;
12947 case MT_FILM: chance -= 26; break;
12948 case MT_ALLOY: chance -= 26; break;
12949 case MT_MITHRIL: chance -= 18; break;
12950 case MT_VIVA: chance -= 16; break;
12951 case MT_POURPOOR: chance -= 30; break;
12952 case MT_LEAD: chance -= 40; break;
12953 case MT_CHROME: chance -= 14; break;
12957 if (uimplant && is_metallic(uimplant) && !is_etheritem(uimplant) && !is_meteosteelitem(uimplant)) {
12959 switch (objects[(uimplant)->otyp].oc_material) {
12960 default: chance -= 20; break;
12961 case MT_METAL: chance -= 22; break;
12962 case MT_STEEL: chance -= 22; break;
12963 case MT_GREEN_STEEL: chance -= 16; break;
12964 case MT_MERCURIAL: chance -= 4; break;
12965 case MT_BRONZE: chance -= 28; break;
12966 case MT_TITANIUM: chance -= 26; break;
12967 case MT_COPPER: chance -= 24; break;
12968 case MT_COBALT: chance -= 22; break;
12969 case MT_SILVER: chance -= 24; break;
12970 case MT_GOLD: chance -= 10; break;
12971 case MT_TINSEL: chance -= 12; break;
12972 case MT_PLATINUM: chance -= 26; break;
12973 case MT_FILM: chance -= 26; break;
12974 case MT_ALLOY: chance -= 26; break;
12975 case MT_MITHRIL: chance -= 18; break;
12976 case MT_VIVA: chance -= 16; break;
12977 case MT_POURPOOR: chance -= 30; break;
12978 case MT_LEAD: chance -= 40; break;
12979 case MT_CHROME: chance -= 14; break;
12983 if (uleft && is_metallic(uleft) && !is_etheritem(uleft) && !is_meteosteelitem(uleft)) {
12985 switch (objects[(uleft)->otyp].oc_material) {
12986 default: chance -= 20; break;
12987 case MT_METAL: chance -= 22; break;
12988 case MT_STEEL: chance -= 22; break;
12989 case MT_GREEN_STEEL: chance -= 16; break;
12990 case MT_MERCURIAL: chance -= 4; break;
12991 case MT_BRONZE: chance -= 28; break;
12992 case MT_TITANIUM: chance -= 26; break;
12993 case MT_COPPER: chance -= 24; break;
12994 case MT_COBALT: chance -= 22; break;
12995 case MT_SILVER: chance -= 24; break;
12996 case MT_GOLD: chance -= 10; break;
12997 case MT_TINSEL: chance -= 12; break;
12998 case MT_PLATINUM: chance -= 26; break;
12999 case MT_FILM: chance -= 26; break;
13000 case MT_ALLOY: chance -= 26; break;
13001 case MT_MITHRIL: chance -= 18; break;
13002 case MT_VIVA: chance -= 16; break;
13003 case MT_POURPOOR: chance -= 30; break;
13004 case MT_LEAD: chance -= 40; break;
13005 case MT_CHROME: chance -= 14; break;
13009 if (uright && is_metallic(uright) && !is_etheritem(uright) && !is_meteosteelitem(uright)) {
13011 switch (objects[(uright)->otyp].oc_material) {
13012 default: chance -= 20; break;
13013 case MT_METAL: chance -= 22; break;
13014 case MT_STEEL: chance -= 22; break;
13015 case MT_GREEN_STEEL: chance -= 16; break;
13016 case MT_MERCURIAL: chance -= 4; break;
13017 case MT_BRONZE: chance -= 28; break;
13018 case MT_TITANIUM: chance -= 26; break;
13019 case MT_COPPER: chance -= 24; break;
13020 case MT_COBALT: chance -= 22; break;
13021 case MT_SILVER: chance -= 24; break;
13022 case MT_GOLD: chance -= 10; break;
13023 case MT_TINSEL: chance -= 12; break;
13024 case MT_PLATINUM: chance -= 26; break;
13025 case MT_FILM: chance -= 26; break;
13026 case MT_ALLOY: chance -= 26; break;
13027 case MT_MITHRIL: chance -= 18; break;
13028 case MT_VIVA: chance -= 16; break;
13029 case MT_POURPOOR: chance -= 30; break;
13030 case MT_LEAD: chance -= 40; break;
13031 case MT_CHROME: chance -= 14; break;
13035 if (ublindf && is_metallic(ublindf) && !is_etheritem(ublindf) && !is_meteosteelitem(ublindf)) {
13037 switch (objects[(ublindf)->otyp].oc_material) {
13038 default: chance -= 20; break;
13039 case MT_METAL: chance -= 22; break;
13040 case MT_STEEL: chance -= 22; break;
13041 case MT_GREEN_STEEL: chance -= 16; break;
13042 case MT_MERCURIAL: chance -= 4; break;
13043 case MT_BRONZE: chance -= 28; break;
13044 case MT_TITANIUM: chance -= 26; break;
13045 case MT_COPPER: chance -= 24; break;
13046 case MT_COBALT: chance -= 22; break;
13047 case MT_SILVER: chance -= 24; break;
13048 case MT_GOLD: chance -= 10; break;
13049 case MT_TINSEL: chance -= 12; break;
13050 case MT_PLATINUM: chance -= 26; break;
13051 case MT_FILM: chance -= 26; break;
13052 case MT_ALLOY: chance -= 26; break;
13053 case MT_MITHRIL: chance -= 18; break;
13054 case MT_VIVA: chance -= 16; break;
13055 case MT_POURPOOR: chance -= 30; break;
13056 case MT_LEAD: chance -= 40; break;
13057 case MT_CHROME: chance -= 14; break;
13063 if (Upolyd && dmgtype(youmonst.data, AD_SPEL) ) {
13064 chance += 5;
13066 if (Upolyd && dmgtype(youmonst.data, AD_CLRC) ) {
13067 chance += 5;
13069 if (Upolyd && dmgtype(youmonst.data, AD_CAST) ) {
13070 chance += 10;
13073 if (!PlayerCannotUseSkills && uwep && is_lightsaber(uwep) && (uwep->lamplit || Role_if(PM_SHADOW_JEDI)) ) {
13074 switch (P_SKILL(P_NIMAN)) {
13075 default: break;
13076 case P_BASIC: chance += 5; break;
13077 case P_SKILLED: chance += 10; break;
13078 case P_EXPERT: chance += 15; break;
13079 case P_MASTER: chance += 20; break;
13080 case P_GRAND_MASTER: chance += 25; break;
13081 case P_SUPREME_MASTER: chance += 30; break;
13086 if (!PlayerCannotUseSkills) {
13087 switch (P_SKILL(P_NIMAN)) {
13088 default: break;
13089 case P_BASIC: chance += 1; break;
13090 case P_SKILLED: chance += 2; break;
13091 case P_EXPERT: chance += 3; break;
13092 case P_MASTER: chance += 4; break;
13093 case P_GRAND_MASTER: chance += 5; break;
13094 case P_SUPREME_MASTER: chance += 6; break;
13099 if (Race_if(PM_INKA) && spellid(spell) == SPE_NATURE_BEAM)
13100 chance += 100;
13102 if (Race_if(PM_VIETIS)) chance -= 20;
13104 if (uarmc && itemhasappearance(uarmc, APP_DNETHACK_CLOAK)) chance -= 10;
13105 if (uarms && uarms->oartifact == ART_DNETHACKC_NOONISHNESS) chance -= 10;
13106 if (RngeDnethack) chance -= 10;
13107 if (Race_if(PM_INHERITOR)) chance -= 10;
13108 if (RngeUnnethack) chance -= 33;
13109 if (ACURR(A_INT) < 3) chance -= 25;
13111 /* artifacts and other items that boost the chance after "hard" penalties are applied go here --Amy */
13113 if (uarmc && itemhasappearance(uarmc, APP_FAILUNCAP_CLOAK) ) chance += 5;
13114 if (uarmh && itemhasappearance(uarmh, APP_FAILUNCAP_HELMET) ) chance += 5;
13115 if (uarmg && itemhasappearance(uarmg, APP_FAILUNCAP_GLOVES) ) chance += 5;
13116 if (uarmf && itemhasappearance(uarmf, APP_FAILUNCAP_SHOES) ) chance += 5;
13117 if (uarm && uarm->oartifact == ART_ALTADOON_HERMA_MORA) chance += 20;
13118 if (uarmg && uarmg->oartifact == ART_HOGWILD_WIZ) chance += 5;
13119 if (uarmg && uarmg->oartifact == ART_WAND_INTO_SPELL) chance += 10;
13120 if (have_magicrystal()) chance += 5;
13121 if (uarmh && uarmh->oartifact == ART_ALL_THE_BETTER_SPELLING) chance += 5;
13123 if (uwep && uwep->oartifact == ART_RASSCHEN_TAAK) chance += 5;
13125 if (Role_if(PM_OTAKU) && uarmc && itemhasappearance(uarmc, APP_FOURCHAN_CLOAK)) chance += 5;
13127 /* very high INT gives a boost, even if your casting stat is WIS --Amy */
13128 if (ACURR(A_INT) >= 16) {
13129 chance += (ACURR(A_INT) - 15);
13132 if (uarm && uarm->oartifact == ART_MOTHERFUCKER_TROPHY) {
13133 chance += 20;
13136 /* "bullshit change" by Amy: make it quite a bit harder to get to 0% fail, because spells are generally easier to
13137 * cast compared to vanilla which results in difficult spells being too easy for non-caster roles
13138 * THIS MUST COME AFTER ANYTHING THAT BOOSTS THE CHANCE */
13139 if (chance > 50) {
13140 int chancediff = (chance - 50);
13141 chancediff /= 2;
13142 if (chancediff > 50) chancediff = 50;
13143 chance -= chancediff;
13145 if (chance > 90) {
13146 int chancediff = (chance - 90);
13147 chancediff *= 9;
13148 chancediff /= 10;
13149 if (chancediff > 90) chancediff = 90;
13150 chance -= chancediff;
13154 /* Clamp to percentile */
13155 if (chance > 100) chance = 100;
13157 if (RememberanceEffect || u.uprops[REMEMBERANCE_EFFECT].extrinsic || have_rememberancestone()) {
13158 if (chance > (spellknow(spell) / 100)) chance = (spellknow(spell) / 100);
13161 if (uarmc && itemhasappearance(uarmc, APP_SHELL_CLOAK) ) chance -= 20;
13163 if (is_grassland(u.ux, u.uy) && !(uarm && uarm->oartifact == ART_DORL_TSCH) && !(uarmf && itemhasappearance(uarmf, APP_GARDEN_SLIPPERS))) chance -= 10;
13164 if (Numbed) chance -= 10;
13166 if (Role_if(PM_FAILED_EXISTENCE)) chance /= 2; /* at least 50% fail for all spells */
13167 if (uarms && uarms->otyp == COMPLETE_BLOCKAGE_SHIELD) chance /= 2;
13168 if (uarmc && uarmc->oartifact == ART_ARTIFICIAL_FAKE_DIFFICULTY) {
13169 chance *= 5;
13170 chance /= 6;
13172 if (ACURR(A_INT) == 1) { /* 25% autofail if you're as stupid as possible */
13173 chance *= 3;
13174 chance /= 4;
13177 if (Race_if(PM_INHERITOR)) chance--;
13179 /* REALLY clamp chance now */
13180 if (chance > 100) chance = 100;
13182 if (SpellColorSilver) {
13184 if (chance == 50) chance = 100;
13185 else if (chance == 100) chance = 10;
13186 else if (chance > 50) chance -= ((chance - 50) * 2);
13187 else if (chance > 0) chance *= 2;
13191 if (chance < (issoviet ? 0 : (spellev(spell) == 8) ? 0 : (spellev(spell) == 7) ? 1 : (spellev(spell) == 6) ? 2 : (spellev(spell) == 5) ? 5 : 10) ) chance = (issoviet ? 0 : (spellev(spell) == 8) ? 0 : (spellev(spell) == 7) ? 1 : (spellev(spell) == 6) ? 2 : (spellev(spell) == 5) ? 5 : 10); /* used to be 0, but that was just stupid in my opinion --Amy */
13193 return chance;
13196 /* increase memory of a spell: now a function; inspired by Elona, the increase is now lower if your current spell memory
13197 * is already rather high. We're trying to make the decrease not be too harsh at first, but 2000% spell memory should be
13198 * extremely difficult to reach. */
13199 void
13200 boostknow(spell,boost)
13201 int spell, boost;
13203 int priorknow = spl_book[spell].sp_know;
13204 int boostmultiplier = 100;
13205 if (priorknow > 190100) boostmultiplier = 1;
13206 else if (priorknow > 180100) boostmultiplier = 2;
13207 else if (priorknow > 170100) boostmultiplier = 3;
13208 else if (priorknow > 160100) boostmultiplier = 4;
13209 else if (priorknow > 150100) boostmultiplier = 5;
13210 else if (priorknow > 140100) boostmultiplier = 6;
13211 else if (priorknow > 130100) boostmultiplier = 7;
13212 else if (priorknow > 120100) boostmultiplier = 8;
13213 else if (priorknow > 110100) boostmultiplier = 9;
13214 else if (priorknow > 100100) boostmultiplier = 10;
13215 else if (priorknow > 90100) boostmultiplier = 15;
13216 else if (priorknow > 80100) boostmultiplier = 20;
13217 else if (priorknow > 70100) boostmultiplier = 30;
13218 else if (priorknow > 60100) boostmultiplier = 40;
13219 else if (priorknow > 50100) boostmultiplier = 50;
13220 else if (priorknow > 40100) boostmultiplier = 60;
13221 else if (priorknow > 30100) boostmultiplier = 70;
13222 else if (priorknow > 20100) boostmultiplier = 80;
13223 else if (priorknow > 10100) boostmultiplier = 90;
13225 boost *= boostmultiplier;
13226 boost /= 100;
13228 if (MagicVacuum) {
13229 boost /= (StrongMagicVacuum) ? 5 : 2;
13230 if (priorknow > 9999) boost /= 2;
13233 if (boost < 0) boost = 0;
13235 spl_book[spell].sp_know = ((spl_book[spell].sp_know + boost > MAX_KNOW) ? MAX_KNOW : (spl_book[spell].sp_know + boost) );
13239 /* reduce memory of a spell, e.g. because you have cyan spells or cast stuff like add spell memory */
13240 void
13241 drainknow(spell, drainamount)
13242 int spell, drainamount;
13244 if (spl_book[spell].sp_know < drainamount) spl_book[spell].sp_know = 0;
13245 else spl_book[spell].sp_know -= drainamount;
13248 void
13249 incrnknow(spell, initial)
13250 int spell;
13251 boolean initial; /* FALSE if you knew the spell before, otherwise TRUE; reduction only if FALSE */
13253 int priorknow = spl_book[spell].sp_know;
13254 int knowvalue = (Race_if(PM_DUNADAN) ? DUNADAN_KEEN : KEEN);
13255 int boostmultiplier = 100;
13256 if (priorknow > 190100) boostmultiplier = 1;
13257 else if (priorknow > 180100) boostmultiplier = 2;
13258 else if (priorknow > 170100) boostmultiplier = 3;
13259 else if (priorknow > 160100) boostmultiplier = 4;
13260 else if (priorknow > 150100) boostmultiplier = 5;
13261 else if (priorknow > 140100) boostmultiplier = 6;
13262 else if (priorknow > 130100) boostmultiplier = 7;
13263 else if (priorknow > 120100) boostmultiplier = 8;
13264 else if (priorknow > 110100) boostmultiplier = 9;
13265 else if (priorknow > 100100) boostmultiplier = 10;
13266 else if (priorknow > 90100) boostmultiplier = 15;
13267 else if (priorknow > 80100) boostmultiplier = 20;
13268 else if (priorknow > 70100) boostmultiplier = 30;
13269 else if (priorknow > 60100) boostmultiplier = 40;
13270 else if (priorknow > 50100) boostmultiplier = 50;
13271 else if (priorknow > 40100) boostmultiplier = 60;
13272 else if (priorknow > 30100) boostmultiplier = 70;
13273 else if (priorknow > 20100) boostmultiplier = 80;
13274 else if (priorknow > 10100) boostmultiplier = 90;
13276 if (initial) boostmultiplier = 100;
13278 knowvalue *= boostmultiplier;
13279 knowvalue /= 100;
13281 if (MagicVacuum) {
13282 knowvalue /= (StrongMagicVacuum) ? 5 : 2;
13283 if (priorknow > 9999) knowvalue /= 2;
13286 if (knowvalue < 0) knowvalue = 0;
13288 spl_book[spell].sp_know = (spl_book[spell].sp_know < 1) ? knowvalue : ((spl_book[spell].sp_know + knowvalue) > MAX_KNOW) ? MAX_KNOW : (spl_book[spell].sp_know + knowvalue);
13293 /* oh my god why oh why does that have to depend on an actual item, why can't we use the item's ID --Amy */
13294 void
13295 initialspell(obj)
13296 struct obj *obj;
13298 initialwonderspell(obj->otyp);
13302 /* Learn a spell during creation of the initial inventory */
13303 void
13304 initialwonderspell(wospelnum)
13305 int wospelnum;
13307 int i;
13309 for (i = 0; i < MAXSPELL; i++) {
13310 if (spellid(i) == wospelnum) { /* not a bug - after all, you might e.g. play a haxor --Amy */
13311 /* pline("Error: Spell %s already known.", OBJ_NAME(objects[wospelnum])); */
13313 /* In Soviet Russia, enhancements aren't a thing. In fact, they don't even know how to spell the word 'enhancement'. Therefore, if someone goes ahead and suggests an enhancement that consists of double spellbooks giving twice the starting spellcasting memory, they say NOPE THAT IS INCOMPATIBLE WITH COMMUNISM and refuse to implement it. --Amy */
13314 if (!issoviet) {
13315 incrnknow(i, TRUE);
13316 if (Role_if(PM_MAHOU_SHOUJO)) incrnknow(i, TRUE);
13318 if (spl_book[i].sp_lev == 3) incrnknow(i, TRUE);
13319 if (spl_book[i].sp_lev == 4) { incrnknow(i, TRUE); incrnknow(i, TRUE);}
13320 if (spl_book[i].sp_lev == 5) { incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE);}
13321 if (spl_book[i].sp_lev == 6) { incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE);}
13322 if (spl_book[i].sp_lev == 7) { incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE);}
13323 if (spl_book[i].sp_lev == 8) { incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE);}
13326 return;
13328 if (spellid(i) == NO_SPELL) {
13329 spl_book[i].sp_id = wospelnum;
13330 spl_book[i].sp_lev = objects[wospelnum].oc_level;
13331 spl_book[i].sp_memorize = TRUE;
13332 incrnknow(i, TRUE);
13333 if (Role_if(PM_MAHOU_SHOUJO)) incrnknow(i, TRUE);
13335 /* high-level starting spells will be known for a longer time
13336 * since you might not be able to cast them at all when you're just starting --Amy */
13337 if (spl_book[i].sp_lev == 3) incrnknow(i, TRUE);
13338 if (spl_book[i].sp_lev == 4) { incrnknow(i, TRUE); incrnknow(i, TRUE);}
13339 if (spl_book[i].sp_lev == 5) { incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE);}
13340 if (spl_book[i].sp_lev == 6) { incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE);}
13341 if (spl_book[i].sp_lev == 7) { incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE);}
13342 if (spl_book[i].sp_lev == 8) { incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE); incrnknow(i, TRUE);}
13344 return;
13347 impossible("Too many spells memorized!");
13348 return;
13351 boolean
13352 studyspell()
13354 /*Vars are for studying spells 'W', 'F', 'I', 'N'*/
13355 int spell_no;
13357 if (getspell(&spell_no, FALSE)) {
13358 if (spellknow(spell_no) <= 0) {
13359 You("are unable to focus your memory of the spell.");
13360 return (FALSE);
13361 } else if (spellknow(spell_no) <= 1000) {
13362 Your("focus and reinforce your memory of the spell.");
13363 incrnknow(spell_no, FALSE);
13364 if (Role_if(PM_MAHOU_SHOUJO)) incrnknow(spell_no, FALSE);
13365 exercise(A_WIS, TRUE); /* extra study */
13366 return (TRUE);
13367 } else if (spellknow(spell_no) < 11000) {
13368 int studyvalue = Race_if(PM_DUNADAN) ? DUNADAN_KEEN : KEEN;
13369 int studydiff = 11000 - spellknow(spell_no); /* between 1 and 10000 */
13371 studyvalue *= studydiff;
13372 studyvalue /= 10000;
13374 Your("focus and reinforce your memory of the spell.");
13375 boostknow(spell_no, studyvalue);
13376 if (Role_if(PM_MAHOU_SHOUJO)) boostknow(spell_no, studyvalue);
13377 return (TRUE);
13378 } else /* 11000 < spellknow(spell_no) <= whatever the maximum is */
13379 You("know that spell quite well already.");
13381 return (FALSE);
13384 boolean
13385 inertiacontrolspell()
13387 int spell_no;
13389 if (getspell(&spell_no, FALSE)) {
13390 if (spellid(spell_no) == SPE_INERTIA_CONTROL) {
13391 You("cannot control the inertia control spell.");
13392 return (FALSE);
13393 } else if (spellid(spell_no) != NO_SPELL) {
13394 u.inertiacontrolspell = spellid(spell_no);
13395 u.inertiacontrolspellno = spell_no;
13396 u.inertiacontrol = 50;
13397 You("start controlling the %s spell.", spellname(spell_no));
13398 return (TRUE);
13399 } else {
13400 You("decided to not control any spell after all.");
13401 return (FALSE);
13404 return (FALSE);
13407 boolean
13408 dememorizespell()
13410 int spell_no;
13412 if (getspell(&spell_no, FALSE)) {
13413 if (spellid(spell_no) != NO_SPELL) {
13414 spl_book[spell_no].sp_know = 0;
13415 pline("Alright, the %s spell is a forgotten spell now.", spellname(spell_no));
13416 return (TRUE);
13417 } else {
13418 You("decided to not dememorize any spell after all.");
13419 return (FALSE);
13423 return (FALSE);
13426 boolean
13427 addsomespellmemory()
13429 int spell_no;
13431 if (getspell(&spell_no, FALSE)) {
13432 if (spellid(spell_no) == SPE_ADD_SPELL_MEMORY) {
13433 You("cannot add memory to that spell.");
13434 } else if (spellid(spell_no) != NO_SPELL) {
13435 if (rn2(10) && spellknow(spell_no) <= 0) {
13436 pline("Your attempt to regain knowledge of that forgotten spell fails.");
13437 return (TRUE);
13439 pline("Your knowledge of the %s spell increases.", spellname(spell_no));
13440 boostknow(spell_no, 500);
13441 return (TRUE);
13442 } else {
13443 You("decided to not add memory to any spell after all.");
13444 return (FALSE);
13448 return (FALSE);
13451 void
13452 extramemory()
13454 if (spellid(0) == NO_SPELL) {
13455 You("don't know any spells, and therefore you cannot add spell memory to them either.");
13456 return;
13459 pline("Choose a spell to add spell memory.");
13460 addxtragain:
13461 if (!addsomespellmemoryX()) {
13462 if (yn("Really exit with no spell selected?") == 'y')
13463 pline("You just wasted the opportunity to add memory to a spell.");
13464 else goto addxtragain;
13468 boolean
13469 addsomespellmemoryX()
13471 int spell_no;
13473 if (getspell(&spell_no, FALSE)) {
13474 if (spellid(spell_no) != NO_SPELL) {
13475 if (rn2(20) && spellknow(spell_no) <= 0) {
13476 pline("Your attempt to regain knowledge of that forgotten spell fails.");
13477 return (TRUE);
13479 pline("Your knowledge of the %s spell increases.", spellname(spell_no));
13480 boostknow(spell_no, rnd(5000));
13481 return (TRUE);
13482 } else {
13483 You("decided to not add memory to any spell after all.");
13484 return (FALSE);
13488 return (FALSE);
13491 /* Assumes u.dx, u.dy already set up */
13492 static int
13493 spell_dash()
13495 register int dashrange = 2;
13497 if (!(PlayerCannotUseSkills) && P_SKILL(P_ELEMENTAL_SPELL) >= P_SKILLED) {
13498 switch (P_SKILL(P_ELEMENTAL_SPELL)) {
13499 default: break;
13500 case P_SKILLED: dashrange = 3; break;
13501 case P_EXPERT: dashrange = 4; break;
13502 case P_MASTER: dashrange = 5; break;
13503 case P_GRAND_MASTER: dashrange = 6; break;
13504 case P_SUPREME_MASTER: dashrange = 7; break;
13508 while (dashrange > 2) {
13509 pline("Current dash range: %d.", dashrange);
13510 if (yn("Reduce the range by one?") == 'y') {
13511 dashrange--;
13512 } else goto dashrangefinish;
13515 dashrangefinish:
13517 if ((!Punished || carried(uball)) && !u.utrap)
13518 You("dash forwards!");
13519 hurtle(u.dx, u.dy, dashrange, FALSE);
13520 multi = 0; /* No paralysis with dash */
13521 return 1;
13524 /* percentage chance for mastermind role to resist amnesia and spell forgetting effects --Amy */
13525 boolean
13526 mastermindsave()
13528 int mmchance = 0;
13530 if (!Role_if(PM_MASTERMIND)) return FALSE; /* shouldn't happen */
13532 if (PlayerCannotUseSkills) return FALSE;
13534 switch (P_SKILL(P_MEMORIZATION)) {
13535 case P_BASIC: mmchance = 20; break;
13536 case P_SKILLED: mmchance = 40; break;
13537 case P_EXPERT: mmchance = 60; break;
13538 case P_MASTER: mmchance = 80; break;
13539 case P_GRAND_MASTER: mmchance = 90; break;
13540 case P_SUPREME_MASTER: mmchance = 95; break;
13543 if (mmchance > rn2(100)) return TRUE;
13545 return FALSE;
13549 /* lose all spells unconditionally --Amy */
13550 void
13551 delete_all_spells()
13553 int n;
13555 for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++) {
13556 spellid(n) = NO_SPELL;
13561 /* calculation for mana cost, externalized --Amy */
13563 manacost(spellnum)
13564 int spellnum;
13566 int energy = (objects[spellnum].oc_level * 5);
13567 if (energy < 5) energy = 5; /* fail safe */
13569 switch (spellnum) {
13570 case SPE_FINGER_OF_DEATH: energy *= 3; break;
13571 case SPE_TIME: energy *= 4; break;
13572 case SPE_INERTIA: energy *= 4; break;
13573 case SPE_TIME_STOP: energy *= 5; break;
13574 case SPE_PARALYSIS: energy *= 2; break;
13575 case SPE_HELLISH_BOLT: energy *= 2; break;
13576 case SPE_PETRIFY: energy *= 4; break;
13577 case SPE_JUMPING: energy *= 5; break;
13578 case SPE_ARMOR_SMASH: energy *= 5; energy /= 3; break;
13579 case SPE_GODMODE: energy *= 5; energy /= 2; break;
13580 case SPE_DISINTEGRATION: energy *= 5; break;
13581 case SPE_DISINTEGRATION_BEAM: energy *= 5; break;
13582 case SPE_FIXING: energy *= 3; break;
13583 case SPE_CONVERGE_BREATH: energy *= 4; break;
13584 case SPE_CHROMATIC_BEAM: energy *= 10; energy /= 7; break;
13585 case SPE_HEALING: energy *= 3; energy /= 2; break;
13586 case SPE_WATER_FLAME: energy *= 3; energy /= 2; break;
13587 case SPE_FIREBALL: energy *= 2; break;
13588 case SPE_SHINING_WAVE: energy *= 5; break;
13589 case SPE_RELOCATION: energy *= 5; break;
13590 case SPE_FIRE_BOLT: energy *= 3; energy /= 2; break;
13591 case SPE_DEFENSIVE_FIREBALL: energy *= 3; energy /= 2; break;
13592 case SPE_CONE_OF_COLD: energy *= 3; energy /= 2; break;
13593 case SPE_MULTIBEAM: energy *= 6; energy /= 5; break;
13594 case SPE_CALL_THE_ELEMENTS: energy *= 7; energy /= 4; break;
13595 case SPE_INFERNO: energy *= 3; energy /= 2; break;
13596 case SPE_ICE_BEAM: energy *= 3; energy /= 2; break;
13597 case SPE_HYPER_BEAM: energy *= 4; energy /= 3; break;
13598 case SPE_ELEMENTAL_BEAM: energy *= 6; energy /= 5; break;
13599 case SPE_NATURE_BEAM: energy *= 5; energy /= 4; break;
13600 case SPE_ULTRA_P: energy *= 3; energy /= 2; break;
13601 default: break;
13604 return energy;
13607 /* learn a random spell ("whichspell" == -1) or a specific one ("whichspell" = ID of the book) --Amy */
13608 void
13609 wonderspell(whichspell)
13610 int whichspell;
13612 register int randomspell = SPE_FORCE_BOLT + rn2((SPE_PSYBEAM + 1) - SPE_FORCE_BOLT);
13614 if (whichspell != -1) randomspell = whichspell;
13616 char splname[BUFSZ];
13617 int i;
13619 sprintf(splname, "%s", OBJ_NAME(objects[randomspell]) );
13621 for (i = 0; i < MAXSPELL; i++) {
13622 if (spellid(i) == randomspell) {
13623 if (spellknow(i) <= MAX_CAN_STUDY) {
13624 Your("knowledge of the %s spell is keener.", splname);
13625 incrnknow(i, FALSE);
13626 if (u.emynluincomplete) boostknow(i, 1000);
13627 if (uarmg && itemhasappearance(uarmg, APP_RUNIC_GLOVES) && !rn2(2) ) incrnknow(i, FALSE);
13628 if (Role_if(PM_MAHOU_SHOUJO)) incrnknow(i, FALSE);
13630 if (!PlayerCannotUseSkills && P_SKILL(P_MEMORIZATION) >= P_BASIC) {
13632 char nervbuf[QBUFSZ];
13633 char thisisannoying = 0;
13635 if (!u.youhavememorized) {
13636 u.youhavememorized = TRUE;
13637 if (!iflags.memorizationknown) pline("You have the memorization skill, which allows you to gain extra spell memory for newly learned spells. Whenever you learn a spell, you are asked whether you want to use the skill to boost the new spell's memory. In the case of doubt you should ALWAYS ANSWER YES. If you answer no, you just throw the bonus away. (Exception is if you want a forgotten spell, but you only ever need one of those normally.)");
13640 if (!iflags.memorizationknown) sprintf(nervbuf, "Memorize this spell to add more spell memory? In the case of doubt you should always answer yes, unless you want the bonus to go to waste.");
13641 else sprintf(nervbuf, "Memorize this spell to add more spell memory?");
13642 thisisannoying = yn_function(nervbuf, ynqchars, 'y');
13643 if (thisisannoying != 'n') {
13645 int memoboost = 0;
13646 switch (P_SKILL(P_MEMORIZATION)) {
13647 case P_BASIC: memoboost = 2; break;
13648 case P_SKILLED: memoboost = 4; break;
13649 case P_EXPERT: memoboost = 6; break;
13650 case P_MASTER: memoboost = 8; break;
13651 case P_GRAND_MASTER: memoboost = 10; break;
13652 case P_SUPREME_MASTER: memoboost = 12; break;
13654 boostknow(i, memoboost * 1000);
13655 spl_book[i].sp_memorize = TRUE;
13656 pline("Spell memory increased! You gained %d%% extra spell memory.", memoboost * 10);
13657 } else {
13658 spl_book[i].sp_memorize = FALSE;
13659 pline("You decided to throw away the spell memory bonus. The spell was set to non-memorization mode. If you did that by mistake, you should open the spell menu and turn memorization for this spell back on so that it properly benefits from memorization skill.");
13664 } else {
13665 You("know %s quite well already.", splname);
13667 break;
13668 } else if (spellid(i) == NO_SPELL) {
13669 spl_book[i].sp_id = randomspell;
13670 spl_book[i].sp_lev = objects[randomspell].oc_level;
13671 spl_book[i].sp_memorize = TRUE;
13672 incrnknow(i, TRUE);
13673 if (u.emynluincomplete) boostknow(i, 1000);
13674 if (uarmg && itemhasappearance(uarmg, APP_RUNIC_GLOVES) && !rn2(2) ) incrnknow(i, TRUE);
13675 if (Role_if(PM_MAHOU_SHOUJO)) incrnknow(i, TRUE);
13676 You("gain knowledge of the %s spell.", splname);
13677 if (randomspell == SPE_FORBIDDEN_KNOWLEDGE) {
13678 u.ugangr += 15;
13679 if (flags.soundok) You_hear("a thunderous growling and rumbling...");
13680 if (PlayerHearsSoundEffects) pline(issoviet ? "Pozdravlyayu, teper' vashe bozhestvo ochen' zol. Pochemu ty ne molish'sya? Eto mozhet byt' prosto privesti svoyu zhizn' do kontsa, a zatem vy mozhete svernut' luchshe, nesovetskimi kharakter nakonets-to! SDELAY ETO SEYCHAS!" : "Grrrrrrr! Grummel! Wummmmmm!");
13683 if (randomspell == SPE_AMNESIA) {
13684 You_feel("dizzy!");
13685 forget(ALL_MAP, FALSE);
13688 if (!PlayerCannotUseSkills && P_SKILL(P_MEMORIZATION) >= P_BASIC) {
13690 char nervbuf[QBUFSZ];
13691 char thisisannoying = 0;
13693 if (!u.youhavememorized) {
13694 u.youhavememorized = TRUE;
13695 if (!iflags.memorizationknown) pline("You have the memorization skill, which allows you to gain extra spell memory for newly learned spells. Whenever you learn a spell, you are asked whether you want to use the skill to boost the new spell's memory. In the case of doubt you should ALWAYS ANSWER YES. If you answer no, you just throw the bonus away. (Exception is if you want a forgotten spell, but you only ever need one of those normally.)");
13698 if (!iflags.memorizationknown) sprintf(nervbuf, "Memorize this spell to add more spell memory? In the case of doubt you should always answer yes, unless you want the bonus to go to waste.");
13699 else sprintf(nervbuf, "Memorize this spell to add more spell memory?");
13700 thisisannoying = yn_function(nervbuf, ynqchars, 'y');
13701 if (thisisannoying != 'n') {
13703 int memoboost = 0;
13704 switch (P_SKILL(P_MEMORIZATION)) {
13705 case P_BASIC: memoboost = 2; break;
13706 case P_SKILLED: memoboost = 4; break;
13707 case P_EXPERT: memoboost = 6; break;
13708 case P_MASTER: memoboost = 8; break;
13709 case P_GRAND_MASTER: memoboost = 10; break;
13710 case P_SUPREME_MASTER: memoboost = 12; break;
13712 boostknow(i, memoboost * 1000);
13713 spl_book[i].sp_memorize = TRUE;
13714 pline("Spell memory increased! You gained %d%% extra spell memory.", memoboost * 10);
13715 } else {
13716 spl_book[i].sp_memorize = FALSE;
13717 pline("You decided to throw away the spell memory bonus. The spell was set to non-memorization mode. If you did that by mistake, you should open the spell menu and turn memorization for this spell back on so that it properly benefits from memorization skill.");
13722 break;
13728 /*spell.c*/