Change unit Attack behaviour to a charge
All charges on a turn are evaluated at the same time, step by step
This commit is contained in:
		
							parent
							
								
									4b37246e53
								
							
						
					
					
						commit
						3fc1f5ee5d
					
				
					 4 changed files with 156 additions and 59 deletions
				
			
		|  | @ -108,14 +108,12 @@ int CTTRTSGame::VerifyPos(uvector2 vec) const | |||
| // Get a units new position
 | ||||
| uvector2 CTTRTSGame::GetNewPosition( const OrderUnitPair& pair ) const | ||||
| { | ||||
| 
 | ||||
|     // Grab the order
 | ||||
|     switch ( pair.order.command) | ||||
|     { | ||||
|     // For forward orders, grab in front
 | ||||
|     case command_c::F: | ||||
|         return pair.unit.getInFront(); | ||||
|         break; | ||||
|     // For all other orders, just grab the old position
 | ||||
|     default: | ||||
|         return pair.unit.getPos(); | ||||
|  | @ -158,7 +156,6 @@ int CTTRTSGame::SimulateToNextTurn() | |||
|                 if ( possible ) | ||||
|                 { | ||||
|                     pair.unit.setPos(newpos); | ||||
|                     pair.order = COrder(); | ||||
|                 } | ||||
|             } | ||||
|             break; | ||||
|  | @ -167,60 +164,115 @@ int CTTRTSGame::SimulateToNextTurn() | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Vector of units to kill
 | ||||
|     std::vector< unit_id_t > toKill; | ||||
| 
 | ||||
|     // Attempt all actions
 | ||||
|     // Turn all units that need turning
 | ||||
|     for ( OrderUnitPair& pair : m_OrderUnitPairs ) | ||||
|     { | ||||
|         switch (  pair.order.command) | ||||
|         { | ||||
|         case command_c::A: | ||||
|             { | ||||
|                 // Verify that there's a unit in front to attack
 | ||||
|                 uvector2 infront = pair.unit.getInFront(); | ||||
| 
 | ||||
|                 // Check if there's any unit in front
 | ||||
|                 // FRIENDLY FIRE IS ENABLED
 | ||||
|                 for ( const OrderUnitPair& pair2 : m_OrderUnitPairs ) | ||||
|                 { | ||||
|                     // if the unit is infront of our unit, then add it to the kill list
 | ||||
|                     if( pair2.unit.getPos() == infront ) | ||||
|                     { | ||||
|                         toKill.push_back(pair2.unit.getID()); | ||||
|                         pair.order = COrder(); | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             break; | ||||
|         case command_c::L: | ||||
|             case command_c::L: | ||||
|             { | ||||
|                 // Simply turn left
 | ||||
|                 pair.unit.turnLeft(); | ||||
|                 pair.order = COrder(); | ||||
|             } | ||||
|             break; | ||||
|         case command_c::R: | ||||
|                 break; | ||||
|             case command_c::R: | ||||
|             { | ||||
|                 // Simply turn right
 | ||||
|                 pair.unit.turnRight(); | ||||
|                 pair.order = COrder(); | ||||
|             } | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|                 break; | ||||
|             default: | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Sort and erase all duplicates
 | ||||
|     std::sort( toKill.begin(), toKill.end() ); | ||||
|     toKill.erase( std::unique( toKill.begin(), toKill.end() ), toKill.end() ); | ||||
| 
 | ||||
|     // Iterate through all kill orders
 | ||||
|     for ( auto id : toKill ) | ||||
|     // Iterate through all charge states
 | ||||
|     bool charging = true; | ||||
|     while(charging) | ||||
|     { | ||||
|         // Assume no more charging
 | ||||
|         charging = false; | ||||
|         // Initially move all units
 | ||||
|         for ( OrderUnitPair& pair : m_OrderUnitPairs ) | ||||
|         { | ||||
|             if ( pair.order.command == command_c::A ) | ||||
|             { | ||||
|                 uvector2 newpos = pair.unit.getInFront(); | ||||
|                 // If move would be within the arena
 | ||||
|                 if ( ( newpos.x <= dimensions.x-1 ) && ( newpos.y <= dimensions.y-1 ) ) | ||||
|                 { | ||||
|                     pair.unit.setPos(newpos); | ||||
| 
 | ||||
|                     // Unit moved, so more charging needs to be done
 | ||||
|                     charging = true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         std::vector< unit_id_t > toKill; // Vector to store which units to kill
 | ||||
| 
 | ||||
|         // Initially move all units to check for pass through
 | ||||
|         for ( OrderUnitPair& pair1 : m_OrderUnitPairs ) | ||||
|         if ( pair1.order.command == command_c::A ) | ||||
|         for ( OrderUnitPair& pair2 : m_OrderUnitPairs ) | ||||
|         if ( pair1.unit.getID() != pair2.unit.getID() // Don't check the same units
 | ||||
|                 && pair2.order.command == command_c::A ) | ||||
|         { | ||||
|             if( CheckForPassThrough(pair1.unit,pair2.unit) ) | ||||
|             { | ||||
|                 toKill.push_back(pair1.unit.getID()); | ||||
|                 toKill.push_back(pair2.unit.getID()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Kill all units to kill
 | ||||
|         KillAll(toKill); | ||||
|         toKill.clear(); | ||||
| 
 | ||||
|         // Check for all matching spots
 | ||||
|         for ( OrderUnitPair& pair1 : m_OrderUnitPairs ) | ||||
|         for ( OrderUnitPair& pair2 : m_OrderUnitPairs ) | ||||
|         { | ||||
|             if( pair1.unit.getID() == pair2.unit.getID() ) continue; // Don't check the same units
 | ||||
| 
 | ||||
|             if( pair1.unit.getPos() ==  pair2.unit.getPos() ) | ||||
|             { | ||||
|                 if( pair1.order.command == command_c::A ) | ||||
|                 { | ||||
|                     toKill.push_back(pair2.unit.getID()); | ||||
|                 } | ||||
| 
 | ||||
|                 if( pair2.order.command == command_c::A ) | ||||
|                 { | ||||
|                     toKill.push_back(pair1.unit.getID()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Kill all units to kill
 | ||||
|         KillAll(toKill); | ||||
|         toKill.clear(); | ||||
|     } | ||||
| 
 | ||||
|     // Clear all orders
 | ||||
|     for ( OrderUnitPair& pair : m_OrderUnitPairs ) | ||||
|         pair.order = COrder(); | ||||
| 
 | ||||
|     // Increment the current turn
 | ||||
|     turn++; | ||||
| 
 | ||||
|     return error; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // Kill all units in list
 | ||||
| void CTTRTSGame::KillAll( std::vector< unit_id_t >& vec ) | ||||
| { | ||||
|     // Sort and erase all duplicates
 | ||||
|     std::sort( vec.begin(), vec.end() ); | ||||
|     vec.erase( std::unique( vec.begin(), vec.end() ), vec.end() ); | ||||
|     for ( auto id : vec ) | ||||
|     { | ||||
|         // Kill the units
 | ||||
|         for ( OrderUnitPairVector::iterator it = m_OrderUnitPairs.begin(); | ||||
|               it != m_OrderUnitPairs.end(); | ||||
|               it++ ) | ||||
|  | @ -230,21 +282,42 @@ int CTTRTSGame::SimulateToNextTurn() | |||
|                 // Remove the unit from our alive unit pairs
 | ||||
|                 m_OrderUnitPairs.erase(it); | ||||
|                 break; | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Check if two units passed through each other
 | ||||
| bool CTTRTSGame::CheckForPassThrough( const CUnit& one, const CUnit& two ) | ||||
| { | ||||
|     uvector2 pos1 = one.getPos(); | ||||
|     uvector2 pos2 = two.getPos(); | ||||
|     dir_t dir1 = one.getDir(); | ||||
|     dir_t dir2 = two.getDir(); | ||||
| 
 | ||||
|     if( pos1.x == pos2.x ) { // Same col
 | ||||
|         if (pos1.y == (pos2.y + 1)) { | ||||
|             if (dir1 == dir_t::N && dir2 == dir_t::S) | ||||
|                 return true; | ||||
|         } | ||||
|         else if (pos1.y == (pos2.y - 1)) { | ||||
|             if (dir1 == dir_t::S && dir2 == dir_t::N) | ||||
|                 return true; | ||||
|         } | ||||
|     } | ||||
|     else if( pos1.y == pos2.y ) { // Same row
 | ||||
|         if( pos1.x == (pos2.x+1) ) { | ||||
|             if( dir1 == dir_t::E && dir2 == dir_t::W ) | ||||
|                 return true; | ||||
|         } | ||||
|         else if( pos1.x == (pos2.x-1) ) { | ||||
|             if( dir1 == dir_t::E && dir2 == dir_t::W ) | ||||
|                 return true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	// Clear all orders
 | ||||
|     for ( OrderUnitPair& pair : m_OrderUnitPairs ) | ||||
|     { | ||||
|         pair.order = COrder(); | ||||
|     } | ||||
| 
 | ||||
|     // Increment the current turn
 | ||||
|     turn++; | ||||
| 
 | ||||
| 	return error; | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| // Add a unit, nonzero return value indicates error
 | ||||
|  | @ -301,7 +374,8 @@ int CTTRTSGame::VerifyOrder( Team team, const COrder& order ) const | |||
|     for ( const OrderUnitPair& pair : m_OrderUnitPairs ) | ||||
| 	{ | ||||
|         // Accept if we have the unit
 | ||||
|         if ( pair.unit.getID() == unitID ) | ||||
|         if ( pair.unit.getID() == unitID | ||||
|                 && pair.unit.getTeam() == team ) | ||||
| 		{ | ||||
|             ret = 0; | ||||
| 			break; | ||||
|  | @ -318,7 +392,7 @@ const CUnit& CTTRTSGame::GetUnitByIDConst( unit_id_t id ) const | |||
|     for ( const OrderUnitPair& pair : m_OrderUnitPairs ) | ||||
|     { | ||||
|         // Attempt the unit add
 | ||||
|         if ( pair.unit.getID()  ) | ||||
|         if ( pair.unit.getID() == id  ) | ||||
|             return pair.unit; | ||||
|     } | ||||
| 
 | ||||
|  | @ -327,13 +401,28 @@ const CUnit& CTTRTSGame::GetUnitByIDConst( unit_id_t id ) const | |||
|     return invalid_unit; | ||||
| } | ||||
| 
 | ||||
| // Get an order by unit ID
 | ||||
| const COrder& CTTRTSGame::GetOrderByIDConst( unit_id_t id ) const | ||||
| { | ||||
|     for ( const OrderUnitPair& pair : m_OrderUnitPairs ) | ||||
|     { | ||||
|         // Attempt the unit add
 | ||||
|         if ( pair.unit.getID() == id  ) | ||||
|             return pair.order; | ||||
|     } | ||||
| 
 | ||||
|     // Return an invalid unit
 | ||||
|     static COrder invalid_order; | ||||
|     return invalid_order; | ||||
| } | ||||
| 
 | ||||
| // Get unit by unit ID
 | ||||
| CUnit& CTTRTSGame::GetUnitByID( unit_id_t id ) | ||||
| { | ||||
|     for ( OrderUnitPair& pair : m_OrderUnitPairs ) | ||||
|     { | ||||
|         // Attempt the unit add
 | ||||
|         if ( pair.unit.getID()  ) | ||||
|         if ( pair.unit.getID() == id ) | ||||
|             return pair.unit; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -85,6 +85,7 @@ public: | |||
| 
 | ||||
|     // Get a unit by it's ID
 | ||||
|     const CUnit& GetUnitByIDConst( unit_id_t id ) const; | ||||
|     const COrder& GetOrderByIDConst( unit_id_t id ) const; | ||||
| 
 | ||||
|     // Get dimensions
 | ||||
|     inline const uvector2 &GetDimensions() const { return dimensions; } | ||||
|  | @ -100,7 +101,7 @@ public: | |||
| 
 | ||||
|     // Get a vector of the teams in the current game
 | ||||
|     std::vector<Team> GetTeams() const; | ||||
| 	 | ||||
| 
 | ||||
| private: | ||||
| 
 | ||||
|     // Verify any order or position - non-zero is error
 | ||||
|  | @ -110,6 +111,12 @@ private: | |||
|     // Get a units new position after an order
 | ||||
|     uvector2 GetNewPosition( const OrderUnitPair& pair ) const; | ||||
| 
 | ||||
|     // Check for a pass through
 | ||||
|     static bool CheckForPassThrough( const CUnit& one, const CUnit& two ); | ||||
| 
 | ||||
|     // Kill all units in list
 | ||||
|     void KillAll( std::vector< unit_id_t >& vec ); | ||||
| 
 | ||||
|     // Get unit by unit ID
 | ||||
|     CUnit& GetUnitByID( unit_id_t id ); | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,10 +11,10 @@ | |||
| // Type for all orders ( as a char )
 | ||||
| enum class command_c : char | ||||
| { | ||||
|     F = 'F', | ||||
|     L = 'L', | ||||
|     R = 'R', | ||||
|     A = 'A', | ||||
|     F = 'F', // Move forward one square
 | ||||
|     L = 'L', // Turn left
 | ||||
|     R = 'R', // Turn right
 | ||||
|     A = 'A', // Attack forwards until a unit or edge of the arena is hit
 | ||||
|     NUM_INVALID | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -87,6 +87,7 @@ private: | |||
| 
 | ||||
| // Typedef for a vector of units
 | ||||
| typedef std::vector< CUnit > CUnitVector; | ||||
| typedef std::vector< unit_id_t > CUnitIDVector; | ||||
| 
 | ||||
| // Simple validation
 | ||||
| inline bool CUnit::valid() const | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue