Repository navigation
Fix the magic shield crash and report a melee with nothing left to strike - #222
Merged
Merged
Conversation
When an attack ignores the defender's shield, because the defender is retreating or the attacker strikes from behind, the attack is made against the armour class the defender would have without the shield. For a magic shield, that takes away its enchantment along with the +1 every shield gives. A cursed shield that makes armour class worse still counts, because the rule negates a shield's bonus and not its penalty. Today a magic shield in that case raises AttributeError, because a MagicItemInstance has no template. When a member's declared melee attack comes up and its group has no living, visible monster left to strike, the attack fizzles with a DeclarationFizzledEvent at battle.melee.fizzled, whose reason is battle.declaration.no_target. The session checks this before the member's position, so it applies whether or not the member closed. A slow attack gets the same check at the end of the round. Today such an attack vanishes with no event. The new tests that fail today are marked xfail for the chunk playtest-fixes. The docstrings and the adaptations register state both rules. Claude-Session: https://claude.ai/code/session_01V7ErtnsmhaP7aLwcfmzohD
An attack on a retreating defender, or an attack from behind, raised AttributeError when the defender carried a magic shield, because the attack roll read the shield's template and a MagicItemInstance has none. The attack roll now reads the shield through a new private helper in items.py, _shield_ac_parts, which Character._armour_parts uses too, so the two can't disagree about what a shield gives. The attack is made against the armour class the defender would have without the shield. A magic shield loses its enchantment along with the +1 every shield gives. A cursed shield that makes armour class worse still counts, because only a positive bonus is taken away. Claude-Session: https://claude.ai/code/session_01V7ErtnsmhaP7aLwcfmzohD
When a member's declared melee attack comes up and its group has no living monster the member can see, the attack now fizzles with a DeclarationFizzledEvent at battle.melee.fizzled, whose reason is battle.declaration.no_target. Before, the attack vanished with no event. _melee_fizzle checks for a target before it checks the member's position, so the member gets this reason whether or not they closed. A slow attack gets the same check at the end of the round, because it goes through the same function. A member who stood within 5' of a group that ran out of the battle in one move also got no event. The engaged member passed the fizzle check, and then _resolve_party_attack returned nothing because the group had fled. That attack now fizzles with combat.attack.out_of_reach. A new guard test in test_melee_no_target.py covers it. The fizzle message now says the member finds nothing left to strike when the reason is no_target. The golden file phase4_delve.json changes, regenerated with tests/generate_phase4_goldens.py from the same seed. One of its battles has two members whose melee attacks are aimed at a group that is already dead when their turn comes. The only change is the two new fizzle events for those members, and their two message lines. No other golden changes. Claude-Session: https://claude.ai/code/session_01V7ErtnsmhaP7aLwcfmzohD
The tests for the ignored magic shield and the melee with nothing left to strike pass, so their expected-to-fail markers come off. The register's entry for a group that runs now also says that a group that runs out of the battle leaves nothing to strike, so even a member who stood within 5' of it fizzles with combat.attack.out_of_reach. Claude-Session: https://claude.ai/code/session_01V7ErtnsmhaP7aLwcfmzohD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two defects that The Snoring King found while playtesting the 2.3.0 build:
shield.template, which a magic shield doesn't have. So a monster attacking a retreating member with a magic shield raisedAttributeError. This was already in 2.2.0. The shield's bonus is now worked out by one helper thatCharacterarmour class and the kernel share, and the whole bonus is ignored, including the enchantment. A cursed shield's penalty still counts, because the OSE SRD negates a shield's bonus, and a cursed shield has none.battle.melee.fizzledwith reasonbattle.declaration.no_target. A member engaged with a group that runs out of the battle now fizzles withcombat.attack.out_of_reachtoo.phase4_delve.jsongains two such fizzle events just before the victory, and nothing else in it changes. No other golden changes.https://claude.ai/code/session_01V7ErtnsmhaP7aLwcfmzohD