@vibemancer/core 0.1.0 → 0.1.2

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 (50) hide show
  1. package/README.md +28 -28
  2. package/dist/{chunk-L7Z7OFXD.js → chunk-OL7ETV6V.js} +3 -3
  3. package/dist/chunk-OL7ETV6V.js.map +1 -0
  4. package/dist/index-browser.d.ts +1 -1
  5. package/dist/index-browser.js +1 -1
  6. package/dist/index.js +1 -1
  7. package/package.json +79 -78
  8. package/src/bots/berserker/01_Stormchaser.ts +457 -457
  9. package/src/bots/berserker/02_Stormcaller.ts +417 -417
  10. package/src/bots/berserker/03_Stormforger.ts +481 -481
  11. package/src/bots/caster/01_Flamecaller.ts +286 -286
  12. package/src/bots/caster/02_Pyromancer.ts +350 -350
  13. package/src/bots/caster/03_Infernalist.ts +492 -492
  14. package/src/bots/defensive/01_Turtle.ts +151 -151
  15. package/src/bots/defensive/02_Sentinel.ts +134 -134
  16. package/src/bots/defensive/03_Golem.ts +357 -357
  17. package/src/bots/duelist/01_Battlemage.ts +433 -433
  18. package/src/bots/duelist/02_Warmage.ts +438 -438
  19. package/src/bots/duelist/03_Archmage.ts +588 -588
  20. package/src/bots/homing/01_Bonemancer.ts +67 -67
  21. package/src/bots/homing/02_Lich.ts +356 -356
  22. package/src/bots/homing/03_Archlich.ts +220 -220
  23. package/src/bots/kiter/01_Spellspinner.ts +398 -398
  24. package/src/bots/kiter/02_Spellweaver.ts +378 -378
  25. package/src/bots/kiter/03_Spellbinder.ts +448 -448
  26. package/src/bots/melee/01_Shadowblade.ts +270 -270
  27. package/src/bots/melee/02_Nightblade.ts +437 -437
  28. package/src/bots/melee/03_Voidblade.ts +582 -582
  29. package/src/bots/sniper/01_Spellshot.ts +385 -385
  30. package/src/bots/sniper/02_Spelltracer.ts +441 -441
  31. package/src/bots/sniper/03_Spellseeker.ts +546 -546
  32. package/src/bots/standalone/Critter.ts +89 -89
  33. package/src/bots/standalone/Doombringer.ts +91 -91
  34. package/src/bots/standalone/Hogger.ts +228 -228
  35. package/src/bots/standalone/Rookie.ts +50 -50
  36. package/src/bots/standalone/TargetDummy.ts +21 -21
  37. package/src/bots/test/cheater.ts +405 -405
  38. package/src/bots/test/crasher.ts +81 -81
  39. package/src/engine/hooks-runtime.ts +394 -394
  40. package/src/engine/manual-match.ts +289 -289
  41. package/src/engine/missile-templates.ts +155 -155
  42. package/src/engine/physics.ts +143 -143
  43. package/src/engine/simulation.ts +828 -828
  44. package/src/engine/spells.ts +128 -128
  45. package/src/engine-version.ts +1 -1
  46. package/src/index.ts +23 -23
  47. package/src/rules.ts +254 -254
  48. package/src/types.ts +193 -193
  49. package/src/utils/index.ts +6 -6
  50. package/dist/chunk-L7Z7OFXD.js.map +0 -1
