1
0
forked from 0ad/0ad

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");
// 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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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);

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
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);

View File

@ -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
}
]
}

View File

@ -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);

View File

@ -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:

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-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: