Why building another Adventure Engine?
When I started playing adventure games back in the 80ies, there were basically two types of game implementations:
- Games written as actual programs
- Games using some portable virtual machine or database
Programmed games
When you booted an 8 bit computer back around 1982, on most machines you would land on a blinking prompt allowing you to program in BASIC directly, so with just your computer manual and a bit (a lot) of patience, you could totally write a complete adventure game doing something like that:
10 PRINT"WELCOME ADVENTURER"
20 INPUT"What's next",A$
30 IF A$="QUIT" THEN PRINT"Goodbye!":END
40 IF A$="HELP" THEN PRINT"Nobody can help you, muahahaha!":GOTO 20
50 IF A$="NORTH" THEN GOTO 100
60 IF A$="SOUTH" THEN GOTO 200
70 IF A$="WEST" THEN GOTO 300
80 IF A$="EAST" THEN GOTO 400
90 GOTO 20
100 REM Handle NORTH command
110 (...)
199 GOTO 20
200 REM Handle SOUTH command
210 (...)
299 GOTO 20
300 REM Handle WEST command
310 (...)
399 GOTO 20
400 REM Handle EAST command
410 (...)
499 GOTO 20
And indeed quite a few games on the machine I owned (a 1984 Oric Atmos) were written like that, including “Encounter”.
The main problem with this approach is that you can’t reuse the game engine to make another game, because there is no separation between the game data (locations, items, actions, texts, …) and the code that manages that.
The second issue is that not all BASIC implementations are identical, specially in the audio and graphical domain, so the more “advanced” your game is, the harder it would be to port to another game system.
Virtual machines and databases
A solution to these problems was to separate the engine from the game, solution which has been implemented differently by different people, two examples would be:
…and I guess we could argue that’s similar to Lucas Arts’s SCUMM used for their graphical adventure games
Z-machine
Infocom games were never released on the Oric, but in 1997 a couple of programmers made an Oric implementation of the system, called Pinforic, which allowed Oric users to finally play Zork on their machine
Since then, this system has been used by Hugo Labrande for his game Tristam Island as well as Stefan Vogt’s Hibernated
The Quill
The Quill is a program who’s been released on quite a few machines, including the Oric.
The first versions only supported text adventures, but some later extensions added support for graphics, unfortunately due to the poor sales of the product this expansion was never released for that machine.
A-code
Quite a few Level 9 games were released on the Oric, all using the same A-code interpreter, such as Colossal Adventure, Adventure Quest, Dungeon Adventure, Lords of Time and Snowball.
Unfortunately there is no easy was to make new games using this system on the Oric
Reinventing the wheel
The main reason for me to build my own engine is that none of the existing ones supported the extended memory supported by a full Oric system with a disk drive, and none of them had support for graphics, audio, animation, etc…
As a remainder, here is what my game looks like:
So I built my own (it’s still a work in progress), using a semi-generic format for the game data, so technically if someone was interested it would not be too hard to port the game to another system.
I’ve a disclaimer though: I did not properly “design” the system, it cames organically from the needs when I wrote the game, and it progressively turned into a minimalistic byte-code based scripting language.
Game structure
The idea being to remove dependencies between the engine and the game means that no engine file should directly reference any location, item or action made by the player:
All that should be data driven in some way or another.
The gamedata in Encounter is structured this way:
- A table of locations, with the links to other locations and pointers to descriptions and “location scripts”
- A table of items, with various flags (is it a container, can it be moved, is it open or closed, …)
- A table of keywords, mapping the written representation (“USE”) into an enumerated value
- A table of actions, mapping enumerated values into “script callbacks”
- One table for each possible mapped action
- Actual scripts
Here is how it’s done (roughly, it’s not exactly like that in the actual code, but these blog posts formats are a bit narrow for large lines of code):
Locations
There are about 40 locations in the game, and each one has the following fields:
- Associated North, South, East, West, Up and Down locations
- Textual description
- Script to run when reaching this location
Locations
LOCATION(TUNNEL,NONE,ALLEY,NONE,TextLocMarket,ScriptMarket)
LOCATION(STREET,NONE,ROAD,MARKET,TextLocAlley,ScriptAlley)
LOCATION(PATH,NONE,NONE,ALLEY,TextLocRoad,ScriptRoad)
Items
The ‘items’ word basically means ‘anything that can be interacted with’, including items but also landscape features (“an open pit”) and creatures (“a growling dog”, “a sleeping thug”).
Items have quite a few parameters:
- Textual description
- Location where they can be found
- Associated item (for containers)
- Flags (movable, container, open/close, disabled/enabled, …)
- Containers that can be used to transport them (ex: Water needs a bucket or bag)
Items
ITEM(TextFridge,KITCHEN,IMMOVABLE|CLOSED)
ITEM(TextSilverKnife,GARDEN)
Keywords
Nothing special there, just a list of text strings and an associated enumeration.
WordsArray
MAPPING("READ" , WORD_READ)
MAPPING("USE" , WORD_USE)
MAPPING("OPEN" , WORD_OPEN)
MAPPING("FRIDGE", ITEM_Fridge)
MAPPING("KNIFE" , ITEM_SilverKnife)
Main Action table
Another straightforward table associating an enum to another table
ActionMappingsArray
MAPPING(WORD_READ ,ReadItemMappingsArray)
MAPPING(WORD_USE ,UseItemMappingsArray)
MAPPING(WORD_OPEN ,OpenItemMappingsArray)
(...)
Action tables
And another one, mapping the enum of an item to an action script
ReadItemMappingsArray
MAPPING(ITEM_Newspaper , ReadNewsPaper)
MAPPING(ITEM_HandWrittenNote , ReadHandWrittenNote)
Scripts
Here is an example of “location script” associated to the “Market place” location from the location table
ScripMarket
WAIT(DELAY_FIRST_BUBBLE)
WHITE_BUBBLE(2)
_BUBBLE_LINE(4,100,0,"The market place")
_BUBBLE_LINE(4,106,4,"is deserted")
END
Here is a script associated to the “READ” + “NOTE” combination of keywords found in the action mapping table
_ReadHandWrittenNote
DISPLAY_IMAGE(LOADER_PICTURE_HANDWRITTEN_NOTE)
WAIT(50*2)
INFO_MESSAGE("That could be useful...")
WAIT(50*2)
INFO_MESSAGE("...if I can access it!")
WAIT(50*2)
UNLOCK_ACHIEVEMENT(ACHIEVEMENT_READ_THE_NOTE)
END_AND_REFRESH
Run time
The way all that goes together is quite simple:
- The game maintains a global location where the player is
- When the player moves into a location
- The matching picture is loaded from disk
- The associated script for that location is executed
- The engine asks the player what they want to do
- When the player enters a series of commands
- The parser isolate each keyword (space separated) and tries to find a matching value in the word mapping table
- It searches in the action mapping table for any matching value for the first keyword
- It runs the associated script
And that’s about it, the scripts themselves are relatively basic and can do the following:
- Basic flag checking to validate the state of an item or their position in the world
- Simple conditional and unconditional jumps
- Delays
- Commands to increase the player score, trigger achievements and game over conditions
- Set of graphical commands to show pictures and graphic overlays on top of pictures
- Set of textual commands to print texts and error messages
You can read more about the nitty gritty details on the documentation of the project on GitHub
I hope that was interesting!
Encounter HD (Oric)
A young girl has been kidnapped, you have two hours to find and free her.
Status | In development |
Author | DefenceForce |
Genre | Visual Novel, Adventure |
Tags | Animals, Detective, Text based |
More posts
- Less than two weeks to go!3 days ago
- October 2024 video50 days ago
- The remaining 80%52 days ago
- Playtesting has started74 days ago
- Milestone!79 days ago
- Hardware performance testing87 days ago
- September project status update97 days ago
- Better item managementJul 19, 2024
- Graphic updateJun 27, 2024
Leave a comment
Log in with itch.io to leave a comment.