/*
 * play.c - game player
 */

#include <stdio.h>
#include "config.h"
#include "game.h"

FILE *fp;
int dfd;
char shohid;
char backsho;
char frv;
char nmf;
char ftg;
char hgp;
char *idus;
char gfn[40], sfn[40], sfnt[40], sfnb[40];
char command[100];
char w1[4], w2[4];
char *dirstr[6];

char *byp(s)
char *s;
 {
    while (*s && isspace(*s))
      s++;
    return(s);
 }

char *unbyp(s)
char *s;
 {
    while (*s && !isspace(*s))
      s++;
    return(s);
 }

char *getword(wp, cp)
char *wp;
char *cp;
 {
    int i;
    char *rv;

    rv = unbyp(cp = byp(cp));
    for (i = 0; i < 4 && *cp && !isspace(*cp); i++)
      *wp++ = *cp++;
    while (i++ < 4)
      *wp++ = 0;
    return(rv);
 }

struct _item_ *findiloc(i, w)
 {
    struct _item_ *itemp;

    return((((itemp = &items[i])->_iloc & 0xff) == (w & 0xff) &&
					(shohid || w > 10 || w < 2 ||
					!(itemp->_iflags & HIDDEN)))
					? itemp : NULL);
 }

main(n, a)
char **a;
 {
    int i;

    printf("PLAY  V%d.%d%c\n\n", MAJOR, MINOR, REV);
    if (n != 2)
     {
	printf("Usage: play FILE\n");
	exit(0);
     }
    sprintf(gfn, "%s.scn", a[1]);
    sprintf(sfn, "%s.sav", a[1]);
    sprintf(sfnt, TMPFMT, a[1]);
    sprintf(sfnb, "%s.bak", a[1]);
    idus = "\nI don't understand\n";
    if ((fp = fopen(gfn, RBIN)) == NULL || (dfd = OPEN(gfn)) == ERROR)
     {
	printf("Can't find %s\n", gfn);
	exit(0);
     }
    input(FULL);
    fclose(fp);
    if ((fp = fopen(sfn, RBIN)) != NULL)
     {
	input(SAVE);
	fclose(fp);
     }
    dirstr[0] = "north";
    dirstr[1] = "south";
    dirstr[2] = "east";
    dirstr[3] = "west";
    dirstr[4] = "up";
    dirstr[5] = "down";
    hgp = ftg = shohid = FALSE;
    initrnd();
    for (;;)
     {
	if (start)
	 {
	    lplay(start);
	    start = 0;
	 }
	if ((locs[uloc]._lflags & DARK) && (!lampon ||
				((i = items[1]._iloc & 0xff) != 0xff &&
				i != uloc)))
	  printf("\nYou can't see anything: it's too dark\n");
	else
	 {
	    swhere();
	    if ((locs[uloc]._lflags & SEEN) == 0)
	     {
		locs[uloc]._lflags |= SEEN;
		if (i = locs[uloc]._longdesc)
		  lplay(i);
	     }
	    spass();
	    sitems(uloc, "You can see:", NULL);
	    sguard();
	 }
	backsho = shohid;
	shohid = FALSE;
	do
	 {
	    prompt("\n-> ");
	    gets(command);
	    lower(command);
	    getword(w2, getword(w1, command));
	 } while(w1[0] == 0);
	if (wordcmp(w1, "go") || wordcmp(w1, "say"))
	 {
	    getword(w1, w2);
	    w2[0] = 0;
	 }
	if (w2[0] == 0 && w1[1] == 0 && (i = inchr("nsewud", w1[0])) != ERROR)
	  getword(w1, dirstr[i]);
	nmf = FALSE;
	dofx(frv = findphr(findword(w1), findword(w2)));
	if (!frv)
	 {
	    if ((i = finddir(w1)) != ERROR)
	      move(i);
	    else if (wordprf(w1, "wait", 2))
	      move(ERROR);
	    else if (wordprf(w1, "take", 2))
	      take(w2);
	    else if (wordprf(w1, "drop", 2))
	      drop(w2);
	    else if (wordprf(w1, "exam", 2))
	      exam(w2);
	    else if (wordprf(w1, "look", 2))
	      look();
	    else if (wordprf(w1, "sear", 2))
	      search();
	    else if (wordprf(w1, "scor", 2))
	     {
		showscore(FALSE);
		nmoves--;
		nmf = TRUE;
	     }
	    else if (wordprf(w1, "inve", 1))
	      sitems(-1, "You are carrying:", "You aren't carrying anything");
	    else if (wordcmp(w1, "on"))
	      setlamp(TRUE);
	    else if (wordcmp(w1, "off"))
	      setlamp(FALSE);
	    else if (wordcmp(w1, "save"))
	     {
		quit(TRUE);
		nmoves--;
		nmf = TRUE;
	     }
	    else if (wordcmp(w1, "quit"))
	     {
	        quit(FALSE);
		nmoves--;
		nmf = TRUE;
	     }
	    else
	     {
		printf(idus);
		nmoves--;
		nmf = TRUE;
	     }
	 }
	chk3();
	nmoves++;
	if (!nmf && guards && !(pflags & (GUARD | NOGUARD)) &&
				rnd(100) < (hgp ? gdprob * 3 : gdprob))
	 {
	    pflags |= GUARD;
	    guards--;
	    ftg = TRUE;
	 }
	hgp = FALSE;
     }
 }

