1 /*
2     level.h
3 
4     Copyright (C) 2010-2019 Amf
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20 
21 #define MOVE_LEFT           0
22 #define MOVE_UP             1
23 #define MOVE_RIGHT          2
24 #define MOVE_DOWN           3
25 #define MOVE_NONE           4
26 #define MOVE_SWAP           5
27 #define MOVE_SWAPPED        6
28 #define MOVE_UNKNOWN        7
29 #define MOVE_REDO           8
30 
31 #define MOVER_FAST          1
32 #define MOVER_UNDO          2
33 #define MOVER_STORE         4
34 
35 #define LEVELFLAG_MOVES     1
36 #define LEVELFLAG_STARS     2
37 #define LEVELFLAG_SWITCH    4
38 #define LEVELFLAG_EXIT      8
39 #define LEVELFLAG_SOLVED    16
40 #define LEVELFLAG_FAILED    32
41 #define LEVELFLAG_PAUSED    64
42 #define LEVELFLAG_UNDO      128
43 #define LEVELFLAG_TESTING   256
44 #define LEVELFLAG_MAP       512
45 #define LEVELFLAG_NOUNDO    1024
46 
47 #ifdef XOR_COMPATIBILITY
48 #define MAPPED_TOP_LEFT     1
49 #define MAPPED_TOP_RIGHT    2
50 #define MAPPED_BOTTOM_LEFT  4
51 #define MAPPED_BOTTOM_RIGHT 8
52 #endif
53 
54 enum {
55     PIECE_SPACE = 0,
56     PIECE_WALL = 1,
57     PIECE_PLAYER_ONE = 2,
58     PIECE_PLAYER_TWO = 3,
59     PIECE_STAR = 4,
60     PIECE_DOTS = 5,
61     PIECE_DOOR = 6,
62     PIECE_CIRCLE = 7,
63     PIECE_ARROW_RED_LEFT = 8,           /* PIECE_ARROW_RED_LEFT % 4 must = 0 */
64     PIECE_ARROW_RED_UP = 9,
65     PIECE_ARROW_RED_RIGHT = 10,
66     PIECE_ARROW_RED_DOWN = 11,
67     PIECE_BOMB_RED_LEFT = 12,
68     PIECE_BOMB_RED_UP = 13,
69     PIECE_BOMB_RED_RIGHT = 14,
70     PIECE_BOMB_RED_DOWN = 15,
71     PIECE_ARROW_GREEN_LEFT = 16,
72     PIECE_ARROW_GREEN_UP = 17,
73     PIECE_ARROW_GREEN_RIGHT = 18,
74     PIECE_ARROW_GREEN_DOWN = 19,
75     PIECE_BOMB_GREEN_LEFT = 20,
76     PIECE_BOMB_GREEN_UP = 21,
77     PIECE_BOMB_GREEN_RIGHT = 22,
78     PIECE_BOMB_GREEN_DOWN = 23,
79     PIECE_ARROW_BLUE_LEFT = 24,
80     PIECE_ARROW_BLUE_UP = 25,
81     PIECE_ARROW_BLUE_RIGHT = 26,
82     PIECE_ARROW_BLUE_DOWN = 27,
83     PIECE_BOMB_BLUE_LEFT = 28,
84     PIECE_BOMB_BLUE_UP = 29,
85     PIECE_BOMB_BLUE_RIGHT = 30,
86     PIECE_BOMB_BLUE_DOWN = 31,
87 
88 #ifdef ENIGMA_COMPATIBILITY
89     PIECE_CIRCLE_DOUBLE,
90     PIECE_DOTS_DOUBLE,
91 #endif
92 
93 #ifdef XOR_COMPATIBILITY
94     PIECE_DOTS_X,
95     PIECE_DOTS_Y,
96     PIECE_SWITCH,
97     PIECE_TELEPORT,
98     PIECE_MAP_TOP_LEFT,
99     PIECE_MAP_TOP_RIGHT,
100     PIECE_MAP_BOTTOM_LEFT,
101     PIECE_MAP_BOTTOM_RIGHT,
102     PIECE_DARKNESS,
103 #endif
104 
105     PIECE_EXPLOSION_RED_LEFT,
106     PIECE_EXPLOSION_RED_HORIZONTAL,
107     PIECE_EXPLOSION_RED_RIGHT,
108     PIECE_EXPLOSION_RED_TOP,
109     PIECE_EXPLOSION_RED_VERTICAL,
110     PIECE_EXPLOSION_RED_BOTTOM,
111     PIECE_EXPLOSION_GREEN_LEFT,
112     PIECE_EXPLOSION_GREEN_HORIZONTAL,
113     PIECE_EXPLOSION_GREEN_RIGHT,
114     PIECE_EXPLOSION_GREEN_TOP,
115     PIECE_EXPLOSION_GREEN_VERTICAL,
116     PIECE_EXPLOSION_GREEN_BOTTOM,
117     PIECE_EXPLOSION_BLUE_LEFT,
118     PIECE_EXPLOSION_BLUE_HORIZONTAL,
119     PIECE_EXPLOSION_BLUE_RIGHT,
120     PIECE_EXPLOSION_BLUE_TOP,
121     PIECE_EXPLOSION_BLUE_VERTICAL,
122     PIECE_EXPLOSION_BLUE_BOTTOM,
123 
124     PIECE_EXPLOSION_NEW_RED_LEFT,
125     PIECE_EXPLOSION_NEW_RED_HORIZONTAL,
126     PIECE_EXPLOSION_NEW_RED_RIGHT,
127     PIECE_EXPLOSION_NEW_RED_TOP,
128     PIECE_EXPLOSION_NEW_RED_VERTICAL,
129     PIECE_EXPLOSION_NEW_RED_BOTTOM,
130     PIECE_EXPLOSION_NEW_GREEN_LEFT,
131     PIECE_EXPLOSION_NEW_GREEN_HORIZONTAL,
132     PIECE_EXPLOSION_NEW_GREEN_RIGHT,
133     PIECE_EXPLOSION_NEW_GREEN_TOP,
134     PIECE_EXPLOSION_NEW_GREEN_VERTICAL,
135     PIECE_EXPLOSION_NEW_GREEN_BOTTOM,
136     PIECE_EXPLOSION_NEW_BLUE_LEFT,
137     PIECE_EXPLOSION_NEW_BLUE_HORIZONTAL,
138     PIECE_EXPLOSION_NEW_BLUE_RIGHT,
139     PIECE_EXPLOSION_NEW_BLUE_TOP,
140     PIECE_EXPLOSION_NEW_BLUE_VERTICAL,
141     PIECE_EXPLOSION_NEW_BLUE_BOTTOM,
142 
143     PIECE_CURSOR,
144     PIECE_GONE,
145     PIECE_UNKNOWN
146 };
147 
148 #define PIECE_EXPLOSION_FIRST   PIECE_EXPLOSION_RED_LEFT
149 #define PIECE_EXPLOSION_LAST    PIECE_EXPLOSION_BLUE_BOTTOM
150 #define PIECE_EXPLOSION_NEW_FIRST   PIECE_EXPLOSION_NEW_RED_LEFT
151 #define PIECE_EXPLOSION_NEW_LAST    PIECE_EXPLOSION_NEW_BLUE_BOTTOM
152 #define PIECE_EXPLOSION_NEW_OFFSET  (PIECE_EXPLOSION_NEW_FIRST - PIECE_EXPLOSION_FIRST)
153 #define PIECE_MOVERS_FIRST  PIECE_ARROW_RED_LEFT
154 #define PIECE_MOVERS_LAST   PIECE_BOMB_BLUE_DOWN
155 #define PIECE_MAX       PIECE_GONE
156 
157 #define isexplosion(x) (x >= PIECE_EXPLOSION_FIRST && x<= PIECE_EXPLOSION_LAST)
158 #define isnewexplosion(x) (x >= PIECE_EXPLOSION_NEW_FIRST && x <= PIECE_EXPLOSION_NEW_LAST)
159 
160 enum {
161     MODE_CHROMA,
162 #ifdef XOR_COMPATIBILITY
163     MODE_XOR,
164 #endif
165 #ifdef ENIGMA_COMPATIBILITY
166     MODE_ENIGMA,
167 #endif
168     MODE_MAX
169 };
170 
171 struct mover
172 {
173     int x;
174     int y;
175     int direction;
176     int piece;
177     int piece_previous;
178     int fast;
179     struct mover* next;
180     struct mover* previous;
181 };
182 
183 struct move
184 {
185     int count;
186     int direction;
187     struct move* previous;
188     struct move* next;
189     struct mover* mover_first;
190     struct mover* mover_last;
191 };
192 
193 struct level
194 {
195     int size_x;
196     int size_y;
197 
198     char *data_pieces;
199     char *data_moving;
200     char *data_previous;
201     char *data_previousmoving;
202     char *data_detonator;
203     char *data_detonatormoving;
204     unsigned int *data_data;
205 
206     struct move* move_first;
207     struct move* move_last;
208     struct move* move_current;
209 
210     struct mover* mover_first;
211     struct mover* mover_last;
212 
213     struct mover* stack_first;
214     struct mover* stack_last;
215 
216     int player;
217     int player_x[3];
218     int player_y[3];
219     int view_x[3];
220     int view_y[3];
221     int alive[2];
222 
223     int moves;
224 
225     int stars_caught;
226     int stars_exploded;
227     int stars_total;
228 
229     char *title;
230 
231     int flags;
232 
233 #ifdef XOR_COMPATIBILITY
234     int switched;
235     int mapped;
236 #endif
237 
238     int mode;
239     int level;
240 
241     int teleport_x[2];
242     int teleport_y[2];
243     int view_teleport_x[2];
244     int view_teleport_y[2];
245 };
246 
247 /* level.c */
248 char piecetochar(int piece);
249 int chartopiece(char c);
250 char directiontochar(int direction);
251 int chartodirection(char c);
252 
253 struct level* level_new();
254 struct level* level_load(char *filename, int partial);
255 int level_save(struct level* plevel, char *filename, int partial);
256 struct level* level_copy(struct level*);
257 void level_addmove(struct level*, int);
258 void level_fix(struct level*);
259 struct level* level_create(int, int);
260 void level_delete(struct level* plevel);
261 
262 char level_piece(struct level*, int, int);
263 void level_setpiece(struct level*, int, int, char);
264 char level_moving(struct level*, int, int);
265 void level_setmoving(struct level*, int, int, char);
266 char level_previous(struct level*, int, int);
267 void level_setprevious(struct level*, int, int, char);
268 char level_detonator(struct level*, int, int);
269 void level_setdetonator(struct level*, int, int, char);
270 char level_detonatormoving(struct level*, int, int);
271 void level_setdetonatormoving(struct level*, int, int, char);
272 char level_previousmoving(struct level*, int, int);
273 void level_setpreviousmoving(struct level*, int, int, char);
274 unsigned int level_data(struct level*, int, int);
275 void level_setdata(struct level*, int, int, unsigned int);
276 void level_settitle(struct level* plevel, char *title);
277 
278 /* engine.c */
279 int level_move(struct level*, int);
280 int level_evolve(struct level*);
281 int canfall(int p, int into, int d);
282 struct mover* mover_new(struct level* plevel, int x, int y, int d, int piece, int fast);
283 struct mover* mover_addtostack(struct level* plevel, int x, int y, int move);
284 void level_storemovers(struct level*);
285 int level_undo(struct level*);
286 struct mover* mover_newundo(struct level* plevel, int x, int y, int d, int piece, int previous, int flags);
287