├── .clang-format ├── .gitignore ├── .gitmodules ├── .travis.yml ├── CMake └── CompileOptions.cmake ├── CMakeLists.txt ├── CMakeSettings.json ├── Includes ├── BaseUnit.h ├── BasicResource.h ├── GameSettings.h ├── HexMap.h ├── HexTile.h ├── Setter.h ├── Terrain.h ├── UnitFactory.h └── Worker.h ├── LICENSE ├── Logo.png ├── README.md ├── Scripts ├── Dockerfile.bionic ├── azure_pipelines_build.yml ├── azure_pipelines_build_windows.yml ├── travis_build.sh └── travis_build_docker.sh ├── Sources ├── BaseUnit.cpp ├── BasicResource.cpp ├── CMakeLists.txt ├── GameSettings.cpp ├── HexMap.cpp ├── HexTile.cpp ├── Setter.cpp ├── Terrain.cpp ├── UnitFactory.cpp └── Worker.cpp ├── Tests └── UnitTests │ ├── BaseUnitTests.cpp │ ├── CMakeLists.txt │ ├── HexMapTests.cpp │ ├── UnitFactoryTests.cpp │ ├── UnitTests.cpp │ └── WorkerTests.cpp ├── appveyor.yml └── azure-pipelines.yml /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: Google 4 | AccessModifierOffset: -3 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlinesLeft: true 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: false 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: false 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: true 20 | AlwaysBreakTemplateDeclarations: true 21 | BinPackArguments: true 22 | BinPackParameters: true 23 | BreakBeforeBraces: Custom 24 | BraceWrapping: 25 | AfterClass: true 26 | AfterControlStatement: true 27 | AfterEnum: true 28 | AfterFunction: true 29 | AfterNamespace: true 30 | AfterObjCDeclaration: true 31 | AfterStruct: true 32 | AfterUnion: true 33 | BeforeCatch: true 34 | BeforeElse: true 35 | IndentBraces: false 36 | BreakBeforeBinaryOperators: None 37 | BreakBeforeTernaryOperators: true 38 | BreakConstructorInitializersBeforeComma: false 39 | BreakAfterJavaFieldAnnotations: false 40 | BreakStringLiterals: true 41 | ColumnLimit: 80 42 | CommentPragmas: '^ IWYU pragma:' 43 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 44 | ConstructorInitializerIndentWidth: 4 45 | ContinuationIndentWidth: 4 46 | Cpp11BracedListStyle: false 47 | DerivePointerAlignment: true 48 | DisableFormat: false 49 | ExperimentalAutoDetectBinPacking: false 50 | ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] 51 | IncludeCategories: 52 | - Regex: '^<.*\.h>' 53 | Priority: 1 54 | - Regex: '^<.*' 55 | Priority: 2 56 | - Regex: '.*' 57 | Priority: 3 58 | IncludeIsMainRegex: '([-_](test|unittest))?$' 59 | IndentCaseLabels: true 60 | IndentWidth: 4 61 | IndentWrappedFunctionNames: false 62 | JavaScriptQuotes: Leave 63 | JavaScriptWrapImports: true 64 | KeepEmptyLinesAtTheStartOfBlocks: false 65 | MacroBlockBegin: '' 66 | MacroBlockEnd: '' 67 | MaxEmptyLinesToKeep: 1 68 | NamespaceIndentation: None 69 | ObjCBlockIndentWidth: 2 70 | ObjCSpaceAfterProperty: false 71 | ObjCSpaceBeforeProtocolList: false 72 | PenaltyBreakBeforeFirstCallParameter: 1 73 | PenaltyBreakComment: 300 74 | PenaltyBreakFirstLessLess: 120 75 | PenaltyBreakString: 1000 76 | PenaltyExcessCharacter: 1000000 77 | PenaltyReturnTypeOnItsOwnLine: 200 78 | PointerAlignment: Left 79 | ReflowComments: true 80 | SortIncludes: true 81 | SpaceAfterCStyleCast: false 82 | SpaceBeforeAssignmentOperators: true 83 | SpaceBeforeParens: ControlStatements 84 | SpaceInEmptyParentheses: false 85 | SpacesBeforeTrailingComments: 2 86 | SpacesInAngles: false 87 | SpacesInContainerLiterals: true 88 | SpacesInCStyleCastParentheses: false 89 | SpacesInParentheses: false 90 | SpacesInSquareBrackets: false 91 | Standard: Auto 92 | TabWidth: 4 93 | UseTab: Never -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # CMake temp/cache files 2 | CMakeCache.txt 3 | CMakeFiles 4 | CMakeScripts 5 | Testing 6 | Makefile 7 | cmake_install.cmake 8 | install_manifest.txt 9 | compile_commands.json 10 | CTestTestfile.cmake 11 | build 12 | 13 | # Visual Studio files 14 | /.vs 15 | 16 | # Visual Studio Code files 17 | /.vscode 18 | *.code-workspace 19 | 20 | # OSX files 21 | .DS_Store 22 | 23 | # CLion files 24 | /.idea 25 | cmake-build-debug 26 | 27 | # vi files 28 | .clang_complete 29 | .syntastic_cpp_config 30 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Libraries/googletest"] 2 | path = Libraries/googletest 3 | url = https://github.com/abseil/googletest.git 4 | [submodule "Libraries/googlebenchmark"] 5 | path = Libraries/googlebenchmark 6 | url = https://github.com/google/benchmark.git 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | matrix: 4 | include: 5 | # Test Docker based on Ubuntu 18.04 LTS + gcc 6 | - os: linux 7 | dist: trusty 8 | sudo: required 9 | services: docker 10 | script: 11 | - sh Scripts/travis_build_docker.sh Scripts/Dockerfile.bionic bionic 12 | # Test OS X 10.12 + Xcode 9 + clang 13 | - os: osx 14 | osx_image: xcode9 15 | compiler: clang 16 | script: 17 | - sh Scripts/travis_build.sh 18 | -------------------------------------------------------------------------------- /CMake/CompileOptions.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Platform and architecture setup 3 | # 4 | 5 | # Set warnings as errors flag 6 | option(CUBBYFLOW_WARNINGS_AS_ERRORS "Treat all warnings as errors" ON) 7 | if(CUBBYFLOW_WARNINGS_AS_ERRORS) 8 | if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") 9 | set(WARN_AS_ERROR_FLAGS "/WX") 10 | else() 11 | set(WARN_AS_ERROR_FLAGS "-Werror") 12 | endif() 13 | endif() 14 | 15 | # Get upper case system name 16 | string(TOUPPER ${CMAKE_SYSTEM_NAME} SYSTEM_NAME_UPPER) 17 | 18 | # Determine architecture (32/64 bit) 19 | set(X64 OFF) 20 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 21 | set(X64 ON) 22 | endif() 23 | 24 | # 25 | # Project options 26 | # 27 | 28 | set(DEFAULT_PROJECT_OPTIONS 29 | CXX_STANDARD 17 # Not available before CMake 3.8.2; see below for manual command line argument addition 30 | LINKER_LANGUAGE "CXX" 31 | POSITION_INDEPENDENT_CODE ON 32 | ) 33 | 34 | # 35 | # Include directories 36 | # 37 | 38 | set(DEFAULT_INCLUDE_DIRECTORIES) 39 | 40 | # 41 | # Libraries 42 | # 43 | 44 | set(DEFAULT_LIBRARIES) 45 | 46 | # 47 | # Compile definitions 48 | # 49 | 50 | set(DEFAULT_COMPILE_DEFINITIONS 51 | SYSTEM_${SYSTEM_NAME_UPPER} 52 | ) 53 | 54 | # MSVC compiler options 55 | if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") 56 | set(DEFAULT_COMPILE_DEFINITIONS ${DEFAULT_COMPILE_DEFINITIONS} 57 | _SCL_SECURE_NO_WARNINGS # Calling any one of the potentially unsafe methods in the Standard C++ Library 58 | _CRT_SECURE_NO_WARNINGS # Calling any one of the potentially unsafe methods in the CRT Library 59 | ) 60 | endif () 61 | 62 | # 63 | # Compile options 64 | # 65 | 66 | set(DEFAULT_COMPILE_OPTIONS) 67 | 68 | # MSVC compiler options 69 | if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") 70 | # remove default warning level from CMAKE_CXX_FLAGS 71 | string (REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") 72 | endif() 73 | 74 | # MSVC compiler options 75 | if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") 76 | set(DEFAULT_COMPILE_OPTIONS ${DEFAULT_COMPILE_OPTIONS} 77 | /MP # -> build with multiple processes 78 | /W4 # -> warning level 4 79 | ${WARN_AS_ERROR_FLAGS} 80 | 81 | # /wd4251 # -> disable warning: 'identifier': class 'type' needs to have dll-interface to be used by clients of class 'type2' 82 | # /wd4592 # -> disable warning: 'identifier': symbol will be dynamically initialized (implementation limitation) 83 | # /wd4201 # -> disable warning: nonstandard extension used: nameless struct/union (caused by GLM) 84 | # /wd4127 # -> disable warning: conditional expression is constant (caused by Qt) 85 | 86 | #$<$: 87 | #/RTCc # -> value is assigned to a smaller data type and results in a data loss 88 | #> 89 | 90 | $<$: 91 | /Gw # -> whole program global optimization 92 | /GS- # -> buffer security check: no 93 | /GL # -> whole program optimization: enable link-time code generation (disables Zi) 94 | /GF # -> enable string pooling 95 | > 96 | 97 | # No manual c++11 enable for MSVC as all supported MSVC versions for cmake-init have C++11 implicitly enabled (MSVC >=2013) 98 | ) 99 | endif () 100 | 101 | # GCC and Clang compiler options 102 | if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 103 | set(DEFAULT_COMPILE_OPTIONS ${DEFAULT_COMPILE_OPTIONS} 104 | -Wall 105 | -Wno-missing-braces 106 | 107 | ${WARN_AS_ERROR_FLAGS} 108 | -std=c++1z 109 | ) 110 | endif () 111 | 112 | # 113 | # Linker options 114 | # 115 | 116 | set(DEFAULT_LINKER_OPTIONS) 117 | 118 | # Use pthreads on mingw and linux 119 | if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_SYSTEM_NAME MATCHES "Linux") 120 | set(DEFAULT_LINKER_OPTIONS 121 | -pthread 122 | -lstdc++fs 123 | ) 124 | endif() 125 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake version 2 | cmake_minimum_required(VERSION 3.8.2 FATAL_ERROR) 3 | 4 | # Include cmake modules 5 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Builds/CMake") 6 | 7 | # Declare project 8 | project(Civilizationpp) 9 | 10 | # Set output directories 11 | set(DEFAULT_CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) 12 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) 13 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) 14 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) 15 | 16 | # Set enable output of compile commands during generation 17 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 18 | 19 | # Includes 20 | include_directories(Includes) 21 | include_directories(Libraries) 22 | include_directories(Libraries/googletest/googletest/include) 23 | 24 | # Compile options 25 | include(CMake/CompileOptions.cmake) 26 | 27 | # Build type - Release by default 28 | if(NOT CMAKE_BUILD_TYPE) 29 | set(CMAKE_BUILD_TYPE Release) 30 | endif() 31 | 32 | # Overrides 33 | set(CMAKE_MACOSX_RPATH ON) 34 | 35 | # Project modules 36 | set(BUILD_GTEST ON CACHE BOOL "" FORCE) 37 | set(BUILD_GMOCK OFF CACHE BOOL "" FORCE) 38 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 39 | add_subdirectory(Libraries/googletest EXCLUDE_FROM_ALL) 40 | cmake_policy(SET CMP0063 NEW) 41 | set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE) 42 | add_subdirectory(Libraries/googlebenchmark) 43 | set(CMAKE_CXX_VISIBILITY_PRESET hidden) 44 | set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) 45 | add_subdirectory(Sources) 46 | add_subdirectory(Tests/UnitTests) -------------------------------------------------------------------------------- /CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file. 3 | "configurations": [ 4 | { 5 | "name": "x86-Debug", 6 | "generator": "Ninja", 7 | "configurationType": "Debug", 8 | "inheritEnvironments": [ "msvc_x86" ], 9 | "buildRoot": "${workspaceRoot}\\build\\${name}", 10 | "installRoot": "${env.USERPROFILE}", 11 | "cmakeCommandArgs": "", 12 | "buildCommandArgs": "-v", 13 | "ctestCommandArgs": "" 14 | }, 15 | { 16 | "name": "x86-Release", 17 | "generator": "Ninja", 18 | "configurationType": "Release", 19 | "inheritEnvironments": [ "msvc_x86" ], 20 | "buildRoot": "${workspaceRoot}\\build\\${name}", 21 | "installRoot": "${env.USERPROFILE}", 22 | "cmakeCommandArgs": "", 23 | "buildCommandArgs": "-v", 24 | "ctestCommandArgs": "" 25 | }, 26 | { 27 | "name": "x64-Debug", 28 | "generator": "Ninja", 29 | "configurationType": "Debug", 30 | "inheritEnvironments": [ "msvc_x64_x64" ], 31 | "buildRoot": "${workspaceRoot}\\build\\${name}", 32 | "installRoot": "${env.USERPROFILE}", 33 | "cmakeCommandArgs": "", 34 | "buildCommandArgs": "-v", 35 | "ctestCommandArgs": "" 36 | }, 37 | { 38 | "name": "x64-Release", 39 | "generator": "Ninja", 40 | "configurationType": "Release", 41 | "inheritEnvironments": [ "msvc_x64_x64" ], 42 | "buildRoot": "${workspaceRoot}\\build\\${name}", 43 | "installRoot": "${env.USERPROFILE}", 44 | "cmakeCommandArgs": "", 45 | "buildCommandArgs": "-v", 46 | "ctestCommandArgs": "" 47 | } 48 | ] 49 | } -------------------------------------------------------------------------------- /Includes/BaseUnit.h: -------------------------------------------------------------------------------- 1 | #ifndef CIVILIZATIONPP_BASE_UNIT_H 2 | #define CIVILIZATIONPP_BASE_UNIT_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace Civilizationpp 9 | { 10 | class BaseUnit 11 | { 12 | private: 13 | int m_positionX{ 0 }; 14 | int m_positionY{ 0 }; 15 | 16 | public: 17 | BaseUnit(int x, int y); 18 | virtual ~BaseUnit() = default; 19 | 20 | virtual std::pair Move(int x, int y) noexcept; 21 | std::pair GetPosition(); 22 | }; 23 | } // namespace Civilizationpp 24 | 25 | #endif // CIVILIZATIONPP_BASE_UNIT_H -------------------------------------------------------------------------------- /Includes/BasicResource.h: -------------------------------------------------------------------------------- 1 | #ifndef CIVILIZATIONPP_BASIC_RESOURCE_H 2 | #define CIVILIZATIONPP_BASIC_RESOURCE_H 3 | 4 | namespace Civilizationpp 5 | { 6 | class BasicResource 7 | { 8 | public: 9 | BasicResource(); 10 | 11 | int GetFood() const; 12 | int GetProduction() const; 13 | int GetGold() const; 14 | 15 | private: 16 | int m_food; 17 | int m_production; 18 | int m_gold; 19 | }; 20 | } // namespace Civilizationpp 21 | 22 | #endif // CIVILIZATIONPP_BASIC_RESOURCE_H 23 | -------------------------------------------------------------------------------- /Includes/GameSettings.h: -------------------------------------------------------------------------------- 1 | #ifndef CIVILIZATIONPP_GAME_SETTINGS_H 2 | #define CIVILIZATIONPP_GAME_SETTINGS_H 3 | 4 | #include 5 | 6 | namespace Civilizationpp 7 | { 8 | struct GameSettings 9 | { 10 | GameSettings(std::size_t rowCount, std::size_t colCount); 11 | 12 | std::size_t rowCount; 13 | std::size_t colCount; 14 | }; 15 | } // namespace Civilizationpp 16 | 17 | #endif // CIVILIZATIONPP_GAME_SETTINGS_H -------------------------------------------------------------------------------- /Includes/HexMap.h: -------------------------------------------------------------------------------- 1 | #ifndef CIVILIZATIONPP_HEX_MAP_H 2 | #define CIVILIZATIONPP_HEX_MAP_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace Civilizationpp 10 | { 11 | class HexMap 12 | { 13 | public: 14 | HexMap(const HexMap&) = delete; 15 | HexMap& operator=(const HexMap&) = delete; 16 | 17 | static HexMap* GetInstance(); 18 | 19 | void Generate(GameSettings settings); 20 | 21 | const HexTile* GetTile(int r, int q) const; 22 | std::vector GetAdjacencies(int r, int q) const; 23 | 24 | static int GetDistance(int r1, int q1, int r2, int q2); 25 | 26 | private: 27 | HexMap(); 28 | ~HexMap(); 29 | 30 | static HexMap* m_instance; 31 | 32 | // Since map won't be changed after its creation (individual 33 | // tiles may change, but the property of map like size won't 34 | // change) it would be better to use static-sized array, 35 | // rather than using map or unordered_map. (Assumed that map 36 | // is always in shape of rhombus.) 37 | 38 | // (0,0) is at the center of 2-d array. If the number of rows 39 | // or that of columns is even, (0, 0) is located at lefter 40 | // position. 41 | std::vector m_map; 42 | GameSettings m_settings; 43 | }; 44 | } // namespace Civilizationpp 45 | 46 | #endif // CIVILIZATIONPP_HEX_MAP_H -------------------------------------------------------------------------------- /Includes/HexTile.h: -------------------------------------------------------------------------------- 1 | #ifndef CIVILIZATIONPP_HEX_TILE_H 2 | #define CIVILIZATIONPP_HEX_TILE_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Civilizationpp 8 | { 9 | class HexTile 10 | { 11 | public: 12 | HexTile(); 13 | 14 | Terrain* GetTerrain() const; 15 | void SetTerrain(Terrain* terrain); 16 | void ChangeResource(BasicResource* resource) const; 17 | 18 | private: 19 | Terrain* m_pTerrain; 20 | }; 21 | } // namespace Civilizationpp 22 | 23 | #endif // CIVILIZATIONPP_HEX_TILE_H 24 | -------------------------------------------------------------------------------- /Includes/Setter.h: -------------------------------------------------------------------------------- 1 | #ifndef CIVILIZATIONPP_SETTER_H 2 | #define CIVILIZATIONPP_SETTER_H 3 | 4 | #include 5 | 6 | namespace Civilizationpp 7 | { 8 | class Setter : public BaseUnit 9 | { 10 | public: 11 | Setter(int x, int y); 12 | }; 13 | } // namespace Civilizationpp 14 | 15 | #endif // CIVILIZATIONPP_SETTER_H -------------------------------------------------------------------------------- /Includes/Terrain.h: -------------------------------------------------------------------------------- 1 | #ifndef CIVILIZATIONPP_TERRAIN_H 2 | #define CIVILIZATIONPP_TERRAIN_H 3 | 4 | #include 5 | 6 | namespace Civilizationpp 7 | { 8 | enum class BaseTerrain 9 | { 10 | Open, 11 | Rough, 12 | Lake, 13 | Coast, 14 | Ocean, 15 | FreshWater 16 | }; 17 | 18 | enum class TerrainName 19 | { 20 | Coast, 21 | Desert, 22 | GrassLand, 23 | Hill, 24 | Mountain, 25 | Ocean, 26 | Plains, 27 | Snow, 28 | Tundra, 29 | Forest, 30 | Jungle, 31 | Marsh, 32 | Atoll, 33 | FloodPlains, 34 | Ice, 35 | LAkes, 36 | Oasis 37 | }; 38 | 39 | class Terrain 40 | { 41 | public: 42 | Terrain(); 43 | 44 | BaseTerrain GetCategory() const; 45 | TerrainName GetName() const; 46 | int GetMovement() const; 47 | int GetCombat() const; 48 | BasicResource* GetResource() const; 49 | void ChangeResource(BasicResource* resource); 50 | 51 | private: 52 | BaseTerrain m_category; 53 | TerrainName m_name; 54 | int m_movement; 55 | int m_combat; 56 | BasicResource* m_pBasicResource; 57 | }; 58 | } // namespace Civilizationpp 59 | 60 | #endif // CIVILIZATIONPP_TERRAIN_H -------------------------------------------------------------------------------- /Includes/UnitFactory.h: -------------------------------------------------------------------------------- 1 | #ifndef CIVILIZATIONPP_UNIT_FACTORY_H 2 | #define CIVILIZATIONPP_UNIT_FACTORY_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Civilizationpp 9 | { 10 | namespace Unit 11 | { 12 | enum class Codes 13 | { 14 | Setter = 0, 15 | Worker = 1 16 | }; 17 | } 18 | 19 | class UnitFactory 20 | { 21 | public: 22 | UnitFactory(int x, int y); 23 | BaseUnit* CreateUnit(Unit::Codes unitCode); 24 | 25 | private: 26 | int m_x; 27 | int m_y; 28 | }; 29 | } // namespace Civilizationpp 30 | 31 | #endif // CIVILIZATIONPP_UNIT_FACTORY_H -------------------------------------------------------------------------------- /Includes/Worker.h: -------------------------------------------------------------------------------- 1 | #ifndef CIVILIZATIONPP_WORKER_H 2 | #define CIVILIZATIONPP_WORKER_H 3 | 4 | #include 5 | 6 | namespace Civilizationpp 7 | { 8 | class Worker : public BaseUnit 9 | { 10 | public: 11 | Worker(int x, int y); 12 | 13 | void Build(BasicResource* tile); 14 | void Build(HexTile* tile, BasicResource* resource); 15 | }; 16 | } // namespace Civilizationpp 17 | 18 | #endif // CIVILIZATIONPP_WORKER_H -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Chris Ohk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/utilForever/Civilizationpp/b0f7b6a0ee60a6f6a93c4476704136650def210f/Logo.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Civilization++ 2 | 3 | 4 | 5 | Civilization++ is civilization simulator using C++ with some reinforcement learning. 6 | 7 | [![License](https://img.shields.io/badge/Licence-MIT-blue.svg)](https://github.com/utilForever/Civilizationpp/blob/master/LICENSE) [![Build Status](https://travis-ci.org/utilForever/Civilizationpp.svg?branch=master)](https://travis-ci.org/utilForever/Civilizationpp/branches) [![Build status](https://ci.appveyor.com/api/projects/status/github/utilForever/Civilizationpp?branch=master&svg=true)](https://ci.appveyor.com/project/utilForever/Civilizationpp/branch/master) [![Build Status](https://dev.azure.com/utilforever/Civilizationpp/_apis/build/status/utilForever.Civilizationpp)](https://dev.azure.com/utilforever/Civilizationpp/_build/latest?definitionId=1) 8 | 9 | ## Key Features 10 | 11 | TBD 12 | 13 | ## How To Contribute 14 | 15 | Contributions are always welcome, either reporting issues/bugs or forking the repository and then issuing pull requests when you have completed some additional coding that you feel will be beneficial to the main project. If you are interested in contributing in a more dedicated capacity, then please contact me. 16 | 17 | ## Contact 18 | 19 | You can contact me via e-mail (utilForever at gmail.com). I am always happy to answer questions or help with any issues you might have, and please be sure to share any additional work or your creations with me, I love seeing what other people are making. 20 | 21 | ## License 22 | 23 | 24 | 25 | The class is licensed under the [MIT License](http://opensource.org/licenses/MIT): 26 | 27 | Copyright © 2018 [Chris Ohk](http://www.github.com/utilForever) and [Junho Seo](https://github.com/JunHo-Seo), [Wonho Ha](https://github.com/Las-Wonho). 28 | 29 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 30 | 31 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 32 | 33 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Scripts/Dockerfile.bionic: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | MAINTAINER Chris Ohk 3 | 4 | RUN apt-get update -yq && \ 5 | apt-get install -yq build-essential cmake 6 | 7 | ADD . /app 8 | 9 | WORKDIR /app/build 10 | RUN cmake .. && \ 11 | make -j`nproc` && \ 12 | make install && \ 13 | bin/UnitTests 14 | -------------------------------------------------------------------------------- /Scripts/azure_pipelines_build.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - checkout: self 3 | fetchDepth: 2 4 | submodules: true 5 | - script: | 6 | mkdir build 7 | cd build 8 | cmake .. 9 | make -j 8 10 | bin/UnitTests -------------------------------------------------------------------------------- /Scripts/azure_pipelines_build_windows.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - checkout: self 3 | fetchDepth: 2 4 | submodules: true 5 | - script: | 6 | md build 7 | cd build 8 | cmake .. -G "Visual Studio 15 2017 Win64" 9 | - task: VSBuild@1 10 | inputs: 11 | solution: 'D:\a\1\s\build\Civilizationpp.sln' 12 | configuration: Release 13 | platform: x64 14 | - script: | 15 | D:\a\1\s\build\bin\Release\UnitTests.exe 16 | -------------------------------------------------------------------------------- /Scripts/travis_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | export NUM_JOBS=1 6 | 7 | mkdir build 8 | cd build 9 | cmake .. 10 | make 11 | bin/UnitTests 12 | -------------------------------------------------------------------------------- /Scripts/travis_build_docker.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if [ $# -eq 0 ] 6 | then 7 | docker build -t utilforever/civilizationpp . 8 | docker run utilforever/civilizationpp 9 | else 10 | docker build -f $1 -t utilforever/civilizationpp:$2 . 11 | docker run utilforever/civilizationpp:$2 12 | fi -------------------------------------------------------------------------------- /Sources/BaseUnit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace Civilizationpp; 4 | 5 | BaseUnit::BaseUnit(int x, int y) 6 | { 7 | m_positionX = x; 8 | m_positionY = y; 9 | } 10 | 11 | std::pair BaseUnit::Move(int x, int y) noexcept 12 | { 13 | m_positionX = x; 14 | m_positionY = y; 15 | return { m_positionX, m_positionY }; 16 | } 17 | 18 | std::pair BaseUnit::GetPosition() 19 | { 20 | return { m_positionX, m_positionY }; 21 | } 22 | -------------------------------------------------------------------------------- /Sources/BasicResource.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace Civilizationpp; 4 | 5 | BasicResource::BasicResource() 6 | { 7 | m_food = 0; 8 | m_gold = 0; 9 | m_production = 0; 10 | } 11 | 12 | int BasicResource::GetFood() const 13 | { 14 | return m_food; 15 | } 16 | 17 | int BasicResource::GetProduction() const 18 | { 19 | return m_production; 20 | } 21 | 22 | int BasicResource::GetGold() const 23 | { 24 | return m_gold; 25 | } 26 | -------------------------------------------------------------------------------- /Sources/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Target name 2 | set(target Civilizationpp) 3 | 4 | # Define 5 | set(root_dir ${CMAKE_CURRENT_SOURCE_DIR}/..) 6 | 7 | # Includes 8 | include_directories( 9 | ${CMAKE_CURRENT_SOURCE_DIR} 10 | ${CMAKE_CURRENT_SOURCE_DIR}/../Libraries 11 | ) 12 | 13 | # Sources 14 | file(GLOB header_dir 15 | ${root_dir}/Includes) 16 | 17 | file(GLOB_RECURSE headers 18 | ${header_dir}/*.h) 19 | 20 | file(GLOB_RECURSE sources 21 | ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) 22 | 23 | # Build library 24 | add_library(${target} 25 | ${sources}) 26 | 27 | # Project options 28 | set_target_properties(${target} 29 | PROPERTIES 30 | ${DEFAULT_PROJECT_OPTIONS} 31 | ) 32 | 33 | # Compile options 34 | target_compile_options(${target} 35 | PRIVATE 36 | 37 | PUBLIC 38 | ${DEFAULT_COMPILE_OPTIONS} 39 | 40 | INTERFACE 41 | ) 42 | 43 | target_link_libraries(${target} 44 | PRIVATE 45 | 46 | PUBLIC 47 | ${DEFAULT_LINKER_OPTIONS} 48 | ${DEFAULT_LIBRARIES} 49 | 50 | INTERFACE 51 | ) 52 | 53 | # Install 54 | install(TARGETS ${target} DESTINATION lib) 55 | install(DIRECTORY ${header_dir} DESTINATION include) -------------------------------------------------------------------------------- /Sources/GameSettings.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace Civilizationpp; 4 | 5 | GameSettings::GameSettings(size_t rowCount, size_t colCount) 6 | : rowCount(rowCount), colCount(colCount) 7 | { 8 | // Do nothing 9 | } 10 | -------------------------------------------------------------------------------- /Sources/HexMap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace Civilizationpp; 10 | 11 | HexMap* HexMap::m_instance = nullptr; 12 | 13 | HexMap* HexMap::GetInstance() 14 | { 15 | if (m_instance == nullptr) 16 | { 17 | m_instance = new HexMap(); 18 | } 19 | 20 | return m_instance; 21 | } 22 | 23 | void HexMap::Generate(GameSettings settings) 24 | { 25 | m_settings = settings; 26 | m_map.resize(settings.rowCount * settings.colCount); 27 | } 28 | 29 | HexMap::HexMap() : m_settings(0, 0) 30 | { 31 | // Do nothing 32 | } 33 | 34 | HexMap::~HexMap() 35 | { 36 | delete m_instance; 37 | } 38 | 39 | const HexTile* HexMap::GetTile(int r, int q) const 40 | { 41 | const auto rowCount = static_cast(m_settings.rowCount); 42 | const auto colCount = static_cast(m_settings.colCount); 43 | 44 | // Convert axial coordinates into 2d array index 45 | const int originRow = (rowCount - 1) / 2; 46 | const int originCol = (colCount - 1) / 2; 47 | 48 | const int tileRow = originRow + r; 49 | if (tileRow < 0 || tileRow >= rowCount) 50 | { 51 | return nullptr; 52 | } 53 | 54 | int tileCol = (originCol + q) % colCount; 55 | if (tileCol < 0) 56 | { 57 | tileCol += colCount; 58 | } 59 | 60 | // Convert 2d array index into 1d array index 61 | const int index = tileCol + tileRow * colCount; 62 | 63 | return &m_map[index]; 64 | } 65 | 66 | std::vector HexMap::GetAdjacencies(int r, int q) const 67 | { 68 | std::vector ret{}; 69 | 70 | ret.push_back(GetTile(r - 1, q)); 71 | ret.push_back(GetTile(r - 1, q + 1)); 72 | ret.push_back(GetTile(r, q + 1)); 73 | ret.push_back(GetTile(r + 1, q)); 74 | ret.push_back(GetTile(r + 1, q - 1)); 75 | ret.push_back(GetTile(r, q - 1)); 76 | ret.erase(std::remove(ret.begin(), ret.end(), nullptr), ret.end()); 77 | 78 | return ret; 79 | } 80 | 81 | int HexMap::GetDistance(int r1, int q1, int r2, int q2) 82 | { 83 | // Convert axial coordinates to cube coordinates 84 | const int y1 = -r1 - q1; 85 | const int y2 = -r2 - q2; 86 | 87 | const int dx = std::abs(q1 - q2); 88 | const int dy = std::abs(y1 - y2); 89 | const int dz = std::abs(r1 - r2); 90 | 91 | return std::max({ dx, dy, dz }); 92 | } 93 | -------------------------------------------------------------------------------- /Sources/HexTile.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace Civilizationpp; 4 | 5 | HexTile::HexTile() 6 | { 7 | m_pTerrain = new Terrain(); 8 | } 9 | 10 | Terrain* HexTile::GetTerrain() const 11 | { 12 | return m_pTerrain; 13 | } 14 | 15 | void HexTile::SetTerrain(Terrain* terrain) 16 | { 17 | m_pTerrain = terrain; 18 | } 19 | 20 | void HexTile::ChangeResource(BasicResource* resource) const 21 | { 22 | m_pTerrain->ChangeResource(resource); 23 | } -------------------------------------------------------------------------------- /Sources/Setter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace Civilizationpp; 4 | 5 | Setter::Setter(int x, int y) : BaseUnit(x, y) 6 | { 7 | // Do nothing 8 | } -------------------------------------------------------------------------------- /Sources/Terrain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace Civilizationpp; 4 | 5 | Terrain::Terrain() : m_category(BaseTerrain::Open), m_name(TerrainName::Plains) 6 | { 7 | m_movement = 0; 8 | m_combat = 0; 9 | } 10 | 11 | BaseTerrain Terrain::GetCategory() const 12 | { 13 | return m_category; 14 | } 15 | 16 | TerrainName Terrain::GetName() const 17 | { 18 | return m_name; 19 | } 20 | 21 | int Terrain::GetMovement() const 22 | { 23 | return m_movement; 24 | } 25 | 26 | int Terrain::GetCombat() const 27 | { 28 | return m_combat; 29 | } 30 | 31 | BasicResource* Terrain::GetResource() const 32 | { 33 | return m_pBasicResource; 34 | } 35 | 36 | void Terrain::ChangeResource(BasicResource* resource) 37 | { 38 | m_pBasicResource = resource; 39 | } -------------------------------------------------------------------------------- /Sources/UnitFactory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace Civilizationpp; 4 | 5 | UnitFactory::UnitFactory(int x, int y) 6 | { 7 | m_x = x; 8 | m_y = y; 9 | } 10 | 11 | BaseUnit* UnitFactory::CreateUnit(Unit::Codes unitCode) 12 | { 13 | BaseUnit* unit; 14 | 15 | if (unitCode == Unit::Codes::Setter) 16 | { 17 | unit = new Setter(m_x, m_y); 18 | return unit; 19 | } 20 | else if (unitCode == Unit::Codes::Worker) 21 | { 22 | unit = new Worker(m_x, m_y); 23 | return unit; 24 | } 25 | 26 | return nullptr; 27 | }; -------------------------------------------------------------------------------- /Sources/Worker.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace Civilizationpp; 4 | 5 | Worker::Worker(int x, int y) : BaseUnit(x, y) 6 | { 7 | // Do nothing 8 | } 9 | 10 | void Worker::Build(BasicResource* resource) 11 | { 12 | auto position = GetPosition(); 13 | HexMap::GetInstance() 14 | ->GetTile(position.first, position.second) 15 | ->ChangeResource(resource); 16 | } 17 | 18 | void Worker::Build(HexTile* tile, BasicResource* resource) 19 | { 20 | tile->ChangeResource(resource); 21 | } 22 | -------------------------------------------------------------------------------- /Tests/UnitTests/BaseUnitTests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | using namespace Civilizationpp; 6 | 7 | TEST(BaseUnit, ShouldCanMove) 8 | { 9 | BaseUnit baseunit{ 1, 2 }; 10 | 11 | auto position = baseunit.Move(+1, -3); 12 | ASSERT_TRUE(position.first == +1 && position.second == -3); 13 | 14 | position = baseunit.Move(-1, +3); 15 | ASSERT_TRUE(position.first == -1 && position.second == +3); 16 | 17 | position = baseunit.Move(-1, +30); 18 | ASSERT_TRUE(position.first == -1 && position.second == +30); 19 | 20 | position = baseunit.Move(-13, +30); 21 | ASSERT_TRUE(position.first == -13 && position.second == +30); 22 | } -------------------------------------------------------------------------------- /Tests/UnitTests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Target name 2 | set(target UnitTests) 3 | 4 | # Includes 5 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 6 | 7 | # Sources 8 | file(GLOB sources 9 | ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) 10 | 11 | # Build executable 12 | add_executable(${target} 13 | ${sources}) 14 | 15 | # Project options 16 | set_target_properties(${target} 17 | PROPERTIES 18 | ${DEFAULT_PROJECT_OPTIONS} 19 | ) 20 | 21 | # Compile options 22 | # GCC and Clang compiler options 23 | if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 24 | set(DEFAULT_COMPILE_OPTIONS ${DEFAULT_COMPILE_OPTIONS} 25 | # /wd4996 # -> disable warning: non-Standard std::tr1 namespace and TR1-only machinery (because of gtest) 26 | -Wno-unused-variable 27 | ) 28 | endif() 29 | target_compile_options(${target} 30 | PRIVATE 31 | ${DEFAULT_COMPILE_OPTIONS} 32 | ) 33 | target_compile_definitions(${target} 34 | PRIVATE 35 | ) 36 | 37 | # Link libraries 38 | target_link_libraries(${target} 39 | PRIVATE 40 | ${DEFAULT_LINKER_OPTIONS} 41 | Civilizationpp 42 | gtest) -------------------------------------------------------------------------------- /Tests/UnitTests/HexMapTests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | using namespace Civilizationpp; 7 | 8 | TEST(HexMap, ShouldAlwaysHaveOrigin) 9 | { 10 | HexMap::GetInstance()->Generate(GameSettings(3, 3)); 11 | 12 | const HexTile* origin = HexMap::GetInstance()->GetTile(0, 0); 13 | ASSERT_NE(origin, static_cast(nullptr)); 14 | } 15 | 16 | TEST(HexMap, ShouldReturnNullptrForInvalidCoordinates) 17 | { 18 | HexMap::GetInstance()->Generate(GameSettings(3, 3)); 19 | 20 | const HexTile* invalid = HexMap::GetInstance()->GetTile(-100, -100); 21 | ASSERT_EQ(invalid, static_cast(nullptr)); 22 | } 23 | 24 | TEST(HexMap, ShouldGenerateDefaultMapOnConstruction) 25 | { 26 | HexMap::GetInstance()->Generate(GameSettings(3, 3)); 27 | 28 | for (int r = -2; r <= 2; ++r) 29 | { 30 | for (int q = -2; q <= 2; ++q) 31 | { 32 | if (r == -2 || r == 2) 33 | { 34 | ASSERT_EQ(HexMap::GetInstance()->GetTile(r, q), 35 | static_cast(nullptr)); 36 | } 37 | else 38 | { 39 | ASSERT_NE(HexMap::GetInstance()->GetTile(r, q), 40 | static_cast(nullptr)); 41 | } 42 | } 43 | } 44 | } 45 | 46 | TEST(HexMap, ShouldSupportColumnWiseWraparound) 47 | { 48 | HexMap::GetInstance()->Generate(GameSettings(3, 3)); 49 | 50 | ASSERT_NE(HexMap::GetInstance()->GetTile(-1, -2), 51 | static_cast(nullptr)); 52 | ASSERT_NE(HexMap::GetInstance()->GetTile(0, -2), 53 | static_cast(nullptr)); 54 | ASSERT_NE(HexMap::GetInstance()->GetTile(+1, -2), 55 | static_cast(nullptr)); 56 | ASSERT_NE(HexMap::GetInstance()->GetTile(-1, +2), 57 | static_cast(nullptr)); 58 | ASSERT_NE(HexMap::GetInstance()->GetTile(0, +2), 59 | static_cast(nullptr)); 60 | ASSERT_NE(HexMap::GetInstance()->GetTile(1, +2), 61 | static_cast(nullptr)); 62 | } 63 | 64 | TEST(HexMap, ShouldNotSupportRowWiseWraparound) 65 | { 66 | HexMap::GetInstance()->Generate(GameSettings(3, 3)); 67 | 68 | ASSERT_EQ(HexMap::GetInstance()->GetTile(-2, -1), 69 | static_cast(nullptr)); 70 | ASSERT_EQ(HexMap::GetInstance()->GetTile(-2, 0), 71 | static_cast(nullptr)); 72 | ASSERT_EQ(HexMap::GetInstance()->GetTile(-2, +1), 73 | static_cast(nullptr)); 74 | ASSERT_EQ(HexMap::GetInstance()->GetTile(+2, -2), 75 | static_cast(nullptr)); 76 | ASSERT_EQ(HexMap::GetInstance()->GetTile(+2, -1), 77 | static_cast(nullptr)); 78 | ASSERT_EQ(HexMap::GetInstance()->GetTile(+2, 0), 79 | static_cast(nullptr)); 80 | ASSERT_EQ(HexMap::GetInstance()->GetTile(+2, +1), 81 | static_cast(nullptr)); 82 | } 83 | 84 | TEST(HexMap, ShouldReturnVectorOfNonNullptrAdjacentTilesOnRequest) 85 | { 86 | HexMap::GetInstance()->Generate(GameSettings(3, 3)); 87 | 88 | std::vector adjacenciesToOrigin = 89 | HexMap::GetInstance()->GetAdjacencies(0, 0); 90 | ASSERT_NE(std::find(adjacenciesToOrigin.begin(), adjacenciesToOrigin.end(), 91 | HexMap::GetInstance()->GetTile(-1, 0)), 92 | adjacenciesToOrigin.end()); 93 | ASSERT_NE(std::find(adjacenciesToOrigin.begin(), adjacenciesToOrigin.end(), 94 | HexMap::GetInstance()->GetTile(-1, 1)), 95 | adjacenciesToOrigin.end()); 96 | ASSERT_NE(std::find(adjacenciesToOrigin.begin(), adjacenciesToOrigin.end(), 97 | HexMap::GetInstance()->GetTile(0, 1)), 98 | adjacenciesToOrigin.end()); 99 | ASSERT_NE(std::find(adjacenciesToOrigin.begin(), adjacenciesToOrigin.end(), 100 | HexMap::GetInstance()->GetTile(1, 0)), 101 | adjacenciesToOrigin.end()); 102 | ASSERT_NE(std::find(adjacenciesToOrigin.begin(), adjacenciesToOrigin.end(), 103 | HexMap::GetInstance()->GetTile(1, -1)), 104 | adjacenciesToOrigin.end()); 105 | ASSERT_NE(std::find(adjacenciesToOrigin.begin(), adjacenciesToOrigin.end(), 106 | HexMap::GetInstance()->GetTile(0, -1)), 107 | adjacenciesToOrigin.end()); 108 | ASSERT_EQ(adjacenciesToOrigin.size(), (size_t)6); 109 | 110 | std::vector adjacenciesToEdge = 111 | HexMap::GetInstance()->GetAdjacencies(-1, -1); 112 | ASSERT_NE(std::find(adjacenciesToEdge.begin(), adjacenciesToEdge.end(), 113 | HexMap::GetInstance()->GetTile(-1, -2)), 114 | adjacenciesToEdge.end()); 115 | ASSERT_NE(std::find(adjacenciesToEdge.begin(), adjacenciesToEdge.end(), 116 | HexMap::GetInstance()->GetTile(0, -2)), 117 | adjacenciesToEdge.end()); 118 | ASSERT_NE(std::find(adjacenciesToEdge.begin(), adjacenciesToEdge.end(), 119 | HexMap::GetInstance()->GetTile(0, -1)), 120 | adjacenciesToEdge.end()); 121 | ASSERT_NE(std::find(adjacenciesToEdge.begin(), adjacenciesToEdge.end(), 122 | HexMap::GetInstance()->GetTile(-1, 0)), 123 | adjacenciesToEdge.end()); 124 | ASSERT_EQ(adjacenciesToEdge.size(), (size_t)4); 125 | } 126 | 127 | TEST(HexMap, ShouldReturnDistanceOfTwoHexTile) 128 | { 129 | // Two same tile should return 0 distance 130 | ASSERT_EQ(0, HexMap::GetDistance(0, 0, 0, 0)); 131 | 132 | // Adjacent tiles should return 1 distance 133 | ASSERT_EQ(1, HexMap::GetDistance(0, 0, 0, -1)); 134 | ASSERT_EQ(1, HexMap::GetDistance(0, 0, -1, 0)); 135 | ASSERT_EQ(1, HexMap::GetDistance(0, 0, -1, 1)); 136 | ASSERT_EQ(1, HexMap::GetDistance(0, 0, 0, 1)); 137 | ASSERT_EQ(1, HexMap::GetDistance(0, 0, 1, 0)); 138 | ASSERT_EQ(1, HexMap::GetDistance(0, 0, 1, -1)); 139 | 140 | // Tiles in 2 distance 141 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, 0, -2)); 142 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, -1, -1)); 143 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, -2, 0)); 144 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, -2, 1)); 145 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, -2, 2)); 146 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, -1, 2)); 147 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, 2, -1)); 148 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, 0, 2)); 149 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, 1, 1)); 150 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, 2, 0)); 151 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, 2, -1)); 152 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, 2, -2)); 153 | ASSERT_EQ(2, HexMap::GetDistance(0, 0, 1, -2)); 154 | } -------------------------------------------------------------------------------- /Tests/UnitTests/UnitFactoryTests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | using namespace Civilizationpp; 6 | 7 | TEST(UnitFactory, CanCreatUnit) 8 | { 9 | UnitFactory factory{ 1, 1 }; 10 | 11 | Setter* setter = 12 | dynamic_cast(factory.CreateUnit(Unit::Codes::Setter)); 13 | ASSERT_NE(setter, static_cast(nullptr)); 14 | delete (setter); 15 | 16 | setter = dynamic_cast(factory.CreateUnit(Unit::Codes::Worker)); 17 | ASSERT_EQ(setter, static_cast(nullptr)); 18 | delete (setter); 19 | 20 | Worker* worker = 21 | dynamic_cast(factory.CreateUnit(Unit::Codes::Worker)); 22 | ASSERT_NE(worker, static_cast(nullptr)); 23 | delete (worker); 24 | 25 | worker = dynamic_cast(factory.CreateUnit(Unit::Codes::Setter)); 26 | ASSERT_EQ(worker, static_cast(nullptr)); 27 | delete (worker); 28 | } -------------------------------------------------------------------------------- /Tests/UnitTests/UnitTests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | ::testing::InitGoogleTest(&argc, argv); 6 | 7 | int ret = RUN_ALL_TESTS(); 8 | 9 | return ret; 10 | } -------------------------------------------------------------------------------- /Tests/UnitTests/WorkerTests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | using namespace Civilizationpp; 6 | 7 | TEST(Worker, CanMoveAnywhere) 8 | { 9 | Worker worker{ 0, 0 }; 10 | 11 | HexMap::GetInstance()->Generate(GameSettings(30, 30)); 12 | 13 | worker.Move(1, 2); 14 | 15 | auto position = worker.GetPosition(); 16 | ASSERT_TRUE(position.first == 1 && position.second == 2); 17 | } 18 | 19 | TEST(Worker, CanChangeTile) 20 | { 21 | Worker worker{ 0, 0 }; 22 | BasicResource res; 23 | 24 | HexMap::GetInstance()->Generate(GameSettings(30, 30)); 25 | 26 | worker.Build(&res); 27 | 28 | auto position = worker.GetPosition(); 29 | ASSERT_EQ(HexMap::GetInstance() 30 | ->GetTile(position.first, position.second) 31 | ->GetTerrain() 32 | ->GetResource(), 33 | &res); 34 | } -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 ({build}) 2 | 3 | skip_branch_with_pr: true 4 | 5 | os: 6 | - Visual Studio 2017 7 | 8 | platform: 9 | - x64 10 | 11 | matrix: 12 | fast_finish: true # Stop remaining jobs after a job failure 13 | 14 | configuration: 15 | - Release 16 | 17 | clone_folder: C:\Civilizationpp 18 | 19 | install: 20 | - git submodule update --init 21 | - ps: | 22 | $env:CMAKE_GENERATOR = "Visual Studio 15 2017 Win64" 23 | 24 | before_build: 25 | - md C:\Civilizationpp\build 26 | - cd C:\Civilizationpp\build 27 | - cmake .. -G "%CMAKE_GENERATOR%" 28 | 29 | build: 30 | project: C:\Civilizationpp\build\Civilizationpp.sln 31 | parallel: true 32 | verbosity: normal 33 | 34 | after_build: 35 | - C:\Civilizationpp\build\bin\Release\UnitTests.exe -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - job: Windows 3 | pool: 4 | vmImage: 'vs2017-win2016' 5 | steps: 6 | - template: Scripts/azure_pipelines_build_windows.yml 7 | - job: Linux 8 | pool: 9 | vmImage: 'Ubuntu-16.04' 10 | steps: 11 | - template: Scripts/azure_pipelines_build.yml 12 | - job: macOS 13 | pool: 14 | vmImage: 'macOS 10.13' 15 | steps: 16 | - template: Scripts/azure_pipelines_build.yml --------------------------------------------------------------------------------