From b77411121a3cca24d4dcbeb30312a2f80c9251b9 Mon Sep 17 00:00:00 2001 From: Marc Di Luzio Date: Tue, 16 Dec 2014 13:13:02 +0000 Subject: [PATCH] Implement conversion of Unit to String and back --- game/orders.cpp | 24 ++++----- game/orders.h | 4 +- game/unit.cpp | 128 ++++++++++++++++++++++++++++++++++++++++++++++-- game/unit.h | 23 +++++++-- maths/vector2.h | 2 + test/test.cpp | 38 +++++++++++--- 6 files changed, 188 insertions(+), 31 deletions(-) diff --git a/game/orders.cpp b/game/orders.cpp index 836d4e8..80bd284 100644 --- a/game/orders.cpp +++ b/game/orders.cpp @@ -6,9 +6,10 @@ std::string GetStringFromOrder(const COrder& order ) { std::string ret; + ret += "O:"; + ret += (char)order.order; + ret += " U:"; ret += std::to_string(order.unit); - ret += ORDER_DELIMITER; - ret += (char)order.order; return ret; } @@ -19,19 +20,18 @@ COrder GetOrderFromString( const std::string& _order ) std::string order = _order; COrder ret; - size_t pos = order.find(ORDER_DELIMITER); - if( pos != std::string::npos ) - { - const std::string order_unit = order.substr(0, pos); + if( order.substr(0, 2) != "O:" ) + return COrder(); + order.erase(0, 2); // Erase the O: prefix - ret.unit = (unit_id_t)atoi( order_unit.c_str() ); + ret.order = (order_c)order[0]; // Grab single char oder + order.erase(0, 2); // Erase the order and a space - // Erase everything up to and including the delimiter - order.erase(0, pos + 1); + if( order.substr(0, 2) != "U:" ) + return COrder(); + order.erase(0, 2); // Erase the U: prefix - // Next single char is the order - ret.order = (order_c)order[0]; - } + ret.unit = (unit_id_t)atoi( order.c_str() ); // Grab the unit ID return ret; } diff --git a/game/orders.h b/game/orders.h index 558682f..dde304f 100644 --- a/game/orders.h +++ b/game/orders.h @@ -6,8 +6,6 @@ #include "gametypes.h" -#define ORDER_DELIMITER ' ' - // Type for all orders ( as a char ) enum class order_c : char { @@ -47,7 +45,7 @@ inline bool COrder::operator== ( const COrder& rhs ) const // Typedef a vector of orders typedef std::vector COrderVector; -// Order strings stored as simply "[unit id] [order char]" +// Order strings stored as simply "O:[order char] U:[unit id]" // string <--> order conversion functions std::string GetStringFromOrder(const COrder& order ); COrder GetOrderFromString( const std::string& order ); diff --git a/game/unit.cpp b/game/unit.cpp index 5b52713..9e5591b 100644 --- a/game/unit.cpp +++ b/game/unit.cpp @@ -29,6 +29,121 @@ namespace } } +// Get a unit from a visual +CUnit GetUnitFromVis( unitVis_c vis ) +{ + CUnit unit; + unit.setFromVisual(vis); + return unit; +} + +// Get a string descriptor of a unit +// "U:[unit_id] T:[team_id] P:[player_id] V:[unit_vis] D:[dir] POS:[pos.x],[pos.y]" +std::string GetStringFromUnit(const CUnit& unit ) +{ + std::string ret; + ret += "U:"; + ret += std::to_string(unit.getID()); + ret += " T:"; + ret += std::to_string((int)unit.getTeam()); + ret += " P:"; + ret += std::to_string(unit.getPlayer()); + ret += " V:"; + ret += (char)unit.getVisual(); + ret += " D:"; + ret += (char)unit.getDir(); + ret += " POS:"; + ret += std::to_string(unit.getPos().x); + ret += ","; + ret += std::to_string(unit.getPos().y); + + return ret; +} + +// Get a unit from a string descriptor +// "U:[unit_id] T:[team_id] P:[player_id] V:[unit_vis] D:[dir] POS:[pos.x],[pos.y]" +CUnit GetUnitFromString(const std::string& _unit ) +{ + std::string unit = _unit; + CUnit ret; + size_t pos; + + // UNIT ID + if( unit.substr(0, 2) != "U:" ) + return CUnit(); + unit.erase(0, 2); // Erase the U: prefix + + pos = unit.find(' '); + if( pos == std::string::npos ) + return CUnit(); + + const unit_id_t id = (unit_id_t)atoi( unit.substr(0,pos).c_str() ); // Grab the ID + ret.setIDForced( id ); // Force set the ID + unit.erase(0, pos+1); // Erase the ID and a space + + // TEAM + if( unit.substr(0, 2) != "T:" ) + return CUnit(); + unit.erase(0, 2); // Erase the T: prefix + + pos = unit.find(' '); + if( pos == std::string::npos ) + return CUnit(); + + const Team team = (Team)atoi( unit.substr(0,pos).c_str() ); // Grab the ID + ret.setTeam( team ); // Force set the ID + unit.erase(0, pos+1); // Erase the team and a space + + // PLAYER + if( unit.substr(0, 2) != "P:" ) + return CUnit(); + unit.erase(0, 2); // Erase the P: prefix + + pos = unit.find(' '); + if( pos == std::string::npos ) + return CUnit(); + + const player_id_t player = (player_id_t)atoi( unit.substr(0,pos).c_str() ); // Grab the ID + ret.setPlayer( player ); // Force set the ID + unit.erase(0, pos+1); // Erase the player and a space + + // VISUAL + if( unit.substr(0, 2) != "V:" ) + return CUnit(); + unit.erase(0, 2); // Erase the W: prefix + + unitVis_c vis = unit[0]; + ret.setVisual(vis); + unit.erase(0, 2); // Erase the vis and a space + + // DIRECTION + if( unit.substr(0, 2) != "D:" ) + return CUnit(); + unit.erase(0, 2); // Erase the D: prefix + + dir_t dir = (dir_t)unit[0]; + ret.setDir(dir); + unit.erase(0, 2); // Erase the ID and a space + + // POSITION + if( unit.substr(0, 4) != "POS:" ) + return CUnit(); + unit.erase(0, 4); // Erase the Pos: prefix + + pos = unit.find(','); + if( pos == std::string::npos ) + return CUnit(); + + uvector2 upos; + upos.x = (ucoord_t)atoi( unit.substr(0,pos).c_str() ); // Grab the x + unit.erase(0, pos+1); // Erase the x and the comma + + upos.y = (ucoord_t)atoi( unit.c_str() ); // Grab the y from what's left + ret.setPos( upos ); //Set the position + + return ret; +} + // Plain constructor CUnit::CUnit() : unit_id ( get_unique_unit_id() ) @@ -66,12 +181,15 @@ CUnit& CUnit::operator=(CUnit&& unit) return *this; } -// Get a unit from a visual -CUnit CUnit::getUnitFromVis( unitVis_c vis ) +// Equals operator +bool CUnit::operator==(const CUnit& rhs) { - CUnit unit; - unit.setFromVisual(vis); - return unit; + return (unit_id == rhs.unit_id) + && (team_id == rhs.team_id) + && (player_id == rhs.player_id) + && (unit_vis == rhs.unit_vis) + && (dir == rhs.dir) + && (pos == rhs.pos); } // Update the visual representation of the unit diff --git a/game/unit.h b/game/unit.h index 4c6d13f..a6ef88d 100644 --- a/game/unit.h +++ b/game/unit.h @@ -15,16 +15,19 @@ public: // Constructor CUnit(); - // Move constructor and move asignement. CUnit cannot be copied + // Move constructor and move assignment. CUnit cannot be copied CUnit(CUnit&& unit); CUnit& operator=(CUnit&& unit); + bool operator==(const CUnit& rhs); + bool operator!=(const CUnit& rhs) { return !(*this == rhs); } + // Default dtor ~CUnit() = default; // Getters for all the members inline const unit_id_t& getID() const { return unit_id; } - inline const Team & getTeam() const { return team_id; } + inline const Team & getTeam() const { return team_id; } inline const player_id_t& getPlayer() const { return player_id; } inline const unitVis_c& getVisual() const { return unit_vis; } inline const dir_t& getDir() const { return dir; } @@ -39,6 +42,9 @@ public: inline const uvector2& getPos() const { return pos; } inline void setPos(const uvector2& v) { pos = v; } + + inline const unit_id_t& setIDForced(const unit_id_t& v) { return (unit_id = v); } + // Get the co-ordinate infront of the unit uvector2 getInFront() const; @@ -48,9 +54,6 @@ public: // Set a unit based solely on it's visual bool setFromVisual( const unitVis_c& vis); - // Factory function for creating units from a visual - static CUnit getUnitFromVis( unitVis_c vis ); - // Orientation methods dir_t turnLeft(); dir_t turnRight(); @@ -92,4 +95,14 @@ inline bool CUnit::valid() const && (unit_vis != unitVis_invalid); } + +// Factory function for creating units from a visual +CUnit GetUnitFromVis( unitVis_c vis ); + +// Units strings stored as +// "U:[unit_id] T:[team_id] P:[player_id] V:[unit_vis] D:[dir] POS:[pos.x],[pos.y]" +// Unit <--> string conversion functions +std::string GetStringFromUnit(const CUnit& unit ); +CUnit GetUnitFromString(const std::string& unit ); + #endif //_UNIT_H_ diff --git a/maths/vector2.h b/maths/vector2.h index 6552807..ee36d5d 100644 --- a/maths/vector2.h +++ b/maths/vector2.h @@ -7,6 +7,7 @@ struct uvector2; struct vector2 { + vector2() : x (0), y (0) {} vector2( coord_t _x, coord_t _y ) : x(_x) , y(_y) @@ -32,6 +33,7 @@ struct vector2 struct uvector2 { + uvector2() : x (0), y (0) {} uvector2( ucoord_t _x, ucoord_t _y ) : x(_x) , y(_y) diff --git a/test/test.cpp b/test/test.cpp index 1306d1e..160f6bb 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -22,9 +22,35 @@ const char* tests() return "Unit IDs the same"; } + // Test basic invalid unit conversion + { + CUnit unit1; + + std::string unit1Desc = GetStringFromUnit(unit1); + CUnit unit2 = GetUnitFromString(unit1Desc); + + if ( unit1 != unit2 ) + return "Failed to convert an empty unit to string and back"; + } + + // Test custom unit conversion + { + CUnit unit1; + unit1.setFromVisual('v'); + unit1.setPlayer(0); + unit1.setTeam(Team::Green); + unit1.setPos( uvector2(5,10) ); + + std::string unit1Desc = GetStringFromUnit(unit1); + CUnit unit2 = GetUnitFromString(unit1Desc); + + if ( unit1 != unit2 ) + return "Failed to convert custom unit to string and back"; + } + // Test if we can successfully create a unit from a visual { - CUnit unit = CUnit::getUnitFromVis('v'); + CUnit unit = GetUnitFromVis('v'); if( unit.getVisual() != 'v' ) return "failed to properly create V unit with factory"; } @@ -56,7 +82,7 @@ const char* tests() CTTRTSGame game( 5, 5 ); { - CUnit unit = CUnit::getUnitFromVis('^'); + CUnit unit = GetUnitFromVis('^'); unit.setPos( {2,2} ); unit.setPlayer(0); unit.setTeam(Team::Red); @@ -65,7 +91,7 @@ const char* tests() } { - CUnit unit = CUnit::getUnitFromVis('^'); + CUnit unit = GetUnitFromVis('^'); unit.setPos( {2,2} ); unit.setPlayer(0); unit.setTeam(Team::Red); @@ -82,7 +108,7 @@ const char* tests() { CTTRTSGame game( 5, 5 ); - CUnit unit = CUnit::getUnitFromVis('>'); + CUnit unit = GetUnitFromVis('>'); const unit_id_t id = unit.getID(); COrder order; @@ -113,7 +139,7 @@ const char* tests() unit_id_t id; { - CUnit unit = CUnit::getUnitFromVis('>'); + CUnit unit = GetUnitFromVis('>'); id = unit.getID(); COrder order; @@ -131,7 +157,7 @@ const char* tests() return "Game failed to issue valid order"; } { - CUnit unit = CUnit::getUnitFromVis('<'); + CUnit unit = GetUnitFromVis('<'); unit.setPos( {1,0} ); unit.setPlayer(2);