Пример #1
0
static void
newmail()
{
	/* produce a scroll of mail */
	struct obj *obj;
	struct monst *md;
	extern char plname[];
	extern struct obj *mksobj();
	extern struct monst *makemon();
	extern struct permonst pm_mail_daemon;

	obj = mksobj(SCR_MAIL);
	if(md = makemon(&pm_mail_daemon, u.ux, u.uy)) /* always succeeds */
		mdrush(md,0);

	pline("\"Hello, %s! I have some mail for you.\"", plname);
	if(md) {
		if(dist(md->mx,md->my) > 2)
			pline("\"Catch!\"");
		more();

		/* let him disappear again */
		mdrush(md,1);
		mondead(md);
	}

	obj = addinv(obj);
	(void) identify(obj);		/* set known and do prinv() */
}
Пример #2
0
/* drop a rock and remove monster */
static void
monstone(struct monst *mdef)
{
	if (strchr(mlarge, mdef->data->mlet))
		mksobj_at(ENORMOUS_ROCK, mdef->mx, mdef->my);
	else
		mksobj_at(ROCK, mdef->mx, mdef->my);
	if (cansee(mdef->mx, mdef->my)) {
		unpmon(mdef);
		atl(mdef->mx, mdef->my, fobj->olet);
	}
	mondead(mdef);
}
Пример #3
0
/* drop (perhaps) a cadaver and remove monster */
void
mondied(struct monst *mdef)
{
	const struct permonst *pd = mdef->data;
	if (letter(pd->mlet) && rn2(3)) {
		(void) mkobj_at(pd->mlet, mdef->mx, mdef->my);
		if (cansee(mdef->mx, mdef->my)) {
			unpmon(mdef);
			atl(mdef->mx, mdef->my, fobj->olet);
		}
		stackobj(fobj);
	}
	mondead(mdef);
}
Пример #4
0
static void
restfakecorr()
{
	int fcx,fcy,fcbeg;
	struct rm *crm;

	while((fcbeg = EGD->fcbeg) < EGD->fcend) {
		fcx = EGD->fakecorr[fcbeg].fx;
		fcy = EGD->fakecorr[fcbeg].fy;
		if((u.ux == fcx && u.uy == fcy) || cansee(fcx,fcy) ||
		   m_at(fcx,fcy))
			return;
		crm = &levl[fcx][fcy];
		crm->typ = EGD->fakecorr[fcbeg].ftyp;
		if(!crm->typ) crm->seen = 0;
		newsym(fcx,fcy);
		EGD->fcbeg++;
	}
	/* it seems he left the corridor - let the guard disappear */
	mondead(guard);
	guard = 0;
}
Пример #5
0
void newmail(void)
{
    // produce a scroll of mail
    struct obj *obj;
    struct monst *md;

    obj = mksobj(SCR_MAIL);
    if (md = makemon(&pm_mail_daemon, u.ux, u.uy))	// always succeeds
	mdrush(md, 0);

    pline("\"Hello, %s! I have some mail for you.\"", plname);
    if (md) {
	if (dist(md->mx, md->my) > 2)
	    pline("\"Catch!\"");
	more();

	// let him disappear again
	mdrush(md, 1);
	mondead(md);
    }
    obj = addinv(obj);
    (void) identify(obj);      // set known and do prinv()
}
Пример #6
0
void
invault()
{
	int tmp = inroom(u.ux, u.uy);

    if(tmp < 0 || rooms[tmp].rtype != VAULT) {
	u.uinvault = 0;
	return;
    }
    if(++u.uinvault % 50 == 0 && (!guard || gdlevel != dlevel)) {
	char buf[BUFSZ];
	int x,y,dd,gx,gy;

	/* first find the goal for the guard */
	for(dd = 1; (dd < ROWNO || dd < COLNO); dd++) {
	  for(y = u.uy-dd; y <= u.uy+dd; y++) {
	    if(y < 0 || y > ROWNO-1) continue;
	    for(x = u.ux-dd; x <= u.ux+dd; x++) {
	      if(y != u.uy-dd && y != u.uy+dd && x != u.ux-dd)
		x = u.ux+dd;
	      if(x < 0 || x > COLNO-1) continue;
	      if(levl[x][y].typ == CORR) goto fnd;
	    }
	  }
	}
	impossible("Not a single corridor on this level??");
	tele();
	return;
fnd:
	gx = x; gy = y;

	/* next find a good place for a door in the wall */
	x = u.ux; y = u.uy;
	while(levl[x][y].typ == ROOM) {
		int dx,dy;

		dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
		dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
		if(abs(gx-x) >= abs(gy-y))
			x += dx;
		else
			y += dy;
	}

	/* make something interesting happen */
	if(!(guard = makemon(&pm_guard,x,y))) return;
	guard->isgd = guard->mpeaceful = 1;
	EGD->gddone = 0;
	gdlevel = dlevel;
	if(!cansee(guard->mx, guard->my)) {
		mondead(guard);
		guard = 0;
		return;
	}

	pline("Suddenly one of the Vault's guards enters!");
	pmon(guard);
	do {
		pline("\"Hello stranger, who are you?\" - ");
		getlin(buf);
	} while (!letter(buf[0]));

	if(!strcmp(buf, "Croesus") || !strcmp(buf, "Kroisos")) {
		pline("\"Oh, yes - of course. Sorry to have disturbed you.\"");
		mondead(guard);
		guard = 0;
		return;
	}
	clrlin();
	pline("\"I don't know you.\"");
	if(!u.ugold)
	    pline("\"Please follow me.\"");
	else {
	    pline("\"Most likely all that gold was stolen from this vault.\"");
	    pline("\"Please drop your gold (say d$ ) and follow me.\"");
	}
	EGD->gdx = gx;
	EGD->gdy = gy;
	EGD->fcbeg = 0;
	EGD->fakecorr[0].fx = x;
	EGD->fakecorr[0].fy = y;
	EGD->fakecorr[0].ftyp = levl[x][y].typ;
	levl[x][y].typ = DOOR;
	EGD->fcend = 1;
    }
}
Пример #7
0
int
dopay(void)
{
	long ltmp;
	struct bill_x *bp;
	struct monst *shkp;
	int pass, tmp;

	multi = 0;
	inshop();
	for (shkp = fmon; shkp; shkp = shkp->nmon)
		if (shkp->isshk && dist(shkp->mx, shkp->my) < 3)
			break;
	if (!shkp && u.uinshop &&
	    inroom(shopkeeper->mx, shopkeeper->my) == ESHK(shopkeeper)->shoproom)
		shkp = shopkeeper;

	if (!shkp) {
		pline("There is nobody here to receive your payment.");
		return (0);
	}
	ltmp = ESHK(shkp)->robbed;
	if (shkp != shopkeeper && NOTANGRY(shkp)) {
		if (!ltmp)
			pline("You do not owe %s anything.", monnam(shkp));
		else if (!u.ugold)
			pline("You have no money.");
		else {
			long ugold = u.ugold;

			if (u.ugold > ltmp) {
				pline("You give %s the %ld gold pieces he asked for.",
				    monnam(shkp), ltmp);
				pay(ltmp, shkp);
			} else {
				pline("You give %s all your gold.", monnam(shkp));
				pay(u.ugold, shkp);
			}
			if (ugold < ltmp / 2)
				pline("Unfortunately, he doesn't look satisfied.");
			else {
				ESHK(shkp)->robbed = 0;
				ESHK(shkp)->following = 0;
				if (ESHK(shkp)->shoplevel != dlevel) {
					/* For convenience's sake, let him disappear */
					shkp->minvent = 0;	/* %% */
					shkp->mgold = 0;
					mondead(shkp);
				}
			}
		}
		return (1);
	}

	if (!ESHK(shkp)->billct) {
		pline("You do not owe %s anything.", monnam(shkp));
		if (!u.ugold) {
			pline("Moreover, you have no money.");
			return (1);
		}
		if (ESHK(shkp)->robbed) {
#define	min(a, b)	((a < b) ? a : b)
			pline("But since his shop has been robbed recently,");
			pline("you %srepay %s's expenses.",
			    (u.ugold < ESHK(shkp)->robbed) ? "partially " : "",
			    monnam(shkp));
			pay(min(u.ugold, ESHK(shkp)->robbed), shkp);
			ESHK(shkp)->robbed = 0;
			return (1);
		}
		if (ANGRY(shkp)) {
			pline("But in order to appease %s,",
			      amonnam(shkp, "angry"));
			if (u.ugold >= 1000) {
				ltmp = 1000;
				pline(" you give him 1000 gold pieces.");
			} else {
				ltmp = u.ugold;
				pline(" you give him all your money.");
			}
			pay(ltmp, shkp);
			if (strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)
			    || rn2(3)) {
				pline("%s calms down.", Monnam(shkp));
				NOTANGRY(shkp) = 1;
			} else
				pline("%s is as angry as ever.", Monnam(shkp));
		}
		return (1);
	}
	if (shkp != shopkeeper) {
		impossible("dopay: not to shopkeeper?");
		if (shopkeeper)
			setpaid();
		return (0);
	}
	for (pass = 0; pass <= 1; pass++) {
		tmp = 0;
		while (tmp < ESHK(shopkeeper)->billct) {
			bp = &bill[tmp];
			if (!pass && !bp->useup) {
				tmp++;
				continue;
			}
			if (!dopayobj(bp))
				return (1);
			bill[tmp] = bill[--ESHK(shopkeeper)->billct];
		}
	}
	pline("Thank you for shopping in %s's %s store!",
	      shkname(shopkeeper),
	      shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]);
	NOTANGRY(shopkeeper) = 1;
	return (1);
}
Пример #8
0
int
doread()
{
	struct obj *scroll;
	boolean confused = (Confusion != 0);
	boolean known = FALSE;

	scroll = getobj("?", "read");
	if(!scroll) return(0);
	if(!scroll->dknown && Blind) {
	    pline("Being blind, you cannot read the formula on the scroll.");
	    return(0);
	}
	if(Blind)
	  pline("As you pronounce the formula on it, the scroll disappears.");
	else
	  pline("As you read the scroll, it disappears.");
	if(confused)
	  pline("Being confused, you mispronounce the magic words ... ");

	switch(scroll->otyp) {
#ifdef MAIL
	case SCR_MAIL:
		readmail(/* scroll */);
		break;
#endif /* MAIL */
	case SCR_ENCHANT_ARMOR:
	    {	struct obj *otmp = some_armor();
		if(!otmp) {
			strange_feeling(scroll,"Your skin glows then fades.");
			return(1);
		}
		if(confused) {
			pline("Your %s glows silver for a moment.",
				objects[otmp->otyp].oc_name);
			otmp->rustfree = 1;
			break;
		}
		if(otmp->spe > 3 && rn2(otmp->spe)) {
	pline("Your %s glows violently green for a while, then evaporates.",
			objects[otmp->otyp].oc_name);
			useup(otmp);
			break;
		}
		pline("Your %s glows green for a moment.",
			objects[otmp->otyp].oc_name);
		otmp->cursed = 0;
		otmp->spe++;
		break;
	    }
	case SCR_DESTROY_ARMOR:
		if(confused) {
			struct obj *otmp = some_armor();
			if(!otmp) {
				strange_feeling(scroll,"Your bones itch.");
				return(1);
			}
			pline("Your %s glows purple for a moment.",
				objects[otmp->otyp].oc_name);
			otmp->rustfree = 0;
			break;
		}
		if(uarm) {
		    pline("Your armor turns to dust and falls to the floor!");
		    useup(uarm);
		} else if(uarmh) {
		    pline("Your helmet turns to dust and is blown away!");
		    useup(uarmh);
		} else if(uarmg) {
			pline("Your gloves vanish!");
			useup(uarmg);
			selftouch("You");
		} else {
			strange_feeling(scroll,"Your skin itches.");
			return(1);
		}
		break;
	case SCR_CONFUSE_MONSTER:
		if(confused) {
			pline("Your hands begin to glow purple.");
			Confusion += rnd(100);
		} else {
			pline("Your hands begin to glow blue.");
			u.umconf = 1;
		}
		break;
	case SCR_SCARE_MONSTER:
	    {	int ct = 0;
		struct monst *mtmp;

		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
			if(cansee(mtmp->mx,mtmp->my)) {
				if(confused)
					mtmp->mflee = mtmp->mfroz =
					mtmp->msleep = 0;
				else
					mtmp->mflee = 1;
				ct++;
			}
		if(!ct) {
		    if(confused)
			pline("You hear sad wailing in the distance.");
		    else
			pline("You hear maniacal laughter in the distance.");
		}
		break;
	    }
	case SCR_BLANK_PAPER:
		if(confused)
		    pline("You see strange patterns on this scroll.");
		else
		    pline("This scroll seems to be blank.");
		break;
	case SCR_REMOVE_CURSE:
	    {	struct obj *obj;
		if(confused)
		  pline("You feel like you need some help.");
		else
		  pline("You feel like someone is helping you.");
		for(obj = invent; obj ; obj = obj->nobj)
			if(obj->owornmask)
				obj->cursed = confused;
		if(Punished && !confused) {
			Punished = 0;
			freeobj(uchain);
			unpobj(uchain);
			free(uchain);
			uball->spe = 0;
			uball->owornmask &= ~W_BALL;
			uchain = uball = (struct obj *) 0;
		}
		break;
	    }
	case SCR_CREATE_MONSTER:
	    {	int cnt = 1;

		if(!rn2(73)) cnt += rnd(4);
		if(confused) cnt += 12;
		while(cnt--)
		    (void) makemon(confused ? PM_ACID_BLOB :
			(struct permonst *) 0, u.ux, u.uy);
		break;
	    }
	case SCR_ENCHANT_WEAPON:
		if(uwep && confused) {
			pline("Your %s glows silver for a moment.",
				objects[uwep->otyp].oc_name);
			uwep->rustfree = 1;
		} else
			if(!chwepon(scroll, 1))		/* tests for !uwep */
				return(1);
		break;
	case SCR_DAMAGE_WEAPON:
		if(uwep && confused) {
			pline("Your %s glows purple for a moment.",
				objects[uwep->otyp].oc_name);
			uwep->rustfree = 0;
		} else
			if(!chwepon(scroll, -1))	/* tests for !uwep */
				return(1);
		break;
	case SCR_TAMING:
	    {	int i,j;
		int bd = confused ? 5 : 1;
		struct monst *mtmp;

		for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++)
		if ((mtmp = m_at(u.ux+i, u.uy+j)))
			(void) tamedog(mtmp, NULL);
		break;
	    }
	case SCR_GENOCIDE:
	    {	extern char genocided[], fut_geno[];
		char buf[BUFSZ];
		struct monst *mtmp, *mtmp2;

		pline("You have found a scroll of genocide!");
		known = TRUE;
		if(confused)
			*buf = u.usym;
		else do {
	    pline("What monster do you want to genocide (Type the letter)? ");
			getlin(buf);
		} while(strlen(buf) != 1 || !monstersym(*buf));
		if(!strchr(fut_geno, *buf))
			charcat(fut_geno, *buf);
		if(!strchr(genocided, *buf))
			charcat(genocided, *buf);
		else {
			pline("Such monsters do not exist in this world.");
			break;
		}
		for(mtmp = fmon; mtmp; mtmp = mtmp2){
			mtmp2 = mtmp->nmon;
			if(mtmp->data->mlet == *buf)
				mondead(mtmp);
		}
		pline("Wiped out all %c's.", *buf);
		if(*buf == u.usym) {
			killer = "scroll of genocide";
			u.uhp = -1;
		}
		break;
		}
	case SCR_LIGHT:
		if(!Blind) known = TRUE;
		litroom(!confused);
		break;
	case SCR_TELEPORTATION:
		if(confused)
			level_tele();
		else {
#ifdef QUEST
			int oux = u.ux, ouy = u.uy;
			tele();
			if(dist(oux, ouy) > 100) known = TRUE;
#else /* QUEST */
			int uroom = inroom(u.ux, u.uy);
			tele();
			if(uroom != inroom(u.ux, u.uy)) known = TRUE;
#endif /* QUEST */
		}
		break;
	case SCR_GOLD_DETECTION:
	    /* Unfortunately this code has become slightly less elegant,
	       now that gold and traps no longer are of the same type. */
	    if(confused) {
		struct trap *ttmp;

		if(!ftrap) {
			strange_feeling(scroll, "Your toes stop itching.");
			return(1);
		} else {
			for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
				if(ttmp->tx != u.ux || ttmp->ty != u.uy)
					goto outtrapmap;
			/* only under me - no separate display required */
			pline("Your toes itch!");
			break;
		outtrapmap:
			cls();
			for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
				at(ttmp->tx, ttmp->ty, '$');
			prme();
			pline("You feel very greedy!");
		}
	    } else {
		struct gold *gtmp;

		if(!fgold) {
			strange_feeling(scroll, "You feel materially poor.");
			return(1);
		} else {
			known = TRUE;
			for(gtmp = fgold; gtmp; gtmp = gtmp->ngold)
				if(gtmp->gx != u.ux || gtmp->gy != u.uy)
					goto outgoldmap;
			/* only under me - no separate display required */
			pline("You notice some gold between your feet.");
			break;
		outgoldmap:
			cls();
			for(gtmp = fgold; gtmp; gtmp = gtmp->ngold)
				at(gtmp->gx, gtmp->gy, '$');
			prme();
			pline("You feel very greedy, and sense gold!");
		}
	    }
		/* common sequel */
		more();
		docrt();
		break;
	case SCR_FOOD_DETECTION:
	    {	int ct = 0, ctu = 0;
		struct obj *obj;
		char foodsym = confused ? POTION_SYM : FOOD_SYM;

		for(obj = fobj; obj; obj = obj->nobj)
			if(obj->olet == FOOD_SYM) {
				if(obj->ox == u.ux && obj->oy == u.uy) ctu++;
				else ct++;
			}
		if(!ct && !ctu) {
			strange_feeling(scroll,"Your nose twitches.");
			return(1);
		} else if(!ct) {
			known = TRUE;
			pline("You smell %s close nearby.",
				confused ? "something" : "food");
			
		} else {
			known = TRUE;
			cls();
			for(obj = fobj; obj; obj = obj->nobj)
			    if(obj->olet == foodsym)
				at(obj->ox, obj->oy, FOOD_SYM);
			prme();
			pline("Your nose tingles and you smell %s!",
				confused ? "something" : "food");
			more();
			docrt();
		}
		break;
	    }
	case SCR_IDENTIFY:
		/* known = TRUE; */
		if(confused)
			pline("You identify this as an identify scroll.");
		else
			pline("This is an identify scroll.");
		useup(scroll);
		objects[SCR_IDENTIFY].oc_name_known = 1;
		if(!confused)
		    while(
			!ggetobj("identify", identify, rn2(5) ? 1 : rn2(5))
			&& invent
		    );
		return(1);
	case SCR_MAGIC_MAPPING:
	    {	struct rm *lev;
		int num, zx, zy;

		known = TRUE;
		pline("On this scroll %s a map!",
			confused ? "was" : "is");
		for(zy = 0; zy < ROWNO; zy++)
			for(zx = 0; zx < COLNO; zx++) {
				if(confused && rn2(7)) continue;
				lev = &(levl[zx][zy]);
				if((num = lev->typ) == 0)
					continue;
				if(num == SCORR) {
					lev->typ = CORR;
					lev->scrsym = CORR_SYM;
				} else
				if(num == SDOOR) {
					lev->typ = DOOR;
					lev->scrsym = '+';
					/* do sth in doors ? */
				} else if(lev->seen) continue;
#ifndef QUEST
				if(num != ROOM)
#endif /* QUEST */
				{
				  lev->seen = lev->new = 1;
				  if(lev->scrsym == ' ' || !lev->scrsym)
				    newsym(zx,zy);
				  else
				    on_scr(zx,zy);
				}
			}
		break;
	    }
	case SCR_AMNESIA:
	    {	int zx, zy;

		known = TRUE;
		for(zx = 0; zx < COLNO; zx++) for(zy = 0; zy < ROWNO; zy++)
		    if(!confused || rn2(7))
			if(!cansee(zx,zy))
			    levl[zx][zy].seen = 0;
		docrt();
		pline("Thinking of Maud you forget everything else.");
		break;
	    }
	case SCR_FIRE:
	    {	int num;
		struct monst *mtmp;

		known = TRUE;
		if(confused) {
		    pline("The scroll catches fire and you burn your hands.");
		    losehp(1, "scroll of fire");
		} else {
		    pline("The scroll erupts in a tower of flame!");
		    if(Fire_resistance)
			pline("You are uninjured.");
		    else {
			num = rnd(6);
			u.uhpmax -= num;
			losehp(num, "scroll of fire");
		    }
		}
		num = (2*num + 1)/3;
		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
		    if(dist(mtmp->mx,mtmp->my) < 3) {
			mtmp->mhp -= num;
			if(strchr("FY", mtmp->data->mlet))
			    mtmp->mhp -= 3*num;	/* this might well kill 'F's */
			if(mtmp->mhp < 1) {
			    killed(mtmp);
			    break;		/* primitive */
			}
		    }
		}
		break;
	    }
	case SCR_PUNISHMENT:
		known = TRUE;
		if(confused) {
			pline("You feel guilty.");
			break;
		}
		pline("You are being punished for your misbehaviour!");
		if(Punished){
			pline("Your iron ball gets heavier.");
			uball->owt += 15;
			break;
		}
		Punished = INTRINSIC;
		setworn(mkobj_at(CHAIN_SYM, u.ux, u.uy), W_CHAIN);
		setworn(mkobj_at(BALL_SYM, u.ux, u.uy), W_BALL);
		uball->spe = 1;		/* special ball (see save) */
		break;
	default:
		impossible("What weird language is this written in? (%u)",
			scroll->otyp);
	}
