Skip to content

Add SITREP inspection feature#19

Open
gitosaurus wants to merge 2 commits intomainfrom
feature/sitrep
Open

Add SITREP inspection feature#19
gitosaurus wants to merge 2 commits intomainfrom
feature/sitrep

Conversation

@gitosaurus
Copy link
Copy Markdown
Owner

Add the ability to produce RDF report of ACX file, a "SITREP" or "SITuation REPort". This is not only the state of the objects in the game, but proximity and vocabulary. It is intended to be enough information to understand the game state without having to read binary ACX.

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.

As part of this work, change the Archetype list literal syntax to use square brackets instead of curly braces; the latter worked but was visually easy to confuse with compound statements.

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 on lines +59 to +63
<< "@prefix archetype: <schema/> .\n"
<< "@prefix type: <type/> .\n"
<< "@prefix obj: <object/> .\n"
<< "@prefix attr: <attr/> .\n"
<< "@prefix msg: <msg/> .\n\n";
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

The PR description calls out object: as a prefix, but the emitted Turtle declares @prefix obj: <object/> and all instances use obj:. If external tooling/docs expect object:, this will be a breaking change; either switch back to object: or update the PR description and any downstream expectations consistently.

Copilot uses AI. Check for mistakes.
Comment thread src/inspect_universe.cc
Comment on lines +114 to +118
// -- Vocabulary: parser state --

ObjectPtr systemObject = Universe::instance().getObject(Universe::SystemObjectId);
SystemObject* system_object = dynamic_cast<SystemObject*>(systemObject.get());
assert(system_object != nullptr);
// What verb and noun phrase match what objects?
// We need to turn the parsing inside out here; the parsed matches are sorted
// from longest to shortest, not arranged by object.
SystemObject* system = dynamic_cast<SystemObject*>(systemObject.get());
assert(system != nullptr);
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

inspect_universe(..., include_methods=false) still emits the vocabulary and proximate-object sections unconditionally. The PR description says the non---full output should be “state-only” (identity/types/attribute values only). If that contract is intended, gate the vocabulary/proximity emission behind include_methods (or a separate flag) so default --inspect stays minimal and machine-friendly.

Copilot uses AI. Check for mistakes.
Comment thread src/update_universe.cc
Comment on lines +140 to +148
if (sitrep and not Universe::instance().ended()) {
try {
Value sitrep_val = dispatch_to_universe("SITREP");
result += "SITREP " + sitrep_val->asRDF() + "\n";
} catch (const std::exception&) {
// SITREP not available; silently skip
}
result += sitrep_parser_context();
}
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

With --sitrep, the appended lines use prefixed names (obj:, type:, archetype:, xsd:) but the output does not include any @prefix declarations (and lines like SITREP ..., PROXIMATE (...) are not valid Turtle triples). If this is meant to be parseable RDF/Turtle as the help text suggests, consider emitting the same prefix block as --inspect (or full URIs) and output valid Turtle statements (e.g., triples) rather than custom labels.

Copilot uses AI. Check for mistakes.
Comment thread src/update_universe.cc
Comment on lines +141 to +145
try {
Value sitrep_val = dispatch_to_universe("SITREP");
result += "SITREP " + sitrep_val->asRDF() + "\n";
} catch (const std::exception&) {
// SITREP not available; silently skip
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

Calling dispatch_to_universe("SITREP") will create a new message ID via Messages.index() if the saved game doesn’t already contain that message name. Even if SITREP is unavailable and you “silently skip”, the universe is still mutated and then re-serialized (out << Universe::instance()), potentially changing the saved file just because --sitrep was requested. To avoid this, use a non-mutating lookup (e.g., Messages.find() + error) when sending optional messages like SITREP.

Suggested change
try {
Value sitrep_val = dispatch_to_universe("SITREP");
result += "SITREP " + sitrep_val->asRDF() + "\n";
} catch (const std::exception&) {
// SITREP not available; silently skip
if (Messages.find("SITREP") >= 0) {
try {
Value sitrep_val = dispatch_to_universe("SITREP");
result += "SITREP " + sitrep_val->asRDF() + "\n";
} catch (const std::exception&) {
// SITREP failed at runtime; silently skip
}

Copilot uses AI. Check for mistakes.
Comment thread src/Value.cc
Comment on lines +40 to +48
// Look up the identifier name bound to an object, or empty string if none.
static std::string identifier_of(int object_id) {
for (auto const& p : Universe::instance().ObjectIdentifiers) {
if (p.second == object_id) {
return Universe::instance().Identifiers.get(p.first);
}
}
return "";
}
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

identifier_of() linearly scans Universe::instance().ObjectIdentifiers on every ObjectValue::asRDF() call. In RDF export paths (inspect + sitrep), this can become O(N^2) for large universes with many object references/attributes. Consider building a reverse map once (object_id -> identifier_id) and reusing it, or adding an efficient reverse lookup facility to Universe.

Copilot uses AI. Check for mistakes.
Comment thread src/main.cc
Comment on lines +92 to +94
<< " --input=<string> In combination with --update, provide command input as a string." << endl
<< " --sitrep In combination with --update, append a situation report (RDF/Turtle)." << endl
<< " --inspect=file.acx Load a saved binary file and dump its contents as RDF/Turtle." << endl
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

The --sitrep usage string claims the appended report is “RDF/Turtle”, but the current --sitrep output path doesn’t emit Turtle prefixes/triples (it prints labeled collections like SITREP (...), PROXIMATE (...)). Either adjust the help text to describe the actual format, or update the output to be well-formed Turtle so users can pipe it directly into RDF tooling.

Copilot uses AI. Check for mistakes.
Comment thread src/inspect_universe.cc
Comment on lines +90 to 96
// Attributes: flat view with evaluated values
for (auto const& attr : obj->attributes_) {
// Archetype has an endearing (sigh) way of instantiating any attributes that have even been
// observed with UNDEFINED. This is one reason why saved games have greater size.
const bool hide_undefined = true;
auto value = dynamic_cast<const ValueExpression*>(attr.second.get());
if (!hide_undefined or (value and value->evaluate()->isDefined())) {
out << " ; prop:hasAttribute attr:" << Universe::instance().Identifiers.get(attr.first) << '\n';
Value value = attr.second->evaluate();
if (value->isDefined()) {
out << "\n ; attr:" << Universe::instance().Identifiers.get(attr.first)
<< " " << value->asRDF();
}
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

inspect_universe currently evaluates every attribute expression (attr.second->evaluate()) without setting self/context and without guarding against non-literal expressions. This can produce incorrect values (wrong context), trigger side effects, or even mutate game state during inspection. Consider limiting inspection to ValueExpression-backed attributes (as before), or setting a ContextScope with selfObject = obj and ensuring evaluation is side-effect-free before calling evaluate().

Copilot uses AI. Check for mistakes.
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