Skip to content

Add SITREP inspection feature#19

Open
gitosaurus wants to merge 12 commits into
mainfrom
feature/sitrep
Open

Add SITREP inspection feature#19
gitosaurus wants to merge 12 commits into
mainfrom
feature/sitrep

Conversation

@gitosaurus
Copy link
Copy Markdown
Owner

@gitosaurus gitosaurus commented Apr 19, 2026

Add SITREP inspection feature: a "SITuation REPort" of an ACX file, with object state, proximity, and vocabulary as RDF. Intended to be enough information to understand the game state — and how the parser sees the world — without having to read the binary ACX directly.

Archetype-side groundwork

  • Extract ROLL CALL as a reusable method on main, called after initialization and after each turn's events
  • Add INVENTORY NAMES message to list_inventory to gather inventory item names into a list without printing them
  • Refactor INVENTORY to use INVENTORY NAMES internally, separating name-gathering from display
  • Add a SITREP method on main that returns a list of key/value pairs: location, exits, visible, inventory, and (when set) it
  • SITREP is not called automatically; it is available on demand

RDF/Turtle output from --inspect

Produces well-formed Turtle:

  • Prefixes: archetype:, type:, obj:, attr:, msg:, xsd:, rdf:, rdfs:
  • Type hierarchy via rdfs:Class / rdfs:subClassOf; instance typing via rdf:type (the a shorthand)
  • Attribute values rendered via asRDF() (e.g., attr:desc "dank cellar") rather than just attribute names. Only materialized values appear — uninitialized default expressions are skipped

--inspect alone is state-only (objects, types, attribute values). Pass --full to also include:

  • Vocabulary: archetype:matchesPhrase for every verb/noun phrase the parser recognizes
  • Effective vocabulary: archetype:matchesNow for phrases whose referent is currently proximate
  • Parser state: archetype:parser a archetype:SystemParser with archetype:mode, archetype:proximate, archetype:playerCommand, archetype:normalized
  • Method tables: archetype:respondsTo msg:MESSAGE_NAME (URI-encoded)

New flags on --update

  • --update --sitrep appends the parser block followed by an archetype:situation a archetype:SituationReport block with one predicate per SITREP key (archetype:location, archetype:exits, etc.)
  • --update --inspect appends a state-only universe dump

Other changes

  • List literal syntax now uses square brackets instead of curly braces. The old {} was visually easy to confuse with compound statements.
  • Unknown command-line options are now rejected with a diagnostic instead of being silently accepted. (A typo like --compile in place of --create used to silently run the interpreter in a different mode.)

gitosaurus and others added 2 commits April 18, 2026 17:15
Lay the Archetype-side groundwork for the situation report feature:

- Extract 'ROLL CALL' as a reusable method on main, called after
  initialization and after each turn's events
- Add 'INVENTORY NAMES' message to list_inventory, which gathers
  inventory item names into a list without printing them
- Refactor 'INVENTORY' to use 'INVENTORY NAMES' internally, so the
  name-gathering and display logic are separated
- Add 'SITREP' method on main that assembles exits, visible objects,
  and inventory as a structured PairValue list of key-value pairs
- SITREP is not called automatically; it is available on demand

Rewrite inspect_universe for proper RDF/Turtle output

The --inspect flag now produces well-formed Turtle with:

- Proper prefixes: archetype:, type:, object:, attr:, msg:, xsd:
- Attribute values rendered via asRDF() (e.g., attr:desc "dank cellar")
  instead of just listing attribute names
- Type hierarchy via rdfs:Class and rdfs:subClassOf
- Instance typing via rdf:type (Turtle 'a' shorthand)
- Vocabulary: verb/noun phrases as archetype:verbPhrase and
  archetype:nounPhrase predicates on each object
- Proximate objects as archetype:proximate on archetype:situation
- Methods (--full flag): archetype:respondsTo msg:MESSAGE_NAME
  with URI-encoded message names

Without --full, only object identity, types, and attribute values are
emitted — this is the "state-only" view suitable for external parsers
or AI systems that need to understand the game situation without
knowing the internal method implementations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

The SITREP must contain the same information a SystemParser uses:
actual object references, not human-readable strings. A consuming
program needs to know that the exit is object:south (an Archetype
object it can reference), not the string "south".

- Add 'INVENTORY OBJECTS' message to list_inventory, which gathers
  member objects (filtered by visibility) as a list of ObjectValues
- Change 'SITREP' to use 'INVENTORY OBJECTS' instead of
  'INVENTORY NAMES' for exits, visible objects, and inventory
- Add player.location as the "location" key
- Add it.referent as the "it" key when a pronoun is set

The existing 'INVENTORY NAMES' and 'INVENTORY' (display) paths
are unchanged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Use type:/obj: prefixes to distinguish prototypes from instances

