Beispiel #1
0
/*
 * Split obj so that it gets size gets reduced by num. The quantity num is
 * put in the object structure delivered by this call.  The returned object
 * has its wornmask cleared and is positioned just following the original
 * in the nobj chain (and nexthere chain when on the floor).
 */
struct obj *
splitobj(struct obj *obj, long int num)
{
    struct obj *otmp;

    if (obj->cobj || num <= 0L || obj->quan <= num)
        panic("splitobj");	/* can't split containers */
    otmp = newobj(obj->oxlth + obj->onamelth);
    *otmp = *obj;		/* copies whole structure */
    otmp->o_id = flags.ident++;
    if (!otmp->o_id) otmp->o_id = flags.ident++;	/* ident overflowed */
    otmp->timed = 0;	/* not timed, yet */
    otmp->lamplit = 0;	/* ditto */
    otmp->owornmask = 0L;	/* new object isn't worn */
    obj->quan -= num;
    obj->owt = weight(obj);
    otmp->quan = num;
    otmp->owt = weight(otmp);	/* -= obj->owt ? */
    obj->nobj = otmp;
    /* Only set nexthere when on the floor, nexthere is also used */
    /* as a back pointer to the container object when contained. */
    if (obj->where == OBJ_FLOOR)
        obj->nexthere = otmp;
    if (obj->oxlth)
        (void)memcpy((genericptr_t)otmp->oextra, (genericptr_t)obj->oextra,
                     obj->oxlth);
    if (obj->onamelth)
        (void)strncpy(ONAME(otmp), ONAME(obj), (int)obj->onamelth);
    if (obj->unpaid) splitbill(obj,otmp);
    if (obj->timed) obj_split_timers(obj, otmp);
    if (obj_sheds_light(obj)) obj_split_light_source(obj, otmp);
    return otmp;
}
Beispiel #2
0
struct obj *oname(struct obj *obj, const char *name)
{
	int lth;
	char buf[PL_PSIZ];

	lth = *name ? (int)(strlen(name) + 1) : 0;
	if (lth > PL_PSIZ) {
		lth = PL_PSIZ;
		name = strncpy(buf, name, PL_PSIZ - 1);
		buf[PL_PSIZ - 1] = '\0';
	}
	/* If named artifact exists in the game, do not create another.
	 * Also trying to create an artifact shouldn't de-artifact
	 * it (e.g. Excalibur from prayer). In this case the object
	 * will retain its current name. */
	if (obj->oartifact || (lth && exist_artifact(obj->otyp, name)))
		return obj;

	if (lth == obj->onamelth) {
		/* no need to replace entire object */
		if (lth) strcpy(ONAME(obj), name);
	} else {
		obj = realloc_obj(obj, obj->oxlth,
			      obj->oextra, lth, name);
	}
	if (lth) artifact_exists(obj, name, TRUE);
	if (obj->oartifact) {
	    /* can't dual-wield with artifact as secondary weapon */
	    if (obj == uswapwep) untwoweapon();
	    /* activate warning if you've just named your weapon "Sting" */
	    if (obj == uwep) set_artifact_intrinsic(obj, TRUE, W_WEP);
	}
	if (carried(obj)) update_inventory();
	return obj;
}
Beispiel #3
0
/*
 * Attach a monster id to an object, to provide
 * a lasting association between the two.
 */
struct obj *obj_attach_mid(struct obj *obj, unsigned mid)
{
    struct obj *otmp;
     int lth, namelth;

    if (!mid || !obj) return NULL;
    lth = sizeof(mid);
    namelth = obj->onamelth ? strlen(ONAME(obj)) + 1 : 0;
    if (namelth) 
	otmp = realloc_obj(obj, lth, &mid, namelth, ONAME(obj));
    else {
	otmp = obj;
	otmp->oxlth = sizeof(mid);
	memcpy(otmp->oextra, (void *)&mid, sizeof(mid));
    }
    if (otmp && otmp->oxlth) otmp->oattached = OATTACHED_M_ID;	/* mark it */
    return otmp;
}
Beispiel #4
0
static struct obj *save_mtraits(struct obj *obj, struct monst *mtmp)
{
	struct obj *otmp;
	int lth, namelth;

