Chapter 10: Game Design
Now we'll apply what we've learned to build a text adventure game.
What We're Building
A classic text adventure (interactive fiction) where the player:
- Explores rooms connected by directions
- Examines objects and interacts with items
- Collects inventory
- Solves simple puzzles
The final game will compile to a standalone executable you can share.
Game Concept
The Lost Key: You wake up in a mysterious house. Somewhere inside is a golden key that unlocks the front door. Find the key and escape!
The world:
[Kitchen] -- east --> [Hallway] -- east --> [Study]
|
south
|
[Garden]Data Modeling
We need to represent:
- Rooms — locations with descriptions and connections
- Items — objects the player can examine or take
- Player state — current room, inventory
- Game state — overall game status
Room Structure
(import (sigil struct))
(define-struct room
(id) ; Symbol: 'kitchen, 'hallway, etc.
(name) ; Display name: "The Kitchen"
(description) ; What the player sees
(exits default: '()) ; ((direction . room-id) ...)
(items default: '())) ; List of item idsItem Structure
(define-struct item
(id) ; Symbol: 'key, 'lamp, etc.
(name) ; Display name: "a golden key"
(description) ; When examined
(takeable default: #t)) ; Can player pick it up?Game State
(define-struct game-state
(current-room) ; Symbol
(inventory default: '()) ; List of item ids
(rooms) ; Alist of (id . room)
(items)) ; Alist of (id . item)Project Structure
We'll organize the code into modules:
adventure/ ├── main.sgl ; Entry point ├── game.sgl ; Main game loop ├── world.sgl ; Rooms and items ├── commands.sgl ; Command parsing └── display.sgl ; Output formatting
Setting Up the Project
Create a directory:
mkdir -p adventure
cd adventureCreate the module files. We'll start simple and build up.
main.sgl:
;;; The Lost Key - A Text Adventure
(import (adventure game))
(run-game)This is our entry point — it just imports the game module and runs it.
Game Loop Design
The core loop:
- Display the current room
- Show prompt
- Read player input
- Parse command
- Execute action
- Check win/lose conditions
- Repeat
(define (game-loop state)
(display-room state)
(display "> ")
(let ((input (read-line)))
(if (eof-object? input)
(quit-game)
(let ((new-state (handle-command input state)))
(if (game-over? new-state)
(end-game new-state)
(game-loop new-state))))))Commands to Support
Basic commands:
look— describe current roomgo <direction>— move to another roomtake <item>— pick up an itemdrop <item>— drop an iteminventoryori— list carried itemsexamine <item>— describe an itemquit— exit the game
Direction shortcuts:
n,s,e,w— short for go north/south/east/west
Thinking About State
In functional style, each command produces a new state rather than modifying the old one:
(define (go-north state)
(let ((current (game-state-current-room state))
(exits (room-exits (lookup-room state current))))
(let ((north-room (assq 'north exits)))
(if north-room
(game-state state current-room: (cdr north-room))
(begin
(display "You can't go that way.")
(newline)
state)))))Passing state as the first argument creates a copy with only current-room changed.
Exercises
Before we start coding:
- Sketch out 4-5 rooms for your game on paper
- List 3-4 items the player might find
- Think about what puzzle(s) might be fun
- What should happen when the player wins?
Planning the Implementation
In the next chapters, we'll implement:
- World — Define rooms and items
- Commands — Parse and execute player actions
- Polish — Save/load, help system, refinements
- Distribution — Build a standalone executable
Ready to start coding? Let's build the world.