EDIT_GETLIN vs monpolycontrol

For wizard mode 'monpolycontrol', the getlin() answer buffer for the
"Change <monster> @ <x,y> into what kind of monster?" prompt is also
used to format the coordinate portion of that prompt, so when
EDIT_GETLIN is enabled getlin() was inadvertently given "<x,y>" to use
as default response.  Clear it after the prompt is formatted instead
of via an initializer.  Also, shorten the prompt on the first try:
"Change <monster> @ <x,y> into what?", expanding to the old prompt if
retry is needed.

This also allows specifying 'chameleon' when <monster> is a chameleon,
'doppelganger' when it's a doppelganger, and 'sandestin' when it's one
of those (but not 'doppelganger' when it's a chameleon or sandestin,
and so forth), instead of blanket refusal to accept any non-vampire
shapechanger as the choice.
This commit is contained in:
PatR
2019-06-15 04:13:34 -07:00
parent a336caf461
commit f0633e6541
2 changed files with 51 additions and 19 deletions

View File

@@ -1,4 +1,4 @@
$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.52 $ $NHDT-Date: 1560387439 2019/06/13 00:57:19 $
$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.53 $ $NHDT-Date: 1560597210 2019/06/15 11:13:30 $
This fixes36.3 file is here to capture information about updates in the 3.6.x
lineage following the release of 3.6.2 in May 2019. Please note, however,
@@ -73,6 +73,9 @@ don't give feedback for monster zapping a wand if a monster plays a fire horn
if hero knows the number of charges in a wand or magical horn and a monster
acquires it and zaps/plays it when not in view, remove the hero's
memory of the number of charges
for wizard mode 'monpolycontrol', allow usually disallowed type 'chameleon',
'doppelganger', or 'sandestin' as answer to "change <monster> @ <x,y>
into what?" prompt when <monster> is really that type of creature
Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository
@@ -90,6 +93,9 @@ curses: sometimes the message window would show a blank line after a prompt
Platform- and/or Interface-Specific Fixes or Features
-----------------------------------------------------
EDIT_GETLIN: wizard mode 'monpolycontrol' was using the getlin() answer buffer
to format the coordinate portion of the "change <monster> @ <x,y> into
what kind of monster?" prompt, resulting in "<x,y>" as default answer
curses: very tall menus tried to use selector characters a-z, A-Z, and 0-9,
but 0-9 should be reserved for counts and if the display was tall
enough for more than 62 entries, arbitrary ASCII punctuation got used

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 mon.c $NHDT-Date: 1559733390 2019/06/05 11:16:30 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.292 $ */
/* NetHack 3.6 mon.c $NHDT-Date: 1560597210 2019/06/15 11:13:30 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.293 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -24,7 +24,7 @@ STATIC_DCL void FDECL(kill_eggs, (struct obj *));
STATIC_DCL int FDECL(pickvampshape, (struct monst *));
STATIC_DCL boolean FDECL(isspecmon, (struct monst *));
STATIC_DCL boolean FDECL(validspecmon, (struct monst *, int));
STATIC_DCL struct permonst *FDECL(accept_newcham_form, (int));
STATIC_DCL struct permonst *FDECL(accept_newcham_form, (struct monst *, int));
STATIC_DCL struct obj *FDECL(make_corpse, (struct monst *, unsigned));
STATIC_DCL void FDECL(m_detach, (struct monst *, struct permonst *));
STATIC_DCL void FDECL(lifesaved_monster, (struct monst *));
@@ -3404,7 +3404,7 @@ int mndx;
if (mndx == NON_PM)
return TRUE; /* caller wants random */
if (!accept_newcham_form(mndx))
if (!accept_newcham_form(mon, mndx))
return FALSE; /* geno'd or !polyok */
if (isspecmon(mon)) {
@@ -3429,17 +3429,17 @@ int *mndx_p, monclass;
if (!is_vampshifter(mon))
return validspecmon(mon, *mndx_p);
if (*mndx_p == PM_VAMPIRE || *mndx_p == PM_VAMPIRE_LORD
|| *mndx_p == PM_VLAD_THE_IMPALER) {
/* player picked some type of vampire; use mon's self */
*mndx_p = mon->cham;
return TRUE;
}
if (mon->cham == PM_VLAD_THE_IMPALER && mon_has_special(mon)) {
/* Vlad with Candelabrum; override choice, then accept it */
*mndx_p = PM_VLAD_THE_IMPALER;
return TRUE;
}
if (*mndx_p >= LOW_PM && is_shapeshifter(&mons[*mndx_p])) {
/* player picked some type of shapeshifter; use mon's self
(vampire or chameleon) */
*mndx_p = mon->cham;
return TRUE;
}
/* basic vampires can't become wolves; any can become fog or bat
(we don't enforce upper-case only for rogue level here) */
if (*mndx_p == PM_WOLF)
@@ -3463,7 +3463,7 @@ int *mndx_p, monclass;
*mndx_p = PM_WOLF;
break;
}
/*FALLTHRU*/
/*FALLTHRU*/
default:
*mndx_p = NON_PM;
break;
@@ -3526,16 +3526,35 @@ struct monst *mon;
/* for debugging: allow control of polymorphed monster */
if (wizard && iflags.mon_polycontrol) {
char pprompt[BUFSZ], buf[BUFSZ] = DUMMY;
int monclass;
char pprompt[BUFSZ], parttwo[QBUFSZ], buf[BUFSZ];
int monclass, len;
Sprintf(pprompt, "Change %s @ %s into what kind of monster?",
noit_mon_nam(mon),
/* construct prompt in pieces */
Sprintf(pprompt, "Change %s", noit_mon_nam(mon));
Sprintf(parttwo, " @ %s into what?",
coord_desc((int) mon->mx, (int) mon->my, buf,
(iflags.getpos_coords != GPCOORDS_NONE)
? iflags.getpos_coords : GPCOORDS_MAP));
tryct = 5;
/* combine the two parts, not exceeding QBUFSZ-1 in overall length;
if combined length is too long it has to be due to monster's
name so we'll chop enough of that off to fit the second part */
if ((len = (int) strlen(pprompt) + (int) strlen(parttwo)) >= QBUFSZ)
/* strlen(parttwo) is less than QBUFSZ/2 so strlen(pprompt) is
more than QBUFSZ/2 and excess amount being truncated can't
exceed pprompt's length and back up to before &pprompt[0]) */
*(eos(pprompt) - (len - (QBUFSZ - 1))) = '\0';
Strcat(pprompt, parttwo);
buf[0] = '\0'; /* clear buffer for EDIT_GETLIN */
#define TRYLIMIT 5
tryct = TRYLIMIT;
do {
if (tryct == TRYLIMIT - 1) { /* first retry */
/* change "into what?" to "into what kind of monster?" */
if (strlen(pprompt) + sizeof " kind of monster" - 1 < QBUFSZ)
Strcpy(eos(pprompt) - 1, " kind of monster?");
}
#undef TRYLIMIT
monclass = 0;
getlin(pprompt, buf);
mungspaces(buf);
@@ -3543,7 +3562,7 @@ struct monst *mon;
if (*buf == '\033')
break;
/* for "*", use NON_PM to pick an arbitrary shape below */
if (!strcmp(buf, "*") || !strcmp(buf, "random")) {
if (!strcmp(buf, "*") || !strcmpi(buf, "random")) {
mndx = NON_PM;
break;
}
@@ -3565,6 +3584,7 @@ struct monst *mon;
pline("It can't become that.");
} while (--tryct > 0);
if (!tryct)
pline1(thats_enough_tries);
if (is_vampshifter(mon) && !validvamp(mon, &mndx, monclass))
@@ -3586,7 +3606,8 @@ struct monst *mon;
/* this used to be inline within newcham() but monpolycontrol needs it too */
STATIC_OVL struct permonst *
accept_newcham_form(mndx)
accept_newcham_form(mon, mndx)
struct monst *mon;
int mndx;
{
struct permonst *mdat;
@@ -3603,6 +3624,11 @@ int mndx;
polyok() rejects, so we need a special case here */
if (is_mplayer(mdat))
return mdat;
/* shapeshifters are rejected by polyok() but allow a shapeshifter
to take on its 'natural' form */
if (is_shapeshifter(mdat)
&& mon->cham >= LOW_PM && mdat == &mons[mon->cham])
return mdat;
/* polyok() rules out M2_PNAME, M2_WERE, and all humans except Kops */
return polyok(mdat) ? mdat : 0;
}
@@ -3674,7 +3700,7 @@ boolean msg; /* "The oldmon turns into a newmon!" */
tryct = 20;
do {
mndx = select_newcham_form(mtmp);
mdat = accept_newcham_form(mndx);
mdat = accept_newcham_form(mtmp, mndx);
/* for the first several tries we require upper-case on
the rogue level (after that, we take whatever we get) */
if (tryct > 15 && Is_rogue_level(&u.uz)