From d1729226981850e94e967756e7ed633629f8aa85 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Mon, 29 Dec 2014 21:55:32 +0000 Subject: [PATCH] Implement invalid unit positions --- source/game/game.cpp | 119 ++++++++++++++++++++++++++++++++++++---- source/game/game.h | 10 +++- source/game/gametypes.h | 7 +++ source/game/unit.h | 2 - 4 files changed, 122 insertions(+), 16 deletions(-) diff --git a/source/game/game.cpp b/source/game/game.cpp index 45c2646..818225f 100644 --- a/source/game/game.cpp +++ b/source/game/game.cpp @@ -101,6 +101,15 @@ int CTTRTSGame::VerifyPosIsValidMovement(uvector2 vec) const return 1; } + // Check within our invalid positions + for ( const uvector2& invalid : m_InvalidPositions ) + { + if( vec == invalid ) + { + return 2; + } + } + return 0; } @@ -158,6 +167,8 @@ int CTTRTSGame::SimulateToNextTurn() // If the movement is still possible if ( possible ) { + // Push back the old position to our invalid positions list + AddInvalidPosition(pair.unit.GetPos()); pair.unit.SetPos(newpos); } } @@ -493,9 +504,30 @@ player_t CTTRTSGame::GetWinningPlayer() const // Get the game information as a string std::string CTTRTSGame::GetStateAsString() const { + // Grab the invalid positions + std::string invalid_positions; + if( m_InvalidPositions.size() == 0 ) + { + invalid_positions = "NONE"; + } + + for ( auto invalid_pos : m_InvalidPositions ) + { + char pos[16]; + if( snprintf(pos, 16, GAME_POS_FORMATTER , invalid_pos.x, invalid_pos.y ) < 0 ) + { + return "BUFFER OVERFLOW"; + } + invalid_positions += pos; + } + + // Print out the header - char header[64]; - snprintf(header, 512, GAME_HEADER_FORMATTER , name.c_str(), dimensions.x, dimensions.y, turn ); + char header[512]; + if ( snprintf(header, 512, GAME_HEADER_FORMATTER , name.c_str(), dimensions.x, dimensions.y, turn, invalid_positions.c_str() ) < 0 ) + { + return "BUFFER OVERFLOW"; + } // Gather unit information std::string units; @@ -514,7 +546,6 @@ std::string CTTRTSGame::GetStateAsString() const return state; } - // Get the game information as a string CTTRTSGame CTTRTSGame::CreateFromString( const std::string& input ) { @@ -524,24 +555,90 @@ CTTRTSGame CTTRTSGame::CreateFromString( const std::string& input ) std::string units = input.substr(headerEnd + strlen(GAME_HEADER_DELIMITER)); // Grab information from the header - char buf[64]; + char name[64]; unsigned int turn; unsigned int sizex; unsigned int sizey; - sscanf(header.c_str(), GAME_HEADER_FORMATTER, buf, &sizex, &sizey, &turn ); + char invalid_positions[512]; + if( sscanf(header.c_str(), GAME_HEADER_FORMATTER, name, &sizex, &sizey, &turn, invalid_positions ) != 5 ) + { + return CTTRTSGame(0,0); + } + + std::vector invalid_pos_vector; + { + std::string invalid_positions_str = invalid_positions; + size_t pos; + while ( ( pos = invalid_positions_str.find(']') ) != std::string::npos ) + { + std::string pos_string = invalid_positions_str.substr(1,pos); + + // Use scanf to extract positions + + unsigned int x; + unsigned int y; + if( sscanf(pos_string.c_str(), GAME_POS_FORMATTER, &x, &y ) != 2 ) + { + return CTTRTSGame(0,0); + } + + uvector2 inv_pos(x,y); + + // Erase this coordinate + invalid_positions_str.erase(0,pos+1); + + // Append our list + invalid_pos_vector.push_back(inv_pos); + } + } CTTRTSGame game(sizex,sizey); - game.SetName(buf); + game.SetName(name); game.SetTurn(turn); // For each line, construct a unit - size_t pos; - while ( ( pos = units.find('\n') ) != std::string::npos ) { - std::string unit_string = units.substr(0,pos); - units.erase(0,pos+1); - game.AddUnit(CUnit::GetUnitFromString(unit_string)); + size_t pos; + while ((pos = units.find('\n')) != std::string::npos) { + std::string unit_string = units.substr(0, pos); + units.erase(0, pos + 1); + game.AddUnit(CUnit::GetUnitFromString(unit_string)); + } + } + + // Add all invalid positions + for ( auto inv : invalid_pos_vector ) + { + game.AddInvalidPosition(inv); } return game; +} + +// Check if any of the units can move +bool CTTRTSGame::UnitsCanMove() const +{ + for( const SOrderUnitPair& pair: m_OrderUnitPairs ) + { + uvector2 pos = pair.unit.GetPos(); + + // Assume if unit is adjacent to any valid tile, then it can move there + if( VerifyPosIsValidMovement(pos + vector2(1, 0) ) == 0 + || VerifyPosIsValidMovement(pos + vector2(0, 1)) == 0 + || VerifyPosIsValidMovement(pos + vector2(-1, 0)) == 0 + || VerifyPosIsValidMovement(pos + vector2(0, -1)) == 0 ) + { + return true; + } + } + + return false; +} + +// Check if the game is over +bool CTTRTSGame::GameOver() const +{ + return ( (GetWinningPlayer() != player_t::NUM_INVALID ) // We have a winning player + || GetNumUnits() == 0 + || !UnitsCanMove() ); // OR we have no units } \ No newline at end of file diff --git a/source/game/game.h b/source/game/game.h index 061ccc5..c3eeca4 100644 --- a/source/game/game.h +++ b/source/game/game.h @@ -6,9 +6,6 @@ #include "order.h" #include "orderunitpair.h" -#define GAME_HEADER_FORMATTER "NAME:%s\nSIZE:[%u,%u]\nTURN:%u" -#define GAME_HEADER_DELIMITER "~~~~\n" - // Full TTRTS Game class // Stores information about the game // Can convert from a string or to a string @@ -79,6 +76,12 @@ public: // Get a vector of the players in the current game std::vector GetPlayers() const; + // Get the vector of current invalid positions + inline std::vector GetInvalidPositions() const { return m_InvalidPositions; } + + // Add an invalid position + inline void AddInvalidPosition( uvector2 vec ) { m_InvalidPositions.push_back(vec); } + private: // Check for a pass through @@ -101,6 +104,7 @@ private: unsigned int turn; // Int to store the current turn uvector2 dimensions; // Dimensions of the game OrderUnitPairVector m_OrderUnitPairs; // Vector to store all units and orders + std::vector m_InvalidPositions; // Vector of invalidated positions }; diff --git a/source/game/gametypes.h b/source/game/gametypes.h index 0ee4e5b..e86ebf3 100644 --- a/source/game/gametypes.h +++ b/source/game/gametypes.h @@ -3,6 +3,13 @@ #include // std::numeric_limits +#define GAME_POS_FORMATTER "[%u,%u]" + +#define GAME_HEADER_FORMATTER "NAME:%s\nSIZE:" GAME_POS_FORMATTER "\nTURN:%u\nWALL:%s" +#define GAME_HEADER_DELIMITER "~~~~\n" + +#define UNIT_FORMATTER "UNIT:%u pl:%u vs:%c dr:%c ps:" GAME_POS_FORMATTER + // Type for a Player IDs enum class player_t : char { diff --git a/source/game/unit.h b/source/game/unit.h index ce9295f..b594836 100644 --- a/source/game/unit.h +++ b/source/game/unit.h @@ -7,8 +7,6 @@ #include "gametypes.h" #include "vector2.h" -#define UNIT_FORMATTER "UNIT:%u pl:%u vs:%c dr:%c ps:[%u,%u]" - // force a reset of the unit ID value void __forceResetCUnitID();