@supalosa/chronodivide-bot 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/.prettierrc +5 -5
  2. package/TODO.md +18 -0
  3. package/dist/bot/bot.js +4 -4
  4. package/dist/bot/bot.js.map +1 -1
  5. package/dist/bot/logic/awareness.js +8 -8
  6. package/dist/bot/logic/awareness.js.map +1 -1
  7. package/dist/bot/logic/building/ArtilleryUnit.js +30 -9
  8. package/dist/bot/logic/building/antiGroundStaticDefence.js +2 -2
  9. package/dist/bot/logic/building/antiGroundStaticDefence.js.map +1 -1
  10. package/dist/bot/logic/building/artilleryUnit.js.map +1 -0
  11. package/dist/bot/logic/building/basicAirUnit.js +3 -2
  12. package/dist/bot/logic/building/basicAirUnit.js.map +1 -1
  13. package/dist/bot/logic/building/basicBuilding.js +1 -1
  14. package/dist/bot/logic/building/basicBuilding.js.map +1 -1
  15. package/dist/bot/logic/building/basicGroundUnit.js +4 -3
  16. package/dist/bot/logic/building/basicGroundUnit.js.map +1 -1
  17. package/dist/bot/logic/building/building.js +11 -55
  18. package/dist/bot/logic/building/buildingRules.js +162 -0
  19. package/dist/bot/logic/building/buildingRules.js.map +1 -0
  20. package/dist/bot/logic/building/harvester.js.map +1 -1
  21. package/dist/bot/logic/building/massedAntiGroundUnit.js +20 -0
  22. package/dist/bot/logic/building/powerPlant.js +1 -1
  23. package/dist/bot/logic/building/powerPlant.js.map +1 -1
  24. package/dist/bot/logic/building/queueController.js +1 -1
  25. package/dist/bot/logic/building/queueController.js.map +1 -1
  26. package/dist/bot/logic/building/queues.js +19 -0
  27. package/dist/bot/logic/building/resourceCollectionBuilding.js +5 -3
  28. package/dist/bot/logic/building/resourceCollectionBuilding.js.map +1 -1
  29. package/dist/bot/logic/common/scout.js +49 -32
  30. package/dist/bot/logic/common/scout.js.map +1 -1
  31. package/dist/bot/logic/common/utils.js +50 -1
  32. package/dist/bot/logic/common/utils.js.map +1 -1
  33. package/dist/bot/logic/knowledge.js +1 -0
  34. package/dist/bot/logic/map/map.js +17 -19
  35. package/dist/bot/logic/map/map.js.map +1 -1
  36. package/dist/bot/logic/map/sector.js +10 -13
  37. package/dist/bot/logic/map/sector.js.map +1 -1
  38. package/dist/bot/logic/mission/basicMission.js +26 -0
  39. package/dist/bot/logic/mission/expansionMission.js +32 -0
  40. package/dist/bot/logic/mission/missionFactories.js +2 -0
  41. package/dist/bot/logic/mission/missionFactories.js.map +1 -1
  42. package/dist/bot/logic/mission/missions/attackMission.js +4 -4
  43. package/dist/bot/logic/mission/missions/attackMission.js.map +1 -1
  44. package/dist/bot/logic/mission/missions/defenceMission.js +2 -1
  45. package/dist/bot/logic/mission/missions/defenceMission.js.map +1 -1
  46. package/dist/bot/logic/mission/missions/engineerMission.js +34 -0
  47. package/dist/bot/logic/mission/missions/engineerMission.js.map +1 -0
  48. package/dist/bot/logic/mission/missions/retreatMission.js.map +1 -1
  49. package/dist/bot/logic/squad/behaviours/attackSquad.js +56 -63
  50. package/dist/bot/logic/squad/behaviours/combatSquad.js +18 -19
  51. package/dist/bot/logic/squad/behaviours/combatSquad.js.map +1 -1
  52. package/dist/bot/logic/squad/behaviours/common.js +19 -2
  53. package/dist/bot/logic/squad/behaviours/common.js.map +1 -1
  54. package/dist/bot/logic/squad/behaviours/defenceSquad.js +2 -15
  55. package/dist/bot/logic/squad/behaviours/engineerSquad.js +36 -0
  56. package/dist/bot/logic/squad/behaviours/engineerSquad.js.map +1 -0
  57. package/dist/bot/logic/squad/behaviours/retreatSquad.js.map +1 -1
  58. package/dist/bot/logic/squad/behaviours/scoutingSquad.js +21 -17
  59. package/dist/bot/logic/squad/behaviours/scoutingSquad.js.map +1 -1
  60. package/dist/bot/logic/squad/behaviours/squadExpansion.js +31 -0
  61. package/dist/bot/logic/squad/behaviours/squadScouters.js +8 -0
  62. package/dist/bot/logic/squad/squad.js +5 -8
  63. package/dist/bot/logic/squad/squad.js.map +1 -1
  64. package/dist/bot/logic/squad/squadBehaviour.js.map +1 -1
  65. package/dist/bot/logic/squad/squadController.js +2 -3
  66. package/dist/bot/logic/squad/squadController.js.map +1 -1
  67. package/dist/bot/logic/threat/threatCalculator.js +4 -3
  68. package/dist/bot/logic/threat/threatCalculator.js.map +1 -1
  69. package/dist/exampleBot.js +6 -6
  70. package/dist/exampleBot.js.map +1 -1
  71. package/package.json +5 -9
  72. package/src/bot/bot.ts +8 -10
  73. package/src/bot/logic/awareness.ts +13 -17
  74. package/src/bot/logic/building/antiGroundStaticDefence.ts +13 -9
  75. package/src/bot/logic/building/artilleryUnit.ts +65 -0
  76. package/src/bot/logic/building/basicAirUnit.ts +10 -8
  77. package/src/bot/logic/building/basicBuilding.ts +1 -1
  78. package/src/bot/logic/building/basicGroundUnit.ts +4 -4
  79. package/src/bot/logic/building/{building.ts → buildingRules.ts} +94 -48
  80. package/src/bot/logic/building/harvester.ts +7 -4
  81. package/src/bot/logic/building/powerPlant.ts +1 -1
  82. package/src/bot/logic/building/queueController.ts +1 -1
  83. package/src/bot/logic/building/resourceCollectionBuilding.ts +8 -12
  84. package/src/bot/logic/common/scout.ts +83 -38
  85. package/src/bot/logic/common/utils.ts +65 -1
  86. package/src/bot/logic/map/map.ts +27 -31
  87. package/src/bot/logic/map/sector.ts +17 -21
  88. package/src/bot/logic/mission/missionFactories.ts +2 -0
  89. package/src/bot/logic/mission/missions/attackMission.ts +27 -27
  90. package/src/bot/logic/mission/missions/defenceMission.ts +3 -3
  91. package/src/bot/logic/mission/missions/engineerMission.ts +61 -0
  92. package/src/bot/logic/mission/missions/retreatMission.ts +2 -2
  93. package/src/bot/logic/squad/behaviours/combatSquad.ts +24 -26
  94. package/src/bot/logic/squad/behaviours/common.ts +33 -3
  95. package/src/bot/logic/squad/behaviours/engineerSquad.ts +53 -0
  96. package/src/bot/logic/squad/behaviours/retreatSquad.ts +2 -2
  97. package/src/bot/logic/squad/behaviours/scoutingSquad.ts +26 -28
  98. package/src/bot/logic/squad/squad.ts +8 -13
  99. package/src/bot/logic/squad/squadBehaviour.ts +9 -10
  100. package/src/bot/logic/squad/squadController.ts +2 -5
  101. package/src/bot/logic/threat/threat.ts +15 -15
  102. package/src/bot/logic/threat/threatCalculator.ts +4 -3
  103. package/src/exampleBot.ts +6 -6
  104. package/dist/bot/logic/awarenessImpl.js +0 -132
  105. package/dist/bot/logic/awarenessImpl.js.map +0 -1
  106. package/dist/bot/logic/building/ArtilleryUnit.js.map +0 -1
  107. package/dist/bot/logic/building/building.js.map +0 -1
  108. package/src/bot/logic/building/ArtilleryUnit.ts +0 -43
