aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/archetype/sys_object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/archetype/sys_object.cpp')
-rw-r--r--engines/glk/archetype/sys_object.cpp305
1 files changed, 305 insertions, 0 deletions
diff --git a/engines/glk/archetype/sys_object.cpp b/engines/glk/archetype/sys_object.cpp
new file mode 100644
index 0000000000..c30a1b87f6
--- /dev/null
+++ b/engines/glk/archetype/sys_object.cpp
@@ -0,0 +1,305 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "glk/archetype/sys_object.h"
+#include "glk/archetype/archetype.h"
+#include "glk/archetype/game_stat.h"
+#include "glk/archetype/heap_sort.h"
+#include "glk/archetype/parser.h"
+#include "glk/archetype/wrap.h"
+#include "common/algorithm.h"
+#include "common/savefile.h"
+
+namespace Glk {
+namespace Archetype {
+
+enum SysStateType {
+ IDLING, INIT_SORTER, OPEN_SORTER, CLOSE_SORTER, NEXT_SORTED, PLAYER_CMD,
+ NORMALIZE, ABBR, OPEN_PARSER, VERB_LIST, NOUN_LIST, CLOSE_PARSER, INIT_PARSER,
+ WHICH_OBJECT, ROLL_CALL, PRESENT, PARSE, NEXT_OBJECT, DEBUG_MESSAGES,
+ DEBUG_EXPRESSIONS, DEBUG_STATEMENTS, DEBUG_MEMORY, FREE_MEMORY, SAVE_STATE, LOAD_STATE
+};
+
+const char *const StateLookup[LOAD_STATE + 1] = {
+ "IDLING", "INIT SORTER", "OPEN SORTER", "CLOSE SORTER", "NEXT SORTED", "PLAYER CMD",
+ "NORMALIZE", "ABBR", "OPEN PARSER", "VERB LIST", "NOUN LIST", "CLOSE PARSER", "INIT PARSER",
+ "WHICH OBJECT", "ROLL CALL", "PRESENT", "PARSE", "NEXT OBJECT", "DEBUG MESSAGES",
+ "DEBUG EXPRESSIONS", "DEBUG STATEMENTS", "DEBUG MEMORY", "FREE MEMORY", "SAVE STATE", "LOAD STATE"
+};
+
+// Global variables which retain the state of the system object between calls
+SysStateType sys_state;
+TargetListType target_list;
+
+void sys_object_init() {
+ sys_state = IDLING;
+ target_list = PARSER_VERBLIST;
+}
+
+static bool figure_state(const String &s) {
+ for (int st = IDLING; st <= LOAD_STATE; ++st) {
+ if (StateLookup[st] == s) {
+ sys_state = (SysStateType)st;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void send_to_system(int transport, String &strmsg, ResultType &result, ContextType &context) {
+ int the_caller;
+ int obj_index;
+ String nomatch;
+ NodePtr np;
+ void *p;
+
+ if (transport == OP_SEND)
+ the_caller = context.self;
+ else
+ the_caller = context.sender;
+
+ do {
+ cleanup(result);
+
+ switch (sys_state) {
+ case IDLING:
+ if (figure_state(strmsg)) {
+ switch (sys_state) {
+ case PLAYER_CMD:
+ case ABBR:
+ case SAVE_STATE:
+ case LOAD_STATE:
+ case OPEN_PARSER:
+ case OPEN_SORTER:
+ case WHICH_OBJECT:
+ return; // come back again!
+
+ case INIT_SORTER:
+ reinit_heap();
+ sys_state = OPEN_SORTER;
+ return;
+
+ case INIT_PARSER:
+ new_parse_list();
+ sys_state = OPEN_PARSER;
+ return;
+
+ default:
+ break;
+ }
+ }
+
+ case PLAYER_CMD:
+ normalize_string(strmsg, g_vm->Command);
+ sys_state = IDLING;
+ break;
+
+ case NORMALIZE:
+ // last normalized command
+ result._kind = STR_PTR;
+ result._str.acl_str = NewDynStr(g_vm->Command);
+ sys_state = IDLING;
+
+ case ABBR:
+ result._kind = STR_PTR;
+ result._str.acl_str = NewDynStr(strmsg);
+
+ if (convert_to(NUMERIC, result)) {
+ g_vm->Abbreviate = result._numeric.acl_int;
+ }
+ else {
+ wraperr("Warning: non-numeric abbreviation message sent to system");
+ cleanup(result);
+ }
+ sys_state = IDLING;
+ break;
+
+ case OPEN_PARSER:
+ if (figure_state(strmsg)) {
+ switch (sys_state) {
+ case CLOSE_PARSER:
+ sys_state = IDLING;
+ break;
+
+ case VERB_LIST:
+ target_list = PARSER_VERBLIST;
+ sys_state = OPEN_PARSER;
+ break;
+
+ case NOUN_LIST:
+ target_list = PARSER_NOUNLIST;
+ sys_state = OPEN_PARSER;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else {
+ add_parse_word(target_list, strmsg, the_caller);
+ }
+
+ return;
+
+ case OPEN_SORTER:
+ if (figure_state(strmsg)) {
+ switch (sys_state) {
+ case CLOSE_SORTER:
+ sys_state = IDLING;
+ break;
+ default:
+ break;
+ }
+ } else {
+ drop_str_on_heap(strmsg);
+ }
+ return;
+
+ case NEXT_SORTED:
+ if (!pop_heap(p)) {
+ cleanup(result);
+ } else {
+ result._kind = STR_PTR;
+ result._str.acl_str = (StringPtr)p;
+ sys_state = IDLING;
+ }
+ break;
+
+ case WHICH_OBJECT:
+ obj_index = find_object(strmsg);
+ if (obj_index != 0) {
+ result._kind = IDENT;
+ result._ident.ident_kind = OBJECT_ID;
+ result._ident.ident_int = obj_index;
+ }
+ sys_state = IDLING;
+ break;
+
+ case ROLL_CALL:
+ dispose_list(g_vm->Proximate);
+ new_list(g_vm->Proximate);
+ sys_state = IDLING;
+ break;
+
+ case PRESENT:
+ np = (NodePtr)malloc(sizeof(NodeType));
+ np->data = nullptr;
+ np->key = the_caller;
+
+ insert_item(g_vm->Proximate, np);
+ sys_state = IDLING;
+ break;
+
+ case PARSE:
+ parse_sentence();
+ sys_state = IDLING;
+ break;
+
+ case NEXT_OBJECT:
+ if (!pop_object(obj_index, nomatch)) {
+ cleanup(result);
+ } else if (obj_index < 0) {
+ result._kind = STR_PTR;
+ result._str.acl_str = NewDynStr(nomatch);
+ } else {
+ result._kind = IDENT;
+ result._ident.ident_kind = OBJECT_ID;
+ result._ident.ident_int = obj_index;
+ }
+
+ sys_state = IDLING;
+ break;
+
+ case DEBUG_MESSAGES:
+ Debug = Debug ^ DEBUG_MSGS;
+ sys_state = IDLING;
+ break;
+
+ case DEBUG_EXPRESSIONS:
+ Debug = Debug ^ DEBUG_EXPR;
+ sys_state = IDLING;
+ break;
+
+ case DEBUG_STATEMENTS:
+ Debug = Debug ^ DEBUG_STMT;
+ sys_state = IDLING;
+ break;
+
+ case DEBUG_MEMORY:
+ wrapout("", true); // get to beginning of line
+ //g_vm->writeln("Maximum memory request: %d bytes", MaxAvail);
+ //g_vm->writeln("Actual free memory: %d bytes", MemAvail);
+ sys_state = IDLING;
+ break;
+
+ case FREE_MEMORY:
+ result._kind = NUMERIC;
+ result._numeric.acl_int = 0xffff; // MemAvail;
+ sys_state = IDLING;
+ break;
+
+ case SAVE_STATE: {
+ Common::OutSaveFile *stfile = g_system->getSavefileManager()->openForSaving(strmsg);
+ if (stfile == nullptr) {
+ g_vm->writeln("Error opening %s", strmsg.c_str());
+ cleanup(result);
+ }
+ else {
+ save_game_state(stfile, g_vm->Object_List);
+ result._kind = RESERVED;
+ result._reserved.keyword = RW_TRUE;
+
+ stfile->finalize();
+ delete stfile;
+ }
+
+ sys_state = IDLING;
+ break;
+ }
+
+ case LOAD_STATE: {
+ Common::InSaveFile *stfile = g_system->getSavefileManager()->openForLoading(strmsg);
+ if (stfile == nullptr) {
+ g_vm->writeln("Error opening %s", strmsg.c_str());
+ cleanup(result);
+ } else {
+ result._kind = RESERVED;
+ result._reserved.keyword = load_game_state(stfile, g_vm->Object_List) ? RW_TRUE : RW_FALSE;
+ delete stfile;
+ }
+
+ sys_state = IDLING;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (g_vm->shouldQuit())
+ sys_state = IDLING;
+ } while (sys_state != IDLING);
+}
+
+} // End of namespace Archetype
+} // End of namespace Glk