OSDN Git Service

GCC says embedding a directive within macro arguments is not portable
[jnethack/source.git] / src / allmain.c
1 /* NetHack 3.6  allmain.c       $NHDT-Date: 1518193644 2018/02/09 16:27:24 $  $NHDT-Branch: githash $:$NHDT-Revision: 1.86 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2012. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2018            */
9 /* JNetHack may be freely redistributed.  See license for details. */
10
11 /* various code that was replicated in *main.c */
12
13 #include "hack.h"
14
15 #ifndef NO_SIGNAL
16 #include <signal.h>
17 #endif
18
19 #ifdef POSITIONBAR
20 STATIC_DCL void NDECL(do_positionbar);
21 #endif
22 STATIC_DCL void FDECL(regen_hp, (int));
23 STATIC_DCL void FDECL(interrupt_multi, (const char *));
24
25 void
26 moveloop(resuming)
27 boolean resuming;
28 {
29 #if defined(MICRO) || defined(WIN32)
30     char ch;
31     int abort_lev;
32 #endif
33     int moveamt = 0, wtcap = 0, change = 0;
34     boolean monscanmove = FALSE;
35
36     /* Note:  these initializers don't do anything except guarantee that
37             we're linked properly.
38     */
39     decl_init();
40     monst_init();
41     monstr_init(); /* monster strengths */
42     objects_init();
43
44     /* if a save file created in normal mode is now being restored in
45        explore mode, treat it as normal restore followed by 'X' command
46        to use up the save file and require confirmation for explore mode */
47     if (resuming && iflags.deferred_X)
48         (void) enter_explore_mode();
49
50     /* side-effects from the real world */
51     flags.moonphase = phase_of_the_moon();
52     if (flags.moonphase == FULL_MOON) {
53 /*JP
54         You("are lucky!  Full moon tonight.");
55 */
56         pline("\83\89\83b\83L\81[\81I\8d¡\94Ó\82Í\96\9e\8c\8e\82¾\81D");
57         change_luck(1);
58     } else if (flags.moonphase == NEW_MOON) {
59 /*JP
60         pline("Be careful!  New moon tonight.");
61 */
62         pline("\92\8d\88Ó\82µ\82ë\81I\8d¡\94Ó\82Í\90V\8c\8e\82¾\81D");
63     }
64     flags.friday13 = friday_13th();
65     if (flags.friday13) {
66 /*JP
67         pline("Watch out!  Bad things can happen on Friday the 13th.");
68 */
69         pline("\97p\90S\82µ\82ë\81I\82P\82R\93ú\82Ì\8bà\97j\93ú\82É\82Í\82æ\82­\82È\82¢\82±\82Æ\82ª\82 \82é\81D") ;
70         change_luck(-1);
71     }
72
73     if (!resuming) { /* new game */
74         context.rndencode = rnd(9000);
75         set_wear((struct obj *) 0); /* for side-effects of starting gear */
76         (void) pickup(1);      /* autopickup at initial location */
77     }
78     context.botlx = TRUE; /* for STATUS_HILITES */
79     update_inventory(); /* for perm_invent */
80     if (resuming) { /* restoring old game */
81         read_engr_at(u.ux, u.uy); /* subset of pickup() */
82     }
83
84     (void) encumber_msg(); /* in case they auto-picked up something */
85     if (defer_see_monsters) {
86         defer_see_monsters = FALSE;
87         see_monsters();
88     }
89     initrack();
90
91     u.uz0.dlevel = u.uz.dlevel;
92     youmonst.movement = NORMAL_SPEED; /* give the hero some movement points */
93     context.move = 0;
94
95     program_state.in_moveloop = 1;
96     for (;;) {
97 #ifdef SAFERHANGUP
98         if (program_state.done_hup)
99             end_of_input();
100 #endif
101         get_nh_event();
102 #ifdef POSITIONBAR
103         do_positionbar();
104 #endif
105
106         if (context.move) {
107             /* actual time passed */
108             youmonst.movement -= NORMAL_SPEED;
109
110             do { /* hero can't move this turn loop */
111                 wtcap = encumber_msg();
112
113                 context.mon_moving = TRUE;
114                 do {
115                     monscanmove = movemon();
116                     if (youmonst.movement >= NORMAL_SPEED)
117                         break; /* it's now your turn */
118                 } while (monscanmove);
119                 context.mon_moving = FALSE;
120
121                 if (!monscanmove && youmonst.movement < NORMAL_SPEED) {
122                     /* both you and the monsters are out of steam this round
123                      */
124                     /* set up for a new turn */
125                     struct monst *mtmp;
126                     mcalcdistress(); /* adjust monsters' trap, blind, etc */
127
128                     /* reallocate movement rations to monsters */
129                     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
130                         mtmp->movement += mcalcmove(mtmp);
131
132                     if (!rn2(u.uevent.udemigod
133                                  ? 25
134                                  : (depth(&u.uz) > depth(&stronghold_level))
135                                        ? 50
136                                        : 70))
137                         (void) makemon((struct permonst *) 0, 0, 0,
138                                        NO_MM_FLAGS);
139
140                     /* calculate how much time passed. */
141                     if (u.usteed && u.umoved) {
142                         /* your speed doesn't augment steed's speed */
143                         moveamt = mcalcmove(u.usteed);
144                     } else {
145                         moveamt = youmonst.data->mmove;
146
147                         if (Very_fast) { /* speed boots or potion */
148                             /* gain a free action on 2/3 of turns */
149                             if (rn2(3) != 0)
150                                 moveamt += NORMAL_SPEED;
151                         } else if (Fast) {
152                             /* gain a free action on 1/3 of turns */
153                             if (rn2(3) == 0)
154                                 moveamt += NORMAL_SPEED;
155                         }
156                     }
157
158                     switch (wtcap) {
159                     case UNENCUMBERED:
160                         break;
161                     case SLT_ENCUMBER:
162                         moveamt -= (moveamt / 4);
163                         break;
164                     case MOD_ENCUMBER:
165                         moveamt -= (moveamt / 2);
166                         break;
167                     case HVY_ENCUMBER:
168                         moveamt -= ((moveamt * 3) / 4);
169                         break;
170                     case EXT_ENCUMBER:
171                         moveamt -= ((moveamt * 7) / 8);
172                         break;
173                     default:
174                         break;
175                     }
176
177                     youmonst.movement += moveamt;
178                     if (youmonst.movement < 0)
179                         youmonst.movement = 0;
180                     settrack();
181
182                     monstermoves++;
183                     moves++;
184
185                     /********************************/
186                     /* once-per-turn things go here */
187                     /********************************/
188
189                     if (Glib)
190                         glibr();
191                     nh_timeout();
192                     run_regions();
193
194                     if (u.ublesscnt)
195                         u.ublesscnt--;
196                     if (flags.time && !context.run)
197                         context.botl = 1;
198
199                     /* One possible result of prayer is healing.  Whether or
200                      * not you get healed depends on your current hit points.
201                      * If you are allowed to regenerate during the prayer,
202                      * the end-of-prayer calculation messes up on this.
203                      * Another possible result is rehumanization, which
204                      * requires that encumbrance and movement rate be
205                      * recalculated.
206                      */
207                     if (u.uinvulnerable) {
208                         /* for the moment at least, you're in tiptop shape */
209                         wtcap = UNENCUMBERED;
210                     } else if (!Upolyd ? (u.uhp < u.uhpmax)
211                                        : (u.mh < u.mhmax
212                                           || youmonst.data->mlet == S_EEL)) {
213                         /* maybe heal */
214                         regen_hp(wtcap);
215                     }
216
217                     /* moving around while encumbered is hard work */
218                     if (wtcap > MOD_ENCUMBER && u.umoved) {
219                         if (!(wtcap < EXT_ENCUMBER ? moves % 30
220                                                    : moves % 10)) {
221                             if (Upolyd && u.mh > 1) {
222                                 u.mh--;
223                             } else if (!Upolyd && u.uhp > 1) {
224                                 u.uhp--;
225                             } else {
226 /*JP
227                                 You("pass out from exertion!");
228 */
229                                 pline("\94æ\98J\82Å\88Ó\8e¯\82ð\8e¸\82Á\82½\81I");
230                                 exercise(A_CON, FALSE);
231                                 fall_asleep(-10, FALSE);
232                             }
233                         }
234                     }
235
236                     if (u.uen < u.uenmax
237                         && ((wtcap < MOD_ENCUMBER
238                              && (!(moves % ((MAXULEV + 8 - u.ulevel)
239                                             * (Role_if(PM_WIZARD) ? 3 : 4)
240                                             / 6)))) || Energy_regeneration)) {
241                         u.uen += rn1(
242                             (int) (ACURR(A_WIS) + ACURR(A_INT)) / 15 + 1, 1);
243                         if (u.uen > u.uenmax)
244                             u.uen = u.uenmax;
245                         context.botl = 1;
246                         if (u.uen == u.uenmax)
247 /*JP
248                             interrupt_multi("You feel full of energy.");
249 */
250                             interrupt_multi("\83G\83l\83\8b\83M\81[\82ª\89ñ\95\9c\82µ\82½\81D");
251                     }
252
253                     if (!u.uinvulnerable) {
254                         if (Teleportation && !rn2(85)) {
255                             xchar old_ux = u.ux, old_uy = u.uy;
256                             tele();
257                             if (u.ux != old_ux || u.uy != old_uy) {
258                                 if (!next_to_u()) {
259                                     check_leash(old_ux, old_uy);
260                                 }
261                                 /* clear doagain keystrokes */
262                                 pushch(0);
263                                 savech(0);
264                             }
265                         }
266                         /* delayed change may not be valid anymore */
267                         if ((change == 1 && !Polymorph)
268                             || (change == 2 && u.ulycn == NON_PM))
269                             change = 0;
270                         if (Polymorph && !rn2(100))
271                             change = 1;
272                         else if (u.ulycn >= LOW_PM && !Upolyd
273                                  && !rn2(80 - (20 * night())))
274                             change = 2;
275                         if (change && !Unchanging) {
276                             if (multi >= 0) {
277                                 stop_occupation();
278                                 if (change == 1)
279                                     polyself(0);
280                                 else
281                                     you_were();
282                                 change = 0;
283                             }
284                         }
285                     }
286
287                     if (Searching && multi >= 0)
288                         (void) dosearch0(1);
289                     if (Warning)
290                         warnreveal();
291                     mkot_trap_warn();
292                     dosounds();
293                     do_storms();
294                     gethungry();
295                     age_spells();
296                     exerchk();
297                     invault();
298                     if (u.uhave.amulet)
299                         amulet();
300                     if (!rn2(40 + (int) (ACURR(A_DEX) * 3)))
301                         u_wipe_engr(rnd(3));
302                     if (u.uevent.udemigod && !u.uinvulnerable) {
303                         if (u.udg_cnt)
304                             u.udg_cnt--;
305                         if (!u.udg_cnt) {
306                             intervene();
307                             u.udg_cnt = rn1(200, 50);
308                         }
309                     }
310                     restore_attrib();
311                     /* underwater and waterlevel vision are done here */
312                     if (Is_waterlevel(&u.uz) || Is_airlevel(&u.uz))
313                         movebubbles();
314                     else if (Is_firelevel(&u.uz))
315                         fumaroles();
316                     else if (Underwater)
317                         under_water(0);
318                     /* vision while buried done here */
319                     else if (u.uburied)
320                         under_ground(0);
321
322                     /* when immobile, count is in turns */
323                     if (multi < 0) {
324                         if (++multi == 0) { /* finished yet? */
325                             unmul((char *) 0);
326                             /* if unmul caused a level change, take it now */
327                             if (u.utotype)
328                                 deferred_goto();
329                         }
330                     }
331                 }
332             } while (youmonst.movement
333                      < NORMAL_SPEED); /* hero can't move loop */
334
335             /******************************************/
336             /* once-per-hero-took-time things go here */
337             /******************************************/
338
339             status_eval_next_unhilite();
340             if (context.bypasses)
341                 clear_bypasses();
342             if ((u.uhave.amulet || Clairvoyant) && !In_endgame(&u.uz)
343                 && !BClairvoyant && !(moves % 15) && !rn2(2))
344                 do_vicinity_map((struct obj *) 0);
345             if (u.utrap && u.utraptype == TT_LAVA)
346                 sink_into_lava();
347             /* when/if hero escapes from lava, he can't just stay there */
348             else if (!u.umoved)
349                 (void) pooleffects(FALSE);
350
351         } /* actual time passed */
352
353         /****************************************/
354         /* once-per-player-input things go here */
355         /****************************************/
356
357         clear_splitobjs();
358         find_ac();
359         if (!context.mv || Blind) {
360             /* redo monsters if hallu or wearing a helm of telepathy */
361             if (Hallucination) { /* update screen randomly */
362                 see_monsters();
363                 see_objects();
364                 see_traps();
365                 if (u.uswallow)
366                     swallowed(0);
367             } else if (Unblind_telepat) {
368                 see_monsters();
369             } else if (Warning || Warn_of_mon)
370                 see_monsters();
371
372             if (vision_full_recalc)
373                 vision_recalc(0); /* vision! */
374         }
375         if (context.botl || context.botlx) {
376             bot();
377             curs_on_u();
378         }
379
380         context.move = 1;
381
382         if (multi >= 0 && occupation) {
383 #if defined(MICRO) || defined(WIN32)
384             abort_lev = 0;
385             if (kbhit()) {
386                 if ((ch = pgetchar()) == ABORT)
387                     abort_lev++;
388                 else
389                     pushch(ch);
390             }
391             if (!abort_lev && (*occupation)() == 0)
392 #else
393             if ((*occupation)() == 0)
394 #endif
395                 occupation = 0;
396             if (
397 #if defined(MICRO) || defined(WIN32)
398                 abort_lev ||
399 #endif
400                 monster_nearby()) {
401                 stop_occupation();
402                 reset_eat();
403             }
404 #if defined(MICRO) || defined(WIN32)
405             if (!(++occtime % 7))
406                 display_nhwindow(WIN_MAP, FALSE);
407 #endif
408             continue;
409         }
410
411         if (iflags.sanity_check)
412             sanity_check();
413
414 #ifdef CLIPPING
415         /* just before rhack */
416         cliparound(u.ux, u.uy);
417 #endif
418
419         u.umoved = FALSE;
420
421         if (multi > 0) {
422             lookaround();
423             if (!multi) {
424                 /* lookaround may clear multi */
425                 context.move = 0;
426                 if (flags.time)
427                     context.botl = 1;
428                 continue;
429             }
430             if (context.mv) {
431                 if (multi < COLNO && !--multi)
432                     context.travel = context.travel1 = context.mv =
433                         context.run = 0;
434                 domove();
435             } else {
436                 --multi;
437                 rhack(save_cm);
438             }
439         } else if (multi == 0) {
440 #ifdef MAIL
441             ckmailstatus();
442 #endif
443             rhack((char *) 0);
444         }
445         if (u.utotype)       /* change dungeon level */
446             deferred_goto(); /* after rhack() */
447         /* !context.move here: multiple movement command stopped */
448         else if (flags.time && (!context.move || !context.mv))
449             context.botl = 1;
450
451         if (vision_full_recalc)
452             vision_recalc(0); /* vision! */
453         /* when running in non-tport mode, this gets done through domove() */
454         if ((!context.run || flags.runmode == RUN_TPORT)
455             && (multi && (!context.travel ? !(multi % 7) : !(moves % 7L)))) {
456             if (flags.time && context.run)
457                 context.botl = 1;
458             display_nhwindow(WIN_MAP, FALSE);
459         }
460     }
461 }
462
463 /* maybe recover some lost health (or lose some when an eel out of water) */
464 STATIC_OVL void
465 regen_hp(wtcap)
466 int wtcap;
467 {
468     int heal = 0;
469     boolean reached_full = FALSE,
470             encumbrance_ok = (wtcap < MOD_ENCUMBER || !u.umoved);
471
472     if (Upolyd) {
473         if (u.mh < 1) { /* shouldn't happen... */
474             rehumanize();
475         } else if (youmonst.data->mlet == S_EEL
476                    && !is_pool(u.ux, u.uy) && !Is_waterlevel(&u.uz)) {
477             /* eel out of water loses hp, similar to monster eels;
478                as hp gets lower, rate of further loss slows down */
479             if (u.mh > 1 && !Regeneration && rn2(u.mh) > rn2(8)
480                 && (!Half_physical_damage || !(moves % 2L)))
481                 heal = -1;
482         } else if (u.mh < u.mhmax) {
483             if (Regeneration || (encumbrance_ok && !(moves % 20L)))
484                 heal = 1;
485         }
486         if (heal) {
487             context.botl = 1;
488             u.mh += heal;
489             reached_full = (u.mh == u.mhmax);
490         }
491
492     /* !Upolyd */
493     } else {
494         /* [when this code was in-line within moveloop(), there was
495            no !Upolyd check here, so poly'd hero recovered lost u.uhp
496            once u.mh reached u.mhmax; that may have been convenient
497            for the player, but it didn't make sense for gameplay...] */
498         if (u.uhp < u.uhpmax && (encumbrance_ok || Regeneration)) {
499             if (u.ulevel > 9) {
500                 if (!(moves % 3L)) {
501                     int Con = (int) ACURR(A_CON);
502
503                     if (Con <= 12) {
504                         heal = 1;
505                     } else {
506                         heal = rnd(Con);
507                         if (heal > u.ulevel - 9)
508                             heal = u.ulevel - 9;
509                     }
510                 }
511             } else { /* u.ulevel <= 9 */
512                 if (!(moves % (long) ((MAXULEV + 12) / (u.ulevel + 2) + 1)))
513                     heal = 1;
514             }
515             if (Regeneration && !heal)
516                 heal = 1;
517
518             if (heal) {
519                 context.botl = 1;
520                 u.uhp += heal;
521                 if (u.uhp > u.uhpmax)
522                     u.uhp = u.uhpmax;
523                 /* stop voluntary multi-turn activity if now fully healed */
524                 reached_full = (u.uhp == u.uhpmax);
525             }
526         }
527     }
528
529     if (reached_full)
530 /*JP
531         interrupt_multi("You are in full health.");
532 */
533         interrupt_multi("\91Ì\97Í\82ª\89ñ\95\9c\82µ\82½\81D");
534 }
535
536 void
537 stop_occupation()
538 {
539     if (occupation) {
540         if (!maybe_finished_meal(TRUE))
541 /*JP
542             You("stop %s.", occtxt);
543 */
544             You("%s\82Ì\82ð\92\86\92f\82µ\82½\81D", occtxt);
545         occupation = 0;
546         context.botl = 1; /* in case u.uhs changed */
547         nomul(0);
548         pushch(0);
549     } else if (multi >= 0) {
550         nomul(0);
551     }
552 }
553
554 void
555 display_gamewindows()
556 {
557     WIN_MESSAGE = create_nhwindow(NHW_MESSAGE);
558 #ifdef STATUS_HILITES
559     status_initialize(0);
560 #else
561     WIN_STATUS = create_nhwindow(NHW_STATUS);
562 #endif
563     WIN_MAP = create_nhwindow(NHW_MAP);
564     WIN_INVEN = create_nhwindow(NHW_MENU);
565     /* in case of early quit where WIN_INVEN could be destroyed before
566        ever having been used, use it here to pacify the Qt interface */
567     start_menu(WIN_INVEN), end_menu(WIN_INVEN, (char *) 0);
568
569 #ifdef MAC
570     /* This _is_ the right place for this - maybe we will
571      * have to split display_gamewindows into create_gamewindows
572      * and show_gamewindows to get rid of this ifdef...
573      */
574     if (!strcmp(windowprocs.name, "mac"))
575         SanePositions();
576 #endif
577
578     /*
579      * The mac port is not DEPENDENT on the order of these
580      * displays, but it looks a lot better this way...
581      */
582 #ifndef STATUS_HILITES
583     display_nhwindow(WIN_STATUS, FALSE);
584 #endif
585     display_nhwindow(WIN_MESSAGE, FALSE);
586     clear_glyph_buffer();
587     display_nhwindow(WIN_MAP, FALSE);
588 }
589
590 void
591 newgame()
592 {
593     int i;
594
595 #ifdef MFLOPPY
596     gameDiskPrompt();
597 #endif
598
599     context.botlx = 1;
600     context.ident = 1;
601     context.stethoscope_move = -1L;
602     context.warnlevel = 1;
603     context.next_attrib_check = 600L; /* arbitrary first setting */
604     context.tribute.enabled = TRUE;   /* turn on 3.6 tributes    */
605     context.tribute.tributesz = sizeof(struct tribute_info);
606
607     for (i = LOW_PM; i < NUMMONS; i++)
608         mvitals[i].mvflags = mons[i].geno & G_NOCORPSE;
609
610     init_objects(); /* must be before u_init() */
611
612     flags.pantheon = -1; /* role_init() will reset this */
613     role_init();         /* must be before init_dungeons(), u_init(),
614                           * and init_artifacts() */
615
616     init_dungeons();  /* must be before u_init() to avoid rndmonst()
617                        * creating odd monsters for any tins and eggs
618                        * in hero's initial inventory */
619     init_artifacts(); /* before u_init() in case $WIZKIT specifies
620                        * any artifacts */
621     u_init();
622
623 #ifndef NO_SIGNAL
624     (void) signal(SIGINT, (SIG_RET_TYPE) done1);
625 #endif
626 #ifdef NEWS
627     if (iflags.news)
628         display_file(NEWS, FALSE);
629 #endif
630     load_qtlist();          /* load up the quest text info */
631     /* quest_init();  --  Now part of role_init() */
632
633     mklev();
634     u_on_upstairs();
635     if (wizard)
636         obj_delivery(FALSE); /* finish wizkit */
637     vision_reset();          /* set up internals for level (after mklev) */
638     check_special_room(FALSE);
639
640     if (MON_AT(u.ux, u.uy))
641         mnexto(m_at(u.ux, u.uy));
642     (void) makedog();
643     docrt();
644
645     if (flags.legacy) {
646         flush_screen(1);
647         com_pager(1);
648     }
649
650     urealtime.realtime = 0L;
651     urealtime.start_timing = getnow();
652 #ifdef INSURANCE
653     save_currentstate();
654 #endif
655     program_state.something_worth_saving++; /* useful data now exists */
656
657     /* Success! */
658     welcome(TRUE);
659     return;
660 }
661
662 /* show "welcome [back] to nethack" message at program startup */
663 void
664 welcome(new_game)
665 boolean new_game; /* false => restoring an old game */
666 {
667     char buf[BUFSZ];
668     boolean currentgend = Upolyd ? u.mfemale : flags.female;
669
670     /* skip "welcome back" if restoring a doomed character */
671     if (!new_game && Upolyd && ugenocided()) {
672         /* death via self-genocide is pending */
673 /*JP
674         pline("You're back, but you still feel %s inside.", udeadinside());
675 */
676         pline("\82 \82È\82½\82Í\8bA\82Á\82Ä\82«\82½\82ª\81C\8d°\82ª%s\82Ü\82Ü\82¾\81D", udeadinside());
677         return;
678     }
679
680     /*
681      * The "welcome back" message always describes your innate form
682      * even when polymorphed or wearing a helm of opposite alignment.
683      * Alignment is shown unconditionally for new games; for restores
684      * it's only shown if it has changed from its original value.
685      * Sex is shown for new games except when it is redundant; for
686      * restores it's only shown if different from its original value.
687      */
688     *buf = '\0';
689     if (new_game || u.ualignbase[A_ORIGINAL] != u.ualignbase[A_CURRENT])
690 /*JP
691         Sprintf(eos(buf), " %s", align_str(u.ualignbase[A_ORIGINAL]));
692 */
693         Sprintf(eos(buf), "%s", align_str(u.ualignbase[A_ORIGINAL]));
694     if (!urole.name.f
695         && (new_game
696                 ? (urole.allow & ROLE_GENDMASK) == (ROLE_MALE | ROLE_FEMALE)
697                 : currentgend != flags.initgend))
698 /*JP
699         Sprintf(eos(buf), " %s", genders[currentgend].adj);
700 */
701         Sprintf(eos(buf), "\82Ì%s", genders[currentgend].adj);
702
703 #if 0 /*JP*/
704     pline(new_game ? "%s %s, welcome to NetHack!  You are a%s %s %s."
705                    : "%s %s, the%s %s %s, welcome back to NetHack!",
706           Hello((struct monst *) 0), plname, buf, urace.adj,
707           (currentgend && urole.name.f) ? urole.name.f : urole.name.m);
708 #else
709     if(new_game){
710         pline("%s\81CNetHack\82Ì\90¢\8aE\82Ö\81I\82±\82Ì\83Q\81[\83\80\82Å\82Í\82 \82È\82½\82Í%s%s(%s)\82¾\81D",
711               Hello((struct monst *) 0), urace.adj,
712               (currentgend && urole.name.f) ? urole.name.f : urole.name.m,
713               buf);
714     } else {
715         pline("%s\81CNetHack\82Ì\90¢\8aE\82Ö\81I\82 \82È\82½\82Í%s%s\82¾\81I",
716               Hello((struct monst *) 0), urace.adj,
717               (currentgend && urole.name.f) ? urole.name.f : urole.name.m);
718     }
719 #endif
720 }
721
722 #ifdef POSITIONBAR
723 STATIC_DCL void
724 do_positionbar()
725 {
726     static char pbar[COLNO];
727     char *p;
728
729     p = pbar;
730     /* up stairway */
731     if (upstair.sx
732         && (glyph_to_cmap(level.locations[upstair.sx][upstair.sy].glyph)
733                 == S_upstair
734             || glyph_to_cmap(level.locations[upstair.sx][upstair.sy].glyph)
735                    == S_upladder)) {
736         *p++ = '<';
737         *p++ = upstair.sx;
738     }
739     if (sstairs.sx
740         && (glyph_to_cmap(level.locations[sstairs.sx][sstairs.sy].glyph)
741                 == S_upstair
742             || glyph_to_cmap(level.locations[sstairs.sx][sstairs.sy].glyph)
743                    == S_upladder)) {
744         *p++ = '<';
745         *p++ = sstairs.sx;
746     }
747
748     /* down stairway */
749     if (dnstair.sx
750         && (glyph_to_cmap(level.locations[dnstair.sx][dnstair.sy].glyph)
751                 == S_dnstair
752             || glyph_to_cmap(level.locations[dnstair.sx][dnstair.sy].glyph)
753                    == S_dnladder)) {
754         *p++ = '>';
755         *p++ = dnstair.sx;
756     }
757     if (sstairs.sx
758         && (glyph_to_cmap(level.locations[sstairs.sx][sstairs.sy].glyph)
759                 == S_dnstair
760             || glyph_to_cmap(level.locations[sstairs.sx][sstairs.sy].glyph)
761                    == S_dnladder)) {
762         *p++ = '>';
763         *p++ = sstairs.sx;
764     }
765
766     /* hero location */
767     if (u.ux) {
768         *p++ = '@';
769         *p++ = u.ux;
770     }
771     /* fence post */
772     *p = 0;
773
774     update_positionbar(pbar);
775 }
776 #endif
777
778 STATIC_DCL void
779 interrupt_multi(msg)
780 const char *msg;
781 {
782     if (multi > 0 && !context.travel && !context.run) {
783         nomul(0);
784         if (flags.verbose && msg)
785             Norep("%s", msg);
786     }
787 }
788
789 /*
790  * Argument processing helpers - for xxmain() to share
791  * and call.
792  *
793  * These should return TRUE if the argument matched,
794  * whether the processing of the argument was
795  * successful or not.
796  *
797  * Most of these do their thing, then after returning
798  * to xxmain(), the code exits without starting a game.
799  *
800  */
801
802 static struct early_opt earlyopts[] = {
803     {ARG_DEBUG, "debug", 5, FALSE},
804     {ARG_VERSION, "version", 4, TRUE},
805 };
806
807 boolean
808 argcheck(argc, argv, e_arg)
809 int argc;
810 char *argv[];
811 enum earlyarg e_arg;
812 {
813     int i, idx;
814     boolean match = FALSE;
815     char *userea = (char *)0;
816     const char *dashdash = "";
817
818     for (idx = 0; idx < SIZE(earlyopts); idx++) {
819         if (earlyopts[idx].e == e_arg)
820             break;
821     }
822     if ((idx >= SIZE(earlyopts)) || (argc <= 1))
823             return FALSE;
824
825     for (i = 1; i < argc; ++i) {
826         if (argv[i][0] != '-')
827             continue;
828         if (argv[i][1] == '-') {
829             userea = &argv[i][2];
830             dashdash = "-";
831         } else {
832             userea = &argv[i][1];
833         }
834         match = match_optname(userea, earlyopts[idx].name,
835                     earlyopts[idx].minlength, earlyopts[idx].valallowed);
836         if (match) break;
837     }
838
839     if (match) {
840         switch(e_arg) {
841             case ARG_DEBUG:
842                         break;
843             case ARG_VERSION: {
844                         boolean insert_into_pastebuf = FALSE;
845                         const char *extended_opt = index(userea,':');
846
847                         if (!extended_opt)
848                             extended_opt = index(userea, '=');
849
850                         if (extended_opt) {
851                             extended_opt++;
852                             if (match_optname(extended_opt, "paste",
853                                                    5, FALSE)) {
854                                 insert_into_pastebuf = TRUE;
855                             } else {
856                                 raw_printf(
857                      "-%sversion can only be extended with -%sversion:paste.\n",
858                                             dashdash, dashdash);
859                                 return TRUE;
860                             }
861                         }
862                         early_version_info(insert_into_pastebuf);
863                         return TRUE;
864                         break;
865             }
866             default:
867                         break;
868         }
869     };
870     return FALSE;
871 }
872
873 /*allmain.c*/