[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,&lt,&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