Initial commit: ZIL source + Python game engine
Original ZIL source code for The Hitchhiker's Guide to the Galaxy (Infocom, 1984) plus a native Python text adventure engine with the Earth opening sequence playable (Bedroom → Front Porch → Front of House → Country Lane → Pub). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@@ -0,0 +1,4 @@
|
|||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
save.qzl
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
3.14
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## What This Is
|
||||||
|
|
||||||
|
This is the original source code for **The Hitchhiker's Guide to the Galaxy** (1984), an interactive fiction game by Infocom (designed by Douglas Adams and Steve Meretzky). The code is written in **ZIL** (Zork Implementation Language), Infocom's proprietary Lisp-like language that compiles to Z-machine bytecode.
|
||||||
|
|
||||||
|
Release 60 (October 2, 1986) — the final release version. The compiled game runs as a `.z5` Z-machine story file (a copy is at `docs/The-Hitchhikers-Guide-to-the-Galaxy_DOS_EN_Z5-format/hitchhik.z5`).
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
ZIL source requires the **ZILF** compiler (open-source ZIL-to-Z-machine compiler) or Infocom's original toolchain. There is no build system or Makefile in this repo. To compile with ZILF:
|
||||||
|
|
||||||
|
```
|
||||||
|
zilf s4.zil
|
||||||
|
zapf s4.zap
|
||||||
|
```
|
||||||
|
|
||||||
|
This produces a `.z5` story file playable in any Z-machine interpreter (Frotz, Lectrote, etc.).
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
**Entry point:** `s4.zil` — includes all other source files via `<INSERT-FILE>`.
|
||||||
|
|
||||||
|
**Source files by function:**
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `s4.zil` | Main file; game title, file includes, property defaults |
|
||||||
|
| `globals.zil` | Global variables, directions, meta-objects (ROOMS, IT, NOT-HERE-OBJECT, LOCAL-GLOBALS) |
|
||||||
|
| `parser.zil` | Text parser — tokenizing input, resolving nouns/adjectives, disambiguation |
|
||||||
|
| `syntax.zil` | Vocabulary: BUZZ words, SYNONYMs, direction aliases, verb SYNTAX definitions |
|
||||||
|
| `verbs.zil` | Verb handler routines (`V-TAKE`, `V-DROP`, `V-EXAMINE`, etc.) and game commands |
|
||||||
|
| `misc.zil` | Utility routines, interrupt/clock system, macros |
|
||||||
|
| `earth.zil` | Earth locations — Arthur's bedroom, front of house, pub, country lane |
|
||||||
|
| `vogon.zil` | Vogon ship — hold, guard's room, airlock, poetry appreciation |
|
||||||
|
| `heart.zil` | Heart of Gold — bridge, engine room, corridors, Infinite Improbability Drive |
|
||||||
|
| `unearth.zil` | Off-Earth locations — Traal (Ravenous Bugblatter Beast), Damogran, Magrathea |
|
||||||
|
|
||||||
|
**Assembly files (`.xzap`):** `s4.xzap` is the assembly include order; `s4freq.xzap` defines frequently-used strings (Huffman-compressed). `s4.errors` is the assembler output log.
|
||||||
|
|
||||||
|
## ZIL Conventions
|
||||||
|
|
||||||
|
- **`<OBJECT ...>`** defines game objects with properties (DESC, SYNONYM, FLAGS, ACTION, etc.)
|
||||||
|
- **`<ROOM ...>`** defines locations (rooms are objects with directional exits)
|
||||||
|
- **`<ROUTINE ...>`** defines functions; `-F` suffix indicates an action handler (e.g., `HOME-F`)
|
||||||
|
- **`<GLOBAL ...>`** defines global variables; parser globals are prefixed `P-`
|
||||||
|
- **Flags on objects** control behavior: `TAKEBIT` (takeable), `OPENBIT` (open), `ONBIT` (lit/on), `TOUCHBIT` (seen), etc.
|
||||||
|
- **`PRSA` / `PRSO` / `PRSI`** — parsed action verb, direct object, indirect object
|
||||||
|
- **`<TELL ...>`** outputs text to the player; `CR` = carriage return
|
||||||
|
- Comments use `;"..."` syntax; `;<...>` comments out an entire form
|
||||||
|
|
||||||
|
## docs/
|
||||||
|
|
||||||
|
Contains the original MS-DOS executable, Z5 story file, game manuals (PDF), hint book, game maps, and photos of physical game "feelies" (props included with the boxed game).
|
||||||
|
After Width: | Height: | Size: 144 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 441 KiB |
|
After Width: | Height: | Size: 508 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,716 @@
|
|||||||
|
"""Earth locations — Bedroom, Front Porch, Front of House, Country Lane, Pub."""
|
||||||
|
|
||||||
|
from h2g2.engine.game_object import GameObject, Room, Flag, Direction, DirectExit, ConditionalExit, BlockedExit
|
||||||
|
from h2g2.engine.world import World
|
||||||
|
from h2g2.engine.state import GameState
|
||||||
|
|
||||||
|
|
||||||
|
# ---- Object action handlers ----
|
||||||
|
|
||||||
|
def phone_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
phone = state.world.get("PHONE")
|
||||||
|
if state.prsa == "take":
|
||||||
|
if phone.fset_q(Flag.TOUCHBIT):
|
||||||
|
out.tell("You've already answered the phone.\n")
|
||||||
|
else:
|
||||||
|
phone.fset(Flag.TOUCHBIT)
|
||||||
|
out.tell("You pick up the receiver. A dialling tone.\n")
|
||||||
|
return True
|
||||||
|
if state.prsa == "answer":
|
||||||
|
phone.fset(Flag.TOUCHBIT)
|
||||||
|
out.tell("You pick up the receiver. A dialling tone.\n")
|
||||||
|
return True
|
||||||
|
if state.prsa == "hang up":
|
||||||
|
out.tell("You put down the receiver.\n")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def bed_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
bed = state.world.get("BED")
|
||||||
|
protagonist = state.protagonist
|
||||||
|
|
||||||
|
if state.prsa == "get out":
|
||||||
|
if state.headache:
|
||||||
|
protagonist.move_to(state.here)
|
||||||
|
state.lying_down = False
|
||||||
|
out.tell(
|
||||||
|
"Very difficult, but you manage it. The room is still "
|
||||||
|
"spinning. It dips and sways a little.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
protagonist.move_to(state.here)
|
||||||
|
state.lying_down = False
|
||||||
|
out.tell("You get out of bed.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
if state.prsa == "look under":
|
||||||
|
out.tell(
|
||||||
|
"There's nothing there. Well, there are a few soiled "
|
||||||
|
"handkerchiefs, a book you thought you'd lost, a couple of "
|
||||||
|
"foreign coins, and something else which can't be fully "
|
||||||
|
"described in a family game, but nothing you'd actually want.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
if state.prsa == "examine":
|
||||||
|
out.tell("It's a bed. It's unmade and looks recently slept in.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def gown_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
gown = state.world.get("GOWN")
|
||||||
|
|
||||||
|
if state.prsa == "take" and state.prso is gown:
|
||||||
|
if state.headache:
|
||||||
|
gown.fclear(Flag.TRYTAKEBIT)
|
||||||
|
gown.fclear(Flag.NDESCBIT)
|
||||||
|
gown.move_to(state.protagonist)
|
||||||
|
out.tell(
|
||||||
|
"Luckily, this is large enough for you to get hold of. "
|
||||||
|
"You notice something in the pocket.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
return False # let default take handle it
|
||||||
|
|
||||||
|
if state.prsa == "put on" and state.prso is gown:
|
||||||
|
if not gown.is_held_by(state.protagonist):
|
||||||
|
# Auto-take it first
|
||||||
|
gown.move_to(state.protagonist)
|
||||||
|
gown.fset(Flag.WORNBIT)
|
||||||
|
out.tell("You are now wearing your gown.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
if state.prsa == "examine":
|
||||||
|
out.tell(
|
||||||
|
"The dressing gown is faded and battered, and is clearly a "
|
||||||
|
"garment which has seen better decades. It has a pocket which "
|
||||||
|
"is "
|
||||||
|
)
|
||||||
|
if gown.fset_q(Flag.OPENBIT):
|
||||||
|
out.tell("open")
|
||||||
|
else:
|
||||||
|
out.tell("closed")
|
||||||
|
out.tell(", and a small loop at the back of the collar.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
if state.prsa == "open":
|
||||||
|
gown.fset(Flag.OPENBIT)
|
||||||
|
visible = gown.contents_string()
|
||||||
|
if visible:
|
||||||
|
out.tell("Opening your gown reveals ")
|
||||||
|
descs = [obj.a_desc() for obj in visible]
|
||||||
|
out.tell(", ".join(descs[:-1]))
|
||||||
|
if len(descs) > 1:
|
||||||
|
out.tell(f", and {descs[-1]}")
|
||||||
|
else:
|
||||||
|
out.tell(descs[0])
|
||||||
|
out.tell(".\n")
|
||||||
|
else:
|
||||||
|
out.tell("You open the gown pocket. It's empty.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
if state.prsa == "look in":
|
||||||
|
if not gown.fset_q(Flag.OPENBIT):
|
||||||
|
gown.fset(Flag.OPENBIT)
|
||||||
|
visible = gown.contents_string()
|
||||||
|
if visible:
|
||||||
|
out.tell("Opening your gown reveals ")
|
||||||
|
descs = [obj.a_desc() for obj in visible]
|
||||||
|
if len(descs) > 1:
|
||||||
|
out.tell(", ".join(descs[:-1]))
|
||||||
|
out.tell(f", and {descs[-1]}")
|
||||||
|
else:
|
||||||
|
out.tell(descs[0])
|
||||||
|
out.tell(".\n")
|
||||||
|
else:
|
||||||
|
out.tell("The pocket is empty.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def tablet_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
tablet = state.world.get("TABLET")
|
||||||
|
|
||||||
|
if state.prsa in ("eat", "take", "drink", "swallow"):
|
||||||
|
tablet.move_to(state.world.local_globals) # consumed
|
||||||
|
state.headache = False
|
||||||
|
state.score += 10
|
||||||
|
out.tell(
|
||||||
|
"You swallow the tablet. After a few seconds the room begins "
|
||||||
|
"to calm down and behave in an orderly manner. Your terrible "
|
||||||
|
"headache goes.\n"
|
||||||
|
)
|
||||||
|
# Unset TRYTAKEBIT on screwdriver and toothbrush
|
||||||
|
screw = state.world.objects.get("SCREWDRIVER")
|
||||||
|
tooth = state.world.objects.get("TOOTHBRUSH")
|
||||||
|
if screw:
|
||||||
|
screw.fclear(Flag.TRYTAKEBIT)
|
||||||
|
if tooth:
|
||||||
|
tooth.fclear(Flag.TRYTAKEBIT)
|
||||||
|
return True
|
||||||
|
|
||||||
|
if state.prsa == "examine":
|
||||||
|
out.tell("It says \"Buffered Analgesic\" on the packet.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def thing_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if state.prsa == "examine":
|
||||||
|
out.tell(
|
||||||
|
'Apart from a label on the bottom saying "Made in Ibiza" it '
|
||||||
|
"furnishes you with no clue as to its purpose, if indeed it "
|
||||||
|
"has one. You are surprised to see it because you thought "
|
||||||
|
"you'd thrown it away. Like most gifts from your aunt, it is "
|
||||||
|
"extraordinarily dull.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def curtains_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
bulldozer = state.world.get("BULLDOZER")
|
||||||
|
|
||||||
|
if state.prsa in ("open", "look in", "examine"):
|
||||||
|
bulldozer.fclear(Flag.INVISIBLE)
|
||||||
|
out.tell(
|
||||||
|
"As you part your curtains you see that it is a bright "
|
||||||
|
"morning, the sun is shining, the birds are singing, the "
|
||||||
|
"meadows are blooming, and a large yellow bulldozer is "
|
||||||
|
"advancing on your home.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def screwdriver_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if state.prsa == "take" and state.headache:
|
||||||
|
out.tell("It dances by you like a thing possessed.\n")
|
||||||
|
return True
|
||||||
|
if state.prsa == "examine":
|
||||||
|
out.tell("It's a flathead screwdriver.\n")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def toothbrush_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if state.prsa == "take" and state.headache:
|
||||||
|
out.tell(
|
||||||
|
"You lunge for it, but the room spins nauseatingly away. "
|
||||||
|
"The floor gives you a light tap on the forehead.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
if state.prsa == "examine":
|
||||||
|
out.tell("It's a perfectly normal toothbrush.\n")
|
||||||
|
return True
|
||||||
|
if state.prsa == "brush":
|
||||||
|
out.tell("Your teeth are fine. It's the rest of you that's a wreck.\n")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def bulldozer_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if state.prsa == "examine":
|
||||||
|
if state.world.get("BULLDOZER").fset_q(Flag.INVISIBLE):
|
||||||
|
out.tell("You can't see any bulldozer.\n")
|
||||||
|
else:
|
||||||
|
out.tell(
|
||||||
|
"A large, My, a huge, My, a really huge yellow bulldozer.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def prosser_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if state.prsa == "examine":
|
||||||
|
if state.prosser_in_mud:
|
||||||
|
out.tell(
|
||||||
|
"Mr. Prosser is lying in the mud in front of the "
|
||||||
|
"bulldozer.\n"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
out.tell(
|
||||||
|
"Mr. Prosser is a rather fat man. He seems agitated.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
if state.prsa in ("tell", "ask", "talk"):
|
||||||
|
if state.in_front_of_bulldozer:
|
||||||
|
out.tell(
|
||||||
|
'"Look, Mr. Dent, the plans have been available in the '
|
||||||
|
"planning office for the last nine months!\"\n"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
out.tell(
|
||||||
|
'"Come on, Mr. Dent, you can\'t win you know."\n'
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def ford_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if state.prsa == "examine":
|
||||||
|
out.tell(
|
||||||
|
"He is not the sort of man you'd want to get stuck in a "
|
||||||
|
"lift with, but at a pinch he'd do.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
if state.prsa in ("tell", "ask", "talk"):
|
||||||
|
if state.here and state.here.id == "PUB":
|
||||||
|
out.tell('"Drink up," says Ford, "you\'ve got three pints to get through."\n')
|
||||||
|
elif state.here and state.here.id == "FRONT-OF-HOUSE":
|
||||||
|
out.tell('"Arthur! Come to the pub! I\'ve got to tell you something!"\n')
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def beer_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
beer = state.world.get("BEER")
|
||||||
|
if state.prsa in ("drink", "eat"):
|
||||||
|
state.beer_counter += 1
|
||||||
|
state.score += 5
|
||||||
|
if state.beer_counter >= 3:
|
||||||
|
beer.move_to(state.world.local_globals)
|
||||||
|
out.tell(
|
||||||
|
"You finish the last of your beer. Ford then buys some "
|
||||||
|
"peanuts and hands you something small and yellow and "
|
||||||
|
"wriggly and shoves it in your ear.\n"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
out.tell(
|
||||||
|
f"You drink {'some' if state.beer_counter == 1 else 'more'} "
|
||||||
|
f"beer. {3 - state.beer_counter} pint"
|
||||||
|
f"{'s' if 3 - state.beer_counter != 1 else ''} left.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
if state.prsa == "examine":
|
||||||
|
out.tell(f"There {'are' if state.beer_counter < 3 else 'is no'} beer"
|
||||||
|
f"{'s' if state.beer_counter == 0 else ''} here.\n")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# ---- Room action handlers ----
|
||||||
|
|
||||||
|
def bedroom_action(state: GameState, rarg: str) -> bool:
|
||||||
|
out = state.output
|
||||||
|
|
||||||
|
if rarg == "M-LOOK":
|
||||||
|
bed = state.world.get("BED")
|
||||||
|
gown = state.world.get("GOWN")
|
||||||
|
|
||||||
|
out.tell("The bedroom is a mess.\n")
|
||||||
|
out.tell(
|
||||||
|
"It is a small bedroom with a faded carpet and old wallpaper. "
|
||||||
|
"There is a washbasin, a chair"
|
||||||
|
)
|
||||||
|
if gown.fset_q(Flag.NDESCBIT):
|
||||||
|
out.tell(" with a tatty dressing gown slung over it")
|
||||||
|
out.tell(
|
||||||
|
", and a window with the curtains drawn. Near the exit "
|
||||||
|
"leading south is a phone.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
if rarg == "M-BEG":
|
||||||
|
bed = state.world.get("BED")
|
||||||
|
protagonist = state.protagonist
|
||||||
|
# If player is in the bed, intercept certain actions
|
||||||
|
if protagonist and protagonist.parent is bed:
|
||||||
|
if state.prsa == "take" and state.prso:
|
||||||
|
# Can't reach things from bed
|
||||||
|
if state.prso.parent is not bed and not state.prso.is_held_by(protagonist):
|
||||||
|
out.tell("You can't reach it from the bed.")
|
||||||
|
if state.headache:
|
||||||
|
out.tell(" The effort almost kills you.")
|
||||||
|
out.tell("\n")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def bedroom_exit(state: GameState) -> "Room | None":
|
||||||
|
out = state.output
|
||||||
|
door = state.world.get("BEDROOM-DOOR")
|
||||||
|
|
||||||
|
# Must be out of bed first
|
||||||
|
protagonist = state.protagonist
|
||||||
|
bed = state.world.get("BED")
|
||||||
|
if protagonist and protagonist.parent is bed:
|
||||||
|
out.tell("You'll have to get out of bed first.\n")
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not door.fset_q(Flag.OPENBIT):
|
||||||
|
out.tell("The door is closed.\n")
|
||||||
|
return None
|
||||||
|
|
||||||
|
if state.headache:
|
||||||
|
out.tell(
|
||||||
|
"You miss the doorway by a good eighteen inches. The wall "
|
||||||
|
"jostles you rather rudely.\n"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
bulldozer = state.world.get("BULLDOZER")
|
||||||
|
if bulldozer.fset_q(Flag.INVISIBLE):
|
||||||
|
out.tell("You make your way down to the front porch.\n\n")
|
||||||
|
else:
|
||||||
|
out.tell("You rush down the stairs in panic.\n\n")
|
||||||
|
|
||||||
|
return state.world.get_room("FRONT-PORCH")
|
||||||
|
|
||||||
|
|
||||||
|
def front_porch_action(state: GameState, rarg: str) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if rarg == "M-LOOK":
|
||||||
|
out.tell(
|
||||||
|
"This is the enclosed front porch of your home. Your front "
|
||||||
|
"garden lies to the south, and you can go back upstairs.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def clothes_exit(state: GameState) -> "Room | None":
|
||||||
|
out = state.output
|
||||||
|
gown = state.world.get("GOWN")
|
||||||
|
if gown.fset_q(Flag.WORNBIT):
|
||||||
|
return state.world.get_room("FRONT-OF-HOUSE")
|
||||||
|
out.tell(
|
||||||
|
"You can't leave the house in your current state. You'd be "
|
||||||
|
"arrested for indecency.\n"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def front_of_house_action(state: GameState, rarg: str) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if rarg == "M-LOOK":
|
||||||
|
if state.house_demolished:
|
||||||
|
out.tell(
|
||||||
|
"Where your home used to be there is now a pile of "
|
||||||
|
"rubble, and through it runs a shiny new bypass.\n"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
out.tell(
|
||||||
|
"You can see your house from here. A large yellow "
|
||||||
|
"bulldozer is approaching it.\n"
|
||||||
|
)
|
||||||
|
if state.in_front_of_bulldozer:
|
||||||
|
out.tell("You are lying in the path of the bulldozer.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
if rarg == "M-ENTER":
|
||||||
|
# Ford arrives after a few turns
|
||||||
|
pass
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def house_enter(state: GameState) -> "Room | None":
|
||||||
|
if state.house_demolished:
|
||||||
|
state.output.tell("Your home is now a pile of rubble.\n")
|
||||||
|
return None
|
||||||
|
return state.world.get_room("FRONT-PORCH")
|
||||||
|
|
||||||
|
|
||||||
|
def country_lane_action(state: GameState, rarg: str) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if rarg == "M-LOOK":
|
||||||
|
out.tell(
|
||||||
|
"You are in a pleasant country lane winding between the "
|
||||||
|
"village and the pub. Your home lies to the north, and the "
|
||||||
|
"pub is south.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def pub_action(state: GameState, rarg: str) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if rarg == "M-LOOK":
|
||||||
|
out.tell(
|
||||||
|
"You are in the saloon bar of the Horse and Groom. "
|
||||||
|
"The pub is pleasant and cheerful. The exit is to the north.\n"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
if rarg == "M-ENTER":
|
||||||
|
ford = state.world.get("FORD")
|
||||||
|
beer = state.world.get("BEER")
|
||||||
|
if not state.ford_arrived:
|
||||||
|
state.ford_arrived = True
|
||||||
|
ford.move_to(state.here)
|
||||||
|
beer.move_to(state.here)
|
||||||
|
out.tell(
|
||||||
|
'\nFord Prefect bursts in. "Arthur! Thank God you\'re here! '
|
||||||
|
"I've got to tell you the most important thing you've ever "
|
||||||
|
'heard!"\n'
|
||||||
|
"He buys you three pints of beer.\n"
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# ---- Registration ----
|
||||||
|
|
||||||
|
def register(world: World) -> None:
|
||||||
|
"""Create all Earth rooms and objects."""
|
||||||
|
|
||||||
|
# ---- Objects (not in rooms yet) ----
|
||||||
|
|
||||||
|
bedroom_door = world.register(GameObject(
|
||||||
|
"BEDROOM-DOOR", desc="door",
|
||||||
|
synonyms=["door"],
|
||||||
|
flags={Flag.DOORBIT, Flag.OPENBIT, Flag.NDESCBIT},
|
||||||
|
))
|
||||||
|
bedroom_door.move_to(world.local_globals)
|
||||||
|
|
||||||
|
bulldozer = world.register(GameObject(
|
||||||
|
"BULLDOZER", desc="bulldozer",
|
||||||
|
synonyms=["bulldozer", "tractor"],
|
||||||
|
adjectives=["large", "yellow", "big"],
|
||||||
|
flags={Flag.INVISIBLE, Flag.NDESCBIT},
|
||||||
|
action=bulldozer_action,
|
||||||
|
))
|
||||||
|
bulldozer.move_to(world.local_globals)
|
||||||
|
|
||||||
|
prosser = world.register(GameObject(
|
||||||
|
"PROSSER", desc="Mr. Prosser",
|
||||||
|
synonyms=["prosser", "man"],
|
||||||
|
adjectives=["fat", "mr"],
|
||||||
|
flags={Flag.NARTICLEBIT, Flag.ACTORBIT, Flag.NDESCBIT},
|
||||||
|
action=prosser_action,
|
||||||
|
))
|
||||||
|
|
||||||
|
ford = world.register(GameObject(
|
||||||
|
"FORD", desc="Ford Prefect",
|
||||||
|
synonyms=["ford", "prefect"],
|
||||||
|
adjectives=["ford"],
|
||||||
|
flags={Flag.NARTICLEBIT, Flag.ACTORBIT, Flag.NDESCBIT},
|
||||||
|
action=ford_action,
|
||||||
|
))
|
||||||
|
|
||||||
|
window = world.register(GameObject(
|
||||||
|
"WINDOW", desc="window",
|
||||||
|
synonyms=["window"],
|
||||||
|
flags={Flag.NDESCBIT},
|
||||||
|
))
|
||||||
|
window.move_to(world.local_globals)
|
||||||
|
|
||||||
|
stairs = world.register(GameObject(
|
||||||
|
"STAIRS", desc="stairs",
|
||||||
|
synonyms=["stairs", "staircase", "stairway"],
|
||||||
|
flags={Flag.NDESCBIT},
|
||||||
|
))
|
||||||
|
stairs.move_to(world.local_globals)
|
||||||
|
|
||||||
|
# ---- BEDROOM ----
|
||||||
|
|
||||||
|
bedroom = world.register(Room(
|
||||||
|
"BEDROOM", desc="Bedroom",
|
||||||
|
flags={Flag.RLANDBIT},
|
||||||
|
action=bedroom_action,
|
||||||
|
global_objects=[
|
||||||
|
world.get("BEDROOM-DOOR"), bulldozer, window, stairs,
|
||||||
|
],
|
||||||
|
))
|
||||||
|
|
||||||
|
bed = world.register(GameObject(
|
||||||
|
"BED", desc="bed",
|
||||||
|
synonyms=["bed"],
|
||||||
|
flags={Flag.VEHBIT, Flag.CONTBIT, Flag.SURFACEBIT,
|
||||||
|
Flag.SEARCHBIT, Flag.OPENBIT, Flag.NDESCBIT},
|
||||||
|
action=bed_action,
|
||||||
|
))
|
||||||
|
bed.move_to(bedroom)
|
||||||
|
|
||||||
|
phone = world.register(GameObject(
|
||||||
|
"PHONE", desc="telephone",
|
||||||
|
synonyms=["phone", "telephone", "receiver"],
|
||||||
|
flags={Flag.NDESCBIT, Flag.TAKEBIT, Flag.TRYTAKEBIT},
|
||||||
|
action=phone_action,
|
||||||
|
))
|
||||||
|
phone.move_to(bedroom)
|
||||||
|
|
||||||
|
gown = world.register(GameObject(
|
||||||
|
"GOWN", desc="your gown",
|
||||||
|
ldesc="Your gown is here.",
|
||||||
|
synonyms=["gown", "pocket", "robe"],
|
||||||
|
adjectives=["my", "your", "dressing", "tatty", "faded", "battered"],
|
||||||
|
flags={Flag.WEARBIT, Flag.TRYTAKEBIT, Flag.TAKEBIT, Flag.CONTBIT,
|
||||||
|
Flag.NDESCBIT, Flag.NARTICLEBIT, Flag.SEARCHBIT},
|
||||||
|
size=15, capacity=14,
|
||||||
|
action=gown_action,
|
||||||
|
))
|
||||||
|
gown.move_to(bedroom)
|
||||||
|
|
||||||
|
curtains = world.register(GameObject(
|
||||||
|
"CURTAINS", desc="your curtains",
|
||||||
|
synonyms=["curtains", "curtain", "shade", "shades"],
|
||||||
|
adjectives=["your"],
|
||||||
|
flags={Flag.NDESCBIT, Flag.NARTICLEBIT},
|
||||||
|
action=curtains_action,
|
||||||
|
))
|
||||||
|
curtains.move_to(bedroom)
|
||||||
|
|
||||||
|
# Objects inside the gown
|
||||||
|
thing = world.register(GameObject(
|
||||||
|
"THING", desc="thing your aunt gave you which you don't know what it is",
|
||||||
|
synonyms=["thing", "gift"],
|
||||||
|
adjectives=["aunt's"],
|
||||||
|
flags={Flag.TAKEBIT, Flag.CONTBIT, Flag.SEARCHBIT, Flag.OPENBIT},
|
||||||
|
size=6, capacity=90,
|
||||||
|
action=thing_action,
|
||||||
|
))
|
||||||
|
thing.move_to(gown)
|
||||||
|
|
||||||
|
fluff = world.register(GameObject(
|
||||||
|
"POCKET-FLUFF", desc="pocket fluff",
|
||||||
|
synonyms=["fluff", "lint"],
|
||||||
|
adjectives=["pocket"],
|
||||||
|
flags={Flag.TAKEBIT, Flag.NARTICLEBIT},
|
||||||
|
size=1,
|
||||||
|
))
|
||||||
|
fluff.move_to(gown)
|
||||||
|
|
||||||
|
tablet = world.register(GameObject(
|
||||||
|
"TABLET", desc="buffered analgesic",
|
||||||
|
synonyms=["analgesic", "tablet", "aspirin", "pill"],
|
||||||
|
adjectives=["large", "buffered"],
|
||||||
|
flags={Flag.TAKEBIT},
|
||||||
|
size=2,
|
||||||
|
action=tablet_action,
|
||||||
|
))
|
||||||
|
tablet.move_to(gown)
|
||||||
|
|
||||||
|
screwdriver = world.register(GameObject(
|
||||||
|
"SCREWDRIVER", desc="flathead screwdriver",
|
||||||
|
synonyms=["screwdriver", "tool", "tools"],
|
||||||
|
adjectives=["flathead", "flat"],
|
||||||
|
flags={Flag.TAKEBIT, Flag.TRYTAKEBIT, Flag.TOOLBIT},
|
||||||
|
size=3,
|
||||||
|
action=screwdriver_action,
|
||||||
|
))
|
||||||
|
screwdriver.move_to(bedroom)
|
||||||
|
|
||||||
|
toothbrush = world.register(GameObject(
|
||||||
|
"TOOTHBRUSH", desc="toothbrush",
|
||||||
|
synonyms=["toothbrush", "brush"],
|
||||||
|
adjectives=["tooth", "my"],
|
||||||
|
flags={Flag.TAKEBIT, Flag.TRYTAKEBIT, Flag.TOOLBIT},
|
||||||
|
size=3,
|
||||||
|
action=toothbrush_action,
|
||||||
|
))
|
||||||
|
toothbrush.move_to(bedroom)
|
||||||
|
|
||||||
|
sink = world.register(GameObject(
|
||||||
|
"SINK", desc="washbasin",
|
||||||
|
synonyms=["basin", "washbasin", "sink"],
|
||||||
|
adjectives=["wash"],
|
||||||
|
flags={Flag.NDESCBIT, Flag.NARTICLEBIT},
|
||||||
|
))
|
||||||
|
sink.move_to(bedroom)
|
||||||
|
|
||||||
|
# Start player in bed
|
||||||
|
world.protagonist.move_to(bed)
|
||||||
|
|
||||||
|
# ---- FRONT PORCH ----
|
||||||
|
|
||||||
|
front_porch = world.register(Room(
|
||||||
|
"FRONT-PORCH", desc="Front Porch",
|
||||||
|
flags={Flag.RLANDBIT, Flag.ONBIT},
|
||||||
|
action=front_porch_action,
|
||||||
|
global_objects=[
|
||||||
|
world.get("BEDROOM-DOOR"), bulldozer, window, stairs,
|
||||||
|
],
|
||||||
|
))
|
||||||
|
|
||||||
|
mail = world.register(GameObject(
|
||||||
|
"MAIL", desc="some junk mail",
|
||||||
|
synonyms=["mail", "junk", "letter", "letters"],
|
||||||
|
flags={Flag.TAKEBIT, Flag.NARTICLEBIT},
|
||||||
|
text="Strewn among the usual junk mail is a notice from the local "
|
||||||
|
"council about a proposed demolition of your house.",
|
||||||
|
))
|
||||||
|
mail.move_to(front_porch)
|
||||||
|
|
||||||
|
# ---- FRONT OF HOUSE ----
|
||||||
|
|
||||||
|
front_of_house = world.register(Room(
|
||||||
|
"FRONT-OF-HOUSE", desc="Front of House",
|
||||||
|
flags={Flag.RLANDBIT, Flag.ONBIT, Flag.OUTSIDEBIT},
|
||||||
|
action=front_of_house_action,
|
||||||
|
global_objects=[bulldozer, prosser],
|
||||||
|
))
|
||||||
|
prosser.move_to(front_of_house)
|
||||||
|
|
||||||
|
# ---- COUNTRY LANE ----
|
||||||
|
|
||||||
|
country_lane = world.register(Room(
|
||||||
|
"COUNTRY-LANE", desc="Country Lane",
|
||||||
|
flags={Flag.RLANDBIT, Flag.ONBIT, Flag.OUTSIDEBIT},
|
||||||
|
action=country_lane_action,
|
||||||
|
))
|
||||||
|
|
||||||
|
# ---- PUB ----
|
||||||
|
|
||||||
|
pub = world.register(Room(
|
||||||
|
"PUB", desc="Pub",
|
||||||
|
flags={Flag.RLANDBIT, Flag.ONBIT},
|
||||||
|
action=pub_action,
|
||||||
|
))
|
||||||
|
|
||||||
|
beer = world.register(GameObject(
|
||||||
|
"BEER", desc="beer",
|
||||||
|
synonyms=["beer", "pint", "pints", "lager", "ale"],
|
||||||
|
adjectives=["three"],
|
||||||
|
flags={Flag.DRINKBIT, Flag.NDESCBIT},
|
||||||
|
action=beer_action,
|
||||||
|
))
|
||||||
|
|
||||||
|
# ---- Connect rooms ----
|
||||||
|
|
||||||
|
bedroom.exits = {
|
||||||
|
Direction.SOUTH: ConditionalExit(bedroom_exit),
|
||||||
|
Direction.OUT: ConditionalExit(bedroom_exit),
|
||||||
|
Direction.DOWN: ConditionalExit(bedroom_exit),
|
||||||
|
}
|
||||||
|
|
||||||
|
front_porch.exits = {
|
||||||
|
Direction.UP: DirectExit(bedroom),
|
||||||
|
Direction.NORTH: DirectExit(bedroom),
|
||||||
|
Direction.SOUTH: ConditionalExit(clothes_exit),
|
||||||
|
Direction.OUT: ConditionalExit(clothes_exit),
|
||||||
|
}
|
||||||
|
|
||||||
|
front_of_house.exits = {
|
||||||
|
Direction.NORTH: ConditionalExit(house_enter),
|
||||||
|
Direction.SOUTH: DirectExit(country_lane),
|
||||||
|
Direction.IN: ConditionalExit(house_enter),
|
||||||
|
}
|
||||||
|
|
||||||
|
country_lane.exits = {
|
||||||
|
Direction.NORTH: DirectExit(front_of_house),
|
||||||
|
Direction.SOUTH: DirectExit(pub),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub.exits = {
|
||||||
|
Direction.NORTH: DirectExit(country_lane),
|
||||||
|
Direction.OUT: DirectExit(country_lane),
|
||||||
|
}
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
"""Global objects — always-visible entities and root containers."""
|
||||||
|
|
||||||
|
from h2g2.engine.game_object import GameObject, Flag
|
||||||
|
from h2g2.engine.world import World
|
||||||
|
from h2g2.engine.state import GameState
|
||||||
|
|
||||||
|
|
||||||
|
def hangover_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if state.prsa == "examine" or state.prsa == "diagnose":
|
||||||
|
if state.headache:
|
||||||
|
out.tell("You have a big blinding throbber.\n")
|
||||||
|
else:
|
||||||
|
out.tell("You don't have a headache.\n")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def light_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if state.prsa == "turn on":
|
||||||
|
if state.here and state.here.fset_q(Flag.ONBIT):
|
||||||
|
out.tell("It is.\n")
|
||||||
|
else:
|
||||||
|
if state.here:
|
||||||
|
state.here.fset(Flag.ONBIT)
|
||||||
|
state.update_lit()
|
||||||
|
out.tell("Good start to the day. Pity it's going to be the worst "
|
||||||
|
"one of your life. The light is now on.\n\n")
|
||||||
|
# Show room description now that light is on
|
||||||
|
from h2g2.engine.loop import GameLoop
|
||||||
|
GameLoop._describe_room_static(state)
|
||||||
|
return True
|
||||||
|
if state.prsa == "turn off":
|
||||||
|
if state.here:
|
||||||
|
state.here.fclear(Flag.ONBIT)
|
||||||
|
state.update_lit()
|
||||||
|
out.tell("It is now pitch dark in here. If you proceed you will "
|
||||||
|
"likely fall into a pit.\n")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def walls_action(state: GameState) -> bool:
|
||||||
|
if state.prsa == "examine":
|
||||||
|
state.output.tell("They look like walls.\n")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def me_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if state.prsa == "examine":
|
||||||
|
if state.headache:
|
||||||
|
out.tell("You look about as ill as you feel.\n")
|
||||||
|
else:
|
||||||
|
out.tell("You look pretty normal.\n")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def ground_action(state: GameState) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if state.prsa == "lie down":
|
||||||
|
state.lying_down = True
|
||||||
|
if state.here and state.here.id == "FRONT-OF-HOUSE":
|
||||||
|
state.in_front_of_bulldozer = True
|
||||||
|
out.tell("You lie down in the path of the advancing bulldozer.\n")
|
||||||
|
else:
|
||||||
|
out.tell("You lie down.\n")
|
||||||
|
return True
|
||||||
|
if state.prsa == "examine":
|
||||||
|
out.tell("It looks like ground.\n")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def register(world: World) -> None:
|
||||||
|
"""Create all global objects and root containers."""
|
||||||
|
|
||||||
|
# Root containers
|
||||||
|
global_objects = world.register(GameObject(
|
||||||
|
"GLOBAL-OBJECTS", desc="global objects",
|
||||||
|
flags={Flag.INVISIBLE},
|
||||||
|
))
|
||||||
|
world.global_objects = global_objects
|
||||||
|
|
||||||
|
local_globals = world.register(GameObject(
|
||||||
|
"LOCAL-GLOBALS", desc="local globals",
|
||||||
|
flags={Flag.INVISIBLE},
|
||||||
|
))
|
||||||
|
local_globals.move_to(global_objects)
|
||||||
|
world.local_globals = local_globals
|
||||||
|
|
||||||
|
protagonist = world.register(GameObject(
|
||||||
|
"PROTAGONIST", desc="you",
|
||||||
|
flags={Flag.INVISIBLE, Flag.ACTORBIT},
|
||||||
|
capacity=100,
|
||||||
|
))
|
||||||
|
world.protagonist = protagonist
|
||||||
|
|
||||||
|
# Globally visible objects
|
||||||
|
world.register(GameObject(
|
||||||
|
"LIGHT", desc="light",
|
||||||
|
synonyms=["light", "lights", "lamp"],
|
||||||
|
flags={Flag.LIGHTBIT},
|
||||||
|
action=light_action,
|
||||||
|
)).move_to(global_objects)
|
||||||
|
|
||||||
|
world.register(GameObject(
|
||||||
|
"WALLS", desc="wall",
|
||||||
|
synonyms=["wall", "walls", "ceiling", "floor"],
|
||||||
|
flags={Flag.NDESCBIT, Flag.TOUCHBIT},
|
||||||
|
action=walls_action,
|
||||||
|
)).move_to(global_objects)
|
||||||
|
|
||||||
|
world.register(GameObject(
|
||||||
|
"ME", desc="yourself",
|
||||||
|
synonyms=["me", "myself", "self", "yourself"],
|
||||||
|
flags={Flag.NDESCBIT, Flag.NARTICLEBIT, Flag.ACTORBIT},
|
||||||
|
action=me_action,
|
||||||
|
)).move_to(global_objects)
|
||||||
|
|
||||||
|
world.register(GameObject(
|
||||||
|
"HANGOVER", desc="splitting headache",
|
||||||
|
synonyms=["headache", "hangover", "throbber"],
|
||||||
|
adjectives=["splitting", "big", "blinding"],
|
||||||
|
action=hangover_action,
|
||||||
|
)).move_to(global_objects)
|
||||||
|
|
||||||
|
world.register(GameObject(
|
||||||
|
"GROUND", desc="ground",
|
||||||
|
synonyms=["ground", "mud", "dirt", "floor", "earth"],
|
||||||
|
flags={Flag.NDESCBIT},
|
||||||
|
action=ground_action,
|
||||||
|
)).move_to(global_objects)
|
||||||
|
|
||||||
|
world.register(GameObject(
|
||||||
|
"HANDS", desc="your hands",
|
||||||
|
synonyms=["hands", "hand"],
|
||||||
|
adjectives=["my", "your"],
|
||||||
|
flags={Flag.NDESCBIT, Flag.NARTICLEBIT},
|
||||||
|
)).move_to(global_objects)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
from h2g2.engine.game_object import GameObject, Room, Flag, Direction, Exit
|
||||||
|
from h2g2.engine.world import World
|
||||||
|
from h2g2.engine.state import GameState
|
||||||
|
from h2g2.engine.output import Output
|
||||||
|
from h2g2.engine.clock import Clock, ClockEntry
|
||||||
|
from h2g2.engine.parser import Parser, ParseResult
|
||||||
|
from h2g2.engine.loop import GameLoop
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"GameObject", "Room", "Flag", "Direction", "Exit",
|
||||||
|
"World", "GameState", "Output",
|
||||||
|
"Clock", "ClockEntry",
|
||||||
|
"Parser", "ParseResult",
|
||||||
|
"GameLoop",
|
||||||
|
]
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
"""Clock/interrupt system — timed events that fire on game turns."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Callable, Any
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ClockEntry:
|
||||||
|
"""A scheduled interrupt."""
|
||||||
|
routine: Callable # (state) -> bool; True = handled/displayed
|
||||||
|
tick: int # Countdown; fires when reaches 0. -1 = every turn
|
||||||
|
enabled: bool = True
|
||||||
|
name: str = "" # For debugging
|
||||||
|
|
||||||
|
|
||||||
|
class Clock:
|
||||||
|
"""Manages timed game events, equivalent to ZIL's C-TABLE/CLOCKER."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.entries: list[ClockEntry] = []
|
||||||
|
|
||||||
|
def queue(self, routine: Callable, tick: int, name: str = "") -> ClockEntry:
|
||||||
|
"""Schedule an interrupt routine to fire after `tick` turns.
|
||||||
|
|
||||||
|
If an entry for the same routine already exists, update its tick.
|
||||||
|
"""
|
||||||
|
for entry in self.entries:
|
||||||
|
if entry.routine is routine:
|
||||||
|
entry.tick = tick
|
||||||
|
entry.enabled = True
|
||||||
|
return entry
|
||||||
|
entry = ClockEntry(routine=routine, tick=tick, name=name)
|
||||||
|
self.entries.append(entry)
|
||||||
|
return entry
|
||||||
|
|
||||||
|
def enable(self, entry: ClockEntry) -> None:
|
||||||
|
entry.enabled = True
|
||||||
|
|
||||||
|
def disable(self, entry: ClockEntry) -> None:
|
||||||
|
entry.enabled = False
|
||||||
|
|
||||||
|
def remove(self, entry: ClockEntry) -> None:
|
||||||
|
if entry in self.entries:
|
||||||
|
self.entries.remove(entry)
|
||||||
|
|
||||||
|
def tick_all(self, state: Any) -> bool:
|
||||||
|
"""Advance all clocks by one turn. Returns True if any event fired."""
|
||||||
|
any_fired = False
|
||||||
|
for entry in list(self.entries): # copy because handlers may modify
|
||||||
|
if not entry.enabled:
|
||||||
|
continue
|
||||||
|
if entry.tick > 0:
|
||||||
|
entry.tick -= 1
|
||||||
|
if entry.tick == 0:
|
||||||
|
result = entry.routine(state)
|
||||||
|
if result:
|
||||||
|
any_fired = True
|
||||||
|
entry.enabled = False # one-shot; re-enable manually
|
||||||
|
elif entry.tick < 0:
|
||||||
|
# Negative tick = fires every turn
|
||||||
|
result = entry.routine(state)
|
||||||
|
if result:
|
||||||
|
any_fired = True
|
||||||
|
return any_fired
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
"""Game object model — items, rooms, NPCs, and the flag/direction system."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import enum
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import Callable, Any
|
||||||
|
|
||||||
|
|
||||||
|
class Flag(enum.Enum):
|
||||||
|
TAKEBIT = enum.auto()
|
||||||
|
OPENBIT = enum.auto()
|
||||||
|
TOUCHBIT = enum.auto()
|
||||||
|
ONBIT = enum.auto()
|
||||||
|
TRANSBIT = enum.auto()
|
||||||
|
WEARBIT = enum.auto()
|
||||||
|
WORNBIT = enum.auto()
|
||||||
|
RLANDBIT = enum.auto()
|
||||||
|
NDESCBIT = enum.auto()
|
||||||
|
INVISIBLE = enum.auto()
|
||||||
|
LIGHTBIT = enum.auto()
|
||||||
|
CONTBIT = enum.auto()
|
||||||
|
SURFACEBIT = enum.auto()
|
||||||
|
ACTORBIT = enum.auto()
|
||||||
|
VEHBIT = enum.auto()
|
||||||
|
DOORBIT = enum.auto()
|
||||||
|
READBIT = enum.auto()
|
||||||
|
DRINKBIT = enum.auto()
|
||||||
|
NARTICLEBIT = enum.auto()
|
||||||
|
VOWELBIT = enum.auto()
|
||||||
|
SEARCHBIT = enum.auto()
|
||||||
|
TRYTAKEBIT = enum.auto()
|
||||||
|
DARKBIT = enum.auto()
|
||||||
|
REVISITBIT = enum.auto()
|
||||||
|
MUNGEDBIT = enum.auto()
|
||||||
|
OUTSIDEBIT = enum.auto()
|
||||||
|
TOOLBIT = enum.auto()
|
||||||
|
INTEGRALBIT = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
|
class Direction(enum.Enum):
|
||||||
|
NORTH = "north"
|
||||||
|
NE = "northeast"
|
||||||
|
EAST = "east"
|
||||||
|
SE = "southeast"
|
||||||
|
SOUTH = "south"
|
||||||
|
SW = "southwest"
|
||||||
|
WEST = "west"
|
||||||
|
NW = "northwest"
|
||||||
|
UP = "up"
|
||||||
|
DOWN = "down"
|
||||||
|
IN = "in"
|
||||||
|
OUT = "out"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DirectExit:
|
||||||
|
"""Simple exit to a fixed room."""
|
||||||
|
destination: Room
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ConditionalExit:
|
||||||
|
"""Exit gated by a function that returns a Room or None."""
|
||||||
|
function: Callable # (state) -> Room | None; None means blocked
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class GatedExit:
|
||||||
|
"""Exit that requires a door object to be open."""
|
||||||
|
destination: Room
|
||||||
|
door: GameObject
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BlockedExit:
|
||||||
|
"""Permanently blocked exit with a message."""
|
||||||
|
message: str
|
||||||
|
|
||||||
|
|
||||||
|
Exit = DirectExit | ConditionalExit | GatedExit | BlockedExit
|
||||||
|
|
||||||
|
|
||||||
|
class GameObject:
|
||||||
|
"""A game entity — item, NPC, abstract concept, or container."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: str,
|
||||||
|
*,
|
||||||
|
desc: str = "",
|
||||||
|
ldesc: str | None = None,
|
||||||
|
fdesc: str | None = None,
|
||||||
|
synonyms: list[str] | None = None,
|
||||||
|
adjectives: list[str] | None = None,
|
||||||
|
flags: set[Flag] | None = None,
|
||||||
|
size: int = 5,
|
||||||
|
capacity: int = 0,
|
||||||
|
action: Callable | None = None,
|
||||||
|
text: str | None = None,
|
||||||
|
):
|
||||||
|
self.id = id
|
||||||
|
self.desc = desc
|
||||||
|
self.ldesc = ldesc
|
||||||
|
self.fdesc = fdesc
|
||||||
|
self.synonyms: list[str] = [s.lower() for s in (synonyms or [])]
|
||||||
|
self.adjectives: list[str] = [a.lower() for a in (adjectives or [])]
|
||||||
|
self.flags: set[Flag] = flags or set()
|
||||||
|
self.size = size
|
||||||
|
self.capacity = capacity
|
||||||
|
self.action = action
|
||||||
|
self.text = text
|
||||||
|
|
||||||
|
# Containment tree
|
||||||
|
self.parent: GameObject | None = None
|
||||||
|
self.children: list[GameObject] = []
|
||||||
|
|
||||||
|
def move_to(self, new_parent: GameObject | None) -> None:
|
||||||
|
"""Move this object into a new container."""
|
||||||
|
if self.parent:
|
||||||
|
self.parent.children.remove(self)
|
||||||
|
self.parent = new_parent
|
||||||
|
if new_parent:
|
||||||
|
new_parent.children.append(self)
|
||||||
|
|
||||||
|
def contains(self, obj: GameObject) -> bool:
|
||||||
|
"""Check if obj is a direct child."""
|
||||||
|
return obj in self.children
|
||||||
|
|
||||||
|
def is_held_by(self, holder: GameObject) -> bool:
|
||||||
|
"""Check if this object is carried by holder (direct or nested)."""
|
||||||
|
current = self.parent
|
||||||
|
while current:
|
||||||
|
if current is holder:
|
||||||
|
return True
|
||||||
|
current = current.parent
|
||||||
|
return False
|
||||||
|
|
||||||
|
def contents_string(self) -> list[GameObject]:
|
||||||
|
"""Return visible children (not INVISIBLE or NDESCBIT)."""
|
||||||
|
return [
|
||||||
|
c for c in self.children
|
||||||
|
if Flag.INVISIBLE not in c.flags and Flag.NDESCBIT not in c.flags
|
||||||
|
]
|
||||||
|
|
||||||
|
def fset(self, flag: Flag) -> None:
|
||||||
|
self.flags.add(flag)
|
||||||
|
|
||||||
|
def fclear(self, flag: Flag) -> None:
|
||||||
|
self.flags.discard(flag)
|
||||||
|
|
||||||
|
def fset_q(self, flag: Flag) -> bool:
|
||||||
|
return flag in self.flags
|
||||||
|
|
||||||
|
def article(self) -> str:
|
||||||
|
"""Return the appropriate article for this object."""
|
||||||
|
if Flag.NARTICLEBIT in self.flags:
|
||||||
|
return ""
|
||||||
|
if Flag.VOWELBIT in self.flags:
|
||||||
|
return "an "
|
||||||
|
return "a "
|
||||||
|
|
||||||
|
def the_desc(self) -> str:
|
||||||
|
"""Return 'the <desc>' or just desc for proper nouns."""
|
||||||
|
if Flag.NARTICLEBIT in self.flags:
|
||||||
|
return self.desc
|
||||||
|
return f"the {self.desc}"
|
||||||
|
|
||||||
|
def a_desc(self) -> str:
|
||||||
|
"""Return 'a/an <desc>' or just desc for proper nouns."""
|
||||||
|
if Flag.NARTICLEBIT in self.flags:
|
||||||
|
return self.desc
|
||||||
|
return f"{self.article()}{self.desc}"
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f"<{self.__class__.__name__} {self.id!r}>"
|
||||||
|
|
||||||
|
|
||||||
|
class Room(GameObject):
|
||||||
|
"""A location in the game world."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: str,
|
||||||
|
*,
|
||||||
|
desc: str = "",
|
||||||
|
ldesc: str | None = None,
|
||||||
|
synonyms: list[str] | None = None,
|
||||||
|
adjectives: list[str] | None = None,
|
||||||
|
flags: set[Flag] | None = None,
|
||||||
|
action: Callable | None = None,
|
||||||
|
exits: dict[Direction, Exit] | None = None,
|
||||||
|
global_objects: list[GameObject] | None = None,
|
||||||
|
pseudo: list[tuple[str, Callable]] | None = None,
|
||||||
|
):
|
||||||
|
super().__init__(
|
||||||
|
id, desc=desc, ldesc=ldesc, synonyms=synonyms,
|
||||||
|
adjectives=adjectives, flags=flags, action=action,
|
||||||
|
)
|
||||||
|
self.exits: dict[Direction, Exit] = exits or {}
|
||||||
|
self.global_objects: list[GameObject] = global_objects or []
|
||||||
|
self.pseudo: list[tuple[str, Callable]] = pseudo or []
|
||||||
@@ -0,0 +1,284 @@
|
|||||||
|
"""Main game loop and PERFORM dispatch chain."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
from h2g2.engine.game_object import (
|
||||||
|
GameObject, Room, Flag, Direction,
|
||||||
|
DirectExit, ConditionalExit, GatedExit, BlockedExit,
|
||||||
|
)
|
||||||
|
from h2g2.engine.parser import Parser, ParseResult
|
||||||
|
from h2g2.engine.state import GameState
|
||||||
|
from h2g2.engine.output import Output
|
||||||
|
|
||||||
|
# Verb handlers: verb_name -> handler function
|
||||||
|
# Each handler receives (state, prso, prsi) -> bool (True = handled)
|
||||||
|
_verb_handlers: dict[str, Callable] = {}
|
||||||
|
_pre_handlers: dict[str, Callable] = {}
|
||||||
|
|
||||||
|
# Meta-verbs that don't advance the clock
|
||||||
|
META_VERBS = {
|
||||||
|
"save", "restore", "restart", "quit", "score",
|
||||||
|
"verbose", "brief", "superbrief", "again", "inventory",
|
||||||
|
"diagnose",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def verb_handler(verb: str) -> Callable:
|
||||||
|
"""Decorator to register a default verb handler."""
|
||||||
|
def decorator(fn: Callable) -> Callable:
|
||||||
|
_verb_handlers[verb] = fn
|
||||||
|
return fn
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def pre_handler(verb: str) -> Callable:
|
||||||
|
"""Decorator to register a pre-action handler."""
|
||||||
|
def decorator(fn: Callable) -> Callable:
|
||||||
|
_pre_handlers[verb] = fn
|
||||||
|
return fn
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
class GameLoop:
|
||||||
|
"""The main game loop — parse, dispatch, clock."""
|
||||||
|
|
||||||
|
def __init__(self, state: GameState, parser: Parser) -> None:
|
||||||
|
self.state = state
|
||||||
|
self.parser = parser
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
"""Run the main game loop until the game ends."""
|
||||||
|
state = self.state
|
||||||
|
out = state.output
|
||||||
|
|
||||||
|
# Initial room description
|
||||||
|
self._describe_room()
|
||||||
|
print(out.flush(), end="")
|
||||||
|
|
||||||
|
while state.running:
|
||||||
|
try:
|
||||||
|
raw = input("\n> ")
|
||||||
|
except (EOFError, KeyboardInterrupt):
|
||||||
|
print("\nGoodbye!")
|
||||||
|
break
|
||||||
|
|
||||||
|
if not raw.strip():
|
||||||
|
continue
|
||||||
|
|
||||||
|
result = self.parser.parse(raw, state)
|
||||||
|
if result is None:
|
||||||
|
out.tell("I don't understand that.\n")
|
||||||
|
print(out.flush(), end="")
|
||||||
|
continue
|
||||||
|
|
||||||
|
self._execute(result)
|
||||||
|
|
||||||
|
# Print output
|
||||||
|
text = out.flush()
|
||||||
|
if text:
|
||||||
|
print(text, end="")
|
||||||
|
|
||||||
|
def _execute(self, result: ParseResult) -> None:
|
||||||
|
"""Execute a parsed command through the dispatch chain."""
|
||||||
|
state = self.state
|
||||||
|
|
||||||
|
# Set parser state
|
||||||
|
state.prsa = result.verb
|
||||||
|
state.prso = result.direct_obj
|
||||||
|
state.prsi = result.indirect_obj
|
||||||
|
state.dont_flag = result.is_negated
|
||||||
|
|
||||||
|
# Handle movement
|
||||||
|
if result.verb == "walk" and result.direction:
|
||||||
|
self._do_walk(result.direction)
|
||||||
|
else:
|
||||||
|
self._perform(result.verb, result.direct_obj, result.indirect_obj)
|
||||||
|
|
||||||
|
# Update IT pronoun
|
||||||
|
if result.direct_obj and result.verb not in META_VERBS:
|
||||||
|
state.p_it_object = result.direct_obj
|
||||||
|
|
||||||
|
# Store for AGAIN
|
||||||
|
if result.verb not in META_VERBS:
|
||||||
|
state.l_prsa = result.verb
|
||||||
|
state.l_prso = result.direct_obj
|
||||||
|
state.l_prsi = result.indirect_obj
|
||||||
|
|
||||||
|
# Advance clock (unless meta-verb)
|
||||||
|
if result.verb not in META_VERBS:
|
||||||
|
state.moves += 1
|
||||||
|
state.clock.tick_all(state)
|
||||||
|
|
||||||
|
def _perform(
|
||||||
|
self, verb: str,
|
||||||
|
prso: GameObject | None, prsi: GameObject | None,
|
||||||
|
) -> bool:
|
||||||
|
"""Execute the verb dispatch chain. Returns True if handled."""
|
||||||
|
state = self.state
|
||||||
|
out = state.output
|
||||||
|
|
||||||
|
# 1. Room M-BEG handler
|
||||||
|
if state.here and state.here.action:
|
||||||
|
result = state.here.action(state, "M-BEG")
|
||||||
|
if result:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 2. Pre-action handler
|
||||||
|
pre = _pre_handlers.get(verb)
|
||||||
|
if pre:
|
||||||
|
result = pre(state, prso, prsi)
|
||||||
|
if result:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 3. Indirect object handler
|
||||||
|
if prsi and prsi.action:
|
||||||
|
result = prsi.action(state)
|
||||||
|
if result:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 4. Direct object handler
|
||||||
|
if prso and prso.action:
|
||||||
|
result = prso.action(state)
|
||||||
|
if result:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 5. Default verb handler
|
||||||
|
handler = _verb_handlers.get(verb)
|
||||||
|
if handler:
|
||||||
|
return handler(state, prso, prsi)
|
||||||
|
|
||||||
|
out.tell("I don't know how to do that.\n")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _do_walk(self, direction_name: str) -> None:
|
||||||
|
"""Handle movement in a direction."""
|
||||||
|
state = self.state
|
||||||
|
out = state.output
|
||||||
|
|
||||||
|
# Check if in a vehicle/bed
|
||||||
|
if (state.protagonist and state.protagonist.parent
|
||||||
|
and state.protagonist.parent != state.here
|
||||||
|
and state.protagonist.parent.fset_q(Flag.VEHBIT)):
|
||||||
|
out.tell("You'll have to get out of "
|
||||||
|
f"{state.protagonist.parent.the_desc()} first.\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
if state.lying_down:
|
||||||
|
out.tell("You'll have to get up first.\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
direction = Direction[direction_name]
|
||||||
|
if state.here is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
exit_def = state.here.exits.get(direction)
|
||||||
|
if exit_def is None:
|
||||||
|
out.tell("You can't go that way.\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
if isinstance(exit_def, DirectExit):
|
||||||
|
self._enter_room(exit_def.destination)
|
||||||
|
elif isinstance(exit_def, ConditionalExit):
|
||||||
|
dest = exit_def.function(state)
|
||||||
|
if dest:
|
||||||
|
self._enter_room(dest)
|
||||||
|
# If function returns None, it should have printed a message
|
||||||
|
elif isinstance(exit_def, GatedExit):
|
||||||
|
if exit_def.door.fset_q(Flag.OPENBIT):
|
||||||
|
self._enter_room(exit_def.destination)
|
||||||
|
else:
|
||||||
|
out.tell(f"The {exit_def.door.desc} is closed.\n")
|
||||||
|
elif isinstance(exit_def, BlockedExit):
|
||||||
|
out.tell(exit_def.message + "\n")
|
||||||
|
|
||||||
|
def _enter_room(self, room: Room) -> None:
|
||||||
|
"""Move the player into a new room."""
|
||||||
|
state = self.state
|
||||||
|
state.here = room
|
||||||
|
state.update_lit()
|
||||||
|
|
||||||
|
# Mark as visited
|
||||||
|
if not room.fset_q(Flag.REVISITBIT):
|
||||||
|
room.fset(Flag.REVISITBIT)
|
||||||
|
|
||||||
|
# Room M-ENTER handler
|
||||||
|
if room.action:
|
||||||
|
room.action(state, "M-ENTER")
|
||||||
|
|
||||||
|
self._describe_room()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _describe_room_static(state: GameState) -> None:
|
||||||
|
"""Describe the current room (static version for external callers)."""
|
||||||
|
GameLoop._describe_room_impl(state)
|
||||||
|
|
||||||
|
def _describe_room(self) -> None:
|
||||||
|
"""Describe the current room."""
|
||||||
|
GameLoop._describe_room_impl(self.state)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _describe_room_impl(state: GameState) -> None:
|
||||||
|
"""Describe the current room (implementation)."""
|
||||||
|
out = state.output
|
||||||
|
|
||||||
|
if state.here is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
state.update_lit()
|
||||||
|
|
||||||
|
if not state.lit:
|
||||||
|
out.tell("It is pitch black.\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Room name
|
||||||
|
out.tell(state.here.desc)
|
||||||
|
# Show if player is in a vehicle/bed
|
||||||
|
if (state.protagonist and state.protagonist.parent
|
||||||
|
and state.protagonist.parent != state.here
|
||||||
|
and state.protagonist.parent.fset_q(Flag.VEHBIT)):
|
||||||
|
out.tell(f", in {state.protagonist.parent.the_desc()}")
|
||||||
|
elif state.lying_down:
|
||||||
|
out.tell(", lying down")
|
||||||
|
out.tell("\n")
|
||||||
|
|
||||||
|
# Room description
|
||||||
|
should_describe = (
|
||||||
|
state.verbosity == 2
|
||||||
|
or not state.here.fset_q(Flag.REVISITBIT)
|
||||||
|
or state.prsa == "look"
|
||||||
|
)
|
||||||
|
|
||||||
|
if should_describe:
|
||||||
|
# Room M-LOOK handler
|
||||||
|
if state.here.action:
|
||||||
|
result = state.here.action(state, "M-LOOK")
|
||||||
|
if result:
|
||||||
|
GameLoop._list_room_objects_impl(state)
|
||||||
|
return
|
||||||
|
|
||||||
|
if state.here.ldesc:
|
||||||
|
out.tell(state.here.ldesc + "\n")
|
||||||
|
|
||||||
|
GameLoop._list_room_objects_impl(state)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _list_room_objects_impl(state: GameState) -> None:
|
||||||
|
"""List visible objects in the current room."""
|
||||||
|
out = state.output
|
||||||
|
|
||||||
|
if state.here is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
for obj in state.here.children:
|
||||||
|
if Flag.INVISIBLE in obj.flags or Flag.NDESCBIT in obj.flags:
|
||||||
|
continue
|
||||||
|
if obj is state.protagonist:
|
||||||
|
continue
|
||||||
|
if obj.fdesc and not obj.fset_q(Flag.TOUCHBIT):
|
||||||
|
out.tell(obj.fdesc + "\n")
|
||||||
|
elif obj.ldesc:
|
||||||
|
out.tell(obj.ldesc + "\n")
|
||||||
|
else:
|
||||||
|
out.tell(f"There is {obj.a_desc()} here.\n")
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
"""Text output buffer — clean, TTS-ready output."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from h2g2.engine.game_object import GameObject
|
||||||
|
|
||||||
|
|
||||||
|
class Output:
|
||||||
|
"""Accumulates game text for display and future TTS consumption.
|
||||||
|
|
||||||
|
No ANSI codes, no terminal escape sequences — just plain text.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._buffer: list[str] = []
|
||||||
|
|
||||||
|
def tell(self, *parts: str) -> None:
|
||||||
|
"""Append text fragments to the output buffer."""
|
||||||
|
self._buffer.append("".join(parts))
|
||||||
|
|
||||||
|
def newline(self) -> None:
|
||||||
|
self._buffer.append("\n")
|
||||||
|
|
||||||
|
def blank_line(self) -> None:
|
||||||
|
self._buffer.append("\n\n")
|
||||||
|
|
||||||
|
def describe(self, obj: "GameObject") -> None:
|
||||||
|
"""Output an object's description (equivalent to ZIL 'D')."""
|
||||||
|
self.tell(obj.desc)
|
||||||
|
|
||||||
|
def a_desc(self, obj: "GameObject") -> None:
|
||||||
|
"""Output 'a/an <desc>' or proper noun."""
|
||||||
|
self.tell(obj.a_desc())
|
||||||
|
|
||||||
|
def the_desc(self, obj: "GameObject") -> None:
|
||||||
|
"""Output 'the <desc>' or proper noun."""
|
||||||
|
self.tell(obj.the_desc())
|
||||||
|
|
||||||
|
def number(self, n: int) -> None:
|
||||||
|
"""Output a number."""
|
||||||
|
self.tell(str(n))
|
||||||
|
|
||||||
|
def flush(self) -> str:
|
||||||
|
"""Return accumulated text and clear the buffer."""
|
||||||
|
result = "".join(self._buffer)
|
||||||
|
self._buffer.clear()
|
||||||
|
return result
|
||||||
|
|
||||||
|
def has_content(self) -> bool:
|
||||||
|
return bool(self._buffer)
|
||||||
@@ -0,0 +1,331 @@
|
|||||||
|
"""Input parser — tokenizes commands, matches verbs, resolves objects."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from h2g2.engine.game_object import GameObject, Direction
|
||||||
|
from h2g2.engine.state import GameState
|
||||||
|
|
||||||
|
# Words stripped from input (articles, filler)
|
||||||
|
BUZZ_WORDS = {
|
||||||
|
"a", "an", "the", "is", "are", "am", "and", "of", "then",
|
||||||
|
"all", "but", "except", "please", "here", "some", "more",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Direction word mappings
|
||||||
|
DIRECTION_WORDS: dict[str, str] = {
|
||||||
|
"north": "NORTH", "n": "NORTH", "fore": "NORTH", "f": "NORTH",
|
||||||
|
"south": "SOUTH", "s": "SOUTH", "aft": "SOUTH",
|
||||||
|
"east": "EAST", "e": "EAST", "starboard": "EAST", "sb": "EAST",
|
||||||
|
"west": "WEST", "w": "WEST", "port": "WEST", "p": "WEST",
|
||||||
|
"up": "UP", "u": "UP",
|
||||||
|
"down": "DOWN", "d": "DOWN",
|
||||||
|
"northeast": "NE", "ne": "NE",
|
||||||
|
"northwest": "NW", "nw": "NW",
|
||||||
|
"southeast": "SE", "se": "SE",
|
||||||
|
"southwest": "SW", "sw": "SW",
|
||||||
|
"in": "IN", "inside": "IN", "into": "IN", "enter": "IN",
|
||||||
|
"out": "OUT", "outside": "OUT", "exit": "OUT", "leave": "OUT",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Prepositions that separate object clauses
|
||||||
|
PREPOSITIONS = {
|
||||||
|
"in", "into", "inside", "on", "onto", "with", "using",
|
||||||
|
"at", "to", "toward", "from", "off", "through", "thru",
|
||||||
|
"under", "below", "beneath", "behind", "before", "near",
|
||||||
|
"around", "about", "over", "across", "against",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Verb synonyms
|
||||||
|
VERB_SYNONYMS: dict[str, str] = {
|
||||||
|
"grab": "take", "catch": "take", "get": "take", "hold": "take",
|
||||||
|
"carry": "take", "pick": "take",
|
||||||
|
"release": "drop", "discard": "drop",
|
||||||
|
"go": "walk", "move": "walk", "run": "walk",
|
||||||
|
"l": "look", "describe": "look",
|
||||||
|
"x": "examine", "inspect": "examine", "check": "examine",
|
||||||
|
"i": "inventory", "possessions": "inventory",
|
||||||
|
"q": "quit", "bye": "quit",
|
||||||
|
"g": "again",
|
||||||
|
"hit": "attack", "kill": "attack", "fight": "attack",
|
||||||
|
"yell": "shout", "scream": "shout",
|
||||||
|
"lie": "lie down",
|
||||||
|
"stand": "stand up", "rise": "stand up",
|
||||||
|
"wear": "put on",
|
||||||
|
"remove": "take off",
|
||||||
|
"drink": "drink",
|
||||||
|
"eat": "eat",
|
||||||
|
"read": "read",
|
||||||
|
"open": "open",
|
||||||
|
"close": "close", "shut": "close",
|
||||||
|
"push": "push", "press": "push",
|
||||||
|
"pull": "pull",
|
||||||
|
"turn": "turn",
|
||||||
|
"switch": "turn",
|
||||||
|
"give": "give",
|
||||||
|
"show": "show",
|
||||||
|
"tell": "tell",
|
||||||
|
"ask": "ask",
|
||||||
|
"wait": "wait", "z": "wait",
|
||||||
|
"save": "save",
|
||||||
|
"restore": "restore",
|
||||||
|
"score": "score",
|
||||||
|
"verbose": "verbose",
|
||||||
|
"brief": "brief",
|
||||||
|
"superbrief": "superbrief",
|
||||||
|
"diagnose": "diagnose",
|
||||||
|
"restart": "restart",
|
||||||
|
"swim": "swim",
|
||||||
|
"sleep": "sleep",
|
||||||
|
"wake": "wake",
|
||||||
|
"enjoy": "enjoy",
|
||||||
|
"listen": "listen",
|
||||||
|
"smell": "smell",
|
||||||
|
"taste": "taste",
|
||||||
|
"touch": "touch", "feel": "touch",
|
||||||
|
"pour": "pour",
|
||||||
|
"fill": "fill",
|
||||||
|
"empty": "empty",
|
||||||
|
"answer": "answer",
|
||||||
|
"call": "call",
|
||||||
|
"count": "count",
|
||||||
|
"drown": "drown",
|
||||||
|
"pray": "pray",
|
||||||
|
"brush": "brush",
|
||||||
|
"swallow": "swallow",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ParseResult:
|
||||||
|
verb: str
|
||||||
|
direct_obj: GameObject | None = None
|
||||||
|
indirect_obj: GameObject | None = None
|
||||||
|
direction: str | None = None # For movement commands
|
||||||
|
prep: str | None = None # Preposition between objects
|
||||||
|
raw_input: str = ""
|
||||||
|
is_negated: bool = False
|
||||||
|
# Unresolved noun text (for disambiguation)
|
||||||
|
direct_noun: str | None = None
|
||||||
|
indirect_noun: str | None = None
|
||||||
|
direct_adj: str | None = None
|
||||||
|
indirect_adj: str | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class Parser:
|
||||||
|
"""Parses player input into structured commands."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.last_result: ParseResult | None = None
|
||||||
|
|
||||||
|
def parse(self, raw: str, state: "GameState") -> ParseResult | None:
|
||||||
|
"""Parse a raw input string into a ParseResult, or None if unparseable."""
|
||||||
|
raw = raw.strip()
|
||||||
|
if not raw:
|
||||||
|
return None
|
||||||
|
|
||||||
|
tokens = raw.lower().split()
|
||||||
|
|
||||||
|
# Handle negation
|
||||||
|
is_negated = False
|
||||||
|
if tokens[0] in ("dont", "don't"):
|
||||||
|
is_negated = True
|
||||||
|
tokens = tokens[1:]
|
||||||
|
if not tokens:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Strip buzz words from beginning (but keep them between clauses)
|
||||||
|
while tokens and tokens[0] in BUZZ_WORDS:
|
||||||
|
tokens.pop(0)
|
||||||
|
if not tokens:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Check for bare direction command
|
||||||
|
if len(tokens) == 1 and tokens[0] in DIRECTION_WORDS:
|
||||||
|
return ParseResult(
|
||||||
|
verb="walk",
|
||||||
|
direction=DIRECTION_WORDS[tokens[0]],
|
||||||
|
raw_input=raw,
|
||||||
|
is_negated=is_negated,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check for "go <direction>"
|
||||||
|
if len(tokens) >= 2 and tokens[0] in ("go", "walk", "run", "move"):
|
||||||
|
if tokens[1] in DIRECTION_WORDS:
|
||||||
|
return ParseResult(
|
||||||
|
verb="walk",
|
||||||
|
direction=DIRECTION_WORDS[tokens[1]],
|
||||||
|
raw_input=raw,
|
||||||
|
is_negated=is_negated,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Extract verb word (don't resolve synonyms yet — check compounds first)
|
||||||
|
verb_word = tokens.pop(0)
|
||||||
|
|
||||||
|
# Handle compound verbs using the RAW verb word
|
||||||
|
verb = verb_word # temporary, before synonym resolution
|
||||||
|
if verb_word == "get" and tokens:
|
||||||
|
if tokens[0] == "out":
|
||||||
|
verb = "get out"
|
||||||
|
tokens.pop(0)
|
||||||
|
if tokens and tokens[0] == "of":
|
||||||
|
tokens.pop(0)
|
||||||
|
elif tokens[0] == "in":
|
||||||
|
verb = "get in"
|
||||||
|
tokens.pop(0)
|
||||||
|
elif tokens[0] == "up":
|
||||||
|
verb = "stand up"
|
||||||
|
tokens.pop(0)
|
||||||
|
else:
|
||||||
|
verb = VERB_SYNONYMS.get(verb_word, verb_word)
|
||||||
|
elif verb_word == "turn" and tokens:
|
||||||
|
if tokens[0] == "on":
|
||||||
|
verb = "turn on"
|
||||||
|
tokens.pop(0)
|
||||||
|
elif tokens[0] == "off":
|
||||||
|
verb = "turn off"
|
||||||
|
tokens.pop(0)
|
||||||
|
else:
|
||||||
|
verb = VERB_SYNONYMS.get(verb_word, verb_word)
|
||||||
|
elif verb_word == "pick" and tokens and tokens[0] == "up":
|
||||||
|
verb = "take"
|
||||||
|
tokens.pop(0)
|
||||||
|
elif verb_word == "put" and tokens and tokens[0] == "on":
|
||||||
|
verb = "put on"
|
||||||
|
tokens.pop(0)
|
||||||
|
elif verb_word == "lie" and tokens and tokens[0] == "down":
|
||||||
|
verb = "lie down"
|
||||||
|
tokens.pop(0)
|
||||||
|
elif verb_word == "stand" and tokens and tokens[0] == "up":
|
||||||
|
verb = "stand up"
|
||||||
|
tokens.pop(0)
|
||||||
|
elif verb_word == "look" and tokens:
|
||||||
|
if tokens[0] == "at":
|
||||||
|
verb = "examine"
|
||||||
|
tokens.pop(0)
|
||||||
|
elif tokens[0] in ("in", "inside"):
|
||||||
|
verb = "look in"
|
||||||
|
tokens.pop(0)
|
||||||
|
elif tokens[0] == "under":
|
||||||
|
verb = "look under"
|
||||||
|
tokens.pop(0)
|
||||||
|
else:
|
||||||
|
verb = VERB_SYNONYMS.get(verb_word, verb_word)
|
||||||
|
elif verb_word == "hang" and tokens and tokens[0] == "up":
|
||||||
|
verb = "hang up"
|
||||||
|
tokens.pop(0)
|
||||||
|
else:
|
||||||
|
verb = VERB_SYNONYMS.get(verb_word, verb_word)
|
||||||
|
|
||||||
|
# Handle post-synonym compounds
|
||||||
|
if verb == "take" and tokens and tokens[0] == "off":
|
||||||
|
verb = "take off"
|
||||||
|
tokens.pop(0)
|
||||||
|
|
||||||
|
# Handle AGAIN
|
||||||
|
if verb == "again" and self.last_result:
|
||||||
|
return self.last_result
|
||||||
|
|
||||||
|
# Handle IT/THEM pronoun
|
||||||
|
for i, t in enumerate(tokens):
|
||||||
|
if t in ("it", "them", "him", "her") and state.p_it_object:
|
||||||
|
# Will resolve during object resolution
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Strip remaining buzz words
|
||||||
|
tokens = [t for t in tokens if t not in BUZZ_WORDS]
|
||||||
|
|
||||||
|
# No object needed for some verbs
|
||||||
|
if not tokens:
|
||||||
|
result = ParseResult(
|
||||||
|
verb=verb, raw_input=raw, is_negated=is_negated,
|
||||||
|
)
|
||||||
|
self.last_result = result
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Split on preposition to get direct/indirect object phrases
|
||||||
|
prep = None
|
||||||
|
direct_tokens: list[str] = []
|
||||||
|
indirect_tokens: list[str] = []
|
||||||
|
in_indirect = False
|
||||||
|
|
||||||
|
for token in tokens:
|
||||||
|
if token in PREPOSITIONS and not in_indirect and direct_tokens:
|
||||||
|
prep = token
|
||||||
|
in_indirect = True
|
||||||
|
elif in_indirect:
|
||||||
|
indirect_tokens.append(token)
|
||||||
|
else:
|
||||||
|
direct_tokens.append(token)
|
||||||
|
|
||||||
|
# Handle "in front of" as a special case
|
||||||
|
if prep == "in" and indirect_tokens and indirect_tokens[0] == "front":
|
||||||
|
indirect_tokens.pop(0)
|
||||||
|
if indirect_tokens and indirect_tokens[0] == "of":
|
||||||
|
indirect_tokens.pop(0)
|
||||||
|
prep = "in front of"
|
||||||
|
|
||||||
|
# Resolve nouns
|
||||||
|
d_adj, d_noun = self._extract_noun(direct_tokens)
|
||||||
|
i_adj, i_noun = self._extract_noun(indirect_tokens)
|
||||||
|
|
||||||
|
# Try to resolve objects
|
||||||
|
d_obj = self._resolve(d_noun, d_adj, state) if d_noun else None
|
||||||
|
i_obj = self._resolve(i_noun, i_adj, state) if i_noun else None
|
||||||
|
|
||||||
|
result = ParseResult(
|
||||||
|
verb=verb,
|
||||||
|
direct_obj=d_obj,
|
||||||
|
indirect_obj=i_obj,
|
||||||
|
prep=prep,
|
||||||
|
raw_input=raw,
|
||||||
|
is_negated=is_negated,
|
||||||
|
direct_noun=d_noun,
|
||||||
|
indirect_noun=i_noun,
|
||||||
|
direct_adj=d_adj,
|
||||||
|
indirect_adj=i_adj,
|
||||||
|
)
|
||||||
|
self.last_result = result
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _extract_noun(self, tokens: list[str]) -> tuple[str | None, str | None]:
|
||||||
|
"""Extract adjective and noun from a token list.
|
||||||
|
|
||||||
|
Returns (adjective, noun). The last word is the noun,
|
||||||
|
preceding words are adjectives.
|
||||||
|
"""
|
||||||
|
if not tokens:
|
||||||
|
return None, None
|
||||||
|
if len(tokens) == 1:
|
||||||
|
return None, tokens[0]
|
||||||
|
# Last token is noun, rest are adjectives
|
||||||
|
return tokens[0], tokens[-1]
|
||||||
|
|
||||||
|
def _resolve(
|
||||||
|
self, noun: str | None, adj: str | None, state: "GameState"
|
||||||
|
) -> "GameObject | None":
|
||||||
|
"""Resolve a noun+adjective to a game object."""
|
||||||
|
if noun is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Handle pronouns
|
||||||
|
if noun in ("it", "them", "him", "her"):
|
||||||
|
return state.p_it_object
|
||||||
|
|
||||||
|
if state.here is None or state.protagonist is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
matches = state.world.find_by_name(
|
||||||
|
noun, adj, state.here, state.protagonist,
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(matches) == 1:
|
||||||
|
return matches[0]
|
||||||
|
elif len(matches) > 1:
|
||||||
|
# Disambiguation — for now, return the first match
|
||||||
|
# TODO: Ask "Which one?" for true disambiguation
|
||||||
|
return matches[0]
|
||||||
|
return None
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
"""Game state — all mutable globals, score, turn counter, puzzle flags."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from h2g2.engine.game_object import GameObject, Room
|
||||||
|
from h2g2.engine.world import World
|
||||||
|
from h2g2.engine.output import Output
|
||||||
|
from h2g2.engine.clock import Clock
|
||||||
|
|
||||||
|
|
||||||
|
class GameState:
|
||||||
|
"""Central mutable state for the game."""
|
||||||
|
|
||||||
|
def __init__(self, world: "World", output: "Output", clock: "Clock") -> None:
|
||||||
|
self.world = world
|
||||||
|
self.output = output
|
||||||
|
self.clock = clock
|
||||||
|
|
||||||
|
# Core
|
||||||
|
self.here: Room | None = None
|
||||||
|
self.protagonist: GameObject | None = None
|
||||||
|
self.winner: GameObject | None = None # current actor
|
||||||
|
self.score: int = 0
|
||||||
|
self.moves: int = 0
|
||||||
|
self.lit: bool = False
|
||||||
|
self.running: bool = True
|
||||||
|
|
||||||
|
# Identity system (multi-character)
|
||||||
|
self.identity_flag: GameObject | None = None # ARTHUR, FORD, etc.
|
||||||
|
|
||||||
|
# Parser state
|
||||||
|
self.prsa: str | None = None # current verb
|
||||||
|
self.prso: GameObject | None = None # direct object
|
||||||
|
self.prsi: GameObject | None = None # indirect object
|
||||||
|
self.p_it_object: GameObject | None = None # last referenced object
|
||||||
|
self.dont_flag: bool = False
|
||||||
|
self.in_front_flag: bool = False
|
||||||
|
|
||||||
|
# Last action (for AGAIN)
|
||||||
|
self.l_prsa: str | None = None
|
||||||
|
self.l_prso: GameObject | None = None
|
||||||
|
self.l_prsi: GameObject | None = None
|
||||||
|
|
||||||
|
# Condition flags
|
||||||
|
self.lying_down: bool = False
|
||||||
|
self.headache: bool = True
|
||||||
|
self.groggy: bool = False
|
||||||
|
self.groggy_counter: int = 0
|
||||||
|
self.verbosity: int = 1 # 0=superbrief, 1=brief, 2=verbose
|
||||||
|
|
||||||
|
# Earth progression
|
||||||
|
self.house_demolished: bool = False
|
||||||
|
self.earth_demolished: bool = False
|
||||||
|
self.in_front_of_bulldozer: bool = False
|
||||||
|
self.ford_arrived: bool = False
|
||||||
|
self.ford_has_satchel: bool = True
|
||||||
|
self.prosser_in_mud: bool = False
|
||||||
|
self.beer_counter: int = 0
|
||||||
|
|
||||||
|
# Vogon
|
||||||
|
self.babel_fish_in_ear: bool = False
|
||||||
|
self.poem_enjoyed: bool = False
|
||||||
|
|
||||||
|
# Heart of Gold
|
||||||
|
self.holding_no_tea: bool = True
|
||||||
|
self.dreaming: bool = False
|
||||||
|
|
||||||
|
# Probability system (dream dispatch weights)
|
||||||
|
self.vogon_prob: int = 100
|
||||||
|
self.heart_prob: int = 0
|
||||||
|
self.traal_prob: int = 60
|
||||||
|
self.fleet_prob: int = 0
|
||||||
|
self.whale_prob: int = 0
|
||||||
|
|
||||||
|
# Deaths
|
||||||
|
self.dead_counter: int = 0
|
||||||
|
|
||||||
|
def update_lit(self) -> None:
|
||||||
|
"""Recalculate whether the current location is lit."""
|
||||||
|
if self.here is None:
|
||||||
|
self.lit = False
|
||||||
|
return
|
||||||
|
from h2g2.engine.game_object import Flag
|
||||||
|
# Room has ONBIT = lit
|
||||||
|
if self.here.fset_q(Flag.ONBIT):
|
||||||
|
self.lit = True
|
||||||
|
return
|
||||||
|
# Check if player carries a light source
|
||||||
|
if self.protagonist:
|
||||||
|
for obj in self.protagonist.children:
|
||||||
|
if obj.fset_q(Flag.LIGHTBIT) and obj.fset_q(Flag.ONBIT):
|
||||||
|
self.lit = True
|
||||||
|
return
|
||||||
|
self.lit = False
|
||||||
@@ -0,0 +1,473 @@
|
|||||||
|
"""Default verb handler implementations."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from h2g2.engine.game_object import GameObject, Flag
|
||||||
|
from h2g2.engine.state import GameState
|
||||||
|
from h2g2.engine.loop import verb_handler
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("look")
|
||||||
|
def v_look(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
from h2g2.engine.loop import GameLoop
|
||||||
|
old_prsa = state.prsa
|
||||||
|
state.prsa = "look"
|
||||||
|
GameLoop._describe_room_impl(state)
|
||||||
|
state.prsa = old_prsa
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("examine")
|
||||||
|
def v_examine(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if prso is None:
|
||||||
|
out.tell("What do you want to examine?\n")
|
||||||
|
return True
|
||||||
|
if prso.text:
|
||||||
|
out.tell(prso.text + "\n")
|
||||||
|
elif prso.ldesc:
|
||||||
|
out.tell(prso.ldesc + "\n")
|
||||||
|
else:
|
||||||
|
out.tell(f"There's nothing special about {prso.the_desc()}.\n")
|
||||||
|
# Show container contents
|
||||||
|
if prso.fset_q(Flag.CONTBIT) or prso.fset_q(Flag.SURFACEBIT):
|
||||||
|
if prso.fset_q(Flag.OPENBIT) or prso.fset_q(Flag.TRANSBIT):
|
||||||
|
visible = prso.contents_string()
|
||||||
|
if visible:
|
||||||
|
out.tell(f"{prso.the_desc().capitalize()} contains:\n")
|
||||||
|
for child in visible:
|
||||||
|
out.tell(f" {child.a_desc()}\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("take")
|
||||||
|
def v_take(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if prso is None:
|
||||||
|
out.tell("What do you want to take?\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
if not prso.fset_q(Flag.TAKEBIT):
|
||||||
|
out.tell(f"You can't take {prso.the_desc()}.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
if prso.parent is state.protagonist:
|
||||||
|
out.tell("You already have that.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
prso.fset(Flag.TOUCHBIT)
|
||||||
|
prso.move_to(state.protagonist)
|
||||||
|
out.tell("Taken.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("drop")
|
||||||
|
def v_drop(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if prso is None:
|
||||||
|
out.tell("What do you want to drop?\n")
|
||||||
|
return True
|
||||||
|
if not prso.is_held_by(state.protagonist):
|
||||||
|
out.tell("You aren't carrying that.\n")
|
||||||
|
return True
|
||||||
|
prso.move_to(state.here)
|
||||||
|
out.tell("Dropped.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("inventory")
|
||||||
|
def v_inventory(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if not state.protagonist or not state.protagonist.children:
|
||||||
|
out.tell("You are empty-handed.\n")
|
||||||
|
return True
|
||||||
|
out.tell("You have:\n")
|
||||||
|
if state.headache:
|
||||||
|
out.tell(" a splitting headache\n")
|
||||||
|
if state.holding_no_tea:
|
||||||
|
out.tell(" no tea\n")
|
||||||
|
for obj in state.protagonist.children:
|
||||||
|
desc = obj.a_desc()
|
||||||
|
if obj.fset_q(Flag.WORNBIT):
|
||||||
|
desc += " (being worn)"
|
||||||
|
out.tell(f" {desc}\n")
|
||||||
|
# Show contents of containers
|
||||||
|
if (obj.fset_q(Flag.CONTBIT) or obj.fset_q(Flag.SURFACEBIT)):
|
||||||
|
visible = obj.contents_string()
|
||||||
|
if visible and (obj.fset_q(Flag.OPENBIT) or obj.fset_q(Flag.TRANSBIT)):
|
||||||
|
out.tell(f" It looks like {obj.the_desc()} contains:\n")
|
||||||
|
for child in visible:
|
||||||
|
out.tell(f" {child.a_desc()}\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("put on")
|
||||||
|
def v_wear(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if prso is None:
|
||||||
|
out.tell("What do you want to wear?\n")
|
||||||
|
return True
|
||||||
|
if not prso.fset_q(Flag.WEARBIT):
|
||||||
|
out.tell(f"You can't wear {prso.the_desc()}.\n")
|
||||||
|
return True
|
||||||
|
if not prso.is_held_by(state.protagonist):
|
||||||
|
out.tell("You aren't carrying that.\n")
|
||||||
|
return True
|
||||||
|
prso.fset(Flag.WORNBIT)
|
||||||
|
prso.move_to(state.protagonist)
|
||||||
|
out.tell(f"You are now wearing {prso.the_desc()}.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("take off")
|
||||||
|
def v_take_off(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if prso is None:
|
||||||
|
out.tell("What do you want to take off?\n")
|
||||||
|
return True
|
||||||
|
if not prso.fset_q(Flag.WORNBIT):
|
||||||
|
out.tell("You aren't wearing that.\n")
|
||||||
|
return True
|
||||||
|
prso.fclear(Flag.WORNBIT)
|
||||||
|
out.tell(f"You take off {prso.the_desc()}.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("open")
|
||||||
|
def v_open(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if prso is None:
|
||||||
|
out.tell("What do you want to open?\n")
|
||||||
|
return True
|
||||||
|
if prso.fset_q(Flag.OPENBIT):
|
||||||
|
out.tell("It's already open.\n")
|
||||||
|
return True
|
||||||
|
if not prso.fset_q(Flag.CONTBIT) and not prso.fset_q(Flag.DOORBIT):
|
||||||
|
out.tell(f"You can't open {prso.the_desc()}.\n")
|
||||||
|
return True
|
||||||
|
prso.fset(Flag.OPENBIT)
|
||||||
|
out.tell("Opened.\n")
|
||||||
|
visible = prso.contents_string()
|
||||||
|
if visible:
|
||||||
|
for child in visible:
|
||||||
|
out.tell(f" {child.a_desc()}\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("close")
|
||||||
|
def v_close(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if prso is None:
|
||||||
|
out.tell("What do you want to close?\n")
|
||||||
|
return True
|
||||||
|
if not prso.fset_q(Flag.OPENBIT):
|
||||||
|
out.tell("It's already closed.\n")
|
||||||
|
return True
|
||||||
|
prso.fclear(Flag.OPENBIT)
|
||||||
|
out.tell("Closed.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("put")
|
||||||
|
def v_put(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if prso is None or prsi is None:
|
||||||
|
out.tell("What do you want to put where?\n")
|
||||||
|
return True
|
||||||
|
if not prso.is_held_by(state.protagonist):
|
||||||
|
out.tell("You aren't carrying that.\n")
|
||||||
|
return True
|
||||||
|
if not prsi.fset_q(Flag.CONTBIT) and not prsi.fset_q(Flag.SURFACEBIT):
|
||||||
|
out.tell(f"You can't put things in {prsi.the_desc()}.\n")
|
||||||
|
return True
|
||||||
|
if not prsi.fset_q(Flag.OPENBIT) and prsi.fset_q(Flag.CONTBIT):
|
||||||
|
out.tell(f"{prsi.the_desc().capitalize()} isn't open.\n")
|
||||||
|
return True
|
||||||
|
prso.move_to(prsi)
|
||||||
|
out.tell("Done.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("look in")
|
||||||
|
def v_look_in(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if prso is None:
|
||||||
|
out.tell("What do you want to look in?\n")
|
||||||
|
return True
|
||||||
|
if not prso.fset_q(Flag.CONTBIT) and not prso.fset_q(Flag.SURFACEBIT):
|
||||||
|
out.tell(f"You can't look inside {prso.the_desc()}.\n")
|
||||||
|
return True
|
||||||
|
if not prso.fset_q(Flag.OPENBIT) and not prso.fset_q(Flag.TRANSBIT):
|
||||||
|
out.tell(f"{prso.the_desc().capitalize()} is closed.\n")
|
||||||
|
return True
|
||||||
|
visible = prso.contents_string()
|
||||||
|
if visible:
|
||||||
|
for child in visible:
|
||||||
|
out.tell(f" {child.a_desc()}\n")
|
||||||
|
else:
|
||||||
|
out.tell(f"{prso.the_desc().capitalize()} is empty.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("look under")
|
||||||
|
def v_look_under(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell(f"There's nothing under {prso.the_desc() if prso else 'that'}.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("read")
|
||||||
|
def v_read(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if prso is None:
|
||||||
|
out.tell("What do you want to read?\n")
|
||||||
|
return True
|
||||||
|
if prso.text:
|
||||||
|
out.tell(prso.text + "\n")
|
||||||
|
else:
|
||||||
|
out.tell(f"There's nothing written on {prso.the_desc()}.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("wait")
|
||||||
|
def v_wait(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("Time passes.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("turn on")
|
||||||
|
def v_turn_on(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if prso is None:
|
||||||
|
# Default: turn on light in the room
|
||||||
|
out.tell("What do you want to turn on?\n")
|
||||||
|
return True
|
||||||
|
prso.fset(Flag.ONBIT)
|
||||||
|
out.tell(f"You turn on {prso.the_desc()}.\n")
|
||||||
|
state.update_lit()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("turn off")
|
||||||
|
def v_turn_off(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if prso is None:
|
||||||
|
out.tell("What do you want to turn off?\n")
|
||||||
|
return True
|
||||||
|
prso.fclear(Flag.ONBIT)
|
||||||
|
out.tell(f"You turn off {prso.the_desc()}.\n")
|
||||||
|
state.update_lit()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("get out")
|
||||||
|
def v_get_out(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
# Getting out of bed, vehicle, etc.
|
||||||
|
# If prso is specified, delegate to its action handler
|
||||||
|
if prso and prso.action:
|
||||||
|
# Temporarily set the verb for the handler
|
||||||
|
old_prsa = state.prsa
|
||||||
|
state.prsa = "get out"
|
||||||
|
result = prso.action(state)
|
||||||
|
state.prsa = old_prsa
|
||||||
|
if result:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Check if protagonist is inside something (bed, vehicle)
|
||||||
|
if state.protagonist and state.protagonist.parent and state.protagonist.parent != state.here:
|
||||||
|
container = state.protagonist.parent
|
||||||
|
if container.action:
|
||||||
|
old_prsa = state.prsa
|
||||||
|
state.prsa = "get out"
|
||||||
|
result = container.action(state)
|
||||||
|
state.prsa = old_prsa
|
||||||
|
if result:
|
||||||
|
return True
|
||||||
|
# Default: move out of container
|
||||||
|
state.protagonist.move_to(state.here)
|
||||||
|
state.lying_down = False
|
||||||
|
state.output.tell("You get out.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
state.output.tell("You're not in anything.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("get in")
|
||||||
|
def v_get_in(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("You get in.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("lie down")
|
||||||
|
def v_lie_down(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.lying_down = True
|
||||||
|
state.output.tell("You lie down.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("stand up")
|
||||||
|
def v_stand_up(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
if not state.lying_down:
|
||||||
|
state.output.tell("You're already standing.\n")
|
||||||
|
return True
|
||||||
|
state.lying_down = False
|
||||||
|
state.output.tell("You stand up.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("score")
|
||||||
|
def v_score(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
out.tell(f"Your score is {state.score} of a possible 400")
|
||||||
|
out.tell(f", in {state.moves} turn{'s' if state.moves != 1 else ''}.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("diagnose")
|
||||||
|
def v_diagnose(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
out = state.output
|
||||||
|
if state.headache:
|
||||||
|
out.tell("You have a big blinding throbber.\n")
|
||||||
|
elif state.groggy:
|
||||||
|
out.tell("You feel weak.\n")
|
||||||
|
else:
|
||||||
|
out.tell("You are in good health.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("verbose")
|
||||||
|
def v_verbose(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.verbosity = 2
|
||||||
|
state.output.tell("Maximum verbosity.\n")
|
||||||
|
# Re-describe room
|
||||||
|
state.prsa = "look"
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("brief")
|
||||||
|
def v_brief(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.verbosity = 1
|
||||||
|
state.output.tell("Brief descriptions.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("superbrief")
|
||||||
|
def v_superbrief(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.verbosity = 0
|
||||||
|
state.output.tell("Super-brief descriptions.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("quit")
|
||||||
|
def v_quit(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("Thanks for playing!\n")
|
||||||
|
state.running = False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("eat")
|
||||||
|
def v_eat(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("That's not edible.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("drink")
|
||||||
|
def v_drink(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("You can't drink that.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("sleep")
|
||||||
|
def v_sleep(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("You don't feel sleepy.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("wake")
|
||||||
|
def v_wake(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("You are already awake.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("listen")
|
||||||
|
def v_listen(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("You hear nothing special.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("smell")
|
||||||
|
def v_smell(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("You smell nothing special.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("taste")
|
||||||
|
def v_taste(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("That doesn't taste like anything.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("touch")
|
||||||
|
def v_touch(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
if prso:
|
||||||
|
state.output.tell(f"You feel nothing unexpected about {prso.the_desc()}.\n")
|
||||||
|
else:
|
||||||
|
state.output.tell("You feel around in the dark.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("shout")
|
||||||
|
def v_shout(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("Shouting gets you nowhere.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("swim")
|
||||||
|
def v_swim(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("There's no water here.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("pray")
|
||||||
|
def v_pray(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("Nothing happens.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("attack")
|
||||||
|
def v_attack(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
if prso:
|
||||||
|
state.output.tell(f"Violence isn't the answer to this one.\n")
|
||||||
|
else:
|
||||||
|
state.output.tell("What do you want to attack?\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("give")
|
||||||
|
def v_give(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("No one is interested.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("show")
|
||||||
|
def v_show(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("No one is interested.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("hang up")
|
||||||
|
def v_hang_up(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("You can't hang that up.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("answer")
|
||||||
|
def v_answer(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("Nobody asked you a question.\n")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@verb_handler("call")
|
||||||
|
def v_call(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
|
||||||
|
state.output.tell("There's no one to call.\n")
|
||||||
|
return True
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
"""World — object registry and containment tree management."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from h2g2.engine.game_object import GameObject, Room, Flag
|
||||||
|
|
||||||
|
|
||||||
|
class World:
|
||||||
|
"""Registry of all game objects and rooms."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.objects: dict[str, GameObject] = {}
|
||||||
|
self.rooms: dict[str, Room] = {}
|
||||||
|
|
||||||
|
# Root containers (created during content registration)
|
||||||
|
self.global_objects: GameObject | None = None
|
||||||
|
self.local_globals: GameObject | None = None
|
||||||
|
self.protagonist: GameObject | None = None
|
||||||
|
|
||||||
|
def register(self, obj: GameObject) -> GameObject:
|
||||||
|
"""Add an object to the registry."""
|
||||||
|
self.objects[obj.id] = obj
|
||||||
|
if isinstance(obj, Room):
|
||||||
|
self.rooms[obj.id] = obj
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def get(self, id: str) -> GameObject:
|
||||||
|
return self.objects[id]
|
||||||
|
|
||||||
|
def get_room(self, id: str) -> Room:
|
||||||
|
room = self.rooms.get(id)
|
||||||
|
if room is None:
|
||||||
|
raise KeyError(f"Room {id!r} not found")
|
||||||
|
return room
|
||||||
|
|
||||||
|
def visible_objects(self, here: Room, protagonist: GameObject) -> list[GameObject]:
|
||||||
|
"""Return all objects the player can currently see/interact with.
|
||||||
|
|
||||||
|
Search order matches ZIL: room contents, inventory, containers
|
||||||
|
with SEARCHBIT, local globals for the room, global objects.
|
||||||
|
"""
|
||||||
|
result: list[GameObject] = []
|
||||||
|
seen: set[int] = set()
|
||||||
|
|
||||||
|
def add(obj: GameObject) -> None:
|
||||||
|
if id(obj) not in seen:
|
||||||
|
seen.add(id(obj))
|
||||||
|
result.append(obj)
|
||||||
|
|
||||||
|
# 1. Room contents
|
||||||
|
for obj in here.children:
|
||||||
|
if Flag.INVISIBLE not in obj.flags:
|
||||||
|
add(obj)
|
||||||
|
# Search inside open/searchable containers
|
||||||
|
if obj.fset_q(Flag.SEARCHBIT) or obj.fset_q(Flag.OPENBIT):
|
||||||
|
for child in obj.children:
|
||||||
|
add(child)
|
||||||
|
|
||||||
|
# 2. Inventory
|
||||||
|
for obj in protagonist.children:
|
||||||
|
add(obj)
|
||||||
|
if obj.fset_q(Flag.SEARCHBIT) or obj.fset_q(Flag.OPENBIT):
|
||||||
|
for child in obj.children:
|
||||||
|
add(child)
|
||||||
|
|
||||||
|
# 3. Local globals for this room
|
||||||
|
for obj in here.global_objects:
|
||||||
|
add(obj)
|
||||||
|
|
||||||
|
# 4. Global objects
|
||||||
|
if self.global_objects:
|
||||||
|
for obj in self.global_objects.children:
|
||||||
|
if Flag.INVISIBLE not in obj.flags:
|
||||||
|
add(obj)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def find_by_name(
|
||||||
|
self, name: str, adjective: str | None,
|
||||||
|
here: Room, protagonist: GameObject,
|
||||||
|
) -> list[GameObject]:
|
||||||
|
"""Find objects matching a noun (and optional adjective)."""
|
||||||
|
name = name.lower()
|
||||||
|
adj = adjective.lower() if adjective else None
|
||||||
|
candidates = self.visible_objects(here, protagonist)
|
||||||
|
matches = []
|
||||||
|
|
||||||
|
for obj in candidates:
|
||||||
|
if name in obj.synonyms or name == obj.id.lower():
|
||||||
|
if adj is None or adj in obj.adjectives:
|
||||||
|
matches.append(obj)
|
||||||
|
|
||||||
|
# Also check room pseudo-objects
|
||||||
|
for word, handler in here.pseudo:
|
||||||
|
if name == word.lower():
|
||||||
|
# Create a temporary pseudo-object
|
||||||
|
pseudo = GameObject(
|
||||||
|
f"pseudo_{word}", desc=word, action=handler,
|
||||||
|
)
|
||||||
|
matches.append(pseudo)
|
||||||
|
|
||||||
|
return matches
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""The Hitchhiker's Guide to the Galaxy — Python text adventure engine."""
|
||||||
|
|
||||||
|
from h2g2.engine.game_object import Flag
|
||||||
|
from h2g2.engine.world import World
|
||||||
|
from h2g2.engine.state import GameState
|
||||||
|
from h2g2.engine.output import Output
|
||||||
|
from h2g2.engine.clock import Clock
|
||||||
|
from h2g2.engine.parser import Parser
|
||||||
|
from h2g2.engine.loop import GameLoop
|
||||||
|
|
||||||
|
# Import verb handlers (registers them via decorators)
|
||||||
|
import h2g2.engine.verbs # noqa: F401
|
||||||
|
|
||||||
|
# Import content modules
|
||||||
|
from h2g2.content import globals_content, earth
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
# Build the world
|
||||||
|
world = World()
|
||||||
|
globals_content.register(world)
|
||||||
|
earth.register(world)
|
||||||
|
|
||||||
|
# Initialize engine
|
||||||
|
output = Output()
|
||||||
|
clock = Clock()
|
||||||
|
state = GameState(world, output, clock)
|
||||||
|
|
||||||
|
# Set starting conditions
|
||||||
|
state.protagonist = world.protagonist
|
||||||
|
state.here = world.get_room("BEDROOM")
|
||||||
|
state.winner = world.protagonist
|
||||||
|
state.lying_down = True # start in bed
|
||||||
|
|
||||||
|
# Banner
|
||||||
|
output.tell(
|
||||||
|
"\n *** THE HITCHHIKER'S GUIDE TO THE GALAXY: "
|
||||||
|
"Interactive Science Fiction ***\n\n"
|
||||||
|
"Copyright (c) 1984 by Infocom, Inc. All Rights Reserved.\n"
|
||||||
|
"Python engine by Claude.\n\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Opening text
|
||||||
|
output.tell(
|
||||||
|
"You wake up. The room is spinning very gently round your head. "
|
||||||
|
"Or at least it would be if you could see it which you can't.\n\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(output.flush(), end="")
|
||||||
|
|
||||||
|
# Run the game loop
|
||||||
|
parser = Parser()
|
||||||
|
loop = GameLoop(state, parser)
|
||||||
|
loop.run()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
def main():
|
||||||
|
print("Hello from h2g2!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,611 @@
|
|||||||
|
"MISC for
|
||||||
|
THE HITCHHIKER'S GUIDE TO THE GALAXY
|
||||||
|
(c) 1984 by Infocom, Inc. All Rights Reserved."
|
||||||
|
|
||||||
|
;"former MACROS.ZIL stuff"
|
||||||
|
|
||||||
|
<SETG C-ENABLED? 0>
|
||||||
|
|
||||||
|
<SETG C-ENABLED 1>
|
||||||
|
|
||||||
|
<SETG C-DISABLED 0>
|
||||||
|
|
||||||
|
;<ROUTINE ENABLED? (RTN "AUX" C E)
|
||||||
|
<SET E <REST ,C-TABLE ,C-TABLELEN>>
|
||||||
|
<SET C <REST ,C-TABLE ,C-INTS>>
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<==? .C .E> <RFALSE>)
|
||||||
|
(<EQUAL? <GET .C ,C-RTN> .RTN>
|
||||||
|
<COND (<0? <GET .C ,C-ENABLED?>>
|
||||||
|
<RFALSE>)
|
||||||
|
(T
|
||||||
|
<RTRUE>)>)>
|
||||||
|
<SET C <REST .C ,C-INTLEN>>>>
|
||||||
|
|
||||||
|
;<ROUTINE QUEUED? (RTN "AUX" C E)
|
||||||
|
<SET E <REST ,C-TABLE ,C-TABLELEN>>
|
||||||
|
<SET C <REST ,C-TABLE ,C-INTS>>
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<==? .C .E> <RFALSE>)
|
||||||
|
(<EQUAL? <GET .C ,C-RTN> .RTN>
|
||||||
|
<COND (<OR <0? <GET .C ,C-ENABLED?>>
|
||||||
|
<0? <GET .C ,C-TICK>>>
|
||||||
|
<RFALSE>)
|
||||||
|
(T <RTRUE>)>)>
|
||||||
|
<SET C <REST .C ,C-INTLEN>>>>
|
||||||
|
|
||||||
|
<ROUTINE RUNNING? (RTN "AUX" C E TICK)
|
||||||
|
<SET E <REST ,C-TABLE ,C-TABLELEN>>
|
||||||
|
<SET C <REST ,C-TABLE ,C-INTS>>
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<==? .C .E> <RFALSE>)
|
||||||
|
(<EQUAL? <GET .C ,C-RTN> .RTN>
|
||||||
|
<COND (<OR <0? <GET .C ,C-ENABLED?>>
|
||||||
|
<0? <SET TICK <GET .C ,C-TICK>>>
|
||||||
|
<G? .TICK 1>>
|
||||||
|
<RFALSE>)
|
||||||
|
(T <RTRUE>)>)>
|
||||||
|
<SET C <REST .C ,C-INTLEN>>>>
|
||||||
|
|
||||||
|
<DEFMAC TELL ("ARGS" A)
|
||||||
|
<FORM PROG ()
|
||||||
|
!<MAPF ,LIST
|
||||||
|
<FUNCTION ("AUX" E P O)
|
||||||
|
<COND (<EMPTY? .A> <MAPSTOP>)
|
||||||
|
(<SET E <NTH .A 1>>
|
||||||
|
<SET A <REST .A>>)>
|
||||||
|
<COND (<TYPE? .E ATOM>
|
||||||
|
<COND (<OR <=? <SET P <SPNAME .E>>
|
||||||
|
"CRLF">
|
||||||
|
<=? .P "CR">>
|
||||||
|
<MAPRET '<CRLF>>)
|
||||||
|
(<EMPTY? .A>
|
||||||
|
<ERROR INDICATOR-AT-END? .E>)
|
||||||
|
(ELSE
|
||||||
|
<SET O <NTH .A 1>>
|
||||||
|
<SET A <REST .A>>
|
||||||
|
<COND (<OR <=? <SET P <SPNAME .E>>
|
||||||
|
"DESC">
|
||||||
|
<=? .P "D">
|
||||||
|
<=? .P "OBJ">
|
||||||
|
<=? .P "O">>
|
||||||
|
<MAPRET <FORM PRINTD .O>>)
|
||||||
|
(<OR <=? .P "NUM">
|
||||||
|
<=? .P "N">>
|
||||||
|
<MAPRET <FORM PRINTN .O>>)
|
||||||
|
(<OR <=? .P "CHAR">
|
||||||
|
<=? .P "CHR">
|
||||||
|
<=? .P "C">>
|
||||||
|
<MAPRET <FORM PRINTC .O>>)
|
||||||
|
(ELSE
|
||||||
|
<MAPRET
|
||||||
|
<FORM PRINT
|
||||||
|
<FORM GETP .O .E>>>)>)>)
|
||||||
|
(<TYPE? .E STRING ZSTRING>
|
||||||
|
<MAPRET <FORM PRINTI .E>>)
|
||||||
|
(<TYPE? .E FORM LVAL GVAL>
|
||||||
|
<MAPRET <FORM PRINT .E>>)
|
||||||
|
(ELSE <ERROR UNKNOWN-TYPE .E>)>>>>>
|
||||||
|
|
||||||
|
<DEFMAC VERB? ("ARGS" ATMS)
|
||||||
|
<MULTIFROB PRSA .ATMS>>
|
||||||
|
|
||||||
|
<DEFMAC PRSO? ("ARGS" ATMS)
|
||||||
|
<MULTIFROB PRSO .ATMS>>
|
||||||
|
|
||||||
|
<DEFMAC PRSI? ("ARGS" ATMS)
|
||||||
|
<MULTIFROB PRSI .ATMS>>
|
||||||
|
|
||||||
|
<DEFMAC ROOM? ("ARGS" ATMS)
|
||||||
|
<MULTIFROB HERE .ATMS>>
|
||||||
|
|
||||||
|
<DEFINE MULTIFROB (X ATMS "AUX" (OO (OR)) (O .OO) (L ()) ATM)
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<EMPTY? .ATMS>
|
||||||
|
<RETURN!- <COND (<LENGTH? .OO 1> <ERROR .X>)
|
||||||
|
(<LENGTH? .OO 2> <NTH .OO 2>)
|
||||||
|
(ELSE <CHTYPE .OO FORM>)>>)>
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<EMPTY? .ATMS> <RETURN!->)>
|
||||||
|
<SET ATM <NTH .ATMS 1>>
|
||||||
|
<SET L
|
||||||
|
(<COND (<TYPE? .ATM ATOM>
|
||||||
|
<FORM GVAL
|
||||||
|
<COND (<==? .X PRSA>
|
||||||
|
<PARSE
|
||||||
|
<STRING "V?"
|
||||||
|
<SPNAME .ATM>>>)
|
||||||
|
(ELSE .ATM)>>)
|
||||||
|
(ELSE .ATM)>
|
||||||
|
!.L)>
|
||||||
|
<SET ATMS <REST .ATMS>>
|
||||||
|
<COND (<==? <LENGTH .L> 3> <RETURN!->)>>
|
||||||
|
<SET O <REST <PUTREST .O (<FORM EQUAL? <FORM GVAL .X> !.L>)>>>
|
||||||
|
<SET L ()>>>
|
||||||
|
|
||||||
|
<DEFMAC BSET ('OBJ "ARGS" BITS)
|
||||||
|
<MULTIBITS FSET .OBJ .BITS>>
|
||||||
|
|
||||||
|
<DEFMAC BCLEAR ('OBJ "ARGS" BITS)
|
||||||
|
<MULTIBITS FCLEAR .OBJ .BITS>>
|
||||||
|
|
||||||
|
<DEFMAC BSET? ('OBJ "ARGS" BITS)
|
||||||
|
<MULTIBITS FSET? .OBJ .BITS>>
|
||||||
|
|
||||||
|
<DEFINE MULTIBITS (X OBJ ATMS "AUX" (O ()) ATM)
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<EMPTY? .ATMS>
|
||||||
|
<RETURN!- <COND (<LENGTH? .O 1> <NTH .O 1>)
|
||||||
|
(<EQUAL? .X FSET?> <FORM OR !.O>)
|
||||||
|
(ELSE <FORM PROG () !.O>)>>)>
|
||||||
|
<SET ATM <NTH .ATMS 1>>
|
||||||
|
<SET ATMS <REST .ATMS>>
|
||||||
|
<SET O
|
||||||
|
(<FORM .X
|
||||||
|
.OBJ
|
||||||
|
<COND (<TYPE? .ATM FORM> .ATM)
|
||||||
|
(ELSE <FORM GVAL .ATM>)>>
|
||||||
|
!.O)>>>
|
||||||
|
|
||||||
|
<DEFMAC RFATAL ()
|
||||||
|
'<PROG () <PUSH 2> <RSTACK>>>
|
||||||
|
|
||||||
|
<DEFMAC PROB ('BASE?)
|
||||||
|
<FORM NOT <FORM L? .BASE? '<RANDOM 100>>>>
|
||||||
|
|
||||||
|
<ROUTINE PICK-ONE (FROB)
|
||||||
|
<GET .FROB <RANDOM <GET .FROB 0>>>>
|
||||||
|
|
||||||
|
<DEFMAC ENABLE ('INT)
|
||||||
|
<FORM PUT .INT ,C-ENABLED? 1>>
|
||||||
|
|
||||||
|
<DEFMAC DISABLE ('INT)
|
||||||
|
<FORM PUT .INT ,C-ENABLED? 0>>
|
||||||
|
|
||||||
|
;"former MAIN.ZIL stuff"
|
||||||
|
|
||||||
|
<GLOBAL PLAYER <>>
|
||||||
|
|
||||||
|
<GLOBAL P-WON <>>
|
||||||
|
|
||||||
|
<CONSTANT M-FATAL 2>
|
||||||
|
<CONSTANT M-BEG 1>
|
||||||
|
<CONSTANT M-END 6>
|
||||||
|
<CONSTANT M-ENTER 2>
|
||||||
|
<CONSTANT M-LOOK 3>
|
||||||
|
<CONSTANT M-FLASH 4>
|
||||||
|
<CONSTANT M-OBJDESC 5>
|
||||||
|
|
||||||
|
<ROUTINE GO ()
|
||||||
|
<PUTB ,P-LEXV 0 59>
|
||||||
|
;"put interrupts on clock chain"
|
||||||
|
<ENABLE <QUEUE I-HOUSEWRECK 20>>
|
||||||
|
<ENABLE <QUEUE I-THING 21>>
|
||||||
|
<ENABLE <QUEUE I-VOGONS 50>>
|
||||||
|
;"set up and go"
|
||||||
|
<SETG WINNER ,PROTAGONIST>
|
||||||
|
<SETG PLAYER ,PROTAGONIST>
|
||||||
|
<SETG HERE ,BEDROOM>
|
||||||
|
<SETG IDENTITY-FLAG ,ARTHUR>
|
||||||
|
<MOVE ,ARTHUR ,GLOBAL-OBJECTS>
|
||||||
|
<SETG LYING-DOWN T>
|
||||||
|
<MOVE ,PROTAGONIST ,BED>
|
||||||
|
<V-VERSION>
|
||||||
|
<CRLF>
|
||||||
|
<TELL
|
||||||
|
"You wake up. The room is spinning very gently round your head. Or at least
|
||||||
|
it would be if you could see it which you can't." CR CR>
|
||||||
|
<V-LOOK>
|
||||||
|
<MAIN-LOOP>
|
||||||
|
<AGAIN>>
|
||||||
|
|
||||||
|
<ROUTINE MAIN-LOOP ("AUX" ICNT OCNT NUM CNT OBJ TBL V PTBL OBJ1 TMP)
|
||||||
|
<REPEAT ()
|
||||||
|
<SET CNT 0>
|
||||||
|
<SET OBJ <>>
|
||||||
|
<SET PTBL T>
|
||||||
|
<COND (<SETG P-WON <PARSER>>
|
||||||
|
<SET ICNT <GET ,P-PRSI ,P-MATCHLEN>>
|
||||||
|
<SET OCNT <GET ,P-PRSO ,P-MATCHLEN>>
|
||||||
|
<COND (<AND ,P-IT-OBJECT <ACCESSIBLE? ,P-IT-OBJECT>>
|
||||||
|
<SET TMP <>>
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<G? <SET CNT <+ .CNT 1>> .ICNT>
|
||||||
|
<RETURN>)
|
||||||
|
(T
|
||||||
|
<COND (<EQUAL? <GET ,P-PRSI .CNT> ,IT>
|
||||||
|
<PUT ,P-PRSI .CNT ,P-IT-OBJECT>
|
||||||
|
<SET TMP T>
|
||||||
|
<RETURN>)>)>>
|
||||||
|
<COND (<NOT .TMP>
|
||||||
|
<SET CNT 0>
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<G? <SET CNT <+ .CNT 1>> .OCNT>
|
||||||
|
<RETURN>)
|
||||||
|
(T
|
||||||
|
<COND (<EQUAL? <GET ,P-PRSO .CNT> ,IT>
|
||||||
|
<PUT ,P-PRSO .CNT ,P-IT-OBJECT>
|
||||||
|
<RETURN>)>)>>)>
|
||||||
|
<SET CNT 0>)>
|
||||||
|
<SET NUM
|
||||||
|
<COND (<0? .OCNT> .OCNT)
|
||||||
|
(<G? .OCNT 1>
|
||||||
|
<SET TBL ,P-PRSO>
|
||||||
|
<COND (<0? .ICNT> <SET OBJ <>>)
|
||||||
|
(T <SET OBJ <GET ,P-PRSI 1>>)>
|
||||||
|
.OCNT)
|
||||||
|
(<G? .ICNT 1>
|
||||||
|
<SET PTBL <>>
|
||||||
|
<SET TBL ,P-PRSI>
|
||||||
|
<SET OBJ <GET ,P-PRSO 1>>
|
||||||
|
.ICNT)
|
||||||
|
(T 1)>>
|
||||||
|
<COND (<AND <NOT .OBJ>
|
||||||
|
<1? .ICNT>>
|
||||||
|
<SET OBJ <GET ,P-PRSI 1>>)>
|
||||||
|
<COND (<EQUAL? ,PRSA ,V?WALK> <SET V <PERFORM ,PRSA ,PRSO>>)
|
||||||
|
(<0? .NUM>
|
||||||
|
<COND (<0? <BAND <GETB ,P-SYNTAX ,P-SBITS> ,P-SONUMS>>
|
||||||
|
<SET V <PERFORM ,PRSA>>
|
||||||
|
<SETG PRSO <>>)
|
||||||
|
(<NOT ,LIT>
|
||||||
|
<TELL ,TOO-DARK CR>
|
||||||
|
<FUCKING-CLEAR>)
|
||||||
|
(T
|
||||||
|
<TELL "There isn't anything to ">
|
||||||
|
<SET TMP <GET ,P-ITBL ,P-VERBN>>
|
||||||
|
<COND (<VERB? TELL>
|
||||||
|
<TELL "talk to">)
|
||||||
|
(<OR ,P-OFLAG ,P-MERGED>
|
||||||
|
<PRINTB <GET .TMP 0>>)
|
||||||
|
(T
|
||||||
|
<WORD-PRINT <GETB .TMP 2>
|
||||||
|
<GETB .TMP 3>>)>
|
||||||
|
<TELL "!" CR>
|
||||||
|
<SET V <>>
|
||||||
|
<FUCKING-CLEAR>)>)
|
||||||
|
(T
|
||||||
|
<SETG P-NOT-HERE 0>
|
||||||
|
<SETG P-MULT <>>
|
||||||
|
<COND (<G? .NUM 1> <SETG P-MULT T>)>
|
||||||
|
<SET TMP <>>
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<G? <SET CNT <+ .CNT 1>> .NUM>
|
||||||
|
<COND (<G? ,P-NOT-HERE 0>
|
||||||
|
<TELL "The ">
|
||||||
|
<COND (<NOT <EQUAL? ,P-NOT-HERE .NUM>>
|
||||||
|
<TELL "other ">)>
|
||||||
|
<TELL "object">
|
||||||
|
<COND (<NOT <EQUAL? ,P-NOT-HERE 1>>
|
||||||
|
<TELL "s">)>
|
||||||
|
<TELL " that you mentioned ">
|
||||||
|
<COND (<NOT <EQUAL? ,P-NOT-HERE 1>>
|
||||||
|
<TELL "are">)
|
||||||
|
(T <TELL "is">)>
|
||||||
|
<TELL "n't here." CR>)
|
||||||
|
(<NOT .TMP>
|
||||||
|
<TELL ,REFERRING CR>)>
|
||||||
|
<RETURN>)
|
||||||
|
(T
|
||||||
|
<COND (.PTBL <SET OBJ1 <GET ,P-PRSO .CNT>>)
|
||||||
|
(T <SET OBJ1 <GET ,P-PRSI .CNT>>)>
|
||||||
|
<SETG PRSO <COND (.PTBL .OBJ1) (T .OBJ)>>
|
||||||
|
<SETG PRSI <COND (.PTBL .OBJ) (T .OBJ1)>>
|
||||||
|
<COND (<OR <G? .NUM 1>
|
||||||
|
<EQUAL? <GET <GET ,P-ITBL ,P-NC1>
|
||||||
|
0>
|
||||||
|
,W?ALL>>
|
||||||
|
<COND (<EQUAL? .OBJ1
|
||||||
|
,NOT-HERE-OBJECT>
|
||||||
|
<SETG P-NOT-HERE
|
||||||
|
<+ ,P-NOT-HERE 1>>
|
||||||
|
<AGAIN>)
|
||||||
|
(<AND <EQUAL? ,P-GETFLAGS
|
||||||
|
,P-ALL>
|
||||||
|
<VERB? TAKE PICK-UP>
|
||||||
|
<OR <AND <NOT <EQUAL?
|
||||||
|
<LOC .OBJ1>
|
||||||
|
,WINNER
|
||||||
|
,HERE
|
||||||
|
,PRSI>>
|
||||||
|
<NOT <FSET?
|
||||||
|
<LOC .OBJ1>
|
||||||
|
,SURFACEBIT>>>
|
||||||
|
<AND <NOT <FSET? .OBJ1
|
||||||
|
,TAKEBIT>>
|
||||||
|
<NOT <FSET? .OBJ1
|
||||||
|
,TRYTAKEBIT>>>>>
|
||||||
|
<AGAIN>)
|
||||||
|
(<AND <VERB? TAKE PICK-UP>
|
||||||
|
,PRSI
|
||||||
|
<NOT <IN? ,PRSO ,PRSI>>>
|
||||||
|
<AGAIN>)
|
||||||
|
(<AND <EQUAL? ,P-GETFLAGS
|
||||||
|
,P-ALL>
|
||||||
|
<VERB? DROP>
|
||||||
|
<NOT <IN? .OBJ1 ,WINNER>>
|
||||||
|
;"next frob semied by JW"
|
||||||
|
;<NOT <IN? ,P-IT-OBJECT
|
||||||
|
,WINNER>>>
|
||||||
|
<AGAIN>)
|
||||||
|
(<AND <EQUAL? ,P-GETFLAGS
|
||||||
|
,P-ALL>
|
||||||
|
,PRSI
|
||||||
|
<==? ,PRSO ,PRSI>>
|
||||||
|
<AGAIN>)
|
||||||
|
(<AND <EQUAL? ,P-GETFLAGS
|
||||||
|
,P-ALL>
|
||||||
|
<VERB? PUT>
|
||||||
|
<HELD? ,PRSO ,PRSI>>
|
||||||
|
<AGAIN>)
|
||||||
|
(<NOT <ACCESSIBLE? .OBJ1>>
|
||||||
|
<AGAIN>)
|
||||||
|
(T
|
||||||
|
<COND (<EQUAL? .OBJ1 ,IT>
|
||||||
|
<PRINTD ,P-IT-OBJECT>)
|
||||||
|
(<TEA-PRINT .OBJ1>
|
||||||
|
<PRINTD .OBJ1>)>
|
||||||
|
<COND (<TEA-PRINT .OBJ1>
|
||||||
|
<TELL ": ">)>)>)>
|
||||||
|
<SET TMP T>
|
||||||
|
<SET V <PERFORM ,PRSA ,PRSO ,PRSI>>
|
||||||
|
<COND (<EQUAL? .V ,M-FATAL> <RETURN>)>)>>)>
|
||||||
|
<COND (<NOT <EQUAL? .V ,M-FATAL>>
|
||||||
|
<COND (<VERB? TELL BRIEF SUPER-BRIEF VERBOSE
|
||||||
|
SAVE VERSION RESTORE SCRIPT UNSCRIPT>
|
||||||
|
T)
|
||||||
|
(T
|
||||||
|
<SET V <APPLY <GETP <LOC ,WINNER> ,P?ACTION>
|
||||||
|
,M-END>>)>)>
|
||||||
|
<COND (<VERB? AGAIN SAVE RESTORE SCRIPT UNSCRIPT
|
||||||
|
VERBOSE BRIEF SUPER-BRIEF>
|
||||||
|
T)
|
||||||
|
(,P-OFLAG T)
|
||||||
|
(T
|
||||||
|
<SETG L-PRSA ,PRSA>
|
||||||
|
<SETG L-PRSO ,PRSO>
|
||||||
|
<SETG L-PRSI ,PRSI>)>
|
||||||
|
<COND (,DONT-FLAG
|
||||||
|
<SETG L-DONT-FLAG T>)
|
||||||
|
(T
|
||||||
|
<SETG L-DONT-FLAG <>>)>
|
||||||
|
<COND (,IN-FRONT-FLAG
|
||||||
|
<SETG L-FRONT-FLAG T>)
|
||||||
|
(T
|
||||||
|
<SETG L-FRONT-FLAG <>>)>
|
||||||
|
<COND (<EQUAL? .V ,M-FATAL>
|
||||||
|
<SETG P-CONT <>>)>)
|
||||||
|
(T
|
||||||
|
<SETG P-CONT <>>)>
|
||||||
|
<COND (,P-WON
|
||||||
|
<COND (<VERB? TELL BRIEF SUPER-BRIEF VERBOSE VERSION QUIT SCORE
|
||||||
|
SAVE RESTORE SCRIPT UNSCRIPT FOOTNOTE HELP RESTART>
|
||||||
|
T)
|
||||||
|
(<AND <VERB? AGAIN>
|
||||||
|
<OR <EQUAL? ,L-PRSA ,V?FIND ,V?FOLLOW ,V?CALL>
|
||||||
|
<EQUAL? ,L-PRSA ,V?WHAT ,V?WHERE ,V?WAIT-FOR>
|
||||||
|
<EQUAL? ,L-PRSA ,V?WHO ,V?WALK-TO ,V?WHAT-ABOUT>
|
||||||
|
<EQUAL? ,L-PRSA ,V?ASK-ABOUT ,V?ASK-FOR ,V?I-AM>
|
||||||
|
<EQUAL? ,L-PRSA ,V?MY-NAME ,V?CARVE ,V?SCORE>
|
||||||
|
<EQUAL? ,L-PRSA ,V?VERSION ,V?FOOTNOTE ,V?HELP>>>
|
||||||
|
T)
|
||||||
|
(<AND <VERB? WAIT>
|
||||||
|
,DONT-FLAG>
|
||||||
|
T)
|
||||||
|
(<AND <VERB? AGAIN>
|
||||||
|
<EQUAL? ,L-PRSA ,V?WAIT>
|
||||||
|
,L-DONT-FLAG>
|
||||||
|
T)
|
||||||
|
(T
|
||||||
|
<SET V <CLOCKER>>)>
|
||||||
|
<SETG PRSA <>>
|
||||||
|
<SETG PRSO <>>
|
||||||
|
<SETG PRSI <>>)
|
||||||
|
(<AND <G? <GETB ,P-LEXV ,P-LEXWORDS> 3>
|
||||||
|
<NOT ,CARELESS-WORDS-FLAG>
|
||||||
|
,EARTH-DEMOLISHED
|
||||||
|
<SAVE-INPUT ,FIRST-BUFFER>>
|
||||||
|
<SETG CARELESS-WORDS-FLAG T>
|
||||||
|
<ENABLE <QUEUE I-CARELESS-WORDS 3>>)>>>
|
||||||
|
|
||||||
|
<GLOBAL FIRST-BUFFER <ITABLE BYTE 100>>
|
||||||
|
|
||||||
|
<ROUTINE SAVE-INPUT (TBL "AUX" (OFFS 0) CNT TMP)
|
||||||
|
<SET CNT <+ <GETB ,P-LEXV <SET TMP <* 4 ,P-INPUT-WORDS>>>
|
||||||
|
<GETB ,P-LEXV <+ .TMP 1>>>>
|
||||||
|
<COND (<EQUAL? .CNT 0> ;"failed"
|
||||||
|
<RFALSE>)>
|
||||||
|
<SET CNT <- .CNT 1>>
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<EQUAL? .OFFS .CNT>
|
||||||
|
<PUTB .TBL .OFFS 0>
|
||||||
|
<RETURN>)
|
||||||
|
(T
|
||||||
|
<PUTB .TBL .OFFS <GETB ,P-INBUF <+ .OFFS 1>>>)>
|
||||||
|
<SET OFFS <+ .OFFS 1>>>
|
||||||
|
<RTRUE>>
|
||||||
|
|
||||||
|
<ROUTINE RESTORE-INPUT (TBL "AUX" CHR)
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<EQUAL? <SET CHR <GETB .TBL 0>> 0>
|
||||||
|
<RETURN>)
|
||||||
|
(T
|
||||||
|
<PRINTC .CHR>
|
||||||
|
<SET TBL <REST .TBL>>)>>>
|
||||||
|
|
||||||
|
<GLOBAL L-PRSA <>>
|
||||||
|
|
||||||
|
<GLOBAL L-PRSO <>>
|
||||||
|
|
||||||
|
<GLOBAL L-PRSI <>>
|
||||||
|
|
||||||
|
<GLOBAL L-DONT-FLAG <>>
|
||||||
|
|
||||||
|
<GLOBAL L-FRONT-FLAG <>>
|
||||||
|
|
||||||
|
<GLOBAL P-MULT <>>
|
||||||
|
|
||||||
|
<GLOBAL P-NOT-HERE 0>
|
||||||
|
|
||||||
|
|
||||||
|
<ROUTINE FAKE-ORPHAN ("AUX" TMP)
|
||||||
|
<ORPHAN ,P-SYNTAX <>>
|
||||||
|
<TELL "Be specific: what object do">
|
||||||
|
<COND (,DONT-FLAG
|
||||||
|
<TELL "n't">)>
|
||||||
|
<TELL " you want to ">
|
||||||
|
<SET TMP <GET ,P-OTBL ,P-VERBN>>
|
||||||
|
<COND (<EQUAL? .TMP 0>
|
||||||
|
<TELL "tell">)
|
||||||
|
(<0? <GETB ,P-VTBL 2>>
|
||||||
|
<PRINTB <GET .TMP 0>>)
|
||||||
|
(T
|
||||||
|
<WORD-PRINT <GETB .TMP 2> <GETB .TMP 3>>
|
||||||
|
<PUTB ,P-VTBL 2 0>)>
|
||||||
|
<SETG P-OFLAG T>
|
||||||
|
<SETG P-WON <>>
|
||||||
|
<PREP-PRINT
|
||||||
|
<GETB ,P-SYNTAX ,P-SPREP1>>
|
||||||
|
<TELL "?" CR>>
|
||||||
|
|
||||||
|
<ROUTINE PERFORM (A "OPTIONAL" (O <>) (I <>) "AUX" V OA OO OI)
|
||||||
|
;<COND (,DEBUG
|
||||||
|
<TELL "[Perform: ">
|
||||||
|
%<COND (<GASSIGNED? PREDGEN> '<TELL N .A>)
|
||||||
|
(T '<PRINC <NTH ,ACTIONS <+ <* .A 2> 1>>>)>
|
||||||
|
<COND (<AND .O <NOT <EQUAL? .A ,V?WALK>>>
|
||||||
|
<TELL " / PRSO = " D .O>)>
|
||||||
|
<COND (.I <TELL " / PRSI = " D .I>)>
|
||||||
|
<TELL "]" CR>
|
||||||
|
<COND (,IN-FRONT-FLAG
|
||||||
|
<TELL "[IN-FRONT-FLAG is set]" CR>)>)>
|
||||||
|
<SET OA ,PRSA>
|
||||||
|
<SET OO ,PRSO>
|
||||||
|
<SET OI ,PRSI>
|
||||||
|
<SETG PRSA .A>
|
||||||
|
<COND (<EQUAL? ,IT .I .O>
|
||||||
|
<COND (<NOT .I>
|
||||||
|
<FAKE-ORPHAN>)
|
||||||
|
(T
|
||||||
|
<TELL ,REFERRING CR>)>
|
||||||
|
<RFATAL>)>
|
||||||
|
<SETG PRSO .O>
|
||||||
|
<COND (<AND ,PRSO
|
||||||
|
<NOT <VERB? WALK>>
|
||||||
|
<NOT <PRSO? ,NOT-HERE-OBJECT>>>
|
||||||
|
<SETG P-IT-OBJECT ,PRSO>)>
|
||||||
|
<SETG PRSI .I>
|
||||||
|
;<COND (<NOT <EQUAL? .A ,V?AGAIN>>
|
||||||
|
<SETG L-PRSA .A>
|
||||||
|
<COND (<EQUAL? .A ,V?WALK> <SETG L-PRSO <>>)
|
||||||
|
(T <SETG L-PRSO .O>)>
|
||||||
|
<SETG L-PRSI .I>)>
|
||||||
|
<COND (<AND <NOT <EQUAL? .A ,V?WALK>>
|
||||||
|
<EQUAL? ,NOT-HERE-OBJECT ,PRSO ,PRSI>
|
||||||
|
<SET V <D-APPLY "Not Here" ,NOT-HERE-OBJECT-F>>>
|
||||||
|
<SETG P-WON <>>
|
||||||
|
.V)
|
||||||
|
(T
|
||||||
|
<SET O ,PRSO>
|
||||||
|
<SET I ,PRSI>
|
||||||
|
<COND (<SET V <D-APPLY "Actor" <GETP ,WINNER ,P?ACTION>>>
|
||||||
|
.V)
|
||||||
|
(<AND ,DONT-FLAG <SET V <DONT-F>>>
|
||||||
|
.V)
|
||||||
|
(<SET V <D-APPLY "M-Beg" <GETP <LOC ,WINNER> ,P?ACTION>
|
||||||
|
,M-BEG>>
|
||||||
|
.V)
|
||||||
|
(<SET V <D-APPLY "Preaction" <GET ,PREACTIONS .A>>>
|
||||||
|
.V)
|
||||||
|
(<AND .I <SET V <D-APPLY "PRSI" <GETP .I ,P?ACTION>>>>
|
||||||
|
.V)
|
||||||
|
;(<AND .O
|
||||||
|
<NOT <EQUAL? .A ,V?WALK>>
|
||||||
|
<LOC .O>
|
||||||
|
<GETP <LOC .O> ,P?CONTFCN>
|
||||||
|
<SET V <D-APPLY "Cont" <GETP <LOC .O> ,P?CONTFCN>>>>
|
||||||
|
.V)
|
||||||
|
(<AND .O
|
||||||
|
<NOT <EQUAL? .A ,V?WALK>>
|
||||||
|
<SET V <D-APPLY "PRSO" <GETP .O ,P?ACTION>>>>
|
||||||
|
.V)
|
||||||
|
(<SET V <D-APPLY <> <GET ,ACTIONS .A>>>
|
||||||
|
.V)>)>
|
||||||
|
<SETG PRSA .OA>
|
||||||
|
<SETG PRSO .OO>
|
||||||
|
<SETG PRSI .OI>
|
||||||
|
.V>
|
||||||
|
|
||||||
|
<ROUTINE D-APPLY (STR FCN "OPTIONAL" (FOO <>) "AUX" RES)
|
||||||
|
<COND (<NOT .FCN> <>)
|
||||||
|
(T
|
||||||
|
;<COND (,DEBUG
|
||||||
|
<COND (<NOT .STR>
|
||||||
|
<TELL CR " Default ->" CR>)
|
||||||
|
(T <TELL CR " " .STR " -> ">)>)>
|
||||||
|
<SET RES
|
||||||
|
<COND (.FOO <APPLY .FCN .FOO>)
|
||||||
|
(T <APPLY .FCN>)>>
|
||||||
|
;<COND (<AND ,DEBUG .STR>
|
||||||
|
<COND (<EQUAL? .RES ,M-FATAL>
|
||||||
|
<TELL "Fatal" CR>)
|
||||||
|
(<NOT .RES>
|
||||||
|
<TELL "Not handled">)
|
||||||
|
(T <TELL "Handled" CR>)>)>
|
||||||
|
.RES)>>
|
||||||
|
|
||||||
|
|
||||||
|
;"former CLOCK.ZIL stuff"
|
||||||
|
|
||||||
|
<GLOBAL CLOCK-WAIT <>>
|
||||||
|
|
||||||
|
<GLOBAL C-TABLE %<COND (<GASSIGNED? PREDGEN>
|
||||||
|
'<ITABLE NONE 105>)
|
||||||
|
(T
|
||||||
|
'<ITABLE NONE 210>)>>
|
||||||
|
|
||||||
|
<CONSTANT C-TABLELEN 210>
|
||||||
|
|
||||||
|
<GLOBAL C-INTS 210>
|
||||||
|
|
||||||
|
<CONSTANT C-INTLEN 6>
|
||||||
|
|
||||||
|
<CONSTANT C-ENABLED? 0>
|
||||||
|
|
||||||
|
<CONSTANT C-TICK 1>
|
||||||
|
|
||||||
|
<CONSTANT C-RTN 2>
|
||||||
|
|
||||||
|
<ROUTINE QUEUE (RTN TICK "AUX" CINT)
|
||||||
|
<PUT <SET CINT <INT .RTN>> ,C-TICK .TICK>
|
||||||
|
.CINT>
|
||||||
|
|
||||||
|
<ROUTINE INT (RTN "OPTIONAL" E C INT)
|
||||||
|
<SET E <REST ,C-TABLE ,C-TABLELEN>>
|
||||||
|
<SET C <REST ,C-TABLE ,C-INTS>>
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<EQUAL? .C .E>
|
||||||
|
<SETG C-INTS <- ,C-INTS ,C-INTLEN>>
|
||||||
|
<SET INT <REST ,C-TABLE ,C-INTS>>
|
||||||
|
<PUT .INT ,C-RTN .RTN>
|
||||||
|
<RETURN .INT>)
|
||||||
|
(<EQUAL? <GET .C ,C-RTN> .RTN> <RETURN .C>)>
|
||||||
|
<SET C <REST .C ,C-INTLEN>>>>
|
||||||
|
|
||||||
|
<ROUTINE CLOCKER ("AUX" C E TICK (FLG <>))
|
||||||
|
<COND (,CLOCK-WAIT <SETG CLOCK-WAIT <>> <RFALSE>)>
|
||||||
|
<SET C <REST ,C-TABLE <COND (,P-WON ,C-INTS)>>>
|
||||||
|
<SET E <REST ,C-TABLE ,C-TABLELEN>>
|
||||||
|
<REPEAT ()
|
||||||
|
<COND (<EQUAL? .C .E>
|
||||||
|
<SETG MOVES <+ ,MOVES 1>>
|
||||||
|
<RETURN .FLG>)
|
||||||
|
(<NOT <0? <GET .C ,C-ENABLED?>>>
|
||||||
|
<SET TICK <GET .C ,C-TICK>>
|
||||||
|
<COND (<0? .TICK>)
|
||||||
|
(T
|
||||||
|
<PUT .C ,C-TICK <- .TICK 1>>
|
||||||
|
<COND (<AND <NOT <G? .TICK 1>>
|
||||||
|
<APPLY <GET .C ,C-RTN>>>
|
||||||
|
<SET FLG T>)>)>)>
|
||||||
|
<SET C <REST .C ,C-INTLEN>>>>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[project]
|
||||||
|
name = "h2g2"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Add your description here"
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.14"
|
||||||
|
dependencies = []
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
Assembling S4.XZAP.1 on Thursday, October 2, 1986 22:03:54
|
||||||
|
Release: 60
|
||||||
|
|
||||||
|
64 Inserting S4FREQ.XZAP.2 (634 bytes)
|
||||||
|
698 Inserting S4DAT.ZAP.1 (19961 bytes)
|
||||||
|
20659 Inserting MISC.ZAP.1 (1826 bytes)
|
||||||
|
22485 Inserting PARSER.ZAP.1 (6083 bytes)
|
||||||
|
28568 Inserting SYNTAX.ZAP.1 (0 bytes)
|
||||||
|
28568 Inserting VERBS.ZAP.1 (15191 bytes)
|
||||||
|
43759 Inserting GLOBALS.ZAP.1 (14345 bytes)
|
||||||
|
58104 Inserting EARTH.ZAP.1 (19174 bytes)
|
||||||
|
77278 Inserting VOGON.ZAP.1 (5744 bytes)
|
||||||
|
83022 Inserting UNEARTH.ZAP.1 (9740 bytes)
|
||||||
|
92762 Inserting HEART.ZAP.1 (13513 bytes)
|
||||||
|
106275 Inserting S4STR.ZAP.1 (7055 bytes)
|
||||||
|
220 objects.
|
||||||
|
239 globals.
|
||||||
|
971 word vocabulary.
|
||||||
|
|
||||||
|
113330 bytes (111K).
|
||||||
|
20453 bytes of preload.
|
||||||
|
9736 bytes of impure.
|
||||||
|
|
||||||
|
Outputting symbol tables
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
.INSERT "S4FREQ"
|
||||||
|
|
||||||
|
|
||||||
|
.INSERT "S4DAT" ; DATA IS IN THIS FILE
|
||||||
|
|
||||||
|
|
||||||
|
.INSERT "MISC"
|
||||||
|
|
||||||
|
|
||||||
|
.INSERT "PARSER"
|
||||||
|
|
||||||
|
|
||||||
|
.INSERT "SYNTAX"
|
||||||
|
|
||||||
|
|
||||||
|
.INSERT "VERBS"
|
||||||
|
|
||||||
|
|
||||||
|
.INSERT "GLOBALS"
|
||||||
|
|
||||||
|
|
||||||
|
.INSERT "EARTH"
|
||||||
|
|
||||||
|
|
||||||
|
.INSERT "VOGON"
|
||||||
|
|
||||||
|
|
||||||
|
.INSERT "UNEARTH"
|
||||||
|
|
||||||
|
|
||||||
|
.INSERT "HEART"
|
||||||
|
|
||||||
|
|
||||||
|
.INSERT "S4STR"
|
||||||
|
|
||||||
|
.END
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
"S4 for
|
||||||
|
THE HITCHHIKER'S GUIDE TO THE GALAXY
|
||||||
|
(c) Copyright 1984 Infocom, Inc. All Rights Reserved."
|
||||||
|
|
||||||
|
<PRINC "
|
||||||
|
*** THE HITCHHIKER'S GUIDE TO THE GALAXY: Interactive Science Fiction ***
|
||||||
|
|
||||||
|
">
|
||||||
|
|
||||||
|
<SNAME "S4">
|
||||||
|
|
||||||
|
<SET REDEFINE T>
|
||||||
|
|
||||||
|
;<OR <GASSIGNED? INSERT-CRUFTY>
|
||||||
|
<DEFINE INSERT-CRUFTY (STR) <INSERT-FILE .STR T>>>
|
||||||
|
|
||||||
|
<INSERT-FILE "MISC" T>
|
||||||
|
<INSERT-FILE "HEART" T>
|
||||||
|
<INSERT-FILE "PARSER" T>
|
||||||
|
<INSERT-FILE "SYNTAX" T>
|
||||||
|
<INSERT-FILE "VERBS" T>
|
||||||
|
<INSERT-FILE "EARTH" T>
|
||||||
|
<INSERT-FILE "VOGON" T>
|
||||||
|
<INSERT-FILE "UNEARTH" T>
|
||||||
|
<INSERT-FILE "GLOBALS" T>
|
||||||
|
|
||||||
|
<PROPDEF SIZE 5>
|
||||||
|
<PROPDEF CAPACITY 0>
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
.FSTR FSTR?1,"the " ;1664 832
|
||||||
|
.FSTR FSTR?2,", " ;842 842
|
||||||
|
.FSTR FSTR?3,"You " ;810 270
|
||||||
|
.FSTR FSTR?4,"you " ;736 368
|
||||||
|
.FSTR FSTR?5,"and " ;736 368
|
||||||
|
.FSTR FSTR?6,"The " ;702 234
|
||||||
|
.FSTR FSTR?7,". " ;529 529
|
||||||
|
.FSTR FSTR?8,"your " ;513 171
|
||||||
|
.FSTR FSTR?9,"that " ;459 153
|
||||||
|
.FSTR FSTR?10,"of " ;406 406
|
||||||
|
.FSTR FSTR?11,"is " ;370 370
|
||||||
|
.FSTR FSTR?12,"to " ;368 368
|
||||||
|
.FSTR FSTR?13,"can't " ;350 70
|
||||||
|
.FSTR FSTR?14,"with " ;303 101
|
||||||
|
.FSTR FSTR?15,"have " ;246 82
|
||||||
|
.FSTR FSTR?16,"are " ;240 120
|
||||||
|
.FSTR FSTR?17,"from " ;237 79
|
||||||
|
.FSTR FSTR?18,"about " ;212 53
|
||||||
|
.FSTR FSTR?19,"in " ;209 209
|
||||||
|
.FSTR FSTR?20,"for " ;202 101
|
||||||
|
.FSTR FSTR?21,"There " ;190 38
|
||||||
|
.FSTR FSTR?22,"which " ;188 47
|
||||||
|
.FSTR FSTR?23,"already " ;180 30
|
||||||
|
.FSTR FSTR?24,"this " ;177 59
|
||||||
|
.FSTR FSTR?25,"something " ;168 21
|
||||||
|
.FSTR FSTR?26,"It " ;166 83
|
||||||
|
.FSTR FSTR?27,"through " ;162 27
|
||||||
|
.FSTR FSTR?28,"This " ;156 39
|
||||||
|
.FSTR FSTR?29,"nothing " ;150 25
|
||||||
|
.FSTR FSTR?30,"Prosser " ;147 21
|
||||||
|
.FSTR FSTR?31,"It's " ;145 29
|
||||||
|
.FSTR FSTR?32,"Ford " ;144 36
|
||||||
|
.FSTR FSTR?33,"don't " ;140 28
|
||||||
|
.FSTR FSTR?34,"Arthur " ;138 23
|
||||||
|
.FSTR FSTR?35,"There's " ;136 17
|
||||||
|
.FSTR FSTR?36,"around " ;135 27
|
||||||
|
.FSTR FSTR?37,"You're " ;133 19
|
||||||
|
.FSTR FSTR?38,"Beast " ;130 26
|
||||||
|
.FSTR FSTR?39,"into " ;126 42
|
||||||
|
.FSTR FSTR?40,"like " ;120 40
|
||||||
|
.FSTR FSTR?41,"it " ;113 113
|
||||||
|
.FSTR FSTR?42,"doesn't " ;112 16
|
||||||
|
.FSTR FSTR?43,"Footnote " ;112 14
|
||||||
|
.FSTR FSTR?44,"but " ;108 54
|
||||||
|
.FSTR FSTR?45,"you're " ;108 18
|
||||||
|
.FSTR FSTR?46,"small " ;104 26
|
||||||
|
.FSTR FSTR?47,"on " ;102 102
|
||||||
|
.FSTR FSTR?48,"will " ;102 34
|
||||||
|
.FSTR FSTR?49,"just " ;102 34
|
||||||
|
.FSTR FSTR?50,"because " ;102 17
|
||||||
|
.FSTR FSTR?51,"see " ;96 48
|
||||||
|
.FSTR FSTR?52,"has " ;96 48
|
||||||
|
.FSTR FSTR?53,"not " ;94 47
|
||||||
|
.FSTR FSTR?54,"seems " ;92 23
|
||||||
|
.FSTR FSTR?55,"it's " ;92 23
|
||||||
|
.FSTR FSTR?56,"Improbability " ;91 7
|
||||||
|
.FSTR FSTR?57,"toward " ;90 18
|
||||||
|
.FSTR FSTR?58,"you've " ;90 15
|
||||||
|
.FSTR FSTR?59,"what " ;87 29
|
||||||
|
.FSTR FSTR?60,"says " ;87 29
|
||||||
|
.FSTR FSTR?61,"at " ;86 86
|
||||||
|
.FSTR FSTR?62,"here" ;84 42
|
||||||
|
.FSTR FSTR?63,"very " ;84 28
|
||||||
|
.FSTR FSTR?64,"looks " ;84 21
|
||||||
|
.FSTR FSTR?65,"probably " ;84 12
|
||||||
|
.FSTR FSTR?66,"you" ;83 83
|
||||||
|
.FSTR FSTR?67,"can " ;82 41
|
||||||
|
.FSTR FSTR?68,"all " ;80 40
|
||||||
|
.FSTR FSTR?69,"out " ;78 39
|
||||||
|
.FSTR FSTR?70,"anything " ;77 11
|
||||||
|
.FSTR FSTR?71,"think " ;76 19
|
||||||
|
.FSTR FSTR?72,"closed" ;76 19
|
||||||
|
.FSTR FSTR?73,"isn't " ;75 15
|
||||||
|
.FSTR FSTR?74,"his " ;74 37
|
||||||
|
.FSTR FSTR?75,"I " ;72 72
|
||||||
|
.FSTR FSTR?76,"down " ;72 24
|
||||||
|
.FSTR FSTR?77,"would " ;72 18
|
||||||
|
.FSTR FSTR?78,"their " ;72 18
|
||||||
|
.FSTR FSTR?79,"large " ;72 18
|
||||||
|
.FSTR FSTR?80,"front " ;72 18
|
||||||
|
.FSTR FSTR?81,"I'm " ;72 18
|
||||||
|
.FSTR FSTR?82,"Unfortunately" ;72 6
|
||||||
|
.FSTR FSTR?83,"be " ;70 70
|
||||||
|
.FSTR FSTR?84,"little " ;70 14
|
||||||
|
.FSTR FSTR?85,"Arthur" ;70 14
|
||||||
|
.FSTR FSTR?86,"even " ;69 23
|
||||||
|
.FSTR FSTR?87,"He " ;66 33
|
||||||
|
.FSTR FSTR?88,"some " ;66 22
|
||||||
|
.FSTR FSTR?89,"Ford" ;66 22
|
||||||
|
.FSTR FSTR?90,"holding " ;66 11
|
||||||
|
.FSTR FSTR?91,"between " ;66 11
|
||||||
|
.FSTR FSTR?92,"anything" ;66 11
|
||||||
|
.FSTR FSTR?93,"across " ;65 13
|
||||||
|
.FSTR FSTR?94,"going " ;64 16
|
||||||
|
.FSTR FSTR?95,"currently " ;64 8
|
||||||
|
.FSTR FSTR?96,"something" ;63 9
|
||||||
|
|
||||||
|
|
||||||
|
;word frequency table of 96 most common words
|
||||||
|
|
||||||
|
WORDS:: .TABLE
|
||||||
|
FSTR?1
|
||||||
|
FSTR?2
|
||||||
|
FSTR?3
|
||||||
|
FSTR?4
|
||||||
|
FSTR?5
|
||||||
|
FSTR?6
|
||||||
|
FSTR?7
|
||||||
|
FSTR?8
|
||||||
|
FSTR?9
|
||||||
|
FSTR?10
|
||||||
|
FSTR?11
|
||||||
|
FSTR?12
|
||||||
|
FSTR?13
|
||||||
|
FSTR?14
|
||||||
|
FSTR?15
|
||||||
|
FSTR?16
|
||||||
|
FSTR?17
|
||||||
|
FSTR?18
|
||||||
|
FSTR?19
|
||||||
|
FSTR?20
|
||||||
|
FSTR?21
|
||||||
|
FSTR?22
|
||||||
|
FSTR?23
|
||||||
|
FSTR?24
|
||||||
|
FSTR?25
|
||||||
|
FSTR?26
|
||||||
|
FSTR?27
|
||||||
|
FSTR?28
|
||||||
|
FSTR?29
|
||||||
|
FSTR?30
|
||||||
|
FSTR?31
|
||||||
|
FSTR?32
|
||||||
|
FSTR?33
|
||||||
|
FSTR?34
|
||||||
|
FSTR?35
|
||||||
|
FSTR?36
|
||||||
|
FSTR?37
|
||||||
|
FSTR?38
|
||||||
|
FSTR?39
|
||||||
|
FSTR?40
|
||||||
|
FSTR?41
|
||||||
|
FSTR?42
|
||||||
|
FSTR?43
|
||||||
|
FSTR?44
|
||||||
|
FSTR?45
|
||||||
|
FSTR?46
|
||||||
|
FSTR?47
|
||||||
|
FSTR?48
|
||||||
|
FSTR?49
|
||||||
|
FSTR?50
|
||||||
|
FSTR?51
|
||||||
|
FSTR?52
|
||||||
|
FSTR?53
|
||||||
|
FSTR?54
|
||||||
|
FSTR?55
|
||||||
|
FSTR?56
|
||||||
|
FSTR?57
|
||||||
|
FSTR?58
|
||||||
|
FSTR?59
|
||||||
|
FSTR?60
|
||||||
|
FSTR?61
|
||||||
|
FSTR?62
|
||||||
|
FSTR?63
|
||||||
|
FSTR?64
|
||||||
|
FSTR?65
|
||||||
|
FSTR?66
|
||||||
|
FSTR?67
|
||||||
|
FSTR?68
|
||||||
|
FSTR?69
|
||||||
|
FSTR?70
|
||||||
|
FSTR?71
|
||||||
|
FSTR?72
|
||||||
|
FSTR?73
|
||||||
|
FSTR?74
|
||||||
|
FSTR?75
|
||||||
|
FSTR?76
|
||||||
|
FSTR?77
|
||||||
|
FSTR?78
|
||||||
|
FSTR?79
|
||||||
|
FSTR?80
|
||||||
|
FSTR?81
|
||||||
|
FSTR?82
|
||||||
|
FSTR?83
|
||||||
|
FSTR?84
|
||||||
|
FSTR?85
|
||||||
|
FSTR?86
|
||||||
|
FSTR?87
|
||||||
|
FSTR?88
|
||||||
|
FSTR?89
|
||||||
|
FSTR?90
|
||||||
|
FSTR?91
|
||||||
|
FSTR?92
|
||||||
|
FSTR?93
|
||||||
|
FSTR?94
|
||||||
|
FSTR?95
|
||||||
|
FSTR?96
|
||||||
|
.ENDT
|
||||||
|
|
||||||
|
.ENDI
|
||||||
@@ -0,0 +1,622 @@
|
|||||||
|
"SYNTAX for
|
||||||
|
THE HITCHHIKER'S GUIDE TO THE GALAXY
|
||||||
|
(c) Copyright 1984 Infocom, Inc. All Rights Reserved."
|
||||||
|
|
||||||
|
<BUZZ A AN THE IS ARE AM AND OF THEN ALL BUT EXCEPT \. \, \"
|
||||||
|
DON\'T DONT PRY PLEASE HERE SOME MORE FRONT>
|
||||||
|
|
||||||
|
<SYNONYM TO TOWARD>
|
||||||
|
<SYNONYM WITH USING>
|
||||||
|
<SYNONYM THROUGH THRU>
|
||||||
|
<SYNONYM ON ONTO>
|
||||||
|
<SYNONYM OUT OUTSIDE>
|
||||||
|
<SYNONYM IN INSIDE INTO>
|
||||||
|
<SYNONYM UNDER BELOW BENEATH UNDERNEATH>
|
||||||
|
<SYNONYM AROUND ALONG>
|
||||||
|
<SYNONYM BEFORE NEAR NEXT AGAINST>
|
||||||
|
<SYNONYM ALL BOTH>
|
||||||
|
<SYNONYM DRUNK BOMBED SMASHE PLASTE>
|
||||||
|
|
||||||
|
<SYNONYM NORTH N FORE F FOREWA>
|
||||||
|
<SYNONYM SOUTH S AFT>
|
||||||
|
<SYNONYM EAST E STARBO SB>
|
||||||
|
<SYNONYM WEST W PORT P>
|
||||||
|
<SYNONYM DOWN D>
|
||||||
|
<SYNONYM UP U>
|
||||||
|
<SYNONYM NW NORTHWEST>
|
||||||
|
<SYNONYM NE NORTHE>
|
||||||
|
<SYNONYM SW SOUTHWEST>
|
||||||
|
<SYNONYM SE SOUTHE>
|
||||||
|
|
||||||
|
|
||||||
|
;"game commands"
|
||||||
|
|
||||||
|
<SYNTAX VERBOSE = V-VERBOSE>
|
||||||
|
|
||||||
|
<SYNTAX BRIEF = V-BRIEF>
|
||||||
|
|
||||||
|
<SYNTAX SUPER = V-SUPER-BRIEF>
|
||||||
|
<SYNONYM SUPER SUPERBRIEF>
|
||||||
|
|
||||||
|
<SYNTAX DIAGNOSE = V-DIAGNOSE>
|
||||||
|
|
||||||
|
<SYNTAX INVENT = V-INVENTORY>
|
||||||
|
<SYNTAX I = V-INVENTORY>
|
||||||
|
<SYNTAX I OBJECT = V-I-AM>
|
||||||
|
<SYNONYM I I\'M IM>
|
||||||
|
|
||||||
|
<SYNTAX QUIT = V-QUIT>
|
||||||
|
<SYNONYM QUIT Q>
|
||||||
|
|
||||||
|
<SYNTAX RESTAR = V-RESTART>
|
||||||
|
|
||||||
|
<SYNTAX RESTOR = V-RESTORE>
|
||||||
|
|
||||||
|
<SYNTAX SAVE = V-SAVE>
|
||||||
|
|
||||||
|
<SYNTAX SCORE = V-SCORE>
|
||||||
|
|
||||||
|
<SYNTAX SCRIPT = V-SCRIPT>
|
||||||
|
|
||||||
|
<SYNTAX UNSCRIPT = V-UNSCRIPT>
|
||||||
|
|
||||||
|
<SYNTAX VERSION = V-VERSION>
|
||||||
|
|
||||||
|
<SYNTAX $VERIFY = V-$VERIFY>
|
||||||
|
<SYNTAX $VERIFY OBJECT = V-$VERIFY>
|
||||||
|
|
||||||
|
;<SYNTAX $DEBUG = V-$DEBUG>
|
||||||
|
|
||||||
|
;<SYNTAX $CHEAT OBJECT = V-$CHEAT>
|
||||||
|
|
||||||
|
;<SYNTAX $PROB = V-$PROB>
|
||||||
|
|
||||||
|
|
||||||
|
;"subtitle real verbs"
|
||||||
|
|
||||||
|
<SYNTAX ADDRES OBJECT (FIND ACTORBIT) (IN-ROOM) = V-TELL>
|
||||||
|
|
||||||
|
<SYNTAX AGAIN = V-AGAIN>
|
||||||
|
<SYNONYM AGAIN G>
|
||||||
|
|
||||||
|
<SYNTAX ANSWER = V-ANSWER>
|
||||||
|
<SYNTAX ANSWER OBJECT = V-REPLY>
|
||||||
|
<SYNTAX ANSWER TO OBJECT = V-REPLY>
|
||||||
|
<SYNONYM ANSWER REPLY>
|
||||||
|
|
||||||
|
<SYNTAX APPLAU = V-APPLAUD>
|
||||||
|
<SYNONYM APPLAU CLAP CHEER>
|
||||||
|
|
||||||
|
<SYNTAX APPREC OBJECT = V-APPRECIATE>
|
||||||
|
|
||||||
|
<SYNTAX APPROA OBJECT = V-WALK-TO>
|
||||||
|
|
||||||
|
<SYNTAX ASK OBJECT (FIND ACTORBIT) ABOUT OBJECT = V-ASK-ABOUT>
|
||||||
|
<SYNTAX ASK OBJECT (FIND ACTORBIT) ON OBJECT = V-ASK-ABOUT>
|
||||||
|
<SYNTAX ASK OBJECT (FIND ACTORBIT) FOR OBJECT = V-ASK-FOR>
|
||||||
|
<SYNONYM ASK CONSUL QUERY>
|
||||||
|
|
||||||
|
<SYNTAX ATTACK OBJECT (FIND ACTORBIT) (ON-GROUND IN-ROOM) = V-KILL>
|
||||||
|
<SYNTAX ATTACK OBJECT (FIND ACTORBIT) (ON-GROUND IN-ROOM)
|
||||||
|
WITH OBJECT (HELD CARRIED HAVE) = V-KILL>
|
||||||
|
<SYNONYM ATTACK ASSAULT FIGHT HIT SLAP KILL MURDER STRIKE PUNCH>
|
||||||
|
|
||||||
|
<SYNTAX BITE OBJECT = V-BITE>
|
||||||
|
|
||||||
|
<SYNTAX BLOCK OBJECT = V-BLOCK>
|
||||||
|
<SYNTAX BLOCK OBJECT WITH OBJECT = V-BLOCK-WITH>
|
||||||
|
<SYNONYM BLOCK STOP>
|
||||||
|
|
||||||
|
<SYNTAX BOARD OBJECT (FIND VEHBIT) (ON-GROUND IN-ROOM) = V-BOARD PRE-BOARD>
|
||||||
|
<SYNONYM BOARD EMBARK>
|
||||||
|
|
||||||
|
<SYNTAX BRUSH OBJECT = V-BRUSH>
|
||||||
|
<SYNTAX BRUSH OBJECT WITH OBJECT (HAVE) = V-BRUSH>
|
||||||
|
<SYNONYM BRUSH>
|
||||||
|
|
||||||
|
<SYNTAX ORDER OBJECT = V-BUY>
|
||||||
|
<SYNONYM ORDER BUY PURCHASE>
|
||||||
|
|
||||||
|
<SYNTAX CARVE OBJECT ON OBJECT = V-CARVE PRE-CARVE>
|
||||||
|
<SYNTAX CARVE OBJECT IN OBJECT = V-CARVE PRE-CARVE>
|
||||||
|
<SYNTAX CARVE OBJECT WITH OBJECT (HAVE) = V-CARVE-WITH>
|
||||||
|
<SYNONYM CARVE INSCRI SCRATC WRITE>
|
||||||
|
|
||||||
|
<SYNTAX CLIMB OBJECT (ON-GROUND IN-ROOM) = V-CLIMB-FOO>
|
||||||
|
<SYNTAX CLIMB ON OBJECT (FIND VEHBIT) (ON-GROUND IN-ROOM) = V-CLIMB-ON>
|
||||||
|
<SYNTAX CLIMB UP OBJECT (FIND RLANDBIT) (ON-GROUND IN-ROOM) = V-CLIMB-UP>
|
||||||
|
<SYNTAX CLIMB DOWN OBJECT (FIND RLANDBIT) (ON-GROUND IN-ROOM) = V-CLIMB-DOWN>
|
||||||
|
<SYNTAX CLIMB OVER OBJECT (ON-GROUND IN-ROOM) = V-CLIMB-OVER>
|
||||||
|
<SYNTAX CLIMB IN OBJECT (FIND VEHBIT) (ON-GROUND IN-ROOM) = V-BOARD PRE-BOARD>
|
||||||
|
<SYNTAX CLIMB THROUGH OBJECT = V-THROUGH>
|
||||||
|
<SYNONYM CLIMB SCALE>
|
||||||
|
|
||||||
|
<SYNTAX CLOSE OBJECT (FIND DOORBIT) (HELD CARRIED ON-GROUND IN-ROOM) = V-CLOSE>
|
||||||
|
<SYNTAX CLOSE OFF OBJECT (FIND LIGHTBIT) (HELD CARRIED ON-GROUND IN-ROOM TAKE)
|
||||||
|
= V-LAMP-OFF>
|
||||||
|
<SYNONYM CLOSE SHUT>
|
||||||
|
|
||||||
|
<SYNTAX CONNECT OBJECT TO OBJECT = V-PLUG>
|
||||||
|
|
||||||
|
<SYNTAX COVER OBJECT WITH OBJECT (HELD MANY) = V-SPUT-ON>
|
||||||
|
|
||||||
|
<SYNTAX COUNT OBJECT = V-COUNT>
|
||||||
|
|
||||||
|
<SYNTAX CUT OBJECT WITH OBJECT (CARRIED HELD) = V-CUT>
|
||||||
|
<SYNTAX CUT THROUGH OBJECT WITH OBJECT (CARRIED HELD) = V-CUT>
|
||||||
|
<SYNONYM CUT SLICE>
|
||||||
|
|
||||||
|
<SYNTAX DEMOLI OBJECT (ON-GROUND IN-ROOM) = V-MUNG>
|
||||||
|
<SYNTAX DEMOLI OBJECT WITH OBJECT (HELD CARRIED TAKE) = V-MUNG>
|
||||||
|
<SYNTAX DEMOLI DOWN OBJECT = V-KILL>
|
||||||
|
<SYNONYM DEMOLI CRACK DESTRO DAMAGE BREAK SMASH WRECK>
|
||||||
|
|
||||||
|
<SYNTAX DANGLE OBJECT (HELD MANY) IN OBJECT = V-PUT PRE-PUT>
|
||||||
|
|
||||||
|
<SYNTAX DESCEN OBJECT (ON-GROUND IN-ROOM) = V-CLIMB-DOWN>
|
||||||
|
|
||||||
|
<SYNTAX DIG IN OBJECT = V-DIG>
|
||||||
|
<SYNTAX DIG WITH OBJECT = V-DIG>
|
||||||
|
<SYNTAX DIG THROUGH OBJECT = V-DIG>
|
||||||
|
|
||||||
|
<SYNTAX DISEMBARK OBJECT (FIND VEHBIT) (ON-GROUND IN-ROOM) = V-DISEMBARK>
|
||||||
|
<SYNONYM DISEMBARK DEBARK>
|
||||||
|
|
||||||
|
<SYNTAX DISROBE = V-GET-UNDRESSED>
|
||||||
|
|
||||||
|
<SYNTAX DOZE = V-DOZE>
|
||||||
|
<SYNONYM DOZE NAP SNOOZE>
|
||||||
|
|
||||||
|
<SYNTAX DRINK OBJECT (FIND DRINKBIT) (HELD CARRIED ON-GROUND IN-ROOM)
|
||||||
|
= V-DRINK>
|
||||||
|
<SYNTAX DRINK FROM OBJECT (HELD CARRIED) = V-DRINK-FROM>
|
||||||
|
<SYNONYM DRINK SIP SWALLOW IMBIBE QUAFF GUZZLE SWILL>
|
||||||
|
|
||||||
|
<SYNTAX DROP OBJECT (HELD MANY HAVE) = V-DROP PRE-DROP>
|
||||||
|
<SYNTAX DROP OBJECT (HELD MANY) BEFORE OBJECT = V-PUT-IN-FRONT PRE-GIVE>
|
||||||
|
<SYNTAX DROP OBJECT (HELD MANY) DOWN OBJECT = V-PUT PRE-PUT>
|
||||||
|
<SYNTAX DROP OBJECT (HELD MANY) IN OBJECT = V-PUT PRE-PUT>
|
||||||
|
<SYNTAX DROP OBJECT (HELD MANY) ON OBJECT = V-PUT-ON PRE-PUT>
|
||||||
|
|
||||||
|
<SYNTAX EAT OBJECT (FIND EATBIT) (HELD CARRIED ON-GROUND IN-ROOM) = V-EAT>
|
||||||
|
<SYNONYM EAT DEVOUR INGEST GOBBLE>
|
||||||
|
|
||||||
|
<SYNTAX ENJOY OBJECT = V-ENJOY>
|
||||||
|
|
||||||
|
<SYNTAX ENTER = V-ENTER>
|
||||||
|
<SYNTAX ENTER OBJECT = V-THROUGH>
|
||||||
|
|
||||||
|
<SYNTAX EXIT = V-EXIT>
|
||||||
|
<SYNTAX EXIT OBJECT = V-EXIT>
|
||||||
|
<SYNONYM EXIT DEPART WITHDR>
|
||||||
|
|
||||||
|
<SYNTAX ESCAPE = V-ESCAPE>
|
||||||
|
<SYNTAX ESCAPE OBJECT = V-ESCAPE>
|
||||||
|
<SYNTAX ESCAPE FROM OBJECT = V-ESCAPE>
|
||||||
|
<SYNONYM ESCAPE FLEE>
|
||||||
|
|
||||||
|
<SYNTAX EXAMINE OBJECT (HELD CARRIED ON-GROUND IN-ROOM) (FIND DARKBIT)
|
||||||
|
= V-EXAMINE PRE-READ>
|
||||||
|
<SYNTAX EXAMINE OBJECT THROUGH OBJECT = V-EXAMINE-THROUGH PRE-READ>
|
||||||
|
<SYNTAX EXAMINE IN OBJECT (HELD CARRIED IN-ROOM ON-GROUND)
|
||||||
|
= V-LOOK-INSIDE>
|
||||||
|
<SYNTAX EXAMINE ON OBJECT (HELD CARRIED IN-ROOM ON-GROUND)
|
||||||
|
= V-LOOK-INSIDE>
|
||||||
|
<SYNTAX EXAMINE FOR OBJECT = V-FIND>
|
||||||
|
<SYNONYM EXAMINE INSPECT DESCRIBE STUDY OBSERVE SEE SCOUR>
|
||||||
|
|
||||||
|
<SYNTAX EXTINGUISH OBJECT (FIND ONBIT) = V-LAMP-OFF>
|
||||||
|
|
||||||
|
<SYNTAX FEED OBJECT (FIND ACTORBIT) = V-FEED>
|
||||||
|
<SYNTAX FEED OBJECT (MANY HELD HAVE) TO OBJECT (FIND ACTORBIT) (ON-GROUND)
|
||||||
|
= V-GIVE PRE-GIVE>
|
||||||
|
<SYNTAX FEED OBJECT (FIND ACTORBIT) (ON-GROUND) OBJECT (MANY HELD HAVE)
|
||||||
|
= V-SGIVE>
|
||||||
|
|
||||||
|
<SYNTAX FILL OBJECT = V-FILL>
|
||||||
|
|
||||||
|
<SYNTAX FIND OBJECT = V-FIND>
|
||||||
|
<SYNONYM FIND SEEK>
|
||||||
|
|
||||||
|
<SYNTAX FOLLOW OBJECT = V-FOLLOW>
|
||||||
|
<SYNONYM FOLLOW PURSUE CHASE>
|
||||||
|
|
||||||
|
<SYNTAX FOOTNOTE = V-FOOTNOTE>
|
||||||
|
<SYNTAX FOOTNOTE OBJECT = V-FOOTNOTE>
|
||||||
|
|
||||||
|
<SYNTAX FRIPPI = V-FRIPPI>
|
||||||
|
<SYNONYM FRIPPI LYSHUS GASHEE MORPHO THOU BLEEM MISERA VENCHI WIMBGU>
|
||||||
|
|
||||||
|
<SYNTAX HAND OBJECT (MANY HELD HAVE) TO OBJECT (FIND ACTORBIT) (ON-GROUND)
|
||||||
|
= V-GIVE PRE-GIVE>
|
||||||
|
<SYNTAX HAND OBJECT (FIND ACTORBIT) (ON-GROUND) OBJECT (MANY HELD HAVE)
|
||||||
|
= V-SGIVE>
|
||||||
|
<SYNTAX HAND UP OBJECT (FIND RLANDBIT) = V-GIVE-UP>
|
||||||
|
<SYNONYM HAND GIVE SELL DONATE OFFER>
|
||||||
|
|
||||||
|
<SYNTAX HANG OBJECT ON OBJECT = V-HANG>
|
||||||
|
<SYNTAX HANG OBJECT FROM OBJECT = V-HANG>
|
||||||
|
<SYNTAX HANG OBJECT (HELD MANY) IN OBJECT = V-PUT PRE-PUT>
|
||||||
|
|
||||||
|
<SYNTAX HEAR OBJECT (FIND DARKBIT) = V-LISTEN>
|
||||||
|
|
||||||
|
<SYNTAX HELLO = V-HELLO>
|
||||||
|
<SYNTAX HELLO OBJECT = V-HELLO>
|
||||||
|
<SYNONYM HELLO HI>
|
||||||
|
|
||||||
|
<SYNTAX HELP = V-HELP>
|
||||||
|
<SYNTAX HELP OBJECT = V-SAVE-SOMETHING>
|
||||||
|
<SYNONYM HELP HINT HINTS>
|
||||||
|
|
||||||
|
<SYNTAX HIDE = V-HIDE>
|
||||||
|
<SYNTAX HIDE UNDER OBJECT = V-HIDE>
|
||||||
|
<SYNTAX HIDE BEHIND OBJECT = V-HIDE>
|
||||||
|
|
||||||
|
<SYNTAX HITCHH = V-HITCHHIKE>
|
||||||
|
<SYNONYM HITCHH HITCH>
|
||||||
|
|
||||||
|
<SYNTAX IDIOT = V-IDIOT>
|
||||||
|
<SYNONYM IDIOT>
|
||||||
|
|
||||||
|
<SYNTAX JUMP = V-LEAP>
|
||||||
|
<SYNTAX JUMP OVER OBJECT = V-LEAP>
|
||||||
|
<SYNTAX JUMP ACROSS OBJECT = V-LEAP>
|
||||||
|
<SYNTAX JUMP IN OBJECT = V-THROUGH>
|
||||||
|
<SYNTAX JUMP FROM OBJECT = V-LEAP>
|
||||||
|
<SYNTAX JUMP OFF OBJECT = V-LEAP>
|
||||||
|
<SYNTAX JUMP OUT OBJECT = V-THROUGH>
|
||||||
|
<SYNTAX JUMP THROUGH OBJECT = V-THROUGH>
|
||||||
|
<SYNONYM JUMP LEAP DIVE>
|
||||||
|
|
||||||
|
<SYNTAX KICK OBJECT = V-KICK>
|
||||||
|
|
||||||
|
<SYNTAX KISS OBJECT (FIND ACTORBIT) (ON-GROUND IN-ROOM) = V-KISS>
|
||||||
|
|
||||||
|
<SYNTAX KNEEL = V-KNEEL>
|
||||||
|
<SYNONYM KNEEL CRAWL PEEK>
|
||||||
|
|
||||||
|
<SYNTAX KNOCK AT OBJECT = V-KNOCK>
|
||||||
|
<SYNTAX KNOCK ON OBJECT = V-KNOCK>
|
||||||
|
<SYNTAX KNOCK DOWN OBJECT (FIND ACTORBIT) (ON-GROUND IN-ROOM) = V-KILL>
|
||||||
|
<SYNONYM KNOCK RAP>
|
||||||
|
|
||||||
|
<SYNTAX LEAVE = V-LEAVE>
|
||||||
|
<SYNTAX LEAVE OBJECT = V-LEAVE>
|
||||||
|
|
||||||
|
<SYNTAX LIE ON OBJECT (FIND VEHBIT) = V-LIE-DOWN>
|
||||||
|
<SYNTAX LIE IN OBJECT (FIND VEHBIT) = V-LIE-DOWN>
|
||||||
|
<SYNTAX LIE DOWN OBJECT (FIND RLANDBIT) = V-LIE-DOWN>
|
||||||
|
<SYNTAX LIE BEFORE OBJECT = V-BLOCK>
|
||||||
|
<SYNONYM LIE RECLIN>
|
||||||
|
|
||||||
|
<SYNTAX LIGHT OBJECT (FIND LIGHTBIT) (HELD CARRIED ON-GROUND IN-ROOM)
|
||||||
|
= V-LAMP-ON>
|
||||||
|
|
||||||
|
<SYNTAX LISTEN TO OBJECT (FIND DARKBIT) = V-LISTEN>
|
||||||
|
|
||||||
|
<SYNTAX LOCK OBJECT (ON-GROUND IN-ROOM) = V-LOCK>
|
||||||
|
<SYNTAX LOCK OBJECT (ON-GROUND IN-ROOM) WITH OBJECT (TAKE) = V-LOCK>
|
||||||
|
|
||||||
|
<SYNTAX LOOK = V-LOOK>
|
||||||
|
<SYNTAX LOOK AROUND OBJECT (FIND RLANDBIT) = V-LOOK>
|
||||||
|
<SYNTAX LOOK DOWN OBJECT (FIND RLANDBIT) = V-LOOK-DOWN>
|
||||||
|
<SYNTAX LOOK UP OBJECT (FIND RLANDBIT) = V-LOOK-UP>
|
||||||
|
<SYNTAX LOOK AT OBJECT (HELD CARRIED ON-GROUND IN-ROOM) (FIND DARKBIT)
|
||||||
|
= V-EXAMINE PRE-READ>
|
||||||
|
<SYNTAX LOOK AT OBJECT THROUGH OBJECT = V-EXAMINE-THROUGH PRE-READ>
|
||||||
|
<SYNTAX LOOK THROUGH OBJECT = V-LOOK-INSIDE>
|
||||||
|
<SYNTAX LOOK OUT OBJECT = V-LOOK-INSIDE>
|
||||||
|
<SYNTAX LOOK UNDER OBJECT = V-LOOK-UNDER PRE-READ>
|
||||||
|
<SYNTAX LOOK BEHIND OBJECT = V-LOOK-BEHIND PRE-READ>
|
||||||
|
<SYNTAX LOOK IN OBJECT (HELD CARRIED ON-GROUND IN-ROOM) = V-LOOK-INSIDE>
|
||||||
|
<SYNTAX LOOK ON OBJECT = V-EXAMINE PRE-READ>
|
||||||
|
<SYNTAX LOOK FOR OBJECT = V-FIND>
|
||||||
|
<SYNTAX LOOK OBJECT = V-CHASTISE>
|
||||||
|
<SYNONYM LOOK L STARE GAZE>
|
||||||
|
|
||||||
|
<SYNTAX LOWER OBJECT = V-LOWER>
|
||||||
|
|
||||||
|
<SYNTAX MAKE OBJECT = V-MAKE>
|
||||||
|
|
||||||
|
<SYNTAX MOVE OBJECT (ON-GROUND IN-ROOM) = V-MOVE>
|
||||||
|
<SYNTAX MOVE OBJECT OBJECT = V-FLIPSWITCH>
|
||||||
|
<SYNTAX MOVE TOGETHER OBJECT = V-PULL-TOGETHER> ;"pull myself together"
|
||||||
|
<SYNONYM MOVE PULL>
|
||||||
|
|
||||||
|
<SYNTAX MY OBJECT OBJECT = V-MY-NAME>
|
||||||
|
|
||||||
|
<SYNTAX NO = V-NO>
|
||||||
|
|
||||||
|
<SYNTAX OPEN OBJECT (FIND DOORBIT) (HELD CARRIED ON-GROUND IN-ROOM) = V-OPEN>
|
||||||
|
<SYNTAX OPEN UP OBJECT (FIND DOORBIT) (HELD CARRIED ON-GROUND IN-ROOM)
|
||||||
|
= V-OPEN>
|
||||||
|
<SYNTAX OPEN OBJECT (FIND DOORBIT) (HELD CARRIED ON-GROUND IN-ROOM)
|
||||||
|
WITH OBJECT (ON-GROUND IN-ROOM HELD CARRIED HAVE) = V-OPEN>
|
||||||
|
<SYNONYM OPEN PART DRAW>
|
||||||
|
|
||||||
|
<SYNTAX PANIC = V-PANIC>
|
||||||
|
|
||||||
|
<SYNTAX PAY FOR OBJECT = V-BUY>
|
||||||
|
|
||||||
|
<SYNTAX PHONE OBJECT = V-CALL>
|
||||||
|
<SYNTAX PHONE OBJECT WITH OBJECT = V-CALL-WITH>
|
||||||
|
<SYNTAX PHONE OBJECT ON OBJECT = V-CALL-WITH>
|
||||||
|
<SYNONYM PHONE CALL>
|
||||||
|
|
||||||
|
<SYNTAX PICK OBJECT = V-PICK>
|
||||||
|
<SYNTAX PICK OBJECT WITH OBJECT = V-PICK>
|
||||||
|
<SYNTAX PICK UP OBJECT (FIND TAKEBIT) (ON-GROUND MANY) = V-PICK-UP PRE-TAKE>
|
||||||
|
|
||||||
|
<SYNTAX PLANT OBJECT (HELD MANY) IN OBJECT = V-PLANT>
|
||||||
|
<SYNONYM PLANT BURY>
|
||||||
|
|
||||||
|
<SYNTAX PLUG OBJECT IN OBJECT = V-PLUG>
|
||||||
|
<SYNTAX PLUG OBJECT TO OBJECT = V-PLUG>
|
||||||
|
<SYNTAX PLUG IN OBJECT IN OBJECT = V-PLUG>
|
||||||
|
<SYNTAX PLUG IN OBJECT TO OBJECT = V-PLUG>
|
||||||
|
|
||||||
|
<SYNTAX POINT AT OBJECT = V-POINT>
|
||||||
|
<SYNTAX POINT TO OBJECT = V-POINT>
|
||||||
|
<SYNTAX POINT OBJECT AT OBJECT = V-STEER>
|
||||||
|
<SYNTAX POINT OBJECT TO OBJECT = V-STEER>
|
||||||
|
<SYNONYM POINT STEER>
|
||||||
|
|
||||||
|
<SYNTAX POUR OBJECT (HELD CARRIED) = V-POUR>
|
||||||
|
<SYNTAX POUR OBJECT (HELD CARRIED) IN OBJECT = V-POUR>
|
||||||
|
<SYNTAX POUR OBJECT (HELD CARRIED) ON OBJECT = V-POUR>
|
||||||
|
<SYNTAX POUR OBJECT (HELD CARRIED) OVER OBJECT = V-POUR>
|
||||||
|
<SYNONYM POUR SPILL SPRINK>
|
||||||
|
|
||||||
|
<SYNTAX PROTEST = V-PROTEST>
|
||||||
|
<SYNONYM PROTEST ARGUE>
|
||||||
|
|
||||||
|
<SYNTAX PUSH OBJECT = V-PUSH>
|
||||||
|
<SYNTAX PUSH OBJECT OBJECT = V-FLIPSWITCH>
|
||||||
|
<SYNTAX PUSH ON OBJECT (IN-ROOM ON-GROUND) = V-PUSH>
|
||||||
|
<SYNTAX PUSH OBJECT UNDER OBJECT = V-PUT-UNDER>
|
||||||
|
<SYNONYM PUSH PRESS>
|
||||||
|
|
||||||
|
<SYNTAX PUT OBJECT (HELD MANY) IN OBJECT = V-PUT PRE-PUT>
|
||||||
|
<SYNTAX PUT OBJECT (HELD MANY) AT OBJECT = V-PUT-IN-FRONT PRE-GIVE>
|
||||||
|
<SYNTAX PUT OBJECT (HELD MANY) BEFORE OBJECT = V-PUT-IN-FRONT PRE-GIVE>
|
||||||
|
<SYNTAX PUT OBJECT (HELD MANY) DOWN OBJECT = V-PUT-ON PRE-PUT>
|
||||||
|
<SYNTAX PUT OBJECT (HELD MANY) ON OBJECT = V-PUT-ON PRE-PUT>
|
||||||
|
<SYNTAX PUT OBJECT (HELD MANY) AROUND OBJECT = V-PUT-ON PRE-PUT>
|
||||||
|
<SYNTAX PUT OBJECT (HELD MANY) OVER OBJECT = V-PUT-ON PRE-PUT>
|
||||||
|
<SYNTAX PUT OBJECT (HELD MANY) ACROSS OBJECT = V-PUT-ON PRE-PUT>
|
||||||
|
<SYNTAX PUT DOWN OBJECT (HELD MANY HAVE) = V-DROP PRE-DROP>
|
||||||
|
<SYNTAX PUT OBJECT UNDER OBJECT = V-PUT-UNDER>
|
||||||
|
<SYNTAX PUT ON OBJECT (FIND WEARBIT) (HAVE) = V-WEAR>
|
||||||
|
<SYNTAX PUT OBJECT BEHIND OBJECT = V-PUT-BEHIND>
|
||||||
|
<SYNONYM PUT STUFF INSERT PLACE LAY>
|
||||||
|
|
||||||
|
<SYNTAX RAISE OBJECT = V-RAISE>
|
||||||
|
<SYNTAX RAISE UP OBJECT = V-RAISE>
|
||||||
|
<SYNONYM RAISE LIFT>
|
||||||
|
|
||||||
|
<SYNTAX RAPE OBJECT (FIND ACTORBIT) = V-RAPE>
|
||||||
|
|
||||||
|
;<SYNTAX REACH IN OBJECT (ON-GROUND IN-ROOM) = V-REACH-IN>
|
||||||
|
|
||||||
|
<SYNTAX READ OBJECT (FIND READBIT) (HELD CARRIED ON-GROUND IN-ROOM TAKE)
|
||||||
|
= V-READ PRE-READ>
|
||||||
|
<SYNTAX READ OBJECT (FIND READBIT) (HELD CARRIED ON-GROUND IN-ROOM TAKE)
|
||||||
|
THROUGH OBJECT = V-READ PRE-READ>
|
||||||
|
<SYNTAX READ OBJECT (FIND READBIT) (HELD CARRIED ON-GROUND IN-ROOM TAKE)
|
||||||
|
WITH OBJECT = V-READ PRE-READ>
|
||||||
|
<SYNONYM READ SKIM>
|
||||||
|
|
||||||
|
<SYNTAX REFUSE OBJECT (IN-ROOM) = V-REFUSE>
|
||||||
|
|
||||||
|
<SYNTAX RELAX = V-RELAX>
|
||||||
|
|
||||||
|
<SYNTAX REMOVE OBJECT (FIND WORNBIT) = V-REMOVE>
|
||||||
|
<SYNTAX REMOVE OBJECT (FIND TAKEBIT) (IN-ROOM CARRIED MANY)
|
||||||
|
FROM OBJECT = V-TAKE PRE-TAKE>
|
||||||
|
<SYNONYM REMOVE DOFF SHED>
|
||||||
|
|
||||||
|
<SYNTAX REPAIR OBJECT = V-REPAIR>
|
||||||
|
<SYNONYM REPAIR FIX UNJAM>
|
||||||
|
|
||||||
|
<SYNTAX REPLACE OBJECT = V-REPLACE>
|
||||||
|
|
||||||
|
<SYNTAX SAVE OBJECT = V-SAVE-SOMETHING>
|
||||||
|
|
||||||
|
<SYNTAX SAY TO OBJECT (FIND ACTORBIT) (IN-ROOM) = V-TELL>
|
||||||
|
<SYNTAX SAY OBJECT = V-SAY-NAME>
|
||||||
|
<SYNTAX SAY = V-SAY>
|
||||||
|
<SYNONYM SAY TALK SPEAK>
|
||||||
|
|
||||||
|
<SYNTAX SEARCH OBJECT = V-SEARCH>
|
||||||
|
<SYNTAX SEARCH IN OBJECT = V-SEARCH>
|
||||||
|
<SYNTAX SEARCH FOR OBJECT = V-FIND>
|
||||||
|
<SYNONYM SEARCH RUMMAG FRISK>
|
||||||
|
|
||||||
|
<SYNTAX SHAKE OBJECT = V-SHAKE>
|
||||||
|
<SYNTAX SHAKE OBJECT WITH OBJECT = V-SHAKE-WITH>
|
||||||
|
|
||||||
|
<SYNTAX SHOOT = V-SHOOT>
|
||||||
|
<SYNTAX SHOOT OBJECT = V-SHOOT>
|
||||||
|
<SYNTAX SHOOT OBJECT WITH OBJECT (HAVE) = V-SHOOT>
|
||||||
|
<SYNTAX SHOOT OBJECT (HAVE) AT OBJECT = V-SSHOOT>
|
||||||
|
<SYNONYM SHOOT FIRE BLAST>
|
||||||
|
|
||||||
|
<SYNTAX SHOW OBJECT (HELD MANY HAVE) TO OBJECT (FIND ACTORBIT) = V-SHOW>
|
||||||
|
<SYNTAX SHOW OBJECT (FIND ACTORBIT) OBJECT (HELD MANY HAVE) = V-SSHOW>
|
||||||
|
|
||||||
|
<SYNTAX SIT ON OBJECT (FIND VEHBIT) (ON-GROUND IN-ROOM) = V-CLIMB-ON>
|
||||||
|
<SYNTAX SIT DOWN OBJECT (FIND RLANDBIT) (ON-GROUND IN-ROOM) = V-SIT>
|
||||||
|
<SYNTAX SIT IN OBJECT (FIND VEHBIT) (ON-GROUND IN-ROOM) = V-BOARD PRE-BOARD>
|
||||||
|
<SYNONYM SIT REST SQUAT>
|
||||||
|
|
||||||
|
<SYNTAX SKIP = V-SKIP>
|
||||||
|
<SYNONYM SKIP HOP>
|
||||||
|
|
||||||
|
<SYNTAX SLEEP = V-SLEEP>
|
||||||
|
<SYNTAX SLEEP IN OBJECT (IN-ROOM ON-GROUND) = V-BOARD>
|
||||||
|
<SYNTAX SLEEP ON OBJECT (IN-ROOM ON-GROUND) = V-BOARD>
|
||||||
|
|
||||||
|
<SYNTAX SLIDE OBJECT = V-PUSH>
|
||||||
|
<SYNTAX SLIDE OBJECT UNDER OBJECT = V-PUT-UNDER>
|
||||||
|
|
||||||
|
<SYNTAX SMELL OBJECT (FIND DARKBIT) = V-SMELL>
|
||||||
|
<SYNONYM SMELL SNIFF WHIFF>
|
||||||
|
|
||||||
|
<SYNTAX SMILE = V-SMILE>
|
||||||
|
<SYNTAX SMILE AT OBJECT = V-SMILE>
|
||||||
|
|
||||||
|
<SYNTAX SPIN OBJECT = V-SPIN>
|
||||||
|
<SYNONYM SPIN WHIRL ROTATE>
|
||||||
|
|
||||||
|
<SYNTAX STAND = V-STAND>
|
||||||
|
<SYNTAX STAND UP OBJECT (FIND RLANDBIT) = V-STAND>
|
||||||
|
<SYNTAX STAND ON OBJECT = V-STAND-ON>
|
||||||
|
<SYNTAX STAND BEFORE OBJECT = V-STAND-BEFORE>
|
||||||
|
<SYNTAX STAND IN OBJECT = V-STAND-ON>
|
||||||
|
<SYNONYM STAND RISE>
|
||||||
|
|
||||||
|
<SYNTAX START OBJECT = V-LAMP-ON>
|
||||||
|
<SYNONYM START ACTIVA>
|
||||||
|
|
||||||
|
<SYNTAX SWITCH OBJECT = V-TURN>
|
||||||
|
<SYNTAX SWITCH OBJECT OBJECT = V-FLIPSWITCH>
|
||||||
|
<SYNTAX SWITCH AROUND OBJECT (FIND RLANDBIT) = V-TURN>
|
||||||
|
<SYNTAX SWITCH OBJECT TO OBJECT = V-TURN>
|
||||||
|
<SYNTAX SWITCH OBJECT WITH OBJECT (HAVE) = V-TURN>
|
||||||
|
<SYNTAX SWITCH ON OBJECT (FIND LIGHTBIT) = V-LAMP-ON>
|
||||||
|
<SYNTAX SWITCH ON OBJECT OBJECT = V-FLIPSWITCH>
|
||||||
|
<SYNTAX SWITCH OFF OBJECT (FIND LIGHTBIT) (TAKE) = V-LAMP-OFF>
|
||||||
|
<SYNTAX SWITCH OFF OBJECT OBJECT = V-FLIPSWITCH>
|
||||||
|
<SYNONYM SWITCH TURN FLIP FLICK TOGGLE>
|
||||||
|
|
||||||
|
<SYNTAX TAKE OBJECT (FIND TAKEBIT) (ON-GROUND IN-ROOM MANY) = V-TAKE PRE-TAKE>
|
||||||
|
<SYNTAX TAKE IN OBJECT (FIND VEHBIT) (ON-GROUND IN-ROOM) = V-BOARD PRE-BOARD>
|
||||||
|
<SYNTAX TAKE OUT OBJECT (FIND VEHBIT) (ON-GROUND) = V-DISEMBARK>
|
||||||
|
<SYNTAX TAKE ON OBJECT (FIND VEHBIT) (ON-GROUND IN-ROOM) = V-CLIMB-ON>
|
||||||
|
<SYNTAX TAKE UP OBJECT (FIND RLANDBIT) = V-STAND>
|
||||||
|
<SYNTAX TAKE DRESSE OBJECT (FIND RLANDBIT) = V-GET-DRESSED>
|
||||||
|
<SYNTAX TAKE UNDRES OBJECT (FIND RLANDBIT) = V-GET-UNDRESSED>
|
||||||
|
<SYNTAX TAKE DRUNK OBJECT (FIND RLANDBIT) = V-GET-DRUNK>
|
||||||
|
<SYNTAX TAKE OBJECT (FIND TAKEBIT) (CARRIED IN-ROOM MANY)
|
||||||
|
OUT OBJECT = V-TAKE PRE-TAKE>
|
||||||
|
<SYNTAX TAKE OBJECT (FIND TAKEBIT) (CARRIED IN-ROOM MANY)
|
||||||
|
OFF OBJECT = V-TAKE PRE-TAKE>
|
||||||
|
<SYNTAX TAKE OBJECT (FIND TAKEBIT) (IN-ROOM CARRIED MANY)
|
||||||
|
FROM OBJECT = V-TAKE PRE-TAKE>
|
||||||
|
<SYNTAX TAKE OBJECT (FIND TAKEBIT) (IN-ROOM CARRIED MANY)
|
||||||
|
IN OBJECT = V-TAKE PRE-TAKE>
|
||||||
|
<SYNTAX TAKE OFF OBJECT (FIND WORNBIT) (HAVE) = V-TAKE-OFF>
|
||||||
|
<SYNONYM TAKE GRAB CATCH GET HOLD CARRY>
|
||||||
|
|
||||||
|
<SYNTAX TASTE OBJECT (FIND DARKBIT) = V-TASTE>
|
||||||
|
<SYNONYM TASTE LICK>
|
||||||
|
|
||||||
|
<SYNTAX TELL OBJECT (FIND ACTORBIT) (IN-ROOM) = V-TELL>
|
||||||
|
<SYNTAX TELL OBJECT (FIND ACTORBIT) ABOUT OBJECT = V-TELL-ABOUT>
|
||||||
|
<SYNTAX TELL OBJECT OBJECT = V-TELL-TIME>
|
||||||
|
<SYNTAX TELL OBJECT TO OBJECT = V-TELL-NAME>
|
||||||
|
|
||||||
|
<SYNTAX THANK OBJECT = V-THANK>
|
||||||
|
<SYNONYM THANK THANKS>
|
||||||
|
|
||||||
|
<SYNTAX THROW OBJECT (HELD CARRIED) = V-THROW PRE-THROW>
|
||||||
|
<SYNTAX THROW OBJECT OBJECT = V-FLIPSWITCH>
|
||||||
|
<SYNTAX THROW OBJECT (HELD CARRIED) UP OBJECT (FIND RLANDBIT)
|
||||||
|
= V-THROW PRE-THROW>
|
||||||
|
<SYNTAX THROW OBJECT (HELD CARRIED) AT OBJECT (ON-GROUND IN-ROOM)
|
||||||
|
= V-THROW PRE-THROW>
|
||||||
|
<SYNTAX THROW OBJECT (HELD CARRIED) TO OBJECT (ON-GROUND IN-ROOM)
|
||||||
|
= V-THROW PRE-THROW>
|
||||||
|
<SYNTAX THROW OBJECT (HELD CARRIED) OFF OBJECT = V-THROW-OFF>
|
||||||
|
<SYNTAX THROW OBJECT (HELD CARRIED) OVER OBJECT = V-THROW-OFF>
|
||||||
|
<SYNTAX THROW OBJECT (HELD CARRIED) THROUGH OBJECT (ON-GROUND IN-ROOM)
|
||||||
|
= V-THROW PRE-THROW>
|
||||||
|
<SYNTAX THROW OBJECT (HELD CARRIED) IN OBJECT = V-THROW PRE-THROW>
|
||||||
|
<SYNTAX THROW IN OBJECT = V-THROW-IN-TOWEL>
|
||||||
|
<SYNONYM THROW HURL TOSS>
|
||||||
|
|
||||||
|
<SYNTAX TIE OBJECT = V-TIE>
|
||||||
|
<SYNTAX TIE TOGETHER OBJECT = V-TIE-TOGETHER>
|
||||||
|
<SYNTAX TIE OBJECT (HELD MANY) AROUND OBJECT = V-PUT-ON PRE-PUT>
|
||||||
|
<SYNTAX TIE OBJECT TO OBJECT = V-PLUG>
|
||||||
|
<SYNONYM TIE FASTEN SECURE ATTACH>
|
||||||
|
|
||||||
|
<SYNTAX TOUCH OBJECT (FIND DARKBIT) = V-RUB>
|
||||||
|
<SYNTAX TOUCH OBJECT WITH OBJECT = V-RUB>
|
||||||
|
<SYNONYM TOUCH FEEL PAT PET RUB>
|
||||||
|
|
||||||
|
<SYNTAX TYPE = V-TYPE>
|
||||||
|
<SYNTAX TYPE ON OBJECT = V-TYPE-ON>
|
||||||
|
|
||||||
|
<SYNTAX UNLOCK OBJECT = V-UNLOCK>
|
||||||
|
<SYNTAX UNLOCK OBJECT WITH OBJECT (HAVE) = V-UNLOCK>
|
||||||
|
|
||||||
|
<SYNTAX UNPLUG OBJECT = V-UNPLUG>
|
||||||
|
<SYNONYM UNPLUG DISCON>
|
||||||
|
|
||||||
|
<SYNTAX UNTIE OBJECT (ON-GROUND IN-ROOM HELD CARRIED) = V-UNTIE>
|
||||||
|
<SYNONYM UNTIE FREE UNFAST UNATTA UNKNOT>
|
||||||
|
|
||||||
|
<SYNTAX WAIT = V-WAIT>
|
||||||
|
<SYNTAX WAIT FOR OBJECT = V-WAIT-FOR>
|
||||||
|
<SYNONYM WAIT Z STAY>
|
||||||
|
|
||||||
|
<SYNTAX WAKE OBJECT (FIND RLANDBIT) = V-ALARM>
|
||||||
|
<SYNTAX WAKE UP OBJECT (FIND RLANDBIT) = V-ALARM>
|
||||||
|
<SYNONYM WAKE AWAKE ROUSE>
|
||||||
|
|
||||||
|
<SYNTAX WALK = V-WALK-AROUND>
|
||||||
|
<SYNTAX WALK OBJECT = V-WALK>
|
||||||
|
<SYNTAX WALK IN OBJECT = V-THROUGH>
|
||||||
|
<SYNTAX WALK OUT OBJECT = V-THROUGH>
|
||||||
|
<SYNTAX WALK ON OBJECT = V-WALK-AROUND>
|
||||||
|
<SYNTAX WALK OVER OBJECT = V-LEAP>
|
||||||
|
<SYNTAX WALK THROUGH OBJECT = V-THROUGH>
|
||||||
|
<SYNTAX WALK AROUND OBJECT = V-WALK-AROUND>
|
||||||
|
<SYNTAX WALK BEHIND OBJECT = V-WALK-AROUND>
|
||||||
|
<SYNTAX WALK UP OBJECT (ON-GROUND IN-ROOM) = V-CLIMB-UP>
|
||||||
|
<SYNTAX WALK DOWN OBJECT (ON-GROUND IN-ROOM) = V-CLIMB-DOWN>
|
||||||
|
<SYNTAX WALK TO OBJECT = V-WALK-TO>
|
||||||
|
<SYNTAX WALK AWAY OBJECT (FIND RLANDBIT) = V-LEAVE>
|
||||||
|
<SYNONYM WALK GO RUN PROCEE STEP>
|
||||||
|
|
||||||
|
<SYNTAX WASH OBJECT = V-CLEAN>
|
||||||
|
<SYNTAX WASH UP OBJECT (FIND RLANDBIT) = V-CLEAN>
|
||||||
|
<SYNONYM WASH CLEAN TIDY>
|
||||||
|
|
||||||
|
<SYNTAX WATER OBJECT WITH OBJECT (HAVE) = V-WATER>
|
||||||
|
|
||||||
|
<SYNTAX WAVE OBJECT (HELD CARRIED) = V-WAVE>
|
||||||
|
<SYNTAX WAVE = V-WAVE-AT>
|
||||||
|
<SYNTAX WAVE AT OBJECT = V-WAVE-AT>
|
||||||
|
<SYNTAX WAVE TO OBJECT = V-WAVE-AT>
|
||||||
|
|
||||||
|
<SYNTAX WEAR OBJECT (FIND WEARBIT) (HAVE) = V-WEAR>
|
||||||
|
<SYNONYM WEAR DON>
|
||||||
|
|
||||||
|
<SYNTAX WHAT OBJECT = V-WHAT>
|
||||||
|
<SYNTAX WHAT ABOUT OBJECT = V-WHAT-ABOUT>
|
||||||
|
<SYNTAX WHAT OBJECT OBJECT = V-WHAT-TIME>
|
||||||
|
<SYNONYM WHAT WHATS WHAT\'>
|
||||||
|
|
||||||
|
<SYNTAX WHERE OBJECT = V-WHERE>
|
||||||
|
<SYNONYM WHERE WHERES>
|
||||||
|
|
||||||
|
<SYNTAX WHO OBJECT = V-WHO>
|
||||||
|
<SYNONYM WHO WHOS>
|
||||||
|
|
||||||
|
<SYNTAX WHY = V-WHY>
|
||||||
|
|
||||||
|
<SYNTAX DRAPE OBJECT IN OBJECT (HELD MANY) = V-SPUT-ON>
|
||||||
|
<SYNTAX DRAPE OBJECT (HELD MANY) ON OBJECT = V-PUT-ON PRE-PUT>
|
||||||
|
<SYNTAX DRAPE OBJECT (HELD MANY) AROUND OBJECT = V-PUT-ON PRE-PUT>
|
||||||
|
<SYNTAX DRAPE OBJECT (HELD MANY) OVER OBJECT = V-PUT-ON PRE-PUT>
|
||||||
|
<SYNONYM DRAPE WRAP>
|
||||||
|
|
||||||
|
<SYNTAX YELL = V-YELL>
|
||||||
|
<SYNTAX YELL AT OBJECT = V-YELL>
|
||||||
|
<SYNTAX YELL TO OBJECT = V-YELL>
|
||||||
|
<SYNONYM YELL SCREAM SHOUT HOWL>
|
||||||
|
|
||||||
|
<SYNTAX YES = V-YES>
|
||||||
|
<SYNONYM YES Y OK OKAY SURE>
|
||||||
@@ -0,0 +1,886 @@
|
|||||||
|
"VOGON for
|
||||||
|
THE HITCHHIKER'S GUIDE TO THE GALAXY
|
||||||
|
(c) Copyright 1984 Infocom, Inc. All Rights Reserved."
|
||||||
|
|
||||||
|
<OBJECT MINERAL-WATER
|
||||||
|
(IN SATCHEL)
|
||||||
|
(DESC "Santraginean Mineral Water")
|
||||||
|
(LDESC "There is a bottle of mineral water here.")
|
||||||
|
(SYNONYM BOTTLE WATER)
|
||||||
|
(ADJECTIVE SANTRA MINERA)
|
||||||
|
(FLAGS NARTICLEBIT DRINKBIT TAKEBIT)
|
||||||
|
(GENERIC MINERAL-WATER)
|
||||||
|
(ACTION MINERAL-WATER-F)>
|
||||||
|
|
||||||
|
<ROUTINE MINERAL-WATER-F ()
|
||||||
|
<COND (<VERB? DRINK DRINK-FROM>
|
||||||
|
<TELL
|
||||||
|
"Bad idea. Even Santraginus Five seawater is illegal on most planets. (You can
|
||||||
|
imagine what kind of beach communities they have.)" CR>)
|
||||||
|
(<VERB? LOOK-INSIDE>
|
||||||
|
<PERFORM ,V?EXAMINE ,PRSO>
|
||||||
|
<RTRUE>)
|
||||||
|
(<VERB? OPEN CLOSE>
|
||||||
|
<TELL
|
||||||
|
"This is one of those clever new always-open always-closed bottles." CR>)
|
||||||
|
(<VERB? POUR THROW>
|
||||||
|
<LIQUID-SPILL>)>>
|
||||||
|
|
||||||
|
<ROOM HOLD
|
||||||
|
(IN ROOMS)
|
||||||
|
(SYNONYM PROTEI)
|
||||||
|
(DESC "Vogon Hold")
|
||||||
|
(WEST "The door to the corridor is locked (from the outside).")
|
||||||
|
(EAST TO AIRLOCK IF VOGON-INNER-DOOR IS OPEN) ;"shouldn't happen"
|
||||||
|
(FLAGS RLANDBIT ONBIT)
|
||||||
|
(GLOBAL VOGON-INNER-DOOR AIRLOCK-OBJECT FLEET HOLD-FURNISHINGS)
|
||||||
|
(PSEUDO "WEAPON" WEAPON-PSEUDO)
|
||||||
|
(ACTION HOLD-F)>
|
||||||
|
|
||||||
|
<ROUTINE HOLD-F (RARG)
|
||||||
|
<COND (<AND <EQUAL? .RARG ,M-END>
|
||||||
|
<NOT <FSET? ,HOLD ,NDESCBIT>>>
|
||||||
|
<FSET ,HOLD ,NDESCBIT>
|
||||||
|
<FSET ,PEANUTS ,TAKEBIT>
|
||||||
|
<FCLEAR ,PEANUTS ,NDESCBIT>
|
||||||
|
<FCLEAR ,PEANUTS ,TRYTAKEBIT>
|
||||||
|
<FCLEAR ,TOWEL ,TRYTAKEBIT>
|
||||||
|
<MOVE ,PEANUTS ,PROTAGONIST>
|
||||||
|
<MOVE ,FORD ,HERE>
|
||||||
|
<MOVE ,MINERAL-WATER ,FORD>
|
||||||
|
<SETG GROGGY T>
|
||||||
|
<ENABLE <QUEUE I-GROGGY 3>>
|
||||||
|
<ENABLE <QUEUE I-FORD 6>>
|
||||||
|
<ENABLE <QUEUE I-ANNOUNCEMENT 18>>
|
||||||
|
<ENABLE <QUEUE I-GUARDS 36>>
|
||||||
|
<SETG LINE-NUMBER <RANDOM 6>>
|
||||||
|
<SETG WORD-NUMBER <RANDOM 3>>
|
||||||
|
<SETG SCORE <+ ,SCORE 8>>
|
||||||
|
<SETG P-IT-OBJECT ,PEANUTS>
|
||||||
|
<CRLF>
|
||||||
|
<TELL
|
||||||
|
"Ford removes the bottle of " D ,MINERAL-WATER " which he's been waving under
|
||||||
|
your nose. He tells you that you are aboard a Vogon spaceship, and gives you
|
||||||
|
some peanuts." CR>)
|
||||||
|
(<AND <EQUAL? .RARG ,M-END>
|
||||||
|
<FSET? ,HOLD ,REVISITBIT>>
|
||||||
|
<SETG DREAMING T>
|
||||||
|
<JIGS-UP
|
||||||
|
"A pair of Vogon guards stand nearby, waving acrid-smelling stun guns an inch
|
||||||
|
away from your face. Simultaneously, they fire.">
|
||||||
|
<RTRUE>)
|
||||||
|
(<EQUAL? .RARG ,M-LOOK>
|
||||||
|
<TELL
|
||||||
|
"This is a squalid room filled with grubby mattresses, unwashed cups, and
|
||||||
|
unidentifiable bits of smelly alien underwear. A door lies to port, and an
|
||||||
|
airlock lies to starboard.">
|
||||||
|
<COND (,GOWN-HUNG
|
||||||
|
<TELL " Your gown is hanging from a hook">
|
||||||
|
<COND (<NOT <FSET? ,TOWEL ,SURFACEBIT>>
|
||||||
|
<TELL ".">)>)>
|
||||||
|
<COND (<FSET? ,TOWEL ,SURFACEBIT>
|
||||||
|
<COND (,GOWN-HUNG
|
||||||
|
<TELL " and a ">)
|
||||||
|
(T
|
||||||
|
<TELL " A ">)>
|
||||||
|
<TELL "towel is draped over a drain on the floor.">)>
|
||||||
|
<COND (<AND ,PANEL-BLOCKER
|
||||||
|
<NOT <EQUAL? ,PANEL-BLOCKER ,SATCHEL>>>
|
||||||
|
<TELL
|
||||||
|
" Resting in front of a " D ,ROBOT-PANEL " at the base of one wall is">
|
||||||
|
<ARTICLE ,PANEL-BLOCKER>
|
||||||
|
<TELL ".">)>
|
||||||
|
<CRLF>)>>
|
||||||
|
|
||||||
|
<OBJECT HOLD-FURNISHINGS
|
||||||
|
(IN LOCAL-GLOBALS)
|
||||||
|
(DESC "it")
|
||||||
|
(SYNONYM MATTRE CUPS CUP UNDERW)
|
||||||
|
(ADJECTIVE GRUBBY UNWASH UNIDEN SMELLY ALIEN)
|
||||||
|
(FLAGS NDESCBIT NARTICLEBIT)
|
||||||
|
(ACTION UNIMPORTANT-THING-F)>
|
||||||
|
|
||||||
|
<ROUTINE I-GROGGY ()
|
||||||
|
<ENABLE <QUEUE I-GROGGY -1>>
|
||||||
|
<SETG GROGGY-COUNTER <+ ,GROGGY-COUNTER 1>>
|
||||||
|
<COND (<NOT ,GROGGY>
|
||||||
|
<DISABLE <INT I-GROGGY>>
|
||||||
|
<SETG GROGGY-COUNTER 0>
|
||||||
|
<RFALSE>)>
|
||||||
|
<CRLF>
|
||||||
|
<COND (<EQUAL? ,GROGGY-COUNTER 1 2>
|
||||||
|
<TELL "You begin to feel ">
|
||||||
|
<COND (<EQUAL? ,GROGGY-COUNTER 2>
|
||||||
|
<TELL "in">)>
|
||||||
|
<TELL "distinctly groggy." CR>)
|
||||||
|
(<EQUAL? ,GROGGY-COUNTER 3>
|
||||||
|
<TELL "You begin to feel very indistinct." CR>)
|
||||||
|
(T
|
||||||
|
<TELL
|
||||||
|
"Your serious allergic reaction to protein loss from" ,BEAM "s becomes a cause
|
||||||
|
celebre amongst various holistic pressure groups in the Galaxy and leads to a
|
||||||
|
total ban on dematerialisation. Within fifty years, space travel is replaced by
|
||||||
|
a keen interest in old furniture restoration and market gardening. In this new,
|
||||||
|
quieter Galaxy, the art of telepathy flourishes as never before, creating a new
|
||||||
|
universal harmony which brings all life together, converts all matter into
|
||||||
|
thought and brings about the rebirth of the entire Universe on a higher and
|
||||||
|
better plane of existence.|
|
||||||
|
|
|
||||||
|
However, none of this affects you, because you are dead." CR>
|
||||||
|
<FINISH>)>>
|
||||||
|
|
||||||
|
<GLOBAL GROGGY-COUNTER 0>
|
||||||
|
|
||||||
|
<GLOBAL GOWN-HUNG <>>
|
||||||
|
|
||||||
|
<GLOBAL PANEL-BLOCKER <>>
|
||||||
|
|
||||||
|
<GLOBAL ITEM-ON-SATCHEL <>>
|
||||||
|
|
||||||
|
<GLOBAL FISH-COUNTER 5>
|
||||||
|
|
||||||
|
<OBJECT DISPENSER
|
||||||
|
(IN HOLD)
|
||||||
|
(DESC "babel fish dispenser")
|
||||||
|
(LDESC "Along one wall is a tall dispensing machine.")
|
||||||
|
(SYNONYM DISPEN MACHIN SLOT)
|
||||||
|
(ADJECTIVE DISPEN BABEL FISH TALL VENDIN)
|
||||||
|
(ACTION DISPENSER-F)>
|
||||||
|
|
||||||
|
<ROUTINE DISPENSER-F ()
|
||||||
|
<COND (<VERB? EXAMINE>
|
||||||
|
<TELL
|
||||||
|
"The dispenser is tall, has a button at around eye-level, and says \"Babel
|
||||||
|
Fish\" in large letters. Anything dispensed would probably come out the slot
|
||||||
|
at around knee-level.">
|
||||||
|
<FINE-PRODUCT>
|
||||||
|
<CRLF>)
|
||||||
|
(<AND <VERB? PUT-IN-FRONT>
|
||||||
|
<PRSO? ,HEAD ,EARS>>
|
||||||
|
<SETG LYING-DOWN T>
|
||||||
|
<TELL
|
||||||
|
"You are now lying down with your ear near the " D ,DISPENSER " slot." CR>)
|
||||||
|
(<AND <VERB? LIE-DOWN>
|
||||||
|
,IN-FRONT-FLAG>
|
||||||
|
<PERFORM ,V?PUT-IN-FRONT ,HEAD ,DISPENSER>
|
||||||
|
<RTRUE>)>>
|
||||||
|
|
||||||
|
<OBJECT DISPENSER-BUTTON
|
||||||
|
(IN HOLD)
|
||||||
|
(DESC "dispenser button")
|
||||||
|
(SYNONYM BUTTON)
|
||||||
|
(ADJECTIVE DISPEN SINGLE BABEL FISH)
|
||||||
|
(FLAGS NDESCBIT)
|
||||||
|
(ACTION DISPENSER-BUTTON-F)>
|
||||||
|
|
||||||
|
<ROUTINE DISPENSER-BUTTON-F ()
|
||||||
|
<COND (<VERB? PUSH>
|
||||||
|
<COND (,LYING-DOWN
|
||||||
|
<TELL "You can't reach it from down here." CR>
|
||||||
|
<RTRUE>)
|
||||||
|
(<EQUAL? ,FISH-COUNTER 0>
|
||||||
|
<TELL "Click." CR>
|
||||||
|
<RTRUE>)>
|
||||||
|
<SETG FISH-COUNTER <- ,FISH-COUNTER 1>>
|
||||||
|
<TELL
|
||||||
|
"A single " D ,BABEL-FISH " shoots out of the slot. It sails across the
|
||||||
|
room and ">
|
||||||
|
<COND (<NOT ,GOWN-HUNG>
|
||||||
|
<TELL
|
||||||
|
"through a " D ,FISH-HOLE " in the wall, just under a " D ,HOOK "." CR>)
|
||||||
|
(T
|
||||||
|
<TELL "hits the dressing gown. The fish slides down the ">
|
||||||
|
<COND (,SLEEVE-TIED
|
||||||
|
<TELL "inside (nice try, though)">)
|
||||||
|
(T
|
||||||
|
<TELL "sleeve">)>
|
||||||
|
<TELL " of the gown and falls to the floor, ">
|
||||||
|
<COND (<NOT <FSET? ,TOWEL ,SURFACEBIT>>
|
||||||
|
<TELL
|
||||||
|
"vanishing through the grating of a hitherto unnoticed drain." CR>)
|
||||||
|
(T
|
||||||
|
<TELL
|
||||||
|
"landing on the towel. A split-second later, a tiny cleaning robot whizzes
|
||||||
|
across the floor, grabs the fish, and continues its breakneck pace toward
|
||||||
|
a " D ,ROBOT-PANEL " at the base of the wall. ">
|
||||||
|
<COND (<NOT ,PANEL-BLOCKER>
|
||||||
|
<TELL
|
||||||
|
"The robot zips through the panel, and is gone." CR>)
|
||||||
|
(<NOT <EQUAL? ,PANEL-BLOCKER ,SATCHEL>>
|
||||||
|
<TELL "The robot zips around">
|
||||||
|
<ARTICLE ,PANEL-BLOCKER>
|
||||||
|
<TELL ", through the panel, and is gone." CR>)
|
||||||
|
(T
|
||||||
|
<TELL
|
||||||
|
"The robot plows into the satchel, sending the " D ,BABEL-FISH>
|
||||||
|
<COND
|
||||||
|
(<AND <NOT <EQUAL? ,ITEM-ON-SATCHEL ,MAIL>>
|
||||||
|
,ITEM-ON-SATCHEL>
|
||||||
|
<TELL " and">
|
||||||
|
<ARTICLE ,ITEM-ON-SATCHEL T>)>
|
||||||
|
<TELL
|
||||||
|
" flying through the air in a graceful arc">
|
||||||
|
<COND
|
||||||
|
(<NOT <EQUAL? ,ITEM-ON-SATCHEL ,MAIL>>
|
||||||
|
<TELL
|
||||||
|
". " ,ROBOT-FLIES-IN "catches the " D ,BABEL-FISH " ">
|
||||||
|
<COND (,ITEM-ON-SATCHEL
|
||||||
|
<MOVE ,ITEM-ON-SATCHEL ,LOCAL-GLOBALS>
|
||||||
|
<TELL "and also manages to catch">
|
||||||
|
<ARTICLE ,ITEM-ON-SATCHEL T>
|
||||||
|
<SETG ITEM-ON-SATCHEL <>>)
|
||||||
|
(T
|
||||||
|
<TELL
|
||||||
|
"(which is all the flying junk it can find)">)>
|
||||||
|
<TELL ", and exits." CR>)
|
||||||
|
(<EQUAL? ,ITEM-ON-SATCHEL ,MAIL>
|
||||||
|
<MOVE ,MAIL ,LOCAL-GLOBALS>
|
||||||
|
<SETG SCORE <+ ,SCORE 12>>
|
||||||
|
<MOVE ,BABEL-FISH ,PROTAGONIST>
|
||||||
|
<COND (<RUNNING? ,I-ANNOUNCEMENT>
|
||||||
|
<ENABLE <QUEUE I-GUARDS 4>>)
|
||||||
|
(<NOT
|
||||||
|
<FSET? ,CAPTAINS-QUARTERS ,TOUCHBIT>>
|
||||||
|
<ENABLE <QUEUE I-ANNOUNCEMENT 4>>
|
||||||
|
<ENABLE <QUEUE I-GUARDS 7>>)>
|
||||||
|
<SETG FISH-COUNTER 0>
|
||||||
|
<SETG ITEM-ON-SATCHEL <>>
|
||||||
|
<TELL
|
||||||
|
" surrounded by a cloud of junk mail. Another robot flies in and begins madly
|
||||||
|
collecting the cluttered plume of mail. The " D ,BABEL-FISH " continues its
|
||||||
|
flight, landing with a loud \"squish\" in your ear." CR>)>)>)>)>)>>
|
||||||
|
|
||||||
|
<OBJECT FISH-HOLE
|
||||||
|
(IN HOLD)
|
||||||
|
(DESC "small hole")
|
||||||
|
(SYNONYM HOLE)
|
||||||
|
(ADJECTIVE SMALL)
|
||||||
|
(FLAGS NDESCBIT)
|
||||||
|
(ACTION FISH-HOLE-F)>
|
||||||
|
|
||||||
|
<ROUTINE FISH-HOLE-F ()
|
||||||
|
<COND (<VERB? LOOK-INSIDE>
|
||||||
|
<TELL "You see only " D ,DARK-OBJECT "." CR>)
|
||||||
|
(<AND <VERB? PUT>
|
||||||
|
<PRSI? ,FISH-HOLE>>
|
||||||
|
<COND (<FSET? ,PRSO ,INTEGRALBIT>
|
||||||
|
<PART-OF>)
|
||||||
|
(<L? <GETP ,PRSO ,P?SIZE> 5>
|
||||||
|
<MOVE ,PRSO ,LOCAL-GLOBALS>
|
||||||
|
<TELL "It falls through the hole and vanishes." CR>)
|
||||||
|
(T
|
||||||
|
<TELL "It doesn't fit through the hole." CR>)>)
|
||||||
|
(<AND <VERB? PUT-ON PUT-IN-FRONT>
|
||||||
|
<PRSI? ,FISH-HOLE>>
|
||||||
|
<COND (<PRSO? ,HANDS ,EARS ,ME ,HEAD>
|
||||||
|
<PERFORM ,V?STAND-BEFORE ,FISH-HOLE>
|
||||||
|
<RTRUE>)>
|
||||||
|
<PERFORM ,V?HANG ,PRSO ,HOOK>
|
||||||
|
<RTRUE>)
|
||||||
|
(<AND <VERB? BLOCK-WITH SPUT-ON>
|
||||||
|
<PRSO? ,FISH-HOLE>>
|
||||||
|
<PERFORM ,V?HANG ,PRSI ,HOOK>
|
||||||
|
<RTRUE>)
|
||||||
|
(<VERB? BLOCK>
|
||||||
|
<PERFORM ,V?STAND-BEFORE ,FISH-HOLE>
|
||||||
|
<RTRUE>)
|
||||||
|
(<AND <VERB? LIE-DOWN>
|
||||||
|
,IN-FRONT-FLAG>
|
||||||
|
<PERFORM ,V?STAND-BEFORE ,FISH-HOLE>
|
||||||
|
<RTRUE>)>>
|
||||||
|
|
||||||
|
<OBJECT HOOK
|
||||||
|
(IN HOLD)
|
||||||
|
(DESC "metal hook")
|
||||||
|
(SYNONYM HOOK)
|
||||||
|
(ADJECTIVE METAL)
|
||||||
|
(FLAGS NDESCBIT)
|
||||||
|
(ACTION HOOK-F)>
|
||||||
|
|
||||||
|
<ROUTINE HOOK-F ()
|
||||||
|
<COND (<VERB? EXAMINE>
|
||||||
|
<COND (,GOWN-HUNG
|
||||||
|
<TELL "Your gown is hanging from it." CR>)
|
||||||
|
(T
|
||||||
|
<TELL
|
||||||
|
"The hook is attached to the wall, inches above a tiny hole." CR>)>)
|
||||||
|
(<VERB? HANG PUT-ON>
|
||||||
|
<COND (,LYING-DOWN
|
||||||
|
<TELL ,WHILE-LYING CR>)
|
||||||
|
(<PRSO?,GOWN>
|
||||||
|
<COND (<FSET? ,GOWN ,WORNBIT>
|
||||||
|
<IDROP>
|
||||||
|
<RTRUE>)>
|
||||||
|
<SETG GOWN-HUNG T>
|
||||||
|
<MOVE ,GOWN ,HERE>
|
||||||
|
<FSET ,GOWN ,NDESCBIT>
|
||||||
|
<FSET ,GOWN ,TRYTAKEBIT>
|
||||||
|
<FCLEAR ,GOWN ,OPENBIT>
|
||||||
|
<TELL
|
||||||
|
"The gown is now hanging from the hook, covering a tiny hole." CR>)
|
||||||
|
(<PRSO? ,HANDS ,EARS ,HEAD>
|
||||||
|
<PERFORM ,V?STAND-BEFORE ,HOOK>
|
||||||
|
<RTRUE>)
|
||||||
|
(<FSET? ,PRSO ,TAKEBIT>
|
||||||
|
<COND (<FSET? ,PRSO ,TRYTAKEBIT>
|
||||||
|
<TELL ,NOT-HOLDING>
|
||||||
|
<ARTICLE ,PRSO T>
|
||||||
|
<TELL "." CR>)
|
||||||
|
(T
|
||||||
|
<MOVE ,PRSO ,HERE>
|
||||||
|
<TELL "It slips off the hook." CR>)>)
|
||||||
|
(T
|
||||||
|
<V-COUNT>)>)>>
|
||||||
|
|
||||||
|
<OBJECT DRAIN
|
||||||
|
(IN HOLD)
|
||||||
|
(DESC "drain")
|
||||||
|
(SYNONYM DRAIN GRATING GRATE)
|
||||||
|
(FLAGS NDESCBIT)
|
||||||
|
(ACTION DRAIN-F)>
|
||||||
|
|
||||||
|
<ROUTINE DRAIN-F ()
|
||||||
|
<COND (<VERB? PUT-ON>
|
||||||
|
<COND (<FSET? ,TOWEL ,SURFACEBIT>
|
||||||
|
<TELL "The drain is already covered by the towel." CR>)
|
||||||
|
(,LYING-DOWN
|
||||||
|
<TELL ,WHILE-LYING CR>)
|
||||||
|
(<PRSO?,TOWEL>
|
||||||
|
<FSET ,TOWEL ,CONTBIT>
|
||||||
|
<FSET ,TOWEL ,SURFACEBIT>
|
||||||
|
<FSET ,TOWEL ,OPENBIT>
|
||||||
|
<FSET ,TOWEL ,NDESCBIT>
|
||||||
|
<FSET ,TOWEL ,TRYTAKEBIT>
|
||||||
|
<MOVE ,TOWEL ,HERE>
|
||||||
|
<PERFORM ,V?EXAMINE ,DRAIN>
|
||||||
|
<RTRUE>)
|
||||||
|
(T
|
||||||
|
<TELL "The drain is too large to be covered by">
|
||||||
|
<ARTICLE ,PRSO T>
|
||||||
|
<TELL "." CR>)>)
|
||||||
|
(<VERB? LOOK-INSIDE>
|
||||||
|
<PERFORM ,V?LOOK-INSIDE ,FISH-HOLE>
|
||||||
|
<RTRUE>)
|
||||||
|
(<AND <VERB? EXAMINE>
|
||||||
|
<FSET? ,TOWEL ,SURFACEBIT>>
|
||||||
|
<TELL "The towel completely covers the drain." CR>)>>
|
||||||
|
|
||||||
|
<OBJECT ROBOT-PANEL
|
||||||
|
(IN HOLD)
|
||||||
|
(DESC "tiny robot panel")
|
||||||
|
(SYNONYM PANEL)
|
||||||
|
(ADJECTIVE ROBOT TINY)
|
||||||
|
(FLAGS NDESCBIT)
|
||||||
|
(ACTION ROBOT-PANEL-F)>
|
||||||
|
|
||||||
|
<ROUTINE ROBOT-PANEL-F ()
|
||||||
|
<COND (<VERB? EXAMINE CLOSE>
|
||||||
|
<TELL
|
||||||
|
"The panel, only a few inches high, is currently closed." CR>)
|
||||||
|
(<VERB? OPEN>
|
||||||
|
<TELL ,BUDGE CR>)
|
||||||
|
(<VERB? BLOCK>
|
||||||
|
<SETG AWAITING-REPLY 6>
|
||||||
|
<ENABLE <QUEUE I-REPLY 2>>
|
||||||
|
<TELL "With " D ,HANDS "s? By force of will?" CR>)
|
||||||
|
(<AND <VERB? LIE-DOWN>
|
||||||
|
,IN-FRONT-FLAG>
|
||||||
|
<PERFORM ,V?STAND-BEFORE ,ROBOT-PANEL>
|
||||||
|
<RTRUE>)
|
||||||
|
(<AND <VERB? PUT-IN-FRONT PUT-IN-FRONT PUT-ON>
|
||||||
|
<PRSI? ,ROBOT-PANEL>>
|
||||||
|
<PERFORM ,V?BLOCK-WITH ,ROBOT-PANEL ,PRSO>
|
||||||
|
<RTRUE>)
|
||||||
|
(<AND <VERB? BLOCK-WITH SPUT-ON>
|
||||||
|
<PRSO? ,ROBOT-PANEL>>
|
||||||
|
<COND (<PRSI? ,HEAD ,HANDS ,EARS ,EYES>
|
||||||
|
<V-COUNT>)
|
||||||
|
(<NOT <HELD? ,PRSI>>
|
||||||
|
<TELL ,NOT-HOLDING>
|
||||||
|
<ARTICLE ,PRSI T>
|
||||||
|
<TELL "." CR>)
|
||||||
|
(,PANEL-BLOCKER
|
||||||
|
<TELL "But">
|
||||||
|
<ARTICLE ,PANEL-BLOCKER T>
|
||||||
|
<TELL
|
||||||
|
" is already in front of the " D ,ROBOT-PANEL "." CR>)
|
||||||
|
(,LYING-DOWN
|
||||||
|
<TELL ,WHILE-LYING CR>)
|
||||||
|
(T
|
||||||
|
<MOVE ,PRSI ,HERE>
|
||||||
|
<SETG PANEL-BLOCKER ,PRSI>
|
||||||
|
<FSET ,PRSI ,TRYTAKEBIT>
|
||||||
|
<TELL "Okay,">
|
||||||
|
<COND (<PRSI? ,SATCHEL>
|
||||||
|
<TELL " the satchel is lying on its side">)
|
||||||
|
(T
|
||||||
|
<FSET ,PRSI ,NDESCBIT>
|
||||||
|
<ARTICLE ,PRSI T>
|
||||||
|
<TELL " is sitting">)>
|
||||||
|
<TELL " in front of the " D ,ROBOT-PANEL "." CR>)>)>>
|
||||||
|
|
||||||
|
<OBJECT BABEL-FISH
|
||||||
|
(IN LOCAL-GLOBALS) ;"just for the purpose of MOBY-FIND"
|
||||||
|
(DESC "babel fish")
|
||||||
|
(SYNONYM FISH)
|
||||||
|
(ADJECTIVE BABEL)
|
||||||
|
(FLAGS TAKEBIT)
|
||||||
|
(ACTION BABEL-FISH-F)>
|
||||||
|
|
||||||
|
<ROUTINE BABEL-FISH-F ()
|
||||||
|
<COND (<VERB? TAKE REMOVE>
|
||||||
|
<TELL
|
||||||
|
"That would be foolish. Having a " D ,BABEL-FISH " in your ear is terribly
|
||||||
|
useful." CR>)>>
|
||||||
|
|
||||||
|
<OBJECT GLASS-CASE
|
||||||
|
(IN HOLD)
|
||||||
|
(DESC "glass case")
|
||||||
|
(LDESC "In the corner is a glass case with a switch and a keyboard.")
|
||||||
|
(SYNONYM CASE LID GLASS)
|
||||||
|
(ADJECTIVE GLASS)
|
||||||
|
(SIZE 40)
|
||||||
|
(FLAGS CONTBIT TRANSBIT SEARCHBIT)
|
||||||
|
(ACTION GLASS-CASE-F)>
|
||||||
|
|
||||||
|
<GLOBAL GLASS-CASE-SCORE <>>
|
||||||
|
|
||||||
|
<ROUTINE GLASS-CASE-F ()
|
||||||
|
<COND (<VERB? EXAMINE>
|
||||||
|
<TELL "The " D ,GLASS-CASE " is ">
|
||||||
|
<COND (<FSET? ,GLASS-CASE ,OPENBIT>
|
||||||
|
<TELL "open">)
|
||||||
|
(T
|
||||||
|
<TELL "closed">)>
|
||||||
|
<TELL
|
||||||
|
". Attached to it are a " D ,KEYBOARD " and a switch." CR>)
|
||||||
|
(<AND <VERB? OPEN>
|
||||||
|
<NOT <FSET? ,GLASS-CASE ,OPENBIT>>>
|
||||||
|
<TELL ,BUDGE CR>)
|
||||||
|
(<VERB? MUNG>
|
||||||
|
<TELL
|
||||||
|
"The hold of the Vogon ship is virtually undamaged by the explosion
|
||||||
|
of the " D ,GLASS-CASE>
|
||||||
|
<JIGS-UP
|
||||||
|
". You, however, are blasted into tiny bits and smeared all over the room.
|
||||||
|
Several cleaning robots fly in and wipe you neatly off the walls.">
|
||||||
|
<RTRUE>)>>
|
||||||
|
|
||||||
|
<ROUTINE GLASS-CASE-OPENS () ;"see V-TYPE"
|
||||||
|
<COND (<FSET? ,GLASS-CASE ,OPENBIT>
|
||||||
|
<TELL "Nothing happens." CR>
|
||||||
|
<FUCKING-CLEAR>)
|
||||||
|
(T
|
||||||
|
<FSET ,GLASS-CASE ,OPENBIT>
|
||||||
|
<TELL "The " D ,GLASS-CASE " opens." CR>
|
||||||
|
<FCLEAR ,PLOTTER ,TRYTAKEBIT>
|
||||||
|
<COND (<NOT ,GLASS-CASE-SCORE>
|
||||||
|
<SETG GLASS-CASE-SCORE T>
|
||||||
|
<SETG SCORE <+ ,SCORE 25>>)>
|
||||||
|
<FUCKING-CLEAR>)>>
|
||||||
|
|
||||||
|
<OBJECT KEYBOARD
|
||||||
|
(IN HOLD)
|
||||||
|
(DESC "keyboard")
|
||||||
|
(SYNONYM KEYBOA)
|
||||||
|
(FLAGS NDESCBIT TRYTAKEBIT)>
|
||||||
|
|
||||||
|
<OBJECT CASE-SWITCH
|
||||||
|
(IN HOLD)
|
||||||
|
(DESC "switch")
|
||||||
|
(SYNONYM SWITCH)
|
||||||
|
(FLAGS NDESCBIT SWITCHBIT)
|
||||||
|
(ACTION CASE-SWITCH-F)>
|
||||||
|
|
||||||
|
<ROUTINE CASE-SWITCH-F ()
|
||||||
|
<COND (<VERB? LAMP-ON TURN PUSH MOVE THROW>
|
||||||
|
<COND (<HELD? ,BABEL-FISH>
|
||||||
|
<TELL
|
||||||
|
"A recording plays: \"To open the case, type in the ">
|
||||||
|
<COND (<EQUAL? ,WORD-NUMBER 1>
|
||||||
|
<TELL "first">)
|
||||||
|
(<EQUAL? ,WORD-NUMBER 2>
|
||||||
|
<TELL "second">)
|
||||||
|
(<EQUAL? ,WORD-NUMBER 3>
|
||||||
|
<TELL "third">)>
|
||||||
|
<TELL
|
||||||
|
" word from the second verse of the Captain's current favourite poem.
|
||||||
|
WARNING: An incorrect input will cause the case to explode.\"" CR>)
|
||||||
|
(T
|
||||||
|
<TELL "A recording plays: \"A">
|
||||||
|
<PRODUCE-GIBBERISH 5>
|
||||||
|
<CRLF>)>)>>
|
||||||
|
|
||||||
|
<ROUTINE PRODUCE-GIBBERISH (N "AUX" GIBBERISH-COUNTER SUPER-COUNTER)
|
||||||
|
<SET SUPER-COUNTER 0>
|
||||||
|
<REPEAT ()
|
||||||
|
<SET SUPER-COUNTER <+ .SUPER-COUNTER 1>>
|
||||||
|
<SET GIBBERISH-COUNTER 0>
|
||||||
|
<REPEAT ()
|
||||||
|
<SET GIBBERISH-COUNTER <+ .GIBBERISH-COUNTER 1>>
|
||||||
|
<TELL <PICK-ONE ,GIBBERISH>>
|
||||||
|
<COND (<EQUAL? .GIBBERISH-COUNTER 10>
|
||||||
|
<COND (<NOT <EQUAL? .SUPER-COUNTER .N>>
|
||||||
|
<TELL " o">)>
|
||||||
|
<RETURN>)>>
|
||||||
|
<COND (<EQUAL? .SUPER-COUNTER .N>
|
||||||
|
<TELL ".\"">
|
||||||
|
<RETURN>)>>>
|
||||||
|
|
||||||
|
<ROUTINE I-ANNOUNCEMENT ()
|
||||||
|
<ENABLE <QUEUE I-ANNOUNCEMENT -1>>
|
||||||
|
<TELL CR "An announcement is coming over the ship's intercom. \"">
|
||||||
|
<COND (<HELD? ,BABEL-FISH ,PROTAGONIST>
|
||||||
|
<TELL
|
||||||
|
"This is the Captain. My instruments show that we've picked up a couple of
|
||||||
|
hitchhikers. I hate freeloaders, and when my guards find you I'll have you
|
||||||
|
thrown into space. On second thought, maybe I'll read you some of my poetry
|
||||||
|
first. Repeating...\"" CR>)
|
||||||
|
(T
|
||||||
|
<TELL "E">
|
||||||
|
<PRODUCE-GIBBERISH 10>
|
||||||
|
<CRLF>)>>
|
||||||
|
|
||||||
|
<GLOBAL GIBBERISH
|
||||||
|
<PLTABLE
|
||||||
|
"toy" "r g" "irb" "kwa" "o s"
|
||||||
|
"fim" "p w" "osh" "flu" "a r"
|
||||||
|
"vup" "d t" "imb" "tha" "i l"
|
||||||
|
"cav" "s g" "ulp" "cho" "u n"
|
||||||
|
"zit" "z z" "eft" "qui" "e h"
|
||||||
|
"kon" "l m" "ork" "gry" "o t"
|
||||||
|
"huv" "x j" "erl" "tru" "a b"
|
||||||
|
"fud" "w c" "oll" "wro" "i s">>
|
||||||
|
|
||||||
|
<ROUTINE I-GUARDS ()
|
||||||
|
<COND (<EQUAL? ,HERE ,HOLD>
|
||||||
|
<DISABLE <INT I-ANNOUNCEMENT>>
|
||||||
|
<TELL CR
|
||||||
|
"Guards burst in and grab you and Ford, who comes slowly awake. They drag you
|
||||||
|
down the corridor to a large cabin, where they strap you into large, menacing
|
||||||
|
chairs..." CR CR>
|
||||||
|
<SETG HERE ,CAPTAINS-QUARTERS>
|
||||||
|
<MOVE ,NAME ,HERE>
|
||||||
|
<SETG LYING-DOWN <>>
|
||||||
|
<ENABLE <QUEUE I-CAPTAIN 2>>
|
||||||
|
<SETG FORD-SLEEPING <>>
|
||||||
|
<FSET ,FORD ,NDESCBIT>
|
||||||
|
<MOVE ,PROTAGONIST ,POETRY-APPRECIATION-CHAIR>
|
||||||
|
<V-LOOK>
|
||||||
|
<MOVE ,FORD ,HERE>
|
||||||
|
<MOVE ,GUARDS ,HERE>)
|
||||||
|
(<NOT <IN? ,RIFLES ,LOCAL-GLOBALS>>
|
||||||
|
<TELL CR ,GUARDS-REALIZE "They">
|
||||||
|
<GUARD-DEATH>
|
||||||
|
<RTRUE>)
|
||||||
|
(T
|
||||||
|
<RFALSE>)>>
|
||||||
|
|
||||||
|
<ROOM CAPTAINS-QUARTERS
|
||||||
|
(IN ROOMS)
|
||||||
|
(DESC "Captain's Quarters")
|
||||||
|
(FLAGS RLANDBIT ONBIT)
|
||||||
|
(PSEUDO "WEAPON" WEAPON-PSEUDO "STRAPS" UNIMPORTANT-THING-F)
|
||||||
|
(GLOBAL FLEET)
|
||||||
|
(ACTION CAPTAINS-QUARTERS-F)>
|
||||||
|
|
||||||
|
<ROUTINE CAPTAINS-QUARTERS-F (RARG)
|
||||||
|
<COND (<EQUAL? .RARG ,M-LOOK>
|
||||||
|
<TELL
|
||||||
|
"This is the cabin of the " D ,VOGON-CAPTAIN ". You and Ford are strapped
|
||||||
|
into " D ,POETRY-APPRECIATION-CHAIR "s." CR>)>>
|
||||||
|
|
||||||
|
<OBJECT POETRY-APPRECIATION-CHAIR
|
||||||
|
(IN CAPTAINS-QUARTERS)
|
||||||
|
(DESC "poetry appreciation chair")
|
||||||
|
(SYNONYM CHAIR CHAIRS SEAT)
|
||||||
|
(ADJECTIVE POETRY APPREC FORMID LARGE MENACI)
|
||||||
|
(FLAGS VEHBIT OPENBIT SEARCHBIT SURFACEBIT CONTBIT)
|
||||||
|
(ACTION POETRY-APPRECIATION-CHAIR-F)>
|
||||||
|
|
||||||
|
<ROUTINE POETRY-APPRECIATION-CHAIR-F ("OPTIONAL" (RARG <>))
|
||||||
|
<COND (.RARG
|
||||||
|
<RFALSE>)
|
||||||
|
(<VERB? DISEMBARK WALK LEAP WALK-AROUND>
|
||||||
|
<SETG AWAITING-REPLY 7>
|
||||||
|
<ENABLE <QUEUE I-REPLY 2>>
|
||||||
|
<TELL "You're strapped in, remember?" CR>)
|
||||||
|
(<AND <VERB? OPEN CLOSE>
|
||||||
|
<PRSO? ,POETRY-APPRECIATION-CHAIR>>
|
||||||
|
<TELL-ME-HOW>)>>
|
||||||
|
|
||||||
|
<OBJECT VOGON-CAPTAIN
|
||||||
|
(IN CAPTAINS-QUARTERS)
|
||||||
|
(DESC "Vogon Captain")
|
||||||
|
(LDESC
|
||||||
|
"The Captain is indescribably hideous, indescribably blubbery,
|
||||||
|
and indescribably mid-to-dark green. He is holding samples of his
|
||||||
|
favourite poetry.")
|
||||||
|
(SYNONYM CAPTAIN VOGONS)
|
||||||
|
(ADJECTIVE VOGON)
|
||||||
|
(FLAGS ACTORBIT)
|
||||||
|
(ACTION VOGON-CAPTAIN-F)>
|
||||||
|
|
||||||
|
<ROUTINE VOGON-CAPTAIN-F ()
|
||||||
|
<COND (<OR <VERB? TELL HELLO THANK>
|
||||||
|
<AND <VERB? ASK-ABOUT ASK-FOR>
|
||||||
|
<EQUAL? ,VOGON-CAPTAIN ,PRSO>>>
|
||||||
|
<TELL
|
||||||
|
"One of the guards lightly bashes your skull with the butt of his weapon">
|
||||||
|
<COND (<HELD? ,BABEL-FISH>
|
||||||
|
<TELL
|
||||||
|
". \"This is a poetry appreciation session, prisoner. No talking!\"" CR>)
|
||||||
|
(T
|
||||||
|
<TELL " and says, \"A">
|
||||||
|
<PRODUCE-GIBBERISH 2>
|
||||||
|
<CRLF>)>
|
||||||
|
<FUCKING-CLEAR>)
|
||||||
|
(<AND <IN? ,POETRY ,HERE>
|
||||||
|
<VERB? BLOCK>>
|
||||||
|
<PERFORM ,V?LISTEN ,POETRY>
|
||||||
|
<RTRUE>)>>
|
||||||
|
|
||||||
|
<GLOBAL CAPTAIN-COUNTER 0>
|
||||||
|
|
||||||
|
<ROUTINE I-CAPTAIN ()
|
||||||
|
<ENABLE <QUEUE I-CAPTAIN -1>>
|
||||||
|
<SETG CAPTAIN-COUNTER <+ ,CAPTAIN-COUNTER 1>>
|
||||||
|
<CRLF>
|
||||||
|
<COND (<EQUAL? ,CAPTAIN-COUNTER 1>
|
||||||
|
<TELL
|
||||||
|
"\"If he's going to read us his poetry,\" mutters Ford, sweating profusely,
|
||||||
|
\"just pray he softens us up with some cudgels first...\"" CR CR>)>
|
||||||
|
<COND (<NOT <HELD? ,BABEL-FISH ,PROTAGONIST>>
|
||||||
|
<TELL "The " D ,VOGON-CAPTAIN " says, \"O">
|
||||||
|
<PRODUCE-GIBBERISH 2>
|
||||||
|
<COND (<EQUAL? ,CAPTAIN-COUNTER 6>
|
||||||
|
<GUARDS-TO-AIRLOCK>)
|
||||||
|
(T
|
||||||
|
<CRLF>)>)
|
||||||
|
(<EQUAL? ,CAPTAIN-COUNTER 1>
|
||||||
|
<TELL
|
||||||
|
"\"Hello, hitchhikers!\" begins the " D ,VOGON-CAPTAIN ". \"I've decided to
|
||||||
|
read you a verse of my poetry!\"" CR>)
|
||||||
|
(<EQUAL? ,CAPTAIN-COUNTER 2>
|
||||||
|
<TELL
|
||||||
|
"\"Oh freddled gruntbuggly, thy nacturations are to me!\"" CR>)
|
||||||
|
(<EQUAL? ,CAPTAIN-COUNTER 3>
|
||||||
|
<TELL
|
||||||
|
"\"As plurdled gabbleblotchits on a lurgid bee.\"" CR>)
|
||||||
|
(<EQUAL? ,CAPTAIN-COUNTER 4>
|
||||||
|
<TELL
|
||||||
|
"\"Groop I implore thee, my foonting turlingdromes.\"" CR>)
|
||||||
|
(<EQUAL? ,CAPTAIN-COUNTER 5>
|
||||||
|
<TELL
|
||||||
|
"\"And hooptiously drangle me with crinkly bindlewurdles, or I will rend
|
||||||
|
thee in the gobberwarts with my blurglecruncheon, see if I don't!\"" CR>)
|
||||||
|
(<EQUAL? ,CAPTAIN-COUNTER 6>
|
||||||
|
<COND (,POEM-ENJOYED
|
||||||
|
<TELL
|
||||||
|
"\"You looked like you enjoyed my poem. I think...yes, I think I'll read
|
||||||
|
the NEXT verse, also!\"" CR>)
|
||||||
|
(T
|
||||||
|
<TELL
|
||||||
|
"\"You didn't seem to enjoy my poem at all! Guards, toss
|
||||||
|
them out the airlock!\"">
|
||||||
|
<GUARDS-TO-AIRLOCK>)>)
|
||||||
|
(<EQUAL? ,CAPTAIN-COUNTER 7>
|
||||||
|
<COND (<EQUAL? ,LINE-NUMBER 1 2>
|
||||||
|
<TELL ,LINE-A CR>)
|
||||||
|
(<EQUAL? ,LINE-NUMBER 3 4>
|
||||||
|
<TELL ,LINE-B CR>)
|
||||||
|
(T
|
||||||
|
<TELL ,LINE-C CR>)>)
|
||||||
|
(<EQUAL? ,CAPTAIN-COUNTER 8>
|
||||||
|
<COND (<EQUAL? ,LINE-NUMBER 3 5>
|
||||||
|
<TELL ,LINE-A CR>)
|
||||||
|
(<EQUAL? ,LINE-NUMBER 1 6>
|
||||||
|
<TELL ,LINE-B CR>)
|
||||||
|
(T
|
||||||
|
<TELL ,LINE-C CR>)>)
|
||||||
|
(<EQUAL? ,CAPTAIN-COUNTER 9>
|
||||||
|
<COND (<EQUAL? ,LINE-NUMBER 4 6>
|
||||||
|
<TELL ,LINE-A CR>)
|
||||||
|
(<EQUAL? ,LINE-NUMBER 2 5>
|
||||||
|
<TELL ,LINE-B CR>)
|
||||||
|
(T
|
||||||
|
<TELL ,LINE-C CR>)>)
|
||||||
|
(<EQUAL? ,CAPTAIN-COUNTER 10>
|
||||||
|
<TELL
|
||||||
|
"\"Gerond withoutitude form into formless bloit, why not then? Moose.\"" CR>)
|
||||||
|
(<EQUAL? ,CAPTAIN-COUNTER 11>
|
||||||
|
<TELL
|
||||||
|
"\"Since you have somehow managed to survive two verses of my poetry, I have
|
||||||
|
no choice but to space you. Guards!\"">
|
||||||
|
<GUARDS-TO-AIRLOCK>)>>
|
||||||
|
|
||||||
|
<GLOBAL LINE-A "\"Fripping lyshus wimbgunts, awhilst moongrovenly kormzibs.\"">
|
||||||
|
|
||||||
|
<GLOBAL LINE-B "\"Gashee morphousite, thou expungiest quoopisk!\"">
|
||||||
|
|
||||||
|
<GLOBAL LINE-C
|
||||||
|
"\"Bleem miserable venchit! Bleem forever mestinglish asunder frapt.\"">
|
||||||
|
|
||||||
|
<GLOBAL LINE-NUMBER 0>
|
||||||
|
|
||||||
|
;"The line order is set randomly from 1 to 6, with the following result:
|
||||||
|
1 Line A, Line B, Line C
|
||||||
|
2 Line A, Line C, Line B
|
||||||
|
3 Line B, Line A, Line C
|
||||||
|
4 Line B, Line C, Line A
|
||||||
|
5 Line C, Line A, Line B
|
||||||
|
6 Line C, Line B, Line A"
|
||||||
|
|
||||||
|
<GLOBAL WORD-NUMBER 0> ;"randomly set between one and three"
|
||||||
|
|
||||||
|
<ROUTINE GUARDS-TO-AIRLOCK ()
|
||||||
|
<DISABLE <INT I-CAPTAIN>>
|
||||||
|
<TELL
|
||||||
|
" A guard grabs you and Ford, and drags you toward the hold. Ford whispers,
|
||||||
|
\"Don't worry, I'll think of something!\"" CR CR>
|
||||||
|
<FCLEAR ,HOLD ,TOUCHBIT>
|
||||||
|
<GOTO ,HOLD>
|
||||||
|
<FCLEAR ,FORD ,NDESCBIT>
|
||||||
|
<MOVE ,GUARDS ,HERE>
|
||||||
|
<MOVE ,FORD ,HERE>
|
||||||
|
<ENABLE <QUEUE I-FORD 1>>>
|
||||||
|
|
||||||
|
<OBJECT POETRY
|
||||||
|
(IN CAPTAINS-QUARTERS)
|
||||||
|
(DESC "Vogon poetry")
|
||||||
|
(SYNONYM POETRY POEM SAMPLE VERSE)
|
||||||
|
(ADJECTIVE VOGON FIRST SECOND)
|
||||||
|
(FLAGS NDESCBIT NARTICLEBIT DARKBIT)
|
||||||
|
(ACTION POETRY-F)>
|
||||||
|
|
||||||
|
<GLOBAL POEM-ENJOYED <>>
|
||||||
|
|
||||||
|
<GLOBAL AIRLOCK-COUNTER 0>
|
||||||
|
|
||||||
|
<ROUTINE POETRY-F ()
|
||||||
|
<COND (<AND <VERB? ENJOY LISTEN>
|
||||||
|
<L? ,CAPTAIN-COUNTER 2>>
|
||||||
|
<TELL "The " D ,VOGON-CAPTAIN " hasn't begun yet!" CR>)
|
||||||
|
(<VERB? ENJOY>
|
||||||
|
<COND (<NOT <HELD? ,BABEL-FISH>>
|
||||||
|
<TELL
|
||||||
|
"You can't even understand it, let alone enjoy it!" CR>)
|
||||||
|
(,POEM-ENJOYED
|
||||||
|
<SETG AWAITING-REPLY 8>
|
||||||
|
<ENABLE <QUEUE I-REPLY 2>>
|
||||||
|
<TELL "Hey, let's not overdo it, okay?" CR>)
|
||||||
|
(T
|
||||||
|
<SETG POEM-ENJOYED T>
|
||||||
|
<SETG SCORE <+ ,SCORE 15>>
|
||||||
|
<TELL
|
||||||
|
"You realise that, although the " D ,POETRY " is indeed astoundingly bad,
|
||||||
|
worse things happen at sea, and in fact, at school. With an effort for which
|
||||||
|
Hercules himself would have patted you on the back, you grit your teeth and
|
||||||
|
enjoy the stuff." CR>)>)
|
||||||
|
(<VERB? LISTEN>
|
||||||
|
<TELL "You have no choice. Why not relax and enjoy it?" CR>)
|
||||||
|
(<AND <IN? ,POETRY ,HERE>
|
||||||
|
<VERB? BLOCK>>
|
||||||
|
<PERFORM ,V?LISTEN ,POETRY>
|
||||||
|
<RTRUE>)
|
||||||
|
(<VERB? READ EXAMINE>
|
||||||
|
<TELL "You can't see it from here." CR>)>>
|
||||||
|
|
||||||
|
<OBJECT VOGON-CORRIDOR-DOOR
|
||||||
|
(IN HOLD)
|
||||||
|
(DESC "corridor door")
|
||||||
|
(SYNONYM DOOR)
|
||||||
|
(ADJECTIVE CORRID)
|
||||||
|
(FLAGS DOORBIT NDESCBIT)
|
||||||
|
(ACTION VOGON-CORRIDOR-DOOR-F)>
|
||||||
|
|
||||||
|
<ROUTINE VOGON-CORRIDOR-DOOR-F ()
|
||||||
|
<COND (<VERB? OPEN UNLOCK THROUGH>
|
||||||
|
<DO-WALK ,P?WEST>)>>
|
||||||
|
|
||||||
|
<OBJECT VOGON-INNER-DOOR
|
||||||
|
(IN LOCAL-GLOBALS)
|
||||||
|
(DESC "inner door")
|
||||||
|
(SYNONYM DOOR)
|
||||||
|
(ADJECTIVE INNER AIRLOC MASSIV)
|
||||||
|
(FLAGS VOWELBIT NDESCBIT DOORBIT)
|
||||||
|
(ACTION VOGON-AIRLOCK-DOOR-F)>
|
||||||
|
|
||||||
|
<OBJECT VOGON-OUTER-DOOR
|
||||||
|
(IN LOCAL-GLOBALS)
|
||||||
|
(DESC "outer door")
|
||||||
|
(SYNONYM DOOR)
|
||||||
|
(ADJECTIVE OUTER AIRLOC MASSIV)
|
||||||
|
(FLAGS VOWELBIT NDESCBIT DOORBIT)
|
||||||
|
(ACTION VOGON-AIRLOCK-DOOR-F)>
|
||||||
|
|
||||||
|
<ROUTINE VOGON-AIRLOCK-DOOR-F ()
|
||||||
|
<COND (<VERB? OPEN THROUGH>
|
||||||
|
<TELL ,BUDGE CR>)>>
|
||||||
|
|
||||||
|
<OBJECT AIRLOCK-OBJECT
|
||||||
|
(IN LOCAL-GLOBALS)
|
||||||
|
(DESC "airlock")
|
||||||
|
(SYNONYM AIRLOC)
|
||||||
|
(FLAGS VOWELBIT)
|
||||||
|
(ACTION AIRLOCK-OBJECT-F)>
|
||||||
|
|
||||||
|
<ROUTINE AIRLOCK-OBJECT-F ()
|
||||||
|
<COND (<VERB? THROUGH WALK-TO>
|
||||||
|
<COND (<EQUAL? ,HERE ,AIRLOCK>
|
||||||
|
<TELL ,LOOK-AROUND CR>)
|
||||||
|
(<EQUAL? ,HERE ,HOLD>
|
||||||
|
<DO-WALK ,P?WEST>)>)
|
||||||
|
(<VERB? LEAVE EXIT DISEMBARK>
|
||||||
|
<COND (<EQUAL? ,HERE ,AIRLOCK>
|
||||||
|
<DO-WALK ,P?EAST>)
|
||||||
|
(T
|
||||||
|
<TELL ,LOOK-AROUND CR>)>)>>
|
||||||
|
|
||||||
|
<OBJECT EQUATIONS
|
||||||
|
(IN LOCAL-GLOBALS)
|
||||||
|
(DESC "it")
|
||||||
|
(SYNONYM EQUATI NUMBER PENCIL)
|
||||||
|
(FLAGS NDESCBIT NARTICLEBIT)
|
||||||
|
(ACTION UNIMPORTANT-THING-F)>
|
||||||
|
|
||||||
|
<ROOM AIRLOCK
|
||||||
|
(IN ROOMS)
|
||||||
|
(SYNONYM BETELG)
|
||||||
|
(DESC "Airlock")
|
||||||
|
(LDESC "This airlock has massive doors to port and starboard.")
|
||||||
|
(WEST TO HOLD IF VOGON-INNER-DOOR IS OPEN) ;"this should never happen"
|
||||||
|
(EAST TO HOLD IF VOGON-OUTER-DOOR IS OPEN) ;"ditto"
|
||||||
|
(FLAGS RLANDBIT ONBIT)
|
||||||
|
(GLOBAL VOGON-INNER-DOOR VOGON-OUTER-DOOR AIRLOCK-OBJECT FLEET EQUATIONS)
|
||||||
|
(ACTION AIRLOCK-F)>
|
||||||
|
|
||||||
|
<ROUTINE AIRLOCK-F (RARG)
|
||||||
|
<COND (<EQUAL? .RARG ,M-END>
|
||||||
|
<SETG AIRLOCK-COUNTER <+ ,AIRLOCK-COUNTER 1>>
|
||||||
|
<CRLF>
|
||||||
|
<COND (<EQUAL? ,AIRLOCK-COUNTER 1>
|
||||||
|
<TELL
|
||||||
|
"Ford points at the " D ,VOGON-OUTER-DOOR ". \"In about two minutes, it will
|
||||||
|
open and we'll be ejected into the vacuum of space. But don't panic, I'll
|
||||||
|
think of something.\"" CR>)
|
||||||
|
(<EQUAL? ,AIRLOCK-COUNTER 2>
|
||||||
|
<TELL "Ford is mumbling to himself." CR>)
|
||||||
|
(<EQUAL? ,AIRLOCK-COUNTER 3>
|
||||||
|
<TELL
|
||||||
|
"Ford produces a pencil and begins scribbling equations on the wall." CR>)
|
||||||
|
(<EQUAL? ,AIRLOCK-COUNTER 4>
|
||||||
|
<TELL
|
||||||
|
"Ford's eyes light up. \"Do you still have the Electronic Sub-Etha Auto
|
||||||
|
Hitching Thu...\" At that moment, the airlock door opens, and you and Ford
|
||||||
|
are blown out into space.||">
|
||||||
|
<COND (<HELD? ,GUIDE>
|
||||||
|
<TELL
|
||||||
|
"Your elbow must have struck some key on " D ,GUIDE " because it begins
|
||||||
|
droning out an entry, coincidentally enough the entry on SPACE. \""
|
||||||
|
,SPACE-TEXT "\" (Footnote 9)" CR CR>)>
|
||||||
|
<TELL
|
||||||
|
"Precisely twenty-nine seconds later, you and Ford are scooped up by a passing
|
||||||
|
ship. Gasping for air, you pass out..." CR CR>
|
||||||
|
<SETG HEART-PROB 100>
|
||||||
|
<GOTO ,DARK>)>)>>
|
||||||