diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 705130aa0..689159932 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -24,7 +24,7 @@ If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - OS: [e.g. mac/linux/windows] - - Version [e.g. 1.3.3] + - Version [e.g. 1.3.4] **Additional context** Add any other context about the problem here. diff --git a/CMakeLists.txt b/CMakeLists.txt index fc50b945f..8f9639320 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.10.0) set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version") -project(Griddly VERSION 1.3.3) +project(Griddly VERSION 1.3.4) set(BINARY ${CMAKE_PROJECT_NAME}) diff --git a/bindings/python.cpp b/bindings/python.cpp index 29e1074ed..705574c74 100644 --- a/bindings/python.cpp +++ b/bindings/python.cpp @@ -12,7 +12,7 @@ namespace griddly { PYBIND11_MODULE(python_griddly, m) { m.doc() = "Griddly python bindings"; - m.attr("version") = "1.3.3"; + m.attr("version") = "1.3.4"; #ifndef NDEBUG spdlog::set_level(spdlog::level::debug); diff --git a/docs/conf.py b/docs/conf.py index 05db46109..e828b2464 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -22,7 +22,7 @@ author = 'Chris Bamford' # The full version, including alpha/beta/rc tags -release = '1.3.3' +release = '1.3.4' # -- General configuration --------------------------------------------------- diff --git a/js/jiddly-app/package.json b/js/jiddly-app/package.json index af90a9256..14ebd7875 100644 --- a/js/jiddly-app/package.json +++ b/js/jiddly-app/package.json @@ -1,6 +1,6 @@ { "name": "jiddly-app", - "version": "1.3.3", + "version": "1.3.4", "private": true, "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.1.1", diff --git a/python/examples/Level Design/custom_level_global.png b/python/examples/Level Design/custom_level_global.png index c5a2f291e..447c24a5f 100644 Binary files a/python/examples/Level Design/custom_level_global.png and b/python/examples/Level Design/custom_level_global.png differ diff --git a/python/examples/Level Design/custom_level_string_player_1.png b/python/examples/Level Design/custom_level_string_player_1.png index c5a2f291e..447c24a5f 100644 Binary files a/python/examples/Level Design/custom_level_string_player_1.png and b/python/examples/Level Design/custom_level_string_player_1.png differ diff --git a/python/examples/Level Design/custom_level_string_player_2.png b/python/examples/Level Design/custom_level_string_player_2.png index c5a2f291e..447c24a5f 100644 Binary files a/python/examples/Level Design/custom_level_string_player_2.png and b/python/examples/Level Design/custom_level_string_player_2.png differ diff --git a/python/examples/Level Design/level_0_global.png b/python/examples/Level Design/level_0_global.png index 5713ecbe2..d17eff50a 100644 Binary files a/python/examples/Level Design/level_0_global.png and b/python/examples/Level Design/level_0_global.png differ diff --git a/python/examples/Level Design/level_1_global.png b/python/examples/Level Design/level_1_global.png index d38d2b64e..dd7033029 100644 Binary files a/python/examples/Level Design/level_1_global.png and b/python/examples/Level Design/level_1_global.png differ diff --git a/python/examples/Level Design/level_1_player_1.png b/python/examples/Level Design/level_1_player_1.png index 8b925984f..1e211fe52 100644 Binary files a/python/examples/Level Design/level_1_player_1.png and b/python/examples/Level Design/level_1_player_1.png differ diff --git a/python/examples/Level Design/level_1_player_2.png b/python/examples/Level Design/level_1_player_2.png index 66d1e5341..7741eeddf 100644 Binary files a/python/examples/Level Design/level_1_player_2.png and b/python/examples/Level Design/level_1_player_2.png differ diff --git a/python/examples/Level Design/level_2_global.png b/python/examples/Level Design/level_2_global.png index 271517bb9..a78469f60 100644 Binary files a/python/examples/Level Design/level_2_global.png and b/python/examples/Level Design/level_2_global.png differ diff --git a/python/examples/Level Design/level_2_player_1.png b/python/examples/Level Design/level_2_player_1.png index ff21434ae..cfb8a22d4 100644 Binary files a/python/examples/Level Design/level_2_player_1.png and b/python/examples/Level Design/level_2_player_1.png differ diff --git a/python/examples/Level Design/level_2_player_2.png b/python/examples/Level Design/level_2_player_2.png index dd245d910..80c1b5f8c 100644 Binary files a/python/examples/Level Design/level_2_player_2.png and b/python/examples/Level Design/level_2_player_2.png differ diff --git a/python/setup.py b/python/setup.py index 83eea1cd8..35923d46f 100644 --- a/python/setup.py +++ b/python/setup.py @@ -71,7 +71,7 @@ def griddly_package_data(config='Debug'): setup( name='griddly', - version="1.3.3", + version="1.3.4", author_email="chrisbam4d@gmail.com", description="Griddly Python Libraries", long_description=long_description, diff --git a/src/Griddly/Core/GDY/Actions/Action.cpp b/src/Griddly/Core/GDY/Actions/Action.cpp index 005767408..289c9d354 100644 --- a/src/Griddly/Core/GDY/Actions/Action.cpp +++ b/src/Griddly/Core/GDY/Actions/Action.cpp @@ -68,7 +68,7 @@ std::shared_ptr Action::getSourceObject() const { spdlog::debug("getting default object"); - return grid()->getPlayerDefaultObject(playerId_); + return grid()->getPlayerDefaultEmptyObject(playerId_); } } @@ -76,21 +76,29 @@ std::shared_ptr Action::getDestinationObject() const { switch (actionMode_) { case ActionMode::SRC_LOC_DST_LOC: case ActionMode::SRC_OBJ_DST_LOC: { + if (destinationLocation_.x >= grid()->getWidth() || destinationLocation_.x < 0 || + destinationLocation_.y >= grid()->getHeight() || destinationLocation_.y < 0) { + return grid()->getPlayerDefaultBoundaryObject(playerId_); + } auto dstObject = grid()->getObject(destinationLocation_); if (dstObject != nullptr) { return dstObject; } - return grid()->getPlayerDefaultObject(playerId_); + return grid()->getPlayerDefaultEmptyObject(playerId_); } case ActionMode::SRC_OBJ_DST_OBJ: return destinationObject_; case ActionMode::SRC_OBJ_DST_VEC: { auto destinationLocation = (getSourceLocation() + vectorToDest_); + if (destinationLocation.x >= grid()->getWidth() || destinationLocation.x < 0 || + destinationLocation.y >= grid()->getHeight() || destinationLocation.y < 0) { + return grid()->getPlayerDefaultBoundaryObject(playerId_); + } auto dstObject = grid()->getObject(destinationLocation); if (dstObject != nullptr) { return dstObject; } - return grid()->getPlayerDefaultObject(playerId_); + return grid()->getPlayerDefaultEmptyObject(playerId_); } } diff --git a/src/Griddly/Core/GDY/Objects/Object.cpp b/src/Griddly/Core/GDY/Objects/Object.cpp index 42bc95011..003e3d75b 100644 --- a/src/Griddly/Core/GDY/Objects/Object.cpp +++ b/src/Griddly/Core/GDY/Objects/Object.cpp @@ -99,6 +99,7 @@ BehaviourResult Object::onActionDst(std::shared_ptr action, std::vector< auto &behavioursForAction = behavioursForActionIt->second; auto behavioursForActionAndDestinationObject = behavioursForAction.find(sourceObjectName); + if (behavioursForActionAndDestinationObject == behavioursForAction.end()) { spdlog::debug("Aborting dst behaviour, (no behaviours for action)", action->getDescription()); return {true}; @@ -708,6 +709,7 @@ std::vector Object::getValidBehaviourIdxs(std::shared_ptr acti auto width = grid()->getWidth(); auto height = grid()->getHeight(); + // Check that the destination of the action is not outside the grid auto destinationLocation = action->getDestinationLocation(); if (destinationLocation.x >= width || destinationLocation.x < 0 || diff --git a/src/Griddly/Core/Grid.cpp b/src/Griddly/Core/Grid.cpp index e881d6ec2..433270d6c 100644 --- a/src/Griddly/Core/Grid.cpp +++ b/src/Griddly/Core/Grid.cpp @@ -68,7 +68,8 @@ void Grid::reset() { objectIds_.clear(); objectVariableIds_.clear(); delayedActions_ = {}; - defaultObject_.clear(); + defaultEmptyObject_.clear(); + defaultBoundaryObject_.clear(); collisionObjectActionNames_.clear(); collisionSourceObjectActionNames_.clear(); @@ -218,15 +219,7 @@ std::unordered_map Grid::executeAction(uint32_t playerId, std auto destinationObject = action->getDestinationObject(); // Need to get this name before anything happens to the object for example if the object is removed in onActionDst. - auto originalDestinationObjectName = destinationObject->getObjectName(); - if (originalDestinationObjectName == "_empty") { - // Check that the destination of the action is not outside the grid - auto destinationLocation = action->getDestinationLocation(); - if (destinationLocation.x >= width_ || destinationLocation.x < 0 || - destinationLocation.y >= height_ || destinationLocation.y < 0) { - originalDestinationObjectName = "_boundary"; - } - } + auto destinationObjectName = destinationObject->getObjectName(); if (sourceObject == nullptr) { spdlog::debug("Cannot perform action on empty space. ({0},{1})", action->getSourceLocation()[0], action->getSourceLocation()[1]); @@ -259,7 +252,7 @@ std::unordered_map Grid::executeAction(uint32_t playerId, std return rewardAccumulator; } - auto srcBehaviourResult = sourceObject->onActionSrc(originalDestinationObjectName, action, validBehaviourIdxs); + auto srcBehaviourResult = sourceObject->onActionSrc(destinationObjectName, action, validBehaviourIdxs); accumulateRewards(rewardAccumulator, srcBehaviourResult.rewards); return rewardAccumulator; } @@ -276,14 +269,6 @@ GridEvent Grid::buildGridEvent(const std::shared_ptr& action, uint32_t p event.actionName = action->getActionName(); event.sourceObjectName = sourceObject->getObjectName(); event.destObjectName = destObject->getObjectName(); - if (event.destObjectName == "_empty") { - // Check that the destination of the action is not outside the grid - auto destinationLocation = action->getDestinationLocation(); - if (destinationLocation.x >= width_ || destinationLocation.x < 0 || - destinationLocation.y >= height_ || destinationLocation.y < 0) { - event.destObjectName = "_boundary"; - } - } if (sourceObject->getObjectName() != "_empty") { event.sourceObjectPlayerId = sourceObject->getPlayerId(); @@ -553,17 +538,24 @@ void Grid::addActionTrigger(std::string actionName, ActionTriggerDefinition acti addCollisionDetector(objectNames, actionName, collisionDetector); } -void Grid::addPlayerDefaultObject(std::shared_ptr object) { - spdlog::debug("Adding default object for player {0}", object->getPlayerId()); +void Grid::addPlayerDefaultObjects(std::shared_ptr emptyObject, std::shared_ptr boundaryObject) { + spdlog::debug("Adding default objects for player {0}", emptyObject->getPlayerId()); + + emptyObject->init({-1, -1}); + boundaryObject->init({-1,-1}); - object->init({-1, -1}); + defaultEmptyObject_[emptyObject->getPlayerId()] = emptyObject; + defaultBoundaryObject_[boundaryObject->getPlayerId()] = boundaryObject; +} - defaultObject_[object->getPlayerId()] = object; +std::shared_ptr Grid::getPlayerDefaultEmptyObject(uint32_t playerId) const { + spdlog::debug("Getting default empty object for player {0}", playerId); + return defaultEmptyObject_.at(playerId); } -std::shared_ptr Grid::getPlayerDefaultObject(uint32_t playerId) const { - spdlog::debug("Getting default object for player {0}", playerId); - return defaultObject_.at(playerId); +std::shared_ptr Grid::getPlayerDefaultBoundaryObject(uint32_t playerId) const { + spdlog::debug("Getting default boundary object for player {0}", playerId); + return defaultBoundaryObject_.at(playerId); } void Grid::addObject(glm::ivec2 location, std::shared_ptr object, bool applyInitialActions, std::shared_ptr originatingAction, DiscreteOrientation orientation) { diff --git a/src/Griddly/Core/Grid.hpp b/src/Griddly/Core/Grid.hpp index a68d57e4a..e9715e3a0 100644 --- a/src/Griddly/Core/Grid.hpp +++ b/src/Griddly/Core/Grid.hpp @@ -107,8 +107,11 @@ class Grid : public std::enable_shared_from_this { virtual const std::unordered_set>& getObjects(); - virtual void addPlayerDefaultObject(std::shared_ptr object); - virtual std::shared_ptr getPlayerDefaultObject(uint32_t playerId) const; + virtual void addPlayerDefaultObjects(std::shared_ptr emptyObject, std::shared_ptr boundaryObject); + + virtual std::shared_ptr getPlayerDefaultEmptyObject(uint32_t playerId) const; + + virtual std::shared_ptr getPlayerDefaultBoundaryObject(uint32_t playerId) const; /** * Gets all the objects at a certain location @@ -232,7 +235,11 @@ class Grid : public std::enable_shared_from_this { // An object that is used if the source of destination location of an action is '_empty' // Allows a subset of actions like "spawn" to be performed in empty space. - std::unordered_map> defaultObject_; + std::unordered_map> defaultEmptyObject_; + + // An object that is used if the source of destination location of an action is '_boundary' + // This is used for special actions where objects go out of bounds for the level + std::unordered_map> defaultBoundaryObject_; std::shared_ptr randomGenerator_ = std::make_shared(RandomGenerator()); diff --git a/src/Griddly/Core/LevelGenerators/MapGenerator.cpp b/src/Griddly/Core/LevelGenerators/MapGenerator.cpp index 88f78231e..12e8173e1 100644 --- a/src/Griddly/Core/LevelGenerators/MapGenerator.cpp +++ b/src/Griddly/Core/LevelGenerators/MapGenerator.cpp @@ -35,8 +35,9 @@ void MapGenerator::reset(std::shared_ptr grid) { } for (auto playerId = 0; playerId < playerCount_ + 1; playerId++) { - auto defaultObject = objectGenerator_->newInstance("_empty", playerId, grid); - grid->addPlayerDefaultObject(defaultObject); + auto defaultEmptyObject = objectGenerator_->newInstance("_empty", playerId, grid); + auto defaultBoundaryObject = objectGenerator_->newInstance("_boundary", playerId, grid); + grid->addPlayerDefaultObjects(defaultEmptyObject, defaultBoundaryObject); } for (auto& actionTriggerDefinitionIt : objectGenerator_->getActionTriggerDefinitions()) { diff --git a/src/Griddly/Core/TurnBasedGameProcess.cpp b/src/Griddly/Core/TurnBasedGameProcess.cpp index dcc6df44b..c8f39f25a 100644 --- a/src/Griddly/Core/TurnBasedGameProcess.cpp +++ b/src/Griddly/Core/TurnBasedGameProcess.cpp @@ -125,12 +125,15 @@ std::shared_ptr TurnBasedGameProcess::clone() { // Adding player default objects for (auto playerId = 0; playerId < players_.size() + 1; playerId++) { - auto defaultObject = objectGenerator->newInstance("_empty", playerId, clonedGrid); - clonedGrid->addPlayerDefaultObject(defaultObject); + auto defaultEmptyObject = objectGenerator->newInstance("_empty", playerId, clonedGrid); + auto defaultBoundaryObject = objectGenerator->newInstance("_boundary", playerId, clonedGrid); + clonedGrid->addPlayerDefaultObjects(defaultEmptyObject, defaultBoundaryObject); - auto defaultObjectToCopy = grid_->getPlayerDefaultObject(playerId); + auto defaultEmptyObjectToCopy = grid_->getPlayerDefaultEmptyObject(playerId); + auto defaultBoundaryObjectToCopy = grid_->getPlayerDefaultBoundaryObject(playerId); - clonedObjectMapping[defaultObjectToCopy] = defaultObject; + clonedObjectMapping[defaultEmptyObjectToCopy] = defaultEmptyObject; + clonedObjectMapping[defaultBoundaryObjectToCopy] = defaultBoundaryObject; } // Behaviour probabilities diff --git a/tests/src/Griddly/Core/GDY/GDYFactoryTest.cpp b/tests/src/Griddly/Core/GDY/GDYFactoryTest.cpp index f1d5350b1..8d6a93f65 100644 --- a/tests/src/Griddly/Core/GDY/GDYFactoryTest.cpp +++ b/tests/src/Griddly/Core/GDY/GDYFactoryTest.cpp @@ -1118,7 +1118,8 @@ TEST(GDYFactoryTest, wallTest) { auto mockWall2Object = std::make_shared(); auto mockWall16Object = std::make_shared(); - auto mockDefaultObject = std::make_shared(); + auto mockDefaultEmptyObject = std::make_shared(); + auto mockDefaultBoundaryObject = std::make_shared(); std::string wall2String = "Wall2"; std::string wall16String = "Wall16"; @@ -1141,10 +1142,16 @@ TEST(GDYFactoryTest, wallTest) { .WillRepeatedly(ReturnRef(wall16String)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(1), Eq(grid))) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(0), Eq(grid))) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(1), Eq(grid))) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(0), Eq(grid))) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq(wall2String), Eq(0), Eq(grid))) .WillRepeatedly(Return(mockWall2Object)); @@ -1171,7 +1178,8 @@ TEST(GDYFactoryTest, zIndexTest) { auto mockFloorObject = std::make_shared(); auto mockGhostObject = std::make_shared(); - auto mockDefaultObject = std::make_shared(); + auto mockDefaultEmptyObject = std::make_shared(); + auto mockDefaultBoundaryObject = std::make_shared(); std::string wall = "Wall2"; std::string floor = "floor"; @@ -1201,10 +1209,16 @@ TEST(GDYFactoryTest, zIndexTest) { .WillRepeatedly(ReturnRef(floor)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(1), Eq(grid))) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(0), Eq(grid))) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(1), Eq(grid))) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(0), Eq(grid))) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq(wall), Eq(0), Eq(grid))) .WillRepeatedly(Return(mockWallObject)); diff --git a/tests/src/Griddly/Core/GameProcessTest.cpp b/tests/src/Griddly/Core/GameProcessTest.cpp index f89c80944..ac4f6c946 100644 --- a/tests/src/Griddly/Core/GameProcessTest.cpp +++ b/tests/src/Griddly/Core/GameProcessTest.cpp @@ -861,7 +861,8 @@ TEST(GameProcessTest, clone) { auto clonedMockObject2 = mockObject("object2", 'b', 1, 0, {4, 6}, DiscreteOrientation(), {}, {{"global_var", globalVar}, {"test_param2", _V(5)}}); auto clonedMockObject3 = mockObject("object3", 'c', 1, 0, {20, 13}, DiscreteOrientation(), {}, {{"global_var", globalVar}, {"test_param3", _V(12)}}); - auto mockPlayerDefaultObject = mockObject("_empty", ' ', 1, 0, {-1, -1}, DiscreteOrientation(), {}, {}); + auto mockPlayerDefaultEmptyObject = mockObject("_empty", ' ', 1, 0, {-1, -1}, DiscreteOrientation(), {}, {}); + auto mockPlayerDefaultBoundaryObject = mockObject("_boundary", ' ', 1, 0, {-1, -1}, DiscreteOrientation(), {}, {}); auto objects = std::unordered_set>{mockObject1, mockObject2, mockObject3}; @@ -891,7 +892,8 @@ TEST(GameProcessTest, clone) { EXPECT_CALL(*mockObjectGeneratorPtr, cloneInstance(Eq(mockObject1), _)).WillRepeatedly(Return(clonedMockObject1)); EXPECT_CALL(*mockObjectGeneratorPtr, cloneInstance(Eq(mockObject2), _)).WillRepeatedly(Return(clonedMockObject2)); EXPECT_CALL(*mockObjectGeneratorPtr, cloneInstance(Eq(mockObject3), _)).WillRepeatedly(Return(clonedMockObject3)); - EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), _, _)).WillRepeatedly(Return(mockPlayerDefaultObject)); + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), _, _)).WillRepeatedly(Return(mockPlayerDefaultEmptyObject)); + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), _, _)).WillRepeatedly(Return(mockPlayerDefaultBoundaryObject)); EXPECT_CALL(*mockGDYFactoryPtr, getObjectGenerator()).WillRepeatedly(Return(mockObjectGeneratorPtr)); diff --git a/tests/src/Griddly/Core/GridTest.cpp b/tests/src/Griddly/Core/GridTest.cpp index 09bcb360a..45982303c 100644 --- a/tests/src/Griddly/Core/GridTest.cpp +++ b/tests/src/Griddly/Core/GridTest.cpp @@ -419,7 +419,7 @@ TEST(GridTest, performActionDestinationObjectOutsideGrid) { grid->setBehaviourProbabilities(behaviourProbabilities); - auto mockActionPtr = mockAction("action", mockSourceObjectPtr, actionDestinationLocation); + auto mockActionPtr = mockAction("action", mockSourceObjectPtr, actionDestinationLocation, true); EXPECT_CALL(*mockSourceObjectPtr, onActionSrc(Eq("_boundary"), Eq(mockActionPtr), UnorderedElementsAre(0))) .Times(1) diff --git a/tests/src/Griddly/Core/LevelGenerator/MapReaderTest.cpp b/tests/src/Griddly/Core/LevelGenerator/MapReaderTest.cpp index 994c92f53..5dcf4cd60 100644 --- a/tests/src/Griddly/Core/LevelGenerator/MapReaderTest.cpp +++ b/tests/src/Griddly/Core/LevelGenerator/MapReaderTest.cpp @@ -34,7 +34,8 @@ TEST(MapGeneratorTest, testLoadStringWithPlayerObjects) { auto mockGridPtr = std::make_shared(); auto mockWallObject = std::make_shared(); auto mockAvatarObject = std::make_shared(); - auto mockDefaultObject = std::make_shared(); + auto mockDefaultEmptyObject = std::make_shared(); + auto mockDefaultBoundaryObject = std::make_shared(); std::shared_ptr mapReader(new MapGenerator(1, mockObjectGeneratorPtr)); std::string wallObjectName = "wall"; @@ -65,11 +66,19 @@ TEST(MapGeneratorTest, testLoadStringWithPlayerObjects) { EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(0), Eq(mockGridPtr))) .Times(1) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(1), Eq(mockGridPtr))) .Times(1) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(0), Eq(mockGridPtr))) + .Times(1) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(1), Eq(mockGridPtr))) + .Times(1) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq(wallObjectName), Eq(0), Eq(mockGridPtr))) .Times(8) @@ -103,7 +112,8 @@ TEST(MapGeneratorTest, testLoadStringWithPlayerObjectsRandomWhitespace) { auto mockGridPtr = std::make_shared(); auto mockWallObject = std::make_shared(); auto mockAvatarObject = std::make_shared(); - auto mockDefaultObject = std::make_shared(); + auto mockDefaultEmptyObject = std::make_shared(); + auto mockDefaultBoundaryObject = std::make_shared(); std::shared_ptr mapReader(new MapGenerator(1, mockObjectGeneratorPtr)); std::string wallObjectName = "wall"; @@ -134,11 +144,19 @@ TEST(MapGeneratorTest, testLoadStringWithPlayerObjectsRandomWhitespace) { EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(0), Eq(mockGridPtr))) .Times(1) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(1), Eq(mockGridPtr))) .Times(1) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(0), Eq(mockGridPtr))) + .Times(1) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(1), Eq(mockGridPtr))) + .Times(1) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq(wallObjectName), Eq(0), Eq(mockGridPtr))) .Times(8) @@ -172,7 +190,8 @@ TEST(MapGeneratorTest, testLoadStringNoSpaces) { auto mockGridPtr = std::make_shared(); auto mockWallObject = std::make_shared(); auto mockAvatarObject = std::make_shared(); - auto mockDefaultObject = std::make_shared(); + auto mockDefaultEmptyObject = std::make_shared(); + auto mockDefaultBoundaryObject = std::make_shared(); std::shared_ptr mapReader(new MapGenerator(1, mockObjectGeneratorPtr)); std::string wallObjectName = "wall"; @@ -203,11 +222,19 @@ TEST(MapGeneratorTest, testLoadStringNoSpaces) { EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(0), Eq(mockGridPtr))) .Times(1) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(1), Eq(mockGridPtr))) .Times(1) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(0), Eq(mockGridPtr))) + .Times(1) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(1), Eq(mockGridPtr))) + .Times(1) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq(wallObjectName), Eq(0), Eq(mockGridPtr))) .Times(8) @@ -240,7 +267,8 @@ TEST(MapGeneratorTest, testLoadStringNoSpacesWithDots) { auto mockGridPtr = std::make_shared(); auto mockWallObject = std::make_shared(); auto mockAvatarObject = std::make_shared(); - auto mockDefaultObject = std::make_shared(); + auto mockDefaultEmptyObject = std::make_shared(); + auto mockDefaultBoundaryObject = std::make_shared(); std::shared_ptr mapReader(new MapGenerator(1, mockObjectGeneratorPtr)); std::string wallObjectName = "wall"; @@ -271,11 +299,19 @@ TEST(MapGeneratorTest, testLoadStringNoSpacesWithDots) { EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(0), Eq(mockGridPtr))) .Times(1) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(1), Eq(mockGridPtr))) .Times(1) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(0), Eq(mockGridPtr))) + .Times(1) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(1), Eq(mockGridPtr))) + .Times(1) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq(wallObjectName), Eq(0), Eq(mockGridPtr))) .Times(12) @@ -308,7 +344,8 @@ TEST(MapGeneratorTest, testLoadStringMultipleOccupants) { auto mockGridPtr = std::make_shared(); auto mockWallObject = std::make_shared(); auto mockAvatarObject = std::make_shared(); - auto mockDefaultObject = std::make_shared(); + auto mockDefaultEmptyObject = std::make_shared(); + auto mockDefaultBoundaryObject = std::make_shared(); auto mockFloorObject = std::make_shared(); std::shared_ptr mapReader(new MapGenerator(1, mockObjectGeneratorPtr)); @@ -351,11 +388,19 @@ TEST(MapGeneratorTest, testLoadStringMultipleOccupants) { EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(0), Eq(mockGridPtr))) .Times(1) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(1), Eq(mockGridPtr))) .Times(1) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(0), Eq(mockGridPtr))) + .Times(1) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(1), Eq(mockGridPtr))) + .Times(1) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq(wallObjectName), Eq(0), Eq(mockGridPtr))) .Times(12) @@ -396,7 +441,8 @@ TEST(MapGeneratorTest, testLoadStringInitialOrientation) { auto mockGridPtr = std::make_shared(); auto mockWallObject = std::make_shared(); auto mockAvatarObject = std::make_shared(); - auto mockDefaultObject = std::make_shared(); + auto mockDefaultEmptyObject = std::make_shared(); + auto mockDefaultBoundaryObject = std::make_shared(); std::shared_ptr mapReader(new MapGenerator(1, mockObjectGeneratorPtr)); @@ -428,11 +474,19 @@ TEST(MapGeneratorTest, testLoadStringInitialOrientation) { EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(0), Eq(mockGridPtr))) .Times(1) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_empty"), Eq(1), Eq(mockGridPtr))) .Times(1) - .WillRepeatedly(Return(mockDefaultObject)); + .WillRepeatedly(Return(mockDefaultEmptyObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(0), Eq(mockGridPtr))) + .Times(1) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); + + EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq("_boundary"), Eq(1), Eq(mockGridPtr))) + .Times(1) + .WillRepeatedly(Return(mockDefaultBoundaryObject)); EXPECT_CALL(*mockObjectGeneratorPtr, newInstance(Eq(wallObjectName), Eq(0), Eq(mockGridPtr))) .Times(12) diff --git a/tests/src/Griddly/Core/TestUtils/common.hpp b/tests/src/Griddly/Core/TestUtils/common.hpp index cef34d460..6edb1806a 100644 --- a/tests/src/Griddly/Core/TestUtils/common.hpp +++ b/tests/src/Griddly/Core/TestUtils/common.hpp @@ -71,10 +71,10 @@ std::shared_ptr static mockAction(std::string actionName, glm::ivec2 return mockActionPtr; } -std::shared_ptr static mockAction(std::string actionName, std::shared_ptr sourceObject, glm::ivec2 destLocation) { +std::shared_ptr static mockAction(std::string actionName, std::shared_ptr sourceObject, glm::ivec2 destLocation, bool isBoundary=false) { auto mockActionPtr = std::make_shared(); - const std::string empty = "_empty"; + const std::string empty = isBoundary ? "_boundary": "_empty"; auto mockDefaultObject = std::make_shared(); EXPECT_CALL(*mockDefaultObject, getObjectName()).WillRepeatedly(ReturnRefOfCopy(empty)); diff --git a/tests/src/Mocks/Griddly/Core/MockGrid.hpp b/tests/src/Mocks/Griddly/Core/MockGrid.hpp index e17321269..b8d13c61e 100644 --- a/tests/src/Mocks/Griddly/Core/MockGrid.hpp +++ b/tests/src/Mocks/Griddly/Core/MockGrid.hpp @@ -26,8 +26,9 @@ class MockGrid : public Grid { MOCK_METHOD(void, initObject, (std::string, std::vector), ()); MOCK_METHOD(void, addObject, (glm::ivec2 location, std::shared_ptr object, bool applyInitialActions, std::shared_ptr originatingAction, DiscreteOrientation orientation), ()); - MOCK_METHOD(void, addPlayerDefaultObject, (std::shared_ptr object)); - MOCK_METHOD(std::shared_ptr, getPlayerDefaultObject, (uint32_t playerId), (const)); + MOCK_METHOD(void, addPlayerDefaultObjects, (std::shared_ptr emptyObject, std::shared_ptr boundaryObject)); + MOCK_METHOD(std::shared_ptr, getPlayerDefaultEmptyObject, (uint32_t playerId), (const)); + MOCK_METHOD(std::shared_ptr, getPlayerDefaultBoundaryObject, (uint32_t playerId), (const)); MOCK_METHOD(bool, removeObject, (std::shared_ptr object), ()); MOCK_METHOD((std::unordered_map>), getObjectCounter, (std::string), ());