adventure-engine

0.6.17 • Public • Published

Simple text-based adventure game engine for NodeJS.

Setting up repl.it

  1. Go to repl.it and make an account. You can sign up using Google.
  2. Click on + new repl. Select NodeJS, make new repl.
  3. Give the game a name and a brief description.

Creating the World

  • See the world.json file in the example project for an example of how to define the world.
  • In your repl.it window, in the files section create a new file named world.json. You will create your game world in this file.
  • For a quick lesson on the JSON format, check out this nice tutorial
  • To error-check your .json file, use this handy tool.

World File Structure

  • The world consists of one large JSON object (dictionary) with the following structure:
{
  "welcome": {
    "description": "Optional description for game. Presented upon starting.",
    "entrance": "optional-name-of-entrance-room-defaults-to-entrance"
  },
  "unique-room-name": {
    (See "Defining a Room" section below.)
  },
  "unique-room-name": {
    ...
  },
  ... any number of rooms
  "end":
    "description": "Optional Text to display upon quitting."
  }
}

Defining an Individual Room

  • You should define individual rooms according to the following structure:
...
"unique-room-name": {
  "description": "Description text for room. Presented upon entering.",
  "exits": {
    "north": "optional-room-to-the-north-name",
    "south": "optional-room-to-the-south-name",
    ...
    "up": "optional-room-up-name",
    "down": "optional-room-down-name"
  }
  "things": {
    "unique-thing-name": {
      "description": "Description text for thing. Presented upon inspection.",
      "attributes": {
        The following optional attributes are built into the game engine:
        "hidden": "optional-boolean-hidden-state",
        "stationary": "optional-boolean-stationary-can't-be-taken",
        "uses": "optional-integer-number-of-times-can-be-used-in-attack",
        "health": "optional-integer-1-to-10-amount-of-health-of-character",
        "agression": "optional-integer-1-to-10-chance-character-attacks-player",
        "accuracy": "optional-integer-1-to-10-chance-character-or-weapon-hits",
        "damage": "optional-integer-1-to-10-amount-of-damage-character-or-weapon-inflicts",
        ...any other attributes you define for your own game.
        You can add additional attributes to things using setAttribute function
        (see below).
      }
    }
  }
}
...

Adding Artwork

Pictures are optional, but add some life to your game. Start by looking at the pictures from the example project in the pictures folder for examples of a picture files. This amazing program can be used to convert images to ASCII art.

  • To add ASCII art (text-based) pictures to your game, in the repl.it files section add a new folder named pictures.
  • Inside of the pictures folder add the individual room or thing artwork files.
  • Room picture files should be named as follows: room-name.txt, with room name being the name of the room.
  • Thing picture files should be named as follows: thing-name.txt, with thing name being the name of the thing.
  • Room pictures are displayed when a room is entered or on a look command.
  • Thing pictures are displayed when a thing is inspected.
  • Pictures should be no larger than 80 characters wide by 30 characters in order to be displayed correctly in the terminal.
  • If available, title.txt will be displayed as the opening screen (before user presses enter).
  • If available, welcome.txt will be displayed as the welcome screen (after user presses enter).
  • If available, end.txt will be displayed as the quit screen.
  • If available, credits.txt will be displayed as the credits screen.

Adding Descriptions

Descriptions can be added as properties of the rooms or things in the world.json map or they can be individual text files located in the descriptions folder.

  • To add a description file, name it thing-name.txt or room-name.txt and store it in the descriptions folder.
  • You can use template strings within the descriptions by enlosing a string with brackets like so: {{string}}. These strings will be replaced when the description is used in the game. In your code you will need to register these strings by using the API function: setTemplateString(string, value). See the welcome.txt file in the descriptions folder of the example project for an example of how to do this.

Template Strings

Templates can be used in descriptions and pictures and allows for simply replacements to be made. A template string is defined as {{string-name}} where {{string-name}} will be replaced by the value that it is set with using the setTemplateString command.

Text Display Control Codes

Control codes are available for advanced displaying of text or animation as follows:

%c  - clear the screen
%w  - wait for the user to press any key
%p# - pause for some amount of time where # is 0-9 in 100 ms intervals, 0 is 1 second
%r# - repeat some number of times where # is 0-9 where 0 repeats forever
%n# - add a number of blank lines where # is 0-9 where 0 is 10 lines

Adding Music

Old Skool style 8-bit music can be added to the game using "song" files. These are text files locatied in the songs folder. Songs files will have the name of a room or thing and they will be played when the room is entered or the thing is inspected. See the welcome.txt file in the songs folder of the example project for an example of how to do this.

  • To add a song file, name it room-name.txt or thing-name.txt and store it in the songs folder.
  • Use the following format for creating a song:
  ! Exlamation mark starts a line comment
  ! Note Duration, Note Duration, Note Duration, Note Duration...
    C#4 4,         Eb4 1,         D3 16,         R 4, 
  ! Where a note is:
  !  [note-letter][note-sharp-flat]?[note-octave]?[ ][note-duration][,]
  ! Where R is a rest/pause
  ! Control codes are as follows:
  !  %t# controls the tone for  where # is 0-3 depending on the desired waveform
  !  %r# controls the number of repeats where # is 0-9, 0 being repeat forever
  ! Each event be it a note or control code MUST be followed by a comma!

 Note durations are as follows:
  0 = triplet, 1 = sixteenth, 2 = eighth, 3 = dotted eighth, 4 = quarter
  5 = 5/16 note, 6 = dotted quarter, 7 = dotted dotted quarter, 8 = half note
  12 = dotted half note, 16 = whole note

