#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 #include #ifdef POWERC #include #include #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