Docstrings: core combat - #92
Merged
Merged
Conversation
Every public member of osrlib.core.combat now answers what it does, why you'd call it, what you need first, what to call next, what to use instead, and when not to use it. The result models, the enums, and the two constants gained attribute documentation, so the reference no longer renders their fields as bare names, and every function a reader would call has a runnable example. Continuation lines in Returns sections are indented, because mkdocstrings' Google parser treats each unindented line as a separate return value and was rendering one description as several table rows. Docstrings only. The module's code is byte-identical apart from the docstrings. Claude-Session: https://claude.ai/code/session_01GL26QnA6dCrvUc3WmhzFSa
mkdocstrings renders each pydantic field and enum member as its own member below the class, and a class-level Attributes: section left those rows bare. Every public field and enum member now has an attribute docstring on the line after it, and the Attributes: sections that would duplicate them are gone. The code comments get the same register as the docstrings: no em dashes, no decision-log vocabulary, one idea per sentence. The facts are unchanged. Docstrings and comments only. The module's code is byte-identical. Claude-Session: https://claude.ai/code/session_01GL26QnA6dCrvUc3WmhzFSa
Thirteen claims traced back to the code and restated. attack_facet and damage_roll now name the magic item with no base weapon, which is most of the catalog. The automatic hit is described by what produces it, a defender whose armour_class is None. drain_monster_hd states the real hit point floor of 1, that the kill triggers at exactly 1 Hit Die, and which events each path yields. deal_damage names the equipment event and the revive entry that permanent death needs. resolve_breath names the absorbed path that takes no save. AttackContext states what an unstated distance means for a missile-only weapon. check_morale and MoraleTracker.check say what the code does with a score outside 2 to 12. resolve_attack's draw accounting covers the paths that cost one draw and the extra dice under striking. The morale_modifier example draws from the combat stream like every other example. Docstrings only. The module's code is byte-identical. Claude-Session: https://claude.ai/code/session_01GL26QnA6dCrvUc3WmhzFSa
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.
A reader who has only the published reference can now run a fight with
osrlib.core.combat: pick the function for the job, build theAttackContextand theRngStreamit needs, read the fields of what comes back, and know which function takes that output next. Every result model field and enum member documents itself on its own row of the page, and every function a reader would call has an example that runs under the docs harness with a fixed seed.Several docstrings disagreed with the code, and I corrected them to what the code does.
attack_facetanddamage_rollsaid a gear item with no fighting stats is the only attack with no combat facet; a magic item whose template names no base weapon is another, and that is most of the magic item catalog.attack_rollandAttackRollResult.autodescribed the automatic hit as one the rules grant without a roll, which left a reader nothing to act on, so they now name the condition, a defender whosearmour_classisNone, and the two monsters that have it.drain_monster_hdclaimed a floor of 1 on a d8, which is no floor at all, and said a monster drained below 1 Hit Die dies when the kill triggers at exactly 1; it now states the real floor, that hit points clamp at 1, and lists the events each path yields.deal_damageomitted the equipment event that ends a destructive kill and thereviveentry that a regenerating monster needs before it can die permanently.resolve_breathdid not mention that an absorbed target takes no save.AttackContext.distance_feetsaid an unstated distance means melee, which holds for a melee weapon but not for a missile-only one.check_moraleandMoraleTracker.checkgave the score as 2 to 12 when the code accepts any integer and treats anything at or below 2 and at or above 12 as exempt.MoraleResultused ML before the page defined it.Two things about how the page renders. I indented the continuation lines of every multi-line
Returns:body, because the Google-style parser in mkdocstrings reads each unindented line in that section as a separate return value and was rendering a two-line description as two table rows with the type repeated. I also put every field and enum-member description on the member itself rather than in a class-levelAttributes:section, because mkdocstrings renders each field again below the class and anAttributes:section leaves those rows bare. Both patterns appear in other modules, which I left alone because they are outside this batch.The code comments went through the same register pass as the docstrings, with their facts unchanged.
No example is
no-run, and nothing is left undocumented on purpose. The module's runtime code is byte-identical: I compared the syntax trees with every docstring stripped.uv run ruff format --check && uv run ruff check && uv run pyright && uv run pytest -q && uv run mkdocs build --strictpasses.https://claude.ai/code/session_01GL26QnA6dCrvUc3WmhzFSa