#define PARSE
#include "dink_sym.h"
#include "dink_glb.h"
#include <string.h>
 
void parse()
/*********************************************************/
/*                                                       */
/*      --- English Language Parsing Subroutine ---      */
/*                                                       */
/*  This subroutine parses a sentence of up to nineteen  */
/*  words and decodes the words into integers and passes */
/*  a twenty element vector back to the calling          */
/*  program.  The digit 0, implies an unused word.  The  */
/*  digit -1 (V_LINE_END), indicates end of sentence.    */
/*                                                       */
/*      Program by Gary A. Allen, Jr.   5 March 1990     */
/*        (c) Copywrite 1990 by Gary A. Allen, Jr.       */
/*                                                       */
/*********************************************************/
{
#ifdef __TURBOC__ 
char getche(void) ;
void purge(int, int*) ;
#endif

register int i, j ;
int m, n, j_point, jacc, i_ws, sw_adverb, sw_purge, j_purge, sw_punct ;
int sw_movement, sw_adverb_fnd ;
int j_old = 0 ; /* this is to keep Lint happy */
/* a sentence can have 19 words of 15 letters */ 
char words[20][15], word[15] ;
char letter ;

/* flush the "sent vector" */
for (i=0; i<=19; i++) sent[i]=0 ;

/* flush the tag vector */
for (i=0; i<= tag_max; i++) tag[i] = FALSE ;

/* Parse and load in the words */
input:
sw_punct = FALSE ;
for (i=0; i <= 18; i++) {
	for (j=0; j <= 14; j++) {
#ifndef __TURBOC__
		letter = getchar() ;	
#endif

#ifdef __TURBOC__
		letter = getche() ;	
#endif

		switch (letter) {
			case '\n':
			case 13 :
				if ((i == 0) && (j == 0)) goto input ;
				words[i][j] = '\0' ;  
				goto decode; 

			case 8:
				if (sw_punct) {
					if (--i < 0) i = 0 ;
					j = j_old ;
					sw_punct = FALSE ;
				}
				else if (--j < 0) j = 0 ;
				--j ;
				continue ;

			case '\"':
			case ' ':
			case ',':
			case '.':
			case ';':
			case ':':
			case '?':
			case '!':
			case '&':
			case '{':
			case '}':
			case '[':
			case ']':
			case ')':
			case '(':
			case '\'':
			case '`':
			case '\t':
				words[i][j] = '\0' ;  
				sw_punct = TRUE ;
				j_old = j ;
				break;

			default:
				words[i][j] = letter ;
				sw_punct = FALSE ;
				continue ;
		}
		break ;
	}
	if (j > 14) {
printf("\nYou're saying nonsense! Type the sentence again. \n");
		break ;
	}
	if (j == 0) i-- ;
}
if (i > 18) 
printf ("\nYour sentence is too long. Type something shorter! \n") ;

#ifndef __TURBOC__
/* Purge the input buffer */
	for (;;) if ('\n' == getchar()) break ;
goto input;
/* decode the words from the known vocabulary */
decode:
#endif

#ifdef __TURBOC__
goto input;
/* decode the words from the known vocabulary */
decode:
printf("\n") ;
#endif

m=i ;
jacc=0;
for (i=0; i<=m; i++) {
	for (j=0; j<=14; j++) {
		word[j] = words[i][j] ; 
	}
	for (j=0; j<=letmax; j++) {
		n = strcmp (word,vocab[j]);
		if (n == 0) {
			if ((j>9)&&(j<20)) j -= 10;
			sent[jacc++]=j+1 ;
			break; 
		}
	}
}

if (jacc == 0) {
	printf ("Nothing you said was understandable! Try again. \n");
	goto input; 
}
 
/* mark last word */
sent[jacc] = V_LINE_END ;
 
/* Check to see if this is a simple move command */
if (sent[0] <= 10) {
	tag[V_MOVE] = TRUE ;
	tag[V_DIRECTION] = TRUE ;
	verb = sent[0] ;
	return ; 
}
 
/* adjective and "in/out" preposition scan */
sw_purge = FALSE ;
for (j = 0; j <= jacc-1; j++) {

	/* check for adjectives*/
	for (i = 0; i <= adj_max; i++) {
		if (sent[j] == adjective[i][Aj_adj]) {

		/* does a noun have to be ignored ? */
		if (adjective[i][Aj_adj_cmd] == F_ignore) {
		if (adjective[i][Aj_trig_noun] != sent[j+1]) break ;
		}

		/* does a noun have to be replaced? */
		if (adjective[i][Aj_adj_cmd] == F_replace) {
			if (adjective[i][Aj_trig_noun] == sent[j+1]) {
			sent[j+1] = adjective[i][Aj_act_noun] ;
			}
		}
		sw_purge = TRUE ;
		j_purge = j ;
		}
	}
}

/* purge processed adjective from sentence */
if (sw_purge) purge(j_purge, &jacc) ;
 
/* Verb grammer check */
/* see if the sentence is of a command sentax */
for (i = 0; i <= verb_max; i++) {
	if (sent[0] == verb_table[i]) goto synonym ;
}
 
/* the first word is --not-- a verb, so one must be swapped in */
if (jacc != 1) for (j = 1; j <= jacc-1; j++) {
	/* Check to see if the word is a move command */
	if (sent[j] <= 10) {
		tag[V_MOVE] = TRUE ;
		i_ws = sent[0] ;
		sent[0] = sent[j] ;
		sent[j] = i_ws ;
		goto synonym ;
	}
	/* if not a move command then check the verb table */
	for (i = 0; i <= verb_max; i++) {
		if (sent[j] == verb_table[i]) {
			i_ws = sent[0] ;
			sent[0] = sent[j] ;
			sent[j] = i_ws ;
			goto synonym ;
		}
	}
}

/* Check to see if this is a "question" sentence */
for (i = 0; i <= quest_max; i++) {
	if (sent[0] == quest[i]) {
		/* shift the sentence over and load in "question" */ 
		for (j = jacc; j >= 0; j--) sent[j+1] = sent[j] ;
		sent[0] = V_QUESTION ;
		tag[V_QUESTION] = TRUE ; 
		if (++jacc == 2) {
		/* Sentence is a one word command */
			tag[V_VERB_ONLY] = TRUE ;
			tag[sent[1]] = TRUE ;
			verb = V_QUESTION ;
			return ;
		}
		goto synonym ;
	} 
}

/* Verb error routine */
printf ("If there was a verb in that sentence, I didn't understand ") ;
printf ("it.\n") ;
goto input ;

synonym:
/* prescan for verb connected movement commands */
switch(sent[0]) { 
case V_go:
case V_move:
case V_walk:
case V_run:
case V_jump:
case V_bop:
case V_hop:
case V_stroll:
case V_saunter:
case V_swagger:
	sw_movement = TRUE ;
	break ;
default:
	sw_movement = FALSE ;
}

/* adverb scan, sent[0] is the verb */
sw_adverb = FALSE ;
sw_adverb_fnd = FALSE ;
for (i = 0; i <= adv_max; i++) {
	for (j = 1; j <= jacc-1; j++) {
		/* see if this is an adverb */
		if (sent[j] == adverb[i][Av_adv]) {
			j_point = j ;
			sw_adverb = TRUE ;

			/* does the sentence have the companion verb? */
			if (adverb[i][Av_verb_old] == sent[0]) {
				sent[0] = adverb[i][Av_verb_new] ;
				sw_adverb = FALSE ;
				sw_adverb_fnd = TRUE ;

			/* purge processed adverb from sentence */
				purge(j, &jacc) ;
			}
		}
	}
}

/* purge unprocessed adverb from sentence */
if (sw_adverb && (!sw_movement)) purge(j_point, &jacc) ;
 
/* scan the sentence for the movement direction */
if ((!sw_adverb_fnd) && sw_movement) {
	for (j = 0; j <= jacc-1; j++) {
		if (sent[j] <= 10) {
			tag[V_MOVE] = TRUE ;
			tag[V_DIRECTION] = TRUE ;
			verb = sent[j] ;
			return ;
		}
		if (sent[j] == V_LINE_END) break ;
	}
	printf("Where to?  In what direction?\n") ;
	goto input ;
} 

tag[sent[0]] = TRUE ;  /* activate the tag for the verb */
 
if (jacc == 1) {
/* Sentence is a one word command */
	tag[V_VERB_ONLY] = TRUE ;
	verb = sent[0] ;
	if (sent[0] <= 4) return ; /* first 5 elements are reserved */
	return ;
}

/* Load the "tag" matrix for detected words and synonyms */
for (j=1; j <= 19; j++) {
	if (sent[j] == V_LINE_END) break ;
	if (sent[j] <= 10) tag[V_DIRECTION] = TRUE ;
	if (sent[j] <= 4) continue ; /* first 5 elements are reserved */
	tag[sent[j]] = TRUE ;  /* activate an element for each word */

	/* Deal with synonym nouns */
	switch(sent[j]) {

	case V_automatic:
	case V_AUTO:
		tag[V_auto] = TRUE ;
		continue ;
 
	case V_bar:
		tag[V_gold] = TRUE ;
		continue ;

	case V_beer:
	case V_fourex:
	case V_Fourex:
		tag[V_can] = TRUE ;
		continue ;

	case V_cockroaches:
		tag[V_PLURAL] = TRUE ;
		tag[V_cockroach] = TRUE ;
		continue ;
 
	case V_diamond:
		tag[V_ring] = TRUE ;
		continue ;
 
	case V_doormat:
		tag[V_mat] = TRUE ;
		continue ;

	case V_drop:
		tag[V_bear] = TRUE ;
		continue ;

	case V_everything:
		tag[V_all] = TRUE ;
		continue ;

	case V_lager:
		tag[V_bottle] = TRUE ;
		continue ;

	case V_fuse:
		tag[V_cap] = TRUE ;
		continue ;

	case V_gleeps:
		tag[V_PLURAL] = TRUE ;
		tag[V_gleep] = TRUE ;
		continue ;

	case V_hoop:
		tag[V_snake] = TRUE ;
		continue ;

	case V_M16:
	case V_m16:
	case V_gun:
		tag[V_rifle] = TRUE ;
		continue ;

	case V_kangaroos:
		tag[V_PLURAL] = TRUE ;
		tag[V_kangaroo] = TRUE ;
		continue ;

	case V_magazine:
	case V_ammo:
		tag[V_clip] = TRUE ;
		continue ;

	case V_mail:
	case V_envelope:
		tag[V_letter] = TRUE ;
		continue ;

	case V_matches:
		tag[V_PLURAL] = TRUE ;
		tag[V_match] = TRUE ;
		continue ;

	case V_Ned:
	case V_kelly:
	case V_Kelly:
		tag[V_ned] = TRUE ;
		continue ;

	case V_off_q:
		tag[V_off] = TRUE ;
		continue ;

	case V_on_q:
		tag[V_on] = TRUE ;
		continue ;
 
	case V_plan:
		tag[V_map] = TRUE ;
		continue ;

	case V_painting:
		tag[V_picture] = TRUE ;
		continue ;

	case V_doors:
		tag[V_PLURAL] = TRUE ;
		tag[V_door] = TRUE ;
		continue ;

	case V_pills:
	case V_packet:
		tag[V_PLURAL] = TRUE ;
	case V_atropine:
		tag[V_pill] = TRUE ;
		continue ;

	case V_safety:
	case V_SAFE:
		tag[V_safe] = TRUE ;
		continue ;
 
	case V_silver:
		tag[V_coin] = TRUE ;
		continue ;

	case V_spinifexes:
		tag[V_PLURAL] = TRUE ;
		tag[V_spinifex] = TRUE ;
		continue ;

	case V_stick:
		tag[V_dynamite] = TRUE ;
		continue ;

	case V_switch:
		tag[V_button] = TRUE ;
		continue ;

	case V_treasure:
		tag[V_all] = TRUE ;
		continue ;

	case V_I:
		tag[V_single] = TRUE ;
		continue ;

	case V_III:
		tag[V_triple] = TRUE ;
		continue ;

	case V_zero:
		tag[V_0] = TRUE ;
		continue ;

	case V_forty_nine:
		tag[V_49] = TRUE ;
		continue ;

	case V_sixty_seven:
		tag[V_67] = TRUE ;
		continue ;

	case V_eighty_two:
		tag[V_82] = TRUE ;
		continue ;

	default:
		continue ;
	}
} /* end of sentence tag word scan */
verb = sent[0] ;
return ;

} /* --- end of "parse" subroutine --- */

