Jeremy Davis
Jeremy Davis
Sitecore, C# and web development
Article printed from: https://blog.jermdavis.dev/posts/2025/textadventure-world

Text adventures: Starting with a world

Lets pretend it's the late 80s and type words to play games!

Published 03 November 2025
Text Games C# ~4 min. read

As you might guess from someone who's been writing a blog for a decade, text adventures were something I really liked back in the day. I spent a lot of time on classic Infocom games like The Hitchiker's Guide to the Galaxy. But what if you wanted to build your own as a .Net developer? This blog series has some suggestions...

For many people, the answer to this question might be something like "Go and play with Twine", but being a C# nerd, for me it's definitely more fun to implement it in code. So this series of posts will cover some basics of a simple approach you might use to get an adventure engine started.

What's in a world? url copied!

The game needs some sort of world model to descibe where you can be plus what you can see and do. What things are in that world? Well one model might include:

flowchart TD
    World --> Rooms
    World --> Exits
    World --> Items
    World --> Characters

					

Those entities are:

  • Rooms
    Locations that a player can go to. Might represent literal rooms in a building, or more esoteric spaces like "a path" or the inside of a car.
  • Exits
    The mesh of connections between rooms. Generally described by a direction that the user can travel from one room to another. Could be a compass point like "east" or something more abstract like "swim" if you're on a beach.
  • Items
    Things that you can find in the world. Might be small stuff you can pick up, or bigger stuff you can interact with. But generally items don't move or do things unless the player makes them.
  • Characters
    Other people or creatures in the world. Things which you might talk to, might move around etc. They might interact with the player.

(Technically you could make Characters and Items the same thing - but it can be a useful distinction, especially if you move into multi-player games)

And you can use those entity types to build up a game world. As a simple examle:

flowchart TD
  beach["Room:
The beach"] sea["Room:
The sea"] gull["Item:
A gull"] beach -- Exit
south --> sea sea -- Exit
north --> beach beach --- gull

Each of these thing is an entity in the world model - and they'll all share some core common properties:

  • A name. When the player types instructions that relate to an entity, you need to be able to identify the right one.
  • An article to use when describing them in output. Things like "the", "a", "some" etc. It's generally easier to have these stored separately as it makes it easier to parse input if they're not part of the name.
  • A description to display when the player looks at the entity.

So the individual types can derive from a basic Entity class, and add whatever extras they need.

  • Rooms have exits, characters and items
  • Characters have a room and items
  • Items have either a room or a character

So you might end up with simple classes for these things that look a bit like:

public abstract class Entity
{
    public string Article { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
}

public class Room : Entity
{
    public Dictionary<string, Room> Exits { get; } = new();
    public List<Character> Characters { get; } = new();
    public List<Item> Items { get; } = new();
}

					

And a world class can sit at the root of this model, holding the set of all the things defined:

public class World
{
    public List<Room> Rooms { get; } = new();
    public List<Character> Characters { get; } = new();
    public List<Item> Items { get; } = new();

    public Player Player { get; set; }
}

					

(The Player here is a subclass of Character - which can add some stuff only the player needs)

This isn't everything the model of the world needs - but commands a player can use, and behaviours that entities can display during the game will get covered later in the series.

Making something with that url copied!

Once you have the types to represent all the entities in your world you can start creating somewhere for your player to explore. For example:

var w = new World();

var beach = new Adventure.Entities.Room()
{
    Article = "The",
    Name = "beach",
    Description = "A wide sandy beach. The waves lap gently to the south, and a path winds off through the sand dunes to the north. Seagulls squawk noisily above you."
};
w.Rooms.Add(beach);

var gull = new Adventure.Entities.Item()
{
    Article = "A",
    Name = "gull",
    Description = "It's a black-headed gull. It is very noisy, and it is clearly scanning the area looking for chips to steal."
};
gull.Room = beach;
w.Items.Add(gull);
beach.Items.Add(gull);

var sea = new Adventure.Entities.Room()
{
    Article = "The",
    Name = "sea",
    Description = "You're standing in the shallows, with waves lapping gently about you. It is icy cold. Behind you the beach looks much warmer."
};
w.Rooms.Add(sea);

beach.Exits.Add("south", sea);
sea.Exits.Add("north", beach);

					

The code is creating each of the rooms, items and exits between the rooms and configuring them. They need to be added to the world's collections (so they can be looked up later if required) and they also need to be interconnected so that when you process any particular room to display it you can easily determine what stuff needs showing.

(In a fully-fledged engine you'd probably treat the definition of the world as data rather than as code, because you need to be able to load and save game state, or to let the user change between different games - but for a simple example this approach will do)

For ease of reading/writing the code, places like this where you need to create stuff and then perform some required steps can be improved with some helper methods. For example you might create helpers for new rooms and items:

public static class EntityHelpers
{
    public static Room CreateRoom(this World world, string article, string name, string description = "")
    {
        var room = new Room() { Article = article, Name = name, Description = description };
        world.Rooms.Add(room);
        return room;
    }

    public static Item CreateItem(this World w, string article, string name, string description = "")
    {
        var itm = new Item() { 
            Article = article,
            Name = name,
            Description = description
        };
    
        w.Items.Add(itm);
    
        return itm;
    }

    public static Room AddItemInRoom(this Room rm, Item itm)
    {
        rm.Items.Add(itm);
        itm.Room = rm;
        return rm;
    }

    public static Room AddExit(this Room fromRoom, string direction, Room toRoom)
    {
        fromRoom.Exits.Add(direction, toRoom);

        return fromRoom;
    }
}

					

And these can allow chained operations, which read a little easier:

var world = new World();

var gull = world
    .CreateItem("A", "gull", "It's a black-headed gull. It is very noisy, and it is clearly scanning the area looking for chips to steal.");

var beach = world
    .CreateRoom("The", "beach", "A wide sandy beach. The waves lap gently to the south, and a path winds off through the sand dunes to the north. Seagulls squawk noisily above you.")
    .AddItemInRoom(gull);

var sea = world
    .CreateRoom("The", "sea", "You're standing in the shallows, with waves lapping gently about you. It is icy cold. Behind you the beach looks much warmer.");

world
    .AddPath(beach, "south", sea)
    .AddPath(sea, "north", beach);

					

And with that you can model the environment for your adventure. The next part of the series will look at how the player can start to interact with the world. But meanwhile, there's example code for the whole of a simple game available on GitHub, so you can have a play and experiment with the code if you want.

↑ Back to top