From 987516cedb552b2b0c119dba77eb0a0aca0bc5c0 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Tue, 28 Aug 2018 19:52:15 +0300 Subject: [PATCH] Split string parsing and monster creation out of create_particular --- src/read.c | 266 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 150 insertions(+), 116 deletions(-) diff --git a/src/read.c b/src/read.c index f86afe04a..bedf5172a 100644 --- a/src/read.c +++ b/src/read.c @@ -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*/