void purge(k_start, k_finish)
/***********************************/
/*                                 */
/*   Sentence Purging Subroutine   */
/*                                 */
/* Version: Mk 1.0  3 March 1990   */
/*                                 */
/***********************************/

int k_start, *k_finish ;
{
register int k ;
int k_end ;

k_end = *k_finish ;
for (k = k_start; k <= k_end-1; k++) sent[k] = sent[k+1] ;
*k_finish = --k_end ;
} /* --- end of "purge" subroutine --- */

void filler()
/***********************************/
/*                                 */
/*        Looker Subroutine        */
/*                                 */
/* Version: Mk 1.0  18 August 1989 */
/*                                 */
/***********************************/
{

if (tag[V_VERB_ONLY]) {
	printf("Fill what?\n") ;
	return ;
}
if (tag[V_can]) {
	if (object[O_can][J_loc] != B_have) 
printf("You don't have the Fourex can in your possession!\n") ;
else printf("I can't do it!  There's a hole in the can's bottom.\n") ;
	return ;
}
if (tag[V_bottle]) {
	if (object[O_bottle][J_loc] != B_have) 
printf("You don't have the bottle in your possession!\n") ;
else printf("I can't do it!  The bottle has a crack in it's bottom.\n");
	return ;
}
printf("I can't fill that!\n") ;
} /* --- end of the "filler" subroutine --- */

