@vibemancer/core 1.0.5 → 1.0.6

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.
@@ -608,7 +608,7 @@ declare function currentRuleset(): Record<string, number>;
608
608
  * Used to gate spectator replays: a recorded match can only be re-simulated when
609
609
  * the runtime engine version matches the version that produced the match.
610
610
  */
611
- declare const ENGINE_VERSION = 4396905295552957;
611
+ declare const ENGINE_VERSION = 1688330189011034;
612
612
 
613
613
  /**
614
614
  * VIBEMANCER — BOT COMPUTE BUDGET
@@ -1289,8 +1289,20 @@ declare function directionTo(from: Position, to: Position): Position;
1289
1289
  */
1290
1290
  declare function directionAway(from: Position, to: Position): Position;
1291
1291
  /**
1292
- * Clamp a position to valid arena bounds.
1293
- * Note: For wizard-specific clamping with radius, use clampToArena from physics.ts
1292
+ * Clamp a position into the arena rectangle — [0, ARENA_SIZE] on both axes.
1293
+ *
1294
+ * READ THIS BEFORE USING IT FOR SAFETY. It does NOT keep a wizard alive. The arena includes
1295
+ * the 30-unit lava border, so clamping to it can hand you back a coordinate that is deep
1296
+ * inside the lava — for example (0, 0), which is lethal. It used to be documented as
1297
+ * clamping to "valid arena bounds", which reads like exactly the safety helper it is not:
1298
+ * a player sanitising a blink target with this will blink into the fire.
1299
+ *
1300
+ * To stay ALIVE you want the safe box for a wizard's CENTRE, which is
1301
+ * [ARENA_MIN + WIZARD_RADIUS, ARENA_MAX - WIZARD_RADIUS] — currently [35, 825], because
1302
+ * `isInLava` tests your edge rather than your centre.
1303
+ *
1304
+ * For the engine's own wizard clamp (arena bounds minus the radius, still not lava-safe),
1305
+ * see clampToArena in physics.ts.
1294
1306
  */
1295
1307
  declare function clampPositionToArena(position: Position): Position;