	lth = sizeof(struct monst) + mtmp->mxlth + mtmp->mnamelth;
	namelth = obj->onamelth ? strlen(ONAME(obj)) + 1 : 0;
	otmp = realloc_obj(obj, lth, mtmp, namelth, ONAME(obj));
	if (otmp && otmp->oxlth) {
		struct monst *mtmp2 = (struct monst *)otmp->oextra;
		if (mtmp->data) mtmp2->mnum = monsndx(mtmp->data);
		/* invalidate pointers */
		/* m_id is needed to know if this is a revived quest leader */
		/* but m_id must be cleared when loading bones */
		mtmp2->nmon     = NULL;
		mtmp2->data     = NULL;
		mtmp2->minvent  = NULL;
		otmp->oattached = OATTACHED_MONST;	/* mark it */
	}
	return otmp;
}
Beispiel #5
0
/*
 * Create a dummy duplicate to put on shop bill.  The duplicate exists
 * only in the billobjs chain.  This function is used when a shop object
 * is being altered, and a copy of the original is needed for billing
 * purposes.  For example, when eating, where an interruption will yield
 * an object which is different from what it started out as; the "I x"
 * command needs to display the original object.
 *
 * The caller is responsible for checking otmp->unpaid and
 * costly_spot(u.ux, u.uy).  This function will make otmp no charge.
 *
 * Note that check_unpaid_usage() should be used instead for partial
 * usage of an object.
 */
