OSDN Git Service

fix #48255
[jnethack/source.git] / src / music.c
1 /* NetHack 3.6  music.c $NHDT-Date: 1573063606 2019/11/06 18:06:46 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.60 $ */
2 /*      Copyright (c) 1989 by Jean-Christophe Collet */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2023            */
8 /* JNetHack may be freely redistributed.  See license for details. */
9
10 /*
11  * This file contains the different functions designed to manipulate the
12  * musical instruments and their various effects.
13  *
14  * The list of instruments / effects is :
15  *
16  * (wooden) flute       may calm snakes if player has enough dexterity
17  * magic flute          may put monsters to sleep:  area of effect depends
18  *                      on player level.
19  * (tooled) horn        Will awaken monsters:  area of effect depends on
20  *                      player level.  May also scare monsters.
21  * fire horn            Acts like a wand of fire.
22  * frost horn           Acts like a wand of cold.
23  * bugle                Will awaken soldiers (if any):  area of effect depends
24  *                      on player level.
25  * (wooden) harp        May calm nymph if player has enough dexterity.
26  * magic harp           Charm monsters:  area of effect depends on player
27  *                      level.
28  * (leather) drum       Will awaken monsters like the horn.
29  * drum of earthquake   Will initiate an earthquake whose intensity depends
30  *                      on player level.  That is, it creates random pits
31  *                      called here chasms.
32  */
33
34 #include "hack.h"
35
36 STATIC_DCL void FDECL(awaken_monsters, (int));
37 STATIC_DCL void FDECL(put_monsters_to_sleep, (int));
38 STATIC_DCL void FDECL(charm_snakes, (int));
39 STATIC_DCL void FDECL(calm_nymphs, (int));
40 STATIC_DCL void FDECL(charm_monsters, (int));
41 STATIC_DCL void FDECL(do_earthquake, (int));
42 STATIC_DCL int FDECL(do_improvisation, (struct obj *));
43
44 #ifdef UNIX386MUSIC
45 STATIC_DCL int NDECL(atconsole);
46 STATIC_DCL void FDECL(speaker, (struct obj *, char *));
47 #endif
48 #ifdef VPIX_MUSIC
49 extern int sco_flag_console; /* will need changing if not _M_UNIX */
50 STATIC_DCL void NDECL(playinit);
51 STATIC_DCL void FDECL(playstring, (char *, size_t));
52 STATIC_DCL void FDECL(speaker, (struct obj *, char *));
53 #endif
54 #ifdef PCMUSIC
55 void FDECL(pc_speaker, (struct obj *, char *));
56 #endif
57 #ifdef AMIGA
58 void FDECL(amii_speaker, (struct obj *, char *, int));
59 #endif
60
61 /*
62  * Wake every monster in range...
63  */
64
65 STATIC_OVL void
66 awaken_monsters(distance)
67 int distance;
68 {
69     register struct monst *mtmp;
70     register int distm;
71
72     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
73         if (DEADMONSTER(mtmp))
74             continue;
75         if ((distm = distu(mtmp->mx, mtmp->my)) < distance) {
76             mtmp->msleeping = 0;
77             mtmp->mcanmove = 1;
78             mtmp->mfrozen = 0;
79             /* may scare some monsters -- waiting monsters excluded */
80             if (!unique_corpstat(mtmp->data)
81                 && (mtmp->mstrategy & STRAT_WAITMASK) != 0)
82                 mtmp->mstrategy &= ~STRAT_WAITMASK;
83             else if (distm < distance / 3
84                      && !resist(mtmp, TOOL_CLASS, 0, NOTELL)
85                      /* some monsters are immune */
86                      && onscary(0, 0, mtmp))
87                 monflee(mtmp, 0, FALSE, TRUE);
88         }
89     }
90 }
91
92 /*
93  * Make monsters fall asleep.  Note that they may resist the spell.
94  */
95
96 STATIC_OVL void
97 put_monsters_to_sleep(distance)
98 int distance;
99 {
100     register struct monst *mtmp;
101
102     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
103         if (DEADMONSTER(mtmp))
104             continue;
105         if (distu(mtmp->mx, mtmp->my) < distance
106             && sleep_monst(mtmp, d(10, 10), TOOL_CLASS)) {
107             mtmp->msleeping = 1; /* 10d10 turns + wake_nearby to rouse */
108             slept_monst(mtmp);
109         }
110     }
111 }
112
113 /*
114  * Charm snakes in range.  Note that the snakes are NOT tamed.
115  */
116
117 STATIC_OVL void
118 charm_snakes(distance)
119 int distance;
120 {
121     register struct monst *mtmp;
122     int could_see_mon, was_peaceful;
123
124     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
125         if (DEADMONSTER(mtmp))
126             continue;
127         if (mtmp->data->mlet == S_SNAKE && mtmp->mcanmove
128             && distu(mtmp->mx, mtmp->my) < distance) {
129             was_peaceful = mtmp->mpeaceful;
130             mtmp->mpeaceful = 1;
131             mtmp->mavenge = 0;
132             mtmp->mstrategy &= ~STRAT_WAITMASK;
133             could_see_mon = canseemon(mtmp);
134             mtmp->mundetected = 0;
135             newsym(mtmp->mx, mtmp->my);
136             if (canseemon(mtmp)) {
137                 if (!could_see_mon)
138 /*JP
139                     You("notice %s, swaying with the music.", a_monnam(mtmp));
140 */
141                     You("%s\82ª\89¹\8ay\82É\8d\87\82í\82¹\82Ä\97h\82ê\82Ä\82¢\82é\82Ì\82É\8bC\95t\82¢\82½\81D", a_monnam(mtmp));
142                 else
143 #if 0 /*JP:T*/
144                     pline("%s freezes, then sways with the music%s.",
145                           Monnam(mtmp),
146                           was_peaceful ? "" : ", and now seems quieter");
147 #else
148                     pline("%s\82Í\97§\82¿\82·\82­\82Ý\81C\89¹\8ay\82É\8d\87\82í\82¹\82Ä\97h\82ê%s\82½\81D",
149                           Monnam(mtmp),
150                           was_peaceful ? "" : "\81C\82¨\82Æ\82È\82µ\82­\82È\82Á");
151 #endif
152             }
153         }
154     }
155 }
156
157 /*
158  * Calm nymphs in range.
159  */
160
161 STATIC_OVL void
162 calm_nymphs(distance)
163 int distance;
164 {
165     register struct monst *mtmp;
166
167     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
168         if (DEADMONSTER(mtmp))
169             continue;
170         if (mtmp->data->mlet == S_NYMPH && mtmp->mcanmove
171             && distu(mtmp->mx, mtmp->my) < distance) {
172             mtmp->msleeping = 0;
173             mtmp->mpeaceful = 1;
174             mtmp->mavenge = 0;
175             mtmp->mstrategy &= ~STRAT_WAITMASK;
176             if (canseemon(mtmp))
177                 pline(
178 /*JP
179                     "%s listens cheerfully to the music, then seems quieter.",
180 */
181                     "%s\82Í\89¹\8ay\82É\95·\82«\82¢\82è\81C\82¨\82Æ\82È\82µ\82­\82È\82Á\82½\81D",
182                       Monnam(mtmp));
183         }
184     }
185 }
186
187 /* Awake soldiers anywhere the level (and any nearby monster). */
188 void
189 awaken_soldiers(bugler)
190 struct monst *bugler; /* monster that played instrument */
191 {
192     register struct monst *mtmp;
193     int distance, distm;
194
195     /* distance of affected non-soldier monsters to bugler */
196     distance = ((bugler == &youmonst) ? u.ulevel : bugler->data->mlevel) * 30;
197
198     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
199         if (DEADMONSTER(mtmp))
200             continue;
201         if (is_mercenary(mtmp->data) && mtmp->data != &mons[PM_GUARD]) {
202             mtmp->mpeaceful = mtmp->msleeping = mtmp->mfrozen = 0;
203             mtmp->mcanmove = 1;
204             mtmp->mstrategy &= ~STRAT_WAITMASK;
205             if (canseemon(mtmp))
206 /*JP
207                 pline("%s is now ready for battle!", Monnam(mtmp));
208 */
209                 pline("%s\82Í\90í\82¢\82Ì\8f\80\94õ\82ª\90®\82Á\82½\81I", Monnam(mtmp));
210             else if (!Deaf)
211 #if 0 /*JP*/
212                 Norep("%s the rattle of battle gear being readied.",
213                       "You hear");  /* Deaf-aware */
214 #else
215                 /*JP:TODO:Deaf\91Î\89\9e*/
216                 Norep("\82 \82È\82½\82Í\90í\82¢\82Ì\8f\80\94õ\82ª\90®\82Á\82½\82±\82Æ\82ð\8e¦\82·\89¹\82ð\95·\82¢\82½\81D");
217 #endif
218         } else if ((distm = ((bugler == &youmonst)
219                                  ? distu(mtmp->mx, mtmp->my)
220                                  : dist2(bugler->mx, bugler->my, mtmp->mx,
221                                          mtmp->my))) < distance) {
222             mtmp->msleeping = 0;
223             mtmp->mcanmove = 1;
224             mtmp->mfrozen = 0;
225             /* may scare some monsters -- waiting monsters excluded */
226             if (!unique_corpstat(mtmp->data)
227                 && (mtmp->mstrategy & STRAT_WAITMASK) != 0)
228                 mtmp->mstrategy &= ~STRAT_WAITMASK;
229             else if (distm < distance / 3
230                      && !resist(mtmp, TOOL_CLASS, 0, NOTELL))
231                 monflee(mtmp, 0, FALSE, TRUE);
232         }
233     }
234 }
235
236 /* Charm monsters in range.  Note that they may resist the spell.
237  * If swallowed, range is reduced to 0.
238  */
239 STATIC_OVL void
240 charm_monsters(distance)
241 int distance;
242 {
243     struct monst *mtmp, *mtmp2;
244
245     if (u.uswallow) {
246         if (!resist(u.ustuck, TOOL_CLASS, 0, NOTELL))
247             (void) tamedog(u.ustuck, (struct obj *) 0);
248     } else {
249         for (mtmp = fmon; mtmp; mtmp = mtmp2) {
250             mtmp2 = mtmp->nmon;
251             if (DEADMONSTER(mtmp))
252                 continue;
253
254             if (distu(mtmp->mx, mtmp->my) <= distance) {
255                 if (!resist(mtmp, TOOL_CLASS, 0, NOTELL))
256                     (void) tamedog(mtmp, (struct obj *) 0);
257             }
258         }
259     }
260 }
261
262 /* Generate earthquake :-) of desired force.
263  * That is:  create random chasms (pits).
264  */
265 STATIC_OVL void
266 do_earthquake(force)
267 int force;
268 {
269     register int x, y;
270     struct monst *mtmp;
271     struct obj *otmp;
272     struct trap *chasm, *trap_at_u = t_at(u.ux, u.uy);
273     int start_x, start_y, end_x, end_y;
274     schar filltype;
275     unsigned tu_pit = 0;
276
277     if (trap_at_u)
278         tu_pit = is_pit(trap_at_u->ttyp);
279     start_x = u.ux - (force * 2);
280     start_y = u.uy - (force * 2);
281     end_x = u.ux + (force * 2);
282     end_y = u.uy + (force * 2);
283     start_x = max(start_x, 1);
284     start_y = max(start_y, 0);
285     end_x = min(end_x, COLNO - 1);
286     end_y = min(end_y, ROWNO - 1);
287     for (x = start_x; x <= end_x; x++)
288         for (y = start_y; y <= end_y; y++) {
289             if ((mtmp = m_at(x, y)) != 0) {
290                 wakeup(mtmp, TRUE); /* peaceful monster will become hostile */
291                 if (mtmp->mundetected && is_hider(mtmp->data)) {
292                     mtmp->mundetected = 0;
293                     if (cansee(x, y))
294 /*JP
295                         pline("%s is shaken loose from the ceiling!",
296 */
297                         pline("%s\82Í\97h\82·\82ç\82ê\81C\93V\88ä\82©\82ç\97\8e\82¿\82Ä\82«\82½\81I",
298                               Amonnam(mtmp));
299                     else
300 /*JP
301                         You_hear("a thumping sound.");
302 */
303                         You_hear("\83h\83\93\83h\83\93\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D");
304                     if (x == u.ux && y == u.uy)
305 /*JP
306                         You("easily dodge the falling %s.", mon_nam(mtmp));
307 */
308                         You("\97\8e\82¿\82Ä\82«\82½%s\82ð\8aÈ\92P\82É\82©\82í\82µ\82½\81D", mon_nam(mtmp));
309                     newsym(x, y);
310                 }
311             }
312             if (!rn2(14 - force))
313                 switch (levl[x][y].typ) {
314                 case FOUNTAIN: /* Make the fountain disappear */
315                     if (cansee(x, y))
316 /*JP
317                         pline_The("fountain falls into a chasm.");
318 */
319                         pline("\90ò\82Í\92n\8a\84\82ê\82É\97\8e\82¿\82½\81D");
320                     goto do_pit;
321                 case SINK:
322                     if (cansee(x, y))
323 /*JP
324                         pline_The("kitchen sink falls into a chasm.");
325 */
326                         pline("\97¬\82µ\91ä\82Í\92n\8a\84\82ê\82É\97\8e\82¿\82½\81D");
327                     goto do_pit;
328                 case ALTAR:
329                     if (Is_astralevel(&u.uz) || Is_sanctum(&u.uz))
330                         break;
331
332                     if (cansee(x, y))
333 /*JP
334                         pline_The("altar falls into a chasm.");
335 */
336                         pline("\8dÕ\92d\82Í\92n\8a\84\82ê\82É\97\8e\82¿\82½\81D");
337                     goto do_pit;
338                 case GRAVE:
339                     if (cansee(x, y))
340 /*JP
341                         pline_The("headstone topples into a chasm.");
342 */
343                         pline("\95æ\90Î\82Í\95ö\82ê\82³\82Á\82½\81D");
344                     goto do_pit;
345                 case THRONE:
346                     if (cansee(x, y))
347 /*JP
348                         pline_The("throne falls into a chasm.");
349 */
350                         pline("\8bÊ\8dÀ\82Í\92n\8a\84\82ê\82É\97\8e\82¿\82½\81D");
351                     /*FALLTHRU*/
352                 case ROOM:
353                 case CORR: /* Try to make a pit */
354  do_pit:
355                     chasm = maketrap(x, y, PIT);
356                     if (!chasm)
357                         break; /* no pit if portal at that location */
358                     chasm->tseen = 1;
359
360                     /* TODO:
361                      * This ought to be split into a separate routine to
362                      * reduce indentation and the consequent line-wraps.
363                      */
364
365                     levl[x][y].doormask = 0;
366                     /*
367                      * Let liquid flow into the newly created chasm.
368                      * Adjust corresponding code in apply.c for
369                      * exploding wand of digging if you alter this sequence.
370                      */
371                     filltype = fillholetyp(x, y, FALSE);
372                     if (filltype != ROOM) {
373                         levl[x][y].typ = filltype; /* flags set via doormask */
374                         liquid_flow(x, y, filltype, chasm, (char *) 0);
375                     }
376
377                     mtmp = m_at(x, y);
378
379                     if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
380                         if (cansee(x, y))
381 #if 0 /*JP:T*/
382                             pline("KADOOM!  The boulder falls into a chasm%s!",
383                                   (x == u.ux && y == u.uy) ? " below you"
384                                                            : "");
385 #else
386                             pline("\83h\83h\81[\83\93\81I\8aâ\82Í%s\92n\8a\84\82ê\82É\97\8e\82¿\82½\81I",
387                                   (x == u.ux && y == u.uy) ? "\82 \82È\82½\82Ì\89º\82Ì"
388                                                            : "");
389 #endif
390                         if (mtmp)
391                             mtmp->mtrapped = 0;
392                         obj_extract_self(otmp);
393                         (void) flooreffects(otmp, x, y, "");
394                         break;
395                     }
396
397                     /* We have to check whether monsters or player
398                        falls in a chasm... */
399                     if (mtmp) {
400                         if (!is_flyer(mtmp->data)
401                             && !is_clinger(mtmp->data)) {
402                             boolean m_already_trapped = mtmp->mtrapped;
403
404                             mtmp->mtrapped = 1;
405                             if (!m_already_trapped) { /* suppress messages */
406                                 if (cansee(x, y))
407 /*JP
408                                     pline("%s falls into a chasm!",
409 */
410                                     pline("%s\82Í\92n\8a\84\82ê\82É\97\8e\82¿\82½\81I",
411                                           Monnam(mtmp));
412                                 else if (humanoid(mtmp->data))
413 /*JP
414                                     You_hear("a scream!");
415 */
416                                     You_hear("\8b©\82Ñ\90º\82ð\95·\82¢\82½\81I");
417                             }
418                             /* Falling is okay for falling down
419                                 within a pit from jostling too */
420 /*JP
421                             mselftouch(mtmp, "Falling, ", TRUE);
422 */
423                             mselftouch(mtmp, "\97\8e\89º\92\86\81C", TRUE);
424                             if (!DEADMONSTER(mtmp)) {
425                                 mtmp->mhp -= rnd(m_already_trapped ? 4 : 6);
426                                 if (DEADMONSTER(mtmp)) {
427                                     if (!cansee(x, y)) {
428 /*JP
429                                         pline("It is destroyed!");
430 */
431                                         pline("\89½\8eÒ\82©\82Í\8e\80\82ñ\82¾\81I");
432                                     } else {
433 #if 0 /*JP*/
434                                         You("destroy %s!",
435                                             mtmp->mtame
436                                               ? x_monnam(mtmp, ARTICLE_THE,
437                                                          "poor",
438                                                          has_mname(mtmp)
439                                                            ? SUPPRESS_SADDLE
440                                                            : 0,
441                                                          FALSE)
442                                               : mon_nam(mtmp));
443 #else
444                                         pline("%s\82Í\8e\80\82ñ\82¾\81I",
445                                             mtmp->mtame
446                                               ? x_monnam(mtmp, ARTICLE_THE,
447                                                          "\82©\82í\82¢\82»\82¤\82È",
448                                                          has_mname(mtmp)
449                                                            ? SUPPRESS_SADDLE
450                                                            : 0,
451                                                          FALSE)
452                                               : mon_nam(mtmp));
453 #endif
454                                     }
455                                     xkilled(mtmp, XKILL_NOMSG);
456                                 }
457                             }
458                         }
459                     } else if (x == u.ux && y == u.uy) {
460                         if (u.utrap && u.utraptype == TT_BURIEDBALL) {
461                             /* Note:  the chain should break if a pit gets
462                                created at the buried ball's location, which
463                                is not necessarily here.  But if we don't do
464                                things this way, entering the new pit below
465                                will override current trap anyway, but too
466                                late to get Lev and Fly handling. */
467 /*JP
468                             Your("chain breaks!");
469 */
470                             Your("\8d½\82Í\89ó\82ê\82½\81I");
471                             reset_utrap(TRUE);
472                         }
473                         if (Levitation || Flying
474                             || is_clinger(youmonst.data)) {
475                             if (!tu_pit) { /* no pit here previously */
476 /*JP
477                                 pline("A chasm opens up under you!");
478 */
479                                 pline("\92n\8a\84\82ê\82ª\91«\8c³\82É\8aJ\82¢\82½\81I");
480 /*JP
481                                 You("don't fall in!");
482 */
483                                 You("\97\8e\82¿\82È\82©\82Á\82½\81I");
484                             }
485                         } else if (!tu_pit || !u.utrap
486                                    || (u.utrap && u.utraptype != TT_PIT)) {
487                             /* no pit here previously, or you were
488                                not in it even if there was */
489 /*JP
490                             You("fall into a chasm!");
491 */
492                             You("\92n\8a\84\82ê\82É\97\8e\82¿\82½\81I");
493                             set_utrap(rn1(6, 2), TT_PIT);
494 #if 0 /*JP:T*/
495                             losehp(Maybe_Half_Phys(rnd(6)),
496                                    "fell into a chasm", NO_KILLER_PREFIX);
497 #else
498                             losehp(Maybe_Half_Phys(rnd(6)),
499                                    "\92n\8a\84\82ê\82É\97\8e\82¿\82Ä", KILLED_BY);
500 #endif
501 /*JP
502                             selftouch("Falling, you");
503 */
504                             selftouch("\97\8e\82¿\82È\82ª\82ç\81C\82 \82È\82½\82Í");
505                         } else if (u.utrap && u.utraptype == TT_PIT) {
506                             boolean keepfooting =
507                                 ((Fumbling && !rn2(5))
508                                  || (!rnl(Role_if(PM_ARCHEOLOGIST) ? 3 : 9))
509                                  || ((ACURR(A_DEX) > 7) && rn2(5)));
510
511 /*JP
512                             You("are jostled around violently!");
513 */
514                             You("\97\90\96\\82É\89\9f\82µ\82Ì\82¯\82ç\82ê\82½\81I");
515                             set_utrap(rn1(6, 2), TT_PIT);
516 #if 0 /*JP:T*/
517                             losehp(Maybe_Half_Phys(rnd(keepfooting ? 2 : 4)),
518                                    "hurt in a chasm", NO_KILLER_PREFIX);
519 #else
520                             losehp(Maybe_Half_Phys(rnd(keepfooting ? 2 : 4)),
521                                    "\92n\8a\84\82ê\82Å\8f\9d\82Â\82¢\82Ä", KILLED_BY);
522 #endif
523                             if (keepfooting)
524                                 exercise(A_DEX, TRUE);
525                             else
526 #if 0 /*JP:T*/
527                                 selftouch(
528                                     (Upolyd && (slithy(youmonst.data)
529                                                 || nolimbs(youmonst.data)))
530                                         ? "Shaken, you"
531                                         : "Falling down, you");
532 #else
533                                 selftouch(
534                                     (Upolyd && (slithy(youmonst.data)
535                                                 || nolimbs(youmonst.data)))
536                                         ? "\97h\82³\82Ô\82ç\82ê\82Ä\81C\82 \82È\82½\82Í"
537                                         : "\97\8e\82¿\82È\82ª\82ç\81C\82 \82È\82½\82Í");
538 #endif
539                         }
540                     } else
541                         newsym(x, y);
542                     break;
543                 case DOOR: /* Make the door collapse */
544                     if (levl[x][y].doormask == D_NODOOR)
545                         goto do_pit;
546                     if (cansee(x, y))
547 /*JP
548                         pline_The("door collapses.");
549 */
550                         pline_The("\94à\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81D");
551                     if (*in_rooms(x, y, SHOPBASE))
552                         add_damage(x, y, 0L);
553                     levl[x][y].doormask = D_NODOOR;
554                     unblock_point(x, y);
555                     newsym(x, y);
556                     break;
557                 }
558         }
559 }
560
561 const char *
562 generic_lvl_desc()
563 {
564     if (Is_astralevel(&u.uz))
565 /*JP
566         return "astral plane";
567 */
568         return "\93V\8fã\8aE";
569     else if (In_endgame(&u.uz))
570 /*JP
571         return "plane";
572 */
573         return "\90¸\97ì\8aE";
574     else if (Is_sanctum(&u.uz))
575 /*JP
576         return "sanctum";
577 */
578         return "\90¹\88æ";
579     else if (In_sokoban(&u.uz))
580 /*JP
581         return "puzzle";
582 */
583         return "\91q\8cÉ";
584     else if (In_V_tower(&u.uz))
585 /*JP
586         return "tower";
587 */
588         return "\93\83";
589     else
590 /*JP
591         return "dungeon";
592 */
593         return "\96À\8b{";
594 }
595
596 const char *beats[] = {
597     "stepper", "one drop", "slow two", "triple stroke roll",
598     "double shuffle", "half-time shuffle", "second line", "train"
599 };
600
601 /*
602  * The player is trying to extract something from his/her instrument.
603  */
604 STATIC_OVL int
605 do_improvisation(instr)
606 struct obj *instr;
607 {
608     int damage, mode, do_spec = !(Stunned || Confusion);
609     struct obj itmp;
610     boolean mundane = FALSE;
611
612     itmp = *instr;
613     itmp.oextra = (struct oextra *) 0; /* ok on this copy as instr maintains
614                                           the ptr to free at some point if
615                                           there is one */
616
617     /* if won't yield special effect, make sound of mundane counterpart */
618     if (!do_spec || instr->spe <= 0)
619         while (objects[itmp.otyp].oc_magic) {
620             itmp.otyp -= 1;
621             mundane = TRUE;
622         }
623
624 #ifdef MAC
625     mac_speaker(&itmp, "C");
626 #endif
627 #ifdef AMIGA
628     amii_speaker(&itmp, "Cw", AMII_OKAY_VOLUME);
629 #endif
630 #ifdef VPIX_MUSIC
631     if (sco_flag_console)
632         speaker(&itmp, "C");
633 #endif
634 #ifdef PCMUSIC
635     pc_speaker(&itmp, "C");
636 #endif
637
638 #define PLAY_NORMAL   0x00
639 #define PLAY_STUNNED  0x01
640 #define PLAY_CONFUSED 0x02
641 #define PLAY_HALLU    0x04
642     mode = PLAY_NORMAL;
643     if (Stunned)
644         mode |= PLAY_STUNNED;
645     if (Confusion)
646         mode |= PLAY_CONFUSED;
647     if (Hallucination)
648         mode |= PLAY_HALLU;
649
650     if (!rn2(2)) {
651         /*
652          * TEMPORARY?  for multiple impairments, don't always
653          * give the generic "it's far from music" message.
654          */
655         /* remove if STUNNED+CONFUSED ever gets its own message below */
656         if (mode == (PLAY_STUNNED | PLAY_CONFUSED))
657             mode = !rn2(2) ? PLAY_STUNNED : PLAY_CONFUSED;
658         /* likewise for stunned and/or confused combined with hallucination */
659         if (mode & PLAY_HALLU)
660             mode = PLAY_HALLU;
661     }
662
663     /* 3.6.3: most of these gave "You produce <blah>" and then many of
664        the instrument-specific messages below which immediately follow
665        also gave "You produce <something>."  That looked strange so we
666        now use a different verb here */
667     switch (mode) {
668     case PLAY_NORMAL:
669 /*JP
670         You("start playing %s.", yname(instr));
671 */
672         You("%s\82ð\91t\82Å\82Í\82\82ß\82½\81D", yname(instr));
673         break;
674     case PLAY_STUNNED:
675         if (!Deaf)
676 /*JP
677             You("radiate an obnoxious droning sound.");
678 */
679             You("\95s\96ù\89õ\82Å\92P\92²\82È\89¹\82ð\94­\82µ\82½\81D");
680         else
681 /*JP
682             You_feel("a monotonous vibration.");
683 */
684             You_feel("\92P\92²\82È\90U\93®\82ð\8a´\82\82½\81D");
685         break;
686     case PLAY_CONFUSED:
687         if (!Deaf)
688 /*JP
689             You("generate a raucous noise.");
690 */
691             You("\8e¨\8fá\82è\82È\89¹\82ð\8fo\82µ\82½\81D");
692         else
693 /*JP
694             You_feel("a jarring vibration.");
695 */
696             You_feel("\8e¨\8fá\82è\82È\90U\93®\82ð\8a´\82\82½\81D");
697         break;
698     case PLAY_HALLU:
699 /*JP
700         You("disseminate a kaleidoscopic display of floating butterflies.");
701 */
702         You("\8bó\82É\95\82\82©\82Ô\92±\82Ì\96\9c\89Ø\8b¾\93I\82È\95\\8c»\82ð\91n\8fo\82µ\82½\81D");
703         break;
704     /* TODO? give some or all of these combinations their own feedback;
705        hallucination ones should reference senses other than hearing... */
706     case PLAY_STUNNED | PLAY_CONFUSED:
707     case PLAY_STUNNED | PLAY_HALLU:
708     case PLAY_CONFUSED | PLAY_HALLU:
709     case PLAY_STUNNED | PLAY_CONFUSED | PLAY_HALLU:
710     default:
711 /*JP
712         pline("What you perform is quite far from music...");
713 */
714         pline("\82 \82È\82½\82ª\91t\82Å\82½\82à\82Ì\82Í\89¹\8ay\82Æ\82Í\82Æ\82Ä\82à\8cÄ\82×\82È\82¢\81D\81D\81D");
715         break;
716     }
717 #undef PLAY_NORMAL
718 #undef PLAY_STUNNED
719 #undef PLAY_CONFUSED
720 #undef PLAY_HALLU
721
722     switch (itmp.otyp) { /* note: itmp.otyp might differ from instr->otyp */
723     case MAGIC_FLUTE: /* Make monster fall asleep */
724         consume_obj_charge(instr, TRUE);
725
726 #if 0 /*JP*/
727         You("%sproduce %s music.", !Deaf ? "" : "seem to ",
728             Hallucination ? "piped" : "soft");
729 #else
730         You("%s\82ð\91t\82Å\82½%s\81D",
731             Hallucination ? "\82a\82f\82l" : "\93î\82ç\82©\82¢\8bÈ",
732             !Deaf ? "" : "\82æ\82¤\82¾");
733 #endif
734         put_monsters_to_sleep(u.ulevel * 5);
735         exercise(A_DEX, TRUE);
736         break;
737     case WOODEN_FLUTE: /* May charm snakes */
738         do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25);
739         if (!Deaf)
740 /*JP
741             pline("%s.", Tobjnam(instr, do_spec ? "trill" : "toot"));
742 */
743             pline("%s\82ð%s\82½\81D", xname(instr), do_spec ? "\91t\82Å" : "\90\81\82¢");
744         else
745 /*JP
746             You_feel("%s %s.", yname(instr), do_spec ? "trill" : "toot");
747 */
748             You_feel("%s\82ð%s\82½\8a´\82\82ª\82µ\82½\81D", yname(instr), do_spec ? "\91t\82Å" : "\90\81\82¢");
749         if (do_spec)
750             charm_snakes(u.ulevel * 3);
751         exercise(A_DEX, TRUE);
752         break;
753     case FIRE_HORN:  /* Idem wand of fire */
754     case FROST_HORN: /* Idem wand of cold */
755         consume_obj_charge(instr, TRUE);
756
757         if (!getdir((char *) 0)) {
758 /*JP
759             pline("%s.", Tobjnam(instr, "vibrate"));
760 */
761             pline("%s\82Í\90k\82¦\82½\81D", xname(instr));
762             break;
763         } else if (!u.dx && !u.dy && !u.dz) {
764             if ((damage = zapyourself(instr, TRUE)) != 0) {
765                 char buf[BUFSZ];
766
767 /*JP
768                 Sprintf(buf, "using a magical horn on %sself", uhim());
769 */
770                 Strcpy(buf, "\8e©\95ª\8e©\90g\82Ì\96\82\96@\82Ì\83z\83\8b\83\93\82Ì\97Í\82ð\97\81\82Ñ\82Ä");
771                 losehp(damage, buf, KILLED_BY); /* fire or frost damage */
772             }
773         } else {
774             buzz((instr->otyp == FROST_HORN) ? AD_COLD - 1 : AD_FIRE - 1,
775                  rn1(6, 6), u.ux, u.uy, u.dx, u.dy);
776         }
777         makeknown(instr->otyp);
778         break;
779     case TOOLED_HORN: /* Awaken or scare monsters */
780         if (!Deaf)
781 /*JP
782             You("produce a frightful, grave sound.");
783 */
784             You("\90g\90k\82¢\82·\82é\82æ\82¤\82È\8e\80\8eÒ\82Ì\89¹\8ay\82ð\91t\82Å\82½\81D");
785         else
786 /*JP
787             You("blow into the horn.");
788 */
789             You("\83z\83\8b\83\93\82ð\90\81\82¢\82½\81D");
790         awaken_monsters(u.ulevel * 30);
791         exercise(A_WIS, FALSE);
792         break;
793     case BUGLE: /* Awaken & attract soldiers */
794         if (!Deaf)
795 /*JP
796             You("extract a loud noise from %s.", yname(instr));
797 */
798             You("%s\82©\82ç\91å\82«\82È\8e¨\8fá\82è\82È\89¹\82ð\8fo\82µ\82½\81D", yname(instr));
799         else
800 /*JP
801             You("blow into the bugle.");
802 */
803             You("\83\89\83b\83p\82ð\90\81\82¢\82½\81D");
804         awaken_soldiers(&youmonst);
805         exercise(A_WIS, FALSE);
806         break;
807     case MAGIC_HARP: /* Charm monsters */
808         consume_obj_charge(instr, TRUE);
809
810         if (!Deaf)
811 /*JP
812             pline("%s very attractive music.", Tobjnam(instr, "produce"));
813 */
814             pline("%s\82Í\82Æ\82Ä\82à\96£\97Í\93I\82È\89¹\8ay\82ð\91t\82Å\82½\81D", xname(instr));
815         else
816 /*JP
817             You_feel("very soothing vibrations.");
818 */
819             You_feel("\82Æ\82Ä\82à\97\8e\82¿\92\85\82¢\82½\95µ\88Í\8bC\82ð\8a´\82\82½\81D");
820         charm_monsters((u.ulevel - 1) / 3 + 1);
821         exercise(A_DEX, TRUE);
822         break;
823     case WOODEN_HARP: /* May calm Nymph */
824         do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25);
825         if (!Deaf)
826 #if 0 /*JP:T*/
827             pline("%s %s.", Yname2(instr),
828                   do_spec ? "produces a lilting melody" : "twangs");
829 #else
830         You("%s\81D", 
831             do_spec ? "\8cy\89õ\82È\89¹\8ay\82ð\91t\82Å\82½" : "\83|\83\8d\81[\83\93\82Æ\82¢\82¤\89¹\82ð\8fo\82µ\82½");
832 #endif
833         else
834 /*JP
835             You_feel("soothing vibrations.");
836 */
837             You_feel("\97\8e\82¿\92\85\82¢\82½\95µ\88Í\8bC\82ð\8a´\82\82½\81D");
838         if (do_spec)
839             calm_nymphs(u.ulevel * 3);
840         exercise(A_DEX, TRUE);
841         break;
842     case DRUM_OF_EARTHQUAKE: /* create several pits */
843         /* a drum of earthquake does not cause deafness
844            while still magically functional, nor afterwards
845            when it invokes the LEATHER_DRUM case instead and
846            mundane is flagged */
847         consume_obj_charge(instr, TRUE);
848
849 /*JP
850         You("produce a heavy, thunderous rolling!");
851 */
852         You("\8fd\8cú\82È\97\8b\82Ì\82æ\82¤\82È\89¹\82ð\91t\82Å\82½\81I");
853 /*JP
854         pline_The("entire %s is shaking around you!", generic_lvl_desc());
855 */
856         pline("\82 \82È\82½\82Ì\89ñ\82è\82Ì%s\82ª\97h\82ê\82½\81I", generic_lvl_desc());
857         do_earthquake((u.ulevel - 1) / 3 + 1);
858         /* shake up monsters in a much larger radius... */
859         awaken_monsters(ROWNO * COLNO);
860         makeknown(DRUM_OF_EARTHQUAKE);
861         break;
862     case LEATHER_DRUM: /* Awaken monsters */
863         if (!mundane) {
864             if (!Deaf) {
865 /*JP
866                 You("beat a deafening row!");
867 */
868                 You("\8e¨\82ª\95·\82±\82¦\82È\82­\82È\82é\82­\82ç\82¢\92@\82¢\82½\81I");
869                 incr_itimeout(&HDeaf, rn1(20, 30));
870             } else {
871 /*JP
872                 You("pound on the drum.");
873 */
874                 You("\91¾\8cÛ\82ð\8c\83\82µ\82­\92@\82¢\82½\81D");
875             }
876             exercise(A_WIS, FALSE);
877         } else
878 #if 0 /*JP*/
879             You("%s %s.",
880                 rn2(2) ? "butcher" : rn2(2) ? "manage" : "pull off",
881                 an(beats[rn2(SIZE(beats))]));
882 #else
883             /*\8f­\82µ\83V\83\93\83v\83\8b\82É*/
884             You("%s\82ð\92@\82¢\82½\81D",
885                 beats[rn2(SIZE(beats))]);
886 #endif
887         awaken_monsters(u.ulevel * (mundane ? 5 : 40));
888         context.botl = TRUE;
889         break;
890     default:
891         impossible("What a weird instrument (%d)!", instr->otyp);
892         return 0;
893     }
894     return 2; /* That takes time */
895 }
896
897 /*
898  * So you want music...
899  */
900 int
901 do_play_instrument(instr)
902 struct obj *instr;
903 {
904     char buf[BUFSZ] = DUMMY, c = 'y';
905     char *s;
906     int x, y;
907     boolean ok;
908
909     if (Underwater) {
910 /*JP
911         You_cant("play music underwater!");
912 */
913         You("\90\85\82Ì\92\86\82Å\82Í\89¹\8ay\82ð\91t\82Å\82ç\82ê\82È\82¢\81I");
914         return 0;
915     } else if ((instr->otyp == WOODEN_FLUTE || instr->otyp == MAGIC_FLUTE
916                 || instr->otyp == TOOLED_HORN || instr->otyp == FROST_HORN
917                 || instr->otyp == FIRE_HORN || instr->otyp == BUGLE)
918                && !can_blow(&youmonst)) {
919 /*JP
920         You("are incapable of playing %s.", the(distant_name(instr, xname)));
921 */
922         You("%s\82ð\89\89\91t\82·\82é\94\\97Í\82ª\82È\82¢\81D", the(distant_name(instr, xname)));
923         return 0;
924     }
925     if (instr->otyp != LEATHER_DRUM && instr->otyp != DRUM_OF_EARTHQUAKE
926         && !(Stunned || Confusion || Hallucination)) {
927 /*JP
928         c = ynq("Improvise?");
929 */
930         c = ynq("\91¦\8b»\82Å\89\89\91t\82·\82é\81H");
931         if (c == 'q')
932             goto nevermind;
933     }
934
935     if (c == 'n') {
936         if (u.uevent.uheard_tune == 2)
937 /*JP
938             c = ynq("Play the passtune?");
939 */
940             c = ynq("\83R\81[\83h\82ð\89\89\91t\82·\82é\81H");
941         if (c == 'q') {
942             goto nevermind;
943         } else if (c == 'y') {
944             Strcpy(buf, tune);
945         } else {
946 /*JP
947             getlin("What tune are you playing? [5 notes, A-G]", buf);
948 */
949             getlin("\82Ç\82Ì\82æ\82¤\82È\92²\82×\82ð\89\89\91t\82µ\82Ü\82·\82©\81H[A-G \82©\82ç5\89¹\82ð\82¢\82ê\82Ä\82Ë]", buf);
950             (void) mungspaces(buf);
951             if (*buf == '\033')
952                 goto nevermind;
953
954             /* convert to uppercase and change any "H" to the expected "B" */
955             for (s = buf; *s; s++) {
956 #ifndef AMIGA
957                 *s = highc(*s);
958 #else
959                 /* The AMIGA supports two octaves of notes */
960                 if (*s == 'h')
961                     *s = 'b';
962 #endif
963                 if (*s == 'H')
964                     *s = 'B';
965             }
966         }
967
968 #if 0 /*JP:T*/
969         You(!Deaf ? "extract a strange sound from %s!"
970                   : "can feel %s emitting vibrations.", the(xname(instr)));
971 #else
972         You(!Deaf ? "%s\82©\82ç\8aï\96­\82È\89¹\82ð\8fo\82µ\82½\81I"
973                   : "%s\82ª\90U\93®\82µ\82½\82Ì\82ð\8a´\82\82½\81D", the(xname(instr)));
974 #endif
975
976 #ifdef UNIX386MUSIC
977         /* if user is at the console, play through the console speaker */
978         if (atconsole())
979             speaker(instr, buf);
980 #endif
981 #ifdef VPIX_MUSIC
982         if (sco_flag_console)
983             speaker(instr, buf);
984 #endif
985 #ifdef MAC
986         mac_speaker(instr, buf);
987 #endif
988 #ifdef PCMUSIC
989         pc_speaker(instr, buf);
990 #endif
991 #ifdef AMIGA
992         {
993             char nbuf[20];
994             int i;
995
996             for (i = 0; buf[i] && i < 5; ++i) {
997                 nbuf[i * 2] = buf[i];
998                 nbuf[(i * 2) + 1] = 'h';
999             }
1000             nbuf[i * 2] = 0;
1001             amii_speaker(instr, nbuf, AMII_OKAY_VOLUME);
1002         }
1003 #endif
1004         /* Check if there was the Stronghold drawbridge near
1005          * and if the tune conforms to what we're waiting for.
1006          */
1007         if (Is_stronghold(&u.uz)) {
1008             exercise(A_WIS, TRUE); /* just for trying */
1009             if (!strcmp(buf, tune)) {
1010                 /* Search for the drawbridge */
1011                 for (y = u.uy - 1; y <= u.uy + 1; y++)
1012                     for (x = u.ux - 1; x <= u.ux + 1; x++)
1013                         if (isok(x, y))
1014                             if (find_drawbridge(&x, &y)) {
1015                                 /* tune now fully known */
1016                                 u.uevent.uheard_tune = 2;
1017                                 if (levl[x][y].typ == DRAWBRIDGE_DOWN)
1018                                     close_drawbridge(x, y);
1019                                 else
1020                                     open_drawbridge(x, y);
1021                                 return 1;
1022                             }
1023             } else if (!Deaf) {
1024                 if (u.uevent.uheard_tune < 1)
1025                     u.uevent.uheard_tune = 1;
1026                 /* Okay, it wasn't the right tune, but perhaps
1027                  * we can give the player some hints like in the
1028                  * Mastermind game */
1029                 ok = FALSE;
1030                 for (y = u.uy - 1; y <= u.uy + 1 && !ok; y++)
1031                     for (x = u.ux - 1; x <= u.ux + 1 && !ok; x++)
1032                         if (isok(x, y))
1033                             if (IS_DRAWBRIDGE(levl[x][y].typ)
1034                                 || is_drawbridge_wall(x, y) >= 0)
1035                                 ok = TRUE;
1036                 if (ok) { /* There is a drawbridge near */
1037                     int tumblers, gears;
1038                     boolean matched[5];
1039
1040                     tumblers = gears = 0;
1041                     for (x = 0; x < 5; x++)
1042                         matched[x] = FALSE;
1043
1044                     for (x = 0; x < (int) strlen(buf); x++)
1045                         if (x < 5) {
1046                             if (buf[x] == tune[x]) {
1047                                 gears++;
1048                                 matched[x] = TRUE;
1049                             } else {
1050                                 for (y = 0; y < 5; y++)
1051                                     if (!matched[y] && buf[x] == tune[y]
1052                                         && buf[y] != tune[y]) {
1053                                         tumblers++;
1054                                         matched[y] = TRUE;
1055                                         break;
1056                                     }
1057                             }
1058                         }
1059                     if (tumblers) {
1060                         if (gears)
1061 #if 0 /*JP:T*/
1062                             You_hear("%d tumbler%s click and %d gear%s turn.",
1063                                      tumblers, plur(tumblers), gears,
1064                                      plur(gears));
1065 #else
1066                             You_hear("%d\8cÂ\82Ì\8bà\8bï\82ª\83J\83`\82Á\82Æ\82È\82è\81C%d\8cÂ\82Ì\8e\95\8eÔ\82ª\82Ü\82í\82é\89¹\82ð\95·\82¢\82½\81D",
1067                                 tumblers, gears);
1068 #endif
1069                         else
1070 #if 0 /*JP:T*/
1071                             You_hear("%d tumbler%s click.", tumblers,
1072                                      plur(tumblers));
1073 #else
1074                             You_hear("%d\8cÂ\82Ì\8bà\8bï\82ª\83J\83`\82Á\82Æ\82È\82é\89¹\82ð\95·\82¢\82½\81D",
1075                                      tumblers);
1076 #endif
1077                     } else if (gears) {
1078 /*JP
1079                         You_hear("%d gear%s turn.", gears, plur(gears));
1080 */
1081                         You_hear("%d\8cÂ\82Ì\8e\95\8eÔ\82ª\89ñ\82é\89¹\82ð\95·\82¢\82½\81D", gears);
1082                         /* could only get `gears == 5' by playing five
1083                            correct notes followed by excess; otherwise,
1084                            tune would have matched above */
1085                         if (gears == 5)
1086                             u.uevent.uheard_tune = 2;
1087                     }
1088                 }
1089             }
1090         }
1091         return 1;
1092     } else
1093         return do_improvisation(instr);
1094
1095  nevermind:
1096     pline1(Never_mind);
1097     return 0;
1098 }
1099
1100 #ifdef UNIX386MUSIC
1101 /*
1102  * Play audible music on the machine's speaker if appropriate.
1103  */
1104
1105 STATIC_OVL int
1106 atconsole()
1107 {
1108     /*
1109      * Kluge alert: This code assumes that your [34]86 has no X terminals
1110      * attached and that the console tty type is AT386 (this is always true
1111      * under AT&T UNIX for these boxen). The theory here is that your remote
1112      * ttys will have terminal type `ansi' or something else other than
1113      * `AT386' or `xterm'. We'd like to do better than this, but testing
1114      * to see if we're running on the console physical terminal is quite
1115      * difficult given the presence of virtual consoles and other modern
1116      * UNIX impedimenta...
1117      */
1118     char *termtype = nh_getenv("TERM");
1119
1120 /*JP
1121     return (!strcmp(termtype, "AT386") || !strcmp(termtype, "xterm"));
1122 */
1123     return (!strcmp(termtype, "AT386") || !strcmp(termtype, "xterm") || !strcmp(termtype, "kterm"));
1124 }
1125
1126 STATIC_OVL void
1127 speaker(instr, buf)
1128 struct obj *instr;
1129 char *buf;
1130 {
1131     /*
1132      * For this to work, you need to have installed the PD speaker-control
1133      * driver for PC-compatible UNIX boxes that I (esr@snark.thyrsus.com)
1134      * posted to comp.sources.unix in Feb 1990.  A copy should be included
1135      * with your nethack distribution.
1136      */
1137     int fd;
1138
1139     if ((fd = open("/dev/speaker", 1)) != -1) {
1140         /* send a prefix to modify instrumental `timbre' */
1141         switch (instr->otyp) {
1142         case WOODEN_FLUTE:
1143         case MAGIC_FLUTE:
1144             (void) write(fd, ">ol", 1); /* up one octave & lock */
1145             break;
1146         case TOOLED_HORN:
1147         case FROST_HORN:
1148         case FIRE_HORN:
1149             (void) write(fd, "<<ol", 2); /* drop two octaves & lock */
1150             break;
1151         case BUGLE:
1152             (void) write(fd, "ol", 2); /* octave lock */
1153             break;
1154         case WOODEN_HARP:
1155         case MAGIC_HARP:
1156             (void) write(fd, "l8mlol", 4); /* fast, legato, octave lock */
1157             break;
1158         }
1159         (void) write(fd, buf, strlen(buf));
1160         (void) nhclose(fd);
1161     }
1162 }
1163 #endif /* UNIX386MUSIC */
1164
1165 #ifdef VPIX_MUSIC
1166
1167 #if 0
1168 #include <sys/types.h>
1169 #include <sys/console.h>
1170 #include <sys/vtkd.h>
1171 #else
1172 #define KIOC ('K' << 8)
1173 #define KDMKTONE (KIOC | 8)
1174 #endif
1175
1176 #define noDEBUG
1177
1178 /* emit tone of frequency hz for given number of ticks */
1179 STATIC_OVL void
1180 tone(hz, ticks)
1181 unsigned int hz, ticks;
1182 {
1183     ioctl(0, KDMKTONE, hz | ((ticks * 10) << 16));
1184 #ifdef DEBUG
1185     printf("TONE: %6d %6d\n", hz, ticks * 10);
1186 #endif
1187     nap(ticks * 10);
1188 }
1189
1190 /* rest for given number of ticks */
1191 STATIC_OVL void
1192 rest(ticks)
1193 int ticks;
1194 {
1195     nap(ticks * 10);
1196 #ifdef DEBUG
1197     printf("REST:        %6d\n", ticks * 10);
1198 #endif
1199 }
1200
1201 #include "interp.c" /* from snd86unx.shr */
1202
1203 STATIC_OVL void
1204 speaker(instr, buf)
1205 struct obj *instr;
1206 char *buf;
1207 {
1208     /* emit a prefix to modify instrumental `timbre' */
1209     playinit();
1210     switch (instr->otyp) {
1211     case WOODEN_FLUTE:
1212     case MAGIC_FLUTE:
1213         playstring(">ol", 1); /* up one octave & lock */
1214         break;
1215     case TOOLED_HORN:
1216     case FROST_HORN:
1217     case FIRE_HORN:
1218         playstring("<<ol", 2); /* drop two octaves & lock */
1219         break;
1220     case BUGLE:
1221         playstring("ol", 2); /* octave lock */
1222         break;
1223     case WOODEN_HARP:
1224     case MAGIC_HARP:
1225         playstring("l8mlol", 4); /* fast, legato, octave lock */
1226         break;
1227     }
1228     playstring(buf, strlen(buf));
1229 }
1230
1231 #ifdef VPIX_DEBUG
1232 main(argc, argv)
1233 int argc;
1234 char *argv[];
1235 {
1236     if (argc == 2) {
1237         playinit();
1238         playstring(argv[1], strlen(argv[1]));
1239     }
1240 }
1241 #endif
1242 #endif /* VPIX_MUSIC */
1243
1244 /*music.c*/