@supalosa/chronodivide-bot 0.1.0

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 (56) hide show
  1. package/.prettierrc +5 -0
  2. package/README.md +46 -0
  3. package/dist/bot/bot.js +269 -0
  4. package/dist/bot/logic/building/ArtilleryUnit.js +24 -0
  5. package/dist/bot/logic/building/antiGroundStaticDefence.js +40 -0
  6. package/dist/bot/logic/building/basicAirUnit.js +39 -0
  7. package/dist/bot/logic/building/basicBuilding.js +25 -0
  8. package/dist/bot/logic/building/basicGroundUnit.js +57 -0
  9. package/dist/bot/logic/building/building.js +77 -0
  10. package/dist/bot/logic/building/harvester.js +15 -0
  11. package/dist/bot/logic/building/massedAntiGroundUnit.js +20 -0
  12. package/dist/bot/logic/building/powerPlant.js +20 -0
  13. package/dist/bot/logic/building/queueController.js +168 -0
  14. package/dist/bot/logic/building/queues.js +19 -0
  15. package/dist/bot/logic/building/resourceCollectionBuilding.js +34 -0
  16. package/dist/bot/logic/map/map.js +57 -0
  17. package/dist/bot/logic/map/sector.js +104 -0
  18. package/dist/bot/logic/mission/basicMission.js +30 -0
  19. package/dist/bot/logic/mission/expansionMission.js +14 -0
  20. package/dist/bot/logic/mission/mission.js +2 -0
  21. package/dist/bot/logic/mission/missionController.js +47 -0
  22. package/dist/bot/logic/squad/behaviours/squadExpansion.js +18 -0
  23. package/dist/bot/logic/squad/behaviours/squadScouters.js +8 -0
  24. package/dist/bot/logic/squad/squad.js +73 -0
  25. package/dist/bot/logic/squad/squadBehaviour.js +5 -0
  26. package/dist/bot/logic/squad/squadController.js +58 -0
  27. package/dist/bot/logic/threat/threat.js +22 -0
  28. package/dist/bot/logic/threat/threatCalculator.js +72 -0
  29. package/dist/exampleBot.js +38 -0
  30. package/package.json +24 -0
  31. package/rules.ini +23126 -0
  32. package/src/bot/bot.ts +378 -0
  33. package/src/bot/logic/building/ArtilleryUnit.ts +43 -0
  34. package/src/bot/logic/building/antiGroundStaticDefence.ts +60 -0
  35. package/src/bot/logic/building/basicAirUnit.ts +68 -0
  36. package/src/bot/logic/building/basicBuilding.ts +47 -0
  37. package/src/bot/logic/building/basicGroundUnit.ts +78 -0
  38. package/src/bot/logic/building/building.ts +120 -0
  39. package/src/bot/logic/building/harvester.ts +27 -0
  40. package/src/bot/logic/building/powerPlant.ts +32 -0
  41. package/src/bot/logic/building/queueController.ts +255 -0
  42. package/src/bot/logic/building/resourceCollectionBuilding.ts +56 -0
  43. package/src/bot/logic/map/map.ts +76 -0
  44. package/src/bot/logic/map/sector.ts +130 -0
  45. package/src/bot/logic/mission/basicMission.ts +42 -0
  46. package/src/bot/logic/mission/expansionMission.ts +25 -0
  47. package/src/bot/logic/mission/mission.ts +47 -0
  48. package/src/bot/logic/mission/missionController.ts +51 -0
  49. package/src/bot/logic/squad/behaviours/squadExpansion.ts +33 -0
  50. package/src/bot/logic/squad/squad.ts +97 -0
  51. package/src/bot/logic/squad/squadBehaviour.ts +43 -0
  52. package/src/bot/logic/squad/squadController.ts +66 -0
  53. package/src/bot/logic/threat/threat.ts +15 -0
  54. package/src/bot/logic/threat/threatCalculator.ts +99 -0
  55. package/src/exampleBot.ts +44 -0
  56. package/tsconfig.json +73 -0