1296
1308
  /**
@@ -1413,7 +1425,13 @@ declare function useHealth(): number;
1413
1425
  * Clamped to [5, 855] — the ARENA bounds minus the wizard radius, NOT the playfield. That
1414
1426
  * distinction is the difference between living and dying: the playfield is [30, 830] and
1415
1427
  * everything outside it is lava, so you can walk straight out of the safe area and be
1416
- * killed. Nothing stops you. Check against ARENA_MIN/ARENA_MAX, not against these numbers.
1428
+ * killed. Nothing stops you.
1429
+ *
1430
+ * And the number you actually need is neither of those. Lava is tested against your EDGE,
1431
+ * not your centre (`isInLava` checks `x + WIZARD_RADIUS > ARENA_MAX`), and this returns your
1432
+ * CENTRE — so with a radius of 5 you die once your centre passes 825. The safe range to
1433
+ * steer by is [35, 825]. Aiming for 828 because "the playfield is [30, 830]" is fatal, which
1434
+ * is exactly what a real fight trace showed: LAVA_DEATH at (826, 430).
1417
1435
  *
1418
1436
  * (This previously quoted the playfield-sized bounds as the clamp, which told the reader
1419
1437
  * they were safely fenced in. They are not — see docs-match-engine.test.ts.)
@@ -1 +1 @@
1
- export { A as ALL_BOTS, a as ARENA_MAX, b as ARENA_MIN, c as ARENA_SIZE, d as ARENA_WATER_BUFFER, e as ActionBuilder, f as AnalyzedThreat, g as Archlich, h as Archmage, B as BLINK_CAST_TIME, i as BLINK_COOLDOWN, j as BLINK_MAX_COOLDOWN, k as BLINK_MAX_RANGE, l as BLINK_MIN_COOLDOWN, m as BLINK_RANGE, n as BOT_GROUPS, o as Battlemage, p as BlinkEvent, q as Bonemancer, s as BotError, t as BrowserManualMatchSandbox, u as BrowserMatchSandbox, v as BrowserSandboxOptions, C as CASTING_MOVEMENT_MULT, x as COLLISION_RADIUS, y as CastCancelEvent, z as CastStartEvent, D as Critter, H as DEFAULT_SEED, I as Doombringer, J as ENGINE_VERSION, K as EnemyState, L as FIGHT_SPAWN_DISTANCES, F as FightResult, N as FightStats, O as FightWinner, P as FinalAction, Q as Flamecaller, R as GCD_DURATION, T as GameConfig, U as GameState, V as Golem, W as Hero, X as Hogger, Y as HomingParams, Z as HookState, _ as Infernalist, $ as InternalWizardState, a0 as KNOCKBACK_DAMAGE_THRESHOLD, a1 as KNOCKBACK_DECAY, a2 as KNOCKBACK_DELAY, a3 as KNOCKBACK_SPEED_PER_DAMAGE, a4 as LAVA_BORDER_WIDTH, a5 as Lich, a6 as MATCH_DURATION, a7 as MAX_HEALTH, a8 as MISSILE_BASE_CAST, a9 as MISSILE_BASE_RADIUS, aa as MISSILE_DAMAGE_POWER, ab as MISSILE_DAMAGE_RADIUS_SCALE, ac as MISSILE_DAMAGE_SCALE, ad as MISSILE_HOMING_COEFF, ae as MISSILE_MIN_CAST_TIME, af as MISSILE_MIN_DAMAGE, ag as MISSILE_MIN_DURATION, ah as MISSILE_MIN_SPEED, ai as MISSILE_RADIUS_PER_DAMAGE, aj as MISSILE_SPEED_DURATION_BASELINE, ak as MISSILE_SPEED_DURATION_COEFF, al as MISSILE_TURN_DURATION_COEFF, am as MOVEMENT_SPEED, an as MOVE_SPEED, ao as ManualMatch, ap as ManualMatchInitOptions, aq as ManualMatchOptions, ar as ManualMatchStepRequest, as as MatchWinner, at as MissileAction, au as MissileActions, av as MissileConfig, aw as MissileContext, ax as MissileExpiredEvent, ay as MissileFunction, az as MissileHitEvent, aA as MissileLaunchEvent, aB as MissileOobEvent, aC as MissileTemplate, aD as Nightblade, aE as ParamDeclaration, aF as Position, aG as ProjectileState, aH as Pyromancer, aI as RULES, aJ as RULESET_RANGES, aK as RefObject, aL as Rookie, aM as SHIELD_CAST_TIME, aN as SHIELD_DECAY_PER_SECOND, aO as SHIELD_DECAY_RATE, aP as SHIELD_MAX_BLOCK, aQ as SHIELD_MAX_STRENGTH, aR as SHIELD_MIN_BLOCK, aS as SHIELD_MIN_STRENGTH, aT as SPAWN_DISTANCE, aU as SeekerParams, aV as Sentinel, aW as Shadowblade, aX as ShieldBlockEvent, aY as ShieldStartEvent, aZ as SimEvent, S as SimulateResult, a_ as Spellbinder, a$ as Spellseeker, b0 as Spellshot, b1 as Spellspinner, b2 as Spelltracer, b3 as Spellweaver, b4 as SpiralParams, b5 as StepResult, b6 as Stormcaller, b7 as Stormchaser, b8 as Stormforger, b9 as StraightParams, ba as TICKS_PER_SECOND, bb as TICK_DURATION_MS, bc as TargetDummy, bd as TestBotBuilder, be as TestFightResult, bf as TestSimulateResult, bg as TraceBotSummary, bh as TraceEvent, bi as TraceEventType, bj as TraceSummary, bk as Turtle, bl as Velocity, bm as Voidblade, bn as WARMUP_DURATION_TOLERANCE, bo as WARMUP_MAX_BONUS, bp as WARMUP_MAX_PENALTY, bq as WARMUP_SPEED_TOLERANCE, br as WARMUP_TURN_TOLERANCE, bs as WIZARD_HEALTH, bt as WIZARD_RADIUS, bu as Warmage, bv as WizardActions, bw as WizardContext, bx as WizardDeathEvent, by as WizardEntry, bz as WizardFunction, bA as WizardGroup, bB as WizardLavaDeathEvent, bC as WizardState, bD as WorkerFactory, bE as WorkerLike, bF as analyzeThreats, bG as angleDiff, bH as angleInRange, bI as angleTo, bJ as applyDamage, bK as applyRulesetOverrides, bL as blink, bM as browserSandboxFight, bN as browserSandboxSimulate, bO as calculateBlinkCooldown, bP as calculateMissileCastTime, bQ as calculateMissileRadius, bR as calculateMissileSimilarity, bS as calculateShieldBlock, bT as calculateWarmupMultiplier, bU as cancel, bV as cancelCast, bW as clampPositionToArena, bX as clampToArena, bY as clearHooks, bZ as clearParamValues, b_ as completeCast, c0 as createEntitySeed, c2 as createInitialState, c3 as createRandom, c4 as createWorkerScript, c5 as currentRuleset, c6 as diagnoseTrace, c7 as directionAway, c8 as directionTo, c9 as distanceTo, ca as effectiveTurnRateCost, cb as extractAction, cc as extractMissileAction, cd as extractStats, ce as extractTraceEvents, cf as fight, cg as findInRange, ch as findNearest, ci as fitMissileForEscapingTarget, cj as fitMissileToBudget, ck as flyStraight, cl as formatDiagnosis, cm as formatStats, cn as formatTraceEvents, co as formatTraceSummary, cp as generateCandidates, cq as generateCombos, cr as getAdaptiveMissileConfig, cs as getEffectiveRange, ct as getLeadPosition, cu as getMissileCastTime, cv as getMissileContext, cw as getPlayerState, cx as getWizardContext, cy as hashCombine, cz as homingMissile, cA as idle, cB as inRange, cC as interceptAngle, cD as isBannedBotName, cE as isInLava, cF as magnitude, cG as matchesAnyBanRule, cI as missile, cJ as move, cK as moveInDirection, cL as moveProjectile, cM as moveWizard, cN as narrowRange, cO as nextRandom, cP as normalize, cQ as normalizeAngle, cR as predictPosition, cT as resetAllHooks, cU as resetRuleset, cV as resolveWizardCollision, cW as runWithHooks, cX as runWizardWithContext, cY as scoreFight, cZ as scoreFightAsWizard2, c_ as seekerMissile, c$ as setParamValues, d0 as shield, d1 as simulate, d2 as simulateMinDuration, d3 as sortByDistance, d4 as spiralMissile, d5 as startCast, d6 as startDiscovery, d7 as stopDiscovery, d8 as straightMissile, d9 as summarizeTrace, da as sweptCircleCollision, db as testBot, dc as tick, dd as turnToAngle, de as turnToward, df as updateShield, dg as useArenaSize, dh as useBlinkCooldown, di as useCastProgress, dj as useCastingSpell, dk as useClosestThreat, dl as useDamageDealt, dm as useDamageTaken, dn as useEffect, dp as useEnemy, dq as useHealth, dr as useLastHitTick, ds as useLastMissileConfig, dt as useMemo, du as useMyProjectiles, dv as useMyThreatsToEnemy, dw as useParam, dx as usePosition, dy as useProjectiles, dz as useRandom, dA as useRef, dB as useShieldStrength, dC as useState, dD as useStatus, dE as useThreats, dF as useTick, dG as useTicksUntilReady, dH as useVelocity, dI as validateHookCall, dJ as validateMissileConfig, dK as withMissileContext, dL as withWizardContext, dM as wrapWithParams } from './index-browser-AFWi8jxB.js';
1
+ export { A as ALL_BOTS, a as ARENA_MAX, b as ARENA_MIN, c as ARENA_SIZE, d as ARENA_WATER_BUFFER, e as ActionBuilder, f as AnalyzedThreat, g as Archlich, h as Archmage, B as BLINK_CAST_TIME, i as BLINK_COOLDOWN, j as BLINK_MAX_COOLDOWN, k as BLINK_MAX_RANGE, l as BLINK_MIN_COOLDOWN, m as BLINK_RANGE, n as BOT_GROUPS, o as Battlemage, p as BlinkEvent, q as Bonemancer, s as BotError, t as BrowserManualMatchSandbox, u as BrowserMatchSandbox, v as BrowserSandboxOptions, C as CASTING_MOVEMENT_MULT, x as COLLISION_RADIUS, y as CastCancelEvent, z as CastStartEvent, D as Critter, H as DEFAULT_SEED, I as Doombringer, J as ENGINE_VERSION, K as EnemyState, L as FIGHT_SPAWN_DISTANCES, F as FightResult, N as FightStats, O as FightWinner, P as FinalAction, Q as Flamecaller, R as GCD_DURATION, T as GameConfig, U as GameState, V as Golem, W as Hero, X as Hogger, Y as HomingParams, Z as HookState, _ as Infernalist, $ as InternalWizardState, a0 as KNOCKBACK_DAMAGE_THRESHOLD, a1 as KNOCKBACK_DECAY, a2 as KNOCKBACK_DELAY, a3 as KNOCKBACK_SPEED_PER_DAMAGE, a4 as LAVA_BORDER_WIDTH, a5 as Lich, a6 as MATCH_DURATION, a7 as MAX_HEALTH, a8 as MISSILE_BASE_CAST, a9 as MISSILE_BASE_RADIUS, aa as MISSILE_DAMAGE_POWER, ab as MISSILE_DAMAGE_RADIUS_SCALE, ac as MISSILE_DAMAGE_SCALE, ad as MISSILE_HOMING_COEFF, ae as MISSILE_MIN_CAST_TIME, af as MISSILE_MIN_DAMAGE, ag as MISSILE_MIN_DURATION, ah as MISSILE_MIN_SPEED, ai as MISSILE_RADIUS_PER_DAMAGE, aj as MISSILE_SPEED_DURATION_BASELINE, ak as MISSILE_SPEED_DURATION_COEFF, al as MISSILE_TURN_DURATION_COEFF, am as MOVEMENT_SPEED, an as MOVE_SPEED, ao as ManualMatch, ap as ManualMatchInitOptions, aq as ManualMatchOptions, ar as ManualMatchStepRequest, as as MatchWinner, at as MissileAction, au as MissileActions, av as MissileConfig, aw as MissileContext, ax as MissileExpiredEvent, ay as MissileFunction, az as MissileHitEvent, aA as MissileLaunchEvent, aB as MissileOobEvent, aC as MissileTemplate, aD as Nightblade, aE as ParamDeclaration, aF as Position, aG as ProjectileState, aH as Pyromancer, aI as RULES, aJ as RULESET_RANGES, aK as RefObject, aL as Rookie, aM as SHIELD_CAST_TIME, aN as SHIELD_DECAY_PER_SECOND, aO as SHIELD_DECAY_RATE, aP as SHIELD_MAX_BLOCK, aQ as SHIELD_MAX_STRENGTH, aR as SHIELD_MIN_BLOCK, aS as SHIELD_MIN_STRENGTH, aT as SPAWN_DISTANCE, aU as SeekerParams, aV as Sentinel, aW as Shadowblade, aX as ShieldBlockEvent, aY as ShieldStartEvent, aZ as SimEvent, S as SimulateResult, a_ as Spellbinder, a$ as Spellseeker, b0 as Spellshot, b1 as Spellspinner, b2 as Spelltracer, b3 as Spellweaver, b4 as SpiralParams, b5 as StepResult, b6 as Stormcaller, b7 as Stormchaser, b8 as Stormforger, b9 as StraightParams, ba as TICKS_PER_SECOND, bb as TICK_DURATION_MS, bc as TargetDummy, bd as TestBotBuilder, be as TestFightResult, bf as TestSimulateResult, bg as TraceBotSummary, bh as TraceEvent, bi as TraceEventType, bj as TraceSummary, bk as Turtle, bl as Velocity, bm as Voidblade, bn as WARMUP_DURATION_TOLERANCE, bo as WARMUP_MAX_BONUS, bp as WARMUP_MAX_PENALTY, bq as WARMUP_SPEED_TOLERANCE, br as WARMUP_TURN_TOLERANCE, bs as WIZARD_HEALTH, bt as WIZARD_RADIUS, bu as Warmage, bv as WizardActions, bw as WizardContext, bx as WizardDeathEvent, by as WizardEntry, bz as WizardFunction, bA as WizardGroup, bB as WizardLavaDeathEvent, bC as WizardState, bD as WorkerFactory, bE as WorkerLike, bF as analyzeThreats, bG as angleDiff, bH as angleInRange, bI as angleTo, bJ as applyDamage, bK as applyRulesetOverrides, bL as blink, bM as browserSandboxFight, bN as browserSandboxSimulate, bO as calculateBlinkCooldown, bP as calculateMissileCastTime, bQ as calculateMissileRadius, bR as calculateMissileSimilarity, bS as calculateShieldBlock, bT as calculateWarmupMultiplier, bU as cancel, bV as cancelCast, bW as clampPositionToArena, bX as clampToArena, bY as clearHooks, bZ as clearParamValues, b_ as completeCast, c0 as createEntitySeed, c2 as createInitialState, c3 as createRandom, c4 as createWorkerScript, c5 as currentRuleset, c6 as diagnoseTrace, c7 as directionAway, c8 as directionTo, c9 as distanceTo, ca as effectiveTurnRateCost, cb as extractAction, cc as extractMissileAction, cd as extractStats, ce as extractTraceEvents, cf as fight, cg as findInRange, ch as findNearest, ci as fitMissileForEscapingTarget, cj as fitMissileToBudget, ck as flyStraight, cl as formatDiagnosis, cm as formatStats, cn as formatTraceEvents, co as formatTraceSummary, cp as generateCandidates, cq as generateCombos, cr as getAdaptiveMissileConfig, cs as getEffectiveRange, ct as getLeadPosition, cu as getMissileCastTime, cv as getMissileContext, cw as getPlayerState, cx as getWizardContext, cy as hashCombine, cz as homingMissile, cA as idle, cB as inRange, cC as interceptAngle, cD as isBannedBotName, cE as isInLava, cF as magnitude, cG as matchesAnyBanRule, cI as missile, cJ as move, cK as moveInDirection, cL as moveProjectile, cM as moveWizard, cN as narrowRange, cO as nextRandom, cP as normalize, cQ as normalizeAngle, cR as predictPosition, cT as resetAllHooks, cU as resetRuleset, cV as resolveWizardCollision, cW as runWithHooks, cX as runWizardWithContext, cY as scoreFight, cZ as scoreFightAsWizard2, c_ as seekerMissile, c$ as setParamValues, d0 as shield, d1 as simulate, d2 as simulateMinDuration, d3 as sortByDistance, d4 as spiralMissile, d5 as startCast, d6 as startDiscovery, d7 as stopDiscovery, d8 as straightMissile, d9 as summarizeTrace, da as sweptCircleCollision, db as testBot, dc as tick, dd as turnToAngle, de as turnToward, df as updateShield, dg as useArenaSize, dh as useBlinkCooldown, di as useCastProgress, dj as useCastingSpell, dk as useClosestThreat, dl as useDamageDealt, dm as useDamageTaken, dn as useEffect, dp as useEnemy, dq as useHealth, dr as useLastHitTick, ds as useLastMissileConfig, dt as useMemo, du as useMyProjectiles, dv as useMyThreatsToEnemy, dw as useParam, dx as usePosition, dy as useProjectiles, dz as useRandom, dA as useRef, dB as useShieldStrength, dC as useState, dD as useStatus, dE as useThreats, dF as useTick, dG as useTicksUntilReady, dH as useVelocity, dI as validateHookCall, dJ as validateMissileConfig, dK as withMissileContext, dL as withWizardContext, dM as wrapWithParams } from './index-browser-q0eR90H1.js';
@@ -223,7 +223,7 @@ import {
223
223
  withMissileContext,
224
224
  withWizardContext,
225
225
  wrapWithParams
226
- } from "./chunk-NEXWZU5I.js";
226
+ } from "./chunk-M6E6IP7L.js";
227
227
  export {
228
228
  ALL_BOTS,
229
229
  ARENA_MAX,
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FightResult, S as SimulateResult } from './index-browser-AFWi8jxB.js';
2
- export { A as ALL_BOTS, a as ARENA_MAX, b as ARENA_MIN, c as ARENA_SIZE, d as ARENA_WATER_BUFFER, e as ActionBuilder, f as AnalyzedThreat, g as Archlich, h as Archmage, B as BLINK_CAST_TIME, i as BLINK_COOLDOWN, j as BLINK_MAX_COOLDOWN, k as BLINK_MAX_RANGE, l as BLINK_MIN_COOLDOWN, m as BLINK_RANGE, n as BOT_GROUPS, o as Battlemage, p as BlinkEvent, q as Bonemancer, r as BotBudgetState, s as BotError, t as BrowserManualMatchSandbox, u as BrowserMatchSandbox, v as BrowserSandboxOptions, w as BudgetLimits, C as CASTING_MOVEMENT_MULT, x as COLLISION_RADIUS, y as CastCancelEvent, z as CastStartEvent, D as Critter, E as DEFAULT_BUDGET, G as DEFAULT_FIGHT_BACKSTOP_MS, H as DEFAULT_SEED, I as Doombringer, J as ENGINE_VERSION, K as EnemyState, L as FIGHT_SPAWN_DISTANCES, M as FightBudget, N as FightStats, O as FightWinner, P as FinalAction, Q as Flamecaller, R as GCD_DURATION, T as GameConfig, U as GameState, V as Golem, W as Hero, X as Hogger, Y as HomingParams, Z as HookState, _ as Infernalist, $ as InternalWizardState, a0 as KNOCKBACK_DAMAGE_THRESHOLD, a1 as KNOCKBACK_DECAY, a2 as KNOCKBACK_DELAY, a3 as KNOCKBACK_SPEED_PER_DAMAGE, a4 as LAVA_BORDER_WIDTH, a5 as Lich, a6 as MATCH_DURATION, a7 as MAX_HEALTH, a8 as MISSILE_BASE_CAST, a9 as MISSILE_BASE_RADIUS, aa as MISSILE_DAMAGE_POWER, ab as MISSILE_DAMAGE_RADIUS_SCALE, ac as MISSILE_DAMAGE_SCALE, ad as MISSILE_HOMING_COEFF, ae as MISSILE_MIN_CAST_TIME, af as MISSILE_MIN_DAMAGE, ag as MISSILE_MIN_DURATION, ah as MISSILE_MIN_SPEED, ai as MISSILE_RADIUS_PER_DAMAGE, aj as MISSILE_SPEED_DURATION_BASELINE, ak as MISSILE_SPEED_DURATION_COEFF, al as MISSILE_TURN_DURATION_COEFF, am as MOVEMENT_SPEED, an as MOVE_SPEED, ao as ManualMatch, ap as ManualMatchInitOptions, aq as ManualMatchOptions, ar as ManualMatchStepRequest, as as MatchWinner, at as MissileAction, au as MissileActions, av as MissileConfig, aw as MissileContext, ax as MissileExpiredEvent, ay as MissileFunction, az as MissileHitEvent, aA as MissileLaunchEvent, aB as MissileOobEvent, aC as MissileTemplate, aD as Nightblade, aE as ParamDeclaration, aF as Position, aG as ProjectileState, aH as Pyromancer, aI as RULES, aJ as RULESET_RANGES, aK as RefObject, aL as Rookie, aM as SHIELD_CAST_TIME, aN as SHIELD_DECAY_PER_SECOND, aO as SHIELD_DECAY_RATE, aP as SHIELD_MAX_BLOCK, aQ as SHIELD_MAX_STRENGTH, aR as SHIELD_MIN_BLOCK, aS as SHIELD_MIN_STRENGTH, aT as SPAWN_DISTANCE, aU as SeekerParams, aV as Sentinel, aW as Shadowblade, aX as ShieldBlockEvent, aY as ShieldStartEvent, aZ as SimEvent, a_ as Spellbinder, a$ as Spellseeker, b0 as Spellshot, b1 as Spellspinner, b2 as Spelltracer, b3 as Spellweaver, b4 as SpiralParams, b5 as StepResult, b6 as Stormcaller, b7 as Stormchaser, b8 as Stormforger, b9 as StraightParams, ba as TICKS_PER_SECOND, bb as TICK_DURATION_MS, bc as TargetDummy, bd as TestBotBuilder, be as TestFightResult, bf as TestSimulateResult, bg as TraceBotSummary, bh as TraceEvent, bi as TraceEventType, bj as TraceSummary, bk as Turtle, bl as Velocity, bm as Voidblade, bn as WARMUP_DURATION_TOLERANCE, bo as WARMUP_MAX_BONUS, bp as WARMUP_MAX_PENALTY, bq as WARMUP_SPEED_TOLERANCE, br as WARMUP_TURN_TOLERANCE, bs as WIZARD_HEALTH, bt as WIZARD_RADIUS, bu as Warmage, bv as WizardActions, bw as WizardContext, bx as WizardDeathEvent, by as WizardEntry, bz as WizardFunction, bA as WizardGroup, bB as WizardLavaDeathEvent, bC as WizardState, bD as WorkerFactory, bE as WorkerLike, bF as analyzeThreats, bG as angleDiff, bH as angleInRange, bI as angleTo, bJ as applyDamage, bK as applyRulesetOverrides, bL as blink, bM as browserSandboxFight, bN as browserSandboxSimulate, bO as calculateBlinkCooldown, bP as calculateMissileCastTime, bQ as calculateMissileRadius, bR as calculateMissileSimilarity, bS as calculateShieldBlock, bT as calculateWarmupMultiplier, bU as cancel, bV as cancelCast, bW as clampPositionToArena, bX as clampToArena, bY as clearHooks, bZ as clearParamValues, b_ as completeCast, b$ as createBudgetState, c0 as createEntitySeed, c1 as createFightBudget, c2 as createInitialState, c3 as createRandom, c4 as createWorkerScript, c5 as currentRuleset, c6 as diagnoseTrace, c7 as directionAway, c8 as directionTo, c9 as distanceTo, ca as effectiveTurnRateCost, cb as extractAction, cc as extractMissileAction, cd as extractStats, ce as extractTraceEvents, cf as fight, cg as findInRange, ch as findNearest, ci as fitMissileForEscapingTarget, cj as fitMissileToBudget, ck as flyStraight, cl as formatDiagnosis, cm as formatStats, cn as formatTraceEvents, co as formatTraceSummary, cp as generateCandidates, cq as generateCombos, cr as getAdaptiveMissileConfig, cs as getEffectiveRange, ct as getLeadPosition, cu as getMissileCastTime, cv as getMissileContext, cw as getPlayerState, cx as getWizardContext, cy as hashCombine, cz as homingMissile, cA as idle, cB as inRange, cC as interceptAngle, cD as isBannedBotName, cE as isInLava, cF as magnitude, cG as matchesAnyBanRule, cH as mayAct, cI as missile, cJ as move, cK as moveInDirection, cL as moveProjectile, cM as moveWizard, cN as narrowRange, cO as nextRandom, cP as normalize, cQ as normalizeAngle, cR as predictPosition, cS as recordSpend, cT as resetAllHooks, cU as resetRuleset, cV as resolveWizardCollision, cW as runWithHooks, cX as runWizardWithContext, cY as scoreFight, cZ as scoreFightAsWizard2, c_ as seekerMissile, c$ as setParamValues, d0 as shield, d1 as simulate, d2 as simulateMinDuration, d3 as sortByDistance, d4 as spiralMissile, d5 as startCast, d6 as startDiscovery, d7 as stopDiscovery, d8 as straightMissile, d9 as summarizeTrace, da as sweptCircleCollision, db as testBot, dc as tick, dd as turnToAngle, de as turnToward, df as updateShield, dg as useArenaSize, dh as useBlinkCooldown, di as useCastProgress, dj as useCastingSpell, dk as useClosestThreat, dl as useDamageDealt, dm as useDamageTaken, dn as useEffect, dp as useEnemy, dq as useHealth, dr as useLastHitTick, ds as useLastMissileConfig, dt as useMemo, du as useMyProjectiles, dv as useMyThreatsToEnemy, dw as useParam, dx as usePosition, dy as useProjectiles, dz as useRandom, dA as useRef, dB as useShieldStrength, dC as useState, dD as useStatus, dE as useThreats, dF as useTick, dG as useTicksUntilReady, dH as useVelocity, dI as validateHookCall, dJ as validateMissileConfig, dK as withMissileContext, dL as withWizardContext, dM as wrapWithParams } from './index-browser-AFWi8jxB.js';
1
+ import { F as FightResult, S as SimulateResult } from './index-browser-q0eR90H1.js';
2
+ export { A as ALL_BOTS, a as ARENA_MAX, b as ARENA_MIN, c as ARENA_SIZE, d as ARENA_WATER_BUFFER, e as ActionBuilder, f as AnalyzedThreat, g as Archlich, h as Archmage, B as BLINK_CAST_TIME, i as BLINK_COOLDOWN, j as BLINK_MAX_COOLDOWN, k as BLINK_MAX_RANGE, l as BLINK_MIN_COOLDOWN, m as BLINK_RANGE, n as BOT_GROUPS, o as Battlemage, p as BlinkEvent, q as Bonemancer, r as BotBudgetState, s as BotError, t as BrowserManualMatchSandbox, u as BrowserMatchSandbox, v as BrowserSandboxOptions, w as BudgetLimits, C as CASTING_MOVEMENT_MULT, x as COLLISION_RADIUS, y as CastCancelEvent, z as CastStartEvent, D as Critter, E as DEFAULT_BUDGET, G as DEFAULT_FIGHT_BACKSTOP_MS, H as DEFAULT_SEED, I as Doombringer, J as ENGINE_VERSION, K as EnemyState, L as FIGHT_SPAWN_DISTANCES, M as FightBudget, N as FightStats, O as FightWinner, P as FinalAction, Q as Flamecaller, R as GCD_DURATION, T as GameConfig, U as GameState, V as Golem, W as Hero, X as Hogger, Y as HomingParams, Z as HookState, _ as Infernalist, $ as InternalWizardState, a0 as KNOCKBACK_DAMAGE_THRESHOLD, a1 as KNOCKBACK_DECAY, a2 as KNOCKBACK_DELAY, a3 as KNOCKBACK_SPEED_PER_DAMAGE, a4 as LAVA_BORDER_WIDTH, a5 as Lich, a6 as MATCH_DURATION, a7 as MAX_HEALTH, a8 as MISSILE_BASE_CAST, a9 as MISSILE_BASE_RADIUS, aa as MISSILE_DAMAGE_POWER, ab as MISSILE_DAMAGE_RADIUS_SCALE, ac as MISSILE_DAMAGE_SCALE, ad as MISSILE_HOMING_COEFF, ae as MISSILE_MIN_CAST_TIME, af as MISSILE_MIN_DAMAGE, ag as MISSILE_MIN_DURATION, ah as MISSILE_MIN_SPEED, ai as MISSILE_RADIUS_PER_DAMAGE, aj as MISSILE_SPEED_DURATION_BASELINE, ak as MISSILE_SPEED_DURATION_COEFF, al as MISSILE_TURN_DURATION_COEFF, am as MOVEMENT_SPEED, an as MOVE_SPEED, ao as ManualMatch, ap as ManualMatchInitOptions, aq as ManualMatchOptions, ar as ManualMatchStepRequest, as as MatchWinner, at as MissileAction, au as MissileActions, av as MissileConfig, aw as MissileContext, ax as MissileExpiredEvent, ay as MissileFunction, az as MissileHitEvent, aA as MissileLaunchEvent, aB as MissileOobEvent, aC as MissileTemplate, aD as Nightblade, aE as ParamDeclaration, aF as Position, aG as ProjectileState, aH as Pyromancer, aI as RULES, aJ as RULESET_RANGES, aK as RefObject, aL as Rookie, aM as SHIELD_CAST_TIME, aN as SHIELD_DECAY_PER_SECOND, aO as SHIELD_DECAY_RATE, aP as SHIELD_MAX_BLOCK, aQ as SHIELD_MAX_STRENGTH, aR as SHIELD_MIN_BLOCK, aS as SHIELD_MIN_STRENGTH, aT as SPAWN_DISTANCE, aU as SeekerParams, aV as Sentinel, aW as Shadowblade, aX as ShieldBlockEvent, aY as ShieldStartEvent, aZ as SimEvent, a_ as Spellbinder, a$ as Spellseeker, b0 as Spellshot, b1 as Spellspinner, b2 as Spelltracer, b3 as Spellweaver, b4 as SpiralParams, b5 as StepResult, b6 as Stormcaller, b7 as Stormchaser, b8 as Stormforger, b9 as StraightParams, ba as TICKS_PER_SECOND, bb as TICK_DURATION_MS, bc as TargetDummy, bd as TestBotBuilder, be as TestFightResult, bf as TestSimulateResult, bg as TraceBotSummary, bh as TraceEvent, bi as TraceEventType, bj as TraceSummary, bk as Turtle, bl as Velocity, bm as Voidblade, bn as WARMUP_DURATION_TOLERANCE, bo as WARMUP_MAX_BONUS, bp as WARMUP_MAX_PENALTY, bq as WARMUP_SPEED_TOLERANCE, br as WARMUP_TURN_TOLERANCE, bs as WIZARD_HEALTH, bt as WIZARD_RADIUS, bu as Warmage, bv as WizardActions, bw as WizardContext, bx as WizardDeathEvent, by as WizardEntry, bz as WizardFunction, bA as WizardGroup, bB as WizardLavaDeathEvent, bC as WizardState, bD as WorkerFactory, bE as WorkerLike, bF as analyzeThreats, bG as angleDiff, bH as angleInRange, bI as angleTo, bJ as applyDamage, bK as applyRulesetOverrides, bL as blink, bM as browserSandboxFight, bN as browserSandboxSimulate, bO as calculateBlinkCooldown, bP as calculateMissileCastTime, bQ as calculateMissileRadius, bR as calculateMissileSimilarity, bS as calculateShieldBlock, bT as calculateWarmupMultiplier, bU as cancel, bV as cancelCast, bW as clampPositionToArena, bX as clampToArena, bY as clearHooks, bZ as clearParamValues, b_ as completeCast, b$ as createBudgetState, c0 as createEntitySeed, c1 as createFightBudget, c2 as createInitialState, c3 as createRandom, c4 as createWorkerScript, c5 as currentRuleset, c6 as diagnoseTrace, c7 as directionAway, c8 as directionTo, c9 as distanceTo, ca as effectiveTurnRateCost, cb as extractAction, cc as extractMissileAction, cd as extractStats, ce as extractTraceEvents, cf as fight, cg as findInRange, ch as findNearest, ci as fitMissileForEscapingTarget, cj as fitMissileToBudget, ck as flyStraight, cl as formatDiagnosis, cm as formatStats, cn as formatTraceEvents, co as formatTraceSummary, cp as generateCandidates, cq as generateCombos, cr as getAdaptiveMissileConfig, cs as getEffectiveRange, ct as getLeadPosition, cu as getMissileCastTime, cv as getMissileContext, cw as getPlayerState, cx as getWizardContext, cy as hashCombine, cz as homingMissile, cA as idle, cB as inRange, cC as interceptAngle, cD as isBannedBotName, cE as isInLava, cF as magnitude, cG as matchesAnyBanRule, cH as mayAct, cI as missile, cJ as move, cK as moveInDirection, cL as moveProjectile, cM as moveWizard, cN as narrowRange, cO as nextRandom, cP as normalize, cQ as normalizeAngle, cR as predictPosition, cS as recordSpend, cT as resetAllHooks, cU as resetRuleset, cV as resolveWizardCollision, cW as runWithHooks, cX as runWizardWithContext, cY as scoreFight, cZ as scoreFightAsWizard2, c_ as seekerMissile, c$ as setParamValues, d0 as shield, d1 as simulate, d2 as simulateMinDuration, d3 as sortByDistance, d4 as spiralMissile, d5 as startCast, d6 as startDiscovery, d7 as stopDiscovery, d8 as straightMissile, d9 as summarizeTrace, da as sweptCircleCollision, db as testBot, dc as tick, dd as turnToAngle, de as turnToward, df as updateShield, dg as useArenaSize, dh as useBlinkCooldown, di as useCastProgress, dj as useCastingSpell, dk as useClosestThreat, dl as useDamageDealt, dm as useDamageTaken, dn as useEffect, dp as useEnemy, dq as useHealth, dr as useLastHitTick, ds as useLastMissileConfig, dt as useMemo, du as useMyProjectiles, dv as useMyThreatsToEnemy, dw as useParam, dx as usePosition, dy as useProjectiles, dz as useRandom, dA as useRef, dB as useShieldStrength, dC as useState, dD as useStatus, dE as useThreats, dF as useTick, dG as useTicksUntilReady, dH as useVelocity, dI as validateHookCall, dJ as validateMissileConfig, dK as withMissileContext, dL as withWizardContext, dM as wrapWithParams } from './index-browser-q0eR90H1.js';
3
3
 
4
4
  /**
5
5
  * A compiled bot ready for sandboxed execution.
package/dist/index.js CHANGED
@@ -229,7 +229,7 @@ import {
229
229
  withMissileContext,
230
230
  withWizardContext,
231
231
  wrapWithParams
232
- } from "./chunk-NEXWZU5I.js";
232
+ } from "./chunk-M6E6IP7L.js";
233
233
 
234
234
  // src/engine/sandbox.ts
235
235
  import ivm from "isolated-vm";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibemancer/core",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Vibemancer game engine - competitive programming wizard battle arena",
5
5
  "type": "module",
6
6
  "author": "Low Entry",
@@ -9,4 +9,4 @@
9
9
  * Used to gate spectator replays: a recorded match can only be re-simulated when
10
10
  * the runtime engine version matches the version that produced the match.
11
11
  */