void looker(n)
/***********************************/
/*                                 */
/*        Looker Subroutine        */
/*                                 */
/* Version: Mk 1.0  18 August 1989 */
/*                                 */
/***********************************/
int n ;
{
#ifdef __TURBOC__
void long_descp(int), describe(int), objlooker(int), gleeper(int) ;
void actor(int), rdtxt(int) ;
#endif

int m ;

/* an isolated "look" means to just look at the room */
if (tag[V_VERB_ONLY]) { 
	/* goto long description test*/
	if ((room[n][M_rm_type] == T_was_long)||(n == R_lift_inside))
	   long_descp(n);
	else describe (n) ;
	objlooker(n) ; /* Check if there are objects in the room */
	gleeper(n) ;   /* check for gleeps and update the gleep count */
	/* describe unmovable action objects and status */
	if (room[n][M_rm_type] == T_action_obj) actor(n) ;
	return ;
}

/* Gleep tank */
if (tag[V_tank]) {
	if (n == R_gleep_tank) {
printf("You look inside the gleep tank and see a blue fluid which\n") ;
printf("smells of chlorine") ;
		if (gleep_score == 0) {
printf(".\n") ;
			return ;
		}
		if (gleep_score == 1) {
printf(" and a single gleep submerged in the fluid.\n") ;
			return ;
		}
printf(" and %d gleeps submerged in the fluid.\n",
		gleep_score) ;
		return ;
	}
	else {
		printf("There is no gleep tank here!\n") ;
		return ;
	}
}

/* wall safe */
if (tag[V_safe]) {
	if ((n == R_office_mang)&&
		(room[R_office_mang][M_rm_status] >= S_revealed)) {
		m = O_safe ;
		rdtxt(m);
	}
	else printf("I see no safe here for me to describe.\n");
	return ;
}

for (;;) {
	/* map from the manager's office */
	if (tag[V_map]) {
		m = O_map_frag ;
		break ;
	}

	/* Fourex can */
	if (tag[V_can]) {
		m = O_can ;
		break ;
	}

	/* Atropine pills */
	if (tag[V_pill]) {
		m = O_pills ;
		break ;
	}

	/* Qadaffi's letter bomb */
	if (tag[V_letter]) {
		m = O_letter ;
		break ;
	}

	/* paper from the safe */
	if (tag[V_paper]) {
		 m = O_paper ;
		break ;
	}

	/* ammo clip */            
	if (tag[V_clip]) {
		m = O_clip ;
		break ;
	}

	/* orange clip */
	if (tag[V_org_clip]) {
		m = O_org_clip ;
		break ;
	}

	/* rifle */
	if (tag[V_rifle]) {
		m = O_rifle ;
		break ;
	}

	/* Semtex detector */
	if (tag[V_detector]) {
		m = O_detector ;
		break ;
	}
 
	/* Deal with unreadable objects */
	printf("There is nothing more that I can describe about it.\n");
	return ;
} /* end of infinite for block */

if (object[m][J_loc] == B_have) rdtxt(m);
else 
printf("I can examine an object only if it is in my possession.\n");

} /* --- end of the "looker" subroutine --- */

void pass()
/***********************************/
/*                                 */
/*        Password Subroutine      */
/*                                 */
/* Version: Mk 1.0  29 July 1989   */
/*                                 */
/***********************************/
{

#ifdef __TURBOC__
void exit(int);
char getch(void) ;
#endif

register int i ;
char chr ;
static char *passwd = "2Xngootx7Ysd4Du9" ;

/* Request password */
printf("Enter password:  ") ;

#ifndef __TURBOC__
for (i = 2; i <= 7; i++) {
	chr = getchar() ;
	if (chr+i-1 != passwd[i]) exit(0) ;
}	
if (getchar() != '\n') exit(0) ;
printf(".\n") ;  /* indicate that the password was accepted */
#endif

#ifdef __TURBOC__
for (i = 2; i <= 7; i++) {
	chr = getch() ;
	if (chr+i-1 != passwd[i]) { 
		for (;;) if (getch() == 3) break ;
		printf("\r                    \n") ;
		exit(0) ;
	}
}
printf("\r.                     \n") ;
#endif

sw_wizard = TRUE ; /* toggle wizard switch */

} /* --- end of the "pass" subroutine */
