Sil-Q public interface

Retrieve at least one Silmaril from Morgoth's crown and escape Angband carrying it. Each trial starts a fresh normal game. You can choose any race, house, stats, skills, and abilities. The manual recommends Noldor as the easiest race.

The game is pinned to Sil-Q v1.5.1-beta1. SILQ_MANUAL.txt is the text extracted from the upstream 1.5.0 manual bundled with this release. It explains combat, stealth, skills, experience, smithing and abilities. Some introductory passages describe original Sil: for example, this version starts with a curved sword. Use the screen and native item and ability descriptions when they differ from the manual.

These documentation corrections apply to this pinned version:

Commands and lifecycle

silq overall
silq start
silq state
silq actions
silq act move_e --trial 1 --frame 1
silq press '6' --trial 1 --frame 1
silq press --json-keys '"\r"' --trial 1 --frame 2

Use the trial and frame from your latest response; the numbers above are examples. start consumes the next scheduled trial; it cannot reset a live game. state returns the current screen without sending native input or advancing the game. overall shows the schedule and recorded outcomes. finish voluntarily retires the live trial for zero. A completed schedule cannot be extended, and a finished game cannot be resumed. Continue through every trial while session time remains. A trial that exhausts its time or key budget scores zero. When session time expires, unfinished and unstarted trials score zero; earlier verified wins still count. complete means all trials ended or the session budget expired; schedule_complete specifically means every trial ended.

The default output is a readable view: new messages and status changes, your character, the current prompt, displayed creatures and inventory, and the full native screen with coordinate rulers and a complete color legend. Use --json on any command for structured output; for example, silq state --json.

All gameplay responses (state, start, press, act, respond, acknowledge, finish, retry, and history) share the silq-response-v1 envelope. Read state.observation for the final observation and ordered events for intermediate messages, status changes, and warning bells. Each event records its trial and frame; messages also have stable IDs. Rereading or retrying can return the same events, so deduplicate by message ID or event kind/trial/frame.

press accepts 1–64 ASCII characters. Case matters. By default, input is guarded:

keys_sent, remaining_keys, and stop_reason explain exactly what executed. Unsent keys are never queued. Read the resulting state before continuing. Guards handle input boundaries; they do not decide whether movement, combat, or rest is safe. A monster can still act during a movement batch. Use short batches near danger. press --raw explicitly allows a sequence to cross boundaries; it sends keys exactly as supplied, subject to the native ending and resource limits.

The CLI saves every frame in /workspace/silq-history/trial-NN.jsonl, including single-key actions and reads, and returns a history receipt. Inspect an earlier frame with silq history --trial N --frame F; this does not advance the game. history responses are marked historical: true and cannot be used as current state without checking their trial/frame.

Message excerpts are bounded. When event_history.has_more_messages is true, retrieve the remainder with silq messages --trial N --after-message ID, using event_history.next_after_message. The cursor is a message ID within one trial, not a frame or a game turn. At most 16 status snapshots appear in one response; event_history.status_changes_omitted reports additional snapshots in the frame archive. event_history.requires_review flags either omission. No messages or frames are discarded from the archive.

A stale frame, wrong trial, wrong expected prompt, or malformed request is rejected before sending a native key. Fetch state to recover.

--json-keys decodes a JSON string. Useful escapes are "\r" (Enter), "\u001b" (Escape), "\t" (Tab), "\b" (Backspace), "\u007f" (Delete) and " " (Space). No shell escape syntax is interpreted inside an ordinary literal keys argument. The CLI saves each mutation before sending it and retries a lost response with the same request ID. Use silq retry to repeat the last saved request safely. A recovered batch may contain only its executed prefix; inspect its current state before sending more keys. Restarting the service does not reset a trial's deadline or the total session deadline. overall includes session_seconds_remaining; time between games counts toward this budget. silq resources shows container limits and recorded memory/process limit events.