12
- export const ENGINE_VERSION = 4396905295552957;
12
+ export const ENGINE_VERSION = 1688330189011034;
@@ -47,7 +47,13 @@ export function useHealth(): number
47
47
  * Clamped to [5, 855] — the ARENA bounds minus the wizard radius, NOT the playfield. That
48
48
  * distinction is the difference between living and dying: the playfield is [30, 830] and
49
49
  * everything outside it is lava, so you can walk straight out of the safe area and be
50
- * killed. Nothing stops you. Check against ARENA_MIN/ARENA_MAX, not against these numbers.
50
+ * killed. Nothing stops you.
51
+ *
52
+ * And the number you actually need is neither of those. Lava is tested against your EDGE,
53
+ * not your centre (`isInLava` checks `x + WIZARD_RADIUS > ARENA_MAX`), and this returns your
54
+ * CENTRE — so with a radius of 5 you die once your centre passes 825. The safe range to
55
+ * steer by is [35, 825]. Aiming for 828 because "the playfield is [30, 830]" is fatal, which
56
+ * is exactly what a real fight trace showed: LAVA_DEATH at (826, 430).
51
57
  *
52
58
  * (This previously quoted the playfield-sized bounds as the clamp, which told the reader
53
59
  * they were safely fenced in. They are not — see docs-match-engine.test.ts.)
