Wikia

Wikihack

Source:NetHack 2.2a/spell.c

2,032pages on
this wiki
Talk0

Below is the full text to spell.c from the source code of NetHack 2.2a. To link to a particular line, write [[NetHack 2.2a/spell.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

Screenshots and source code from Hack are used under the CWI license.
1.    /*	SCCS Id: @(#)spell.c	2.1	87/10/07
2.     */
3.    
4.    #include "hack.h"
5.    #ifdef SPELLS
6.    extern char *nomovemsg;
7.    
8.    doxcribe() {
9.    	register struct obj *book;
10.   	struct	 obj	*getobj();
11.   	register boolean confused = (Confusion != 0);
12.   	register boolean oops;
13.   	register schar	 delay;
14.   	register int   booktype;
15.   	register int	 i;
16.   
17.   	book = getobj("+", "transcribe");
18.   	if(!book) return(0);
19.   
20.   	if(Blind) {
21.   	    pline("Being blind, you cannot read the mystic runes.");
22.   	    useup(book);		/* well, if you are stupid... */
23.   	    return(0);
24.   	}
25.   
26.   	if(confused) {
27.   	    pline("Being confused, you cannot grasp the meaning of this tome.");
28.   	    useup(book);		/* and more stupidity... */
29.   	    return(0);
30.   	}
31.   	booktype = book->otyp;
32.   	oops = !rn2(u.ulevel - objects[booktype].spl_lev + 7);
33.   	switch(booktype)  {
34.   
35.   /* level 1 spells */
36.   	case SPE_HEALING:
37.   	case SPE_DETECT_MONSTERS:
38.   	case SPE_FORCE_BOLT:
39.   	case SPE_LIGHT:
40.   	case SPE_SLEEP:
41.   /* level 2 spells */
42.   	case SPE_MAGIC_MISSILE:
43.   	case SPE_CONFUSE_MONSTER:
44.   	case SPE_SLOW_MONSTER:
45.   	case SPE_CURE_BLINDNESS:
46.   	case SPE_CREATE_MONSTER:
47.   	case SPE_DETECT_FOOD:
48.   		delay = -objects[booktype].oc_delay;
49.   		break;
50.   /* level 3 spells */
51.   	case SPE_HASTE_SELF:
52.   	case SPE_CAUSE_FEAR:
53.   	case SPE_CURE_SICKNESS:
54.   	case SPE_DETECT_UNSEEN:
55.   	case SPE_EXTRA_HEALING:
56.   	case SPE_CHARM_MONSTER:
57.   /* level 4 spells */
58.   	case SPE_LEVITATION:
59.   	case SPE_RESTORE_STRENGTH:
60.   	case SPE_INVISIBILITY:
61.   	case SPE_FIREBALL:
62.   	case SPE_DETECT_TREASURE:
63.   		delay = -(objects[booktype].spl_lev - 1) * objects[booktype].oc_delay;
64.   		break;
65.   /* level 5 spells */
66.   	case SPE_REMOVE_CURSE:
67.   	case SPE_MAGIC_MAPPING:
68.   	case SPE_CONE_OF_COLD:
69.   	case SPE_IDENTIFY:
70.   	case SPE_DIG:
71.   /* level 6 spells */
72.   	case SPE_TURN_UNDEAD:
73.   	case SPE_POLYMORPH:
74.   	case SPE_CREATE_FAMILIAR:
75.   	case SPE_TELEPORT_AWAY:
76.   		delay = -objects[booktype].spl_lev * objects[booktype].oc_delay;
77.   		break;
78.   /* level 7 spells */
79.   	case SPE_CANCELLATION:
80.   	case SPE_FINGER_OF_DEATH:
81.   	case SPE_GENOCIDE:
82.   		delay = -8 * objects[booktype].oc_delay;
83.   		break;
84.   /* impossible */
85.   	default:
86.   		impossible("Unknown spell-book, %d;", booktype);
87.   		return(0);
88.   	}
89.   
90.   	pline("You begin to transcribe the spell.");
91.   	if(oops || book->cursed)  {
92.   		cursed_book(objects[booktype].spl_lev);
93.   		nomul(delay);			/* study time */
94.   	} else  {
95.   		nomul(delay);			/* study time */
96.   		for(i = 0; i < MAXSPELL; i++)  {
97.   		    if(spl_book[i].sp_id == booktype)  {
98.   #ifdef HARD
99.   			nomovemsg = "You make that spell more legible.";
100.  			spl_book[i].sp_uses += rn1(3,8-spl_book[i].sp_lev);
101.  #else			
102.  			nomovemsg = "Oh, you already know that one!";
103.  #endif
104.  			useup(book);
105.  			return(1);
106.  		    } else if (spl_book[i].sp_id == NO_SPELL)  {
107.  			spl_book[i].sp_id = booktype;
108.  			spl_book[i].sp_lev = objects[booktype].spl_lev;
109.  			spl_book[i].sp_flags = objects[booktype].bits;
110.  #ifdef HARD
111.  			/* spells have 2 .. 10-level uses. */
112.  			/* ie 2 or 3 uses w/ most potent */
113.  			spl_book[i].sp_uses = rn1(3,8-spl_book[i].sp_lev);
114.  #endif
115.  			nomovemsg = "You add the spell to your books.";
116.  			objects[booktype].oc_name_known = 1;
117.  			useup(book);
118.  			return(1);
119.  		    }
120.  		}
121.  		impossible("Too many spells in spellbook!");
122.  	}
123.  	useup(book);
124.  	return(1);
125.  }
126.  
127.  cursed_book(level)
128.  	register int	level;
129.  {
130.  	switch(rn2(level)) {
131.  	case 0:
132.  		pline("You feel a wrenching sensation.");
133.  		tele();		/* teleport him */
134.  		break;
135.  	case 1:
136.  		pline("You feel threatened.");
137.  		aggravate();
138.  		break;
139.  	case 2:
140.  		if(!Blind)	pline("A cloud of darkness falls upon you.");
141.  		Blinded += rn1(100,250);
142.  		seeoff(0);
143.  		break;
144.  	case 3:
145.  		if (u.ugold <= 0)  {
146.  			pline("You feel a strange sensation.");
147.  		} else {
148.  			pline("You notice you have no gold!");
149.  			u.ugold = 0;
150.  			flags.botl = 1;
151.  		}
152.  		break;
153.  	case 4:
154.  		pline("These runes were just too much to comprehend.");
155.  		HConfusion += rn1(7,16);
156.  		break;
157.  	case 5:
158.  		pline("The book was coated with contact poison!");
159.  		if(Poison_resistance) {
160.  		    losestr(rn1(1,2));
161.  		    losehp(rnd(6), "contact poison");
162.  		} else {
163.  		    losestr(rn1(4,3));
164.  		    losehp(rnd(10), "contact poison");
165.  		}
166.  		break;
167.  	case 6:
168.  		pline("As you read the book, it explodes in your face!");
169.  		losehp (2*rnd(10)+5, "exploding rune");
170.  		break;
171.  	default:
172.  		rndcurse();
173.  		break;
174.  	}
175.  	return(0);
176.  }
177.  
178.  docast()
179.  {
180.  	register int	 spell, energy, damage;
181.  	register boolean confused = (Confusion != 0);
182.  	register struct  obj	*pseudo;
183.  	struct	 obj	 *mksobj();
184.  
185.  	spell = getspell();
186.  	if (!spell) return(0);
187.  	else  {
188.  #ifdef HARD
189.  		/* note that turning to the page decrements the # of uses,  */
190.  		/* even if the mage does not have enough food/energy to use */
191.  		/* the spell */
192.  		switch (spelluses(spell)) {
193.  		case 0:
194.  		    pline ("That page is too faint to read at the moment.");
195.  		    return(0);
196.  		case 1:
197.  		    pline ("You can barely make out the runes on this page.");
198.  		    break;
199.  		case 2:
200.  		    pline ("This spell is starting to look well used.");
201.  		    break;
202.  		default:
203.  		    break;
204.  		}
205.  		decrnuses(spell);
206.  #endif		
207.  		energy = spellev(spell);
208.  #ifdef BVH
209.  		if (has_amulet()) {
210.  
211.  		    pline("You feel the amulet draining your energy away.");
212.  		    energy *= rnd(6);
213.  		}
214.  #endif
215.  		if(energy > u.uen)  {
216.  			pline("You are too weak to cast that spell.");
217.  			return(0);
218.  		} else  if ((u.uhunger <= 100) || (u.ustr < 6))  {
219.  			pline("You miss the strength for that spell.");
220.  			return(0);
221.  		} else	{
222.  			morehungry(energy * 10);
223.  			u.uen -= energy;
224.  		}
225.  		flags.botl = 1;
226.  	}
227.  #ifdef HARD
228.  	if (confused ||
229.  	    (rn2(10) + (int)(u.ulevel + u.uluck) - 3*spellev(spell)) < 0) {
230.  
231.  		if (Hallucination)
232.  			pline("Far out... a light show!");
233.  		else	pline("The air around you crackles as you goof up.");
234.  		return(0);
235.  	}
236.  #endif
237.  
238.  /*	pseudo is a temporary "false" object containing the spell stats. */
239.  	pseudo = mksobj(spellid(spell));
240.  	pseudo->quan = 20;			/* do not let useup get it */
241.  	switch(pseudo->otyp)  {
242.  
243.  /* These spells are all duplicates of wand effects */
244.  	case SPE_FORCE_BOLT:
245.  	case SPE_SLEEP:
246.  	case SPE_MAGIC_MISSILE:
247.  	case SPE_SLOW_MONSTER:
248.  	case SPE_FIREBALL:
249.  	case SPE_CONE_OF_COLD:
250.  	case SPE_DIG:
251.  	case SPE_TURN_UNDEAD:
252.  	case SPE_POLYMORPH:
253.  	case SPE_TELEPORT_AWAY:
254.  	case SPE_CANCELLATION:
255.  	case SPE_FINGER_OF_DEATH:
256.  	case SPE_LIGHT:
257.  	case SPE_DETECT_UNSEEN:
258.  		if (!(objects[pseudo->otyp].bits & NODIR)) {
259.  			getdir(1);
260.  			if(!u.dx && !u.dy && !u.dz && (u.ulevel > 8)) {
261.  			    if((damage = zapyourself(pseudo)))
262.  				losehp(damage, "self-inflicted injury");
263.  			} else	weffects(pseudo);
264.  		} else weffects(pseudo);
265.  		break;
266.  /* These are all duplicates of scroll effects */
267.  	case SPE_CONFUSE_MONSTER:
268.  	case SPE_DETECT_FOOD:
269.  	case SPE_CAUSE_FEAR:
270.  	case SPE_CHARM_MONSTER:
271.  	case SPE_REMOVE_CURSE:
272.  	case SPE_MAGIC_MAPPING:
273.  	case SPE_CREATE_MONSTER:
274.  	case SPE_IDENTIFY:
275.  	case SPE_GENOCIDE:
276.  		seffects(pseudo);
277.  		break;
278.  	case SPE_HASTE_SELF:
279.  	case SPE_DETECT_TREASURE:
280.  	case SPE_DETECT_MONSTERS:
281.  	case SPE_LEVITATION:
282.  	case SPE_RESTORE_STRENGTH:
283.  	case SPE_INVISIBILITY:
284.  		peffects(pseudo);
285.  		break;
286.  	case SPE_HEALING:
287.  		pline("You feel a bit better.");
288.  		healup(rnd(8), 0, 0, 0);
289.  		break;
290.  	case SPE_CURE_BLINDNESS:
291.  		healup(0, 0, 0, 1);
292.  		break;
293.  	case SPE_CURE_SICKNESS:
294.  		pline("You are no longer ill.");
295.  		healup(0, 0, 1, 0);
296.  		break;
297.  	case SPE_EXTRA_HEALING:
298.  		pline("You feel a fair bit better.");
299.  		healup(d(2,8), 1, 0, 0);
300.  		break;
301.  	case SPE_CREATE_FAMILIAR:
302.  		{	register struct monst *mtmp;
303.  			struct   monst  *makedog();
304.  
305.  			mtmp = makedog();
306.  			if(mtmp) {
307.  				/* make it into something else */
308.  				(void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]);
309.  				if(confused)
310.  					mtmp->mtame = mtmp->mpeaceful = 0;
311.  			}
312.  		}
313.  		break;
314.  	default:
315.  		impossible("Unknown spell %d attempted.", spell);
316.  		obfree(pseudo, (struct obj *)0);
317.  		return(0);
318.  	}
319.  	obfree(pseudo, (struct obj *)0);	/* now, get rid of it */
320.  	return(1);
321.  }
322.  
323.  getspell()  {
324.  
325.  	register int	max, ilet, i;
326.  	char	 lets[BUFSZ], buf[BUFSZ];
327.  
328.  	if (spl_book[0].sp_id == NO_SPELL)  {
329.  
330.  		pline("You don't know any spells right now.");
331.  		return(0);
332.  	} else  {
333.  
334.  	    for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++);
335.  	    if (max >= MAXSPELL)  {
336.  
337.  		impossible("Too many spells memorized.");
338.  		return(0);
339.  	    }
340.  
341.  	    for(i = 0; (i < max) && (i < 26); buf[++i] = 0)  buf[i] = 'a' + i;
342.  	    for(i = 26; (i < max) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26;
343.  
344.  	    if (max == 1)  strcpy(lets, "a");
345.  	    else if (max < 27)  sprintf(lets, "a-%c", 'a' + max - 1);
346.  	    else if (max == 27)  sprintf(lets, "a-z A");
347.  	    else sprintf(lets, "a-z A-%c", 'A' + max - 27);
348.  	    for(;;)  {
349.  
350.  		pline("Cast which spell [%s ?]: ", lets);
351.  		if ((ilet = readchar()) == '?')  {
352.  			dovspell();
353.  			continue;
354.  		} else if ((ilet == '\033')||(ilet == '\n')||(ilet == ' '))
355.  			return(0);
356.  		else for(i = 0; buf[i] != 0; i++)  if(ilet == buf[i])  return(++i);
357.  		pline("You don't know that spell.");
358.  	    }
359.  	}
360.  }
361.  
362.  losespells() {
363.  	register boolean confused = (Confusion != 0);
364.  	register int	 n, nzap, i;
365.  
366.  	for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++);
367.  	if (!n) return;
368.  	if (n < MAXSPELL) {
369.  		nzap = rnd(n);
370.  		if (nzap < n) nzap += confused;
371.  		for (i = 0; i < nzap; i++) spl_book[n-i-1].sp_id = NO_SPELL;
372.  	} else impossible("Too many spells in spellbook!");
373.  	return;
374.  }
375.  
376.  dovspell() {
377.  
378.  	register int max, i, side;
379.  	char     buf[BUFSZ],
380.  		 *spellname();
381.  
382.  	if (spl_book[0].sp_id == NO_SPELL)  {
383.  
384.  		pline("You don't know any spells right now.");
385.  		return(0);
386.  	} else  {
387.  
388.  	    for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++);
389.  	    if (max >= MAXSPELL)  {
390.  
391.  		impossible("Too many spells memorized.");
392.  		return(0);
393.  	    }
394.  	}
395.  	set_pager(0);
396.  	side = (max + 1) / 2;
397.  	if(page_line("Currently known spells:") || page_line(""))  goto quit;
398.  
399.  	for(i = 1; i <= side; i++) {
400.  
401.  		if((i < side) || !(max % 2))  {
402.  
403.  		    (void) sprintf(buf, "%c - (%d) %22s          %c - (%d) %22s",
404.  				   spellet(i), spellev(i), spellname(i),
405.  				   spellet(i + side), spellev(i + side), spellname(i + side));
406.  		} else {
407.  
408.  		    (void) sprintf(buf, "%c - (%d) %22s", spellet(i), spellev(i), spellname(i));
409.  		}
410.  		if(page_line(buf)) goto quit;
411.  	}
412.  
413.  	set_pager(1);
414.  	return(0);
415.  quit:
416.  	set_pager(2);
417.  	return(0);
418.  }
419.  
420.  spellet(spl)  {
421.  
422.  	if (spl < 27)	return('a' + spl - 1);
423.  	else		return('A' + spl - 27);
424.  }
425.  
426.  spellev(spl)  {
427.  
428.  	return(spl_book[spl-1].sp_lev);
429.  }
430.  
431.  char *
432.  spellname(spl)  {
433.  
434.  	return(objects[spl_book[spl-1].sp_id].oc_name);
435.  }
436.  
437.  spellid(spl)  {		return(spl_book[spl-1].sp_id);		}
438.  
439.  #ifdef HARD
440.  spelluses(spell) {	return(spl_book[spell-1].sp_uses);	}
441.  decrnuses(spell) {	spl_book[spell-1].sp_uses--;		}
442.  #endif
443.  
444.  #endif /* SPELLS /**/

Around Wikia's network

Random Wiki