Writing the Code

See the index.js file in the example project for an example on coding using the adventure-engine.

  • You game code should be written in the repl.it index.js file.
  • A lot of your code will be written in the form of callback functions that respond to different events that occur in the game. See the callback section for more information on this.
  • The basic program template is as fallows.
    Note that all of your functions should be defined INSIDE of a function called game:
// This line is necessary and starts the game on port 3000
require("adventure-engine").init(game, 3000);

function game() {
  // Your code here
  ...
}

Global API

The following functions/methods are available globally as part of the API:

// Register a callback for responding to different game events
addCallback(callback-function);  
// OR
addCallback(callback-name, function);

// Remove a callback function (prevents game from using that function unless it is re-registered)
removeCallback(callback-name);

// End the game by presenting the end picture/description and quitting the game
end();

// Get a thing object with thing-name from the world, optionally include room-name to restrict getting the thing from a specific room
var thing = getThing(thing-name, optional-room-name);

// Get a room object with room-name from the world
var room = getRoom(room-name);

// Get the player's inventory object
var inventory = getInventory();

// Read a line of text from the console, printing the prompt beforehand
var text = readLine(prompt);

// Print a line of text to the console
println(text);

// Print several lines of text with pauses in between based on ".." being present in text
printPaused(text);

// Print the description of a room or thing to the console
printDescription(room-or-thing-name-or-filename);

// Print the picture of a room or thing to the console
printPicture(room-or-thing-name-or-filename);

// Clear the console
clearScreen();

// Play a song file on a channel (0 or 1)
playSong(text-or-filename, optional-channel-number);

// Stop playing a song on a channel
stop(optional-channel-number);

// Mute the sound
muteSound();

// UnMute the sound
unmuteSound();

// Get a random true value based on a certain percentage
var isTrue = getRandomChance(percentage, optional-scale);

// Get a random integer between a set range
var intVal = getRandomInt(lower-limit, upper-limit);

// Get the current high scores list from a file as an array of object in the form:
// [ { name: "Dave", points: 10 }, { name: "Sara", points: 20 } ...]
var highScores = loadHighScores();

// Save the current high score to a file
saveHighScore(name, points, optional-max-scores);

// Add a command to the player's command menu
addCommand(command-name-or-function);
// OR
addCommand(command-name, function);

// Remove a command from the player's command menu
removeCommand(command-name);

// Sets the value for a string used within a description template for example {{string-name}}, the {{string-name}} will be replaced with the supplied value.
setTemplateString(string-name, value);

Room Object API

The following functions/methods are part of the room object API:

// First get the object for the room
var room = getRoom(room-name);

// Get the text description for the room
var text = room.getDescription();

// Set the text description for the room
room.setDescription(text);

// Print the room's current description
room.printDescription();

// Get the text (ascii) picture for the room
var text = room.getPicture());

// Set the text (ascii) picture for the room
room.setPicture(text);

// Print the room's current picture
room.printPicture();

// Get an array listing of the names of the things in the room
var thingNames = room.listThings();

// Determine if the room contains a certain thing name
var roomHasThing = room.contains(thing-name);

// Add a thing object to the room (uses the same object format as in world.json)
addThing(thing-name, thing-object);

// Get a thing object from the room
var thing = room.getThing(thing-name);

// Remove a thing from the room, returns true/false if thing was succesfully removed
var wasThingRemoved = room.removeThing(thing-name);

// Get an array listing of the naems of the exits in the room
var exitNames = room.listExits();

// Add an exit to the room
room.addExit(exit-name, to-room-name);

// Remove and exit from the room, return true/false if exit was succesfully removed
room.removeExit(exit-name);

// Get an array listing of the rooms adjacent to this one based on the exits available
var roomNames = room.listAdjacentRooms();

// Get the exit for a room that is adjacent to this one based on the room name
var exitName = room.getExitForRoom(adjacent-room-name);

Thing Object API

The following functions/methods are part of the room object API:

// First, get the object for the thing.
// If room-name is not provided, search is global
// If room-name is provided, search will be limited to room and player's inventory
var thing = getThing(thing-name, optional-room-name);

// Get the text description for the thing
var text = thing.getDescription();

// Set the text description for the thing
thing.setDescription(text);

// Print the thing's current description
thing.printDescription();

// Get the text (ascii) picture for the thing
var text = thing.getPicture());

// Set the text (ascii) picture for the thing
thing.setPicture(text);

// Print the thing's current picture
thing.printPicture();

// Get an array listing of the thing's attributes
var attributeNames = thing.listAttributes();

// Get the value of a thing's attribute given its name
var attribute = thing.getAttribute(attribute-name);

