add a very-easy level for AI, addresses #2899

This was SVN commit r15990.
This commit is contained in:
mimo 2014-11-18 21:21:21 +00:00
parent da1af993f7
commit f90841cf78
9 changed files with 47 additions and 37 deletions

View File

@ -26,7 +26,7 @@ function init(settings)
var aiDiff = Engine.GetGUIObjectByName("aiDifficulty"); var aiDiff = Engine.GetGUIObjectByName("aiDifficulty");
// Translation: AI difficulty level. // 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; aiDiff.selected = settings.difficulty;
} }

View File

@ -130,9 +130,17 @@ m.AttackPlan = function(gameState, Config, uniqueID, type, data)
// Put some randomness on the attack size // Put some randomness on the attack size
var variation = 0.8 + 0.4*Math.random(); 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) 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) for (var cat in this.unitStat)
{ {
this.unitStat[cat]["targetSize"] = Math.round(variation * this.unitStat[cat]["targetSize"]); 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") if (gameState.civ() === "maur")
stat["classes"] = ["Elephant", "Champion"]; stat["classes"] = ["Elephant", "Champion"];
if (this.Config.difficulty < 2) if (this.Config.difficulty < 2)
stat["targetSize"] = 1;
else if (this.Config.difficulty < 3)
stat["targetSize"] = 2; stat["targetSize"] = 2;
this.addBuildOrder(gameState, "Siege", stat, true); this.addBuildOrder(gameState, "Siege", stat, true);
return true; return true;

View File

@ -3,8 +3,8 @@ var PETRA = function(m)
m.Config = function(difficulty) m.Config = function(difficulty)
{ {
// 0 is sandbox, 1 is easy, 2 is medium, 3 is hard, 4 is very hard. // 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 : 2; this.difficulty = (difficulty !== undefined) ? difficulty : 3;
// debug level: 0=none, 1=sanity checks, 2=debug; 3=detailed debug // debug level: 0=none, 1=sanity checks, 2=debug; 3=detailed debug
this.debug = 0; this.debug = 0;
@ -112,24 +112,26 @@ m.Config.prototype.setConfig = function(gameState)
this.personality.cooperative = Math.random(); this.personality.cooperative = Math.random();
this.personality.defensive = Math.random(); this.personality.defensive = Math.random();
} }
else
this.personality.aggressive = 0.1;
// changing settings based on difficulty (if < 2) or personality // changing settings based on difficulty or personality
if (this.difficulty === 0) if (this.difficulty < 2)
{ {
this.Military.popForBarracks1 = 60; this.Military.popForBarracks1 = 60;
this.Military.popForBarracks2 = 150; // shouldn't reach it this.Military.popForBarracks2 = 300;
this.Military.popForBlacksmith = 150; // shouldn't reach it this.Military.popForBlacksmith = 300;
this.Economy.cityPhase = 240000; this.Economy.cityPhase = 240000;
this.Economy.popForMarket = 200; this.Economy.popForMarket = 200;
this.Economy.femaleRatio = 0.7; this.Economy.femaleRatio = 0.7;
this.Economy.initialFields = 1; this.Economy.initialFields = 1;
} }
else if (this.difficulty === 1) else if (this.difficulty < 3)
{ {
this.Military.popForBarracks1 = 35; this.Military.popForBarracks1 = 35;
this.Military.popForBarracks2 = 150; // shouldn't reach it this.Military.popForBarracks2 = 150;
this.Military.popForBlacksmith = 150; // shouldn't reach it this.Military.popForBlacksmith = 150;
this.Economy.cityPhase = 1800; this.Economy.cityPhase = 1800;
this.Economy.popForMarket = 80; 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) if (gameState.getPopulationMax() < 300)
this.popScaling = Math.sqrt(gameState.getPopulationMax() / 300); this.popScaling = Math.sqrt(gameState.getPopulationMax() / 300);

View File

@ -97,9 +97,9 @@ m.HQ.prototype.init = function(gameState, queues, deserializing)
API3.warn(" >>> zone " + region + " taille " + gameState.ai.accessibility.regionSize[region]); 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()))); 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))); this.targetNumWorkers = Math.max(1, Math.min(60, Math.floor(gameState.getPopulationMax()/2)));
else else
this.targetNumWorkers = Math.max(1, Math.min(120, Math.floor(gameState.getPopulationMax()/3))); 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 // Called by the "town phase" research plan once it's started
m.HQ.prototype.OnTownPhase = function(gameState) 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.femaleRatio = 0.4;
this.phaseStarted = 2; this.phaseStarted = 2;
@ -503,7 +503,7 @@ m.HQ.prototype.OnTownPhase = function(gameState)
// Called by the "city phase" research plan once it's started // Called by the "city phase" research plan once it's started
m.HQ.prototype.OnCityPhase = function(gameState) 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.femaleRatio = 0.3;
this.phaseStarted = 3; this.phaseStarted = 3;
@ -1293,8 +1293,6 @@ m.HQ.prototype.buildMoreHouses = function(gameState,queues)
if (numPlanned < 3 || (numPlanned < 5 && gameState.getPopulation() > 80)) if (numPlanned < 3 || (numPlanned < 5 && gameState.getPopulation() > 80))
{ {
var plan = new m.ConstructionPlan(gameState, "structures/{civ}_house"); 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; var self = this;
// change the starting condition according to the situation. // change the starting condition according to the situation.
plan.isGo = function (gameState) { plan.isGo = function (gameState) {
@ -1310,9 +1308,9 @@ m.HQ.prototype.buildMoreHouses = function(gameState,queues)
freeSlots = gameState.getPopulationLimit() + HouseNb*popBonus - gameState.getPopulation(); freeSlots = gameState.getPopulationLimit() + HouseNb*popBonus - gameState.getPopulation();
if (self.saveResources) if (self.saveResources)
return (freeSlots <= 10); return (freeSlots <= 10);
else if (gameState.getPopulation() > 55 && difficulty > 1) else if (gameState.getPopulation() > 55)
return (freeSlots <= 21); return (freeSlots <= 21);
else if (gameState.getPopulation() >= 30 && difficulty > 0) else if (gameState.getPopulation() > 30)
return (freeSlots <= 15); return (freeSlots <= 15);
else else
return (freeSlots <= 10); return (freeSlots <= 10);

View File

@ -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 // TODO find a way to properly serialize functions. For the time being, they are manually added
if (this.type == gameState.applyCiv("structures/{civ}_house")) if (this.type == gameState.applyCiv("structures/{civ}_house"))
{ {
var difficulty = gameState.ai.Config.difficulty;
// change the starting condition according to the situation. // change the starting condition according to the situation.
this.isGo = function (gameState) { this.isGo = function (gameState) {
if (!gameState.ai.HQ.canBuild(gameState, "structures/{civ}_house")) 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(); freeSlots = gameState.getPopulationLimit() + HouseNb*popBonus - gameState.getPopulation();
if (gameState.ai.HQ.saveResources) if (gameState.ai.HQ.saveResources)
return (freeSlots <= 10); return (freeSlots <= 10);
else if (gameState.getPopulation() > 55 && difficulty > 1) else if (gameState.getPopulation() > 55)
return (freeSlots <= 21); return (freeSlots <= 21);
else if (gameState.getPopulation() >= 30 && difficulty > 0) else if (gameState.getPopulation() > 30)
return (freeSlots <= 15); return (freeSlots <= 15);
else else
return (freeSlots <= 10); return (freeSlots <= 10);

View File

@ -6,63 +6,63 @@
"Civ": "gaia", "Civ": "gaia",
"Colour": { "r": 255, "g": 255, "b": 255 }, "Colour": { "r": 255, "g": 255, "b": 255 },
"AI": "", "AI": "",
"AIDiff": 2 "AIDiff": 3
}, },
{ {
"Name": "Player 1", "Name": "Player 1",
"Civ": "athen", "Civ": "athen",
"Colour": { "r": 46, "g": 46, "b": 200 }, "Colour": { "r": 46, "g": 46, "b": 200 },
"AI": "", "AI": "",
"AIDiff": 2 "AIDiff": 3
}, },
{ {
"Name": "Player 2", "Name": "Player 2",
"Civ": "cart", "Civ": "cart",
"Colour": { "r": 150, "g": 20, "b": 20 }, "Colour": { "r": 150, "g": 20, "b": 20 },
"AI": "petra", "AI": "petra",
"AIDiff": 2 "AIDiff": 3
}, },
{ {
"Name": "Player 3", "Name": "Player 3",
"Civ": "gaul", "Civ": "gaul",
"Colour": { "r": 50, "g": 165, "b": 5 }, "Colour": { "r": 50, "g": 165, "b": 5 },
"AI": "petra", "AI": "petra",
"AIDiff": 2 "AIDiff": 3
}, },
{ {
"Name": "Player 4", "Name": "Player 4",
"Civ": "iber", "Civ": "iber",
"Colour": { "r": 230, "g": 230, "b": 75 }, "Colour": { "r": 230, "g": 230, "b": 75 },
"AI": "petra", "AI": "petra",
"AIDiff": 2 "AIDiff": 3
}, },
{ {
"Name": "Player 5", "Name": "Player 5",
"Civ": "mace", "Civ": "mace",
"Colour": { "r": 50, "g": 170, "b": 170 }, "Colour": { "r": 50, "g": 170, "b": 170 },
"AI": "petra", "AI": "petra",
"AIDiff": 2 "AIDiff": 3
}, },
{ {
"Name": "Player 6", "Name": "Player 6",
"Civ": "maur", "Civ": "maur",
"Colour": { "r": 160, "g": 80, "b": 200 }, "Colour": { "r": 160, "g": 80, "b": 200 },
"AI": "petra", "AI": "petra",
"AIDiff": 2 "AIDiff": 3
}, },
{ {
"Name": "Player 7", "Name": "Player 7",
"Civ": "pers", "Civ": "pers",
"Colour": { "r": 235, "g": 120, "b": 20 }, "Colour": { "r": 235, "g": 120, "b": 20 },
"AI": "petra", "AI": "petra",
"AIDiff": 2 "AIDiff": 3
}, },
{ {
"Name": "Player 8", "Name": "Player 8",
"Civ": "rome", "Civ": "rome",
"Colour": { "r": 64, "g": 64, "b": 64 }, "Colour": { "r": 64, "g": 64, "b": 64 },
"AI": "petra", "AI": "petra",
"AIDiff": 2 "AIDiff": 3
} }
] ]
} }

View File

@ -37,7 +37,8 @@ function InitGame(settings)
{ {
cmpAIManager.AddPlayer(settings.PlayerData[i].AI, i+1, +settings.PlayerData[i].AIDiff); cmpAIManager.AddPlayer(settings.PlayerData[i].AI, i+1, +settings.PlayerData[i].AIDiff);
cmpPlayer.SetAI(true); 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) if (settings.PopulationCap)
cmpPlayer.SetMaxPopulation(settings.PopulationCap); cmpPlayer.SetMaxPopulation(settings.PopulationCap);

View File

@ -9,7 +9,7 @@ Basic gameplay:
Autostart: Autostart:
-autostart="TYPEDIR/MAPNAME" enables autostart and sets MAPNAME; TYPEDIR is skirmishes, scenarios, or random -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-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-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) -autostart-aiseed=AISEED sets the seed used for the AI random generator (default 0, use -1 for random)
Multiplayer: Multiplayer:

View File

@ -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="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-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-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) * -autostart-aiseed=AISEED sets the seed used for the AI random generator (default 0, use -1 for random)
* Multiplayer: * Multiplayer: