Changeset View
Standalone View
binaries/data/mods/public/simulation/ai/petra/diplomacyManager.js
Show First 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* Check if any allied needs help (tribute) and sent it if we have enough resource | * Check if any allied needs help (tribute) and sent it if we have enough resource | ||||
* or ask for a tribute if we are in need and one ally can help | * or ask for a tribute if we are in need and one ally can help | ||||
*/ | */ | ||||
m.DiplomacyManager.prototype.tributes = function(gameState) | m.DiplomacyManager.prototype.tributes = function(gameState) | ||||
{ | { | ||||
this.nextTributeUpdate = gameState.ai.elapsedTime + 30; | this.nextTributeUpdate = gameState.ai.elapsedTime + 30; | ||||
let totalResources = gameState.getResources(); | let totalResources = gameState.getResources(); | ||||
Silier: could you move this after resTribCodes.length check ? | |||||
let availableResources = gameState.ai.queueManager.getAvailableResources(gameState); | let availableResources = gameState.ai.queueManager.getAvailableResources(gameState); | ||||
Done Inline Actionssame Silier: same | |||||
let mostNeeded; | let mostNeeded; | ||||
for (let i = 1; i < gameState.sharedScript.playersData.length; ++i) | for (let i = 1; i < gameState.sharedScript.playersData.length; ++i) | ||||
Done Inline ActionsShouldn't there be a ! here? Nescio: Shouldn't there be a `!` here? | |||||
Done Inline Actionsyes should, thanks for noticing, I did not really check last updates yet :) Silier: yes should, thanks for noticing, I did not really check last updates yet :) | |||||
{ | { | ||||
if (i === PlayerID || !gameState.isPlayerAlly(i) || gameState.ai.HQ.attackManager.defeated[i]) | if (i === PlayerID || !gameState.isPlayerAlly(i) || gameState.ai.HQ.attackManager.defeated[i]) | ||||
continue; | continue; | ||||
let donor = gameState.getAlliedVictory() || gameState.getEntities(i).length < gameState.getOwnEntities().length; | let donor = gameState.getAlliedVictory() || gameState.getEntities(i).length < gameState.getOwnEntities().length; | ||||
let allyResources = gameState.sharedScript.playersData[i].resourceCounts; | let allyResources = gameState.sharedScript.playersData[i].resourceCounts; | ||||
let allyPop = gameState.sharedScript.playersData[i].popCount; | let allyPop = gameState.sharedScript.playersData[i].popCount; | ||||
let tribute = {}; | let tribute = {}; | ||||
let toSend = false; | let toSend = false; | ||||
for (let res in allyResources) | for (let res in allyResources) | ||||
{ | { | ||||
// Do not send resources which are untributable | |||||
if (Resources.GetCodes("tributable").indexOf(res) == -1) | |||||
Done Inline Actionsno big deal but calling n*m times, possibly save it to variable before L72. Silier: no big deal but calling n*m times, possibly save it to variable before L72. | |||||
continue; | |||||
if (donor && availableResources[res] > 200 && allyResources[res] < 0.2 * availableResources[res]) | if (donor && availableResources[res] > 200 && allyResources[res] < 0.2 * availableResources[res]) | ||||
{ | { | ||||
tribute[res] = Math.floor(0.3*availableResources[res] - allyResources[res]); | tribute[res] = Math.floor(0.3*availableResources[res] - allyResources[res]); | ||||
toSend = true; | toSend = true; | ||||
} | } | ||||
else if (donor && allyPop < Math.min(30, 0.5*gameState.getPopulation()) && totalResources[res] > 500 && allyResources[res] < 100) | else if (donor && allyPop < Math.min(30, 0.5*gameState.getPopulation()) && totalResources[res] > 500 && allyResources[res] < 100) | ||||
{ | { | ||||
tribute[res] = 100; | tribute[res] = 100; | ||||
toSend = true; | toSend = true; | ||||
} | } | ||||
else if (this.Config.chat && availableResources[res] === 0 && allyResources[res] > totalResources[res] + 600) | else if (this.Config.chat && availableResources[res] === 0 && allyResources[res] > totalResources[res] + 600) | ||||
{ | { | ||||
if (gameState.ai.elapsedTime < this.nextTributeRequest.get("all")) | if (gameState.ai.elapsedTime < this.nextTributeRequest.get("all")) | ||||
continue; | continue; | ||||
if (this.nextTributeRequest.has(res) && gameState.ai.elapsedTime < this.nextTributeRequest.get(res)) | if (this.nextTributeRequest.has(res) && gameState.ai.elapsedTime < this.nextTributeRequest.get(res)) | ||||
continue; | continue; | ||||
if (!mostNeeded) | if (!mostNeeded) | ||||
mostNeeded = gameState.ai.HQ.pickMostNeededResources(gameState); | mostNeeded = gameState.ai.HQ.pickMostNeededResources(gameState); | ||||
Done Inline Actionshere we should pick mostNeeded tributable Silier: here we should pick mostNeeded tributable | |||||
Done Inline ActionsAgain, filter through object... Freagarach: Again, filter through object... | |||||
Done Inline Actionsprobably the best would be to copy pickMostNeededResources and morphe it to what we need Silier: probably the best would be to copy pickMostNeededResources and morphe it to what we need | |||||
for (let k = 0; k < 2; ++k) | for (let k = 0; k < 2; ++k) | ||||
{ | { | ||||
if (mostNeeded[k].type == res && mostNeeded[k].wanted > 0) | if (mostNeeded[k].type == res && mostNeeded[k].wanted > 0) | ||||
{ | { | ||||
this.nextTributeRequest.set("all", gameState.ai.elapsedTime + 90); | this.nextTributeRequest.set("all", gameState.ai.elapsedTime + 90); | ||||
this.nextTributeRequest.set(res, gameState.ai.elapsedTime + 240); | this.nextTributeRequest.set(res, gameState.ai.elapsedTime + 240); | ||||
m.chatRequestTribute(gameState, res); | m.chatRequestTribute(gameState, res); | ||||
if (this.Config.debug > 1) | if (this.Config.debug > 1) | ||||
▲ Show 20 Lines • Show All 288 Lines • ▼ Show 20 Lines | else if (requestType === "ally" && gameState.getEntities(player).length < gameState.getOwnEntities().length && randBool(0.4) || | ||||
requestType === "neutral" && moreEnemiesThanAllies && randBool(0.8)) | requestType === "neutral" && moreEnemiesThanAllies && randBool(0.8)) | ||||
{ | { | ||||
response = "accept"; | response = "accept"; | ||||
this.changePlayerDiplomacy(gameState, player, requestType); | this.changePlayerDiplomacy(gameState, player, requestType); | ||||
this.receivedDiplomacyRequests.set(player, { "requestType": requestType, "status": "accepted" }); | this.receivedDiplomacyRequests.set(player, { "requestType": requestType, "status": "accepted" }); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// Try to request a tribute. | |||||
// If a resource is not tributable, do not request it. | |||||
Done Inline Actionswell, decline then, else requiredTribute will be last resource in list. Silier: well, decline then, else requiredTribute will be last resource in list.
| |||||
// If no resources are tributable, decline. | |||||
let tributableResources = Resources.GetCodes("tributable"); | |||||
Done Inline ActionsWhy not for (let i = 0; Resource.GetCodes().length; ++i) { ... } Also this function should request tributes anyways. You just need to pick the most wanted tributable resource. The check should probably done in gameState.ai.HQ.pickMostNeededResources(gameState)[i] Stan: Why not
```
for (let i = 0; Resource.GetCodes().length; ++i)
{
...
}
```
Also this function… | |||||
Done Inline ActionsAh, thats what I wanted! I couldn't come up with that.
But this is what it does right? At least that is what I meant ;) It loops over all resources and when the most needed resource is untributable, try the next one. If the the resource is tributable it should break the loop and use the requiredTribute as set lastly. Or am I thinking wrong now? Freagarach: Ah, thats what I wanted! I couldn't come up with that.
> Also this function should request… | |||||
Done Inline ActionsThen one can do // Returns the first element matching the condition IsResourceTributable // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find let requiredTribute = gameState.ai.HQ.pickMostNeededResources(gameState).find(res => Resources.GetTributable[requiredTribute]); // Do not request tributes if no resources can be tributed. if(!requiredTribute) return; Stan: Then one can do
```lang=js
// Returns the first element matching the condition… | |||||
Done Inline ActionsI can't seem to get this working. I've tried: let requiredTribute = gameState.ai.HQ.pickMostNeededResources(gameState).find(res => Resources.GetTributable[res]); for I think that is what you meant, but it keeps giving me a WARNING: JavaScript warning: simulation/ai/petra/diplomacyManager.js line 408 reference to undefined property Resources.GetTributable[res] :( Freagarach: I can't seem to get this working. I've tried:
```
let requiredTribute = gameState.ai.HQ. | |||||
Done Inline Actionstry with !== undefined ? Stan: try with !== undefined ? | |||||
Done Inline Actionslet requiredTribute = gameState.ai.HQ.pickMostNeededResources(gameState).find(res => Resources.GetTributable[res]); I think you could with something like this (not sure): let requiredTribute = gameState.ai.HQ.pickMostNeededResources(gameState).find(res => !!Resources.GetTributable[res] && Resources.GetTributable[res]); Silier: ```
let requiredTribute = gameState.ai.HQ.pickMostNeededResources(gameState).find(res =>… | |||||
Done Inline ActionsSadly not, neither of your suggestions work. There is no warning given, but requiredTribute is still not defined. uneval gives "(void 0)". Freagarach: Sadly not, neither of your suggestions work. There is no warning given, but requiredTribute is… | |||||
Done Inline ActionsI've fixed it :) Thanks for the help! Freagarach: I've fixed it :) Thanks for the help! | |||||
Done Inline ActionsI think requiredTribute = gameState.ai.HQ.pickMostNeededResources(gameState).find(res => Resources.GetTributableCodes().some(res2 => res2 == res)); would be better. Stan: I think requiredTribute = gameState.ai.HQ.pickMostNeededResources(gameState).find(res =>… | |||||
Done Inline ActionsIn terms of performance? Or is there a different reason? Freagarach: In terms of performance? Or is there a different reason? | |||||
Done Inline ActionsForgot type gameState.ai.HQ.pickMostNeededResources(gameState).find(res => Resources.GetTributableCodes().some(res2 => res2 == res.type)); I think it's more readable saying "I want the first resource in the most needed resource that's in Resources.GetTributableCode()" Than "I want the first resource in the most needed resource that's in where the first Resources.GetTributableCodes() that is not false is equal to res.type" Stan: Forgot type
```
gameState.ai.HQ.pickMostNeededResources(gameState).find(res => Resources. | |||||
Done Inline ActionsI thought this Resources.GetTributableCodes().find(res2 => res2) would just kind of loop over the tributable resource codes in that array? So returning that value. Freagarach: I thought this
```
Resources.GetTributableCodes().find(res2 => res2)
```
would just kind of… | |||||
Done Inline ActionsWell this returns the first element that it finds :) let array = [12,41,42,31,26]; let result = array.find(a => a); // → result = 12 Stan: Well this returns the first element that it finds :)
```
let array = [12,41,42,31,26];
let… | |||||
Done Inline ActionsUse .find(res => Resources.GetCodes("tributable").indexOf(res.type) != -1) - might also want to make Resources.GetCodes("tributable") out of the 'loop'. wraitii: Use `.find(res => Resources.GetCodes("tributable").indexOf(res.type) != -1)` - might also want… | |||||
requiredTribute = gameState.ai.HQ.pickMostNeededResources(gameState).find(res => tributableResources.indexOf(res.type) != -1)); | |||||
FreagarachAuthorUnsubmitted Done Inline ActionsExtra ")". Reported by @Nescio. Freagarach: Extra ")". Reported by @Nescio. | |||||
Done Inline Actionswill pickMostNeededResources return non empty array always? else I see out of bounds Silier: will pickMostNeededResources return non empty array always? else I see out of bounds | |||||
if (requiredTribute) | |||||
Done Inline Actionsnot needed repeated calling, call this gameState.ai.HQ.pickMostNeededResources(gameState) before looping and then go with [i] over object Silier: not needed repeated calling, call this
```
gameState.ai.HQ.pickMostNeededResources(gameState)… | |||||
{ | |||||
Done Inline Actionswhat brings me to this check, actually it is not correct. Silier: what brings me to this check, actually it is not correct.
If your resource is not tributable… | |||||
Done Inline Actionsok, sorry its too late here :D (you find first tributable and break, got it now) but, it does not look correct anyway. You have to handle when no resource is tributable somewhere :) Silier: ok, sorry its too late here :D (you find first tributable and break, got it now) but, it does… | |||||
Done Inline ActionsI understand, it looks ugly ;) Freagarach: I understand, it looks ugly ;)
Perhaps an "if i == Resources.GetCodes().length" after the i++? | |||||
Done Inline Actionsyou can and should do check if at least one tributable resource globally exists before even calling mostneeded resources and deal with it there. Silier: you can and should do check if at least one tributable resource globally exists before even… | |||||
response = "acceptWithTribute"; | response = "acceptWithTribute"; | ||||
requiredTribute = gameState.ai.HQ.pickMostNeededResources(gameState)[0]; | |||||
requiredTribute.wanted = Math.max(1000, gameState.getOwnUnits().length * (requestType === "ally" ? 10 : 5)); | requiredTribute.wanted = Math.max(1000, gameState.getOwnUnits().length * (requestType === "ally" ? 10 : 5)); | ||||
this.receivedDiplomacyRequests.set(player, { | this.receivedDiplomacyRequests.set(player, { | ||||
"status": "waitingForTribute", | "status": "waitingForTribute", | ||||
"wanted": requiredTribute.wanted, | "wanted": requiredTribute.wanted, | ||||
"type": requiredTribute.type, | "type": requiredTribute.type, | ||||
"warnTime": gameState.ai.elapsedTime + 60, | "warnTime": gameState.ai.elapsedTime + 60, | ||||
"sentWarning": false, | "sentWarning": false, | ||||
"requestType": requestType | "requestType": requestType | ||||
}); | }); | ||||
} | } | ||||
else | |||||
{ | |||||
this.receivedDiplomacyRequests.set(player, { "requestType": requestType, "status": "declinedRequest" }); | |||||
response = "decline"; | |||||
} | |||||
} | |||||
m.chatAnswerRequestDiplomacy(gameState, player, requestType, response, requiredTribute); | m.chatAnswerRequestDiplomacy(gameState, player, requestType, response, requiredTribute); | ||||
}; | }; | ||||
m.DiplomacyManager.prototype.changePlayerDiplomacy = function(gameState, player, newDiplomaticStance) | m.DiplomacyManager.prototype.changePlayerDiplomacy = function(gameState, player, newDiplomaticStance) | ||||
{ | { | ||||
if (gameState.isPlayerEnemy(player) && (newDiplomaticStance === "ally" || newDiplomaticStance === "neutral")) | if (gameState.isPlayerEnemy(player) && (newDiplomaticStance === "ally" || newDiplomaticStance === "neutral")) | ||||
gameState.ai.HQ.attackManager.cancelAttacksAgainstPlayer(gameState, player); | gameState.ai.HQ.attackManager.cancelAttacksAgainstPlayer(gameState, player); | ||||
Engine.PostCommand(PlayerID, { "type": "diplomacy", "player": player, "to": newDiplomaticStance }); | Engine.PostCommand(PlayerID, { "type": "diplomacy", "player": player, "to": newDiplomaticStance }); | ||||
▲ Show 20 Lines • Show All 135 Lines • Show Last 20 Lines |
could you move this after resTribCodes.length check ?