@@ -0,0 +1,65 @@
1
+ import { GameApi, GameMath, PlayerData, TechnoRules } from "@chronodivide/game-api";
2
+ import { GlobalThreat } from "../threat/threat.js";
3
+ import { AiBuildingRules, numBuildingsOwnedOfType } from "./buildingRules.js";
4
+
5
+ export class ArtilleryUnit implements AiBuildingRules {
6
+ constructor(
7
+ private basePriority: number,
8
+ private artilleryPower: number,
9
+ private antiGroundPower: number,
10
+ private baseAmount: number,
11
+ ) {}
12
+
13
+ getPlacementLocation(
14
+ game: GameApi,
15
+ playerData: PlayerData,
16
+ technoRules: TechnoRules,
17
+ ): { rx: number; ry: number } | undefined {
18
+ return undefined;
19
+ }
20
+
21
+ getPriority(
22
+ game: GameApi,
23
+ playerData: PlayerData,
24
+ technoRules: TechnoRules,
25
+ threatCache: GlobalThreat | null,
26
+ ): number {
27
+ const numOwned = numBuildingsOwnedOfType(game, playerData, technoRules);
28
+ let priority = this.basePriority;
29
+ // If the enemy's defensive power is increasing we will start to build these.
30
+ if (threatCache && threatCache.totalDefensivePower > threatCache.totalAvailableAntiGroundFirepower) {
31
+ priority +=
32
+ this.artilleryPower *
33
+ (threatCache.totalAvailableAntiGroundFirepower / Math.max(1, threatCache.totalDefensivePower));
34
+ }
35
+ if (threatCache && this.antiGroundPower > 0) {
36
+ // If the enemy's power is increasing we should try to keep up.
37
+ if (threatCache.totalOffensiveLandThreat > threatCache.totalAvailableAntiGroundFirepower) {
38
+ priority +=
39
+ this.antiGroundPower *
40
+ this.basePriority *
41
+ (threatCache.totalOffensiveLandThreat / Math.max(1, threatCache.totalAvailableAntiGroundFirepower));
42
+ } else {
43
+ // But also, if our power dwarfs the enemy, keep pressing the advantage.
44
+ priority +=
45
+ (this.antiGroundPower *
46
+ this.basePriority *
47
+ GameMath.sqrt(
48
+ threatCache.totalAvailableAntiGroundFirepower /
49
+ Math.max(1, threatCache.totalOffensiveLandThreat + threatCache.totalDefensiveThreat),
50
+ )) /
51
+ (numOwned + 1);
52
+ }
53
+ }
54
+ return priority * (1.0 - numOwned / this.baseAmount);
55
+ }
56
+
57
+ getMaxCount(
58
+ game: GameApi,
59
+ playerData: PlayerData,
60
+ technoRules: TechnoRules,
61
+ threatCache: GlobalThreat | null,
62
+ ): number | null {
63
+ return null;
64
+ }
65
+ }
@@ -1,19 +1,19 @@
1
- import { GameApi, PlayerData, TechnoRules } from "@chronodivide/game-api";
1
+ import { GameApi, GameMath, PlayerData, TechnoRules } from "@chronodivide/game-api";
2
2
  import { GlobalThreat } from "../threat/threat.js";
