Home Reference Source

The Basics

In this guide:

The Maze

For our first game, we will create a simple maze for the player to solve. You won't need to write any JavaScript functions for this section.

To help us keep things straight, here's a map of the maze we'll create:

in +-+-+-+-+
 --> |   | |
   + + + + +
   |   |   |
   + +-+ +-+
   |   |   |
   +-+ + + +
   |   | | --> out
   +-+-+-+-+

All content is written in HTML and Markdown. You should read up on Markdown before continuing. Try it live in your browser here.

Introducing situations

A Jumbo Grove game is made of situations. You can also think of them as "rooms," but we use the word "situation" because all they are is some hypertext shown to the player, and a decision to be made (which link to click).

The bare minimum for a Jumbo Grove game is an id that uniquely identifies your game, and at least one situation:

jumbogrove.jumbogrove('#game', {
  id: 'maze-game-2000',
  situations: [
    {
      id: 'start',  // the situation with id=start is how the game begins
      content: `
        You are standing at the entrance of a maze.
      ` // <- backticks let you write multi-line strings.
        //    You can indent multi-line strings as much as you want.
        //    Jumbo Grove will remove the extra spaces.
    }
  ]
});

If you're not an experienced JavaScript programmer, you might be doing a lot of copying and pasting. That's OK! You might need to ask a lot of questions. That's also OK!

In fact, here is an officially sanctioned copy-paste template for situations:

{
  id: 'REPLACE THIS',
  tags: [],  // like ['maze-room', 'castle']
  autosave: false,
  displayOrder: 0,  // determines placement in choices list (higher = farther down)
  optionText: 'Go to the copy-pasted situation',
  content: `
    # Title, if you want

    Some more text

    [Append some text](>write:text_to_append)

    [Replace this with some text](>replaceself:text_to_replace)

    [Go to another situation](@some-situation-id)

    [Perform an action](>some_action)
  `,
  snippets: {
    text_to_append: "Here is some more text.",
    text_to_replace: "I'm a little teapot"
  },
  choices: ['#maze-room', 'some-situation-id'],
  actions: {
    some_action: function(model, ui, action) {
      console.log("You did a", action);
    }
  }
}

It doesn't include absolutely everything, but it does have the most common fields.

Laying out the maze

Let's assign letters to each square in the maze:

   +-+-+-+-+
->  A|B C|D|
   + + + + +
   |E F|G H|
   + +-+ +-+
   |I J|K L|
   +-+ + + +
   |M N|O|P ->
   +-+-+-+-+

Looking at the upper left, you can see that the entrance of the maze leads to situation A.

There are two ways to write that out. Here's Option 1:

jumbogrove.jumbogrove('#game', {
  id: 'maze-game',
  situations: [
    {
      id: 'start',  // the situation with id=start is how the game begins
      content: `
        You are standing at the entrance of a maze.

        [Enter the maze](@A)
      `
    },
    {id: 'A', content: "You are standing in cell A.", optionText: "Enter the maze"}
  ]
});

When you write a Markdown link whose target starts with @, it links to the situation with that ID instead of behaving like a normal HTML link. [Enter the maze](@A) creates a link that moves the player to situation 'A'. Whenever you show the user any HTML, Jumbo Grove scans it for specially formatted links like this.

Here's Option 2:

jumbogrove.jumbogrove('#game', {
  id: 'maze-game',
  situations: [
    {
      id: 'start',  // the situation with id=start is how the game begins
      content: `
        You are standing at the entrance of a maze.
      `,
      choices: ['A']
    },
    {id: 'A', content: "You are standing in cell A.", optionText: "Enter the maze"}
  ]
});

Instead of writing out the link in our content string, we provide a list of IDs that are OK to go to next, and the situation itself says what the choice text should say.

Here's the maze game so far, running right in this page:

Here's the whole maze wired up the same way. The solution is AEFBCGKLP.

