192 lines · 3.1 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <thread.h>#include <draw.h> #include "map.h"#include "bt.h" #include "dat.h"#include "alg.h" enum{	LSIZE	= 20,}; int debug;int farmsg = 0;Monster *player;char *user;char *home;long turn = 0; intisyou(Monster *m){	return m == player;} intnearyou(Point p){	if(farmsg)		return 1;	return manhattan(player->pt, p) < ORTHOCOST*5;} /* * sort monsters for movement order. * player comes first, followed by monsters, * sorted by what their total move points will be * after adjusting for the ones they will gain during * mupdate. */static intmonsort(void *a, void *b){	int sa, sb;	const Monster *am, *bm;	am = a, bm = b;	sa = am->mvp + am->mvr;	sb = bm->mvp + bm->mvr; 	if(am == player)		return -1;	if(sa > sb)		return -1;	return sa < sb;} static voidmovemons(void){	Point p;	Monster *m;	Level *l;	Priq *tomove; 	tomove = priqnew(32);	l = player->l; 	/* run ai on level, for spawns etc */	bttick(l->bt, l->bs, l); 	for(p.x = 0; p.x < l->width; p.x++){		for(p.y = 0; p.y < l->height; p.y++){			if(hasflagat(l, p, Fhasmonster)){				m = tileat(l, p)->monst;				/* i don't think this is supposed to happen. */				if(m == nil)					continue;				incref(&m->ref);				priqpush(tomove, m, monsort);			}		}	} 	while((m = priqpop(tomove, monsort)) != nil){		/* it's possible the monster died in the meantime. */		if((m->flags & Mdead) == 0)			mupdate(m);		mfree(m);	} 	/* always give the player a move if dead, otherwise the ui breaks */	if(player->flags & Mdead)		mupdate(player); 	priqfree(tomove);} static voidusage(void){	fprint(2, "usage: %s [-d]\n", argv0);	threadexitsall("usage");} voidthreadmain(int argc, char *argv[]){	unsigned long seed;	Tile *t;	Level *level; 	seed = -1; 	ARGBEGIN{	case 'd':		debug++;		break;	case 'S':		seed = atoi(EARGF(usage()));		break;	default:		usage();	}ARGEND 	//#include <pool.h>	//mainmem->flags = POOL_PARANOIA|POOL_ANTAGONISM; 	if(seed == -1)		seed = truerand();	srand(seed); 	if(debug)		fprint(2, "seed %lud\n", seed); 	quotefmtinstall(); 	user = getenv("user");	home = getenv("home"); 	uiinit(argv0);	aiinit();	linit(); 	if(!itemdbopen("/lib/hack9/item.ndb"))		if(!itemdbopen("item.ndb"))			sysfatal("itemdbopen: %r"); 	if(!monstdbopen("/lib/hack9/monster.ndb"))		if(!monstdbopen("monster.ndb"))			sysfatal("monstdbopen: %r"); 	/* initial level */	if((level = lgenerate(nrand(LSIZE)+LSIZE, nrand(LSIZE)+LSIZE, debug?0:nrand(3)+1)) == nil)		sysfatal("genlevel: %r"); 	/* the player */	player = mbyname("wizard");	if(player == nil)		sysfatal("monst: %r"); 	/* don't delete when we die so ui works */	incref(&player->ref); 	player->l = level;	player->pt = level->up; 	maddinv(player, ibyname("dagger")); 	t = tileat(level, player->pt);	t->unit = player->md->tile;	t->monst = player;	setflagat(level, player->pt, Fhasmonster); 	player->bt = btroot(btleaf("input", uibt, nil));	player->bs = btstatenew(player->bt); 	if(debug > 0){		player->hp = 500;		player->maxhp = 500;	}		uiredraw(0); 	for(;;){			turn++;			movemons();	}}