From a574ca2e8f24ebee1dfe2ff809d3aca3d1b1a618 Mon Sep 17 00:00:00 2001 From: mimo Date: Wed, 23 Jul 2014 17:57:32 +0000 Subject: [PATCH] Petra: improve use of garrisoning for defense + some cleanings This was SVN commit r15552. --- .../public/simulation/ai/common-api/entity.js | 2 +- .../simulation/ai/common-api/gamestate.js | 20 +- .../simulation/ai/petra/defenseManager.js | 266 ++++++------------ .../simulation/ai/petra/garrisonManager.js | 5 +- .../simulation/ai/petra/headquarters.js | 2 +- .../simulation/ai/petra/queueManager.js | 32 +-- .../simulation/ai/petra/tradeManager.js | 16 +- 7 files changed, 130 insertions(+), 213 deletions(-) diff --git a/binaries/data/mods/public/simulation/ai/common-api/entity.js b/binaries/data/mods/public/simulation/ai/common-api/entity.js index 2a9b7d8e60..814128dcf0 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/entity.js +++ b/binaries/data/mods/public/simulation/ai/common-api/entity.js @@ -406,7 +406,7 @@ m.Template = m.Class({ buffHeal: function() { if (!this.get("GarrisonHolder")) return undefined; - return this.get("GarrisonHolder/BuffHeal"); + return +this.get("GarrisonHolder/BuffHeal"); }, promotion: function() { diff --git a/binaries/data/mods/public/simulation/ai/common-api/gamestate.js b/binaries/data/mods/public/simulation/ai/common-api/gamestate.js index 2d609dca10..86ad5067a4 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/gamestate.js +++ b/binaries/data/mods/public/simulation/ai/common-api/gamestate.js @@ -324,13 +324,19 @@ m.GameState.prototype.getEnemies = function(){ return ret; }; -m.GameState.prototype.getAllies = function(){ // Player is not included +m.GameState.prototype.getAllies = function(){ var ret = []; - for (var i in this.playerData.isAlly){ - if (this.playerData.isAlly[i] && +i !== this.player){ + for (var i in this.playerData.isAlly) + if (this.playerData.isAlly[i]) + ret.push(i); + return ret; +}; + +m.GameState.prototype.getExclusiveAllies = function(){ // Player is not included + var ret = []; + for (var i in this.playerData.isAlly) + if (this.playerData.isAlly[i] && +i !== this.player) ret.push(i); - } - } return ret; }; @@ -388,6 +394,10 @@ m.GameState.prototype.getAllyEntities = function() { return this.entities.filter(m.Filters.byOwners(this.getAllies())); }; +m.GameState.prototype.getExclusiveAllyEntities = function() { + return this.entities.filter(m.Filters.byOwners(this.getExclusiveAllies())); +}; + // Try to use a parameter for those three, it'll be a lot faster. m.GameState.prototype.getEnemyEntities = function(enemyID) { diff --git a/binaries/data/mods/public/simulation/ai/petra/defenseManager.js b/binaries/data/mods/public/simulation/ai/petra/defenseManager.js index 59871b1f5b..5ac7d2b483 100644 --- a/binaries/data/mods/public/simulation/ai/petra/defenseManager.js +++ b/binaries/data/mods/public/simulation/ai/petra/defenseManager.js @@ -107,7 +107,7 @@ m.DefenseManager.prototype.isDangerous = function(gameState, entity) if (this.Config.personality.cooperative > 0.3) { - var allyCC = gameState.getAllyEntities().filter(API3.Filters.byClass("CivCentre")); + var allyCC = gameState.getExclusiveAllyEntities().filter(API3.Filters.byClass("CivCentre")); for (var i in allyCC._entities) { if (this.Config.personality.cooperative < 0.6 && allyCC._entities[i].foundationProgress() !== undefined) @@ -217,18 +217,16 @@ m.DefenseManager.prototype.checkEnemyArmies = function(gameState, events) // army in neutral territory // TODO check smaller distance with all our buildings instead of only ccs with big distance var stillDangerous = false; - var bases = gameState.getOwnStructures().filter(API3.Filters.byClass("CivCentre")).toEntityArray(); if (this.Config.personality.cooperative > 0.3) - { - var allyCC = gameState.getAllyEntities().filter(API3.Filters.byClass("CivCentre")).toEntityArray(); - bases = bases.concat(allyCC); - } + var bases = gameState.getAllyEntities().filter(API3.Filters.byClass("CivCentre")).toEntityArray(); + else + var bases = gameState.getOwnStructures().filter(API3.Filters.byClass("CivCentre")).toEntityArray(); for (var i in bases) { if (API3.SquareVectorDistance(bases[i].position(), army.foePosition) < 40000) { if(this.Config.debug > 0) - warn("army in neutral territory, but still near one of our CC"); + API3.warn("army in neutral territory, but still near one of our CC"); stillDangerous = true; break; } @@ -307,7 +305,7 @@ m.DefenseManager.prototype.assignDefenders = function(gameState) if (aMin === undefined) { for (var a = 0; a < armiesNeeding.length; ++a) - warn(" defense/armiesNeeding " + uneval(armiesNeeding[a]["need"])); + API3.warn(" defense/armiesNeeding " + uneval(armiesNeeding[a]["need"])); } var str = m.getMaxStrength(ent); @@ -331,7 +329,7 @@ m.DefenseManager.prototype.assignDefenders = function(gameState) }; // If our defense structures are attacked, garrison soldiers inside when possible -// TODO transfer most of that code in a garrisonManager +// and if a support unit is attacked and has less than 30% health, garrison it inside the nearest cc m.DefenseManager.prototype.checkEvents = function(gameState, events) { var self = this; @@ -339,186 +337,98 @@ m.DefenseManager.prototype.checkEvents = function(gameState, events) for (var evt of attackedEvents) { var target = gameState.getEntityById(evt.target); - if (!target || !gameState.isEntityOwn(target) || !target.getArrowMultiplier()) - continue; - if (!target.isGarrisonHolder() || gameState.ai.HQ.garrisonManager.numberOfGarrisonedUnits(target) >= target.garrisonMax()) + if (!target || !gameState.isEntityOwn(target) || !target.position()) continue; if (target.hasClass("Ship")) // TODO integrate ships later need to be sure it is accessible continue; + + if (target.hasClass("Support") && target.healthLevel() < 0.4) + { + this.garrisonUnitForHealing(gameState, target); + continue; + } + var attacker = gameState.getEntityById(evt.attacker); if (!attacker || !attacker.position()) continue; - var attackTypes = target.attackTypes(); - if (!attackTypes || attackTypes.indexOf("Ranged") === -1) - continue; - var dist = API3.SquareVectorDistance(attacker.position(), target.position()); - var range = target.attackRange("Ranged").max; - if (dist >= range*range) - continue; - var index = gameState.ai.accessibility.getAccessValue(target.position()); - var garrisonManager = gameState.ai.HQ.garrisonManager; - gameState.getOwnUnits().filter(API3.Filters.byClassesAnd(["Infantry", "Ranged"])).filterNearest(target.position()).forEach(function(ent) { - if (garrisonManager.numberOfGarrisonedUnits(target) >= target.garrisonMax()) - return; - if (!ent.position()) - return; - if (ent.getMetadata(PlayerID, "transport") !== undefined) - return; - if (ent.getMetadata(PlayerID, "plan") === -2 || ent.getMetadata(PlayerID, "plan") === -3) - return; - if (ent.getMetadata(PlayerID, "plan") !== undefined && ent.getMetadata(PlayerID, "plan") !== -1) - { - var subrole = ent.getMetadata(PlayerID, "subrole"); - if (subrole && (subrole === "completing" || subrole === "walking" || subrole === "attacking")) - return; - } - if (gameState.ai.accessibility.getAccessValue(ent.position()) !== index) - return; - var army = ent.getMetadata(PlayerID, "PartOfArmy"); - if (army !== undefined) - { - army = self.getArmy(army); - if (army !== undefined) - army.removeOwn(gameState, ent.id(), ent); - } - garrisonManager.garrison(gameState, ent, target, "protection"); - }); + if (target.isGarrisonHolder() && target.getArrowMultiplier()) + this.garrisonRangedUnitsInside(gameState, target, attacker); } }; -// this processes the attackmessages -// So that a unit that gets attacked will not be completely dumb. -// warning: big levels of indentation coming. -//m.DefenseManager.prototype.MessageProcess = function(gameState,events) { -/* var self = this; - var attackedEvents = events["Attacked"]; - for (var key in attackedEvents){ - var e = attackedEvents[key]; - if (gameState.isEntityOwn(gameState.getEntityById(e.target))) { - var attacker = gameState.getEntityById(e.attacker); - var ourUnit = gameState.getEntityById(e.target); - - // the attacker must not be already dead, and it must not be me (think catapults that miss). - if (attacker === undefined || attacker.owner() === PlayerID || attacker.position() === undefined) - continue; - - var mapPos = this.dangerMap.gamePosToMapPos(attacker.position()); - this.dangerMap.addInfluence(mapPos[0], mapPos[1], 4, 1, 'constant'); - - // disregard units from attack plans and defense. - if (ourUnit.getMetadata(PlayerID, "role") == "defense" || ourUnit.getMetadata(PlayerID, "role") == "attack") - continue; - - var territory = this.territoryMap.getOwner(attacker.position()); - - if (attacker.owner() == 0) - { - if (ourUnit !== undefined && ourUnit.hasClass("Unit") && !ourUnit.hasClass("Support")) - ourUnit.attack(e.attacker); - else - { - ourUnit.flee(attacker); - ourUnit.setMetadata(PlayerID,"fleeing", gameState.getTimeElapsed()); - } - if (territory === PlayerID) - { - // anyway we'll register the animal as dangerous, and attack it (note: only on our territory. Don't care otherwise). - this.listOfWantedUnits[attacker.id()] = new EntityCollection(gameState.sharedScript); - this.listOfWantedUnits[attacker.id()].addEnt(attacker); - this.listOfWantedUnits[attacker.id()].freeze(); - this.listOfWantedUnits[attacker.id()].registerUpdates(); - - var filter = Filters.byTargetedEntity(attacker.id()); - this.WantedUnitsAttacker[attacker.id()] = this.myUnits.filter(filter); - this.WantedUnitsAttacker[attacker.id()].registerUpdates(); - } - } // Disregard military units except in our territory. Disregard all calls in enemy territory. - else if (territory == PlayerID || (territory != attacker.owner() && ourUnit.hasClass("Support"))) - { - // TODO: this does not differentiate with buildings... - // These ought to be treated differently. - // units in attack plans will react independently, but we still list the attacks here. - if (attacker.hasClass("Structure")) { - // todo: we ultimately have to check wether it's a danger point or an isolated area, and if it's a danger point, mark it as so. - - // Right now, to make the AI less gameable, we'll mark any surrounding resource as inaccessible. - // usual tower range is 80. Be on the safe side. - var close = gameState.getResourceSupplies("wood").filter(Filters.byDistance(attacker.position(), 90)); - close.forEach(function (supply) { //}){ - supply.setMetadata(PlayerID, "inaccessible", true); - }); - } else { - // TODO: right now a soldier always retaliate... Perhaps it should be set in "Defense" mode. - - // TODO: handle the ship case - if (attacker.hasClass("Ship")) - continue; - - // This unit is dangerous. if it's in an army, it's being dealt with. - // if it's not in an army, it means it's either a lone raider, or it has got friends. - // In which case we must check for other dangerous units around, and perhaps armify them. - // TODO: perhaps someday army detection will have improved and this will require change. - var armyID = attacker.getMetadata(PlayerID, "inArmy"); - if (armyID == undefined || !this.enemyArmy[attacker.owner()] || !this.enemyArmy[attacker.owner()][armyID]) { - if (this.reevaluateEntity(gameState, attacker)) - { - var position = attacker.position(); - var close = HQ.enemyWatchers[attacker.owner()].enemySoldiers.filter(Filters.byDistance(position, self.armyCompactSize)); - - if (close.length > 2 || ourUnit.hasClass("Support") || attacker.hasClass("Siege")) - { - // armify it, then armify units close to him. - this.armify(gameState,attacker); - armyID = attacker.getMetadata(PlayerID, "inArmy"); - - close.forEach(function (ent) { //}){ - if (API3.SquareVectorDistance(position, ent.position()) < self.armyCompactSize) - { - ent.setMetadata(PlayerID, "inArmy", armyID); - self.enemyArmy[ent.owner()][armyID].addEnt(ent); - } - }); - return; // don't use too much processing power. If there are other cases, they'll be processed soon enough. - } - } - // Defensemanager will deal with them in the next turn. - } - if (ourUnit !== undefined && ourUnit.hasClass("Unit")) { - if (ourUnit.hasClass("Support")) { - // let's try to garrison this support unit. - if (ourUnit.position()) - { - var buildings = gameState.getOwnEntities().filter(Filters.byCanGarrison()).filterNearest(ourUnit.position(),4).toEntityArray(); - var garrisoned = false; - for (var i in buildings) - { - var struct = buildings[i]; - if (struct.garrisoned() && struct.garrisonMax() - struct.garrisoned().length > 0) - { - garrisoned = true; - ourUnit.garrison(struct); - break; - } - } - if (!garrisoned) { - ourUnit.flee(attacker); - ourUnit.setMetadata(PlayerID,"fleeing", gameState.getTimeElapsed()); - } - } - } else { - // It's a soldier. Right now we'll retaliate - // TODO: check for stronger units against this type, check for fleeing options, etc. - // Check also for neighboring towers and garrison there perhaps? - ourUnit.attack(e.attacker); - } - } - } - } +m.DefenseManager.prototype.garrisonRangedUnitsInside = function(gameState, target, attacker) +{ + if (gameState.ai.HQ.garrisonManager.numberOfGarrisonedUnits(target) >= target.garrisonMax()) + return; + var attackTypes = target.attackTypes(); + if (!attackTypes || attackTypes.indexOf("Ranged") === -1) + return; + var dist = API3.SquareVectorDistance(attacker.position(), target.position()); + var range = target.attackRange("Ranged").max; + if (dist >= range*range) + return; + var index = gameState.ai.accessibility.getAccessValue(target.position()); + var garrisonManager = gameState.ai.HQ.garrisonManager; + gameState.getOwnUnits().filter(API3.Filters.byClassesAnd(["Infantry", "Ranged"])).filterNearest(target.position()).forEach(function(ent) { + if (garrisonManager.numberOfGarrisonedUnits(target) >= target.garrisonMax()) + return; + if (!ent.position()) + return; + if (ent.getMetadata(PlayerID, "transport") !== undefined) + return; + if (ent.getMetadata(PlayerID, "plan") === -2 || ent.getMetadata(PlayerID, "plan") === -3) + return; + if (ent.getMetadata(PlayerID, "plan") !== undefined && ent.getMetadata(PlayerID, "plan") !== -1) + { + var subrole = ent.getMetadata(PlayerID, "subrole"); + if (subrole && (subrole === "completing" || subrole === "walking" || subrole === "attacking")) + return; } - } - */ -//}; // nice sets of closing brackets, isn't it? + if (gameState.ai.accessibility.getAccessValue(ent.position()) !== index) + return; + var army = ent.getMetadata(PlayerID, "PartOfArmy"); + if (army !== undefined) + { + army = self.getArmy(army); + if (army !== undefined) + army.removeOwn(gameState, ent.id(), ent); + } + garrisonManager.garrison(gameState, ent, target, "protection"); + }); +}; + +// garrison a hurt unit inside the nearest healing structure +m.DefenseManager.prototype.garrisonUnitForHealing = function(gameState, unit) +{ + var distmin = Math.min(); + var nearest = undefined; + var unitAccess = gameState.ai.accessibility.getAccessValue(unit.position()); + var garrisonManager = gameState.ai.HQ.garrisonManager; + gameState.getAllyEntities().filter(API3.Filters.byClass("Structure")).forEach(function(ent) { + if (!ent.buffHeal()) + return; + if (!MatchesClassList(ent.garrisonableClasses(), unit.classes())) + return; + if (garrisonManager.numberOfGarrisonedUnits(ent) >= ent.garrisonMax()) + return; + var entAccess = ent.getMetadata(PlayerID, "access"); + if (!entAccess) + { + entAccess = gameState.ai.accessibility.getAccessValue(ent.position()); + ent.setMetadata(PlayerID, "access", entAccess); + } + if (entAccess !== unitAccess) + return; + var dist = API3.SquareVectorDistance(ent.position(), unit.position()); + if (dist > distmin) + return; + distmin = dist; + nearest = ent; + }); + if (nearest) + garrisonManager.garrison(gameState, unit, nearest, "protection"); +}; return m; }(PETRA); diff --git a/binaries/data/mods/public/simulation/ai/petra/garrisonManager.js b/binaries/data/mods/public/simulation/ai/petra/garrisonManager.js index 068dff26ec..17fb00439c 100644 --- a/binaries/data/mods/public/simulation/ai/petra/garrisonManager.js +++ b/binaries/data/mods/public/simulation/ai/petra/garrisonManager.js @@ -66,8 +66,6 @@ m.GarrisonManager.prototype.update = function(gameState, queues) return false; }); - var healer = holder.buffHeal(); - for (var entId of holder._entity.garrisoned) { var ent = gameState.getEntityById(entId); @@ -147,8 +145,7 @@ m.GarrisonManager.prototype.keepGarrisoned = function(ent, holder, enemiesAround case 'trade': // trader garrisoned in ship return true; case 'protection': // hurt unit for healing or ranged infantry for defense - var healer = holder.buffHeal(); - if (healer && healer > 0 && ent.isHurt()) + if (ent.isHurt() && holder.buffHeal()) return true; if (enemiesAround && (ent.hasClass("Support") || (ent.hasClass("Ranged") && ent.hasClass("Infantry")))) return true; diff --git a/binaries/data/mods/public/simulation/ai/petra/headquarters.js b/binaries/data/mods/public/simulation/ai/petra/headquarters.js index a2ab623161..c9b5db7571 100644 --- a/binaries/data/mods/public/simulation/ai/petra/headquarters.js +++ b/binaries/data/mods/public/simulation/ai/petra/headquarters.js @@ -936,7 +936,7 @@ m.HQ.prototype.findStrategicCCLocation = function(gameState, template) // TODO check that it is on same accessIndex m.HQ.prototype.findMarketLocation = function(gameState, template) { - var markets = gameState.getAllyEntities().filter(API3.Filters.byClass("Market")).toEntityArray(); + var markets = gameState.getExclusiveAllyEntities().filter(API3.Filters.byClass("Market")).toEntityArray(); if (!markets.length) markets = gameState.getOwnStructures().filter(API3.Filters.byClass("Market")).toEntityArray(); diff --git a/binaries/data/mods/public/simulation/ai/petra/queueManager.js b/binaries/data/mods/public/simulation/ai/petra/queueManager.js index 3fb4bf3542..a14d99e0e8 100644 --- a/binaries/data/mods/public/simulation/ai/petra/queueManager.js +++ b/binaries/data/mods/public/simulation/ai/petra/queueManager.js @@ -149,15 +149,15 @@ m.QueueManager.prototype.printQueues = function(gameState) if (ent.getMetadata(PlayerID, "role") == "worker" && ent.getMetadata(PlayerID, "plan") == undefined) numWorkers++; }); - warn("---------- QUEUES ------------ with pop " + gameState.getPopulation() + " and workers " + numWorkers); + API3.warn("---------- QUEUES ------------ with pop " + gameState.getPopulation() + " and workers " + numWorkers); for (var i in this.queues) { var qStr = ""; var q = this.queues[i]; if (q.queue.length > 0) { - warn(i + ": ( with priority " + this.priorities[i] +" and accounts " + uneval(this.accounts[i]) +")"); - warn(" while maxAccountWanted(0.6) is " + uneval(q.maxAccountWanted(gameState, 0.6))); + API3.warn(i + ": ( with priority " + this.priorities[i] +" and accounts " + uneval(this.accounts[i]) +")"); + API3.warn(" while maxAccountWanted(0.6) is " + uneval(q.maxAccountWanted(gameState, 0.6))); } for (var j in q.queue) { @@ -165,18 +165,18 @@ m.QueueManager.prototype.printQueues = function(gameState) if (q.queue[j].number) qStr += "x" + q.queue[j].number; qStr += " isGo " + q.queue[j].isGo(gameState); - warn(qStr); + API3.warn(qStr); } } - warn("Accounts"); + API3.warn("Accounts"); for (var p in this.accounts) - warn(p + ": " + uneval(this.accounts[p])); - warn("Current Resources: " + uneval(gameState.getResources())); - warn("Available Resources: " + uneval(this.getAvailableResources(gameState))); - warn("Wanted Gather Rates: " + uneval(this.wantedGatherRates(gameState))); - warn("Current Gather Rates: " + uneval(gameState.ai.HQ.GetCurrentGatherRates(gameState))); - warn("Most needed resources: " + uneval(gameState.ai.HQ.pickMostNeededResources(gameState))); - warn("------------------------------------"); + API3.warn(p + ": " + uneval(this.accounts[p])); + API3.warn("Current Resources: " + uneval(gameState.getResources())); + API3.warn("Available Resources: " + uneval(this.getAvailableResources(gameState))); + API3.warn("Wanted Gather Rates: " + uneval(this.wantedGatherRates(gameState))); + API3.warn("Current Gather Rates: " + uneval(gameState.ai.HQ.GetCurrentGatherRates(gameState))); + API3.warn("Most needed resources: " + uneval(gameState.ai.HQ.pickMostNeededResources(gameState))); + API3.warn("------------------------------------"); }; // nice readable HTML version. @@ -344,7 +344,7 @@ m.QueueManager.prototype.distributeResources = function(gameState) } } if (available < 0) - warn("Petra: problem with remaining " + res + " in queueManager " + available); + API3.warn("Petra: problem with remaining " + res + " in queueManager " + available); } }; @@ -378,7 +378,7 @@ m.QueueManager.prototype.switchResource = function(gameState, res) this.accounts[i][res] -= diff; ++otherQueue.switched; if (this.Config.debug > 1) - warn ("switching queue " + res + " from " + i + " to " + j + " in amount " + diff); + API3.warn ("switching queue " + res + " from " + i + " to " + j + " in amount " + diff); break; } } @@ -419,7 +419,7 @@ m.QueueManager.prototype.update = function(gameState) this.queues[i].check(gameState); // do basic sanity checks on the queue if (this.priorities[i] > 0) continue; - warn("QueueManager received bad priorities, please report this error: " + uneval(this.priorities)); + API3.warn("QueueManager received bad priorities, please report this error: " + uneval(this.priorities)); this.priorities[i] = 1; // TODO: make the Queue Manager not die when priorities are zero. } @@ -512,7 +512,7 @@ m.QueueManager.prototype.getPriority = function(queueName) m.QueueManager.prototype.changePriority = function(queueName, newPriority) { if (this.Config.debug > 0) - warn(">>> Priority of queue " + queueName + " changed from " + this.priorities[queueName] + " to " + newPriority); + API3.warn(">>> Priority of queue " + queueName + " changed from " + this.priorities[queueName] + " to " + newPriority); var self = this; if (this.queues[queueName] !== undefined) this.priorities[queueName] = newPriority; diff --git a/binaries/data/mods/public/simulation/ai/petra/tradeManager.js b/binaries/data/mods/public/simulation/ai/petra/tradeManager.js index ee1d022ad0..62cac7838a 100644 --- a/binaries/data/mods/public/simulation/ai/petra/tradeManager.js +++ b/binaries/data/mods/public/simulation/ai/petra/tradeManager.js @@ -72,7 +72,7 @@ m.TradeManager.prototype.buildTradeRoute = function(gameState, queues) { var filter = API3.Filters.and(API3.Filters.byClass("Market"), API3.Filters.not(API3.Filters.isFoundation())); var market1 = gameState.getOwnStructures().filter(filter).toEntityArray(); - var market2 = gameState.getAllyEntities().filter(filter).toEntityArray(); + var market2 = gameState.getExclusiveAllyEntities().filter(filter).toEntityArray(); if (market1.length + market2.length < 1) // We have to wait ... a first market will be built soon return false; @@ -110,7 +110,7 @@ m.TradeManager.prototype.buildTradeRoute = function(gameState, queues) if (distmax > 0) { if (this.Config.debug > 1) - warn(" a second market will be built in base " + base); + API3.warn(" a second market will be built in base " + base); // TODO build also docks when better queues.economicBuilding.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_market", { "base": base })); } @@ -153,11 +153,11 @@ m.TradeManager.prototype.buildTradeRoute = function(gameState, queues) if (distmax < 0) { if (this.Config.debug > 1) - warn("no trade route possible"); + API3.warn("no trade route possible"); return false; } if (this.Config.debug > 0) - warn("one trade route set with gain " + Math.round(distmax / this.Config.distUnitGain)); + API3.warn("one trade route set with gain " + Math.round(distmax / this.Config.distUnitGain)); return true; }; @@ -202,7 +202,7 @@ m.TradeManager.prototype.setTradingGoods = function(gameState) tradingGoods[mostNeeded[0].type] += nextNeed; Engine.PostCommand(PlayerID, {"type": "set-trading-goods", "tradingGoods": tradingGoods}); if (this.Config.debug == 2) - warn(" trading goods set to " + uneval(tradingGoods)); + API3.warn(" trading goods set to " + uneval(tradingGoods)); }; // Try to barter unneeded resources for needed resources. @@ -269,7 +269,7 @@ m.TradeManager.prototype.performBarter = function(gameState) { barterers[0].barter(buy, bestToSell, 100); if (this.Config.debug > 1) - warn("Necessity bartering: sold " + bestToSell +" for " + buy + " >> need sell " + needs[bestToSell] + API3.warn("Necessity bartering: sold " + bestToSell +" for " + buy + " >> need sell " + needs[bestToSell] + " need buy " + needs[buy] + " rate buy " + rates[buy] + " available sell " + available[bestToSell] + " available buy " + available[buy] + " barterRate " + bestRate); return true; @@ -302,7 +302,7 @@ m.TradeManager.prototype.performBarter = function(gameState) { barterers[0].barter(bestToBuy, "food", 100); if (this.Config.debug > 1) - warn("Contingency bartering: sold food for " + bestToBuy + " available sell " + available["food"] + API3.warn("Contingency bartering: sold food for " + bestToBuy + " available sell " + available["food"] + " available buy " + available[bestToBuy] + " barterRate " + getBarterRate(prices, bestToBuy, "food")); return true; } @@ -322,7 +322,7 @@ m.TradeManager.prototype.update = function(gameState, queues) if (!source || !target || !gameState.getEntityById(source.id()) || !gameState.getEntityById(target.id())) { if (this.Config.debug > 1) - warn("We have lost our trade route"); + API3.warn("We have lost our trade route"); this.tradeRoute = undefined; return; }