@supalosa/chronodivide-bot 0.5.3 → 0.6.4

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 (134) hide show
  1. package/.env.template +4 -4
  2. package/.github/workflows/npm-publish.yml +24 -0
  3. package/README.md +108 -97
  4. package/dist/bot/bot.js +105 -105
  5. package/dist/bot/bot.js.map +1 -1
  6. package/dist/bot/logic/awareness.js +136 -136
  7. package/dist/bot/logic/building/antiAirStaticDefence.js +42 -42
  8. package/dist/bot/logic/building/antiGroundStaticDefence.js +34 -30
  9. package/dist/bot/logic/building/antiGroundStaticDefence.js.map +1 -1
  10. package/dist/bot/logic/building/{ArtilleryUnit.js → artilleryUnit.js} +18 -18
  11. package/dist/bot/logic/building/basicAirUnit.js +19 -19
  12. package/dist/bot/logic/building/basicBuilding.js +26 -26
  13. package/dist/bot/logic/building/basicGroundUnit.js +19 -19
  14. package/dist/bot/logic/building/buildingRules.js +175 -174
  15. package/dist/bot/logic/building/buildingRules.js.map +1 -1
  16. package/dist/bot/logic/building/common.js +19 -18
  17. package/dist/bot/logic/building/common.js.map +1 -1
  18. package/dist/bot/logic/building/harvester.js +16 -16
  19. package/dist/bot/logic/building/powerPlant.js +20 -20
  20. package/dist/bot/logic/building/queueController.js +183 -183
  21. package/dist/bot/logic/building/resourceCollectionBuilding.js +36 -36
  22. package/dist/bot/logic/common/scout.js +126 -126
  23. package/dist/bot/logic/common/utils.js +95 -85
  24. package/dist/bot/logic/common/utils.js.map +1 -1
  25. package/dist/bot/logic/composition/alliedCompositions.js +12 -12
  26. package/dist/bot/logic/composition/common.js +1 -1
  27. package/dist/bot/logic/composition/sovietCompositions.js +12 -12
  28. package/dist/bot/logic/map/map.js +44 -44
  29. package/dist/bot/logic/map/sector.js +137 -137
  30. package/dist/bot/logic/mission/actionBatcher.js +91 -91
  31. package/dist/bot/logic/mission/mission.js +122 -122
  32. package/dist/bot/logic/mission/missionController.js +321 -321
  33. package/dist/bot/logic/mission/missionFactories.js +12 -12
  34. package/dist/bot/logic/mission/missions/attackMission.js +214 -214
  35. package/dist/bot/logic/mission/missions/defenceMission.js +82 -82
  36. package/dist/bot/logic/mission/missions/engineerMission.js +63 -63
  37. package/dist/bot/logic/mission/missions/expansionMission.js +60 -60
  38. package/dist/bot/logic/mission/missions/retreatMission.js +33 -33
  39. package/dist/bot/logic/mission/missions/scoutingMission.js +133 -133
  40. package/dist/bot/logic/mission/missions/squads/combatSquad.js +115 -115
  41. package/dist/bot/logic/mission/missions/squads/common.js +57 -57
  42. package/dist/bot/logic/mission/missions/squads/squad.js +1 -1
  43. package/dist/bot/logic/threat/threat.js +22 -22
  44. package/dist/bot/logic/threat/threatCalculator.js +73 -73
  45. package/dist/exampleBot.js +100 -112
  46. package/dist/exampleBot.js.map +1 -1
  47. package/package.json +32 -29
  48. package/src/bot/bot.ts +161 -161
  49. package/src/bot/logic/awareness.ts +245 -245
  50. package/src/bot/logic/building/antiAirStaticDefence.ts +64 -64
  51. package/src/bot/logic/building/antiGroundStaticDefence.ts +55 -51
  52. package/src/bot/logic/building/artilleryUnit.ts +39 -39
  53. package/src/bot/logic/building/basicAirUnit.ts +39 -39
  54. package/src/bot/logic/building/basicBuilding.ts +49 -49
  55. package/src/bot/logic/building/basicGroundUnit.ts +39 -39
  56. package/src/bot/logic/building/buildingRules.ts +250 -247
  57. package/src/bot/logic/building/common.ts +21 -23
  58. package/src/bot/logic/building/harvester.ts +31 -31
  59. package/src/bot/logic/building/powerPlant.ts +32 -32
  60. package/src/bot/logic/building/queueController.ts +297 -297
  61. package/src/bot/logic/building/resourceCollectionBuilding.ts +52 -52
  62. package/src/bot/logic/common/scout.ts +183 -183
  63. package/src/bot/logic/common/utils.ts +120 -112
  64. package/src/bot/logic/composition/alliedCompositions.ts +22 -22
  65. package/src/bot/logic/composition/common.ts +3 -3
  66. package/src/bot/logic/composition/sovietCompositions.ts +21 -21
  67. package/src/bot/logic/map/map.ts +66 -66
  68. package/src/bot/logic/map/sector.ts +174 -174
  69. package/src/bot/logic/mission/actionBatcher.ts +124 -124
  70. package/src/bot/logic/mission/mission.ts +232 -232
  71. package/src/bot/logic/mission/missionController.ts +413 -413
  72. package/src/bot/logic/mission/missionFactories.ts +51 -51
  73. package/src/bot/logic/mission/missions/attackMission.ts +336 -336
  74. package/src/bot/logic/mission/missions/defenceMission.ts +151 -151
  75. package/src/bot/logic/mission/missions/engineerMission.ts +113 -113
  76. package/src/bot/logic/mission/missions/expansionMission.ts +104 -104
  77. package/src/bot/logic/mission/missions/retreatMission.ts +54 -54
  78. package/src/bot/logic/mission/missions/scoutingMission.ts +186 -186
  79. package/src/bot/logic/mission/missions/squads/combatSquad.ts +160 -160
  80. package/src/bot/logic/mission/missions/squads/common.ts +63 -63
  81. package/src/bot/logic/mission/missions/squads/squad.ts +19 -19
  82. package/src/bot/logic/threat/threatCalculator.ts +100 -100
  83. package/src/exampleBot.ts +111 -124
  84. package/tsconfig.json +73 -73
  85. package/dist/bot/logic/building/building.js +0 -82
  86. package/dist/bot/logic/building/massedAntiGroundUnit.js +0 -20
  87. package/dist/bot/logic/building/queues.js +0 -19
  88. package/dist/bot/logic/knowledge.js +0 -1
  89. package/dist/bot/logic/mission/basicMission.js +0 -26
  90. package/dist/bot/logic/mission/behaviours/combatSquad.js +0 -124
  91. package/dist/bot/logic/mission/behaviours/combatSquad.js.map +0 -1
  92. package/dist/bot/logic/mission/behaviours/common.js +0 -56
  93. package/dist/bot/logic/mission/behaviours/common.js.map +0 -1
  94. package/dist/bot/logic/mission/behaviours/engineerSquad.js +0 -39
  95. package/dist/bot/logic/mission/behaviours/engineerSquad.js.map +0 -1
  96. package/dist/bot/logic/mission/behaviours/expansionSquad.js +0 -46
  97. package/dist/bot/logic/mission/behaviours/expansionSquad.js.map +0 -1
  98. package/dist/bot/logic/mission/behaviours/retreatSquad.js +0 -31
  99. package/dist/bot/logic/mission/behaviours/retreatSquad.js.map +0 -1
  100. package/dist/bot/logic/mission/behaviours/scoutingSquad.js +0 -94
  101. package/dist/bot/logic/mission/behaviours/scoutingSquad.js.map +0 -1
  102. package/dist/bot/logic/mission/expansionMission.js +0 -32
  103. package/dist/bot/logic/mission/missions/basicMission.js +0 -13
  104. package/dist/bot/logic/mission/missions/basicMission.js.map +0 -1
  105. package/dist/bot/logic/mission/missions/missionBehaviour.js +0 -2
  106. package/dist/bot/logic/mission/missions/missionBehaviour.js.map +0 -1
  107. package/dist/bot/logic/mission/missions/oneTimeMission.js +0 -27
  108. package/dist/bot/logic/mission/missions/oneTimeMission.js.map +0 -1
  109. package/dist/bot/logic/squad/behaviours/actionBatcher.js +0 -36
  110. package/dist/bot/logic/squad/behaviours/actionBatcher.js.map +0 -1
  111. package/dist/bot/logic/squad/behaviours/attackSquad.js +0 -82
  112. package/dist/bot/logic/squad/behaviours/combatSquad.js +0 -106
  113. package/dist/bot/logic/squad/behaviours/combatSquad.js.map +0 -1
  114. package/dist/bot/logic/squad/behaviours/common.js +0 -55
  115. package/dist/bot/logic/squad/behaviours/common.js.map +0 -1
  116. package/dist/bot/logic/squad/behaviours/defenceSquad.js +0 -48
  117. package/dist/bot/logic/squad/behaviours/engineerSquad.js +0 -38
  118. package/dist/bot/logic/squad/behaviours/engineerSquad.js.map +0 -1
  119. package/dist/bot/logic/squad/behaviours/expansionSquad.js +0 -45
  120. package/dist/bot/logic/squad/behaviours/expansionSquad.js.map +0 -1
  121. package/dist/bot/logic/squad/behaviours/retreatSquad.js +0 -31
  122. package/dist/bot/logic/squad/behaviours/retreatSquad.js.map +0 -1
  123. package/dist/bot/logic/squad/behaviours/scoutingSquad.js +0 -93
  124. package/dist/bot/logic/squad/behaviours/scoutingSquad.js.map +0 -1
  125. package/dist/bot/logic/squad/behaviours/squadExpansion.js +0 -31
  126. package/dist/bot/logic/squad/behaviours/squadScouters.js +0 -8
  127. package/dist/bot/logic/squad/squad.js +0 -126
  128. package/dist/bot/logic/squad/squad.js.map +0 -1
  129. package/dist/bot/logic/squad/squadBehaviour.js +0 -6
  130. package/dist/bot/logic/squad/squadBehaviour.js.map +0 -1
  131. package/dist/bot/logic/squad/squadBehaviours.js +0 -7
  132. package/dist/bot/logic/squad/squadBehaviours.js.map +0 -1
  133. package/dist/bot/logic/squad/squadController.js +0 -215
  134. package/dist/bot/logic/squad/squadController.js.map +0 -1