Replace per-type instance prefixes (room:, wearable:, etc.) with a
single obj: prefix for all instances. The type relationship is already
captured by rdf:type triples, so encoding it in the URI is redundant.
This gives a clean two-prefix scheme: type: for prototypes, obj: for
instances.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Add TestInspectUniverse test suite

Covers class/type emission for null-parent and typed instances,
Turtle well-formedness of the vocabulary block (no stray leading
semicolon), and the proximate list (no stray leading comma).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Brackets: list literals now use [...]; {...} is exclusively a compound
statement. Parser, PairValue::display, intrptr.arch sources, and tests
updated. See list_design.md for the rationale (spreadsheet-model
preservation, ending the list/block homoglyph).

REPL: results now print as `=> value` using display() only. Dropped the
trailing stringConversion tail, which duplicated scalar output (`8 8`)
for values whose display and string forms happen to match. Matches
Python/Ruby/Lisp convention.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR lays groundwork for a “SITREP” (situation report) feature and modernizes the --inspect output to emit RDF/Turtle, alongside a syntax change for Archetype list literals from {} to [].

Changes:

  • Add an optional --sitrep path to --update to append a structured situation report (SITREP + parser context).
  • Rewrite --inspect to emit Turtle with richer type/attribute/method modeling and parser vocabulary/proximity output.
  • Introduce Value::asRDF() and switch list literal display syntax from {} to [], with updated/added tests.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/update_universe.hh Extends update_universe API to optionally append sitrep output.
src/update_universe.cc Implements sitrep emission and parser-context dump after UPDATE.
src/main.cc Adds --sitrep and --full flags and wires them into update/inspect flows.
src/inspect_universe.hh Extends inspect_universe signature with include_methods toggle.
src/inspect_universe.cc Rewrites inspection output as Turtle with prefixes, types, attributes, methods, and parser vocabulary/proximity.
src/Value.hh Adds asRDF() to the Value interface and concrete value types.
src/Value.cc Implements asRDF() for values and updates PairValue display + RDF rendering.
src/TestValue.cc Updates list display expectations to the new [] syntax.
src/TestInspectUniverse.hh Adds a new test suite for Turtle output structure.
src/TestInspectUniverse.cc Adds tests for type output and Turtle syntax constraints for vocabulary/proximity.
src/TestExpression.hh Adds tests for list literal parsing and REPL output formatting.
src/TestExpression.cc Implements list literal parsing tests and REPL display regression test.
src/SystemParser.hh Updates friend declarations to match new inspect signature and sitrep helper.
src/SystemObject.hh Updates friend declarations to match new inspect signature and sitrep helper.
src/ReadEvalPrintLoop.cc Adjusts REPL output formatting to => <display> only.
src/Object.hh Updates inspect_universe friend declaration signature.
src/Expression.cc Switches list literal parsing from {} to [].
src/CMakeLists.txt Adds new TestInspectUniverse to the build.
games/intrptr.arch Adds ROLL CALL and SITREP methods and refactors inventory listing; updates list literal usage to [].

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/inspect_universe.cc
Comment thread src/inspect_universe.cc Outdated
Comment thread src/update_universe.cc
Comment thread src/update_universe.cc Outdated
Comment thread src/Value.cc
Comment thread src/main.cc Outdated
Comment thread src/inspect_universe.cc Outdated
gitosaurus and others added 10 commits April 18, 2026 18:11
Emit archetype:verbPhrase / nounPhrase values through a local
escape_literal helper so quotes and backslashes in phrases stay valid
Turtle.  The helper mirrors escape_string in Value.cc, kept local to
avoid a cross-TU dependency.

In intrptr.arch, rename the local variable inside 'INVENTORY OBJECTS'
from 'names' to 'items' to reflect that it collects objects, not
strings, and declare 'items' on list_inventory alongside the existing
'names' attribute used by the sibling methods.
The parser-context portion of --sitrep was emitting a custom text
format (PROXIMATE/NOUNS/VERBS s-expressions) out of step with the
Turtle produced everywhere else.  Unify on Turtle and promote the
parser to a first-class RDF entity.

Changes in inspect_universe:

- Factor the RDF emission into dump_universe_rdf (no deserialization)
  and write_parser_rdf, both callable independently.  inspect_universe
  now deserializes and delegates.
- Collapse archetype:verbPhrase and archetype:nounPhrase into a single
  archetype:matchesPhrase predicate.  The kind of match (verb vs noun)
  is already conveyed by the object's rdf:type.
- Add archetype:matchesNow, the subset of noun phrases whose referent
  is currently proximate.  Pre-baked here so LLM-style consumers
  without SPARQL can answer "what can the player type right now?"
  with a direct scan.
