#define MAX_OBJECTS 400
#define MAX_WORDS 20
#define STACK_SIZE 10
#define VERSION 3
#define RELEASE 0
#define DEFAULT_CONFIG "\\games\\jacl\\config"
/*#define POWERC*/
#include <stdio.h>
#include <stdlib.h>
#ifdef POWERC
#include <conio.h>
#include <bios.h>
#endif
#ifdef __STDC__
int scope(int index, char *expected);
long value_of(int index);
long attribute_resolve(int wordno);
struct function_type *function_resolve(char *name);
struct variable_type *variable_resolve(int wordno);
#else
int scope();
long value_of();
long attribute_resolve();
struct function_type *function_resolve();
struct variable_type *variable_resolve();
#endif
#define HELD CURRENT_PLAYER->value+MAX_OBJECTS
#define HERE object[CURRENT_PLAYER->value]->location
#define LIMBO 32765
#define SCENERY 100
#define HEAVY 99
#define CURRENT_PLAYER variable[0]
#define TOTAL_MOVES variable[1]
#define TURN_WORKED variable[2]
#define CURRENT_SCORE variable[3]
#define INTERNAL_VERSION variable[4]
#define DISPLAY_MODE variable[5]
#define FALSE 0
#define TRUE 1
#define SEEK_SET 0
#define SEEK_CURRENT 1
#define SEEK_END 2
char current_function[81];
char function_name[81];
char default_function[81];
char before_function[81];
char after_function[81];
char override[81];
char text_buffer[161];
char write_buffer[240];
char last_command[81];
char current_command[81] = "\0";
char *word[MAX_WORDS + 2];
char punctuation[MAX_WORDS + 2];
int wp;
int destination = 1;
int locations, objects;
int it;
int them;
int her;
int him;
int parent;
int stack = 0;
int current_level;
int execution_level;
int custom_error;
int row = 0;
int column = 0;
int noun[4];
int screen_width = 79;
int screen_depth = 25;
int significance = 8;
int variable_contents;
int oec, location_element_contents;
int *object_element_address, *location_element_address;
int *object_backup_address, *location_backup_address;
short int restarting = FALSE;
short int spaced = FALSE;
short int notify = FALSE;
short int object_expected = FALSE;
FILE *file = NULL;
struct stack_type {
int execution_level;
int current_level;
long address;
char name[81];
};
struct stack_type backup[STACK_SIZE];
struct object_type {
char label[21];
char article[11];
struct name_type *first_name;
char inventory[41];
char described[81];
char described_backup[81];
char initial[81];
int location;
int location_backup;
long attributes;
long attributes_backup;
int info;
int info_backup;
int mass;
int mass_backup;
};
struct object_type *object[MAX_OBJECTS];
struct location_type {
char label[21];
long no_go;
int north;
int north_backup;
long go_north;
long no_north;
int northeast;
int northeast_backup;
long go_northeast;
long no_northeast;
int northwest;
int northwest_backup;
long go_northwest;
long no_northwest;
int south;
int south_backup;
long go_south;
long no_south;
int southeast;
int southeast_backup;
long go_southeast;
long no_southeast;
int southwest;
int southwest_backup;
long go_southwest;
long no_southwest;
int east;
int east_backup;
long go_east;
long no_east;
int west;
int west_backup;
long go_west;
long no_west;
int up;
int up_backup;
long go_up;
long no_up;
int down;
int down_backup;
long go_down;
long no_down;
int in;
int in_backup;
long go_in;
long no_in;
int out;
int out_backup;
long go_out;
long no_out;
long attributes;
long attributes_backup;
};
struct location_type *location[MAX_OBJECTS];
struct variable_type {
char name[21];
int value;
int value_backup;
struct variable_type *next_variable;
};
struct variable_type *variable_table = NULL;
struct variable_type *variable[6];
struct function_type {
char name[81];
long position;
struct function_type *next_function;
};
struct function_type *function_table = NULL;
struct word_type {
char word[21];
struct word_type *first_child;
struct word_type *next_sibling;
};
struct word_type *grammar_table = NULL;
struct synonym_type {
char original[21];
char standard[21];
struct synonym_type *next_synonym;
};
struct synonym_type *synonym_table = NULL;
struct name_type {
char name[21];
struct name_type *next_name;
};
struct filter_type {
char word[21];
struct filter_type *next_filter;
};
struct filter_type *filter_table = NULL;
main(argc, argv)
int argc;
char *argv[];
{
int index;
override[0] = 0;
if ((file = fopen("config", "r")) != NULL)
read_config_file();
else if ((file = fopen(DEFAULT_CONFIG, "r")) != NULL)
read_config_file();
if (screen_width < 30)
screen_width = 30;
if (screen_depth < 10)
screen_depth = 10;
if (argc == 1) {
clrscrn();
version_info();
write_text("you are welcome to redistribute it under certain ");
write_text("conditions, type ~info~ for details.^^");
printf("ENTER NAME OF GAME FILE: ");
fgets(text_buffer, 80, stdin);
strcat(override, text_buffer);
row = 0;
} else
strcat(override, argv[1]);
if (text_buffer[0] == 10) {
write_text("ERROR: No data file specified, can't continue.^");
terminate(1);
}
for (index = 0; index < strlen(override); index++) {
if (override[index] == 10)
override[index] = 0;
}
if ((file = fopen(override, "r")) == NULL) {
write_text("ERROR: Unable to open data file ~");
write_text(override);
write_text("~, can't continue.^");
terminate(1);
}
read_gamefile();
if (location[1] == NULL) {
write_text("ERROR: No locations defined, can't continue.^");
terminate(1);
}
strcpy(function_name, "{global_intro");
execute(function_name);
if (object[CURRENT_PLAYER->value] == NULL) {
write_text("ERROR: Variable CURRENT_PLAYER does not point to an ");
write_text("object, can't continue.^");
terminate(1);
}
strcpy(function_name, "{global_eachturn");
execute(function_name);
do {
if (TURN_WORKED->value) {
TOTAL_MOVES->value++;
strcpy(function_name, "{global_eachturn");
execute(function_name);
if (!check_light(HERE)) {
strcpy(function_name, "{global_grued");
if (execute(function_name) == FALSE) {
unkfunrun("{global_grued");
terminate(0);
}
}
}
TURN_WORKED->value = TRUE;
custom_error = FALSE;
row = 0;
newline();
printf(">");
strcpy(last_command, current_command);
fgets(text_buffer, 80, stdin);
if (feof(stdin)) {
write_text("END OF FILE^");
terminate(0);
}
for (index = 0; index < 80; index++)
text_buffer[index] = tolower(text_buffer[index]);
strcpy(current_command, text_buffer);
encapsulate();
truncate();
if (word[0] != NULL) {
if (strcmp(word[0], "undo"))
save_game_state();
word_check();
} else {
write_text("A fiendishly clever move.^");
TURN_WORKED->value = FALSE;
}
}
while (TRUE);
}
word_check()
{
if (!strncmp(word[wp], "quit", significance) || !strncmp(word[wp], "q", significance)) {
TURN_WORKED->value = FALSE;
printf("\nAre you sure you want to quit? >");
fgets(text_buffer, 4, stdin);
if (text_buffer[0] == 121 || text_buffer[0] == 89) {
newline();
strcpy(function_name, "{global_score");
execute(function_name);
terminate(0);
} else
write_text("Returning to game.^");
} else if (!strncmp(word[wp], "restart", significance)) {
TURN_WORKED->value = FALSE;
printf("\nAre you sure you want to restart? >");
fgets(text_buffer, 4, stdin);
if (text_buffer[0] == 121 || text_buffer[0] == 89) {
write_text("^Restarting...^");
restart_game();
} else
write_text("Returning to game.^");
} else if (!strncmp(word[wp], "again", significance) || !strncmp(word[wp], "g", significance)) {
if (last_command[0] == 0) {
write_text("But you haven't done anything yet!^");
TURN_WORKED->value = FALSE;
} else if (last_command[0] == 10) {
write_text("It wasn't so clever as to be worth repeating.^");
current_command[0] = 10;
TURN_WORKED->value = FALSE;
} else {
strcpy(text_buffer, last_command);
strcpy(current_command, last_command);
encapsulate();
truncate();
word_check();
}
} else if (!strncmp(word[wp], "save", significance))
save_game();
else if (!strncmp(word[wp], "restore", significance))
restore_game();
else if (!strncmp(word[wp], "undo", significance)) {
if (TOTAL_MOVES->value && strncmp(last_command, "undo", 4))
restore_game_state();
else {
write_text("Nothing to undo.^");
TURN_WORKED->value = FALSE;
}
} else if (!strncmp(word[wp], "info", significance)) {
version_info();
write_text("you can redistribute it and/or modify it under the ");
write_text("terms of the GNU General Public License as published by ");
write_text("the Free Software Foundation; either version 2 of the ");
write_text("License, or any later version.^^");
write_text("This program is distributed in the hope that it will be ");
write_text("useful, but WITHOUT ANY WARRANTY; without even the ");
write_text("implied warranty of MERCHANTABILITY or FITNESS FOR A ");
write_text("PARTICULAR PURPOSE. See the GNU General Public License ");
write_text("for more details.^^");
write_text("You should have received a copy of the GNU General ");
write_text("Public License along with this program; if not, write ");
write_text("to the Free Software Foundation, Inc., 675 Mass Ave, ");
write_text("Cambridge, MA 02139, USA.^^");
printf("OBJECTS DEFINED: %d", objects);
newline();
printf("LOCATIONS DEFINED: %d", locations);
newline();
TURN_WORKED->value = FALSE;
} else
parser();
}
read_config_file()
{
fgets(text_buffer, 80, file);
while (!feof(file)) {
encapsulate();
if (word[0] == NULL);
else if (!strcmp(word[0], "columns")) {
if (word[1] != NULL)
screen_width = atoi(word[1]);
} else if (!strcmp(word[0], "lines")) {
if (word[1] != NULL)
screen_depth = atoi(word[1]);
} else if (!strcmp(word[0], "spaced")) {
spaced = TRUE;
} else if (!strcmp(word[0], "notify")) {
notify = TRUE;
} else if (!strcmp(word[0], "significance")) {
if (word[1] != NULL)
significance = atoi(word[1]);
} else if (!strcmp(word[0], "path")) {
if (word[1] != NULL)
strcpy(override, word[1]);
}
fgets(text_buffer, 80, file);
}
fclose(file);
file = NULL;
}
version_info()
{
printf("JACL Engine v%d / r%d ", VERSION, RELEASE);
printf("/ %d object.", MAX_OBJECTS);
write_text("^Copyright (C) 1990-1997 Stuart Allen.^^");
write_text("This program is free software; ");
}
encapsulate()
{
int index, length;
int position = 0;
int new_word = TRUE;
length = strlen(text_buffer);
text_buffer[--length] = 0;
index = 0;
for (index = 0; index < length; index++) {
switch (text_buffer[index]) {
case ',':
punctuation[position - 1] = text_buffer[index];
text_buffer[index] = 0;
new_word = TRUE;
break;
case ':':
case '\t':
case ' ':
text_buffer[index] = 0;
new_word = TRUE;
break;
case ';':
text_buffer[index] = 0;
index = length;
break;
case '"':
index++;
if (new_word) {
word[position] = &text_buffer[index];
new_word = FALSE;
if (position < MAX_WORDS) {
position++;
punctuation[position] = 0;
}
}
for (; index < length; index++) {
if (text_buffer[index] == 34) {
text_buffer[index] = 0;
new_word = TRUE;
break;
}
}
break;
default:
if (new_word) {
word[position] = &text_buffer[index];
new_word = FALSE;
if (position < MAX_WORDS) {
position++;
punctuation[position] = 0;
}
}
break;
}
}
word[position] = NULL;
wp = 0;
}
truncate()
{
int index, counter, match;
int position = 0;
struct synonym_type *synonym;
struct filter_type *filter = filter_table;
if (filter != NULL) {
while (word[position] != NULL) {
match = FALSE;
do {
if (!strncmp(word[position], filter->word, significance)) {
for (index = position; word[index + 1] != NULL; index++) {
word[index] = word[index + 1];
punctuation[index] = punctuation[index + 1];
}
word[index] = NULL;
punctuation[index] = 0;
match = TRUE;
}
filter = filter->next_filter;
}
while (filter != NULL && !match);
filter = filter_table;
if (!match)
position++;
};
}
if (synonym_table != NULL) {
for (counter = 0; word[counter] != NULL; counter++) {
synonym = synonym_table;
do {
if (!strncmp(word[counter], synonym->original, significance)) {
word[counter] = synonym->standard;
break;
}
if (synonym->next_synonym != NULL)
synonym = synonym->next_synonym;
else
break;
}
while (TRUE);
}
}
}
parser()
{
struct word_type *pointer;
int index;
int current_noun = -1;
noun[0] = FALSE;
noun[1] = FALSE;
if (grammar_table != NULL) {
pointer = grammar_table;
while (word[wp] != NULL) {
object_expected = FALSE;
do {
if (!strncmp(word[wp], pointer->word, significance)) {
if (pointer->first_child == NULL) {
write_text("ERROR: Incomplete grammar statement.^");
return;
} else {
pointer = pointer->first_child;
wp++;
break;
}
} else if (pointer->word[0] == '*' && (index = noun_resolve(pointer))) {
noun[++current_noun] = index;
if (position(noun[current_noun], pointer->word)) {
if (pointer->first_child == NULL) {
write_text("ERROR: Incomplete grammar statement.^");
return;
} else {
pointer = pointer->first_child;
wp++;
break;
}
} else {
TURN_WORKED->value = FALSE;
return;
}
} else {
if (custom_error == TRUE) {
TURN_WORKED->value = FALSE;
return;
} else if (pointer->next_sibling != NULL)
pointer = pointer->next_sibling;
else {
diagnose();
return;
}
}
}
while (TRUE);
};
do {
if (!strncmp(pointer->word, "->", 2)) {
strcpy(function_name, "{");
strcat(function_name, pointer->word + 2);
strcat(function_name, "_");
strcpy(override, function_name);
strcpy(before_function, "{global_before_");
strcat(before_function, pointer->word + 2);
strcpy(after_function, "{global_after_");
strcat(after_function, pointer->word + 2);
strcpy(default_function, "{global_default_");
strcat(default_function, pointer->word + 2);
if (execute(before_function) != FALSE)
return;
if (noun[0] == FALSE) {
strcat(function_name, location[HERE]->label);
if (execute(function_name) == FALSE) {
strcat(override, "override_");
strcat(override, location[HERE]->label);
strcpy(function_name, "{global_");
strcat(function_name, pointer->word + 2);
if (execute(function_name) == FALSE)
unkfunrun(function_name);
}
} else if (noun[1] == FALSE) {
strcat(function_name, object[noun[0]]->label);
if (execute(function_name) == FALSE) {
strcat(override, "override_");
strcat(override, object[noun[0]]->label);
strcpy(function_name, "{global_");
strcat(function_name, pointer->word + 2);
if (execute(function_name) == FALSE)
unkfunrun(function_name);
}
} else {
strcat(function_name, object[noun[1]]->label);
strcat(function_name, "_");
strcat(function_name, object[noun[0]]->label);
if (execute(function_name) == FALSE) {
strcat(override, object[noun[1]]->label);
strcat(override, "_override_");
strcat(override, object[noun[0]]->label);
strcpy(function_name, "{global_");
strcat(function_name, pointer->word + 2);
if (execute(function_name) == FALSE)
unkfunrun(function_name);
}
}
execute(after_function);
return;
} else {
if (pointer->next_sibling == NULL)
break;
else
pointer = pointer->next_sibling;
}
}
while (TRUE);
diagnose();
return;
}
diagnose();
}
diagnose()
{
if (custom_error) {
TURN_WORKED->value = FALSE;
return;
}
if (word[wp] == NULL) {
write_text("The sentence you typed was incomplete.^");
} else if (object_expected && wp != 0) {
write_text("You can't see any such thing.^");
} else {
strcpy(write_buffer, "You can't use the word ~");
strcat(write_buffer, word[wp]);
strcat(write_buffer, "~ in that context.^");
write_text(write_buffer);
}
TURN_WORKED->value = FALSE;
}
position(index, expected)
int index;
char expected[];
{
if (!strcmp(expected, "*held")) {
if (object[index]->location == HELD)
return (TRUE);
else {
strcpy(write_buffer, "You are not holding ");
sentence_output(index, 0);
strcat(write_buffer, ".^");
write_text(write_buffer);
return (FALSE);
}
} else if (!strcmp(expected, "*here")) {
if (object[index]->location == HERE)
return (TRUE);
else if (object[index]->location == HELD) {
strcpy(write_buffer, "That will be a bit hard while you're holding ");
sentence_output(index, 0);
strcat(write_buffer, ".^");
write_text(write_buffer);
return (FALSE);
} else if (find_parent(index)) {
if (object[parent]->attributes & 32) {
strcpy(write_buffer, "You don't see ");
sentence_output(index, 0);
strcat(write_buffer, " here.^");
write_text(write_buffer);
return (FALSE);
} else if (object[parent]->attributes & 2097152) {
write_buffer[0] = 0;
sentence_output(parent, 1);
strcat(write_buffer, " currently has ");
sentence_output(index, 0);
strcat(write_buffer, ".^");
write_text(write_buffer);
return (FALSE);
} else
return (TRUE);
} else {
strcpy(write_buffer, "You don't see ");
sentence_output(index, 0);
strcat(write_buffer, " here.^");
write_text(write_buffer);
return (FALSE);
}
} else if (!strcmp(expected, "*anywhere"))
return (TRUE);
else {
if (object[index]->location == HERE || object[index]->location == HELD)
return (TRUE);
else if (find_parent(index)) {
if (object[parent]->attributes & 32) {
strcpy(write_buffer, "You don't see ");
sentence_output(index, 0);
strcat(write_buffer, " here.^");
write_text(write_buffer);
return (FALSE);
} else if (object[parent]->attributes & 2097152 && !strcmp(expected, "*present")) {
write_buffer[0] = 0;
sentence_output(parent, 1);
strcat(write_buffer, " currently has ");
sentence_output(index, 0);
strcat(write_buffer, ".^");
write_text(write_buffer);
return (FALSE);
} else
return (TRUE);
} else {
strcpy(write_buffer, "You don't see ");
sentence_output(index, 0);
strcat(write_buffer, " here.^");
write_text(write_buffer);
return (FALSE);
}
}
}
scope(index, expected)
int index;
char *expected;
{
if (!strcmp(expected, "*held")) {
if (object[index]->location == HELD)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(expected, "*here")) {
if (object[index]->location == HERE)
return (TRUE);
else if (object[index]->location == HELD)
return (FALSE);
else if (find_parent(index)) {
if (object[parent]->attributes & 32)
return (FALSE);
return (TRUE);
} else
return (FALSE);
} else if (!strcmp(expected, "*anywhere"))
return (TRUE);
else {
if (object[index]->location == HERE || object[index]->location == HELD)
return (TRUE);
else if (find_parent(index)) {
if (object[parent]->attributes & 32)
return (FALSE);
return (TRUE);
} else
return (FALSE);
}
}
save_game()
{
struct variable_type *current_variable = variable_table;
FILE *bookmark;
int index;
char text_buffer[81];
if (word[++wp] == NULL)
strcpy(text_buffer, "bookmark");
else
strncpy(text_buffer, word[wp], 80);
if ((bookmark = fopen(text_buffer, "w")) == NULL) {
write_text("Error opening save file ~");
write_text(text_buffer);
write_text("~.^");
return;
}
do {
fprintf(bookmark, "%d/", current_variable->value);
current_variable = current_variable->next_variable;
}
while (current_variable != NULL);
for (index = 1; index <= objects; index++) {
fprintf(bookmark, "%d/%ld/%d/%d/", object[index]->info, object[index]->attributes, object[index]->location, object[index]->mass);
}
for (index = 1; index <= locations; index++) {
fprintf(bookmark, "%d/%d/%d/%d/%d/", location[index]->in, location[index]->out, location[index]->north, location[index]->south, location[index]->east);
fprintf(bookmark, "%d/%d/%d/%d/", location[index]->northeast, location[index]->northwest, location[index]->southeast, location[index]->southwest);
fprintf(bookmark, "%d/%d/%d/%ld/", location[index]->west, location[index]->up, location[index]->down, location[index]->attributes);
}
fprintf(bookmark, "\n");
for (index = 1; index <= objects; index++) {
strcpy(text_buffer, object[index]->described);
strcat(text_buffer, "\n");
fputs(text_buffer, bookmark);
}
fclose(bookmark);
write_text("Game saved.^");
TURN_WORKED->value = FALSE;
}
save_game_state()
{
int index;
struct variable_type *current_variable = variable_table;
do {
current_variable->value_backup = current_variable->value;
current_variable = current_variable->next_variable;
}
while (current_variable != NULL);
for (index = 1; index <= objects; index++) {
object[index]->info_backup = object[index]->info;
object[index]->location_backup = object[index]->location;
object[index]->attributes_backup = object[index]->attributes;
strcpy(object[index]->described_backup, object[index]->described);
}
for (index = 1; index <= locations; index++) {
location[index]->north_backup = location[index]->north;
location[index]->northeast_backup = location[index]->northeast;
location[index]->east_backup = location[index]->east;
location[index]->southeast_backup = location[index]->southeast;
location[index]->south_backup = location[index]->south;
location[index]->southwest_backup = location[index]->southwest;
location[index]->west_backup = location[index]->west;
location[index]->northwest_backup = location[index]->northwest;
location[index]->in_backup = location[index]->in;
location[index]->out_backup = location[index]->out;
location[index]->up_backup = location[index]->up;
location[index]->down_backup = location[index]->down;
location[index]->attributes_backup = location[index]->attributes;
}
}
restore_game()
{
struct variable_type *current_variable = variable_table;
FILE *bookmark;
int index, counter;
char text_buffer[81];
if (word[++wp] == NULL)
strcpy(text_buffer, "bookmark");
else
strncpy(text_buffer, word[wp], 80);
if ((bookmark = fopen(text_buffer, "r")) == NULL) {
write_text("Error opening save file ~");
write_text(text_buffer);
write_text("~.^");
return;
}
do {
fscanf(bookmark, "%d/", ¤t_variable->value);
current_variable = current_variable->next_variable;
}
while (current_variable != NULL);
for (index = 1; index <= objects; index++) {
fscanf(bookmark, "%d/%ld/%d/%d/", &object[index]->info, &object[index]->attributes, &object[index]->location, &object[index]->mass);
}
for (index = 1; index <= locations; index++) {
fscanf(bookmark, "%d/%d/%d/%d/%d/", &location[index]->in, &location[index]->out, &location[index]->north, &location[index]->south, &location[index]->east);
fscanf(bookmark, "%d/%d/%d/%d/", &location[index]->northeast, &location[index]->northwest, &location[index]->southeast, &location[index]->southwest);
fscanf(bookmark, "%d/%d/%d/%ld/", &location[index]->west, &location[index]->up, &location[index]->down, &location[index]->attributes);
}
fscanf(bookmark, "\n");
for (index = 1; index <= objects; index++) {
fgets(object[index]->described, 80, bookmark);
for (counter = 0; counter < strlen(object[index]->described); counter++) {
if (object[index]->described[counter] == 10) {
object[index]->described[counter] = 0;
break;
}
}
}
fclose(bookmark);
write_text("Game restored.^^");
location[HERE]->attributes &= ~1L;
display();
TURN_WORKED->value = FALSE;
}
restore_game_state()
{
int index;
struct variable_type *current_variable = variable_table;
do {
current_variable->value = current_variable->value_backup;
current_variable = current_variable->next_variable;
}
while (current_variable != NULL);
for (index = 1; index <= objects; index++) {
object[index]->info = object[index]->info_backup;
object[index]->location = object[index]->location_backup;
object[index]->attributes = object[index]->attributes_backup;
strcpy(object[index]->described, object[index]->described_backup);
}
for (index = 1; index <= locations; index++) {
location[index]->north = location[index]->north_backup;
location[index]->northeast = location[index]->northeast_backup;
location[index]->east = location[index]->east_backup;
location[index]->southeast = location[index]->southeast_backup;
location[index]->south = location[index]->south_backup;
location[index]->southwest = location[index]->southwest_backup;
location[index]->west = location[index]->west_backup;
location[index]->northwest = location[index]->northwest_backup;
location[index]->in = location[index]->in_backup;
location[index]->out = location[index]->out_backup;
location[index]->up = location[index]->up_backup;
location[index]->down = location[index]->down_backup;
location[index]->attributes = location[index]->attributes_backup;
}
write_text("Previous move undone.^^");
location[HERE]->attributes &= ~1L;
display();
TURN_WORKED->value = FALSE;
}
display()
{
int index;
strcpy(function_name, "{global_title");
execute(function_name);
if (DISPLAY_MODE->value)
location[HERE]->attributes &= ~1L;
strcpy(function_name, "{look_");
strcat(function_name, location[HERE]->label);
execute(function_name);
location[HERE]->attributes = location[HERE]->attributes | 1;
for (index = 1; index <= objects; index++) {
if (object[index]->location == HERE && object[index]->mass < SCENERY) {
if (object[index]->attributes & 8388608 || object[index]->initial[0] == 0) {
if (spaced)
newline();
write_text(object[index]->described);
} else {
if (spaced)
newline();
write_text(object[index]->initial);
}
newline();
}
}
}
check_light(where)
int where;
{
int index;
if ((location[where]->attributes & 2) == FALSE)
return (TRUE);
else {
for (index = 1; index <= objects; index++) {
if ((object[index]->attributes & 64) && scope(index, "*present"))
return (TRUE);
}
}
return (FALSE);
}
move_player(go_pointer, no_pointer)
long go_pointer;
long no_pointer;
{
strcpy(function_name, "{global_movement");
if (execute(function_name) == TRUE) {
TURN_WORKED->value = FALSE;
return (FALSE);
}
if (destination) {
if (check_light(destination)) {
if (go_pointer != 0) {
fseek(file, go_pointer, SEEK_SET);
fgets(text_buffer, 160, file);
encapsulate();
if (word[1] != NULL) {
write_text(word[1]);
newline();
newline();
}
}
HERE = destination;
display();
} else {
write_text("It's dark ");
if (location[HERE]->attributes & 32)
write_text("out");
else
write_text("in");
write_text(" there, you'll need a light.^");
TURN_WORKED->value = FALSE;
}
} else {
TURN_WORKED->value = FALSE;
if (no_pointer != 0) {
fseek(file, no_pointer, SEEK_SET);
fgets(text_buffer, 160, file);
encapsulate();
if (word[1] != NULL) {
write_text(word[1]);
newline();
} else
write_text("You can't go that way.^");
} else if (location[HERE]->no_go != 0) {
fseek(file, location[HERE]->no_go, SEEK_SET);
fgets(text_buffer, 160, file);
encapsulate();
if (word[1] != NULL) {
write_text(word[1]);
newline();
} else
write_text("You can't go that way.^");
} else
write_text("You can't go that way.^");
}
}
find_parent(index)
int index;
{
if ((object[index]->location > MAX_OBJECTS) && (object[index]->location < (MAX_OBJECTS * 2))) {
parent = object[index]->location - MAX_OBJECTS;
if (object[parent]->location == HELD || object[parent]->location == HERE) {
if (object[parent]->attributes & 1)
return (FALSE);
else
return (TRUE);
} else {
if (object[parent]->attributes & 1)
return (FALSE);
else
return (find_parent(parent));
}
} else
return (FALSE);
}
sentence_output(index, capital)
int index;
int capital;
{
char text_buffer[52];
if (!strcmp(object[index]->article, "name")) {
strcpy(text_buffer, object[index]->inventory);
} else {
strcpy(text_buffer, "the");
strcat(text_buffer, " ");
strcat(text_buffer, object[index]->inventory);
}
if (capital)
text_buffer[0] = toupper(text_buffer[0]);
strcat(write_buffer, text_buffer);
}
isnt_output(index)
int index;
{
if (object[index]->attributes & 16384)
strcat(write_buffer, " aren't");
else
strcat(write_buffer, " isn't");
}
is_output(index)
int index;
{
if (object[index]->attributes & 16384)
strcat(write_buffer, " are");
else
strcat(write_buffer, " is");
}
doesnt_output(index)
int index;
{
if (object[index]->attributes & 16384)
strcat(write_buffer, " don't ");
else
strcat(write_buffer, " doesn't ");
}
does_output(index)
int index;
{
if (object[index]->attributes & 16384)
strcat(write_buffer, " do ");
else
strcat(write_buffer, " does ");
}
list_output(index, capital)
int index;
int capital;
{
char text_buffer[52];
if (!strcmp(object[index]->article, "name")) {
strcpy(text_buffer, object[index]->inventory);
} else {
strcpy(text_buffer, object[index]->article);
strcat(text_buffer, " ");
strcat(text_buffer, object[index]->inventory);
}
if (capital)
text_buffer[0] = toupper(text_buffer[0]);
strcat(write_buffer, text_buffer);
}
terminate(code)
int code;
{
write_text("^---JACL ENGINE TERMINATED---^^^");
more();
if (file != NULL)
fclose(file);
exit(code);
}
execute(funcname)
char *funcname;
{
char subfunc[81];
int index, to, from;
int counter = 0;
int *container;
int contents;
long top_of_loop = FALSE;
long go_pointer;
long no_pointer;
long bit_mask;
struct function_type *resolved_function;
struct variable_type *resolved_variable;
struct name_type *current_name;
char temporary_buffer[161];
char variable_buffer[16];
resolved_function = function_resolve(funcname);
if (resolved_function == NULL)
return (FALSE);
execution_level = 0;
current_level = 0;
strcpy(current_function, funcname);
fseek(file, resolved_function->position, SEEK_SET);
fgets(text_buffer, 160, file);
while (text_buffer[0] != 125) {
encapsulate();
if (word[0] == NULL);
else if (!strcmp(word[0], "endif")) {
current_level--;
if (current_level < execution_level)
execution_level = current_level;
} else if (!strcmp(word[0], "endall")) {
current_level = 0;
execution_level = 0;
} else if (!strcmp(word[0], "else")) {
if (current_level == execution_level)
execution_level--;
else if (current_level == execution_level + 1)
execution_level++;
} else if (current_level == execution_level) {
if (!strcmp(word[0], "more"))
more();
else if (!strcmp(word[0], "look")) {
push_stack(ftell(file));
location[HERE]->attributes &= ~1L;
display();
pop_stack();
} else if (!strcmp(word[0], "endgame")) {
while (TRUE) {
write_text("^Please type S to start again, Q to quit ");
write_text("or U to undo >");
row = 0;
fgets(text_buffer, 4, stdin);
if (text_buffer[0] == 'U' || text_buffer[0] == 'u') {
restore_game_state();
return (TRUE);
} else if (text_buffer[0] == 'Q' || text_buffer[0] == 'q')
terminate(0);
else if (text_buffer[0] == 'S' || text_buffer[0] == 's') {
write_text("^Restarting...^");
restart_game();
return (TRUE);
}
};
} else if (!strcmp(word[0], "loop")) {
top_of_loop = ftell(file);
noun[2] = 1;
} else if (!strcmp(word[0], "endloop")) {
if (top_of_loop == FALSE)
printf("ERROR: In function \"%s\", endloop command without loop command.", funcname);
else {
noun[2]++;
if (noun[2] > objects) {
top_of_loop = FALSE;
noun[2] = FALSE;
} else
fseek(file, top_of_loop, SEEK_SET);
}
} else if (!strcmp(word[0], "proxy")) {
push_stack(ftell(file));
temporary_buffer[0] = 0;
for (counter = 1; word[counter] != NULL; counter++) {
if (!strcmp(word[counter], "noun1")) {
current_name = object[noun[0]]->first_name;
while (current_name != NULL) {
strcat(temporary_buffer, " ");
strcat(temporary_buffer, current_name->name);
current_name = current_name->next_name;
}
} else if (!strcmp(word[counter], "noun2")) {
current_name = object[noun[1]]->first_name;
while (current_name != NULL) {
strcat(temporary_buffer, " ");
strcat(temporary_buffer, current_name->name);
current_name = current_name->next_name;
}
} else if (!strcmp(word[counter], "noun3")) {
current_name = object[noun[2]]->first_name;
while (current_name != NULL) {
strcat(temporary_buffer, " ");
strcat(temporary_buffer, current_name->name);
current_name = current_name->next_name;
}
} else if (!strcmp(word[counter], "noun4")) {
current_name = object[noun[3]]->first_name;
while (current_name != NULL) {
strcat(temporary_buffer, " ");
strcat(temporary_buffer, current_name->name);
current_name = current_name->next_name;
}
} else
strcat(temporary_buffer, word[counter]);
}
strcat(temporary_buffer, "\n");
strcpy(text_buffer, temporary_buffer);
encapsulate();
truncate();
word_check();
pop_stack();
} else if (!strcmp(word[0], "override")) {
push_stack(ftell(file));
if (execute(override) == TRUE) {
pop_stack();
return (TRUE);
} else {
if (execute(default_function) == TRUE) {
pop_stack();
return (TRUE);
} else {
pop_stack();
}
}
} else if (!strcmp(word[0], "execute")) {
if (word[1] == NULL)
noproprun();
else {
strcpy(subfunc, "{");
strcat(subfunc, word[1]);
push_stack(ftell(file));
if (execute(subfunc) == FALSE) {
printf("ERROR: In function \"%s\", attempt to execute undefined function \"%s\".\n", funcname, subfunc);
}
pop_stack();
}
} else if (!strcmp(word[0], "terminate"))
terminate(0);
else if (!strcmp(word[0], "points")) {
if (word[1] != NULL) {
CURRENT_SCORE->value = CURRENT_SCORE->value + atoi(word[1]);
if (notify) {
strcpy(write_buffer, "^[YOUR SCORE JUST WENT UP BY ");
strcat(write_buffer, word[1]);
if (atoi(word[1]) == 1)
strcat(write_buffer, " POINT]^");
else
strcat(write_buffer, " POINTS]^");
write_text(write_buffer);
}
} else
noproprun();
} else if (!strcmp(word[0], "right")) {
if (word[1] != NULL) {
write_right(word[1]);
newline();
} else
noproprun();
} else if (!strcmp(word[0], "centre")) {
if (word[1] != NULL) {
write_centred(word[1]);
newline();
} else
noproprun();
} else if (!strcmp(word[0], "write")) {
write_buffer[0] = 0;
for (counter = 1; word[counter] != NULL; counter++) {
if (!strcmp(word[counter], "noun1")) {
if (noun[0] != 0)
sentence_output(noun[0], 0);
} else if (!strcmp(word[counter], "noun1(inventory)")) {
if (noun[0] != 0)
list_output(noun[0], 0);
} else if (!strcmp(word[counter], "noun1(does)")) {
if (noun[0] != 0)
does_output(noun[0]);
} else if (!strcmp(word[counter], "noun1(doesnt)")) {
if (noun[0] != 0)
doesnt_output(noun[0]);
} else if (!strcmp(word[counter], "noun1(s)")) {
if (noun[0] != 0) {
if (!(object[noun[0]]->attributes & 16384))
strcat(write_buffer, "s");
}
} else if (!strcmp(word[counter], "noun1(is)")) {
if (noun[0] != 0)
is_output(noun[0]);
} else if (!strcmp(word[counter], "noun1(isnt)")) {
if (noun[0] != 0)
isnt_output(noun[0]);
} else if (!strcmp(word[counter], "Noun1(inventory)")) {
if (noun[0] != 0)
list_output(noun[0], 1);
} else if (!strcmp(word[counter], "Noun1")) {
if (noun[0] != 0)
sentence_output(noun[0], 1);
} else if (!strcmp(word[counter], "noun2")) {
if (noun[1] != 0)
sentence_output(noun[1], 0);
} else if (!strcmp(word[counter], "noun2(inventory)")) {
if (noun[1] != 0)
list_output(noun[1], 0);
} else if (!strcmp(word[counter], "noun2(does)")) {
if (noun[1] != 0)
does_output(noun[1]);
} else if (!strcmp(word[counter], "noun2(doesnt)")) {
if (noun[1] != 0)
doesnt_output(noun[1]);
} else if (!strcmp(word[counter], "noun2(s)")) {
if (noun[1] != 0) {
if (!(object[noun[1]]->attributes & 16384))
strcat(write_buffer, "s");
}
} else if (!strcmp(word[counter], "noun2(is)")) {
if (noun[1] != 0)
is_output(noun[1]);
} else if (!strcmp(word[counter], "noun2(isnt)")) {
if (noun[1] != 0)
isnt_output(noun[1]);
} else if (!strcmp(word[counter], "Noun2(inventory)")) {
if (noun[1] != 0)
list_output(noun[1], 1);
} else if (!strcmp(word[counter], "Noun2")) {
if (noun[1] != 0)
sentence_output(noun[1], 1);
} else if (!strcmp(word[counter], "noun3")) {
if (noun[2] != 0)
sentence_output(noun[2], 0);
} else if (!strcmp(word[counter], "noun3(inventory)")) {
if (noun[2] != 0)
list_output(noun[2], 0);
} else if (!strcmp(word[counter], "noun3(does)")) {
if (noun[2] != 0)
does_output(noun[2]);
} else if (!strcmp(word[counter], "noun3(doesnt)")) {
if (noun[2] != 0)
doesnt_output(noun[2]);
} else if (!strcmp(word[counter], "noun3(s)")) {
if (noun[2] != 0) {
if (!(object[noun[2]]->attributes & 16384))
strcat(write_buffer, "s");
}
} else if (!strcmp(word[counter], "noun3(is)")) {
if (noun[2] != 0)
is_output(noun[2]);
} else if (!strcmp(word[counter], "noun3(isnt)")) {
if (noun[2] != 0)
isnt_output(noun[2]);
} else if (!strcmp(word[counter], "Noun3(inventory)")) {
if (noun[2] != 0)
list_output(noun[2], 1);
} else if (!strcmp(word[counter], "Noun3")) {
if (noun[2] != 0)
sentence_output(noun[2], 1);
} else if (!strcmp(word[counter], "noun4")) {
if (noun[3] != 0)
sentence_output(noun[3], 0);
} else if (!strcmp(word[counter], "noun4(inventory)")) {
if (noun[3] != 0)
list_output(noun[3], 0);
} else if (!strcmp(word[counter], "noun4(does)")) {
if (noun[3] != 0)
does_output(noun[3]);
} else if (!strcmp(word[counter], "noun4(doesnt)")) {
if (noun[3] != 0)
doesnt_output(noun[3]);
} else if (!strcmp(word[counter], "noun4(s)")) {
if (noun[3] != 0) {
if (!(object[noun[3]]->attributes & 16384))
strcat(write_buffer, "s");
}
} else if (!strcmp(word[counter], "noun4(is)")) {
if (noun[3] != 0)
is_output(noun[3]);
} else if (!strcmp(word[counter], "noun4(isnt)")) {
if (noun[3] != 0)
isnt_output(noun[3]);
} else if (!strcmp(word[counter], "Noun4(inventory)")) {
if (noun[3] != 0)
list_output(noun[3], 1);
} else if (!strcmp(word[counter], "Noun4")) {
if (noun[3] != 0)
sentence_output(noun[3], 1);
} else if ((resolved_variable = variable_resolve(counter)) != NULL) {
variable_buffer[0] = 0;
sprintf(variable_buffer, "%d", resolved_variable->value);
strcat(write_buffer, variable_buffer);
} else
strcat(write_buffer, word[counter]);
}
write_text(write_buffer);
} else if (!strcmp(word[0], "break")) {
if (word[1] == NULL)
return (TRUE);
else if (!strcmp(word[1], "false"))
return (FALSE);
else
return (TRUE);
} else if (!strcmp(word[0], "clear"))
clrscrn();
else if (!strcmp(word[0], "describe")) {
if (word[1] == NULL)
noproprun();
else if (index = object_resolve(1)) {
if (word[3] == NULL)
noproprun();
else {
strncpy(object[index]->described, word[3], 80);
object[index]->described[80] = 0;
}
} else
unkobjrun(1);
} else if (!strcmp(word[0], "set")) {
if (word[3] == NULL)
noproprun();
else if ((resolved_variable = variable_resolve(1)) != NULL)
container = &resolved_variable->value;
else if (location_element_resolve(1))
container = location_element_address;
else if (object_element_resolve(1))
container = object_element_address;
else if (!strcmp(word[1], "noun1"))
container = &noun[0];
else if (!strcmp(word[1], "noun2"))
container = &noun[1];
else if (!strcmp(word[1], "noun3"))
container = &noun[2];
else if (!strcmp(word[1], "noun4"))
container = &noun[3];
else
unkvarrun(1);
contents = value_of(3);
if (!strcmp(word[2], "+"))
*container += contents;
else if (!strcmp(word[2], "-"))
*container -= contents;
else if (!strcmp(word[2], "*"))
*container = *container * contents;
else if (!strcmp(word[2], "/"))
*container = *container / contents;
else if (!strcmp(word[2], "="))
*container = contents;
else if (!strcmp(word[2], "parentof")) {
if (object[contents]->location > MAX_OBJECTS)
*container = object[contents]->location - MAX_OBJECTS;
else
*container = 0;
} else
printf("ERROR: Illegal operator \"%s\".", word[2]);
} else if (!strcmp(word[0], "ensure")) {
if (word[3] == NULL)
noproprun();
else {
if (bit_mask = attribute_resolve(3)) {
if (index = object_resolve(1)) {
if (!strcmp(word[2], "has")) {
object[index]->attributes = object[index]->attributes | bit_mask;
} else if (!strcmp(word[2], "hasnt")) {
bit_mask = ~bit_mask;
object[index]->attributes = object[index]->attributes & bit_mask;
}
} else if (index = location_resolve(1)) {
if (!strcmp(word[2], "has")) {
location[index]->attributes = location[index]->attributes | bit_mask;
} else if (!strcmp(word[2], "hasnt")) {
bit_mask = ~bit_mask;
location[index]->attributes = location[index]->attributes & bit_mask;
}
}
} else {
printf("ERROR: Unknown attribute \"%s\".\n", word[3]);
}
}
} else if (!strcmp(word[0], "move")) {
if (word[3] == NULL)
noproprun();
else if (!strcmp(word[1], "player")) {
push_stack(ftell(file), funcname);
if (!strcmp(word[3], "north")) {
destination = location[HERE]->north;
go_pointer = location[HERE]->go_north;
no_pointer = location[HERE]->no_north;
move_player(go_pointer, no_pointer);
} else if (!strcmp(word[3], "northeast")) {
destination = location[HERE]->northeast;
go_pointer = location[HERE]->go_northeast;
no_pointer = location[HERE]->no_northeast;
move_player(go_pointer, no_pointer);
} else if (!strcmp(word[3], "northwest")) {
destination = location[HERE]->northwest;
go_pointer = location[HERE]->go_northwest;
no_pointer = location[HERE]->no_northwest;
move_player(go_pointer, no_pointer);
} else if (!strcmp(word[3], "south")) {
destination = location[HERE]->south;
go_pointer = location[HERE]->go_south;
no_pointer = location[HERE]->no_south;
move_player(go_pointer, no_pointer);
} else if (!strcmp(word[3], "southeast")) {
destination = location[HERE]->southeast;
go_pointer = location[HERE]->go_southeast;
no_pointer = location[HERE]->no_southeast;
move_player(go_pointer, no_pointer);
} else if (!strcmp(word[3], "southwest")) {
destination = location[HERE]->southwest;
go_pointer = location[HERE]->go_southwest;
no_pointer = location[HERE]->no_southwest;
move_player(go_pointer, no_pointer);
} else if (!strcmp(word[3], "east")) {
destination = location[HERE]->east;
go_pointer = location[HERE]->go_east;
no_pointer = location[HERE]->no_east;
move_player(go_pointer, no_pointer);
} else if (!strcmp(word[3], "west")) {
destination = location[HERE]->west;
go_pointer = location[HERE]->go_west;
no_pointer = location[HERE]->no_west;
move_player(go_pointer, no_pointer);
} else if (!strcmp(word[3], "up")) {
destination = location[HERE]->up;
go_pointer = location[HERE]->go_up;
no_pointer = location[HERE]->no_up;
move_player(go_pointer, no_pointer);
} else if (!strcmp(word[3], "down")) {
destination = location[HERE]->down;
go_pointer = location[HERE]->go_down;
no_pointer = location[HERE]->no_down;
move_player(go_pointer, no_pointer);
} else if (!strcmp(word[3], "in")) {
destination = location[HERE]->in;
go_pointer = location[HERE]->go_in;
no_pointer = location[HERE]->no_in;
move_player(go_pointer, no_pointer);
} else if (!strcmp(word[3], "out")) {
destination = location[HERE]->out;
go_pointer = location[HERE]->go_out;
no_pointer = location[HERE]->no_out;
move_player(go_pointer, no_pointer);
} else {
unklocrun(3);
}
pop_stack();
} else if (index = object_resolve(1)) {
from = object[index]->location;
if (from > MAX_OBJECTS && from != LIMBO) {
object[from - MAX_OBJECTS]->info += object[index]->mass;
}
if (to = location_resolve(3))
object[index]->location = to;
else if (location_element_resolve(3))
object[index]->location = location_element_contents;
else if (to = object_resolve(3)) {
object[index]->location = to + MAX_OBJECTS;
object[to]->info -= object[index]->mass;
} else if (!strcmp(word[3], "limbo"))
object[index]->location = LIMBO;
else
unklocrun(3);
} else
unkobjrun(1);
} else if (!strcmp(word[0], "if")) {
current_level++;
if (word[3] == NULL)
noproprun(0);
else if (condition())
execution_level++;
} else
printf("ERROR: In function \"%s\", unknown command \"%s\".\n", funcname, word[0]);
} else if (!strcmp(word[wp], "if"))
current_level++;
fgets(text_buffer, 160, file);
};
return (TRUE);
}
pop_stack()
{
stack--;
strcpy(current_function, backup[stack].name);
current_level = backup[stack].current_level;
execution_level = backup[stack].execution_level;
fseek(file, backup[stack].address, SEEK_SET);
}
push_stack(file_pointer)
long file_pointer;
{
if (stack == STACK_SIZE) {
puts("ERROR: Stack overflow.");
terminate(1);
} else {
strcpy(backup[stack].name, current_function);
backup[stack].address = file_pointer;
backup[stack].current_level = current_level;
backup[stack].execution_level = execution_level;
}
stack++;
}
newline()
{
printf("\n");
scroll();
}
write_right(string)
char string[];
{
int index;
if (strlen(string) > screen_width)
puts(string);
else {
index = (screen_width - strlen(string));
index -= column;
if (index < 0)
index = 0;
for (; index != 0; index--)
printf(" ");
printf("%s", string);
}
}
write_centred(string)
char string[];
{
int index;
if (strlen(string) > screen_width)
puts(string);
else {
index = ((screen_width - strlen(string)) / 2);
for (; index != 0; index--)
printf(" ");
printf("%s", string);
}
}
write_text(tout_buffer)
char tout_buffer[];
{
char chunk_buffer[512];
int counter = 0;
int index;
for (index = 0; index < strlen(tout_buffer); index++) {
if (tout_buffer[index] != '^') {
chunk_buffer[counter] = tout_buffer[index];
counter++;
} else {
chunk_buffer[counter] = 0;
if (chunk_buffer[0] != 0)
output_text(chunk_buffer);
newline();
counter = 0;
}
}
chunk_buffer[counter] = 0;
output_text(chunk_buffer);
}
output_text(string)
char string[];
{
int index;
int done = FALSE;
char text_buffer[512];
char temporary_buffer[512];
char *pointer;
strcpy(text_buffer, string);
if (strlen(text_buffer) + column < screen_width) {
if (text_buffer[0] == 32 && column == 0) {
pointer = &text_buffer[1];
printj(pointer);
} else
printj(text_buffer);
} else {
for (index = screen_width - column; index > 0; index--) {
if (text_buffer[index] == 32) {
done = TRUE;
text_buffer[index] = 0;
if (text_buffer[0] == 32 && column == 0) {
pointer = &text_buffer[1];
printj(pointer);
} else
printj(text_buffer);
newline();
index++;
pointer = &text_buffer[index];
write_text(pointer);
break;
}
}
if (done == FALSE) {
if (column == 0) {
strncpy(temporary_buffer, text_buffer, screen_width);
printj(temporary_buffer);
newline();
pointer = &text_buffer[screen_width];
write_text(pointer);
} else {
newline();
write_text(text_buffer);
}
}
}
}
printj(output_string)
char output_string[];
{
int index;
for (index = 0; output_string[index] != 0; index++) {
if (output_string[index] == '~') {
printf("\"");
column++;
} else {
printf("%c", output_string[index]);
column++;
}
}
}
scroll()
{
column = 0;
row++;
if (row == screen_depth - 2)
more();
}
condition()
{
long compare = 0;
long index = 0;
int type = 0;
struct variable_type *resolved_variable;
if (word[3] == NULL) {
noproprun();
return (FALSE);
} else
compare = value_of(3);
if (index = object_resolve(1))
type = 1;
else if (index = location_resolve(1))
type = 2;
else if ((resolved_variable = variable_resolve(1)) != NULL)
index = resolved_variable->value;
else if (object_element_resolve(1))
index = oec;
else if (location_element_resolve(1))
index = location_element_contents;
if (!strcmp(word[2], "=")) {
if (index == compare)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(word[2], ">")) {
if (index > compare)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(word[2], "<")) {
if (index < compare)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(word[2], "is")) {
return (scope(index, word[3]));
} else if (!strcmp(word[2], "isnt")) {
return (!scope(index, word[3]));
} else if (!strcmp(word[2], "has")) {
if (type == 1)
index = object[index]->attributes;
else if (type == 2)
index = location[index]->attributes;
if (index & compare)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(word[2], "hasnt")) {
if (type == 1)
index = object[index]->attributes;
else if (type == 2)
index = location[index]->attributes;
if (index & compare)
return (FALSE);
else
return (TRUE);
} else if (!strcmp(word[2], "!=")) {
if (index != compare)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(word[2], ">=") || !strcmp(word[2], "=>")) {
if (index >= compare)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(word[2], "<=") || !strcmp(word[2], "=<")) {
if (index <= compare)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(word[2], "childof")) {
if (object[index]->location == compare + MAX_OBJECTS)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(word[2], "!childof")) {
if (object[index]->location != compare + MAX_OBJECTS)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(word[2], "grandof")) {
find_parent(compare);
if (parent == index)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(word[2], "!grandof")) {
find_parent(compare);
if (parent != index)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(word[2], "parentof")) {
if (object[index]->location == compare - MAX_OBJECTS)
return (TRUE);
else
return (FALSE);
} else if (!strcmp(word[2], "!parentof")) {
if (object[index]->location != compare - MAX_OBJECTS)
return (TRUE);
else
return (FALSE);
} else {
printf("ERROR: In function \"%s\", illegal operand \"%s\".\n", function_name, word[2]);
return (FALSE);
}
}
long value_of(index)
int index;
{
long compare = 0;
struct variable_type *resolved_variable;
if (!strcmp(word[index], "objects"))
return (MAX_OBJECTS);
else if (!strcmp(word[index], "limbo"))
return (LIMBO);
else if (!strcmp(word[index], "scenery"))
return (SCENERY);
else if (!strcmp(word[index], "heavy"))
return (HEAVY);
else if (!strcmp(word[index], "true"))
return (TRUE);
else if (!strcmp(word[index], "false"))
return (FALSE);
else if (!strcmp(word[index], "nowhere"))
return (FALSE);
else if ((resolved_variable = variable_resolve(index)) != NULL)
return (resolved_variable->value);
else if (object_element_resolve(index))
return (oec);
else if (location_element_resolve(index))
return (location_element_contents);
else if (compare = attribute_resolve(index))
return (compare);
else if (compare = object_resolve(index))
return (compare);
else if (compare = location_resolve(index))
return (compare);
else
return (atoi(word[index]));
}
struct variable_type *
variable_resolve(wordno)
int wordno;
{
struct variable_type *pointer = variable_table;
do {
if (!strcmp(word[wordno], pointer->name))
return (pointer);
else
pointer = pointer->next_variable;
}
while (pointer != NULL);
return (NULL);
}
struct function_type *
function_resolve(name)
char *name;
{
struct function_type *pointer = function_table;
if (function_table == NULL)
return (NULL);
do {
if (!strcmp(name, pointer->name))
return (pointer);
else
pointer = pointer->next_function;
}
while (pointer != NULL);
return (NULL);
}
object_element_resolve(wordno)
int wordno;
{
int index;
int delimiter = 0;
int match = 0;
char wordtemp[161];
strcpy(wordtemp, word[wordno]);
if (!strncmp(wordtemp, "noun1(", 6)) {
if (noun[0] != FALSE) {
index = noun[0];
delimiter = 5;
match = TRUE;
}
} else if (!strncmp(wordtemp, "noun2(", 6)) {
index = noun[1];
delimiter = 5;
match = TRUE;
} else if (!strncmp(wordtemp, "noun3(", 6)) {
index = noun[2];
delimiter = 5;
match = TRUE;
} else if (!strncmp(wordtemp, "noun4(", 6)) {
index = noun[3];
delimiter = 5;
match = TRUE;
} else if (!strncmp(wordtemp, "player(", 7)) {
index = CURRENT_PLAYER->value;
delimiter = 6;
match = TRUE;
} else {
for (index = 0; index < strlen(wordtemp); index++) {
if (wordtemp[index] == 40) {
delimiter = index;
wordtemp[index] = 0;
break;
}
}
if (delimiter) {
for (index = 1; index <= objects; index++) {
if (!strcmp(wordtemp, object[index]->label)) {
match = TRUE;
break;
}
}
}
}
if (match) {
delimiter++;
if (!strcmp(&wordtemp[delimiter], "mass)")) {
oec = object[index]->mass;
object_element_address = &object[index]->mass;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "info)")) {
oec = object[index]->info;
object_element_address = &object[index]->info;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "location)")) {
object_element_address = &object[index]->location;
oec = object[index]->location;
return (TRUE);
}
}
return (FALSE);
}
location_element_resolve(wordno)
int wordno;
{
int index;
int delimiter = 0;
int match = 0;
char wordtemp[161];
strcpy(wordtemp, word[wordno]);
if (!strncmp(wordtemp, "here(", 5)) {
index = HERE;
delimiter = 4;
match = TRUE;
} else {
for (index = 0; index < strlen(wordtemp); index++) {
if (wordtemp[index] == 40) {
delimiter = index;
wordtemp[index] = 0;
break;
}
}
if (delimiter) {
for (index = 1; index <= locations; index++) {
if (!strcmp(wordtemp, location[index]->label)) {
match = TRUE;
break;
}
}
}
}
if (match) {
delimiter++;
if (!strcmp(&wordtemp[delimiter], "north)")) {
location_element_contents = location[index]->north;
location_element_address = &location[index]->north;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "northeast)")) {
location_element_contents = location[index]->northeast;
location_element_address = &location[index]->northeast;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "northwest)")) {
location_element_contents = location[index]->northwest;
location_element_address = &location[index]->northwest;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "south)")) {
location_element_contents = location[index]->south;
location_element_address = &location[index]->south;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "southeast)")) {
location_element_contents = location[index]->southeast;
location_element_address = &location[index]->southeast;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "southwest)")) {
location_element_contents = location[index]->southwest;
location_element_address = &location[index]->southwest;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "east)")) {
location_element_contents = location[index]->east;
location_element_address = &location[index]->east;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "west)")) {
location_element_contents = location[index]->west;
location_element_address = &location[index]->west;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "up)")) {
location_element_contents = location[index]->up;
location_element_address = &location[index]->up;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "down)")) {
location_element_contents = location[index]->down;
location_element_address = &location[index]->down;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "in)")) {
location_element_contents = location[index]->in;
location_element_address = &location[index]->in;
return (TRUE);
} else if (!strcmp(&wordtemp[delimiter], "out)")) {
location_element_contents = location[index]->out;
location_element_address = &location[index]->out;
return (TRUE);
}
}
return (FALSE);
}
object_resolve(wordno)
int wordno;
{
int index;
if (!strcmp(word[wordno], "noun1"))
return (noun[0]);
else if (!strcmp(word[wordno], "noun2"))
return (noun[1]);
else if (!strcmp(word[wordno], "noun3"))
return (noun[2]);
else if (!strcmp(word[wordno], "noun4"))
return (noun[3]);
else if (!strcmp(word[wordno], "player"))
return (CURRENT_PLAYER->value);
else {
for (index = 1; index <= objects; index++) {
if (!strcmp(word[wordno], object[index]->label))
return (index);
}
}
return (FALSE);
}
location_resolve(wordno)
int wordno;
{
int index;
if (!strcmp(word[wordno], "here"))
return (HERE);
if (!strcmp(word[wordno], "destination"))
return (destination);
for (index = 1; index <= locations; index++) {
if (!strcmp(word[wordno], location[index]->label))
return (index);
}
return (FALSE);
}
restart_game()
{
int index;
struct variable_type *current_variable;
struct variable_type *previous_variable;
struct name_type *current_name;
struct name_type *next_name;
restarting = TRUE;
for (index = 1; index <= objects; index++) {
current_name = object[index]->first_name;
while (current_name->next_name != NULL) {
next_name = current_name->next_name;
free(current_name);
current_name = next_name;
}
free(current_name);
free(object[index]);
}
for (index = 1; index <= locations; index++)
free(location[index]);
do {
current_variable = variable_table;
previous_variable = variable_table;
while (current_variable->next_variable != NULL) {
previous_variable = current_variable;
current_variable = current_variable->next_variable;
}
free(current_variable);
previous_variable->next_variable = NULL;
}
while (previous_variable != variable_table);
free(variable_table);
variable_table = NULL;
read_gamefile();
row = 0;
strcpy(function_name, "{global_intro");
execute(function_name);
}
read_gamefile()
{
int index, reference, errors;
int object_count, location_count;
int last = 0;
int line = 0;
long start_of_file = 0;
long current_file_position = 0;
long bit_mask;
struct filter_type *current_filter;
struct filter_type *new_filter;
struct synonym_type *current_synonym;
struct synonym_type *new_synonym;
struct function_type *current_function;
struct variable_type *current_variable;
struct name_type *current_name;
char function_name[81];
if ((variable_table = (struct variable_type *) malloc(sizeof(struct variable_type))) == NULL)
outofmem();
CURRENT_PLAYER = variable_table;
for (index = 1; index < 6; index++) {
if ((variable[index] = (struct variable_type *) malloc(sizeof(struct variable_type))) == NULL)
outofmem();
variable[index - 1]->next_variable = variable[index];
}
current_variable = DISPLAY_MODE;
errors = FALSE;
objects = 0;
locations = 0;
fseek(file, start_of_file, SEEK_SET);
fgets(text_buffer, 160, file);
line++;
while (!feof(file)) {
encapsulate();
if (word[0] == NULL);
else if (text_buffer[0] == 123 && restarting == FALSE) {
while (word[wp] != NULL) {
if (!strncmp(text_buffer, "{global_", 8)) {
strncpy(function_name, word[wp], 80);
function_name[80] = 0;
} else if (last == 0) {
printf("ERROR: In line %d, non-global function before object or location.\n", line);
errors++;
} else if (last == 1) {
if (word[wp][0] == 123)
function_name[0] = 0;
else
strcpy(function_name, "{");
strncat(function_name, word[wp], 39);
strcat(function_name, "_");
strcat(function_name, location[locations]->label);
} else if (last == 2) {
if (word[wp][0] == 123)
function_name[0] = 0;
else
strcpy(function_name, "{");
strncat(function_name, word[wp], 59);
strcat(function_name, "_");
strcat(function_name, object[objects]->label);
}
if (function_table == NULL) {
if ((function_table = (struct function_type *) malloc(sizeof(struct function_type))) == NULL)
outofmem();
else {
current_function = function_table;
strcpy(current_function->name, function_name);
current_function->position = ftell(file);
current_function->next_function = NULL;
}
} else {
if ((current_function->next_function = (struct function_type *) malloc(sizeof(struct function_type))) == NULL)
outofmem();
else {
current_function = current_function->next_function;
strcpy(current_function->name, function_name);
current_function->position = ftell(file);
current_function->next_function = NULL;
}
}
wp++;
}
while (!feof(file)) {
fgets(text_buffer, 160, file);
line++;
if (text_buffer[0] == 125)
break;
}
} else {
if (!strcmp(word[0], "grammar") && restarting == FALSE) {
if (word[++wp] == NULL) {
noproperr(line);
errors++;
} else {
if (grammar_table == NULL) {
if ((grammar_table = (struct word_type *) malloc(sizeof(struct word_type))) == NULL)
outofmem();
else {
strncpy(grammar_table->word, word[wp], 20);
grammar_table->word[20] = 0;
grammar_table->next_sibling = NULL;
grammar_table->first_child = NULL;
build_grammar_table(grammar_table);
}
} else
build_grammar_table(grammar_table);
}
} else if (!strcmp(word[0], "location")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else {
locations++;
if (locations == MAX_OBJECTS) {
printf("ERROR: Maximum number of locations exceeded, can't continue.\n");
} else {
if ((location[locations] = (struct location_type *) malloc(sizeof(struct location_type))) == NULL)
outofmem();
strncpy(location[locations]->label, word[1], 20);
location[locations]->label[20] = 0;
last = 1;
}
}
} else if (!strcmp(word[0], "object")) {
if (word[2] == NULL) {
noproperr(line);
terminate(1);
} else {
objects++;
if (objects == MAX_OBJECTS) {
printf("ERROR: Maximum number of objects exceeded, can't continue.\n");
terminate(1);
} else {
if ((object[objects] = (struct object_type *) malloc(sizeof(struct object_type))) == NULL)
outofmem();
strncpy(object[objects]->label, word[1], 20);
object[objects]->label[20] = 0;
if (locations == 0)
object[objects]->location = 1;
else
object[objects]->location = locations;
last = 2;
}
}
} else if (!strcmp(word[0], "synonym") && restarting == FALSE) {
if (word[++wp] == NULL) {
noproperr(line);
errors++;
} else {
if ((new_synonym = (struct synonym_type *) malloc(sizeof(struct synonym_type))) == NULL)
outofmem();
else {
if (synonym_table == NULL) {
synonym_table = new_synonym;
} else {
current_synonym->next_synonym = new_synonym;
}
}
current_synonym = new_synonym;
strncpy(current_synonym->original, word[wp], 20);
current_synonym->original[20] = 0;
if (word[++wp] == NULL) {
noproperr(line);
errors++;
} else {
strncpy(current_synonym->standard, word[wp], 20);
current_synonym->standard[20] = 0;
}
current_synonym->next_synonym = NULL;
}
} else if (!strcmp(word[0], "filter") && restarting == FALSE) {
if (word[++wp] == NULL) {
noproperr(line);
errors++;
} else {
if ((new_filter = (struct filter_type *) malloc(sizeof(struct filter_type))) == NULL)
outofmem();
else {
if (filter_table == NULL) {
filter_table = new_filter;
} else {
current_filter->next_filter = new_filter;
}
current_filter = new_filter;
strncpy(current_filter->word, word[wp], 20);
current_filter->word[20] = 0;
current_filter->next_filter = NULL;
}
}
} else if (!strcmp(word[0], "variable")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else {
if ((current_variable->next_variable = (struct variable_type *) malloc(sizeof(struct variable_type))) == NULL)
outofmem();
else {
current_variable = current_variable->next_variable;
strncpy(current_variable->name, word[1], 20);
current_variable->name[20] = 0;
current_variable->next_variable = NULL;
}
if (word[2] != NULL) {
if (!strcmp(word[2], "true"))
current_variable->value = TRUE;
else if (!strcmp(word[2], "false"))
current_variable->value = FALSE;
else
current_variable->value = atoi(word[2]);
} else
current_variable->value = FALSE;
}
}
}
fgets(text_buffer, 160, file);
line++;
}
setdefaults();
fseek(file, start_of_file, SEEK_SET);
object_count = 0;
location_count = 0;
line = 0;
fgets(text_buffer, 160, file);
line++;
while (!feof(file)) {
if (text_buffer[0] == 123) {
while (!feof(file)) {
fgets(text_buffer, 160, file);
line++;
if (text_buffer[0] == 125)
break;
}
} else {
encapsulate();
if (word[0] == NULL);
else if (!strcmp(word[0], "variable"));
else if (!strcmp(word[0], "synonym"));
else if (!strcmp(word[0], "grammar"));
else if (!strcmp(word[0], "filter"));
else if (!strcmp(word[0], "has")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else {
for (index = 1; word[index] != NULL; index++) {
if (bit_mask = attribute_resolve(index)) {
if (last == 0);
else if (last == 1)
location[location_count]->attributes += bit_mask;
else if (last == 2)
object[object_count]->attributes += bit_mask;
} else {
unkkeyerr(line, index);
errors++;
}
}
}
} else if (!strcmp(word[0], "location")) {
location_count++;
last = 1;
} else if (!strcmp(word[0], "object")) {
object_count++;
last = 2;
if ((object[object_count]->first_name = (struct name_type *) malloc(sizeof(struct name_type))) == NULL)
outofmem();
else {
current_name = object[object_count]->first_name;
strncpy(current_name->name, word[2], 20);
current_name->name[20] = 0;
current_name->next_name = NULL;
}
wp = 3;
while (word[wp] != NULL) {
if ((current_name->next_name = (struct name_type *) malloc(sizeof(struct name_type))) == NULL)
outofmem();
else {
current_name = current_name->next_name;
strncpy(current_name->name, word[wp], 20);
current_name->name[20] = 0;
current_name->next_name = NULL;
}
wp++;
}
} else if (!strcmp(word[0], "no_go")) {
location[location_count]->no_go = current_file_position;
} else if (!strcmp(word[0], "northeast")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "nowhere"));
else {
if (reference = location_resolve(1)) {
location[location_count]->northeast = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
} else if (!strcmp(word[0], "no_northeast")) {
location[location_count]->no_northeast = current_file_position;
} else if (!strcmp(word[0], "go_northeast")) {
location[location_count]->go_northeast = current_file_position;
} else if (!strcmp(word[0], "northwest")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "nowhere"));
else {
if (reference = location_resolve(1)) {
location[location_count]->northwest = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
} else if (!strcmp(word[0], "no_northwest")) {
location[location_count]->no_northwest = current_file_position;
} else if (!strcmp(word[0], "go_northwest")) {
location[location_count]->go_northwest = current_file_position;
} else if (!strcmp(word[0], "southeast")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "nowhere"));
else {
if (reference = location_resolve(1)) {
location[location_count]->southeast = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
} else if (!strcmp(word[0], "no_southeast")) {
location[location_count]->no_southeast = current_file_position;
} else if (!strcmp(word[0], "go_southeast")) {
location[location_count]->go_southeast = current_file_position;
} else if (!strcmp(word[0], "southwest")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "nowhere"));
else {
if (reference = location_resolve(1)) {
location[location_count]->southwest = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
} else if (!strcmp(word[0], "no_southwest")) {
location[location_count]->no_southwest = current_file_position;
} else if (!strcmp(word[0], "go_southwest")) {
location[location_count]->go_southwest = current_file_position;
} else if (!strcmp(word[0], "in")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "nowhere"));
else {
if (reference = location_resolve(1)) {
location[location_count]->in = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
} else if (!strcmp(word[0], "no_in")) {
location[location_count]->no_in = current_file_position;
} else if (!strcmp(word[0], "go_in")) {
location[location_count]->go_in = current_file_position;
} else if (!strcmp(word[0], "out")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "nowhere"));
else {
if (reference = location_resolve(1)) {
location[location_count]->out = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
} else if (!strcmp(word[0], "no_out")) {
location[location_count]->no_out = current_file_position;
} else if (!strcmp(word[0], "go_out")) {
location[location_count]->go_out = current_file_position;
} else if (!strcmp(word[0], "up")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "nowhere"));
else {
if (reference = location_resolve(1)) {
location[location_count]->up = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
} else if (!strcmp(word[0], "no_up")) {
location[location_count]->no_up = current_file_position;
} else if (!strcmp(word[0], "go_up")) {
location[location_count]->go_up = current_file_position;
} else if (!strcmp(word[0], "down")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "nowhere"));
else {
if (reference = location_resolve(1)) {
location[location_count]->down = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
} else if (!strcmp(word[0], "no_down")) {
location[location_count]->no_down = current_file_position;
} else if (!strcmp(word[0], "go_down")) {
location[location_count]->go_down = current_file_position;
} else if (!strcmp(word[0], "north")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "nowhere"));
else {
if (reference = location_resolve(1)) {
location[location_count]->north = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
} else if (!strcmp(word[0], "no_north")) {
location[location_count]->no_north = current_file_position;
} else if (!strcmp(word[0], "go_north")) {
location[location_count]->go_north = current_file_position;
} else if (!strcmp(word[0], "south")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "nowhere"));
else {
if (reference = location_resolve(1)) {
location[location_count]->south = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
} else if (!strcmp(word[0], "no_south")) {
location[location_count]->no_south = current_file_position;
} else if (!strcmp(word[0], "go_south")) {
location[location_count]->go_south = current_file_position;
} else if (!strcmp(word[0], "east")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "nowhere"));
else {
if (reference = location_resolve(1)) {
location[location_count]->east = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
} else if (!strcmp(word[0], "no_east")) {
location[location_count]->no_east = current_file_position;
} else if (!strcmp(word[0], "go_east")) {
location[location_count]->go_east = current_file_position;
} else if (!strcmp(word[0], "west")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "nowhere"));
else {
if (reference = location_resolve(1)) {
location[location_count]->west = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
} else if (!strcmp(word[0], "no_west")) {
location[location_count]->no_west = current_file_position;
} else if (!strcmp(word[0], "go_west")) {
location[location_count]->go_west = current_file_position;
} else if (!strcmp(word[0], "inventory")) {
if (word[2] == NULL) {
noproperr(line);
errors++;
} else {
strncpy(object[object_count]->article, word[1], 10);
object[object_count]->article[10] = 0;
strncpy(object[object_count]->inventory, word[2], 40);
object[object_count]->inventory[40] = 0;
}
} else if (!strcmp(word[0], "described")) {
strncpy(object[object_count]->described, word[1], 80);
object[object_count]->described[80] = 0;
} else if (!strcmp(word[0], "initial")) {
strncpy(object[object_count]->initial, word[1], 80);
object[object_count]->initial[80] = 0;
} else if (!strcmp(word[0], "starts")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "childof")) {
if (word[2] == NULL) {
noproperr(line);
errors++;
} else if (reference = object_resolve(2)) {
object[object_count]->location = reference + MAX_OBJECTS;
} else {
unkobjerr(line, 2);
errors++;
}
} else {
if (!strcmp(word[1], "limbo"))
object[object_count]->location = LIMBO;
else if (!strcmp(word[1], "here"))
object[object_count]->location = location_count;
else {
if (reference = location_resolve(1)) {
object[object_count]->location = reference;
} else {
unklocerr(line, 1);
errors++;
}
}
}
} else if (!strcmp(word[0], "quantity")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else
object[object_count]->info = atoi(word[1]);
} else if (!strcmp(word[0], "mass")) {
if (word[1] == NULL) {
noproperr(line);
errors++;
} else if (!strcmp(word[1], "scenery"))
object[object_count]->mass = SCENERY;
else if (!strcmp(word[1], "heavy"))
object[object_count]->mass = HEAVY;
else
object[object_count]->mass = atoi(word[1]);
} else {
unkkeyerr(line, 0);
errors++;
}
}
current_file_position = ftell(file);
fgets(text_buffer, 160, file);
line++;
}
if (errors) {
newline();
if (errors == 1)
printf("1 error detected.\n");
else
printf("%d errors detected.\n", errors);
terminate(1);
}
}
build_grammar_table(pointer)
struct word_type *pointer;
{
do {
if (!strcmp(word[wp], pointer->word)) {
if (pointer->first_child == NULL && word[wp + 1] != NULL) {
if ((pointer->first_child = (struct word_type *) malloc(sizeof(struct word_type))) == NULL)
outofmem();
else {
pointer = pointer->first_child;
strncpy(pointer->word, word[++wp], 20);
pointer->word[20] = 0;
pointer->next_sibling = NULL;
pointer->first_child = NULL;
}
} else {
pointer = pointer->first_child;
wp++;
}
} else {
if (pointer->next_sibling == NULL) {
if ((pointer->next_sibling = (struct word_type *) malloc(sizeof(struct word_type))) == NULL)
outofmem();
else {
pointer = pointer->next_sibling;
strncpy(pointer->word, word[wp], 20);
pointer->word[20] = 0;
pointer->next_sibling = NULL;
pointer->first_child = NULL;
}
} else
pointer = pointer->next_sibling;
}
}
while (word[wp] != NULL);
}
unkfunrun(name)
char *name;
{
printf("ERROR: Attempt to execute unknown function \"%s\".\n", name);
}
unkkeyerr(line, wordno)
int line;
int wordno;
{
printf("ERROR: In line %d, unknown keyword \"%s\".\n", line, word[wordno]);
}
noproprun()
{
printf("ERROR: In function \"%s\", \"%s\" command with insufficient arguments.\n", current_function, word[0]);
}
noproperr(line)
int line;
{
printf("ERROR: In line %d, \"%s\" keyword with insufficient arguments.\n", line, word[0]);
}
unklocerr(line, wordno)
int line;
int wordno;
{
printf("ERROR: In line %d, reference to undefined location \"%s\".\n", line, word[wordno]);
}
unklocrun(wordno)
int wordno;
{
printf("ERROR: In function \"%s\", reference to undefined location \"%s\".\n", current_function, word[wordno]);
}
unkobjerr(line, wordno)
int line;
int wordno;
{
printf("ERROR: In line %d, reference to undefined object \"%s\".\n", line, word[wordno]);
}
unkobjrun(wordno)
int wordno;
{
printf("ERROR: In function \"%s\", reference to undefined object \"%s\".\n", current_function, word[wordno]);
}
unkvarrun(wordno)
int wordno;
{
printf("ERROR: In function \"%s\", reference to undefined variable \"%s\".\n", current_function, word[wordno]);
}
outofmem()
{
printf("ERROR: Out of memory, can't continue.\n");
terminate(1);
}
long attribute_resolve(wordno)
int wordno;
{
if (!strcmp(word[wordno], "VISITED"))
return (1);
else if (!strcmp(word[wordno], "DARK"))
return (2);
else if (!strcmp(word[wordno], "ON_WATER"))
return (4);
else if (!strcmp(word[wordno], "UNDER_WATER"))
return (8);
else if (!strcmp(word[wordno], "WITHOUT_AIR"))
return (16);
else if (!strcmp(word[wordno], "OUTDOORS"))
return (32);
else if (!strcmp(word[wordno], "MID_AIR"))
return (64);
else if (!strcmp(word[wordno], "TIGHT_ROPE"))
return (128);
else if (!strcmp(word[wordno], "POLLUTED"))
return (256);
else if (!strcmp(word[wordno], "SOLVED"))
return (512);
else if (!strcmp(word[wordno], "MID_WATER"))
return (1024);
else if (!strcmp(word[wordno], "CLOSED"))
return (1);
else if (!strcmp(word[wordno], "LOCKED"))
return (2);
else if (!strcmp(word[wordno], "DEAD"))
return (4);
else if (!strcmp(word[wordno], "EDIBLE"))
return (8);
else if (!strcmp(word[wordno], "WORN"))
return (16);
else if (!strcmp(word[wordno], "CONCEALING"))
return (32);
else if (!strcmp(word[wordno], "LUMINOUS"))
return (64);
else if (!strcmp(word[wordno], "WEARABLE"))
return (128);
else if (!strcmp(word[wordno], "CLOSABLE"))
return (256);
else if (!strcmp(word[wordno], "LOCKABLE"))
return (512);
else if (!strcmp(word[wordno], "ANIMATE"))
return (1024);
else if (!strcmp(word[wordno], "LIQUID"))
return (2048);
else if (!strcmp(word[wordno], "CONTAINER"))
return (4096);
else if (!strcmp(word[wordno], "SURFACE"))
return (8192);
else if (!strcmp(word[wordno], "PLURAL"))
return (16384);
else if (!strcmp(word[wordno], "FLAMMABLE"))
return (32768);
else if (!strcmp(word[wordno], "BURNING"))
return (65536);
else if (!strcmp(word[wordno], "SWITCHABLE"))
return (131072);
else if (!strcmp(word[wordno], "ON"))
return (262144);
else if (!strcmp(word[wordno], "DAMAGED"))
return (524288);
else if (!strcmp(word[wordno], "FEMALE"))
return (1048576);
else if (!strcmp(word[wordno], "POSSESSIVE"))
return (2097152);
else if (!strcmp(word[wordno], "OUT_OF_REACH"))
return (4194304);
else if (!strcmp(word[wordno], "TOUCHED"))
return (8388608);
else if (!strcmp(word[wordno], "SCORED"))
return (16777216);
else if (!strcmp(word[wordno], "SITTING"))
return (33554432);
else if (!strcmp(word[wordno], "CUSTOM1"))
return (67108864);
else if (!strcmp(word[wordno], "CUSTOM2"))
return (134217728);
else if (!strcmp(word[wordno], "CUSTOM3"))
return (268435456);
else if (!strcmp(word[wordno], "CUSTOM4"))
return (536870912);
else if (!strcmp(word[wordno], "CUSTOM5"))
return (1073741824);
else
return (0);
}
setdefaults()
{
int index;
strcpy(CURRENT_PLAYER->name, "CURRENT_PLAYER");
CURRENT_PLAYER->value = 0;
strcpy(TOTAL_MOVES->name, "TOTAL_MOVES");
TOTAL_MOVES->value = 0;
strcpy(TURN_WORKED->name, "TURN_WORKED");
TURN_WORKED->value = FALSE;
strcpy(CURRENT_SCORE->name, "CURRENT_SCORE");
CURRENT_SCORE->value = 0;
strcpy(DISPLAY_MODE->name, "DISPLAY_MODE");
DISPLAY_MODE->value = 0;
strcpy(INTERNAL_VERSION->name, "INTERNAL_VERSION");
INTERNAL_VERSION->value = VERSION;
for (index = 1; index <= objects; index++) {
strcpy(object[index]->described, object[index]->label);
object[index]->initial[0] = 0;
strcpy(object[index]->inventory, object[index]->label);
object[index]->attributes = FALSE;
object[index]->info = 0;
object[index]->mass = SCENERY;
}
for (index = 1; index <= locations; index++) {
location[index]->in = FALSE;
location[index]->out = FALSE;
location[index]->north = FALSE;
location[index]->northeast = FALSE;
location[index]->northwest = FALSE;
location[index]->south = FALSE;
location[index]->southeast = FALSE;
location[index]->southwest = FALSE;
location[index]->east = FALSE;
location[index]->west = FALSE;
location[index]->up = FALSE;
location[index]->down = FALSE;
location[index]->go_north = FALSE;
location[index]->go_northeast = FALSE;
location[index]->go_northwest = FALSE;
location[index]->go_south = FALSE;
location[index]->go_southeast = FALSE;
location[index]->go_southwest = FALSE;
location[index]->go_east = FALSE;
location[index]->go_west = FALSE;
location[index]->go_up = FALSE;
location[index]->go_down = FALSE;
location[index]->go_in = FALSE;
location[index]->go_out = FALSE;
location[index]->no_north = FALSE;
location[index]->no_northeast = FALSE;
location[index]->no_northwest = FALSE;
location[index]->no_south = FALSE;
location[index]->no_southeast = FALSE;
location[index]->no_southwest = FALSE;
location[index]->no_east = FALSE;
location[index]->no_west = FALSE;
location[index]->no_up = FALSE;
location[index]->no_down = FALSE;
location[index]->no_in = FALSE;
location[index]->no_out = FALSE;
location[index]->no_go = FALSE;
location[index]->attributes = FALSE;
}
}
no_it()
{
char buffer[200];
strcpy(buffer, "You must have referred to an appropriate noun previously to use the word \"");
strcat(buffer, word[wp]);
strcat(buffer, "\".");
write_text(buffer);
newline();
custom_error = TRUE;
}
noun_resolve(pointer)
struct word_type *pointer;
{
int word_found, index, counter;
int matches = 0;
int confidence[MAX_OBJECTS];
int highest_confidence = 0;
int prime_suspect = 0;
int name_found = FALSE;
int done = FALSE;
int backup_pointer = wp;
short int last_word = FALSE;
struct word_type *options = pointer;
struct word_type *terminator = options->first_child;
struct name_type *current_name;
char buffer[200];
if (!strncmp("it", word[wp], significance)) {
if (it)
return (it);
else {
no_it();
return (FALSE);
}
} else if (!strncmp("them", word[wp], significance)) {
if (them)
return (them);
else {
no_it();
return (FALSE);
}
} else if (!strncmp("him", word[wp], significance)) {
if (him)
return (him);
else {
no_it();
return (FALSE);
}
} else if (!strncmp("her", word[wp], significance)) {
if (her)
return (her);
else {
no_it();
return (FALSE);
}
}
if (!strncmp("itself", word[wp], significance) || !strncmp("themselves", word[wp], significance) || !strncmp("himself", word[wp], significance) || !strncmp("herself", word[wp], significance) || !strncmp("yourself", word[wp], significance)) {
if (noun[0] == FALSE) {
strcpy(buffer, "You must have referred to a noun previously in the same sentence to use the word \"");
strcat(buffer, word[wp]);
strcat(buffer, "\".");
write_text(buffer);
newline();
custom_error = TRUE;
return (FALSE);
} else
return (noun[0]);
}
for (index = 1; index <= objects; index++)
confidence[index] = 1;
while (word[wp] != NULL && last_word != TRUE) {
if (punctuation[wp] != 0) {
last_word = TRUE;
} else if (options != NULL) {
do {
if (!strncmp(word[wp], options->word, significance)) {
if (!matches)
return (FALSE);
else {
done = TRUE;
break;
}
}
}
while ((options = options->next_sibling) != NULL);
}
if (done == TRUE) {
break;
}
for (index = 1; index <= objects; index++) {
if (!confidence[index])
continue;
word_found = FALSE;
current_name = object[index]->first_name;
while (current_name != NULL) {
if (!strncmp(word[wp], current_name->name, significance)) {
word_found = TRUE;
name_found = TRUE;
options = terminator;
break;
}
current_name = current_name->next_name;
}
if (word_found) {
if (confidence[index] == 1)
matches++;
if (confidence[index] != FALSE)
confidence[index]++;
} else {
if (confidence[index] > 1)
matches--;
confidence[index] = FALSE;
}
}
if (!name_found && !matches)
break;
wp++;
name_found = FALSE;
}
wp--;
if (matches == 0) {
object_expected = TRUE;
wp = backup_pointer;
return (FALSE);
}
for (index = 1; index <= objects; index++) {
if (confidence[index] != FALSE && strcmp(pointer->word, "*anywhere")) {
if (scope(index, "*present") == FALSE) {
matches--;
confidence[index] = FALSE;
}
}
if (confidence[index] != FALSE) {
current_name = object[index]->first_name;
counter = 0;
while (current_name != NULL) {
counter++;
current_name = current_name->next_name;
}
confidence[index] = ((confidence[index] - 1) * 100) / counter;
if (confidence[index] > highest_confidence)
highest_confidence = confidence[index];
}
}
if (matches > 1) {
for (index = 1; index <= objects; index++) {
if (confidence[index] != FALSE) {
if (confidence[index] < highest_confidence) {
confidence[index] = FALSE;
matches--;
}
}
}
}
for (index = 1; index <= objects; index++) {
if (confidence[index] != FALSE) {
if (scope(index, "*present") != FALSE)
prime_suspect = index;
if (scope(index, pointer->word) == FALSE) {
matches--;
confidence[index] = FALSE;
}
}
}
if (matches == 0) {
if (prime_suspect != FALSE) {
if (!(object[prime_suspect]->attributes & 1024))
it = prime_suspect;
if (object[prime_suspect]->attributes & 16384)
them = prime_suspect;
if (object[prime_suspect]->attributes & 1024 && object[prime_suspect]->attributes & 1048576)
her = prime_suspect;
if (object[prime_suspect]->attributes & 1024 && !(object[prime_suspect]->attributes & 1048576))
him = prime_suspect;
return (prime_suspect);
} else {
object_expected = TRUE;
wp = backup_pointer;
return (FALSE);
}
}
if (matches == 1) {
for (index = 1; index <= objects; index++) {
if (confidence[index] != FALSE) {
if (!(object[index]->attributes & 1024))
it = index;
if (object[index]->attributes & 16384)
them = index;
if (object[index]->attributes & 1024 && object[index]->attributes & 1048576)
her = index;
if (object[index]->attributes & 1024 && !(object[index]->attributes & 1048576))
him = index;
return (index);
}
}
}
strcpy(write_buffer, "Are you referring to ");
for (index = 1; index <= objects; index++) {
if (confidence[index] != FALSE) {
sentence_output(index, 0);
matches--;
if (matches == 1)
strcat(write_buffer, " or ");
else if (matches > 1)
strcat(write_buffer, ", ");
}
}
strcat(write_buffer, "?^");
write_text(write_buffer);
custom_error = TRUE;
return (FALSE);
}
#ifndef POWERC
clrscrn()
{
int y = screen_depth;
for (; y >= 0; y--)
printf("\n");
}
more()
{
write_centred("---[PRESS ENTER]---");
getchar();
row = 0;
}
#else
more()
{
int index;
int y;
y = cursrow();
write_centred("---[MORE]---");
kbhit();
getch();
poscurs(y, 0);
for (index = 0; index < screen_width; index++)
printf(" ");
poscurs(y, 0);
row = 0;
}
#endif