#ifndef lint
static char *RCSid = "$Header: /usr/brule/guest/empire/empire/emprcs/lib/common/nstr_subs.c,v 2.1 1995/07/27 20:58:25 empire Exp $";
#endif

/*
 * nstr.c
 *
 * compile and execute the item selections
 * on sectors.
 *
 * Dave Pare, 1989
 */

#include <ctype.h>
#include "struct.h"
#include "misc.h"
#include "var.h"
#include "xy.h"
#include "sect.h"
#include "nsc.h"
#include "nat.h"
#include "match.h"
#include "file.h"
#include "player.h"

/*
 * return true if the conditions on this item
 * are all true.
 */
int
nstr_exec(conds, ncond, ptr, type)
	struct	nscstr *conds;
	register int ncond;
	caddr_t	ptr;
	int	type;
{
	register struct nscstr *nsc;
	register int op;
	register int lhs;
	register int rhs;

	for (nsc=conds; --ncond >= 0; nsc++) {
		lhs = decode(player->cnum, nsc->fld1, ptr, type);
		rhs = decode(player->cnum, nsc->fld2, ptr, type);
		op = nsc->oper;
		if ((op == '<' && lhs >= rhs) ||
		    (op == '=' && lhs != rhs) ||
		    (op == '>' && lhs <= rhs) ||
		    (op == '#' && lhs == rhs))
			return 0;
	}
	return 1;
}

int
decode(cnum, code, addr, type)
	register natid cnum;
	register long code;
	register s_char *addr;
	int	type;
{
	register int val;
	register int nsc_code;
	struct natstr *np;

	val = (code & ~NSC_MASK) & 0xffff;
	
	/* handle negative numbers properly */
	/* this assumes a binary two's complement number representation */
	if (val>=0x8000) val -= 0x10000;
	
	nsc_code = code & NSC_CMASK;
	if (nsc_code == NSC_VAR) {
		val = getvar(val, addr, type);
	} else if (nsc_code == NSC_OFF) {
		/*
		 * add offset to value
		 */
		addr += val;
		switch (code & NSC_TMASK) {
		case NSC_CHAR:
			val = *((s_char *) addr);
			break;
		case NSC_UCHAR:
			val = (int) *((unsigned char *) addr);
			break;
		case NSC_SHORT:
			val = *((short *) addr);
			break;
		case NSC_USHORT:
			val = *((u_short *) addr);
			break;
		case NSC_INT:
			val = *((int *) addr);
			break;
		case NSC_LONG:
			val = *((long *) addr);
			break;
		case NSC_XCOORD:
			val = *((short *) addr);
			np = getnatp(cnum);
			val = xrel(np, val);
			break;
		case NSC_YCOORD:
			val = *((short *) addr);
			np = getnatp(cnum);
			val = yrel(np, val);
			break;
		default:
			logerror("bad type in decode: %x!\n",
				code & NSC_TMASK);
			val = 0;
			break;
		}
	}
	if (code & NSC_ROUND)
		val = round(val, 10);
	return val;
}

s_char *
decodep(code, addr)
	register long code;
	register s_char *addr;
{
	addr = addr + ((code & ~NSC_MASK) & 0xffff);

	if ((code & NSC_TMASK) == NSC_CHARP)
		return *addr?*((s_char **)addr):"";
	return addr;
}