@@ -1,64 +1,64 @@
1
- import { OrderType } from "@chronodivide/game-api";
2
- import { Mission, disbandMission, noop, requestUnits } from "../mission.js";
3
- const CAPTURE_COOLDOWN_TICKS = 30;
4
- /**
5
- * A mission that tries to send an engineer into a building (e.g. to capture tech building or repair bridge)
6
- */
7
- export class EngineerMission extends Mission {
8
- constructor(uniqueName, priority, captureTargetId, logger) {
9
- super(uniqueName, logger);
10
- this.priority = priority;
11
- this.captureTargetId = captureTargetId;
12
- this.hasAttemptedCaptureWith = null;
13
- }
14
- _onAiUpdate(gameApi, actionsApi, playerData, matchAwareness, actionBatcher) {
15
- const engineerTypes = ["ENGINEER", "SENGINEER"];
16
- const engineers = this.getUnitsOfTypes(gameApi, ...engineerTypes);
17
- if (engineers.length === 0) {
18
- // Perhaps we deployed already (or the unit was destroyed), end the mission.
19
- if (this.hasAttemptedCaptureWith !== null) {
20
- return disbandMission();
21
- }
22
- return requestUnits(engineerTypes, this.priority);
23
- }
24
- else if (!this.hasAttemptedCaptureWith ||
25
- gameApi.getCurrentTick() > this.hasAttemptedCaptureWith.gameTick + CAPTURE_COOLDOWN_TICKS) {
26
- actionsApi.orderUnits(engineers.map((engineer) => engineer.id), OrderType.Capture, this.captureTargetId);
27
- // Add a cooldown to deploy attempts.
28
- this.hasAttemptedCaptureWith = {
29
- unitId: engineers[0].id,
30
- gameTick: gameApi.getCurrentTick(),
31
- };
32
- }
33
- return noop();
34
- }
35
- getGlobalDebugText() {
36
- return undefined;
37
- }
38
- getPriority() {
39
- return this.priority;
40
- }
41
- }
42
- // Only try to capture tech buildings within this radius of the starting point.
43
- const MAX_TECH_CAPTURE_RADIUS = 50;
44
- const TECH_CHECK_INTERVAL_TICKS = 300;
45
- export class EngineerMissionFactory {
46
- constructor() {
47
- this.lastCheckAt = 0;
48
- }
49
- getName() {
50
- return "EngineerMissionFactory";
51
- }
52
- maybeCreateMissions(gameApi, playerData, matchAwareness, missionController, logger) {
53
- if (!(gameApi.getCurrentTick() > this.lastCheckAt + TECH_CHECK_INTERVAL_TICKS)) {
54
- return;
55
- }
56
- this.lastCheckAt = gameApi.getCurrentTick();
57
- const eligibleTechBuildings = gameApi.getVisibleUnits(playerData.name, "hostile", (r) => r.capturable && r.produceCashAmount > 0);
58
- eligibleTechBuildings.forEach((techBuildingId) => {
59
- missionController.addMission(new EngineerMission("capture-" + techBuildingId, 100, techBuildingId, logger));
60
- });
61
- }
62
- onMissionFailed(gameApi, playerData, matchAwareness, failedMission, failureReason, missionController) { }
63
- }
1
+ import { OrderType } from "@chronodivide/game-api";
2
+ import { Mission, disbandMission, noop, requestUnits } from "../mission.js";
3
+ const CAPTURE_COOLDOWN_TICKS = 30;
4
+ /**
5
+ * A mission that tries to send an engineer into a building (e.g. to capture tech building or repair bridge)
6
+ */
7
+ export class EngineerMission extends Mission {
8
+ constructor(uniqueName, priority, captureTargetId, logger) {
9
+ super(uniqueName, logger);
10
+ this.priority = priority;
11
+ this.captureTargetId = captureTargetId;
12
+ this.hasAttemptedCaptureWith = null;
13
+ }
14
+ _onAiUpdate(gameApi, actionsApi, playerData, matchAwareness, actionBatcher) {
15
+ const engineerTypes = ["ENGINEER", "SENGINEER"];
16
+ const engineers = this.getUnitsOfTypes(gameApi, ...engineerTypes);
17
+ if (engineers.length === 0) {
18
+ // Perhaps we deployed already (or the unit was destroyed), end the mission.
19
+ if (this.hasAttemptedCaptureWith !== null) {
20
+ return disbandMission();
21
+ }
22
+ return requestUnits(engineerTypes, this.priority);
23
+ }
24
+ else if (!this.hasAttemptedCaptureWith ||
25
+ gameApi.getCurrentTick() > this.hasAttemptedCaptureWith.gameTick + CAPTURE_COOLDOWN_TICKS) {
26
+ actionsApi.orderUnits(engineers.map((engineer) => engineer.id), OrderType.Capture, this.captureTargetId);
27
+ // Add a cooldown to deploy attempts.
28
+ this.hasAttemptedCaptureWith = {
29
+ unitId: engineers[0].id,
30
+ gameTick: gameApi.getCurrentTick(),
31
+ };
32
+ }
33
+ return noop();
34
+ }
35
+ getGlobalDebugText() {
36
+ return undefined;
37
+ }
38
+ getPriority() {
39
+ return this.priority;
40
+ }
41
+ }
42
+ // Only try to capture tech buildings within this radius of the starting point.
43
+ const MAX_TECH_CAPTURE_RADIUS = 50;
44
+ const TECH_CHECK_INTERVAL_TICKS = 300;
45
+ export class EngineerMissionFactory {
46
+ constructor() {
47
+ this.lastCheckAt = 0;
48
+ }
49
+ getName() {
50
+ return "EngineerMissionFactory";
51
+ }
52
+ maybeCreateMissions(gameApi, playerData, matchAwareness, missionController, logger) {
53
+ if (!(gameApi.getCurrentTick() > this.lastCheckAt + TECH_CHECK_INTERVAL_TICKS)) {
54
+ return;
55
+ }
56
+ this.lastCheckAt = gameApi.getCurrentTick();
57
+ const eligibleTechBuildings = gameApi.getVisibleUnits(playerData.name, "hostile", (r) => r.capturable && r.produceCashAmount > 0);
58
+ eligibleTechBuildings.forEach((techBuildingId) => {
59
+ missionController.addMission(new EngineerMission("capture-" + techBuildingId, 100, techBuildingId, logger));
60
+ });
61
+ }
62
+ onMissionFailed(gameApi, playerData, matchAwareness, failedMission, failureReason, missionController) { }
63
+ }
64
64
  //# sourceMappingURL=engineerMission.js.map