swhere()
 {
    int i;
    int k;
    int l;
    char lstr[256];

    SEEK(dfd, locs[uloc]._ldesc + offset);
    read(dfd, lstr, 256 / RWBSIZ);
    for (i = l = 0; i < 256 && (k = lstr[i]); i++)
     {
	if (i == 128)
	  l = 0;
	lstr[i] = (lstr[i] ^ l) & 0x7f;
	l = k;
     }
    printf("\nYou%s%s are %s\n", pflags & HASASST ? " and " : "",
					pflags & HASASST ? asst : "", lstr);
 }

spass()
 {
    int k;
    struct _loc_ *locp;

    k = sways("A passage leads", "Passages lead", locp = &locs[uloc], 0, 0);
    k = sways("A door leads", "Doors lead", locp, 0x0100, k); 
    sways("Stairs go", "Stairs go", locp, 0x0200, k);
 }

sways(s1, s2, locp, m, k)
char *s1, *s2;
struct _loc_ *locp;
 {
    int i;
    int j;

    for (i = j = 0; i < 6; i++)
      if (locp->_ways[i] && (locp->_ways[i] & 0xff00) == m)
	j++;
    if (j == 0)
      return(k);
    if (k == 0)
      nl();
    printf(j == 1 ? s1 : s2);
    for (i = k = 0; i < 6; i++)
     {
	if (locp->_ways[i] && (locp->_ways[i] & 0xff00) == m)
	 {
	    if (++k == j && j != 1)
	      printf(" and");
	    printf(" %s", dirstr[i]);
	    if (k < j - 1)
	      putchar(',');
	 }
     }
    nl();
    return(1);
 }

sitems(w, s, t)
char *s;
char *t;
 {
    int i;
    struct _item_ *itemp;

    for (i = 0; i < MAXIITM; i++)
      if (itemp = findiloc(i, w))
	break;
    if (i < MAXIITM)
     {
	printf("\n%s\n", s);
	for (i = 0; i < MAXIITM; i++)
	  if (itemp = findiloc(i, w))
	    printf("%s\n", strings[itemp->_idesc & 0xff]);
     }
    else if (t)
      printf("\n%s\n", t);
 }

sguard()
 {
    if ((pflags & (GUARD | NOGUARD)) == GUARD && (uloc < 5 || uloc > 15))
     {
	printf("\n%s\n", guard);
	if (!nmf && !ftg)
	  dofx(gdact);
	ftg = FALSE;
     }
 }

