This website requires JavaScript.
Explore
Help
Sign In
ctan
/
pf1e-simulator
Watch
1
Star
0
Fork
0
You've already forked pf1e-simulator
Code
Issues
Pull Requests
Actions
Packages
Projects
Releases
Wiki
Activity
Files
8b5043072ac3fb2c221934fc94d1494b83149674
pf1e-simulator
/
src
/
pf1e_simulator
T
History
ctan
8b5043072a
feat(phase2): candidate actions
2026-09-21 13:46:05 +02:00
..
loaders
fix(loaders): resource pools validated consistently before grant merge
2026-09-20 17:13:09 +02:00
__init__.py
chore: scaffold pf1e_simulator package (uv, ruff, basedpyright, pytest)
2026-08-17 22:49:50 +02:00
abilities.py
fix(rules): misty Scaled Skin electricity resist 5 and Maw or Claw bite 1d6 (SRD ARG daemon-spawn traits: resistance encoded in resistances, bite upgraded from the sheet's estimated 1d4 to the Medium 1d6 with the discrepancy recorded in notes)
2026-09-19 12:43:38 +02:00
areas.py
fix(rules): a grazed caster cell no longer shortens a line spell - SRD Aiming a Spell: a line 'starts from any corner of your square and extends to the limit of its range' (Lightning Bolt: 'The bolt begins at your fingertips'), so the caster's own squares are origin space the line starts PAST and must not consume one of the length_cells squares; line_cells took a fixed ray[1:length_cells+1] window and dropped caster cells inside it, so a 2x2 caster's line came out one square short per grazed footprint cell (the old code documented this as a simplification); the ray is now extended (reach = length_cells + 1 + len(caster_cells)) and caster cells are skipped WITHOUT spending a length slot, so a multi-cell line runs its full length starting just past the footprint; 1x1 casters are bit-identical (the only skipped cell is the origin at ray[0], already outside the counted window); the barrier/LoE stop and out-of-bounds semantics are unchanged (a straight ray never re-enters a convex map); golden untouched (no line spell in it); +3 tests (grazed-cell full-length template, 1x1 bit-identical regression, engine-level reach of a foe the short line missed)
2026-09-20 00:41:02 +02:00
candidates.py
feat(phase2): candidate actions
2026-09-21 13:46:05 +02:00
cli.py
fix(cli): require --round-cap >= 1
2026-09-20 17:40:29 +02:00
combat.py
feat(phase2): observation-only LLMPolicy entry (D1) + pinned schema_version (P0.1)
2026-09-21 11:10:28 +02:00
conditions.py
fix(rules): mirror image rolled image count with dynamic images/(images+1) concealment miss chance, bleed cantrip gated on the SRD dying-target eligibility, bane -1 fear-scoped penalty via a dedicated bane condition (SRD spells/mirror-image.md, spells/bleed.md, spells/bane.md)
2026-09-19 13:22:19 +02:00
dice.py
fix(dice): parse_dice validates sides >= _MIN_SIDES so d1/1d1 raise DiceParseError instead of leaking the model validator's pydantic ValidationError; drop the dead not-sides_str guard (regex \\d+ already guarantees non-empty) + 3 rejected-notation cases (d1, 1d1, 2D6)
2026-09-19 18:51:38 +02:00
effects.py
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
grid.py
feat(rules): 3D flight over ground terrain - airborne creatures (fly >= land, V4 budget from fly speed) move on Grid.airborne_view: ground difficult terrain costs 1 and cells impassable to walkers (pits, water, rubble, low obstacles) are crossable at cost 1, EXCEPT blocks_los cells (solid barriers, assumed full height) which still stop flight; run/charge/5-foot-step gates and diagonal corner rule follow the same view (flying past a pit is legal, past a wall corner is not); elevation climb cost still applies (step heights, not wall heights - documented); line of effect, cover and high ground use the unchanged real grid so combat geometry is unaffected by flight (SRD Movement, Position and Distance: flying creatures not hampered by difficult terrain, able to avoid most obstacles), 11 tests
2026-09-20 22:21:40 +02:00
llm_view.py
feat(phase2): compact observation view for LLM prompts
2026-09-21 13:21:33 +02:00
los.py
fix(rules): adjacent melee cover uses the SRD any-line rule (cover.md: 'any line from any corner of your square to the target's square goes through a wall') - the gate previously applied the ranged best-corner rule to distance-1 melee, systematically under-granting cover; non-adjacent melee (reach) keeps the ranged rule, bonus scoring aligned per branch, README 'pire coin' wording updated
2026-09-19 15:35:56 +02:00
map.py
docs(map): make omitted move_cost explicitly mean impassable
2026-09-20 18:03:46 +02:00
metrics.py
feat(runner): Monte Carlo runner, closed-form metrics and balance CLI
2026-08-17 22:49:50 +02:00
models.py
feat(rules): SplashSpec data model - data-driven splash marker on thrown weapons, Alchemist's Fire splash 1 fire on oni/tammara (SRD Throw Splash Weapon, Alchemist's fire)
2026-09-20 19:11:39 +02:00
objectives.py
feat(phase2): danger-cartography spike - per-run outcomes, objectives, focus-fire adversary
2026-09-21 12:07:23 +02:00
phase2_spike.py
feat(phase2): danger-cartography spike - per-run outcomes, objectives, focus-fire adversary
2026-09-21 12:07:23 +02:00
rng.py
feat(combat): add concealment miss chance, sneak attack, and Precise Shot
2026-09-10 10:22:50 +02:00
runner.py
feat(phase2): danger-cartography spike - per-run outcomes, objectives, focus-fire adversary
2026-09-21 12:07:23 +02:00
spells.py
feat(rules): spell components + deafened verbal failure and arcane spell failure rolls
2026-09-20 14:02:10 +02:00
Powered by
TurnKey Linux
.