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
Reference in a new issue