OSDN Git Service

upgrade to 3.6.2
[jnethack/source.git] / src / read.c
index 2881b19..943eec8 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 read.c  $NHDT-Date: 1515802375 2018/01/13 00:12:55 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.150 $ */
+/* NetHack 3.6 read.c  $NHDT-Date: 1546465285 2019/01/02 21:41:25 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.164 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -24,19 +24,23 @@ static NEARDATA const char readable[] = { ALL_CLASSES, SCROLL_CLASS,
 static const char all_count[] = { ALLOW_COUNT, ALL_CLASSES, 0 };
 
 STATIC_DCL boolean FDECL(learnscrolltyp, (SHORT_P));
-STATIC_DCL char * FDECL(erode_obj_text, (struct obj *, char *));
-STATIC_DCL void NDECL(do_class_genocide);
+STATIC_DCL char *FDECL(erode_obj_text, (struct obj *, char *));
+STATIC_DCL char *FDECL(apron_text, (struct obj *, char *buf));
 STATIC_DCL void FDECL(stripspe, (struct obj *));
 STATIC_DCL void FDECL(p_glow1, (struct obj *));
 STATIC_DCL void FDECL(p_glow2, (struct obj *, const char *));
-STATIC_DCL void FDECL(randomize, (int *, int));
 STATIC_DCL void FDECL(forget_single_object, (int));
+#if 0 /* not used */
+STATIC_DCL void FDECL(forget_objclass, (int));
+#endif
+STATIC_DCL void FDECL(randomize, (int *, int));
 STATIC_DCL void FDECL(forget, (int));
 STATIC_DCL int FDECL(maybe_tame, (struct monst *, struct obj *));
-STATIC_DCL boolean FDECL(is_valid_stinking_cloud_pos, (int, int, BOOLEAN_P));
-STATIC_DCL void FDECL(display_stinking_cloud_positions, (int));
 STATIC_DCL boolean FDECL(get_valid_stinking_cloud_pos, (int, int));
+STATIC_DCL boolean FDECL(is_valid_stinking_cloud_pos, (int, int, BOOLEAN_P));
+STATIC_PTR void FDECL(display_stinking_cloud_positions, (int));
 STATIC_PTR void FDECL(set_lit, (int, int, genericptr));
+STATIC_DCL void NDECL(do_class_genocide);
 
 STATIC_OVL boolean
 learnscrolltyp(scrolltyp)
@@ -61,7 +65,7 @@ struct obj *sobj;
         (void) learnscrolltyp(sobj->otyp);
 }
 
-char *
+STATIC_OVL char *
 erode_obj_text(otmp, buf)
 struct obj *otmp;
 char *buf;
@@ -250,7 +254,7 @@ char *buf;
     return erode_obj_text(tshirt, buf);
 }
 
-char *
+STATIC_OVL char *
 apron_text(apron, buf)
 struct obj *apron;
 char *buf;
@@ -503,6 +507,7 @@ doread()
         return 0;
     } else if (Blind && (scroll->otyp != SPE_BOOK_OF_THE_DEAD)) {
         const char *what = 0;
+
         if (scroll->oclass == SPBOOK_CLASS)
 /*JP
             what = "mystic runes";
@@ -1200,7 +1205,7 @@ int x,y;
               || distu(x, y) >= 32));
 }
 
-boolean
+STATIC_OVL boolean
 is_valid_stinking_cloud_pos(x, y, showmsg)
 int x, y;
 boolean showmsg;
@@ -1216,7 +1221,7 @@ boolean showmsg;
     return TRUE;
 }
 
-void
+STATIC_PTR void
 display_stinking_cloud_positions(state)
 int state;
 {
@@ -2089,7 +2094,8 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
                 pline("Where do you want to center the explosion?");
 */
                 pline("\82Ç\82±\82ð\94\9a\94­\82Ì\92\86\90S\82É\82µ\82Ü\82·\82©\81H");
-                getpos_sethilite(display_stinking_cloud_positions, get_valid_stinking_cloud_pos);
+                getpos_sethilite(display_stinking_cloud_positions,
+                                 get_valid_stinking_cloud_pos);
 /*JP
                 (void) getpos(&cc, TRUE, "the desired position");
 */
@@ -2188,7 +2194,8 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
 #endif
         cc.x = u.ux;
         cc.y = u.uy;
-        getpos_sethilite(display_stinking_cloud_positions, get_valid_stinking_cloud_pos);
+        getpos_sethilite(display_stinking_cloud_positions,
+                         get_valid_stinking_cloud_pos);
 /*JP
         if (getpos(&cc, TRUE, "the desired position") < 0) {
 */
@@ -2205,6 +2212,11 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
     default:
         impossible("What weird effect is this? (%u)", otyp);
     }
