1
0
forked from 0ad/0ad

[PetraAI] - Use enum-like variables instead of magic values. -- [2]

Improved readability. Easier find-and-replace.

This commit focused on:
- Worker
- TransportPlan
- Difficulty

Patch by: @JCWasmx86
Differential revision: https://code.wildfiregames.com/D4343
Refs. #6256
Comments by: @nani, @Silier, @Stan
This was SVN commit r26063.
This commit is contained in:
Freagarach 2021-12-13 08:04:33 +00:00
parent 7e0a42c87d
commit a8c25837cb
18 changed files with 173 additions and 142 deletions

View File

@ -171,7 +171,7 @@ PETRA.AttackManager.prototype.assignBombers = function(gameState)
if (ent.getMetadata(PlayerID, "plan") !== undefined && ent.getMetadata(PlayerID, "plan") != -1)
{
let subrole = ent.getMetadata(PlayerID, "subrole");
if (subrole && (subrole == "completing" || subrole == "walking" || subrole == "attacking"))
if (subrole && (subrole === PETRA.Worker.SUBROLE_COMPLETING || subrole === PETRA.Worker.SUBROLE_WALKING || subrole === PETRA.Worker.SUBROLE_ATTACKING))
continue;
}
let alreadyBombing = false;
@ -393,7 +393,7 @@ PETRA.AttackManager.prototype.update = function(gameState, queues, events)
}
// Check if we have some unused ranged siege unit which could do something useful while waiting
if (this.Config.difficulty > 1 && gameState.ai.playedTurn % 5 == 0)
if (this.Config.difficulty > PETRA.DIFFICULTY_VERY_EASY && gameState.ai.playedTurn % 5 == 0)
this.assignBombers(gameState);
};
@ -734,7 +734,7 @@ PETRA.AttackManager.prototype.switchDefenseToAttack = function(gameState, target
if (unit && accessOk && attackPlan.isAvailableUnit(gameState, unit))
{
unit.setMetadata(PlayerID, "plan", attackPlan.name);
unit.setMetadata(PlayerID, "role", "attack");
unit.setMetadata(PlayerID, "role", PETRA.Worker.ROLE_ATTACK);
attackPlan.unitCollection.updateEnt(unit);
}
}
@ -745,7 +745,7 @@ PETRA.AttackManager.prototype.switchDefenseToAttack = function(gameState, target
return false;
}
for (let unit of attackPlan.unitCollection.values())
unit.setMetadata(PlayerID, "role", "attack");
unit.setMetadata(PlayerID, "role", PETRA.Worker.ROLE_ATTACK);
attackPlan.targetPlayer = target.owner();
attackPlan.targetPos = pos;
attackPlan.target = target;

View File

