aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/scott/scott.h
blob: ec6a8601baf2c62f3c245066e85b747f9b325ee7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/* 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.
 *
 */

#ifndef GLK_SCOTT
#define GLK_SCOTT

/*
 *  Controlling block
 */

#include "common/scummsys.h"
#include "glk/glk.h"

namespace Gargoyle {
namespace Scott {

#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

enum GameOption {
	YOUARE      = 1,        ///< You are not I am
	SCOTTLIGHT  = 2,        ///< Authentic Scott Adams light messages
	DEBUGGING   = 4,        ///< Info from database load
	TRS80_STYLE = 8,        ///< Display in style used on TRS-80
	PREHISTORIC_LAMP = 16   ///< Destroy the lamp (very old databases)
};

#define TRS80_LINE  "\n<------------------------------------------------------------>\n"
#define MyLoc   (GameHeader.PlayerRoom)

struct Header {
	int Unknown;
	int NumItems;
	int NumActions;
	int NumWords;           ///< Smaller of verb/noun is padded to same size
	int NumRooms;
	int MaxCarry;
	int PlayerRoom;
	int Treasures;
	int WordLength;
	int LightTime;
	int NumMessages;
	int TreasureRoom;

	Header() : Unknown(0), NumItems(0), NumActions(0), NumWords(0), NumRooms(0),
		MaxCarry(0), PlayerRoom(0), Treasures(0), WordLength(0), LightTime(0),
		NumMessages(0), TreasureRoom(0) {}
};

struct Action {
	uint Vocab;
	uint Condition[5];
	uint action[2];

	Action() : Vocab(0) {
		Common::fill(&Condition[0], &Condition[5], 0);
		Common::fill(&action[0], &action[2], 0);
	}
};

struct Room {
	char *Text;
	short Exits[6];

	Room() : Text(0) {
		Common::fill(&Exits[0], &Exits[6], 0);
	}
};

struct Item {
	char *Text;     // PORTABILITY WARNING: THESE TWO MUST BE 8 BIT VALUES.
	byte Location;
	byte InitialLoc;
	char *AutoGet;

	Item() : Text(nullptr), Location(0), InitialLoc(0), AutoGet(nullptr) {}
};

struct Tail {
	int Version;
	int AdventureNumber;
	int Unknown;

	Tail() : Version(0), AdventureNumber(0), Unknown(0) {}
};

/**
 * Scott Adams game interpreter
 */
class Scott : public Glk {
private:
	Header GameHeader;
	Item *Items;
	Room *Rooms;
	const char **Verbs;
	const char **Nouns;
	const char **Messages;
	Action *Actions;
	int LightRefill;
	char NounText[16];
	int Counters[16];   ///< Range unknown
	int CurrentCounter;
	int SavedRoom;
	int RoomSaved[16];  ///< Range unknown
	int Options;        ///< Option flags set
	int Width;          ///< Terminal width
	int TopHeight;      ///< Height of top window

	bool split_screen;
	winid_t Bottom, Top;
	uint32 BitFlags;    ///< Might be >32 flags - I haven't seen >32 yet
	int _saveSlot;		///< Save slot when loading savegame from launcher
private:
	/**
	 * Initialization code
	 */
	void initialize();

	void display(winid_t w, const char *fmt, ...);
	void delay(int seconds);
	void fatal(const char *x);
	void clearScreen(void);
	void *memAlloc(int size);
	bool randomPercent(uint n);
	int countCarried(void);
	const char *mapSynonym(const char *word);
	int matchUpItem(const char *text, int loc);
	char *readString(Common::SeekableReadStream *f);
	void loadDatabase(Common::SeekableReadStream *f, bool loud);
	void output(const char *a);
	void outputNumber(int a);
	void look(void);
	int whichWord(const char *word, const char **list);
	void lineInput(char *buf, size_t n);
	void saveGame(void);
	void loadGame(void);
	int getInput(int *vb, int *no);
	int performLine(int ct);
	int performActions(int vb, int no);

	int xstrcasecmp(const char *, const char *);
	int xstrncasecmp(const char *, const char *, size_t);
	void readInts(Common::SeekableReadStream *f, size_t count, ...);
public:
	/**
	 * Constructor
	 */
	Scott(OSystem *syst, const GargoyleGameDescription *gameDesc);

	/**
	 * Execute the game
	 */
	virtual void runGame(Common::SeekableReadStream *gameFile) override;

	/**
	 * Load a savegame
	 */
	virtual Common::Error loadGameState(int slot) override;

	/**
	 * Save the game
	 */
	virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
};

} // End of namespace Scott
} // End of namespace Gargoyle

#endif