move(i)
 {
    int old;
    int mold;
    int mnew;
    struct _move_ *movep;
    char *fpds;
    
    fpds = "\nYou fell into a pit and died\n";
    old = uloc;
    if (i != ERROR)
     {
	if (mnew = locs[uloc]._ways[i])
	 {
	    if (mnew >> 8 == 4)
	     {
		if ((locs[uloc]._lflags & DARK) && (!lampon ||
					((i = items[1]._iloc & 0xff) != 0xff &&
					i != uloc)))
		 {
		    printf(fpds);
		    badend();
		 }
		printf("\n%s\n", strings[mnew & 0xff]);
	     }
	    else
	     {
		if ((locs[uloc]._lflags & DARK) && (!lampon ||
				((i = items[1]._iloc & 0xff) != 0xff &&
				i != uloc)) && rnd(10) == 3)
		 {
		    printf(fpds);
		    badend();
		 }
		loc = mnew & 0xff;
	     }
	 }
	else
	 {
	    if ((locs[uloc]._lflags & DARK) && (!lampon ||
					((i = items[1]._iloc & 0xff) != 0xff &&
					i != uloc)))
	     {
		printf(fpds);
		badend();
	     }
	    printf("\nYou can't go that way\n");
	    return;
	 }
     }
    else
     {
	printf("\nTime passes .....\n");
	hgp = TRUE;
     }
    for (i = 0; i < MAXMOVE; i++)
      if (((mold = (movep = &moves[i])->_mfrom & 0xff) == old ||
				mold == 0xff) &&
				((mnew = movep->_mto & 0xff) == uloc ||
				mnew == 0xff))
	dofx(movep->_mfx);
    score += locs[uloc]._lscore;
    locs[uloc]._lscore = 0;
 }

take(w)
char *w;
 {
    int i;
    int j;
    int n;
    int c;
    struct _item_ *itemp;

    n = j = 0;
    c = curwt();
    if (strcmp(w, "all") == 0)
     {
	for (i = 0; i < MAXIITM; i++)
	 {
	    if (((itemp = &items[i])->_iloc & 0xff) == uloc &&
				(uloc > 10 || uloc == 1 ||
				backsho || !(itemp->_iflags & HIDDEN)) &&
				!(itemp->_iflags & NOTALL) &&
				(itemp->_weight & 0xff) != 0xff)
	     {
		if (c + itemp->_weight > 100)
		 {
		    if (n == 0)
		     {
			n = 1;
			printf(
"\nYou can't take everything, it's too much to carry\n");
		     }
		 }
		else
		 {
		    score += itemp->_iscore;
		    itemp->_iscore = 0;
		    j = itemp->_iloc = -1;
		    c += itemp->_weight;
		 }
	     }
	 }
     }
    else if ((i = finditem(w)) != ERROR && (itemp = &items[i])->_iloc == uloc)
     {
	if (c + itemp->_weight > 100)
	 {
	    n = 1;
	    printf("\nYou can't take it, it's too heavy\n");
	 }
	else
	 {
	    score += itemp->_iscore;
	    itemp->_iscore = 0;
	    j = itemp->_iloc = -1;
	 }
     }
    if (n == 0)
     {
	if (j)
	  printf("\nOK\n");
	else
	  printf("\nTake what?\n");
     }
 }

drop(w)
char *w;
 {
    int i;
    int j;
    struct _item_ *itemp;

    j = 0;
    if (strcmp(w, "all") == 0)
     {
	for (i = 0; i < MAXIITM; i++)
	 {
	    if (((itemp = &items[i])->_iloc & 0xff) == 0xff)
	      j = itemp->_iloc = uloc;
	 }
     }
    else if ((i = finditem(w)) != ERROR &&
				((itemp = &items[i])->_iloc & 0xff) == 0xff)
      j = itemp->_iloc = uloc;
    if (j)
      printf("\nOK\n");
    else
      printf("\nDrop what?\n");
 }

