Authors: Dama Correch, Jeff Miiller
What is the problem?
The aim of our project is to develop an in-depth, immersive, text-based interactive fiction game. The game will consist of a world within which players can move, explore the surroundings, interact with objects in the world through issuing short, text-based commands. As an example, players may be able to issue commands to move in particular directions, inspect particular objects more closely, pick up objects, or read particular things. In order to progress in the game, players will need to move around the map and try to find a way out of the location they are stuck in. Players will find themselves thrust into the midst of a mysterious location with a unusual, interesting history and must explore the world to learn more about it. In particular, we hope to model our game after other text-based interactive fiction games such as Zork.
In order to implement this game, we will need to accomplish several tasks. Firstly, we will need to devise a sufficiently intelligent parser that is capable of interpreting a variety of possible text-based commands that, furthermore, is also reasonably flexible (i.e. there are multiple ways to achieve the same thing) to provide players with greater ease of use. Secondly, we will need to devise a way to represent the world itself and any objects, interactive or otherwise, within each location of the world. Building a traversable graph or tree structure would likely be sufficient to complete this task. Finally, we must write the story and world within which the game will take place.
The basic functionality of the natural language parser is adapted WhatTheFunctional's HaskelAdventure repo, while game's basic functionality is original code of an interactive map that players can walk around and explore.
What is the something extra?
We have added the following extra functionality to the game.
- The ability to hold an inventory of objects and treasures picked up in the map.
- The treasures add up to a total score upon completing the game, the more points, the better you did!
- Scenes with interactive elements (for example opening doors, peeling the carpet, etc).
- An escape route as well as multiple death scenes that terminate the game depending on what the player does in each scene.
What did we learn from doing this?
What we did:
- Summary: We managed to successfully build a text-based interactive fiction game with modestly flexible natural language processing and a detailed, immersive map.
- How we did it?
- We used a basic graph structure as our map, adding descriptions and actions available at each “scene” of the map (scenes are nodes in the graph), enabling players to interact with their environment. The subgraphs are the scenes that can be accessed by players via movement (north/south/east/west).
- We also adapted our natural language parser and lexer from Laurence Emms’ Haskell Adventure parser, simplifying their code to fit our needs. The natural language parser is able to recognize pre-specified (i.e. each scene contains actions that have sentences they match to) verb and verb-noun phrases. These phrases can be of any length, so long as they contain the correct key words.
- For our extra functionality, we defined extra data types to handle items in the game; a Treasure type and a special Action type called InventoryChange that adds items to the inventory when players take the item. We then added extra functions with cases made specifically to handle InventoryChange actions (performAction and actionMatchesWithSentences). During the game, players can discover items, which are placed into their inventory. They are able to check their inventory in-game. When they die or finish the game, they are given a score based on how many items they collected.
- How we did it?
What we learned (i.e. Is functional programming feasible for this task?):
- The basic functionality of moving around the map is very well achieved by functional programming. The graph structure is simple and effective, as is clear from how our Scene data type looks like; without looking at the list of Action, the structure is just a description and 4 subgraphs for the user to go to. The complexity comes in with the interactions that go beyond basic movement.
- The list of Action is what lets users interact with the Scene beyond basic movement. This may not be best handled by functional programming, as it requires extensive lists of Action for each Scene to be added to each scene, as can be seen in the Scenes.hs file.
- Functional programming is very well suited for natural language processing. In particular, Haskell’s Algebraic Data Types made it quite easy to build the natural language processing and, furthermore, would make it quite easy to extend it further to include more complex sentence types. Plus, I think I am in love with Haskell’s pattern matching. It allows the developer to write expressive, simple code that is easy to understand.
- Another added plus for the Haskell language in particular is that it is very well supported. It has a pretty great HUnit testing package, just like Java’s JUnit and C#’s NUnit. And it also has great plugins for polished IDEs like IntelliJ and Atom.
- Overall, we found the experience of programming in Haskell to be very pleasant. Because Haskell is a pure functional language (and, thus, enforces referential transparency on its functions) it was very easy and simple to test out our functions and fix/spot bugs. Using an object-oriented programming language with state would likely have been much more challenging to debug. Plus, Haskell’s static typing forced to write good, clean, well-typed code from the get-go, refusing us the ability to write sloppy code. Although the Haskell compiler can be a pain sometimes, we find that the pain more than outweighs the rewards.
- All in all, we are very, very impressed with Haskell as a language. Jeff plans to continue learning about Haskell after this course, because he loves the language so much. Dama thinks it's pretty fun too!
Links to code etc