OSDN Git Service

update year to 2020
[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-2020            */
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 /*JP:TODO \83T\83h\83\8b\8aÖ\98A\82Í\96¢\8f\88\97\9d */
444                                         pline("%s%s\82Í\8e\80\82ñ\82¾\81I",
445                                               mtmp->mtame
446                                               ? "\82©\82í\82¢\82»\82¤\82È" : "",
447                                               mon_nam(mtmp));
448 #endif
449                                     }
450                                     xkilled(mtmp, XKILL_NOMSG);
451                                 }
452                             }
453                         }
454                     } else if (x == u.ux && y == u.uy) {
455                         if (u.utrap && u.utraptype == TT_BURIEDBALL) {
456                             /* Note:  the chain should break if a pit gets
457                                created at the buried ball's location, which
458                                is not necessarily here.  But if we don't do
459                                things this way, entering the new pit below
460                                will override current trap anyway, but too
461                                late to get Lev and Fly handling. */
462 /*JP
463                             Your("chain breaks!");
464 */
465                             Your("\8d½\82Í\89ó\82ê\82½\81I");
466                             reset_utrap(TRUE);
467                         }
468                         if (Levitation || Flying
469                             || is_clinger(youmonst.data)) {
470                             if (!tu_pit) { /* no pit here previously */
471 /*JP
472                                 pline("A chasm opens up under you!");
473 */
474                                 pline("\92n\8a\84\82ê\82ª\91«\8c³\82É\8aJ\82¢\82½\81I");
475 /*JP
476                                 You("don't fall in!");
477 */
478                                 You("\97\8e\82¿\82È\82©\82Á\82½\81I");
479                             }
480                         } else if (!tu_pit || !u.utrap
481                                    || (u.utrap && u.utraptype != TT_PIT)) {
482                             /* no pit here previously, or you were
483                                not in it even if there was */
484 /*JP
485                             You("fall into a chasm!");
486 */
487                             You("\92n\8a\84\82ê\82É\97\8e\82¿\82½\81I");
488                             set_utrap(rn1(6, 2), TT_PIT);
489 #if 0 /*JP:T*/
490                             losehp(Maybe_Half_Phys(rnd(6)),
491                                    "fell into a chasm", NO_KILLER_PREFIX);
492 #else
493                             losehp(Maybe_Half_Phys(rnd(6)),
494                                    "\92n\8a\84\82ê\82É\97\8e\82¿\82Ä", KILLED_BY);
495 #endif
496 /*JP
497                             selftouch("Falling, you");
498 */
499                             selftouch("\97\8e\82¿\82È\82ª\82ç\81C\82 \82È\82½\82Í");
500                         } else if (u.utrap && u.utraptype == TT_PIT) {
501                             boolean keepfooting =
502                                 ((Fumbling && !rn2(5))
503                                  || (!rnl(Role_if(PM_ARCHEOLOGIST) ? 3 : 9))
504                                  || ((ACURR(A_DEX) > 7) && rn2(5)));
505
506 /*JP
507                             You("are jostled around violently!");
508 */
509                             You("\97\90\96\\82É\89\9f\82µ\82Ì\82¯\82ç\82ê\82½\81I");
510                             set_utrap(rn1(6, 2), TT_PIT);
511 #if 0 /*JP:T*/
512                             losehp(Maybe_Half_Phys(rnd(keepfooting ? 2 : 4)),
513                                    "hurt in a chasm", NO_KILLER_PREFIX);
514 #else
515                             losehp(Maybe_Half_Phys(rnd(keepfooting ? 2 : 4)),
516                                    "\92n\8a\84\82ê\82Å\8f\9d\82Â\82¢\82Ä", KILLED_BY);
517 #endif
518                             if (keepfooting)
519                                 exercise(A_DEX, TRUE);
520                             else
521 #if 0 /*JP:T*/
522                                 selftouch(
523                                     (Upolyd && (slithy(youmonst.data)
524                                                 || nolimbs(youmonst.data)))
525                                         ? "Shaken, you"
526                                         : "Falling down, you");
527 #else
528                                 selftouch(
529                                     (Upolyd && (slithy(youmonst.data)
530                                                 || nolimbs(youmonst.data)))
531                                         ? "\97h\82³\82Ô\82ç\82ê\82Ä\81C\82 \82È\82½\82Í"
532                                         : "\97\8e\82¿\82È\82ª\82ç\81C\82 \82È\82½\82Í");
533 #endif
534                         }
535                     } else
536                         newsym(x, y);
537                     break;
538                 case DOOR: /* Make the door collapse */
539                     if (levl[x][y].doormask == D_NODOOR)
540                         goto do_pit;
541                     if (cansee(x, y))
542 /*JP
543                         pline_The("door collapses.");
544 */
545                         pline_The("\94à\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81D");
546                     if (*in_rooms(x, y, SHOPBASE))
547                         add_damage(x, y, 0L);
548                     levl[x][y].doormask = D_NODOOR;
549                     unblock_point(x, y);
550                     newsym(x, y);
551                     break;
552                 }
553         }
554 }
555
556 const char *
557 generic_lvl_desc()
558 {
559     if (Is_astralevel(&u.uz))
560 /*JP
561         return "astral plane";
562 */
563         return "\93V\8fã\8aE";
564     else if (In_endgame(&u.uz))
565 /*JP
566         return "plane";
567 */
568         return "\90¸\97ì\8aE";
569     else if (Is_sanctum(&u.uz))
570 /*JP
571         return "sanctum";
572 */
573         return "\90¹\88æ";
574     else if (In_sokoban(&u.uz))
575 /*JP
576         return "puzzle";
577 */
578         return "\91q\8cÉ";
579     else if (In_V_tower(&u.uz))
580 /*JP
581         return "tower";
582 */
583         return "\93\83";
584     else
585 /*JP
586         return "dungeon";
587 */
588         return "\96À\8b{";
589 }
590
591 const char *beats[] = {
592     "stepper", "one drop", "slow two", "triple stroke roll",
593     "double shuffle", "half-time shuffle", "second line", "train"
594 };
595
596 /*
597  * The player is trying to extract something from his/her instrument.
598  */
599 STATIC_OVL int
600 do_improvisation(instr)
601 struct obj *instr;
602 {
603     int damage, mode, do_spec = !(Stunned || Confusion);
604     struct obj itmp;
605     boolean mundane = FALSE;
606
607     itmp = *instr;
608     itmp.oextra = (struct oextra *) 0; /* ok on this copy as instr maintains
609                                           the ptr to free at some point if
610                                           there is one */
611
612     /* if won't yield special effect, make sound of mundane counterpart */
613     if (!do_spec || instr->spe <= 0)
614         while (objects[itmp.otyp].oc_magic) {
615             itmp.otyp -= 1;
616             mundane = TRUE;
617         }
618
619 #ifdef MAC
620     mac_speaker(&itmp, "C");
621 #endif
622 #ifdef AMIGA
623     amii_speaker(&itmp, "Cw", AMII_OKAY_VOLUME);
624 #endif
625 #ifdef VPIX_MUSIC
626     if (sco_flag_console)
627         speaker(&itmp, "C");
628 #endif
629 #ifdef PCMUSIC
630     pc_speaker(&itmp, "C");
631 #endif
632
633 #define PLAY_NORMAL   0x00
634 #define PLAY_STUNNED  0x01
635 #define PLAY_CONFUSED 0x02
636 #define PLAY_HALLU    0x04
637     mode = PLAY_NORMAL;
638     if (Stunned)
639         mode |= PLAY_STUNNED;
640     if (Confusion)
641         mode |= PLAY_CONFUSED;
642     if (Hallucination)
643         mode |= PLAY_HALLU;
644
645     if (!rn2(2)) {
646         /*
647          * TEMPORARY?  for multiple impairments, don't always
648          * give the generic "it's far from music" message.
649          */
650         /* remove if STUNNED+CONFUSED ever gets its own message below */
651         if (mode == (PLAY_STUNNED | PLAY_CONFUSED))
652             mode = !rn2(2) ? PLAY_STUNNED : PLAY_CONFUSED;
653         /* likewise for stunned and/or confused combined with hallucination */
654         if (mode & PLAY_HALLU)
655             mode = PLAY_HALLU;
656     }
657
658     /* 3.6.3: most of these gave "You produce <blah>" and then many of
659        the instrument-specific messages below which immediately follow
660        also gave "You produce <something>."  That looked strange so we
661        now use a different verb here */
662     switch (mode) {
663     case PLAY_NORMAL:
664 /*JP
665         You("start playing %s.", yname(instr));
666 */
667         You("%s\82ð\91t\82Å\82Í\82\82ß\82½\81D", yname(instr));
668         break;
669     case PLAY_STUNNED:
670         if (!Deaf)
671 /*JP
672             You("radiate an obnoxious droning sound.");
673 */
674             You("\95s\96ù\89õ\82Å\92P\92²\82È\89¹\82ð\94­\82µ\82½\81D");
675         else
676 /*JP
677             You_feel("a monotonous vibration.");
678 */
679             You_feel("\92P\92²\82È\90U\93®\82ð\8a´\82\82½\81D");
680         break;
681     case PLAY_CONFUSED:
682         if (!Deaf)
683 /*JP
684             You("generate a raucous noise.");
685 */
686             You("\8e¨\8fá\82è\82È\89¹\82ð\8fo\82µ\82½\81D");
687         else
688 /*JP
689             You_feel("a jarring vibration.");
690 */
691             You_feel("\8e¨\8fá\82è\82È\90U\93®\82ð\8a´\82\82½\81D");
692         break;
693     case PLAY_HALLU:
694 /*JP
695         You("disseminate a kaleidoscopic display of floating butterflies.");
696 */
697         You("\8bó\82É\95\82\82©\82Ô\92±\82Ì\96\9c\89Ø\8b¾\93I\82È\95\\8c»\82ð\91n\8fo\82µ\82½\81D");
698         break;
699     /* TODO? give some or all of these combinations their own feedback;
700        hallucination ones should reference senses other than hearing... */
701     case PLAY_STUNNED | PLAY_CONFUSED:
702     case PLAY_STUNNED | PLAY_HALLU:
703     case PLAY_CONFUSED | PLAY_HALLU:
704     case PLAY_STUNNED | PLAY_CONFUSED | PLAY_HALLU:
705     default:
706 /*JP
707         pline("What you perform is quite far from music...");
708 */
709         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");
710         break;
711     }
712 #undef PLAY_NORMAL
713 #undef PLAY_STUNNED
714 #undef PLAY_CONFUSED
715 #undef PLAY_HALLU
716
717     switch (itmp.otyp) { /* note: itmp.otyp might differ from instr->otyp */
718     case MAGIC_FLUTE: /* Make monster fall asleep */
719         consume_obj_charge(instr, TRUE);
720
721 #if 0 /*JP*/
722         You("%sproduce %s music.", !Deaf ? "" : "seem to ",
723             Hallucination ? "piped" : "soft");
724 #else
725         You("%s\82ð\91t\82Å\82½%s\81D",
726             Hallucination ? "\82a\82f\82l" : "\93î\82ç\82©\82¢\8bÈ",
727             !Deaf ? "" : "\82æ\82¤\82¾");
728 #endif
729         put_monsters_to_sleep(u.ulevel * 5);
730         exercise(A_DEX, TRUE);
731         break;
732     case WOODEN_FLUTE: /* May charm snakes */
733         do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25);
734         if (!Deaf)
735 /*JP
736             pline("%s.", Tobjnam(instr, do_spec ? "trill" : "toot"));
737 */
738             pline("%s\82ð%s\82½\81D", xname(instr), do_spec ? "\91t\82Å" : "\90\81\82¢");
739         else
740 /*JP
741             You_feel("%s %s.", yname(instr), do_spec ? "trill" : "toot");
742 */
743             You_feel("%s\82ð%s\82½\8a´\82\82ª\82µ\82½\81D", yname(instr), do_spec ? "\91t\82Å" : "\90\81\82¢");
744         if (do_spec)
745             charm_snakes(u.ulevel * 3);
746         exercise(A_DEX, TRUE);
747         break;
748     case FIRE_HORN:  /* Idem wand of fire */
749     case FROST_HORN: /* Idem wand of cold */
750         consume_obj_charge(instr, TRUE);
751
752         if (!getdir((char *) 0)) {
753 /*JP
754             pline("%s.", Tobjnam(instr, "vibrate"));
755 */
756             pline("%s\82Í\90k\82¦\82½\81D", xname(instr));
757             break;
758         } else if (!u.dx && !u.dy && !u.dz) {
759             if ((damage = zapyourself(instr, TRUE)) != 0) {
760                 char buf[BUFSZ];
761
762 /*JP
763                 Sprintf(buf, "using a magical horn on %sself", uhim());
764 */
765                 Strcpy(buf, "\8e©\95ª\8e©\90g\82Ì\96\82\96@\82Ì\83z\83\8b\83\93\82Ì\97Í\82ð\97\81\82Ñ\82Ä");
766                 losehp(damage, buf, KILLED_BY); /* fire or frost damage */
767             }
768         } else {
769             buzz((instr->otyp == FROST_HORN) ? AD_COLD - 1 : AD_FIRE - 1,
770                  rn1(6, 6), u.ux, u.uy, u.dx, u.dy);
771         }
772         makeknown(instr->otyp);
773         break;
774     case TOOLED_HORN: /* Awaken or scare monsters */
775         if (!Deaf)
776 /*JP
777             You("produce a frightful, grave sound.");
778 */
779             You("\90g\90k\82¢\82·\82é\82æ\82¤\82È\8e\80\8eÒ\82Ì\89¹\8ay\82ð\91t\82Å\82½\81D");
780         else
781 /*JP
782             You("blow into the horn.");
783 */
784             You("\83z\83\8b\83\93\82ð\90\81\82¢\82½\81D");
785         awaken_monsters(u.ulevel * 30);
786         exercise(A_WIS, FALSE);
787         break;
788     case BUGLE: /* Awaken & attract soldiers */
789         if (!Deaf)
790 /*JP
791             You("extract a loud noise from %s.", yname(instr));
792 */
793             You("%s\82©\82ç\91å\82«\82È\8e¨\8fá\82è\82È\89¹\82ð\8fo\82µ\82½\81D", yname(instr));
794         else
795 /*JP
796             You("blow into the bugle.");
797 */
798             You("\83\89\83b\83p\82ð\90\81\82¢\82½\81D");
799         awaken_soldiers(&youmonst);
800         exercise(A_WIS, FALSE);
801         break;
802     case MAGIC_HARP: /* Charm monsters */
803         consume_obj_charge(instr, TRUE);
804
805         if (!Deaf)
806 /*JP
807             pline("%s very attractive music.", Tobjnam(instr, "produce"));
808 */
809             pline("%s\82Í\82Æ\82Ä\82à\96£\97Í\93I\82È\89¹\8ay\82ð\91t\82Å\82½\81D", xname(instr));
810         else
811 /*JP
812             You_feel("very soothing vibrations.");
813 */
814             You_feel("\82Æ\82Ä\82à\97\8e\82¿\92\85\82¢\82½\95µ\88Í\8bC\82ð\8a´\82\82½\81D");
815         charm_monsters((u.ulevel - 1) / 3 + 1);
816         exercise(A_DEX, TRUE);
817         break;
818     case WOODEN_HARP: /* May calm Nymph */
819         do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25);
820         if (!Deaf)
821 #if 0 /*JP:T*/
822             pline("%s %s.", Yname2(instr),
823                   do_spec ? "produces a lilting melody" : "twangs");
824 #else
825         You("%s\81D", 
826             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½");
827 #endif
828         else
829 /*JP
830             You_feel("soothing vibrations.");
831 */
832             You_feel("\97\8e\82¿\92\85\82¢\82½\95µ\88Í\8bC\82ð\8a´\82\82½\81D");
833         if (do_spec)
834             calm_nymphs(u.ulevel * 3);
835         exercise(A_DEX, TRUE);
836         break;
837     case DRUM_OF_EARTHQUAKE: /* create several pits */
838         /* a drum of earthquake does not cause deafness
839            while still magically functional, nor afterwards
840            when it invokes the LEATHER_DRUM case instead and
841            mundane is flagged */
842         consume_obj_charge(instr, TRUE);
843
844 /*JP
845         You("produce a heavy, thunderous rolling!");
846 */
847         You("\8fd\8cú\82È\97\8b\82Ì\82æ\82¤\82È\89¹\82ð\91t\82Å\82½\81I");
848 /*JP
849         pline_The("entire %s is shaking around you!", generic_lvl_desc());
850 */
851         pline("\82 \82È\82½\82Ì\89ñ\82è\82Ì%s\82ª\97h\82ê\82½\81I", generic_lvl_desc());
852         do_earthquake((u.ulevel - 1) / 3 + 1);
853         /* shake up monsters in a much larger radius... */
854         awaken_monsters(ROWNO * COLNO);
855         makeknown(DRUM_OF_EARTHQUAKE);
856         break;
857     case LEATHER_DRUM: /* Awaken monsters */
858         if (!mundane) {
859             if (!Deaf) {
860 /*JP
861                 You("beat a deafening row!");
862 */
863                 You("\8e¨\82ª\95·\82±\82¦\82È\82­\82È\82é\82­\82ç\82¢\92@\82¢\82½\81I");
864                 incr_itimeout(&HDeaf, rn1(20, 30));
865             } else {
866 /*JP
867                 You("pound on the drum.");
868 */
869                 You("\91¾\8cÛ\82ð\8c\83\82µ\82­\92@\82¢\82½\81D");
870             }
871             exercise(A_WIS, FALSE);
872         } else
873 #if 0 /*JP*/
874             You("%s %s.",
875                 rn2(2) ? "butcher" : rn2(2) ? "manage" : "pull off",
876                 an(beats[rn2(SIZE(beats))]));
877 #else
878             /*\8f­\82µ\83V\83\93\83v\83\8b\82É*/
879             You("%s\82ð\92@\82¢\82½\81D",
880                 beats[rn2(SIZE(beats))]);
881 #endif
882         awaken_monsters(u.ulevel * (mundane ? 5 : 40));
883         context.botl = TRUE;
884         break;
885     default:
886         impossible("What a weird instrument (%d)!", instr->otyp);
887         return 0;
888     }
889     return 2; /* That takes time */
890 }
891
892 /*
893  * So you want music...
894  */
895 int
896 do_play_instrument(instr)
897 struct obj *instr;
898 {
899     char buf[BUFSZ] = DUMMY, c = 'y';
900     char *s;
901     int x, y;
902     boolean ok;
903
904     if (Underwater) {
905 /*JP
906         You_cant("play music underwater!");
907 */
908         You("\90\85\82Ì\92\86\82Å\82Í\89¹\8ay\82ð\91t\82Å\82ç\82ê\82È\82¢\81I");
909         return 0;
910     } else if ((instr->otyp == WOODEN_FLUTE || instr->otyp == MAGIC_FLUTE
911                 || instr->otyp == TOOLED_HORN || instr->otyp == FROST_HORN
912                 || instr->otyp == FIRE_HORN || instr->otyp == BUGLE)
913                && !can_blow(&youmonst)) {
914 /*JP
915         You("are incapable of playing %s.", the(distant_name(instr, xname)));
916 */
917         You("%s\82ð\89\89\91t\82·\82é\94\\97Í\82ª\82È\82¢\81D", the(distant_name(instr, xname)));
918         return 0;
919     }
920     if (instr->otyp != LEATHER_DRUM && instr->otyp != DRUM_OF_EARTHQUAKE
921         && !(Stunned || Confusion || Hallucination)) {
922 /*JP
923         c = ynq("Improvise?");
924 */
925         c = ynq("\91¦\8b»\82Å\89\89\91t\82·\82é\81H");
926         if (c == 'q')
927             goto nevermind;
928     }
929
930     if (c == 'n') {
931         if (u.uevent.uheard_tune == 2)
932 /*JP
933             c = ynq("Play the passtune?");
934 */
935             c = ynq("\83R\81[\83h\82ð\89\89\91t\82·\82é\81H");
936         if (c == 'q') {
937             goto nevermind;
938         } else if (c == 'y') {
939             Strcpy(buf, tune);
940         } else {
941 /*JP
942             getlin("What tune are you playing? [5 notes, A-G]", buf);
943 */
944             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);
945             (void) mungspaces(buf);
946             if (*buf == '\033')
947                 goto nevermind;
948
949             /* convert to uppercase and change any "H" to the expected "B" */
950             for (s = buf; *s; s++) {
951 #ifndef AMIGA
952                 *s = highc(*s);
953 #else
954                 /* The AMIGA supports two octaves of notes */
955                 if (*s == 'h')
956                     *s = 'b';
957 #endif
958                 if (*s == 'H')
959                     *s = 'B';
960             }
961         }
962
963 #if 0 /*JP:T*/
964         You(!Deaf ? "extract a strange sound from %s!"
965                   : "can feel %s emitting vibrations.", the(xname(instr)));
966 #else
967         You(!Deaf ? "%s\82©\82ç\8aï\96­\82È\89¹\82ð\8fo\82µ\82½\81I"
968                   : "%s\82ª\90U\93®\82µ\82½\82Ì\82ð\8a´\82\82½\81D", the(xname(instr)));
969 #endif
970
971 #ifdef UNIX386MUSIC
972         /* if user is at the console, play through the console speaker */
973         if (atconsole())
974             speaker(instr, buf);
975 #endif
976 #ifdef VPIX_MUSIC
977         if (sco_flag_console)
978             speaker(instr, buf);
979 #endif
980 #ifdef MAC
981         mac_speaker(instr, buf);
982 #endif
983 #ifdef PCMUSIC
984         pc_speaker(instr, buf);
985 #endif
986 #ifdef AMIGA
987         {
988             char nbuf[20];
989             int i;
990
991             for (i = 0; buf[i] && i < 5; ++i) {
992                 nbuf[i * 2] = buf[i];
993                 nbuf[(i * 2) + 1] = 'h';
994             }
995             nbuf[i * 2] = 0;
996             amii_speaker(instr, nbuf, AMII_OKAY_VOLUME);
997         }
998 #endif
999         /* Check if there was the Stronghold drawbridge near
1000          * and if the tune conforms to what we're waiting for.
1001          */
1002         if (Is_stronghold(&u.uz)) {
1003             exercise(A_WIS, TRUE); /* just for trying */
1004             if (!strcmp(buf, tune)) {
1005                 /* Search for the drawbridge */
1006                 for (y = u.uy - 1; y <= u.uy + 1; y++)
1007                     for (x = u.ux - 1; x <= u.ux + 1; x++)
1008                         if (isok(x, y))
1009                             if (find_drawbridge(&x, &y)) {
1010                                 /* tune now fully known */
1011                                 u.uevent.uheard_tune = 2;
1012                                 if (levl[x][y].typ == DRAWBRIDGE_DOWN)
1013                                     close_drawbridge(x, y);
1014                                 else
1015                                     open_drawbridge(x, y);
1016                                 return 1;
1017                             }
1018             } else if (!Deaf) {
1019                 if (u.uevent.uheard_tune < 1)
1020                     u.uevent.uheard_tune = 1;
1021                 /* Okay, it wasn't the right tune, but perhaps
1022                  * we can give the player some hints like in the
1023                  * Mastermind game */
1024                 ok = FALSE;
1025                 for (y = u.uy - 1; y <= u.uy + 1 && !ok; y++)
1026                     for (x = u.ux - 1; x <= u.ux + 1 && !ok; x++)
1027                         if (isok(x, y))
1028                             if (IS_DRAWBRIDGE(levl[x][y].typ)
1029                                 || is_drawbridge_wall(x, y) >= 0)
1030                                 ok = TRUE;
1031                 if (ok) { /* There is a drawbridge near */
1032                     int tumblers, gears;
1033                     boolean matched[5];
1034
1035                     tumblers = gears = 0;
1036                     for (x = 0; x < 5; x++)
1037                         matched[x] = FALSE;
1038
1039                     for (x = 0; x < (int) strlen(buf); x++)
1040                         if (x < 5) {
1041                             if (buf[x] == tune[x]) {
1042                                 gears++;
1043                                 matched[x] = TRUE;
1044                             } else {
1045                                 for (y = 0; y < 5; y++)
1046                                     if (!matched[y] && buf[x] == tune[y]
1047                                         && buf[y] != tune[y]) {
1048                                         tumblers++;
1049                                         matched[y] = TRUE;
1050                                         break;
1051                                     }
1052                             }
1053                         }
1054                     if (tumblers) {
1055                         if (gears)
1056 #if 0 /*JP:T*/
1057                             You_hear("%d tumbler%s click and %d gear%s turn.",
1058                                      tumblers, plur(tumblers), gears,
1059                                      plur(gears));
1060 #else
1061                             You_hear("%d\82Ì\8bà\8bï\82ª\83J\83`\82Á\82Æ\82È\82è\81C%d\82Ì\8e\95\8eÔ\82ª\82Ü\82í\82é\89¹\82ð\95·\82¢\82½\81D",
1062                                 tumblers, gears);
1063 #endif
1064                         else
1065 #if 0 /*JP:T*/
1066                             You_hear("%d tumbler%s click.", tumblers,
1067                                      plur(tumblers));
1068 #else
1069                             You_hear("%d\82Ì\8bà\8bï\82ª\83J\83`\82Á\82Æ\82È\82é\89¹\82ð\95·\82¢\82½\81D",
1070                                      tumblers);
1071 #endif
1072                     } else if (gears) {
1073 /*JP
1074                         You_hear("%d gear%s turn.", gears, plur(gears));
1075 */
1076                         You_hear("%d\82Ì\8e\95\8eÔ\82ª\89ñ\82é\89¹\82ð\95·\82¢\82½\81D", gears);
1077                         /* could only get `gears == 5' by playing five
1078                            correct notes followed by excess; otherwise,
1079                            tune would have matched above */
1080                         if (gears == 5)
1081                             u.uevent.uheard_tune = 2;
1082                     }
1083                 }
1084             }
1085         }
1086         return 1;
1087     } else
1088         return do_improvisation(instr);
1089
1090  nevermind:
1091     pline1(Never_mind);
1092     return 0;
1093 }
1094
1095 #ifdef UNIX386MUSIC
1096 /*
1097  * Play audible music on the machine's speaker if appropriate.
1098  */
1099
1100 STATIC_OVL int
1101 atconsole()
1102 {
1103     /*
1104      * Kluge alert: This code assumes that your [34]86 has no X terminals
1105      * attached and that the console tty type is AT386 (this is always true
1106      * under AT&T UNIX for these boxen). The theory here is that your remote
1107      * ttys will have terminal type `ansi' or something else other than
1108      * `AT386' or `xterm'. We'd like to do better than this, but testing
1109      * to see if we're running on the console physical terminal is quite
1110      * difficult given the presence of virtual consoles and other modern
1111      * UNIX impedimenta...
1112      */
1113     char *termtype = nh_getenv("TERM");
1114
1115 /*JP
1116     return (!strcmp(termtype, "AT386") || !strcmp(termtype, "xterm"));
1117 */
1118     return (!strcmp(termtype, "AT386") || !strcmp(termtype, "xterm") || !strcmp(termtype, "kterm"));
1119 }
1120
1121 STATIC_OVL void
1122 speaker(instr, buf)
1123 struct obj *instr;
1124 char *buf;
1125 {
1126     /*
1127      * For this to work, you need to have installed the PD speaker-control
1128      * driver for PC-compatible UNIX boxes that I (esr@snark.thyrsus.com)
1129      * posted to comp.sources.unix in Feb 1990.  A copy should be included
1130      * with your nethack distribution.
1131      */
1132     int fd;
1133
1134     if ((fd = open("/dev/speaker", 1)) != -1) {
1135         /* send a prefix to modify instrumental `timbre' */
1136         switch (instr->otyp) {
1137         case WOODEN_FLUTE:
1138         case MAGIC_FLUTE:
1139             (void) write(fd, ">ol", 1); /* up one octave & lock */
1140             break;
1141         case TOOLED_HORN:
1142         case FROST_HORN:
1143         case FIRE_HORN:
1144             (void) write(fd, "<<ol", 2); /* drop two octaves & lock */
1145             break;
1146         case BUGLE:
1147             (void) write(fd, "ol", 2); /* octave lock */
1148             break;
1149         case WOODEN_HARP:
1150         case MAGIC_HARP:
1151             (void) write(fd, "l8mlol", 4); /* fast, legato, octave lock */
1152             break;
1153         }
1154         (void) write(fd, buf, strlen(buf));
1155         (void) nhclose(fd);
1156     }
1157 }
1158 #endif /* UNIX386MUSIC */
1159
1160 #ifdef VPIX_MUSIC
1161
1162 #if 0
1163 #include <sys/types.h>
1164 #include <sys/console.h>
1165 #include <sys/vtkd.h>
1166 #else
1167 #define KIOC ('K' << 8)
1168 #define KDMKTONE (KIOC | 8)
1169 #endif
1170
1171 #define noDEBUG
1172
1173 /* emit tone of frequency hz for given number of ticks */
1174 STATIC_OVL void
1175 tone(hz, ticks)
1176 unsigned int hz, ticks;
1177 {
1178     ioctl(0, KDMKTONE, hz | ((ticks * 10) << 16));
1179 #ifdef DEBUG
1180     printf("TONE: %6d %6d\n", hz, ticks * 10);
1181 #endif
1182     nap(ticks * 10);
1183 }
1184
1185 /* rest for given number of ticks */
1186 STATIC_OVL void
1187 rest(ticks)
1188 int ticks;
1189 {
1190     nap(ticks * 10);
1191 #ifdef DEBUG
1192     printf("REST:        %6d\n", ticks * 10);
1193 #endif
1194 }
1195
1196 #include "interp.c" /* from snd86unx.shr */
1197
1198 STATIC_OVL void
1199 speaker(instr, buf)
1200 struct obj *instr;
1201 char *buf;
1202 {
1203     /* emit a prefix to modify instrumental `timbre' */
1204     playinit();
1205     switch (instr->otyp) {
1206     case WOODEN_FLUTE:
1207     case MAGIC_FLUTE:
1208         playstring(">ol", 1); /* up one octave & lock */
1209         break;
1210     case TOOLED_HORN:
1211     case FROST_HORN:
1212     case FIRE_HORN:
1213         playstring("<<ol", 2); /* drop two octaves & lock */
1214         break;
1215     case BUGLE:
1216         playstring("ol", 2); /* octave lock */
1217         break;
1218     case WOODEN_HARP:
1219     case MAGIC_HARP:
1220         playstring("l8mlol", 4); /* fast, legato, octave lock */
1221         break;
1222     }
1223     playstring(buf, strlen(buf));
1224 }
1225
1226 #ifdef VPIX_DEBUG
1227 main(argc, argv)
1228 int argc;
1229 char *argv[];
1230 {
1231     if (argc == 2) {
1232         playinit();
1233         playstring(argv[1], strlen(argv[1]));
1234     }
1235 }
1236 #endif
1237 #endif /* VPIX_MUSIC */
1238
1239 /*music.c*/