@@ -1,61 +1,61 @@
1
- import { OrderType } from "@chronodivide/game-api";
2
- import { Mission, disbandMission, noop, requestSpecificUnits, requestUnits } from "../mission.js";
3
- const DEPLOY_COOLDOWN_TICKS = 30;
4
- /**
5
- * A mission that tries to create an MCV (if it doesn't exist) and deploy it somewhere it can be deployed.
6
- */
7
- export class ExpansionMission extends Mission {
8
- constructor(uniqueName, priority, selectedMcv, logger) {
9
- super(uniqueName, logger);
10
- this.priority = priority;
11
- this.selectedMcv = selectedMcv;
12
- this.hasAttemptedDeployWith = null;
13
- }
14
- _onAiUpdate(gameApi, actionsApi, playerData, matchAwareness, actionBatcher) {
15
- const mcvTypes = ["AMCV", "SMCV"];
16
- const mcvs = this.getUnitsOfTypes(gameApi, ...mcvTypes);
17
- if (mcvs.length === 0) {
18
- // Perhaps we deployed already (or the unit was destroyed), end the mission.
19
- if (this.hasAttemptedDeployWith !== null) {
20
- return disbandMission();
21
- }
22
- // We need an mcv!
23
- if (this.selectedMcv) {
24
- return requestSpecificUnits([this.selectedMcv], this.priority);
25
- }
26
- else {
27
- return requestUnits(mcvTypes, this.priority);
28
- }
29
- }
30
- else if (!this.hasAttemptedDeployWith ||
31
- gameApi.getCurrentTick() > this.hasAttemptedDeployWith.gameTick + DEPLOY_COOLDOWN_TICKS) {
32
- actionsApi.orderUnits(mcvs.map((mcv) => mcv.id), OrderType.DeploySelected);
33
- // Add a cooldown to deploy attempts.
34
- this.hasAttemptedDeployWith = {
35
- unitId: mcvs[0].id,
36
- gameTick: gameApi.getCurrentTick(),
37
- };
38
- }
39
- return noop();
40
- }
41
- getGlobalDebugText() {
42
- return `Expand with MCV ${this.selectedMcv}`;
43
- }
44
- getPriority() {
45
- return this.priority;
46
- }
47
- }
48
- export class ExpansionMissionFactory {
49
- getName() {
50
- return "ExpansionMissionFactory";
51
- }
52
- maybeCreateMissions(gameApi, playerData, matchAwareness, missionController, logger) {
53
- // At this point, only expand if we have a loose MCV.
54
- const mcvs = gameApi.getVisibleUnits(playerData.name, "self", (r) => gameApi.getGeneralRules().baseUnit.includes(r.name));
55
- mcvs.forEach((mcv) => {
56
- missionController.addMission(new ExpansionMission("expand-with-" + mcv, 100, mcv, logger));
57
- });
58
- }
59
- onMissionFailed(gameApi, playerData, matchAwareness, failedMission, failureReason, missionController) { }
60
- }
1
+ import { OrderType } from "@chronodivide/game-api";
2
+ import { Mission, disbandMission, noop, requestSpecificUnits, requestUnits } from "../mission.js";
3
+ const DEPLOY_COOLDOWN_TICKS = 30;
4
+ /**
5
+ * A mission that tries to create an MCV (if it doesn't exist) and deploy it somewhere it can be deployed.
6
+ */
7
+ export class ExpansionMission extends Mission {
8
+ constructor(uniqueName, priority, selectedMcv, logger) {
9
+ super(uniqueName, logger);
10
+ this.priority = priority;
11
+ this.selectedMcv = selectedMcv;
12
+ this.hasAttemptedDeployWith = null;
13
+ }
14
+ _onAiUpdate(gameApi, actionsApi, playerData, matchAwareness, actionBatcher) {
15
+ const mcvTypes = ["AMCV", "SMCV"];
16
+ const mcvs = this.getUnitsOfTypes(gameApi, ...mcvTypes);
17
+ if (mcvs.length === 0) {
18
+ // Perhaps we deployed already (or the unit was destroyed), end the mission.
19
+ if (this.hasAttemptedDeployWith !== null) {
20
+ return disbandMission();
21
+ }
22
+ // We need an mcv!
23
+ if (this.selectedMcv) {
24
+ return requestSpecificUnits([this.selectedMcv], this.priority);
25
+ }
26
+ else {
27
+ return requestUnits(mcvTypes, this.priority);
28
+ }
29
+ }
30
+ else if (!this.hasAttemptedDeployWith ||
31
+ gameApi.getCurrentTick() > this.hasAttemptedDeployWith.gameTick + DEPLOY_COOLDOWN_TICKS) {
32
+ actionsApi.orderUnits(mcvs.map((mcv) => mcv.id), OrderType.DeploySelected);
33
+ // Add a cooldown to deploy attempts.
34
+ this.hasAttemptedDeployWith = {
35
+ unitId: mcvs[0].id,
36
+ gameTick: gameApi.getCurrentTick(),
37
+ };
38
+ }
39
+ return noop();
40
+ }
41
+ getGlobalDebugText() {
42
+ return `Expand with MCV ${this.selectedMcv}`;
43
+ }
44
+ getPriority() {
45
+ return this.priority;
46
+ }
47
+ }
48
+ export class ExpansionMissionFactory {
49
+ getName() {
50
+ return "ExpansionMissionFactory";
51
+ }
52
+ maybeCreateMissions(gameApi, playerData, matchAwareness, missionController, logger) {
53
+ // At this point, only expand if we have a loose MCV.
54
+ const mcvs = gameApi.getVisibleUnits(playerData.name, "self", (r) => gameApi.getGeneralRules().baseUnit.includes(r.name));
55
+ mcvs.forEach((mcv) => {
56
+ missionController.addMission(new ExpansionMission("expand-with-" + mcv, 100, mcv, logger));
57
+ });
58
+ }
59
+ onMissionFailed(gameApi, playerData, matchAwareness, failedMission, failureReason, missionController) { }
60
+ }
61
61
  //# sourceMappingURL=expansionMission.js.map
