@v12-engine/engine 0.0.0-stage → 0.1.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.
- package/LICENSE +21 -0
- package/dist/abilities/buffs.d.ts +83 -0
- package/dist/abilities/castTold.d.ts +12 -0
- package/dist/abilities/charges.d.ts +28 -0
- package/dist/abilities/dispel.d.ts +9 -0
- package/dist/abilities/effectFields.d.ts +10 -0
- package/dist/abilities/effects/buff.d.ts +8 -0
- package/dist/abilities/effects/core.d.ts +1 -0
- package/dist/abilities/effects/damage.d.ts +1 -0
- package/dist/abilities/effects/heal.d.ts +2 -0
- package/dist/abilities/effects/missile.d.ts +1 -0
- package/dist/abilities/effects/moves.d.ts +11 -0
- package/dist/abilities/effects/passives.d.ts +15 -0
- package/dist/abilities/effects/sight.d.ts +4 -0
- package/dist/abilities/effects/spawn.d.ts +2 -0
- package/dist/abilities/effects/timed.d.ts +4 -0
- package/dist/abilities/effects/trade.d.ts +1 -0
- package/dist/abilities/effects.d.ts +122 -0
- package/dist/abilities/land.d.ts +21 -0
- package/dist/abilities/scaled.d.ts +21 -0
- package/dist/abilities/text.d.ts +113 -0
- package/dist/ai/area.d.ts +53 -0
- package/dist/ai/brain.d.ts +528 -0
- package/dist/ai/budget.d.ts +67 -0
- package/dist/ai/checks.d.ts +115 -0
- package/dist/ai/computer.d.ts +166 -0
- package/dist/ai/defence.d.ts +108 -0
- package/dist/ai/define.d.ts +21 -0
- package/dist/ai/economy.d.ts +129 -0
- package/dist/ai/geometry.d.ts +35 -0
- package/dist/ai/goals.d.ts +360 -0
- package/dist/ai/index.d.ts +38 -0
- package/dist/ai/knowledge.d.ts +418 -0
- package/dist/ai/lanes.d.ts +232 -0
- package/dist/ai/melee/build.d.ts +61 -0
- package/dist/ai/melee/goals.d.ts +299 -0
- package/dist/ai/melee/heroes.d.ts +27 -0
- package/dist/ai/melee/index.d.ts +14 -0
- package/dist/ai/melee/production.d.ts +8 -0
- package/dist/ai/melee/surrender.d.ts +24 -0
- package/dist/ai/micro.d.ts +278 -0
- package/dist/ai/mission.d.ts +195 -0
- package/dist/ai/missionRules.d.ts +18 -0
- package/dist/ai/module.d.ts +116 -0
- package/dist/ai/options.d.ts +61 -0
- package/dist/ai/plans/build.d.ts +280 -0
- package/dist/ai/plans/placement.d.ts +82 -0
- package/dist/ai/plans/plans.d.ts +105 -0
- package/dist/ai/plans/production.d.ts +210 -0
- package/dist/ai/plans/purse.d.ts +73 -0
- package/dist/ai/plans/tech.d.ts +37 -0
- package/dist/ai/profiles.d.ts +204 -0
- package/dist/ai/reach.d.ts +4 -0
- package/dist/ai/report.d.ts +203 -0
- package/dist/ai/roles.d.ts +133 -0
- package/dist/ai/rules.d.ts +288 -0
- package/dist/ai/scouting.d.ts +98 -0
- package/dist/ai/settings.d.ts +73 -0
- package/dist/ai/squads.d.ts +429 -0
- package/dist/ai/strength.d.ts +167 -0
- package/dist/ai/task.d.ts +118 -0
- package/dist/ai/tasks/attack.d.ts +7 -0
- package/dist/ai/tasks/capture.d.ts +21 -0
- package/dist/ai/tasks/creep.d.ts +16 -0
- package/dist/ai/tasks/defend.d.ts +29 -0
- package/dist/ai/tasks/drop.d.ts +34 -0
- package/dist/ai/tasks/escort.d.ts +16 -0
- package/dist/ai/tasks/gather.d.ts +23 -0
- package/dist/ai/tasks/harass.d.ts +7 -0
- package/dist/ai/tasks/hold.d.ts +20 -0
- package/dist/ai/tasks/index.d.ts +32 -0
- package/dist/ai/tasks/move.d.ts +19 -0
- package/dist/ai/tasks/patrol.d.ts +8 -0
- package/dist/ai/tasks/retreat.d.ts +20 -0
- package/dist/ai/tasks/scout.d.ts +29 -0
- package/dist/ai/tasks/shared.d.ts +74 -0
- package/dist/ai/team.d.ts +155 -0
- package/dist/ai/threat.d.ts +91 -0
- package/dist/ai/view.d.ts +366 -0
- package/dist/ai/waves.d.ts +126 -0
- package/dist/ai.js +6239 -0
- package/dist/ai.js.map +1 -0
- package/dist/aiTesting.d.ts +179 -0
- package/dist/areas.d.ts +149 -0
- package/dist/attacks.d.ts +66 -0
- package/dist/attributes.d.ts +66 -0
- package/dist/brain-BvVdUhX8.js +7659 -0
- package/dist/brain-BvVdUhX8.js.map +1 -0
- package/dist/builds-C6LfgvEU.js +460 -0
- package/dist/builds-C6LfgvEU.js.map +1 -0
- package/dist/bytes.d.ts +6 -0
- package/dist/camps.d.ts +95 -0
- package/dist/capture.d.ts +131 -0
- package/dist/cellLayers.d.ts +75 -0
- package/dist/cinematics.d.ts +194 -0
- package/dist/clock.d.ts +32 -0
- package/dist/commands.d.ts +235 -0
- package/dist/components.d.ts +184 -0
- package/dist/computers.d.ts +108 -0
- package/dist/concealment.d.ts +61 -0
- package/dist/coreComponents-syuh2fPG.js +5149 -0
- package/dist/coreComponents-syuh2fPG.js.map +1 -0
- package/dist/coreComponents.d.ts +1 -0
- package/dist/dashing.d.ts +8 -0
- package/dist/debug.d.ts +36 -0
- package/dist/debug.js +3 -0
- package/dist/debugCommands-CzjrSm66.js +14739 -0
- package/dist/debugCommands-CzjrSm66.js.map +1 -0
- package/dist/debugCommands.d.ts +213 -0
- package/dist/debugging.d.ts +10 -0
- package/dist/definitions.d.ts +43 -0
- package/dist/defs.d.ts +1162 -0
- package/dist/denying.d.ts +81 -0
- package/dist/destructibles.d.ts +27 -0
- package/dist/determinism-BCymQwiE.js +518 -0
- package/dist/determinism-BCymQwiE.js.map +1 -0
- package/dist/determinism.d.ts +121 -0
- package/dist/dialog.d.ts +94 -0
- package/dist/effectRefs.d.ts +16 -0
- package/dist/effects.d.ts +80 -0
- package/dist/endings.d.ts +22 -0
- package/dist/engagement.d.ts +108 -0
- package/dist/engineEvents.d.ts +710 -0
- package/dist/entity.d.ts +409 -0
- package/dist/entityIndex.d.ts +50 -0
- package/dist/errors.d.ts +85 -0
- package/dist/events.d.ts +97 -0
- package/dist/exactMath.d.ts +63 -0
- package/dist/features.d.ts +10 -0
- package/dist/fields.d.ts +114 -0
- package/dist/fixture.d.ts +17 -0
- package/dist/fog.d.ts +110 -0
- package/dist/formation.d.ts +111 -0
- package/dist/friendlyFire.d.ts +26 -0
- package/dist/game-DiJEN-Ks.js +5800 -0
- package/dist/game-DiJEN-Ks.js.map +1 -0
- package/dist/game.d.ts +501 -0
- package/dist/gameData.d.ts +325 -0
- package/dist/gameFiles.d.ts +26 -0
- package/dist/gates.d.ts +28 -0
- package/dist/generate.d.ts +403 -0
- package/dist/generateWorker.d.ts +39 -0
- package/dist/grid.d.ts +53 -0
- package/dist/ground.d.ts +127 -0
- package/dist/groundSpeed.d.ts +22 -0
- package/dist/hero.d.ts +177 -0
- package/dist/home.d.ts +14 -0
- package/dist/hooks.d.ts +780 -0
- package/dist/hotReload.d.ts +76 -0
- package/dist/ids.d.ts +26 -0
- package/dist/index.d.ts +227 -0
- package/dist/index.js +4701 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect-D9dWHmZ0.js +491 -0
- package/dist/inspect-D9dWHmZ0.js.map +1 -0
- package/dist/inspect.d.ts +176 -0
- package/dist/inventory.d.ts +18 -0
- package/dist/items.d.ts +91 -0
- package/dist/lanes.d.ts +213 -0
- package/dist/life.d.ts +53 -0
- package/dist/local-Dkovq42k.js +1379 -0
- package/dist/local-Dkovq42k.js.map +1 -0
- package/dist/log.d.ts +140 -0
- package/dist/manaBurn.d.ts +39 -0
- package/dist/map/file.d.ts +114 -0
- package/dist/map/images.d.ts +18 -0
- package/dist/map/look.d.ts +47 -0
- package/dist/map/pathProfile.d.ts +13 -0
- package/dist/map/resize.d.ts +54 -0
- package/dist/map/schema.d.ts +10 -0
- package/dist/map/terrain.d.ts +32 -0
- package/dist/map/types.d.ts +613 -0
- package/dist/map.d.ts +7 -0
- package/dist/mapCheck/cells.d.ts +19 -0
- package/dist/mapCheck/rule.d.ts +30 -0
- package/dist/mapCheck/rules/names.d.ts +3 -0
- package/dist/mapCheck/rules/objects.d.ts +3 -0
- package/dist/mapCheck/rules/paths.d.ts +3 -0
- package/dist/mapCheck/rules/players.d.ts +3 -0
- package/dist/mapCheck/rules/races.d.ts +3 -0
- package/dist/mapCheck/rules/random.d.ts +3 -0
- package/dist/mapCheck/rules/regions.d.ts +3 -0
- package/dist/mapCheck/rules/targets.d.ts +3 -0
- package/dist/mapCheck/rules/walking.d.ts +3 -0
- package/dist/mapCheck.d.ts +23 -0
- package/dist/mapFields.d.ts +364 -0
- package/dist/mapFile.d.ts +23 -0
- package/dist/mapMeasure.d.ts +95 -0
- package/dist/mapMerge.d.ts +19 -0
- package/dist/mapObjectives.d.ts +82 -0
- package/dist/mapObjects.d.ts +1 -0
- package/dist/math.d.ts +44 -0
- package/dist/messages.d.ts +150 -0
- package/dist/missionRules-C-bGxm0Q.js +523 -0
- package/dist/missionRules-C-bGxm0Q.js.map +1 -0
- package/dist/missionRules.d.ts +179 -0
- package/dist/mods.d.ts +146 -0
- package/dist/names.d.ts +93 -0
- package/dist/navigation/agentParams.d.ts +4 -0
- package/dist/navigation/air.d.ts +89 -0
- package/dist/navigation/builds.d.ts +140 -0
- package/dist/navigation/groundAreas.d.ts +23 -0
- package/dist/navigation/navigation.d.ts +127 -0
- package/dist/navigation/recast.d.ts +214 -0
- package/dist/navigation/sidePaths.d.ts +69 -0
- package/dist/navigation/sized.d.ts +1 -0
- package/dist/navigation-worker.js +11 -0
- package/dist/navigation-worker.js.map +1 -0
- package/dist/nearest.d.ts +8 -0
- package/dist/noise.d.ts +12 -0
- package/dist/objectives.d.ts +93 -0
- package/dist/orders/basic.d.ts +96 -0
- package/dist/orders/build.d.ts +91 -0
- package/dist/orders/cast.d.ts +105 -0
- package/dist/orders/facts.d.ts +14 -0
- package/dist/orders/harvest.d.ts +94 -0
- package/dist/orders/idle.d.ts +7 -0
- package/dist/orders/items.d.ts +14 -0
- package/dist/orders/queue.d.ts +24 -0
- package/dist/pack.schema.json +6621 -0
- package/dist/packs/director/index.d.ts +81 -0
- package/dist/packs/heroes/campaign.d.ts +137 -0
- package/dist/packs/heroes/carry.d.ts +59 -0
- package/dist/packs/heroes/commands.d.ts +6 -0
- package/dist/packs/heroes/hire.d.ts +9 -0
- package/dist/packs/heroes/index.d.ts +12 -0
- package/dist/packs/heroes/making.d.ts +16 -0
- package/dist/packs/heroes/respawn.d.ts +42 -0
- package/dist/packs/moba/index.d.ts +34 -0
- package/dist/packs/pack.d.ts +84 -0
- package/dist/packs-g5thvmGn.js +3199 -0
- package/dist/packs-g5thvmGn.js.map +1 -0
- package/dist/packs.d.ts +84 -0
- package/dist/paths.d.ts +51 -0
- package/dist/plain.d.ts +17 -0
- package/dist/player.d.ts +117 -0
- package/dist/portals.d.ts +66 -0
- package/dist/prefabs.d.ts +139 -0
- package/dist/presetBuildings.d.ts +52 -0
- package/dist/presetGround.d.ts +22 -0
- package/dist/profiles-B3NS9jwk.js +335 -0
- package/dist/profiles-B3NS9jwk.js.map +1 -0
- package/dist/races.d.ts +136 -0
- package/dist/randomGroups.d.ts +2 -0
- package/dist/registry.d.ts +464 -0
- package/dist/remains.d.ts +119 -0
- package/dist/replication.d.ts +103 -0
- package/dist/rng.d.ts +17 -0
- package/dist/rules.d.ts +395 -0
- package/dist/rulesCheck.d.ts +37 -0
- package/dist/runes.d.ts +41 -0
- package/dist/save.d.ts +277 -0
- package/dist/scenario.d.ts +56 -0
- package/dist/scheduler.d.ts +67 -0
- package/dist/score.d.ts +306 -0
- package/dist/sequences.d.ts +132 -0
- package/dist/server/doorman.d.ts +21 -0
- package/dist/server/gameServer.d.ts +346 -0
- package/dist/server/index.d.ts +24 -0
- package/dist/server/lobby.d.ts +1 -0
- package/dist/server/log.d.ts +13 -0
- package/dist/server/match.d.ts +24 -0
- package/dist/server/mode.d.ts +168 -0
- package/dist/server/navigation-worker.d.ts +1 -0
- package/dist/server/navigation.d.ts +11 -0
- package/dist/server/ops.d.ts +78 -0
- package/dist/server/packs.d.ts +15 -0
- package/dist/server/ratings.d.ts +62 -0
- package/dist/server/relay.d.ts +34 -0
- package/dist/server/rooms.d.ts +162 -0
- package/dist/server/seat.d.ts +2 -0
- package/dist/server/seatSettings.d.ts +15 -0
- package/dist/server/secret.d.ts +5 -0
- package/dist/server/start.d.ts +54 -0
- package/dist/server/websocket.d.ts +74 -0
- package/dist/server.js +2861 -0
- package/dist/server.js.map +1 -0
- package/dist/session/can.d.ts +20 -0
- package/dist/session/commandReplay.d.ts +92 -0
- package/dist/session/debug.d.ts +65 -0
- package/dist/session/delay.d.ts +15 -0
- package/dist/session/delta.d.ts +98 -0
- package/dist/session/entityState.d.ts +1 -0
- package/dist/session/local.d.ts +214 -0
- package/dist/session/memory.d.ts +27 -0
- package/dist/session/protocol.d.ts +1155 -0
- package/dist/session/remote.d.ts +530 -0
- package/dist/session/replay.d.ts +114 -0
- package/dist/session/seed.d.ts +7 -0
- package/dist/session/share.d.ts +78 -0
- package/dist/session/socket.d.ts +8 -0
- package/dist/session/wire.d.ts +153 -0
- package/dist/session/worker.d.ts +227 -0
- package/dist/shared.d.ts +171 -0
- package/dist/sides.d.ts +75 -0
- package/dist/sight.d.ts +27 -0
- package/dist/simulate-oXBiw1Ff.js +167 -0
- package/dist/simulate-oXBiw1Ff.js.map +1 -0
- package/dist/simulate-worker.d.ts +1 -0
- package/dist/simulate-worker.js +28 -0
- package/dist/simulate-worker.js.map +1 -0
- package/dist/simulate.d.ts +154 -0
- package/dist/smart.d.ts +9 -0
- package/dist/spatial.d.ts +62 -0
- package/dist/spawning.d.ts +33 -0
- package/dist/stances.d.ts +76 -0
- package/dist/start.d.ts +71 -0
- package/dist/stats.d.ts +122 -0
- package/dist/summons.d.ts +63 -0
- package/dist/systems/abilities.d.ts +3 -0
- package/dist/systems/combat.d.ts +71 -0
- package/dist/systems/combatTold.d.ts +14 -0
- package/dist/systems/construction.d.ts +34 -0
- package/dist/systems/economy.d.ts +21 -0
- package/dist/systems/fog.d.ts +19 -0
- package/dist/systems/life.d.ts +3 -0
- package/dist/systems/movement.d.ts +105 -0
- package/dist/systems/orders.d.ts +7 -0
- package/dist/systems/production.d.ts +49 -0
- package/dist/systems/productionQueue.d.ts +40 -0
- package/dist/systems/victory.d.ts +14 -0
- package/dist/talk.d.ts +65 -0
- package/dist/tech.d.ts +62 -0
- package/dist/techTree.d.ts +38 -0
- package/dist/terrain.d.ts +173 -0
- package/dist/terrainSave.d.ts +29 -0
- package/dist/testing.d.ts +58 -0
- package/dist/testing.js +822 -0
- package/dist/testing.js.map +1 -0
- package/dist/tiles.d.ts +34 -0
- package/dist/timers.d.ts +146 -0
- package/dist/tomes.d.ts +48 -0
- package/dist/trade.d.ts +28 -0
- package/dist/transport.d.ts +76 -0
- package/dist/tunables.d.ts +45 -0
- package/dist/upkeep.d.ts +16 -0
- package/dist/veterancy.d.ts +80 -0
- package/dist/walls.d.ts +86 -0
- package/dist/world.d.ts +1118 -0
- package/package.json +80 -5
- package/README.md +0 -3
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { type UnitTypeDef } from '#engine/defs';
|
|
2
|
+
import type { PlayerId } from '#engine/entity';
|
|
3
|
+
import { type Vec2 } from '#engine/math';
|
|
4
|
+
import type { Registry } from '#engine/registry';
|
|
5
|
+
import type { EntityState, LearnableInfo, Snapshot } from '#engine/session/protocol';
|
|
6
|
+
import type { Brain } from './brain';
|
|
7
|
+
import { type AiModuleDef } from './module';
|
|
8
|
+
import { type AiCondition } from './rules';
|
|
9
|
+
import { type Squad } from './squads';
|
|
10
|
+
import { UnitSet } from './view';
|
|
11
|
+
/**
|
|
12
|
+
* What a computer player sees as it weighs an ability, for the ability's `ai` to decide with (`AbilityDef.ai`)
|
|
13
|
+
*
|
|
14
|
+
* @beta
|
|
15
|
+
*/
|
|
16
|
+
export interface AbilityAiView {
|
|
17
|
+
snapshot: Snapshot;
|
|
18
|
+
registry: Registry;
|
|
19
|
+
playerId: PlayerId;
|
|
20
|
+
/** Enemy units it sees, near enough to the caster to matter */
|
|
21
|
+
enemies: EntityState[];
|
|
22
|
+
/** Its own and allied units that fight, near the caster */
|
|
23
|
+
friends: EntityState[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* One rule of who is worth hitting first (`MicroOptions.targets`): what it picks out, how much it adds, when it counts.
|
|
27
|
+
* Plain data
|
|
28
|
+
*
|
|
29
|
+
* @beta
|
|
30
|
+
*/
|
|
31
|
+
export interface TargetRule {
|
|
32
|
+
/**
|
|
33
|
+
* What it picks out: a role (`caster`, `hero`, `siege`, `worker`, `healer`), `building`, a tag (`ranged`, the game's
|
|
34
|
+
* own), or a unit type by id
|
|
35
|
+
*/
|
|
36
|
+
match: string;
|
|
37
|
+
/** What it adds to the worth of what it picks out: 1 when left out. Rules add up; a foe no rule names is worth 1 */
|
|
38
|
+
weight?: number;
|
|
39
|
+
/** When it counts: a condition (`AiCondition`, as data or a function). Always when left out */
|
|
40
|
+
when?: AiCondition;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Who a squad hits, in code (`MicroOptions.targets`): of the foes in its fight, the one; nothing to leave the units to
|
|
44
|
+
* themselves this time
|
|
45
|
+
*
|
|
46
|
+
* @beta
|
|
47
|
+
*/
|
|
48
|
+
export type TargetPicker = (ai: Brain, squad: Squad, foes: UnitSet) => EntityState | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Where to use an ability, in code (`MicroOptions.spells`, by ability id): where (`point`) and on whom (`target`),
|
|
51
|
+
* `null` for not now, `undefined` to leave it to what the kit works out from the effects. `foes` are the enemies within
|
|
52
|
+
* the ability's reach of the caster, `friends` its own and its allies' fighters near it
|
|
53
|
+
*
|
|
54
|
+
* @beta
|
|
55
|
+
*/
|
|
56
|
+
export type SpellAim = (ai: Brain, caster: EntityState, foes: readonly EntityState[], friends: readonly EntityState[], level: number) => {
|
|
57
|
+
point: Vec2;
|
|
58
|
+
target?: number;
|
|
59
|
+
} | null | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* A hero the brain means to have (`MicroOptions.heroes`): which, what it learns in what order, what it buys
|
|
62
|
+
*
|
|
63
|
+
* @beta
|
|
64
|
+
*/
|
|
65
|
+
export interface HeroPlan {
|
|
66
|
+
/** The hero's unit type */
|
|
67
|
+
type: string;
|
|
68
|
+
/**
|
|
69
|
+
* The order its skills are learned in, each level a line (`['stomp', 'holyLight', 'stomp', …]`); past the end, or
|
|
70
|
+
* left out, the ultimate as soon as it can be had and then whatever is furthest behind. Or a function: the skill to
|
|
71
|
+
* learn next of those it may, by id
|
|
72
|
+
*/
|
|
73
|
+
skills?: string[] | ((ai: Brain, hero: EntityState, learnable: readonly LearnableInfo[]) => string | undefined);
|
|
74
|
+
/** What it shops for, in place of the brain's `shopping` */
|
|
75
|
+
items?: ShoppingItem[];
|
|
76
|
+
/** The chance it is made at all, 0 to 1 (1 when left out): rolled once, with the brain's numbers, and remembered */
|
|
77
|
+
chance?: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* A line of a hero's shopping list (`MicroOptions.shopping`, `HeroPlan.items`): an item to carry, how many, when
|
|
81
|
+
*
|
|
82
|
+
* @beta
|
|
83
|
+
*/
|
|
84
|
+
export interface ShoppingItem {
|
|
85
|
+
/** The item, by id */
|
|
86
|
+
item: string;
|
|
87
|
+
/** How many of it to carry: 1 when left out */
|
|
88
|
+
count?: number;
|
|
89
|
+
/** When it is wanted: a condition. Always when left out */
|
|
90
|
+
when?: AiCondition;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* A line of what a brain hires (`MicroOptions.hiring`): a unit a place hires out, how many of it to have, when
|
|
94
|
+
*
|
|
95
|
+
* @beta
|
|
96
|
+
*/
|
|
97
|
+
export interface HiringItem {
|
|
98
|
+
/** The unit type, by id: one a place that hires lists (`UnitTypeDef.hires`) */
|
|
99
|
+
unit: string;
|
|
100
|
+
/** How many of it to have: 1 when left out */
|
|
101
|
+
count?: number;
|
|
102
|
+
/** When it is wanted: a condition. Always when left out */
|
|
103
|
+
when?: AiCondition;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* How a brain fights (`BrainDef.micro`, the seat's `AiOptions.micro` over it, the `micro()` module's own under both):
|
|
107
|
+
* whom it hits first, whether its ranged units kite, when its units flee, how it casts, what it buys, how its siege is
|
|
108
|
+
* used, which heroes it makes. Every field has a data form a save keeps; the function forms are the brain's to give
|
|
109
|
+
* again
|
|
110
|
+
*
|
|
111
|
+
* @beta
|
|
112
|
+
*/
|
|
113
|
+
export interface MicroOptions {
|
|
114
|
+
/**
|
|
115
|
+
* Who is worth hitting first, as ranked rules (`TargetRule`), or a function that picks (`TargetPicker`). The kit's
|
|
116
|
+
* when left out: casters 2, heroes 1.5 (with `targetHeroes`), siege 1, healers 2, over the type's declared
|
|
117
|
+
* `UnitTypeDef.ai.priority`; among those alike, the weakest, the nearest
|
|
118
|
+
*/
|
|
119
|
+
targets?: TargetRule[] | TargetPicker;
|
|
120
|
+
/** Whether heroes are worth hitting first (the classic Target Heroes): yes when left out */
|
|
121
|
+
targetHeroes?: boolean;
|
|
122
|
+
/** Seconds a squad keeps hitting the rival it was told to before another is chosen: 4 */
|
|
123
|
+
focusEvery?: number;
|
|
124
|
+
/**
|
|
125
|
+
* Whether ranged units step back from the melee closing on them, when they are the faster: `'ranged'` (or `true`)
|
|
126
|
+
* when left out, `false` never
|
|
127
|
+
*/
|
|
128
|
+
kite?: boolean | 'ranged';
|
|
129
|
+
/** The share of its health under which a unit leaves the fight for safety (the classic Units Flee): 0.25. `false` never */
|
|
130
|
+
unitsFlee?: number | false;
|
|
131
|
+
/** The same for heroes (Heroes Flee): 0.35. `false` never */
|
|
132
|
+
heroesFlee?: number | false;
|
|
133
|
+
/** The share of its health at which a unit that fled is back: 0.8 */
|
|
134
|
+
returnAt?: number;
|
|
135
|
+
/** Whether the hurt go home to heal between fights, not only out of one (Remove Injuries): no when left out */
|
|
136
|
+
removeInjuries?: boolean;
|
|
137
|
+
/** Whether a unit that fled stays out until healed, however long (Ignore Injured): no when left out, so one nothing heals (or that heals too slowly to wait a minute for) comes back once safe */
|
|
138
|
+
ignoreInjured?: boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Where to use abilities, by ability id (`SpellAim`): before the ability's own `ai`, and before what the kit works
|
|
141
|
+
* out from its effects. `false` casts nothing: what is on autocast looks after itself
|
|
142
|
+
*/
|
|
143
|
+
spells?: Record<string, SpellAim> | false;
|
|
144
|
+
/** Whether a potion is drunk when it is needed: yes when left out */
|
|
145
|
+
potions?: boolean;
|
|
146
|
+
/** Whether what lies about is picked up (Take Items): yes when left out */
|
|
147
|
+
takeItems?: boolean;
|
|
148
|
+
/** Whether heroes buy from a shop in reach (Buy Items): yes when left out, where there is a shop and a list */
|
|
149
|
+
buyItems?: boolean;
|
|
150
|
+
/**
|
|
151
|
+
* What a hero shops for, in order (`ShoppingItem`), or a function that names the item a hero should buy next (none
|
|
152
|
+
* for nothing). The cheapest item whose ability heals, one of it, when left out; `false` nothing
|
|
153
|
+
*/
|
|
154
|
+
shopping?: ShoppingItem[] | ((ai: Brain, hero: EntityState) => string | undefined) | false;
|
|
155
|
+
/** Whether it hires units at a place that hires in reach (a tavern, a mercenary camp: `UnitTypeDef.hires`): yes when left out, where there is one */
|
|
156
|
+
hireUnits?: boolean;
|
|
157
|
+
/**
|
|
158
|
+
* What it hires, in order (`HiringItem`), or a function that names the unit to hire next of those a place offers (none
|
|
159
|
+
* for nothing). When left out: no hero, the strongest soldier for its price, with money to spare (150 past it) and
|
|
160
|
+
* supply free, four at the most. `false` nothing
|
|
161
|
+
*/
|
|
162
|
+
hiring?: HiringItem[] | ((ai: Brain, offered: readonly UnitTypeDef[]) => string | undefined) | false;
|
|
163
|
+
/** Whether siege units shoot buildings when they may and stay behind the squad (Smart Artillery): yes when left out */
|
|
164
|
+
smartArtillery?: boolean;
|
|
165
|
+
/**
|
|
166
|
+
* The heroes to make, in order (`HeroPlan`: which, its skills, its items, a chance), or a function that picks the
|
|
167
|
+
* next of those that could be made. The first that can be made, and the ultimate first, when left out
|
|
168
|
+
*/
|
|
169
|
+
heroes?: HeroPlan[] | ((ai: Brain, candidates: readonly UnitTypeDef[]) => UnitTypeDef | string | undefined);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* What the micro module remembers between thinks, as a save keeps it
|
|
173
|
+
*
|
|
174
|
+
* @beta
|
|
175
|
+
*/
|
|
176
|
+
export interface MicroMemory {
|
|
177
|
+
v: 1;
|
|
178
|
+
/** Whom each squad hits, by squad name: the foe and since when */
|
|
179
|
+
focus: Record<string, {
|
|
180
|
+
target: number;
|
|
181
|
+
since: number;
|
|
182
|
+
}>;
|
|
183
|
+
/** When each unit last stepped back, by unit id */
|
|
184
|
+
kited: Record<string, number>;
|
|
185
|
+
/** Each unit that fled, by id: the squad it left, since when, where to, and why */
|
|
186
|
+
fled: Record<string, {
|
|
187
|
+
squad?: string;
|
|
188
|
+
since: number;
|
|
189
|
+
to: Vec2;
|
|
190
|
+
why: 'hurt' | 'injured';
|
|
191
|
+
}>;
|
|
192
|
+
/** What each siege unit was told to shoot, by unit id */
|
|
193
|
+
siege: Record<string, {
|
|
194
|
+
target: number;
|
|
195
|
+
since: number;
|
|
196
|
+
}>;
|
|
197
|
+
/** What each hero is on its way to buy, by hero id */
|
|
198
|
+
shopping: Record<string, {
|
|
199
|
+
shop: number;
|
|
200
|
+
item: string;
|
|
201
|
+
since: number;
|
|
202
|
+
}>;
|
|
203
|
+
/** Who is on their way to hire what, by the id of the unit sent: the place that hires, the unit type, since when */
|
|
204
|
+
hiring?: Record<string, {
|
|
205
|
+
place: number;
|
|
206
|
+
unit: string;
|
|
207
|
+
since: number;
|
|
208
|
+
}>;
|
|
209
|
+
/** The chance of each hero plan as it was rolled, by its place in the list */
|
|
210
|
+
rolled: Record<string, boolean>;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* The fights as the report shows them (`AiReport.micro`): each squad in one, its foes, its odds, whom it hits; the
|
|
214
|
+
* units that fled; the heroes and what each learns next; who shops for what
|
|
215
|
+
*
|
|
216
|
+
* @beta
|
|
217
|
+
*/
|
|
218
|
+
export interface MicroReport {
|
|
219
|
+
fights: {
|
|
220
|
+
squad: string;
|
|
221
|
+
foes: number;
|
|
222
|
+
odds: number;
|
|
223
|
+
/** Whom the squad hits: the foe, its type, since when */
|
|
224
|
+
target?: {
|
|
225
|
+
id: number;
|
|
226
|
+
type: string;
|
|
227
|
+
since: number;
|
|
228
|
+
};
|
|
229
|
+
/** Its units that stepped back this think */
|
|
230
|
+
kiting: number[];
|
|
231
|
+
/** Its siege units told to shoot a building this think */
|
|
232
|
+
siege: number[];
|
|
233
|
+
}[];
|
|
234
|
+
fleeing: {
|
|
235
|
+
unit: number;
|
|
236
|
+
type: string;
|
|
237
|
+
health: number;
|
|
238
|
+
to: [number, number];
|
|
239
|
+
since: number;
|
|
240
|
+
why: 'hurt' | 'injured';
|
|
241
|
+
}[];
|
|
242
|
+
heroes: {
|
|
243
|
+
id: number;
|
|
244
|
+
type: string;
|
|
245
|
+
level: number;
|
|
246
|
+
next?: string;
|
|
247
|
+
}[];
|
|
248
|
+
shopping: {
|
|
249
|
+
hero: number;
|
|
250
|
+
item: string;
|
|
251
|
+
shop: number;
|
|
252
|
+
since: number;
|
|
253
|
+
}[];
|
|
254
|
+
/** Who is on their way to hire what: the unit sent, the place, the unit type, since when */
|
|
255
|
+
hiring: {
|
|
256
|
+
by: number;
|
|
257
|
+
place: number;
|
|
258
|
+
unit: string;
|
|
259
|
+
since: number;
|
|
260
|
+
}[];
|
|
261
|
+
/** Abilities cast last think */
|
|
262
|
+
cast: number;
|
|
263
|
+
/** Thinks whose fights it left alone, slips of its profile's `mistakes` */
|
|
264
|
+
slipped?: number;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* The micro module: the fights of the brain's squads each think, after the squads sent and watched their tasks
|
|
268
|
+
* (`ai.micro.think`): focus fire, kiting, siege, fleeing and coming back, spells, items, the heroes' skills. With how it
|
|
269
|
+
* fights where the brain's definition and the seat's options say nothing (`MicroOptions`)
|
|
270
|
+
*
|
|
271
|
+
* @beta
|
|
272
|
+
*/
|
|
273
|
+
export declare const micro: (options?: MicroOptions) => AiModuleDef;
|
|
274
|
+
declare module './area' {
|
|
275
|
+
interface AreaMemories {
|
|
276
|
+
micro?: MicroMemory;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { type Vec2 } from '#engine/math';
|
|
2
|
+
import type { EntityState } from '#engine/session/protocol';
|
|
3
|
+
import { type Brain, type BrainDef, type BrainExtension } from './brain';
|
|
4
|
+
import { type AiModuleDef } from './module';
|
|
5
|
+
import type { AiRole } from './roles';
|
|
6
|
+
import { type AiAction, type AiCondition } from './rules';
|
|
7
|
+
import type { UnitSet } from './view';
|
|
8
|
+
/**
|
|
9
|
+
* Where a mission's part is: a point, or a name the map or the rules gave an entity (`world.named`) or a region of the
|
|
10
|
+
* map
|
|
11
|
+
*
|
|
12
|
+
* @beta
|
|
13
|
+
*/
|
|
14
|
+
export type MissionPlace = Vec2 | string;
|
|
15
|
+
/**
|
|
16
|
+
* Which of its units a part takes, as data: those named (`named`), of a type, a role or a tag, near a place (`near`,
|
|
17
|
+
* `within`), at most so many (`count`, the nearest the part's place first). Its fighters (soldiers and heroes) where
|
|
18
|
+
* none of `named`, `type`, `role`, `tag` is given
|
|
19
|
+
*
|
|
20
|
+
* @beta
|
|
21
|
+
*/
|
|
22
|
+
export interface MissionUnitsData {
|
|
23
|
+
/** Entities the map or the rules named (`world.named`): those of them that are its own */
|
|
24
|
+
named?: string[];
|
|
25
|
+
/** Of a type, or of any of a list */
|
|
26
|
+
type?: string | string[];
|
|
27
|
+
role?: AiRole;
|
|
28
|
+
tag?: string;
|
|
29
|
+
/** Near a place */
|
|
30
|
+
near?: MissionPlace;
|
|
31
|
+
/** How near `near` (the part's reach when left out) */
|
|
32
|
+
within?: number;
|
|
33
|
+
/** At most so many, the nearest the part's place first */
|
|
34
|
+
count?: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Which of its units a part takes: data (`MissionUnitsData`), or a function choosing from those it may have
|
|
38
|
+
* (`available`: what no goal holds, and what goals it may take from hold)
|
|
39
|
+
*
|
|
40
|
+
* @beta
|
|
41
|
+
*/
|
|
42
|
+
export type MissionUnits = MissionUnitsData | ((ai: Brain, available: UnitSet) => Iterable<EntityState>);
|
|
43
|
+
/**
|
|
44
|
+
* What every part of a mission takes
|
|
45
|
+
*
|
|
46
|
+
* @beta
|
|
47
|
+
*/
|
|
48
|
+
export interface MissionPartOptions {
|
|
49
|
+
/**
|
|
50
|
+
* Its id: the module's, the goal's and the squad's, what the report and the log name it by. `mission.<part>:<place>`
|
|
51
|
+
* when left out (`mission.hold:camp`); give one where two parts of a kind share a place
|
|
52
|
+
*/
|
|
53
|
+
id?: string;
|
|
54
|
+
/** Which of its units it takes, once, as it is first picked: those at its place when left out (its fighters for `fleeWhen`) */
|
|
55
|
+
units?: MissionUnits;
|
|
56
|
+
/** Whether units that come later and fit `units` are taken too: no when left out (`waveFrom` always takes what comes) */
|
|
57
|
+
refill?: boolean;
|
|
58
|
+
/** Only while this holds: the part lets go of its units while it does not (a condition, as data or a function) */
|
|
59
|
+
when?: AiCondition;
|
|
60
|
+
/** What it is worth against the brain's other goals: 1 when left out (10 for `fleeWhen`) */
|
|
61
|
+
weight?: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* What a part remembers between thinks, as a save keeps it: its own units, and what its kind adds (an ambush's spring,
|
|
65
|
+
* a wave's count)
|
|
66
|
+
*
|
|
67
|
+
* @beta
|
|
68
|
+
*/
|
|
69
|
+
export interface MissionPartMemory {
|
|
70
|
+
v: 1;
|
|
71
|
+
/** Whether it took its units yet: they are taken once */
|
|
72
|
+
took: boolean;
|
|
73
|
+
/** Its own units, by id: what it takes back after a word or a rule had them */
|
|
74
|
+
units: number[];
|
|
75
|
+
/** An ambush: the tick it sprang at, while sprung; how many times it sprang; whether its `then` was done */
|
|
76
|
+
sprung?: number;
|
|
77
|
+
times?: number;
|
|
78
|
+
acted?: boolean;
|
|
79
|
+
/** A wave: how many were sent; the tick the last went at (or the part began at) */
|
|
80
|
+
sent?: number;
|
|
81
|
+
last?: number;
|
|
82
|
+
/** `surrenderWhen`: whether it gave up */
|
|
83
|
+
done?: boolean;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The mission brain's definition: a brain's (`BrainDef`) with the parts given as `modules`, after the ones every mission
|
|
87
|
+
* has. Its `id` is what a save remembers the seat by: list the brain in `GameModule.brains`
|
|
88
|
+
*
|
|
89
|
+
* @beta
|
|
90
|
+
*/
|
|
91
|
+
export interface MissionBrainDef extends BrainExtension {
|
|
92
|
+
id: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Its units hold a place: they go there, fight what comes within its reach (`radius`, or the region's size, else 10),
|
|
96
|
+
* and go back once it is gone. Its units: those at the place as it is first picked (within its reach and a little), or
|
|
97
|
+
* what `units` say
|
|
98
|
+
*
|
|
99
|
+
* @beta
|
|
100
|
+
*/
|
|
101
|
+
export declare function holdPosition(place: MissionPlace, options?: MissionPartOptions & {
|
|
102
|
+
radius?: number;
|
|
103
|
+
}): AiModuleDef;
|
|
104
|
+
/**
|
|
105
|
+
* Its units walk a round of places, one after the other and back to the first, fighting what they meet on the way. Its
|
|
106
|
+
* units: those near the first place as it is first picked, or what `units` say. Places it does not know are passed over
|
|
107
|
+
*
|
|
108
|
+
* @beta
|
|
109
|
+
*/
|
|
110
|
+
export declare function patrol(points: readonly MissionPlace[], options?: MissionPartOptions): AiModuleDef;
|
|
111
|
+
/**
|
|
112
|
+
* Its units stay by an entity, by its name (`world.named`) or its id: a unit they follow, a building they hold round
|
|
113
|
+
* (within `radius`, 12 when left out), fighting what comes near it. While the entity stands: once it is gone, its units
|
|
114
|
+
* are let go of. Its units: those near it as it is first picked (within 20), or what `units` say
|
|
115
|
+
*
|
|
116
|
+
* @beta
|
|
117
|
+
*/
|
|
118
|
+
export declare function guard(entity: string | number, options?: MissionPartOptions & {
|
|
119
|
+
radius?: number;
|
|
120
|
+
}): AiModuleDef;
|
|
121
|
+
/**
|
|
122
|
+
* What an ambush does once the fight it sprang is over: `return` to its place and wait again (the default), `stay`
|
|
123
|
+
* where it is, or an action (a word it tells itself, `{ say: 'attack' }`, or a function of the brain), done once
|
|
124
|
+
*
|
|
125
|
+
* @beta
|
|
126
|
+
*/
|
|
127
|
+
export type AmbushThen = 'return' | 'stay' | AiAction;
|
|
128
|
+
/**
|
|
129
|
+
* Its units wait at a place on hold (they hit what walks into reach and move for nothing), and spring once a rival's
|
|
130
|
+
* unit comes within `radius` of it (or once `trigger` holds): they go for the intruders, fighting what they meet. Once
|
|
131
|
+
* that fight is over, `then` (`AmbushThen`). `once`: it springs the first time only. Its units: those at the place as it
|
|
132
|
+
* is first picked, or what `units` say
|
|
133
|
+
*
|
|
134
|
+
* @beta
|
|
135
|
+
*/
|
|
136
|
+
export declare function ambush(place: MissionPlace, options?: MissionPartOptions & {
|
|
137
|
+
radius?: number;
|
|
138
|
+
trigger?: AiCondition;
|
|
139
|
+
then?: AmbushThen;
|
|
140
|
+
once?: boolean;
|
|
141
|
+
}): AiModuleDef;
|
|
142
|
+
/**
|
|
143
|
+
* Where a wave goes: a place (a point, or a name), or a function of the brain. The nearest building of a rival's it
|
|
144
|
+
* knows of when left out, else the nearest rival it sees, else the first base the seat was told (`AiOptions.enemyBases`)
|
|
145
|
+
*
|
|
146
|
+
* @beta
|
|
147
|
+
*/
|
|
148
|
+
export type MissionTarget = MissionPlace | ((ai: Brain) => Vec2 | undefined);
|
|
149
|
+
/**
|
|
150
|
+
* The units that come out of a spawner (what the mission's own rules spawn there, or what a building there trains),
|
|
151
|
+
* gathered there and sent as a wave: once there are as many as `group` says (a number, or so many of each type or
|
|
152
|
+
* role: `{ footman: 4, caster: 1 }`; 4 when left out), or, with `every`, every so many seconds with what has gathered
|
|
153
|
+
* (at least `minForces` of the group: a share, any when left out). A wave goes for `target` (`MissionTarget`) and, once
|
|
154
|
+
* that is cleared, for the next it knows of. `first`: seconds before the first wave may go (`every`, else none). Nothing
|
|
155
|
+
* is trained or built: a mission with no economy feeds it
|
|
156
|
+
*
|
|
157
|
+
* @beta
|
|
158
|
+
*/
|
|
159
|
+
export declare function waveFrom(source: MissionPlace, options?: Omit<MissionPartOptions, 'units' | 'refill'> & {
|
|
160
|
+
group?: number | Record<string, number>;
|
|
161
|
+
every?: number;
|
|
162
|
+
minForces?: number;
|
|
163
|
+
first?: number;
|
|
164
|
+
target?: MissionTarget;
|
|
165
|
+
radius?: number;
|
|
166
|
+
}): AiModuleDef;
|
|
167
|
+
/**
|
|
168
|
+
* When the condition holds, its units run: to `to` (a place), else home, else away from the nearest rival; and stand
|
|
169
|
+
* there while it holds. Once it no longer does, they are let go of, and the parts that had them take them back. An
|
|
170
|
+
* urgent goal worth 10: it takes its units from any other. Its units: its fighters, or what `units` say
|
|
171
|
+
*
|
|
172
|
+
* @beta
|
|
173
|
+
*/
|
|
174
|
+
export declare function fleeWhen(condition: AiCondition, options?: Omit<MissionPartOptions, 'refill'> & {
|
|
175
|
+
to?: MissionPlace;
|
|
176
|
+
}): AiModuleDef;
|
|
177
|
+
/**
|
|
178
|
+
* When the condition holds, the computer gives up: the engine's `surrender` command, as a player's, once. Out of the
|
|
179
|
+
* game as if beaten
|
|
180
|
+
*
|
|
181
|
+
* @beta
|
|
182
|
+
*/
|
|
183
|
+
export declare function surrenderWhen(condition: AiCondition, options?: {
|
|
184
|
+
id?: string;
|
|
185
|
+
}): AiModuleDef;
|
|
186
|
+
/**
|
|
187
|
+
* A computer player for a mission: a brain (`defineBrain`) of what every mission's computer has (its rules, the words
|
|
188
|
+
* every brain may be told, the goals' picker, squads, micro) and the parts it is given (`modules`: `holdPosition`,
|
|
189
|
+
* `patrol`, `guard`, `ambush`, `waveFrom`, `fleeWhen`, `surrenderWhen`, any module of the kit's or of its own). Nothing
|
|
190
|
+
* builds, trains, gathers, scouts or answers raids on its bases unless a module for it is given (`economy()`,
|
|
191
|
+
* `scouting()`, `defence()`). Everything else of `BrainDef` as for any brain (`goals`, `micro`, `without`, `knowledge`)
|
|
192
|
+
*
|
|
193
|
+
* @beta
|
|
194
|
+
*/
|
|
195
|
+
export declare function missionBrain(def: MissionBrainDef): BrainDef;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type MissionRule } from '#engine/missionRules';
|
|
2
|
+
import type { GamePack } from '#engine/packs/pack';
|
|
3
|
+
/**
|
|
4
|
+
* Mission rules as data (campaign plan MS1): the rules a map keeps (`MissionRule`, under `GameMap.data.rules`, written
|
|
5
|
+
* in the editor's Rules panel) run as the game plays, `rules` of the game's own code beside them. Each `when` a
|
|
6
|
+
* condition of the computer players' language holds (`docs/ai.md`), asked as a player, `do`es its actions
|
|
7
|
+
* (`MissionActionData`: an objective of the map's given, done or failed, a line said, a cinematic played, a prefab
|
|
8
|
+
* spawned, a computer told, a relation set, a timer started, win, lose). Checked once a second; what the rules
|
|
9
|
+
* remember is in the world's state, so a save mid-mission has it. The code reaches the rules with `tellRules` and hears
|
|
10
|
+
* them fire as `ruleFired`; the map's checks say what is wrong with them (`checkMissionRules`). Of `@v12-engine/engine/ai`, as
|
|
11
|
+
* a condition is asked of a watcher seated as the computer players are (`ruleWatcher`); the map objectives pack
|
|
12
|
+
* (`mapObjectives`) goes with it, for the objectives a rule gives
|
|
13
|
+
*
|
|
14
|
+
* @beta
|
|
15
|
+
*/
|
|
16
|
+
export declare function missionRules(options?: {
|
|
17
|
+
rules?: MissionRule[];
|
|
18
|
+
}): GamePack;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A module of a brain (`AiModule`): one part of a think, made for each brain (`defineModule`). Apart from the brain
|
|
3
|
+
* (`brain.ts`), which is made of them, so that a module and an area of the kit import this and the brain's type only,
|
|
4
|
+
* and the brain imports no module back
|
|
5
|
+
*/
|
|
6
|
+
import type { Brain } from './brain';
|
|
7
|
+
import type { AiReport } from './report';
|
|
8
|
+
/**
|
|
9
|
+
* One named part of a computer player's think (`defineBrain`'s `modules`). Modules run in their order each think, over
|
|
10
|
+
* the same picture of the game, each reading it through the brain it is handed (`ai.snapshot`, later `ai.view`) and
|
|
11
|
+
* acting through `ai.send`. A module is made for each brain (`AiModuleDef`: a function of the brain), so that what it
|
|
12
|
+
* keeps in itself is one seat's. What it remembers between thinks goes through `save` and `restore`, as plain data
|
|
13
|
+
*
|
|
14
|
+
* @beta
|
|
15
|
+
*/
|
|
16
|
+
export interface AiModule {
|
|
17
|
+
/** Unique in a brain: what its memory is kept under, what the timing and the debug tools name it by */
|
|
18
|
+
id: string;
|
|
19
|
+
/**
|
|
20
|
+
* The version of what it remembers (`save`): 1 when left out. Raised when the shape of it changes; a load that finds
|
|
21
|
+
* memory of another version gives it to `migrate`, or starts the module afresh where there is none
|
|
22
|
+
*/
|
|
23
|
+
version?: number;
|
|
24
|
+
/** Runs once in so many thinks, for work that does not need doing every think. Every think when left out */
|
|
25
|
+
everyThinks?: number;
|
|
26
|
+
/** With `everyThinks`, the think in each round it runs at: modules with the same `every` and other offsets spread the work */
|
|
27
|
+
offset?: number;
|
|
28
|
+
/**
|
|
29
|
+
* When in a think it runs (`AiPhase`): the brain runs its modules phase by phase, as listed within each. Left out,
|
|
30
|
+
* in the phase of the module listed before it (the first phase for the first)
|
|
31
|
+
*/
|
|
32
|
+
phase?: AiPhase;
|
|
33
|
+
/**
|
|
34
|
+
* Ids of modules of the brain this one runs ahead of, for what one phase needs within itself. Ids of modules the
|
|
35
|
+
* brain does not have are passed over
|
|
36
|
+
*/
|
|
37
|
+
before?: string[];
|
|
38
|
+
/** Ids of modules of the brain this one runs after, within its phase */
|
|
39
|
+
after?: string[];
|
|
40
|
+
/**
|
|
41
|
+
* Ids this module's memory was kept under before it was called what it is: a save made then gives it back under
|
|
42
|
+
* the old id, and it is read as this module's (through `migrate` where the version differs too)
|
|
43
|
+
*/
|
|
44
|
+
wasCalled?: string[];
|
|
45
|
+
/** Its part of the think */
|
|
46
|
+
think(ai: Brain): void;
|
|
47
|
+
/** What it remembers between thinks, as plain data for a save. Nothing (`undefined`) for a module that remembers nothing */
|
|
48
|
+
save?(): unknown;
|
|
49
|
+
/** Takes back what `save` gave, in a game loaded from a save */
|
|
50
|
+
restore?(data: unknown): void;
|
|
51
|
+
/**
|
|
52
|
+
* Brings what an earlier version of the module saved (`from`: its version) up to what this one takes. Nothing
|
|
53
|
+
* (`undefined`) says it cannot be brought up, and the module starts afresh; so does a module without `migrate`
|
|
54
|
+
*/
|
|
55
|
+
migrate?(data: unknown, from: number): unknown;
|
|
56
|
+
/**
|
|
57
|
+
* What it is thinking, as plain data, for the debug tools: what the report has no part for, kept under the module's
|
|
58
|
+
* id in its `sections` (`Brain.report`)
|
|
59
|
+
*/
|
|
60
|
+
inspect?(): unknown;
|
|
61
|
+
/**
|
|
62
|
+
* Writes its part of the report (`Brain.report`), where the report has a part for it: a kit's module fills the part
|
|
63
|
+
* it names (its squads, its plans). Plain data only
|
|
64
|
+
*/
|
|
65
|
+
report?(report: AiReport): void;
|
|
66
|
+
/** Lets go of what it holds outside the brain when the computer is unseated */
|
|
67
|
+
dispose?(): void;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The phases of a think, in the order they run (`AiModule.phase`): `hear` what it was told and its rules, `sense`
|
|
71
|
+
* what threatens it and its team, `plan` its economy, buildings and training, `decide` what its own goals are, `act`
|
|
72
|
+
* the picker, the squads and the waves, `fight` the micro
|
|
73
|
+
*
|
|
74
|
+
* @beta
|
|
75
|
+
*/
|
|
76
|
+
export declare const AI_PHASES: readonly ['hear', 'sense', 'plan', 'decide', 'act', 'fight'];
|
|
77
|
+
/**
|
|
78
|
+
* A phase of a think (`AI_PHASES`)
|
|
79
|
+
*
|
|
80
|
+
* @beta
|
|
81
|
+
*/
|
|
82
|
+
export type AiPhase = (typeof AI_PHASES)[number];
|
|
83
|
+
/**
|
|
84
|
+
* What finds a module of a brain with its shape (`ai.module(key)`): its id, typed. The kit's are `MELEE_ARMY` and
|
|
85
|
+
* `LANES`; a game makes its own with `moduleKey`
|
|
86
|
+
*
|
|
87
|
+
* @beta
|
|
88
|
+
*/
|
|
89
|
+
export interface ModuleKey<M extends AiModule> {
|
|
90
|
+
readonly id: string;
|
|
91
|
+
/** The shape the module has: never set, for the type alone */
|
|
92
|
+
readonly shape?: M;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* A key to a module of a game's own (`ai.module(key)` gives it with its shape)
|
|
96
|
+
*
|
|
97
|
+
* @beta
|
|
98
|
+
*/
|
|
99
|
+
export declare function moduleKey<M extends AiModule>(id: string): ModuleKey<M>;
|
|
100
|
+
/**
|
|
101
|
+
* A module of a brain: made for each brain by a function of it, so that two brains never share one; or one as it is,
|
|
102
|
+
* for a module that keeps nothing. A function made with `defineModule` carries the module's id before it is made,
|
|
103
|
+
* which is how `BrainDef.without` names it
|
|
104
|
+
*
|
|
105
|
+
* @beta
|
|
106
|
+
*/
|
|
107
|
+
export type AiModuleDef = AiModule | (((ai: Brain) => AiModule) & {
|
|
108
|
+
id?: string;
|
|
109
|
+
});
|
|
110
|
+
/**
|
|
111
|
+
* A module made for each brain by a function of it, with its id known before it is made: what a brain's `without`
|
|
112
|
+
* leaves out by name (`meleeBrain.with({ without: ['scouting'] })`). The kit's modules are all defined so
|
|
113
|
+
*
|
|
114
|
+
* @beta
|
|
115
|
+
*/
|
|
116
|
+
export declare function defineModule(id: string, make: (ai: Brain) => AiModule): AiModuleDef;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Vec2 } from '#engine/math';
|
|
2
|
+
import type { GoalDef } from './goals';
|
|
3
|
+
import type { ThinkBudgetOptions } from './budget';
|
|
4
|
+
import type { RolesFinder } from './roles';
|
|
5
|
+
import type { AiSettings } from './settings';
|
|
6
|
+
import type { StrengthFormula } from './strength';
|
|
7
|
+
/**
|
|
8
|
+
* What a computer player is seated with (`world.computers.seat`): where its rivals started, its
|
|
9
|
+
* difficulty, its personality and its settings (`Brain.options`). The data in it (numbers, lists, names) is kept
|
|
10
|
+
* in a save with the seat; a function given as an option is not (`world.computers.seat` says what becomes of it)
|
|
11
|
+
*
|
|
12
|
+
* @beta
|
|
13
|
+
*/
|
|
14
|
+
export interface AiOptions {
|
|
15
|
+
/** Where opponents started. Known to everyone at the start of a game, as in classic RTS games. A brain that goes by what it sees does without */
|
|
16
|
+
enemyBases?: Vec2[];
|
|
17
|
+
/** Seconds between thinks. What the brain says when left out: its profile's (the difficulty's), 1 for a brain that says nothing */
|
|
18
|
+
every?: number;
|
|
19
|
+
/**
|
|
20
|
+
* How much of a think one tick may do (`ThinkBudgetOptions`): so many of the brain's modules, so many units looked at
|
|
21
|
+
* as they say, a think with more going on at the next tick over the same picture of the game, so that no tick does
|
|
22
|
+
* all of it; and the milliseconds a module is warned over. Counted in work, never in milliseconds, so that the game is
|
|
23
|
+
* the same on every machine. Over the profile's (`AiProfile.budget`); a number is the modules a tick. Everything in
|
|
24
|
+
* one tick when left out. Data
|
|
25
|
+
*/
|
|
26
|
+
budget?: number | ThinkBudgetOptions;
|
|
27
|
+
/**
|
|
28
|
+
* Goals of the game's own, picked with the engine's each turn (`ai.goals`): a goal that scores itself from
|
|
29
|
+
* considerations and claims units (`defineGoal`). A raid on workers, holding a hill, escorting a caravan. Code: not kept
|
|
30
|
+
* in a save; a brain's own goals are (`meleeBrain.with({ goals })`, `GameModule.brains`)
|
|
31
|
+
*/
|
|
32
|
+
goals?: GoalDef[];
|
|
33
|
+
/**
|
|
34
|
+
* How hard it plays (`easy`, `normal`, `hard`, `insane`, or a game's own: `GameModule.ai.difficulties`): how often it thinks, when it first attacks
|
|
35
|
+
* and how many it sends, how far it comes to defend, how many workers it keeps, how many commands a think, how often
|
|
36
|
+
* it slips, whether it sees through the fog (`insane`). A layer of the profile (`AiProfile`): the personality's, the
|
|
37
|
+
* map's and the seat's settings go over it. `normal` when left out
|
|
38
|
+
*/
|
|
39
|
+
difficulty?: string;
|
|
40
|
+
/**
|
|
41
|
+
* How it likes to play (`balanced`, `rusher`, `turtle`, `expander`, `harasser`, or a game's own: `GameModule.ai.personalities`):
|
|
42
|
+
* the weights of its goals, when it attacks and expands, its towers. Over the difficulty. `balanced` when left out
|
|
43
|
+
*/
|
|
44
|
+
personality?: string;
|
|
45
|
+
/**
|
|
46
|
+
* The seat's own settings (`AiSettings`, keyed by area: `{ economy: { workers: 6 }, army: { firstAttack: 90 },
|
|
47
|
+
* flags: { kite: false } }`): the top layer, over the personality and the map's (`MapAi.settings`). Data, but for a
|
|
48
|
+
* flag given as a function
|
|
49
|
+
*/
|
|
50
|
+
settings?: AiSettings;
|
|
51
|
+
/**
|
|
52
|
+
* What the game's unit types are for, found the game's way (`RolesFinder`): in place of what the kit infers from
|
|
53
|
+
* the definitions (`inferRoles`); what a type declares (`UnitTypeDef.ai`) goes over either. Code: not kept in a save
|
|
54
|
+
*/
|
|
55
|
+
roles?: RolesFinder;
|
|
56
|
+
/**
|
|
57
|
+
* How strong a unit is, in place of the kit's formula (`defaultStrength`): what `odds`, `matchup`, the threat map and
|
|
58
|
+
* `UnitSet.strength()` are made of. Being code, it is not kept in a save: a brain's own goes in `BrainDef.strength`
|
|
59
|
+
*/
|
|
60
|
+
strength?: StrengthFormula;
|
|
61
|
+
}
|