[scottfree] 01/08: Import Upstream version 1.14
Stephen Kitt
skitt at moszumanska.debian.org
Fri Jan 20 08:00:45 UTC 2017
This is an automated email from the git hooks/post-receive script.
skitt pushed a commit to branch master
in repository scottfree.
commit a025d042abf1eace605089e33a61b3500c3f2cfb
Author: Stephen Kitt <steve at sk2.org>
Date: Fri Jan 20 08:47:45 2017 +0100
Import Upstream version 1.14
---
Definition | 142 ++++++
Makefile | 14 +
README | 180 +++++++
Scott.h | 79 ++++
ScottCurses.c | 1454 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 1869 insertions(+)
diff --git a/Definition b/Definition
new file mode 100755
index 0000000..93e1ce3
--- /dev/null
+++ b/Definition
@@ -0,0 +1,142 @@
+Game
+
+A game consists of a header of 14 values each apparently 16 bit
+
+0 Unknown
+1 Number of items
+2 Number of actions
+3 Number of Nouns and Verbs (one list is padded)
+4 Number of rooms
+5 Maximum a player can carry
+6 Starting Room
+7 Total Treasures (*)
+8 Word Length (only seen 3,4 or 5)
+9 Time light source lasts. This counts down every time item 9 is
+ in game. Brian Howarths games allow -1 for never run down. When
+ it runs out the light item (9) is dumped in room 0 and a look
+ done. Messages vary between interpreters and include things
+ like 'Your light is flickering and dying' as well as
+ 'Light runs out in %d turns'.
+10 Number of Messages
+11 Room you must put treasure in to score points. Not all games use
+ the treasure system for scoring
+12 Unknown
+
+All the number of something values are the last item to be read counting
+from 0. Thus 3 messages, means messages 0, 1, 2 and 3.
+
+(*) This can be calculated in game. What happens if the number is wrong
+I don't know. I've found no games that it occurs in.
+
+A game has 16 (maybe more) binary flags, and 8 (maybe more counters). A few
+later games seem to have 2 (maybe more) values to store location numbers in
+temporarily - eg Yoho spell in Claymorgue.
+
+Following the header is a list of game actions. Each is of the form
+
+150*verb+noun
+5 repeats of condition+20*value
+150*action1+action2
+150*action3+action4
+
+Conditions
+
+0 Parameter
+1 Item <arg> carried
+2 Item <arg> in room with player
+3 Item <arg> carried or in room with player
+4 In room <arg>
+5 Item <arg> not in room with player
+6 Item <arg> not carried
+7 Not in room <arg>
+8 BitFlag <arg> is set.
+9 BitFlag <arg> is cleared
+10 Something carried (arg unused)
+11 Nothing carried (arg unused)
+12 Item <arg> not carried nor in room with player
+13 Item <arg> is in game [not in room 0]
+14 Item <arg> is not in game [in room 0]
+15 CurrentCounter <= <arg>
+16 CurrentCounter >= <arg>
+17 Object still in initial room
+18 Object not in initial room
+19 CurrentCounter = <arg>
+
+Actions
+
+0 Does nothing
+1-51 Print message 0-50. Some drivers add a space some add a newline.
+52 Get item <arg>. Checks if you can carry it first
+53 Drops item <arg>
+54 Moves to room <arg>
+55 Item <arg> is removed from the game (put in room 0)
+56 The darkness flag is set
+57 The darkness flag is cleared
+58 Bitflag <arg> is set
+59 The same as 55 (it seems - I'm cautious about this)
+60 BitFlag <arg> is cleared
+61 Death. Dark flag cleared, player moved to last room
+62 Item <arg> put in room <arg>
+63 Game over.
+64 Describe room
+65 Score
+66 Inventory
+67 BitFlag 0 is set
+68 BitFlag 0 is cleared
+69 Refill lamp (?)
+70 Screen is cleared. This varies by driver from no effect upwards
+71 Saves the game. Choices of filename etc depend on the driver alone.
+72 Swap item <arg1> and item <arg2> locations
+73 Continue with next line (the next line starts verb 0 noun 0)
+74 Take item <arg> - no check is done too see if it can be carried.
+75 Put item <arg1> with item <arg2> - Not certain seems to do this
+ from examination of Claymorgue
+76 Look (same as 64 ?? - check)
+77 Decrement current counter. Will not go below 0
+78 Print current counter value. Some drivers only cope with 0-99
+ apparently
+79 Set current counter value
+80 Swap location with current location-swap flag
+81 Select a counter. Current counter is swapped with backup counter
+ <arg>
+82 Add <arg> to current counter
+83 Subtract <arg> from current counter
+84 Echo noun player typed without CR
+85 Echo the noun the player typed
+86 CR
+87 Swap current location value with backup location-swap value <arg>
+88 Wait 2 seconds
+89 SAGA - draw picture <n> (actually <n+number of rooms>, as each
+ Look() draws picture <room number> automatically)
+ Older spectrum driver - crashes
+ Spectrum Seas of Blood - seems to start Fighting Fantasy combat mode
+90-101 Unused
+102+ Print message 51-99
+
+
+This is followed by the words with verbs and nouns interleaved. A word with
+a * at the beginning is a synonym for the word above.
+Verb 1 is GO, verb 10 is GET, verb 18 is DROP (always).
+Nouns 1-6 are directions.
+
+This is followed by the rooms. Each room is 6 exits (north south east west
+up down) followed by a text string.
+
+Then come the messages, stored as a list of strings.
+
+Next come the items in the format item text then location. Item text may
+end with /TEXT/. This text is not printed but means that an automatic
+get/drop will be done for 'GET/DROP TEXT' on this item. Item names beginning
+with '*' are treasures. The '*' is printed. If you put all treasures in the
+treasure room (in the header) and 'SCORE' the game finishes with a well done
+message. Item location -1 is the inventory (255 on C64 and Spectrum tape
+games) and 0 means not in play in every game I've looked at. The lamp (always
+object 9) behaviour supports this belief.
+
+A set of strings follow this. In order they match to each line of verb/noun
+actions, and are comments. The Spectrum and C64 tape system where the
+database is compiled into the program has no comments.
+
+Finally three values follow which are version, adventure number and an
+unknown magic number.
+
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..abe57c4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the thing
+#
+CC = gcc
+#
+#
+all : ScottCurses
+
+ScottCurses.o: ScottCurses.c Scott.h
+
+ScottCurses: ScottCurses.o
+ $(CC) ScottCurses.o -o ScottCurses -lcurses -ltermcap
+
+
diff --git a/README b/README
new file mode 100755
index 0000000..bb68cf6
--- /dev/null
+++ b/README
@@ -0,0 +1,180 @@
+This is my second serious production edition of the Scott Adams game
+player. It needs curses (or an equivalent - eg pccurses. A non-curses
+port should be easy too), and an ANSI C compiler.
+
+This code has been tested on a SUN3(SunOS 4.1.1) and on a Pyramid 9820 in
+the att universe.
+
+Installation
+------------
+
+Type 'make'. You will need a system with curses and an ANSI C compiler (eg
+gcc).
+
+Operation
+---------
+
+ScottFree reads and executes TRS80 format Scott Adams datafiles. It is
+possible to run other formats either by writing a loader for that format or
+a convertor to TRS80 format. Remember the Scott Adams games are still
+copyright - you need to buy or obtain the games legally for use with this
+interpreter. Some Scott Adams material is available fairly freely . Dec 1980
+Byte contains a game driver and also a program to write a version of Pirate
+Adventure. A PC-SIG disk contains Adventureland in BASIC with a database in
+DATA statements. The file 'Definition' in this archive explains the TRS80
+format as I believe it exists. Much of this definition comes from P.D.Doherty
+who provided a lot of information.
+
+ScottFree should run all the Scott Adams, Brian Howarth and some other
+Adventure International games. (Gremlins and Supergran have a compressed
+action table, Robin Of Sherwood and Seas Of Blood have both a compressed
+action table and compressed text. Seas Of Blood won't run straight off due
+to the bizarre Fighting Fantasy (tm) combat system built into it.)
+
+Command Options
+---------------
+
+ScottFree [flags] <databasename> [save-file]
+
+Specifying save-file causes a restore of the save to take place.
+
+The flags are
+
+-d Debugging info on load
+-i Generate 'I am' type messages (default)
+-y Generate 'You are', 'You are carrying' type messages for games that
+ use these instead (eg Robin Of Sherwood)
+-s Generate authentic Scott Adams driver light messages rather than
+ other driver style ones (Light goes out in %d turns..)
+-t Generate TRS80 style display (terminal width is 64 characters; a
+ line <-----------------> is displayed after the top stuff; objects
+ have periods after them instead of hyphens
+
+
+Statement Of Copyright/License
+------------------------------
+
+This software is supplied subject to the GNU software copyleft (version 2)
+available from GNU or for FTP from prep.ai.mit.edu. All material in this
+program was developed by Swansea University Computer Society without
+disassembly of any other game drivers, only of game databases as permitted
+by EEC law (for purposes of compatibility). It is your responsibility not
+to transfer this software to any country where such reverse engineering is
+not permitted. This software license does not include any rights with
+regards to the Scott Adams games themselves. These games are copyright and
+you should obtain them from a legal source.
+
+The following information sources were used to produce the game driver:
+
+PC-SIG disk of Adventureland:
+ This gives the Adventureland database as well as about 80% of the
+full interpreter system. The core of the gamedriver was written using this
+as a reference to the game code.
+
+Byte Dec 1980:
+ This contains a good article about Scott and his games, as well as
+a TRS80 driver and datafile writer for the 'Pirate Adventure' game. This
+filled in some more answers as well as bits of the TRS80 data format
+
+P.D.Doherty:
+ Many thanks go to him for figuring out a load more actions, testing,
+hunting for games which used unknown actions and for writing a Scott Adams
+database to readable text convertor. This helped resolve several other
+actions.
+
+
+Changes 1.14
+------------
+
+o Bit flag 16 support
+o Lamp behaviour flag '-p' for prehistoric databases which don't use
+ bit 16
+o Light out messages don't appear when the lamp is elsewhere.
+o Automatic get/drop has synonym support.
+
+Changes 1.13
+------------
+
+o Darkness is now done like the actual Scott driver seems to do it,
+ using bit flag 15. Fixes problems in The Count
+o Display problem with 4.4BSD curses fixed (added a wmove() call)
+o Can't TAKE ALL in a dark room.
+
+Changes 1.12a
+-------------
+
+o Merged in some fixes by Steve Rice <sarice at edaca.ingr.com>
+ (Variables for terminal size, wrong wraparound due to bug in Look(),
+ TRS80 style option)
+o Updated PC version.
+
+Changes 1.12
+------------
+
+o Merged in some fixes by Antoine Sabot-Durand <sabot at fr.dgac.stna7>
+ (Redraw in dark rooms, darkness flag testing, Action 74 bug).
+ 'Pirate Adventure' should now work.
+o Added some comments
+o Added a makefile
+o Fixed several missing redraws.
+
+Changes 1.11
+------------
+
+o Major bug in file reading routines fixed. This should now read
+ _ALL_ the Scott Adams files without you having to add spaces.
+o Knows about the use of // in item texts and correctly handles it.
+o Uses unsigned char for the location of an item so that it correctly
+ behaves like the spectrum editions on wrapping. This makes a lot
+ more of the Brian Howarth material work.
+o Rewrote the awful OutBuf() function to be a bit neater.
+o Messed up the neat OutBuf() function by supporting old BSD curses
+ too. Linux people and 386BSD people should now be in luck, as
+ should any old BSD4.x users.
+o TAKE ALL/DROP ALL. Emulates Brian Howarth driver including the
+ number of moves bug.
+ NOTE:: TAKE ALL/DROP ALL count as one move. In some games that
+ give limited moves for things this makes it easier or enables
+ you to do things you should not be able to. The Brian Howarth
+ games all have this feature and should be fine.
+o Started work on an Xview version - don't expect it just yet.
+o Fixed a major cockup in the execution rules for lines. Robin Of
+ Sherwood lets you out of the cell without killing you at last.
+o Place item -> location failed with some compilers (most), now
+ made portable.
+o WAIT action refreshes display first
+o Redraws any pending display changes before the status table
+o Option flags tidied up.
+
+Changes 1.10
+------------
+
+o Action 75 added (dunno how it was missed)
+o Corrected second Byte year reference
+
+Changes 1.9
+-----------
+
+o Inventory short cut
+o Swap room flag/location now fixed. This should make Claymorgue work
+ correctly (ha!).
+o Corrected Byte reference from 1990 to 1980.
+
+Changes 1.8
+-----------
+
+o Move location action sets the redraw flag
+o Driver ignored last line of table (now fixed)
+o Save/Load implemented.
+o N,E,S,W,U,D shortcuts added. I will add the item ones once I've
+ loaded a few more fake saves into the genuine Brian Howarth driver
+ to figure out how it works.
+
+To Do
+-----
+
+o Tidy up TAKE ALL/DROP ALL. They match the Spectrum version -
+ which appears to be buggy. Also note that using GET ALL / DROP ALL
+ with older games _MAY_BREAK_THINGS_. Maybe this should be a flagged
+ option.
+
diff --git a/Scott.h b/Scott.h
new file mode 100755
index 0000000..7a1d0c7
--- /dev/null
+++ b/Scott.h
@@ -0,0 +1,79 @@
+/*
+ * SCOTT FREE
+ *
+ * A free Scott Adams style adventure interpreter
+ *
+ * Copyright:
+ * This software is placed under the GNU license.
+ *
+ * Statement:
+ * Everything in this program has been deduced or obtained solely
+ * from published material. No game interpreter code has been
+ * disassembled, only published BASIC sources (PC-SIG, and Byte Dec
+ * 1980) have been used.
+ */
+
+/*
+ * Controlling block
+ */
+
+#define LIGHT_SOURCE 9 /* Always 9 how odd */
+#define CARRIED 255 /* Carried */
+#define DESTROYED 0 /* Destroyed */
+#define DARKBIT 15
+#define LIGHTOUTBIT 16 /* Light gone out */
+
+typedef struct
+{
+ short Unknown;
+ short NumItems;
+ short NumActions;
+ short NumWords; /* Smaller of verb/noun is padded to same size */
+ short NumRooms;
+ short MaxCarry;
+ short PlayerRoom;
+ short Treasures;
+ short WordLength;
+ short LightTime;
+ short NumMessages;
+ short TreasureRoom;
+} Header;
+
+typedef struct
+{
+ unsigned short Vocab;
+ unsigned short Condition[5];
+ unsigned short Action[2];
+} Action;
+
+typedef struct
+{
+ char *Text;
+ short Exits[6];
+} Room;
+
+typedef struct
+{
+ char *Text;
+ /* PORTABILITY WARNING: THESE TWO MUST BE 8 BIT VALUES. */
+ unsigned char Location;
+ unsigned char InitialLoc;
+ char *AutoGet;
+} Item;
+
+typedef struct
+{
+ short Version;
+ short AdventureNumber;
+ short Unknown;
+} Tail;
+
+
+
+#define YOUARE 1 /* You are not I am */
+#define SCOTTLIGHT 2 /* Authentic Scott Adams light messages */
+#define DEBUGGING 4 /* Info from database load */
+#define TRS80_STYLE 8 /* Display in style used on TRS-80 */
+#define PREHISTORIC_LAMP 16 /* Destroy the lamp (very old databases) */
+
+
diff --git a/ScottCurses.c b/ScottCurses.c
new file mode 100755
index 0000000..978a5e7
--- /dev/null
+++ b/ScottCurses.c
@@ -0,0 +1,1454 @@
+/*
+ * ScottFree Revision 1.14
+ *
+ *
+ * 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.
+ *
+ *
+ * You must have an ANSI C compiler to build this program.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#ifndef PYRAMID
+#include <stdlib.h>
+#endif
+#include <ctype.h>
+#include <curses.h>
+#include <stdarg.h>
+#include <signal.h>
+
+#include "Scott.h"
+
+#ifdef AMIGA
+#define NOGETPID
+#define NOSTRNCASECMP
+#endif
+
+#ifdef PYRAMID
+#define NOSTRNCASECMP
+#endif
+
+/*
+ * Configuration Twiddles
+ */
+
+#ifdef NOSTRNCASECMP
+
+static int strncasecmp(char *a,char *b, int n)
+{
+ while(*a&&n>0)
+ {
+ char c=*a;
+ char d=*b;
+ if(islower(c))
+ c=toupper(c);
+ if(islower(d))
+ d=toupper(d);
+ if(c<d)
+ return(-1);
+ if(c>d)
+ return(1);
+ a++;
+ b++;
+ n--;
+ if(n==0)
+ return(0);
+ }
+ if(*b)
+ return(1);
+ return(0);
+}
+#endif
+
+#ifdef NOGETPID
+#ifndef AMIGA
+#define getpid() 6031769
+#else
+#define getpid() ((int)FindTask(NULL))
+#endif
+#endif
+
+Header GameHeader;
+Tail GameTail;
+Item *Items;
+Room *Rooms;
+char **Verbs;
+char **Nouns;
+char **Messages;
+Action *Actions;
+int LightRefill;
+char NounText[16];
+int Counters[16]; /* Range unknown */
+int CurrentCounter;
+int SavedRoom;
+int RoomSaved[16]; /* Range unknown */
+int DisplayUp; /* Curses up */
+WINDOW *Top,*Bottom;
+int Redraw; /* Update item window */
+int Options; /* Option flags set */
+int Width; /* Terminal width */
+int TopHeight; /* Height of top window */
+int BottomHeight; /* Height of bottom window */
+
+#define TRS80_LINE "\n<------------------------------------------------------------>\n"
+
+#define MyLoc (GameHeader.PlayerRoom)
+
+long BitFlags=0; /* Might be >32 flags - I haven't seen >32 yet */
+
+void Fatal(char *x)
+{
+ if(DisplayUp)
+ endwin();
+ fprintf(stderr,"%s.\n",x);
+ exit(1);
+}
+
+void Aborted()
+{
+ Fatal("User exit");
+}
+
+void ClearScreen(void)
+{
+ werase(Bottom);
+ wrefresh(Bottom);
+}
+
+void *MemAlloc(int size)
+{
+ void *t=(void *)malloc(size);
+ if(t==NULL)
+ Fatal("Out of memory");
+ return(t);
+}
+
+int RandomPercent(int n)
+{
+ unsigned int rv=rand()<<6;
+ rv%=100;
+ if(rv<n)
+ return(1);
+ return(0);
+}
+
+int CountCarried()
+{
+ int ct=0;
+ int n=0;
+ while(ct<=GameHeader.NumItems)
+ {
+ if(Items[ct].Location==CARRIED)
+ n++;
+ ct++;
+ }
+ return(n);
+}
+
+char *MapSynonym(char *word)
+{
+ int n=1;
+ char *tp;
+ static char lastword[16]; /* Last non synonym */
+ while(n<=GameHeader.NumWords)
+ {
+ tp=Nouns[n];
+ if(*tp=='*')
+ tp++;
+ else
+ strcpy(lastword,tp);
+ if(strncasecmp(word,tp,GameHeader.WordLength)==0)
+ return(lastword);
+ n++;
+ }
+ return(NULL);
+}
+
+int MatchUpItem(char *text, int loc)
+{
+ char *word=MapSynonym(text);
+ int ct=0;
+
+ if(word==NULL)
+ word=text;
+
+ while(ct<=GameHeader.NumItems)
+ {
+ if(Items[ct].AutoGet && Items[ct].Location==loc &&
+ strncasecmp(Items[ct].AutoGet,word,GameHeader.WordLength)==0)
+ return(ct);
+ ct++;
+ }
+ return(-1);
+}
+
+char *ReadString(FILE *f)
+{
+ char tmp[1024];
+ char *t;
+ int c,nc;
+ int ct=0;
+oops: do
+ {
+ c=fgetc(f);
+ }
+ while(c!=EOF && isspace(c));
+ if(c!='"')
+ {
+ Fatal("Initial quote expected");
+ }
+ do
+ {
+ c=fgetc(f);
+ if(c==EOF)
+ Fatal("EOF in string");
+ if(c=='"')
+ {
+ nc=fgetc(f);
+ if(nc!='"')
+ {
+ ungetc(nc,f);
+ break;
+ }
+ }
+ if(c==0x60)
+ c='"'; /* pdd */
+ tmp[ct++]=c;
+ }
+ while(1);
+ tmp[ct]=0;
+ t=MemAlloc(ct+1);
+ memcpy(t,tmp,ct+1);
+ return(t);
+}
+
+void LoadDatabase(FILE *f, int loud)
+{
+ int ni,na,nw,nr,mc,pr,tr,wl,lt,mn,trm;
+ int ct;
+ short lo;
+ Action *ap;
+ Room *rp;
+ Item *ip;
+/* Load the header */
+
+ if(fscanf(f,"%*d %d %d %d %d %d %d %d %d %d %d %d",
+ &ni,&na,&nw,&nr,&mc,&pr,&tr,&wl,<,&mn,&trm,&ct)<10)
+ Fatal("Invalid database(bad header)");
+ GameHeader.NumItems=ni;
+ Items=(Item *)MemAlloc(sizeof(Item)*(ni+1));
+ GameHeader.NumActions=na;
+ Actions=(Action *)MemAlloc(sizeof(Action)*(na+1));
+ GameHeader.NumWords=nw;
+ GameHeader.WordLength=wl;
+ Verbs=(char **)MemAlloc(sizeof(char *)*(nw+1));
+ Nouns=(char **)MemAlloc(sizeof(char *)*(nw+1));
+ GameHeader.NumRooms=nr;
+ Rooms=(Room *)MemAlloc(sizeof(Room)*(nr+1));
+ GameHeader.MaxCarry=mc;
+ GameHeader.PlayerRoom=pr;
+ GameHeader.Treasures=tr;
+ GameHeader.LightTime=lt;
+ LightRefill=lt;
+ GameHeader.NumMessages=mn;
+ Messages=(char **)MemAlloc(sizeof(char *)*(mn+1));
+ GameHeader.TreasureRoom=trm;
+
+/* Load the actions */
+
+ ct=0;
+ ap=Actions;
+ if(loud)
+ printf("Reading %d actions.\n",na);
+ while(ct<na+1)
+ {
+ if(fscanf(f,"%hd %hd %hd %hd %hd %hd %hd %hd",
+ &ap->Vocab,
+ &ap->Condition[0],
+ &ap->Condition[1],
+ &ap->Condition[2],
+ &ap->Condition[3],
+ &ap->Condition[4],
+ &ap->Action[0],
+ &ap->Action[1])!=8)
+ {
+ printf("Bad action line (%d)\n",ct);
+ exit(1);
+ }
+ ap++;
+ ct++;
+ }
+ ct=0;
+ if(loud)
+ printf("Reading %d word pairs.\n",nw);
+ while(ct<nw+1)
+ {
+ Verbs[ct]=ReadString(f);
+ Nouns[ct]=ReadString(f);
+ ct++;
+ }
+ ct=0;
+ rp=Rooms;
+ if(loud)
+ printf("Reading %d rooms.\n",nr);
+ while(ct<nr+1)
+ {
+ fscanf(f,"%hd %hd %hd %hd %hd %hd",
+ &rp->Exits[0],&rp->Exits[1],&rp->Exits[2],
+ &rp->Exits[3],&rp->Exits[4],&rp->Exits[5]);
+ rp->Text=ReadString(f);
+ ct++;
+ rp++;
+ }
+ ct=0;
+ if(loud)
+ printf("Reading %d messages.\n",mn);
+ while(ct<mn+1)
+ {
+ Messages[ct]=ReadString(f);
+ ct++;
+ }
+ ct=0;
+ if(loud)
+ printf("Reading %d items.\n",ni);
+ ip=Items;
+ while(ct<ni+1)
+ {
+ ip->Text=ReadString(f);
+ ip->AutoGet=strchr(ip->Text,'/');
+ /* Some games use // to mean no auto get/drop word! */
+ if(ip->AutoGet && strcmp(ip->AutoGet,"//") && strcmp(ip->AutoGet,"/*"))
+ {
+ char *t;
+ *ip->AutoGet++=0;
+ t=strchr(ip->AutoGet,'/');
+ if(t!=NULL)
+ *t=0;
+ }
+ fscanf(f,"%hd",&lo);
+ ip->Location=(unsigned char)lo;
+ ip->InitialLoc=ip->Location;
+ ip++;
+ ct++;
+ }
+ ct=0;
+ /* Discard Comment Strings */
+ while(ct<na+1)
+ {
+ free(ReadString(f));
+ ct++;
+ }
+ fscanf(f,"%d",&ct);
+ if(loud)
+ printf("Version %d.%02d of Adventure ",
+ ct/100,ct%100);
+ fscanf(f,"%d",&ct);
+ if(loud)
+ printf("%d.\nLoad Complete.\n\n",ct);
+}
+
+int OutputPos=0;
+
+void OutReset()
+{
+ OutputPos=0;
+ wmove(Bottom,BottomHeight-1,0);
+ wclrtoeol(Bottom);
+}
+
+void OutBuf(char *buffer)
+{
+ char word[80];
+ int wp;
+ while(*buffer)
+ {
+ if(OutputPos==0)
+ {
+ while(*buffer && isspace(*buffer))
+ {
+ if(*buffer=='\n')
+ {
+ scroll(Bottom);
+ wmove(Bottom,BottomHeight-1,0);
+ wclrtoeol(Bottom);
+ OutputPos=0;
+ }
+ buffer++;
+ }
+ }
+ if(*buffer==0)
+ return;
+ wp=0;
+ while(*buffer && !isspace(*buffer))
+ {
+ word[wp++]=*buffer++;
+ }
+ word[wp]=0;
+/* fprintf(stderr,"Word '%s' at %d\n",word,OutputPos);*/
+ if(OutputPos+strlen(word)>(Width-2))
+ {
+ scroll(Bottom);
+ wmove(Bottom,BottomHeight-1,0);
+ wclrtoeol(Bottom);
+ OutputPos=0;
+ }
+ wprintw(Bottom,word);
+ OutputPos+=strlen(word);
+
+ if(*buffer==0)
+ return;
+
+ if(*buffer=='\n')
+ {
+ scroll(Bottom);
+ wmove(Bottom,BottomHeight-1,0);
+ wclrtoeol(Bottom);
+ OutputPos=0;
+ }
+ else
+ {
+ OutputPos++;
+ if(OutputPos<(Width-1))
+ wprintw(Bottom," ");
+ }
+ buffer++;
+ }
+}
+
+void Output(char *a)
+{
+ char block[512];
+ strcpy(block,a);
+ OutBuf(block);
+}
+
+void OutputNumber(int a)
+{
+ char buf[16];
+ sprintf(buf,"%d ",a);
+ OutBuf(buf);
+}
+
+void Look()
+{
+ static char *ExitNames[6]=
+ {
+ "North","South","East","West","Up","Down"
+ };
+ Room *r;
+ int ct,f;
+ int pos;
+
+ werase(Top);
+ wmove(Top,0,0); /* Needed by some curses variants */
+ if((BitFlags&(1<<DARKBIT)) && Items[LIGHT_SOURCE].Location!= CARRIED
+ && Items[LIGHT_SOURCE].Location!= MyLoc)
+ {
+ if(Options&YOUARE)
+ wprintw(Top,"You can't see. It is too dark!\n");
+ else
+ wprintw(Top,"I can't see. It is too dark!\n");
+ if (Options & TRS80_STYLE)
+ wprintw(Top,TRS80_LINE);
+ wrefresh(Top);
+ return;
+ }
+ r=&Rooms[MyLoc];
+ if(*r->Text=='*')
+ wprintw(Top,"%s\n",r->Text+1);
+ else
+ {
+ if(Options&YOUARE)
+ wprintw(Top,"You are %s\n",r->Text);
+ else
+ wprintw(Top,"I'm in a %s\n",r->Text);
+ }
+ ct=0;
+ f=0;
+ wprintw(Top,"\nObvious exits: ");
+ while(ct<6)
+ {
+ if(r->Exits[ct]!=0)
+ {
+ if(f==0)
+ f=1;
+ else
+ wprintw(Top,", ");
+ wprintw(Top,"%s",ExitNames[ct]);
+ }
+ ct++;
+ }
+ if(f==0)
+ wprintw(Top,"none");
+ wprintw(Top,".\n");
+ ct=0;
+ f=0;
+ pos=0;
+ while(ct<=GameHeader.NumItems)
+ {
+ if(Items[ct].Location==MyLoc)
+ {
+ if(f==0)
+ {
+ if(Options&YOUARE)
+ wprintw(Top,"\nYou can also see: ");
+ else
+ wprintw(Top,"\nI can also see: ");
+ pos=16;
+ f++;
+ }
+ else if (!(Options & TRS80_STYLE))
+ {
+ wprintw(Top," - ");
+ pos+=3;
+ }
+ if(pos+strlen(Items[ct].Text)>(Width-10))
+ {
+ pos=0;
+ wprintw(Top,"\n");
+ }
+ wprintw(Top,"%s",Items[ct].Text);
+ pos += strlen(Items[ct].Text);
+ if (Options & TRS80_STYLE)
+ {
+ wprintw(Top,". ");
+ pos+=2;
+ }
+ }
+ ct++;
+ }
+ wprintw(Top,"\n");
+ if (Options & TRS80_STYLE)
+ wprintw(Top,TRS80_LINE);
+ wrefresh(Top);
+}
+
+int WhichWord(char *word, char **list)
+{
+ int n=1;
+ int ne=1;
+ char *tp;
+ while(ne<=GameHeader.NumWords)
+ {
+ tp=list[ne];
+ if(*tp=='*')
+ tp++;
+ else
+ n=ne;
+ if(strncasecmp(word,tp,GameHeader.WordLength)==0)
+ return(n);
+ ne++;
+ }
+ return(-1);
+}
+
+
+
+void LineInput(char *buf)
+{
+ int pos=0;
+ int ch;
+ while(1)
+ {
+ wrefresh(Bottom);
+ ch=wgetch(Bottom);
+ switch(ch)
+ {
+ case 10:;
+ case 13:;
+ buf[pos]=0;
+ scroll(Bottom);
+ wmove(Bottom,BottomHeight,0);
+ return;
+ case 8:;
+ case 127:;
+ if(pos>0)
+ {
+ int y,x;
+ getyx(Bottom,y,x);
+ x--;
+ if(x==-1)
+ {
+ x=Width-1;
+ y--;
+ }
+ mvwaddch(Bottom,y,x,' ');
+ wmove(Bottom,y,x);
+ wrefresh(Bottom);
+ pos--;
+ }
+ break;
+ default:
+ if(ch>=' '&&ch<=126)
+ {
+ buf[pos++]=ch;
+ waddch(Bottom,(char)ch);
+ wrefresh(Bottom);
+ }
+ break;
+ }
+ }
+}
+
+void GetInput(vb,no)
+int *vb,*no;
+{
+ char buf[256];
+ char verb[10],noun[10];
+ int vc,nc;
+ int num;
+ do
+ {
+ do
+ {
+ Output("\nTell me what to do ? ");
+ wrefresh(Bottom);
+ LineInput(buf);
+ OutReset();
+ num=sscanf(buf,"%9s %9s",verb,noun);
+ }
+ while(num==0||*buf=='\n');
+ if(num==1)
+ *noun=0;
+ if(*noun==0 && strlen(verb)==1)
+ {
+ switch(isupper(*verb)?tolower(*verb):*verb)
+ {
+ case 'n':strcpy(verb,"NORTH");break;
+ case 'e':strcpy(verb,"EAST");break;
+ case 's':strcpy(verb,"SOUTH");break;
+ case 'w':strcpy(verb,"WEST");break;
+ case 'u':strcpy(verb,"UP");break;
+ case 'd':strcpy(verb,"DOWN");break;
+ /* Brian Howarth interpreter also supports this */
+ case 'i':strcpy(verb,"INVENTORY");break;
+ }
+ }
+ nc=WhichWord(verb,Nouns);
+ /* The Scott Adams system has a hack to avoid typing 'go' */
+ if(nc>=1 && nc <=6)
+ {
+ vc=1;
+ }
+ else
+ {
+ vc=WhichWord(verb,Verbs);
+ nc=WhichWord(noun,Nouns);
+ }
+ *vb=vc;
+ *no=nc;
+ if(vc==-1)
+ {
+ Output("You use word(s) I don't know! ");
+ }
+ }
+ while(vc==-1);
+ strcpy(NounText,noun); /* Needed by GET/DROP hack */
+}
+
+void SaveGame()
+{
+ char buf[256];
+ int ct;
+ FILE *f;
+ Output("Filename: ");
+ LineInput(buf);
+ Output("\n");
+ f=fopen(buf,"w");
+ if(f==NULL)
+ {
+ Output("Unable to create save file.\n");
+ return;
+ }
+ for(ct=0;ct<16;ct++)
+ {
+ fprintf(f,"%d %d\n",Counters[ct],RoomSaved[ct]);
+ }
+ fprintf(f,"%ld %d %hd %d %d %hd\n",BitFlags, (BitFlags&(1<<DARKBIT))?1:0,
+ MyLoc,CurrentCounter,SavedRoom,GameHeader.LightTime);
+ for(ct=0;ct<=GameHeader.NumItems;ct++)
+ fprintf(f,"%hd\n",(short)Items[ct].Location);
+ fclose(f);
+ Output("Saved.\n");
+}
+
+void LoadGame(char *name)
+{
+ FILE *f=fopen(name,"r");
+ int ct=0;
+ short lo;
+ short DarkFlag;
+ if(f==NULL)
+ {
+ Output("Unable to restore game.");
+ return;
+ }
+ for(ct=0;ct<16;ct++)
+ {
+ fscanf(f,"%d %d\n",&Counters[ct],&RoomSaved[ct]);
+ }
+ fscanf(f,"%ld %d %hd %d %d %hd\n",
+ &BitFlags,&DarkFlag,&MyLoc,&CurrentCounter,&SavedRoom,
+ &GameHeader.LightTime);
+ /* Backward compatibility */
+ if(DarkFlag)
+ BitFlags|=(1<<15);
+ for(ct=0;ct<=GameHeader.NumItems;ct++)
+ {
+ fscanf(f,"%hd\n",&lo);
+ Items[ct].Location=(unsigned char)lo;
+ }
+ fclose(f);
+}
+
+int PerformLine(int ct)
+{
+ int continuation=0;
+ int param[5],pptr=0;
+ int act[4];
+ int cc=0;
+ while(cc<5)
+ {
+ int cv,dv;
+ cv=Actions[ct].Condition[cc];
+ dv=cv/20;
+ cv%=20;
+ switch(cv)
+ {
+ case 0:
+ param[pptr++]=dv;
+ break;
+ case 1:
+ if(Items[dv].Location!=CARRIED)
+ return(0);
+ break;
+ case 2:
+ if(Items[dv].Location!=MyLoc)
+ return(0);
+ break;
+ case 3:
+ if(Items[dv].Location!=CARRIED&&
+ Items[dv].Location!=MyLoc)
+ return(0);
+ break;
+ case 4:
+ if(MyLoc!=dv)
+ return(0);
+ break;
+ case 5:
+ if(Items[dv].Location==MyLoc)
+ return(0);
+ break;
+ case 6:
+ if(Items[dv].Location==CARRIED)
+ return(0);
+ break;
+ case 7:
+ if(MyLoc==dv)
+ return(0);
+ break;
+ case 8:
+ if((BitFlags&(1<<dv))==0)
+ return(0);
+ break;
+ case 9:
+ if(BitFlags&(1<<dv))
+ return(0);
+ break;
+ case 10:
+ if(CountCarried()==0)
+ return(0);
+ break;
+ case 11:
+ if(CountCarried())
+ return(0);
+ break;
+ case 12:
+ if(Items[dv].Location==CARRIED||Items[dv].Location==MyLoc)
+ return(0);
+ break;
+ case 13:
+ if(Items[dv].Location==0)
+ return(0);
+ break;
+ case 14:
+ if(Items[dv].Location)
+ return(0);
+ break;
+ case 15:
+ if(CurrentCounter>dv)
+ return(0);
+ break;
+ case 16:
+ if(CurrentCounter<=dv)
+ return(0);
+ break;
+ case 17:
+ if(Items[dv].Location!=Items[dv].InitialLoc)
+ return(0);
+ break;
+ case 18:
+ if(Items[dv].Location==Items[dv].InitialLoc)
+ return(0);
+ break;
+ case 19:/* Only seen in Brian Howarth games so far */
+ if(CurrentCounter!=dv)
+ return(0);
+ break;
+ }
+ cc++;
+ }
+ /* Actions */
+ act[0]=Actions[ct].Action[0];
+ act[2]=Actions[ct].Action[1];
+ act[1]=act[0]%150;
+ act[3]=act[2]%150;
+ act[0]/=150;
+ act[2]/=150;
+ cc=0;
+ pptr=0;
+ while(cc<4)
+ {
+ if(act[cc]>=1 && act[cc]<52)
+ {
+ Output(Messages[act[cc]]);
+ Output("\n");
+ }
+ else if(act[cc]>101)
+ {
+ Output(Messages[act[cc]-50]);
+ Output("\n");
+ }
+ else switch(act[cc])
+ {
+ case 0:/* NOP */
+ break;
+ case 52:
+ if(CountCarried()==GameHeader.MaxCarry)
+ {
+ if(Options&YOUARE)
+ Output("You are carrying too much. ");
+ else
+ Output("I've too much to carry! ");
+ break;
+ }
+ if(Items[param[pptr]].Location==MyLoc)
+ Redraw=1;
+ Items[param[pptr++]].Location= CARRIED;
+ break;
+ case 53:
+ Redraw=1;
+ Items[param[pptr++]].Location=MyLoc;
+ break;
+ case 54:
+ Redraw=1;
+ MyLoc=param[pptr++];
+ break;
+ case 55:
+ if(Items[param[pptr]].Location==MyLoc)
+ Redraw=1;
+ Items[param[pptr++]].Location=0;
+ break;
+ case 56:
+ BitFlags|=1<<DARKBIT;
+ break;
+ case 57:
+ BitFlags&=~(1<<DARKBIT);
+ break;
+ case 58:
+ BitFlags|=(1<<param[pptr++]);
+ break;
+ case 59:
+ if(Items[param[pptr]].Location==MyLoc)
+ Redraw=1;
+ Items[param[pptr++]].Location=0;
+ break;
+ case 60:
+ BitFlags&=~(1<<param[pptr++]);
+ break;
+ case 61:
+ if(Options&YOUARE)
+ Output("You are dead.\n");
+ else
+ Output("I am dead.\n");
+ BitFlags&=~(1<<DARKBIT);
+ MyLoc=GameHeader.NumRooms;/* It seems to be what the code says! */
+ Look();
+ break;
+ case 62:
+ {
+ /* Bug fix for some systems - before it could get parameters wrong */
+ int i=param[pptr++];
+ Items[i].Location=param[pptr++];
+ Redraw=1;
+ break;
+ }
+ case 63:
+doneit: Output("The game is now over.\n");
+ wrefresh(Bottom);
+ sleep(5);
+ endwin();
+ exit(0);
+ case 64:
+ Look();
+ break;
+ case 65:
+ {
+ int ct=0;
+ int n=0;
+ while(ct<=GameHeader.NumItems)
+ {
+ if(Items[ct].Location==GameHeader.TreasureRoom &&
+ *Items[ct].Text=='*')
+ n++;
+ ct++;
+ }
+ if(Options&YOUARE)
+ Output("You have stored ");
+ else
+ Output("I've stored ");
+ OutputNumber(n);
+ Output(" treasures. On a scale of 0 to 100, that rates ");
+ OutputNumber((n*100)/GameHeader.Treasures);
+ Output(".\n");
+ if(n==GameHeader.Treasures)
+ {
+ Output("Well done.\n");
+ goto doneit;
+ }
+ break;
+ }
+ case 66:
+ {
+ int ct=0;
+ int f=0;
+ if(Options&YOUARE)
+ Output("You are carrying:\n");
+ else
+ Output("I'm carrying:\n");
+ while(ct<=GameHeader.NumItems)
+ {
+ if(Items[ct].Location==CARRIED)
+ {
+ if(f==1)
+ {
+ if (Options & TRS80_STYLE)
+ Output(". ");
+ else
+ Output(" - ");
+ }
+ f=1;
+ Output(Items[ct].Text);
+ }
+ ct++;
+ }
+ if(f==0)
+ Output("Nothing");
+ Output(".\n");
+ break;
+ }
+ case 67:
+ BitFlags|=(1<<0);
+ break;
+ case 68:
+ BitFlags&=~(1<<0);
+ break;
+ case 69:
+ GameHeader.LightTime=LightRefill;
+ if(Items[LIGHT_SOURCE].Location==MyLoc)
+ Redraw=1;
+ Items[LIGHT_SOURCE].Location=CARRIED;
+ BitFlags&=~(1<<LIGHTOUTBIT);
+ break;
+ case 70:
+ ClearScreen(); /* pdd. */
+ OutReset();
+ break;
+ case 71:
+ SaveGame();
+ break;
+ case 72:
+ {
+ int i1=param[pptr++];
+ int i2=param[pptr++];
+ int t=Items[i1].Location;
+ if(t==MyLoc || Items[i2].Location==MyLoc)
+ Redraw=1;
+ Items[i1].Location=Items[i2].Location;
+ Items[i2].Location=t;
+ break;
+ }
+ case 73:
+ continuation=1;
+ break;
+ case 74:
+ if(Items[param[pptr]].Location==MyLoc)
+ Redraw=1;
+ Items[param[pptr++]].Location= CARRIED;
+ break;
+ case 75:
+ {
+ int i1,i2;
+ i1=param[pptr++];
+ i2=param[pptr++];
+ if(Items[i1].Location==MyLoc)
+ Redraw=1;
+ Items[i1].Location=Items[i2].Location;
+ if(Items[i2].Location==MyLoc)
+ Redraw=1;
+ break;
+ }
+ case 76: /* Looking at adventure .. */
+ Look();
+ break;
+ case 77:
+ if(CurrentCounter>=0)
+ CurrentCounter--;
+ break;
+ case 78:
+ OutputNumber(CurrentCounter);
+ break;
+ case 79:
+ CurrentCounter=param[pptr++];
+ break;
+ case 80:
+ {
+ int t=MyLoc;
+ MyLoc=SavedRoom;
+ SavedRoom=t;
+ Redraw=1;
+ break;
+ }
+ case 81:
+ {
+ /* This is somewhat guessed. Claymorgue always
+ seems to do select counter n, thing, select counter n,
+ but uses one value that always seems to exist. Trying
+ a few options I found this gave sane results on ageing */
+ int t=param[pptr++];
+ int c1=CurrentCounter;
+ CurrentCounter=Counters[t];
+ Counters[t]=c1;
+ break;
+ }
+ case 82:
+ CurrentCounter+=param[pptr++];
+ break;
+ case 83:
+ CurrentCounter-=param[pptr++];
+ if(CurrentCounter< -1)
+ CurrentCounter= -1;
+ /* Note: This seems to be needed. I don't yet
+ know if there is a maximum value to limit too */
+ break;
+ case 84:
+ Output(NounText);
+ break;
+ case 85:
+ Output(NounText);
+ Output("\n");
+ break;
+ case 86:
+ Output("\n");
+ break;
+ case 87:
+ {
+ /* Changed this to swap location<->roomflag[x]
+ not roomflag 0 and x */
+ int p=param[pptr++];
+ int sr=MyLoc;
+ MyLoc=RoomSaved[p];
+ RoomSaved[p]=sr;
+ Redraw=1;
+ break;
+ }
+ case 88:
+ wrefresh(Top);
+ wrefresh(Bottom);
+ sleep(2); /* DOC's say 2 seconds. Spectrum times at 1.5 */
+ break;
+ case 89:
+ pptr++;
+ /* SAGA draw picture n */
+ /* Spectrum Seas of Blood - start combat ? */
+ /* Poking this into older spectrum games causes a crash */
+ break;
+ default:
+ fprintf(stderr,"Unknown action %d [Param begins %d %d]\n",
+ act[cc],param[pptr],param[pptr+1]);
+ break;
+ }
+ cc++;
+ }
+ return(1+continuation);
+}
+
+
+int PerformActions(int vb,int no)
+{
+ static int disable_sysfunc=0; /* Recursion lock */
+ int d=BitFlags&(1<<DARKBIT);
+
+ int ct=0;
+ int fl;
+ int doagain=0;
+ if(vb==1 && no == -1 )
+ {
+ Output("Give me a direction too.");
+ return(0);
+ }
+ if(vb==1 && no>=1 && no<=6)
+ {
+ int nl;
+ if(Items[LIGHT_SOURCE].Location==MyLoc ||
+ Items[LIGHT_SOURCE].Location==CARRIED)
+ d=0;
+ if(d)
+ Output("Dangerous to move in the dark! ");
+ nl=Rooms[MyLoc].Exits[no-1];
+ if(nl!=0)
+ {
+ MyLoc=nl;
+ Look();
+ return(0);
+ }
+ if(d)
+ {
+ if(Options&YOUARE)
+ Output("You fell down and broke your neck. ");
+ else
+ Output("I fell down and broke my neck. ");
+ wrefresh(Bottom);
+ sleep(5);
+ endwin();
+ exit(0);
+ }
+ if(Options&YOUARE)
+ Output("You can't go in that direction. ");
+ else
+ Output("I can't go in that direction. ");
+ return(0);
+ }
+ fl= -1;
+ while(ct<=GameHeader.NumActions)
+ {
+ int vv,nv;
+ vv=Actions[ct].Vocab;
+ /* Think this is now right. If a line we run has an action73
+ run all following lines with vocab of 0,0 */
+ if(vb!=0 && (doagain&&vv!=0))
+ break;
+ /* Oops.. added this minor cockup fix 1.11 */
+ if(vb!=0 && !doagain && fl== 0)
+ break;
+ nv=vv%150;
+ vv/=150;
+ if((vv==vb)||(doagain&&Actions[ct].Vocab==0))
+ {
+ if((vv==0 && RandomPercent(nv))||doagain||
+ (vv!=0 && (nv==no||nv==0)))
+ {
+ int f2;
+ if(fl== -1)
+ fl= -2;
+ if((f2=PerformLine(ct))>0)
+ {
+ /* ahah finally figured it out ! */
+ fl=0;
+ if(f2==2)
+ doagain=1;
+ if(vb!=0 && doagain==0)
+ return;
+ }
+ }
+ }
+ ct++;
+ if(Actions[ct].Vocab!=0)
+ doagain=0;
+ }
+ if(fl!=0 && disable_sysfunc==0)
+ {
+ int i;
+ if(Items[LIGHT_SOURCE].Location==MyLoc ||
+ Items[LIGHT_SOURCE].Location==CARRIED)
+ d=0;
+ if(vb==10 || vb==18)
+ {
+ /* Yes they really _are_ hardcoded values */
+ if(vb==10)
+ {
+ if(strcasecmp(NounText,"ALL")==0)
+ {
+ int ct=0;
+ int f=0;
+
+ if(d)
+ {
+ Output("It is dark.\n");
+ return 0;
+ }
+ while(ct<=GameHeader.NumItems)
+ {
+ if(Items[ct].Location==MyLoc && Items[ct].AutoGet!=NULL && Items[ct].AutoGet[0]!='*')
+ {
+ no=WhichWord(Items[ct].AutoGet,Nouns);
+ disable_sysfunc=1; /* Don't recurse into auto get ! */
+ PerformActions(vb,no); /* Recursively check each items table code */
+ disable_sysfunc=0;
+ if(CountCarried()==GameHeader.MaxCarry)
+ {
+ if(Options&YOUARE)
+ Output("You are carrying too much. ");
+ else
+ Output("I've too much to carry. ");
+ return(0);
+ }
+ Items[ct].Location= CARRIED;
+ Redraw=1;
+ OutBuf(Items[ct].Text);
+ Output(": O.K.\n");
+ f=1;
+ }
+ ct++;
+ }
+ if(f==0)
+ Output("Nothing taken.");
+ return(0);
+ }
+ if(no==-1)
+ {
+ Output("What ? ");
+ return(0);
+ }
+ if(CountCarried()==GameHeader.MaxCarry)
+ {
+ if(Options&YOUARE)
+ Output("You are carrying too much. ");
+ else
+ Output("I've too much to carry. ");
+ return(0);
+ }
+ i=MatchUpItem(NounText,MyLoc);
+ if(i==-1)
+ {
+ if(Options&YOUARE)
+ Output("It is beyond your power to do that. ");
+ else
+ Output("It's beyond my power to do that. ");
+ return(0);
+ }
+ Items[i].Location= CARRIED;
+ Output("O.K. ");
+ Redraw=1;
+ return(0);
+ }
+ if(vb==18)
+ {
+ if(strcasecmp(NounText,"ALL")==0)
+ {
+ int ct=0;
+ int f=0;
+ while(ct<=GameHeader.NumItems)
+ {
+ if(Items[ct].Location==CARRIED && Items[ct].AutoGet && Items[ct].AutoGet[0]!='*')
+ {
+ no=WhichWord(Items[ct].AutoGet,Nouns);
+ disable_sysfunc=1;
+ PerformActions(vb,no);
+ disable_sysfunc=0;
+ Items[ct].Location=MyLoc;
+ OutBuf(Items[ct].Text);
+ Output(": O.K.\n");
+ Redraw=1;
+ f=1;
+ }
+ ct++;
+ }
+ if(f==0)
+ Output("Nothing dropped.\n");
+ return(0);
+ }
+ if(no==-1)
+ {
+ Output("What ? ");
+ return(0);
+ }
+ i=MatchUpItem(NounText,CARRIED);
+ if(i==-1)
+ {
+ if(Options&YOUARE)
+ Output("It's beyond your power to do that.\n");
+ else
+ Output("It's beyond my power to do that.\n");
+ return(0);
+ }
+ Items[i].Location=MyLoc;
+ Output("O.K. ");
+ Redraw=1;
+ return(0);
+ }
+ }
+ }
+ return(fl);
+}
+
+void main(int argc, char *argv[])
+{
+ FILE *f;
+ int vb,no;
+
+ while(argv[1])
+ {
+ if(*argv[1]!='-')
+ break;
+ switch(argv[1][1])
+ {
+ case 'y':
+ Options|=YOUARE;
+ break;
+ case 'i':
+ Options&=~YOUARE;
+ break;
+ case 'd':
+ Options|=DEBUGGING;
+ break;
+ case 's':
+ Options|=SCOTTLIGHT;
+ break;
+ case 't':
+ Options|=TRS80_STYLE;
+ break;
+ case 'p':
+ Options|=PREHISTORIC_LAMP;
+ break;
+ case 'h':
+ default:
+ fprintf(stderr,"%s: [-h] [-y] [-s] [-i] [-t] [-d] [-p] <gamename> [savedgame].\n",
+ argv[0]);
+ exit(1);
+ }
+ if(argv[1][2]!=0)
+ {
+ fprintf(stderr,"%s: option -%c does not take a parameter.\n",
+ argv[0],argv[1][1]);
+ exit(1);
+ }
+ argv++;
+ argc--;
+ }
+
+ if(argc!=2 && argc!=3)
+ {
+ fprintf(stderr,"%s <database> <savefile>.\n",argv[0]);
+ exit(1);
+ }
+ f=fopen(argv[1],"r");
+ if(f==NULL)
+ {
+ perror(argv[1]);
+ exit(1);
+ }
+ signal(SIGINT,Aborted); /* For BSD curses */
+ signal(SIGQUIT,SIG_IGN);
+ signal(SIGTSTP,SIG_IGN);
+
+ if (Options & TRS80_STYLE)
+ {
+ Width = 64;
+ TopHeight = 11;
+ BottomHeight = 13;
+ }
+ else
+ {
+ Width = 80;
+ TopHeight = 10;
+ BottomHeight = 14;
+ }
+
+ DisplayUp=1;
+ initscr();
+ Top=newwin(TopHeight,Width,0,0);
+ Bottom=newwin(BottomHeight,Width,TopHeight,0);
+ scrollok(Bottom,TRUE);
+ leaveok(Top,TRUE);
+ leaveok(Bottom,FALSE);
+ idlok(Bottom,TRUE);
+ noecho();
+ cbreak();
+ wmove(Bottom,BottomHeight-1,0);
+ OutReset();
+ OutBuf("\
+Scott Free, A Scott Adams game driver in C.\n\
+Release 1.14, (c) 1993,1994,1995 Swansea University Computer Society.\n\
+Distributed under the GNU software license\n\n");
+ LoadDatabase(f,(Options&DEBUGGING)?1:0);
+ fclose(f);
+ if(argc==3)
+ LoadGame(argv[2]);
+ srand(time(NULL)^getpid()^getuid());
+ Look();
+ while(1)
+ {
+ if(Redraw!=0)
+ {
+ Look();
+ Redraw=0;
+ }
+ PerformActions(0,0);
+ if(Redraw!=0)
+ {
+ Look();
+ Redraw=0;
+ }
+ GetInput(&vb,&no);
+ switch(PerformActions(vb,no))
+ {
+ case -1:Output("I don't understand your command. ");
+ break;
+ case -2:Output("I can't do that yet. ");
+ break;
+ }
+ /* Brian Howarth games seem to use -1 for forever */
+ if(Items[LIGHT_SOURCE].Location/*==-1*/!=DESTROYED && GameHeader.LightTime!= -1)
+ {
+ GameHeader.LightTime--;
+ if(GameHeader.LightTime<1)
+ {
+ BitFlags|=(1<<LIGHTOUTBIT);
+ if(Items[LIGHT_SOURCE].Location==CARRIED ||
+ Items[LIGHT_SOURCE].Location==MyLoc)
+ {
+ if(Options&SCOTTLIGHT)
+ Output("Light has run out! ");
+ else
+ Output("Your light has run out. ");
+ }
+ if(Options&PREHISTORIC_LAMP)
+ Items[LIGHT_SOURCE].Location=DESTROYED;
+ }
+ else if(GameHeader.LightTime<25)
+ {
+ if(Items[LIGHT_SOURCE].Location==CARRIED ||
+ Items[LIGHT_SOURCE].Location==MyLoc)
+ {
+
+ if(Options&SCOTTLIGHT)
+ {
+ Output("Light runs out in ");
+ OutputNumber(GameHeader.LightTime);
+ Output(" turns. ");
+ }
+ else
+ {
+ if(GameHeader.LightTime%5==0)
+ Output("Your light is growing dim. ");
+ }
+ }
+ }
+ }
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/scottfree.git
More information about the Pkg-games-commits
mailing list