Пример #9
0
void killed(struct monst *mtmp)
{
#define NEW_SCORING

    int tmp;
    int tmp2;
    int nk;
    int x;
    int y;
    struct permonst *mdat = mtmp->data;

    if(mtmp->cham != 0) {
        mdat = PM_CHAM;
    }

    if(Blind != 0) {
        pline("You destroy it!");
    }
    else {
        if(mtmp->mtame != 0) {
            pline("You destroy %s!", amonnam(mtmp, "poor"));
        }
        else {
            pline("You destroy %s!", monnam(mtmp));
        }
    }

    if(u.umconf != 0) {
        if(Blind == 0) {
            pline("Your hands stop clowing blue.");
            u.umconf = 0;
        }
    }

    /* Count killed monsters */
#define MAXMONNO 100
    /* In case we cannot find it in mons */
    nk = 1;

    /* Index in mons array (if not 'd', '@', ...) */
    tmp = mdat - mons;

    if((tmp >= 0) && (tmp < (CMNUM + 2))) {
        extern char fut_geno[];

        ++u.nr_killed[tmp];
        nk = u.nr_killed[tmp];
        if((nk > MAXMONNO) && (index(fut_geno, mdat->mlet) == 0)) {
            charcat(fut_geno, mdat->mlet);
        }
    }

    /* Punish bad behaviour */
    if(mdat->mlet == '@') {
        Telepat = 0;
        u.uluck -= 2;
    }

    if((mtmp->mpeaceful != 0) || (mtmp->mtame != 0)) {
        --u.uluck;
    }

    if(mdat->mlet == 'u') {
        u.uluck -= 5;
    }

    /* Give experience points */
    tmp = 1 + (mdat->mlevel * mdat->mlevel);

    if(mdat->ac < 3) {
        tmp += (2 * (7 - mdat->ac));
    }

    if(index("AcsSDXaeRTVWU&In:P", mdat->mlet) != 0) {
        tmp += (2 * mdat->mlevel);
    }

    if(index("DeV&P", mdat->mlet) != 0) {
        tmp += (7 * mdat->mlevel);
    }

    if(mdat->mlevel > 6) {
        tmp += 50;
    }

#ifdef NEW_SCORING
    /*
     * ------- Recent addition: make number of points decrease
     * when this is not the first of this kind
     */
    int ul = u.ulevel;
    int ml = mdat->mlevel;
    
    /* Points are given based on present and future level */
    if(ul < 14) {
        for(tmp2 = 0; (tmp2 == 0) || ((ul + tmp2) <= ml); ++tmp2) {
            if(tmp <= 0) {
                if(((u.uexp + 1) + ((tmp + (0)) / nk)) >= (10 * pow(2, (unsigned)(ul - 1)))) {
                    ++ul;
                    if(ul == 14) {
                        break;
                    }
                }
            }
            else {
                if(((u.uexp + 1) + ((tmp + (4 << (tmp2 - 1))) / nk)) >= (10 * pow(2, (unsigned)(ul - 1)))) {
                    ++ul;
                    if(ul == 14) {
                        break;
                    }
                }
            }
        }
    }

    tmp2 = (ml - ul) - 1;
    
    if(tmp2 < 0) {
        tmp = (tmp + (0)) / nk;
    }
    else {
        tmp = (tmp + (4 << tmp2)) / nk;
    }

    if(tmp == 0) {
        tmp = 1;
    }

    /* 
     * Note: ul is not necessarily the future value of u.ulevel
     * ------- End of recent valuation change -------
     */
#endif

    u.uexp += tmp;
    u.urexp += (4 * tmp);
    flags.botl = 1;

    while((u.ulevel < 14) && (u.uexp >= (10 * pow(2, u.ulevel - 1)))) {
        ++u.ulevel;
        pline("Welcome to level %d.", u.ulevel);

        tmp = rnd(30);

        if(tmp < 3) {
            tmp = rnd(10);
        }

        u.uhpmax += tmp;
        u.uhp += tmp;
        flags.botl = 1;
    }

    /* Dispose of monster and make cadaver */
    x = mtmp->mx;
    y = mtmp->my;
    mondead(mtmp);
    tmp = mdat->mlet;

    if(tmp == 'm') {
        /* He killed a minotaur, give him a wand of digging */
        /* Note: The dead minotaur will be on top of it! */
        mksobj_at(WAND_SYM, WAN_DIGGING, x, y);

        /*
         * if(cansee(x, y) != 0) {
         *     atl(x, y, fobj->olet);
         * }
         */

        stackobj(fobj);
    }
#ifndef NOWORM
    else if(tmp == 'w') {
        mksobj_at(WEAPON_SYM, WORM_TOOTH, x, y);
        stackobj(fobj);
    }
#endif
    else {
        if((letter(tmp) == 0) || (rn2(3) == 0)) {
            tmp = 0;
        }

        if(levl[x][y].typ >= DOOR) {
            /* Might be a mimic in wall */
            if((x != u.ux) || (y != u.uy)) {
                /* Might be here after swallowed */
                if((index("NTVm&", mdat->mlet) != NULL) || (rn2(5) != 0)) {
                    mkobj_at(tmp, x, y);
                    
                    if(cansee(x, y) != 0) {
                        atl(x, y, fobj->olet);
                    }

                    stackobj(fobj);
                }
            }
        }
    }
}
Пример #10
0
movemon()
{
	register struct monst *mtmp;
	register int fr;

	warnlevel = 0;

	while(1) {
		/* find a monster that we haven't treated yet */
		/* note that mtmp or mtmp->nmon might get killed
		   while mtmp moves, so we cannot just walk down the
		   chain (even new monsters might get created!) */
		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
			if(mtmp->mlstmv < moves) goto next_mon;
		/* treated all monsters */
		break;

	next_mon:
		mtmp->mlstmv = moves;

		/* most monsters drown in pools */
		{ boolean inpool, iseel;

		  inpool = (levl[mtmp->mx][mtmp->my].typ == POOL);
		  iseel = (mtmp->data->mlet == ';');
		  if(inpool && !iseel) {
			if(cansee(mtmp->mx,mtmp->my))
			    pline("%s drowns.", Monnam(mtmp));
			mondead(mtmp);
			continue;
		  }
		/* but eels have a difficult time outside */
		  if(iseel && !inpool) {
			if(mtmp->mhp > 1) mtmp->mhp--;
			mtmp->mflee = 1;
			mtmp->mfleetim += 2;
		  }
		}
		if(mtmp->mblinded && !--mtmp->mblinded)
			mtmp->mcansee = 1;
		if(mtmp->mfleetim && !--mtmp->mfleetim)
			mtmp->mflee = 0;
		if(mtmp->mimic) continue;
		if(mtmp->mspeed != MSLOW || !(moves%2)){
			/* continue if the monster died fighting */
			fr = -1;
			if(Conflict && cansee(mtmp->mx,mtmp->my)
				&& (fr = fightm(mtmp)) == 2)
				continue;
			if(fr<0 && dochugw(mtmp))
				continue;
		}
		if(mtmp->mspeed == MFAST && dochugw(mtmp))
			continue;
	}

	warnlevel -= u.ulevel;
	if(warnlevel >= SIZE(warnings))
		warnlevel = SIZE(warnings)-1;
	if(warnlevel >= 0)
	if(warnlevel > lastwarnlev || moves > lastwarntime + 5){
	    register char *rr;
/* KLUDGE -- can't switch on longs!!
	    switch(Warning & (LEFT_RING | RIGHT_RING)){
	    case LEFT_RING:
		rr = "Your left ring glows";
		break;
	    case RIGHT_RING:
		rr = "Your right ring glows";
		break;
	    case LEFT_RING | RIGHT_RING:
		rr = "Both your rings glow";
		break;
	    default:
		rr = "Your fingertips glow";
		break;
	    }
*/
	    long swtval = Warning & (LEFT_RING | RIGHT_RING);
	         if(swtval == LEFT_RING)         rr = "Your left ring glows";
	    else if(swtval == RIGHT_RING)        rr = "Your right ring glows";
	    else if(swtval == LEFT_RING
	                    | RIGHT_RING)        rr = "Both your rings glow";
	    else                                 rr = "Your fingertips glow";
	    pline("%s %s!", rr, warnings[warnlevel]);
	    lastwarntime = moves;
	    lastwarnlev = warnlevel;
	}

	dmonsfree();	/* remove all dead monsters */
}
Пример #11
0
// What does the return value indicate??
Boolean dopay()
{
  Long ltmp;
  bill_t *bp;
  monst_t *shkp;
  Short pass, tmp;

  multi = 0;
  inshop();
  for (shkp = fmon ; shkp ; shkp = shkp->nmon)
    if ((shkp->bitflags & M_IS_SHOPKEEPER) && dist(shkp->mx,shkp->my) < 3)
      break;
  if (!shkp && you.uinshop &&
      inroom(shopkeeper->mx,shopkeeper->my) == ESHK(shopkeeper)->shoproom)
    shkp = shopkeeper;

  if (!shkp) {
    message("There is nobody here to receive your payment.");
    return false;
  }
  ltmp = ESHK(shkp)->robbed;
  if (shkp != shopkeeper && NOTANGRY(shkp)) {
    if (!ltmp) {
      StrPrintF(ScratchBuffer, "You do not owe %s anything.", monnam(shkp));
      message(ScratchBuffer);
    } else
      if (!you.ugold) {
	message("You have no money.");
      } else {
	Long ugold = you.ugold;

	if (you.ugold > ltmp) {
	  StrPrintF(ScratchBuffer,
		    "You give %s the %ld gold pieces he asked for.",
		    monnam(shkp), ltmp);
	  message(ScratchBuffer);
	  pay(ltmp, shkp);
	} else {
	  StrPrintF(ScratchBuffer, "You give %s all your gold.", monnam(shkp));
	  message(ScratchBuffer);
	  pay(you.ugold, shkp);
	}
	if (ugold < ltmp/2) {
	  message("Unfortunately, he doesn't look satisfied.");
	} else {
	  ESHK(shkp)->robbed = 0;
	  ESHK(shkp)->following = false;
	  if (ESHK(shkp)->shoplevel != dlevel) {
	    /* For convenience's sake, let him disappear */
	    shkp->minvent = NULL;	/* %% */ // xxx leak?
	    shkp->mgold = 0;
	    mondead(shkp);
	  }
	}
      }
    return true;
  }
		
  if (!ESHK(shkp)->billct) {
    StrPrintF(ScratchBuffer, "You do not owe %s anything.", monnam(shkp));
    message(ScratchBuffer);
    if (!you.ugold) {
      message("Moreover, you have no money.");
      return true;
    }
    if (ESHK(shkp)->robbed) {
      message("But since his shop has been robbed recently,");
      StrPrintF(ScratchBuffer, "you%srepay %s's expenses.",
		(you.ugold < ESHK(shkp)->robbed) ? " partially " : " ",
		monnam(shkp));
      message(ScratchBuffer);
      pay(min(you.ugold, ESHK(shkp)->robbed), shkp);
      ESHK(shkp)->robbed = 0;
      return true;
    }
    if (ANGRY(shkp)) {
      StrPrintF(ScratchBuffer, "But in order to appease %s,",
		amonnam(shkp, "angry"));
      message(ScratchBuffer);
      if (you.ugold >= 1000) {
	ltmp = 1000;
	message(" you give him 1000 gold pieces.");
      } else {
	ltmp = you.ugold;
	message(" you give him all your money.");
      }
      pay(ltmp, shkp);
      if (StrNCompare(ESHK(shkp)->customer, plname, PL_NSIZ)
	  || rund(3)){
	StrPrintF(ScratchBuffer, "%s calms down.", Monnam(shkp));
	message(ScratchBuffer);
	shkp->bitflags |= M_IS_PEACEFUL; // NOTANGRY(shopkeeper) = 1;
      } else {
	StrPrintF(ScratchBuffer, "%s is as angry as ever.",
		  Monnam(shkp));
	message(ScratchBuffer);
      }
    }
    return true;
  }
  if (shkp != shopkeeper) {
    message("BUG: dopay: not to shopkeeper?");
    if (shopkeeper) setpaid();
    return false;
  }
  for (pass = 0 ; pass <= 1 ; pass++) {
    tmp = 0;
    while (tmp < ESHK(shopkeeper)->billct) {
      bp = &bill[tmp];
      if (!pass && !bp->useup) {
	tmp++;
	continue;
      }
      if (!dopayobj(bp)) return true;
      bill[tmp] = bill[--ESHK(shopkeeper)->billct];
    }
  }
  StrPrintF(ScratchBuffer, "Thank you for shopping in %s's %s store!",
	    shkname(shopkeeper),
	    shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]);
  shopkeeper->bitflags |= M_IS_PEACEFUL; // NOTANGRY(shopkeeper) = 1;
  return true;
}
Пример #12
0
void
getlev(int fd, int pid, xchar lev)
{
	struct gold    *gold;
	struct trap    *trap;
#ifndef NOWORM
	struct wseg    *wtmp;
#endif	/* NOWORM */
	int		tmp;
	long            omoves;
	int             hpid;
	xchar           dlvl;

	/* First some sanity checks */
	mread(fd, &hpid, sizeof(hpid));
	mread(fd, &dlvl, sizeof(dlvl));
	if ((pid && pid != hpid) || (lev && dlvl != lev)) {
		pline("Strange, this map is not as I remember it.");
		pline("Somebody is trying some trickery here ...");
		pline("This game is void ...");
		done("tricked");
	}
	fgold = 0;
	ftrap = 0;
	mread(fd, levl, sizeof(levl));
	mread(fd, &omoves, sizeof(omoves));
	mread(fd, &xupstair, sizeof(xupstair));
	mread(fd, &yupstair, sizeof(yupstair));
	mread(fd, &xdnstair, sizeof(xdnstair));
	mread(fd, &ydnstair, sizeof(ydnstair));

	fmon = restmonchn(fd);

	/* regenerate animals while on another level */
	{
		long            tmoves = (moves > omoves) ? moves - omoves : 0;
		struct monst   *mtmp, *mtmp2;

		for (mtmp = fmon; mtmp; mtmp = mtmp2) {
			long            newhp;	/* tmoves may be very large */

			mtmp2 = mtmp->nmon;
			if (strchr(genocided, mtmp->data->mlet)) {
				mondead(mtmp);
				continue;
			}
			if (mtmp->mtame && tmoves > 250) {
				mtmp->mtame = 0;
				mtmp->mpeaceful = 0;
			}
			newhp = mtmp->mhp +
				(strchr(MREGEN, mtmp->data->mlet) ? tmoves : tmoves / 20);
			if (newhp > mtmp->mhpmax)
				mtmp->mhp = mtmp->mhpmax;
			else
				mtmp->mhp = newhp;
		}
	}

	setgd();
	gold = newgold();
	mread(fd, gold, sizeof(struct gold));
	while (gold->gx) {
		gold->ngold = fgold;
		fgold = gold;
		gold = newgold();
		mread(fd, gold, sizeof(struct gold));
	}
	free(gold);
	trap = newtrap();
	mread(fd, trap, sizeof(struct trap));
	while (trap->tx) {
		trap->ntrap = ftrap;
		ftrap = trap;
		trap = newtrap();
		mread(fd, trap, sizeof(struct trap));
	}
	free(trap);
	fobj = restobjchn(fd);
	billobjs = restobjchn(fd);
	rest_engravings(fd);
#ifndef QUEST
	mread(fd, rooms, sizeof(rooms));
	mread(fd, doors, sizeof(doors));
#endif	/* QUEST */
#ifndef NOWORM
	mread(fd, wsegs, sizeof(wsegs));
	for (tmp = 1; tmp < 32; tmp++)
		if (wsegs[tmp]) {
			wheads[tmp] = wsegs[tmp] = wtmp = newseg();
			while (1) {
				mread(fd, wtmp, sizeof(struct wseg));
				if (!wtmp->nseg)
					break;
				wheads[tmp]->nseg = wtmp = newseg();
				wheads[tmp] = wtmp;
			}
		}
	mread(fd, wgrowtime, sizeof(wgrowtime));
#endif	/* NOWORM */
}
Пример #13
0
/*
 * mhitu: monster hits you
 *	  returns 1 if monster dies (e.g. 'y', 'F'), 0 otherwise
 */