+    /* if sobj is gone, we've already called useup() above and the
+       update_inventory() that it performs might have come too soon
+       (before charging an item, for instance) */
+    if (!sobj)
+        update_inventory();
     return sobj ? 0 : 1;
 }
 
@@ -2335,7 +2347,7 @@ boolean confused, byu;
             }
         }
         mtmp->mhp -= mdmg;
-        if (mtmp->mhp <= 0) {
+        if (DEADMONSTER(mtmp)) {
             if (byu) {
                 killed(mtmp);
             } else {
@@ -3029,8 +3041,8 @@ struct obj *sobj;
     uball->spe = 1; /* special ball (see save) */
 
     /*
-     *  Place ball & chain if not swallowed.  If swallowed, the ball &
-     *  chain variables will be set at the next call to placebc().
+     *  Place ball & chain if not swallowed.  If swallowed, the ball & chain
+     *  variables will be set at the next call to placebc().
      */
     if (!u.uswallow) {
         placebc();
@@ -3083,6 +3095,185 @@ struct obj *from_obj;
     return FALSE;
 }
 
+struct _create_particular_data {
+    int which;
+    int fem;
+    char monclass;
+    boolean randmonst;
+    boolean maketame, makepeaceful, makehostile;
+    boolean sleeping, saddled, invisible;
+};
+
+boolean
+create_particular_parse(str, d)
+char *str;
+struct _create_particular_data *d;
+{
+    char *bufp = str;
+    char *tmpp;
+
+    d->monclass = MAXMCLASSES;
+    d->which = urole.malenum; /* an arbitrary index into mons[] */
+    d->fem = -1; /* gender not specified */
+    d->randmonst = FALSE;
+    d->maketame = d->makepeaceful = d->makehostile = FALSE;
+    d->sleeping = d->saddled = d->invisible = FALSE;
+
+    if ((tmpp = strstri(bufp, "saddled ")) != 0) {
+        d->saddled = TRUE;
+        (void) memset(tmpp, ' ', sizeof "saddled " - 1);
+    }
+    if ((tmpp = strstri(bufp, "sleeping ")) != 0) {
+        d->sleeping = TRUE;
+        (void) memset(tmpp, ' ', sizeof "sleeping " - 1);
+    }
+    if ((tmpp = strstri(bufp, "invisible ")) != 0) {
+        d->invisible = TRUE;
+        (void) memset(tmpp, ' ', sizeof "invisible " - 1);
+    }
+    /* check "female" before "male" to avoid false hit mid-word */
+    if ((tmpp = strstri(bufp, "female ")) != 0) {
+        d->fem = 1;
+        (void) memset(tmpp, ' ', sizeof "female " - 1);
+    }
+    if ((tmpp = strstri(bufp, "male ")) != 0) {
+        d->fem = 0;
+        (void) memset(tmpp, ' ', sizeof "male " - 1);
+    }
+    bufp = mungspaces(bufp); /* after potential memset(' ') */
+    /* allow the initial disposition to be specified */
+#if 0 /*JP*/
+    if (!strncmpi(bufp, "tame ", 5)) {
+        bufp += 5;
+#else
+    if (!strncmpi(bufp, "\8eè\82È\82¸\82¯\82ç\82ê\82½", 14)) {
+        bufp += 14;
+#endif
+        d->maketame = TRUE;
+#if 0 /*JP*/
+    } else if (!strncmpi(bufp, "peaceful ", 9)) {
+        bufp += 9;
+#else
+    } else if (!strncmpi(bufp, "\97F\8dD\93I\82È", 8)) {
+        bufp += 8;
+#endif
+        d->makepeaceful = TRUE;
+#if 0 /*JP*/
+    } else if (!strncmpi(bufp, "hostile ", 8)) {
+        bufp += 8;
+#else
+    } else if (!strncmpi(bufp, "\93G\91Î\93I\82È", 8)) {
+        bufp += 8;
+#endif
+        d->makehostile = TRUE;
+    }
+    /* decide whether a valid monster was chosen */
+/*JP
+        if (wizard && (!strcmp(bufp, "*") || !strcmp(bufp, "random"))) {
+*/
+        if (wizard && (!strcmp(bufp, "*") || !strcmp(bufp, "\83\89\83\93\83_\83\80"))) {
+        d->randmonst = TRUE;
+        return TRUE;
+    }
+    d->which = name_to_mon(bufp);
+    if (d->which >= LOW_PM)
+        return TRUE; /* got one */
+    d->monclass = name_to_monclass(bufp, &d->which);
+
+    if (d->which >= LOW_PM) {
+        d->monclass = MAXMCLASSES; /* matters below */
+        return TRUE;
+    } else if (d->monclass == S_invisible) { /* not an actual monster class */
+        d->which = PM_STALKER;
+        d->monclass = MAXMCLASSES;
+        return TRUE;
+    } else if (d->monclass == S_WORM_TAIL) { /* empty monster class */
+        d->which = PM_LONG_WORM;
+        d->monclass = MAXMCLASSES;
+        return TRUE;
+    } else if (d->monclass > 0) {
+        d->which = urole.malenum; /* reset from NON_PM */
+        return TRUE;
+    }
+    return FALSE;
+}
+
+boolean
+create_particular_creation(d)
+struct _create_particular_data *d;
+{
+    struct permonst *whichpm = NULL;
+    int i, firstchoice = NON_PM;
+    struct monst *mtmp;
+    boolean madeany = FALSE;
+
+    if (!d->randmonst) {
+        firstchoice = d->which;
+        if (cant_revive(&d->which, FALSE, (struct obj *) 0)
+            && firstchoice != PM_LONG_WORM_TAIL) {
+            /* wizard mode can override handling of special monsters */
+            char buf[BUFSZ];
+
+#if 0 /*JP*/
+            Sprintf(buf, "Creating %s instead; force %s?",
+                    mons[d->which].mname, mons[firstchoice].mname);
+#else
+            Sprintf(buf, "\91ã\82í\82è\82É%s\82ª\8dì\82ç\82ê\82Ü\82·\81G%s\82É\82·\82é\81H",
+                    mons[d->which].mname, mons[firstchoice].mname);
+#endif
+            if (yn(buf) == 'y')
+                d->which = firstchoice;
+        }
+        whichpm = &mons[d->which];
+    }
+    for (i = 0; i <= multi; i++) {
+        if (d->monclass != MAXMCLASSES)
+            whichpm = mkclass(d->monclass, 0);
+        else if (d->randmonst)
+            whichpm = rndmonst();
+        mtmp = makemon(whichpm, u.ux, u.uy, NO_MM_FLAGS);
+        if (!mtmp) {
+            /* quit trying if creation failed and is going to repeat */
+            if (d->monclass == MAXMCLASSES && !d->randmonst)
+                break;
+            /* otherwise try again */
+            continue;
+        }
+        /* 'is_FOO()' ought to be called 'always_FOO()' */
+        if (d->fem != -1 && !is_male(mtmp->data) && !is_female(mtmp->data))
+            mtmp->female = d->fem; /* ignored for is_neuter() */
+        if (d->maketame) {
+            (void) tamedog(mtmp, (struct obj *) 0);
+        } else if (d->makepeaceful || d->makehostile) {
+            mtmp->mtame = 0; /* sanity precaution */
+            mtmp->mpeaceful = d->makepeaceful ? 1 : 0;
+            set_malign(mtmp);
+        }
+        if (d->saddled && can_saddle(mtmp) && !which_armor(mtmp, W_SADDLE)) {
+            struct obj *otmp = mksobj(SADDLE, TRUE, FALSE);
+
+            put_saddle_on_mon(otmp, mtmp);
+        }
+        if (d->invisible) {
+            int mx = mtmp->mx, my = mtmp->my;
+            mon_set_minvis(mtmp);
+            if (does_block(mx, my, &levl[mx][my]))
+                block_point(mx, my);
+            else
+                unblock_point(mx, my);
+        }
+        if (d->sleeping)
+            mtmp->msleeping = 1;
+        madeany = TRUE;
+        /* in case we got a doppelganger instead of what was asked
+           for, make it start out looking like what was asked for */
+        if (mtmp->cham != NON_PM && firstchoice != NON_PM
+            && mtmp->cham != firstchoice)
+            (void) newcham(mtmp, &mons[firstchoice], FALSE, FALSE);
+    }
+    return madeany;
+}
+
 /*
  * Make a new monster with the type controlled by the user.
  *
@@ -3098,23 +3289,11 @@ struct obj *from_obj;
 boolean
 create_particular()
 {
-    char buf[BUFSZ] = DUMMY, *bufp, monclass;
-    char *tmpp;
-    int which, tryct, i, firstchoice = NON_PM;
-    struct permonst *whichpm = NULL;
-    struct monst *mtmp;
-    boolean madeany = FALSE, randmonst = FALSE,
-        maketame, makepeaceful, makehostile, saddled, invisible,
-        sleeping;
-    int fem;
+    char buf[BUFSZ] = DUMMY, *bufp;
+    int  tryct = 5;
+    struct _create_particular_data d;
 
-    tryct = 5;
     do {
-        monclass = MAXMCLASSES;
-        which = urole.malenum; /* an arbitrary index into mons[] */
-        maketame = makepeaceful = makehostile = FALSE;
-        sleeping = saddled = invisible = FALSE;
-        fem = -1; /* gender not specified */
 /*JP
         getlin("Create what kind of monster? [type the name or symbol]", buf);
 */
@@ -3122,73 +3301,10 @@ create_particular()
         bufp = mungspaces(buf);
         if (*bufp == '\033')
             return FALSE;
-        if ((tmpp = strstri(bufp, "saddled ")) != 0) {
-            saddled = TRUE;
-            (void) memset(tmpp, ' ', sizeof "saddled " - 1);
-        }
-        if ((tmpp = strstri(bufp, "sleeping ")) != 0) {
-            sleeping = TRUE;
-            (void) memset(tmpp, ' ', sizeof "sleeping " - 1);
-        }
-        if ((tmpp = strstri(bufp, "invisible ")) != 0) {
-            invisible = TRUE;
-            (void) memset(tmpp, ' ', sizeof "invisible " - 1);
-        }
-        /* check "female" before "male" to avoid false hit mid-word */
-        if ((tmpp = strstri(bufp, "female ")) != 0) {
-            fem = 1;
-            (void) memset(tmpp, ' ', sizeof "female " - 1);
-        }
-        if ((tmpp = strstri(bufp, "male ")) != 0) {
-            fem = 0;
-            (void) memset(tmpp, ' ', sizeof "male " - 1);
-        }
-        bufp = mungspaces(bufp); /* after potential memset(' ') */
-        /* allow the initial disposition to be specified */
-#if 0 /*JP*/
-        if (!strncmpi(bufp, "tame ", 5)) {
-            bufp += 5;
-#else
-        if (!strncmpi(bufp, "\8eè\82È\82¸\82¯\82ç\82ê\82½", 14)) {
-            bufp += 14;
-#endif
-            maketame = TRUE;
-#if 0 /*JP*/
-        } else if (!strncmpi(bufp, "peaceful ", 9)) {
-            bufp += 9;
-#else
-        } else if (!strncmpi(bufp, "\97F\8dD\93I\82È", 8)) {
-            bufp += 8;
-#endif
-            makepeaceful = TRUE;
-#if 0 /*JP*/
-        } else if (!strncmpi(bufp, "hostile ", 8)) {
-            bufp += 8;
-#else
-        } else if (!strncmpi(bufp, "\93G\91Î\93I\82È", 8)) {
-            bufp += 8;
-#endif
-            makehostile = TRUE;
-        }
-        /* decide whether a valid monster was chosen */
-/*JP
-        if (wizard && (!strcmp(bufp, "*") || !strcmp(bufp, "random"))) {
-*/
-        if (wizard && (!strcmp(bufp, "*") || !strcmp(bufp, "\83\89\83\93\83_\83\80"))) {
-            randmonst = TRUE;
-            break;
-        }
-        which = name_to_mon(bufp);
-        if (which >= LOW_PM)
-            break; /* got one */
-        monclass = name_to_monclass(bufp, &which);
-        if (which >= LOW_PM) {
-            monclass = MAXMCLASSES; /* matters below */
-            break;
-        } else if (monclass > 0) {
-            which = urole.malenum; /* reset from NON_PM */
+
+        if (create_particular_parse(bufp, &d))
             break;
-        }
+
         /* no good; try again... */
 /*JP
         pline("I've never heard of such monsters.");
@@ -3196,66 +3312,12 @@ create_particular()
         pline("\82»\82Ì\82æ\82¤\82È\89ö\95¨\82Í\95·\82¢\82½\82±\82Æ\82ª\82È\82¢\81D");
     } while (--tryct > 0);
 
-    if (!tryct) {
+    if (!tryct)
         pline1(thats_enough_tries);
-    } else {
-        if (!randmonst) {
-            firstchoice = which;
-            if (cant_revive(&which, FALSE, (struct obj *) 0)) {
-                /* wizard mode can override handling of special monsters */
-#if 0 /*JP*/
-                Sprintf(buf, "Creating %s instead; force %s?",
-                        mons[which].mname, mons[firstchoice].mname);
-#else
-                Sprintf(buf, "\91ã\82í\82è\82É%s\82ª\8dì\82ç\82ê\82Ü\82·\81G%s\82É\82·\82é\81H",
-                        mons[which].mname, mons[firstchoice].mname);
-#endif
-                if (yn(buf) == 'y')
-                    which = firstchoice;
-            }
-            whichpm = &mons[which];
-        }
-        for (i = 0; i <= multi; i++) {
-            if (monclass != MAXMCLASSES)
-                whichpm = mkclass(monclass, 0);
-            else if (randmonst)
-                whichpm = rndmonst();
-            mtmp = makemon(whichpm, u.ux, u.uy, NO_MM_FLAGS);
-            if (!mtmp) {
-                /* quit trying if creation failed and is going to repeat */
-                if (monclass == MAXMCLASSES && !randmonst)
-                    break;
-                /* otherwise try again */
-                continue;
-            }
-            /* 'is_FOO()' ought to be called 'always_FOO()' */
-            if (fem != -1 && !is_male(mtmp->data) && !is_female(mtmp->data))
-                mtmp->female = fem; /* ignored for is_neuter() */
-            if (maketame) {
-                (void) tamedog(mtmp, (struct obj *) 0);
-            } else if (makepeaceful || makehostile) {
-                mtmp->mtame = 0; /* sanity precaution */
-                mtmp->mpeaceful = makepeaceful ? 1 : 0;
-                set_malign(mtmp);
-            }
-            if (saddled && can_saddle(mtmp) && !which_armor(mtmp, W_SADDLE)) {
-                struct obj *otmp = mksobj(SADDLE, TRUE, FALSE);
+    else
+        return create_particular_creation(&d);
 
-                put_saddle_on_mon(otmp, mtmp);
-            }
-            if (invisible)
-                mon_set_minvis(mtmp);
-            if (sleeping)
-                mtmp->msleeping = 1;
-            madeany = TRUE;
-            /* in case we got a doppelganger instead of what was asked
-               for, make it start out looking like what was asked for */
-            if (mtmp->cham != NON_PM && firstchoice != NON_PM
-                && mtmp->cham != firstchoice)
-                (void) newcham(mtmp, &mons[firstchoice], FALSE, FALSE);
-        }
-    }
-    return madeany;
+    return FALSE;
 }
 
 /*read.c*/