1 /* SCCS Id: @(#)music.c 3.4 2003/05/25 */
2 /* Copyright (c) 1989 by Jean-Christophe Collet */
3 /* NetHack may be freely redistributed. See license for details. */
6 * This file contains the different functions designed to manipulate the
7 * musical instruments and their various effects.
9 * Actually the list of instruments / effects is :
11 * (wooden) flute may calm snakes if player has enough dexterity
12 * magic flute may put monsters to sleep: area of effect depends
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
20 * (wooden) harp May calm nymph if player has enough dexterity.
21 * magic harp Charm monsters: area of effect depends on player
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 random pits
31 STATIC_DCL
void put_monsters_to_sleep(int);
32 STATIC_DCL
void charm_snakes(int);
33 STATIC_DCL
void calm_nymphs(int);
34 STATIC_DCL
void charm_monsters(int);
35 /*STATIC_DCL void do_earthquake(int);*/
36 STATIC_DCL
int do_improvisation(struct obj
*);
39 STATIC_DCL
int atconsole(void);
40 STATIC_DCL
void speaker(struct obj
*,char *);
43 extern int sco_flag_console
; /* will need changing if not _M_UNIX */
44 STATIC_DCL
void playinit(void);
45 STATIC_DCL
void playstring(char *,size_t);
46 STATIC_DCL
void speaker(struct obj
*,char *);
49 void pc_speaker(struct obj
*, char * );
52 void amii_speaker(struct obj
*, char *, int );
56 * Wake every monster in range...
60 awaken_monsters(distance
)
63 register struct monst
*mtmp
= fmon
;
67 if (!DEADMONSTER(mtmp
)) {
68 distm
= distu(mtmp
->mx
, mtmp
->my
);
69 if (distm
< distance
) {
74 /* May scare some monsters */
75 if (distm
< distance
/3 &&
76 !resist(mtmp
, TOOL_CLASS
, 0, NOTELL
))
77 monflee(mtmp
, rnd(10), FALSE
, TRUE
);
85 * Make monsters fall asleep. Note that they may resist the spell.
89 put_monsters_to_sleep(distance
)
92 register struct monst
*mtmp
= fmon
;
95 if (!DEADMONSTER(mtmp
) && distu(mtmp
->mx
, mtmp
->my
) < distance
&&
96 sleep_monst(mtmp
, d(10,10), TOOL_CLASS
)) {
97 mtmp
->msleeping
= 1; /* 10d10 turns + wake_nearby to rouse */
105 * Charm snakes in range. Note that the snakes are NOT tamed.
109 charm_snakes(distance
)
112 register struct monst
*mtmp
= fmon
;
113 int could_see_mon
, was_peaceful
;
116 if (!DEADMONSTER(mtmp
) && mtmp
->data
->mlet
== S_SNAKE
&& mtmp
->mcanmove
&&
117 distu(mtmp
->mx
, mtmp
->my
) < distance
) {
118 was_peaceful
= mtmp
->mpeaceful
;
119 if (!mtmp
->mfrenzied
) {
123 could_see_mon
= canseemon(mtmp
);
124 mtmp
->mundetected
= 0;
125 newsym(mtmp
->mx
, mtmp
->my
);
126 if (canseemon(mtmp
)) {
128 You("notice %s, swaying with the music.",
131 pline("%s freezes, then sways with the music%s.",
133 was_peaceful
? "" : ", and now seems quieter");
141 * Calm nymphs in range.
145 calm_nymphs(distance
)
148 register struct monst
*mtmp
= fmon
;
151 if (!DEADMONSTER(mtmp
) && mtmp
->data
->mlet
== S_NYMPH
&& mtmp
->mcanmove
&&
152 distu(mtmp
->mx
, mtmp
->my
) < distance
) {
154 if (!mtmp
->mfrenzied
) {
160 "%s listens cheerfully to the music, then seems quieter.",
167 /* Awake only soldiers of the level. */
170 awaken_soldiers(awakeflag
)
173 register struct monst
*mtmp
= fmon
;
176 if (!DEADMONSTER(mtmp
) &&
177 ((is_mercenary(mtmp
->data
) && mtmp
->data
!= &mons
[PM_GUARD
] && mtmp
->data
!= &mons
[PM_MASTER_GUARD
] && mtmp
->data
!= &mons
[PM_EXPERIENCED_GUARD
] && mtmp
->data
!= &mons
[PM_EXCEPTIONAL_GUARD
] && mtmp
->data
!= &mons
[PM_ELITE_GUARD
] && mtmp
->data
!= &mons
[PM_CROUPIER
] && mtmp
->data
!= &mons
[PM_MASTER_CROUPIER
] && mtmp
->data
!= &mons
[PM_EXPERIENCED_CROUPIER
] && mtmp
->data
!= &mons
[PM_EXCEPTIONAL_CROUPIER
] && mtmp
->data
!= &mons
[PM_ELITE_CROUPIER
]) || (awakeflag
== 1)) ) {
178 mtmp
->mpeaceful
= mtmp
->msleeping
= mtmp
->mfrozen
= 0;
179 if (awakeflag
== 2 && !mtmp
->mtame
) mtmp
->mfrenzied
= 1;
183 pline("%s is now ready for battle!", Monnam(mtmp
));
185 Norep("You hear the rattle of battle gear being readied.");
191 /* Charm monsters in range. Note that they may resist the spell.
192 * If swallowed, range is reduced to 0.
196 charm_monsters(distance
)
199 struct monst
*mtmp
, *mtmp2
;
202 if (!resist(u
.ustuck
, TOOL_CLASS
, 0, NOTELL
))
203 (void) tamedog(u
.ustuck
, (struct obj
*) 0, FALSE
);
205 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp2
) {
207 if (DEADMONSTER(mtmp
)) continue;
209 if (distu(mtmp
->mx
, mtmp
->my
) <= distance
) {
210 if (!resist(mtmp
, TOOL_CLASS
, 0, NOTELL
))
211 (void) tamedog(mtmp
, (struct obj
*) 0, FALSE
);
218 /* Generate earthquake :-) of desired force.
219 * That is: create random chasms (pits).
230 int start_x
, start_y
, end_x
, end_y
;
232 pline("Magnitude %d!",force
);
234 start_x
= u
.ux
- (force
* 2);
235 start_y
= u
.uy
- (force
* 2);
236 end_x
= u
.ux
+ (force
* 2);
237 end_y
= u
.uy
+ (force
* 2);
238 if (start_x
< 1) start_x
= 1;
239 if (start_y
< 1) start_y
= 1;
240 if (end_x
>= COLNO
) end_x
= COLNO
- 1;
241 if (end_y
>= ROWNO
) end_y
= ROWNO
- 1;
242 for (x
=start_x
; x
<=end_x
; x
++) for (y
=start_y
; y
<=end_y
; y
++) {
243 if ((mtmp
= m_at(x
,y
)) != 0) {
244 wakeup(mtmp
); /* peaceful monster will become hostile */
245 if (mtmp
->mundetected
&& (is_hider(mtmp
->data
) || mtmp
->egotype_hide
|| mtmp
->egotype_mimic
) ) {
246 mtmp
->mundetected
= 0;
248 pline("%s is shaken loose from the ceiling!",
251 You_hear("a thumping sound.");
252 if (x
==u
.ux
&& y
==u
.uy
)
253 You("easily dodge the falling %s.",
258 if (!rn2(14 - force
)) switch (levl
[x
][y
].typ
) {
259 case FOUNTAIN
: /* Make the fountain disappear */
261 pline_The("fountain falls into a chasm.");
265 pline_The("kitchen sink falls into a chasm.");
269 pline("The toilet falls into a chasm.");
272 if (Is_astralevel(&u
.uz
) || Is_sanctum(&u
.uz
)) break;
275 pline_The("altar falls into a chasm.");
279 pline_The("headstone topples into a chasm.");
283 pline_The("throne falls into a chasm.");
284 /* Falls into next case */
286 case CORR
: /* Try to make a pit */
287 do_pit
: chasm
= maketrap(x
,y
,PIT
,0, FALSE
);
288 if (!chasm
) break; /* no pit if portal at that location */
289 if (!chasm
->hiddentrap
) chasm
->tseen
= 1;
291 levl
[x
][y
].doormask
= 0;
295 if ((otmp
= sobj_at(BOULDER
, x
, y
)) != 0) {
297 pline("KADOOM! The boulder falls into a chasm%s!",
298 ((x
== u
.ux
) && (y
== u
.uy
)) ? " below you" : "");
301 obj_extract_self(otmp
);
302 (void) flooreffects(otmp
, x
, y
, "");
306 /* We have to check whether monsters or player
307 falls in a chasm... */
310 if(!is_flyer(mtmp
->data
) && (!mtmp
->egotype_flying
) && !is_clinger(mtmp
->data
)) {
313 pline("%s falls into a chasm!", Monnam(mtmp
));
314 else if (flags
.soundok
&& humanoid(mtmp
->data
))
315 You_hear("a scream!");
316 mselftouch(mtmp
, "Falling, ", TRUE
);
318 if ((mtmp
->mhp
-= rnd(6)) <= 0) {
320 pline("It is destroyed!");
322 You("destroy %s!", mtmp
->mtame
?
323 x_monnam(mtmp
, ARTICLE_THE
, "poor",
324 mtmp
->mnamelth
? SUPPRESS_SADDLE
: 0, FALSE
):
330 } else if (x
== u
.ux
&& y
== u
.uy
) {
331 /* KMH, balance patch -- new intrinsic */
332 if (Levitation
|| Flying
||
333 is_clinger(youmonst
.data
)) {
334 pline("A chasm opens up under you!");
335 You("don't fall in!");
337 You("fall into a chasm!");
339 u
.utraptype
= TT_PIT
;
340 losehp(rnd(6),"fell into a chasm",
342 selftouch("Falling, you");
346 case DOOR
: /* Make the door collapse */
347 /* ALI - artifact doors */
348 if (artifact_door(x
, y
)) break;
349 if (levl
[x
][y
].doormask
== D_NODOOR
) goto do_pit
;
351 pline_The("door collapses.");
352 if (*in_rooms(x
, y
, SHOPBASE
))
353 add_damage(x
, y
, 0L);
354 levl
[x
][y
].doormask
= D_NODOOR
;
363 * The player is trying to extract something from his/her instrument.
367 do_improvisation(instr
)
370 int damage
, do_spec
= !(Confusion
&& !Conf_resist
);
371 #if defined(MAC) || defined(AMIGA) || defined(VPIX_MUSIC) || defined (PCMUSIC)
375 /* if won't yield special effect, make sound of mundane counterpart */
376 if (!do_spec
|| instr
->spe
<= 0)
377 while (objects
[itmp
.otyp
].oc_magic
) itmp
.otyp
-= 1;
379 mac_speaker(&itmp
, "C");
382 amii_speaker(&itmp
, "Cw", AMII_OKAY_VOLUME
);
385 if (sco_flag_console
)
389 pc_speaker ( &itmp
, "C");
391 #endif /* MAC || AMIGA || VPIX_MUSIC || PCMUSIC */
394 pline("What you produce is quite far from music...");
396 You("start playing %s.", the(xname(instr
)));
398 int nochargechange
= 10;
399 if (!(PlayerCannotUseSkills
)) {
400 switch (P_SKILL(P_DEVICES
)) {
402 case P_BASIC
: nochargechange
= 9; break;
403 case P_SKILLED
: nochargechange
= 8; break;
404 case P_EXPERT
: nochargechange
= 7; break;
405 case P_MASTER
: nochargechange
= 6; break;
406 case P_GRAND_MASTER
: nochargechange
= 5; break;
407 case P_SUPREME_MASTER
: nochargechange
= 4; break;
411 switch (instr
->otyp
) {
412 case MAGIC_FLUTE
: /* Make monster fall asleep */
413 if (do_spec
&& instr
->spe
> 0) {
414 if (nochargechange
>= rnd(10)) consume_obj_charge(instr
, TRUE
);
415 use_skill(P_DEVICES
,1);
416 if (Race_if(PM_FAWN
)) {
417 use_skill(P_DEVICES
,1);
419 if (Race_if(PM_SATRE
)) {
420 use_skill(P_DEVICES
,1);
421 use_skill(P_DEVICES
,1);
423 if (uarmh
&& itemhasappearance(uarmh
, APP_MUSICAL_HELMET
) )
424 use_skill(P_DEVICES
,9);
426 You("produce soft music.");
427 put_monsters_to_sleep(GushLevel
* 5);
428 exercise(A_DEX
, TRUE
);
430 } /* else FALLTHRU */
431 case WOODEN_FLUTE
: /* May charm snakes */
432 /* KMH, balance patch -- removed, but re-inserted by Amy */
435 do_spec
&= (rn2(ACURR(A_DEX
)) + GushLevel
> (25 + rn2(40)) );
436 pline("%s.", Tobjnam(instr
, do_spec
? "trill" : "toot"));
438 charm_snakes(GushLevel
* 3);
439 if (instr
&& instr
->oartifact
== ART_DBL_PLAY_SPEED
) charm_snakes(GushLevel
* 5);
441 exercise(A_DEX
, TRUE
);
443 case FROST_HORN
: /* Idem wand of cold */
444 case FIRE_HORN
: /* Idem wand of fire */
445 case TEMPEST_HORN
: /* Idem wand of lightning */
446 case ETHER_HORN
: /* Idem wand of mm */
447 case CHROME_HORN
: /* Idem wand of poison */
448 case DEATH_HORN
: /* Idem wand of disint beam */
449 case SHADOW_HORN
: /* Idem wand of acid */
450 if (do_spec
&& instr
->spe
> 0) {
451 if ((!instr
->oartifact
|| !rn2(2) ) && (nochargechange
>= rnd(10)) ) consume_obj_charge(instr
, TRUE
);
452 use_skill(P_DEVICES
,1);
453 if (Race_if(PM_FAWN
)) {
454 use_skill(P_DEVICES
,1);
456 if (Race_if(PM_SATRE
)) {
457 use_skill(P_DEVICES
,1);
458 use_skill(P_DEVICES
,1);
460 if (uarmh
&& itemhasappearance(uarmh
, APP_MUSICAL_HELMET
) )
461 use_skill(P_DEVICES
,9);
464 if (!getdir((char *)0)) {
466 if (yn("Do you really want to input no direction?") == 'y') {
467 pline("%s.", Tobjnam(instr
, "vibrate"));
473 } else if (!u
.dx
&& !u
.dy
&& !u
.dz
) {
474 if ((damage
= zapyourself(instr
, TRUE
)) != 0) {
476 sprintf(buf
, "using a magical horn on %sself", uhim());
477 losehp(damage
, buf
, KILLED_BY
);
480 buzz((instr
->otyp
== FROST_HORN
) ? AD_COLD
-1 : (instr
->otyp
== TEMPEST_HORN
) ? AD_ELEC
-1 : (instr
->otyp
== ETHER_HORN
) ? AD_MAGM
-1 : (instr
->otyp
== CHROME_HORN
) ? 26 : (instr
->otyp
== DEATH_HORN
) ? 24 : (instr
->otyp
== SHADOW_HORN
) ? AD_ACID
-1 : AD_FIRE
-1,
481 rn1(6,6), u
.ux
, u
.uy
, u
.dx
, u
.dy
);
483 makeknown(instr
->otyp
);
485 } /* else FALLTHRU */
487 case TOOLED_HORN
: /* Awaken or scare monsters */
488 You("produce a frightful, grave sound.");
490 if (instr
&& instr
->oartifact
== ART_VUVUZELA
) {
493 pline("In fact, the sound of your vuvuzela is so annoying, I bet the entire dungeon population wants to flog you now.");
496 awaken_monsters(GushLevel
* 30);
498 if (!obsidianprotection()) switch (rn2(17)) {
502 case 3: make_confused(HConfusion
+ 12, FALSE
); /* 40% */
506 case 6: make_confused(HConfusion
+ (2L * 12 / 3L), FALSE
); /* 30% */
507 make_stunned(HStun
+ (12 / 3L), FALSE
);
510 case 8: make_stunned(HStun
+ (2L * 12 / 3L), FALSE
); /* 20% */
511 make_confused(HConfusion
+ (12 / 3L), FALSE
);
513 case 9: make_stunned(HStun
+ 12, FALSE
); /* 10% */
515 case 10: make_numbed(HNumbed
+ 12, FALSE
); /* 10% */
517 case 11: make_frozen(HFrozen
+ 12, FALSE
); /* 10% */
519 case 12: make_burned(HBurned
+ 12, FALSE
); /* 10% */
521 case 13: make_feared(HFeared
+ 12, FALSE
); /* 10% */
523 case 14: make_blinded(Blinded
+ 12, FALSE
); /* 10% */
525 case 15: make_hallucinated(HHallucination
+ 12, FALSE
, 0L); /* 10% */
527 case 16: make_dimmed(HDimmed
+ 12, FALSE
); /* 10% */
531 exercise(A_WIS
, FALSE
);
535 case BUGLE
: /* Awaken & attract soldiers */
536 You("extract a loud noise from %s.", the(xname(instr
)));
537 if (instr
&& instr
->oartifact
== ART_HEAR_FAR_AND_WIDE
) awaken_soldiers(1);
538 else if (instr
&& instr
->oartifact
== ART_THIS_IS_NOT_A_DRILL
) awaken_soldiers(2);
539 else awaken_soldiers(0);
540 exercise(A_WIS
, FALSE
);
542 if (instr
&& instr
->oartifact
== ART_MESSAGE_MEGAPHONE
) {
543 pline_The("message is broadcast all over the dungeon!");
544 if (Role_if(PM_DEMAGOGUE
)) {
545 awaken_monsters(GushLevel
* 30);
549 awaken_monsters(GushLevel
* 5);
556 case MAGIC_HARP
: /* Charm monsters */
557 if (do_spec
&& instr
->spe
> 0) {
558 if (nochargechange
>= rnd(10)) consume_obj_charge(instr
, TRUE
);
559 use_skill(P_DEVICES
,1);
560 if (Race_if(PM_FAWN
)) {
561 use_skill(P_DEVICES
,1);
563 if (Race_if(PM_SATRE
)) {
564 use_skill(P_DEVICES
,1);
565 use_skill(P_DEVICES
,1);
567 if (uarmh
&& itemhasappearance(uarmh
, APP_MUSICAL_HELMET
) )
568 use_skill(P_DEVICES
,9);
570 pline("%s very attractive music.", Tobjnam(instr
, "produce"));
571 charm_monsters((GushLevel
- 1) / 3 + 1);
572 exercise(A_DEX
, TRUE
);
574 } /* else FALLTHRU */
575 case WOODEN_HARP
: /* May calm Nymph */
576 do_spec
&= (rn2(ACURR(A_DEX
)) + GushLevel
> (25 + rn2(40)) );
577 pline("%s %s.", The(xname(instr
)),
578 do_spec
? "produces a lilting melody" : "twangs");
579 if (do_spec
) calm_nymphs(GushLevel
* 3);
580 exercise(A_DEX
, TRUE
);
582 case DRUM_OF_EARTHQUAKE
: /* create several pits */
583 if (do_spec
&& instr
->spe
> 0) {
584 if (nochargechange
>= rnd(10)) consume_obj_charge(instr
, TRUE
);
585 use_skill(P_DEVICES
,1);
586 if (Race_if(PM_FAWN
)) {
587 use_skill(P_DEVICES
,1);
589 if (Race_if(PM_SATRE
)) {
590 use_skill(P_DEVICES
,1);
591 use_skill(P_DEVICES
,1);
593 if (uarmh
&& itemhasappearance(uarmh
, APP_MUSICAL_HELMET
) )
594 use_skill(P_DEVICES
,9);
596 You("produce a heavy, thunderous rolling!");
597 pline_The("entire dungeon is shaking around you!");
598 do_earthquake((GushLevel
- 1) / 3 + 1);
599 /* shake up monsters in a much larger radius... */
600 awaken_monsters(ROWNO
* COLNO
);
601 makeknown(DRUM_OF_EARTHQUAKE
);
603 } /* else FALLTHRU */
604 /* KMH, balance patch -- removed (in the wrong place anyways)
605 * Amy edit: added back in, and a fallthrough wouldn't work anyway due to two different magical pan pipes */
606 case PAN_PIPE_OF_SUMMONING
: /* yikes! */
607 if (do_spec
&& instr
->spe
> 0) {
609 register int cnt
= 1;
610 register struct monst
*mtmp
;
612 if (instr
->oartifact
== ART_SACMATERIAL
) {
617 if (nochargechange
>= rnd(10)) consume_obj_charge(instr
, TRUE
);
618 use_skill(P_DEVICES
,1);
619 if (Race_if(PM_FAWN
)) {
620 use_skill(P_DEVICES
,1);
622 if (Race_if(PM_SATRE
)) {
623 use_skill(P_DEVICES
,1);
624 use_skill(P_DEVICES
,1);
626 if (uarmh
&& itemhasappearance(uarmh
, APP_MUSICAL_HELMET
) )
627 use_skill(P_DEVICES
,9);
631 mtmp
= makemon((struct permonst
*) 0, u
.ux
, u
.uy
, NO_MM_FLAGS
);
633 if (mtmp
&& instr
->oartifact
== ART_SNATCHES_OF_SONG
&& !instr
->cursed
&& (!rn2(3) || instr
->blessed
) ) {
634 (void) tamedog(mtmp
, (struct obj
*) 0, FALSE
);
638 else goto panpipeduedeldiedue
;
640 case PAN_PIPE_OF_THE_SEWERS
:
641 if (do_spec
&& instr
->spe
> 0) {
643 register int cnt
= 1;
645 if (instr
->oartifact
== ART_MEFAN_S_FRUSTRATION
) {
647 You("gain some money for your performance!");
650 if (nochargechange
>= rnd(10)) consume_obj_charge(instr
, TRUE
);
651 use_skill(P_DEVICES
,1);
652 if (Race_if(PM_FAWN
)) {
653 use_skill(P_DEVICES
,1);
655 if (Race_if(PM_SATRE
)) {
656 use_skill(P_DEVICES
,1);
657 use_skill(P_DEVICES
,1);
659 if (uarmh
&& itemhasappearance(uarmh
, APP_MUSICAL_HELMET
) )
660 use_skill(P_DEVICES
,9);
662 You("call out the rats!");
663 register struct monst
*mtmp
;
665 cnt
+= (rn2(2) + 2); /* reduced by Amy */
667 /* Amy change: instead of super-useless sewer rats, summon random r-class monsters, please */
668 mtmp
= makemon(mkclass(S_RODENT
,0), u
.ux
, u
.uy
, NO_MM_FLAGS
);
669 /* Amy change: BUC should determine likelihood of tame ones */
670 if (mtmp
&& !instr
->cursed
&& (!rn2(3) || instr
->blessed
) ) {
671 (void) tamedog(mtmp
, (struct obj
*) 0, FALSE
);
675 else goto panpipeduedeldiedue
;
677 case LEATHER_DRUM
: /* Awaken monsters */
679 int drumloudness
= GushLevel
* 40;
680 if (instr
->oartifact
== ART_BOM_BOM_BOM
) {
681 drumloudness
*= 3; drumloudness
/= 2;
683 if (instr
->oartifact
== ART_BOBOBOBOBOM
) {
688 You("beat a deafening row!");
689 if (instr
->oartifact
== ART_BOBOBOBOBOM
) pline("In fact, people will probably have heard it from ten miles away.");
690 awaken_monsters(drumloudness
);
691 Deafness
+= (drumloudness
);
694 if (!obsidianprotection()) switch (rn2(52)) {
698 case 3: make_confused(HConfusion
+ 12, FALSE
); /* 40% */
702 case 6: make_confused(HConfusion
+ (2L * 12 / 3L), FALSE
); /* 30% */
703 make_stunned(HStun
+ (12 / 3L), FALSE
);
706 case 8: make_stunned(HStun
+ (2L * 12 / 3L), FALSE
); /* 20% */
707 make_confused(HConfusion
+ (12 / 3L), FALSE
);
709 case 9: make_stunned(HStun
+ 12, FALSE
); /* 10% */
711 case 10: make_numbed(HNumbed
+ 12, FALSE
); /* 10% */
713 case 11: make_frozen(HFrozen
+ 12, FALSE
); /* 10% */
715 case 12: make_burned(HBurned
+ 12, FALSE
); /* 10% */
717 case 13: make_feared(HFeared
+ 12, FALSE
); /* 10% */
719 case 14: make_blinded(Blinded
+ 12, FALSE
); /* 10% */
721 case 15: make_hallucinated(HHallucination
+ 12, FALSE
, 0L); /* 10% */
723 case 16: make_dimmed(HDimmed
+ 12, FALSE
); /* 10% */
728 exercise(A_WIS
, FALSE
);
732 impossible("What a weird instrument (%ld)!", instr
->otyp
);
735 return 2; /* That takes time */
739 * So you want music...
743 do_play_instrument(instr
)
746 char buf
[BUFSZ
], c
= 'y';
748 boolean usebufx
= FALSE
;
754 You_cant("play music underwater!");
758 if ( ((instr
->otyp
== WOODEN_FLUTE
) || (instr
->otyp
== PAN_PIPE
) || (instr
->otyp
== TOOLED_HORN
) || (instr
->otyp
== FOG_HORN
) || (instr
->otyp
== WOODEN_HARP
) || (instr
->otyp
== LEATHER_DRUM
) || (instr
->otyp
== MAGIC_FLUTE
&& instr
->spe
< 1) || (instr
->otyp
== PAN_PIPE_OF_SUMMONING
&& instr
->spe
< 1) || (instr
->otyp
== PAN_PIPE_OF_THE_SEWERS
&& instr
->spe
< 1) || (instr
->otyp
== MAGIC_HARP
&& instr
->spe
< 1) || (instr
->otyp
== DRUM_OF_EARTHQUAKE
&& instr
->spe
< 1) || (Confusion
&& !Conf_resist
)) && !(Role_if(PM_BARD
) && rn2(100)) && !(Role_if(PM_MUSICIAN
) && rn2(20)) && !(instr
->oartifact
== ART_HARD_STRING
&& rn2(5)) && (!instr
->oartifact
|| !rn2(10)) && !rn2(isfriday
? 50 : 200)) {
760 Your("instrument breaks into pieces!");
764 if (instr
->oartifact
== ART_KILLER_PIANO
) {
766 getnastytrapintrinsic();
770 if (instr
->otyp
!= LEATHER_DRUM
&& instr
->otyp
!= DRUM_OF_EARTHQUAKE
) {
773 getlin ("Improvise? [y/yes/no]",bufX
);
777 if (usebufx
&& strcmp(bufX
, "yes") && strcmp(bufX
, "y") && strcmp(bufX
, "ye") && strcmp(bufX
, "ys")) {
778 if (u
.uevent
.uheard_tune
== 2 && yn("Play the passtune?") == 'y') {
781 getlin("What tune are you playing? [5 notes, A-G]", buf
);
782 (void)mungspaces(buf
);
783 /* convert to uppercase and change any "H" to the expected "B" */
784 for (s
= buf
; *s
; s
++) {
788 /* The AMIGA supports two octaves of notes */
789 if (*s
== 'h') *s
= 'b';
791 if (*s
== 'H') *s
= 'B';
794 You("extract a strange sound from %s!", the(xname(instr
)));
796 /* if user is at the console, play through the console speaker */
801 if (sco_flag_console
)
805 mac_speaker ( instr
, buf
) ;
808 pc_speaker ( instr
, buf
);
814 for( i
= 0; buf
[i
] && i
< 5; ++i
)
816 nbuf
[ i
*2 ] = buf
[ i
];
817 nbuf
[ (i
*2)+1 ] = 'h';
820 amii_speaker ( instr
, nbuf
, AMII_OKAY_VOLUME
) ;
823 /* Check if there was the Stronghold drawbridge near
824 * and if the tune conforms to what we're waiting for.
826 if(Is_stronghold(&u
.uz
)) {
827 exercise(A_WIS
, TRUE
); /* just for trying */
828 if(!strcmp(buf
,tune
)) {
829 /* Search for the drawbridge */
830 for(y
=u
.uy
-1; y
<=u
.uy
+1; y
++)
831 for(x
=u
.ux
-1;x
<=u
.ux
+1;x
++)
833 if(find_drawbridge(&x
,&y
)) {
834 u
.uevent
.uheard_tune
= 2; /* tune now fully known */
835 if(levl
[x
][y
].typ
== DRAWBRIDGE_DOWN
)
836 close_drawbridge(x
,y
);
838 open_drawbridge(x
,y
);
839 return /*0*/1; /*annoying bug fixed now --Amy*/
841 } else if(flags
.soundok
) {
842 if (u
.uevent
.uheard_tune
< 1) u
.uevent
.uheard_tune
= 1;
843 /* Okay, it wasn't the right tune, but perhaps
844 * we can give the player some hints like in the
847 for(y
= u
.uy
-1; y
<= u
.uy
+1 && !ok
; y
++)
848 for(x
= u
.ux
-1; x
<= u
.ux
+1 && !ok
; x
++)
850 if(IS_DRAWBRIDGE(levl
[x
][y
].typ
) ||
851 is_drawbridge_wall(x
,y
) >= 0)
853 if(ok
) { /* There is a drawbridge near */
857 tumblers
= gears
= 0;
861 for(x
=0; x
< (int)strlen(buf
); x
++)
863 if(buf
[x
] == tune
[x
]) {
876 if (instr
&& instr
->cursed
) { /* evil patch idea: cursed instruments make the drawbridge lie to you */
882 You_hear("%d tumbler%s click and %d gear%s turn.",
883 tumblers
, plur(tumblers
), gears
, plur(gears
));
885 You_hear("%d tumbler%s click.",
886 tumblers
, plur(tumblers
));
888 You_hear("%d gear%s turn.", gears
, plur(gears
));
889 /* could only get `gears == 5' by playing five
890 correct notes followed by excess; otherwise,
891 tune would have matched above */
892 if (gears
== 5) u
.uevent
.uheard_tune
= 2;
899 return do_improvisation(instr
);
904 * Play audible music on the machine's speaker if appropriate.
911 * Kluge alert: This code assumes that your [34]86 has no X terminals
912 * attached and that the console tty type is AT386 (this is always true
913 * under AT&T UNIX for these boxen). The theory here is that your remote
914 * ttys will have terminal type `ansi' or something else other than
915 * `AT386' or `xterm'. We'd like to do better than this, but testing
916 * to see if we're running on the console physical terminal is quite
917 * difficult given the presence of virtual consoles and other modern
918 * UNIX impedimenta...
920 char *termtype
= nh_getenv("TERM");
922 return(!strcmp(termtype
, "AT386") || !strcmp(termtype
, "xterm"));
931 * For this to work, you need to have installed the PD speaker-control
932 * driver for PC-compatible UNIX boxes that I (esr@snark.thyrsus.com)
933 * posted to comp.sources.unix in Feb 1990. A copy should be included
934 * with your nethack distribution.
938 if ((fd
= open("/dev/speaker", 1)) != -1)
940 /* send a prefix to modify instrumental `timbre' */
946 case PAN_PIPE_OF_SUMMONING
:
947 case PAN_PIPE_OF_THE_SEWERS
:
948 (void) write(fd
, ">ol", 1); /* up one octave & lock */
959 (void) write(fd
, "<<ol", 2); /* drop two octaves & lock */
962 (void) write(fd
, "ol", 2); /* octave lock */
966 (void) write(fd
, "l8mlol", 4); /* fast, legato, octave lock */
969 (void) write(fd
, buf
, strlen(buf
));
973 #endif /* UNIX386MUSIC */
978 #include <sys/types.h>
979 #include <sys/console.h>
980 #include <sys/vtkd.h>
982 #define KIOC ('K' << 8)
983 #define KDMKTONE (KIOC | 8)
988 STATIC_OVL
void tone(hz
, ticks
)
989 /* emit tone of frequency hz for given number of ticks */
990 unsigned int hz
, ticks
;
992 ioctl(0,KDMKTONE
,hz
|((ticks
*10)<<16));
994 printf("TONE: %6d %6d\n",hz
,ticks
* 10);
999 STATIC_OVL
void rest(ticks
)
1000 /* rest for given number of ticks */
1005 printf("REST: %6d\n",ticks
* 10);
1010 #include "interp.c" /* from snd86unx.shr */
1018 /* emit a prefix to modify instrumental `timbre' */
1020 switch (instr
->otyp
)
1025 case PAN_PIPE_OF_SUMMONING
:
1026 case PAN_PIPE_OF_THE_SEWERS
:
1027 playstring(">ol", 1); /* up one octave & lock */
1038 playstring("<<ol", 2); /* drop two octaves & lock */
1041 playstring("ol", 2); /* octave lock */
1045 playstring("l8mlol", 4); /* fast, legato, octave lock */
1048 playstring( buf
, strlen(buf
));
1057 playstring(argv
[1], strlen(argv
[1]));
1061 #endif /* VPIX_MUSIC */