jumbogrove.jumbogrove('#game', {
  id: 'maze-game',
  situations: [
    {
      id: 'start',  // the situation with id=start is how the game begins
      content: `
        You are standing at the entrance of a maze.
      `,
      choices: ['A']
    },
    { id: 'A', optionText: "Enter the maze",
      content: "You are standing in cell A.",
      choices: ['E'] },
    { id: 'B', optionText: "Go to B", content: "You are standing in cell B.",
      choices: ['F', 'C']},
    { id: 'C', optionText: "Go to C", content: "You are standing in cell C.",
      choices: ['B', 'G']},
    { id: 'D', optionText: "Go to D", content: "You are standing in cell D.",
      choices: ['H']},
    { id: 'E', optionText: "Go to E", content: "You are standing in cell E.",
      choices: ['A', 'I', 'F']},
    { id: 'F', optionText: "Go to F", content: "You are standing in cell F.",
      choices: ['E', 'B']},
    { id: 'G', optionText: "Go to G", content: "You are standing in cell G.",
      choices: ['C', 'K', 'H']},
    { id: 'H', optionText: "Go to H", content: "You are standing in cell H.",
      choices: ['G', 'D']},
    { id: 'I', optionText: "Go to I", content: "You are standing in cell I.",
      choices: ['E', 'J']},
    { id: 'J', optionText: "Go to J", content: "You are standing in cell J.",
      choices: ['I', 'N']},
    { id: 'K', optionText: "Go to K", content: "You are standing in cell K.",
      choices: ['G', 'O', 'L']},
    { id: 'L', optionText: "Go to L", content: "You are standing in cell L.",
      choices: ['K', 'P']},
    { id: 'M', optionText: "Go to M", content: "You are standing in cell M.",
      choices: ['N']},
    { id: 'N', optionText: "Go to N", content: "You are standing in cell N.",
      choices: ['M', 'J']},
    { id: 'O', optionText: "Go to O", content: "You are standing in cell O.",
      choices: ['K']},
    { id: 'P', optionText: "Go to P", content: "You are standing in cell P.",
      choices: ['L', 'win']},
    {
      id: 'win',
      optionText: 'Exit the maze',
      content: `
        You exit the maze victorious!
      `
    }
  ]
});

Introducing Tags

When you specify some choices for your situation, you can include a hashtag to refer to a group of situations.

In this case, the living-room situation would provide choices for both the bathroom and bedroom situations:

jumbogrove.jumbogrove('#game', {
  id: 'house-game',
  initialSituation: 'living-room',  // use this instead of 'start' if you want
  situations: [
    {
      id: 'living-room',
      optionText: 'Go to the living room',
      content: "The living room has a couch and a TV.",
      choices: ['#from-living-room']
    },
    {
      id: 'bathroom',
      tags: ['from-living-room'],
      optionText: "Enter the bathroom",
      displayOrder: 2,  // show up AFTER the bedroom in the choices list
      content: "The bathroom contains a sink and a toilet.",
      choices: ['living-room']
    },
    {
      id: 'bedroom',
      tags: ['from-living-room'],
      displayOrder: 1,  // show up BEFORE the bathroom in the choices list
      optionText: "Enter the bedroom",
      content: "The bedroom is filled by a queen sized bed and a dresser.",
      choices: ['living-room']
    },
  ]
})

Maze game teleporter pads

We can use this feature to add teleporter pads to a few cells of our maze. Any teleporter room can send the user to any other teleporter room. If we have lots of teleporters, we don't want to have to individually connect them all!

The marked squares will contain teleporters:

in +-+-+-+-+
->   |   |D|
   + + + + +
   |   |   |
   + +-+ +-+
   |   |  L|
   +-+ + + +
   |M  | |  -> out
   +-+-+-+-+
