ctan
1238c40e43
fix(rules): resistance is a +1 resistance bonus on fort/ref/will saves for 1 minute - SRD spells/resistance.md grants the subject a +1 resistance bonus on saving throws for 1 minute (Will negates, harmless); the resistance bonus type already exists in the stacking model (effects.py BonusType), so the buff is expressible as a BuffEffect and was only deferred because _find_buff_spell returns the FIRST BuffEffect in known-spell order and cantrips cost no slots - encoding it would have made default_policy cast Resistance every round (for Tammara it would preempt Divine Favor and never kill anything); resistance.json now carries a BuffEffect (+1 resistance on fort/ref/will, 10 rounds = 1 minute) and _find_buff_spell skips level-0 spells (cantrips have no spell slot in the engine's budget - spell_slots_left has no level-0 key - and the policy deliberately never auto-casts them, a cantrip buff would be cast every round degrading the policy), so Resistance cannot preempt a leveled buff (Divine Favor) in the known-spell order; leveled buffs keep the historical first-match behavior (if the first one's slots are exhausted the buff branch gives up - the golden pins that); the resistance bonus type does not stack with itself (resolve_modifiers keeps the higher value); +9 tests (test_resistance.py: buff shape, cast on a willing ally consumes no d20 and applies without a save roll, the bonus rides save rolls, no self-stacking, expiry at 10 rounds, _find_buff_spell skips the slot-less cantrip / returns None without a leveled buff, _choose_spell_action proposes Divine Favor and never Resistance); golden untouched; 1714 tests green
2026-09-20 10:10:32 +02:00
..
2026-08-17 22:49:50 +02:00
2026-09-04 23:02:20 +02:00
2026-09-16 21:24:48 +02:00
2026-09-10 20:52:28 +02:00
2026-09-19 22:02:36 +02:00
2026-09-10 14:08:25 +02:00
2026-09-16 19:30:08 +02:00
2026-09-19 14:16:26 +02:00
2026-09-19 17:02:21 +02:00
2026-09-12 12:58:32 +02:00
2026-09-19 15:51:15 +02:00
2026-09-17 23:06:03 +02:00
2026-09-19 15:44:12 +02:00
2026-09-19 23:23:00 +02:00
2026-09-19 23:23:00 +02:00
2026-09-16 21:46:04 +02:00
2026-09-04 23:02:20 +02:00
2026-09-19 11:50:53 +02:00
2026-09-19 23:05:25 +02:00
2026-09-12 13:26:52 +02:00
2026-09-16 19:38:49 +02:00
2026-09-16 19:22:00 +02:00
2026-09-17 23:06:03 +02:00
2026-09-19 16:24:31 +02:00
2026-09-13 13:39:44 +02:00
2026-09-19 16:34:22 +02:00
2026-09-19 15:35:56 +02:00
2026-09-19 16:19:23 +02:00
2026-09-16 21:46:04 +02:00
2026-09-16 21:32:19 +02:00
2026-09-11 23:35:07 +02:00
2026-09-11 00:19:06 +02:00
2026-09-19 16:29:38 +02:00
2026-09-19 23:23:00 +02:00
2026-09-19 11:40:02 +02:00
2026-09-11 13:02:31 +02:00
2026-09-10 11:32:08 +02:00
2026-09-12 09:27:03 +02:00
2026-09-19 22:27:46 +02:00
2026-09-13 10:48:09 +02:00
2026-09-17 23:13:22 +02:00
2026-09-11 21:15:14 +02:00
2026-09-05 00:16:17 +02:00
2026-09-19 18:51:38 +02:00
2026-09-10 21:45:50 +02:00
2026-09-16 20:16:35 +02:00
2026-09-16 15:48:36 +02:00
2026-09-16 21:48:40 +02:00
2026-09-05 16:18:56 +02:00
2026-09-16 19:55:53 +02:00
2026-09-11 22:06:46 +02:00
2026-09-19 12:47:40 +02:00
2026-09-13 16:41:40 +02:00
2026-09-10 17:46:57 +02:00
2026-08-17 22:49:50 +02:00
2026-08-17 22:49:50 +02:00
2026-08-17 22:49:50 +02:00
2026-09-19 22:27:46 +02:00
2026-09-13 17:19:58 +02:00
2026-09-13 10:48:09 +02:00
2026-09-19 17:06:30 +02:00
2026-09-10 12:04:10 +02:00
2026-09-19 23:05:25 +02:00
2026-09-20 00:41:02 +02:00
2026-09-10 15:56:21 +02:00
2026-09-19 15:35:56 +02:00
2026-09-16 15:36:43 +02:00
2026-09-16 20:25:34 +02:00
2026-09-19 17:12:42 +02:00
2026-08-17 22:49:50 +02:00
2026-09-16 22:06:59 +02:00
2026-09-16 13:47:10 +02:00
2026-09-20 00:29:36 +02:00
2026-09-06 10:22:58 +02:00
2026-09-13 12:05:56 +02:00
2026-09-16 12:25:30 +02:00
2026-09-19 22:27:46 +02:00
2026-09-06 11:07:30 +02:00
2026-09-13 13:39:44 +02:00
fix(rules): guidance is a one-shot +1 competence bonus on a single attack roll - SRD spells/guidance.md grants '+1 competence bonus on a SINGLE attack roll, saving throw, or skill check' (duration 1 minute or until discharged); the engine had no spell effect that could write the one-shot attack track (aid_attack_bonus is hardwired to aid-another +2 and expires at the start of the beneficiary's next turn), and a persistent BuffEffect would misrepresent the discharge rule (it would boost every roll for a minute) and would become the first buff spell in the casters' known-spell order, degrading default_policy; a new OneShotEffect type is added (track/value/bonus_type/duration_rounds, parser 'one_shot', SpellEffect union, summary 'one-shot +X type on track'), stored as ActiveOneShot on CombatantState (one_shot_bonuses, decremented with the other duration-tracked effects, exposed in the snapshot), discharged by the FIRST roll of the encoded track via _discharge_one_shot (best value wins, each casting is its own charge) and folded into the resolve_modifiers pool so bonus-type stacking applies; the attack track rides the attack roll only, NOT the crit-confirm roll (the SRD grants it to a SINGLE attack roll, so unlike aid another the confirmation is untouched - _attack_roll_modifiers returns (pool_mod, attack_roll_mod) and resolve_attack uses the latter for the total while the confirm keeps the former); the save and skill tracks are wired in the mechanism (resolve_save folds a save-track shot into save_mods, resolve_skill discharges a skill-track shot into _skill_static_bonus via extra_mods) but guidance.json encodes the attack track only - the SRD 'attack OR save OR skill' choice has no declaration channel in the engine, so the attack-roll variant is encoded (documented); _apply_targeted_spell_effect dispatches OneShotEffect to _apply_one_shot_effect (a successful save negates it, 'one-shot negated'); guidance.json now carries the effect (1 minute = 10 rounds) and default_policy never casts it (cantrips have no spell slot and the one-shot type is not a buff/heal/offensive pick); _spell_effect_summary split into _damage_effect_summary/_non_damage_effect_summary to stay under the PLR0911 return cap; test_spell_registry_batch2._EFFECT_TYPES gains OneShotEffect; +14 tests (test_one_shot_guidance.py: cast-and-discharge on the next attack, not on the crit-confirm roll, save/skill tracks, stacking by bonus type, expiry at 10 rounds, save negation, snapshot exposure, no auto-cast by default_policy); golden untouched; 1705 tests green
2026-09-20 09:53:53 +02:00
2026-09-11 22:06:46 +02:00
2026-09-10 13:57:34 +02:00
2026-09-16 15:10:21 +02:00
2026-09-19 23:05:25 +02:00
2026-09-10 20:52:28 +02:00
2026-09-04 23:02:20 +02:00
2026-09-10 21:45:50 +02:00
2026-09-10 21:45:50 +02:00
2026-09-13 15:35:23 +02:00
2026-09-13 14:54:15 +02:00
2026-09-19 17:02:21 +02:00
2026-09-10 21:45:50 +02:00
fix(rules): resistance is a +1 resistance bonus on fort/ref/will saves for 1 minute - SRD spells/resistance.md grants the subject a +1 resistance bonus on saving throws for 1 minute (Will negates, harmless); the resistance bonus type already exists in the stacking model (effects.py BonusType), so the buff is expressible as a BuffEffect and was only deferred because _find_buff_spell returns the FIRST BuffEffect in known-spell order and cantrips cost no slots - encoding it would have made default_policy cast Resistance every round (for Tammara it would preempt Divine Favor and never kill anything); resistance.json now carries a BuffEffect (+1 resistance on fort/ref/will, 10 rounds = 1 minute) and _find_buff_spell skips level-0 spells (cantrips have no spell slot in the engine's budget - spell_slots_left has no level-0 key - and the policy deliberately never auto-casts them, a cantrip buff would be cast every round degrading the policy), so Resistance cannot preempt a leveled buff (Divine Favor) in the known-spell order; leveled buffs keep the historical first-match behavior (if the first one's slots are exhausted the buff branch gives up - the golden pins that); the resistance bonus type does not stack with itself (resolve_modifiers keeps the higher value); +9 tests (test_resistance.py: buff shape, cast on a willing ally consumes no d20 and applies without a save roll, the bonus rides save rolls, no self-stacking, expiry at 10 rounds, _find_buff_spell skips the slot-less cantrip / returns None without a leveled buff, _choose_spell_action proposes Divine Favor and never Resistance); golden untouched; 1714 tests green
2026-09-20 10:10:32 +02:00
2026-09-12 14:35:42 +02:00
2026-08-17 22:49:50 +02:00
2026-09-16 15:36:43 +02:00
2026-09-19 23:23:00 +02:00
2026-08-17 22:49:50 +02:00
2026-09-19 22:49:40 +02:00
2026-09-19 22:38:39 +02:00
2026-09-10 17:25:05 +02:00
2026-08-17 22:49:50 +02:00
2026-09-19 22:38:39 +02:00
2026-09-19 13:34:30 +02:00
fix(rules): guidance is a one-shot +1 competence bonus on a single attack roll - SRD spells/guidance.md grants '+1 competence bonus on a SINGLE attack roll, saving throw, or skill check' (duration 1 minute or until discharged); the engine had no spell effect that could write the one-shot attack track (aid_attack_bonus is hardwired to aid-another +2 and expires at the start of the beneficiary's next turn), and a persistent BuffEffect would misrepresent the discharge rule (it would boost every roll for a minute) and would become the first buff spell in the casters' known-spell order, degrading default_policy; a new OneShotEffect type is added (track/value/bonus_type/duration_rounds, parser 'one_shot', SpellEffect union, summary 'one-shot +X type on track'), stored as ActiveOneShot on CombatantState (one_shot_bonuses, decremented with the other duration-tracked effects, exposed in the snapshot), discharged by the FIRST roll of the encoded track via _discharge_one_shot (best value wins, each casting is its own charge) and folded into the resolve_modifiers pool so bonus-type stacking applies; the attack track rides the attack roll only, NOT the crit-confirm roll (the SRD grants it to a SINGLE attack roll, so unlike aid another the confirmation is untouched - _attack_roll_modifiers returns (pool_mod, attack_roll_mod) and resolve_attack uses the latter for the total while the confirm keeps the former); the save and skill tracks are wired in the mechanism (resolve_save folds a save-track shot into save_mods, resolve_skill discharges a skill-track shot into _skill_static_bonus via extra_mods) but guidance.json encodes the attack track only - the SRD 'attack OR save OR skill' choice has no declaration channel in the engine, so the attack-roll variant is encoded (documented); _apply_targeted_spell_effect dispatches OneShotEffect to _apply_one_shot_effect (a successful save negates it, 'one-shot negated'); guidance.json now carries the effect (1 minute = 10 rounds) and default_policy never casts it (cantrips have no spell slot and the one-shot type is not a buff/heal/offensive pick); _spell_effect_summary split into _damage_effect_summary/_non_damage_effect_summary to stay under the PLR0911 return cap; test_spell_registry_batch2._EFFECT_TYPES gains OneShotEffect; +14 tests (test_one_shot_guidance.py: cast-and-discharge on the next attack, not on the crit-confirm roll, save/skill tracks, stacking by bonus type, expiry at 10 rounds, save negation, snapshot exposure, no auto-cast by default_policy); golden untouched; 1705 tests green
2026-09-20 09:53:53 +02:00
2026-09-17 21:28:00 +02:00
2026-09-13 12:44:35 +02:00
2026-09-19 22:27:46 +02:00
2026-09-19 23:13:06 +02:00
2026-09-17 23:06:03 +02:00
2026-09-13 15:35:23 +02:00
2026-09-05 11:28:46 +02:00
2026-09-10 13:36:27 +02:00