Index: ps/trunk/binaries/data/mods/public/simulation/ai/petra/config.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/ai/petra/config.js (revision 24596)
+++ ps/trunk/binaries/data/mods/public/simulation/ai/petra/config.js (revision 24597)
@@ -1,291 +1,291 @@
PETRA.Config = function(difficulty, behavior)
{
// 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;
// for instance "balanced", "aggressive" or "defensive"
this.behavior = behavior || "random";
// debug level: 0=none, 1=sanity checks, 2=debug, 3=detailed debug, -100=serializatio debug
this.debug = 0;
this.chat = true; // false to prevent AI's chats
this.popScaling = 1; // scale factor depending on the max population
this.Military = {
"towerLapseTime": 90, // Time to wait between building 2 towers
"fortressLapseTime": 390, // Time to wait between building 2 fortresses
"popForBarracks1": 25,
"popForBarracks2": 95,
"popForForge": 65,
"numSentryTowers": 1
};
// Define damage type importance factors here.
this.DamageTypeImportance = {
"Hack": 0.085,
"Pierce": 0.075,
"Crush": 0.065
};
this.Economy = {
"popPhase2": 38, // How many units we want before aging to phase2.
"workPhase3": 65, // How many workers we want before aging to phase3.
"workPhase4": 80, // How many workers we want before aging to phase4 or higher.
"popForDock": 25,
"targetNumWorkers": 40, // dummy, will be changed later
"targetNumTraders": 5, // Target number of traders
"targetNumFishers": 1, // Target number of fishers per sea
"supportRatio": 0.35, // fraction of support workers among the workforce
"provisionFields": 2
};
// Note: attack settings are set directly in attack_plan.js
// defense
this.Defense =
{
"defenseRatio": { "ally": 1.4, "neutral": 1.8, "own": 2 }, // ratio of defenders/attackers.
"armyCompactSize": 2000, // squared. Half-diameter of an army.
"armyBreakawaySize": 3500, // squared.
"armyMergeSize": 1400 // squared.
};
// Additional buildings that the AI does not yet know when to build
// and that it will try to build on phase 3 when enough resources.
this.buildings =
{
"default": [],
"athen": [
"structures/{civ}/gymnasium",
"structures/{civ}/prytaneion",
"structures/{civ}/theater"
],
"brit": [],
"cart": [
"structures/{civ}/embassy_celtic",
"structures/{civ}/embassy_iberian",
"structures/{civ}/embassy_italic"
],
"gaul": [
- "structures/{civ}/tavern"
+ "structures/{civ}/assembly"
],
"iber": [
"structures/{civ}/monument"
],
"kush": [
"structures/{civ}/camp_blemmye",
"structures/{civ}/camp_noba",
"structures/{civ}/pyramid_large",
"structures/{civ}/pyramid_small",
"structures/{civ}/temple_amun"
],
"mace": [
"structures/{civ}/library",
"structures/{civ}/theater"
],
"maur": [
"structures/{civ}/palace",
"structures/{civ}/pillar_ashoka"
],
"pers": [
"structures/{civ}/apadana"
],
"ptol": [
"structures/{civ}/library"
],
"rome": [
"structures/{civ}/army_camp",
"structures/{civ}/temple_vesta"
],
"sele": [
"structures/{civ}/library"
],
"spart": [
"structures/{civ}/syssiton",
"structures/{civ}/theater"
]
};
this.priorities =
{
"villager": 30, // should be slightly lower than the citizen soldier one to not get all the food
"citizenSoldier": 60,
"trader": 50,
"healer": 20,
"ships": 70,
"house": 350,
"dropsites": 200,
"field": 400,
"dock": 90,
"corral": 100,
"economicBuilding": 90,
"militaryBuilding": 130,
"defenseBuilding": 70,
"civilCentre": 950,
"majorTech": 700,
"minorTech": 40,
"wonder": 1000,
"emergency": 1000 // used only in emergency situations, should be the highest one
};
// Default personality (will be updated in setConfig)
this.personality =
{
"aggressive": 0.5,
"cooperative": 0.5,
"defensive": 0.5
};
// See PETRA.QueueManager.prototype.wantedGatherRates()
this.queues =
{
"firstTurn": {
"food": 10,
"wood": 10,
"default": 0
},
"short": {
"food": 200,
"wood": 200,
"default": 100
},
"medium": {
"default": 0
},
"long": {
"default": 0
}
};
this.garrisonHealthLevel = { "low": 0.4, "medium": 0.55, "high": 0.7 };
};
PETRA.Config.prototype.setConfig = function(gameState)
{
if (this.difficulty > 0)
{
// Setup personality traits according to the user choice:
// The parameter used to define the personality is basically the aggressivity or (1-defensiveness)
// as they are anticorrelated, although some small smearing to decorelate them will be added.
// And for each user choice, this parameter can vary between min and max
let personalityList = {
"random": { "min": 0, "max": 1 },
"defensive": { "min": 0, "max": 0.27 },
"balanced": { "min": 0.37, "max": 0.63 },
"aggressive": { "min": 0.73, "max": 1 }
};
let behavior = randFloat(-0.5, 0.5);
// make agressive and defensive quite anticorrelated (aggressive ~ 1 - defensive) but not completelety
let variation = 0.15 * randFloat(-1, 1) * Math.sqrt(Math.square(0.5) - Math.square(behavior));
let aggressive = Math.max(Math.min(behavior + variation, 0.5), -0.5) + 0.5;
let defensive = Math.max(Math.min(-behavior + variation, 0.5), -0.5) + 0.5;
let min = personalityList[this.behavior].min;
let max = personalityList[this.behavior].max;
this.personality = {
"aggressive": min + aggressive * (max - min),
"defensive": 1 - max + defensive * (max - min),
"cooperative": randFloat(0, 1)
};
}
// Petra usually uses the continuous values of personality.aggressive and personality.defensive
// to define its behavior according to personality. But when discontinuous behavior is needed,
// it uses the following personalityCut which should be set such that:
// behavior="aggressive" => personality.aggressive > personalityCut.strong &&
// personality.defensive < personalityCut.weak
// and inversely for behavior="defensive"
this.personalityCut = { "weak": 0.3, "medium": 0.5, "strong": 0.7 };
if (gameState.playerData.teamsLocked)
this.personality.cooperative = Math.min(1, this.personality.cooperative + 0.30);
else if (gameState.getAlliedVictory())
this.personality.cooperative = Math.min(1, this.personality.cooperative + 0.15);
// changing settings based on difficulty or personality
this.Military.towerLapseTime = Math.round(this.Military.towerLapseTime * (1.1 - 0.2 * this.personality.defensive));
this.Military.fortressLapseTime = Math.round(this.Military.fortressLapseTime * (1.1 - 0.2 * this.personality.defensive));
this.priorities.defenseBuilding = Math.round(this.priorities.defenseBuilding * (0.9 + 0.2 * this.personality.defensive));
if (this.difficulty < 2)
{
this.Economy.supportRatio = 0.5;
this.Economy.provisionFields = 1;
this.Military.numSentryTowers = this.personality.defensive > this.personalityCut.strong ? 1 : 0;
}
else if (this.difficulty < 3)
{
this.Economy.supportRatio = 0.4;
this.Economy.provisionFields = 1;
this.Military.numSentryTowers = this.personality.defensive > this.personalityCut.strong ? 1 : 0;
}
else
{
if (this.difficulty == 3)
this.Military.numSentryTowers = 1;
else
this.Military.numSentryTowers = 2;
if (this.personality.defensive > this.personalityCut.strong)
++this.Military.numSentryTowers;
else if (this.personality.defensive < this.personalityCut.weak)
--this.Military.numSentryTowers;
if (this.personality.aggressive > this.personalityCut.strong)
{
this.Military.popForBarracks1 = 12;
this.Economy.popPhase2 = 50;
this.priorities.healer = 10;
}
}
let maxPop = gameState.getPopulationMax();
if (this.difficulty < 2)
this.Economy.targetNumWorkers = Math.max(1, Math.min(40, maxPop));
else if (this.difficulty < 3)
this.Economy.targetNumWorkers = Math.max(1, Math.min(60, Math.floor(maxPop/2)));
else
this.Economy.targetNumWorkers = Math.max(1, Math.min(120, Math.floor(maxPop/3)));
this.Economy.targetNumTraders = 2 + this.difficulty;
if (gameState.getVictoryConditions().has("wonder"))
{
this.Economy.workPhase3 = Math.floor(0.9 * this.Economy.workPhase3);
this.Economy.workPhase4 = Math.floor(0.9 * this.Economy.workPhase4);
}
if (maxPop < 300)
{
this.popScaling = Math.sqrt(maxPop / 300);
this.Military.popForBarracks1 = Math.min(Math.max(Math.floor(this.Military.popForBarracks1 * this.popScaling), 12), Math.floor(maxPop/5));
this.Military.popForBarracks2 = Math.min(Math.max(Math.floor(this.Military.popForBarracks2 * this.popScaling), 45), Math.floor(maxPop*2/3));
this.Military.popForForge = Math.min(Math.max(Math.floor(this.Military.popForForge * this.popScaling), 30), Math.floor(maxPop/2));
this.Economy.popPhase2 = Math.min(Math.max(Math.floor(this.Economy.popPhase2 * this.popScaling), 20), Math.floor(maxPop/2));
this.Economy.workPhase3 = Math.min(Math.max(Math.floor(this.Economy.workPhase3 * this.popScaling), 40), Math.floor(maxPop*2/3));
this.Economy.workPhase4 = Math.min(Math.max(Math.floor(this.Economy.workPhase4 * this.popScaling), 45), Math.floor(maxPop*2/3));
this.Economy.targetNumTraders = Math.round(this.Economy.targetNumTraders * this.popScaling);
}
this.Economy.targetNumWorkers = Math.max(this.Economy.targetNumWorkers, this.Economy.popPhase2);
this.Economy.workPhase3 = Math.min(this.Economy.workPhase3, this.Economy.targetNumWorkers);
this.Economy.workPhase4 = Math.min(this.Economy.workPhase4, this.Economy.targetNumWorkers);
if (this.difficulty < 2)
this.Economy.workPhase3 = Infinity; // prevent the phasing to city phase
if (this.debug < 2)
return;
API3.warn(" >>> Petra bot: personality = " + uneval(this.personality));
};
PETRA.Config.prototype.Serialize = function()
{
var data = {};
for (let key in this)
if (this.hasOwnProperty(key) && key != "debug")
data[key] = this[key];
return data;
};
PETRA.Config.prototype.Deserialize = function(data)
{
for (let key in data)
this[key] = data[key];
};
Index: ps/trunk/binaries/data/mods/public/simulation/components/Identity.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/Identity.js (revision 24596)
+++ ps/trunk/binaries/data/mods/public/simulation/components/Identity.js (revision 24597)
@@ -1,204 +1,204 @@
function Identity() {}
Identity.prototype.Schema =
"Specifies various names and values associated with the entity, typically for GUI display to users." +
"" +
"athen" +
"Athenian Hoplite" +
"Hoplī́tēs Athēnaïkós" +
"units/athen_infantry_spearman.png" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"tokens" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"Basic" +
"Advanced" +
"Elite" +
"" +
"" +
"" +
"" +
"" +
"" +
"tokens" +
"" +
"" +
"" +
"" +
"" +
- "" +
+ "" +
"" +
"tokens" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"tokens" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"";
Identity.prototype.Init = function()
{
this.classesList = GetIdentityClasses(this.template);
this.visibleClassesList = GetVisibleIdentityClasses(this.template);
if (this.template.Phenotype)
this.phenotype = pickRandom(this.GetPossiblePhenotypes());
else
this.phenotype = "default";
this.controllable = this.template.Controllable ? this.template.Controllable == "true" : true;
};
Identity.prototype.HasSomeFormation = function()
{
return this.GetFormationsList().length > 0;
};
Identity.prototype.GetCiv = function()
{
return this.template.Civ;
};
Identity.prototype.GetLang = function()
{
return this.template.Lang || "greek"; // ugly default
};
/**
* Get a list of possible Phenotypes.
* @return {string[]} A list of possible phenotypes.
*/
Identity.prototype.GetPossiblePhenotypes = function()
{
return this.template.Phenotype._string.split(/\s+/);
};
/**
* Get the current Phenotype.
* @return {string} The current phenotype.
*/
Identity.prototype.GetPhenotype = function()
{
return this.phenotype;
};
Identity.prototype.GetRank = function()
{
return this.template.Rank || "";
};
Identity.prototype.GetClassesList = function()
{
return this.classesList;
};
Identity.prototype.GetVisibleClassesList = function()
{
return this.visibleClassesList;
};
Identity.prototype.HasClass = function(name)
{
return this.GetClassesList().indexOf(name) != -1;
};
Identity.prototype.GetFormationsList = function()
{
if (this.template.Formations && this.template.Formations._string)
return this.template.Formations._string.split(/\s+/);
return [];
};
Identity.prototype.CanUseFormation = function(template)
{
return this.GetFormationsList().indexOf(template) != -1;
};
Identity.prototype.GetSelectionGroupName = function()
{
return this.template.SelectionGroupName || "";
};
Identity.prototype.GetGenericName = function()
{
return this.template.GenericName;
};
Identity.prototype.IsUndeletable = function()
{
return this.template.Undeletable == "true";
};
Identity.prototype.IsControllable = function()
{
return this.controllable;
};
Identity.prototype.SetControllable = function(controllability)
{
this.controllable = controllability;
};
Engine.RegisterComponentType(IID_Identity, "Identity", Identity);
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/gaul/assembly.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/gaul/assembly.xml (revision 24596)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/gaul/assembly.xml (revision 24597)
@@ -1,75 +1,86 @@
+
+ Council
+
- 500
+ 200
- 500
- 500
+ 400
10.0
- 5
+ 20
0.1
Unit
Support Infantry Cavalry
0
2
2000
decay|rubble/rubble_stone_6x6
gaul
Assembly of Princes
Remogantion
- City Assembly
+ Train Heroes.
+ ConquestCritical CivSpecific
+ City Council
structures/tholos.png
phase_city
- 100
- 100
+ 80
+
+ 0.7
+
+ units/{civ}/hero_brennus
+ units/{civ}/hero_viridomarus
+ units/{civ}/hero_vercingetorix
+
+
20
30
3
- 3
+ 1
10
- 3
+ 1
interface/complete/building/complete_iber_monument.xml
false
- 100
+ 40
40000
40
structures/gauls/theater.xml
structures/fndn_6x6.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/gaul/fortress.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/gaul/fortress.xml (revision 24596)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/gaul/fortress.xml (revision 24597)
@@ -1,32 +1,29 @@
gaul
Dunon
- Territory root. Train Champion Infantry and Heroes. Garrison Soldiers for additional arrows.
+ Territory root. Train Champion Infantry. Garrison Soldiers for additional arrows.
12
units/{civ}/champion_infantry
- units/{civ}/hero_brennus
- units/{civ}/hero_viridomarus
- units/{civ}/hero_vercingetorix
interface/complete/building/complete_fortress.xml
structures/gauls/fortress.xml
16.8
5.8
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/infantry_javelineer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/infantry_javelineer_b.xml (revision 24596)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/infantry_javelineer_b.xml (revision 24597)
@@ -1,15 +1,20 @@
+
+
+ structures/gaul/assembly
+
+
gaul
units/gaul/infantry_javelineer_b
Adretos
units/gaul_infantry_javelinist.png
units/gaul/infantry_javelineer_a
units/gauls/infantry_javelinist_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/infantry_slinger_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/infantry_slinger_b.xml (revision 24596)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/infantry_slinger_b.xml (revision 24597)
@@ -1,16 +1,21 @@
+
+
+ structures/gaul/assembly
+
+
gaul
units/gaul/infantry_slinger_b
Talmoris
units/gaul_infantry_slinger.png
phase_town
units/gaul/infantry_slinger_a
units/gauls/infantry_slinger_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/infantry_spearman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/infantry_spearman_b.xml (revision 24596)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/infantry_spearman_b.xml (revision 24597)
@@ -1,15 +1,20 @@
+
+
+ structures/gaul/assembly
+
+
gaul
units/gaul/infantry_spearman_b
Catucos
units/gaul_infantry_spearman.png
units/gaul/infantry_spearman_a
units/gauls/infantry_spearman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/support_female_citizen.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/support_female_citizen.xml (revision 24596)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/support_female_citizen.xml (revision 24597)
@@ -1,12 +1,17 @@
+
+
+ structures/gaul/assembly
+
+
gaul
Celtic Woman
Bena
units/celt_support_female_citizen.png
units/celts/female_citizen.xml