- Replace the standalone archetype:situation block with an
  archetype:parser block (a archetype:SystemParser) carrying mode,
  proximate, playerCommand, normalized, and parsedValue.  This is the
  natural home for what was previously emitted as ad-hoc text.

Changes in update_universe:

- Delete sitrep_parser_context.  --sitrep now appends proper Turtle
  via write_parser_rdf with prefixes.
- Add an inspect parameter; --update --inspect appends the full
  post-turn universe (via dump_universe_rdf), closing the UX gap where
  there was no single invocation to get SITREP plus full game state.

Tests in TestInspectUniverse updated to match the unified predicates
and the relocated proximate block.
- TestInspectUniverse::testParserBlock_ drives the parser through a
  PLAYER CMD so playerCommand_ and normalized_ are populated, then
  pins archetype:parser a archetype:SystemParser along with mode,
  playerCommand, and normalized in the Turtle output.
- New TestUpdateUniverse suite exercises update_universe() across its
  three modes: plain (no RDF appended), --sitrep (prefixes + parser
  block appended), --inspect (full universe dump appended).  Uses a
  minimal null-parent main object so the assertions don't depend on
  standard.arch vocabulary.
The --sitrep path was still emitting the old ad-hoc header
  SITREP ( ( "location" obj:cell ) ... )
which is a Turtle collection floating without a subject/predicate —
not a valid triple.  Walk the list returned by 'SITREP' (a sequence
of [ "key" value ] pairs) and emit each pair as its own predicate on
archetype:situation, an instance of archetype:SituationReport.  This
gives consumers proper RDF they can query directly
(?s archetype:inventory ?x) instead of traversing a nested list.

Key names are sanitized to valid Turtle local-name characters;
non-identifier characters fold to underscore.  Trusting the game-side
convention that SITREP keys are short identifier-ish words.

Extends TestUpdateUniverse with testSitrepUnpacksPairs_ to pin the
predicate-per-pair shape and guard against regression to the old
"SITREP (" label.
Address PR #19 feedback: dispatch_to_universe("SITREP") calls
Messages.index(), which inserts a new ID when the message is absent.
Because update_universe serializes the universe back to disk after
its work, this silently grew the message table of any saved game
that lacked a SITREP handler. Guard the dispatch with Messages.find()
so the table is only consulted, never mutated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Address PR #19 feedback: the previous code called evaluate() on every
attribute expression without setting self, which could yield wrong
values for self-referential expressions and could trigger side effects
for non-literal attribute defaults. Limit emission to attributes whose
expressions are ValueExpression (the form Object::setAttribute stores
into) and wrap the evaluation in a ContextScope, matching the pattern
used in AttributeValue::dereference_().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously the option parser stuffed any --name[=value] token into
the opts map and the rest of main() only count()ed the names it knew
about. A misspelled flag (e.g. --compile in place of --create) was
silently accepted, causing the interpreter to run in a different mode
than the user intended.

Refactor each consumer to find() and erase-by-iterator (single lookup,
O(1) amortized erase), then validate opts and args at every exit path.
Anything left over now produces a diagnostic and exit code 1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Address PR #19 feedback: dump_universe_rdf emitted the parser block
(vocabulary, matches, proximity) unconditionally even when include_methods
was false, mixing world state with parser internals. Move that block
under the same flag that gates method signatures.

After this change:
  --inspect              world state only (objects, types, attribute values)
  --inspect --full       state plus methods and parser vocabulary
  --update --inspect     state only (post-turn snapshot)
  --update --sitrep      parser block plus per-key situation report

Update the --inspect and --full help text to match. Adjust
TestInspectUniverse's helper to take an include_methods argument so the
vocabulary/proximate/parser-block tests can request the fuller output.
Rename TestUpdateUniverse::testInspectAppendsFullRdf_ to
testInspectAppendsStateRdf_ and invert its parser-block assertion to
reflect the new contract.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Address PR #19 feedback: ObjectValue::asRDF, ObjectValue::display, and
ObjectValue::identifierConversion each performed a linear scan over
ObjectIdentifiers to find the name bound to an object, making RDF
emission and display O(N^2) in the number of named objects.

Add a parallel std::map<object_id, identifier_id> on Universe, kept in
sync at the single write site (assignObjectIdentifier) and rebuilt
after deserialization. Expose it via Universe::identifierForObject,
which the three call sites now use directly.

inspect_universe.cc also built its own local reverse map twice
(build_reverse_ids / obj_name_for) to dodge the same problem within a
single emission; drop that duplication and call the Universe API.

No behavior change: every entry in ObjectIdentifiers represents a
unique (identifier, object) pair under current Archetype syntax
(assignObjectIdentifier is only invoked at declaration time and there
is no syntactic path to bind a second name to an existing object), so
the reverse map is well-defined.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants