Differential D157 Diff 598 ps/trunk/binaries/data/mods/public/simulation/ai/petra/gameTypeManager.js
Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/binaries/data/mods/public/simulation/ai/petra/gameTypeManager.js
var PETRA = function(m) | var PETRA = function(m) | ||||
{ | { | ||||
/** | /** | ||||
* Handle events that are important to specific gameTypes | * Handle events that are important to specific gameTypes | ||||
* In regicide, train and manage healer guards for the hero | * In regicide, train and manage healer guards and military guards for the hero. | ||||
* TODO: Assign military units to guard the hero in regicide | |||||
*/ | */ | ||||
m.GameTypeManager = function(Config) | m.GameTypeManager = function(Config) | ||||
{ | { | ||||
this.Config = Config; | this.Config = Config; | ||||
this.criticalEnts = new Map(); | this.criticalEnts = new Map(); | ||||
// Holds ids of all ents who are (or can be) guarding and if the ent is currently guarding | // Holds ids of all ents who are (or can be) guarding and if the ent is currently guarding | ||||
this.guardEnts = new Map(); | this.guardEnts = new Map(); | ||||
Show All 19 Lines | if (gameState.getGameType() === "regicide") | ||||
for (let hero of heroEnts) | for (let hero of heroEnts) | ||||
{ | { | ||||
let heroStance = hero.hasClass("Soldier") ? "aggressive" : "passive"; | let heroStance = hero.hasClass("Soldier") ? "aggressive" : "passive"; | ||||
hero.setStance(heroStance); | hero.setStance(heroStance); | ||||
this.criticalEnts.set(hero.id(), { | this.criticalEnts.set(hero.id(), { | ||||
"garrisonEmergency": false, | "garrisonEmergency": false, | ||||
"stance": heroStance, | "stance": heroStance, | ||||
"healersAssigned": 0, | "healersAssigned": 0, | ||||
"guardsAssigned": 0, // for non-healer guards | |||||
"guards": new Map() // ids of ents who are currently guarding this hero | "guards": new Map() // ids of ents who are currently guarding this hero | ||||
}); | }); | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
/** | /** | ||||
* In regicide mode, if the hero has less than 70% health, try to garrison it in a healing structure | * In regicide mode, if the hero has less than 70% health, try to garrison it in a healing structure | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | for (let evt of events.Garrison) | ||||
if (hero.garrisonEmergency) | if (hero.garrisonEmergency) | ||||
hero.garrisonEmergency = false; | hero.garrisonEmergency = false; | ||||
let holderEnt = gameState.getEntityById(evt.holder); | let holderEnt = gameState.getEntityById(evt.holder); | ||||
if (!holderEnt || !holderEnt.hasClass("Ship")) | if (!holderEnt || !holderEnt.hasClass("Ship")) | ||||
continue; | continue; | ||||
// If the hero is garrisoned on a ship, remove its guards | // If the hero is garrisoned on a ship, remove its guards | ||||
for (let guardId of hero.guards) | for (let guardId of hero.guards.keys()) | ||||
{ | { | ||||
let guardEnt = gameState.getEntityById(guardId); | let guardEnt = gameState.getEntityById(guardId); | ||||
if (!guardEnt) | if (!guardEnt) | ||||
continue; | continue; | ||||
guardEnt.removeGuard(); | guardEnt.removeGuard(); | ||||
this.guardEnts.set(guardId, false); | this.guardEnts.set(guardId, false); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | m.GameTypeManager.prototype.buildWonder = function(gameState, queues) | ||||
if (!queues.wonder) | if (!queues.wonder) | ||||
gameState.ai.queueManager.addQueue("wonder", 1000); | gameState.ai.queueManager.addQueue("wonder", 1000); | ||||
queues.wonder.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_wonder")); | queues.wonder.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_wonder")); | ||||
}; | }; | ||||
/** | /** | ||||
* Try to keep some military units guarding any criticalEnts. | * Try to keep some military units guarding any criticalEnts. | ||||
* TODO: Prefer champion units, and swap citizen soldier guards with champions if they become available. | * TODO: Swap citizen soldier guards with champions if they become available. | ||||
*/ | */ | ||||
m.GameTypeManager.prototype.manageCriticalEntGuards = function(gameState) | m.GameTypeManager.prototype.manageCriticalEntGuards = function(gameState) | ||||
{ | { | ||||
for (let [id, data] of this.criticalEnts) | for (let [id, data] of this.criticalEnts) | ||||
{ | { | ||||
let criticalEnt = gameState.getEntityById(id); | let criticalEnt = gameState.getEntityById(id); | ||||
if (!criticalEnt) | if (!criticalEnt) | ||||
continue; | continue; | ||||
let militaryGuardsPerCriticalEnt = (criticalEnt.hasClass("Wonder") ? 10 : 4) + | let militaryGuardsPerCriticalEnt = (criticalEnt.hasClass("Wonder") ? 10 : 4) + | ||||
Math.round(this.Config.personality.defensive * 5); | Math.round(this.Config.personality.defensive * 5); | ||||
if (data.guardsAssigned >= militaryGuardsPerCriticalEnt) | if (data.guardsAssigned >= militaryGuardsPerCriticalEnt) | ||||
continue; | continue; | ||||
// First try to pick guards in the criticalEnt's accessIndex, to avoid unnecessary transports | // First try to pick guards in the criticalEnt's accessIndex, to avoid unnecessary transports | ||||
for (let checkForSameAccess of [true, false]) | for (let checkForSameAccess of [true, false]) | ||||
{ | { | ||||
for (let entity of gameState.ai.HQ.attackManager.outOfPlan.values()) | // First try to assign any Champion units we might have | ||||
for (let entity of gameState.getOwnEntitiesByClass("Champion", true).values()) | |||||
{ | { | ||||
if (entity.getMetadata(PlayerID, "transport") !== undefined || | if (!this.tryAssignMilitaryGuard(gameState, entity, criticalEnt, checkForSameAccess)) | ||||
checkForSameAccess && (!entity.position() || !criticalEnt.position() || | |||||
m.getLandAccess(gameState, criticalEnt) !== m.getLandAccess(gameState, entity))) | |||||
continue; | continue; | ||||
if (++data.guardsAssigned >= militaryGuardsPerCriticalEnt) | |||||
break; | |||||
} | |||||
if (!this.assignGuardToCriticalEnt(gameState, entity, id)) | if (data.guardsAssigned >= militaryGuardsPerCriticalEnt) | ||||
continue; | break; | ||||
entity.setMetadata(PlayerID, "plan", -2); | for (let entity of gameState.ai.HQ.attackManager.outOfPlan.values()) | ||||
entity.setMetadata(PlayerID, "role", "criticalEntGuard"); | { | ||||
if (!this.tryAssignMilitaryGuard(gameState, entity, criticalEnt, checkForSameAccess)) | |||||
continue; | |||||
if (++data.guardsAssigned >= militaryGuardsPerCriticalEnt) | if (++data.guardsAssigned >= militaryGuardsPerCriticalEnt) | ||||
break; | break; | ||||
} | } | ||||
if (data.guardsAssigned >= militaryGuardsPerCriticalEnt) | if (data.guardsAssigned >= militaryGuardsPerCriticalEnt) | ||||
break; | break; | ||||
for (let entity of gameState.getOwnEntitiesByClass("Soldier", true).values()) | for (let entity of gameState.getOwnEntitiesByClass("Soldier", true).values()) | ||||
{ | { | ||||
if (entity.getMetadata(PlayerID, "plan") !== undefined || | if (!this.tryAssignMilitaryGuard(gameState, entity, criticalEnt, checkForSameAccess)) | ||||
entity.getMetadata(PlayerID, "transport") !== undefined || | |||||
checkForSameAccess && (!entity.position() || !criticalEnt.position() || | |||||
m.getLandAccess(gameState, criticalEnt) !== m.getLandAccess(gameState, entity))) | |||||
continue; | |||||
if (!this.assignGuardToCriticalEnt(gameState, entity, id)) | |||||
continue; | continue; | ||||
entity.setMetadata(PlayerID, "plan", -2); | |||||
entity.setMetadata(PlayerID, "role", "criticalEntGuard"); | |||||
if (++data.guardsAssigned >= militaryGuardsPerCriticalEnt) | if (++data.guardsAssigned >= militaryGuardsPerCriticalEnt) | ||||
break; | break; | ||||
} | } | ||||
if (data.guardsAssigned >= militaryGuardsPerCriticalEnt) | if (data.guardsAssigned >= militaryGuardsPerCriticalEnt) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
m.GameTypeManager.prototype.tryAssignMilitaryGuard = function(gameState, guardEnt, criticalEnt, checkForSameAccess) | |||||
{ | |||||
if (guardEnt.getMetadata(PlayerID, "plan") !== undefined || | |||||
guardEnt.getMetadata(PlayerID, "transport") !== undefined || this.criticalEnts.has(guardEnt.id()) || | |||||
checkForSameAccess && (!guardEnt.position() || !criticalEnt.position() || | |||||
m.getLandAccess(gameState, criticalEnt) !== m.getLandAccess(gameState, guardEnt))) | |||||
return false; | |||||
if (!this.assignGuardToCriticalEnt(gameState, guardEnt, criticalEnt.id())) | |||||
return false; | |||||
guardEnt.setMetadata(PlayerID, "plan", -2); | |||||
guardEnt.setMetadata(PlayerID, "role", "criticalEntGuard"); | |||||
return true; | |||||
}; | |||||
m.GameTypeManager.prototype.pickCriticalEntRetreatLocation = function(gameState, criticalEnt, emergency) | m.GameTypeManager.prototype.pickCriticalEntRetreatLocation = function(gameState, criticalEnt, emergency) | ||||
{ | { | ||||
gameState.ai.HQ.defenseManager.garrisonAttackedUnit(gameState, criticalEnt, emergency); | gameState.ai.HQ.defenseManager.garrisonAttackedUnit(gameState, criticalEnt, emergency); | ||||
let plan = criticalEnt.getMetadata(PlayerID, "plan"); | let plan = criticalEnt.getMetadata(PlayerID, "plan"); | ||||
if (plan === -2 || plan === -3) | if (plan === -2 || plan === -3) | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | m.GameTypeManager.prototype.update = function(gameState, events, queues) | ||||
this.checkEvents(gameState, events); | this.checkEvents(gameState, events); | ||||
if (gameState.getGameType() === "wonder" && gameState.ai.playedTurn % 10 === 0) | if (gameState.getGameType() === "wonder" && gameState.ai.playedTurn % 10 === 0) | ||||
{ | { | ||||
this.buildWonder(gameState, queues); | this.buildWonder(gameState, queues); | ||||
this.manageCriticalEntGuards(gameState); | this.manageCriticalEntGuards(gameState); | ||||
} | } | ||||
if (gameState.getGameType() !== "regicide") | if (gameState.getGameType() === "regicide") | ||||
return; | { | ||||
if (gameState.ai.playedTurn % 10 === 0) | |||||
if (gameState.ai.playedTurn % 50 === 0) | { | ||||
for (let [id, data] of this.criticalEnts) | for (let [id, data] of this.criticalEnts) | ||||
{ | { | ||||
let ent = gameState.getEntityById(id); | let ent = gameState.getEntityById(id); | ||||
if (ent && ent.healthLevel() > 0.7 && ent.hasClass("Soldier") && | if (ent && ent.healthLevel() > 0.7 && ent.hasClass("Soldier") && | ||||
data.stance !== "aggressive") | data.stance !== "aggressive") | ||||
ent.setStance("aggressive"); | ent.setStance("aggressive"); | ||||
} | |||||
for (let [id, data] of this.criticalEnts) | |||||
if (data.healersAssigned < this.healersPerCriticalEnt && | if (data.healersAssigned < this.healersPerCriticalEnt && | ||||
this.guardEnts.size < gameState.getPopulationMax() / 10) | this.guardEnts.size < gameState.getPopulationMax() / 10) | ||||
this.trainCriticalEntHealer(gameState, queues, id); | this.trainCriticalEntHealer(gameState, queues, id); | ||||
} | |||||
// Assign military guards if we can afford it | |||||
if (gameState.getPopulation() > 30) | |||||
this.manageCriticalEntGuards(gameState); | |||||
} | |||||
} | |||||
}; | }; | ||||
m.GameTypeManager.prototype.Serialize = function() | m.GameTypeManager.prototype.Serialize = function() | ||||
{ | { | ||||
return { | return { | ||||
"criticalEnts": this.criticalEnts, | "criticalEnts": this.criticalEnts, | ||||
"guardEnts": this.guardEnts, | "guardEnts": this.guardEnts, | ||||
"healersPerCriticalEnt": this.healersPerCriticalEnt | "healersPerCriticalEnt": this.healersPerCriticalEnt | ||||
Show All 11 Lines |
Wildfire Games · Phabricator