3
- import { AiBuildingRules, getDefaultPlacementLocation, numBuildingsOwnedOfType } from "./building.js";
3
+ import { AiBuildingRules, getDefaultPlacementLocation, numBuildingsOwnedOfType } from "./buildingRules.js";
4
4
 
5
5
  export class BasicAirUnit implements AiBuildingRules {
6
6
  constructor(
7
7
  private basePriority: number,
8
8
  private baseAmount: number,
9
9
  private antiGroundPower: number = 1, // boolean for now, but will eventually be used in weighting.
10
- private antiAirPower: number = 0
10
+ private antiAirPower: number = 0,
11
11
  ) {}
12
12
 
13
13
  getPlacementLocation(
14
14
  game: GameApi,
15
15
  playerData: PlayerData,
16
- technoRules: TechnoRules
16
+ technoRules: TechnoRules,
17
17
  ): { rx: number; ry: number } | undefined {
18
18
  return undefined;
19
19
  }
@@ -22,7 +22,7 @@ export class BasicAirUnit implements AiBuildingRules {
22
22
  game: GameApi,
23
23
  playerData: PlayerData,
24
24
  technoRules: TechnoRules,
25
- threatCache: GlobalThreat | null
25
+ threatCache: GlobalThreat | null,
26
26
  ): number {
27
27
  // If the enemy's anti-air power is low we might build more.
28
28
  if (threatCache) {
@@ -48,8 +48,10 @@ export class BasicAirUnit implements AiBuildingRules {
48
48
  1.0,
49
49
  Math.max(
50
50
  1,
51
- Math.sqrt(threatCache.totalAvailableAirPower / Math.max(1, threatCache.totalOffensiveAntiAirThreat))
52
- )
51
+ GameMath.sqrt(
52
+ threatCache.totalAvailableAirPower / Math.max(1, threatCache.totalOffensiveAntiAirThreat),
53
+ ),
54
+ ),
53
55
  );
54
56
  return this.baseAmount * priority;
55
57
  }
@@ -61,7 +63,7 @@ export class BasicAirUnit implements AiBuildingRules {
61
63
  game: GameApi,
62
64
  playerData: PlayerData,
63
65
  technoRules: TechnoRules,
64
- threatCache: GlobalThreat | null
66
+ threatCache: GlobalThreat | null,
65
67
  ): number | null {
66
68
  return null;
67
69
  }
@@ -1,5 +1,5 @@
1
1
  import { GameApi, PlayerData, TechnoRules } from "@chronodivide/game-api";
2
- import { AiBuildingRules, getDefaultPlacementLocation, numBuildingsOwnedOfType } from "./building.js";
2
+ import { AiBuildingRules, getDefaultPlacementLocation, numBuildingsOwnedOfType } from "./buildingRules.js";
3
3
  import { GlobalThreat } from "../threat/threat.js";
4
4
 
5
5
  export class BasicBuilding implements AiBuildingRules {
@@ -1,6 +1,6 @@
1
- import { GameApi, PlayerData, TechnoRules } from "@chronodivide/game-api";
1
+ import { GameApi, GameMath, PlayerData, TechnoRules } from "@chronodivide/game-api";
2
2
  import { GlobalThreat } from "../threat/threat.js";
3
- import { AiBuildingRules, getDefaultPlacementLocation, numBuildingsOwnedOfType } from "./building.js";
3
+ import { AiBuildingRules, getDefaultPlacementLocation, numBuildingsOwnedOfType } from "./buildingRules.js";
4
4
 
5
5
  export class BasicGroundUnit implements AiBuildingRules {
6
6
  constructor(
@@ -40,7 +40,7 @@ export class BasicGroundUnit implements AiBuildingRules {
40
40
  priority +=
41
41
  (this.antiGroundPower *
42
42
  this.basePriority *
43
- Math.sqrt(
43
+ GameMath.sqrt(
44
44
  threatCache.totalAvailableAntiGroundFirepower /
45
45
  Math.max(
46
46
  1,
@@ -60,7 +60,7 @@ export class BasicGroundUnit implements AiBuildingRules {
60
60
  priority +=
61
61
  (this.antiAirPower *
62
62
  this.basePriority *
63
- Math.sqrt(
63
+ GameMath.sqrt(
64
64
  threatCache.totalAvailableAntiAirFirepower /
65
65
  Math.max(1, threatCache.totalOffensiveAirThreat + threatCache.totalDefensiveThreat),
66
66
  )) /
@@ -1,22 +1,24 @@
1
1
  import {
2
2
  BuildingPlacementData,
3
3
  GameApi,
4
+ GameMath,
4
5
  ObjectType,
5
6
  PlayerData,
6
- Point2D,
7
7
  Size,
8
8
  TechnoRules,
9
9
  Tile,
10
+ Vector2,
10
11
  } from "@chronodivide/game-api";
11
12
  import { GlobalThreat } from "../threat/threat.js";
12
13
  import { AntiGroundStaticDefence } from "./antiGroundStaticDefence.js";
13
- import { ArtilleryUnit } from "./ArtilleryUnit.js";
14
+ import { ArtilleryUnit } from "./artilleryUnit.js";
14
15
  import { BasicAirUnit } from "./basicAirUnit.js";
15
16
  import { BasicBuilding } from "./basicBuilding.js";
16
17
  import { BasicGroundUnit } from "./basicGroundUnit.js";
17
18
  import { PowerPlant } from "./powerPlant.js";
18
19
  import { ResourceCollectionBuilding } from "./resourceCollectionBuilding.js";
19
20
  import { Harvester } from "./harvester.js";
21
+ import { uniqBy } from "../common/utils.js";
20
22
 
21
23
  export interface AiBuildingRules {
22
24
  getPriority(
@@ -48,74 +50,118 @@ export function numBuildingsOwnedOfName(game: GameApi, playerData: PlayerData, n
48
50
  return game.getVisibleUnits(playerData.name, "self", (r) => r.name === name).length;
49
51
  }
50
52
 
51
- function computeAdjacentRect(point: Point2D, t: Size, adjacent: number) {
53
+ /**
54
+ * Computes a rect 'centered' around a structure of a certain size with additional radius.
55
+ *
56
+ * This is essentially the placeable area around a given structure.
57
+ *
58
+ * @param point Top-left location of the inner rect.
59
+ * @param t Size of the inner rect.
60
+ * @param adjacent Size of the outer rect.
61
+ * @returns
62
+ */
63
+ function computeAdjacentRect(point: Vector2, t: Size, adjacent: number) {
52
64
  return {
53
65
  x: point.x - adjacent,
54
66
  y: point.y - adjacent,
55
67
  width: t.width + 2 * adjacent,
56
- height: t.height + 2 * adjacent
68
+ height: t.height + 2 * adjacent,
57
69
  };
58
70
  }
59
- export function getAdjacencyTiles(game: GameApi,playerData: PlayerData,technoRules: TechnoRules){
60
- let tiles = []
61
- let buildings= game.getVisibleUnits(playerData.name,"self",(tech:TechnoRules)=>{ return tech.type === ObjectType.Building })
62
- for(let i in buildings){
63
- let building = game.getUnitData(buildings[i])
64
-
65
- if(building?.rules?.baseNormal){
66
- let foundation = building?.foundation;
67
- let range = computeAdjacentRect({x:building?.tile.rx,y:building?.tile.ry},{width:foundation?.width,height:foundation?.height},technoRules.adjacent)
68
- let baseTile = game.mapApi.getTile(range.x,range.y)
69
- if (!baseTile){
70
- continue
71
+
72
+ export function getAdjacencyTiles(
73
+ game: GameApi,
74
+ playerData: PlayerData,
75
+ technoRules: TechnoRules,
76
+ minimumSpace: number,
77
+ ) {
78
+ const placementRules = game.getBuildingPlacementData(technoRules.name);
79
+ const { width: newBuildingWidth, height: newBuildingHeight } = placementRules.foundation;
80
+ const tiles = [];
81
+ const buildings = game.getVisibleUnits(playerData.name, "self", (r: TechnoRules) => r.type === ObjectType.Building);
82
+ const removedTiles = new Set<string>();
83
+ for (let buildingId of buildings) {
84
+ const building = game.getUnitData(buildingId);
85
+ if (building?.rules?.baseNormal) {
86
+ const { foundation, tile } = building;
87
+ const buildingBase = new Vector2(tile.rx, tile.ry);
88
+ const buildingSize = {
89
+ width: foundation?.width,
90
+ height: foundation?.height,
91
+ };
92
+ const range = computeAdjacentRect(buildingBase, buildingSize, technoRules.adjacent);
93
+ const baseTile = game.mapApi.getTile(range.x, range.y);
94
+ if (!baseTile) {
95
+ continue;
71
96
  }
72
- tiles.push(...game.mapApi.getTilesInRect(baseTile,{width:range.width,height:range.height}))
97
+ const adjacentTiles = game.mapApi.getTilesInRect(baseTile, {
98
+ width: range.width,
99
+ height: range.height,
100
+ });
101
+ tiles.push(...adjacentTiles);
102
+
103
+ // Prevent placing the new building on tiles that would cause it to overlap with this building.
104
+ const modifiedBase = new Vector2(
105
+ buildingBase.x - (newBuildingWidth - 1),
106
+ buildingBase.y - (newBuildingHeight - 1),
107
+ );
108
+ const modifiedSize = {
109
+ width: buildingSize.width + (newBuildingWidth - 1),
110
+ height: buildingSize.height + (newBuildingHeight - 1),
111
+ };
112
+ const blockedRect = computeAdjacentRect(modifiedBase, modifiedSize, minimumSpace);
113
+ const buildingTiles = adjacentTiles.filter((tile) => {
114
+ return (
115
+ tile.rx >= blockedRect.x &&
116
+ tile.rx < blockedRect.x + blockedRect.width &&
117
+ tile.ry >= blockedRect.y &&
118
+ tile.ry < blockedRect.y + blockedRect.height
119
+ );
120
+ });
121
+ buildingTiles.forEach((buildingTile) => removedTiles.add(buildingTile.id));
73
122
  }
74
123
  }
75
- return tiles
124
+ // Remove duplicate tiles.
125
+ const withDuplicatesRemoved = uniqBy(tiles, (tile) => tile.id);
126
+ // Remove tiles containing buildings and potentially area around them removed as well.
127
+ return withDuplicatesRemoved.filter((tile) => !removedTiles.has(tile.id));
76
128
  }
77
129
 
78
-
79
- function getTileDistances(startPoint: Point2D, tiles: Tile[]) {
80
- let ret = [];
81
- for (let i in tiles) {
82
- let currentTile = tiles[i]
83
- ret.push({
84
- tile:currentTile,
85
- distance:distance(currentTile.rx, currentTile.ry, startPoint.x, startPoint.y)
86
- })
87
- }
88
- ret.sort((a,b)=>{
89
- return a.distance - b. distance
90
- })
91
- return ret
130
+ function getTileDistances(startPoint: Vector2, tiles: Tile[]) {
131
+ return tiles
132
+ .map((tile) => ({
133
+ tile,
134
+ distance: distance(tile.rx, tile.ry, startPoint.x, startPoint.y),
135
+ }))
136
+ .sort((a, b) => {
137
+ return a.distance - b.distance;
138
+ });
92
139
  }
93
140
 
94
- function distance(x1: number, y1 :number, x2:number, y2:number) {
95
- var dx = x1 - x2
141
+ function distance(x1: number, y1: number, x2: number, y2: number) {
142
+ var dx = x1 - x2;
96
143
  var dy = y1 - y2;
97
144
  let tmp = dx * dx + dy * dy;
98
145
  if (0 === tmp) {
99
- return 0
146
+ return 0;
100
147
  }
101
- return Math.sqrt(tmp)
148
+ return GameMath.sqrt(tmp);
102
149
  }
103
150
 
104
-
105
151
  export function getDefaultPlacementLocation(
106
152
  game: GameApi,
107
153
  playerData: PlayerData,
108
- startPoint: Point2D,
154
+ startPoint: Vector2,
109
155
  technoRules: TechnoRules,
110
- space: number = 1,
156
+ minSpace: number = 1,
111
157
  ): { rx: number; ry: number } | undefined {
112
158
  // Random location, preferably near start location.
113
- let size: BuildingPlacementData = game.getBuildingPlacementData(technoRules.name);
159
+ const size: BuildingPlacementData = game.getBuildingPlacementData(technoRules.name);
114
160
  if (!size) {
115
161
  return undefined;
116
162
  }
117
- let tiles = getAdjacencyTiles(game, playerData, technoRules)
118
- let tileDistances = getTileDistances(startPoint, tiles)
163
+ const tiles = getAdjacencyTiles(game, playerData, technoRules, minSpace);
164
+ const tileDistances = getTileDistances(startPoint, tiles);
119
165
 
120
166
  for (let tileDistance of tileDistances) {
121
167
  if (tileDistance.tile && game.canPlaceBuilding(playerData.name, technoRules.name, tileDistance.tile)) {
@@ -137,9 +183,9 @@ export const BUILDING_NAME_TO_RULES = new Map<string, AiBuildingRules>([
137
183
  ["GAWEAP", new BasicBuilding(15, 1)], // War Factory
138
184
  ["GAPILE", new BasicBuilding(12, 1)], // Barracks
139
185
  ["CMIN", new Harvester(15, 4, 2)], // Chrono Miner
140
- ["ENGINEER", new BasicBuilding(1, 1, 10000)], // Engineer
186
+ ["ENGINEER", new BasicBuilding(10, 1, 1000)], // Engineer
141
187
  ["GADEPT", new BasicBuilding(1, 1, 10000)], // Repair Depot
142
- ["GAAIRC", new BasicBuilding(8, 1, 6000)], // Airforce Command
188
+ ["GAAIRC", new BasicBuilding(10, 1, 500)], // Airforce Command
143
189
 
144
190
  ["GATECH", new BasicBuilding(20, 1, 4000)], // Allied Battle Lab
145
191
  ["GAYARD", new BasicBuilding(0, 0, 0)], // Naval Yard, disabled
@@ -154,7 +200,7 @@ export const BUILDING_NAME_TO_RULES = new Map<string, AiBuildingRules>([
154
200
  ["FV", new BasicGroundUnit(5, 2, 0.5, 1)], // IFV
155
201
  ["JUMPJET", new BasicAirUnit(10, 1, 1, 1)], // Rocketeer
156
202
  ["ORCA", new BasicAirUnit(7, 1, 2, 0)], // Rocketeer
157
- ["SREF", new ArtilleryUnit(9, 1)], // Prism Tank
203
+ ["SREF", new ArtilleryUnit(10, 5, 3, 3)], // Prism Tank
158
204
  ["CLEG", new BasicGroundUnit(0, 0)], // Chrono Legionnaire (Disabled - we don't handle the warped out phase properly and it tends to bug both bots out)
159
205
  ["SHAD", new BasicGroundUnit(0, 0)], // Nighthawk (Disabled)
160
206
 
@@ -164,9 +210,9 @@ export const BUILDING_NAME_TO_RULES = new Map<string, AiBuildingRules>([
164
210
  ["NAWEAP", new BasicBuilding(15, 1)], // War Factory
165
211
  ["NAHAND", new BasicBuilding(12, 1)], // Barracks
166
212
  ["HARV", new Harvester(15, 4, 2)], // War Miner
167
- ["SENGINEER", new BasicBuilding(1, 1, 10000)], // Soviet Engineer
213
+ ["SENGINEER", new BasicBuilding(10, 1, 1000)], // Soviet Engineer
168
214
  ["NADEPT", new BasicBuilding(1, 1, 10000)], // Repair Depot
169
- ["NARADR", new BasicBuilding(8, 1, 4000)], // Radar
215
+ ["NARADR", new BasicBuilding(10, 1, 500)], // Radar
170
216
  ["NANRCT", new PowerPlant()], // Nuclear Reactor
171
217
  ["NAYARD", new BasicBuilding(0, 0, 0)], // Naval Yard, disabled
172
218
 
@@ -181,5 +227,5 @@ export const BUILDING_NAME_TO_RULES = new Map<string, AiBuildingRules>([
181
227
  ["APOC", new BasicGroundUnit(6, 1, 5, 0)], // Apocalypse Tank
182
228
  ["HTK", new BasicGroundUnit(5, 2, 0.33, 1.5)], // Flak Track
183
229
  ["ZEP", new BasicAirUnit(5, 1, 5, 1)], // Kirov
184
- ["V3", new ArtilleryUnit(9, 1)], // V3 Rocket Launcher
230
+ ["V3", new ArtilleryUnit(9, 10, 0, 3)], // V3 Rocket Launcher
185
231
  ]);
@@ -1,12 +1,15 @@
1
- import { GameApi, PlayerData, Point2D, TechnoRules, Tile } from "@chronodivide/game-api";
1
+ import { GameApi, PlayerData, TechnoRules } from "@chronodivide/game-api";
2
2
  import { GlobalThreat } from "../threat/threat.js";
3
- import { BasicBuilding } from "./basicBuilding.js";
4
3
  import { BasicGroundUnit } from "./basicGroundUnit.js";
5
4
 
6
5
  const IDEAL_HARVESTERS_PER_REFINERY = 2;
7
6
 
8
7
  export class Harvester extends BasicGroundUnit {
9
- constructor(basePriority: number, baseAmount: number, private minNeeded: number) {
8
+ constructor(
9
+ basePriority: number,
10
+ baseAmount: number,
11
+ private minNeeded: number,
12
+ ) {
10
13
  super(basePriority, baseAmount, 0, 0);
11
14
  }
12
15
 
@@ -15,7 +18,7 @@ export class Harvester extends BasicGroundUnit {
15
18
  game: GameApi,
16
19
  playerData: PlayerData,
17
20
  technoRules: TechnoRules,
18
- threatCache: GlobalThreat | null
21
+ threatCache: GlobalThreat | null,
19
22
  ): number {
20
23
  const refineries = game.getVisibleUnits(playerData.name, "self", (r) => r.refinery).length;
21
24
  const harvesters = game.getVisibleUnits(playerData.name, "self", (r) => r.harvester).length;
@@ -1,5 +1,5 @@
1
1
  import { GameApi, PlayerData, TechnoRules } from "@chronodivide/game-api";
2
- import { AiBuildingRules, getDefaultPlacementLocation } from "./building.js";
2
+ import { AiBuildingRules, getDefaultPlacementLocation } from "./buildingRules.js";
3
3
  import { GlobalThreat } from "../threat/threat.js";
4
4
 
5
5
  export class PowerPlant implements AiBuildingRules {
@@ -13,7 +13,7 @@ import {
13
13
  BUILDING_NAME_TO_RULES,
14
14
  DEFAULT_BUILDING_PRIORITY,
15
15
  getDefaultPlacementLocation,
16
- } from "./building.js";
16
+ } from "./buildingRules.js";
17
17
 
18
18
  export const QUEUES = [
19
19
  QueueType.Structures,
@@ -1,12 +1,8 @@
1
- import { GameApi, PlayerData, Point2D, TechnoRules, Tile } from "@chronodivide/game-api";
1
+ import { GameApi, GameMath, PlayerData, TechnoRules, Tile } from "@chronodivide/game-api";
2
2
  import { GlobalThreat } from "../threat/threat.js";
3
3
  import { BasicBuilding } from "./basicBuilding.js";
4
- import {
5
- AiBuildingRules,
6
- getDefaultPlacementLocation,
7
- numBuildingsOwnedOfName,
8
- numBuildingsOwnedOfType,
9
- } from "./building.js";
4
+ import { getDefaultPlacementLocation } from "./buildingRules.js";
5
+ import { Vector2 } from "three";
10
6
 
11
7
  export class ResourceCollectionBuilding extends BasicBuilding {
12
8
  constructor(basePriority: number, maxNeeded: number, onlyBuildWhenFloatingCreditsAmount?: number) {
@@ -16,7 +12,7 @@ export class ResourceCollectionBuilding extends BasicBuilding {
16
12
  getPlacementLocation(
17
13
  game: GameApi,
18
14
  playerData: PlayerData,
19
- technoRules: TechnoRules
15
+ technoRules: TechnoRules,
20
16
  ): { rx: number; ry: number } | undefined {
21
17
  // Prefer spawning close to ore.
22
18
  let selectedLocation = playerData.startLocation;
@@ -27,9 +23,9 @@ export class ResourceCollectionBuilding extends BasicBuilding {
27
23
  for (let i = 0; i < allTileResourceData.length; ++i) {
28
24
  let tileResourceData = allTileResourceData[i];
29
25
  if (tileResourceData.spawnsOre) {
30
- let dist = Math.sqrt(
26
+ let dist = GameMath.sqrt(
31
27
  (selectedLocation.x - tileResourceData.tile.rx) ** 2 +
32
- (selectedLocation.y - tileResourceData.tile.ry) ** 2
28
+ (selectedLocation.y - tileResourceData.tile.ry) ** 2,
33
29
  );
34
30
  if (closeOreDist == undefined || dist < closeOreDist) {
35
31
  closeOreDist = dist;
@@ -38,7 +34,7 @@ export class ResourceCollectionBuilding extends BasicBuilding {
38
34
  }
39
35
  }
40
36
  if (closeOre) {
41
- selectedLocation = { x: closeOre.rx, y: closeOre.ry };
37
+ selectedLocation = new Vector2(closeOre.rx, closeOre.ry);
42
38
  }
43
39
  return getDefaultPlacementLocation(game, playerData, selectedLocation, technoRules);
44
40
  }
@@ -48,7 +44,7 @@ export class ResourceCollectionBuilding extends BasicBuilding {
48
44
  game: GameApi,
49
45
  playerData: PlayerData,
50
46
  technoRules: TechnoRules,
51
- threatCache: GlobalThreat | null
47
+ threatCache: GlobalThreat | null,
52
48
  ): number | null {
53
49
  const harvesters = game.getVisibleUnits(playerData.name, "self", (r) => r.harvester).length;
54
50
  return Math.max(1, harvesters * 2);