diff options
Diffstat (limited to 'engines/glk/alan2/exe.cpp')
-rw-r--r-- | engines/glk/alan2/exe.cpp | 1845 |
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 |