aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/scott/scott.h
blob: 7f0e76109ae0987da79920a0952f2f8a78dee9a9 (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
192
/* 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_api.h"

namespace Glk {
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 MY_LOC   (_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 {
	int _vocab;
	int _condition[5];
	int _action[2];

	Action() : _vocab(0) {
		Common::fill(&_condition[0], &_condition[5], 0);
		Common::fill(&_action[0], &_action[2], 0);
	}
};

struct Room {
	Common::String _text;
	int _exits[6];

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

struct Item {
	Common::String _text;
	byte _location;
	byte _initialLoc;
	Common::String _autoGet;

	Item() : _location(0), _initialLoc(0) {}
};

struct Tail {
	int _version;
	int _adventureNumber;
	int _unknown;

	Tail() : _version(0), _adventureNumber(0), _unknown(0) {}
};

/**
 * Scott Adams game interpreter
 */
class Scott : public GlkAPI {
private:
	Header _gameHeader;
	Common::Array<Item> _items;
	Common::Array<Room> _rooms;
	Common::StringArray _verbs;
	Common::StringArray _nouns;
	Common::StringArray _messages;
	Common::Array<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 _splitScreen;
	winid_t _bottomWindow, _topWindow;
	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);
	bool randomPercent(uint n);
	int countCarried(void);
	const char *mapSynonym(const char *word);
	int matchUpItem(const char *text, int loc);
	Common::String readString(Common::SeekableReadStream *f);
	void loadDatabase(Common::SeekableReadStream *f, bool loud);
	void output(const Common::String &a);
	void outputNumber(int a);
	void look(void);
	int whichWord(const char *word, const Common::StringArray &list);
	void lineInput(char *buf, size_t n);
	int getInput(int *vb, int *no);
	int performLine(int ct);
	int performActions(int vb, int no);

	void readInts(Common::SeekableReadStream *f, size_t count, ...);
public:
	/**
	 * Constructor
	 */
	Scott(OSystem *syst, const GlkGameDescription &gameDesc);

	/**
	 * Returns the running interpreter type
	 */
	virtual InterpreterType getInterpreterType() const override { return INTERPRETER_SCOTT; }

	/**
	 * Execute the game
	 */
	virtual void runGame() override;

	/**
	 * Load a savegame from the passed Quetzal file chunk stream
	 */
	virtual Common::Error readSaveData(Common::SeekableReadStream *rs) override;

	/**
	 * Save the game. The passed write stream represents access to the UMem chunk
	 * in the Quetzal save file that will be created
	 */
	virtual Common::Error writeGameData(Common::WriteStream *ws) override;
};

} // End of namespace Scott
} // End of namespace Glk

#endif