Move enums to own files in ai

This way they don't accidentally get mutated.
This commit is contained in:
phosit
2025-08-07 19:54:19 +02:00
committed by Phosit
parent 0a2bd6a5a4
commit 062be89694
11 changed files with 82 additions and 75 deletions
@@ -2,7 +2,8 @@ import * as filters from "simulation/ai/common-api/filters.js";
import { warn as aiWarn, SquareVectorDistance, VectorDistance } from "simulation/ai/common-api/utils.js"; import { warn as aiWarn, SquareVectorDistance, VectorDistance } from "simulation/ai/common-api/utils.js";
import { AttackPlan } from "simulation/ai/petra/attackPlan.js"; import { AttackPlan } from "simulation/ai/petra/attackPlan.js";
import * as chat from "simulation/ai/petra/chatHelper.js"; import * as chat from "simulation/ai/petra/chatHelper.js";
import { Config, DIFFICULTY_VERY_EASY } from "simulation/ai/petra/config.js"; import { Config } from "simulation/ai/petra/config.js";
import * as difficulty from "simulation/ai/petra/difficultyLevel.js";
import { allowCapture, getLandAccess } from "simulation/ai/petra/entityExtend.js"; import { allowCapture, getLandAccess } from "simulation/ai/petra/entityExtend.js";
import { Worker } from "simulation/ai/petra/worker.js"; import { Worker } from "simulation/ai/petra/worker.js";
@@ -435,7 +436,7 @@ AttackManager.prototype.update = function(gameState, queues, events)
} }
// Check if we have some unused ranged siege unit which could do something useful while waiting // Check if we have some unused ranged siege unit which could do something useful while waiting
if (this.Config.difficulty > DIFFICULTY_VERY_EASY && gameState.ai.playedTurn % 5 == 0) if (this.Config.difficulty > difficulty.VERY_EASY && gameState.ai.playedTurn % 5 == 0)
this.assignBombers(gameState); this.assignBombers(gameState);
}; };
@@ -1,7 +1,8 @@
import { EntityCollection } from "simulation/ai/common-api/entitycollection.js"; import { EntityCollection } from "simulation/ai/common-api/entitycollection.js";
import * as filters from "simulation/ai/common-api/filters.js"; import * as filters from "simulation/ai/common-api/filters.js";
import { SquareVectorDistance, VectorDistance, warn as aiWarn } from "simulation/ai/common-api/utils.js"; import { SquareVectorDistance, VectorDistance, warn as aiWarn } from "simulation/ai/common-api/utils.js";
import { Config, DIFFICULTY_EASY, DIFFICULTY_MEDIUM } from "simulation/ai/petra/config.js"; import { Config } from "simulation/ai/petra/config.js";
import * as difficulty from "simulation/ai/petra/difficultyLevel.js";
import { allowCapture, dumpEntity, getHolder, getLandAccess, isSiegeUnit, returnResources } from import { allowCapture, dumpEntity, getHolder, getLandAccess, isSiegeUnit, returnResources } from
"simulation/ai/petra/entityExtend.js"; "simulation/ai/petra/entityExtend.js";
import { TrainingPlan } from "simulation/ai/petra/queueplanTraining.js"; import { TrainingPlan } from "simulation/ai/petra/queueplanTraining.js";
@@ -179,18 +180,18 @@ export function AttackPlan(gameState, config, uniqueID, type = AttackPlan.TYPE_D
// Put some randomness on the attack size // Put some randomness on the attack size
let variation = randFloat(0.8, 1.2); let variation = randFloat(0.8, 1.2);
// and lower priority and smaller sizes for easier difficulty levels // and lower priority and smaller sizes for easier difficulty levels
if (this.Config.difficulty < DIFFICULTY_EASY) if (this.Config.difficulty < difficulty.EASY)
{ {
priority *= 0.4; priority *= 0.4;
variation *= 0.2; variation *= 0.2;
} }
else if (this.Config.difficulty < DIFFICULTY_MEDIUM) else if (this.Config.difficulty < difficulty.MEDIUM)
{ {
priority *= 0.8; priority *= 0.8;
variation *= 0.6; variation *= 0.6;
} }
if (this.Config.difficulty < DIFFICULTY_EASY) if (this.Config.difficulty < difficulty.EASY)
{ {
for (const cat in this.unitStat) for (const cat in this.unitStat)
{ {
@@ -432,7 +433,7 @@ AttackPlan.prototype.addSiegeUnits = function(gameState)
this.siegeState = AttackPlan.SIEGE_ADDED; this.siegeState = AttackPlan.SIEGE_ADDED;
let targetSize; let targetSize;
if (this.Config.difficulty < DIFFICULTY_MEDIUM) if (this.Config.difficulty < difficulty.MEDIUM)
targetSize = this.type === AttackPlan.TYPE_HUGE_ATTACK ? Math.max(this.Config.difficulty, 1) : Math.max(this.Config.difficulty - 1, 0); targetSize = this.type === AttackPlan.TYPE_HUGE_ATTACK ? Math.max(this.Config.difficulty, 1) : Math.max(this.Config.difficulty - 1, 0);
else else
targetSize = this.type === AttackPlan.TYPE_HUGE_ATTACK ? this.Config.difficulty + 1 : this.Config.difficulty - 1; targetSize = this.type === AttackPlan.TYPE_HUGE_ATTACK ? this.Config.difficulty + 1 : this.Config.difficulty - 1;
@@ -761,7 +762,7 @@ AttackPlan.prototype.assignUnits = function(gameState)
// Finally add also some workers for the higher difficulties, // Finally add also some workers for the higher difficulties,
// If Rush, assign all kind of workers, keeping only a minimum number of defenders // 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 // Otherwise, assign only some idle workers if too much of them
if (this.Config.difficulty <= DIFFICULTY_EASY) if (this.Config.difficulty <= difficulty.EASY)
return added; return added;
let num = 0; let num = 0;
@@ -1,6 +1,7 @@
import * as filters from "simulation/ai/common-api/filters.js"; import * as filters from "simulation/ai/common-api/filters.js";
import { SquareVectorDistance, warn as aiWarn } from "simulation/ai/common-api/utils.js"; import { SquareVectorDistance, warn as aiWarn } from "simulation/ai/common-api/utils.js";
import { Config, DIFFICULTY_EASY, DIFFICULTY_MEDIUM } from "simulation/ai/petra/config.js"; import { Config } from "simulation/ai/petra/config.js";
import * as difficulty from "simulation/ai/petra/difficultyLevel.js";
import { getBestBase, getBuiltEntity, getLandAccess, isFastMoving, isNotWorthBuilding } from import { getBestBase, getBuiltEntity, getLandAccess, isFastMoving, isNotWorthBuilding } from
"simulation/ai/petra/entityExtend.js"; "simulation/ai/petra/entityExtend.js";
import { createObstructionMap } from "simulation/ai/petra/mapModule.js"; import { createObstructionMap } from "simulation/ai/petra/mapModule.js";
@@ -36,7 +37,7 @@ export function BaseManager(gameState, basesManager)
this.constructing = false; this.constructing = false;
// Defenders to train in this cc when its construction is finished // Defenders to train in this cc when its construction is finished
this.neededDefenders = this.Config.difficulty > DIFFICULTY_EASY ? 3 + 2*(this.Config.difficulty - 3) : 0; this.neededDefenders = this.Config.difficulty > difficulty.EASY ? 3 + 2*(this.Config.difficulty - 3) : 0;
// vector for iterating, to check one use the HQ map. // vector for iterating, to check one use the HQ map.
this.territoryIndices = []; this.territoryIndices = [];
@@ -97,7 +98,7 @@ BaseManager.prototype.reset = function(gameState, state)
this.constructing = true; this.constructing = true;
else else
this.constructing = false; this.constructing = false;
if (state !== BaseManager.STATE_CAPTURED || this.Config.difficulty < DIFFICULTY_MEDIUM) if (state !== BaseManager.STATE_CAPTURED || this.Config.difficulty < difficulty.MEDIUM)
this.neededDefenders = 0; this.neededDefenders = 0;
else else
this.neededDefenders = 3 + 2 * (this.Config.difficulty - 3); this.neededDefenders = 3 + 2 * (this.Config.difficulty - 3);
@@ -1,18 +1,9 @@
import { warn as aiWarn } from "simulation/ai/common-api/utils.js"; import { warn as aiWarn } from "simulation/ai/common-api/utils.js";
import * as difficultyLevel from "simulation/ai/petra/difficultyLevel.js";
// These integers must be sequential export function Config(difficulty = difficultyLevel.MEDIUM, behavior)
/* eslint-disable prefer-const -- Mods should be able to change them */
export let DIFFICULTY_SANDBOX = 0;
export let DIFFICULTY_VERY_EASY = 1;
export let DIFFICULTY_EASY = 2;
export let DIFFICULTY_MEDIUM = 3;
export let DIFFICULTY_HARD = 4;
export let DIFFICULTY_VERY_HARD = 5;
/* eslint-enable prefer-const */
export function Config(difficulty = DIFFICULTY_MEDIUM, behavior)
{ {
this.difficulty = difficulty; this.difficulty = difficultyLevel;
// for instance "balanced", "aggressive" or "defensive" // for instance "balanced", "aggressive" or "defensive"
this.behavior = behavior || "random"; this.behavior = behavior || "random";
@@ -210,7 +201,7 @@ export function Config(difficulty = DIFFICULTY_MEDIUM, behavior)
Config.prototype.setConfig = function(gameState) Config.prototype.setConfig = function(gameState)
{ {
if (this.difficulty > DIFFICULTY_SANDBOX) if (this.difficulty > difficultyLevel.SANDBOX)
{ {
// Setup personality traits according to the user choice: // Setup personality traits according to the user choice:
// The parameter used to define the personality is basically the aggressivity or (1-defensiveness) // The parameter used to define the personality is basically the aggressivity or (1-defensiveness)
@@ -253,14 +244,14 @@ Config.prototype.setConfig = function(gameState)
this.Military.fortressLapseTime = Math.round(this.Military.fortressLapseTime * (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)); this.priorities.defenseBuilding = Math.round(this.priorities.defenseBuilding * (0.9 + 0.2 * this.personality.defensive));
if (this.difficulty < DIFFICULTY_EASY) if (this.difficulty < difficulty.EASY)
{ {
this.popScaling = 0.5; this.popScaling = 0.5;
this.Economy.supportRatio = 0.5; this.Economy.supportRatio = 0.5;
this.Economy.provisionFields = 1; this.Economy.provisionFields = 1;
this.Military.numSentryTowers = this.personality.defensive > this.personalityCut.strong ? 1 : 0; this.Military.numSentryTowers = this.personality.defensive > this.personalityCut.strong ? 1 : 0;
} }
else if (this.difficulty < DIFFICULTY_MEDIUM) else if (this.difficulty < difficulty.MEDIUM)
{ {
this.popScaling = 0.7; this.popScaling = 0.7;
this.Economy.supportRatio = 0.4; this.Economy.supportRatio = 0.4;
@@ -269,7 +260,7 @@ Config.prototype.setConfig = function(gameState)
} }
else else
{ {
if (this.difficulty == DIFFICULTY_MEDIUM) if (this.difficulty == difficulty.MEDIUM)
this.Military.numSentryTowers = 1; this.Military.numSentryTowers = 1;
else else
this.Military.numSentryTowers = 2; this.Military.numSentryTowers = 2;
@@ -287,9 +278,9 @@ Config.prototype.setConfig = function(gameState)
} }
const maxPop = gameState.getPopulationMax(); const maxPop = gameState.getPopulationMax();
if (this.difficulty < DIFFICULTY_EASY) if (this.difficulty < difficulty.EASY)
this.Economy.targetNumWorkers = Math.max(1, Math.min(40, maxPop)); this.Economy.targetNumWorkers = Math.max(1, Math.min(40, maxPop));
else if (this.difficulty < DIFFICULTY_MEDIUM) else if (this.difficulty < difficulty.MEDIUM)
this.Economy.targetNumWorkers = Math.max(1, Math.min(60, Math.floor(maxPop/2))); this.Economy.targetNumWorkers = Math.max(1, Math.min(60, Math.floor(maxPop/2)));
else else
this.Economy.targetNumWorkers = Math.max(1, Math.min(120, Math.floor(maxPop/3))); this.Economy.targetNumWorkers = Math.max(1, Math.min(120, Math.floor(maxPop/3)));
@@ -315,7 +306,7 @@ Config.prototype.setConfig = function(gameState)
this.Economy.targetNumWorkers = Math.max(this.Economy.targetNumWorkers, this.Economy.popPhase2); this.Economy.targetNumWorkers = Math.max(this.Economy.targetNumWorkers, this.Economy.popPhase2);
this.Economy.workPhase3 = Math.min(this.Economy.workPhase3, this.Economy.targetNumWorkers); this.Economy.workPhase3 = Math.min(this.Economy.workPhase3, this.Economy.targetNumWorkers);
this.Economy.workPhase4 = Math.min(this.Economy.workPhase4, this.Economy.targetNumWorkers); this.Economy.workPhase4 = Math.min(this.Economy.workPhase4, this.Economy.targetNumWorkers);
if (this.difficulty < DIFFICULTY_EASY) if (this.difficulty < difficulty.EASY)
this.Economy.workPhase3 = Infinity; // prevent the phasing to city phase this.Economy.workPhase3 = Infinity; // prevent the phasing to city phase
this.emergencyValues = { this.emergencyValues = {
@@ -0,0 +1,9 @@
// These integers must be sequential
/* eslint-disable prefer-const -- Mods should be able to change them */
export let SANDBOX = 0;
export let VERY_EASY = 1;
export let EASY = 2;
export let MEDIUM = 3;
export let HARD = 4;
export let VERY_HARD = 5;
/* eslint-enable prefer-const */
@@ -5,15 +5,17 @@ import { AttackManager } from "simulation/ai/petra/attackManager.js";
import { AttackPlan } from "simulation/ai/petra/attackPlan.js"; import { AttackPlan } from "simulation/ai/petra/attackPlan.js";
import { BasesManager } from "simulation/ai/petra/basesManager.js"; import { BasesManager } from "simulation/ai/petra/basesManager.js";
import { BuildManager } from "simulation/ai/petra/buildManager.js"; import { BuildManager } from "simulation/ai/petra/buildManager.js";
import { Config, DIFFICULTY_SANDBOX, DIFFICULTY_EASY } from "simulation/ai/petra/config.js"; import { Config } from "simulation/ai/petra/config.js";
import { DefenseManager } from "simulation/ai/petra/defenseManager.js"; import { DefenseManager } from "simulation/ai/petra/defenseManager.js";
import * as difficulty from "simulation/ai/petra/difficultyLevel.js";
import { DiplomacyManager } from "simulation/ai/petra/diplomacyManager.js"; import { DiplomacyManager } from "simulation/ai/petra/diplomacyManager.js";
import { EmergencyManager } from "simulation/ai/petra/emergencyManager.js"; import { EmergencyManager } from "simulation/ai/petra/emergencyManager.js";
import { allowCapture, getAttackBonus, getLandAccess, getMaxStrength, isLineInsideEnemyTerritory, import { allowCapture, getAttackBonus, getLandAccess, getMaxStrength, isLineInsideEnemyTerritory,
setSeaAccess } from "simulation/ai/petra/entityExtend.js"; setSeaAccess } from "simulation/ai/petra/entityExtend.js";
import { GarrisonManager } from "simulation/ai/petra/garrisonManager.js"; import { GarrisonManager } from "simulation/ai/petra/garrisonManager.js";
import { createBorderMap, createObstructionMap, createTerritoryMap, fullBorder_Mask, fullFrontier_Mask, import * as mapMask from "simulation/ai/petra/mapMask.js";
largeFrontier_Mask, narrowFrontier_Mask, outside_Mask } from "simulation/ai/petra/mapModule.js"; import { createBorderMap, createObstructionMap, createTerritoryMap } from
"simulation/ai/petra/mapModule.js";
import { NavalManager } from "simulation/ai/petra/navalManager.js"; import { NavalManager } from "simulation/ai/petra/navalManager.js";
import { ConstructionPlan } from "simulation/ai/petra/queueplanBuilding.js"; import { ConstructionPlan } from "simulation/ai/petra/queueplanBuilding.js";
import { TrainingPlan } from "simulation/ai/petra/queueplanTraining.js"; import { TrainingPlan } from "simulation/ai/petra/queueplanTraining.js";
@@ -261,7 +263,7 @@ Headquather.prototype.checkEvents = function(gameState, events)
} }
// Then deals with decaying structures: destroy them if being lost to enemy (except in easier difficulties) // Then deals with decaying structures: destroy them if being lost to enemy (except in easier difficulties)
if (this.Config.difficulty < DIFFICULTY_EASY) if (this.Config.difficulty < difficulty.EASY)
return; return;
for (const entId of this.decayingStructures) for (const entId of this.decayingStructures)
{ {
@@ -811,7 +813,7 @@ Headquather.prototype.findEconomicCCLocation = function(gameState, template, res
continue; continue;
} }
if (this.borderMap.map[j] & fullBorder_Mask) // disfavor the borders of the map if (this.borderMap.map[j] & mapMask.fullBorder) // disfavor the borders of the map
norm *= 0.5; norm *= 0.5;
let val = 2 * gameState.sharedScript.ccResourceMaps[resource].map[j]; let val = 2 * gameState.sharedScript.ccResourceMaps[resource].map[j];
@@ -966,7 +968,7 @@ Headquather.prototype.findStrategicCCLocation = function(gameState, template)
currentVal += delta*delta; currentVal += delta*delta;
} }
// disfavor border of the map // disfavor border of the map
if (this.borderMap.map[j] & fullBorder_Mask) if (this.borderMap.map[j] & mapMask.fullBorder)
currentVal += 10000; currentVal += 10000;
if (bestVal !== undefined && currentVal > bestVal) if (bestVal !== undefined && currentVal > bestVal)
@@ -1047,7 +1049,7 @@ Headquather.prototype.findMarketLocation = function(gameState, template)
for (let j = 0; j < this.territoryMap.length; ++j) for (let j = 0; j < this.territoryMap.length; ++j)
{ {
// do not try on the narrow border of our territory // do not try on the narrow border of our territory
if (this.borderMap.map[j] & narrowFrontier_Mask) if (this.borderMap.map[j] & mapMask.narrowFrontier)
continue; continue;
if (this.baseAtIndex(j) == 0) // only in our territory if (this.baseAtIndex(j) == 0) // only in our territory
continue; continue;
@@ -1193,9 +1195,9 @@ Headquather.prototype.findDefensiveLocation = function(gameState, template)
if (!wonderMode) if (!wonderMode)
{ {
// do not try if well inside or outside territory // do not try if well inside or outside territory
if (!(this.borderMap.map[j] & fullFrontier_Mask)) if (!(this.borderMap.map[j] & mapMask.fullFrontier))
continue; continue;
if (this.borderMap.map[j] & largeFrontier_Mask && isTower) if (this.borderMap.map[j] & mapMask.largeFrontier && isTower)
continue; continue;
} }
if (this.baseAtIndex(j) == 0) // inaccessible cell if (this.baseAtIndex(j) == 0) // inaccessible cell
@@ -1985,10 +1987,10 @@ Headquather.prototype.updateTerritories = function(gameState)
for (let j = 0; j < this.territoryMap.length; ++j) for (let j = 0; j < this.territoryMap.length; ++j)
{ {
if (this.borderMap.map[j] & outside_Mask) if (this.borderMap.map[j] & mapMask.outside)
continue; continue;
if (this.borderMap.map[j] & fullFrontier_Mask) if (this.borderMap.map[j] & mapMask.fullFrontier)
this.borderMap.map[j] &= ~fullFrontier_Mask; // reset the frontier this.borderMap.map[j] &= ~mapMask.fullFrontier; // reset the frontier
if (this.territoryMap.getOwnerIndex(j) != PlayerID) if (this.territoryMap.getOwnerIndex(j) != PlayerID)
this.basesManager.removeBaseFromTerritoryIndex(j); this.basesManager.removeBaseFromTerritoryIndex(j);
@@ -2006,12 +2008,12 @@ Headquather.prototype.updateTerritories = function(gameState)
let jz = iz + Math.round(insideSmall*a[1]); let jz = iz + Math.round(insideSmall*a[1]);
if (jz < 0 || jz >= width) if (jz < 0 || jz >= width)
continue; continue;
if (this.borderMap.map[jx+width*jz] & outside_Mask) if (this.borderMap.map[jx+width*jz] & mapMask.outside)
continue; continue;
let territoryOwner = this.territoryMap.getOwnerIndex(jx+width*jz); let territoryOwner = this.territoryMap.getOwnerIndex(jx+width*jz);
if (territoryOwner != PlayerID && !(alliedVictory && gameState.isPlayerAlly(territoryOwner))) if (territoryOwner != PlayerID && !(alliedVictory && gameState.isPlayerAlly(territoryOwner)))
{ {
this.borderMap.map[j] |= narrowFrontier_Mask; this.borderMap.map[j] |= mapMask.narrowFrontier;
break; break;
} }
jx = ix + Math.round(insideLarge*a[0]); jx = ix + Math.round(insideLarge*a[0]);
@@ -2020,14 +2022,14 @@ Headquather.prototype.updateTerritories = function(gameState)
jz = iz + Math.round(insideLarge*a[1]); jz = iz + Math.round(insideLarge*a[1]);
if (jz < 0 || jz >= width) if (jz < 0 || jz >= width)
continue; continue;
if (this.borderMap.map[jx+width*jz] & outside_Mask) if (this.borderMap.map[jx+width*jz] & mapMask.outside)
continue; continue;
territoryOwner = this.territoryMap.getOwnerIndex(jx+width*jz); territoryOwner = this.territoryMap.getOwnerIndex(jx+width*jz);
if (territoryOwner != PlayerID && !(alliedVictory && gameState.isPlayerAlly(territoryOwner))) if (territoryOwner != PlayerID && !(alliedVictory && gameState.isPlayerAlly(territoryOwner)))
onFrontier = true; onFrontier = true;
} }
if (onFrontier && !(this.borderMap.map[j] & narrowFrontier_Mask)) if (onFrontier && !(this.borderMap.map[j] & mapMask.narrowFrontier))
this.borderMap.map[j] |= largeFrontier_Mask; this.borderMap.map[j] |= mapMask.largeFrontier;
if (this.basesManager.addTerritoryIndexToBase(gameState, j, passabilityMap)) if (this.basesManager.addTerritoryIndexToBase(gameState, j, passabilityMap))
expansion++; expansion++;
@@ -2322,7 +2324,7 @@ Headquather.prototype.update = function(gameState, queues, events)
if (gameState.ai.playedTurn % 3 == 0) if (gameState.ai.playedTurn % 3 == 0)
{ {
this.constructTrainingBuildings(gameState, queues); this.constructTrainingBuildings(gameState, queues);
if (this.Config.difficulty > DIFFICULTY_SANDBOX) if (this.Config.difficulty > difficulty.SANDBOX)
this.buildDefenses(gameState, queues); this.buildDefenses(gameState, queues);
} }
@@ -2330,7 +2332,7 @@ Headquather.prototype.update = function(gameState, queues, events)
this.navalManager.update(gameState, queues, events); this.navalManager.update(gameState, queues, events);
if (this.Config.difficulty > DIFFICULTY_SANDBOX && (this.hasActiveBase() || !this.canBuildUnits)) if (this.Config.difficulty > difficulty.SANDBOX && (this.hasActiveBase() || !this.canBuildUnits))
this.attackManager.update(gameState, queues, events); this.attackManager.update(gameState, queues, events);
this.diplomacyManager.update(gameState, events); this.diplomacyManager.update(gameState, events);
@@ -0,0 +1,8 @@
/* eslint-disable prefer-const -- Mods should be able to change them */
export let outside = 1;
export let border = 2;
export let fullBorder = outside | border;
export let narrowFrontier = 4;
export let largeFrontier = 8;
export let fullFrontier = narrowFrontier | largeFrontier;
/* eslint-enable prefer-const */
@@ -1,6 +1,7 @@
import * as filters from "simulation/ai/common-api/filters.js"; import * as filters from "simulation/ai/common-api/filters.js";
import { InfoMap } from "simulation/ai/common-api/map-module.js"; import { InfoMap } from "simulation/ai/common-api/map-module.js";
import { getMapIndices } from "simulation/ai/common-api/utils.js"; import { getMapIndices } from "simulation/ai/common-api/utils.js";
import * as mapMask from "simulation/ai/petra/mapMask.js";
/** map functions */ /** map functions */
@@ -138,15 +139,6 @@ export function createTerritoryMap(gameState)
* - large border (inside our territory, exclusive of narrow) => bit 3 * - large border (inside our territory, exclusive of narrow) => bit 3
*/ */
/* eslint-disable prefer-const -- Mods should be able to change them */
export let outside_Mask = 1;
export let border_Mask = 2;
export let fullBorder_Mask = outside_Mask | border_Mask;
export let narrowFrontier_Mask = 4;
export let largeFrontier_Mask = 8;
export let fullFrontier_Mask = narrowFrontier_Mask | largeFrontier_Mask;
/* eslint-enable prefer-const */
export function createBorderMap(gameState) export function createBorderMap(gameState)
{ {
const map = new InfoMap(gameState.sharedScript, "territory"); const map = new InfoMap(gameState.sharedScript, "territory");
@@ -165,13 +157,13 @@ export function createBorderMap(gameState)
const radius = dx*dx + dy*dy; const radius = dx*dx + dy*dy;
if (radius < radcut) if (radius < radcut)
continue; continue;
map.map[j] = outside_Mask; map.map[j] = mapMask.outside;
const ind = getMapIndices(j, map, passabilityMap); const ind = getMapIndices(j, map, passabilityMap);
for (const k of ind) for (const k of ind)
{ {
if (passabilityMap.data[k] & obstructionMask) if (passabilityMap.data[k] & obstructionMask)
continue; continue;
map.map[j] = border_Mask; map.map[j] = mapMask.border;
break; break;
} }
} }
@@ -185,13 +177,13 @@ export function createBorderMap(gameState)
const iy = Math.floor(j/width); const iy = Math.floor(j/width);
if (ix < border || ix >= borderCut || iy < border || iy >= borderCut) if (ix < border || ix >= borderCut || iy < border || iy >= borderCut)
{ {
map.map[j] = outside_Mask; map.map[j] = mapMask.outside;
const ind = getMapIndices(j, map, passabilityMap); const ind = getMapIndices(j, map, passabilityMap);
for (const k of ind) for (const k of ind)
{ {
if (passabilityMap.data[k] & obstructionMask) if (passabilityMap.data[k] & obstructionMask)
continue; continue;
map.map[j] = border_Mask; map.map[j] = mapMask.border;
break; break;
} }
} }
@@ -3,8 +3,8 @@ import { InfoMap } from "simulation/ai/common-api/map-module.js";
import { ResourcesManager } from "simulation/ai/common-api/resources.js"; import { ResourcesManager } from "simulation/ai/common-api/resources.js";
import { SquareVectorDistance, VectorDistance, warn as aiWarn } from "simulation/ai/common-api/utils.js"; import { SquareVectorDistance, VectorDistance, warn as aiWarn } from "simulation/ai/common-api/utils.js";
import { getBuiltEntity, getLandAccess, getSeaAccess } from "simulation/ai/petra/entityExtend.js"; import { getBuiltEntity, getLandAccess, getSeaAccess } from "simulation/ai/petra/entityExtend.js";
import { border_Mask, createObstructionMap, fullBorder_Mask, outside_Mask } from import * as mapMask from "simulation/ai/petra/mapMask.js";
"simulation/ai/petra/mapModule.js"; import { createObstructionMap } from "simulation/ai/petra/mapModule.js";
import { QueuePlan } from "simulation/ai/petra/queueplan.js"; import { QueuePlan } from "simulation/ai/petra/queueplan.js";
/** /**
@@ -260,7 +260,7 @@ ConstructionPlan.prototype.findGoodPosition = function(gameState)
for (let j = 0; j < placement.map.length; ++j) for (let j = 0; j < placement.map.length; ++j)
{ {
let value = placement.map[j] - gameState.sharedScript.resourceMaps.wood.map[j]/3; let value = placement.map[j] - gameState.sharedScript.resourceMaps.wood.map[j]/3;
if (HQ.borderMap.map[j] & fullBorder_Mask) if (HQ.borderMap.map[j] & mapMask.fullBorder)
value /= 2; // we need space around farmstead, so disfavor map border value /= 2; // we need space around farmstead, so disfavor map border
placement.set(j, value); placement.set(j, value);
} }
@@ -282,9 +282,9 @@ ConstructionPlan.prototype.findGoodPosition = function(gameState)
placement.map[j] = 0; placement.map[j] = 0;
else if (placement.map[j] > 0) else if (placement.map[j] > 0)
{ {
if (favorBorder && HQ.borderMap.map[j] & border_Mask) if (favorBorder && HQ.borderMap.map[j] & mapMask.border)
placement.set(j, placement.map[j] + 50); placement.set(j, placement.map[j] + 50);
else if (disfavorBorder && !(HQ.borderMap.map[j] & fullBorder_Mask)) else if (disfavorBorder && !(HQ.borderMap.map[j] & mapMask.fullBorder))
placement.set(j, placement.map[j] + 10); placement.set(j, placement.map[j] + 10);
const x = (j % placement.width + 0.5) * cellSize; const x = (j % placement.width + 0.5) * cellSize;
@@ -302,9 +302,9 @@ ConstructionPlan.prototype.findGoodPosition = function(gameState)
placement.map[j] = 0; placement.map[j] = 0;
else if (placement.map[j] > 0) else if (placement.map[j] > 0)
{ {
if (favorBorder && HQ.borderMap.map[j] & border_Mask) if (favorBorder && HQ.borderMap.map[j] & mapMask.border)
placement.set(j, placement.map[j] + 50); placement.set(j, placement.map[j] + 50);
else if (disfavorBorder && !(HQ.borderMap.map[j] & fullBorder_Mask)) else if (disfavorBorder && !(HQ.borderMap.map[j] & mapMask.fullBorder))
placement.set(j, placement.map[j] + 10); placement.set(j, placement.map[j] + 10);
const x = (j % placement.width + 0.5) * cellSize; const x = (j % placement.width + 0.5) * cellSize;
@@ -496,7 +496,7 @@ ConstructionPlan.prototype.findDockPosition = function(gameState)
} }
// Add a penalty if on the map border as ship movement will be difficult // Add a penalty if on the map border as ship movement will be difficult
if (gameState.ai.HQ.borderMap.map[j] & fullBorder_Mask) if (gameState.ai.HQ.borderMap.map[j] & mapMask.fullBorder)
score += 20; score += 20;
// Do a pre-selection, supposing we will have the best possible water // Do a pre-selection, supposing we will have the best possible water
@@ -825,7 +825,7 @@ ConstructionPlan.prototype.getFrontierProximity = function(gameState, j)
const jz = iz + Math.round(i*step*a[1]); const jz = iz + Math.round(i*step*a[1]);
if (jz < 0 || jz >= width) if (jz < 0 || jz >= width)
continue; continue;
if (borderMap.map[jx+width*jz] & outside_Mask) if (borderMap.map[jx+width*jz] & mapMask.outside)
continue; continue;
territoryOwner = territoryMap.getOwnerIndex(jx+width*jz); territoryOwner = territoryMap.getOwnerIndex(jx+width*jz);
if (alliedVictory && gameState.isPlayerAlly(territoryOwner) || territoryOwner == PlayerID) if (alliedVictory && gameState.isPlayerAlly(territoryOwner) || territoryOwner == PlayerID)
@@ -1,7 +1,8 @@
import * as filters from "simulation/ai/common-api/filters.js"; import * as filters from "simulation/ai/common-api/filters.js";
import { ResourcesManager } from "simulation/ai/common-api/resources.js"; import { ResourcesManager } from "simulation/ai/common-api/resources.js";
import { SquareVectorDistance, warn as aiWarn } from "simulation/ai/common-api/utils.js"; import { SquareVectorDistance, warn as aiWarn } from "simulation/ai/common-api/utils.js";
import { Config, DIFFICULTY_SANDBOX } from "simulation/ai/petra/config.js"; import { Config } from "simulation/ai/petra/config.js";
import * as difficulty from "simulation/ai/petra/difficultyLevel.js";
import { gatherTreasure, getLandAccess, isFastMoving } from "simulation/ai/petra/entityExtend.js"; import { gatherTreasure, getLandAccess, isFastMoving } from "simulation/ai/petra/entityExtend.js";
import { Headquather } from "simulation/ai/petra/headquarters.js"; import { Headquather } from "simulation/ai/petra/headquarters.js";
import { ConstructionPlan } from "simulation/ai/petra/queueplanBuilding.js"; import { ConstructionPlan } from "simulation/ai/petra/queueplanBuilding.js";
@@ -35,7 +36,7 @@ Headquather.prototype.gameAnalysis = function(gameState)
// Sandbox difficulty should not try to expand // Sandbox difficulty should not try to expand
this.canExpand = this.Config.difficulty != DIFFICULTY_SANDBOX; this.canExpand = this.Config.difficulty != difficulty.SANDBOX;
// If no base yet, check if we can construct one. If not, dispatch our units to possible tasks/attacks // If no base yet, check if we can construct one. If not, dispatch our units to possible tasks/attacks
this.canBuildUnits = true; this.canBuildUnits = true;
if (!gameState.getOwnStructures().filter(filters.byClass("CivCentre")).hasEntities()) if (!gameState.getOwnStructures().filter(filters.byClass("CivCentre")).hasEntities())
@@ -1,7 +1,8 @@
import * as filters from "simulation/ai/common-api/filters.js"; import * as filters from "simulation/ai/common-api/filters.js";
import { SquareVectorDistance, warn as aiWarn } from "simulation/ai/common-api/utils.js"; import { SquareVectorDistance, warn as aiWarn } from "simulation/ai/common-api/utils.js";
import { newTradeRoute as chatNewTradeRoute } from "simulation/ai/petra/chatHelper.js"; import { newTradeRoute as chatNewTradeRoute } from "simulation/ai/petra/chatHelper.js";
import { Config, DIFFICULTY_VERY_EASY } from "simulation/ai/petra/config.js"; import { Config } from "simulation/ai/petra/config.js";
import * as difficulty from "simulation/ai/petra/difficultyLevel.js";
import { gatherTreasure, getBestBase, getLandAccess, getSeaAccess, isLineInsideEnemyTerritory } from import { gatherTreasure, getBestBase, getLandAccess, getSeaAccess, isLineInsideEnemyTerritory } from
"simulation/ai/petra/entityExtend.js"; "simulation/ai/petra/entityExtend.js";
import { ConstructionPlan } from "simulation/ai/petra/queueplanBuilding.js"; import { ConstructionPlan } from "simulation/ai/petra/queueplanBuilding.js";
@@ -680,7 +681,7 @@ TradeManager.prototype.update = function(gameState, events, queues)
if (gameState.ai.HQ.canBarter && Resources.GetBarterableCodes().length) if (gameState.ai.HQ.canBarter && Resources.GetBarterableCodes().length)
this.performBarter(gameState); this.performBarter(gameState);
if (this.Config.difficulty <= DIFFICULTY_VERY_EASY) if (this.Config.difficulty <= difficulty.VERY_EASY)
return; return;
if (this.checkEvents(gameState, events)) // true if one market was built or destroyed if (this.checkEvents(gameState, events)) // true if one market was built or destroyed