Source:NetHack 3.1.0/music.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to music.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/music.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: @(#)music.c	3.1	92/11/26	*/
2.    /* 	Copyright (c) 1989 by Jean-Christophe Collet */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    /*
6.     * This file contains the different functions designed to manipulate the
7.     * musical instruments and their various effects.
8.     *
9.     * Actually the list of instruments / effects is :
10.    *
11.    * (wooden) flute	may calm snakes if player has enough dexterity
12.    * magic flute		may put monsters to sleep:  area of effect depends
13.    *			on player level.
14.    * (tooled) horn	Will awaken monsters:  area of effect depends on player
15.    *			level.  May also scare monsters.
16.    * fire horn		Acts like a wand of fire.
17.    * frost horn		Acts like a wand of cold.
18.    * bugle		Will awaken soldiers (if any):  area of effect depends
19.    *			on player level.
20.    * (wooden) harp	May calm nymph if player has enough dexterity.
21.    * magic harp		Charm monsters:  area of effect depends on player
22.    *			level.
23.    * (leather) drum	Will awaken monsters like the horn.
24.    * drum of earthquake	Will initiate an earthquake whose intensity depends
25.    *			on player level.  That is, it creates ramdom pits
26.    *			called here chasms.
27.    */
28.   
29.   #include "hack.h"
30.   
31.   static void FDECL(awaken_monsters,(int));
32.   static void FDECL(put_monsters_to_sleep,(int));
33.   static void FDECL(charm_snakes,(int));
34.   static void FDECL(calm_nymphs,(int));
35.   static void FDECL(charm_monsters,(int));
36.   static void FDECL(do_earthquake,(int));
37.   static int FDECL(do_improvisation,(struct obj *));
38.   
39.   /*
40.    * Wake every monster in range...
41.    */
42.   
43.   static void
44.   awaken_monsters(distance)
45.   int distance;
46.   {
47.   	register struct monst *mtmp = fmon;
48.   
49.   	while(mtmp) {
50.   		if (distu(mtmp->mx, mtmp->my) < distance/3) {
51.   			/* May scare some monsters */
52.   			if (!resist(mtmp, SCROLL_CLASS, 0, NOTELL))
53.   			  mtmp->mflee = 1;
54.   		} else if (distu(mtmp->mx, mtmp->my) < distance) {
55.   			mtmp->msleep = 0;
56.   			mtmp->mcanmove = 1;
57.   			mtmp->mfrozen = 0;
58.   		}
59.   		mtmp = mtmp->nmon;
60.   	}
61.   }
62.   
63.   /*
64.    * Make monsters fall asleep.  Note that they may resist the spell.
65.    */
66.   
67.   static void
68.   put_monsters_to_sleep(distance)
69.   int distance;
70.   {
71.   	register struct monst *mtmp = fmon;
72.   
73.   	while(mtmp) {
74.   		  if (distu(mtmp->mx, mtmp->my) < distance)
75.   		    if(mtmp->mcanmove && !resist(mtmp, WAND_CLASS, 0, NOTELL))
76.   		      mtmp->mcanmove = mtmp->mfrozen = 0;
77.   		mtmp = mtmp->nmon;
78.   	}
79.   }
80.   
81.   /*
82.    * Charm snakes in range.  Note that the snakes are NOT tamed.
83.    */
84.   
85.   static void
86.   charm_snakes(distance)
87.   int distance;
88.   {
89.   	register struct monst *mtmp = fmon;
90.   
91.   	while (mtmp) {
92.   		if (mtmp->data->mlet == S_SNAKE &&
93.   		    distu(mtmp->mx, mtmp->my) < distance) {
94.   			mtmp->mpeaceful = 1;
95.   			if (cansee(mtmp->mx, mtmp->my))
96.   				pline(
97.    "%s freezes and sways with the music, then seems quieter.", Monnam(mtmp));
98.   		}
99.   		mtmp = mtmp->nmon;
100.  	}
101.  }
102.  
103.  /*
104.   * Calm nymphs in range.
105.   */
106.  
107.  static void
108.  calm_nymphs(distance)
109.  int distance;
110.  {
111.  	register struct monst *mtmp = fmon;
112.  
113.  	while (mtmp) {
114.  		if (mtmp->data->mlet == S_NYMPH &&
115.  		    distu(mtmp->mx, mtmp->my) < distance) {
116.  			mtmp->mpeaceful = 1;
117.  			if (cansee(mtmp->mx, mtmp->my))
118.  				pline(
119.   "%s listens cheerfully to the music, then seems quieter.", Monnam(mtmp));
120.  		}
121.  		mtmp = mtmp->nmon;
122.  	}
123.  }
124.  
125.  /* Awake only soldiers of the level. */
126.  
127.  void
128.  awaken_soldiers() {
129.  #ifdef ARMY
130.  	register struct monst *mtmp = fmon;
131.  
132.  	while(mtmp) {
133.  	    if (is_mercenary(mtmp->data) && mtmp->data != &mons[PM_GUARD]) {
134.  		mtmp->mpeaceful = mtmp->msleep = 0;
135.  		mtmp->mcanmove = 1;
136.  		if (canseemon(mtmp))
137.  		    pline("%s is now ready for battle!", Monnam(mtmp));
138.  		else
139.  		    Norep("You hear the sound of battle gear being readied.");
140.  	    }
141.  	    mtmp = mtmp->nmon;
142.  	}
143.  #endif /* ARMY */
144.  }
145.  
146.  /* Charm monsters in range.  Note that they may resist the spell. */
147.  
148.  static void
149.  charm_monsters(distance)
150.  int distance;
151.  {
152.  	register struct monst *mtmp = fmon, *mtmp2;
153.  
154.  	while(mtmp) {
155.  		mtmp2 = mtmp->nmon;
156.  		if (distu(mtmp->mx, mtmp->my) <= distance)
157.  		    if(!resist(mtmp, SCROLL_CLASS, 0, NOTELL))
158.  			(void) tamedog(mtmp, (struct obj *) 0);
159.  		mtmp = mtmp2;
160.  	}
161.  
162.  }
163.  
164.  /* Generate earthquake :-) of desired force.
165.   * That is:  create random chasms (pits).
166.   */
167.  
168.  static void
169.  do_earthquake(force)
170.  int force;
171.  {
172.  	register int x,y;
173.  	struct monst *mtmp;
174.  	struct obj *otmp;
175.  	struct trap *chasm;
176.  	int start_x, start_y, end_x, end_y;
177.  
178.  	start_x = u.ux - (force * 2);
179.  	start_y = u.uy - (force * 2);
180.  	end_x = u.ux + (force * 2);
181.  	end_y = u.uy + (force * 2);
182.  	if (start_x < 1) start_x = 1;
183.  	if (start_y < 1) start_y = 1;
184.  	if (end_x >= COLNO) end_x = COLNO - 1;
185.  	if (end_y >= ROWNO) end_y = ROWNO - 1;
186.  	for (x=start_x; x<=end_x; x++) for (y=start_y; y<=end_y; y++) {
187.  	    if (mtmp = m_at(x,y)) {
188.  		if (mtmp->mundetected && is_hider(mtmp->data)) {
189.  		    mtmp->mundetected = 0;
190.  		    if (cansee(x,y))
191.  			pline("%s is shaken loose from the ceiling!",
192.  							    Amonnam(mtmp));
193.  		    else
194.  			You("hear a thumping sound.");
195.  		    if (x==u.ux && y==u.uy)
196.  			You("easily dodge the falling %s.",
197.  							    mon_nam(mtmp));
198.  		    newsym(x,y);
199.  		}
200.  	    }
201.  	    if (!rn2(14 - force)) switch (levl[x][y].typ) {
202.  		  case FOUNTAIN : /* Make the fountain disappear */
203.  			if (cansee(x,y))
204.  				pline("The fountain falls into a chasm.");
205.  			goto do_pit;
206.  #ifdef SINKS
207.  		  case SINK :
208.  			if (cansee(x,y))
209.  				pline("The kitchen sink falls into a chasm.");
210.  			goto do_pit;
211.  #endif
212.  		  case ALTAR :
213.  			if (cansee(x,y))
214.  				pline("The altar falls into a chasm.");
215.  			goto do_pit;
216.  		  case THRONE :
217.  			if (cansee(x,y))
218.  				pline("The throne falls into a chasm.");
219.  			/* Falls into next case */
220.  		  case ROOM :
221.  		  case CORR : /* Try to make a pit */
222.  do_pit:		    chasm = maketrap(x,y,PIT);
223.  		    chasm->tseen = 1;
224.  
225.  		    levl[x][y].doormask = 0;
226.  
227.  		    mtmp = m_at(x,y);
228.  
229.  		    if (otmp = sobj_at(BOULDER, x, y)) {
230.  			if (cansee(x, y))
231.  			   pline("KADOOM! The boulder falls into a chasm%s!",
232.  			      ((x == u.ux) && (y == u.uy)) ? " below you" : "");
233.  			if (mtmp)
234.  				mtmp->mtrapped = 0;
235.  			freeobj(otmp);
236.  			(void) flooreffects(otmp, x, y, "");
237.  			break;
238.  		    }	
239.  
240.  		    /* We have to check whether monsters or player
241.  		       falls in a chasm... */
242.  
243.  		    if (mtmp) {
244.  			if(!is_flyer(mtmp->data) && !is_clinger(mtmp->data)) {
245.  			    mtmp->mtrapped = 1;
246.  			    if(cansee(x,y))
247.  				pline("%s falls into a chasm!", Monnam(mtmp));
248.  			    else if (flags.soundok && humanoid(mtmp->data))
249.  				You("hear a scream!");
250.  			    if ((mtmp->mhp -= rnd(6)) <= 0) {
251.  				if(!cansee(x,y))
252.  				    pline("It is destroyed!");
253.  				else {
254.  				    You("destroy %s!", mtmp->mtame ?
255.  					x_monnam(mtmp, 0, "poor", 0) :
256.  					mon_nam(mtmp));
257.  				}
258.  				xkilled(mtmp,0);
259.  			    }
260.  			}
261.  		    } else if (x == u.ux && y == u.uy) {
262.  			    if (Levitation
263.  #ifdef POLYSELF
264.  				|| is_flyer(uasmon) || is_clinger(uasmon)
265.  #endif
266.  				) {
267.  				    pline("A chasm opens up under you!");
268.  				    You("don't fall in!");
269.  			    } else {
270.  				    You("fall into a chasm!");
271.  				    u.utrap = rn1(6,2);
272.  				    u.utraptype = TT_PIT;
273.  				    losehp(rnd(6),"fell into a chasm",
274.  					NO_KILLER_PREFIX);
275.  				    selftouch("Falling, you");
276.  			    }
277.  		    } else newsym(x,y);
278.  		    break;
279.  		  case DOOR : /* Make the door collapse */
280.  		    if (levl[x][y].doormask == D_NODOOR) break;
281.  		    if (cansee(x,y))
282.  			pline("The door collapses.");
283.  		    levl[x][y].doormask = D_NODOOR;
284.  		    newsym(x,y);
285.  		    break;
286.  	    }
287.  	}
288.  }
289.  
290.  /*
291.   * The player is trying to extract something from his/her instrument.
292.   */
293.  
294.  static int
295.  do_improvisation(instr)
296.  struct obj *instr;
297.  {
298.  	int damage;
299.  
300.  #ifdef MAC
301.  	mac_speaker ( instr , "C" ) ;
302.  #endif
303.  
304.  	if (Confusion)
305.  	  pline("What you produce is quite far from music...");
306.  	else
307.  	  You("start playing %s.", the(xname(instr)));
308.  	switch (instr->otyp) {
309.  	      case WOODEN_FLUTE:	/* May charm snakes */
310.  		if (rn2(ACURR(A_DEX)) + u.ulevel > 25)
311.  		  charm_snakes((int)u.ulevel*3);
312.  		exercise(A_DEX, TRUE);
313.  		break;
314.  	      case MAGIC_FLUTE: /* Make monster fall asleep */
315.  		if (instr->spe > 0) {
316.  			instr->spe--;
317.  			You("produce soft music.");
318.  			put_monsters_to_sleep((int)u.ulevel*5);
319.  		}
320.  		exercise(A_DEX, TRUE);
321.  		break;
322.  	      case TOOLED_HORN:	/* Awaken monsters or scare monsters */
323.  		You("produce a frightful, grave sound.");
324.  		awaken_monsters((int)u.ulevel*30);
325.  		exercise(A_WIS, FALSE);
326.  		break;
327.  	      case FROST_HORN:	/* Idem wand of cold */
328.  	      case FIRE_HORN:	/* Idem wand of fire */
329.  		if (instr->spe > 0) {
330.  			instr->spe--;
331.  			if (!getdir(NULL)) {
332.  				if (!Blind)
333.  				    pline("%s glows then fades.",
334.  					  The(xname(instr)));
335.  			} else {
336.  				if (!u.dx && !u.dy && !u.dz) {
337.  					if((damage = zapyourself(instr)))
338.  					  losehp(damage,
339.  		self_pronoun("using a magical horn on %sself", "him"),
340.  					  NO_KILLER_PREFIX);
341.  					makeknown(instr->otyp);
342.  					return(2);
343.  				}
344.  				buzz((instr->otyp == FROST_HORN) ? AD_COLD-1 : AD_FIRE-1, rn1(6,6), u.ux, u.uy, u.dx, u.dy);
345.  				makeknown(instr->otyp);
346.  				return(2);
347.  			}
348.  		}
349.  		break;
350.  	      case BUGLE:	/* Awaken & attract soldiers */
351.  		You("extract a loud noise from %s.", the(xname(instr)));
352.  		awaken_soldiers();
353.  		exercise(A_WIS, FALSE);
354.  		break;
355.  	      case WOODEN_HARP:	/* May calm Nymph */
356.  		if (rn2(ACURR(A_DEX)) + u.ulevel > 25)
357.  		  calm_nymphs((int)u.ulevel*3);
358.  		exercise(A_DEX, TRUE);
359.  		break;
360.  	      case MAGIC_HARP:	/* Charm monsters */
361.  		if (instr->spe > 0) {
362.  			pline("%s produces very attractive music.",
363.  			      The(xname(instr)));
364.  			instr->spe--;
365.  			charm_monsters(((int)u.ulevel - 1) / 3 + 1);
366.  		}
367.  		exercise(A_DEX, TRUE);
368.  		break;
369.  	      case LEATHER_DRUM:	/* Awaken monsters */
370.  		You("beat a deafening row!");
371.  		awaken_monsters((int)u.ulevel * 40);
372.  		exercise(A_WIS, FALSE);
373.  		break;
374.  	      case DRUM_OF_EARTHQUAKE:	/* create several pits */
375.  		if (instr->spe > 0) {
376.  			You("produce a heavy, thunderous rolling!");
377.  			pline("The entire dungeon is shaking around you!");
378.  			instr->spe--;
379.  			do_earthquake(((int)u.ulevel - 1) / 3 + 1);
380.  			makeknown(DRUM_OF_EARTHQUAKE);
381.  		}
382.  		break;
383.  	      default:
384.  		impossible("What a weird instrument (%d)!",instr->otyp);
385.  		break;
386.  	}
387.  	return (2);		/* That takes time */
388.  }
389.  
390.  #ifdef SYSV386MUSIC
391.  /*
392.   * Play audible music on the machine's speaker if appropriate.
393.   */
394.  
395.  static int
396.  atconsole()
397.  {
398.      /*
399.       * Kluge alert: This code assumes that your [34]86 has no X terminals
400.       * attached and that the console tty type is AT386 (this is always true
401.       * under AT&T UNIX for these boxen). The theory here is that your remote
402.       * ttys will have terminal type `ansi' or something else other than
403.       * `AT386' or `xterm'. We'd like to do better than this, but testing
404.       * to see if we're running on the console physical terminal is quite
405.       * difficult given the presence of virtual consoles and other modern
406.       * UNIX impedimenta...
407.       */
408.      char	*termtype = getenv("TERM");
409.  
410.       return(!strcmp(termtype, "AT386") || !strcmp(termtype, "xterm"));
411.  }
412.  
413.  static void
414.  speaker(instr, buf)
415.  struct obj *instr;
416.  char	*buf;
417.  {
418.      /*
419.       * For this to work, you need to have installed the PD speaker-control
420.       * driver for PC-compatible UNIX boxes that I (eric@snark.uu.net)
421.       * posted to comp.sources.unix in Feb 1990. A copy may be included
422.       * with your nethack distribution.
423.       */
424.      int	fd;
425.  
426.      if ((fd = open("/dev/speaker", 1)) != -1)
427.      {
428.  	/* emit a prefix to modify instrumental `timbre' */
429.  	switch (instr->otyp)
430.  	{
431.  	case WOODEN_FLUTE:
432.  	case MAGIC_FLUTE:
433.  	    (void) write(fd, ">ol", 1); /* up one octave & lock */
434.  	    break;
435.  	case TOOLED_HORN:
436.  	case FROST_HORN:
437.  	case FIRE_HORN:
438.  	    (void) write(fd, "<<ol", 2); /* drop two octaves & lock */
439.  	    break;
440.  	case BUGLE:
441.  	    (void) write(fd, "ol", 2); /* octave lock */
442.  	    break;
443.  	case WOODEN_HARP:
444.  	case MAGIC_HARP:
445.  	    (void) write(fd, "l8mlol", 4); /* fast, legato, octave lock */
446.  	    break;
447.  	}
448.  	(void) write(fd, buf, strlen(buf));
449.  	(void) close(fd);
450.      }
451.  }
452.  #endif /* SYSV386MUSIC */
453.  
454.  /*
455.   * So you want music...
456.   */
457.  
458.  int
459.  do_play_instrument(instr)
460.  struct obj *instr;
461.  {
462.      char buf[BUFSZ], *s, c = 'y';
463.      int x,y;
464.      boolean ok;
465.  
466.      if (Underwater) {
467.  	You("can't play music underwater!");
468.  	return(0);
469.      }
470.      if (instr->otyp != LEATHER_DRUM && instr->otyp != DRUM_OF_EARTHQUAKE) {
471.  	c = yn("Improvise?");
472.      }
473.      if (c == 'n') {
474.  	getlin("What tune are you playing? [what 5 notes]", buf);
475.  	for (s=buf; *s; s++) *s = highc(*s);
476.  	You("extract a strange sound from %s!", the(xname(instr)));
477.  #ifdef SYSV386MUSIC 
478.  	/* if user is at the console, play through the console speaker */
479.  	if (atconsole())
480.  	    speaker(instr, buf);
481.  #endif /* SYSV386MUSIC */
482.  #ifdef MAC
483.  	mac_speaker ( instr , buf ) ;
484.  #endif
485.  	/* Check if there was the Stronghold drawbridge near
486.  	 * and if the tune conforms to what we're waiting for.
487.  	 */
488.  	if(Is_stronghold(&u.uz)) {
489.  	    exercise(A_WIS, TRUE);		/* just for trying */
490.  	    if(!strcmp(buf,tune)) {
491.  		/* Search for the drawbridge */
492.  		for(y=u.uy-1; y<=u.uy+1; y++)
493.  		    for(x=u.ux-1;x<=u.ux+1;x++)
494.  			if(isok(x,y))
495.  			if(find_drawbridge(&x,&y)) {
496.  			    if(levl[x][y].typ == DRAWBRIDGE_DOWN)
497.  				close_drawbridge(x,y);
498.  			    else
499.  				open_drawbridge(x,y);
500.  			    return 0;
501.  			}
502.  	    } else if(flags.soundok) {
503.  		if (u.uevent.uheard_tune < 1) u.uevent.uheard_tune = 1;
504.  		/* Okay, it wasn't the right tune, but perhaps
505.  		 * we can give the player some hints like in the
506.  		 * Mastermind game */
507.  		ok = FALSE;
508.  		for(y = u.uy-1; y <= u.uy+1 && !ok; y++)
509.  		    for(x = u.ux-1; x <= u.ux+1 && !ok; x++)
510.  			if(isok(x,y))
511.  			if(IS_DRAWBRIDGE(levl[x][y].typ) ||
512.  			   is_drawbridge_wall(x,y) >= 0)
513.  				ok = TRUE;
514.  		if(ok) { /* There is a drawbridge near */
515.  		    int tumblers, gears;
516.  		    boolean matched[5];
517.  
518.  		    tumblers = gears = 0;
519.  		    for(x=0; x < 5; x++)
520.  			matched[x] = FALSE;
521.  
522.  		    for(x=0; x < (int)strlen(buf); x++)
523.  			if(x < 5) {
524.  			    if(buf[x] == tune[x]) {
525.  				gears++;
526.  				matched[x] = TRUE;
527.  			    } else
528.  				for(y=0; y < 5; y++)
529.  				    if(!matched[y] &&
530.  				       buf[x] == tune[y] &&
531.  				       buf[y] != tune[y]) {
532.  					tumblers++;
533.  					matched[y] = TRUE;
534.  					break;
535.  				    }
536.  			}
537.  		    if(tumblers)
538.  			if(gears)
539.  			    You("hear %d tumbler%s click and %d gear%s turn.",
540.  				tumblers, plur(tumblers), gears, plur(gears));
541.  			else
542.  			    You("hear %d tumbler%s click.",
543.  				tumblers, plur(tumblers));
544.  		    else if(gears) {
545.  			You("hear %d gear%s turn.", gears, plur(gears));
546.  			if (gears == 5) u.uevent.uheard_tune = 2;
547.  		    }
548.  		}
549.  	    }
550.  	  }
551.  	return 1;
552.      } else
553.  	    return do_improvisation(instr);
554.  }
555.  
556.  /*music.c*/