@@ -0,0 +1,72 @@
1
+ import { MovementZone, ObjectType } from "@chronodivide/game-api";
2
+ import { GlobalThreat } from "./threat.js";
3
+ export function calculateGlobalThreat(game, playerData, visibleAreaPercent) {
4
+ let groundUnits = game.getVisibleUnits(playerData.name, "hostile", (r) => r.type == ObjectType.Vehicle || r.type == ObjectType.Infantry);
5
+ let airUnits = game.getVisibleUnits(playerData.name, "hostile", (r) => r.movementZone == MovementZone.Fly);
6
+ let groundDefence = game
7
+ .getVisibleUnits(playerData.name, "hostile", (r) => r.type == ObjectType.Building)
8
+ .filter((unitId) => isAntiGround(game, unitId));
9
+ let antiAirPower = game
10
+ .getVisibleUnits(playerData.name, "hostile", (r) => r.type != ObjectType.Building)
11
+ .filter((unitId) => isAntiAir(game, unitId));
12
+ let ourAntiGroundUnits = game
13
+ .getVisibleUnits(playerData.name, "self", (r) => r.isSelectableCombatant)
14
+ .filter((unitId) => isAntiGround(game, unitId));
15
+ let ourAntiAirUnits = game
16
+ .getVisibleUnits(playerData.name, "self", (r) => r.isSelectableCombatant)
17
+ .filter((unitId) => isAntiAir(game, unitId));
18
+ let ourGroundDefence = game
19
+ .getVisibleUnits(playerData.name, "self", (r) => r.type == ObjectType.Building)
20
+ .filter((unitId) => isAntiGround(game, unitId));
21
+ let ourAirUnits = game.getVisibleUnits(playerData.name, "self", (r) => r.movementZone == MovementZone.Fly && r.isSelectableCombatant);
22
+ let observedGroundThreat = calculateFirepowerForUnits(game, groundUnits);
23
+ let observedAirThreat = calculateFirepowerForUnits(game, airUnits);
24
+ let observedAntiAirThreat = calculateFirepowerForUnits(game, antiAirPower);
25
+ let observedGroundDefence = calculateFirepowerForUnits(game, groundDefence);
26
+ let ourAntiGroundPower = calculateFirepowerForUnits(game, ourAntiGroundUnits);
27
+ let ourAntiAirPower = calculateFirepowerForUnits(game, ourAntiAirUnits);
28
+ let ourAirPower = calculateFirepowerForUnits(game, ourAirUnits);
29
+ let ourGroundDefencePower = calculateFirepowerForUnits(game, ourGroundDefence);
30
+ return new GlobalThreat(visibleAreaPercent, observedGroundThreat, observedAirThreat, observedAntiAirThreat, observedGroundDefence * 0.25, ourGroundDefencePower * 0.25, ourAntiGroundPower, ourAntiAirPower, ourAirPower);
31
+ }
32
+ function isAntiGround(gameApi, unitId) {
33
+ let unit = gameApi.getUnitData(unitId);
34
+ if (unit && unit.primaryWeapon) {
35
+ return unit.primaryWeapon.projectileRules.isAntiGround;
36
+ }
37
+ return false;
38
+ }
39
+ function isAntiAir(gameApi, unitId) {
40
+ let unit = gameApi.getUnitData(unitId);
41
+ if (unit && unit.primaryWeapon) {
42
+ return unit.primaryWeapon.projectileRules.isAntiAir;
43
+ }
44
+ return false;
45
+ }
46
+ function calculateFirepowerForUnit(unitData) {
47
+ let threat = 0;
48
+ let hpRatio = unitData.hitPoints / Math.max(1, unitData.maxHitPoints);
49
+ if (unitData.primaryWeapon) {
50
+ threat +=
51
+ (hpRatio *
52
+ ((unitData.primaryWeapon.rules.damage + 1) * Math.sqrt(unitData.primaryWeapon.rules.range + 1))) /
53
+ Math.max(unitData.primaryWeapon.cooldownTicks, 1);
54
+ }
55
+ if (unitData.secondaryWeapon) {
56
+ threat +=
57
+ (hpRatio *
58
+ ((unitData.secondaryWeapon.rules.damage + 1) * Math.sqrt(unitData.secondaryWeapon.rules.range + 1))) /
59
+ Math.max(unitData.secondaryWeapon.cooldownTicks, 1);
60
+ }
61
+ return Math.min(800, threat);
62
+ }
63
+ function calculateFirepowerForUnits(game, unitIds) {
64
+ let threat = 0;
65
+ unitIds.forEach((unitId) => {
66
+ let unitData = game.getUnitData(unitId);
67
+ if (unitData) {
68
+ threat += calculateFirepowerForUnit(unitData);
69
+ }
70
+ });
71
+ return threat;
72
+ }
@@ -0,0 +1,38 @@
1
+ import { cdapi } from "@chronodivide/game-api";
2
+ import { ExampleBot } from "./bot/bot.js";
3
+ async function main() {
4
+ const mapName = "mp03t4.map";
5
+ // Bot names must be unique in online mode
6
+ const botName = `Joe${String(Date.now()).substr(-6)}`;
7
+ const otherBotName = `Bob${String(Date.now() + 1).substr(-6)}`;
8
+ await cdapi.init(process.env.MIX_DIR || "./");
9
+ console.log("Server URL: " + process.env.SERVER_URL);
10
+ console.log("Client URL: " + process.env.CLIENT_URL);
11
+ const game = await cdapi.createGame({
12
+ // Uncomment the following lines to play in real time versus the bot
13
+ online: true,
14
+ serverUrl: process.env.SERVER_URL,
15
+ clientUrl: process.env.CLIENT_URL,
16
+ agents: [new ExampleBot(botName, "Americans"), { name: otherBotName, country: "French" }],
17
+ //agents: [new ExampleBot(botName, "Russians", false), new ExampleBot(otherBotName, "Americans", true)],
18
+ buildOffAlly: false,
19
+ cratesAppear: false,
20
+ credits: 10000,
21
+ gameMode: cdapi.getAvailableGameModes(mapName)[0],
22
+ gameSpeed: 6,
23
+ mapName,
24
+ mcvRepacks: true,
25
+ shortGame: true,
26
+ superWeapons: false,
27
+ unitCount: 0,
28
+ });
29
+ while (!game.isFinished()) {
30
+ await game.update();
31
+ }
32
+ game.saveReplay();
33
+ game.dispose();
34
+ }
35
+ main().catch((e) => {
36
+ console.error(e);
37
+ process.exit(1);
38
+ });
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@supalosa/chronodivide-bot",
3
+ "version": "0.1.0",
4
+ "description": "Example bot for Chrono Divide",
5
+ "main": "dist/exampleBot.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "build": "tsc -p .",
9
+ "watch": "tsc -p . -w",
10
+ "start": "node . --es-module-specifier-resolution=node",
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "license": "UNLICENSED",
14
+ "devDependencies": {
15
+ "@types/node": "^14.17.32",
16
+ "typescript": "^4.3.5"
17
+ },
18
+ "dependencies": {
19
+ "@chronodivide/game-api": "^0.43.0",
20
+ "@types/luxon": "^3.3.2",
21
+ "luxon": "^3.4.3",
22
+ "priority-queue-typescript": "^1.0.1"
23
+ }
24
+ }