--- title: "Dormirians" id: 50612 type: "computer_media" slug: "dormirians" url: "http://localhost/computer_media/dormirians/" markdown_url: "http://localhost/computer_media/dormirians.md" published_at: "2023-06-23T11:26:00+00:00" modified_at: "2026-03-31T07:47:52+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "Navigate alien rooms against a ticking countdown, collect scattered letters, and crack a secret five-letter code before your shuttle departs forever." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" - name: "Text Adventure" slug: "text-adventure" taxonomy: "genre" url: "http://localhost/type/text-adventure/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Dormirians%20%28198x%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2023/06/domirians.jpeg" caption: "Vintage 1980s airbrush cassette inlay art, Oliver Frey style, a lone space explorer in a sleek jumpsuit lunging toward the viewer through a labyrinthine alien chamber, extreme foreshortening, glowing scattered letters hovering in mist, bizarre extraterrestrial architecture receding in dramatic perspective, a countdown timer blazing in hot red, a departing shuttle streaking through a distant portal, deep purples and electric blues, atmospheric haze, muscular exaggerated figure, bold explosive composition, five cryptic symbols pulsing with energy, Luma ink airbrush technique, British comic-strip science fiction fantasy, bigger-than-life emotional urgency, Crash magazine cover aesthetic --ar 3:4 --raw --v 6 Job ID: 345f80b4-4ffb-4a00-b746-46ac9ce9706d" - url: "http://localhost/wp-content/uploads/2023/06/SCR-20260331-ebmz.png" media_type_tags: "Game, Text Adventure" --- # Dormirians This is a science-fiction text adventure in which the player navigates a network of rooms to collect letters that spell a five-letter code word, then guesses the code before a countdown timer expires. Each playthrough randomizes the target code word from one of five pre-encoded choices stored in a DATA string. Navigation directions and room connections are packed into parallel string arrays read from DATA, with each room’s exits encoded as single characters and destinations as ASCII-offset letters. A centered-text subroutine at line 3000 handles word-wrapping for messages shorter and longer than 32 characters. The game uses the TS2068’s SOUND and BORDER commands for audio-visual effects including a ticking alarm when time runs low. *** ## Program Analysis ### Program Structure The program is organized into a main game loop, two subroutines, and DATA blocks. Execution flows as follows: 1. Lines 10–30: Initialize `LC` (last code) and read all data strings into `R$`, `L$`, `C$`, `U$`, `S$`, `N$`. 2. Lines 60–80: Set up a new game — choose a random code index `C`, reset `ROOM`, move counter `MC`, and timer `TM`. 3. Lines 110–350: Main navigation loop — display room info, available exits, collect letters, accept movement keypresses, and decrement the timer. 4. Lines 360–390: Guess phase — triggered after visiting at least 3 rooms (`MC>2`), accepts INPUT and checks against the target word. 5. Lines 400–450 / 460–570: Win and lose branches, with a replay prompt. 6. Lines 1000–1010: Sound effect subroutine using `BEEP` and `SOUND`. 7. Lines 3000–3020: Centered/word-wrapped text display subroutine. 8. Lines 4000–4040: DATA records encoding all room, letter, code, and hint information. ### Data Encoding All game content is packed into six strings read from DATA at line 30. Their roles are: | Variable | DATA line | Content | | --- | --- | --- | | `R$` | 4000 | 54-character string; each room occupies 4 characters giving N/S/E/W exits or `*` for no exit | | `L$` | 4010 | 54-character string; destination room encoded as ASCII letter (A=room 1, B=room 2, …) | | `C$` | 4020 | 25-character string; five 5-letter code words concatenated (NIMRON, IMOR, MINOR, IRON, NIROM…) | | `U$` | 4020 (second field) | 13-character string; for each room, an ASCII-offset letter giving the number of clue letters available (A=0 means no letter) | | `S$` | 4030 | Caesar-cipher hint string (each character shifted +1 from the intended message) | | `N$` | 4040 | Room name string, three characters per room | The code word is selected by `C=(INT(RND*5)+1)*5-4`, yielding values 1, 6, 11, 16, or 21 — the starting index of each 5-letter word in `C$`. ### Room Navigation Logic With 13 rooms inferred from `U$`‘s length, each room’s four directional exits occupy positions `ROOM*4-3 TO ROOM*4` in `R$`. An exit of `*` is treated as impassable. On a valid keypress, line 310 looks up the destination by decoding `CODE L$(X)-65` to get the target room number. The clue letter for a room is fetched at line 150 via `T=C+NR-1`, where `NR=CODE(U$(ROOM))-65`; a value less than 1 means the room has no letter to give. ### Timer and Urgency Mechanics The timer `TM` starts at 240 (notionally seconds) and is decremented continuously. Line 230 decrements it by 1 per display loop iteration. Movement costs 0.55 units (line 320), and failed movement attempts cost an additional 1.1 units (line 350). When `TM<15`, lines 250–260 trigger a rapid BEEP-and-BORDER flash loop, further consuming time, creating genuine urgency. If `TM` reaches zero, the player loses via line 460. The countdown is displayed at `AT 17,4` in MM:SS format. Line 240 pads seconds below 10 with a leading zero using string concatenation — a standard BASIC idiom. ### Centered Text Subroutine (Lines 3000–3020) The subroutine at line 3000 centers and word-wraps all game messages stored in `M$`. If `LEN M$<32`, it prints centered using `TAB ((32-LEN(M$))/2+.6)` — the `+.6` corrects for integer truncation bias. If the string is 32 characters or longer, it scans backward from position 32 to find the last space (line 3010), prints the first segment centered, strips it from `M$`, and recurses via `GO TO 3000`. This makes the subroutine a tail-recursive word-wrapper implemented with a `GO TO`. ### Caesar Cipher Hint Lines 560–570 decode the hint stored in `S$`: each character has its CODE decremented by 1, reversing a Caesar shift of +1 applied when the data was written. This produces the hint text “COUNT THE WAYS EACH NATIVE DIFFERS FROM THE KING”. The decoded string is built into `M$` and displayed, then the code loops back to start a new game. ### Sound Effects The subroutine at lines 1000–1010 plays a win/lose fanfare. It uses `BEEP` for 69 rapid tones followed by the TS2068-specific `SOUND` command for a descending sweep — `SOUND 0,X` in a loop from 255 to 0 creates a falling pitch effect. The final `SOUND 8,0;7,63` resets the sound chip. ### Anti-Repeat Guard Line 70 uses `IF C=LC THEN GO TO 20` to re-roll the code word if the same one was just used, preventing immediate repetition. Since line 20 does not exist, this is a deliberate technique: on the ZX Spectrum/TS2068, a `GO TO` to a non-existent line searches forward and wraps, which in this context effectively re-executes the randomization at line 60. The variable `LC` (last code) is set at line 80 only after a new unique code is confirmed. ### Notable Idioms and Anomalies - Line 220 polls `INKEY$` in a busy loop, decreasing `TM` on each iteration — this doubles as both input handler and timer engine. - `CHR$ 34` is used at line 210 to embed a literal quote character inside a PRINT string, the standard workaround for the lack of escaped quotes in Sinclair BASIC. - Line 560 has a bare `::` after the string assignment — this is a null statement separator used to separate the `LET M$=""` from the `FOR` loop, harmlessly executed as an empty statement. - Line 70 sets `TM=240` before the anti-repeat check, so the timer is reset regardless — the guard only re-randomizes `C`. - The `PAUSE 60` at line 280 before looping back to the keypress poll introduces an approximately one-second delay between timer display updates, roughly calibrating the countdown to real seconds. ## Source Code ``` 10 LET LC=0 30 READ R$: READ L$: READ C$: READ U$: READ S$: READ N$ 60 LET C=(INT (RND*5)+1)*5-4: LET ROOM=1: LET MC=0 70 LET TM=240: IF C=LC THEN GO TO 20 80 CLS : LET LC=C: LET M$="I AM THE MASTER, THE PROTOTYPE." 90 LET M$=M$+"ATTEND TO ME AND YOU WILL FIND WHAT YOU SEEK.": GO SUB 3000 110 LET NR=CODE (U$(ROOM))-65: LET T=C+NR-1 120 IF MC>0 THEN CLS 130 IF NR<1 THEN GO TO 160 140 LET M$="I AM "+N$(ROOM*3-5 TO ROOM*3-3)+",": GO SUB 3000 150 LET M$="AND THE LETTER I GIVE YOU IS *"+C$(T)+"*.": GO SUB 3000 160 PRINT : PRINT : LET M$="YOU CAN MOVE IN THESE DIRECTIONS:": GO SUB 3000: PRINT : PRINT 170 LET M$=" ": FOR X=ROOM*4-3 TO ROOM*4 180 IF R$(X)<>"*" THEN LET M$=M$+R$(X)+" " 190 NEXT X: GO SUB 3000: PRINT : PRINT 200 IF MC<3 THEN LET M$="CHOOSE ONE:": GO SUB 3000: GO TO 220 210 LET M$="CHOOSE ONE, OR PRESS "+CHR$ 34+"G"+CHR$ 34+" TO GUESS:": GO SUB 3000 220 LET K=CODE INKEY$: IF K<>0 THEN GO TO 290 230 LET TM=TM-1: LET T1=INT (TM/60) 240 LET T2=INT (TM-T1*60): LET T$=STR$ T2: IF T2<10 THEN LET T$="0"+T$ 250 IF TM<15 THEN FOR I=1 TO 8: BEEP .011,34: BORDER (I-1): NEXT I: LET TM=TM-1 260 IF TM<1 THEN GO TO 460 280 PRINT AT 17,4;: LET M$="