exam(w)
char *w;
 {
    int i;
    struct _item_ *itemp;

    if (w[0] == 0)
     {
	printf("\nexamine what?\n");
	return;
     }
    if ((i = finditem(w)) != ERROR &&
				((itemp = &items[i])->_iloc & 0xff) == 0xff)
     {
	if (itemp->_exam)
	  printf("\n%s\n", strings[itemp->_exam & 0xff]);
	else
	  printf("\nYou don't see anything special\n");
     }
    else
      printf("\nYou don't have one to examine\n");
 }

look()
 {
    locs[uloc]._lflags &= ~SEEN;
 }

search()
 {
    shohid = TRUE;
 }

setlamp(val)
 {
    if ((items[1]._iloc & 0xff) != 0xff)
      printf("\nYou don't have anything to turn %s\n", val ? "on" : "off");
    else
     {
	lampon = val;
	printf("\nOK\n");
     }
 }

showscore(type)
 {
    printf("\nYour %sscore %s %d", type ? "final " : "", type ? "was" : "is",
								score);
    if (maxscor)
      printf(" out of %d", maxscor);
    printf(", after %d turns\n", nmoves);
 }

quit(save)
 {
    char ans[40];

    printf("Are you sure? ");
    fflush(stdout);
    gets(ans);
    if ((ans[0] | 0x20) == 'y')
     {
	if (save)
	 {
	    if ((fp = fopen(sfnt, WBIN)) == NULL)
	     {
		printf("Error: Can't write %s\n", sfnt);
		return;
	     }
	    output();
	    fclose(fp);
	    unlink(sfnb);
	    rename(sfn, sfnb);
	    rename(sfnt, sfn);
	 }
	exit();
     }
 }

lplay(num)
 {
    int i;
    int k;
    int l;
    char buff[128];

    nl();
    SEEK(dfd, num + offset);
    while (read(dfd, buff, 128 / RWBSIZ) == 128 / RWBSIZ)
     {
	for (i = l = 0; i < 128 && (k = buff[i]); i++)
	 {
	    putchar((buff[i] ^ l) & 0x7f);
	    l = k;
	 }
	if (k == 0)
	  break;
     }
    nl();
 }

