aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/alan2/exe.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/alan2/exe.cpp')
-rw-r--r--engines/glk/alan2/exe.cpp1845
1 files changed, 1845 insertions, 0 deletions
diff --git a/engines/glk/alan2/exe.cpp b/engines/glk/alan2/exe.cpp
new file mode 100644
index 0000000000..1cccf3d32d
--- /dev/null
+++ b/engines/glk/alan2/exe.cpp
@@ -0,0 +1,1845 @@
+/* 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/alan2/types.h"
+#include "glk/alan2/alan2.h"
+
+#ifdef USE_READLINE
+#include "glk/alan2/readline.h"
+#endif
+
+#include "glk/alan2/main.h"
+#include "glk/alan2/parse.h"
+#include "glk/alan2/inter.h"
+#include "glk/alan2/stack.h"
+#include "glk/alan2/decode.h"
+
+#include "glk/alan2/exe.h"
+
+namespace Glk {
+namespace Alan2 {
+
+#define WIDTH 80
+
+#define N_EVTS 100
+
+
+/* PUBLIC DATA */
+
+/* The event queue */
+EvtqElem eventq[N_EVTS]; /* Event queue */
+int etop = 0; /* Event queue top pointer */
+
+Boolean looking = FALSE; /* LOOKING? flag */
+
+int dscrstkp = 0; /* Describe-stack pointer */
+
+
+#ifdef _PROTOTYPES_
+void dscrobjs(void);
+void dscracts(void);
+#else
+void dscrobjs();
+void dscracts();
+#endif
+
+
+
+#ifdef _PROTOTYPES_
+void print(Aword fpos, Aword len)
+#else
+void print(fpos, len)
+ Aword fpos, len;
+#endif
+{
+ char str[2*WIDTH]; /* String buffer */
+ int outlen = 0; /* Current output length */
+ int ch;
+ int i;
+ long savfp; /* Temporary saved text file position */
+ static Boolean printFlag = FALSE; /* Printing already? */
+ Boolean savedPrintFlag = printFlag;
+ void *info; /* Saved decoding info */
+
+
+ if (len == 0) return;
+
+ if (isHere(HERO)) { /* Check if the player will see it */
+ if (printFlag) { /* Already printing? */
+ /* Save current text file position and/or decoding info */
+ if (header->pack)
+ info = pushDecode();
+ else
+ savfp = ftell(txtfil);
+ }
+ printFlag = TRUE; /* We're printing now! */
+ fseek(txtfil, fpos, 0); /* Position to start of text */
+ if (header->pack)
+ startDecoding();
+ for (outlen = 0; outlen != (int)len; outlen = outlen + strlen(str)) {
+ /* Fill the buffer from the beginning */
+ for (i = 0; i <= WIDTH || (i > WIDTH && ch != ' '); i++) {
+ if (outlen + i == (int)len) /* No more characters? */
+ break;
+ if (header->pack)
+ ch = decodeChar();
+ else
+ ch = getc(txtfil);
+ if (ch == EOFChar) /* Or end of text? */
+ break;
+ str[i] = ch;
+ }
+ str[i] = '\0';
+#if ISO == 0
+ fromIso(str, str);
+#endif
+ output(str);
+ }
+ /* And restore */
+ printFlag = savedPrintFlag;
+ if (printFlag) {
+ if (header->pack)
+ popDecode(info);
+ else
+ fseek(txtfil, savfp, 0);
+ }
+ }
+}
+
+
+#ifdef _PROTOTYPES_
+void sys(Aword fpos, Aword len)
+#else
+void sys(fpos, len)
+ Aword fpos, len;
+#endif
+{
+#ifdef GLK
+ ::error("system calls aren't supported");
+#else
+ char *command;
+
+ getstr(fpos, len); /* Returns address to string on stack */
+ command = (char *)pop();
+ int tmp = system(command);
+ free(command);
+#endif
+}
+
+
+#ifdef _PROTOTYPES_
+void getstr(Aword fpos, Aword len)
+#else
+void getstr(fpos, len)
+ Aword fpos, len;
+#endif
+{
+ char *buf = (char *)allocate(len+1);
+
+ push((Aptr) buf); /* Push the address to the string */
+ fseek(txtfil, fpos, 0); /* Position to start of text */
+ if (header->pack)
+ startDecoding();
+ while (len--)
+ if (header->pack)
+ *(buf++) = decodeChar();
+ else
+ *(buf++) = getc(txtfil);
+ *buf = '\0';
+}
+
+
+
+#ifdef _PROTOTYPES_
+void score(Aword sc)
+#else
+void score(sc)
+ Aword sc;
+#endif
+{
+ char buf[80];
+
+ if (sc == 0) {
+ prmsg(M_SCORE1);
+ sprintf(buf, "%d", cur.score);
+ output(buf);
+ prmsg(M_SCORE2);
+ sprintf(buf, "%ld.", (unsigned long) header->maxscore);
+ output(buf);
+ } else {
+ cur.score += scores[sc-1];
+ scores[sc-1] = 0;
+ }
+}
+
+#ifdef _PROTOTYPES_
+void visits(Aword v)
+#else
+void visits(v)
+ Aword v;
+#endif
+{
+ cur.visits = v;
+}
+
+
+#ifdef _PROTOTYPES_
+Boolean confirm(MsgKind msgno)
+#else
+Boolean confirm(msgno)
+ MsgKind msgno;
+#endif
+{
+ char buf[80];
+
+ /* This is a bit of a hack since we really want to compare the input,
+ it could be affirmative, but for now any input is NOT! */
+ prmsg(msgno);
+
+#ifdef USE_READLINE
+ if (!readline(buf)) return TRUE;
+#else
+ if (gets(buf) == NULL) return TRUE;
+#endif
+ col = 1;
+
+ return (buf[0] == '\0');
+}
+
+
+#ifdef _PROTOTYPES_
+void quit(void)
+#else
+void quit()
+#endif
+{
+ char buf[80];
+ char choices[10];
+
+ para();
+ while (TRUE) {
+ col = 1;
+ statusline();
+ prmsg(M_QUITACTION);
+#ifdef USE_READLINE
+ if (!readline(buf)) terminate(0);
+#else
+ if (gets(buf) == NULL) terminate(0);
+#endif
+ if (strcmp(buf, "restart") == 0)
+ //longjmp(restart_label, TRUE);
+ ::error("TODO: restart");
+ else if (strcmp(buf, "restore") == 0) {
+ restore();
+ return;
+ } else if (strcmp(buf, "quit") == 0)
+ terminate(0);
+ }
+ syserr("Fallthrough in QUIT");
+}
+
+
+
+#ifdef _PROTOTYPES_
+void restart(void)
+#else
+void restart()
+#endif
+{
+ para();
+ if (confirm(M_REALLY)) {
+ //longjmp(restart_label, TRUE);
+ ::error("TODO: restart");
+ } else
+ return;
+ syserr("Fallthrough in RESTART");
+}
+
+
+
+#ifdef _PROTOTYPES_
+void cancl(Aword evt)
+#else
+void cancl(evt)
+ Aword evt;
+#endif
+{
+ int i;
+
+ for(i = etop-1; i>=0; i--)
+ if (eventq[i].event == evt) {
+ while (i < etop-1) {
+ eventq[i].event = eventq[i+1].event;
+ eventq[i].time = eventq[i+1].time;
+ eventq[i].where = eventq[i+1].where;
+ i++;
+ }
+ etop--;
+ return;
+ }
+}
+
+
+#ifdef _PROTOTYPES_
+void schedule(Aword evt, Aword whr, Aword aft)
+#else
+void schedule(evt, whr, aft)
+ Aword evt, whr, aft;
+#endif
+{ int i;
+ int time;
+
+ cancl(evt);
+ /* Check for overflow */
+ if (etop == N_EVTS) syserr("Out of event space.");
+
+ time = cur.tick+aft;
+
+ /* Bubble this event down */
+ for (i = etop; i >= 1 && eventq[i-1].time <= time; i--) {
+ eventq[i].event = eventq[i-1].event;
+ eventq[i].time = eventq[i-1].time;
+ eventq[i].where = eventq[i-1].where;
+ }
+
+ eventq[i].time = time;
+ eventq[i].where = whr;
+ eventq[i].event = evt;
+ etop++;
+}
+
+
+/*----------------------------------------------------------------------
+
+ getatr()
+
+ Get an attribute value from an attribute list
+
+ */
+#ifdef _PROTOTYPES_
+static Aptr getatr(
+ Aaddr atradr, /* IN - ACODE address to attribute table */
+ Aaddr atr /* IN - The attribute to read */
+)
+#else
+static Aptr getatr(atradr, atr)
+ Aaddr atradr; /* IN - ACODE address to attribute table */
+ Aaddr atr; /* IN - The attribute to read */
+#endif
+{
+ AtrElem *at;
+
+ at = (AtrElem *) addrTo(atradr);
+ return at[atr-1].val;
+}
+
+
+/*----------------------------------------------------------------------
+
+ setatr()
+
+ Set a particular attribute to a value.
+
+ */
+#ifdef _PROTOTYPES_
+static void setatr(
+ Aaddr atradr, /* IN - ACODE address to attribute table */
+ Aword atr, /* IN - attribute code */
+ Aword val /* IN - new value */
+)
+#else
+static void setatr(atradr, atr, val)
+ Aaddr atradr; /* IN - ACODE address to attribute table */
+ Aword atr; /* IN - attribute code */
+ Aword val; /* IN - new value */
+#endif
+{
+ AtrElem *at;
+
+ at = (AtrElem *) addrTo(atradr);
+ at[atr-1].val = val;
+}
+
+
+/*----------------------------------------------------------------------
+
+ make()
+
+ */
+
+#ifdef _PROTOTYPES_
+static void makloc(Aword loc, Aword atr, Aword val)
+#else
+static void makloc(loc, atr, val)
+ Aword loc, atr, val;
+#endif
+{
+ setatr(locs[loc-LOCMIN].atrs, atr, val);
+}
+
+#ifdef _PROTOTYPES_
+static void makobj(Aword obj, Aword atr, Aword val)
+#else
+static void makobj(obj, atr, val)
+ Aword obj, atr, val;
+#endif
+{
+ setatr(objs[obj-OBJMIN].atrs, atr, val);
+}
+
+#ifdef _PROTOTYPES_
+static void makact(Aword act, Aword atr, Aword val)
+#else
+static void makact(act, atr, val)
+ Aword act, atr, val;
+#endif
+{
+ setatr(acts[act-ACTMIN].atrs, atr, val);
+}
+
+
+#ifdef _PROTOTYPES_
+void make(Aword id, Aword atr, Aword val)
+#else
+void make(id, atr, val)
+ Aword id, atr, val;
+#endif
+{
+ char str[80];
+
+ if (isObj(id))
+ makobj(id, atr, val);
+ else if (isLoc(id))
+ makloc(id, atr, val);
+ else if (isAct(id))
+ makact(id, atr, val);
+ else {
+ sprintf(str, "Can't MAKE item (%ld).", (unsigned long) id);
+ syserr(str);
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+
+ set()
+
+ */
+
+#ifdef _PROTOTYPES_
+static void setloc(Aword loc, Aword atr, Aword val)
+#else
+static void setloc(loc, atr, val)
+ Aword loc, atr, val;
+#endif
+{
+ setatr(locs[loc-LOCMIN].atrs, atr, val);
+ locs[loc-LOCMIN].describe = 0;
+}
+
+
+#ifdef _PROTOTYPES_
+static void setobj(Aword obj, Aword atr, Aword val)
+#else
+static void setobj(obj, atr, val)
+ Aword obj, atr, val;
+#endif
+{
+ setatr(objs[obj-OBJMIN].atrs, atr, val);
+}
+
+#ifdef _PROTOTYPES_
+static void setact(Aword act, Aword atr, Aword val)
+#else
+static void setact(act, atr, val)
+ Aword act, atr, val;
+#endif
+{
+ setatr(acts[act-ACTMIN].atrs, atr, val);
+}
+
+
+#ifdef _PROTOTYPES_
+void set(Aword id, Aword atr, Aword val)
+#else
+void set(id, atr, val)
+ Aword id, atr, val;
+#endif
+{
+ char str[80];
+
+ if (isObj(id))
+ setobj(id, atr, val);
+ else if (isLoc(id))
+ setloc(id, atr, val);
+ else if (isAct(id))
+ setact(id, atr, val);
+ else {
+ sprintf(str, "Can't SET item (%ld).", (unsigned long) id);
+ syserr(str);
+ }
+}
+
+
+#ifdef _PROTOTYPES_
+void setstr(Aword id, Aword atr, Aword str)
+#else
+void setstr(id, atr, str)
+ Aword id, atr, str;
+#endif
+{
+ free((char *)attribute(id, atr));
+ set(id, atr, str);
+}
+
+
+
+/*-----------------------------------------------------------------------------
+
+ incr/decr
+
+ */
+
+/*----------------------------------------------------------------------
+
+ incratr()
+
+ Increment a particular attribute by a value.
+
+ */
+#ifdef _PROTOTYPES_
+static void incratr(
+ Aaddr atradr, /* IN - ACODE address to attribute table */
+ Aword atr, /* IN - attribute code */
+ Aword step /* IN - step to increment by */
+)
+#else
+static void incratr(atradr, atr, step)
+ Aaddr atradr, atr, step;
+#endif
+{
+ AtrElem *at;
+
+ at = (AtrElem *) addrTo(atradr);
+ at[atr-1].val += step;
+}
+
+
+#ifdef _PROTOTYPES_
+static void incrloc(Aword loc, Aword atr, Aword step)
+#else
+static void incrloc(loc, atr, step)
+ Aword loc, atr, step;
+#endif
+{
+ incratr(locs[loc-LOCMIN].atrs, atr, step);
+ locs[loc-LOCMIN].describe = 0;
+}
+
+
+#ifdef _PROTOTYPES_
+static void incrobj(Aword obj, Aword atr, Aword step)
+#else
+static void incrobj(obj, atr, step)
+ Aword obj, atr, step;
+#endif
+{
+ incratr(objs[obj-OBJMIN].atrs, atr, step);
+}
+
+#ifdef _PROTOTYPES_
+static void incract(Aword act, Aword atr, Aword step)
+#else
+static void incract(act, atr, step)
+ Aword act, atr, step;
+#endif
+{
+ incratr(acts[act-ACTMIN].atrs, atr, step);
+}
+
+
+#ifdef _PROTOTYPES_
+void incr(Aword id, Aword atr, Aword step)
+#else
+void incr(id, atr, step)
+ Aword id, atr, step;
+#endif
+{
+ char str[80];
+
+ if (isObj(id))
+ incrobj(id, atr, step);
+ else if (isLoc(id))
+ incrloc(id, atr, step);
+ else if (isAct(id))
+ incract(id, atr, step);
+ else {
+ sprintf(str, "Can't INCR item (%ld).", (unsigned long) id);
+ syserr(str);
+ }
+}
+
+#ifdef _PROTOTYPES_
+void decr(Aword id, Aword atr, Aword step)
+#else
+void decr(id, atr, step)
+ Aword id, atr, step;
+#endif
+{
+ char str[80];
+
+ if (isObj(id))
+ incrobj(id, atr, -step);
+ else if (isLoc(id))
+ incrloc(id, atr, -step);
+ else if (isAct(id))
+ incract(id, atr, -step);
+ else {
+ sprintf(str, "Can't DECR item (%ld).", (unsigned long) id);
+ syserr(str);
+ }
+}
+
+
+
+/*----------------------------------------------------------------------
+
+ attribute()
+
+ */
+
+#ifdef _PROTOTYPES_
+static Aptr locatr(Aword loc, Aword atr)
+#else
+static Aptr locatr(loc, atr)
+ Aword loc, atr;
+#endif
+{
+ return getatr(locs[loc-LOCMIN].atrs, atr);
+}
+
+
+
+#ifdef _PROTOTYPES_
+static Aptr objatr(Aword obj, Aword atr)
+#else
+static Aptr objatr(obj, atr)
+ Aword obj, atr;
+#endif
+{
+ return getatr(objs[obj-OBJMIN].atrs, atr);
+}
+
+#ifdef _PROTOTYPES_
+static Aptr actatr(Aword act, Aword atr)
+#else
+static Aptr actatr(act, atr)
+ Aword act, atr;
+#endif
+{
+ return getatr(acts[act-ACTMIN].atrs, atr);
+}
+
+#ifdef _PROTOTYPES_
+static Aptr litatr(Aword lit, Aword atr)
+#else
+static Aptr litatr(lit, atr)
+ Aword lit, atr;
+#endif
+{
+ char str[80];
+
+ if (atr == 1)
+ return litValues[lit-LITMIN].value;
+ else {
+ sprintf(str, "Unknown attribute for literal (%ld).", (unsigned long) atr);
+ syserr(str);
+ }
+ return (Aptr)EOF;
+}
+
+
+#ifdef _PROTOTYPES_
+Aptr attribute(Aword id, Aword atr)
+#else
+Aptr attribute(id, atr)
+ Aword id, atr;
+#endif
+{
+ char str[80];
+
+ if (isObj(id))
+ return objatr(id, atr);
+ else if (isLoc(id))
+ return locatr(id, atr);
+ else if (isAct(id))
+ return actatr(id, atr);
+ else if (isLit(id))
+ return litatr(id, atr);
+ else {
+ sprintf(str, "Can't ATTRIBUTE item (%ld).", (unsigned long) id);
+ syserr(str);
+ }
+ return (Aptr)EOF;
+}
+
+
+#ifdef _PROTOTYPES_
+Aptr strattr(Aword id, Aword atr)
+#else
+Aptr strattr(id, atr)
+ Aword id, atr;
+#endif
+{
+ return (Aptr) strdup((char *)attribute(id, atr));
+}
+
+
+/*----------------------------------------------------------------------
+
+ where()
+
+ */
+
+#ifdef _PROTOTYPES_
+static Aword objloc(Aword obj)
+#else
+static Aword objloc(obj)
+ Aword obj;
+#endif
+{
+ if (isCnt(objs[obj-OBJMIN].loc)) /* In something ? */
+ if (isObj(objs[obj-OBJMIN].loc) || isAct(objs[obj-OBJMIN].loc))
+ return(where(objs[obj-OBJMIN].loc));
+ else /* Containers not anywhere is where the hero is! */
+ return(where(HERO));
+ else
+ return(objs[obj-OBJMIN].loc);
+}
+
+
+#ifdef _PROTOTYPES_
+static Aword actloc(Aword act)
+#else
+static Aword actloc(act)
+ Aword act;
+#endif
+{
+ return(acts[act-ACTMIN].loc);
+}
+
+
+#ifdef _PROTOTYPES_
+Aword where(Aword id)
+#else
+Aword where(id)
+ Aword id;
+#endif
+{
+ char str[80];
+
+ if (isObj(id))
+ return objloc(id);
+ else if (isAct(id))
+ return actloc(id);
+ else {
+ sprintf(str, "Can't WHERE item (%ld).", (unsigned long) id);
+ syserr(str);
+ }
+ return (Aptr)EOF;
+}
+
+
+
+/*----------------------------------------------------------------------
+
+ aggregates
+
+ */
+
+#ifdef _PROTOTYPES_
+Aint agrmax(Aword atr, Aword whr)
+#else
+Aint agrmax(atr, whr)
+ Aword atr, whr;
+#endif
+{
+ Aword i;
+ Aint max = 0;
+
+ for (i = OBJMIN; i <= OBJMAX; i++) {
+ if (isLoc(whr)) {
+ if (where(i) == whr && attribute(i, atr) > max)
+ max = attribute(i, atr);
+ } else if (objs[i-OBJMIN].loc == whr && attribute(i, atr) > max)
+ max = attribute(i, atr);
+ }
+ return(max);
+}
+
+#ifdef _PROTOTYPES_
+Aint agrsum(Aword atr, Aword whr)
+#else
+Aint agrsum(atr, whr)
+ Aword atr, whr;
+#endif
+{
+ Aword i;
+ Aint sum = 0;
+
+ for (i = OBJMIN; i <= OBJMAX; i++) {
+ if (isLoc(whr)) {
+ if (where(i) == whr)
+ sum += attribute(i, atr);
+ } else if (objs[i-OBJMIN].loc == whr)
+ sum += attribute(i, atr);
+ }
+ return(sum);
+}
+
+
+#ifdef _PROTOTYPES_
+Aint agrcount(Aword whr)
+#else
+Aint agrcount(whr)
+ Aword whr;
+#endif
+{
+ Aword i;
+ Aword count = 0;
+
+ for (i = OBJMIN; i <= OBJMAX; i++) {
+ if (isLoc(whr)) {
+ if (where(i) == whr)
+ count++;
+ } else if (objs[i-OBJMIN].loc == whr)
+ count++;
+ }
+ return(count);
+}
+
+
+/*----------------------------------------------------------------------
+
+ locate()
+
+ */
+
+#ifdef _PROTOTYPES_
+static void locobj(Aword obj, Aword whr)
+#else
+static void locobj(obj, whr)
+ Aword obj, whr;
+#endif
+{
+ if (isCnt(whr)) { /* Into a container */
+ if (whr == obj)
+ syserr("Locating something inside itself.");
+ if (checklim(whr, obj))
+ return;
+ else
+ objs[obj-OBJMIN].loc = whr;
+ } else {
+ objs[obj-OBJMIN].loc = whr;
+ /* Make sure the location is described since it's changed */
+ locs[whr-LOCMIN].describe = 0;
+ }
+}
+
+
+#ifdef _PROTOTYPES_
+static void locact(Aword act, Aword whr)
+#else
+static void locact(act, whr)
+ Aword act, whr;
+#endif
+{
+ Aword prevact = cur.act;
+ Aword prevloc = cur.loc;
+
+ cur.loc = whr;
+ acts[act-ACTMIN].loc = whr;
+ if (act == HERO) {
+ if (locs[acts[act-ACTMIN].loc-LOCMIN].describe % (cur.visits+1) == 0)
+ look();
+ else {
+ if (anyOutput)
+ para();
+ say(where(HERO));
+ prmsg(M_AGAIN);
+ newline();
+ dscrobjs();
+ dscracts();
+ }
+ locs[where(HERO)-LOCMIN].describe++;
+ locs[where(HERO)-LOCMIN].describe %= (cur.visits+1);
+ } else
+ locs[whr-LOCMIN].describe = 0;
+ if (locs[cur.loc-LOCMIN].does != 0) {
+ cur.act = act;
+ interpret(locs[cur.loc-LOCMIN].does);
+ cur.act = prevact;
+ }
+
+ if (cur.act != act)
+ cur.loc = prevloc;
+}
+
+
+#ifdef _PROTOTYPES_
+void locate(Aword id, Aword whr)
+#else
+void locate(id, whr)
+ Aword id, whr;
+#endif
+{
+ char str[80];
+
+ if (isObj(id))
+ locobj(id, whr);
+ else if (isAct(id))
+ locact(id, whr);
+ else {
+ sprintf(str, "Can't LOCATE item (%ld).", (unsigned long) id);
+ syserr(str);
+ }
+}
+
+
+/*----------------------------------------------------------------------
+
+ isHere()
+
+ */
+
+#ifdef _PROTOTYPES_
+static Abool objhere(Aword obj)
+#else
+static Abool objhere(obj)
+ Aword obj;
+#endif
+{
+ if (isCnt(objs[obj-OBJMIN].loc)) { /* In something? */
+ if (isObj(objs[obj-OBJMIN].loc) || isAct(objs[obj-OBJMIN].loc))
+ return(isHere(objs[obj-OBJMIN].loc));
+ else /* If the container wasn't anywhere, assume where HERO is! */
+ return(where(HERO) == cur.loc);
+ } else
+ return(objs[obj-OBJMIN].loc == cur.loc);
+}
+
+
+#ifdef _PROTOTYPES_
+static Aword acthere(Aword act)
+#else
+static Aword acthere(act)
+ Aword act;
+#endif
+{
+ return(acts[act-ACTMIN].loc == cur.loc);
+}
+
+
+#ifdef _PROTOTYPES_
+Abool isHere(Aword id)
+#else
+Abool isHere(id)
+ Aword id;
+#endif
+{
+ char str[80];
+
+ if (isObj(id))
+ return objhere(id);
+ else if (isAct(id))
+ return acthere(id);
+ else {
+ sprintf(str, "Can't HERE item (%ld).", (unsigned long) id);
+ syserr(str);
+ }
+ return (Abool)EOF;
+}
+
+/*----------------------------------------------------------------------
+
+ isNear()
+
+ */
+
+#ifdef _PROTOTYPES_
+static Aword objnear(Aword obj)
+#else
+static Aword objnear(obj)
+ Aword obj;
+#endif
+{
+ if (isCnt(objs[obj-OBJMIN].loc)) { /* In something? */
+ if (isObj(objs[obj-OBJMIN].loc) || isAct(objs[obj-OBJMIN].loc))
+ return(isNear(objs[obj-OBJMIN].loc));
+ else /* If the container wasn't anywhere, assume here, so not nearby! */
+ return(FALSE);
+ } else
+ return(exitto(where(obj), cur.loc));
+}
+
+
+#ifdef _PROTOTYPES_
+static Aword actnear(Aword act)
+#else
+static Aword actnear(act)
+ Aword act;
+#endif
+{
+ return(exitto(where(act), cur.loc));
+}
+
+
+#ifdef _PROTOTYPES_
+Abool isNear(Aword id)
+#else
+Abool isNear(id)
+ Aword id;
+#endif
+{
+ char str[80];
+
+ if (isObj(id))
+ return objnear(id);
+ else if (isAct(id))
+ return actnear(id);
+ else {
+ sprintf(str, "Can't NEAR item (%ld).", (unsigned long) id);
+ syserr(str);
+ }
+ return (Abool)EOF;
+}
+
+
+
+/*----------------------------------------------------------------------
+
+ in()
+
+ */
+
+#ifdef _PROTOTYPES_
+Abool in(Aword obj, Aword cnt)
+#else
+Abool in(obj, cnt)
+ Aword obj;
+ Aword cnt;
+#endif
+{
+ if (!isObj(obj))
+ return(FALSE);
+ if (!isCnt(cnt))
+ syserr("IN in a non-container.");
+
+ return(objs[obj-OBJMIN].loc == cnt);
+}
+
+
+/*----------------------------------------------------------------------
+
+ say()
+
+ */
+
+#ifdef _PROTOTYPES_
+static void sayloc(Aword loc)
+#else
+static void sayloc(loc)
+ Aword loc;
+#endif
+{
+ interpret(locs[loc-LOCMIN].nams);
+}
+
+
+#ifdef _PROTOTYPES_
+static void sayobj(Aword obj)
+#else
+static void sayobj(obj)
+ Aword obj;
+#endif
+{
+ interpret(objs[obj-OBJMIN].dscr2);
+}
+
+#ifdef _PROTOTYPES_
+static void sayact(Aword act)
+#else
+static void sayact(act)
+ Aword act;
+#endif
+{
+ interpret(acts[act-ACTMIN].nam);
+}
+
+
+#ifdef _PROTOTYPES_
+void sayint(Aword val)
+#else
+void sayint(val)
+ Aword val;
+#endif
+{
+ char buf[25];
+
+ if (isHere(HERO)) {
+ sprintf(buf, "%ld", (unsigned long) val);
+ output(buf);
+ }
+}
+
+
+#ifdef _PROTOTYPES_
+void saystr(char *str)
+#else
+void saystr(str)
+ char *str;
+#endif
+{
+ if (isHere(HERO))
+ output(str);
+ free(str);
+}
+
+
+#ifdef _PROTOTYPES_
+static void saylit(Aword lit)
+#else
+static void saylit(lit)
+ Aword lit;
+#endif
+{
+ char *str;
+
+ if (isNum(lit))
+ sayint(litValues[lit-LITMIN].value);
+ else {
+ str = (char *)strdup((char *)litValues[lit-LITMIN].value);
+ saystr(str);
+ }
+}
+
+
+#ifdef _PROTOTYPES_
+void sayarticle(Aword id)
+#else
+void sayarticle(id)
+ Aword id;
+#endif
+{
+ if (!isObj(id))
+ syserr("Trying to say article of something *not* an object.");
+ if (objs[id-OBJMIN].art != 0)
+ interpret(objs[id-OBJMIN].art);
+ else
+ prmsg(M_ARTICLE);
+}
+
+
+#ifdef _PROTOTYPES_
+void say(Aword id)
+#else
+void say(id)
+ Aword id;
+#endif
+{
+ char str[80];
+
+ if (isHere(HERO)) {
+ if (isObj(id))
+ sayobj(id);
+ else if (isLoc(id))
+ sayloc(id);
+ else if (isAct(id))
+ sayact(id);
+ else if (isLit(id))
+ saylit(id);
+ else {
+ sprintf(str, "Can't SAY item (%ld).", (unsigned long) id);
+ syserr(str);
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------
+
+ describe()
+
+ */
+
+#ifdef _PROTOTYPES_
+static void dscrloc(Aword loc)
+#else
+static void dscrloc(loc)
+ Aword loc;
+#endif
+{
+ if (locs[loc-LOCMIN].dscr != 0)
+ interpret(locs[loc-LOCMIN].dscr);
+}
+
+
+#ifdef _PROTOTYPES_
+static void dscrobj(Aword obj)
+#else
+static void dscrobj(obj)
+ Aword obj;
+#endif
+{
+ objs[obj-OBJMIN].describe = FALSE;
+ if (objs[obj-OBJMIN].dscr1 != 0)
+ interpret(objs[obj-OBJMIN].dscr1);
+ else {
+ prmsg(M_SEEOBJ1);
+ sayarticle(obj);
+ say(obj);
+ prmsg(M_SEEOBJ4);
+ if (objs[obj-OBJMIN].cont != 0)
+ list(obj);
+ }
+}
+
+
+#ifdef _PROTOTYPES_
+static void dscract(Aword act)
+#else
+static void dscract(act)
+ Aword act;
+#endif
+{
+ ScrElem *scr = NULL;
+
+ if (acts[act-ACTMIN].script != 0) {
+ for (scr = (ScrElem *) addrTo(acts[act-ACTMIN].scradr); !endOfTable(scr); scr++)
+ if (scr->code == acts[act-ACTMIN].script)
+ break;
+ if (endOfTable(scr)) scr = NULL;
+ }
+ if (scr != NULL && scr->dscr != 0)
+ interpret(scr->dscr);
+ else if (acts[act-ACTMIN].dscr != 0)
+ interpret(acts[act-ACTMIN].dscr);
+ else {
+ interpret(acts[act-ACTMIN].nam);
+ prmsg(M_SEEACT);
+ }
+ acts[act-ACTMIN].describe = FALSE;
+}
+
+
+static Aword dscrstk[255];
+
+#ifdef _PROTOTYPES_
+void describe(Aword id)
+#else
+void describe(id)
+ Aword id;
+#endif
+{
+ int i;
+ char str[80];
+
+ for (i = 0; i < dscrstkp; i++)
+ if (dscrstk[i] == id)
+ syserr("Recursive DESCRIBE.");
+ dscrstk[dscrstkp++] = id;
+
+ if (isObj(id))
+ dscrobj(id);
+ else if (isLoc(id))
+ dscrloc(id);
+ else if (isAct(id))
+ dscract(id);
+ else {
+ sprintf(str, "Can't DESCRIBE item (%ld).", (unsigned long) id);
+ syserr(str);
+ }
+
+ dscrstkp--;
+}
+
+
+/*----------------------------------------------------------------------
+
+ use()
+
+ */
+
+#ifdef _PROTOTYPES_
+void use(Aword act, Aword scr)
+#else
+void use(act, scr)
+ Aword act, scr;
+#endif
+{
+ char str[80];
+
+ if (!isAct(act)) {
+ sprintf(str, "Item is not an Actor (%ld).", (unsigned long) act);
+ syserr(str);
+ }
+
+ acts[act-ACTMIN].script = scr;
+ acts[act-ACTMIN].step = 0;
+}
+
+
+
+/*----------------------------------------------------------------------
+
+ list()
+
+ */
+
+#ifdef _PROTOTYPES_
+void list(Aword cnt)
+#else
+void list(cnt)
+ Aword cnt;
+#endif
+{
+ int i;
+ Aword props;
+ Aword prevobj;
+ Boolean found = FALSE;
+ Boolean multiple = FALSE;
+
+ /* Find container properties */
+ if (isObj(cnt))
+ props = objs[cnt-OBJMIN].cont;
+ else if (isAct(cnt))
+ props = acts[cnt-ACTMIN].cont;
+ else
+ props = cnt;
+
+ for (i = OBJMIN; i <= OBJMAX; i++) {
+ if (in(i, cnt)) { /* Yes, it's in this container */
+ if (!found) {
+ found = TRUE;
+ if (cnts[props-CNTMIN].header != 0)
+ interpret(cnts[props-CNTMIN].header);
+ else {
+ prmsg(M_CONTAINS1);
+ if (cnts[props-CNTMIN].nam != 0) /* It has it's own name */
+ interpret(cnts[props-CNTMIN].nam);
+ else
+ say(cnts[props-CNTMIN].parent); /* It is actually an object or actor */
+ prmsg(M_CONTAINS2);
+ }
+ } else {
+ if (multiple) {
+ needsp = FALSE;
+ prmsg(M_CONTAINS3);
+ }
+ multiple = TRUE;
+ sayarticle(prevobj);
+ say(prevobj);
+ }
+ prevobj = i;
+ }
+ }
+
+ if (found) {
+ if (multiple)
+ prmsg(M_CONTAINS4);
+ sayarticle(prevobj);
+ say(prevobj);
+ prmsg(M_CONTAINS5);
+ } else {
+ if (cnts[props-CNTMIN].empty != 0)
+ interpret(cnts[props-CNTMIN].empty);
+ else {
+ prmsg(M_EMPTY1);
+ if (cnts[props-CNTMIN].nam != 0) /* It has it's own name */
+ interpret(cnts[props-CNTMIN].nam);
+ else
+ say(cnts[props-CNTMIN].parent); /* It is actually an actor or object */
+ prmsg(M_EMPTY2);
+ }
+ }
+ needsp = TRUE;
+}
+
+
+/*----------------------------------------------------------------------
+
+ empty()
+
+ */
+
+#ifdef _PROTOTYPES_
+void empty(Aword cnt, Aword whr)
+#else
+void empty(cnt, whr)
+ Aword cnt;
+ Aword whr;
+#endif
+{
+ int i;
+
+ for (i = OBJMIN; i <= OBJMAX; i++)
+ if (in(i, cnt))
+ locate(i, whr);
+}
+
+
+
+/*----------------------------------------------------------------------*\
+
+ Description of current location
+
+ dscrobjs()
+ dscracts()
+ look()
+
+\*----------------------------------------------------------------------*/
+
+#ifdef _PROTOTYPES_
+void dscrobjs(void)
+#else
+void dscrobjs()
+#endif
+{
+ int i;
+ int prevobj;
+ Boolean found = FALSE;
+ Boolean multiple = FALSE;
+
+ /* First describe everything here with its own description */
+ for (i = OBJMIN; i <= OBJMAX; i++)
+ if (objs[i-OBJMIN].loc == cur.loc &&
+ objs[i-OBJMIN].describe &&
+ objs[i-OBJMIN].dscr1)
+ describe(i);
+
+ /* Then list everything else here */
+ for (i = OBJMIN; i <= OBJMAX; i++)
+ if (objs[i-OBJMIN].loc == cur.loc &&
+ objs[i-OBJMIN].describe) {
+ if (!found) {
+ prmsg(M_SEEOBJ1);
+ sayarticle(i);
+ say(i);
+ found = TRUE;
+ } else {
+ if (multiple) {
+ needsp = FALSE;
+ prmsg(M_SEEOBJ2);
+ sayarticle(prevobj);
+ say(prevobj);
+ }
+ multiple = TRUE;
+ }
+ prevobj = i;
+ }
+
+ if (found) {
+ if (multiple) {
+ prmsg(M_SEEOBJ3);
+ sayarticle(prevobj);
+ say(prevobj);
+ }
+ prmsg(M_SEEOBJ4);
+ }
+
+ /* Set describe flag for all objects */
+ for (i = OBJMIN; i <= OBJMAX; i++)
+ objs[i-OBJMIN].describe = TRUE;
+}
+
+
+#ifdef _PROTOTYPES_
+void dscracts(void)
+#else
+void dscracts()
+#endif
+{
+ int i;
+
+ for (i = HERO+1; i <= ACTMAX; i++)
+ if (acts[i-ACTMIN].loc == cur.loc &&
+ acts[i-ACTMIN].describe)
+ describe(i);
+
+ /* Set describe flag for all actors */
+ for (i = HERO; i <= ACTMAX; i++)
+ acts[i-ACTMIN].describe = TRUE;
+}
+
+
+#ifdef _PROTOTYPES_
+void look(void)
+#else
+void look()
+#endif
+{
+ int i;
+
+ if (looking)
+ syserr("Recursive LOOK.");
+
+ looking = TRUE;
+ /* Set describe flag for all objects and actors */
+ for (i = OBJMIN; i <= OBJMAX; i++)
+ objs[i-OBJMIN].describe = TRUE;
+ for (i = ACTMIN; i <= ACTMAX; i++)
+ acts[i-ACTMIN].describe = TRUE;
+
+ if (anyOutput)
+ para();
+
+g_vm->glk_set_style(style_Subheader);
+needsp = FALSE;
+ say(cur.loc);
+ needsp = FALSE;
+ output(".");
+g_vm->glk_set_style(style_Normal);
+ newline();
+needsp = FALSE;
+ describe(cur.loc);
+ dscrobjs();
+ dscracts();
+ looking = FALSE;
+}
+
+
+
+static char savfnm[256];
+
+
+/*----------------------------------------------------------------------
+
+ save()
+
+ */
+
+#ifdef GARGLK
+void save() {
+ g_vm->saveGame();
+}
+
+#else
+
+#ifdef _PROTOTYPES_
+void save(void)
+#else
+void save()
+#endif
+{
+ int i;
+ char str[256];
+ AtrElem *atr;
+ FILE *savfil;
+
+ /* First save ? */
+ if (savfnm[0] == '\0') {
+ strcpy(savfnm, advnam);
+ strcat(savfnm, ".sav");
+ }
+ prmsg(M_SAVEWHERE);
+ sprintf(str, "(%s) : ", savfnm);
+ output(str);
+
+#ifdef USE_READLINE
+ readline(str);
+#else
+ gets(str);
+#endif
+
+frefid_t fref;
+fref = g_vm->glk_fileref_create_by_prompt(fileusage_SavedGame, filemode_Write, 0);
+if (fref == NULL)
+ error(M_SAVEFAILED);
+strcpy(str, g_vm->garglk_fileref_get_name(fref));
+g_vm->glk_fileref_destroy(fref);
+
+ if (str[0] == '\0')
+ strcpy(str, savfnm);
+ col = 1;
+ if ((savfil = fopen(str, READ_MODE)) != NULL)
+ /* It already existed */
+ if (!confirm(M_SAVEOVERWRITE))
+ error(MSGMAX); /* Return to player without saying anything */
+ if ((savfil = fopen(str, WRITE_MODE)) == NULL)
+ error(M_SAVEFAILED);
+ strcpy(savfnm, str);
+
+ /* Save version of interpreter and name of game */
+ fwrite((void *)&header->vers, sizeof(Aword), 1, savfil);
+ fwrite((void *)advnam, strlen(advnam)+1, 1, savfil);
+ /* Save current values */
+ fwrite((void *)&cur, sizeof(cur), 1, savfil);
+ /* Save actors */
+ for (i = ACTMIN; i <= ACTMAX; i++) {
+ fwrite((void *)&acts[i-ACTMIN].loc, sizeof(Aword), 1, savfil);
+ fwrite((void *)&acts[i-ACTMIN].script, sizeof(Aword), 1, savfil);
+ fwrite((void *)&acts[i-ACTMIN].step, sizeof(Aword), 1, savfil);
+ fwrite((void *)&acts[i-ACTMIN].count, sizeof(Aword), 1, savfil);
+ if (acts[i-ACTMIN].atrs)
+ for (atr = (AtrElem *) addrTo(acts[i-ACTMIN].atrs); !endOfTable(atr); atr++)
+ fwrite((void *)&atr->val, sizeof(Aword), 1, savfil);
+ }
+
+ /* Save locations */
+ for (i = LOCMIN; i <= LOCMAX; i++) {
+ fwrite((void *)&locs[i-LOCMIN].describe, sizeof(Aword), 1, savfil);
+ if (locs[i-LOCMIN].atrs)
+ for (atr = (AtrElem *) addrTo(locs[i-LOCMIN].atrs); !endOfTable(atr); atr++)
+ fwrite((void *)&atr->val, sizeof(Aword), 1, savfil);
+ }
+
+ /* Save objects */
+ for (i = OBJMIN; i <= OBJMAX; i++) {
+ fwrite((void *)&objs[i-OBJMIN].loc, sizeof(Aword), 1, savfil);
+ if (objs[i-OBJMIN].atrs)
+ for (atr = (AtrElem *) addrTo(objs[i-OBJMIN].atrs); !endOfTable(atr); atr++)
+ fwrite((void *)&atr->val, sizeof(atr->val), 1, savfil);
+ }
+
+ /* Save the event queue */
+ eventq[etop].time = 0; /* Mark the top */
+ fwrite((void *)&eventq[0], sizeof(eventq[0]), etop+1, savfil);
+
+ /* Save scores */
+ for (i = 0; scores[i] != EOF; i++)
+ fwrite((void *)&scores[i], sizeof(Aword), 1, savfil);
+
+ fclose(savfil);
+}
+#endif
+
+/*----------------------------------------------------------------------
+
+ restore()
+
+ */
+
+#ifdef GARGLK
+void restore() {
+ g_vm->loadGame();
+}
+
+#else
+
+#ifdef _PROTOTYPES_
+void restore(void)
+#else
+void restore()
+#endif
+{
+ int i,tmp;
+ FILE *savfil;
+ char str[256];
+ AtrElem *atr;
+ char savedVersion[4];
+ char savedName[256];
+
+ /* First save ? */
+ if (savfnm[0] == '\0') {
+ strcpy(savfnm, advnam);
+ strcat(savfnm, ".sav");
+ }
+ prmsg(M_RESTOREFROM);
+ sprintf(str, "(%s) : ", savfnm);
+ output(str);
+#ifdef USE_READLINE
+ readline(str);
+#else
+ gets(str);
+#endif
+
+ if (str[0] == '\0')
+ strcpy(str, savfnm);
+ col = 1;
+ if (str[0] == '\0')
+ strcpy(str, savfnm); /* Use the name temporarily */
+ if ((savfil = fopen(str, READ_MODE)) == NULL)
+ error(M_SAVEMISSING);
+ strcpy(savfnm, str); /* Save it for future use */
+
+ tmp = fread((void *)&savedVersion, sizeof(Aword), 1, savfil);
+ /* 4f - save file version check doesn't seem to work on PC's! */
+ if (strncmp(savedVersion, header->vers, 4)) {
+ fclose(savfil);
+ error(M_SAVEVERS);
+ return;
+ }
+ i = 0;
+ while ((savedName[i++] = fgetc(savfil)) != '\0');
+ if (strcmp(savedName, advnam) != 0) {
+ fclose(savfil);
+ error(M_SAVENAME);
+ return;
+ }
+
+ /* Restore current values */
+ tmp = fread((void *)&cur, sizeof(cur), 1, savfil);
+ /* Restore actors */
+ for (i = ACTMIN; i <= ACTMAX; i++) {
+ tmp = fread((void *)&acts[i-ACTMIN].loc, sizeof(Aword), 1, savfil);
+ tmp = fread((void *)&acts[i-ACTMIN].script, sizeof(Aword), 1, savfil);
+ tmp = fread((void *)&acts[i-ACTMIN].step, sizeof(Aword), 1, savfil);
+ tmp = fread((void *)&acts[i-ACTMIN].count, sizeof(Aword), 1, savfil);
+ if (acts[i-ACTMIN].atrs)
+ for (atr = (AtrElem *) addrTo(acts[i-ACTMIN].atrs); !endOfTable(atr); atr++)
+ tmp = fread((void *)&atr->val, sizeof(Aword), 1, savfil);
+ }
+
+ /* Restore locations */
+ for (i = LOCMIN; i <= LOCMAX; i++) {
+ tmp = fread((void *)&locs[i-LOCMIN].describe, sizeof(Aword), 1, savfil);
+ if (locs[i-LOCMIN].atrs)
+ for (atr = (AtrElem *) addrTo(locs[i-LOCMIN].atrs); !endOfTable(atr); atr++)
+ tmp = fread((void *)&atr->val, sizeof(Aword), 1, savfil);
+ }
+
+ /* Restore objects */
+ for (i = OBJMIN; i <= OBJMAX; i++) {
+ tmp = fread((void *)&objs[i-OBJMIN].loc, sizeof(Aword), 1, savfil);
+ if (objs[i-OBJMIN].atrs)
+ for (atr = (AtrElem *) addrTo(objs[i-OBJMIN].atrs); !endOfTable(atr); atr++)
+ tmp = fread((void *)&atr->val, sizeof(atr->val), 1, savfil);
+ }
+
+ /* Restore the eventq */
+ etop = 0;
+ do {
+ tmp = fread((void *)&eventq[etop], sizeof(eventq[0]), 1, savfil);
+ etop++;
+ } while (eventq[etop-1].time != 0);
+ etop--;
+
+ /* Restore scores */
+ for (i = 0; scores[i] != EOF; i++)
+ tmp = fread((void *)&scores[i], sizeof(Aword), 1, savfil);
+
+ fclose(savfil);
+}
+
+#endif
+
+/*----------------------------------------------------------------------
+
+ rnd()
+
+ */
+
+#ifdef _PROTOTYPES_
+Aword rnd(Aword from, Aword to)
+#else
+Aword rnd(from, to)
+ Aword from, to;
+#endif
+{
+ if (to == from)
+ return to;
+ else if (to > from)
+ return (rand()/10)%(to-from+1)+from;
+ else
+ return (rand()/10)%(from-to+1)+to;
+}
+
+/*----------------------------------------------------------------------
+
+ btw()
+
+ BETWEEN
+
+ */
+
+#ifdef _PROTOTYPES_
+Abool btw(Aint val, Aint low, Aint high)
+#else
+Abool btw(val, low, high)
+ Aint val, low, high;
+#endif
+{
+ if (high > low)
+ return low <= val && val <= high;
+ else
+ return high <= val && val <= low;
+}
+
+
+
+/*----------------------------------------------------------------------
+
+ contains()
+
+ */
+
+#ifdef _PROTOTYPES_
+Aword contains(Aptr string, Aptr substring)
+#else
+Aword contains(string, substring)
+ Aptr string, substring;;
+#endif
+{
+ Abool found;
+
+ strlow((char *)string);
+ strlow((char *)substring);
+
+ found = (strstr((char *)string, (char *)substring) != 0);
+
+ free((char *)string);
+ free((char *)substring);
+
+ return(found);
+}
+
+
+
+/*----------------------------------------------------------------------
+
+ streq()
+
+ Compare two strings approximately, ignore case
+
+ */
+#ifdef _PROTOTYPES_
+Abool streq(char a[], char b[])
+#else
+Abool streq(a, b)
+ char a[], b[]; /* IN - Strings to compare */
+#endif
+{
+ Boolean eq;
+
+ strlow(a);
+ strlow(b);
+
+ eq = (strcmp(a, b) == 0);
+
+ free(a);
+ free(b);
+
+ return(eq);
+}
+
+} // End of namespace Alan2
+} // End of namespace Glk