jumbogrove.jumbogrove('#game', {
  id: 'maze-game',
  situations: [
    {
      id: 'start',  // the situation with id=start is how the game begins
      content: `
        You are standing at the entrance of a maze.
      `,
      choices: ['A']
    },
    { id: 'A', optionText: "Enter the maze",
      content: "You are standing in cell A.",
      choices: ['E'] },
    { id: 'B', optionText: "Go to B", content: "You are standing in cell B.",
      choices: ['F', 'C']},
    { id: 'C', optionText: "Go to C", content: "You are standing in cell C.",
      choices: ['B', 'G']},
    {
      id: 'D',
      tags: ['teleporter'],
      optionText: "Go to D",
      content: "You are standing in cell D. There is a teleporter here.",
      choices: ['H', '#teleporter']
    },
    { id: 'E', optionText: "Go to E", content: "You are standing in cell E.",
      choices: ['A', 'I', 'F']},
    { id: 'F', optionText: "Go to F", content: "You are standing in cell F.",
      choices: ['E', 'B']},
    { id: 'G', optionText: "Go to G", content: "You are standing in cell G.",
      choices: ['C', 'K', 'H']},
    { id: 'H', optionText: "Go to H", content: "You are standing in cell H.",
      choices: ['G', 'D']},
    { id: 'I', optionText: "Go to I", content: "You are standing in cell I.",
      choices: ['E', 'J']},
    { id: 'J', optionText: "Go to J", content: "You are standing in cell J.",
      choices: ['I', 'N']},
    { id: 'K', optionText: "Go to K", content: "You are standing in cell K.",
      choices: ['G', 'O', 'L']},
    {
      id: 'L',
      tags: ['teleporter'],
      optionText: "Go to L",
      content: "You are standing in cell L. There is a teleporter here.",
      choices: ['K', 'P', '#teleporter']
    },
    {
      id: 'M',
      tags: ['teleporter'],
      optionText: "Go to M",
      content: "You are standing in cell M. There is a teleporter here.",
      choices: ['N', '#teleporter']
    },
    { id: 'N', optionText: "Go to N", content: "You are standing in cell N.",
      choices: ['M', 'J']},
    { id: 'O', optionText: "Go to O", content: "You are standing in cell O.",
      choices: ['K']},
    { id: 'P', optionText: "Go to P", content: "You are standing in cell P.",
      choices: ['L', 'win']},
    {
      id: 'win',
      optionText: 'Exit the maze',
      content: `
        You exit the maze victorious!
      `
    }
  ]
});

The user can now take a more circuitous route to the exit: AEIJNMLKOP. Here's the running code:

Clearing the Transcript

If you don't like the continuous scrolling style and prefer something more like Twine, you can add clear: true to your situation. Here's the maze example, with each situation clearing the screen.

jumbogrove.jumbogrove('#game' {
  id: 'maze-game',
  situations: [
    {
      id: 'start',  // the situation with id=start is how the game begins
      content: `
        You are standing at the entrance of a maze.
      `,
      choices: ['A']
    },
    { id: 'A', optionText: "Enter the maze",
      clear: true,
      content: "You are standing in cell A.",
      choices: ['E'] },
    { id: 'B', optionText: "Go to B", content: "You are standing in cell B.",
      clear: true,
      choices: ['F', 'C']},
    { id: 'C', optionText: "Go to C", content: "You are standing in cell C.",
      clear: true,
      choices: ['B', 'G']},
    {
      id: 'D',
      tags: ['teleporter'],
      optionText: "Go to D",
      clear: true,
      content: "You are standing in cell D. There is a teleporter here.",
      choices: ['H', '#teleporter']
    },
    { id: 'E', optionText: "Go to E", content: "You are standing in cell E.",
      clear: true,
      choices: ['A', 'I', 'F']},
    { id: 'F', optionText: "Go to F", content: "You are standing in cell F.",
      clear: true,
      choices: ['E', 'B']},
    { id: 'G', optionText: "Go to G", content: "You are standing in cell G.",
      clear: true,
      choices: ['C', 'K', 'H']},
    { id: 'H', optionText: "Go to H", content: "You are standing in cell H.",
      clear: true,
      choices: ['G', 'D']},
    { id: 'I', optionText: "Go to I", content: "You are standing in cell I.",
      clear: true,
      choices: ['E', 'J']},
    { id: 'J', optionText: "Go to J", content: "You are standing in cell J.",
      clear: true,
      choices: ['I', 'N']},
    { id: 'K', optionText: "Go to K", content: "You are standing in cell K.",
      clear: true,
      choices: ['G', 'O', 'L']},
    {
      id: 'L',
      tags: ['teleporter'],
      optionText: "Go to L",
      clear: true,
      content: "You are standing in cell L. There is a teleporter here.",
      choices: ['K', 'P', '#teleporter']
    },
    {
      id: 'M',
      tags: ['teleporter'],
      optionText: "Go to M",
      clear: true,
      content: "You are standing in cell M. There is a teleporter here.",
      choices: ['N', '#teleporter']
    },
    { id: 'N', optionText: "Go to N", content: "You are standing in cell N.",
      clear: true,
      choices: ['M', 'J']},
    { id: 'O', optionText: "Go to O", content: "You are standing in cell O.",
      clear: true,
      choices: ['K']},
    { id: 'P', optionText: "Go to P", content: "You are standing in cell P.",
      clear: true,
      choices: ['L', 'win']},
    {
      id: 'win',
      optionText: 'Exit the maze',
      clear: true,
      content: `
        You exit the maze victorious!
      `
    }
  ]
});

That's most of what you can do without writing any JavaScript functions.