Skip to content
This repository has been archived by the owner on Apr 14, 2020. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Jenkins committed Jan 14, 2020
2 parents b460435 + 96e2b53 commit e9b70d5
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 70 deletions.
99 changes: 44 additions & 55 deletions source/AI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,22 +276,18 @@ void AI::IssueMoveTarget(const PlayerInfo &player, const Point &target, const Sy


// Commands issued via the keyboard (mostly, to the flagship).
void AI::UpdateKeys(PlayerInfo &player, Command &clickCommands, bool isActive)
void AI::UpdateKeys(PlayerInfo &player, Command &activeCommands, bool isActive)
{
shift = (SDL_GetModState() & KMOD_SHIFT);
escortsUseAmmo = Preferences::Has("Escorts expend ammo");
escortsAreFrugal = Preferences::Has("Escorts use ammo frugally");

Command oldHeld = keyHeld;
keyHeld.ReadKeyboard();
autoPilot |= clickCommands;
clickCommands.Clear();
keyDown = keyHeld.AndNot(oldHeld);
if(keyHeld.Has(AutopilotCancelCommands()))
autoPilot |= activeCommands;
if(activeCommands.Has(AutopilotCancelCommands()))
{
bool canceled = (autoPilot.Has(Command::JUMP) && !keyHeld.Has(Command::JUMP));
canceled |= (autoPilot.Has(Command::LAND) && !keyHeld.Has(Command::LAND));
canceled |= (autoPilot.Has(Command::BOARD) && !keyHeld.Has(Command::BOARD));
bool canceled = (autoPilot.Has(Command::JUMP) && !activeCommands.Has(Command::JUMP));
canceled |= (autoPilot.Has(Command::LAND) && !activeCommands.Has(Command::LAND));
canceled |= (autoPilot.Has(Command::BOARD) && !activeCommands.Has(Command::BOARD));
if(canceled)
Messages::Add("Disengaging autopilot.");
autoPilot.Clear();
Expand All @@ -301,12 +297,8 @@ void AI::UpdateKeys(PlayerInfo &player, Command &clickCommands, bool isActive)
if(!isActive || !flagship || flagship->IsDestroyed())
return;

++landKeyInterval;
if(oldHeld.Has(Command::LAND))
landKeyInterval = 0;

// Only toggle the "cloak" command if one of your ships has a cloaking device.
if(keyDown.Has(Command::CLOAK))
if(activeCommands.Has(Command::CLOAK))
for(const auto &it : player.Ships())
if(!it->IsParked() && it->Attributes().Get("cloak"))
{
Expand All @@ -316,15 +308,15 @@ void AI::UpdateKeys(PlayerInfo &player, Command &clickCommands, bool isActive)
}

// Toggle your secondary weapon.
if(keyDown.Has(Command::SELECT))
if(activeCommands.Has(Command::SELECT))
player.SelectNext();

// The commands below here only apply if you have escorts or fighters.
if(player.Ships().size() < 2)
return;

// Only toggle the "deploy" command if one of your ships has fighter bays.
if(keyDown.Has(Command::DEPLOY))
if(activeCommands.Has(Command::DEPLOY))
for(const auto &it : player.Ships())
if(it->HasBays())
{
Expand All @@ -335,23 +327,24 @@ void AI::UpdateKeys(PlayerInfo &player, Command &clickCommands, bool isActive)

shared_ptr<Ship> target = flagship->GetTargetShip();
Orders newOrders;
if(keyDown.Has(Command::FIGHT) && target && !target->IsYours())
if(activeCommands.Has(Command::FIGHT) && target && !target->IsYours())
{
newOrders.type = target->IsDisabled() ? Orders::FINISH_OFF : Orders::ATTACK;
newOrders.target = target;
IssueOrders(player, newOrders, "focusing fire on \"" + target->Name() + "\".");
}
if(keyDown.Has(Command::HOLD))
if(activeCommands.Has(Command::HOLD))
{
newOrders.type = Orders::HOLD_POSITION;
IssueOrders(player, newOrders, "holding position.");
}
if(keyDown.Has(Command::GATHER))
if(activeCommands.Has(Command::GATHER))
{
newOrders.type = Orders::GATHER;
newOrders.target = player.FlagshipPtr();
IssueOrders(player, newOrders, "gathering around your flagship.");
}

// Get rid of any invalid orders. Carried ships will retain orders in case they are deployed.
for(auto it = orders.begin(); it != orders.end(); )
{
Expand Down Expand Up @@ -428,7 +421,7 @@ void AI::ClearOrders()



void AI::Step(const PlayerInfo &player)
void AI::Step(const PlayerInfo &player, Command &activeCommands)
{
// First, figure out the comparative strengths of the present governments.
const System *playerSystem = player.GetSystem();
Expand Down Expand Up @@ -469,7 +462,7 @@ void AI::Step(const PlayerInfo &player)

if(it.get() == flagship)
{
MovePlayer(*it, player);
MovePlayer(*it, player, activeCommands);
continue;
}

Expand Down Expand Up @@ -3003,7 +2996,7 @@ double AI::RendezvousTime(const Point &p, const Point &v, double vp)



void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
void AI::MovePlayer(Ship &ship, const PlayerInfo &player, Command &activeCommands)
{
Command command;

Expand Down Expand Up @@ -3092,7 +3085,7 @@ void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
ship.SetTargetStellar(system->FindStellar(bestDestination));
}

if(keyDown.Has(Command::NEAREST))
if(activeCommands.Has(Command::NEAREST))
{
// Find the nearest ship to the flagship. If `Shift` is held, consider friendly ships too.
double closest = numeric_limits<double>::infinity();
Expand Down Expand Up @@ -3138,7 +3131,7 @@ void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
}
}
}
else if(keyDown.Has(Command::TARGET))
else if(activeCommands.Has(Command::TARGET))
{
// Find the "next" ship to target. Holding `Shift` will cycle through escorts.
shared_ptr<const Ship> target = ship.GetTargetShip();
Expand All @@ -3164,7 +3157,7 @@ void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
if(selectNext)
ship.SetTargetShip(shared_ptr<Ship>());
}
else if(keyDown.Has(Command::BOARD))
else if(activeCommands.Has(Command::BOARD))
{
// Board the nearest disabled ship, focusing on hostiles before allies. Holding
// `Shift` results in boarding only player-owned escorts in need of assistance.
Expand Down Expand Up @@ -3194,10 +3187,10 @@ void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
}
}
if(!foundAnything)
keyDown.Clear(Command::BOARD);
activeCommands.Clear(Command::BOARD);
}
}
else if(keyDown.Has(Command::LAND) && !ship.IsEnteringHyperspace())
else if(activeCommands.Has(Command::LAND) && !ship.IsEnteringHyperspace())
{
// Track all possible landable objects in the current system.
auto landables = vector<const StellarObject *>{};
Expand Down Expand Up @@ -3231,7 +3224,7 @@ void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
// selected, then press "land" again, do not toggle to the other if
// you are within landing range of the one you have selected.
}
else if(message.empty() && target && landKeyInterval < 60)
else if(message.empty() && target && activeCommands.Has(Command::WAIT))
{
// Select the next landable in the list after the currently selected object.
if(++landIt == landables.cend())
Expand Down Expand Up @@ -3311,7 +3304,7 @@ void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
if(!message.empty())
Messages::Add(message);
}
else if(keyDown.Has(Command::JUMP))
else if(activeCommands.Has(Command::JUMP))
{
if(!ship.GetTargetSystem() && !isWormhole)
{
Expand Down Expand Up @@ -3344,30 +3337,30 @@ void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
Messages::Add("Engaging autopilot to jump to the " + name + " system.");
}
}
else if(keyHeld.Has(Command::SCAN))
else if(activeCommands.Has(Command::SCAN))
command |= Command::SCAN;

const shared_ptr<const Ship> target = ship.GetTargetShip();
AimTurrets(ship, command, !Preferences::Has("Turrets focus fire"));
if(Preferences::Has("Automatic firing") && !ship.IsBoarding()
&& !(autoPilot | keyHeld).Has(Command::LAND | Command::JUMP | Command::BOARD)
&& !(autoPilot | activeCommands).Has(Command::LAND | Command::JUMP | Command::BOARD)
&& (!target || target->GetGovernment()->IsEnemy()))
AutoFire(ship, command, false);
if(keyHeld)
if(activeCommands)
{
if(keyHeld.Has(Command::FORWARD))
if(activeCommands.Has(Command::FORWARD))
command |= Command::FORWARD;
if(keyHeld.Has(Command::RIGHT | Command::LEFT))
command.SetTurn(keyHeld.Has(Command::RIGHT) - keyHeld.Has(Command::LEFT));
if(keyHeld.Has(Command::BACK))
if(activeCommands.Has(Command::RIGHT | Command::LEFT))
command.SetTurn(activeCommands.Has(Command::RIGHT) - activeCommands.Has(Command::LEFT));
if(activeCommands.Has(Command::BACK))
{
if(!keyHeld.Has(Command::FORWARD) && ship.Attributes().Get("reverse thrust"))
if(!activeCommands.Has(Command::FORWARD) && ship.Attributes().Get("reverse thrust"))
command |= Command::BACK;
else if(!keyHeld.Has(Command::RIGHT | Command::LEFT))
else if(!activeCommands.Has(Command::RIGHT | Command::LEFT))
command.SetTurn(TurnBackward(ship));
}

if(keyHeld.Has(Command::PRIMARY))
if(activeCommands.Has(Command::PRIMARY))
{
int index = 0;
for(const Hardpoint &hardpoint : ship.Weapons())
Expand All @@ -3377,7 +3370,7 @@ void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
++index;
}
}
if(keyHeld.Has(Command::SECONDARY))
if(activeCommands.Has(Command::SECONDARY))
{
int index = 0;
for(const Hardpoint &hardpoint : ship.Weapons())
Expand All @@ -3387,15 +3380,15 @@ void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
++index;
}
}
if(keyHeld.Has(Command::AFTERBURNER))
if(activeCommands.Has(Command::AFTERBURNER))
command |= Command::AFTERBURNER;