@@ -1,89 +1,89 @@
1
- import {WizardFunction} from '../../types.js';
2
- import {ARENA_WIDTH, ARENA_HEIGHT} from '../../rules.js';
3
-
4
- /**
5
- * Bot: Critter
6
- *
7
- * BEHAVIOR: Picks random valid actions each tick — random movement, random spells,
8
- * random missile configs, random directions. Occasionally cancels its own casts.
9
- * Uses engine-provided seeded random for deterministic behavior. Useful for
10
- * finding edge cases in the engine, but completely useless in combat.
11
- *
12
- * NAMING RATIONALE: In WoW, critters are the 1-HP ambient mobs (rabbits, squirrels,
13
- * prairie dogs) that wander around doing nothing useful and die to literally anything.
14
- * This bot is the wizard equivalent — it flails around randomly and gets destroyed by
15
- * anyone with a plan. The word "Critter" immediately tells any gamer "this thing is
16
- * helpless and exists only to fill space."
17
- *
18
- * STANDALONE — no tier progression. Critters don't level up. However, a future
19
- * "Hogger" bot could be an elite critter: same chaotic spirit but actually dangerous
20
- * (like the famous WoW elite that wipes unprepared lowbies).
21
- */
22
- export const Critter: WizardFunction = ({state, random}) =>
23
- {
24
- // Use the engine-provided random function (seeded, isolated, deterministic)
25
- // World-space movement: random x/y in [-100, 100] range
26
- const move = {
27
- x: random() * 200 - 100, // -100 to 100
28
- y: random() * 200 - 100, // -100 to 100
29
- };
30
-
31
- if (state.state === 'idle' && random() > 0.95)
32
- {
33
- const spellRoll = random();
34
- if (spellRoll > 0.6)
35
- {
36
- return {
37
- move,
38
- startCast: {
39
- spell: 'missile',
40
- config: {
41
- damage: Math.floor(random() * 20) + 5,
42
- speed: random() * 5 + 2,
43
- turnRate: random() * 3,
44
- duration: Math.floor(random() * 200) + 100,
45
- },
46
- // Missile AI gets its own random from engine - use it for random targeting
47
- missileAI: ({random: missileRandom}) => ({
48
- turnToward:
49
- missileRandom() > 0.5
50
- ? {
51
- x: missileRandom() * ARENA_WIDTH,
52
- y: missileRandom() * ARENA_HEIGHT,
53
- }
54
- : undefined,
55
- }),
56
- direction: random() * 360,
57
- },
58
- };
59
- }
60
- else if (spellRoll > 0.3)
61
- {
62
- return {
63
- move,
64
- startCast: {spell: 'shield'},
65
- };
66
- }
67
- else if (state.blinkCooldown === 0)
68
- {
69
- return {
70
- move,
71
- startCast: {
72
- spell: 'blink',
73
- target: {x: random() * ARENA_WIDTH, y: random() * ARENA_HEIGHT},
74
- },
75
- };
76
- }
77
- }
78
-
79
- if (
80
- (state.state === 'casting' || state.state === 'channeling') &&
81
- random() > 0.98
82
- )
83
- {
84
- return {move, cancel: true};
85
- }
86
-
87
- // Override auto-aim with random direction — Critter doesn't know where anything is
88
- return {move, aimDirection: random() * 360};
89
- };
1
+ import {WizardFunction} from '../../types.js';
2
+ import {ARENA_WIDTH, ARENA_HEIGHT} from '../../rules.js';
3
+
4
+ /**
5
+ * Bot: Critter
6
+ *
7
+ * BEHAVIOR: Picks random valid actions each tick — random movement, random spells,
8
+ * random missile configs, random directions. Occasionally cancels its own casts.
9
+ * Uses engine-provided seeded random for deterministic behavior. Useful for
10
+ * finding edge cases in the engine, but completely useless in combat.
11
+ *
12
+ * NAMING RATIONALE: In WoW, critters are the 1-HP ambient mobs (rabbits, squirrels,
13
+ * prairie dogs) that wander around doing nothing useful and die to literally anything.
14
+ * This bot is the wizard equivalent — it flails around randomly and gets destroyed by
15
+ * anyone with a plan. The word "Critter" immediately tells any gamer "this thing is
16
+ * helpless and exists only to fill space."
17
+ *
18
+ * STANDALONE — no tier progression. Critters don't level up. However, a future
19
+ * "Hogger" bot could be an elite critter: same chaotic spirit but actually dangerous
20
+ * (like the famous WoW elite that wipes unprepared lowbies).
21
+ */
22
+ export const Critter: WizardFunction = ({state, random}) =>
23
+ {
24
+ // Use the engine-provided random function (seeded, isolated, deterministic)
25
+ // World-space movement: random x/y in [-100, 100] range
26
+ const move = {
27
+ x: random() * 200 - 100, // -100 to 100
28
+ y: random() * 200 - 100, // -100 to 100
29
+ };
30
+
31
+ if (state.state === 'idle' && random() > 0.95)
32
+ {
33
+ const spellRoll = random();
34
+ if (spellRoll > 0.6)
35
+ {
36
+ return {
37
+ move,
38
+ startCast: {
39
+ spell: 'missile',
40
+ config: {
41
+ damage: Math.floor(random() * 20) + 5,
42
+ speed: random() * 5 + 2,
43
+ turnRate: random() * 3,
44
+ duration: Math.floor(random() * 200) + 100,
45
+ },
46
+ // Missile AI gets its own random from engine - use it for random targeting
47
+ missileAI: ({random: missileRandom}) => ({
48
+ turnToward:
49
+ missileRandom() > 0.5
50
+ ? {
51
+ x: missileRandom() * ARENA_WIDTH,
52
+ y: missileRandom() * ARENA_HEIGHT,
53
+ }
54
+ : undefined,
55
+ }),
56
+ direction: random() * 360,
57
+ },
58
+ };
59
+ }
60
+ else if (spellRoll > 0.3)
61
+ {
62
+ return {
63
+ move,
64
+ startCast: {spell: 'shield'},
65
+ };
66
+ }
67
+ else if (state.blinkCooldown === 0)
68
+ {
69
+ return {
70
+ move,
71
+ startCast: {
72
+ spell: 'blink',
73
+ target: {x: random() * ARENA_WIDTH, y: random() * ARENA_HEIGHT},
74
+ },
75
+ };
76
+ }
77
+ }
78
+
79
+ if (
80
+ (state.state === 'casting' || state.state === 'channeling') &&
81
+ random() > 0.98
82
+ )
83
+ {
84
+ return {move, cancel: true};
85
+ }
86
+
87
+ // Override auto-aim with random direction — Critter doesn't know where anything is
88
+ return {move, aimDirection: random() * 360};
89
+ };
@@ -1,91 +1,91 @@
1
- import {WizardFunction, MissileAIFunction} from '../../types.js';
2
- import {angleTo} from '../../utils/angles.js';
3
- import {distanceTo} from '../../utils/distance.js';
4
- import {fitMissileToBudget} from '../../utils/combat.js';
5
- import {
6
- getThreats,
7
- getMostUrgentThreat,
8
- getBlinkToCenter,
9
- } from '../shared.js';
10
-
11
- const HomingAI: MissileAIFunction = ({worldState}) =>
12
- {
13
- const enemy = worldState.enemies[0];
14
- return {turnToward: enemy?.position};
15
- };
16
-
17
- /**
18
- * Bot: Doombringer
19
- *
20
- * BEHAVIOR: Fires a single maximum-damage homing missile with infinite budget.
21
- * No damage cap — goes for the biggest possible hit. Exists as a benchmark to
22
- * demonstrate why lower-damage + shield play is superior. Has basic shield
23
- * defense but no sophisticated tactics. One fat cast, one fat hit.
24
- *
25
- * STANDALONE — no tier progression. Benchmark/test bot.
26
- */
27
- export const Doombringer: WizardFunction = ({state}) =>
28
- {
29
- const enemy = state.enemies[0];
30
- if (!enemy)
31
- {
32
- return {move: {x: 0, y: 0}};
33
- }
34
-
35
- const distance = distanceTo(state.position, enemy.position);
36
- const threats = getThreats(state);
37
- const urgentThreat = getMostUrgentThreat(threats);
38
-
39
- // === DEFENSE: Handle channeling ===
40
- if (state.state === 'channeling')
41
- {
42
- if (!urgentThreat || urgentThreat.ticksToImpact > 150)
43
- {
44
- return {move: {x: 0, y: 0}, cancel: true};
45
- }
46
- return {move: {x: 0, y: 0}};
47
- }
48
-
49
- // === DEFENSE: Shield undodgeable threats ===
50
- if (
51
- state.state === 'idle' &&
52
- urgentThreat &&
53
- !urgentThreat.bestDodgeDirection
54
- )
55
- {
56
- if (urgentThreat.canBlockInTime && urgentThreat.ticksToStartShield <= 3)
57
- {
58
- return {
59
- move: {x: 0, y: 0},
60
- startCast: {spell: 'shield'},
61
- };
62
- }
63
- else if (!urgentThreat.canBlockInTime && state.blinkCooldown === 0)
64
- {
65
- return {
66
- move: {x: 0, y: 0},
67
- startCast: {spell: 'blink', target: getBlinkToCenter(state.position)},
68
- };
69
- }
70
- }
71
-
72
- // === OFFENSE: Fire max-damage homing missile (no damage cap) ===
73
- if (state.state === 'idle')
74
- {
75
- const config = fitMissileToBudget(Infinity, distance, {minTurnRate: 0.5});
76
- if (config)
77
- {
78
- return {
79
- move: {x: 0, y: 0},
80
- startCast: {
81
- spell: 'missile',
82
- config,
83
- missileAI: HomingAI,
84
- direction: angleTo(state.position, enemy.position),
85
- },
86
- };
87
- }
88
- }
89
-
90
- return {move: {x: 0, y: 0}};
91
- };
1
+ import {WizardFunction, MissileAIFunction} from '../../types.js';
2
+ import {angleTo} from '../../utils/angles.js';
3
+ import {distanceTo} from '../../utils/distance.js';
4
+ import {fitMissileToBudget} from '../../utils/combat.js';
5
+ import {
6
+ getThreats,
7
+ getMostUrgentThreat,
8
+ getBlinkToCenter,
9
+ } from '../shared.js';
10
+
11
+ const HomingAI: MissileAIFunction = ({worldState}) =>
12
+ {
13
+ const enemy = worldState.enemies[0];
14
+ return {turnToward: enemy?.position};
15
+ };
16
+
17
+ /**
18
+ * Bot: Doombringer
19
+ *
20
+ * BEHAVIOR: Fires a single maximum-damage homing missile with infinite budget.
21
+ * No damage cap — goes for the biggest possible hit. Exists as a benchmark to
22
+ * demonstrate why lower-damage + shield play is superior. Has basic shield
23
+ * defense but no sophisticated tactics. One fat cast, one fat hit.
24
+ *
25
+ * STANDALONE — no tier progression. Benchmark/test bot.
26
+ */
27
+ export const Doombringer: WizardFunction = ({state}) =>
28
+ {
29
+ const enemy = state.enemies[0];
30
+ if (!enemy)
31
+ {
32
+ return {move: {x: 0, y: 0}};
33
+ }
34
+
35
+ const distance = distanceTo(state.position, enemy.position);
36
+ const threats = getThreats(state);
37
+ const urgentThreat = getMostUrgentThreat(threats);
38
+
39
+ // === DEFENSE: Handle channeling ===
40
+ if (state.state === 'channeling')
41
+ {
42
+ if (!urgentThreat || urgentThreat.ticksToImpact > 150)
43
+ {
44
+ return {move: {x: 0, y: 0}, cancel: true};
45
+ }
46
+ return {move: {x: 0, y: 0}};
47
+ }
48
+
49
+ // === DEFENSE: Shield undodgeable threats ===
50
+ if (
51
+ state.state === 'idle' &&
52
+ urgentThreat &&
53
+ !urgentThreat.bestDodgeDirection
54
+ )
55
+ {
56
+ if (urgentThreat.canBlockInTime && urgentThreat.ticksToStartShield <= 3)
57
+ {
58
+ return {
59
+ move: {x: 0, y: 0},
60
+ startCast: {spell: 'shield'},
61
+ };
62
+ }
63
+ else if (!urgentThreat.canBlockInTime && state.blinkCooldown === 0)
64
+ {
65
+ return {
66
+ move: {x: 0, y: 0},
67
+ startCast: {spell: 'blink', target: getBlinkToCenter(state.position)},
68
+ };
69
+ }
70
+ }
71
+
72
+ // === OFFENSE: Fire max-damage homing missile (no damage cap) ===
73
+ if (state.state === 'idle')
74
+ {
75
+ const config = fitMissileToBudget(Infinity, distance, {minTurnRate: 0.5});
76
+ if (config)
77
+ {
78
+ return {
79
+ move: {x: 0, y: 0},
80
+ startCast: {
81
+ spell: 'missile',
82
+ config,
83
+ missileAI: HomingAI,
84
+ direction: angleTo(state.position, enemy.position),
85
+ },
86
+ };
87
+ }
88
+ }
89
+
90
+ return {move: {x: 0, y: 0}};
91
+ };