-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathdungeonTypes.h
298 lines (267 loc) · 9.44 KB
/
dungeonTypes.h
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
#pragma once
#include <Arduino.h>
#if !defined(__AVR_ATtiny85__)
#include "SerialHexTools.h"
#endif
const uint8_t LEVEL_WIDTH = 16;
const uint8_t LEVEL_HEIGHT = 16;
const uint16_t MAX_LEVEL_BYTES = LEVEL_WIDTH * LEVEL_HEIGHT;
const uint8_t MAX_VIEW_DISTANCE = 3;
const uint8_t MAX_MONSTERS = 10;
const uint8_t WINDOW_SIZE_X = 96;
const uint8_t WINDOW_CENTER_X = WINDOW_SIZE_X / 2; /* = 48 */
const uint8_t WINDOW_SIZE_Y = 64;
const uint8_t WINDOW_CENTER_Y = WINDOW_SIZE_Y / 2; /* = 32 */
const int8_t POTION_HITPOINT_BONUS = 8;
// possible item types
enum
{
// bit 2 marks an object as a "monster"
FLAG_MONSTER = 0x04,
// bit 3 is reserved for marking objects as "SOLID", making them impassable
FLAG_SOLID = 0x08,
WALL_MASK = 0x10,
OBJECT_MASK = 0xF0 | FLAG_SOLID | FLAG_MONSTER,
EMPTY = 0x00,
// Caution! The following objects are always rendered *on* a wall,
// so the wall bit (0) is always set!
FAKE_WALL = 0x10,
WALL = FAKE_WALL | FLAG_SOLID,
DOOR = 0x30 | FLAG_SOLID,
LVR_LEFT = 0x50 | FLAG_SOLID,
LVR_RIGHT = 0x70 | FLAG_SOLID,
// Caution! The following objects are *never* rendered on a wall,
// so the wall bit (0) must be '0'
RAT = 0x20 | FLAG_MONSTER | FLAG_SOLID,
SKELETON = 0x40 | FLAG_MONSTER | FLAG_SOLID,
BEHOLDER = 0x60 | FLAG_MONSTER | FLAG_SOLID,
CLOSED_CHEST = 0x80, // | FLAG_SOLID,
// a mimic is like a chest, but you may not pass through it
MIMIC = CLOSED_CHEST | FLAG_MONSTER | FLAG_SOLID,
OPEN_CHEST = 0xA0, // | FLAG_SOLID,
FOUNTAIN = 0xC0 | FLAG_SOLID,
BARS = 0xE0 | FLAG_SOLID,
};
// special FX types
enum
{
TELEPORTER = 0x01,
SPINNER = 0x02,
};
// list of items in chests or monster treasure
enum
{
ITEM_NONE = 0x00,
ITEM_COMPASS = 0x01,
ITEM_AMULET = 0x02,
ITEM_RING = 0x04,
ITEM_KEY = 0x08,
ITEM_POTION = 0x10,
ITEM_SWORD = 0x20,
ITEM_SHIELD = 0x40,
ITEM_VICTORY = 0x80,
};
// monster stats
class MONSTER_STATS
{
public:
// monster position (byte offset from level start)
uint8_t position;
// monster type
uint8_t monsterType;
// hit points
int8_t hitpoints;
// damage (additional to 1D8)
int8_t damageBonus;
// monster attacks first?
uint8_t attacksFirst;
// treasure (bit mask)
uint8_t treasureItemMask;
#if !defined(__AVR_ATtiny85__)
void serialPrint()
{
Serial.print( F(" position = (") ); Serial.print( position % LEVEL_WIDTH ); Serial.print(F(", ")); Serial.print( position / LEVEL_WIDTH ); Serial.println(F(")"));
Serial.print( F(" monsterType = ") ); printHexToSerial( monsterType, false );
Serial.print( F(" hitpoints = ") ); Serial.println( hitpoints );
Serial.print( F(" damageBonus = ") ); Serial.println( damageBonus );
Serial.print( F(" attacksFirst = ") ); Serial.println( ( attacksFirst != 0 ) ? "yes" : "no" );
Serial.print( F(" treasureItemMask = ") ); Serial.println( treasureItemMask );
Serial.println();
}
#endif
};
// DUNGEON
class DUNGEON
{
public:
int8_t playerX;
int8_t playerY;
uint8_t dir;
int8_t playerHP;
int8_t playerDamage;
int8_t playerArmour;
uint8_t playerItems;
#if !defined( __AVR_ATtiny85__ )
int8_t dice;
#endif
uint8_t displayXorEffect;
uint8_t invertMonsterEffect;
uint8_t invertStatusEffect;
uint8_t currentLevel[MAX_LEVEL_BYTES];
#ifdef _USE_FIELD_OF_VIEW_
uint8_t fieldOfView[5 * MAX_VIEW_DISTANCE];
#endif
MONSTER_STATS monsterStats[MAX_MONSTERS];
#if !defined(__AVR_ATtiny85__)
void serialPrint()
{
Serial.println( F("DUNGEON") );
Serial.print( F(" playerX = ") );Serial.print( playerX );
Serial.print( F(", playerY = ") );Serial.print( playerY );
Serial.print( F(", dir = ") );Serial.print( dir );
Serial.print( F(", HP = ") );Serial.print( playerHP );
Serial.print( F(", DAM = ") );Serial.print( playerDamage );
Serial.print( F(", Armour = ") );Serial.print( playerArmour );
Serial.print( F(", Items = ") );printHexToSerial( playerItems, false );Serial.print( F(", "));
Serial.print( F(", Keys = ") );Serial.print( ( playerItems & ITEM_KEY ) != 0 );
Serial.print( F(", Compass = ") );Serial.print( ( playerItems & ITEM_COMPASS ) != 0 );
Serial.print( F(", displayXorEffect = ") );Serial.print( displayXorEffect );
Serial.println();
for ( uint8_t y = 0; y < LEVEL_HEIGHT; y++ )
{
for( uint8_t x = 0; x < LEVEL_WIDTH; x++ )
{
uint8_t cellValue = currentLevel[y * LEVEL_WIDTH + x];
char text[3] = "..";
if ( ( cellValue & OBJECT_MASK ) == LVR_LEFT ) { memcpy_P( text, F("W>"), 2 ); }
else if ( ( cellValue & OBJECT_MASK ) == LVR_RIGHT ) { memcpy_P( text, F("W<"), 2 ); }
else if ( ( cellValue & WALL_MASK ) == FAKE_WALL ) { memcpy_P( text, F("W "), 2 ); }
else if ( cellValue == SKELETON ) { memcpy_P( text, F("sk"), 2 ); }
else if ( cellValue == BEHOLDER ) { memcpy_P( text, F("bh"), 2 ); }
else if ( cellValue == RAT ) { memcpy_P( text, F("rt"), 2 ); }
else if ( cellValue == MIMIC ) { memcpy_P( text, F("mi"), 2 ); }
else if ( ( cellValue & OBJECT_MASK ) == DOOR ) { memcpy_P( text, F("D "), 2 ); }
else if ( ( cellValue & OBJECT_MASK ) == BARS ) { memcpy_P( text, F("# "), 2 ); }
else if ( ( cellValue & OBJECT_MASK ) == FOUNTAIN ) { memcpy_P( text, F("F "), 2 ); }
Serial.print( text );
Serial.print( F(" ") );
}
Serial.println();
}
Serial.println();
}
#endif
};
// NON_WALL_OBJECT
class NON_WALL_OBJECT
{
public:
uint8_t itemType;
uint8_t bitmapWidth;
uint8_t bitmapVerticalOffsetInBits;
uint8_t bitmapHeightInBits;
uint8_t nextLineOffset;
uint8_t scalingThreshold[3];
const uint8_t *bitmapData;
#if !defined(__AVR_ATtiny85__)
void serialPrint()
{
Serial.println( F("NON_WALL_OBJECT") );
Serial.print( F(" itemType = ") );Serial.println( itemType );
Serial.print( F(" bitmapWidth = ") );Serial.print( bitmapWidth );Serial.println();
Serial.print( F(" bitmapVerticalOffsetInBytes = ") );Serial.print( bitmapVerticalOffsetInBits );Serial.println();
Serial.print( F(" bitmapHeightInBytes = ") );Serial.print( bitmapHeightInBits );Serial.println();
Serial.print( F(" nextLineOffset = ") );Serial.println( nextLineOffset );
Serial.print( F(" scalingThreshold[0] = ") );Serial.print( scalingThreshold[1] );Serial.println();
Serial.print( F(" scalingThreshold[1] = ") );Serial.print( scalingThreshold[2] );Serial.println();
Serial.print( F(" scalingThreshold[2] = ") );Serial.print( scalingThreshold[3] );Serial.println();
Serial.println();
}
#endif
};
// information for single wall display
// SIMPLE_WALL_INFO
class SIMPLE_WALL_INFO
{
public:
// wall bitmap to use
const uint8_t *wallBitmap;
// screen start position for this bitmap
int8_t startPosX;
// screen end position for this bitmap
int8_t endPosX;
// start and end position for Y
int8_t posStartEndY;
// view distance of this object
int8_t viewDistance;
// offset to left or right
int8_t leftRightOffset;
// relative offset from left screen edge
int8_t relPos;
// width off the bitmap/offset to the next line
int8_t width;
};
// interaction information
class INTERACTION_INFO
{
public:
// position in which the dungeon is interacted with
uint8_t currentPosition;
// required status of this position
uint8_t currentStatus;
// new status if true
uint8_t nextStatus;
// bit coded item number for gained items, i.e. keys
uint8_t newItem;
// position in which the dungeon will be modified
uint8_t modifiedPosition;
// new status on modified position
uint8_t modifiedPositionCellValue;
#if !defined(__AVR_ATtiny85__)
void serialPrint()
{
Serial.println( F("INTERACTION_INFO") );
Serial.print( F(" currentPosition = ") );Serial.println( currentPosition );
Serial.print( F(" currentStatus = ") );printHexToSerial( currentStatus );Serial.println();
Serial.print( F(" nextStatus = ") );printHexToSerial( nextStatus );Serial.println();
Serial.print( F(" newItem = ") );printHexToSerial( newItem );Serial.println();
Serial.print( F(" modifiedPosition = ") );Serial.println( modifiedPosition );
Serial.print( F(" modifiedPosValue = ") );printHexToSerial( modifiedPositionCellValue );Serial.println();
Serial.println();
}
#endif
};
// interaction information
class SPECIAL_CELL_INFO
{
public:
// cell type
uint8_t specialFX;
// combined xy-position of the effect (as byte offset from level start)
uint8_t position;
// additional parameter 1 (target position x, ...)
uint8_t value_1;
// additional parameter 2 (target position y, ...)
uint8_t value_2;
#if !defined(__AVR_ATtiny85__)
void serialPrint()
{
Serial.print( F(" specialFX = ") );if ( specialFX == TELEPORTER ) { Serial.println( F("TELEPORTER") ); } else { Serial.println( F("SPINNER") ); }
Serial.print( F(" value = (") );Serial.print( value_1 ); Serial.print( F(", ") );Serial.print( value_2 );Serial.println( F(")"));
Serial.println();
}
#endif
};
// orientations
enum
{
NORTH = 0,
UP = NORTH,
EAST = 1,
RIGHT = EAST,
SOUTH = 2,
DOWN = SOUTH,
WEST = 3,
LEFT = WEST,
MAX_ORIENTATION = 4,
};