Unify trade gain computation between simulation and ai

Reviewed By: elexis
Differential Revision: https://code.wildfiregames.com/D964
This was SVN commit r20320.
This commit is contained in:
mimo 2017-10-21 08:40:11 +00:00
parent e5ec6d0bff
commit 23893415d1
6 changed files with 45 additions and 16 deletions

View File

@ -0,0 +1,15 @@
/**
* Normalize the trade gain as a function of mapSize, default=1024
*/
function TradeGainNormalization(mapSize)
{
return 1;
}
/**
* Dependance of the gain with distance, normalized on a distance of 100m
*/
function NormalizedTradeGain(distanceSquared)
{
return distanceSquared / 10000;
}

View File

@ -936,10 +936,13 @@ m.GameState.prototype.getTraderTemplatesGains = function()
let supportTraderTemplateName = this.applyCiv("units/{civ}_support_trader");
let shipMerchantTemplate = !this.isTemplateDisabled(shipMechantTemplateName) && this.getTemplate(shipMechantTemplateName);
let supportTraderTemplate = !this.isTemplateDisabled(supportTraderTemplateName) && this.getTemplate(supportTraderTemplateName);
return {
"navalGainMultiplier": shipMerchantTemplate && shipMerchantTemplate.gainMultiplier(),
"landGainMultiplier": supportTraderTemplate && supportTraderTemplate.gainMultiplier()
};
let norm = TradeGainNormalization(this.sharedScript.mapSize);
let ret = {};
if (supportTraderTemplate)
ret.landGainMultiplier = norm * supportTraderTemplate.gainMultiplier();
if (shipMerchantTemplate)
ret.navalGainMultiplier = norm * shipMerchantTemplate.gainMultiplier();
return ret;
};
return m;

View File

@ -1104,8 +1104,9 @@ m.HQ.prototype.findStrategicCCLocation = function(gameState, template)
/**
* Returns the best position to build a new market: if the allies already have a market, build it as far as possible
* from it, although not in our border to be able to defend it easily. If no allied market, our second market will
* follow the same logic
* TODO check that it is on same accessIndex
* follow the same logic.
* To do so, we suppose that the gain/distance is an increasing function of distance and look for the max distance
* for performance reasons.
*/
m.HQ.prototype.findMarketLocation = function(gameState, template)
{
@ -1127,6 +1128,8 @@ m.HQ.prototype.findMarketLocation = function(gameState, template)
let bestIdx;
let bestJdx;
let bestVal;
let bestDistSq;
let bestGainMult;
let radius = Math.ceil(template.obstructionRadius().max / obstructions.cellSize);
let isNavalMarket = template.hasClass("NavalMarket");
@ -1152,6 +1155,8 @@ m.HQ.prototype.findMarketLocation = function(gameState, template)
let pos = [cellSize * (j%width+0.5), cellSize * (Math.floor(j/width)+0.5)];
// checking distances to other markets
let maxVal = 0;
let maxDistSq;
let maxGainMult;
let gainMultiplier;
for (let market of markets)
{
@ -1168,9 +1173,13 @@ m.HQ.prototype.findMarketLocation = function(gameState, template)
continue;
if (!gainMultiplier)
continue;
let val = API3.SquareVectorDistance(market.position(), pos) * gainMultiplier;
if (val > maxVal)
maxVal = val;
let distSq = API3.SquareVectorDistance(market.position(), pos);
if (gainMultiplier * distSq > maxVal)
{
maxVal = gainMultiplier * distSq;
maxDistSq = distSq;
maxGainMult = gainMultiplier;
}
}
if (maxVal === 0)
continue;
@ -1179,6 +1188,8 @@ m.HQ.prototype.findMarketLocation = function(gameState, template)
if (this.isDangerousLocation(gameState, pos, halfSize))
continue;
bestVal = maxVal;
bestDistSq = maxDistSq;
bestGainMult = maxGainMult;
bestIdx = i;
bestJdx = j;
}
@ -1188,7 +1199,7 @@ m.HQ.prototype.findMarketLocation = function(gameState, template)
if (bestVal === undefined) // no constraints. For the time being, place it arbitrarily by the ConstructionPlan
return [-1, -1, -1, 0];
let expectedGain = Math.round(bestVal / 10000);
let expectedGain = Math.round(bestGainMult * NormalizedTradeGain(bestDistSq));
if (this.Config.debug > 1)
API3.warn("this would give a trading gain of " + expectedGain);
// do not keep it if gain is too small, except if this is our first BarterMarket

View File

@ -444,7 +444,7 @@ m.TradeManager.prototype.checkRoutes = function(gameState, accessIndex)
gainMultiplier = traderTemplatesGains.navalGainMultiplier;
else
continue;
let gain = Math.round(API3.SquareVectorDistance(m1.position(), m2.position()) * gainMultiplier / 10000);
let gain = Math.round(gainMultiplier * NormalizedTradeGain(API3.SquareVectorDistance(m1.position(), m2.position())));
if (gain < this.minimalGain)
continue;
if (m1.foundationProgress() === undefined && m2.foundationProgress() === undefined)

View File

@ -11,7 +11,7 @@ Trader.prototype.Schema =
"<a:example>" +
"<GainMultiplier>0.75</GainMultiplier>" +
"</a:example>" +
"<element name='GainMultiplier' a:help='Trader gain for a 100m distance'>" +
"<element name='GainMultiplier' a:help='Trader gain for a 100m distance and mapSize = 1024'>" +
"<ref name='positiveDecimal'/>" +
"</element>";

View File

@ -18,19 +18,19 @@ function CalculateTraderGain(firstMarket, secondMarket, traderTemplate, trader)
let firstMarketPosition = cmpFirstMarketPosition.GetPosition2D();
let secondMarketPosition = cmpSecondMarketPosition.GetPosition2D();
let gainMultiplier;
let gainMultiplier = TradeGainNormalization(Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain).GetMapSize());
if (trader)
{
let cmpTrader = Engine.QueryInterface(trader, IID_Trader);
if (!cmpTrader)
return null;
gainMultiplier = cmpTrader.GetTraderGainMultiplier();
gainMultiplier *= cmpTrader.GetTraderGainMultiplier();
}
else //called from the gui, modifications already applied
{
if (!traderTemplate || !traderTemplate.GainMultiplier)
return null;
gainMultiplier = traderTemplate.GainMultiplier;
gainMultiplier *= traderTemplate.GainMultiplier;
}
let gain = {};
@ -40,7 +40,7 @@ function CalculateTraderGain(firstMarket, secondMarket, traderTemplate, trader)
let distanceSq = firstMarketPosition.distanceToSquared(secondMarketPosition);
// We calculate gain as square of distance to encourage trading between remote markets
// and gainMultiplier corresponds to the gain for a 100m distance
gain.traderGain = gainMultiplier * distanceSq / 10000;
gain.traderGain = gainMultiplier * NormalizedTradeGain(distanceSq);
gain.market1Owner = cmpMarket1Player.GetPlayerID();
gain.market2Owner = cmpMarket2Player.GetPlayerID();