From d2ae6fd5d2f487299e8760fc557d80f1e0706625 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Fri, 8 Dec 2023 08:32:07 +0200 Subject: [PATCH] Split out wizmode monpolycontrol part --- src/mon.c | 157 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 82 insertions(+), 75 deletions(-) diff --git a/src/mon.c b/src/mon.c index 5d736be1e..ce6a6dcaf 100644 --- a/src/mon.c +++ b/src/mon.c @@ -30,6 +30,7 @@ static int pick_animal(void); static int pickvampshape(struct monst *); static boolean isspecmon(struct monst *); static boolean validspecmon(struct monst *, int); +static int wiz_force_cham_form(struct monst *); static struct permonst *accept_newcham_form(struct monst *, int); static void kill_eggs(struct obj *); static void pacify_guard(struct monst *); @@ -4623,6 +4624,85 @@ validvamp(struct monst* mon, int* mndx_p, int monclass) return (boolean) (*mndx_p != NON_PM); } +static int +wiz_force_cham_form(struct monst *mon) +{ + char pprompt[BUFSZ], parttwo[QBUFSZ], buf[BUFSZ], prevbuf[BUFSZ]; + int monclass, len, tryct, mndx = NON_PM; + + /* 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)); + /* 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] = prevbuf[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); + /* for ESC, take form selected above (might be NON_PM) */ + if (*buf == '\033') + break; + /* for "*", use NON_PM to pick an arbitrary shape below */ + if (!strcmp(buf, "*") || !strcmpi(buf, "random")) { + mndx = NON_PM; + break; + } + mndx = name_to_mon(buf, (int *) 0); + if (mndx == NON_PM) { + /* didn't get a type, so check whether it's a class + (single letter or text match with def_monsyms[]) */ + monclass = name_to_monclass(buf, &mndx); + if (monclass && mndx == NON_PM) + mndx = mkclass_poly(monclass); + } + if (mndx >= LOW_PM) { + /* got a specific type of monster; use it if we can */ + if (validvamp(mon, &mndx, monclass)) + break; + /* can't; revert to random in case we exhaust tryct */ + mndx = NON_PM; + } + + pline("It can't become that."); +#ifdef EDIT_GETLIN + /* EDIT_GETLIN preloads the input buffer with the previous + response but we shouldn't just keep repeating that if player + leaves it unchanged; affects retry for empty input too */ + if (!strcmp(buf, prevbuf)) + Strcpy(buf, "random"); + Strcpy(prevbuf, buf); +#else + nhUse(prevbuf); +#endif + } while (--tryct > 0); + + if (!tryct) + pline1(thats_enough_tries); + if (is_vampshifter(mon) && !validvamp(mon, &mndx, monclass)) + mndx = pickvampshape(mon); /* don't resort to arbitrary */ + return mndx; +} + int select_newcham_form(struct monst* mon) { @@ -4676,81 +4756,8 @@ select_newcham_form(struct monst* mon) } /* for debugging: allow control of polymorphed monster */ - if (wizard && iflags.mon_polycontrol) { - char pprompt[BUFSZ], parttwo[QBUFSZ], buf[BUFSZ], prevbuf[BUFSZ]; - int monclass, len; - - /* 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)); - /* 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] = prevbuf[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); - /* for ESC, take form selected above (might be NON_PM) */ - if (*buf == '\033') - break; - /* for "*", use NON_PM to pick an arbitrary shape below */ - if (!strcmp(buf, "*") || !strcmpi(buf, "random")) { - mndx = NON_PM; - break; - } - mndx = name_to_mon(buf, (int *) 0); - if (mndx == NON_PM) { - /* didn't get a type, so check whether it's a class - (single letter or text match with def_monsyms[]) */ - monclass = name_to_monclass(buf, &mndx); - if (monclass && mndx == NON_PM) - mndx = mkclass_poly(monclass); - } - if (mndx >= LOW_PM) { - /* got a specific type of monster; use it if we can */ - if (validvamp(mon, &mndx, monclass)) - break; - /* can't; revert to random in case we exhaust tryct */ - mndx = NON_PM; - } - - pline("It can't become that."); -#ifdef EDIT_GETLIN - /* EDIT_GETLIN preloads the input buffer with the previous - response but we shouldn't just keep repeating that if player - leaves it unchanged; affects retry for empty input too */ - if (!strcmp(buf, prevbuf)) - Strcpy(buf, "random"); - Strcpy(prevbuf, buf); -#else - nhUse(prevbuf); -#endif - } while (--tryct > 0); - - if (!tryct) - pline1(thats_enough_tries); - if (is_vampshifter(mon) && !validvamp(mon, &mndx, monclass)) - mndx = pickvampshape(mon); /* don't resort to arbitrary */ - } + if (wizard && iflags.mon_polycontrol) + mndx = wiz_force_cham_form(mon); /* if no form was specified above, pick one at random now */ if (mndx == NON_PM) {