⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hack.shk.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. *//* hack.shk.c - version 1.0.3 */#include "hack.h"#ifdef QUESTint shlevel = 0;struct monst *shopkeeper = 0;struct obj *billobjs = 0;obfree(obj,merge) register struct obj *obj, *merge; {	free((char *) obj);}inshop(){ return(0); }shopdig(){}addtobill(){}subfrombill(){}splitbill(){}dopay(){ return(0); }paybill(){}doinvbill(){ return(0); }shkdead(){}shkcatch(){ return(0); }shk_move(){ return(0); }replshk(mtmp,mtmp2) struct monst *mtmp, *mtmp2; {}char *shkname(){ return(""); }#else QUEST#include	"hack.mfndpos.h"#include	"def.mkroom.h"#include	"def.eshk.h"#define	ESHK(mon)	((struct eshk *)(&(mon->mextra[0])))#define	NOTANGRY(mon)	mon->mpeaceful#define	ANGRY(mon)	!NOTANGRY(mon)extern char plname[], *xname();extern struct obj *o_on(), *bp_to_obj();/* Descriptor of current shopkeeper. Note that the bill need not be   per-shopkeeper, since it is valid only when in a shop. */static struct monst *shopkeeper = 0;static struct bill_x *bill;static int shlevel = 0;	/* level of this shopkeeper */       struct obj *billobjs;	/* objects on bill with bp->useup */				/* only accessed here and by save & restore */static long int total;		/* filled by addupbill() */static long int followmsg;	/* last time of follow message *//*	invariants: obj->unpaid iff onbill(obj) [unless bp->useup]		obj->quan <= bp->bquan */char shtypes[] = {	/* 8 shoptypes: 7 specialized, 1 mixed */	RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, SCROLL_SYM,	POTION_SYM, ARMOR_SYM, 0};static char *shopnam[] = {	"engagement ring", "walking cane", "antique weapon",	"delicatessen", "second hand book", "liquor",	"used armor", "assorted antiques"};char *shkname(mtmp)				/* called in do_name.c */register struct monst *mtmp;{	return(ESHK(mtmp)->shknam);}static void setpaid();shkdead(mtmp)				/* called in mon.c */register struct monst *mtmp;{	register struct eshk *eshk = ESHK(mtmp);	if(eshk->shoplevel == dlevel)		rooms[eshk->shoproom].rtype = 0;	if(mtmp == shopkeeper) {		setpaid();		shopkeeper = 0;		bill = (struct bill_x *) -1000;	/* dump core when referenced */	}}replshk(mtmp,mtmp2)register struct monst *mtmp, *mtmp2;{	if(mtmp == shopkeeper) {		shopkeeper = mtmp2;		bill = &(ESHK(shopkeeper)->bill[0]);	}}static voidsetpaid(){	/* caller has checked that shopkeeper exists */		/* either we paid or left the shop or he just died */register struct obj *obj;register struct monst *mtmp;	for(obj = invent; obj; obj = obj->nobj)		obj->unpaid = 0;	for(obj = fobj; obj; obj = obj->nobj)		obj->unpaid = 0;	for(obj = fcobj; obj; obj = obj->nobj)		obj->unpaid = 0;	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)		for(obj = mtmp->minvent; obj; obj = obj->nobj)			obj->unpaid = 0;	for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)		for(obj = mtmp->minvent; obj; obj = obj->nobj)			obj->unpaid = 0;	while(obj = billobjs){		billobjs = obj->nobj;		free((char *) obj);	}	ESHK(shopkeeper)->billct = 0;}staticaddupbill(){	/* delivers result in total */		/* caller has checked that shopkeeper exists */register ct = ESHK(shopkeeper)->billct;register struct bill_x *bp = bill;	total = 0;	while(ct--){		total += bp->price * bp->bquan;		bp++;	}}inshop(){register roomno = inroom(u.ux,u.uy);	static void findshk();	/* Did we just leave a shop? */	if(u.uinshop &&	    (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) {		if(shopkeeper) {		    if(ESHK(shopkeeper)->billct) { 			if(inroom(shopkeeper->mx, shopkeeper->my)  			    == u.uinshop - 1)	/* ab@unido */ 			    pline("Somehow you escaped the shop without paying!");			addupbill();			pline("You stole for a total worth of %ld zorkmids.",				total);			ESHK(shopkeeper)->robbed += total;			setpaid();			if((rooms[ESHK(shopkeeper)->shoproom].rtype == GENERAL)			    == (rn2(3) == 0))			    ESHK(shopkeeper)->following = 1;		    }		    shopkeeper = 0;		    shlevel = 0;		} 		u.uinshop = 0;	}	/* Did we just enter a zoo of some kind? */	if(roomno >= 0) {		register int rt = rooms[roomno].rtype;		register struct monst *mtmp;		if(rt == ZOO) {			pline("Welcome to David's treasure zoo!");		} else		if(rt == SWAMP) {			pline("It looks rather muddy down here.");		} else		if(rt == MORGUE) {			if(midnight())				pline("Go away! Go away!");			else				pline("You get an uncanny feeling ...");		} else			rt = 0;		if(rt != 0) {			rooms[roomno].rtype = 0;			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)				if(rt != ZOO || !rn2(3))					mtmp->msleep = 0;		}	}	/* Did we just enter a shop? */	if(roomno >= 0 && rooms[roomno].rtype >= 8) {	    if(shlevel != dlevel || !shopkeeper				 || ESHK(shopkeeper)->shoproom != roomno)		findshk(roomno);	    if(!shopkeeper) {		rooms[roomno].rtype = 0;		u.uinshop = 0;	    } else if(!u.uinshop){		if(!ESHK(shopkeeper)->visitct ||		    strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)){		    /* He seems to be new here */		    ESHK(shopkeeper)->visitct = 0;		    ESHK(shopkeeper)->following = 0;		    (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);		    NOTANGRY(shopkeeper) = 1;		}		if(!ESHK(shopkeeper)->following) {		    boolean box, pick;		    pline("Hello %s! Welcome%s to %s's %s shop!",			plname,			ESHK(shopkeeper)->visitct++ ? " again" : "",			shkname(shopkeeper),			shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8] );		    box = carrying(ICE_BOX);		    pick = carrying(PICK_AXE);		    if(box || pick) {			if(dochug(shopkeeper)) {				u.uinshop = 0;	/* he died moving */				return(0);			}			pline("Will you please leave your %s outside?",			    (box && pick) ? "box and pick-axe" :			    box ? "box" : "pick-axe");		    }		}		u.uinshop = roomno + 1;	    }	}	return(u.uinshop);}static voidfindshk(roomno)register roomno;{register struct monst *mtmp;	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)	    if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno			   && ESHK(mtmp)->shoplevel == dlevel) {		shopkeeper = mtmp;		bill = &(ESHK(shopkeeper)->bill[0]);		shlevel = dlevel;		if(ANGRY(shopkeeper) &&		   strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ))			NOTANGRY(shopkeeper) = 1;		/* billobjs = 0; -- this is wrong if we save in a shop */		/* (and it is harmless to have too many things in billobjs) */		return;	}	shopkeeper = 0;	shlevel = 0;	bill = (struct bill_x *) -1000;	/* dump core when referenced */}static struct bill_x *onbill(obj) register struct obj *obj; {register struct bill_x *bp;	if(!shopkeeper) return(0);	for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++)		if(bp->bo_id == obj->o_id) {			if(!obj->unpaid) pline("onbill: paid obj on bill?");			return(bp);		}	if(obj->unpaid) pline("onbill: unpaid obj not on bill?");	return(0);}/* called with two args on merge */obfree(obj,merge) register struct obj *obj, *merge; {register struct bill_x *bp = onbill(obj);register struct bill_x *bpm;	if(bp) {		if(!merge){			bp->useup = 1;			obj->unpaid = 0;	/* only for doinvbill */			obj->nobj = billobjs;			billobjs = obj;			return;		}		bpm = onbill(merge);		if(!bpm){			/* this used to be a rename */			impossible("obfree: not on bill??");			return;		} else {			/* this was a merger */			bpm->bquan += bp->bquan;			ESHK(shopkeeper)->billct--;			*bp = bill[ESHK(shopkeeper)->billct];		}	}	free((char *) obj);}staticpay(tmp,shkp)long tmp;register struct monst *shkp;{	long robbed = ESHK(shkp)->robbed;	u.ugold -= tmp;	shkp->mgold += tmp;	flags.botl = 1;	if(robbed) {		robbed -= tmp;		if(robbed < 0) robbed = 0;		ESHK(shkp)->robbed = robbed;	}}dopay(){long ltmp;register struct bill_x *bp;register struct monst *shkp;int pass, tmp;	static int dopayobj();	multi = 0;	(void) 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);}/* return 1 if paid successfully *//*        0 if not enough money *//*       -1 if object could not be found (but was paid) */staticdopayobj(bp) register struct bill_x *bp; {register struct obj *obj;long ltmp;	/* find the object on one of the lists */	obj = bp_to_obj(bp);	if(!obj) {		impossible("Shopkeeper administration out of order.");		setpaid();	/* be nice to the player */		return(0);	}	if(!obj->unpaid && !bp->useup){		impossible("Paid object on bill??");		return(1);	}	obj->unpaid = 0;	ltmp = bp->price * bp->bquan;	if(ANGRY(shopkeeper)) ltmp += ltmp/3;	if(u.ugold < ltmp){		pline("You don't have gold enough to pay %s.",			doname(obj));		obj->unpaid = 1;		return(0);	}	pay(ltmp, shopkeeper);	pline("You bought %s for %ld gold piece%s.",		doname(obj), ltmp, plur(ltmp));	if(bp->useup) {		register struct obj *otmp = billobjs;		if(obj == billobjs)			billobjs = obj->nobj;		else {			while(otmp && otmp->nobj != obj) otmp = otmp->nobj;			if(otmp) otmp->nobj = obj->nobj;			else pline("Error in shopkeeper administration.");		}		free((char *) obj);	}	return(1);}/* routine called after dying (or quitting) with nonempty bill */paybill(){	if(shlevel == dlevel && shopkeeper && ESHK(shopkeeper)->billct){		addupbill();		if(total > u.ugold){			shopkeeper->mgold += u.ugold;			u.ugold = 0;		pline("%s comes and takes all your possessions.",			Monnam(shopkeeper));		} else {			u.ugold -= total;			shopkeeper->mgold += total;	pline("%s comes and takes the %ld zorkmids you owed him.",		Monnam(shopkeeper), total);		}		setpaid();	/* in case we create bones */	}}/* find obj on one of the lists */struct obj *bp_to_obj(bp)register struct bill_x *bp;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -