1 #include "game_player.h"
2 #include "doctest.h"
3 #include "options.h"
4 #include "game_map.h"
5 #include "main_data.h"
6 #include "game_system.h"
7 #include "rand.h"
8 #include <climits>
9
10 #include "mock_game.h"
11
12 TEST_SUITE_BEGIN("Game_Player Input");
13
14 static constexpr auto map_id = MockMap::ePassBlock20x15;
15
16 // FIXME: Test conditions which disable input
17
testPos(Game_Player & ch,int x,int y,int dir,int face,int remaining_step,bool jumping,int stop_count,int max_stop_count,int encounter_steps,bool encounter_calling,bool menu_calling,int vehicle,bool boarding,bool aboard)18 static void testPos(Game_Player& ch, int x, int y,
19 int dir, int face,
20 int remaining_step, bool jumping,
21 int stop_count, int max_stop_count,
22 int encounter_steps, bool encounter_calling,
23 bool menu_calling,
24 int vehicle, bool boarding, bool aboard)
25 {
26
27 REQUIRE_EQ(ch.GetX(), x);
28 REQUIRE_EQ(ch.GetY(), y);
29 REQUIRE_EQ(ch.GetDirection(), dir);
30 REQUIRE_EQ(ch.GetFacing(), face);
31 REQUIRE_EQ(ch.GetRemainingStep(), remaining_step);
32 REQUIRE_EQ(ch.IsJumping(), jumping);
33 REQUIRE_EQ(ch.GetStopCount(), stop_count);
34 REQUIRE_EQ(ch.GetMaxStopCount(), max_stop_count);
35 REQUIRE_EQ(ch.GetEncounterSteps(), encounter_steps);
36 REQUIRE_EQ(ch.IsEncounterCalling(), encounter_calling);
37 REQUIRE_EQ(ch.IsMenuCalling(), menu_calling);
38 REQUIRE_EQ(ch.GetVehicleType(),vehicle);
39 REQUIRE_EQ(ch.IsBoardingOrUnboarding(), boarding);
40 REQUIRE_EQ(ch.IsAboard(), aboard);
41 }
42
testMove(bool success,int input_dir,int dir,int x,int y,int dx,int dy,bool cheat,bool debug)43 static void testMove(bool success, int input_dir, int dir, int x, int y, int dx, int dy, bool cheat, bool debug) {
44 DebugGuard dg(debug);
45 const MockGame mg(map_id);
46 auto& ch = *mg.GetPlayer();
47
48 CAPTURE(cheat);
49 CAPTURE(debug);
50 CAPTURE(input_dir);
51 CAPTURE(dir);
52 CAPTURE(x);
53 CAPTURE(y);
54
55 ch.SetX(x);
56 ch.SetY(y);
57
58 Input::ResetKeys();
59
60 Input::dir4 = input_dir;
61
62 if (cheat) {
63 Input::press_time[Input::DEBUG_THROUGH] = 1;
64 }
65
66 const auto tx = x + dx;
67 const auto ty = y + dy;
68
69 // Force RNG to always fail to generate a random encounter
70 Rand::LockGuard lk(INT32_MAX);
71 ForceUpdate(ch);
72 if (success) {
73 int enc_steps = (cheat && debug) ? 0 : 100;
74 testPos(ch, tx, ty, dir, dir, 224, false, 0, 0, enc_steps, false, false, 0, false, false);
75 } else {
76 testPos(ch, tx, ty, dir, dir, 0, false, 1, 0, 0, false, false, 0, false, false);
77 }
78 }
79
80 TEST_CASE("Move") {
81 testMove(true, 8, Up, 4, 8, 0, -1, false, false);
82 testMove(true, 6, Right, 4, 8, 1, 0, false, false);
83 testMove(true, 2, Down, 4, 8, 0, 1, false, false);
84 testMove(true, 4, Left, 4, 8, -1, 0, false, false);
85
86 testMove(false, 8, Up, 16, 8, 0, 0, false, false);
87 testMove(false, 6, Right, 16, 8, 0, 0, false, false);
88 testMove(false, 2, Down, 16, 8, 0, 0, false, false);
89 testMove(false, 4, Left, 16, 8, 0, 0, false, false);
90
91 testMove(false, 8, Up, 16, 8, 0, 0, true, false);
92 testMove(false, 6, Right, 16, 8, 0, 0, true, false);
93 testMove(false, 2, Down, 16, 8, 0, 0, true, false);
94 testMove(false, 4, Left, 16, 8, 0, 0, true, false);
95
96 testMove(true, 8, Up, 16, 8, 0, -1, true, true);
97 testMove(true, 6, Right, 16, 8, 1, 0, true, true);
98 testMove(true, 2, Down, 16, 8, 0, 1, true, true);
99 testMove(true, 4, Left, 16, 8, -1, 0, true, true);
100 }
101
testDecision(bool moved,int vehicle,bool boarding,bool aboard)102 static void testDecision(bool moved, int vehicle, bool boarding, bool aboard) {
103 auto& ch = *MockGame::GetPlayer();
104
105 ch.SetX(8);
106 ch.SetY(8);
107
108 Input::ResetKeys();
109
110 Input::triggered[Input::DECISION] = true;
111
112 ForceUpdate(ch);
113
114 int y = moved ? 9 : 8;
115 int rs = moved ? 224 : 0;
116 int stp = moved ? 0 : 1;
117 testPos(ch, 8, y, Down, Down, rs, false, stp, 0, 0, false, false, vehicle, boarding, aboard);
118 }
119
120 TEST_CASE("DecisionNone") {
121 const MockGame mg(map_id);
122
123 testDecision(false, 0, false, false);
124 }
125
126 TEST_CASE("DecisionEvent") {
127 const MockGame mg(map_id);
128
129 auto* event = Game_Map::GetEvent(1);
130 REQUIRE(event);
131 event->MoveTo(1, 8, 9);
132
133 testDecision(false, 0, false, false);
134
135 // FIXME: Add map page which triggers
136 }
137
138 TEST_CASE("DecisionBoard") {
139 const MockGame mg(map_id);
140 auto& ch = *Main_Data::game_player;
141
142 auto* vh = Game_Map::GetVehicle(Game_Vehicle::Boat);
143 REQUIRE(vh);
144 vh->MoveTo(1, 8, 9);
145
146 testDecision(true, Game_Vehicle::Boat, true, false);
147
148 while (!ch.IsStopping()) {
149 ForceUpdate(ch);
150 }
151
152 testPos(ch, 8, 9, Down, Left, 0, false, 0, 0, 0, false, false, Game_Vehicle::Boat, 0, true);
153 }
154
155 TEST_CASE("DecisionUnboard") {
156 const MockGame mg(map_id);
157
158 // FIXME: Implement
159 }
160
testMenu(bool success)161 static void testMenu(bool success) {
162 auto& ch = *Main_Data::game_player;
163 ch.SetX(8);
164 ch.SetY(8);
165
166 Input::ResetKeys();
167
168 Input::triggered[Input::CANCEL] = true;
169
170 ForceUpdate(ch);
171 testPos(ch, 8, 8, Down, Down, 0, false, 1, 0, 0, false, success, 0, false, false);
172
173 // FIXME: Test conditions which disable menu calling
174 }
175
176 TEST_CASE("CallMenu") {
177 const MockGame mg(map_id);
178
179 testMenu(true);
180 }
181
182 TEST_CASE("CallMenuDisabled") {
183 const MockGame mg(map_id);
184
185 Main_Data::game_system->SetAllowMenu(false);
186
187 testMenu(false);
188 }
189
190 TEST_SUITE_END();
191