1 #include "game_player.h"
2 #include "doctest.h"
3 #include "options.h"
4 #include "game_map.h"
5 #include "game_vehicle.h"
6 #include "main_data.h"
7 #include "game_switches.h"
8 #include <climits>
9 #include <initializer_list>
10
11 #include "test_move_route.h"
12
13 TEST_SUITE_BEGIN("MoveRoute");
14
MakeRoute(std::initializer_list<lcf::rpg::MoveCommand> cmds,bool repeat=false,bool skip=false)15 lcf::rpg::MoveRoute MakeRoute(std::initializer_list<lcf::rpg::MoveCommand> cmds, bool repeat = false, bool skip = false) {
16 lcf::rpg::MoveRoute mr;
17 mr.move_commands = cmds;
18 mr.repeat = repeat;
19 mr.skippable = skip;
20 return mr;
21 }
22
testMoveRoute(const Game_Character & ch,bool paused,int move_frequency,int stop_count,int max_stop_count,int move_route_idx,bool overwritten,bool done,const lcf::rpg::MoveRoute & mr)23 static void testMoveRoute(
24 const Game_Character& ch,
25 bool paused, int move_frequency,
26 int stop_count, int max_stop_count,
27 int move_route_idx, bool overwritten, bool done,
28 const lcf::rpg::MoveRoute& mr)
29 {
30 CAPTURE(paused);
31 CAPTURE(move_frequency);
32 CAPTURE(stop_count);
33 CAPTURE(max_stop_count);
34 CAPTURE(move_route_idx);
35 CAPTURE(overwritten);
36 CAPTURE(done);
37 CAPTURE(mr);
38
39 REQUIRE_EQ(ch.IsPaused(), paused);
40 REQUIRE_EQ(ch.GetMoveFrequency(), move_frequency);
41 REQUIRE_EQ(ch.GetStopCount(), stop_count);
42 REQUIRE_EQ(ch.GetMaxStopCount(), max_stop_count);
43 REQUIRE_EQ(ch.GetMoveRouteIndex(), move_route_idx);
44 REQUIRE_EQ(ch.IsMoveRouteOverwritten(), overwritten);
45 REQUIRE_EQ(ch.IsMoveRouteRepeated(), done);
46 REQUIRE_EQ(ch.GetMoveRoute(), mr);
47 REQUIRE_EQ(ch.IsStopCountActive(), stop_count < max_stop_count);
48 }
49
50 template <typename... Args>
testMoveRouteDir(const Game_Character & ch,int dir,int face,Args &&...args)51 static void testMoveRouteDir(const Game_Character& ch,
52 int dir, int face,
53 Args&&... args) {
54
55 CAPTURE(dir);
56 CAPTURE(face);
57
58 REQUIRE_EQ(ch.GetDirection(), dir);
59 REQUIRE_EQ(ch.GetFacing(), face);
60 testMoveRoute(ch, std::forward<Args>(args)...);
61 }
62
63 template <typename... Args>
testMoveRouteMove(const Game_Character & ch,int x,int y,int remaining_step,Args &&...args)64 static void testMoveRouteMove(const Game_Character& ch,
65 int x, int y, int remaining_step,
66 Args&&... args) {
67
68 CAPTURE(x);
69 CAPTURE(y);
70 CAPTURE(remaining_step);
71
72 REQUIRE_EQ(ch.GetX(), x);
73 REQUIRE_EQ(ch.GetY(), y);
74 REQUIRE_GE(ch.GetRemainingStep(), 0);
75 REQUIRE_EQ(ch.GetRemainingStep(), remaining_step);
76 REQUIRE(!ch.IsJumping());
77 if (remaining_step > 0) {
78 REQUIRE(ch.IsMoving());
79 } else {
80 REQUIRE(ch.IsStopping());
81 REQUIRE(!ch.IsMoving());
82 }
83 testMoveRouteDir(ch, std::forward<Args>(args)...);
84 }
85
86 template <typename... Args>
testMoveRouteJump(const Game_Character & ch,int x,int y,int remaining_step,bool is_jumping,int begin_jump_x,int begin_jump_y,Args &&...args)87 static void testMoveRouteJump(const Game_Character& ch,
88 int x, int y, int remaining_step,
89 bool is_jumping, int begin_jump_x, int begin_jump_y,
90 Args&&... args) {
91
92 CAPTURE(x);
93 CAPTURE(y);
94 CAPTURE(remaining_step);
95 CAPTURE(is_jumping);
96 CAPTURE(begin_jump_x);
97 CAPTURE(begin_jump_y);
98
99 REQUIRE_EQ(ch.GetX(), x);
100 REQUIRE_EQ(ch.GetY(), y);
101 REQUIRE_GE(ch.GetRemainingStep(), 0);
102 REQUIRE_EQ(ch.GetRemainingStep(), remaining_step);
103
104 REQUIRE_EQ(ch.GetBeginJumpX(), begin_jump_x);
105 REQUIRE_EQ(ch.GetBeginJumpY(), begin_jump_y);
106
107 if (remaining_step > 0) {
108 REQUIRE_EQ(ch.IsJumping(), is_jumping);
109 REQUIRE_EQ(ch.IsMoving(), !is_jumping);
110 } else {
111 REQUIRE(ch.IsStopping());
112 REQUIRE(!ch.IsJumping());
113 REQUIRE(!ch.IsMoving());
114 }
115 testMoveRouteDir(ch, std::forward<Args>(args)...);
116 }
117
118 TEST_CASE("DefaultMoveRoute") {
119 auto ch = MoveRouteVehicle();
120 testMoveRoute(ch, false, 2, 0, 0, 0, false, false, lcf::rpg::MoveRoute());
121 }
122
123 TEST_CASE("ForceMoveRouteEmpty") {
124 auto ch = MoveRouteVehicle();
125 ch.ForceMoveRoute(lcf::rpg::MoveRoute(), 2);
126 testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, false, false, lcf::rpg::MoveRoute());
127 }
128
129 TEST_CASE("ForceMoveRouteSameFreq") {
130 auto ch = MoveRouteVehicle();
131 lcf::rpg::MoveRoute mr;
132 mr.move_commands.push_back({});
133
134 ch.ForceMoveRoute(mr, 2);
135 // Note: Same freq means don't reset max stop count
136 testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr);
137
138 ch.CancelMoveRoute();
139 testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, false, false, mr);
140 }
141
142 TEST_CASE("ForceMoveRouteDiffFreq") {
143 auto ch = MoveRouteVehicle();
144 auto mr = MakeRoute({{}});
145 mr.move_commands.push_back({});
146
147 ch.ForceMoveRoute(mr, 3);
148 testMoveRoute(ch, false, 3, 0xFFFF, 64, 0, true, false, mr);
149
150 // FIXME: Test original move frequency is robust to save games
151 ch.CancelMoveRoute();
152 testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, false, false, mr);
153 }
154
testInvalidCmd(bool repeat,bool skip)155 static void testInvalidCmd(bool repeat, bool skip) {
156 auto ch = MoveRouteVehicle();
157 auto mr = MakeRoute({{ -1 }}, repeat, skip);
158
159 ch.ForceMoveRoute(mr, 3);
160 testMoveRoute(ch, false, 3, 0xFFFF, 64, 0, true, false, mr);
161
162 ForceUpdate(ch);
163 if (repeat) {
164 testMoveRoute(ch, false, 3, 0xFFFF + 1, 64, 0, true, true, mr);
165 } else {
166 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
167 }
168 }
169
170 TEST_CASE("TestMoveRouteInvalidCmd") {
171 const MapGuard mg;
172
173 testInvalidCmd(false, false);
174 testInvalidCmd(false, true);
175 testInvalidCmd(true, false);
176 testInvalidCmd(true, true);
177 }
178
179 template <bool success, bool repeat, bool skip>
testMove(lcf::rpg::MoveCommand::Code code,int x,int y,int dir,int face,int tx,int ty,int tdir,int tface,int px=0,int py=0)180 static void testMove(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int tx, int ty, int tdir, int tface, int px = 0, int py = 0) {
181 Main_Data::game_player->SetX(px);
182 Main_Data::game_player->SetY(py);
183
184 auto ch = MoveRouteVehicle();
185 ch.SetX(x);
186 ch.SetY(y);
187 ch.SetDirection(dir);
188 ch.SetFacing(face);
189 ch.SetAllowMovement(success);
190
191 auto mr = MakeRoute({{ static_cast<int>(code) }}, repeat, skip);
192
193 CAPTURE(code);
194 CAPTURE(x);
195 CAPTURE(y);
196 CAPTURE(dir);
197 CAPTURE(face);
198 CAPTURE(tx);
199 CAPTURE(ty);
200 CAPTURE(tdir);
201 CAPTURE(tface);
202 CAPTURE(px);
203 CAPTURE(py);
204 CAPTURE(success);
205 CAPTURE(repeat);
206 CAPTURE(skip);
207
208 auto dx = tx - x;
209 auto dy = ty - y;
210
211 ch.ForceMoveRoute(mr, 3);
212 testMoveRouteMove(ch, x, y, 0, dir, face, false, 3, 0xFFFF, 64, 0, true, false, mr);
213
214 if (success) {
215 bool repeated = false;
216 for(int n = (repeat ? 3 : 1); n > 0; --n) {
217 CAPTURE(n);
218 for(int i = 224; i > 0; i -= 32) {
219 ForceUpdate(ch);
220 testMoveRouteMove(ch, tx, ty, i, tdir, tface, false, 3, 0, 64, 1, true, repeated, mr);
221 }
222
223 if (!repeat) {
224 ForceUpdate(ch);
225 testMoveRouteMove(ch, tx, ty, 0, tdir, tface, false, 2, 0, 128, 0, false, false, mr);
226 break;
227 }
228
229 repeated = true;
230 for (int i = 0; i <= 64; ++i) {
231 ForceUpdate(ch);
232 testMoveRouteMove(ch, tx, ty, 0, tdir, tface, false, 3, i, 64, 0, true, repeated, mr);
233 }
234
235 tx += dx;
236 ty += dy;
237 }
238 } else {
239 ForceUpdate(ch);
240 if (skip) {
241 if (repeat) {
242 for (int i = 1; i <= 3; ++i) {
243 testMoveRouteMove(ch, tx, ty, 0, tdir, tface, false, 3, 0xFFFF + i, 64, 0, true, true, mr);
244 ForceUpdate(ch);
245 }
246 } else {
247 testMoveRouteMove(ch, tx, ty, 0, tdir, tface, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
248 }
249 } else {
250 testMoveRouteMove(ch, tx, ty, 0, tdir, tface, false, 3, 0xFFFF + 1, 64, 0, true, false, mr);
251 }
252 }
253 }
254
255 template <typename... Args>
testMoveSuccess(const Args &...args)256 static void testMoveSuccess(const Args&... args) {
257 testMove<true, false, false>(args...);
258 testMove<true, false, true>(args...);
259 testMove<true, true, false>(args...);
260 testMove<true, true, true>(args...);
261 }
262
263 template <typename... Args>
testMoveSuccessNoRepeat(const Args &...args)264 static void testMoveSuccessNoRepeat(const Args&... args) {
265 testMove<true, false, false>(args...);
266 testMove<true, false, true>(args...);
267 }
268
testMoveFail(lcf::rpg::MoveCommand::Code code,int x,int y,int dir,int face,int tdir,int tface,int px=0,int py=0)269 static void testMoveFail(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int tdir, int tface, int px = 0, int py = 0) {
270 testMove<false, false, false>(code, x, y, dir, face, x, y, tdir, tface, px, py);
271 testMove<false, true, false>(code, x, y, dir, face, x, y, tdir, tface, px, py);
272 }
273
testMoveSkip(lcf::rpg::MoveCommand::Code code,int x,int y,int dir,int face,int px=0,int py=0)274 static void testMoveSkip(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int px = 0, int py = 0) {
275 testMove<false, false, true>(code, x, y, dir, face, x, y, dir, face, px, py);
276 testMove<false, true, true>(code, x, y, dir, face, x, y, dir, face, px, py);
277 }
278
279
280 TEST_CASE("CommandMove") {
281 const MapGuard mg;
282
283 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_up, 8, 8, Down, Down, 8, 7, Up, Up);
284 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_right, 8, 8, Down, Down, 9, 8, Right, Right);
285 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_down, 8, 8, Down, Down, 8, 9, Down, Down);
286 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_left, 8, 8, Down, Down, 7, 8, Left, Left);
287 }
288
289 TEST_CASE("CommandMoveFail") {
290 const MapGuard mg;
291
292 testMoveFail(lcf::rpg::MoveCommand::Code::move_up, 8, 8, Down, Down, Up, Up);
293 testMoveFail(lcf::rpg::MoveCommand::Code::move_right, 8, 8, Down, Down, Right, Right);
294 testMoveFail(lcf::rpg::MoveCommand::Code::move_down, 8, 8, Down, Down, Down, Down);
295 testMoveFail(lcf::rpg::MoveCommand::Code::move_left, 8, 8, Down, Down, Left, Left);
296 }
297
298 TEST_CASE("CommandMoveSkip") {
299 const MapGuard mg;
300
301 testMoveSkip(lcf::rpg::MoveCommand::Code::move_up, 8, 8, Down, Down);
302 testMoveSkip(lcf::rpg::MoveCommand::Code::move_right, 8, 8, Down, Down);
303 testMoveSkip(lcf::rpg::MoveCommand::Code::move_down, 8, 8, Down, Down);
304 testMoveSkip(lcf::rpg::MoveCommand::Code::move_left, 8, 8, Down, Down);
305 }
306
307 TEST_CASE("CommandMoveDiagonal") {
308 const MapGuard mg;
309
310 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Up, Up, 9, 7, UpRight, Up);
311 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Right, Right, 9, 7, UpRight, Right);
312 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Down, Down, 9, 7, UpRight, Up);
313 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Left, Left, 9, 7, UpRight, Right);
314
315 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Up, Up, 9, 9, DownRight, Down);
316 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Right, Right, 9, 9, DownRight, Right);
317 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Down, Down, 9, 9, DownRight, Down);
318 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Left, Left, 9, 9, DownRight, Right);
319
320 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Up, Up, 7, 9, DownLeft, Down);
321 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Right, Right, 7, 9, DownLeft, Left);
322 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Down, Down, 7, 9, DownLeft, Down);
323 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Left, Left, 7, 9, DownLeft, Left);
324
325 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Up, Up, 7, 7, UpLeft, Up);
326 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Right, Right, 7, 7, UpLeft, Left);
327 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Down, Down, 7, 7, UpLeft, Up);
328 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Left, Left, 7, 7, UpLeft, Left);
329 }
330
331 TEST_CASE("CommandMoveDiagonalFail") {
332 const MapGuard mg;
333
334 testMoveFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Up, Up, UpRight, Up);
335 testMoveFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Right, Right, UpRight, Right);
336 testMoveFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Down, Down, UpRight, Up);
337 testMoveFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Left, Left, UpRight, Right);
338
339 testMoveFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Up, Up, DownRight, Down);
340 testMoveFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Right, Right, DownRight, Right);
341 testMoveFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Down, Down, DownRight, Down);
342 testMoveFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Left, Left, DownRight, Right);
343
344 testMoveFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Up, Up, DownLeft, Down);
345 testMoveFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Right, Right, DownLeft, Left);
346 testMoveFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Down, Down, DownLeft, Down);
347 testMoveFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Left, Left, DownLeft, Left);
348
349 testMoveFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Up, Up, UpLeft, Up);
350 testMoveFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Right, Right, UpLeft, Left);
351 testMoveFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Down, Down, UpLeft, Up);
352 testMoveFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Left, Left, UpLeft, Left);
353 }
354
355 TEST_CASE("CommandMoveDiagonalSkip") {
356 const MapGuard mg;
357
358 testMoveSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Up, Up);
359 testMoveSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Right, Right);
360 testMoveSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Down, Down);
361 testMoveSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Left, Left);
362
363 testMoveSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Up, Up);
364 testMoveSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Right, Right);
365 testMoveSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Down, Down);
366 testMoveSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Left, Left);
367
368 testMoveSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Up, Up);
369 testMoveSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Right, Right);
370 testMoveSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Down, Down);
371 testMoveSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Left, Left);
372
373 testMoveSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Up, Up);
374 testMoveSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Right, Right);
375 testMoveSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Down, Down);
376 testMoveSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Left, Left);
377 }
378
379 TEST_CASE("CommandMoveForward") {
380 const MapGuard mg;
381
382 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Up, Up, 8, 7, Up, Up);
383 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Right, Right, 9, 8, Right, Right);
384 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Down, Down, 8, 9, Down, Down);
385 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Left, Left, 7, 8, Left, Left);
386
387 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Up, 9, 7, UpRight, Up);
388 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Right, 9, 7, UpRight, Right);
389 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Down, 9, 9, DownRight, Down);
390 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Right, 9, 9, DownRight, Right);
391 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Up, 7, 7, UpLeft, Up);
392 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Left, 7, 7, UpLeft, Left);
393 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Down, 7, 9, DownLeft, Down);
394 testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Left, 7, 9, DownLeft, Left);
395 }
396
397 TEST_CASE("CommandMoveForwardFail") {
398 const MapGuard mg;
399
400 testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Up, Up, Up, Up);
401 testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Right, Right, Right, Right);
402 testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Down, Down, Down, Down);
403 testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Left, Left, Left, Left);
404
405 testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Up, UpRight, Up);
406 testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Right, UpRight, Right);
407 testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Down, DownRight, Down);
408 testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Right, DownRight, Right);
409 testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Up, UpLeft, Up);
410 testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Left, UpLeft, Left);
411 testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Down, DownLeft, Down);
412 testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Left, DownLeft, Left);
413 }
414
415 TEST_CASE("CommandMoveForwardSkip") {
416 const MapGuard mg;
417
418 testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Up, Up);
419 testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Right, Right);
420 testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Down, Down);
421 testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Left, Left);
422
423 testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Up);
424 testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Right);
425 testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Down);
426 testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Right);
427 testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Up);
428 testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Left);
429 testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Down);
430 testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Left);
431 }
432
433 TEST_CASE("CommandMoveRandom") {
434 // FIXME: TBD
435 }
436
437
testTurn(lcf::rpg::MoveCommand::Code code,int orig_dir,int dir,int face,int x=0,int y=0,int px=0,int py=0)438 static void testTurn(lcf::rpg::MoveCommand::Code code, int orig_dir, int dir, int face, int x = 0, int y = 0, int px = 0, int py = 0) {
439 Main_Data::game_player->SetX(px);
440 Main_Data::game_player->SetY(py);
441
442 auto ch = MoveRouteVehicle();
443 ch.SetX(x);
444 ch.SetY(y);
445 ch.SetDirection(orig_dir);
446 ch.SetFacing(orig_dir);
447 auto mr = MakeRoute({{ static_cast<int>(code) }});
448
449 CAPTURE(code);
450 CAPTURE(orig_dir);
451 CAPTURE(dir);
452 CAPTURE(face);
453 CAPTURE(x);
454 CAPTURE(y);
455 CAPTURE(px);
456 CAPTURE(py);
457
458 ch.ForceMoveRoute(mr, 2);
459 testMoveRouteDir(ch, orig_dir, orig_dir, false, 2, 0xFFFF, 0, 0, true, false, mr);
460
461 for(int i = 1; i <= 64; ++i) {
462 ForceUpdate(ch);
463 testMoveRouteDir(ch, dir, face, false, 2, i, 64, 1, true, false, mr);
464 }
465
466 ForceUpdate(ch);
467 testMoveRouteDir(ch, dir, face, false, 2, 65, 128, 1, false, false, mr);
468 }
469
470 TEST_CASE("CommandTurn") {
471 const MapGuard mg;
472
473 testTurn(lcf::rpg::MoveCommand::Code::face_up, Down, Up, Up);
474 testTurn(lcf::rpg::MoveCommand::Code::face_left, Down, Left, Left);
475 testTurn(lcf::rpg::MoveCommand::Code::face_right, Down, Right, Right);
476 testTurn(lcf::rpg::MoveCommand::Code::face_down, Down, Down, Down);
477
478 testTurn(lcf::rpg::MoveCommand::Code::turn_180_degree, Down, Up, Up);
479 testTurn(lcf::rpg::MoveCommand::Code::turn_180_degree, Up, Down, Down);
480 testTurn(lcf::rpg::MoveCommand::Code::turn_180_degree, Left, Right, Right);
481 testTurn(lcf::rpg::MoveCommand::Code::turn_180_degree, Right, Left, Left);
482
483 testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_right, Down, Left, Left);
484 testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_right, Left, Up, Up);
485 testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_right, Up, Right, Right);
486 testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_right, Right, Down, Down);
487
488 testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_left, Down, Right, Right);
489 testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_left, Right, Up, Up);
490 testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_left, Up, Left, Left);
491 testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_left, Left, Down, Down);
492 }
493
494 TEST_CASE("CommandTurnRandom") {
495 const MapGuard mg;
496
497 for (int i = 0; i < 10; ++i) {
498 auto ch = MoveRouteVehicle();
499 auto mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::face_random_direction) }});
500
501 ch.ForceMoveRoute(mr, 3);
502 testMoveRouteDir(ch, Down, Down, false, 3, 0xFFFF, 64, 0, true, false, mr);
503
504 ForceUpdate(ch);
505 testMoveRoute(ch, false, 3, 1, 32, 1, true, false, mr);
506
507 REQUIRE_GE(ch.GetDirection(), Up);
508 REQUIRE_LE(ch.GetDirection(), Left);
509 }
510 }
511
512
513 TEST_CASE("CommandWait") {
514 const MapGuard mg;
515
516 auto ch = MoveRouteVehicle();
517 auto mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::wait) }});
518
519 ch.ForceMoveRoute(mr, 2);
520 testMoveRouteDir(ch, Down, Down, false, 2, 0xFFFF, 0, 0, true, false, mr);
521
522 for(int i = 1; i <= 84; ++i) {
523 ForceUpdate(ch);
524 testMoveRouteDir(ch, Down, Down, false, 2, i, 84, 1, true, false, mr);
525 }
526
527 ForceUpdate(ch);
528 testMoveRouteDir(ch, Down, Down, false, 2, 85, 128, 1, false, false, mr);
529 }
530
531 template <bool success, bool repeat, bool skip, bool end>
testJump(lcf::rpg::MoveCommand::Code code,int x,int y,int dir,int face,int tx,int ty,int tdir,int tface,int px=0,int py=0)532 static void testJump(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int tx, int ty, int tdir, int tface, int px = 0, int py = 0) {
533 Main_Data::game_player->SetX(px);
534 Main_Data::game_player->SetY(py);
535
536 auto ch = MoveRouteVehicle();
537 ch.SetX(x);
538 ch.SetY(y);
539 ch.SetDirection(dir);
540 ch.SetFacing(face);
541 ch.SetAllowMovement(success);
542
543 auto mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::begin_jump) }}, repeat, skip);
544 if (code != lcf::rpg::MoveCommand::Code::end_jump) {
545 mr.move_commands.push_back({ static_cast<int>(code) });
546 }
547 if (end) {
548 mr.move_commands.push_back({ static_cast<int>(lcf::rpg::MoveCommand::Code::end_jump) });
549 }
550 auto num_cmds = static_cast<int>(mr.move_commands.size());
551
552 CAPTURE(code);
553 CAPTURE(x);
554 CAPTURE(y);
555 CAPTURE(dir);
556 CAPTURE(face);
557 CAPTURE(tx);
558 CAPTURE(ty);
559 CAPTURE(tdir);
560 CAPTURE(tface);
561 CAPTURE(px);
562 CAPTURE(py);
563 CAPTURE(success);
564 CAPTURE(repeat);
565 CAPTURE(skip);
566
567 auto dx = tx - x;
568 auto dy = ty - y;
569
570 ch.ForceMoveRoute(mr, 3);
571 testMoveRouteJump(ch, x, y, 0, false, 0, 0, dir, face, false, 3, 0xFFFF, 64, 0, true, false, mr);
572
573 if (!end) {
574 ForceUpdate(ch);
575 if (repeat) {
576 testMoveRouteJump(ch, x, y, 0, false, 0, 0, dir, face, false, 3, 0xFFFF + 1, 64, 0, true, true, mr);
577 } else {
578 testMoveRouteJump(ch, x, y, 0, false, 0, 0, dir, face, false, 2, 0xFFFF + 1, 128, num_cmds, false, false, mr);
579 }
580
581 return;
582 }
583
584 if (success) {
585 bool repeated = false;
586 for(int n = (repeat ? 3 : 1); n > 0; --n) {
587 CAPTURE(n);
588 for(int i = 232; i > 0; i -= 24) {
589 ForceUpdate(ch);
590 testMoveRouteJump(ch, tx, ty, i, true, x, y, tdir, tface, false, 3, 0, 64, num_cmds, true, repeated, mr);
591 }
592
593 if (!repeat) {
594 ForceUpdate(ch);
595 testMoveRouteJump(ch, tx, ty, 0, false, x, y, tdir, tface, false, 2, 0, 128, 0, false, false, mr);
596 break;
597 }
598
599 repeated = true;
600 for (int i = 0; i <= 64; ++i) {
601 ForceUpdate(ch);
602 testMoveRouteMove(ch, tx, ty, 0, tdir, tface, false, 3, i, 64, 0, true, repeated, mr);
603 }
604
605 x = tx;
606 y = ty;
607 tx += dx;
608 ty += dy;
609 }
610 } else {
611 ForceUpdate(ch);
612 if (skip) {
613 if (repeat) {
614 for (int i = 1; i <= 3; ++i) {
615 testMoveRouteJump(ch, tx, ty, 0, false, 0, 0, tdir, tface, false, 3, 0xFFFF + i, 64, 0, true, true, mr);
616 ForceUpdate(ch);
617 }
618 } else {
619 testMoveRouteJump(ch, tx, ty, 0, false, 0, 0, tdir, tface, false, 2, 0xFFFF + 1, 128, num_cmds, false, false, mr);
620 }
621 } else {
622 testMoveRouteJump(ch, tx, ty, 0, false, 0, 0, tdir, tface, false, 3, 0xFFFF + 1, 64, 0, true, false, mr);
623 }
624 }
625 }
626
627 template <typename... Args>
testJumpSuccess(const Args &...args)628 static void testJumpSuccess(const Args&... args) {
629 testJump<true, false, false, true>(args...);
630 testJump<true, false, true, true>(args...);
631 testJump<true, true, false, true>(args...);
632 testJump<true, true, true, true>(args...);
633 }
634
635 template <typename... Args>
testJumpSuccessNoRepeat(const Args &...args)636 static void testJumpSuccessNoRepeat(const Args&... args) {
637 testJump<true, false, false, true>(args...);
638 testJump<true, false, true, true>(args...);
639 }
640
testJumpFail(lcf::rpg::MoveCommand::Code code,int x,int y,int dir,int face,int tdir,int tface,int px=0,int py=0)641 static void testJumpFail(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int tdir, int tface, int px = 0, int py = 0) {
642 testJump<false, false, false, true>(code, x, y, dir, face, x, y, tdir, tface, px, py);
643 testJump<false, true, false, true>(code, x, y, dir, face, x, y, tdir, tface, px, py);
644 }
645
testJumpSkip(lcf::rpg::MoveCommand::Code code,int x,int y,int dir,int face,int px=0,int py=0)646 static void testJumpSkip(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int px = 0, int py = 0) {
647 testJump<false, false, true, true>(code, x, y, dir, face, x, y, dir, face, px, py);
648 testJump<false, true, true, true>(code, x, y, dir, face, x, y, dir, face, px, py);
649 }
650
testJumpNoEnd(lcf::rpg::MoveCommand::Code code,int x,int y,int dir,int face,int px=0,int py=0)651 static void testJumpNoEnd(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int px = 0, int py = 0) {
652 testJump<false, false, true, false>(code, x, y, dir, face, x, y, dir, face, px, py);
653 testJump<false, true, true, false>(code, x, y, dir, face, x, y, dir, face, px, py);
654 }
655
656 TEST_CASE("CommandJumpInPlace") {
657 const MapGuard mg;
658
659 // FIXME: Verify this behavior
660 testJumpSuccess(lcf::rpg::MoveCommand::Code::end_jump, 8, 8, Up, Up, 8, 8, Down, Up);
661 testJumpSuccess(lcf::rpg::MoveCommand::Code::end_jump, 8, 8, Right, Right, 8, 8, Down, Right);
662 testJumpSuccess(lcf::rpg::MoveCommand::Code::end_jump, 8, 8, Down, Down, 8, 8, Down, Down);
663 testJumpSuccess(lcf::rpg::MoveCommand::Code::end_jump, 8, 8, Left, Left, 8, 8, Down, Left);
664
665 // FIXME: Test no collision
666 }
667
668 TEST_CASE("CommandJump") {
669 const MapGuard mg;
670
671 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_up, 8, 8, Down, Down, 8, 7, Up, Up);
672 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_right, 8, 8, Down, Down, 9, 8, Right, Right);
673 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_down, 8, 8, Down, Down, 8, 9, Down, Down);
674 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_left, 8, 8, Down, Down, 7, 8, Left, Left);
675 }
676
677 TEST_CASE("CommandJumpFail") {
678 const MapGuard mg;
679
680 testJumpFail(lcf::rpg::MoveCommand::Code::move_up, 8, 8, Down, Down, Up, Up);
681 testJumpFail(lcf::rpg::MoveCommand::Code::move_right, 8, 8, Down, Down, Right, Right);
682 testJumpFail(lcf::rpg::MoveCommand::Code::move_down, 8, 8, Down, Down, Down, Down);
683 testJumpFail(lcf::rpg::MoveCommand::Code::move_left, 8, 8, Down, Down, Left, Left);
684 }
685
686 TEST_CASE("CommandJumpSkip") {
687 const MapGuard mg;
688
689 testJumpSkip(lcf::rpg::MoveCommand::Code::move_up, 8, 8, Down, Down);
690 testJumpSkip(lcf::rpg::MoveCommand::Code::move_right, 8, 8, Down, Down);
691 testJumpSkip(lcf::rpg::MoveCommand::Code::move_down, 8, 8, Down, Down);
692 testJumpSkip(lcf::rpg::MoveCommand::Code::move_left, 8, 8, Down, Down);
693 }
694
695 TEST_CASE("CommandJumpDiagonal") {
696 const MapGuard mg;
697
698 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Up, Up, 9, 7, Up, Up);
699 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Right, Right, 9, 7, Up, Up);
700 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Down, Down, 9, 7, Up, Up);
701 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Left, Left, 9, 7, Up, Up);
702
703 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Up, Up, 9, 9, Down, Down);
704 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Right, Right, 9, 9, Down, Down);
705 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Down, Down, 9, 9, Down, Down);
706 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Left, Left, 9, 9, Down, Down);
707
708 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Up, Up, 7, 9, Down, Down);
709 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Right, Right, 7, 9, Down, Down);
710 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Down, Down, 7, 9, Down, Down);
711 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Left, Left, 7, 9, Down, Down);
712
713 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Up, Up, 7, 7, Up, Up);
714 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Right, Right, 7, 7, Up, Up);
715 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Down, Down, 7, 7, Up, Up);
716 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Left, Left, 7, 7, Up, Up);
717 }
718
719 TEST_CASE("CommandJumpDiagonalFail") {
720 const MapGuard mg;
721
722 testJumpFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Up, Up, Up, Up);
723 testJumpFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Right, Right, Up, Up);
724 testJumpFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Down, Down, Up, Up);
725 testJumpFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Left, Left, Up, Up);
726
727 testJumpFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Up, Up, Down, Down);
728 testJumpFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Right, Right, Down, Down);
729 testJumpFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Down, Down, Down, Down);
730 testJumpFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Left, Left, Down, Down);
731
732 testJumpFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Up, Up, Down, Down);
733 testJumpFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Right, Right, Down, Down);
734 testJumpFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Down, Down, Down, Down);
735 testJumpFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Left, Left, Down, Down);
736
737 testJumpFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Up, Up, Up, Up);
738 testJumpFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Right, Right, Up, Up);
739 testJumpFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Down, Down, Up, Up);
740 testJumpFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Left, Left, Up, Up);
741 }
742
743 TEST_CASE("CommandJumpDiagonalSkip") {
744 const MapGuard mg;
745
746 testJumpSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Up, Up);
747 testJumpSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Right, Right);
748 testJumpSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Down, Down);
749 testJumpSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Left, Left);
750
751 testJumpSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Up, Up);
752 testJumpSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Right, Right);
753 testJumpSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Down, Down);
754 testJumpSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Left, Left);
755
756 testJumpSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Up, Up);
757 testJumpSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Right, Right);
758 testJumpSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Down, Down);
759 testJumpSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Left, Left);
760
761 testJumpSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Up, Up);
762 testJumpSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Right, Right);
763 testJumpSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Down, Down);
764 testJumpSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Left, Left);
765 }
766
767 TEST_CASE("CommandJumpForward") {
768 const MapGuard mg;
769
770 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Up, Up, 8, 7, Up, Up);
771 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Right, Right, 9, 8, Right, Right);
772 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Down, Down, 8, 9, Down, Down);
773 testJumpSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Left, Left, 7, 8, Left, Left);
774
775 // FIXME: For repeat, these will move diag and then up or down afterwards.
776 testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Up, 9, 7, Up, Up);
777 testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Right, 9, 7, Up, Up);
778 testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Down, 9, 9, Down, Down);
779 testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Right, 9, 9, Down, Down);
780 testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Up, 7, 7, Up, Up);
781 testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Left, 7, 7, Up, Up);
782 testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Down, 7, 9, Down, Down);
783 testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Left, 7, 9, Down, Down);
784 }
785
786 TEST_CASE("CommandJumpForwardFail") {
787 const MapGuard mg;
788
789 testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Up, Up, Up, Up);
790 testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Right, Right, Right, Right);
791 testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Down, Down, Down, Down);
792 testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Left, Left, Left, Left);
793
794 testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Up, Up, Up);
795 testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Right, Up, Up);
796 testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Down, Down, Down);
797 testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Right, Down, Down);
798 testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Up, Up, Up);
799 testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Left, Up, Up);
800 testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Down, Down, Down);
801 testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Left, Down, Down);
802 }
803
804 TEST_CASE("CommandJumpForwardSkip") {
805 const MapGuard mg;
806
807 testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Up, Up);
808 testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Right, Right);
809 testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Down, Down);
810 testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Left, Left);
811
812 testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Up);
813 testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Right);
814 testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Down);
815 testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Right);
816 testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Up);
817 testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Left);
818 testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Down);
819 testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Left);
820 }
821
822 TEST_CASE("CommandJumpRandom") {
823 // FIXME: TBD
824 }
825
826 TEST_CASE("CommandJumpNoEnd") {
827 const MapGuard mg;
828
829 // This makes a move route with just "Jump"
830 testJumpNoEnd(lcf::rpg::MoveCommand::Code::end_jump, 8, 8, Down, Down);
831 }
832
833
834 TEST_CASE("CommandMoveTurnJumpHero") {
835 const MapGuard mg;
836
837 int x = 8;
838 int y = 8;
839 for (int dx = -2; dx <= 2; ++dx) {
840 for (int dy = -2; dy <= 2; ++dy) {
841 auto step_x = 0;
842 auto step_y = 0;
843 auto dir = Down;
844
845 if (std::abs(dx) > std::abs(dy)) {
846 dir = (dx > 0 ? Right : Left);
847 step_x = (dx > 0 ? 1 : -1);
848 } else {
849 dir = (dy >= 0 ? Down : Up);
850 step_y = (dy >= 0 ? 1 : -1);
851 }
852 auto rdir = Game_Character::GetDirection180Degree(dir);
853
854 auto px = x + dx;
855 auto py = y + dy;
856
857 testTurn(lcf::rpg::MoveCommand::Code::face_hero, Left, dir, dir, x, y, px, py);
858 testTurn(lcf::rpg::MoveCommand::Code::face_away_from_hero, Left, rdir, rdir, x, y, px, py);
859
860 testMoveSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_towards_hero, x, y, Left, Left, x + step_x, y + step_y, dir, dir, px, py);
861 testMoveSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_away_from_hero, x, y, Left, Left, x - step_x, y - step_y, rdir, rdir, px, py);
862
863 testMoveFail(lcf::rpg::MoveCommand::Code::move_towards_hero, x, y, Left, Left, dir, dir, px, py);
864 testMoveFail(lcf::rpg::MoveCommand::Code::move_away_from_hero, x, y, Left, Left, rdir, rdir, px, py);
865
866 testMoveSkip(lcf::rpg::MoveCommand::Code::move_towards_hero, x, y, Left, Left, px, py);
867 testMoveSkip(lcf::rpg::MoveCommand::Code::move_away_from_hero, x, y, Left, Left, px, py);
868
869 testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_towards_hero, x, y, Left, Left, x + step_x, y + step_y, dir, dir, px, py);
870 testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_away_from_hero, x, y, Left, Left, x - step_x, y - step_y, rdir, rdir, px, py);
871
872 testJumpFail(lcf::rpg::MoveCommand::Code::move_towards_hero, x, y, Left, Left, dir, dir, px, py);
873 testJumpFail(lcf::rpg::MoveCommand::Code::move_away_from_hero, x, y, Left, Left, rdir, rdir, px, py);
874
875 testJumpSkip(lcf::rpg::MoveCommand::Code::move_towards_hero, x, y, Left, Left, px, py);
876 testJumpSkip(lcf::rpg::MoveCommand::Code::move_away_from_hero, x, y, Left, Left, px, py);
877 }
878 }
879 }
880
testLockFacing(lcf::rpg::EventPage::AnimType at)881 void testLockFacing(lcf::rpg::EventPage::AnimType at) {
882 const MapGuard mg;
883
884 auto ch = MoveRouteVehicle();
885 ch.SetAnimationType(at);
886 auto mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::lock_facing) }});
887
888 ch.ForceMoveRoute(mr, 2);
889 testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr);
890 REQUIRE_EQ(ch.IsFacingLocked(), Game_Character::IsDirectionFixedAnimationType(at));
891
892 ForceUpdate(ch);
893 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
894 REQUIRE(ch.IsFacingLocked());
895
896 mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::unlock_facing) }});
897 ch.ForceMoveRoute(mr, 2);
898 testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr);
899 REQUIRE(ch.IsFacingLocked());
900
901 ForceUpdate(ch);
902 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
903 REQUIRE_EQ(ch.IsFacingLocked(), Game_Character::IsDirectionFixedAnimationType(at));
904 }
905
906 TEST_CASE("CommandLockFacing") {
907 for (int i = 0; i <= static_cast<int>(lcf::rpg::EventPage::AnimType_step_frame_fix); ++i) {
908 testLockFacing(static_cast<lcf::rpg::EventPage::AnimType>(i));
909 }
910 }
911
912 TEST_CASE("CommandSpeedChange") {
913 const MapGuard mg;
914
915 auto ch = MoveRouteVehicle();
916 auto mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::increase_movement_speed) }});
917 const int n = 10;
918
919 ch.SetMoveSpeed(1);
920 int prev = ch.GetMoveSpeed();
921 for (int i = 0; i < 10; ++i) {
922 ch.ForceMoveRoute(mr, 2);
923 testMoveRoute(ch, false, 2, 0xFFFF, (i == 0 ? 0 : 128), 0, true, false, mr);
924 REQUIRE_EQ(ch.GetMoveSpeed(), prev);
925
926 ForceUpdate(ch);
927 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
928 REQUIRE_EQ(ch.GetMoveSpeed(), std::min(prev + 1, 6));
929
930 prev= ch.GetMoveSpeed();
931 }
932
933 mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::decrease_movement_speed) }});
934 for (int i = 0; i < 10; ++i) {
935 ch.ForceMoveRoute(mr, 2);
936 testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr);
937 REQUIRE_EQ(ch.GetMoveSpeed(), prev);
938
939 ForceUpdate(ch);
940 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
941 REQUIRE_EQ(ch.GetMoveSpeed(), std::max(prev - 1, 1));
942
943 prev= ch.GetMoveSpeed();
944 }
945 }
946
947 TEST_CASE("CommandFreqChange") {
948 const MapGuard mg;
949
950 auto ch = MoveRouteVehicle();
951 auto mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::increase_movement_frequence) }});
952 const int n = 10;
953
954 for (int i = 1; i < 10; ++i) {
955 const int freq = Utils::Clamp(i, 1, 8);
956
957 ch.ForceMoveRoute(mr, freq);
958 testMoveRoute(ch, false, freq, 0xFFFF, (i == 0 && freq == 2 ? 0 : Game_Character::GetMaxStopCountForStep(freq)), 0, true, false, mr);
959
960 const int next_freq = Utils::Clamp(freq + 1, 1, 8);
961 ForceUpdate(ch);
962 // FIXME: Need another command for the frequency to not get reset when move route is done.
963 //testMoveRoute(ch, false, next_freq, 0xFFFF + 1, Game_Character::GetMaxStopCountForStep(next_freq), 1, false, false, mr);
964
965 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
966
967 }
968
969 mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::decrease_movement_frequence) }});
970
971 for (int i = 1; i < 10; ++i) {
972 const int freq = Utils::Clamp(i, 1, 8);
973
974 ch.ForceMoveRoute(mr, freq);
975 testMoveRoute(ch, false, freq, 0xFFFF, Game_Character::GetMaxStopCountForStep(freq), 0, true, false, mr);
976
977 const int next_freq = Utils::Clamp(freq - 1, 1, 8);
978 ForceUpdate(ch);
979 // FIXME: Need another command for the frequency to not get reset when move route is done.
980 //testMoveRoute(ch, false, next_freq, 0xFFFF + 1, Game_Character::GetMaxStopCountForStep(next_freq), 1, false, false, mr);
981 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
982 }
983 }
984
985 TEST_CASE("CommandTranspChange") {
986 const MapGuard mg;
987
988 auto ch = MoveRouteVehicle();
989 auto mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::increase_transp) }});
990 const int n = 10;
991
992 ch.SetTransparency(0);
993 int prev = ch.GetTransparency();
994 for (int i = 0; i < 10; ++i) {
995 ch.ForceMoveRoute(mr, 2);
996 testMoveRoute(ch, false, 2, 0xFFFF, (i == 0 ? 0 : 128), 0, true, false, mr);
997 REQUIRE_EQ(ch.GetTransparency(), prev);
998
999 ForceUpdate(ch);
1000 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
1001 REQUIRE_EQ(ch.GetTransparency(), std::min(prev + 1, 7));
1002
1003 prev = ch.GetTransparency();
1004 }
1005
1006 mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::decrease_transp) }});
1007 for (int i = 0; i < 10; ++i) {
1008 ch.ForceMoveRoute(mr, 2);
1009 testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr);
1010 REQUIRE_EQ(ch.GetTransparency(), prev);
1011
1012 ForceUpdate(ch);
1013 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
1014 REQUIRE_EQ(ch.GetTransparency(), std::max(prev - 1, 0));
1015
1016 prev = ch.GetTransparency();
1017 }
1018 }
1019
1020 TEST_CASE("CommandThrough") {
1021 const MapGuard mg;
1022
1023 auto ch = MoveRouteVehicle();
1024 auto mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::walk_everywhere_on) }});
1025
__anoncd9cbc7e0102() 1026 auto testoff = [&]() {
1027 REQUIRE(!ch.GetThrough());
1028 ch.SetThrough(true);
1029 REQUIRE(ch.GetThrough());
1030 ch.ResetThrough();
1031 REQUIRE(!ch.GetThrough());
1032 };
1033
__anoncd9cbc7e0202() 1034 auto teston = [&]() {
1035 REQUIRE(ch.GetThrough());
1036 ch.SetThrough(false);
1037 REQUIRE(!ch.GetThrough());
1038 ch.ResetThrough();
1039 REQUIRE(ch.GetThrough());
1040 };
1041
1042 ch.ForceMoveRoute(mr, 2);
1043 testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr);
1044 testoff();
1045
1046 ForceUpdate(ch);
1047 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
1048 teston();
1049
1050 mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::walk_everywhere_off) }});
1051 ch.ForceMoveRoute(mr, 2);
1052 testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr);
1053 teston();
1054
1055 ForceUpdate(ch);
1056 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
1057 testoff();
1058
1059 ch.SetThrough(true);
1060
1061 mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::walk_everywhere_off) }});
1062 ch.ForceMoveRoute(mr, 2);
1063 testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr);
1064 REQUIRE(ch.GetThrough());
1065
1066 ForceUpdate(ch);
1067 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
1068 testoff();
1069
1070 ch.SetThrough(true);
1071 mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::walk_everywhere_on) }});
1072 ch.ForceMoveRoute(mr, 2);
1073 REQUIRE(ch.GetThrough());
1074
1075 ForceUpdate(ch);
1076 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
1077 teston();
1078 }
1079
1080 TEST_CASE("CommandStopAnimation") {
1081 const MapGuard mg;
1082
1083 auto ch = MoveRouteVehicle();
1084 auto mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::stop_animation) }});
1085
1086 ch.ForceMoveRoute(mr, 2);
1087 testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr);
1088 REQUIRE(!ch.IsAnimPaused());
1089
1090 ForceUpdate(ch);
1091 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
1092 REQUIRE(ch.IsAnimPaused());
1093
1094 mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::start_animation) }});
1095 ch.ForceMoveRoute(mr, 2);
1096 testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr);
1097 REQUIRE(ch.IsAnimPaused());
1098
1099 ForceUpdate(ch);
1100 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
1101 REQUIRE(!ch.IsAnimPaused());
1102 }
1103
1104 TEST_CASE("CommandSwitchToggle") {
1105 const MapGuard mg;
1106
1107 auto ch = MoveRouteVehicle();
1108 auto mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::switch_on), "", 3 }});
1109
1110 REQUIRE_NE(Main_Data::game_switches, nullptr);
1111
1112 ch.ForceMoveRoute(mr, 2);
1113 testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr);
1114 REQUIRE(!Main_Data::game_switches->Get(3));
1115
1116 ForceUpdate(ch);
1117 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
1118 REQUIRE(Main_Data::game_switches->Get(3));
1119
1120 mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::switch_off), "", 3 }});
1121 ch.ForceMoveRoute(mr, 2);
1122 testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr);
1123 REQUIRE(Main_Data::game_switches->Get(3));
1124
1125 ForceUpdate(ch);
1126 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
1127 REQUIRE(!Main_Data::game_switches->Get(3));
1128 }
1129
1130 TEST_CASE("CommandChangeGraphic") {
1131 const MapGuard mg;
1132
1133 auto ch = MoveRouteVehicle();
1134 auto mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::change_graphic), "x", 3 }});
1135
1136 ch.ForceMoveRoute(mr, 2);
1137 testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr);
1138 REQUIRE_EQ(ch.GetSpriteName(), "");
1139 REQUIRE_EQ(ch.GetSpriteIndex(), 0);
1140
1141 ForceUpdate(ch);
1142 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
1143 REQUIRE_EQ(ch.GetSpriteName(), "x");
1144 REQUIRE_EQ(ch.GetSpriteIndex(), 3);
1145 }
1146
1147 TEST_CASE("CommandPlaySound") {
1148 const MapGuard mg;
1149
1150 auto ch = MoveRouteVehicle();
1151 auto mr = MakeRoute({{ static_cast<int>(lcf::rpg::MoveCommand::Code::play_sound_effect), "", 100, 100, 100 }});
1152
1153 ch.ForceMoveRoute(mr, 2);
1154 testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr);
1155
1156 ForceUpdate(ch);
1157 testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr);
1158
1159 // FIXME: Check mocked audio subsystem?
1160 }
1161
1162 TEST_CASE("ClearPause") {
1163 auto ch = MoveRouteVehicle();
1164
1165 ch.SetPaused(true);
1166 REQUIRE(ch.IsPaused());
1167
1168 auto mr = MakeRoute({{}});
1169 ch.ForceMoveRoute(mr, 3);
1170
1171 REQUIRE(!ch.IsPaused());
1172 }
1173
1174 TEST_SUITE_END();
1175