Show ReferenceAI.cpp syntax highlighted
#include "ReferenceAI.h"
#include "../universe/Universe.h"
#include "../universe/Fleet.h"
#include "../universe/Ship.h"
#include "../universe/ShipDesign.h"
#include "../universe/System.h"
#include "../Empire/Empire.h"
#include "../util/AppInterface.h"
#include "../util/MultiplayerCommon.h"
#include <set>
ReferenceAI::ReferenceAI()
{}
void ReferenceAI::GenerateOrders()
{
Universe& universe = GetUniverse();
int empire_id = AIInterface::EmpireID();
Fleet* fleet;
// 1) Split stationary multi-ship fleets into multiple single-ship fleets
Universe::ObjectVec stat_fleets = universe.FindObjects(StationaryFleetVisitor(empire_id));
Universe::ObjectVec::iterator fleet_it;
for (fleet_it = stat_fleets.begin(); fleet_it != stat_fleets.end(); ++fleet_it) {
if(!(fleet = dynamic_cast<Fleet*>(*fleet_it))) continue;
// split fleet into single-ship fleets if it presently has more than one ship
if (fleet->NumShips() > 1) {
SplitFleet(fleet);
}
}
// 2) Give stationary fleets orders
stat_fleets = universe.FindObjects(StationaryFleetVisitor(empire_id)); // redo to get any newly created fleets from above
for (fleet_it = stat_fleets.begin(); fleet_it != stat_fleets.end(); ++fleet_it) {
if(!(fleet = dynamic_cast<Fleet*>(*fleet_it))) continue;
if (fleet->NumShips() < 1) continue; // shouldn't be possible... but to be safe...
// get ship, design
Ship* ship = universe.Object<Ship>(*(fleet->begin())); if (!ship) continue;
const ShipDesign *design = ship->Design();
// give orders according to type of ship in fleet
if (design->name == "Scout") {
Explore(fleet);
} else if (design->name == "Colony Ship") {
ColonizeSomewhere(fleet);
}
}
AIInterface::DoneTurn();
}
void ReferenceAI::HandleChatMessage(int sender_id, const std::string& msg)
{
}
void ReferenceAI::Explore(Fleet* fleet) {
if (!fleet) return;
Logger().debugStream() << "telling fleet to explore";
Universe& universe = GetUniverse();
int empire_id = AIInterface::EmpireID();
// ensure this player owns this fleet
const std::set<int>& owners = fleet->Owners();
if (owners.size() != 1 || *(owners.begin()) != empire_id) return; // don't own fleet
const Empire* empire = AIInterface::GetEmpire();
if (!empire) throw std::runtime_error("Couldn't get pointer to empire when telling fleet to Explore");
int start_id = fleet->SystemID(); // system where fleet is presently
Logger().debugStream() << "telling fleet to explore2";
// attempt to find an unexplored system that can be explored (fleet can get to)
std::vector<System*> systems = universe.FindObjects<System>();
for (std::vector<System*>::const_iterator system_it = systems.begin(); system_it != systems.end(); ++system_it) {
System* system = *system_it;
int dest_id = system->ID(); // system to go to
if (empire->HasExploredSystem(dest_id)) continue; // already explored system
if (m_fleet_exploration_targets_map.find(dest_id) != m_fleet_exploration_targets_map.end()) continue; // another fleet has been dispatched
Logger().debugStream() << "telling fleet to explore3";
// get path to destination. don't care that it's short, but just that it exists
std::list<System*> route = universe.ShortestPath(start_id, dest_id, empire_id).first;
if (route.empty()) continue; // can't get to system (with present starlanes knowledge)
Logger().debugStream() << "telling fleet to explore4";
// order ship to go ot system
AIInterface::IssueFleetMoveOrder(fleet->ID(), dest_id);
Logger().debugStream() << "telling fleet to explore5";
// mark system as targeted for exploration, so another ship isn't sent to it redundantly
m_fleet_exploration_targets_map.insert(std::pair<int, int>(dest_id, fleet->ID()));
return; // don't need to keep looping at this point
}
}
void ReferenceAI::ColonizeSomewhere(Fleet* fleet)
{
}
void ReferenceAI::SplitFleet(Fleet* fleet)
{
if (!fleet) return; // no fleet to process...
if (fleet->NumShips() < 2) return; // can't split fleet with one (or no?) ships
Universe& universe = GetUniverse();
int empire_id = AIInterface::EmpireID();
// ensure this player owns this fleet
const std::set<int>& owners = fleet->Owners();
if (owners.size() != 1 || *(owners.begin()) != empire_id) return; // don't own fleet
// starting with second ship, pick ships to transfer to new fleets
std::set<int> ship_ids_to_remove;
for (Fleet::iterator ship_it = ++(fleet->begin()); ship_it != fleet->end(); ++ship_it) {
Ship *ship = universe.Object<Ship>(*ship_it);
const std::set<int>& ship_owners = ship->Owners();
if (ship_owners.size() != 1 || *(ship_owners.begin()) != empire_id) continue; // don't own ship
ship_ids_to_remove.insert(*ship_it);
}
if (ship_ids_to_remove.empty()) return; // nothing more to do
// order transfers of ships from old fleet to new fleets
for (std::set<int>::iterator ship_it = ship_ids_to_remove.begin(); ship_it != ship_ids_to_remove.end(); ++ship_it) {
std::vector<int> ship_ids;
ship_ids.push_back(*ship_it);
std::string fleet_name = UserString("FW_NEW_FLEET_NAME");
AIInterface::IssueNewFleetOrder(fleet_name, ship_ids);
}
}
See more files for this project here