void bill_dummy_object(struct obj *otmp)
{
	struct obj *dummy;

	if (otmp->unpaid)
	    subfrombill(otmp, shop_keeper(level, *u.ushops));
	dummy = newobj(otmp->oxlth + otmp->onamelth);
	*dummy = *otmp;
	dummy->where = OBJ_FREE;
	dummy->o_id = flags.ident++;
	if (!dummy->o_id) dummy->o_id = flags.ident++;	/* ident overflowed */
	dummy->timed = 0;
	if (otmp->oxlth)
	    memcpy(dummy->oextra,
			otmp->oextra, otmp->oxlth);
	if (otmp->onamelth)
	    strncpy(ONAME(dummy), ONAME(otmp), (int)otmp->onamelth);
	if (Is_candle(dummy)) dummy->lamplit = 0;
	addtobill(dummy, FALSE, TRUE, TRUE);
	otmp->no_charge = 1;
	otmp->unpaid = 0;
	return;
}
Beispiel #6
0
/*ARGSUSED*/
STATIC_OVL void
newmail(struct mail_info *info)
{
    struct monst *md;
    coord start, stop;
    boolean message_seen = FALSE;

    /* Try to find good starting and stopping places. */
    if (!md_start(&start) || !md_stop(&stop,&start)) goto give_up;

    /* Make the daemon.  Have it rush towards the hero. */
    if (!(md = makemon(&mons[PM_MAIL_DAEMON], start.x, start.y, NO_MM_FLAGS)))
        goto give_up;
    if (!md_rush(md, stop.x, stop.y)) goto go_back;

    message_seen = TRUE;
    verbalize("%s, %s!  %s.", Hello(md), plname, info->display_txt);

    if (info->message_typ) {
        struct obj *obj = mksobj(SCR_MAIL, FALSE, FALSE);
        if (info->message_typ == MSG_HINT) obj->spe = MAIL_HINT;
        if (distu(md->mx,md->my) > 2)
            verbalize("Catch!");
        display_nhwindow(WIN_MESSAGE, FALSE);
        if (info->object_nam) {
            obj = oname(obj, info->object_nam);
            if (info->response_cmd) {	/*(hide extension of the obj name)*/
                int namelth = info->response_cmd - info->object_nam - 1;
                if ( namelth <= 0 || namelth >= (int) obj->onamelth )
                    warning("mail delivery screwed up");
                else
                    *(ONAME(obj) + namelth) = '\0';
                /* Note: renaming object will discard the hidden command. */
            }
        }
        obj = hold_another_object(obj, "Oops!",
                                  (const char *)0, (const char *)0);
    }

    /* zip back to starting location */
go_back:
    (void) md_rush(md, start.x, start.y);
    mongone(md);
    /* deliver some classes of messages even if no daemon ever shows up */
give_up:
    if (!message_seen && info->message_typ == MSG_OTHER)
        pline("Hark!  \"%s.\"", info->display_txt);
}
Beispiel #7
0
void save_obj(struct memfile *mf, struct obj *obj)
{
    unsigned int oflags;
    
    oflags = (obj->cursed << 31) | (obj->blessed << 30) | (obj->unpaid << 29) |
	     (obj->no_charge << 28) | (obj->known << 27) | (obj->dknown << 26) |
	     (obj->bknown << 25) | (obj->rknown << 24) | (obj->oeroded << 22) |
	     (obj->oeroded2 << 20) | (obj->oerodeproof << 19) | (obj->olocked << 18) |
	     (obj->obroken << 17) | (obj->otrapped << 16) | (obj->recharged << 13) |
	     (obj->lamplit << 12) | (obj->greased << 11) | (obj->oattached << 9) |
	     (obj->in_use << 8) | (obj->was_thrown << 7) | (obj->bypass << 6);
    
    mfmagic_set(mf, OBJ_MAGIC);
    
    mwrite32(mf, obj->onamelth);    
    mwrite32(mf, obj->o_id);
    mwrite32(mf, obj->owt);
    mwrite32(mf, obj->quan);
    mwrite32(mf, obj->corpsenm);
    mwrite32(mf, obj->oeaten);
    mwrite32(mf, obj->age);
    mwrite32(mf, obj->owornmask);
    mwrite32(mf, oflags);
    
    mwrite16(mf, obj->otyp);
    
    mwrite8(mf, obj->ox);
    mwrite8(mf, obj->oy);
    mwrite8(mf, obj->spe);
    mwrite8(mf, obj->oclass);
    mwrite8(mf, obj->invlet);
    mwrite8(mf, obj->oartifact);
    mwrite8(mf, obj->where);
    mwrite8(mf, obj->timed);
    /* no need to save the value of the cobj pointer, but we will need to know
     * if there is something in here that needs to be restored */
    mwrite8(mf, obj->cobj ? 1 : 0);
    
    if (obj->onamelth)
	mwrite(mf, ONAME(obj), obj->onamelth);
    
    if (obj->oattached == OATTACHED_MONST)
	save_mon(mf, (struct monst*)obj->oextra);
    else if (obj->oattached == OATTACHED_M_ID)
	mwrite32(mf, *(unsigned int*)obj->oextra);
}
Beispiel #8
0
char *xname(struct obj *obj)
{
    static char bufr[BUFSZ];

    /* Leave room for "17 -3 " */
    char *buf = &(bufr[PREFIX]);
    int nn = objects[obj->otyp].oc_name_known;
    char *an = objects[obj->otyp].oc_name;
    char *dn = objects[obj->otyp].oc_descr;
    char *un = objects[obj->otyp].oc_uname;
    int pl = 0;

    if(obj->quan != 0) {
        pl = 1;
    }

    if((obj->dknown == 0) && (Blind == 0)) {
        /* %% Doesn't belong here */
        obj->dknown = 1;
    }

    switch(obj->olet) {
    case AMULET_SYM:
        if((obj->spe < 0) && (obj->known != 0)) {
            strcpy(buf, "cheap plastic imitation of the ");
        }
        else {
            strcpy(buf, "");
        }

        strcat(buf, "Amulet of Yendor");

        break;
    case TOOL_SYM:
        if(nn == 0) {
            strcpy(buf, dn);

            break;
        }

        strcpy(buf, an);

        break;
    case FOOD_SYM:
        if((obj->otyp == CLOVE_OF_GARLIC) && (pl != 0)) {
            pl = 0;
            strcpy(buf, "cloves of garlic");

            break;
        }

        if((obj->otyp == DEAD_HOMUNCULUS) && (pl != 0)) {
            pl = 0;
            strcpy(buf, "dead homunculi");

            break;
        }
        
        /* Fungis ? */
        /* Fall into next case */
    case WEAPON_SYM:
        if((obj->otyp == WORM_TOOTH) && (pl != 0)) {
            pl = 0;
            strcpy(buf, "worm teeth");

            break;
        }

        if((obj->otyp == CRYSKNIFE) && (pl != 0)) {
            pl = 0;
            strcpy(buf, "crysknifes");

            break;
        }

        /* Fall into next case */
    case ARMOR_SYM:
    case CHAIN_SYM:
    case ROCK_SYM:
        strcpy(buf, an);

        break;
    case BALL_SYM:
        if(obj->owt > objects[obj->otyp].oc_weight) {
            sprintf(buf, "%sheavy iron ball", "very ");
        }
        else {
            sprintf(buf, "%sheavy iron ball", "");
        }

        break;
    case POTION_SYM:
        if((nn != 0) || (un != 0) || (obj->dknown == 0)) {
            strcpy(buf, "potion");

            if(pl != 0) {
                pl = 0;
                strcat(buf, "s");
            }

            if(obj->dknown == 0) {
                break;
            }

            if(un != 0) {
                strcat(buf, " called ");
                strcat(buf, un);
            }
            else {
                strcat(buf, " of ");
                strcat(buf, an);
            }
        }
        else {
           strcpy(buf, dn);
           strcat(buf, " potion");
        }

        break;
    case SCROLL_SYM:
        strcpy(buf, "scroll");
        
        if(pl != 0) {
            pl = 0;
            strcat(buf, "s");
        }

        if(obj->dknown == 0) {
            break;
        }

        if(nn != 0) {
            strcat(buf, " of ");
            strcat(buf, an);
        }
        else if(un != 0) {
            strcat(buf, " called ");
            strcat(buf, un);
        }
        else {
            strcat(buf, " labeled ");
            strcat(buf, dn);
        }

        break;
    case WAND_SYM:
        if(obj->dknown == 0) {
            sprintf(buf, "wand");
        }
        else if(nn != 0) {
            sprintf(buf, "wand of %s", an);
        }
        else if(un != 0) {
            sprintf(buf, "wand called %s", un);
        }
        else {
	    sprintf(buf, "%s wand", dn);
        }
        
        break;
    case RING_SYM:
        if(obj->dknown == 0) {
            sprintf(buf, "ring");
        }
        else if(nn != 0) {
            sprintf(buf, "ring of %s", an);
        }
        else if(un != 0) {
            sprintf(buf, "ring called %s", un);
        }
        else {
            sprintf(buf, "%s ring", dn);
        }

        break;
    case GEM_SYM:
        if(obj->dknown == 0) {
            strcpy(buf, "gem");
            
            break;
        }

        if(nn == 0) {
            sprintf(buf, "%s gem", dn);

            break;
        }

        if((pl != 0) && (strncmp("worthless piece", an, 15) == 0)) {
            pl = 0;
            sprintf(buf, "worthless pieces%s", an + 15);

            break;
        }

        strcpy(buf, an);

        if((obj->otyp >= TURQUOISE) && (obj->otyp <= JADE)) {
            strcat(buf, " stone");
        }

        break;
    default:
        sprintf(buf,
                "glorkum %c (0%o) %d %d",
                obj->olet,
                obj->olet,
                obj->otyp,
                obj->spe);
    }

    if(pl != 0) {
        char *p = eos(buf) - 1;

        if((*p == 's')
           || (*p == 'z')
           || (*p == 'x')
           || ((*p == 'h') && p[-1] == 's')) {
            /* Boxes */
            strcat(buf, "es");
        }
        else if((*p == 'y') && (index(vowels, p[-1]) == 0)) {
            /* Rubies, zruties */
            strcpy(p, "ies");
        }
        else {
            strcat(buf, "s");
        }
    }

    if(obj->onamelth) {
        strcat(buf, " named ");
        strcat(buf, ONAME(obj));
    }

    return buf;
}
Beispiel #9
0
/* return TRUE if mon still alive */
bool
hmon(struct monst *mon, struct obj *obj, int thrown)
{
	int tmp;
	bool hittxt = FALSE;

	if (!obj) {
		tmp = rnd(2);	/* attack with bare hands */
		if (mon->data->mlet == 'c' && !uarmg) {
			pline("You hit the cockatrice with your bare hands.");
			pline("You turn to stone ...");
			done_in_by(mon);
		}
	} else if (obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE) {
		if (obj == uwep && (obj->otyp > SPEAR || obj->otyp < BOOMERANG))
			tmp = rnd(2);
		else {
			if (strchr(mlarge, mon->data->mlet)) {
				tmp = rnd(objects[obj->otyp].wldam);
				if (obj->otyp == TWO_HANDED_SWORD)
					tmp += d(2, 6);
				else if (obj->otyp == FLAIL)
					tmp += rnd(4);
			} else
				tmp = rnd(objects[obj->otyp].wsdam);
			tmp += obj->spe;
			if (!thrown && obj == uwep && obj->otyp == BOOMERANG
			    && !rn2(3)) {
				pline("As you hit %s, the boomerang breaks into splinters.",
				    monnam(mon));
				freeinv(obj);
				setworn(NULL, obj->owornmask);
				obfree(obj, NULL);
				tmp++;
			}
		}
		if (mon->data->mlet == 'O' && obj->otyp == TWO_HANDED_SWORD &&
		    !strcmp(ONAME(obj), "Orcrist"))
			tmp += rnd(10);
	} else
		switch (obj->otyp) {
		case HEAVY_IRON_BALL:
			tmp = rnd(25);
			break;
		case EXPENSIVE_CAMERA:
			pline("You succeed in destroying your camera. Congratulations!");
			freeinv(obj);
			if (obj->owornmask)
				setworn(NULL, obj->owornmask);
			obfree(obj, NULL);
			return (TRUE);
		case DEAD_COCKATRICE:
			pline("You hit %s with the cockatrice corpse.",
			      monnam(mon));
			if (mon->data->mlet == 'c') {
				tmp = 1;
				hittxt = TRUE;
				break;
			}
			pline("%s is turned to stone!", Monnam(mon));
			killed(mon);
			return (FALSE);
		case CLOVE_OF_GARLIC:	/* no effect against demons */
			if (strchr(UNDEAD, mon->data->mlet))
				mon->mflee = 1;
			tmp = 1;
			break;
		default:
			/* non-weapons can damage because of their weight */
			/* (but not too much) */
			tmp = obj->owt / 10;
			if (tmp < 1)
				tmp = 1;
			else
				tmp = rnd(tmp);
			if (tmp > 6)
				tmp = 6;
		}

	/****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG) */

	tmp += u.udaminc + dbon();
	if (u.uswallow) {
		if ((tmp -= u.uswldtim) <= 0) {
			pline("Your arms are no longer able to hit.");
			return (TRUE);
		}
	}
	if (tmp < 1)
		tmp = 1;
	mon->mhp -= tmp;
	if (mon->mhp < 1) {
		killed(mon);
		return (FALSE);
	}
	if (mon->mtame && (!mon->mflee || mon->mfleetim)) {
		mon->mflee = 1;		/* Rick Richardson */
		mon->mfleetim += 10 * rnd(tmp);
	}

	if (!hittxt) {
		if (thrown) {
			/* this assumes that we cannot throw plural things */
			hit(xname(obj) /* or: objects[obj->otyp].oc_name */,
			    mon, exclam(tmp));
		} else if (Blind)
			pline("You hit it.");
		else
			pline("You hit %s%s", monnam(mon), exclam(tmp));
	}

	if (u.umconf && !thrown) {
		if (!Blind) {
			pline("Your hands stop glowing blue.");
			if (!mon->mfroz && !mon->msleep)
				pline("%s appears confused.", Monnam(mon));
		}
		mon->mconf = 1;
		u.umconf = 0;
	}
	return (TRUE);		/* mon still alive */
}
Beispiel #10
0
struct obj *restore_obj(struct memfile *mf)
{
    unsigned int oflags;
    char namelen;
    struct obj *otmp;
    
