Exemple #1
0
/* 
 * Steal gold coins only.  Leprechauns don't care for lesser coins.
 */
void stealgold(struct monst *mtmp)
{
	struct obj *fgold = gold_at(level, u.ux, u.uy);
	struct obj *ygold;
	long tmp;

        /* skip lesser coins on the floor */        
        while (fgold && fgold->otyp != GOLD_PIECE) fgold = fgold->nexthere; 

        /* Do you have real gold? */
        ygold = findgold(invent);

	if (fgold && ( !ygold || fgold->quan > ygold->quan || !rn2(5))) {
            obj_extract_self(fgold);
	    add_to_minv(mtmp, fgold);
	    newsym(u.ux, u.uy);
	    pline("%s quickly snatches some gold from between your %s!",
		    Monnam(mtmp), makeplural(body_part(FOOT)));
	    if (!ygold || !rn2(5)) {
		if (!tele_restrict(mtmp)) rloc(level, mtmp, FALSE);
		monflee(mtmp, 0, FALSE, FALSE);
	    }
	} else if (ygold) {
            const int gold_price = objects[GOLD_PIECE].oc_cost;
	    tmp = (somegold(money_cnt(invent)) + gold_price - 1) / gold_price;
	    tmp = min(tmp, ygold->quan);
            if (tmp < ygold->quan) ygold = splitobj(ygold, tmp);
            freeinv(ygold);
            add_to_minv(mtmp, ygold);
	    pline("Your purse feels lighter.");
	    if (!tele_restrict(mtmp)) rloc(level, mtmp, FALSE);
	    monflee(mtmp, 0, FALSE, FALSE);
	    iflags.botl = 1;
	}
}
Exemple #2
0
/* Returns 1 if otmp is free'd, 0 otherwise. */
int mpickobj(struct monst *mtmp, struct obj *otmp)
{
    int freed_otmp;

    boolean snuff_otmp = FALSE;
    /* don't want hidden light source inside the monster; assumes that
       engulfers won't have external inventories; whirly monsters cause
       the light to be extinguished rather than letting it shine thru */
    if (otmp->lamplit &&  /* hack to avoid function calls for most objs */
      	obj_sheds_light(otmp) &&
	attacktype(mtmp->data, AT_ENGL)) {
	/* this is probably a burning object that you dropped or threw */
	if (u.uswallow && mtmp == u.ustuck && !Blind)
	    pline("%s out.", Tobjnam(otmp, "go"));
	snuff_otmp = TRUE;
    }
    /* Must do carrying effects on object prior to add_to_minv() */
    carry_obj_effects(otmp);
    /* add_to_minv() might free otmp [if merged with something else],
       so we have to call it after doing the object checks */
    freed_otmp = add_to_minv(mtmp, otmp);
    /* and we had to defer this until object is in mtmp's inventory */
    if (snuff_otmp) snuff_light_source(mtmp->mx, mtmp->my);

    return freed_otmp;
}
Exemple #3
0
/* Returns 1 if otmp is free'd, 0 otherwise. */
int mpickobj (struct monst *mtmp, struct obj *otmp) {
    int freed_otmp;

    if (otmp->oclass == COIN_CLASS) {
        mtmp->mgold += otmp->quan;
        obfree(otmp, (struct obj *)0);
        freed_otmp = 1;
    } else {
        bool snuff_otmp = false;
        /* don't want hidden light source inside the monster; assumes that
           engulfers won't have external inventories; whirly monsters cause
           the light to be extinguished rather than letting it shine thru */
        if (otmp->lamplit &&  /* hack to avoid function calls for most objs */
                obj_sheds_light(otmp) &&
                attacktype(mtmp->data, AT_ENGL)) {
            /* this is probably a burning object that you dropped or threw */
            if (u.uswallow && mtmp == u.ustuck && !Blind()) {
                message_object(MSG_O_GO_OUT, otmp);
            }
            snuff_otmp = true;
        }
        /* Must do carrying effects on object prior to add_to_minv() */
        carry_obj_effects(otmp);
        /* add_to_minv() might free otmp [if merged with something else],
           so we have to call it after doing the object checks */
        freed_otmp = add_to_minv(mtmp, otmp);
        /* and we had to defer this until object is in mtmp's inventory */
        if (snuff_otmp) snuff_light_source(mtmp->mx, mtmp->my);
    }
    return freed_otmp;
}
Exemple #4
0
/* release the objects the creature is carrying */
void
relobj(struct monst *mtmp, int show, boolean is_pet)
{       /* If true, pet should keep wielded/worn items */
    struct obj *otmp;
    int omx = mtmp->mx, omy = mtmp->my;
    struct obj *keepobj = 0;
    struct pet_weapons p;
    initialize_pet_weapons(mtmp, &p);

    while ((otmp = mtmp->minvent) != 0) {
        obj_extract_self(otmp);

        if (is_pet && pet_wants_object(&p, otmp)) {
            otmp->nobj = keepobj;
            keepobj = otmp;
            continue;
        }

        if (otmp->owornmask & W_MASK(os_wep))
            setmnotwielded(mtmp, otmp);
        mdrop_obj(mtmp, otmp, is_pet && flags.verbose);
    }

    /* put kept objects back */
    while ((otmp = keepobj) != NULL) {
        keepobj = otmp->nobj;
        add_to_minv(mtmp, otmp);
    }

    if (show & cansee(omx, omy) && mtmp->dlevel == level)
        newsym(omx, omy);
}
Exemple #5
0
/* release the objects the creature is carrying */
void
relobj(struct monst *mtmp, int show, boolean is_pet)
{       /* If true, pet should keep wielded/worn items */
    struct obj *otmp;
    int omx = mtmp->mx, omy = mtmp->my;
    struct obj *keepobj = 0;
    struct obj *wep = MON_WEP(mtmp), *hwep = attacktype(mtmp->data, AT_WEAP)
        ? select_hwep(mtmp) : (struct obj *)0, *proj =
        attacktype(mtmp->data, AT_WEAP)
        ? select_rwep(mtmp) : (struct obj *)0, *rwep;
    boolean item1 = FALSE, item2 = FALSE;

    rwep = attacktype(mtmp->data, AT_WEAP) ? propellor : &zeroobj;


    if (!is_pet || mindless(mtmp->data) || is_animal(mtmp->data))
        item1 = item2 = TRUE;
    if (!tunnels(mtmp->data) || !needspick(mtmp->data))
        item1 = TRUE;

    while ((otmp = mtmp->minvent) != 0) {
        obj_extract_self(otmp);
        /* special case: pick-axe and unicorn horn are non-worn */
        /* items that we also want pets to keep 1 of */
        /* (It is a coincidence that these can also be wielded.) */
        if (otmp->owornmask || otmp == wep || otmp == hwep || otmp == rwep ||
            otmp == proj ||
            would_prefer_hwep(mtmp, otmp) ||  /* cursed item in hand? */
            would_prefer_rwep(mtmp, otmp) || could_use_item(mtmp, otmp) ||
            ((!rwep || rwep == &zeroobj) &&
             (is_ammo(otmp) || is_launcher(otmp))) ||
            (rwep && rwep != &zeroobj && ammo_and_launcher(otmp, rwep)) ||
            ((!item1 && otmp->otyp == PICK_AXE) ||
             (!item2 && otmp->otyp == UNICORN_HORN && !otmp->cursed))) {
            if (is_pet) {       /* dont drop worn/wielded item */
                if (otmp->otyp == PICK_AXE)
                    item1 = TRUE;
                if (otmp->otyp == UNICORN_HORN && !otmp->cursed)
                    item2 = TRUE;
                otmp->nobj = keepobj;
                keepobj = otmp;
                continue;
            }
        }
        if (otmp == wep)
            setmnotwielded(mtmp, otmp);
        mdrop_obj(mtmp, otmp, is_pet && flags.verbose);
    }

    /* put kept objects back */
    while ((otmp = keepobj) != NULL) {
        keepobj = otmp->nobj;
        add_to_minv(mtmp, otmp);
    }

    if (show & cansee(omx, omy))
        newsym(omx, omy);
}
Exemple #6
0
/* release the objects the creature is carrying */
// bool is_pet         /* If true, pet should keep wielded/worn items */
void relobj ( struct monst *mtmp, int show, bool is_pet) {
    struct obj *otmp;
    int omx = mtmp->mx, omy = mtmp->my;
    struct obj *keepobj = 0;
    struct obj *wep = MON_WEP(mtmp);
    bool item1 = false, item2 = false;

    if (!is_pet || mindless(mtmp->data) || is_animal(mtmp->data))
        item1 = item2 = true;
    if (!tunnels(mtmp->data) || !needspick(mtmp->data))
        item1 = true;

    while ((otmp = mtmp->minvent) != 0) {
        obj_extract_self(otmp);
        /* special case: pick-axe and unicorn horn are non-worn */
        /* items that we also want pets to keep 1 of */
        /* (It is a coincidence that these can also be wielded.) */
        if (otmp->owornmask || otmp == wep ||
                ((!item1 && otmp->otyp == PICK_AXE) ||
                 (!item2 && otmp->otyp == UNICORN_HORN && !otmp->cursed))) {
            if (is_pet) { /* dont drop worn/wielded item */
                if (otmp->otyp == PICK_AXE)
                    item1 = true;
                if (otmp->otyp == UNICORN_HORN && !otmp->cursed)
                    item2 = true;
                otmp->nobj = keepobj;
                keepobj = otmp;
                continue;
            }
        }
        mdrop_obj(mtmp, otmp, is_pet && flags.verbose);
    }

    /* put kept objects back */
    while ((otmp = keepobj) != (struct obj *)0) {
        keepobj = otmp->nobj;
        (void) add_to_minv(mtmp, otmp);
    }
    if (mtmp->mgold) {
        long g = mtmp->mgold;
        (void) mkgold(g, omx, omy);
        if (is_pet && cansee(omx, omy) && flags.verbose) {
            message_monster_int(MSG_M_DROPS_X_GOLD_PIECES, mtmp, g);
        }
        mtmp->mgold = 0L;
    }

    if (show & cansee(omx, omy))
        newsym(omx, omy);
}
Exemple #7
0
/* release the objects the creature is carrying */
void relobj(struct monst *mtmp, int show, 
	    boolean is_pet) /* If true, pet should keep wielded/worn items */
{
	struct obj *otmp;
	int omx = mtmp->mx, omy = mtmp->my;
	struct obj *keepobj = 0;
	struct obj *wep = MON_WEP(mtmp);
	boolean item1 = FALSE, item2 = FALSE;

	if (!is_pet || mindless(mtmp->data) || is_animal(mtmp->data))
		item1 = item2 = TRUE;
	if (!tunnels(mtmp->data) || !needspick(mtmp->data))
		item1 = TRUE;

	while ((otmp = mtmp->minvent) != 0) {
		obj_extract_self(otmp);
		/* special case: pick-axe and unicorn horn are non-worn */
		/* items that we also want pets to keep 1 of */
		/* (It is a coincidence that these can also be wielded.) */
		if (otmp->owornmask || otmp == wep ||
		    ((!item1 && otmp->otyp == PICK_AXE) ||
		     (!item2 && otmp->otyp == UNICORN_HORN && !otmp->cursed))) {
			if (is_pet) { /* dont drop worn/wielded item */
				if (otmp->otyp == PICK_AXE)
					item1 = TRUE;
				if (otmp->otyp == UNICORN_HORN && !otmp->cursed)
					item2 = TRUE;
				otmp->nobj = keepobj;
				keepobj = otmp;
				continue;
			}
		}
		mdrop_obj(mtmp, otmp, is_pet && flags.verbose);
	}

	/* put kept objects back */
	while ((otmp = keepobj) != NULL) {
	    keepobj = otmp->nobj;
	    add_to_minv(mtmp, otmp);
	}
	
	if (show & cansee(omx, omy))
		newsym(omx, omy);
}
Exemple #8
0
/*
 * return  1: guard moved,  0: guard didn't,  -1: let m_move do it,  -2: died
 */
