if_character.cpp (9096B)
1 #include "scraps/game/action_eval/if.hpp" // IWYU pragma: associated 2 3 #include "scraps/game/action_eval/test_helper.hpp" 4 #include "scraps/game/character_state.hpp" 5 #include "scraps/game/room_state.hpp" 6 #include "scraps/uuid.hpp" 7 8 #include <libshit/except.hpp> 9 #include <libshit/nonowning_string.hpp> 10 11 // IWYU pragma: no_include <type_traits> 12 // IWYU pragma: no_forward_declare Scraps::Game::IdKey 13 // IWYU pragma: no_forward_declare Scraps::Game::NameKey 14 15 namespace Scraps::Game::ActionEvalPrivate 16 { 17 TEST_SUITE_BEGIN("Scraps::Game::ActionEval"); 18 19 std::optional<bool> IfCharacterCustomProperty(IfParam p) 20 { 21 RAGS_IF_CUSTOM_PROPERTY_GET_PARTS; 22 auto c = p.gc->GetCharacterColl().Get<NameKey>(parts[0]); if (!c) return {}; 23 return IfCustomPropertyCommon(p, c->GetProperties(), parts[1]); 24 } 25 26 TEST_CASE_FIXTURE(Fixture, "IfCharacterCustomProperty") 27 { 28 SetCk("chars_0", "Equals", "Value 0"); 29 CHECK(IfCharacterCustomProperty(p) == std::nullopt); // no colon 30 SetCk("chara_0:key_0:foo", "Equals", "Value 0"); 31 CHECK(IfCharacterCustomProperty(p) == std::nullopt); // too many colon 32 SetCk("chara_0:nosuch", "Equals", "Value 0"); 33 CHECK(IfCharacterCustomProperty(p) == std::nullopt); // no prop 34 SetCk("nosuch:key_0", "Equals", "Value 0"); 35 CHECK(IfCharacterCustomProperty(p) == std::nullopt); // no chara 36 SetCk("chara_0:key_0", "Equals", "Value 0"); 37 CHECK(IfCharacterCustomProperty(p) == true); // OK 38 } 39 40 std::optional<bool> IfPlayerCustomProperty(IfParam p) 41 { 42 return IfCustomPropertyCommon( 43 p, p.gc->GetPlayer().GetProperties(), p.check.GetParam0()); 44 } 45 46 // --------------------------------------------------------------------------- 47 48 static bool GenderCommon( 49 IfParam p, ConstCharacterProxy c, Libshit::NonowningString param) 50 { 51 auto gender = Format::Proto::Gender::OTHER; 52 param = p.Replace(p.eval.tmp_str0, param); 53 if (param == "Male") gender = Format::Proto::Gender::MALE; 54 else if (param == "Female") gender = Format::Proto::Gender::FEMALE; 55 56 return c.GetGender() == gender; 57 } 58 59 std::optional<bool> IfCharacterGender(IfParam p) 60 { 61 auto name = p.Replace(p.eval.tmp_str0, p.check.GetParam0()); 62 auto c = p.gc->GetCharacterColl().Get<NameKey>(name); 63 if (!c) return {}; 64 65 return GenderCommon(p, *c, p.check.GetParam1()); 66 } 67 68 TEST_CASE_FIXTURE(Fixture, "IfCharacterGender") 69 { 70 SetCk("nochar", "Male", ""); 71 CHECK(IfCharacterGender(p) == std::nullopt); 72 73 SetCk("chara_0", "Male", ""); 74 CHECK(IfCharacterGender(p) == true); 75 SetCk("chara_0", "male", ""); // case sensitive 76 CHECK(IfCharacterGender(p) == false); 77 78 SetCk("chara_1", "Female", ""); 79 CHECK(IfCharacterGender(p) == true); 80 81 SetCk("chara_2", "whatever... I mean Other", ""); 82 CHECK(IfCharacterGender(p) == true); 83 } 84 85 std::optional<bool> IfPlayerGender(IfParam p) 86 { return GenderCommon(p, p.gc->GetPlayer(), p.check.GetParam0()); } 87 88 TEST_CASE_FIXTURE(Fixture, "IfPlayerGender") 89 { 90 SetCk("Male", "", ""); 91 CHECK(IfPlayerGender(p) == true); 92 SetCk("Anything", "", ""); 93 CHECK(IfPlayerGender(p) == false); 94 } 95 96 // --------------------------------------------------------------------------- 97 98 static bool InRoomCommon( 99 IfParam p, RoomId rid, Libshit::NonowningString uuid, bool check_player) 100 { 101 uuid = p.Replace(p.eval.tmp_str0, uuid); 102 103 // fast track for player's current room 104 if (check_player && uuid == Uuid::PLAYER_ROOM_STR) 105 return rid == p.gc->GetPlayer().GetRoomId(); 106 107 auto r = p.gc->GetRoomColl().StateGet<IdKey>(rid); 108 // if not in any room -> check void uuid 109 if (!r) return uuid == Uuid::VOID_ROOM_STR; 110 111 auto uuid_p = Uuid::TryParse(uuid); 112 return uuid_p && r->uuid == *uuid_p; 113 } 114 115 std::optional<bool> IfCharacterInRoom(IfParam p) 116 { 117 auto name = p.Replace(p.eval.tmp_str0, p.check.GetParam0()); 118 auto rid = p.gc->GetCharacterColl().At<NameKey>(name).GetRoomId(); 119 120 return InRoomCommon(p, rid, p.check.GetParam1(), true); 121 } 122 123 TEST_CASE_FIXTURE(Fixture, "IfCharacterInRoom") 124 { 125 SetCk("nosuch", "00000000-0000-4004-0000-000000000000", ""); 126 CHECK_THROWS(IfCharacterInRoom(p)); 127 128 SetCk("chara_0", "nosuch", ""); 129 CHECK(IfCharacterInRoom(p) == false); 130 131 SetCk("chara_0", "00000000-0000-4004-0000-ffffffffffff", ""); 132 CHECK(IfCharacterInRoom(p) == false); 133 134 SetCk("chara_0", "00000000-0000-4004-0000-000000000000", ""); 135 CHECK(IfCharacterInRoom(p) == true); 136 137 // the player is in the same room as player. wow! 138 SetCk("chara_0", Uuid::PLAYER_ROOM_STR, ""); 139 CHECK(IfCharacterInRoom(p) == true); 140 SetCk("chara_0", "00000000000000000000000000000001", ""); 141 CHECK(IfCharacterInRoom(p) == false); // UUID not parsed 142 SetCk("chara_0", Uuid::VOID_ROOM_STR, ""); 143 CHECK(IfCharacterInRoom(p) == false); // but not in void 144 145 st.GetCharacterColl().At(1).SetRoomId(RoomId{}); 146 SetCk("chara_1", Uuid::VOID_ROOM_STR, ""); 147 CHECK(IfCharacterInRoom(p) == true); // chara 1 is in void 148 SetCk("chara_1", Uuid::PLAYER_ROOM_STR, ""); 149 CHECK(IfCharacterInRoom(p) == false); // not same as player 150 SetCk("chara_1", "00000000-0000-4004-0000-000000000000", ""); 151 CHECK(IfCharacterInRoom(p) == false); // not room 0... 152 } 153 154 std::optional<bool> IfPlayerInRoom(IfParam p) 155 { 156 return InRoomCommon( 157 p, p.gc->GetPlayer().GetRoomId(), p.check.GetParam0(), false); 158 } 159 160 TEST_CASE_FIXTURE(Fixture, "IfPlayerInRoom") 161 { 162 SetCk("00000000-0000-4004-0000-000000000000", "", ""); 163 CHECK(IfPlayerInRoom(p) == true); 164 // same room as player not handled 165 SetCk(Uuid::PLAYER_ROOM_STR, "", ""); 166 CHECK(IfPlayerInRoom(p) == false); 167 SetCk(Uuid::VOID_ROOM_STR, "", ""); 168 CHECK(IfPlayerInRoom(p) == false); 169 170 st.GetPlayer().SetRoomId(RoomId{}); // don't try this at home 171 CHECK(IfPlayerInRoom(p) == true); 172 } 173 174 // --------------------------------------------------------------------------- 175 176 std::optional<bool> IfCharacterInRoomGroup(IfParam p) 177 { 178 auto name = p.Replace(p.eval.tmp_str0, p.check.GetParam0()); 179 auto c = p.gc->GetCharacterColl().At<NameKey>(name); 180 auto r = p.gc->GetRoomColl().Get<IdKey>(c.GetRoomId()); 181 if (!r) return false; 182 183 return IfInGroupCommon(p, p.gc->GetRoomGroupColl(), r->GetGroupId(), 184 p.check.GetParam1(), "None"); 185 } 186 187 TEST_CASE_FIXTURE(Fixture, "IfCharacterInRoomGroup") 188 { 189 SetCk("nosuch", "None", ""); 190 CHECK_THROWS(IfCharacterInRoomGroup(p)); 191 192 st.GetCharacterColl().At(1).SetRoomId({}); 193 SetCk("chara_1", "None", ""); 194 CHECK(IfCharacterInRoomGroup(p) == false); 195 SetCk("chara_1", "foobar", ""); 196 CHECK(IfCharacterInRoomGroup(p) == false); 197 SetCk("chara_1", "room_group_0", ""); 198 CHECK(IfCharacterInRoomGroup(p) == false); 199 200 SetCk("chara_0", "room_group_0", ""); 201 CHECK(IfCharacterInRoomGroup(p) == true); 202 SetCk("chara_0", "room_group_1", ""); 203 CHECK(IfCharacterInRoomGroup(p) == false); 204 SetCk("chara_0", "None", ""); 205 CHECK(IfCharacterInRoomGroup(p) == false); 206 } 207 208 std::optional<bool> IfPlayerInRoomGroup(IfParam p) 209 { 210 auto r = p.gc->GetPlayerRoom(); 211 return IfInGroupCommon(p, p.gc->GetRoomGroupColl(), r.GetGroupId(), 212 p.check.GetParam0(), "None"); 213 } 214 215 TEST_CASE_FIXTURE(Fixture, "IfCharacterInRoomGroup") 216 { 217 SetCk("None", "", ""); 218 CHECK(IfPlayerInRoomGroup(p) == false); 219 SetCk("room_group_0", "", ""); 220 CHECK(IfPlayerInRoomGroup(p) == true); 221 222 dummy.game.GetRooms()[0].SetGroupId(0); 223 SetCk("None", "", ""); 224 CHECK(IfPlayerInRoomGroup(p) == true); 225 SetCk("room_group_0", "", ""); 226 CHECK(IfPlayerInRoomGroup(p) == false); 227 } 228 229 // --------------------------------------------------------------------------- 230 231 std::optional<bool> IfPlayerInSameRoomAs(IfParam p) 232 { 233 auto name = p.Replace(p.eval.tmp_str0, p.check.GetParam0()); 234 return p.gc->GetPlayer().GetRoomId() == 235 p.gc->GetCharacterColl().At<NameKey>(name).GetRoomId(); 236 } 237 238 TEST_CASE_FIXTURE(Fixture, "IfPlayerInSameRoomAs") 239 { 240 SetCk("nosuch", "", ""); 241 CHECK_THROWS(IfPlayerInSameRoomAs(p)); 242 243 SetCk("chara_1", "", ""); 244 CHECK(IfPlayerInSameRoomAs(p) == false); 245 st.GetCharacterColl().At(1).SetRoomId(st.GetPlayerRoom().GetId()); 246 CHECK(IfPlayerInSameRoomAs(p) == true); 247 } 248 249 // --------------------------------------------------------------------------- 250 251 std::optional<bool> IfPlayerMoving(IfParam p) 252 { 253 auto dir = RagsStr2Dir(p.Replace(p.eval.tmp_str0, p.check.GetParam0())); 254 if (!dir.has_value()) 255 LIBSHIT_THROW(ActionEvalError, "Invalid direction", 256 "Direction", p.eval.tmp_str0); 257 return dir == p.gc.GetActionEval().GetMovingDirection(); 258 } 259 260 TEST_CASE_FIXTURE(Fixture, "IfPlayerMoving") 261 { 262 SetCk("nosuch", "", ""); 263 CHECK_THROWS(IfPlayerMoving(p)); 264 265 SetCk("Empty", "", ""); 266 CHECK(IfPlayerMoving(p) == true); 267 SetCk("South", "", ""); 268 CHECK(IfPlayerMoving(p) == false); 269 270 eval.moving_direction = ExitState::Dir::SOUTH; 271 CHECK(IfPlayerMoving(p) == true); 272 } 273 274 TEST_SUITE_END(); 275 }