    mfmagic_check(mf, OBJ_MAGIC);
    
    namelen = mread32(mf);
    otmp = newobj(namelen);
    memset(otmp, 0, namelen + sizeof(struct obj));
    
    otmp->o_id = mread32(mf);
    otmp->owt = mread32(mf);
    otmp->quan = mread32(mf);
    otmp->corpsenm = mread32(mf);
    otmp->oeaten = mread32(mf);
    otmp->age = mread32(mf);
    otmp->owornmask = mread32(mf);
    oflags = mread32(mf);
    
    otmp->otyp = mread16(mf);
    
    otmp->ox = mread8(mf);
    otmp->oy = mread8(mf);
    otmp->spe = mread8(mf);
    otmp->oclass = mread8(mf);
    otmp->invlet = mread8(mf);
    otmp->oartifact = mread8(mf);
    otmp->where = mread8(mf);
    otmp->timed = mread8(mf);
    otmp->cobj = mread8(mf) ? (void*)1 : NULL; /* set the pointer to 1 if there will be contents */
    otmp->onamelth = namelen;
    
    otmp->cursed	= (oflags >> 31) & 1;
    otmp->blessed	= (oflags >> 30) & 1;
    otmp->unpaid	= (oflags >> 29) & 1;
    otmp->no_charge	= (oflags >> 28) & 1;
    otmp->known 	= (oflags >> 27) & 1;
    otmp->dknown	= (oflags >> 26) & 1;
    otmp->bknown	= (oflags >> 25) & 1;
    otmp->rknown	= (oflags >> 24) & 1;
    otmp->oeroded	= (oflags >> 22) & 3;
    otmp->oeroded2	= (oflags >> 20) & 3;
    otmp->oerodeproof	= (oflags >> 19) & 1;
    otmp->olocked	= (oflags >> 18) & 1;
    otmp->obroken	= (oflags >> 17) & 1;
    otmp->otrapped	= (oflags >> 16) & 1;
    otmp->recharged	= (oflags >> 13) & 7;
    otmp->lamplit	= (oflags >> 12) & 1;
    otmp->greased	= (oflags >> 11) & 1;
    otmp->oattached	= (oflags >>  9) & 3;
    otmp->in_use	= (oflags >>  8) & 1;
    otmp->was_thrown	= (oflags >>  7) & 1;
    otmp->bypass	= (oflags >>  6) & 1;
    