if(keyHeld.Has(AutopilotCancelCommands()))
autoPilot = keyHeld;
if(activeCommands.Has(AutopilotCancelCommands()))
autoPilot = activeCommands;
}
bool shouldAutoAim = false;
if(Preferences::Has("Automatic aiming") && !command.Turn() && !ship.IsBoarding()
&& (Preferences::Has("Automatic firing") || keyHeld.Has(Command::PRIMARY))
&& (Preferences::Has("Automatic firing") || activeCommands.Has(Command::PRIMARY))
&& ((target && target->GetSystem() == ship.GetSystem() && target->IsTargetable())
|| ship.GetTargetAsteroid())
&& !autoPilot.Has(Command::LAND | Command::JUMP | Command::BOARD))
Expand All @@ -3415,7 +3408,7 @@ void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
command.SetTurn(TurnToward(ship, TargetAim(ship)));
}

if(autoPilot.Has(Command::JUMP) && !player.HasTravelPlan())
if(autoPilot.Has(Command::JUMP) && !(player.HasTravelPlan() || ship.GetTargetSystem()))
{
// The player completed their travel plan, which may have indicated a destination within the final system.
autoPilot.Clear(Command::JUMP);
Expand All @@ -3439,7 +3432,7 @@ void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
if(autoPilot.Has(Command::LAND) || (autoPilot.Has(Command::JUMP) && isWormhole))
{
if(ship.GetPlanet())
autoPilot.Clear();
autoPilot.Clear(Command::LAND | Command::JUMP);
else
{
MoveToPlanet(ship, command);
Expand All @@ -3448,33 +3441,29 @@ void AI::MovePlayer(Ship &ship, const PlayerInfo &player)
}
else if(autoPilot.Has(Command::JUMP))
{
bool isNewPress = keyDown.Has(Command::JUMP) || !keyHeld.Has(Command::JUMP);
if(!ship.Attributes().Get("hyperdrive") && !ship.Attributes().Get("jump drive"))
{
Messages::Add("You do not have a hyperdrive installed.");
autoPilot.Clear();
if(isNewPress)
Audio::Play(Audio::Get("fail"));
Audio::Play(Audio::Get("fail"));
}
else if(!ship.JumpFuel(ship.GetTargetSystem()))
{
Messages::Add("You cannot jump to the selected system.");
autoPilot.Clear();
if(isNewPress)
Audio::Play(Audio::Get("fail"));
Audio::Play(Audio::Get("fail"));
}
else if(!ship.JumpsRemaining() && !ship.IsEnteringHyperspace())
{
Messages::Add("You do not have enough fuel to make a hyperspace jump.");
autoPilot.Clear();
if(isNewPress)
Audio::Play(Audio::Get("fail"));
Audio::Play(Audio::Get("fail"));
}
else
{
PrepareForHyperspace(ship, command);
command |= Command::JUMP;
if(keyHeld.Has(Command::JUMP))
if(activeCommands.Has(Command::WAIT))
command |= Command::WAIT;
}
}
Expand Down
10 changes: 2 additions & 8 deletions source/AI.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ template <class Type>
// but not when they jump from one system to another.
void ClearOrders();
// Issue AI commands to all ships for one game step.
void Step(const PlayerInfo &player);
void Step(const PlayerInfo &player, Command &activeCommands);

// Get the in-system strength of each government's allies and enemies.
int64_t AllyStrength(const Government *government);
Expand Down Expand Up @@ -133,7 +133,7 @@ template <class Type>
// projectile. If it cannot hit the target, this returns NaN.
static double RendezvousTime(const Point &p, const Point &v, double vp);

void MovePlayer(Ship &ship, const PlayerInfo &player);
void MovePlayer(Ship &ship, const PlayerInfo &player, Command &activeCommands);

// True if the ship performed the indicated event to the other ship.
bool Has(const Ship &ship, const std::weak_ptr<const Ship> &other, int type) const;
Expand Down Expand Up @@ -183,10 +183,6 @@ template <class Type>
// helps limit how often certain actions occur (such as changing targets).
int step = 0;

// Commands that are newly active for this step.
Command keyDown;
// Commands that are active for this step.
Command keyHeld;
// Command applied by the player's "autopilot."
Command autoPilot;

Expand All @@ -197,8 +193,6 @@ template <class Type>

bool escortsAreFrugal = true;
bool escortsUseAmmo = true;
// Pressing "land" rapidly toggles targets; pressing it once re-engages landing.
int landKeyInterval = 0;

// Current orders for the player's ships. Because this map only applies to
// player ships, which are never deleted except when landed, it can use
Expand Down
8 changes: 8 additions & 0 deletions source/Command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,14 @@ bool Command::Has(Command command) const



// Get the commands that are set in this and in the given command.
Command Command::And(Command command) const
{
return Command(state & command.state);
}



// Get the commands that are set in this and not in the given command.
Command Command::AndNot(Command command) const
{
Expand Down
10 changes: 8 additions & 2 deletions source/Command.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,12 @@ class Command {
static const Command GATHER;
static const Command HOLD;
static const Command AMMO;
// This command from the AI tells a ship not to jump or land yet even if it
// is in position to do so. (There is no key mapped to this command.)
// This command is given in combination with JUMP or LAND and tells a ship
// not to jump or land yet even if it is in position to do so. It can be
// given from the AI when a ship is waiting for its parent. It can also be
// given from the player/input engine when the player is preparing his/her
// fleet for jumping or to indicate that the player is switching landing
// targets. (There is no explicit key mapped to this command.)
static const Command WAIT;
// This command from the AI tells a ship that if possible, it should apply
// less than its full thrust in order to come to a complete stop.
Expand Down Expand Up @@ -93,6 +97,8 @@ class Command {
void Clear(Command command);
void Set(Command command);
bool Has(Command command) const;
// Get the commands that are set in this and in the given command.
Command And(Command command) const;
// Get the commands that are set in this and not in the given command.
Command AndNot(Command command) const;

Expand Down
Loading

0 comments on commit e9b70d5

Please sign in to comment.