@@ -43,8 +43,20 @@ export function directionAway(from: Position, to: Position): Position
43
43
  }
44
44
 
45
45
  /**
46
- * Clamp a position to valid arena bounds.
47
- * Note: For wizard-specific clamping with radius, use clampToArena from physics.ts
46
+ * Clamp a position into the arena rectangle — [0, ARENA_SIZE] on both axes.
47
+ *
48
+ * READ THIS BEFORE USING IT FOR SAFETY. It does NOT keep a wizard alive. The arena includes
49
+ * the 30-unit lava border, so clamping to it can hand you back a coordinate that is deep
50
+ * inside the lava — for example (0, 0), which is lethal. It used to be documented as
51
+ * clamping to "valid arena bounds", which reads like exactly the safety helper it is not:
52
+ * a player sanitising a blink target with this will blink into the fire.
53
+ *
54
+ * To stay ALIVE you want the safe box for a wizard's CENTRE, which is
55
+ * [ARENA_MIN + WIZARD_RADIUS, ARENA_MAX - WIZARD_RADIUS] — currently [35, 825], because
56
+ * `isInLava` tests your edge rather than your centre.
57
+ *
58
+ * For the engine's own wizard clamp (arena bounds minus the radius, still not lava-safe),
59
+ * see clampToArena in physics.ts.
48
60
  */
49
61
  export function clampPositionToArena(position: Position): Position
50
62
  {