    if (otmp->onamelth)
	mread(mf, ONAME(otmp), otmp->onamelth);
    
    if (otmp->oattached == OATTACHED_MONST) {
	struct monst *mtmp = restore_mon(mf);
	int monlen = sizeof(struct monst) + mtmp->mnamelth + mtmp->mxlth;
	otmp = realloc_obj(otmp, monlen, mtmp, otmp->onamelth, ONAME(otmp));
	dealloc_monst(mtmp);
    } else if (otmp->oattached == OATTACHED_M_ID) {
	unsigned int mid = mread32(mf);
	otmp = obj_attach_mid(otmp, mid);
    }
    
    return otmp;
}
Beispiel #11
0
int chwepon(struct obj *otmp, int amount)
{
	const char *color = hcolor((amount < 0) ? "black" : "blue");
	const char *xtime;
	int otyp = STRANGE_OBJECT;

	if (!uwep || (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep))) {
		char buf[BUFSZ];

		sprintf(buf, "Your %s %s.", makeplural(body_part(HAND)),
			(amount >= 0) ? "twitch" : "itch");
		strange_feeling(otmp, buf);
		exercise(A_DEX, (boolean) (amount >= 0));
		return 0;
	}

	if (otmp && otmp->oclass == SCROLL_CLASS) otyp = otmp->otyp;

	if (uwep->otyp == WORM_TOOTH && amount >= 0) {
		uwep->otyp = CRYSKNIFE;
		uwep->oerodeproof = 0;
		pline("Your weapon seems sharper now.");
		uwep->cursed = 0;
		if (otyp != STRANGE_OBJECT) makeknown(otyp);
		return 1;
	}

	if (uwep->otyp == CRYSKNIFE && amount < 0) {
		uwep->otyp = WORM_TOOTH;
		uwep->oerodeproof = 0;
		pline("Your weapon seems duller now.");
		if (otyp != STRANGE_OBJECT && otmp->bknown) makeknown(otyp);
		return 1;
	}

	if (amount < 0 && uwep->oartifact && restrict_name(uwep, ONAME(uwep))) {
	    if (!Blind)
		pline("Your %s %s.", aobjnam(uwep, "faintly glow"), color);
	    return 1;
	}
	/* there is a (soft) upper and lower limit to uwep->spe */
	if (((uwep->spe > 5 && amount >= 0) || (uwep->spe < -5 && amount < 0))
								&& rn2(3)) {
	    if (!Blind)
	    pline("Your %s %s for a while and then %s.",
		 aobjnam(uwep, "violently glow"), color,
		 otense(uwep, "evaporate"));
	    else
		pline("Your %s.", aobjnam(uwep, "evaporate"));

	    useupall(uwep);	/* let all of them disappear */
	    return 1;
	}
	if (!Blind) {
	    xtime = (amount*amount == 1) ? "moment" : "while";
	    pline("Your %s %s for a %s.",
		 aobjnam(uwep, amount == 0 ? "violently glow" : "glow"),
		 color, xtime);
	    if (otyp != STRANGE_OBJECT && uwep->known &&
		    (amount > 0 || (amount < 0 && otmp->bknown)))
		makeknown(otyp);
	}
	uwep->spe += amount;
	if (amount > 0) uwep->cursed = 0;

	/*
	 * Enchantment, which normally improves a weapon, has an
	 * addition adverse reaction on Magicbane whose effects are
	 * spe dependent.  Give an obscure clue here.
	 */
	if (uwep->oartifact == ART_MAGICBANE && uwep->spe >= 0) {
		pline("Your right %s %sches!",
			body_part(HAND),
			(((amount > 1) && (uwep->spe > 1)) ? "flin" : "it"));
	}

	/* an elven magic clue, cookie@keebler */
	/* elven weapons vibrate warningly when enchanted beyond a limit */
	if ((uwep->spe > 5)
		&& (is_elven_weapon(uwep) || uwep->oartifact || !rn2(7)))
	    pline("Your %s unexpectedly.",
		aobjnam(uwep, "suddenly vibrate"));

	return 1;
}
Beispiel #12
0
struct monst *
make_familiar(struct obj *otmp, xchar x, xchar y, boolean quietly)
{
    const struct permonst *pm;
    struct monst *mtmp = 0;
    int chance, trycnt = 100;

    do {
        if (otmp) {     /* figurine; otherwise spell */
            int mndx = otmp->corpsenm;

            pm = &mons[mndx];
            /* activating a figurine provides one way to exceed the maximum
               number of the target critter created--unless it has a special
               limit (erinys, Nazgul) */
            if ((mvitals[mndx].mvflags & G_EXTINCT) &&
                mbirth_limit(mndx) != MAXMONNO) {
                if (!quietly)
                    /* have just been given "You <do something with> the
                       figurine and it transforms." message */
                    pline("... into a pile of dust.");
                break;  /* mtmp is null */
            }
        } else if (!rn2(3)) {
            pm = &mons[pet_type(NULL)];
        } else {
            pm = rndmonst(&u.uz, rng_t_create_monster);
            if (!pm) {
                if (!quietly)
                    pline
                        ("There seems to be nothing available for a familiar.");
                break;
            }
        }

        mtmp = makemon(pm, level, x, y, MM_EDOG | MM_IGNOREWATER |
                       (otmp ? 0 : (MM_CREATEMONSTER | MM_CMONSTER_T)));
        if (otmp && !mtmp) {    /* monster was genocided or square occupied */
            if (!quietly)
                pline("The figurine writhes and then shatters into pieces!");
            break;
        }
    } while (!mtmp && --trycnt > 0);

    if (!mtmp)
        return NULL;

    if (is_pool(level, mtmp->mx, mtmp->my) && minliquid(mtmp))
        return NULL;

    initedog(mtmp);
    mtmp->msleeping = 0;
    if (otmp) { /* figurine; resulting monster might not become a pet */
        chance = rn2_on_rng(10, rng_figurine_effect);
        /* 0: tame, 1: peaceful, 2: hostile, 3+: matching BCU; this gives
           an 80% chance of the desired effect, 10% of each other effect */
        if (chance > 2)
            chance = otmp->blessed ? 0 : !otmp->cursed ? 1 : 2;
        if (chance > 0) {
            mtmp->mtame = 0;    /* not tame after all */
            if (chance == 2) {  /* hostile (cursed figurine) */
                if (!quietly)
                    pline("You get a bad feeling about this.");
                msethostility(mtmp, TRUE, TRUE);
            }
        }
        /* if figurine has been named, give same name to the monster */
        if (otmp->onamelth)
            mtmp = christen_monst(mtmp, ONAME(otmp));
    }
    set_malign(mtmp);   /* more alignment changes */
    newsym(mtmp->mx, mtmp->my);

    /* must wield weapon immediately since pets will otherwise drop it */
    if (mtmp->mtame && attacktype(mtmp->data, AT_WEAP)) {
        mtmp->weapon_check = NEED_HTH_WEAPON;
        mon_wield_item(mtmp);
    }
    return mtmp;
}
Beispiel #13
0
/*
 * Allocate a new and possibly larger storage space for an obj.
 */
