Ejemplo n.º 1
0
void docall(struct obj *obj)
{
	char buf[BUFSZ], qbuf[QBUFSZ];
	struct obj otemp;
	char **str1;

	if (!obj->dknown) return; /* probably blind */
	otemp = *obj;
	otemp.quan = 1L;
	otemp.onamelth = 0;
	otemp.oxlth = 0;
	if (objects[otemp.otyp].oc_class == POTION_CLASS && otemp.fromsink)
	    /* kludge, meaning it's sink water */
	    sprintf(qbuf,"Call a stream of %s fluid:",
		    OBJ_DESCR(objects[otemp.otyp]));
	else
	    sprintf(qbuf, "Call %s:", an(xname(&otemp)));
	getlin(qbuf, buf);
	if (!*buf || *buf == '\033')
		return;

	/* clear old name */
	str1 = &(objects[obj->otyp].oc_uname);
	if (*str1) free(*str1);

	/* strip leading and trailing spaces; uncalls item if all spaces */
	mungspaces(buf);
	if (!*buf) {
	    if (*str1) {	/* had name, so possibly remove from disco[] */
		/* strip name first, for the update_inventory() call
		   from undiscover_object() */
		*str1 = NULL;
		undiscover_object(obj->otyp);
	    }
	} else {
	    *str1 = strcpy(malloc((unsigned)strlen(buf)+1), buf);
	    discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */
	}
}
Ejemplo n.º 2
0
/* Note: may return TRUE when mdef is blind (e.g. new cream-pie attack) */
boolean
can_blnd(struct monst * magr,   /* NULL == no specific aggressor */
         struct monst * mdef, uchar aatyp, struct obj * obj)
{       /* aatyp == AT_WEAP, AT_SPIT */
    boolean is_you = (mdef == &youmonst);
    boolean check_visor = FALSE;
    struct obj *o;
    const char *s;

    /* no eyes protect against all attacks for now */
    if (!haseyes(mdef->data))
        return FALSE;

    switch (aatyp) {
    case AT_EXPL:
    case AT_BOOM:
    case AT_GAZE:
    case AT_MAGC:
    case AT_BREA:      /* assumed to be lightning */
        /* light-based attacks may be cancelled or resisted */
        if (magr && magr->mcan)
            return FALSE;
        return !resists_blnd(mdef);

    case AT_WEAP:
    case AT_SPIT:
    case AT_NONE:
        /* an object is used (thrown/spit/other) */
        if (obj && (obj->otyp == CREAM_PIE)) {
            if (is_you && Blindfolded)
                return FALSE;
        } else if (obj && (obj->otyp == BLINDING_VENOM)) {
            /* all ublindf, including LENSES, protect, cream-pies too */
            if (is_you && (ublindf || u.ucreamed))
                return FALSE;
            check_visor = TRUE;
        } else if (obj && (obj->otyp == POT_BLINDNESS)) {
            return TRUE;        /* no defense */
        } else
            return FALSE;       /* other objects cannot cause blindness yet */
        if ((magr == &youmonst) && Engulfed)
            return FALSE;       /* can't affect eyes while inside monster */
        break;

    case AT_ENGL:
        if (is_you && (Blindfolded || u_helpless(hm_asleep) || u.ucreamed))
            return FALSE;
        if (!is_you && mdef->msleeping)
            return FALSE;
        break;

    case AT_CLAW:
        /* e.g. raven: all ublindf, including LENSES, protect */
        if (is_you && ublindf)
            return FALSE;
        if ((magr == &youmonst) && Engulfed)
            return FALSE;       /* can't affect eyes while inside monster */
        check_visor = TRUE;
        break;

    case AT_TUCH:
    case AT_STNG:
        /* some physical, blind-inducing attacks can be cancelled */
        if (magr && magr->mcan)
            return FALSE;
        break;

    default:
        break;
    }

    /* check if wearing a visor (only checked if visor might help) */
    if (check_visor) {
        o = (mdef == &youmonst) ? invent : mdef->minvent;
        for (; o; o = o->nobj)
            if ((o->owornmask & W_MASK(os_armh)) &&
                (s = OBJ_DESCR(objects[o->otyp])) != NULL &&
                !strcmp(s, "visored helmet"))
                return FALSE;
    }

