Split string parsing and monster creation out of create_particular

This commit is contained in:
Pasi Kallinen
2018-08-28 19:52:15 +03:00
parent 599edde94d
commit 987516cedb

View File

@@ -2424,6 +2424,146 @@ 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 (!strncmpi(bufp, "tame ", 5)) {
bufp += 5;
d->maketame = TRUE;
} else if (!strncmpi(bufp, "peaceful ", 9)) {
bufp += 9;
d->makepeaceful = TRUE;
} else if (!strncmpi(bufp, "hostile ", 8)) {
bufp += 8;
d->makehostile = TRUE;
}
/* decide whether a valid monster was chosen */
if (wizard && (!strcmp(bufp, "*") || !strcmp(bufp, "random"))) {
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 > 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)) {
/* wizard mode can override handling of special monsters */
char buf[BUFSZ];
Sprintf(buf, "Creating %s instead; force %s?",
mons[d->which].mname, mons[firstchoice].mname);
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)
mon_set_minvis(mtmp);
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.
*
@@ -2439,135 +2579,29 @@ 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 */
getlin("Create what kind of monster? [type the name or symbol]", buf);
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 (!strncmpi(bufp, "tame ", 5)) {
bufp += 5;
maketame = TRUE;
} else if (!strncmpi(bufp, "peaceful ", 9)) {
bufp += 9;
makepeaceful = TRUE;
} else if (!strncmpi(bufp, "hostile ", 8)) {
bufp += 8;
makehostile = TRUE;
}
/* decide whether a valid monster was chosen */
if (wizard && (!strcmp(bufp, "*") || !strcmp(bufp, "random"))) {
randmonst = TRUE;
if (create_particular_parse(bufp, &d))
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 */
break;
}
/* no good; try again... */
pline("I've never heard of such monsters.");
} 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 */
Sprintf(buf, "Creating %s instead; force %s?",
mons[which].mname, mons[firstchoice].mname);
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*/