struct obj *realloc_obj(struct obj *obj, int oextra_size, void *oextra_src,
			int oname_size, const char *name)
{
	struct obj *otmp;

	otmp = newobj(oextra_size + oname_size);
	*otmp = *obj;	/* the cobj pointer is copied to otmp */
	if (oextra_size) {
	    if (oextra_src)
		memcpy(otmp->oextra, oextra_src, oextra_size);
	} else {
	    otmp->oattached = OATTACHED_NOTHING;
	}
	otmp->oxlth = oextra_size;
	otmp->onamelth = oname_size;
	
	if (oname_size) {
	    if (name)
		strcpy(ONAME(otmp), name);
	}

	/* !obj->olev means the obj is currently being restored and no pointer
	 * from or to it is valid. Re-equipping, timer linking, etc. will happen
	 * elsewhere in that case. */
	if (obj->olev) { 
	    if (obj->owornmask) {
		    boolean save_twoweap = u.twoweap;
		    /* unwearing the old instance will clear dual-wield mode
		    if this object is either of the two weapons */
		    setworn(NULL, obj->owornmask);
		    setworn(otmp, otmp->owornmask);
		    u.twoweap = save_twoweap;
	    }

	    /* replace obj with otmp */
	    replace_object(obj, otmp);

	    /* fix ocontainer pointers */
	    if (Has_contents(obj)) {
		    struct obj *inside;

		    for (inside = obj->cobj; inside; inside = inside->nobj)
			    inside->ocontainer = otmp;
	    }

	    /* move timers and light sources from obj to otmp */
	    otmp->timed = 0;	/* not timed, yet */
	    if (obj->timed) obj_move_timers(obj, otmp);
	    otmp->lamplit = 0;	/* ditto */
	    if (obj->lamplit) obj_move_light_source(obj, otmp);

	    /* objects possibly being manipulated by multi-turn occupations
	    which have been interrupted but might be subsequently resumed */
	    if (obj->oclass == FOOD_CLASS)
		food_substitution(obj, otmp);	/* eat food or open tin */
	    else if (obj->oclass == SPBOOK_CLASS)
		book_substitution(obj, otmp);	/* read spellbook */
	} else {
	    /* make sure dealloc_obj doesn't explode */
	    obj->where = OBJ_FREE;
	    obj->timed = FALSE;
	    obj->lamplit = FALSE;
	}
	/* obfree(obj, otmp);	now unnecessary: no pointers on bill */
	dealloc_obj(obj);	/* let us hope nobody else saved a pointer */
	return otmp;
}