Search code examples
data-structuresocamlgame-engineadventure

OCaml: design datatypes for a text adventure game


I am trying to make a simple naive text adventure game (base one this page) to learn OCaml.

The game is about making an game engine, so all the information about rooms, items ect, is store in a json file.

Sample json file would be like this:

{
  "rooms":
  [
    {
      "id": "room1",
      "description": "This is Room 1.  There is an exit to the north.\nYou should drop the white hat here.",
      "items": ["black hat"],
      "points": 10,
      "exits": [
        {
          "direction": "north",
          "room": "room2"
        }
      ],
      "treasure": ["white hat"]
    },
    {
      "id": "room2",
      "description": "This is Room 2.  There is an exit to the south.\nYou should drop the black hat here.",
      "items": [],
      "points": 10,
      "exits": [
        {
          "direction": "south",
          "room": "room1"
        }
      ],
      "treasure": ["black hat"]
    }
  ],
  "start_room": "room1",
  "items":
  [
    {
      "id": "black hat",
      "description": "A black fedora",
      "points": 100
    },
    {
      "id": "white hat",
      "description": "A white panama",
      "points": 100
    }
  ],
  "start_items": ["white hat"]
}

I've almost done the game, but on the project description page, it says two of the objectives are

  • Design user-defined data types, especially records and variants.
  • Write code that uses pattern matching and higher-order functions on lists and on trees.

However, the only user-defined datatype I made is a record type used to capture the current state of the game, I did not use tree and variant :

type state = {
  current_inventory : string list ;
  current_room      : string ;
  current_score     : int ;
  current_turn      : int ;
}

then just parse user input and use pattern matching to handle different situations.

I'm been trying to figure out how should I use variant (or polymorphic variant) and tree in my game.

Can anyone please provide some suggestions?


Solution

  • The json is inherently a tree. You may, of course just parse the json without having an in-memory representation and perform side-effectful computations as you descent though the json data to fill in hash tables with the data that you've read. This is a valid option, but it looks like that authors of the course expect, that you first read the entire json and represent it in memory as a tree, and then perform lookups on the tree.

    What concerning variants, then you should represent with a variant type the following data:

    1. movement directions: type dir = N | NE | E ...
    2. verbs type verb = Go | Take of item | Drop of item

    Also, it would be a good idea to create an abstract data types for room and items, that will guarantee that they are is actually present in the json data bases. You're using string to represent them. But this type includes all values, including those, that doesn't represent a valid identifiers, as well as those, that doesn't occur in the game description file. Inventory items are also deserve to get their own type.

    In general in languages with rich type system, you should try to express as much as possible with the type system.

    Just to be less theoretical, if I were you, then I will have the following types in my game (as a first approximation):

    type game
    type room
    type item
    type verb 
    type dir
    type treasure
    type state
    
    (** a static representation of a game (using a tree inside) *)
    module Game : sig 
      type t = game
      val from_json : string -> t option
      val start : t -> room
      val room_exits : t -> room -> (dir * room) list
    end
    
    module Room : sig
      type t = room
      val description : t -> string
      val items : t -> item list
      val points : t -> int
      val treasure : t -> treasure list
    end
    ...