input(type)
 {
    int i;
    int j;
    int k;
    int l;
    struct _loc_ *locp;
    struct _item_ *itemp;
    struct _fx_ *fxp;
    struct _move_ *movep;
    struct _phrase_ *phrp;
    char str[160];

    if ((getc(fp) & 0xff) != 0x1a || (getc(fp) & 0xff) != 0xe5 ||
		(getc(fp) & 0xff) != 0xff || (getc(fp) & 0xff) != 0x64)
     {
	printf("%s file is corrupted\n", type == FULL ? "Game" : "Save");
	exit(0);
     }
    version = getww(fp);
    nmoves = getww(fp);
    score = getww(fp);
    start = getww(fp);
    good = getww(fp);
    bad = getww(fp);
    gdact = getww(fp);
    maxscor = getww(fp);
    offset = getww(fp);
    for (i = 0; i < 40; i++)
      asst[i] = getc(fp);
    for (i = 0; i < 60; i++)
      guard[i] = getc(fp);
    pflags = getc(fp);
    guards = getc(fp);
    gdprob = getc(fp);
    loc = getc(fp);
    lampon = getc(fp);
    for (i = 0, locp = locs; i < MAXLOC; i++, locp++)
     {
	locp->_ldesc = getww(fp);
	locp->_lflags = getc(fp);
	locp->_longdesc = getww(fp);
	locp->_lscore = getc(fp);
	for (j = 0; j < 6; j++)
	  locp->_ways[j] = getww(fp);
     }
    for (i = 0, itemp = items; i < MAXITEM; i++, itemp++)
     {
	itemp->_idesc = getc(fp);
	itemp->_iflags = getc(fp);
	itemp->_weight = getc(fp);
	itemp->_iloc = getc(fp);
	itemp->_exam = getc(fp);
	itemp->_iscore = getc(fp);
	itemp->_iwords[0] = getc(fp);
	itemp->_iwords[1] = getc(fp);
     }
    for (i = 0; i < MAXVAR; i++)
      vars[i] = getc(fp);
    if (type == FULL)
     {
	for (i = 0, fxp = fxs; i < MAXFX; i++, fxp++)
	 {
	    fxp->_ftype = getww(fp);
	    fxp->_fa1 = getww(fp);
	    fxp->_fa2 = getww(fp);
	 }
	for (i = 0, movep = moves; i < MAXMOVE; i++, movep++)
	 {
	    movep->_mfrom = getc(fp);
	    movep->_mto = getc(fp);
	    movep->_mfx = getww(fp);
	 }
	for (i = 0, phrp = phrases; i < MAXPHR; i++, phrp++)
	 {
	    phrp->_pw1 = getc(fp);
	    phrp->_pw2 = getc(fp);
	    phrp->_pfx = getww(fp);
	 }
	for (i = 0; i < MAXWORD; i++)
	  for (j = 0; j < 4; j++)
	    words[i][j] = getc(fp);
	for (i = 0; i < MAXSTR; i++)
	 {
	    for (j = l = 0; k = str[j] = getc(fp); j++)
	     {
		str[j] = (str[j] ^ l) & 0x7f;
		l = k;
	     }
	    if (j)
	     {
		if (strings[i] = alloc(j + 2))
		  strcpy(strings[i], str);
		else
		 {
		    printf("Out of memory\n");
		    exit();
		 }
	     }
	 }
	for (i = 0; i < MAXWORD; i++)
	 {
	    if (words[i][0])
	     {
		for (j = l = 0; j < 4; j++)
		 {
		    k = words[i][j];
		    words[i][j] = (words[i][j] ^ l) & 0x7f;
		    l = k;
		 }
	     }
	 }
     }
    for (j = l = 0; k = asst[j]; j++)
     {
	asst[j] = (asst[j] ^ l) & 0x7f;
	l = k;
     }
    for (j = l = 0; k = guard[j]; j++)
     {
	guard[j] = (guard[j] ^ l) & 0x7f;
	l = k;
     }
    if ((version & 0xf000) != MAJOR << 12)
     {
	printf("Bad version number\n");
	exit(0);
     }
 }

output()
 {
    int i;
    int j;
    struct _loc_ *locp;
    struct _item_ *itemp;

    for (i = j = 0; asst[i]; i++)
      j = asst[i] = (asst[i] ^ j) | 0x80;
    for (i = j = 0; guard[i]; i++)
      j = guard[i] = (guard[i] ^ j) | 0x80;
    putc(0x1a, fp);
    putc(0xe5, fp);
    putc(0xff, fp);
    putc(0x64, fp);
    putww(version, fp);
    putww(nmoves, fp);
    putww(score, fp);
    putww(start, fp);
    putww(good, fp);
    putww(bad, fp);
    putww(gdact, fp);
    putww(maxscor, fp);
    putww(offset, fp);
    for (i = 0; i < 40; i++)
      putc(asst[i], fp);
    for (i = 0; i < 60; i++)
      putc(guard[i], fp);
    putc(pflags, fp);
    putc(guards, fp);
    putc(gdprob, fp);
    putc(loc, fp);
    putc(lampon, fp);
    for (i = 0, locp = locs; i < MAXLOC; i++, locp++)
     {
	putww(locp->_ldesc, fp);
	putc(locp->_lflags, fp);
	putww(locp->_longdesc, fp);
	putc(locp->_lscore, fp);
	for (j = 0; j < 6; j++)
	  putww(locp->_ways[j], fp);
     }
    for (i = 0, itemp = items; i < MAXITEM; i++, itemp++)
     {
	putc(itemp->_idesc, fp);
	putc(itemp->_iflags, fp);
	putc(itemp->_weight, fp);
	putc(itemp->_iloc, fp);
	putc(itemp->_exam, fp);
	putc(itemp->_iscore, fp);
	putc(itemp->_iwords[0], fp);
	putc(itemp->_iwords[1], fp);
     }
    for (i = 0; i < MAXVAR; i++)
      putc(vars[i], fp);
 }