int
gd_move(struct monst *grd)
{
    int x, y, nx, ny, m, n;
    int dx, dy, gx = 0, gy = 0, fci;
    uchar typ;
    struct fakecorridor *fcp;
    struct egd *egrd = EGD(grd);
    struct rm *crm;
    boolean goldincorridor = FALSE, u_in_vault =
        vault_occupied(u.urooms) ? TRUE : FALSE, grd_in_vault =
        *in_rooms(level, grd->mx, grd->my, VAULT) ? TRUE : FALSE;
    boolean disappear_msg_seen = FALSE, semi_dead = (grd->mhp <= 0);
    long umoney = money_cnt(invent);
    boolean u_carry_gold = ((umoney + hidden_gold()) > 0L);
    boolean see_guard;

    if (!on_level(&(egrd->gdlevel), &u.uz))
        return -1;
    nx = ny = m = n = 0;
    if (!u_in_vault && !grd_in_vault)
        wallify_vault(grd);
    if (!grd->mpeaceful) {
        if (semi_dead) {
            egrd->gddone = 1;
            goto newpos;
        }
        if (!u_in_vault &&
            (grd_in_vault ||
             (in_fcorridor(grd, grd->mx, grd->my) &&
              !in_fcorridor(grd, u.ux, u.uy)))) {
            rloc(grd, FALSE);
            wallify_vault(grd);
            clear_fcorr(grd, TRUE);
            goto letknow;
        }
        if (!in_fcorridor(grd, grd->mx, grd->my))
            clear_fcorr(grd, TRUE);
        return -1;
    }
    if (abs(egrd->ogx - grd->mx) > 1 || abs(egrd->ogy - grd->my) > 1)
        return -1;      /* teleported guard - treat as monster */
    if (egrd->fcend == 1) {
        if (u_in_vault && (u_carry_gold || um_dist(grd->mx, grd->my, 1))) {
            if (egrd->warncnt == 3)
                verbalize("I repeat, %sfollow me!",
                          u_carry_gold ? (!umoney ?
                                          "drop that hidden money and " :
                                          "drop that money and ") : "");
            if (egrd->warncnt == 7) {
                m = grd->mx;
                n = grd->my;
                verbalize("You've been warned, knave!");
                mnexto(grd);
                level->locations[m][n].typ = egrd->fakecorr[0].ftyp;
                newsym(m, n);
                msethostility(grd, TRUE, FALSE);
                return -1;
            }
            /* not fair to get mad when (s)he's fainted or paralyzed */
            if (!u_helpless(hm_all))
                egrd->warncnt++;
            return 0;
        }

        if (!u_in_vault) {
            if (u_carry_gold) { /* player teleported */
                m = grd->mx;
                n = grd->my;
                rloc(grd, FALSE);
                level->locations[m][n].typ = egrd->fakecorr[0].ftyp;
                newsym(m, n);
                msethostility(grd, TRUE, FALSE);
            letknow:
                if (!cansee(grd->mx, grd->my) || !mon_visible(grd))
                    You_hear("the shrill sound of a guard's whistle.");
                else
                    pline(um_dist(grd->mx, grd->my, 2) ?
                          "You see an angry guard approaching." :
                          "You are confronted by an angry guard.");
                return -1;
            } else {
                verbalize("Well, begone.");
                wallify_vault(grd);
                egrd->gddone = 1;
                goto cleanup;
            }
        }
    }

    if (egrd->fcend > 1) {
        if (egrd->fcend > 2 && in_fcorridor(grd, grd->mx, grd->my) &&
            !egrd->gddone && !in_fcorridor(grd, u.ux, u.uy) &&
            level->locations[egrd->fakecorr[0].fx][egrd->fakecorr[0].fy].typ ==
            egrd->fakecorr[0].ftyp) {
            if (canseemon(grd)) {
                pline("%s, confused, disappears.", Monnam(grd));
                disappear_msg_seen = TRUE;
            }
            goto cleanup;
        }
        if (u_carry_gold && (in_fcorridor(grd, u.ux, u.uy) ||
                             /* cover a 'blind' spot */
                             (egrd->fcend > 1 && u_in_vault))) {
            if (!grd->mx) {
                restfakecorr(grd);
                return -2;
            }
            if (egrd->warncnt < 6) {
                egrd->warncnt = 6;
                verbalize("Drop all your gold, scoundrel!");
                return 0;
            } else {
                verbalize("So be it, rogue!");
                msethostility(grd, TRUE, FALSE);
                return -1;
            }
        }
    }
    for (fci = egrd->fcbeg; fci < egrd->fcend; fci++)
        if (gold_at(level, egrd->fakecorr[fci].fx, egrd->fakecorr[fci].fy)) {
            m = egrd->fakecorr[fci].fx;
            n = egrd->fakecorr[fci].fy;
            goldincorridor = TRUE;
        }
    if (goldincorridor && !egrd->gddone) {
        boolean yours = FALSE;

        x = grd->mx;
        y = grd->my;
        if (m == u.ux && n == u.uy) {
            struct obj *gold = gold_at(level, m, n);

            yours = TRUE;
            /* Grab the gold from between the hero's feet.  */
            obj_extract_self(gold);
            add_to_minv(grd, gold);
            newsym(m, n);
        } else if (m == x && n == y) {
            mpickgold(grd);     /* does a newsym */
        } else {
            /* just for insurance... */
            if (MON_AT(level, m, n) && m != grd->mx && n != grd->my) {
                verbalize("Out of my way, scum!");
                rloc(m_at(level, m, n), FALSE);
            }
            remove_monster(level, grd->mx, grd->my);
            newsym(grd->mx, grd->my);
            place_monster(grd, m, n);
            mpickgold(grd);     /* does a newsym */
        }
        if (cansee(m, n)) {
            if (yours) {
                pline("%s%s picks up the gold.", Monnam(grd),
                      grd->mpeaceful ? " calms down and" : "");
            } else {
                pline("%s picks up some gold.", Monnam(grd));
            }
        }
        if (x != grd->mx || y != grd->my) {
            remove_monster(level, grd->mx, grd->my);
            newsym(grd->mx, grd->my);
            place_monster(grd, x, y);
            newsym(x, y);
        }
        if (!grd->mpeaceful)
            return -1;
        else {
            egrd->warncnt = 5;
            return 0;
        }
    }
    if (um_dist(grd->mx, grd->my, 1) || egrd->gddone) {
        if (!egrd->gddone && !rn2(10))
            verbalize("Move along!");
        restfakecorr(grd);
        return 0;       /* didn't move */
    }
    x = grd->mx;
    y = grd->my;

    if (u_in_vault)
        goto nextpos;

    /* look around (hor & vert only) for accessible places */
    for (nx = x - 1; nx <= x + 1; nx++)
        for (ny = y - 1; ny <= y + 1; ny++) {
            if ((nx == x || ny == y) && (nx != x || ny != y) && isok(nx, ny)) {

                typ = (crm = &level->locations[nx][ny])->typ;
                if (!IS_STWALL(typ) && !IS_POOL(typ)) {

                    if (in_fcorridor(grd, nx, ny))
                        goto nextnxy;

                    if (*in_rooms(level, nx, ny, VAULT))
                        continue;

                    /* seems we found a good place to leave him alone */
                    egrd->gddone = 1;
                    if (ACCESSIBLE(typ))
                        goto newpos;
                    crm->typ = (typ == SCORR) ? CORR : DOOR;
                    if (crm->typ == DOOR)
                        crm->doormask = D_NODOOR;
                    goto proceed;
                }
            }
        nextnxy:;
        }
nextpos:
    nx = x;
    ny = y;
    gx = egrd->gdx;
    gy = egrd->gdy;
    dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
    dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
    if (abs(gx - x) >= abs(gy - y))
        nx += dx;
    else
        ny += dy;

    while ((typ = (crm = &level->locations[nx][ny])->typ) != 0) {
        /* in view of the above we must have IS_WALL(typ) or typ == POOL */
        /* must be a wall here */
        if (isok(nx + nx - x, ny + ny - y) && !IS_POOL(typ) &&
            IS_ROOM(level->locations[nx + nx - x][ny + ny - y].typ)) {
            crm->typ = DOOR;
            crm->doormask = D_NODOOR;
            goto proceed;
        }
        if (dy && nx != x) {
            nx = x;
            ny = y + dy;
            continue;
        }
        if (dx && ny != y) {
            ny = y;
            nx = x + dx;
            dy = 0;
            continue;
        }
        /* I don't like this, but ... */
        if (IS_ROOM(typ)) {
            crm->typ = DOOR;
            crm->doormask = D_NODOOR;
            goto proceed;
        }
        break;
    }
    crm->typ = CORR;
proceed:
    unblock_point(nx, ny);      /* doesn't block light */
    if (cansee(nx, ny))
        newsym(nx, ny);

    if ((nx != gx || ny != gy) || (grd->mx != gx || grd->my != gy)) {
        fcp = &(egrd->fakecorr[egrd->fcend]);
        if (egrd->fcend++ == FCSIZ)
            panic("fakecorr overflow");
        fcp->fx = nx;
        fcp->fy = ny;
        fcp->ftyp = typ;
    } else if (!egrd->gddone) {
        /* We're stuck, so try to find a new destination. */
        if (!find_guard_dest(grd, &egrd->gdx, &egrd->gdy) ||
            (egrd->gdx == gx && egrd->gdy == gy)) {
            pline("%s, confused, disappears.", Monnam(grd));
            disappear_msg_seen = TRUE;
            goto cleanup;
        } else
            goto nextpos;
    }
newpos:
    if (egrd->gddone) {
        /* The following is a kludge.  We need to keep the guard around in order
           to be able to make the fake corridor disappear as the player moves
           out of it, but we also need the guard out of the way.  We send the
           guard to never-never land.  We set ogx ogy to mx my in order to avoid
           a check at the top of this function.  At the end of the process, the
           guard is killed in restfakecorr().  */
    cleanup:
        x = grd->mx;
        y = grd->my;

        see_guard = canspotmon(grd);
        wallify_vault(grd);
        remove_monster(level, grd->mx, grd->my);
        newsym(grd->mx, grd->my);
        grd->mx = COLNO;
        grd->my = ROWNO;
        egrd->ogx = grd->mx;
        egrd->ogy = grd->my;
        restfakecorr(grd);
        if (!semi_dead && (in_fcorridor(grd, u.ux, u.uy) || cansee(x, y))) {
            if (!disappear_msg_seen && see_guard)
                pline("Suddenly, %s disappears.", noit_mon_nam(grd));
            return 1;
        }
        return -2;
    }
    egrd->ogx = grd->mx;        /* update old positions */
    egrd->ogy = grd->my;
    remove_monster(level, grd->mx, grd->my);
    place_monster(grd, nx, ny);
    newsym(grd->mx, grd->my);
    restfakecorr(grd);
    return 1;
}