From f90841cf7849ae6129c1618c8c8553e4c331692b Mon Sep 17 00:00:00 2001 From: mimo Date: Tue, 18 Nov 2014 21:21:21 +0000 Subject: [PATCH] add a very-easy level for AI, addresses #2899 This was SVN commit r15990. --- .../data/mods/public/gui/aiconfig/aiconfig.js | 2 +- .../public/simulation/ai/petra/attackPlan.js | 14 ++++++++++-- .../mods/public/simulation/ai/petra/config.js | 22 ++++++++++--------- .../simulation/ai/petra/headquarters.js | 14 +++++------- .../simulation/ai/petra/queueplan-building.js | 5 ++--- .../simulation/data/player_defaults.json | 18 +++++++-------- .../public/simulation/helpers/InitGame.js | 3 ++- binaries/system/readme.txt | 2 +- source/ps/GameSetup/GameSetup.cpp | 4 ++-- 9 files changed, 47 insertions(+), 37 deletions(-) diff --git a/binaries/data/mods/public/gui/aiconfig/aiconfig.js b/binaries/data/mods/public/gui/aiconfig/aiconfig.js index 39ae88c3c7..32ed2192d0 100644 --- a/binaries/data/mods/public/gui/aiconfig/aiconfig.js +++ b/binaries/data/mods/public/gui/aiconfig/aiconfig.js @@ -26,7 +26,7 @@ function init(settings) var aiDiff = Engine.GetGUIObjectByName("aiDifficulty"); // Translation: AI difficulty level. - aiDiff.list = [translateWithContext("aiDiff", "Sandbox"), translateWithContext("aiDiff", "Easy"), translateWithContext("aiDiff", "Medium"), translateWithContext("aiDiff", "Hard"), translateWithContext("aiDiff", "Very Hard")]; + aiDiff.list = [translateWithContext("aiDiff", "Sandbox"), translateWithContext("aiDiff", "Very Easy"), translateWithContext("aiDiff", "Easy"), translateWithContext("aiDiff", "Medium"), translateWithContext("aiDiff", "Hard"), translateWithContext("aiDiff", "Very Hard")]; aiDiff.selected = settings.difficulty; } diff --git a/binaries/data/mods/public/simulation/ai/petra/attackPlan.js b/binaries/data/mods/public/simulation/ai/petra/attackPlan.js index c0107020cc..f93ccc4f95 100644 --- a/binaries/data/mods/public/simulation/ai/petra/attackPlan.js +++ b/binaries/data/mods/public/simulation/ai/petra/attackPlan.js @@ -130,9 +130,17 @@ m.AttackPlan = function(gameState, Config, uniqueID, type, data) // Put some randomness on the attack size var variation = 0.8 + 0.4*Math.random(); - // and smaller sizes for easy difficulty level + // and lower priority and smaller sizes for easier difficulty levels if (this.Config.difficulty < 2) - variation *= 0.7; + { + priority *= 0.6; + variation *= 0.6; + } + else if (this.Config.difficulty < 3) + { + priority *= 0.8; + variation *= 0.8; + } for (var cat in this.unitStat) { this.unitStat[cat]["targetSize"] = Math.round(variation * this.unitStat[cat]["targetSize"]); @@ -354,6 +362,8 @@ m.AttackPlan.prototype.addSiegeUnits = function(gameState) if (gameState.civ() === "maur") stat["classes"] = ["Elephant", "Champion"]; if (this.Config.difficulty < 2) + stat["targetSize"] = 1; + else if (this.Config.difficulty < 3) stat["targetSize"] = 2; this.addBuildOrder(gameState, "Siege", stat, true); return true; diff --git a/binaries/data/mods/public/simulation/ai/petra/config.js b/binaries/data/mods/public/simulation/ai/petra/config.js index 707c0ff049..41d441c536 100644 --- a/binaries/data/mods/public/simulation/ai/petra/config.js +++ b/binaries/data/mods/public/simulation/ai/petra/config.js @@ -3,8 +3,8 @@ var PETRA = function(m) m.Config = function(difficulty) { - // 0 is sandbox, 1 is easy, 2 is medium, 3 is hard, 4 is very hard. - this.difficulty = (difficulty !== undefined) ? difficulty : 2; + // 0 is sandbox, 1 is very easy, 2 is easy, 3 is medium, 4 is hard and 5 is very hard. + this.difficulty = (difficulty !== undefined) ? difficulty : 3; // debug level: 0=none, 1=sanity checks, 2=debug; 3=detailed debug this.debug = 0; @@ -112,24 +112,26 @@ m.Config.prototype.setConfig = function(gameState) this.personality.cooperative = Math.random(); this.personality.defensive = Math.random(); } + else + this.personality.aggressive = 0.1; - // changing settings based on difficulty (if < 2) or personality - if (this.difficulty === 0) + // changing settings based on difficulty or personality + if (this.difficulty < 2) { this.Military.popForBarracks1 = 60; - this.Military.popForBarracks2 = 150; // shouldn't reach it - this.Military.popForBlacksmith = 150; // shouldn't reach it + this.Military.popForBarracks2 = 300; + this.Military.popForBlacksmith = 300; this.Economy.cityPhase = 240000; this.Economy.popForMarket = 200; this.Economy.femaleRatio = 0.7; this.Economy.initialFields = 1; } - else if (this.difficulty === 1) + else if (this.difficulty < 3) { this.Military.popForBarracks1 = 35; - this.Military.popForBarracks2 = 150; // shouldn't reach it - this.Military.popForBlacksmith = 150; // shouldn't reach it + this.Military.popForBarracks2 = 150; + this.Military.popForBlacksmith = 150; this.Economy.cityPhase = 1800; this.Economy.popForMarket = 80; @@ -151,7 +153,7 @@ m.Config.prototype.setConfig = function(gameState) } } - this.Economy.targetNumTraders = 2 * this.difficulty; + this.Economy.targetNumTraders = 2 + this.difficulty; if (gameState.getPopulationMax() < 300) this.popScaling = Math.sqrt(gameState.getPopulationMax() / 300); diff --git a/binaries/data/mods/public/simulation/ai/petra/headquarters.js b/binaries/data/mods/public/simulation/ai/petra/headquarters.js index 7b0267706a..654fd4af64 100644 --- a/binaries/data/mods/public/simulation/ai/petra/headquarters.js +++ b/binaries/data/mods/public/simulation/ai/petra/headquarters.js @@ -97,9 +97,9 @@ m.HQ.prototype.init = function(gameState, queues, deserializing) API3.warn(" >>> zone " + region + " taille " + gameState.ai.accessibility.regionSize[region]); } - if (this.Config.difficulty == 0) + if (this.Config.difficulty < 2) this.targetNumWorkers = Math.max(1, Math.min(40, Math.floor(gameState.getPopulationMax()))); - else if (this.Config.difficulty == 1) + else if (this.Config.difficulty < 3) this.targetNumWorkers = Math.max(1, Math.min(60, Math.floor(gameState.getPopulationMax()/2))); else this.targetNumWorkers = Math.max(1, Math.min(120, Math.floor(gameState.getPopulationMax()/3))); @@ -494,7 +494,7 @@ m.HQ.prototype.checkEvents = function (gameState, events, queues) // Called by the "town phase" research plan once it's started m.HQ.prototype.OnTownPhase = function(gameState) { - if (this.Config.difficulty >= 2 && this.femaleRatio > 0.4) + if (this.Config.difficulty > 2 && this.femaleRatio > 0.4) this.femaleRatio = 0.4; this.phaseStarted = 2; @@ -503,7 +503,7 @@ m.HQ.prototype.OnTownPhase = function(gameState) // Called by the "city phase" research plan once it's started m.HQ.prototype.OnCityPhase = function(gameState) { - if (this.Config.difficulty >= 2 && this.femaleRatio > 0.3) + if (this.Config.difficulty > 2 && this.femaleRatio > 0.3) this.femaleRatio = 0.3; this.phaseStarted = 3; @@ -1293,8 +1293,6 @@ m.HQ.prototype.buildMoreHouses = function(gameState,queues) if (numPlanned < 3 || (numPlanned < 5 && gameState.getPopulation() > 80)) { var plan = new m.ConstructionPlan(gameState, "structures/{civ}_house"); - // make the difficulty available to the isGo function without having to pass it as argument - var difficulty = this.Config.difficulty; var self = this; // change the starting condition according to the situation. plan.isGo = function (gameState) { @@ -1310,9 +1308,9 @@ m.HQ.prototype.buildMoreHouses = function(gameState,queues) freeSlots = gameState.getPopulationLimit() + HouseNb*popBonus - gameState.getPopulation(); if (self.saveResources) return (freeSlots <= 10); - else if (gameState.getPopulation() > 55 && difficulty > 1) + else if (gameState.getPopulation() > 55) return (freeSlots <= 21); - else if (gameState.getPopulation() >= 30 && difficulty > 0) + else if (gameState.getPopulation() > 30) return (freeSlots <= 15); else return (freeSlots <= 10); diff --git a/binaries/data/mods/public/simulation/ai/petra/queueplan-building.js b/binaries/data/mods/public/simulation/ai/petra/queueplan-building.js index 758bafa4b3..675a8f5174 100644 --- a/binaries/data/mods/public/simulation/ai/petra/queueplan-building.js +++ b/binaries/data/mods/public/simulation/ai/petra/queueplan-building.js @@ -478,7 +478,6 @@ m.ConstructionPlan.prototype.Deserialize = function(gameState, data) // TODO find a way to properly serialize functions. For the time being, they are manually added if (this.type == gameState.applyCiv("structures/{civ}_house")) { - var difficulty = gameState.ai.Config.difficulty; // change the starting condition according to the situation. this.isGo = function (gameState) { if (!gameState.ai.HQ.canBuild(gameState, "structures/{civ}_house")) @@ -493,9 +492,9 @@ m.ConstructionPlan.prototype.Deserialize = function(gameState, data) freeSlots = gameState.getPopulationLimit() + HouseNb*popBonus - gameState.getPopulation(); if (gameState.ai.HQ.saveResources) return (freeSlots <= 10); - else if (gameState.getPopulation() > 55 && difficulty > 1) + else if (gameState.getPopulation() > 55) return (freeSlots <= 21); - else if (gameState.getPopulation() >= 30 && difficulty > 0) + else if (gameState.getPopulation() > 30) return (freeSlots <= 15); else return (freeSlots <= 10); diff --git a/binaries/data/mods/public/simulation/data/player_defaults.json b/binaries/data/mods/public/simulation/data/player_defaults.json index 5e7642d5f1..7989b5d39a 100644 --- a/binaries/data/mods/public/simulation/data/player_defaults.json +++ b/binaries/data/mods/public/simulation/data/player_defaults.json @@ -6,63 +6,63 @@ "Civ": "gaia", "Colour": { "r": 255, "g": 255, "b": 255 }, "AI": "", - "AIDiff": 2 + "AIDiff": 3 }, { "Name": "Player 1", "Civ": "athen", "Colour": { "r": 46, "g": 46, "b": 200 }, "AI": "", - "AIDiff": 2 + "AIDiff": 3 }, { "Name": "Player 2", "Civ": "cart", "Colour": { "r": 150, "g": 20, "b": 20 }, "AI": "petra", - "AIDiff": 2 + "AIDiff": 3 }, { "Name": "Player 3", "Civ": "gaul", "Colour": { "r": 50, "g": 165, "b": 5 }, "AI": "petra", - "AIDiff": 2 + "AIDiff": 3 }, { "Name": "Player 4", "Civ": "iber", "Colour": { "r": 230, "g": 230, "b": 75 }, "AI": "petra", - "AIDiff": 2 + "AIDiff": 3 }, { "Name": "Player 5", "Civ": "mace", "Colour": { "r": 50, "g": 170, "b": 170 }, "AI": "petra", - "AIDiff": 2 + "AIDiff": 3 }, { "Name": "Player 6", "Civ": "maur", "Colour": { "r": 160, "g": 80, "b": 200 }, "AI": "petra", - "AIDiff": 2 + "AIDiff": 3 }, { "Name": "Player 7", "Civ": "pers", "Colour": { "r": 235, "g": 120, "b": 20 }, "AI": "petra", - "AIDiff": 2 + "AIDiff": 3 }, { "Name": "Player 8", "Civ": "rome", "Colour": { "r": 64, "g": 64, "b": 64 }, "AI": "petra", - "AIDiff": 2 + "AIDiff": 3 } ] } diff --git a/binaries/data/mods/public/simulation/helpers/InitGame.js b/binaries/data/mods/public/simulation/helpers/InitGame.js index 74fae08108..67b19dce25 100644 --- a/binaries/data/mods/public/simulation/helpers/InitGame.js +++ b/binaries/data/mods/public/simulation/helpers/InitGame.js @@ -37,7 +37,8 @@ function InitGame(settings) { cmpAIManager.AddPlayer(settings.PlayerData[i].AI, i+1, +settings.PlayerData[i].AIDiff); cmpPlayer.SetAI(true); - cmpPlayer.SetGatherRateMultiplier(+Math.max(0.5,(+settings.PlayerData[i].AIDiff+1)/3.0)); // Sandbox: 50%, easy: 66%, Medium: 100%, hard: 133%, very hard: 166% + // Sandbox: 50%, very easy: 50%, easy: 66%, Medium: 100%, hard: 133%, very hard: 166% + cmpPlayer.SetGatherRateMultiplier(Math.max(0.5,(+settings.PlayerData[i].AIDiff)/3.0)); } if (settings.PopulationCap) cmpPlayer.SetMaxPopulation(settings.PopulationCap); diff --git a/binaries/system/readme.txt b/binaries/system/readme.txt index a55b7bbd79..eed8dd585e 100644 --- a/binaries/system/readme.txt +++ b/binaries/system/readme.txt @@ -9,7 +9,7 @@ Basic gameplay: Autostart: -autostart="TYPEDIR/MAPNAME" enables autostart and sets MAPNAME; TYPEDIR is skirmishes, scenarios, or random -autostart-ai=PLAYER:AI sets the AI for PLAYER (e.g. 2:petra) --autostart-aidiff=PLAYER:DIFF sets the DIFFiculty of PLAYER's AI (0: sandbox, 4: very hard) +-autostart-aidiff=PLAYER:DIFF sets the DIFFiculty of PLAYER's AI (0: sandbox, 5: very hard) -autostart-civ=PLAYER:CIV sets PLAYER's civilisation to CIV (skirmish and random maps only) -autostart-aiseed=AISEED sets the seed used for the AI random generator (default 0, use -1 for random) Multiplayer: diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index 3c9cd82f4a..e9521b0c3d 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -1159,11 +1159,11 @@ CStr8 LoadSettingsOfScenarioMap(const VfsPath &mapPath) } /* - * Command line options for autostart (keep synchronized with readme.txt): + * Command line options for autostart (keep synchronized with binaries/system/readme.txt): * * -autostart="TYPEDIR/MAPNAME" enables autostart and sets MAPNAME; TYPEDIR is skirmishes, scenarios, or random * -autostart-ai=PLAYER:AI sets the AI for PLAYER (e.g. 2:petra) - * -autostart-aidiff=PLAYER:DIFF sets the DIFFiculty of PLAYER's AI (0: sandbox, 4: very hard) + * -autostart-aidiff=PLAYER:DIFF sets the DIFFiculty of PLAYER's AI (0: sandbox, 5: very hard) * -autostart-civ=PLAYER:CIV sets PLAYER's civilisation to CIV (skirmish and random maps only) * -autostart-aiseed=AISEED sets the seed used for the AI random generator (default 0, use -1 for random) * Multiplayer: