Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

## [Unreleased]

## [1.5.0] - 2026-08-07

### Added

- Authored quests, the state they advance, and the ending they reach. A `QuestSpec` (`osrlib.crawl.quests`) is adventure data like a trigger: an optional activation clause, `ObjectiveSpec`s each with a completion clause of their own, `rewards` from the same `ConsequenceCommand` surface under the same `@party`/`@first` selectors, a completion rule of `"all"` or `"any"`, and an optional `concludes_adventure` marker. Every "did this happen?" is a `TriggerClause` — a `TriggerPattern` plus the conditions gates use, matched by the same matcher and the same live evaluation triggers get, so the two surfaces cannot drift; a consuming condition is rejected at parse, because a quest observes and does not take. `Adventure.quests` carries them in document order, with an `Adventure.quest(id)` accessor, and `validate_adventure` walks every clause and reward through the same reference and party-selector checks a trigger gets. Quest state is engine-owned: `GameSession.quests` maps each quest id to a `QuestState` (`inactive` → `active` → `completed`) holding an `ObjectiveState` (`revealed`, `complete`) per objective, seeded at construction from the adventure — activation-less quests active from round 0, objectives visible unless authored `hidden` — so `new`, `load_game`, and replay all begin from the same block. Four referee commands are its only writers: `ActivateQuest`, `RevealObjective`, `CompleteObjective` (which reveals as it completes), and `CompleteQuest`, each emitting a player-visible event carrying the authored beat — `QuestActivatedEvent`, `ObjectiveRevealedEvent`, `ObjectiveCompletedEvent`, `QuestCompletedEvent`, and, when a concluding quest finishes outside a terminal mode, `AdventureCompletedEvent` as the session clears any open encounter or battle and enters `victory`. Unlike `MarkTriggerFired`'s open trigger id, their ids are a closed domain resolved against the adventure's own specs (`session.command.unknown_quest`, `session.command.unknown_objective`), and a command contradicting the state it finds rejects with `session.command.quest_state`; `CompleteQuest` deliberately checks only that the quest is active, because ruling a quest done is the referee's call. Each beat appends its display text to the journal as itself, with no `JournalEntryAddedEvent` behind it — the lifecycle event *is* that beat's event. The `Interpreter` plays all of it: per event, the adventure's triggers in document order and then its quests, issuing every lifecycle command, reward, and note stamped `source="quest:{id}"`, checking the completion rule the moment a completion it issued lands, and dropping a reward that cannot land — a spawn in `victory`, say — with a note rather than a raise. The block persists under a new `quests` key with no `schema_version` bump: a save written without it keeps the constructor's seed, and an adventure that authors no quests plays exactly as before.
Expand Down Expand Up @@ -108,7 +110,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
- The documentation site: quickstart, guides, front-end walk-throughs, and a full reference for every command, event, rejection code, message code, RNG stream, and content id.
- The typed surface: complete type hints under `py.typed`, checked in CI.

[Unreleased]: https://github.com/mmacy/osrlib-python/compare/v1.4.0...HEAD
[Unreleased]: https://github.com/mmacy/osrlib-python/compare/v1.5.0...HEAD
[1.5.0]: https://github.com/mmacy/osrlib-python/compare/v1.4.0...v1.5.0
[1.4.0]: https://github.com/mmacy/osrlib-python/compare/v1.3.0...v1.4.0
[1.3.0]: https://github.com/mmacy/osrlib-python/compare/v1.2.1...v1.3.0
[1.2.1]: https://github.com/mmacy/osrlib-python/compare/v1.2.0...v1.2.1
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "osrlib"
version = "1.4.0"
version = "1.5.0"
description = "B/X (1981 Basic/Expert) tabletop RPG rules engine for turn-based dungeon crawlers"
readme = "README.md"
# The wheel ships Open Game Content (osrlib/data/*.json and its LICENSE-OGL.md
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading