Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags
(2 edits)

Update 4 - Monster Factory

I've started programming the game in earnest now. I have a basic monster up and running, some debug functions, and a few other bits and pieces as I think of them. I'll just talk about the monster for now, and save the rest for another time.

First, I should note that when I say I've programmed things, what I usually mean is that I've adapted code from the documentation. Inform 7's documentation comes with a "Recipe Book," full of example code showing you how to program things like an NPC that follows the player. I believe most of these are written by Emily Short. I think they're there to be used (at least I hope so), so I have done, with comments in my source code giving credit where it's due.

Here's the first part of my monster code:

The monster is an animal.
The monster is in Lair.
The monster is neuter.
Understand "wendigo" or "wendifaux" or "yeti" or "snowman" or "bigfoot" or "sasquatch" or "beast" or "creature" or "thing" as the monster.
Description of the monster is "Like you, but colder."

(Sorry, all the code blocks are walls of text in this update. Itch.io's post formatting seems to think that empty line breaks in code blocks are just suggestions.)

One big advantage of Inform 7's natural language code is that it's completely readable without much explanation. But there are a fewdesign choices here to go through.

The monster is a "neuter animal," meaning a being referred to as "it." Inform 7 has a built-in understanding of "animal," "man" and "woman" as types of person, which in turn is a type of thing which can probably be talked to and which probably can't be picked up and carried around. I thought it might be interesting to define the monster explicitly as more human, since the wendigo in folklore seems to be something like an emaciated frostbitten human. (Hence the vague description field, which will appear when the player types something like "examine monster".) But a person, whether animal, man or woman, is always tied to a binary "male/female" property, and you can only escape that by making it an animal and adding a neuter property (and even then, Inform 7 might consider it male if you run a function finding all male people in the game.)

(Yes, this means there's no native support for non-binary people in Inform 7. Yes, this sucks. I'm hoping the next release of Inform 7, which was due last autumn, will address this.)

Also, that long "understand..." sentence is trying to catch different terms the player might use to address the monster. As well as "examine monster," you can now use "examine wendigo," "examine yeti"... I appreciate that this conflates the wendigo, yeti and bigfoot, and that's no good, but I'm trying to make life easier for the player who sees a monster in a cold forest and makes automatic assumptions.

The rest of my monster code is the start of a simple state machine. I create tags for the monster here, and a simple AI that will send it towards the player.

Section - Monster behaviour states
Behaviour is a kind of value. The behaviours are chasing, feasting, and aggressive.
The monster has a behaviour. The monster is chasing.
Section - Monster pursuing the player
[Adapted from Inform Documentation example 39, "Van Helsing"]
Every turn when the location of the monster is the location of the player:
    if the monster is aggressive:
        say "The monster [one of]brays.[or]claws at you![purely at random]";
    otherwise:
        now the monster is aggressive.
Every turn when the location of the monster is not the location of the player:
    if the monster is not chasing:
        now the monster is chasing;
    let the way be the best route from the location of the monster to the location of the player;
    try the monster going the way.

In the "chasing" state, the monster goes after the player. "Best route from [x] to [y]" is an automatic pathfinding algorithm within Inform 7, and I love that it exists, because I was dreading having to do the pathfinding code myself.

You can make doors in Inform 7 by putting them between rooms (e.g. "The front door is north of the Driveway and south of the Porch"). This is how you can make simple find-the-key-to-unlock-the-door puzzles. Oddly enough, the pathfinding code won't use doors by default, unless you specify otherwise (which is as easy as adding "using doors" to your code). This is perfect for me, because it gives me an easy way to make routes that the player can use but the monster can't. For example, I could say that some stepping stones across the river are a door, albeit one that the player can't close, and the monster will have to go around instead of following the player across the,.

In the "aggressive" state, the monster will attack the player. That is, it will print some text which says it's attacking you, but there'll be no real effect because I haven't programmed player health yet. If you look carefully, you might notice that when the player moves, the monster flips from aggressive to chasing, follows the player, then flips back to aggressive in the same turn. This seems inefficient, but it stops the monster attacking the player immediately in that same turn. The monster sticks to the player like glue right now, so this will give the player a little leeway.

It's random whether the monster will "claw at you" or whether it will just roar. I think this is how I want my monster to behave in practice. It exerts enough pressure that the player will be safer escaping it, but the brave player can gamble on the monster not attacking that turn in order to do some puzzle solving. The randomness helps to instill a little suspense into the game - it's looking increasingly like the player will have to lure and manipulate the monster to solve puzzles, which will require predictable monster behaviour, so I want to temper that with a little danger.

The thief from Zork I is basically the model for my monster at this point. He attacks and steals from players who hang out in the same room as him, and the player can either safely flee or risk their life and inventory to try to do something else. I think that's about as random as you can get without being too frustrating.

My monster also has a "feasting" state, which is unused for now. (I can't call it "eating," because Inform 7 stops you doing that so that it won't get confused with the "eating" action the player can do.) I want to give the player a supply of meat, which can be used to distract the monster for a few turns.

I don't know how I'm going to do this yet, exactly. I don't want to give the player unlimited meat because that could be abused easily, if the player just distributes armfuls of meat across the world so that the monster can't do anything. But I'm keen to avoid limited resources, because that could make it easy to render the game unwinnable if the player runs out of meat before running out of puzzles. But maybe that's fine, since the game will be small and probably winnable within a few minutes if the player knows what to do? That is, having to restart the game won't ever set you back too far. I have to think harder about this.

Thank you for reading or skimming all the text. To round off, here's a sample of what the game looks like so far, also showing off the automatic debug function I made to make sure the monster is moving. ("Z" is just a shortcut for "wait".)

Wendigo
An Interactive Fiction by wisprabbit
Release 1 / Serial number 200127 / Inform 7 build 6M62 (I6/v6.33 lib 6/12N) SD
Campsite
>e
Forest
(Monster location: Cave Entrance; state: chasing.}
>z
Time passes.
(Monster location: Clearing; state: chasing.}
>z
Time passes.
(Monster location: Cliff; state: chasing.}
>z
Time passes.
The monster arrives from the north.
(Monster location: Forest; state: aggressive.}
>z
Time passes.
The monster claws at you!
(Monster location: Forest; state: aggressive.}
>n
Cliff
The monster arrives from the south.
(Monster location: Cliff; state: aggressive.}
>z
Time passes.
The monster brays.
(Monster location: Cliff; state: aggressive.}
>w
Forest
The monster arrives from the east.
(Monster location: Forest; state: aggressive.}

Whoops I've just noticed that I'm closing the monster status report with a curly brace instead of a regular bracket. I don't need to fix these because it won't be in the final game, but it will annoy me forever if I don't.