@ -170,18 +170,18 @@ PETRA.AttackPlan = function(gameState, Config, uniqueID, type = PETRA.AttackPlan
// Put some randomness on the attack size
let variation = randFloat(0.8, 1.2);
// and lower priority and smaller sizes for easier difficulty levels
if (this.Config.difficulty < 2)
if (this.Config.difficulty < PETRA.DIFFICULTY_EASY)
{
priority *= 0.4;
variation *= 0.2;
}
else if (this.Config.difficulty < 3)
else if (this.Config.difficulty < PETRA.DIFFICULTY_MEDIUM)
{
priority *= 0.8;
variation *= 0.6;
}
if (this.Config.difficulty < 2)
if (this.Config.difficulty < PETRA.DIFFICULTY_EASY)
{
for (const cat in this.unitStat)
{
@ -422,7 +422,7 @@ PETRA.AttackPlan.prototype.addSiegeUnits = function(gameState)
this.siegeState = PETRA.AttackPlan.SIEGE_ADDED;
let targetSize;
if (this.Config.difficulty < 3)
if (this.Config.difficulty < PETRA.DIFFICULTY_MEDIUM)
targetSize = this.type === PETRA.AttackPlan.TYPE_HUGE_ATTACK ? Math.max(this.Config.difficulty, 1) : Math.max(this.Config.difficulty - 1, 0);
else
targetSize = this.type === PETRA.AttackPlan.TYPE_HUGE_ATTACK ? this.Config.difficulty + 1 : this.Config.difficulty - 1;
@ -586,8 +586,8 @@ PETRA.AttackPlan.prototype.updatePreparation = function(gameState)
ent.setMetadata(PlayerID, "plan", -1);
continue;
}
ent.setMetadata(PlayerID, "role", "attack");
ent.setMetadata(PlayerID, "subrole", "completing");
ent.setMetadata(PlayerID, "role", PETRA.Worker.ROLE_ATTACK);
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_COMPLETING);
let queued = false;
if (ent.resourceCarrying() && ent.resourceCarrying().length)
queued = PETRA.returnResources(gameState, ent);
@ -675,7 +675,7 @@ PETRA.AttackPlan.prototype.trainMoreUnits = function(gameState)
let max = firstOrder[3].batchSize;
let specialData = "Plan_" + this.name + "_" + firstOrder[4];
let data = { "plan": this.name, "special": specialData, "base": 0 };
data.role = gameState.getTemplate(template).hasClass("CitizenSoldier") ? "worker" : "attack";
data.role = gameState.getTemplate(template).hasClass("CitizenSoldier") ? PETRA.Worker.ROLE_WORKER : PETRA.Worker.ROLE_ATTACK;
let trainingPlan = new PETRA.TrainingPlan(gameState, template, data, max, max);
if (trainingPlan.template)
queue.addPlan(trainingPlan);
@ -746,7 +746,7 @@ PETRA.AttackPlan.prototype.assignUnits = function(gameState)
// Finally add also some workers for the higher difficulties,
// If Rush, assign all kind of workers, keeping only a minimum number of defenders
// Otherwise, assign only some idle workers if too much of them
if (this.Config.difficulty <= 2)
if (this.Config.difficulty <= PETRA.DIFFICULTY_EASY)
return added;
let num = 0;
@ -754,7 +754,7 @@ PETRA.AttackPlan.prototype.assignUnits = function(gameState)
let keep = this.type !== PETRA.AttackPlan.TYPE_RUSH ?
6 + 4 * gameState.getNumPlayerEnemies() + 8 * this.Config.personality.defensive : 8;
keep = Math.round(this.Config.popScaling * keep);
for (const ent of gameState.getOwnEntitiesByRole("worker", true).values())
for (const ent of gameState.getOwnEntitiesByRole(PETRA.Worker.ROLE_WORKER, true).values())
{
if (!ent.hasClass("CitizenSoldier") || !this.isAvailableUnit(gameState, ent))
continue;
@ -769,7 +769,7 @@ PETRA.AttackPlan.prototype.assignUnits = function(gameState)
}
if (num++ < keep || numbase[baseID] < 5)
continue;
if (this.type !== PETRA.AttackPlan.TYPE_RUSH && ent.getMetadata(PlayerID, "subrole") != "idle")
if (this.type !== PETRA.AttackPlan.TYPE_RUSH && ent.getMetadata(PlayerID, "subrole") !== PETRA.Worker.SUBROLE_IDLE)
continue;
ent.setMetadata(PlayerID, "plan", plan);
this.unitCollection.updateEnt(ent);
@ -1256,7 +1256,7 @@ PETRA.AttackPlan.prototype.StartAttack = function(gameState)
for (let ent of this.unitCollection.values())
{
ent.setMetadata(PlayerID, "subrole", "walking");
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_WALKING);
let stance = ent.isPackable() ? "standground" : "aggressive";
if (ent.getStance() != stance)
ent.setStance(stance);
@ -1316,7 +1316,7 @@ PETRA.AttackPlan.prototype.update = function(gameState, events)
this.startingAttack = true;
this.unitCollection.forEach(ent => {
ent.stopMoving();
ent.setMetadata(PlayerID, "subrole", "attacking");
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_ATTACKING);
});
if (this.type === PETRA.AttackPlan.TYPE_RUSH) // try to find a better target for rush
{
@ -2041,7 +2041,7 @@ PETRA.AttackPlan.prototype.Abort = function(gameState)
for (let ent of this.unitCollection.values())
{
if (ent.getMetadata(PlayerID, "role") == "attack")
if (ent.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_ATTACK)
ent.stopMoving();
if (rallyPoint)
ent.moveToRange(rallyPoint[0], rallyPoint[1], 0, 15);
@ -2057,10 +2057,10 @@ PETRA.AttackPlan.prototype.Abort = function(gameState)
PETRA.AttackPlan.prototype.removeUnit = function(ent, update)
{
if (ent.getMetadata(PlayerID, "role") == "attack")
if (ent.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_ATTACK)
{
if (ent.hasClass("CitizenSoldier"))
ent.setMetadata(PlayerID, "role", "worker");
ent.setMetadata(PlayerID, "role", PETRA.Worker.ROLE_WORKER);
else
ent.setMetadata(PlayerID, "role", undefined);
ent.setMetadata(PlayerID, "subrole", undefined);

View File

@ -27,7 +27,7 @@ PETRA.BaseManager = function(gameState, basesManager)
this.constructing = false;
// Defenders to train in this cc when its construction is finished
this.neededDefenders = this.Config.difficulty > 2 ? 3 + 2*(this.Config.difficulty - 3) : 0;
this.neededDefenders = this.Config.difficulty > PETRA.DIFFICULTY_EASY ? 3 + 2*(this.Config.difficulty - 3) : 0;
// vector for iterating, to check one use the HQ map.
this.territoryIndices = [];
@ -62,7 +62,7 @@ PETRA.BaseManager.prototype.init = function(gameState, state)
this.workerObject = new PETRA.Worker(this);
// entitycollections
this.units = gameState.getOwnUnits().filter(API3.Filters.byMetadata(PlayerID, "base", this.ID));
this.workers = this.units.filter(API3.Filters.byMetadata(PlayerID, "role", "worker"));
this.workers = this.units.filter(API3.Filters.byMetadata(PlayerID, "role", PETRA.Worker.ROLE_WORKER));
this.buildings = gameState.getOwnStructures().filter(API3.Filters.byMetadata(PlayerID, "base", this.ID));
this.mobileDropsites = this.units.filter(API3.Filters.isDropsite());
@ -88,8 +88,7 @@ PETRA.BaseManager.prototype.reset = function(gameState, state)
this.constructing = true;
else
this.constructing = false;
if (state !== PETRA.BaseManager.STATE_CAPTURED || this.Config.difficulty < 3)
if (state !== PETRA.BaseManager.STATE_CAPTURED || this.Config.difficulty < PETRA.DIFFICULTY_MEDIUM)
this.neededDefenders = 0;
else
this.neededDefenders = 3 + 2 * (this.Config.difficulty - 3);
@ -510,14 +509,14 @@ PETRA.BaseManager.prototype.addGatherRates = function(gameState, currentRates)
});
if (res == "food")
{
this.workersBySubrole(gameState, "hunter").forEach(ent => {
this.workersBySubrole(gameState, PETRA.Worker.SUBROLE_HUNTER).forEach(ent => {
if (ent.isIdle() || !ent.position())
return;
let gRate = ent.currentGatherRate();
if (gRate)
currentRates[res] += Math.log(1+gRate)/1.1;
});
this.workersBySubrole(gameState, "fisher").forEach(ent => {
this.workersBySubrole(gameState, PETRA.Worker.SUBROLE_FISHER).forEach(ent => {
if (ent.isIdle() || !ent.position())
return;
let gRate = ent.currentGatherRate();
@ -536,7 +535,7 @@ PETRA.BaseManager.prototype.assignRolelessUnits = function(gameState, roleless)
for (let ent of roleless)
{
if (ent.hasClasses(["Worker", "CitizenSoldier", "FishingBoat"]))
ent.setMetadata(PlayerID, "role", "worker");
ent.setMetadata(PlayerID, "role", PETRA.Worker.ROLE_WORKER);
}
};
@ -632,7 +631,7 @@ PETRA.BaseManager.prototype.reassignIdleWorkers = function(gameState, idleWorker
// Search for idle workers, and tell them to gather resources based on demand
if (!idleWorkers)
{
let filter = API3.Filters.byMetadata(PlayerID, "subrole", "idle");
const filter = API3.Filters.byMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_IDLE);
idleWorkers = gameState.updatingCollection("idle-workers-base-" + this.ID, filter, this.workers).values();
}
@ -660,7 +659,7 @@ PETRA.BaseManager.prototype.reassignIdleWorkers = function(gameState, idleWorker
continue;
if (needed.type != "food" && this.basesManager.isResourceExhausted(needed.type))
continue;
ent.setMetadata(PlayerID, "subrole", "gatherer");
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_GATHERER);
ent.setMetadata(PlayerID, "gather-type", needed.type);
this.basesManager.AddTCResGatherer(needed.type);
break;
@ -668,9 +667,9 @@ PETRA.BaseManager.prototype.reassignIdleWorkers = function(gameState, idleWorker
}
}
else if (PETRA.isFastMoving(ent) && ent.canGather("food") && ent.canAttackClass("Animal"))
ent.setMetadata(PlayerID, "subrole", "hunter");
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_HUNTER);
else if (ent.hasClass("FishingBoat"))
ent.setMetadata(PlayerID, "subrole", "fisher");
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_FISHER);
}
};
@ -681,7 +680,7 @@ PETRA.BaseManager.prototype.workersBySubrole = function(gameState, subrole)
PETRA.BaseManager.prototype.gatherersByType = function(gameState, type)
{
return gameState.updatingCollection("workers-gathering-" + type +"-base-" + this.ID, API3.Filters.byMetadata(PlayerID, "gather-type", type), this.workersBySubrole(gameState, "gatherer"));
return gameState.updatingCollection("workers-gathering-" + type +"-base-" + this.ID, API3.Filters.byMetadata(PlayerID, "gather-type", type), this.workersBySubrole(gameState, PETRA.Worker.SUBROLE_GATHERER));
};
/**
@ -702,13 +701,13 @@ PETRA.BaseManager.prototype.pickBuilders = function(gameState, workers, number)
availableWorkers.sort((a, b) => {
let vala = 0;
let valb = 0;
if (a.getMetadata(PlayerID, "subrole") == "builder")
if (a.getMetadata(PlayerID, "subrole") === PETRA.Worker.SUBROLE_BUILDER)
vala = 100;
if (b.getMetadata(PlayerID, "subrole") == "builder")
if (b.getMetadata(PlayerID, "subrole") === PETRA.Worker.SUBROLE_BUILDER)
valb = 100;
if (a.getMetadata(PlayerID, "subrole") == "idle")
if (a.getMetadata(PlayerID, "subrole") === PETRA.Worker.SUBROLE_IDLE)
vala = -50;
if (b.getMetadata(PlayerID, "subrole") == "idle")
if (b.getMetadata(PlayerID, "subrole") === PETRA.Worker.SUBROLE_IDLE)
valb = -50;
if (a.getMetadata(PlayerID, "plan") === undefined)
vala = -20;
@ -720,7 +719,7 @@ PETRA.BaseManager.prototype.pickBuilders = function(gameState, workers, number)
for (let i = 0; i < needed; ++i)
{
availableWorkers[i].stopMoving();
availableWorkers[i].setMetadata(PlayerID, "subrole", "idle");
availableWorkers[i].setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_IDLE);
workers.addEnt(availableWorkers[i]);
}
return;
@ -742,7 +741,7 @@ PETRA.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
return;
let workers = this.workers.filter(ent => ent.isBuilder());
let builderWorkers = this.workersBySubrole(gameState, "builder");
const builderWorkers = this.workersBySubrole(gameState, PETRA.Worker.SUBROLE_BUILDER);
let idleBuilderWorkers = builderWorkers.filter(API3.Filters.isIdle());
// if we're constructing and we have the foundations to our base anchor, only try building that.
@ -768,7 +767,7 @@ PETRA.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
let baseID = this.ID;
fromOtherBase.forEach(worker => {
worker.setMetadata(PlayerID, "base", baseID);
worker.setMetadata(PlayerID, "subrole", "builder");
worker.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_BUILDER);
workers.updateEnt(worker);
builderWorkers.updateEnt(worker);
idleBuilderWorkers.updateEnt(worker);
@ -850,7 +849,7 @@ PETRA.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
if (assigned >= targetNB || builderTot >= maxTotalBuilders)
continue;
let nonBuilderWorkers = workers.filter(function(ent) {
if (ent.getMetadata(PlayerID, "subrole") == "builder")
if (ent.getMetadata(PlayerID, "subrole") === PETRA.Worker.SUBROLE_BUILDER)
return false;
if (!ent.position())
return false;
@ -878,7 +877,7 @@ PETRA.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
++builderTot;
let ent = nonBuilderWorkers[current++];
ent.stopMoving();
ent.setMetadata(PlayerID, "subrole", "builder");
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_BUILDER);
ent.setMetadata(PlayerID, "target-foundation", target.id());
}
}
@ -933,7 +932,7 @@ PETRA.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
if (assigned >= targetNB || builderTot >= maxTotalBuilders)
continue;
let nonBuilderWorkers = workers.filter(function(ent) {
if (ent.getMetadata(PlayerID, "subrole") == "builder")
if (ent.getMetadata(PlayerID, "subrole") === PETRA.Worker.SUBROLE_BUILDER)
return false;
if (!ent.position())
return false;
@ -950,7 +949,7 @@ PETRA.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
++assigned;
++builderTot;
ent.stopMoving();
ent.setMetadata(PlayerID, "subrole", "builder");
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_BUILDER);
ent.setMetadata(PlayerID, "target-foundation", target.id());
});
}

View File

@ -175,7 +175,7 @@ PETRA.BasesManager.prototype.checkEvents = function(gameState, events)
{
builders.forEach(worker => {
worker.setMetadata(PlayerID, "base", newbase.ID);
worker.setMetadata(PlayerID, "subrole", "builder");
worker.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_BUILDER);
worker.setMetadata(PlayerID, "target-foundation", ent.id());
});
}
@ -189,7 +189,7 @@ PETRA.BasesManager.prototype.checkEvents = function(gameState, events)
{
builders.forEach(worker => {
worker.setMetadata(PlayerID, "base", newbase.ID);
worker.setMetadata(PlayerID, "subrole", "builder");
worker.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_BUILDER);
worker.setMetadata(PlayerID, "target-foundation", ent.id());
});
}
@ -275,7 +275,7 @@ PETRA.BasesManager.prototype.checkEvents = function(gameState, events)
continue;
// Assign it immediately to something useful to do.
if (ent.getMetadata(PlayerID, "role") == "worker")
if (ent.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_WORKER)
{
let base;
if (ent.getMetadata(PlayerID, "base") === undefined)
@ -591,7 +591,7 @@ PETRA.BasesManager.prototype.assignEntity = function(gameState, ent, territoryIn
if (ent.position() && bestbase.ID !== this.noBase.ID)
{
bestbase.assignRolelessUnits(gameState, [ent]);
if (ent.getMetadata(PlayerID, "role") === "worker")
if (ent.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_WORKER)
{
bestbase.reassignIdleWorkers(gameState, [ent]);
bestbase.workerObject.update(gameState, ent);

View File

@ -1,7 +1,14 @@
PETRA.Config = function(difficulty, behavior)
// These integers must be sequential
PETRA.DIFFICULTY_SANDBOX = 0;
PETRA.DIFFICULTY_VERY_EASY = 1;
PETRA.DIFFICULTY_EASY = 2;
PETRA.DIFFICULTY_MEDIUM = 3;
PETRA.DIFFICULTY_HARD = 4;
PETRA.DIFFICULTY_VERY_HARD = 5;
PETRA.Config = function(difficulty = PETRA.DIFFICULTY_MEDIUM, 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;
this.difficulty = difficulty;
// for instance "balanced", "aggressive" or "defensive"
this.behavior = behavior || "random";
@ -169,7 +176,7 @@ PETRA.Config = function(difficulty, behavior)
PETRA.Config.prototype.setConfig = function(gameState)
{
if (this.difficulty > 0)
if (this.difficulty > PETRA.DIFFICULTY_SANDBOX)
{
// Setup personality traits according to the user choice:
// The parameter used to define the personality is basically the aggressivity or (1-defensiveness)
@ -212,14 +219,14 @@ PETRA.Config.prototype.setConfig = function(gameState)
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)
if (this.difficulty < PETRA.DIFFICULTY_EASY)
{
this.popScaling = 0.5;
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)
else if (this.difficulty < PETRA.DIFFICULTY_MEDIUM)
{
this.popScaling = 0.7;
this.Economy.supportRatio = 0.4;
@ -228,7 +235,7 @@ PETRA.Config.prototype.setConfig = function(gameState)
}
else
{
if (this.difficulty == 3)
if (this.difficulty == PETRA.DIFFICULTY_MEDIUM)
this.Military.numSentryTowers = 1;
else
this.Military.numSentryTowers = 2;
@ -246,9 +253,9 @@ PETRA.Config.prototype.setConfig = function(gameState)
}
let maxPop = gameState.getPopulationMax();
if (this.difficulty < 2)
if (this.difficulty < PETRA.DIFFICULTY_EASY)
this.Economy.targetNumWorkers = Math.max(1, Math.min(40, maxPop));
else if (this.difficulty < 3)
else if (this.difficulty < PETRA.DIFFICULTY_MEDIUM)
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)));
@ -274,7 +281,7 @@ PETRA.Config.prototype.setConfig = function(gameState)
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)
if (this.difficulty < PETRA.DIFFICULTY_EASY)
this.Economy.workPhase3 = Infinity; // prevent the phasing to city phase
if (this.debug < 2)

View File

@ -119,9 +119,9 @@ PETRA.DefenseArmy.prototype.addOwn = function(gameState, id, force)
else
ent.setMetadata(PlayerID, "plan", -3);
let subrole = ent.getMetadata(PlayerID, "subrole");
if (subrole === undefined || subrole !== "defender")
if (subrole === undefined || subrole !== PETRA.Worker.SUBROLE_DEFENDER)
ent.setMetadata(PlayerID, "formerSubrole", subrole);
ent.setMetadata(PlayerID, "subrole", "defender");
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_DEFENDER);
return true;
};
@ -159,11 +159,11 @@ PETRA.DefenseArmy.prototype.removeOwn = function(gameState, id, Entity)
ent.setMetadata(PlayerID, "subrole", undefined);
ent.setMetadata(PlayerID, "formerSubrole", undefined);
// Remove from tranport plan if not yet on Board
// Remove from transport plan if not yet on Board
if (ent.getMetadata(PlayerID, "transport") !== undefined)
{
let plan = gameState.ai.HQ.navalManager.getPlan(ent.getMetadata(PlayerID, "transport"));
if (plan && plan.state == "boarding" && ent.position())
if (plan && plan.state === PETRA.TransportPlan.BOARDING && ent.position())
plan.removeUnit(gameState, ent);
}

View File

@ -429,7 +429,8 @@ PETRA.DefenseManager.prototype.assignDefenders = function(gameState)
if (ent.getMetadata(PlayerID, "plan") !== undefined && ent.getMetadata(PlayerID, "plan") != -1)
{
let subrole = ent.getMetadata(PlayerID, "subrole");
if (subrole && (subrole == "completing" || subrole == "walking" || subrole == "attacking"))
if (subrole &&
(subrole === PETRA.Worker.SUBROLE_COMPLETING || subrole === PETRA.Worker.SUBROLE_WALKING || subrole === PETRA.Worker.SUBROLE_ATTACKING))
return;
}
potentialDefenders.push(ent.id());
@ -778,7 +779,8 @@ PETRA.DefenseManager.prototype.garrisonUnitsInside = function(gameState, target,
{
let subrole = ent.getMetadata(PlayerID, "subrole");
// When structure decaying (usually because we've just captured it in enemy territory), also allow units from an attack plan.
if (typeGarrison !== PETRA.GarrisonManager.TYPE_DECAY && subrole && (subrole == "completing" || subrole == "walking" || subrole == "attacking"))
if (typeGarrison !== PETRA.GarrisonManager.TYPE_DECAY && subrole &&
(subrole === PETRA.Worker.SUBROLE_COMPLETING || subrole === PETRA.Worker.SUBROLE_WALKING || subrole === PETRA.Worker.SUBROLE_ATTACKING))
return false;
}
if (PETRA.getLandAccess(gameState, ent) != access)

View File

@ -250,7 +250,7 @@ PETRA.GarrisonManager.prototype.garrison = function(gameState, ent, holder, type
ent.setMetadata(PlayerID, "plan", -2);
else
ent.setMetadata(PlayerID, "plan", -3);
ent.setMetadata(PlayerID, "subrole", "garrisoning");
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_GARRISONING);
ent.setMetadata(PlayerID, "garrisonHolder", holder.id());
ent.setMetadata(PlayerID, "garrisonType", type);
ent.garrison(holder);

View File

@ -151,13 +151,13 @@ PETRA.HQ.prototype.checkEvents = function(gameState, events)
ent.setMetadata(PlayerID, "PartOfArmy", undefined);
if (ent.hasClass("Trader"))
{
ent.setMetadata(PlayerID, "role", "trader");
ent.setMetadata(PlayerID, "role", PETRA.Worker.ROLE_TRADER);
ent.setMetadata(PlayerID, "route", undefined);
}
if (ent.hasClass("Worker"))
{
ent.setMetadata(PlayerID, "role", "worker");
ent.setMetadata(PlayerID, "subrole", "idle");
ent.setMetadata(PlayerID, "role", PETRA.Worker.ROLE_WORKER);
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_IDLE);
}
if (ent.hasClass("Ship"))
PETRA.setSeaAccess(gameState, ent);
@ -233,7 +233,7 @@ PETRA.HQ.prototype.checkEvents = function(gameState, events)
}
// Then deals with decaying structures: destroy them if being lost to enemy (except in easier difficulties)
if (this.Config.difficulty < 2)
if (this.Config.difficulty < PETRA.DIFFICULTY_EASY)
return;
for (let entId of this.decayingStructures)
{
@ -378,7 +378,7 @@ PETRA.HQ.prototype.trainMoreWorkers = function(gameState, queues)
let numberOfWorkers = 0; // all workers
let numberOfSupports = 0; // only support workers (i.e. non fighting)
gameState.getOwnUnits().forEach(ent => {
if (ent.getMetadata(PlayerID, "role") == "worker" && ent.getMetadata(PlayerID, "plan") === undefined)
if (ent.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_WORKER && ent.getMetadata(PlayerID, "plan") === undefined)
{
++numberOfWorkers;
if (ent.hasClass("Support"))
@ -390,7 +390,7 @@ PETRA.HQ.prototype.trainMoreWorkers = function(gameState, queues)
for (let item of ent.trainingQueue())
{
numberInTraining += item.count;
if (item.metadata && item.metadata.role && item.metadata.role == "worker" &&
if (item.metadata && item.metadata.role && item.metadata.role === PETRA.Worker.ROLE_WORKER &&
item.metadata.plan === undefined)
{
numberOfWorkers += item.count;
@ -467,9 +467,9 @@ PETRA.HQ.prototype.trainMoreWorkers = function(gameState, queues)
// If the template variable is empty, the default unit (Support unit) will be used
// base "0" means automatic choice of base
if (!template && templateDef)
queues.villager.addPlan(new PETRA.TrainingPlan(gameState, templateDef, { "role": "worker", "base": 0, "support": true }, size, size));
queues.villager.addPlan(new PETRA.TrainingPlan(gameState, templateDef, { "role": PETRA.Worker.ROLE_WORKER, "base": 0, "support": true }, size, size));
else if (template)
queues.citizenSoldier.addPlan(new PETRA.TrainingPlan(gameState, template, { "role": "worker", "base": 0 }, size, size));
queues.citizenSoldier.addPlan(new PETRA.TrainingPlan(gameState, template, { "role": PETRA.Worker.ROLE_WORKER, "base": 0 }, size, size));
};
/** picks the best template based on parameters and classes */
@ -1867,7 +1867,7 @@ PETRA.HQ.prototype.trainEmergencyUnits = function(gameState, positions)
break;
}
}
let metadata = { "role": "worker", "base": nearestAnchor.getMetadata(PlayerID, "base"), "plan": -1, "trainer": nearestAnchor.id() };
const metadata = { "role": PETRA.Worker.ROLE_WORKER, "base": nearestAnchor.getMetadata(PlayerID, "base"), "plan": -1, "trainer": nearestAnchor.id() };
if (autogarrison)
metadata.garrisonType = PETRA.GarrisonManager.TYPE_PROTECTION;
gameState.ai.queues.emergency.addPlan(new PETRA.TrainingPlan(gameState, templateFound[0], metadata, 1, 1));
@ -2154,12 +2154,12 @@ PETRA.HQ.prototype.getAccountedWorkers = function(gameState)
{
if (this.turnCache.accountedWorkers == undefined)
{
let workers = gameState.getOwnEntitiesByRole("worker", true).length;
let workers = gameState.getOwnEntitiesByRole(PETRA.Worker.ROLE_WORKER, true).length;
for (let ent of gameState.getOwnTrainingFacilities().values())
{
for (let item of ent.trainingQueue())
{
if (!item.metadata || !item.metadata.role || item.metadata.role != "worker")
if (!item.metadata || !item.metadata.role || item.metadata.role !== PETRA.Worker.ROLE_WORKER)
continue;
workers += item.count;
}
@ -2273,7 +2273,7 @@ PETRA.HQ.prototype.update = function(gameState, queues, events)
if (gameState.ai.playedTurn % 3 == 0)
{
this.constructTrainingBuildings(gameState, queues);
if (this.Config.difficulty > 0)
if (this.Config.difficulty > PETRA.DIFFICULTY_SANDBOX)
this.buildDefenses(gameState, queues);
}
@ -2281,7 +2281,7 @@ PETRA.HQ.prototype.update = function(gameState, queues, events)
this.navalManager.update(gameState, queues, events);
if (this.Config.difficulty > 0 && (this.hasActiveBase() || !this.canBuildUnits))
if (this.Config.difficulty > PETRA.DIFFICULTY_SANDBOX && (this.hasActiveBase() || !this.canBuildUnits))
this.attackManager.update(gameState, queues, events);
this.diplomacyManager.update(gameState, events);

View File

@ -38,7 +38,7 @@ PETRA.NavalManager.prototype.init = function(gameState, deserializing)
this.docks = gameState.getOwnStructures().filter(API3.Filters.byClasses(["Dock", "Shipyard"]));
this.docks.registerUpdates();
this.ships = gameState.getOwnUnits().filter(API3.Filters.and(API3.Filters.byClass("Ship"), API3.Filters.not(API3.Filters.byMetadata(PlayerID, "role", "trader"))));
this.ships = gameState.getOwnUnits().filter(API3.Filters.and(API3.Filters.byClass("Ship"), API3.Filters.not(API3.Filters.byMetadata(PlayerID, "role", PETRA.Worker.ROLE_TRADER))));
// note: those two can overlap (some transport ships are warships too and vice-versa).
this.transportShips = this.ships.filter(API3.Filters.and(API3.Filters.byCanGarrison(), API3.Filters.not(API3.Filters.byClass("FishingBoat"))));
this.warShips = this.ships.filter(API3.Filters.byClass("Warship"));
@ -285,7 +285,7 @@ PETRA.NavalManager.prototype.checkEvents = function(gameState, queues, events)
let shipId = evt.entityObj.id();
if (this.Config.debug > 1)
API3.warn("one ship " + shipId + " from plan " + plan.ID + " destroyed during " + plan.state);
if (plan.state == "boarding")
if (plan.state === PETRA.TransportPlan.BOARDING)
{
// just reset the units onBoard metadata and wait for a new ship to be assigned to this plan
plan.units.forEach(ent => {
@ -295,7 +295,7 @@ PETRA.NavalManager.prototype.checkEvents = function(gameState, queues, events)
});
plan.needTransportShips = !plan.transportShips.hasEntities();
}
else if (plan.state == "sailing")
else if (plan.state === PETRA.TransportPlan.SAILING)
{
let endIndex = plan.endIndex;
for (let ent of plan.units.values())
@ -361,7 +361,7 @@ PETRA.NavalManager.prototype.requireTransport = function(gameState, ent, startIn
let plans = [];
for (let plan of this.transportPlans)
{
if (plan.startIndex != startIndex || plan.endIndex != endIndex || plan.state != "boarding")
if (plan.startIndex != startIndex || plan.endIndex != endIndex || plan.state !== PETRA.TransportPlan.BOARDING)
continue;
// Limit the number of siege units per transport to avoid problems when ungarrisoning
if (PETRA.isSiegeUnit(ent) && plan.units.filter(unit => PETRA.isSiegeUnit(unit)).length > 3)
@ -514,7 +514,7 @@ PETRA.NavalManager.prototype.maintainFleet = function(gameState, queues)
let template = this.getBestShip(gameState, sea, "fishing");
if (template)
{
queues.ships.addPlan(new PETRA.TrainingPlan(gameState, template, { "base": 0, "role": "worker", "sea": sea }, 1, 1));
queues.ships.addPlan(new PETRA.TrainingPlan(gameState, template, { "base": 0, "role": PETRA.Worker.ROLE_WORKER, "sea": sea }, 1, 1));
continue;
}
}
@ -613,7 +613,7 @@ PETRA.NavalManager.prototype.moveApart = function(gameState)
if (!shipPosition)
continue;
let role = ship.getMetadata(PlayerID, "role");
if (!role || role != "trader") // already accounted before
if (role === undefined || role !== PETRA.Worker.ROLE_TRADER) // already accounted before
continue;
let unitAIState = ship.unitAIState();
@ -691,7 +691,7 @@ PETRA.NavalManager.prototype.moveApart = function(gameState)
if (blockedIds.indexOf(blockingShip.id()) != -1 || !blockingShip.position())
continue;
let role = blockingShip.getMetadata(PlayerID, "role");
if (!role || role != "trader") // already accounted before
if (role === undefined || role !== PETRA.Worker.ROLE_TRADER) // already accounted before
continue;
let distSquare = API3.SquareVectorDistance(shipPosition, blockingShip.position());
let unitAIState = blockingShip.unitAIState();

View File

@ -158,7 +158,7 @@ PETRA.QueueManager.prototype.printQueues = function(gameState)
{
let numWorkers = 0;
gameState.getOwnUnits().forEach(ent => {
if (ent.getMetadata(PlayerID, "role") == "worker" && ent.getMetadata(PlayerID, "plan") === undefined)
if (ent.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_WORKER && ent.getMetadata(PlayerID, "plan") === undefined)
numWorkers++;
});
API3.warn("---------- QUEUES ------------ with pop " + gameState.getPopulation() + " and workers " + numWorkers);
@ -414,7 +414,7 @@ PETRA.QueueManager.prototype.update = function(gameState)
// Recovery system: if short of workers after an attack, pause (and reset) some queues to favor worker training
PETRA.QueueManager.prototype.checkPausedQueues = function(gameState)
{
let numWorkers = gameState.countOwnEntitiesAndQueuedWithRole("worker");
const numWorkers = gameState.countOwnEntitiesAndQueuedWithRole(PETRA.Worker.ROLE_WORKER);
let workersMin = Math.min(Math.max(12, 24 * this.Config.popScaling), this.Config.Economy.popPhase2);
for (let q in this.queues)
{

View File

@ -79,7 +79,7 @@ PETRA.TrainingPlan.prototype.start = function(gameState)
let wantedIndex;
if (this.metadata && this.metadata.index)
wantedIndex = this.metadata.index;
let workerUnit = this.metadata && this.metadata.role && this.metadata.role == "worker";
const workerUnit = this.metadata && this.metadata.role && this.metadata.role === PETRA.Worker.ROLE_WORKER;
let supportUnit = this.template.hasClass("Support");
this.trainers.sort(function(a, b) {
// Prefer training buildings with short queues

View File

@ -79,7 +79,7 @@ PETRA.ResearchManager.prototype.researchWantedTechs = function(gameState, techs)
{
let phase1 = gameState.currentPhase() === 1;
let available = phase1 ? gameState.ai.queueManager.getAvailableResources(gameState) : null;
let numWorkers = phase1 ? gameState.getOwnEntitiesByRole("worker", true).length : 0;
const numWorkers = phase1 ? gameState.getOwnEntitiesByRole(PETRA.Worker.ROLE_WORKER, true).length : 0;
for (let tech of techs)
{
if (tech[0].indexOf("unlock_champion") == 0)
@ -123,7 +123,7 @@ PETRA.ResearchManager.prototype.researchPreferredTechs = function(gameState, tec
{
let phase2 = gameState.currentPhase() === 2;
let available = phase2 ? gameState.ai.queueManager.getAvailableResources(gameState) : null;
let numWorkers = phase2 ? gameState.getOwnEntitiesByRole("worker", true).length : 0;
const numWorkers = phase2 ? gameState.getOwnEntitiesByRole(PETRA.Worker.ROLE_WORKER, true).length : 0;
for (let tech of techs)
{
if (!tech[1]._template.modifications)

View File

@ -27,7 +27,7 @@ PETRA.HQ.prototype.gameAnalysis = function(gameState)
// Sandbox difficulty should not try to expand
this.canExpand = this.Config.difficulty != 0;
this.canExpand = this.Config.difficulty != PETRA.DIFFICULTY_SANDBOX;
// If no base yet, check if we can construct one. If not, dispatch our units to possible tasks/attacks
this.canBuildUnits = true;
if (!gameState.getOwnStructures().filter(API3.Filters.byClass("CivCentre")).hasEntities())

View File

@ -13,7 +13,7 @@ PETRA.TradeManager = function(Config)
PETRA.TradeManager.prototype.init = function(gameState)
{
this.traders = gameState.getOwnUnits().filter(API3.Filters.byMetadata(PlayerID, "role", "trader"));
this.traders = gameState.getOwnUnits().filter(API3.Filters.byMetadata(PlayerID, "role", PETRA.Worker.ROLE_TRADER));
this.traders.registerUpdates();
this.minimalGain = gameState.ai.HQ.navalMap ? 3 : 5;
};
@ -25,7 +25,7 @@ PETRA.TradeManager.prototype.hasTradeRoute = function()
PETRA.TradeManager.prototype.assignTrader = function(ent)
{
ent.setMetadata(PlayerID, "role", "trader");
ent.setMetadata(PlayerID, "role", PETRA.Worker.ROLE_TRADER);
this.traders.updateEnt(ent);
};
@ -41,7 +41,7 @@ PETRA.TradeManager.prototype.trainMoreTraders = function(gameState, queues)
gameState.getOwnTrainingFacilities().forEach(function(ent) {
for (let item of ent.trainingQueue())
{
if (!item.metadata || !item.metadata.role || item.metadata.role != "trader")
if (!item.metadata || !item.metadata.role || item.metadata.role !== PETRA.Worker.ROLE_TRADER)
continue;
numTraders += item.count;
if (item.metadata.sea !== undefined)
@ -56,7 +56,7 @@ PETRA.TradeManager.prototype.trainMoreTraders = function(gameState, queues)
return;
let template;
let metadata = { "role": "trader" };
const metadata = { "role": PETRA.Worker.ROLE_TRADER };
if (this.tradeRoute.sea)
{
// if we have some merchand ships assigned to transport, try first to reassign them
@ -67,7 +67,7 @@ PETRA.TradeManager.prototype.trainMoreTraders = function(gameState, queues)
gameState.ai.HQ.navalManager.seaTransportShips[this.tradeRoute.sea].forEach(function(ship) {
if (already || !ship.hasClass("Trader"))
return;
if (ship.getMetadata(PlayerID, "role") == "switchToTrader")
if (ship.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_SWITCH_TO_TRADER)
{
already = true;
return;
@ -79,9 +79,9 @@ PETRA.TradeManager.prototype.trainMoreTraders = function(gameState, queues)
if (shipToSwitch)
{
if (shipToSwitch.getMetadata(PlayerID, "transporter") === undefined)
shipToSwitch.setMetadata(PlayerID, "role", "trader");
shipToSwitch.setMetadata(PlayerID, "role", PETRA.Worker.ROLE_TRADER);
else
shipToSwitch.setMetadata(PlayerID, "role", "switchToTrader");
shipToSwitch.setMetadata(PlayerID, "role", PETRA.Worker.ROLE_SWITCH_TO_TRADER);
return;
}
@ -645,7 +645,7 @@ PETRA.TradeManager.prototype.update = function(gameState, events, queues)
if (gameState.ai.HQ.canBarter && Resources.GetBarterableCodes().length)
this.performBarter(gameState);
if (this.Config.difficulty <= 1)
if (this.Config.difficulty <= PETRA.DIFFICULTY_VERY_EASY)
return;
if (this.checkEvents(gameState, events)) // true if one market was built or destroyed

View File

@ -67,13 +67,22 @@ PETRA.TransportPlan = function(gameState, units, startIndex, endIndex, endPos, s
API3.warn("Starting a new transport plan with ID " + this.ID +
" to index " + endIndex + " with units length " + units.length);
this.state = "boarding";
this.state = PETRA.TransportPlan.BOARDING;
this.boardingPos = {};
this.needTransportShips = ship === undefined;
this.nTry = {};
return true;
};
/**
* We're trying to board units onto our ships.
*/
PETRA.TransportPlan.BOARDING = "boarding";
/**
* We're moving ships and eventually unload units.
*/
PETRA.TransportPlan.SAILING = "sailing";
PETRA.TransportPlan.prototype.init = function(gameState)
{
this.units = gameState.getOwnUnits().filter(API3.Filters.byMetadata(PlayerID, "transport", this.ID));
@ -117,7 +126,7 @@ PETRA.TransportPlan.prototype.assignUnitToShip = function(gameState, ent)
ent.setMetadata(PlayerID, "onBoard", ship.id());
if (this.debug > 1)
{
if (ent.getMetadata(PlayerID, "role") == "attack")
if (ent.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_ATTACK)
Engine.PostCommand(PlayerID, { "type": "set-shading-color", "entities": [ent.id()], "rgb": [2, 0, 0] });
else
Engine.PostCommand(PlayerID, { "type": "set-shading-color", "entities": [ent.id()], "rgb": [0, 2, 0] });
@ -223,8 +232,8 @@ PETRA.TransportPlan.prototype.releaseShip = function(ship)
ship.setStance(defaultStance);
ship.setMetadata(PlayerID, "transporter", undefined);
if (ship.getMetadata(PlayerID, "role") == "switchToTrader")
ship.setMetadata(PlayerID, "role", "trader");
if (ship.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_SWITCH_TO_TRADER)
ship.setMetadata(PlayerID, "role", PETRA.Worker.ROLE_TRADER);
};
PETRA.TransportPlan.prototype.releaseAll = function()
@ -273,17 +282,13 @@ PETRA.TransportPlan.prototype.cancelTransport = function(gameState)
/**
* try to move on. There are two states:
* - "boarding" means we're trying to board units onto our ships
* - "sailing" means we're moving ships and eventually unload units
* - then the plan is cleared
* Try to move on and then clear the plan.
*/
PETRA.TransportPlan.prototype.update = function(gameState)
{
if (this.state == "boarding")
if (this.state === PETRA.TransportPlan.BOARDING)
this.onBoarding(gameState);
else if (this.state == "sailing")
else if (this.state === PETRA.TransportPlan.SAILING)
this.onSailing(gameState);
return this.units.length;
@ -422,7 +427,7 @@ PETRA.TransportPlan.prototype.onBoarding = function(gameState)
this.boardingPos[ship.id()] = this.getBoardingPos(gameState, ship, this.endIndex, this.sea, this.endPos, true);
ship.move(this.boardingPos[ship.id()][0], this.boardingPos[ship.id()][1]);
}
this.state = "sailing";
this.state = PETRA.TransportPlan.SAILING;
this.nTry = {};
this.unloaded = [];
this.recovered = [];

View File

@ -78,7 +78,7 @@ PETRA.VictoryManager.prototype.checkEvents = function(gameState, events)
for (let worker of builders.values())
{
worker.setMetadata(PlayerID, "base", base.ID);
worker.setMetadata(PlayerID, "subrole", "builder");
worker.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_BUILDER);
worker.setMetadata(PlayerID, "target-foundation", ent.id());
}
}
@ -141,7 +141,7 @@ PETRA.VictoryManager.prototype.checkEvents = function(gameState, events)
for (let entId of evt.entities)
{
let ent = gameState.getEntityById(entId);
if (ent && ent.isOwn(PlayerID) && ent.getMetadata(PlayerID, "role") == "criticalEntHealer")
if (ent && ent.isOwn(PlayerID) && ent.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_CRITICAL_ENT_HEALER)
this.assignGuardToCriticalEnt(gameState, ent);
}
@ -253,8 +253,8 @@ PETRA.VictoryManager.prototype.checkEvents = function(gameState, events)
continue;
// If this ent travelled to a criticalEnt's accessValue, try again to assign as a guard
if ((ent.getMetadata(PlayerID, "role") == "criticalEntHealer" ||
ent.getMetadata(PlayerID, "role") == "criticalEntGuard") && !this.guardEnts.get(evt.entity))
if ((ent.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_CRITICAL_ENT_HEALER ||
ent.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_CRITICAL_ENT_GUARD) && !this.guardEnts.get(evt.entity))
{
this.assignGuardToCriticalEnt(gameState, ent, ent.getMetadata(PlayerID, "guardedEnt"));
continue;
@ -342,7 +342,7 @@ PETRA.VictoryManager.prototype.manageCriticalEntHealers = function(gameState, qu
if (data.healersAssigned === undefined || data.healersAssigned >= this.healersPerCriticalEnt)
continue;
let template = gameState.applyCiv("units/{civ}/support_healer_b");
queues.healer.addPlan(new PETRA.TrainingPlan(gameState, template, { "role": "criticalEntHealer", "base": 0 }, 1, 1));
queues.healer.addPlan(new PETRA.TrainingPlan(gameState, template, { "role": PETRA.Worker.ROLE_CRITICAL_ENT_HEALER, "base": 0 }, 1, 1));
return;
}
};
@ -354,7 +354,7 @@ PETRA.VictoryManager.prototype.manageCriticalEntHealers = function(gameState, qu
*/
PETRA.VictoryManager.prototype.manageCriticalEntGuards = function(gameState)
{
let numWorkers = gameState.getOwnEntitiesByRole("worker", true).length;
let numWorkers = gameState.getOwnEntitiesByRole(PETRA.Worker.ROLE_WORKER, true).length;
if (numWorkers < 20)
{
for (let data of this.criticalEnts.values())
@ -363,7 +363,7 @@ PETRA.VictoryManager.prototype.manageCriticalEntGuards = function(gameState)
{
let guardEnt = gameState.getEntityById(guardId);
if (!guardEnt || !guardEnt.hasClass("CitizenSoldier") ||
guardEnt.getMetadata(PlayerID, "role") != "criticalEntGuard")
guardEnt.getMetadata(PlayerID, "role") !== PETRA.Worker.ROLE_CRITICAL_ENT_GUARD)
continue;
guardEnt.removeGuard();
@ -451,7 +451,7 @@ PETRA.VictoryManager.prototype.tryAssignMilitaryGuard = function(gameState, guar
return false;
guardEnt.setMetadata(PlayerID, "plan", -2);
guardEnt.setMetadata(PlayerID, "role", "criticalEntGuard");
guardEnt.setMetadata(PlayerID, "role", PETRA.Worker.ROLE_CRITICAL_ENT_GUARD);
return true;
};
@ -547,7 +547,7 @@ PETRA.VictoryManager.prototype.assignGuardToCriticalEnt = function(gameState, gu
{
let queued = PETRA.returnResources(gameState, guardEnt);
guardEnt.guard(criticalEnt, queued);
let guardRole = guardEnt.getMetadata(PlayerID, "role") == "criticalEntHealer" ? "healer" : "guard";
const guardRole = guardEnt.getMetadata(PlayerID, "role") === PETRA.Worker.ROLE_CRITICAL_ENT_HEALER ? "healer" : "guard";
this.criticalEnts.get(criticalEntId).guards.set(guardEnt.id(), guardRole);
// Switch this guard ent to the criticalEnt's base

View File

@ -8,6 +8,24 @@ PETRA.Worker = function(base)
this.baseID = base.ID;
};
PETRA.Worker.ROLE_ATTACK = "attack";
PETRA.Worker.ROLE_TRADER = "trader";
PETRA.Worker.ROLE_SWITCH_TO_TRADER = "switchToTrader";
PETRA.Worker.ROLE_WORKER = "worker";
PETRA.Worker.ROLE_CRITICAL_ENT_GUARD = "criticalEntGuard";
PETRA.Worker.ROLE_CRITICAL_ENT_HEALER = "criticalEntHealer";
PETRA.Worker.SUBROLE_DEFENDER = "defender";
PETRA.Worker.SUBROLE_IDLE = "idle";
PETRA.Worker.SUBROLE_BUILDER = "builder";
PETRA.Worker.SUBROLE_COMPLETING = "completing";
PETRA.Worker.SUBROLE_WALKING = "walking";
PETRA.Worker.SUBROLE_ATTACKING = "attacking";
PETRA.Worker.SUBROLE_GATHERER = "gatherer";
PETRA.Worker.SUBROLE_HUNTER = "hunter";
PETRA.Worker.SUBROLE_FISHER = "fisher";
PETRA.Worker.SUBROLE_GARRISONING = "garrisoning";
PETRA.Worker.prototype.update = function(gameState, ent)
{
if (!ent.position() || ent.getMetadata(PlayerID, "plan") == -2 || ent.getMetadata(PlayerID, "plan") == -3)
@ -19,18 +37,18 @@ PETRA.Worker.prototype.update = function(gameState, ent)
if (ent.getMetadata(PlayerID, "transport") !== undefined)
{
// Except if builder with their foundation destroyed, in which case cancel the transport if not yet on board
if (subrole == "builder" && ent.getMetadata(PlayerID, "target-foundation") !== undefined)
if (subrole === PETRA.Worker.SUBROLE_BUILDER && ent.getMetadata(PlayerID, "target-foundation") !== undefined)
{
let plan = gameState.ai.HQ.navalManager.getPlan(ent.getMetadata(PlayerID, "transport"));
let target = gameState.getEntityById(ent.getMetadata(PlayerID, "target-foundation"));
if (!target && plan && plan.state == "boarding" && ent.position())
if (!target && plan && plan.state === PETRA.TransportPlan.BOARDING && ent.position())
plan.removeUnit(gameState, ent);
}
// and gatherer if there are no more dropsite accessible in the base the ent is going to
if (subrole == "gatherer" || subrole == "hunter")
if (subrole === PETRA.Worker.SUBROLE_GATHERER || subrole === PETRA.Worker.SUBROLE_HUNTER)
{
let plan = gameState.ai.HQ.navalManager.getPlan(ent.getMetadata(PlayerID, "transport"));
if (plan.state == "boarding" && ent.position())
if (plan.state === PETRA.TransportPlan.BOARDING && ent.position())
{
let hasDropsite = false;
let gatherType = ent.getMetadata(PlayerID, "gather-type") || "food";
@ -72,9 +90,9 @@ PETRA.Worker.prototype.update = function(gameState, ent)
else
this.baseAccess = this.base.accessIndex;
if (!subrole) // subrole may-be undefined after a transport, garrisoning, army, ...
if (subrole == undefined) // subrole may-be undefined after a transport, garrisoning, army, ...
{
ent.setMetadata(PlayerID, "subrole", "idle");
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_IDLE);
this.base.reassignIdleWorkers(gameState, [ent]);
this.update(gameState, ent);
return;
@ -83,7 +101,7 @@ PETRA.Worker.prototype.update = function(gameState, ent)
this.ent = ent;
let unitAIState = ent.unitAIState();
if ((subrole == "hunter" || subrole == "gatherer") &&
if ((subrole === PETRA.Worker.SUBROLE_HUNTER || subrole === PETRA.Worker.SUBROLE_GATHERER) &&
(unitAIState == "INDIVIDUAL.GATHER.GATHERING" || unitAIState == "INDIVIDUAL.GATHER.APPROACHING" ||
unitAIState == "INDIVIDUAL.COMBAT.APPROACHING"))
{
@ -156,7 +174,7 @@ PETRA.Worker.prototype.update = function(gameState, ent)
// Also, if we are attacking, do not capture
if (unitAIStateOrder == "COMBAT")
{
if (subrole == "fisher")
if (subrole === PETRA.Worker.SUBROLE_FISHER)
this.startFishing(gameState);
else if (unitAIState == "INDIVIDUAL.COMBAT.APPROACHING" && ent.unitAIOrderData().length &&
!ent.getMetadata(PlayerID, "PartOfArmy"))
@ -193,7 +211,7 @@ PETRA.Worker.prototype.update = function(gameState, ent)
// If we're gathering, we'll check that we haven't run idle.
// And we'll also check that we're gathering a resource we want to gather.
if (subrole == "gatherer")
if (subrole === PETRA.Worker.SUBROLE_GATHERER)
{
if (ent.isIdle())
{
@ -290,7 +308,7 @@ PETRA.Worker.prototype.update = function(gameState, ent)
}
}
}
else if (subrole == "builder")
else if (subrole === PETRA.Worker.SUBROLE_BUILDER)
{
if (unitAIStateOrder == "REPAIR")
{
@ -307,7 +325,7 @@ PETRA.Worker.prototype.update = function(gameState, ent)
return;
}
ent.setMetadata(PlayerID, "target-foundation", undefined);
ent.setMetadata(PlayerID, "subrole", "idle");
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_IDLE);
ent.stopMoving();
if (this.baseID != gameState.ai.HQ.basesManager.baselessBase().ID)
{
@ -328,7 +346,7 @@ PETRA.Worker.prototype.update = function(gameState, ent)
let target = gameState.getEntityById(ent.getMetadata(PlayerID, "target-foundation"));
if (!target || target.foundationProgress() === undefined && target.needsRepair() === false)
{
ent.setMetadata(PlayerID, "subrole", "idle");
ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_IDLE);
ent.setMetadata(PlayerID, "target-foundation", undefined);
if (this.baseID != gameState.ai.HQ.basesManager.baselessBase().ID)
{
@ -348,7 +366,7 @@ PETRA.Worker.prototype.update = function(gameState, ent)
gameState.ai.HQ.navalManager.requireTransport(gameState, ent, this.entAccess, goalAccess, target.position());
}
}
else if (subrole == "hunter")
else if (subrole === PETRA.Worker.SUBROLE_HUNTER)
{
let lastHuntSearch = ent.getMetadata(PlayerID, "lastHuntSearch");
if (ent.isIdle() && (!lastHuntSearch || gameState.ai.elapsedTime - lastHuntSearch > 20))
@ -395,7 +413,7 @@ PETRA.Worker.prototype.update = function(gameState, ent)
}
}
}
else if (subrole == "fisher")
else if (subrole === PETRA.Worker.SUBROLE_FISHER)
{
if (ent.isIdle())
this.startFishing(gameState);
@ -412,13 +430,13 @@ PETRA.Worker.prototype.retryWorking = function(gameState, subrole)
{
switch (subrole)
{
case "gatherer":
case PETRA.Worker.SUBROLE_GATHERER:
return this.startGathering(gameState);
case "hunter":
case PETRA.Worker.SUBROLE_HUNTER:
return this.startHunting(gameState);
case "fisher":
case PETRA.Worker.SUBROLE_FISHER:
return this.startFishing(gameState);
case "builder":
case PETRA.Worker.SUBROLE_BUILDER:
return this.startBuilding(gameState);
default:
return false;
@ -587,7 +605,7 @@ PETRA.Worker.prototype.startGathering = function(gameState)
if (foundation.getMetadata(PlayerID, "base") != this.baseID)
this.ent.setMetadata(PlayerID, "base", foundation.getMetadata(PlayerID, "base"));
this.ent.setMetadata(PlayerID, "target-foundation", foundation.id());
this.ent.setMetadata(PlayerID, "subrole", "builder");
this.ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_BUILDER);
this.ent.repair(foundation);
return true;
}
@ -657,7 +675,7 @@ PETRA.Worker.prototype.startGathering = function(gameState)
if (foundation.getMetadata(PlayerID, "base") != this.baseID)
this.ent.setMetadata(PlayerID, "base", foundation.getMetadata(PlayerID, "base"));
this.ent.setMetadata(PlayerID, "target-foundation", foundation.id());
this.ent.setMetadata(PlayerID, "subrole", "builder");
this.ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_BUILDER);
return true;
}
}
@ -720,7 +738,7 @@ PETRA.Worker.prototype.startGathering = function(gameState)
gameState.ai.HQ.lastFailedGather[resource] = gameState.ai.elapsedTime;
if (gameState.ai.Config.debug > 2)
API3.warn(" >>>>> worker with gather-type " + resource + " with nothing to gather ");
this.ent.setMetadata(PlayerID, "subrole", "idle");
this.ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_IDLE);
return false;
};
@ -925,8 +943,8 @@ PETRA.Worker.prototype.startFishing = function(gameState)
this.ent.setMetadata(PlayerID, "target-foundation", undefined);
return true;
}
if (this.ent.getMetadata(PlayerID, "subrole") == "fisher")
this.ent.setMetadata(PlayerID, "subrole", "idle");
if (this.ent.getMetadata(PlayerID, "subrole") === PETRA.Worker.SUBROLE_FISHER)
this.ent.setMetadata(PlayerID, "subrole", PETRA.Worker.SUBROLE_IDLE);
return false;
};
@ -1006,7 +1024,7 @@ PETRA.Worker.prototype.moveToGatherer = function(gameState, ent, forced)
return;
if (!forced && gameState.ai.elapsedTime < (ent.getMetadata(PlayerID, "nextMoveToGatherer") || 5))
return;
let gatherers = this.base.workersBySubrole(gameState, "gatherer");
const gatherers = this.base.workersBySubrole(gameState, PETRA.Worker.SUBROLE_GATHERER);
let dist = Math.min();
let destination;
let access = PETRA.getLandAccess(gameState, ent);