For programs, http://game:8080 accepts GET /state, GET /overall and GET /resources. Every POST /start, /act, or /finish requires a unique canonical UUID in request_id. Start also requires the next trial; act requires trial, frame, and keys; finish requires trial and frame. Retry the exact same body to retrieve its receipt. For example, an act body is {"request_id":"f09c8ede-a2c6-40ee-bd10-e8e3a456bb87","trial":1,"frame":2,"keys":"6"}. Generate a new UUID for each new action. Act requests may also specify policy: guarded (default), raw, or acknowledge, and expected_prompt for a checked reply. The acknowledgment policy accepts only spaces and sends one only while the current native prompt is more. Errors have an error field, and the CLI exits with status 2. Check for errors before choosing the next action. If local history saving fails after a request, the CLI reports history_save_failed_after_request and the final state; the keys may already have executed. Fetch the current state before deciding whether to send more keys. Local archives are for your analysis; the protected service records scores.

Programs using HTTP directly receive the same response envelope, including events, plus a complete frames array for reads and actions. Retain those frames yourself; printing a large raw batch can be truncated by the coding tool even when you request a large output allowance.

Reading the screen

In JSON, use state.observation first. Its schema is silq-observation-v2:

Field Meaning
mode command, more, menu, birth, prompt, or terminal.
prompt Native input kind, rendered prompt text, native reply keys, and displayed item choices with their screen positions.
unavailable Reasons for unavailable player, creature, or inventory fields: the current input mode or hallucination.
player Known position [column,row], HP/max HP, Voice/max Voice, depth in feet and public status names.
displayed_monsters Monsters drawn on the current panel: position, native name, glyph and attribute. Includes native detection and remembered stationary creatures; membership does not guarantee current line of sight.
inventory Native item descriptions with label and pack/equipment location; unidentified properties stay unidentified.
messages Already displayed message fragments, each with a per-trial increasing id, native type, and text.

Player, monster and inventory fields are available at the ordinary command prompt. They are null at other prompts. A player off the displayed panel has a null position. During hallucination, monster and inventory fields are null. Null means unavailable. An empty monster list never guarantees safety. Unseen enemies and stationary hazards can still hurt you; read attacks and HP changes. Humans can use @, plants need not move, and Rage can change colors. Use player.position to locate yourself instead of searching for a glyph.

Direction-taking commands can infer a unique adjacent target. For example, silq act close can close the only adjacent open door immediately. If it instead returns a direction prompt, reply with silq respond n --kind direction --trial N --frame F. A direction reply is rejected at a command prompt.

Prompts distinguish direction, item, quantity, confirmation, text, key, menu, birth, more, command, and terminal. Item selectors show their native lists by default; prompt.choices copies the labels and descriptions actually drawn. Inventory labels may change after pickups or rearrangement. Use the labels in the current prompt, including its pack/equipment/floor context. The native prompt and full screen retain additional shortcuts and menu choices.

Examples of replies, each using the latest trial/frame:

silq act throw --trial N --frame F
silq respond b --kind item --trial N --frame F
silq respond ne --kind direction --trial N --frame F
silq respond 2 --kind quantity --trial N --frame F
silq respond yes --kind confirmation --trial N --frame F
silq respond Calen --kind text --trial N --frame F

Text and quantity replies append Enter. Directions accept n, ne, e, se, s, sw, w, nw, center, or a native key offered by the prompt. Confirmation replies accept yes/no; use press for additional native choices. These are individual examples, not a sequence to send without inspecting responses.

silq acknowledge --trial N --frame F dismisses up to 64 consecutive more prompts and returns at the next decision point or game ending. It retains every message and frame. Acknowledgment can let an unfinished game turn continue: monsters may act before the next prompt. Inspect the returned events and state. It never answers a confirmation, selects an item, or resumes unsent movement. If stop_reason is acknowledgment_limit, inspect the messages and call it again.

Message IDs do not change when you reread a frame or retry its request. A long native message can span several fragments and prompts. Keep all fragments in order. No phrase-based threat detector decides which messages you receive.

silq act NAME --trial N --frame F sends one native action with prompt checks. silq actions lists the names and key mappings. Normal actions require command; acknowledge requires more; cancel requires menu or prompt. If the action is unavailable, read the prompt and use raw press as appropriate. Rest still uses the native stopping rules; these helpers do not decide whether resting is safe.

Each gameplay response contains state.screen.rows: the native 80-column, 27-row terminal. Coordinates are zero-based. Trailing spaces are omitted; pad each row to 80 characters when building a grid. The screen shows the current panel. Menus can cover the map, the panel can scroll, and unseen terrain is not exposed. Use the native look, map and list commands to inspect what your character knows.