@@ -1,34 +1,34 @@
1
- import { OrderType } from "@chronodivide/game-api";
2
- import { Mission, disbandMission, requestSpecificUnits } from "../mission.js";
3
- export class RetreatMission extends Mission {
4
- constructor(uniqueName, retreatToPoint, withUnitIds, logger) {
5
- super(uniqueName, logger);
6
- this.retreatToPoint = retreatToPoint;
7
- this.withUnitIds = withUnitIds;
8
- this.createdAt = null;
9
- }
10
- _onAiUpdate(gameApi, actionsApi, playerData, matchAwareness, actionBatcher) {
11
- if (!this.createdAt) {
12
- this.createdAt = gameApi.getCurrentTick();
13
- }
14
- if (this.getUnitIds().length > 0) {
15
- // Only send the order once we have managed to claim some units.
16
- actionsApi.orderUnits(this.getUnitIds(), OrderType.AttackMove, this.retreatToPoint.x, this.retreatToPoint.y);
17
- return disbandMission();
18
- }
19
- if (this.createdAt && gameApi.getCurrentTick() > this.createdAt + 240) {
20
- // Disband automatically after 240 ticks in case we couldn't actually claim any units.
21
- return disbandMission();
22
- }
23
- else {
24
- return requestSpecificUnits(this.withUnitIds, 1000);
25
- }
26
- }
27
- getGlobalDebugText() {
28
- return `retreat with ${this.withUnitIds.length} units`;
29
- }
30
- getPriority() {
31
- return 100;
32
- }
33
- }
1
+ import { OrderType } from "@chronodivide/game-api";
2
+ import { Mission, disbandMission, requestSpecificUnits } from "../mission.js";
3
+ export class RetreatMission extends Mission {
4
+ constructor(uniqueName, retreatToPoint, withUnitIds, logger) {
5
+ super(uniqueName, logger);
6
+ this.retreatToPoint = retreatToPoint;
7
+ this.withUnitIds = withUnitIds;
8
+ this.createdAt = null;
9
+ }
10
+ _onAiUpdate(gameApi, actionsApi, playerData, matchAwareness, actionBatcher) {
11
+ if (!this.createdAt) {
12
+ this.createdAt = gameApi.getCurrentTick();
13
+ }
14
+ if (this.getUnitIds().length > 0) {
15
+ // Only send the order once we have managed to claim some units.
16
+ actionsApi.orderUnits(this.getUnitIds(), OrderType.AttackMove, this.retreatToPoint.x, this.retreatToPoint.y);
17
+ return disbandMission();
18
+ }
19
+ if (this.createdAt && gameApi.getCurrentTick() > this.createdAt + 240) {
20
+ // Disband automatically after 240 ticks in case we couldn't actually claim any units.
21
+ return disbandMission();
22
+ }
23
+ else {
24
+ return requestSpecificUnits(this.withUnitIds, 1000);
25
+ }
26
+ }
27
+ getGlobalDebugText() {
28
+ return `retreat with ${this.withUnitIds.length} units`;
29
+ }
30
+ getPriority() {
31
+ return 100;
32
+ }
33
+ }
34
34
  //# sourceMappingURL=retreatMission.js.map
