@vibemancer/core 0.1.0 → 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.
Files changed (50) hide show
  1. package/README.md +28 -28
  2. package/dist/{chunk-L7Z7OFXD.js → chunk-7VDJHO22.js} +3 -3
  3. package/dist/chunk-7VDJHO22.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,128 +1,128 @@
1
- import {WizardState, MissileConfig, ProjectileState} from '../types.js';
2
- import {
3
- SHIELD_MAX_BLOCK,
4
- SHIELD_DECAY_PER_SECOND,
5
- SHIELD_MIN_BLOCK,
6
- TICKS_PER_SECOND,
7
- GCD_DURATION,
8
- SHIELD_CAST_TIME,
9
- BLINK_CAST_TIME,
10
- calculateMissileCastTime,
11
- calculateWarmupMultiplier,
12
- } from '../rules.js';
13
-
14
- /**
15
- * Start casting a spell.
16
- * For missiles, applies warmup system (bonus for similar, penalty for switching).
17
- */
18
- export function startCast(wizard: WizardState, spell: 'missile' | 'shield' | 'blink', config?: MissileConfig): void
19
- {
20
- wizard.state = 'casting';
21
- wizard.castingSpell = spell;
22
- wizard.castProgress = 0;
23
-
24
- if (spell === 'missile' && config)
25
- {
26
- // calculateMissileCastTime includes warmup when lastMissileConfig is passed
27
- const castTimeSec = calculateMissileCastTime(config, wizard.lastMissileConfig);
28
- wizard.castDuration = Math.max(1, Math.round(castTimeSec * TICKS_PER_SECOND));
29
- // Store warmup multiplier for visualization
30
- wizard.warmupMultiplier = calculateWarmupMultiplier(wizard.lastMissileConfig, config);
31
- }
32
- else if (spell === 'shield')
33
- {
34
- wizard.castDuration = SHIELD_CAST_TIME;
35
- }
36
- else if (spell === 'blink')
37
- {
38
- wizard.castDuration = BLINK_CAST_TIME;
39
- }
40
- }
41
-
42
- /**
43
- * Cancel the current cast.
44
- */
45
- export function cancelCast(wizard: WizardState): void
46
- {
47
- wizard.state = 'idle';
48
- delete wizard.castingSpell;
49
- delete wizard.castProgress;
50
- delete wizard.castDuration;
51
- }
52
-
53
- /**
54
- * Complete the current cast and trigger the spell effect.
55
- */
56
- export function completeCast(wizard: WizardState): void
57
- {
58
- const spell = wizard.castingSpell;
59
-
60
- if (spell === 'shield')
61
- {
62
- wizard.state = 'channeling';
63
- wizard.channelingSpell = 'shield';
64
- wizard.channelDuration = 0;
65
- }
66
- else if (spell === 'missile')
67
- {
68
- wizard.state = 'gcd_locked';
69
- wizard.gcdRemaining = GCD_DURATION;
70
- }
71
- else
72
- {
73
- // Blink: no GCD — can act immediately after teleporting
74
- wizard.state = 'idle';
75
- }
76
-
77
- delete wizard.castingSpell;
78
- delete wizard.castProgress;
79
- delete wizard.castDuration;
80
- }
81
-
82
- /**
83
- * Update the shield channel state.
84
- */
85
- export function updateShield(wizard: WizardState, deltaTicks: number): void
86
- {
87
- if (wizard.state === 'channeling' && wizard.channelingSpell === 'shield')
88
- {
89
- wizard.channelDuration = (wizard.channelDuration ?? 0) + deltaTicks;
90
- }
91
- }
92
-
93
- /**
94
- * Calculate the current block percentage of a shield based on channel duration.
95
- */
96
- export function calculateShieldBlock(channelDurationTicks: number): number
97
- {
98
- const channelSeconds = channelDurationTicks / TICKS_PER_SECOND;
99
- const decay = channelSeconds * SHIELD_DECAY_PER_SECOND;
100
- return Math.max(SHIELD_MIN_BLOCK, SHIELD_MAX_BLOCK - decay);
101
- }
102
-
103
- /**
104
- * Apply damage to a wizard, considering shield mitigation.
105
- *
106
- * Shield blocks a percentage of damage based on channel duration:
107
- * - Fresh shield (0s): 90% block → 10% damage through
108
- * - Decayed shield: block % decreases over time (20%/sec)
109
- * - Minimum: 30% block → 70% damage through
110
- *
111
- * (Design doc lines 196-212)
112
- */
113
- export function applyDamage(wizard: WizardState, damage: number, _projectile?: ProjectileState): number
114
- {
115
- if (wizard.invincible) return 0;
116
-
117
- let finalDamage = damage;
118
-
119
- if (wizard.state === 'channeling' && wizard.channelingSpell === 'shield')
120
- {
121
- const blockPercent = calculateShieldBlock(wizard.channelDuration ?? 0);
122
- // Simple block: damage through = damage * (1 - blockPercent)
123
- finalDamage = damage * (1 - blockPercent);
124
- }
125
-
126
- wizard.health = Math.max(0, wizard.health - finalDamage);
127
- return finalDamage;
128
- }
1
+ import {WizardState, MissileConfig, ProjectileState} from '../types.js';
2
+ import {
3
+ SHIELD_MAX_BLOCK,
4
+ SHIELD_DECAY_PER_SECOND,
5
+ SHIELD_MIN_BLOCK,
6
+ TICKS_PER_SECOND,
7
+ GCD_DURATION,
8
+ SHIELD_CAST_TIME,
9
+ BLINK_CAST_TIME,
10
+ calculateMissileCastTime,
11
+ calculateWarmupMultiplier,
12
+ } from '../rules.js';
13
+
14
+ /**
15
+ * Start casting a spell.
16
+ * For missiles, applies warmup system (bonus for similar, penalty for switching).
17
+ */
18
+ export function startCast(wizard: WizardState, spell: 'missile' | 'shield' | 'blink', config?: MissileConfig): void
19
+ {
20
+ wizard.state = 'casting';
21
+ wizard.castingSpell = spell;
22
+ wizard.castProgress = 0;
23
+
24
+ if (spell === 'missile' && config)
25
+ {
26
+ // calculateMissileCastTime includes warmup when lastMissileConfig is passed
27
+ const castTimeSec = calculateMissileCastTime(config, wizard.lastMissileConfig);
28
+ wizard.castDuration = Math.max(1, Math.round(castTimeSec * TICKS_PER_SECOND));
29
+ // Store warmup multiplier for visualization
30
+ wizard.warmupMultiplier = calculateWarmupMultiplier(wizard.lastMissileConfig, config);
31
+ }
32
+ else if (spell === 'shield')
33
+ {
34
+ wizard.castDuration = SHIELD_CAST_TIME;
35
+ }
36
+ else if (spell === 'blink')
37
+ {
38
+ wizard.castDuration = BLINK_CAST_TIME;
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Cancel the current cast.
44
+ */
45
+ export function cancelCast(wizard: WizardState): void
46
+ {
47
+ wizard.state = 'idle';
48
+ delete wizard.castingSpell;
49
+ delete wizard.castProgress;
50
+ delete wizard.castDuration;
51
+ }
52
+
53
+ /**
54
+ * Complete the current cast and trigger the spell effect.
55
+ */
56
+ export function completeCast(wizard: WizardState): void
57
+ {
58
+ const spell = wizard.castingSpell;
59
+
60
+ if (spell === 'shield')
61
+ {
62
+ wizard.state = 'channeling';
63
+ wizard.channelingSpell = 'shield';
64
+ wizard.channelDuration = 0;
65
+ }
66
+ else if (spell === 'missile')
67
+ {
68
+ wizard.state = 'gcd_locked';
69
+ wizard.gcdRemaining = GCD_DURATION;
70
+ }
71
+ else
72
+ {
73
+ // Blink: no GCD — can act immediately after teleporting
74
+ wizard.state = 'idle';
75
+ }
76
+
77
+ delete wizard.castingSpell;
78
+ delete wizard.castProgress;
79
+ delete wizard.castDuration;
80
+ }
81
+
82
+ /**
83
+ * Update the shield channel state.
84
+ */
85
+ export function updateShield(wizard: WizardState, deltaTicks: number): void
86
+ {
87
+ if (wizard.state === 'channeling' && wizard.channelingSpell === 'shield')
88
+ {
89
+ wizard.channelDuration = (wizard.channelDuration ?? 0) + deltaTicks;
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Calculate the current block percentage of a shield based on channel duration.
95
+ */
96
+ export function calculateShieldBlock(channelDurationTicks: number): number
97
+ {
98
+ const channelSeconds = channelDurationTicks / TICKS_PER_SECOND;
99
+ const decay = channelSeconds * SHIELD_DECAY_PER_SECOND;
100
+ return Math.max(SHIELD_MIN_BLOCK, SHIELD_MAX_BLOCK - decay);
101
+ }
102
+
103
+ /**
104
+ * Apply damage to a wizard, considering shield mitigation.
105
+ *
106
+ * Shield blocks a percentage of damage based on channel duration:
107
+ * - Fresh shield (0s): 90% block → 10% damage through
108
+ * - Decayed shield: block % decreases over time (20%/sec)
109
+ * - Minimum: 30% block → 70% damage through
110
+ *
111
+ * (Design doc lines 196-212)
112
+ */
113
+ export function applyDamage(wizard: WizardState, damage: number, _projectile?: ProjectileState): number
114
+ {
115
+ if (wizard.invincible) return 0;
116
+
117
+ let finalDamage = damage;
118
+
119
+ if (wizard.state === 'channeling' && wizard.channelingSpell === 'shield')
120
+ {
121
+ const blockPercent = calculateShieldBlock(wizard.channelDuration ?? 0);
122
+ // Simple block: damage through = damage * (1 - blockPercent)
123
+ finalDamage = damage * (1 - blockPercent);
124
+ }
125
+
126
+ wizard.health = Math.max(0, wizard.health - finalDamage);
127
+ return finalDamage;
128
+ }
@@ -8,4 +8,4 @@
8
8
  * Used to gate spectator replays: a recorded match can only be re-simulated when
9
9
  * the runtime engine version matches the version that produced the match.
10
10
  */
11
- export const ENGINE_VERSION = 1777556890699;
11
+ export const ENGINE_VERSION = 1777570524251;
package/src/index.ts CHANGED
@@ -1,24 +1,24 @@
1
- export * from './types.js';
2
- export * from './rules.js';
3
- export * from './engine-version.js';
4
- export * from './engine/simulation.js';
5
- export * from './engine/hooks-runtime.js';
6
- export * from './engine/physics.js';
7
- export * from './engine/spells.js';
8
- export * from './engine/manual-match.js';
9
- export * from './engine/missile-templates.js';
10
- export * from './utils/index.js';
11
- export * from './bots/index.js';
12
- export * from './hooks/index.js';
13
- export * from './engine/params-runtime.js';
14
- export * from './engine/optimizer.js';
15
- export {BotBundle, compileMatchBundle, MatchSandbox, sandboxFight, sandboxSimulate} from './engine/sandbox.js';
16
- export type {CompileOptions, SandboxOptions} from './engine/sandbox.js';
17
- export {BrowserMatchSandbox, BrowserManualMatchSandbox, browserSandboxFight, browserSandboxSimulate, createWorkerScript} from './engine/sandbox-browser.js';
18
- export type {BrowserSandboxOptions, ManualMatchInitOptions, ManualMatchStepRequest, WorkerFactory, WorkerLike} from './engine/sandbox-browser.js';
19
- export {testBot} from './testing.js';
20
- export {extractStats, formatStats} from './stats.js';
21
- export type {FightStats} from './stats.js';
22
- export {extractTraceEvents, summarizeTrace, formatTraceEvents, formatTraceSummary, diagnoseTrace, formatDiagnosis} from './trace.js';
23
- export type {TraceEvent, TraceEventType, TraceSummary, TraceBotSummary} from './trace.js';
1
+ export * from './types.js';
2
+ export * from './rules.js';
3
+ export * from './engine-version.js';
4
+ export * from './engine/simulation.js';
5
+ export * from './engine/hooks-runtime.js';
6
+ export * from './engine/physics.js';
7
+ export * from './engine/spells.js';
8
+ export * from './engine/manual-match.js';
9
+ export * from './engine/missile-templates.js';
10
+ export * from './utils/index.js';
11
+ export * from './bots/index.js';
12
+ export * from './hooks/index.js';
13
+ export * from './engine/params-runtime.js';
14
+ export * from './engine/optimizer.js';
15
+ export {BotBundle, compileMatchBundle, MatchSandbox, sandboxFight, sandboxSimulate} from './engine/sandbox.js';
16
+ export type {CompileOptions, SandboxOptions} from './engine/sandbox.js';
17
+ export {BrowserMatchSandbox, BrowserManualMatchSandbox, browserSandboxFight, browserSandboxSimulate, createWorkerScript} from './engine/sandbox-browser.js';
18
+ export type {BrowserSandboxOptions, ManualMatchInitOptions, ManualMatchStepRequest, WorkerFactory, WorkerLike} from './engine/sandbox-browser.js';
19
+ export {testBot} from './testing.js';
20
+ export {extractStats, formatStats} from './stats.js';
21
+ export type {FightStats} from './stats.js';
22
+ export {extractTraceEvents, summarizeTrace, formatTraceEvents, formatTraceSummary, diagnoseTrace, formatDiagnosis} from './trace.js';
23
+ export type {TraceEvent, TraceEventType, TraceSummary, TraceBotSummary} from './trace.js';
24
24
  export type {TestBotBuilder, TestFightResult, TestSimulateResult} from './testing.js';