aboutsummaryrefslogtreecommitdiff
path: root/engines/adl/adl.h
blob: 4ea756666997fdf6295a2fb9797aaad2fedcdc6d (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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/* 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 ADL_ADL_H
#define ADL_ADL_H

#include "common/array.h"
#include "common/rect.h"
#include "common/str.h"

#include "engines/engine.h"

namespace Common {
class ReadStream;
class SeekableReadStream;
}

namespace Adl {

class Display;
struct AdlGameDescription;

// Conditional opcodes
#define IDO_CND_ITEM_IN_ROOM   0x03
#define IDO_CND_MOVES_GE       0x05
#define IDO_CND_VAR_EQ         0x06
#define IDO_CND_CUR_PIC_EQ     0x09
#define IDO_CND_ITEM_PIC_EQ    0x0a

// Action opcodes
#define IDO_ACT_VAR_ADD        0x01
#define IDO_ACT_VAR_SUB        0x02
#define IDO_ACT_VAR_SET        0x03
#define IDO_ACT_LIST_ITEMS     0x04
#define IDO_ACT_MOVE_ITEM      0x05
#define IDO_ACT_SET_ROOM       0x06
#define IDO_ACT_SET_CUR_PIC    0x07
#define IDO_ACT_SET_PIC        0x08
#define IDO_ACT_PRINT_MSG      0x09
#define IDO_ACT_SET_LIGHT      0x0a
#define IDO_ACT_SET_DARK       0x0b
#define IDO_ACT_QUIT           0x0d
#define IDO_ACT_SAVE           0x0f
#define IDO_ACT_LOAD           0x10
#define IDO_ACT_RESTART        0x11
#define IDO_ACT_PLACE_ITEM     0x12
#define IDO_ACT_SET_ITEM_PIC   0x13
#define IDO_ACT_RESET_PIC      0x14
#define IDO_ACT_GO_NORTH       0x15
#define IDO_ACT_GO_SOUTH       0x16
#define IDO_ACT_GO_EAST        0x17
#define IDO_ACT_GO_WEST        0x18
#define IDO_ACT_GO_UP          0x19
#define IDO_ACT_GO_DOWN        0x1a
#define IDO_ACT_TAKE_ITEM      0x1b
#define IDO_ACT_DROP_ITEM      0x1c
#define IDO_ACT_SET_ROOM_PIC   0x1d

#define IDI_WORD_SIZE 8

struct Room {
	byte description;
	byte connections[6];
	byte picture;
	byte curPicture;
};

struct Picture {
	byte block;
	uint16 offset;
};

struct Command {
	byte room;
	byte verb, noun;
	byte numCond, numAct;
	Common::Array<byte> script;
};

enum {
	IDI_ITEM_NOT_MOVED,
	IDI_ITEM_MOVED,
	IDI_ITEM_DOESNT_MOVE
};

#define IDI_NONE 0xfe

struct Item {
	byte noun;
	byte room;
	byte picture;
	bool isLineArt;
	Common::Point position;
	int state;
	byte description;
	Common::Array<byte> roomPictures;
};

struct State {
	Common::Array<Room> rooms;
	Common::Array<Item> items;
	Common::Array<byte> vars;

	byte room;
	uint16 moves;
	bool isDark;

	State() : room(1), moves(0), isDark(false) { }
};

typedef Common::List<Command> Commands;
typedef Common::HashMap<Common::String, uint> WordMap;

class AdlEngine : public Engine {
public:
	virtual ~AdlEngine();

protected:
	AdlEngine(OSystem *syst, const AdlGameDescription *gd);

	Common::String readString(Common::ReadStream &stream, byte until = 0) const;
	Common::String readStringAt(Common::SeekableReadStream &stream, uint offset, byte until = 0) const;

	virtual void printMessage(uint idx, bool wait = true) const;
	void delay(uint32 ms) const;

	Common::String inputString(byte prompt = 0) const;
	byte inputKey() const;

	void loadWords(Common::ReadStream &stream, WordMap &map) const;
	void readCommands(Common::ReadStream &stream, Commands &commands);

	Display *_display;

	// Message strings in data file
	Common::Array<Common::String> _messages;
	// Picture data
	Common::Array<Picture> _pictures;
	// Dropped item screen offsets
	Common::Array<Common::Point> _itemOffsets;
	// Drawings consisting of horizontal and vertical lines only, but
	// supporting scaling and rotation
	Common::Array<Common::Array<byte> > _lineArt;
	// <room, verb, noun, script> lists
	Commands _roomCommands;
	Commands _globalCommands;

	WordMap _verbs;
	WordMap _nouns;

	struct {
		Common::String enterCommand;
		Common::String dontHaveIt;
		Common::String gettingDark;
		Common::String verbError;
		Common::String nounError;
		Common::String playAgain;
	} _strings;

	struct {
		uint cantGoThere;
		uint dontUnderstand;
		uint itemDoesntMove;
		uint itemNotHere;
		uint thanksForPlaying;
	} _messageIds;

	// Game state
	State _state;

private:
	virtual void runIntro() const { }
	virtual void loadData() = 0;
	virtual void initState() = 0;
	virtual void restartGame() = 0;
	virtual void drawPic(byte pic, Common::Point pos = Common::Point()) const = 0;

	// Engine
	Common::Error run();
	bool hasFeature(EngineFeature f) const;
	Common::Error loadGameState(int slot);
	bool canLoadGameStateCurrently();
	Common::Error saveGameState(int slot, const Common::String &desc);
	bool canSaveGameStateCurrently();

	// Text output
	void wordWrap(Common::String &str) const;

	// Text input
	byte convertKey(uint16 ascii) const;
	Common::String getLine() const;
	Common::String getWord(const Common::String &line, uint &index) const;
	void getInput(uint &verb, uint &noun);

	// Graphics
	void showRoom() const;
	void clearScreen() const;
	void drawItems() const;
	void drawNextPixel(Common::Point &p, byte color, byte bits, byte quadrant) const;
	void drawLineArt(const Common::Array<byte> &lineArt, const Common::Point &pos, byte rotation = 0, byte scaling = 1, byte color = 0x7f) const;

	// Game state functions
	const Room &getRoom(uint i) const;
	Room &getRoom(uint i);
	const Room &getCurRoom() const;
	Room &getCurRoom();
	const Item &getItem(uint i) const;
	Item &getItem(uint i);
	byte getVar(uint i) const;
	void setVar(uint i, byte value);
	void takeItem(byte noun);
	void dropItem(byte noun);
	bool matchCommand(const Command &command, byte verb, byte noun, uint *actions = nullptr) const;
	void doActions(const Command &command, byte noun, byte offset);
	bool doOneCommand(const Commands &commands, byte verb, byte noun);
	void doAllCommands(const Commands &commands, byte verb, byte noun);

	const AdlGameDescription *_gameDescription;
	bool _isRestarting, _isRestoring;
	byte _saveVerb, _saveNoun, _restoreVerb, _restoreNoun;
	bool _canSaveNow, _canRestoreNow;
};

AdlEngine *HiRes1Engine__create(OSystem *syst, const AdlGameDescription *gd);

} // End of namespace Adl

#endif