// Set the value of a thing's attribute given its name and value
thing.setAttribute(attributeName, value);

// Determine if the thing is stationary based on its stationary attribute
var isStationary = thing.isStationary();

// Determine if the thing is visible based on its hidden attribute
var isVisible = thing.isVisible();

// Set the thing's hidden attribute to true
thing.hide();

// Set the thing's hidden attribute to false
thing.reveal();

// Determine if the thing is alive by checking that health attribute > 0
var isAlive = thing.isAlive();

// Subtract from the thing's health attribute by a certain amount, limit to 0
thing.injure(amount);

// Add to the thing's health attribute by a certain amount, limit to 10
thing.heal(amount);

// Set thing's health attribute to 0
thing.kill()

// Move thing to another room, or through an exit
thing.move(in-direction-or-room-name);

// Determine if a thing is expired by checking that uses attribute is 0
var isExpired = thing.isExpired();

// Decrement thing's uses attribute by amount or 1 if not provided
thing.expend();

// Expire thing by setting thing's uses attribute to 0
thing.expire();

// Get thing's current location name
var locationName = thing.getLocationName();

// If thing is the player then get its inventory object, if not return undefined
var inventory = thing.getInventory();

### Inventory Object API

The following functions/methods are part of the inventory object API:

// First, get the inventory from the player
var inventory = getInventory();

// Get an array listing of the player's inventory
var thingNames = inventory.list();

// Determine if the player's inventory contains a thing given its name
var inventoryContainsThing = inventory.contains(thing-name);

// Remove a thing from the player's inventory or return false if it wasn't found
inventory.removeThing(thing-name);

// Get a thing object from the player's inventory
var thing = inventory.getThing(thing-name);

Callbacks

All callbacks need to be registerd using the addCallback(callbackName or function) function. Returning nothing or false from a callback will override the default behavior, returning true will run execute behavior.

Welcome Callbacks

  • beforeWelcome(): Called before the picture and description of the welcome screen are displayed.
  • afterWelcome(): Called after the picture and description of the welcome screen are displayed.

Basic Command Callbacks

  • onPrompt(prompt): Called before prompt displayed. Add to prompt or return a different prompt to override the default.
  • onCommand(commandName): Called before a command is run. Can be used to override/add to default command behavior.
  • onLookAt(roomName) or onLookAtRoomName(): Called before default look command output.
  • onInspect(thingName) or onInspectThingName(): Called before default inspect command output.
  • onTake(thingName) or onTakeThingName(): Called before default take command output.
  • onCarrying(): Called before default carrying command output.
  • onUse(thingName) or onUseThingName(): Called before default use command output.
  • afterUse(thingName) or afterUseThingName(): Called after _use_command.
  • onDrop(thingName) or onDropThingName(): Called before default drop command output.

Attack Command Callbacks

  • onAttack(thingName, withWeaponName) or onAttackThingName(withWeaponName): Called before running an attack on a thing and before default attack command output.
  • onAttackUsing(weaponName, thingName) or onAttackUsingWeaponName(thingName): Called before running an attack on a thing and before default attack command output.
  • onExpired(weaponName) or onExpiredWeaponName(): Called after a weapon has just expired.
  • afterHit(thingName, damage) or afterHitThingName(damage): Called after a thing has been hit in an attack by the player.
  • onKilled(thingName, usingWeaponName) or onKilledThingName(usingWeaponName): Called before a thing has been killed by the player.
  • afterKilled(thingName, usingWeaponName) or afterKilledThingName(usingWeaponName): Called after a thing has been killed by the player.
  • onRunAttacks(): Called before character attacks are run against player.
  • onAttackedBy(thingName) or onAttackedByThingName(): Called before a thing attacks the player.
  • onHitBy(thingName, damage) or onHitByThingName(damage): Called before a thing hits the player.
  • afterHitBy(thingName, damage) or afterHitByThingName(damage): Called after a thing hits the player.
  • onKilledBy(thingName) or onKilledByThingName(): Called before the player is killed by a thing.

Move Command Callbacks

  • onMoveTo(roomName, fromRoomName) or onMoveToRoomName(fromRoomName): Called before the player moves from one room to another.
  • onExit(fromRoomName, toRoomName) or onExitRoomName(toRoomName): Called when the player exits a room.
  • beforeEnter(roomName, fromRoomName) or beforeEnterRoomName(fromRoomName): Called before player enters a room.
  • onPrintRoom(roomName) or onPrintRoomRoomName(): Called before the default room picture and description is printed.
  • onEnter(roomName, fromRoomName) or onEnterRoomName(fromRoomName): Called before automatic look is output when entering a room.
  • afterEnter(roomName, fromRoomName) or afterEnterRoomName(fromRoomName): Called after player enters a room.

Quit Callbacks

  • onQuit(): Called before end screen is displayed.

Dependents (1)

Package Sidebar

Install

npm i adventure-engine

Weekly Downloads

1

Version

0.6.17

License

ISC

Unpacked Size

124 kB

Total Files

13

Last publish

Collaborators

  • blpiltin