Source:NetHack 3.0.0/spell.c

From NetHackWiki
Revision as of 05:31, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.0.0/spell.c moved to Source:NetHack 3.0.0/spell.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

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

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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