Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/ai/petra/navalManager.js
Show All 32 Lines | m.NavalManager = function(Config) | ||||
// shore-line regions where we can load and unload units | // shore-line regions where we can load and unload units | ||||
this.landingZones = {}; | this.landingZones = {}; | ||||
}; | }; | ||||
/** More initialisation for stuff that needs the gameState */ | /** More initialisation for stuff that needs the gameState */ | ||||
m.NavalManager.prototype.init = function(gameState, deserializing) | m.NavalManager.prototype.init = function(gameState, deserializing) | ||||
{ | { | ||||
// finished docks | // docks | ||||
this.docks = gameState.getOwnStructures().filter(API3.Filters.and(API3.Filters.byClassesOr(["Dock", "Shipyard"]), | this.docks = gameState.getOwnStructures().filter(API3.Filters.byClassesOr(["Dock", "Shipyard"])); | ||||
API3.Filters.not(API3.Filters.isFoundation()))); | |||||
this.docks.registerUpdates(); | this.docks.registerUpdates(); | ||||
this.ships = gameState.getOwnUnits().filter(API3.Filters.and(API3.Filters.byClass("Ship"), API3.Filters.not(API3.Filters.byMetadata(PlayerID, "role", "trader")))); | this.ships = gameState.getOwnUnits().filter(API3.Filters.and(API3.Filters.byClass("Ship"), API3.Filters.not(API3.Filters.byMetadata(PlayerID, "role", "trader")))); | ||||
// note: those two can overlap (some transport ships are warships too and vice-versa). | // note: those two can overlap (some transport ships are warships too and vice-versa). | ||||
this.transportShips = this.ships.filter(API3.Filters.and(API3.Filters.byCanGarrison(), API3.Filters.not(API3.Filters.byClass("FishingBoat")))); | this.transportShips = this.ships.filter(API3.Filters.and(API3.Filters.byCanGarrison(), API3.Filters.not(API3.Filters.byClass("FishingBoat")))); | ||||
this.warShips = this.ships.filter(API3.Filters.byClass("Warship")); | this.warShips = this.ships.filter(API3.Filters.byClass("Warship")); | ||||
this.fishShips = this.ships.filter(API3.Filters.byClass("FishingBoat")); | this.fishShips = this.ships.filter(API3.Filters.byClass("FishingBoat")); | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | else | ||||
this.wantedFishShips.push(this.Config.Economy.targetNumFishers); | this.wantedFishShips.push(this.Config.Economy.targetNumFishers); | ||||
else | else | ||||
this.wantedFishShips.push(0); | this.wantedFishShips.push(0); | ||||
this.neededTransportShips.push(0); | this.neededTransportShips.push(0); | ||||
this.neededWarShips.push(0); | this.neededWarShips.push(0); | ||||
} | } | ||||
} | } | ||||
// load units and buildings from the config files | |||||
let civ = gameState.getPlayerCiv(); | |||||
if (civ in this.Config.buildings.naval) | |||||
this.bNaval = this.Config.buildings.naval[civ]; | |||||
else | |||||
this.bNaval = this.Config.buildings.naval['default']; | |||||
for (let i in this.bNaval) | |||||
this.bNaval[i] = gameState.applyCiv(this.bNaval[i]); | |||||
if (deserializing) | if (deserializing) | ||||
return; | return; | ||||
// determination of the possible landing zones | // determination of the possible landing zones | ||||
let width = gameState.getPassabilityMap().width; | let width = gameState.getPassabilityMap().width; | ||||
let length = width * gameState.getPassabilityMap().height; | let length = width * gameState.getPassabilityMap().height; | ||||
for (let i = 0; i < length; ++i) | for (let i = 0; i < length; ++i) | ||||
{ | { | ||||
Show All 39 Lines | for (let sea in this.landingZones[land]) | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Assign our initial docks and ships | // Assign our initial docks and ships | ||||
for (let ship of this.ships.values()) | for (let ship of this.ships.values()) | ||||
this.setShipIndex(gameState, ship); | this.setShipIndex(gameState, ship); | ||||
for (let dock of this.docks.values()) | for (let dock of this.docks.values()) | ||||
this.setAccessIndices(gameState, dock); | this.setAccessIndices(gameState, dock); | ||||
Sandarac: You switch `this.docks` to include docks that are foundations, but there is still the loop here… | |||||
Not Done Inline Actionsi agree, but it is called twice only for those foundations available at startup (so usually never happens). The main reason of this change was that now getUnconnectedSeas now also takes into account dock foundations (which was not the case before) and which i think is better. But your comment let me realize that it supposes that accesses are already set. mimo: i agree, but it is called twice only for those foundations available at startup (so usually… | |||||
}; | }; | ||||
m.NavalManager.prototype.updateFishingBoats = function(sea, num) | m.NavalManager.prototype.updateFishingBoats = function(sea, num) | ||||
{ | { | ||||
if (this.wantedFishShips[sea]) | if (this.wantedFishShips[sea]) | ||||
this.wantedFishShips[sea] = num; | this.wantedFishShips[sea] = num; | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | return around.every(a => | ||||
return true; | return true; | ||||
}); | }); | ||||
}; | }; | ||||
/** get the list of seas (or lands) around this region not connected by a dock */ | /** get the list of seas (or lands) around this region not connected by a dock */ | ||||
m.NavalManager.prototype.getUnconnectedSeas = function(gameState, region) | m.NavalManager.prototype.getUnconnectedSeas = function(gameState, region) | ||||
{ | { | ||||
let seas = gameState.ai.accessibility.regionLinks[region].slice(); | let seas = gameState.ai.accessibility.regionLinks[region].slice(); | ||||
let docks = gameState.getOwnStructures().filter(API3.Filters.byClass("Dock")); | this.docks.forEach(function (dock) { | ||||
docks.forEach(function (dock) { | if (!dock.hasClass("Dock") || dock.getMetadata(PlayerID, "access") !== region) | ||||
if (dock.getMetadata(PlayerID, "access") !== region) | |||||
return; | return; | ||||
let i = seas.indexOf(dock.getMetadata(PlayerID, "sea")); | let i = seas.indexOf(dock.getMetadata(PlayerID, "sea")); | ||||
if (i !== -1) | if (i !== -1) | ||||
seas.splice(i--,1); | seas.splice(i--,1); | ||||
}); | }); | ||||
return seas; | return seas; | ||||
}; | }; | ||||
Show All 33 Lines | for (let evt of events.Destroy) | ||||
let shipId = evt.entityObj.id(); | let shipId = evt.entityObj.id(); | ||||
if (this.Config.debug > 1) | if (this.Config.debug > 1) | ||||
API3.warn("one ship " + shipId + " from plan " + plan.ID + " destroyed during " + plan.state); | API3.warn("one ship " + shipId + " from plan " + plan.ID + " destroyed during " + plan.state); | ||||
if (plan.state === "boarding") | if (plan.state === "boarding") | ||||
{ | { | ||||
// just reset the units onBoard metadata and wait for a new ship to be assigned to this plan | // just reset the units onBoard metadata and wait for a new ship to be assigned to this plan | ||||
plan.units.forEach(function (ent) { | plan.units.forEach(function (ent) { | ||||
if ((ent.getMetadata(PlayerID, "onBoard") === "onBoard" && ent.position()) || | if (ent.getMetadata(PlayerID, "onBoard") === "onBoard" && ent.position() || | ||||
ent.getMetadata(PlayerID, "onBoard") === shipId) | ent.getMetadata(PlayerID, "onBoard") === shipId) | ||||
ent.setMetadata(PlayerID, "onBoard", undefined); | ent.setMetadata(PlayerID, "onBoard", undefined); | ||||
}); | }); | ||||
plan.needTransportShips = !plan.transportShips.hasEntities(); | plan.needTransportShips = !plan.transportShips.hasEntities(); | ||||
} | } | ||||
else if (plan.state === "sailing") | else if (plan.state === "sailing") | ||||
{ | { | ||||
let endIndex = plan.endIndex; | let endIndex = plan.endIndex; | ||||
let self = this; | let self = this; | ||||
▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Lines | for (let sea = 0; sea < this.neededTransportShips.length; sea++) | ||||
if (this.neededTransportShips[sea] > 2) | if (this.neededTransportShips[sea] > 2) | ||||
++this.wantedTransportShips[sea]; | ++this.wantedTransportShips[sea]; | ||||
}; | }; | ||||
m.NavalManager.prototype.maintainFleet = function(gameState, queues) | m.NavalManager.prototype.maintainFleet = function(gameState, queues) | ||||
{ | { | ||||
if (queues.ships.hasQueuedUnits()) | if (queues.ships.hasQueuedUnits()) | ||||
return; | return; | ||||
if (!gameState.getOwnEntitiesByClass("Dock", true).filter(API3.Filters.isBuilt()).hasEntities() && | if (!this.docks.filter(API3.Filters.isBuilt()).hasEntities()) | ||||
!gameState.getOwnEntitiesByClass("Shipyard", true).filter(API3.Filters.isBuilt()).hasEntities()) | |||||
return; | return; | ||||
// check if we have enough transport ships per region. | // check if we have enough transport ships per region. | ||||
for (let sea = 0; sea < this.seaShips.length; ++sea) | for (let sea = 0; sea < this.seaShips.length; ++sea) | ||||
{ | { | ||||
if (this.seaShips[sea] === undefined) | if (this.seaShips[sea] === undefined) | ||||
continue; | continue; | ||||
if (gameState.countOwnQueuedEntitiesWithMetadata("sea", sea) > 0) | if (gameState.countOwnQueuedEntitiesWithMetadata("sea", sea) > 0) | ||||
continue; | continue; | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | if (queues.dock.countQueuedUnitsWithClass("NavalMarket") === 0 && | ||||
dockStarted = true; | dockStarted = true; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (gameState.currentPhase() < 2 || gameState.getPopulation() < this.Config.Economy.popForTown + 15 || | if (gameState.currentPhase() < 2 || gameState.getPopulation() < this.Config.Economy.popForTown + 15 || | ||||
queues.militaryBuilding.hasQueuedUnits() || this.bNaval.length === 0) | queues.militaryBuilding.hasQueuedUnits()) | ||||
return; | return; | ||||
let docks = gameState.getOwnStructures().filter(API3.Filters.byClass("Dock")); | if (!this.docks.filter(API3.Filters.byClass("Dock")).hasEntities() || | ||||
if (!docks.hasEntities()) | this.docks.filter(API3.Filters.byClass("Shipyard")).hasEntities()) | ||||
return; | |||||
let template; | |||||
if (gameState.ai.HQ.canBuild(gameState, "structures/{civ}_super_dock")) | |||||
template = "structures/{civ}_super_dock"; | |||||
else if (gameState.ai.HQ.canBuild(gameState, "structures/{civ}_shipyard")) | |||||
template = "structures/{civ}_shipyard"; | |||||
else | |||||
return; | return; | ||||
let nNaval = 0; | |||||
for (let naval of this.bNaval) | |||||
nNaval += gameState.countEntitiesAndQueuedByType(naval, true); | |||||
if (nNaval === 0 || (nNaval < this.bNaval.length && gameState.getPopulation() > 120)) | |||||
{ | |||||
for (let naval of this.bNaval) | |||||
{ | |||||
if (gameState.countEntitiesAndQueuedByType(naval, true) < 1 && gameState.ai.HQ.canBuild(gameState, naval)) | |||||
{ | |||||
let wantedLand = {}; | let wantedLand = {}; | ||||
for (let base of gameState.ai.HQ.baseManagers) | for (let base of gameState.ai.HQ.baseManagers) | ||||
if (base.anchor) | if (base.anchor) | ||||
wantedLand[base.accessIndex] = true; | wantedLand[base.accessIndex] = true; | ||||
let sea = docks.toEntityArray()[0].getMetadata(PlayerID, "sea"); | let sea = this.docks.toEntityArray()[0].getMetadata(PlayerID, "sea"); | ||||
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, naval, { "land": wantedLand, "sea": sea })); | queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, template, { "land": wantedLand, "sea": sea })); | ||||
break; | API3.warn(" on lance un shipyard " + gameState.applyCiv(template) + " wantedLand " + uneval(wantedLand) + " sea " + uneval(sea)); | ||||
} | |||||
} | |||||
} | |||||
}; | }; | ||||
/** goal can be either attack (choose ship with best arrowCount) or transport (choose ship with best capacity) */ | /** goal can be either attack (choose ship with best arrowCount) or transport (choose ship with best capacity) */ | ||||
m.NavalManager.prototype.getBestShip = function(gameState, sea, goal) | m.NavalManager.prototype.getBestShip = function(gameState, sea, goal) | ||||
{ | { | ||||
let civ = gameState.getPlayerCiv(); | let civ = gameState.getPlayerCiv(); | ||||
let trainableShips = []; | let trainableShips = []; | ||||
gameState.getOwnTrainingFacilities().filter(API3.Filters.byMetadata(PlayerID, "sea", sea)).forEach(function(ent) { | gameState.getOwnTrainingFacilities().filter(API3.Filters.byMetadata(PlayerID, "sea", sea)).forEach(function(ent) { | ||||
▲ Show 20 Lines • Show All 122 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
You switch this.docks to include docks that are foundations, but there is still the loop here that calls setAccessIndices,
even though that is done for foundations in the events.ConstructionFinished loop. So setAccessIndices is called twice in this case.