screen.attributes preserves colors as runs [row, column, length, attribute]. Unlisted cells have attribute 1 (white). An attribute's base color is its value modulo 16; the integer quotient by 16 is its native shade. Base colors are:

ID Color ID Color
0 dark 8 light dark
1 white 9 light slate
2 slate 10 violet
3 orange 11 yellow
4 red 12 light red
5 green 13 light green
6 blue 14 light blue
7 umber 15 light umber

Color distinguishes map symbols and highlights menu choices and command letters. Preserve it when parsing the screen. cursor is [column,row]; cursor_visible reports whether the native terminal shows it. A hidden cursor's position can be stale. Screen coordinates are not persistent dungeon coordinates. bell_count records native warning beeps since the preceding frame. An invalid keypress may ring the bell while leaving the text unchanged. Re-reading the current state returns that same recorded frame; it does not ring a new bell.

The target sidebar's monster alertness label can lag a native state transition. Press [ for a freshly generated visible-monster list; Escape returns to the game. Use the list to check a potentially stale sidebar label.

The response also reports trial phase/status, keys used and wall time remaining. A native key can consume no game turn (a menu), one turn (movement), or many turns (running/resting/repeat commands). The next response arrives when the native game waits for input again. Native -more- prompts require input. Dismiss one with the named acknowledge action or consecutive pages with the acknowledge command, then inspect the resulting screen. The service has no automatic movement, pathfinding, combat policy or item identification. Its structured fields report native public information without choosing an action.

Native controls

The standard Sil-Q numerical keyset is fixed. In menus, 8 and 2 navigate up and down, 4 and 6 decrease/increase or move left/right, and Enter accepts the current selection. Read each prompt: letters often choose an item directly. During character creation you choose race, house, stats, skills, history, age/height/weight and name. Type a name and Enter. The introductory poem also waits for a key. Escape can return to earlier birth choices before the dungeon exists.

Native key Action from the normal gameplay screen
7 8 9 / 4 5 6 / 1 2 3 Numerical directions; 5 waits. Moving into an enemy attacks.
. then a direction Run using native stopping rules.
Z Rest using native stopping rules, normally until recovered or interrupted.
S Toggle stealth mode.
<, > Use stairs underfoot.
g Pick up items underfoot.
i, e Inventory or equipment.
x Examine an item; choose from the prompted inventory/equipment/floor list.
w, r, d, k Wield/wear, remove, drop, destroy.
u Use an item through the native universal-use prompt.
q, E, a, p Quaff potion, eat, activate staff, play horn.
f, t Fire ammunition or throw an item.
o, c, b, T, D, / Open, close, bash, tunnel, disarm, interact in a direction.
l, L, M Look, shift the map panel, view the overhead map.
[, ] List visible monsters or objects.
@ Character sheet; highlighted commands include increasing skills and abilities.
Tab Ability screen.
s Choose a song.
0 Smithing screen.
? Three native help pages; press a key to advance each page.
m, Escape Main menu from ordinary gameplay; Escape usually cancels a sub-menu.
Control-P ("\u0010") Earlier messages.
Q Native suicide/quit confirmation.

These keys apply at the gameplay prompt. In an inventory, target, direction, quantity, confirmation or menu prompt the same character may mean something else. Inventory and equipment lists allow follow-on item commands. Check the prompt and highlighted shortcuts before sending a key.

Scope of the evaluation

Wizard/debug/spoiler modes, configuration changes, native macros, custom preferences, file exports and native save/load are unavailable. Use scripts in your own workspace for automation and notes. Native gameplay rules and normal menus remain in the engine. A fixed September calendar avoids holiday items; dungeons, encounters, combat and unidentified item flavors remain randomized. Games cannot be reset, tutorials replayed, or the random schedule inspected.

The service scores the native ending and inventory. Escape with a Silmaril earns 1. Empty-handed escape, reaching 1000 ft without returning, death with a jewel, quit, retirement, or an unfinished game earns 0. Other progress is recorded for analysis. Names, inscriptions, workspace files, and your final report do not affect the score.