@@ -1,134 +1,134 @@
1
- import { OrderType } from "@chronodivide/game-api";
2
- import { Mission, disbandMission, noop, requestUnits } from "../mission.js";
3
- import { AttackMission } from "./attackMission.js";
4
- import { getDistanceBetweenTileAndPoint } from "../../map/map.js";
5
- const SCOUT_MOVE_COOLDOWN_TICKS = 30;
6
- // Max units to spend on a particular scout target.
7
- const MAX_ATTEMPTS_PER_TARGET = 5;
8
- // Maximum ticks to spend trying to scout a target *without making progress towards it*.
9
- // Every time a unit gets closer to the target, the timer refreshes.
10
- const MAX_TICKS_PER_TARGET = 600;
11
- /**
12
- * A mission that tries to scout around the map with a cheap, fast unit (usually attack dogs)
13
- */
14
- export class ScoutingMission extends Mission {
15
- constructor(uniqueName, priority, logger) {
16
- super(uniqueName, logger);
17
- this.priority = priority;
18
- this.scoutTarget = null;
19
- this.attemptsOnCurrentTarget = 0;
20
- this.scoutTargetRefreshedAt = 0;
21
- this.lastMoveCommandTick = 0;
22
- this.scoutTargetIsPermanent = false;
23
- this.hadUnit = false;
24
- }
25
- _onAiUpdate(gameApi, actionsApi, playerData, matchAwareness, actionBatcher) {
26
- const scoutNames = ["ADOG", "DOG", "E1", "E2", "FV", "HTK"];
27
- const scouts = this.getUnitsOfTypes(gameApi, ...scoutNames);
28
- if ((matchAwareness.getSectorCache().getOverallVisibility() || 0) > 0.9) {
29
- return disbandMission();
30
- }
31
- if (scouts.length === 0) {
32
- // Count the number of times the scout dies trying to uncover the current scoutTarget.
33
- if (this.scoutTarget && this.hadUnit) {
34
- this.attemptsOnCurrentTarget++;
35
- this.hadUnit = false;
36
- }
37
- return requestUnits(scoutNames, this.priority);
38
- }
39
- else if (this.scoutTarget) {
40
- this.hadUnit = true;
41
- if (!this.scoutTargetIsPermanent) {
42
- if (this.attemptsOnCurrentTarget > MAX_ATTEMPTS_PER_TARGET) {
43
- this.logger(`Scout target ${this.scoutTarget.x},${this.scoutTarget.y} took too many attempts, moving to next`);
44
- this.setScoutTarget(null, 0);
45
- return noop();
46
- }
47
- if (gameApi.getCurrentTick() > this.scoutTargetRefreshedAt + MAX_TICKS_PER_TARGET) {
48
- this.logger(`Scout target ${this.scoutTarget.x},${this.scoutTarget.y} took too long, moving to next`);
49
- this.setScoutTarget(null, 0);
50
- return noop();
51
- }
52
- }
53
- const targetTile = gameApi.mapApi.getTile(this.scoutTarget.x, this.scoutTarget.y);
54
- if (!targetTile) {
55
- throw new Error(`target tile ${this.scoutTarget.x},${this.scoutTarget.y} does not exist`);
56
- }
57
- if (gameApi.getCurrentTick() > this.lastMoveCommandTick + SCOUT_MOVE_COOLDOWN_TICKS) {
58
- this.lastMoveCommandTick = gameApi.getCurrentTick();
59
- scouts.forEach((unit) => {
60
- if (this.scoutTarget) {
61
- actionsApi.orderUnits([unit.id], OrderType.AttackMove, this.scoutTarget.x, this.scoutTarget.y);
62
- }
63
- });
64
- // Check that a scout is actually moving closer to the target.
65
- const distances = scouts.map((unit) => getDistanceBetweenTileAndPoint(unit.tile, this.scoutTarget));
66
- const newMinDistance = Math.min(...distances);
67
- if (!this.scoutMinDistance || newMinDistance < this.scoutMinDistance) {
68
- this.logger(`Scout timeout refreshed because unit moved closer to point (${newMinDistance} < ${this.scoutMinDistance})`);
69
- this.scoutTargetRefreshedAt = gameApi.getCurrentTick();
70
- this.scoutMinDistance = newMinDistance;
71
- }
72
- }
73
- if (gameApi.mapApi.isVisibleTile(targetTile, playerData.name)) {
74
- this.logger(`Scout target ${this.scoutTarget.x},${this.scoutTarget.y} successfully scouted, moving to next`);
75
- this.setScoutTarget(null, gameApi.getCurrentTick());
76
- }
77
- }
78
- else {
79
- const nextScoutTarget = matchAwareness.getScoutingManager().getNewScoutTarget();
80
- if (!nextScoutTarget) {
81
- this.logger(`No more scouting targets available, disbanding.`);
82
- return disbandMission();
83
- }
84
- this.setScoutTarget(nextScoutTarget, gameApi.getCurrentTick());
85
- }
86
- return noop();
87
- }
88
- setScoutTarget(target, currentTick) {
89
- this.attemptsOnCurrentTarget = 0;
90
- this.scoutTargetRefreshedAt = currentTick;
91
- this.scoutTarget = target?.asVector2() ?? null;
92
- this.scoutMinDistance = undefined;
93
- this.scoutTargetIsPermanent = target?.isPermanent ?? false;
94
- }
95
- getGlobalDebugText() {
96
- return "scouting";
97
- }
98
- getPriority() {
99
- return this.priority;
100
- }
101
- }
102
- const SCOUT_COOLDOWN_TICKS = 300;
103
- export class ScoutingMissionFactory {
104
- constructor(lastScoutAt = -SCOUT_COOLDOWN_TICKS) {
105
- this.lastScoutAt = lastScoutAt;
106
- }
107
- getName() {
108
- return "ScoutingMissionFactory";
109
- }
110
- maybeCreateMissions(gameApi, playerData, matchAwareness, missionController, logger) {
111
- if (gameApi.getCurrentTick() < this.lastScoutAt + SCOUT_COOLDOWN_TICKS) {
112
- return;
113
- }
114
- if (!matchAwareness.getScoutingManager().hasScoutTargets()) {
115
- return;
116
- }
117
- if (!missionController.addMission(new ScoutingMission("globalScout", 10, logger))) {
118
- this.lastScoutAt = gameApi.getCurrentTick();
119
- }
120
- }
121
- onMissionFailed(gameApi, playerData, matchAwareness, failedMission, failureReason, missionController, logger) {
122
- if (gameApi.getCurrentTick() < this.lastScoutAt + SCOUT_COOLDOWN_TICKS) {
123
- return;
124
- }
125
- if (!matchAwareness.getScoutingManager().hasScoutTargets()) {
126
- return;
127
- }
128
- if (failedMission instanceof AttackMission) {
129
- missionController.addMission(new ScoutingMission("globalScout", 10, logger));
130
- this.lastScoutAt = gameApi.getCurrentTick();
131
- }
132
- }
133
- }
1
+ import { OrderType } from "@chronodivide/game-api";
2
+ import { Mission, disbandMission, noop, requestUnits } from "../mission.js";
3
+ import { AttackMission } from "./attackMission.js";
4
+ import { getDistanceBetweenTileAndPoint } from "../../map/map.js";
5
+ const SCOUT_MOVE_COOLDOWN_TICKS = 30;
6
+ // Max units to spend on a particular scout target.
7
+ const MAX_ATTEMPTS_PER_TARGET = 5;
8
+ // Maximum ticks to spend trying to scout a target *without making progress towards it*.
9
+ // Every time a unit gets closer to the target, the timer refreshes.
10
+ const MAX_TICKS_PER_TARGET = 600;
11
+ /**
12
+ * A mission that tries to scout around the map with a cheap, fast unit (usually attack dogs)
13
+ */
14
+ export class ScoutingMission extends Mission {
15
+ constructor(uniqueName, priority, logger) {
16
+ super(uniqueName, logger);
17
+ this.priority = priority;
18
+ this.scoutTarget = null;
19
+ this.attemptsOnCurrentTarget = 0;
20
+ this.scoutTargetRefreshedAt = 0;
21
+ this.lastMoveCommandTick = 0;
22
+ this.scoutTargetIsPermanent = false;
23
+ this.hadUnit = false;
24
+ }
25
+ _onAiUpdate(gameApi, actionsApi, playerData, matchAwareness, actionBatcher) {
26
+ const scoutNames = ["ADOG", "DOG", "E1", "E2", "FV", "HTK"];
27
+ const scouts = this.getUnitsOfTypes(gameApi, ...scoutNames);
28
+ if ((matchAwareness.getSectorCache().getOverallVisibility() || 0) > 0.9) {
29
+ return disbandMission();
30
+ }
31
+ if (scouts.length === 0) {
32
+ // Count the number of times the scout dies trying to uncover the current scoutTarget.
33
+ if (this.scoutTarget && this.hadUnit) {
34
+ this.attemptsOnCurrentTarget++;
35
+ this.hadUnit = false;
36
+ }
37
+ return requestUnits(scoutNames, this.priority);
38
+ }
39
+ else if (this.scoutTarget) {
40
+ this.hadUnit = true;
41
+ if (!this.scoutTargetIsPermanent) {
42
+ if (this.attemptsOnCurrentTarget > MAX_ATTEMPTS_PER_TARGET) {
43
+ this.logger(`Scout target ${this.scoutTarget.x},${this.scoutTarget.y} took too many attempts, moving to next`);
44
+ this.setScoutTarget(null, 0);
45
+ return noop();
46
+ }
47
+ if (gameApi.getCurrentTick() > this.scoutTargetRefreshedAt + MAX_TICKS_PER_TARGET) {
48
+ this.logger(`Scout target ${this.scoutTarget.x},${this.scoutTarget.y} took too long, moving to next`);
49
+ this.setScoutTarget(null, 0);
50
+ return noop();
51
+ }
52
+ }
53
+ const targetTile = gameApi.mapApi.getTile(this.scoutTarget.x, this.scoutTarget.y);
54
+ if (!targetTile) {
55
+ throw new Error(`target tile ${this.scoutTarget.x},${this.scoutTarget.y} does not exist`);
56
+ }
57
+ if (gameApi.getCurrentTick() > this.lastMoveCommandTick + SCOUT_MOVE_COOLDOWN_TICKS) {
58
+ this.lastMoveCommandTick = gameApi.getCurrentTick();
59
+ scouts.forEach((unit) => {
60
+ if (this.scoutTarget) {
61
+ actionsApi.orderUnits([unit.id], OrderType.AttackMove, this.scoutTarget.x, this.scoutTarget.y);
62
+ }
63
+ });
64
+ // Check that a scout is actually moving closer to the target.
65
+ const distances = scouts.map((unit) => getDistanceBetweenTileAndPoint(unit.tile, this.scoutTarget));
66
+ const newMinDistance = Math.min(...distances);
67
+ if (!this.scoutMinDistance || newMinDistance < this.scoutMinDistance) {
68
+ this.logger(`Scout timeout refreshed because unit moved closer to point (${newMinDistance} < ${this.scoutMinDistance})`);
69
+ this.scoutTargetRefreshedAt = gameApi.getCurrentTick();
70
+ this.scoutMinDistance = newMinDistance;
71
+ }
72
+ }
73
+ if (gameApi.mapApi.isVisibleTile(targetTile, playerData.name)) {
74
+ this.logger(`Scout target ${this.scoutTarget.x},${this.scoutTarget.y} successfully scouted, moving to next`);
75
+ this.setScoutTarget(null, gameApi.getCurrentTick());
76
+ }
77
+ }
78
+ else {
79
+ const nextScoutTarget = matchAwareness.getScoutingManager().getNewScoutTarget();
80
+ if (!nextScoutTarget) {
81
+ this.logger(`No more scouting targets available, disbanding.`);
82
+ return disbandMission();
83
+ }
84
+ this.setScoutTarget(nextScoutTarget, gameApi.getCurrentTick());
85
+ }
86
+ return noop();
87
+ }
88
+ setScoutTarget(target, currentTick) {
89
+ this.attemptsOnCurrentTarget = 0;
90
+ this.scoutTargetRefreshedAt = currentTick;
91
+ this.scoutTarget = target?.asVector2() ?? null;
92
+ this.scoutMinDistance = undefined;
93
+ this.scoutTargetIsPermanent = target?.isPermanent ?? false;
94
+ }
95
+ getGlobalDebugText() {
96
+ return "scouting";
97
+ }
98
+ getPriority() {
99
+ return this.priority;
100
+ }
101
+ }
102
+ const SCOUT_COOLDOWN_TICKS = 300;
103
+ export class ScoutingMissionFactory {
104
+ constructor(lastScoutAt = -SCOUT_COOLDOWN_TICKS) {
105
+ this.lastScoutAt = lastScoutAt;
106
+ }
107
+ getName() {
108
+ return "ScoutingMissionFactory";
109
+ }
110
+ maybeCreateMissions(gameApi, playerData, matchAwareness, missionController, logger) {
111
+ if (gameApi.getCurrentTick() < this.lastScoutAt + SCOUT_COOLDOWN_TICKS) {
112
+ return;
113
+ }
114
+ if (!matchAwareness.getScoutingManager().hasScoutTargets()) {
115
+ return;
116
+ }
117
+ if (!missionController.addMission(new ScoutingMission("globalScout", 10, logger))) {
118
+ this.lastScoutAt = gameApi.getCurrentTick();
119
+ }
120
+ }
121
+ onMissionFailed(gameApi, playerData, matchAwareness, failedMission, failureReason, missionController, logger) {
122
+ if (gameApi.getCurrentTick() < this.lastScoutAt + SCOUT_COOLDOWN_TICKS) {
123
+ return;
124
+ }
125
+ if (!matchAwareness.getScoutingManager().hasScoutTargets()) {
126
+ return;
127
+ }
128
+ if (failedMission instanceof AttackMission) {
129
+ missionController.addMission(new ScoutingMission("globalScout", 10, logger));
130
+ this.lastScoutAt = gameApi.getCurrentTick();
131
+ }
132
+ }
133
+ }
134
134
  //# sourceMappingURL=scoutingMission.js.map