The AI class and it’s update method

The AI class contain all the stuff that’s needed for the AI to run its empire. At the moment it looks like this:

private Empire empire;
private Map<Integer, Map<Sector, InfluenceNode>> influenceMaps;
private ScoutAI scout;
private List<SettlementAI> governors;
private int newObjectiveId;
private List<Objective> objectives;
private Financial financialAdvisor;

// AI personality
Personality personality;

// List of all active tasks. Is emptied after they have been processed.
private List<Task> tasks;

// List of all requests from sub-AIs this turn. Is emptied after each turn.
private List<Request> requests;

// Constructor
public AI(Empire empire, Personality personality) {
	this.empire = empire;
	this.influenceMaps = new HashMap<Integer, Map<Sector, InfluenceNode>>();
	this.scout = new ScoutAI();
	this.governors = new ArrayList<SettlementAI>();
	this.newObjectiveId = 1;
	this.objectives = new ArrayList<Objective>();
	this.financialAdvisor = new Financial();
	this.personality = personality;
	this.tasks = new ArrayList<Task>();
	this.requests = new ArrayList<Request>();
// End constructor

As you can see it contain all the sub-AIs that we’ve previously covered here at the ‘Words from the Netherlords’. It also has a variable int newObjectiveId that is used to give each new objective a seperate id.

The AI is run as a seperate thread. This means that while the player looks at the results of his orders and issue new ones the AI for all computer controlled empires run their process in the background. When the player is ready to press the ‘end turn’-button the AI will, in most cases, be ready and the new turn can be processed right away. If the AI is still thinking the game let the AI complete before the new turn is processed.

It’s very important that all steps in method AI.update is done in the right order. First we start with clearing all old data from the previous turn. Then we update the influence map as this will be needed when the sub-AIs are processed. This can be called the preparations phase.

* This method updates the AI at the beginning of a new turn. It ends by executing all tasks.
public void update(World w, Data data) {
	// Clear data from last turn
	this.requests = new ArrayList<Request>();
	// Update influence maps
	LogWriter.outputAI(this.empire,"<h3>Updating influence maps</h3>");
	AIMethods.updateInfluenceMaps(this, w, data);

Now we’re are ready to run the first sub-AIs and we start with the scout AI as this will generate/update important knowledge about the world in general. When this is done we update all governors in settlement AIs (at the moment there is only one type so not much happens) and when this is ready we process each seperate settlement AI. Both the scout AI and the settlement AI work independently and uses their own resources, this is why we start with them.

	// Update scout AI and let it issue orders
	LogWriter.outputAI(this.empire,"<h3>Update scout AI</h3>");
	scout.update(w, this, data);
	// Update list of governors
	LogWriter.outputAI(this.empire,"<h3>Update list of settlement AIs</h3>");
	AIMethods.updateGovernors(this, w, data);
	// Update all settlement AIs and let them issue orders
	LogWriter.outputAI(this.empire,"<h3>Update settlement AI</h3>");
	for ( SettlementAI sai:governors ) {
		sai.update(w, this, data);

Now we come to all advisors. At the moment we have three advisors; financial, military and civilian. They each generate requests in their respective field. The financial advisor is more passive than the military and civilian advisors and its main task is to hold detailed economical facts about the empire. The military and civilian advisors take an active role in running the empire and issue requests as they see fit.

	// All advisors create their requests
	Civilian.advisor(w, this);
	Military.advisor(w, this);

As all sub-AIs and advisors that can generate requests has been run we come to the planner phase. This is the actual strategic AI which decide which request to respond to. Most of its decisions generate new objectives.

	// Analyze list of requests
	LogWriter.outputAI(this.empire,"<h3>Analyze list of requests</h3>");
	// Plan strategy:
	// This is an utility based AI that plans how the AI responds and decides what objectives
	// it will try to fulfill.
	LogWriter.outputAI(this.empire,"<h3>Strategy planner (utility based main AI)</h3>");

Each objective is a sub-AI in itself and the objective phase start with all objectives claiming armies and fleets that they need to fulfill their goal. When that’s completed each objective is processed and issue tasks to build new armies and move around them. When an objective is completed it will be removed.

	// Distribute uncontrolled armies and fleets to Objectives that need them.
	LogWriter.outputAI(this.empire,"<h3>Distribute un-claimed armies</h3>");
	// Process all Objectives and remove completed ones
	LogWriter.outputAI(this.empire,"<h3>Process all objectives</h3>");
	ObjectiveMethods.process(w, data, this);

The last thing is that we execute all tasks. Here the tactics AI of each army and asset by the empire transforms the tasks into real orders. A task might say that an army shall move towards a specific location, but here we decide exactly wich path it will take to reach its target location.

	// Patrol territory around settlements with un-claimed armies
	LogWriter.outputAI(this.empire,"<h3>Patrol with free armies</h3>");
	ScoutAIMethods.patrol(w, data, this);
	// Select new research if needed
	LogWriter.outputAI(this.empire,"<h3>Select new research projects</h3>");
	AIMethods.selectResearchProjects(data, this);
	// Execute all tasks
	LogWriter.outputAI(this.empire,"<h3>Execute all tasks</h3>");
	this.empire.setOrders(TaskMethods.executeTasks(w, data, this));

Here at the end we also issue tasks for patrol armies and update the research settings of the empire.

Leave a Reply