getww(fp)
FILE *fp;
 {
    int i;

    i = getc(fp);
    return(i + (getc(fp) << 8));
 }

putww(w, fp)
FILE *fp;
 {
    putc(w, fp);
    putc(w >> 8, fp);
 }

wordcmp(s, t)
char *s, *t;
 {
    return(!strncmp(s, t, 4));
 }

wordprf(s, t, l)
char *s, *t;
 {
    int i;

    for (i = 0; i < 4 && *s; i++)
      if (*s++ != *t++)
	return(FALSE);
    return(i >= l);
 }

dofx(num)
 {
    struct _fx_ *fxp;

    if (num == 0)
      return(FALSE);
    if (num > MAXFX)
      return(TRUE);
    switch ((fxp = &fxs[num])->_ftype)
     {
	case FTRUE:
	case FIDLE:
	  return(TRUE);
	case FCH:
	  return (dofx(fxp->_fa1) || dofx(fxp->_fa2));
	case FTA:
	 {
	    if (dofx(fxp->_fa1))
	     {
		dofx(fxp->_fa2);
		return(TRUE);
	     }
	    return(FALSE);
	 }
	case FTT:
	  return(dotest(fxp->_fa1) && (fxp->_fa2 == 0 || dofx(fxp->_fa2)));
	case FAA:
	 {
	    dofx(fxp->_fa2);
	    doact(fxp->_fa1);
	    return(TRUE);
	 }
     }
 }

dotest(tnum)
 {
    int v, c, n;

    switch ((tnum >> 14) & 3)
     {
	case 0:
	  return(TRUE);
	case 1:
	 {
	    if (tnum & 0x2000)
	      return(rnd(100) < (tnum & 127));
	    else
	     {
		switch (tnum & 3)
		 {
		    case 0:
		      return(pflags & HASASST);
		    case 1:
		      return(!(pflags & HASASST));
		    case 2:
		      return((pflags & (GUARD | NOGUARD)) == GUARD);
		    case 3:
		      return((pflags & (GUARD | NOGUARD)) != GUARD);
		 }
	     }
	 }
	break;
	case 2:
	 {
	    v = (tnum >> 7) & 31;
	    n = tnum & 127;
	    switch ((tnum >> 12) & 3)
	     {
		case 0:
		  return(vars[v] == n);
		case 1:
		  return(vars[v] != n);
		case 2:
		  return(vars[v] < n);
		case 3:
		  return(vars[v] > n);
	     }
	 }
	break;
	case 3:
	 {
	    v = tnum >> 7 & 63;
	    n = tnum & 127;
	    if (n == (-3 & 63))
	      n = uloc;
	    if (tnum & 0x2000)
	      return(((v == (-1 & 63)) ? uloc : (items[v]._iloc & 127)) != n);
	    else
	      return(((v == (-1 & 63)) ? uloc : (items[v]._iloc & 127)) == n);
	 }
	break;
     }
 }