    return TRUE;
}
Ejemplo n.º 3
0
int
dowrite(struct obj *pen, const struct nh_cmd_arg *arg)
{
    struct obj *paper;
    const char *namebuf, *nm, *bp;
    struct obj *new_obj;
    int basecost, actualcost;
    int curseval;
    const char *qbuf;
    int first, last, i;
    boolean by_descr = FALSE, by_name = FALSE;
    const char *typeword;

    if (nohands(youmonst.data)) {
        pline(msgc_cancelled, "You need hands to be able to write!");
        return 0;
    } else if (slippery_fingers(&youmonst)) {
        pline(msgc_cancelled1, "%s from your %s.", Tobjnam(pen, "slip"),
              makeplural(body_part(FINGER)));
        unwield_silently(pen);
        dropx(pen);
        return 1;
    }

    /* get paper to write on */
    paper = getargobj(arg, write_on, "write on");
    if (!paper)
        return 0;

    typeword = (paper->oclass == SPBOOK_CLASS) ? "spellbook" : "scroll";
    if (Blind && !paper->dknown) {
        pline(msgc_cancelled1,
              "You don't know if that %s is blank or not!", typeword);
        return 1;
    }
    paper->dknown = 1;
    if (paper->otyp != SCR_BLANK_PAPER && paper->otyp != SPE_BLANK_PAPER) {
        pline(msgc_cancelled1, "That %s is not blank!", typeword);
        exercise(A_WIS, FALSE);
        return 1;
    }

    /* what to write */
    qbuf = msgprintf("What type of %s do you want to write?", typeword);
    namebuf = getarglin(arg, qbuf);
    namebuf = msgmungspaces(namebuf);   /* remove any excess whitespace */
    if (namebuf[0] == '\033' || !namebuf[0])
        return 1;
    nm = namebuf;
    if (!strncmpi(nm, "scroll ", 7))
        nm += 7;
    else if (!strncmpi(nm, "spellbook ", 10))
        nm += 10;
    if (!strncmpi(nm, "of ", 3))
        nm += 3;

    if ((bp = strstri(nm, " armour")) != 0)
        nm = msgcat_many(msgchop(nm, bp-nm), " armor", bp+7, NULL);

    first = bases[(int)paper->oclass];
    last = bases[(int)paper->oclass + 1] - 1;
    for (i = first; i <= last; i++) {
        /* extra shufflable descr not representing a real object */
        if (!OBJ_NAME(objects[i]))
            continue;

        if (!strcmpi(OBJ_NAME(objects[i]), nm))
            goto found;
        if (!strcmpi(OBJ_DESCR(objects[i]), nm)) {
            by_descr = TRUE;
            goto found;
        }
        if (objects[i].oc_uname &&
            !strcmpi(objects[i].oc_uname, nm)) {
            by_name = TRUE;
            goto found;
        }
    }

    pline(msgc_cancelled1, "There is no such %s!", typeword);
    return 1;
found:

    if (i == SCR_BLANK_PAPER || i == SPE_BLANK_PAPER) {
        pline(msgc_cancelled1, "You can't write that!");
        pline(msgc_cancelled1, "It's obscene!");
        return 1;
    } else if (i == SPE_BOOK_OF_THE_DEAD) {
        pline(msgc_cancelled1, "No mere dungeon adventurer could write that.");
        return 1;
    } else if ((by_descr || by_name) && paper->oclass == SPBOOK_CLASS &&
               !objects[i].oc_name_known) {
        /* can't write unknown spellbooks by description */
        pline(msgc_cancelled1,
              "Unfortunately you don't have enough information to go on.");
        return 1;
    }

    /* KMH, conduct */
    break_conduct(conduct_illiterate);

    new_obj = mksobj(level, i, FALSE, FALSE, rng_main);
    new_obj->bknown = (paper->bknown && pen->bknown);

    /* shk imposes a flat rate per use, not based on actual charges used */
    check_unpaid(pen);

    /* see if there's enough ink */
    basecost = cost(new_obj);
    if (pen->spe < basecost / 2) {
        pline(msgc_failcurse, "Your marker is too dry to write that!");
        obfree(new_obj, NULL);
        return 1;
    }

    /* we're really going to write now, so calculate cost

       no custom RNG used: too much influence from player actions */
    actualcost = rn1(basecost / 2, basecost / 2);
    curseval = bcsign(pen) + bcsign(paper);
    exercise(A_WIS, TRUE);
    /* dry out marker */
    if (pen->spe < actualcost) {
        pen->spe = 0;
        pline(msgc_itemloss, "Your marker dries out!");
        /* scrolls disappear, spellbooks don't */
        if (paper->oclass == SPBOOK_CLASS) {
            pline(msgc_failcurse,
                  "The spellbook is left unfinished and your writing fades.");
            update_inventory(); /* pen charges */
        } else {
            pline(msgc_failcurse, "The scroll is now useless and disappears!");
            useup(paper);
        }
        obfree(new_obj, NULL);
        return 1;
    }
    pen->spe -= actualcost;

    /* can't write if we don't know it - unless we're lucky */
    if (!(objects[new_obj->otyp].oc_name_known) &&
        (rnl(Role_if(PM_WIZARD) ? 3 : 15))) {
        pline(msgc_failrandom, "You %s to write that!",
              by_descr ? "fail" : "don't know how");
        /* scrolls disappear, spellbooks don't */
        if (paper->oclass == SPBOOK_CLASS) {
            pline_implied(msgc_failrandom,
                          "You write in your best handwriting:  "
                          "\"My Diary\", but it quickly fades.");
            update_inventory(); /* pen charges */
        } else {
            const char *written;
            if (by_descr) {
                written = OBJ_DESCR(objects[new_obj->otyp]);
                written = eroded_text(written,
                                      (6 + MAXULEV - youmonst.m_lev) / 6, 0);
            } else
                written = msgprintf("%s was here!", u.uplname);
            pline_implied(msgc_failrandom,
                          "You write \"%s\" and the scroll disappears.",
                          written);
            useup(paper);
        }
        obfree(new_obj, NULL);
        return 1;
    }

    /* useup old scroll / spellbook */
    useup(paper);

    /* success */
    if (new_obj->oclass == SPBOOK_CLASS) {
        /* acknowledge the change in the object's description... */
        pline(msgc_actionok, "The spellbook warps strangely, then turns %s.",
              OBJ_DESCR(objects[new_obj->otyp]));
    }
    new_obj->blessed = (curseval > 0);
    new_obj->cursed = (curseval < 0);
    hold_another_object(new_obj, "Oops!  %s out of your grasp!",
                        The(aobjnam(new_obj, "slip")), NULL);
    return 1;
}
Ejemplo n.º 4
0
int
use_saddle(struct obj *otmp, const struct nh_cmd_arg *arg)
{
    struct monst *mtmp;
    const struct permonst *ptr;
    int chance;
    const char *s;
    schar dx, dy, dz;

    /* Can you use it? */
    if (nohands(youmonst.data)) {
        pline("You have no hands!");    /* not `body_part(HAND)' */
        return 0;
    } else if (!freehand()) {
        pline("You have no free %s.", body_part(HAND));
        return 0;
    }

    /* Select an animal */
    if (Engulfed || Underwater || !getargdir(arg, NULL, &dx, &dy, &dz)) {
        pline("Never mind.");
        return 0;
    }
    if (!dx && !dy) {
        pline("Saddle yourself?  Very funny...");
        return 0;
    }
    if (!isok(u.ux + dx, u.uy + dy) ||
            !((mtmp = m_at(level, u.ux + dx, u.uy + dy))) || !canspotmon(mtmp)) {
        if (knownwormtail(u.ux + dx, u.uy + dy))
            pline("It's hard to strap a saddle to a tail.");
        else
            pline("I see nobody there.");
        return 0;
    }

    /* Is this a valid monster? */
    if (mtmp->misc_worn_check & W_MASK(os_saddle) ||
            which_armor(mtmp, os_saddle)) {
        pline("%s doesn't need another one.", Monnam(mtmp));
        return 0;
    }
    ptr = mtmp->data;
    if (!uarmg && touched_monster(ptr - mons)) {
        pline("You touch %s.", mon_nam(mtmp));
        instapetrify(killer_msg(STONING, msgcat("attempting to saddle ",
                                                an(mtmp->data->mname))));
    }
    if (ptr == &mons[PM_INCUBUS] || ptr == &mons[PM_SUCCUBUS]) {
        pline("Shame on you!");
        exercise(A_WIS, FALSE);
        return 1;
    }
    if (mtmp->isminion || mtmp->isshk || mtmp->ispriest || mtmp->isgd ||
            mtmp->iswiz) {
        pline("I think %s would mind.", mon_nam(mtmp));
        return 0;
    }
    if (!can_saddle(mtmp)) {
        pline("You can't saddle such a creature.");
        return 0;
    }

    /* Calculate your chance */
    chance = ACURR(A_DEX) + ACURR(A_CHA) / 2 + 2 * mtmp->mtame;
    chance += u.ulevel * (mtmp->mtame ? 20 : 5);
    if (!mtmp->mtame)
        chance -= 10 * mtmp->m_lev;
    if (Role_if(PM_KNIGHT))
        chance += 20;
    switch (P_SKILL(P_RIDING)) {
    case P_ISRESTRICTED:
    case P_UNSKILLED:
    default:
        chance -= 20;
        break;
    case P_BASIC:
        break;
    case P_SKILLED:
        chance += 15;
        break;
    case P_EXPERT:
        chance += 30;
        break;
    }
    if (Confusion || Fumbling || Glib)
        chance -= 20;
    else if (uarmg && (s = OBJ_DESCR(objects[uarmg->otyp])) != NULL &&
             !strncmp(s, "riding ", 7))
        /* Bonus for wearing "riding" (but not fumbling) gloves */
        chance += 10;
    else if (uarmf && (s = OBJ_DESCR(objects[uarmf->otyp])) != NULL &&
             !strncmp(s, "riding ", 7))
        /* ... or for "riding boots" */
        chance += 10;
    if (otmp->cursed)
        chance -= 50;

    /* steed becomes alert if possible */
    maybewakesteed(mtmp);

    /* Make the attempt */
    if (rn2(100) < chance) {
        pline("You put the saddle on %s.", mon_nam(mtmp));
        if (otmp->owornmask)
            remove_worn_item(otmp, FALSE);
        freeinv(otmp);
        /* mpickobj may free otmp it if merges, but we have already checked for
           a saddle above, so no merger should happen */
        mpickobj(mtmp, otmp);
        mtmp->misc_worn_check |= W_MASK(os_saddle);
        otmp->owornmask = W_MASK(os_saddle);
        otmp->leashmon = mtmp->m_id;
        update_mon_intrinsics(mtmp, otmp, TRUE, FALSE);
    } else
        pline("%s resists!", Monnam(mtmp));
    return 1;
}