bool
mhitu(struct monst *mtmp)
{
	struct permonst *mdat = mtmp->data;
	int tmp, ctmp;

	nomul(0);

	/* If swallowed, can only be affected by hissers and by u.ustuck */
	if (u.uswallow) {
		if (mtmp != u.ustuck) {
			if (mdat->mlet == 'c' && !rn2(13)) {
				pline("Outside, you hear %s's hissing!",
				      monnam(mtmp));
				pline("%s gets turned to stone!",
				      Monnam(u.ustuck));
				pline("And the same fate befalls you.");
				done_in_by(mtmp);
				/* "notreached": not return(1); */
			}
			return (0);
		}
		switch (mdat->mlet) {	/* now mtmp == u.ustuck */
		case ',':
			youswld(mtmp, (u.uac > 0) ? u.uac + 4 : 4,
				5, "The trapper");
			break;
		case '\'':
			youswld(mtmp, rnd(6), 7, "The lurker above");
			break;
		case 'P':
			youswld(mtmp, d(2, 4), 12, "The purple worm");
			break;
		default:
			/* This is not impossible! */
			pline("The mysterious monster totally digests you.");
			u.uhp = 0;
		}
		if (u.uhp < 1)
			done_in_by(mtmp);
		return (0);
	}

	if (mdat->mlet == 'c' && Stoned)
		return (0);

	/* make eels visible the moment they hit/miss us */
	if (mdat->mlet == ';' && mtmp->minvis && cansee(mtmp->mx, mtmp->my)) {
		mtmp->minvis = 0;
		pmon(mtmp);
	}
	if (!strchr("1&DuxynNF", mdat->mlet))
		tmp = hitu(mtmp, d(mdat->damn, mdat->damd));
	else
		tmp = 0;
	if (strchr(UNDEAD, mdat->mlet) && midnight())
		tmp += hitu(mtmp, d(mdat->damn, mdat->damd));

	ctmp = tmp && !mtmp->mcan &&
	    (!uarm || objects[uarm->otyp].a_can < rnd(3) || !rn2(50));
	switch (mdat->mlet) {
	case '1':
		if (wiz_hit(mtmp))	/* he disappeared */
			return (1);
		break;
	case '&':
		if (!mtmp->cham && !mtmp->mcan && !rn2(13)) {
			makemon(PM_DEMON, u.ux, u.uy);
		} else {
			hitu(mtmp, d(2, 6));
			hitu(mtmp, d(2, 6));
			hitu(mtmp, rnd(3));
			hitu(mtmp, rnd(3));
			hitu(mtmp, rn1(4, 2));
		}
		break;
	case ',':
		if (tmp)
			justswld(mtmp, "The trapper");
		break;
	case '\'':
		if (tmp)
			justswld(mtmp, "The lurker above");
		break;
	case ';':
		if (ctmp) {
			if (!u.ustuck && !rn2(10)) {
				pline("%s swings itself around you!",
				      Monnam(mtmp));
				u.ustuck = mtmp;
			} else if (u.ustuck == mtmp &&
				   levl[mtmp->mx][mtmp->my].typ == POOL) {
				pline("%s drowns you ...", Monnam(mtmp));
				done("drowned");
			}
		}
		break;
	case 'A':
		if (ctmp && rn2(2)) {
			if (Poison_resistance)
				pline("The sting doesn't seem to affect you.");
			else {
				pline("You feel weaker!");
				losestr(1);
			}
		}
		break;
	case 'C':
		hitu(mtmp, rnd(6));
		break;
	case 'c':
		if (!rn2(5)) {
			pline("You hear %s's hissing!", monnam(mtmp));
			if (ctmp || !rn2(20) || (flags.moonphase == NEW_MOON
			    && !carrying(DEAD_LIZARD)))
				Stoned = 5;
		}
		break;
	case 'D':
		if (rn2(6) || mtmp->mcan) {
			hitu(mtmp, d(3, 10));
			hitu(mtmp, rnd(8));
			hitu(mtmp, rnd(8));
			break;
		}
		kludge("%s breathes fire!", "The dragon");
		buzz(-1, mtmp->mx, mtmp->my, u.ux - mtmp->mx, u.uy - mtmp->my);
		break;
	case 'd':
		hitu(mtmp, d(2, (flags.moonphase == FULL_MOON) ? 3 : 4));
		break;
	case 'e':
		hitu(mtmp, d(3, 6));
		break;
	case 'F':
		if (mtmp->mcan)
			break;
		kludge("%s explodes!", "The freezing sphere");
		if (Cold_resistance)
			pline("You don't seem affected by it.");
		else {
			xchar dn;
			if (17 - (u.ulevel / 2) > rnd(20)) {
				pline("You get blasted!");
				dn = 6;
			} else {
				pline("You duck the blast...");
				dn = 3;
			}
			losehp_m(d(dn, 6), mtmp);
		}
		mondead(mtmp);
		return (1);
	case 'g':
		if (ctmp && multi >= 0 && !rn2(3)) {
			kludge("You are frozen by %ss juices", "the cube'");
			nomul(-rnd(10));
		}
		break;
	case 'h':
		if (ctmp && multi >= 0 && !rn2(5)) {
			nomul(-rnd(10));
			kludge("You are put to sleep by %ss bite!",
			       "the homunculus'");
		}
		break;
	case 'j':
		tmp = hitu(mtmp, rnd(3));
		tmp &= hitu(mtmp, rnd(3));
		if (tmp) {
			hitu(mtmp, rnd(4));
			hitu(mtmp, rnd(4));
		}
		break;
	case 'k':
		if ((hitu(mtmp, rnd(4)) || !rn2(3)) && ctmp)
			poisoned("bee's sting", mdat->mname);
		break;
	case 'L':
		if (tmp)
			stealgold(mtmp);
		break;
	case 'N':
		if (mtmp->mcan && !Blind) {
			pline("%s tries to seduce you, but you seem not interested.",
			    Amonnam(mtmp, "plain"));
			if (rn2(3))
				rloc(mtmp);
		} else if (steal(mtmp)) {
			rloc(mtmp);
			mtmp->mflee = 1;
		}
		break;
	case 'n':
		if (!uwep && !uarm && !uarmh && !uarms && !uarmg) {
			pline("%s hits! (I hope you don't mind)",
			      Monnam(mtmp));
			u.uhp += rnd(7);
			if (!rn2(7))
				u.uhpmax++;
			if (u.uhp > u.uhpmax)
				u.uhp = u.uhpmax;
			flags.botl = 1;
			if (!rn2(50))
				rloc(mtmp);
		} else {
			hitu(mtmp, d(2, 6));
			hitu(mtmp, d(2, 6));
		}
		break;
	case 'o':
		tmp = hitu(mtmp, rnd(6));
		if (hitu(mtmp, rnd(6)) && tmp &&	/* hits with both paws */
		    !u.ustuck && rn2(2)) {
			u.ustuck = mtmp;
			kludge("%s has grabbed you!", "The owlbear");
			u.uhp -= d(2, 8);
		} else if (u.ustuck == mtmp) {
			u.uhp -= d(2, 8);
			pline("You are being crushed.");
		}
		break;
	case 'P':
		if (ctmp && !rn2(4))
			justswld(mtmp, "The purple worm");
		else
			hitu(mtmp, d(2, 4));
		break;
	case 'Q':
		hitu(mtmp, rnd(2));
		hitu(mtmp, rnd(2));
		break;
	case 'R':
		if (tmp && uarmh && !uarmh->rustfree &&
		    (int)uarmh->spe >= -1) {
			pline("Your helmet rusts!");
			uarmh->spe--;
		} else if (ctmp && uarm && !uarm->rustfree &&	/* Mike Newton */
		    uarm->otyp < STUDDED_LEATHER_ARMOR &&
		    (int)uarm->spe >= -1) {
			pline("Your armor rusts!");
			uarm->spe--;
		}
		break;
	case 'S':
		if (ctmp && !rn2(8))
			poisoned("snake's bite", mdat->mname);
		break;
	case 's':
		if (tmp && !rn2(8))
			poisoned("scorpion's sting", mdat->mname);
		hitu(mtmp, rnd(8));
		hitu(mtmp, rnd(8));
		break;
	case 'T':
		hitu(mtmp, rnd(6));
		hitu(mtmp, rnd(6));
		break;
	case 't':
		if (!rn2(5))
			rloc(mtmp);
		break;
	case 'u':
		mtmp->mflee = 1;
		break;
	case 'U':
		hitu(mtmp, d(3, 4));
		hitu(mtmp, d(3, 4));
		break;
	case 'v':
		if (ctmp && !u.ustuck)
			u.ustuck = mtmp;
		break;
	case 'V':
		if (tmp)
			u.uhp -= 4;
		if (ctmp)
			losexp();
		break;
	case 'W':
		if (ctmp)
			losexp();
		break;
#ifndef NOWORM
	case 'w':
		if (tmp)
			wormhit(mtmp);
#endif /* NOWORM */
		break;
	case 'X':
		hitu(mtmp, rnd(5));
		hitu(mtmp, rnd(5));
		hitu(mtmp, rnd(5));
		break;
	case 'x':
		{
			long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
			pline("%s pricks in your %s leg!",
			    Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left");
			set_wounded_legs(side, rnd(50));
			losehp_m(2, mtmp);
			break;
		}
	case 'y':
		if (mtmp->mcan)
			break;
		mondead(mtmp);
		if (!Blind) {
			pline("You are blinded by a blast of light!");
			Blind = d(4, 12);
			seeoff(0);
		}
		return (1);
	case 'Y':
		hitu(mtmp, rnd(6));
		break;
	}
	if (u.uhp < 1)
		done_in_by(mtmp);
	return (0);
}