doact(anum)
 {
    int v;
    int n;

    switch ((anum >> 14) & 3)
     {
	case 0:
	break;
	case 1:
	 {
	    switch ((anum >> 12) & 3)
	     {
		case 0:
		  memcpy(&items[(anum >> 6) & 63], &items[anum & 63],
							sizeof(items[0]));
		break;
		case 1:
		 {
		    switch (anum & 15)
		     {
			case 0:
			  pflags |= HASASST;
			break;
			case 1:
			  pflags &= ~HASASST;
			break;
			case 2:
			  pflags &= ~NOGUARD;
			break;
			case 3:
			  pflags |= NOGUARD;
			break;
			case 4:
			  pflags &= ~(NOGUARD | GUARD);
			break;
			case 5:
			  goodend();
			break;
			case 6:
			  badend();
			break;
			case 7:
			  printf("\nNothing happens\n");
			break;
			case 8:
			  printf(idus);
			break;
			case 9:
			  frv = FALSE;
			break;
		     }
		 }
		break;
		case 2:
		 {
		    if (anum & (1 << 11))
		      loc = anum & 127;
		    else
		      score += anum & 127;
		 }
		break;
		case 3:
		  printf("\n%s\n", strings[anum & 255]);
		break;
	     }
	 }
	break;
	case 2:
	 {
	    v = (anum >> 7) & 31;
	    n = anum & 127;
	    switch ((anum >> 12) & 3)
	     {
		case 0:
		  vars[v] = n;
		break;
		case 1:
		  vars[v] += n;
		break;
		case 2:
		  vars[v] -= n;
		break;
	     }
	 }
	break;
	case 3:
	  memcpy(&locs[(anum >> 7) & 127], &locs[anum & 127],
							sizeof(locs[0]));
	break;
     }
 }

chk3()
 {
    int i;
    struct _item_ *itemp;

    for (i = 0; i < MAXIITM; i++)
      if (((itemp = &items[i])->_iloc & 0xff) == (-3 & 0xff))
	itemp->_iloc = uloc;
 }

curwt()
 {
    int i;
    int w;
    struct _item_ *itemp;

    for (i = w = 0; i < MAXIITM; i++)
      if (((itemp = &items[i])->_iloc & 0xff) == 0xff)
	w += itemp->_weight & 0xff;
    return(w);
 }

findphr(wv1, wv2)
 {
    int i;
    struct _phrase_ *phrp;

    if (wv1 == ERROR && wv2 == ERROR)
      return(0);
    for (i = 0; i < MAXPHR; i++)
      if (((phrp = &phrases[i])->_pw1 & 0xff) == wv1 &&
						(phrp->_pw2 & 0xff) == wv2)
	return(phrp->_pfx);
    return(0);
 }

findword(w)
char *w;
 {
    int i;
    
    if (w[0] == '\0')
      return(0);
    for (i = 0; i < MAXWORD; i++)
      if (wordcmp(words[i], w))
	return(i);
    return(ERROR);
 }

finddir(w)
char *w;
 {
    int i;

    for (i = 0; i < 6; i++)
      if (wordcmp(w, dirstr[i]))
	return(i);
    return(ERROR);
 }

finditem(w)
char *w;
 {
    int i;
    int j;
    
    if ((i = findword(w)) == ERROR || i == 0)
      return(ERROR);
    for (j = 0; j < MAXIITM; j++)
      if ((items[j]._iwords[0] & 0xff) == i ||
					(items[j]._iwords[1] & 0xff) == i)
	return(j);
    return(ERROR);
 }

goodend()
 {
    lplay(good);
    showscore(TRUE);
    exit(0);
 }

badend()
 {
    lplay(bad);
    showscore(TRUE);
    exit(0);
 }

lower(s)
char *s;
 {
    while (*s)
     {
	*s = (isupper(*s) ? tolower(*s) : *s);
	s++;
     }
 }

inchr(s, c)
char *s;
 {
    int i;

    for (i = 0; *s; i++, s++)
      if (*s == c)
	return(i);
    return(ERROR);
 }

memcpy(s, t, n)
char *s, *t;
 {
    while (n--)
      *s++ = *t++;
 }

nl()
 {
    putchar('\n');
 }

puts(s)
char *s;
 {
    printf(s);
 }
