You are on page 1of 52

D’Orazio, James, Oakes 1

Lair of the Forgotten Beast

_______________

A Capstone Report

_________________________

California State University, Monterey Bay

_______________

In Partial Fulfillment

of the Requirements for the Degree

Bachelor of Science

in

Computer Science

_______________

by

Nick D’Orazio, Brian James, and Kyle Oakes

Summer 2021
D’Orazio, James, Oakes 2

Copyright © 2020

by Nick D’Orazio, Brain James, Kyle Oakes

All Rights Reserved


D’Orazio, James, Oakes 3

Executive Summary

The project was designed for the development of a video game which implements

features that have been previously unexplored in interactive fiction games. Along with many

recognizable features from previous text-based adventures, this game will also have a unique

system for casting magic spells. The setting for Lair of the Forgotten Beast will be a fantasy

world that includes a hero, monsters, and magic. The main goal of this project is to highlight the

new magic features and offer the client an improved experience over previous designs done by

other software developers.

After many years of interactive text adventures, the genre now has a game that is more

complex in its magic spell system. pts to use a magic spell during gameplay, a text entry is

required. For example, “Cast Fireball on hobgoblin”. A canned response is usually set up to react

to this text input with very little function. This method of magic is simplistic to a fault. The

interactive fiction products rarely expand on the magic spell casting that make fantasy game

settings so interesting. This project will attempt to address this issue in a way that creates a very

satisfying experience for the client.


D’Orazio, James, Oakes 4

Table of Contents

Executive Summary 3
Table of Contents 4
List of Figures 6
Background and Approach 7
Introduction/Background 7
Project Name and Description 7
Problem and/or Issue in Technology & Solution to the Problem and/or Issue 8
Evidence that the Proposed Project is Needed 9
Project Goals and Objectives 9
Stakeholders and Community 10
Feasibility Report 11
Design Requirements 12
Functional decomposition of the project 12
Command Line Instruction Execution 12
Object Creation using Abstract Factory Pattern 14
Selection of design criterion 17
Final Deliverables 19
Approach/Methodology 19
Ethical Considerations 20
Legal Considerations 20
Final Report 21
Timeline/Budget 21
Usability Testing/Evaluation 22
Final Implementation 24
Abstract Factory design pattern 24
Command Line 26
Discussion 29
References 31
Appendix A 32
Usability/Evaluation Test Plan 32
Usability Test Post-Survey 32
Appendix B 35
D’Orazio, James, Oakes 5

Team Members 35
Appendix C 36
Client/Focus Group Feedback 36
Introduction 36
Focus-Group Testing 39
Form Q&A 40
Appendix D 45
Client-Side Javascript 45
Appendix E 46
CommandInterpreter Code 46
Appendix F 48
CommandDictionary Code 48
D’Orazio, James, Oakes 6

List of Figures

Figure 1: Command Interpretation Flow Diagram 14

Figure 2: Abstract Factory Pattern 16

Figure 3: User Stories in Pivotal Tracker 17

Figure 4: Github Kanban Card System 18

Figure 5: Abstract Creature Factory Interface 24

Figure 6: Creature Factory Concrete Class Create Method 25

Figure 7: HTML for the Command Line Form 26

Figure 8: Get Method for Retrieving a Lambda Within the CommandDictionary Class 27

Figure 9: ICommand Interface 27


D’Orazio, James, Oakes 7

PART I

Background and Approach

Introduction/Background

Project Name and Description

This project is called “Lair of the Forgotten Beast”, and is a text-based fantasy adventure

game, a modern homage to the classic older games in the genre.

A blinking cursor greets your black screen. What do you do? “Start Game”. You hear

what sounds like an airplane as the mainframe draws more power. White text begins to scroll the

screen.

MONDAY MAY 10, 1847

TOTAL MILEAGE IS 575

FOOD BULLETS CLOTHING MISC. SUPPLIES CASH

46 1090 40 45 205

DO YOU WANT TO (1) STOP AT THE NEXT FORT, (2) HUNT, OR (3) CONTINUE

?3

YOU HAVE DIED OF DYSENTERY


D’Orazio, James, Oakes 8

Text-based computer games have been around since the 1960s where they could be

played on University, and Business mainframes. Many of the original mainframe games have

been lost to time, but a few have lasted. You may not be familiar with the text output above, but

you’ve probably played or at least heard of the game it came from; The Oregon Trail will be half

a century old as of this year, yet it is still being remade for mobile devices today.

While the rise of point and click games started the downfall of text-based games, and led

to the AAA games we play today there is still a spot for those old text games in the modern

culture. Recently A Dark Room hit number one in the app store and the modern text-based game

grossed over $800,0001. This shows that text-based games are still relevant today. It's unclear

why the game gained such popularity. The Artifice states, “many [text-based games] offer

something genuinely entertaining, and, ironically, seem new and fresh.”2

While creating the project, “Lair of the Forgotten Beast”, we did just that: bring

something entertaining, new, and fresh to the history of text-based games. Our game is an RPG

text-based adventure. The player plays through the story of falling into a cave when the ground

beneath their feet collapses. Introduced to a rarely seen part of the world the character lives in,

the player must find their way to safety. During the hero’s journey, they will need to overcome

many challenges. This ultimately leaves the character with a new perspective of the world once

they return.

Problem and/or Issue in Technology & Solution to the Problem and/or Issue

Art enriches people’s lives and improves their quality of life. With the fast-paced bustle

of life, it’s more important than ever to take time to enjoy art. Video games such as ours compose
D’Orazio, James, Oakes 9

a unique art form which not only provides entertainment and enrichment but can also help

develop problem-solving skills.

Evidence that the Proposed Project is Needed

There are other games that exist which are similar to Lair of the Forgotten Beast, each of

which has its own issues. We produced a game which solves some of the existing issues with

related games, serving as an improvement over existing games. We took a new approach with

our new magic system that will combine ease of use for casual players with complexity.

Project Goals and Objectives

The main goal in developing The Lair of the Forgotten Beast was to create a text

adventure game that would be received well by an audience. The game had to be able to perform

all the common functions of an interactive fiction piece, and also implement new features unique

to the project. Another long-term goal of the project was to design and implement a new magic

system in a game unlike those that have come before it.

During this project, there were several objectives timely ordered to meet weekly goals.

The project began with basic building blocks of the program; Pivotal Tracker was set up first, a

project was created, and a GitHub repository was made, and weekly work was being tracked on

the Kanban cards within Github. After the skeleton of the project was laid out, we began adding

features. The first feature we added was a grid map in Java which served as an abstraction for the

fantasy game setting, specifically the locations the player can visit. Unit testing was included as a

standard operating procedure in development. After that, a preliminary generation of rooms,


D’Orazio, James, Oakes 10

creatures, magic, and items were listed and implemented. Once enough data was accumulated,

work began developing the services and methods that support these objects. More objects were

added later after some proof of concept was completed with the initial portion of data. Data

structures formed the infrastructure that supports all of the program objects that are processed

using Java Spring Boot controllers and classes. Then, the game map was populated with Java

objects that represent places, people, creatures, items, and spells. It is in this phase that the new

magic system was implemented. After all Java classes and methods were unit tested, the team

increased the scope and complexity of the game. The game was considered finished when the

team carved out the entire game world and verified the functionality of all the components in

end-to-end testing.

Stakeholders and Community

The stakeholders on this project were the developers and end users. The project was

created with the combined experience and motivations of three developers.

The first developer was motivated to create a properly advanced magic system, and

would gain from creating the system he always wanted introduced into a text-based game. He

also benefited from the experience of working on a project of this scale as well as game design

experience.

The second has career plans to become a game developer, and this project helped him to

get experience in the field. Creating the Lair of the Forgotten Beast was the first step in building

the necessary resume experience to be on track to achieve this professional goal.

The last developer, having never played a purely text-based game before, has gained

additional knowledge and experience from working on the project.


D’Orazio, James, Oakes 11

Feasibility Report

As the project team scanned the environment, other interactive fiction games were

examined. Some of the features that existed in the older games were important enough to

consider in Lair of the Forgotten Beast. The use of directional navigation text such as “north”,

“n”, or “go north” were recreated. This is a nod to games produced in the 1980’s like Zork (Zork

1) or Adventure (Adventure 1, 2021). The use of one-word or two-word commands in a

verb-noun combination allowed the team to continue some of the features that made those old

games so easy to play. Other resources including articles from the internet were examined and

compared with the features that were planned. This game was designed to be unique among a

decades-long community full of text-based adventures. One of the main databases for finding

interactive fiction works is called the Interactive Fiction Database or IFDB (The Interactive

Fiction Database, 2021). This site was designed to archive all of this genre in one place with user

reviews and ratings. The games and the reviews given to them offered a lot of insight into what

made a game that interactive fiction enthusiasts prefer. The Lair of the Forgotten Beast will join

this historical database of games appreciated by people of all ages.

The spell and magic system in the older games like Adventure were mostly shallow and

lacked complexity. In this project, a new form of casting spells was introduced. Spells,

components, runes, and item enchantments were all considered and experimented with in the

design process. After some deliberation about how to do it, magic words are discovered

throughout the game world. Combining specific magic words can be used to cast spells with

different effects that the player must learn through some trial and error.

To create a set of room items and creatures, a factory design pattern was introduced to

populate the map. The factory pattern allows for the game to implement a randomization system
D’Orazio, James, Oakes 12

for map generation. This will result in a better user experience over the older games, which used

a static map each time a new game was created. During the development process, statically

assigned map objects were used to test features under construction.

PART II

Design Requirements

Functional decomposition of the project

Command Line Instruction Execution

Lair of the Forgotten Beast is a text-based game that relies on user input through a

console input window. This gives the game the daunting task of having to parse the user's input

into usable strings that can then be interpreted by the program to run specific commands. Our

game uses the same noun-verb system that older text-based games do. The system architecture

starts at the command line console window. When the user enters a command the Home

Controller routes the instructions to the Game Service and provides a ResultObject object for

which the returned UI (User Interface) feedback is packaged up for displaying back to the user.

The Game Service creates a new Command Tokenizer, Command Interpreter, Command

Dictionary, and Static World Map to hold the player's current game world instance.
D’Orazio, James, Oakes 13

The Command Tokenizer was created to be the first step in parsing inputs. Sentences are

to be provided by the user, then the Command Tokenizer separates out individual words in a list

format for easy processing by the Command Interpreter. With the user input already parsed into

separate words the Command Interpreter has the job of reading the words and determining how

the user’s instructions should be handled. The Command Interpreter, working in concert with the

Command Dictionary, determines which command path the user instruction will take. The

Command Dictionary, which sets up the valid command routes the instructions can be processed

through, is passed the parsed command. If the first word in the instruction maps to a valid

command route, the Command Dictionary wraps up a lambda function with the path to take and

sends it back to the Command Interpreter. It is up to the Command Interpreter to handle any

errors and redirect the instruction to a different route, a default route, if needed. With an

established instruction route the ICommand functional interface’s call method is invoked. The

ICommand interface is used in the manner a railway switch is used. The Command Interpreter

and Command Dictionary determined the route and now it is up to the ICommand Interface to

unify the command calling process to make sure each command goes to where it needs to be

processed. Fourteen commands and the ability to save and re-execute the last command

instruction used are currently in the game.

The way commands are currently being handled can be expanded for new routes when

necessary, by simply implementing a new command class off of the ICommand interface and
D’Orazio, James, Oakes 14

adding the routing for that command to the Command Dictionary.

Figure 1. Command Interpretation Flow Diagram


D’Orazio, James, Oakes 15

Object Creation using Abstract Factory Pattern

This game has multiple creatures and room items that require many individual instances

of functional response. In the process of creating Lair of the Forgotten Beast, there was a need

for efficient creation of numerous objects in the game. This game application uses a software

design creation pattern called “factory”. This pattern is used more than any other in Java. The

factory is considered the top way to create a Java object, because it does not reveal the creation

logic associated with private code. Instead of pointing to a concrete class, the client service refers

to a newly created object using a common interface. Depending on what parameters are supplied

to the factory methods, a different type of creature or room item will be generated by the same

factory method.

The program executes the object creations from its map domain functions

WorldMapGenerator and StaticWorldMapGenerator. From those processes, the factories are

called using parameters similar to “name”, “description”, or “attack damage”. A call to a java

method is made to get the values that are stored in these fields and a different set of methods is

used to overwrite them. In the diagram below, the abstract factory named

AbstractCreatureFactory is an interface that is implemented by the CreatureFactory.


D’Orazio, James, Oakes 16

Figure 2. Abstract Factory Pattern

From the CreatureFactory, a creature class can call one of several types of creatures. For

room objects, they are referred to in the project as “props”, which can be any object inside a

room that is not a creature object. The factories can be used to create custom versions of existing

creatures or props by changing the input parameters to the factory methods. The diagram above

shows the abstract class called Creature downstream from the CreatureFactory, and has multiple

variants that extend the Creature class like “Humanoid” or “Undead''.


D’Orazio, James, Oakes 17

Selection of design criterion

In the beginning, the team wanted to build a video game. This was the first known

requirement to be written down and recorded. Following that initial request, numerous other

tasks were created to complete the project. There were many details to figure out, and technology

helped to organize work. When crafting Lair of the Forgotten Beast, the team manufactured

several user stories that would eventually shape the entire program. The user stories quickly

became functional requirements that held together the entire user experience. In Figure 1 below,

these stories were set up in Pivotal Tracker.

Figure 3. User Stories in Pivotal Tracker


D’Orazio, James, Oakes 18

User stories are typically set up as a way to track functionality in a non-technical way.

They clarify the reason for the functionality in the first place. The stories should be a reminder of

what was discussed, but not necessarily every small detail. In this case, the stories were able to

help the team develop ideas on boilerplate java code so that the program would execute the

stated tasks within each story. The technical mandates that come from the user stories eventually

found their way into the Github project card system. Below is a picture of the Github project

cards.

Figure 4. Github Kanban Card system

The cards represent technical tasks in various states of progress. The first column is an icebox,

which works in a similar way to the icebox found in Pivotal Tracker. The second column is the

To Do list. This has all of the tasks that are currently waiting to be accepted. The third column is

the In Progress area. This column is used for any tasks that are currently being worked on.

Finally there is the Done column which is where an In Progress card will go once it is completed.
D’Orazio, James, Oakes 19

Final Deliverables

For the final deliverables on the project, the team has created a functional video game

written in Java and JavaScript. The backend uses Spring Boot and the game is being deployed on

a Heroku server. The team has also conducted a first round of acceptance testing requiring a

small focus group, five test subjects, playing the game in a one-on-one testing session with a

developer present and completing a usability feedback survey at the end of the subjects’ game

playthrough.

Approach/Methodology

The team used an Agile methodology for software development. The tasks were divided

into three time-boxed two-week sprints. During each sprint, the team would look at both the

Pivotal Tracker user stories and the small changes that were recorded within the Github project

page. On the project page, one was able to write task cards and assign them to an appropriate

column such as “Done”. Many of the complex changes were solved in user stories, as they

typically required multiple services to be configured in specific ways before they can be

considered done. In Pivotal Tracker, the user stories would be gathered, evaluated for priority,

then classified into weighted points. These points could then be applied to the next iteration to

better determine how to time-box the task. Three tasks that are worth one point will take the

same time to complete as a single task worth three points. Going through these evaluation steps

helped to meet self-imposed deadlines for progress.


D’Orazio, James, Oakes 20

Ethical Considerations

Ethical concerns played a role in the choices that were made when building Lair of the

Forgotten Beast. The first concern was that this game would cost too much to play. It was

decided that the game would be free to play since the team believed that everyone should have

the opportunity. There are some games that are free to play, but also have microtransactions. Lair

of the Forgotten Beast does not have them.

The use of violent or sexual content was never something that the team had thought about

including in the game. There are some fantasy role playing games that include violence or

sexuality. This game was not one of those, and depicts combat in a non-sensationalized manner.

The team understands that our game can be played on any device that has a web browser, and

children could find it. The game is completely safe for young children to play and contains no

objectionable material.

The testing done on this project was also done with awareness of rules and ethical

concerns surrounding the use of human subjects. The development team was able to secure five

live test subjects from a focus group, which had received prior approval from the Committee for

the Protection of Human Subjects (CPHS).

Legal Considerations

Legal considerations for video game development influenced where boundaries were for

what the team was allowed to create. The work done in this game was original. This project

obeyed the copyright laws within the United States. No images, scene images, settings,

dialogues, or music that has been produced and copyrighted was used in Lair of the Forgotten

Beast. (Copyright Laws and Video Games, 2021).


D’Orazio, James, Oakes 21

PART III

Final Report

Timeline/Budget
The video game, Lair of the Forgotten Beast, was created under a strict deadline of six

weeks. Under this deadline the game development life cycle was set up to include three back to

back agile style sprints of two weeks each. To keep this fast pace, a schedule was created to keep

the developers on track. In the first two week iteration, the initial set up would be completed.

Initial setup involved creating a Github repository, Pivotal Tracker account, a Heroku pipeline,

the webpage routing system, and a command line interface for users to enter text into. Work on

game movement and basic mechanics would begin in development and go through to the next

iteration. In iteration two game mechanics would be added to the game to parse commands, fill

rooms with items and monsters, and create an inventory system for the players to hold objects as

they interacted with the fictitious world that is the setting of Lair of the Forgotten Beast. With the

first two iterations done, the last iteration would begin to introduce the main feature targeted with

this game. Introducing a more complex magic system than other games were able to provide had

always been the focus of the game. As the magic system developed, so too would the combat

system. Lastly, in this final iteration the team had to begin game testing by gathering game

testers in one-on-one meetings where they would give feedback to a developer.

The budget for Lair of the Forgotten Beast was initially set to a total of $4 to host the

Heroku pipeline in a non-personal account for the added features doing so would make available.

The team only exceeded this budget after the game's conclusion when creating the video and
D’Orazio, James, Oakes 22

slides necessary to present the project at the Capstone Festival. Two of the developers incurred

another $20 cost each for special features in the slides. One cost was to include an AI voice to

automate reading the slide scripts over the video. The second of the costs was to include icons as

graphics on the slides. An account at iconfinder.com was paid for to get access to icons that had

suitable commercial use licenses that would legally help the team avoid incurring copyright

infringement fines at any point in the future.

Usability Testing/Evaluation
In week six of the video game’s development cycle the team began user testing. The team

had previously consulted friends and family members, along with other Cal State Monterey Bay

students within the same cohort, to build a list of potential testers for each of the game’s features.

Lair of the Forgotten Beast’s game developers reached out to the pool of potential testers and

received five responses. At this point the developers scheduled one-on-one meetings with each of

the testers where a single developer would sit through a game playthrough and listen to any

feedback or concerns the testers could provide. During the playthrough the developers took notes

which were used to make game changes to address the concerns of the testers. At the end of the

playthrough session the testers were asked to complete a survey (see Appendix A) to create a

concrete record of what they thought of the game’s design. The results of the survey indicated

that improvements were needed to bring the game up to the users standards.

The survey responses (see Appendix C) indicated that all the testers had previously

familiarity with Interactive Fiction or Text Adventure games in the past. Generally consensus

between the testers state that Lair of the Forgotten Beast fell below an average difficulty to use

rating indicating that most testers found the game difficult to use as it was when tested. Concerns

leading to this rating include that the code for the user login/sign up page had not been fully
D’Orazio, James, Oakes 23

merged into the project before the testers received the playthrough, the magic system was not

well documented for the players to know that it existed without being told about it from the

developers, and no game over sequences had been created. One tester responded to the survey

stating, “I did not know you could cast magic. I am IMMORTAL (-850/100)!”. The last part of

the statement shows he was able to still play the game when his character’s health points had

fallen into extreme negative values. Even with survey responses generally stating that the game

needed more improvements, all but one of the testers indicated that they would play Lair of the

Forgotten Beast again.

After the testing phase was completed the development team immediately began trying to

address the feedback in what few days they had left before the final Capstone deadline. Almost

all the testers' concerns were addressed, while a few concerns of both the testers and developers

were unable to be resolved in the time period given. The final project being presented for the

Capstone presentation includes bug fixes to allow user login and signup options, along with

scrolls intended to aid the players solve the final boss riddle, an introduction to the magic system

early on in the game, and making user inputs non-case sensitive. Concerns that were not able to

be addressed at the time of this writing would have involved creating story content to make the

game more cohesive.

Final Implementation

Abstract Factory design pattern

The final implementation of the project uses a creation design pattern used in the

generation of game objects. The abstract factory pattern was able to create as many in-game

objects as the team needed. The creatures and room objects could be instantiated without specific
D’Orazio, James, Oakes 24

parameters or with all constructor fields specified. The game started with only a few objects for

testing. Once more game rooms were created, additional objects were added. This worked well

while the team had not yet developed the combat system. In the second project sprint, the

complexity of the objects changed as additional fields were introduced like attackDamage. The

Java classes used in the program to generate the creatures were then modified to create specific

creatures with predictable equipment in their inventories. For example, a hobgoblin cultist would

always be generated with a bronze sword if no other parameters were passed to the function.

Alternatively, the game can call the CreatureFactory function specifying a hobgoblin with a

much larger sword that does more attack damage.

Here is a code snippet from the AbstractCreatureFactory and the CreatureFactory files:

package LairOfTheForgottenBeast.factory;

import LairOfTheForgottenBeast.domain.map.rooms.RoomDynamic;
import LairOfTheForgottenBeast.domain.prop.Item;

public interface AbstractCreatureFactory<T> {

T create(String creatureType, String name, String shortDesc, String


longDesc, int attackDamage, int currentHitPoints,
int maxHitPoints, RoomDynamic room);

T create(String creatureType, String name, String shortDesc, String


longDesc, Item weapon, int attackDamage, int currentHitPoints,
int maxHitPoints, RoomDynamic room);

T create(String creatureType, RoomDynamic room);

Figure 5. Abstract Creature Factory Interface


D’Orazio, James, Oakes 25

// Create method using all the parameters including weapons


@Override
public Creature create(String creatureType, String name, String
shortDesc, String longDesc,
Item weapon, int attackDamage, int currentHitPoints, int
maxHitPoints, RoomDynamic room) {
if ("Human".equalsIgnoreCase(creatureType)) {
Humanoid human = new Humanoid();
human.setName(name);
human.setShortDescription(shortDesc);
human.setLongDescription(longDesc);
human.setWeapon(weapon);
human.setAttackDamage(attackDamage);
human.setCurrentHitPoints(currentHitPoints);
human.setMaxHitPoints(maxHitPoints);
human.setCurrentRoom(room);
return human;
}
}

Figure 6. Creature Factory Concrete Class create method

Command Line

Our initial design for the command line interface involved setting up a HTML form

consisting of a single text field to enter a command and submit a POST request to a route on the

server.

<div id="console-input" align="center">


<form id="command-form" action="#" th:action="@{/console}"
th:object="${commandInfo}" method="post">
<input type="text" id="input-window" name="commandString" />
D’Orazio, James, Oakes 26

<button type="submit" value="Submit">Submit!</button>


<div>
<span><input type="text" id="username" name="username"
placeholder="Type your username"
th:value="${user.username}" hidden/></span>
</div>
<div>
<span>Multiplayer? </span>
<span><input type="checkbox" id="multiplayer"
name="multiplayer" value="multiplayer"/></span>
</div>
</form>
</div>

Figure 7. HTML for the Command Line Form

In the server route, the command string is passed from the client into a CommandTokenizer class

which parses the command from a space-delimited String to a List data structure that represents a

list of words in the command. Then, the list of command words is passed to a

CommandInterpreter class (see Appendix E) which checks the beginning of the command to

identify which command should be executed. For example, in the case of “examine torch”, the

first word, “examine” corresponds to the “examine” command. The CommandInterpreter uses

the first word as a lookup key within the CommandDictionary (see Appendix F), which is a

HashMap that holds a string as a key to get a lambda to the desired command class logic.

public BiFunction<GameState, CommandInfo, String> get(String command)


{
BiFunction<GameState, CommandInfo, String> lambda =
commandDictionary.get(command);
return lambda;
}

Figure 8. Get method for retrieving a lambda within the CommandDictionary Class
D’Orazio, James, Oakes 27

The CommandInterpreter gets handed back the lambda which it then uses to call a

functional interface called ICommand. ICommand allows any class that implements its interface

to have an attached call function that will determine a command's behavior in a unique way for

that class.

package LairOfTheForgottenBeast.domain.commands;

import LairOfTheForgottenBeast.domain.CommandInfo;
import LairOfTheForgottenBeast.domain.GameState;

public interface ICommand<Return> {


public <AnyType> String call(GameState gameState, CommandInfo
commandInfo);
}

Figure 9. ICommand Interface

Problems During the Design and Implementation Phases

One challenge that the developers encountered during the design phase was the fact that

the client web page was going to refresh each time the player entered a command. This meant

that a history of commands and command output could not be kept on the console page as

planned. In order to solve this, the developers wrote client-side javascript which handles form

submissions and HTML requests using AJAX; then, upon receiving the response from the server,

the javascript uses JQuery to update the client page (see Appendix D).

One of the biggest problems that came up during the implementation phase was a

problem with the github repository that rendered the game unplayable until it was fixed. This

issue occurred because Kyle (see Appendix B) did not correctly communicate with the rest of the
D’Orazio, James, Oakes 28

team that they were editing several files. What they should have done was create a kanban card

in the GitHub project board (and possibly open an “issue”) in order to fulfill the communication

guidelines established by the team to prevent issues like this. Another team member, Brian (see

Appendix B), worked on the same files during the same time period. The edits made by the two

developers were not compatible and resulted in many severe merge conflicts. One of the

developers spent several hours resolving the merge conflicts, then merged the pull request. Once

the pull request was merged, the application ceased to function.

In order to repair the application, after attending a meeting with the other team members,

Kyle attempted to roll-back the latest pull request by branching off from main “reverting” the

pull request in the new branch. He then merged Brian’s pull request and resolved any issues, then

attempted to merge Kyle’s pull request; GitHub would no longer merge the commits that had

been reverted, and so the main branch remained broken. Kyle and Brian met in a video

conference, shared screens, and manually integrated Kyle’s code into Brian’s local branch. After

this, Kyle met with Nick (see Appendix B) to integrate this newly-stable version of the project

into Nick’s branch, which Nick then used to override the main branch. This had to be done by

Nick, because he originally set up the GitHub repository and was thus the only one who could

directly modify the security settings to allow overriding main. Once main was overridden, the

project was stable and the developers could once again work on it asynchronously.

Another problem that came up during the implementation phase was the database

connection limit. In our development testing, the team ran into this issue on multiple occasions

and needed to clear the sessions to regain access to the application.

The project was not rolled out for permanent use by users because although it is a

playable game, it is missing a lot of balancing and polish. At this point, the project is released in
D’Orazio, James, Oakes 29

“early access” and can be accessed and played at a specific URL, but it does not have an official

full release yet. Currently, only a few users can access the game at once without crashing it. This

is because of the current limit to the number of database connections. This limitation is due to the

current database setup, which works with a free database meant for small-scale projects, but

which can be scaled by purchasing upgrades. The biggest upgrade that would be necessary in

order to support more players would be to upgrade the database to support more connections.

Additionally, increasing the number of dynos would improve the stability and scalability of the

application. This can be done smoothly in Heroku by paying for these upgrades.

Discussion

As stated in the final implementation section, the developers learned several new

programming concepts and implementations, including the Abstract Factory design pattern used

in the generation of game objects, command line interfaces, and some functional programming

techniques using lambdas. We first designed the command interpretation code in such a way that

it relied heavily on conditional statements to interpret commands. We later modified the

command interpretation code to use lambdas to make it more easily scalable.

The developers also learned the importance and difficulty of balancing planning and

implementation within such a limited timeframe; this was particularly pertinent when

considering quick implementation of features versus robust and scalable design. On the one

hand, it was important to spend time planning and implementing solutions in robust, scalable,

and easily-debuggable ways; on the other hand, there was often insufficient time to perform

thorough planning, and it was sometimes necessary to sacrifice code quality in favor of speed of

implementation of features in order to remain on schedule.


D’Orazio, James, Oakes 30

An idea which the team had not considered before the project but ended up implementing

in the game is the client-server architecture where the server waits for user input from clients in

order to update the game state and send a response back to the client web page, which should

then update to reflect the results of the changed game state without refreshing the page. Most of

the video games that the developers were familiar with prior to the project utilized what is known

as a “game loop” in order to enable continuous processing in addition to the strict

input-processing-output that strongly characterizes applications such as Lair of the Forgotten

Beast. Almost all video games use a game loop, particularly real-time games such as action

games; Lair of the Forgotten Beast is an interesting exception to this trend.


D’Orazio, James, Oakes 31

References

Adventure 1. (2021, Mar 5). Retrieved from Moby Games:

https://www.mobygames.com/game/adventure-1

Copyright Laws and Video Games. (2021). Retrieved from LegalZoom:

https://info.legalzoom.com/article/copyright-laws-and-video-games

Failory.com. (2018). A Dark Room: From Sabbatical Year to $800,000. [online] Available at:

https://www.failory.com/blog/battle-scars [Accessed 26 May 2021].

Interactive Fiction Database. (2021). Retrieved from The Interactive Fiction Database:

https://ifdb.org/index

The-artifice.com. (2015). The Text Adventure: Relic of Gaming History, or Timeless Medium? |

The Artifice. [online] Available at: https://the-artifice.com/text-adventure-gaming-history

[Accessed 26 May 2021].

Zork 1. (n.d.). Retrieved from Infocom: http://www.infocom-if.org/games/zork1/zork1.html


D’Orazio, James, Oakes 32

Appendix A

Usability/Evaluation Test Plan

After the first two project sprints, the development team sought out people to test the

game and provide feedback. A Heroku application was created to get play feedback from the

testers. A schedule of appointment slots controlled who would reserve the application during the

third sprint to keep the game instance refreshed for each player tester. Each of the five people

were given instructions to create an account on the game application web page and start playing

the game. After each person completed their session, they filled out a usability testing survey

with written feedback. The survey was provided to testers via Google Forms and included

questions related to the intuitiveness of the user interface and game mechanics, the presence or

absence of bugs, and other factors.

Usability Test Post-Survey

https://docs.google.com/forms/d/16jmjZkgwLpXv_jhXi5uvVDyrBGw1bNWtZ5Rud2uvO84/edit
D’Orazio, James, Oakes 33
D’Orazio, James, Oakes 34
D’Orazio, James, Oakes 35

Appendix B

Team Members

The team members on this project are Brian James, Nick D’Orazio, and Kyle Oakes. The

team did not assign specific tasks to specific members of the team. Instead, the team utilized an

agile software methodology with a kanban-style task list and each team member volunteered

time to the most current or prioritized task in this “To Do” list. The team collectively populated

Pivotal Tracker and the GitHub project board with user stories and other technical tasks. Each

member of the team was able to claim tasks listed on “To Do” list kanban cards in order to work

asynchronously. In addition to this work, the team held regular meetings at various times in live

video conferencing. These sessions would include live coding with collaboration or planning the

next tasks to work on. The end of a week always included a live session where the team would

update the project report page together and close any remaining tasks that were time-boxed for

that week.
D’Orazio, James, Oakes 36

Appendix C

Client/Focus Group Feedback

Introduction

1. What is your target audience? (age, occupation, interests, comfort level with technology,
etc.)
We split the demographic groups into a number of years as 21 or under, 21 to 35,
and 35 and over. The target audience were people who may have played interactive
fiction games at some point in their life.
Target audience:
● Age: 21 and over.
● Occupation: Any occupation.
● Interests: fantasy role-playing games, interactive fiction
● Comfort level with technology: moderate comfort level

2. Who will be testing your project? If you have a focus group, please state everyone's
names (first names okay) and describe how they fit your target audience demographics.
Otherwise, just do this part for your client.

All testers are over the age of 21. Three are between 21-35 and two are over 35,
making an approximately even spread between the two age groups asked. All the
respondents have previous familiarity with Interactive Fiction or Text Adventure games.

Christopher Fey: has played interactive fiction games.


● Age:35 and over
● Interests: fantasy role-playing games, video games, Dungeons & Dragons,
Movies.
● Comfort level with technology: average tech-literacy for age group, very
comfortable playing video games.
Dan Sedano: has played interactive fiction games.
● Age: 21 to 35
● Interests: computer science
● Comfort level with technology: has played interactive fiction games.
Rocker D’Antonio: has played interactive fiction games.
● Age: 35 and over
D’Orazio, James, Oakes 37

● Interests: fantasy role-playing games, video games, Dungeons & Dragons,


Software engineering.
● Comfort level with technology: average tech-literacy for age group, very
comfortable playing video games.
Roman Baca: has played interactive fiction games.
● Age: 21-35
● Interests: fantasy role-playing games, video games, Dungeons & Dragons,
English and literature, film, graphic novels, video game design
● Comfort level with technology: average tech-literacy for age group, very
comfortable playing video games
Chris Johnson: has played interactive fiction games.
● Age: 21-35
● Interests: science fiction and fantasy role-playing games, video games, Dungeons
& Dragons
● Comfort level with technology: average tech-literacy for age group, very
comfortable playing video games

3. What are the main tasks you would like your client/group to be able to complete while
testing? Your tasks should be specific and measurable (i.e. Can they sign up and log in?
Can they navigate to one specific part of the site? Are they able to play through the first
level of the game?). To get good feedback, you should have 3-5 tasks to test them on.

Christopher Fey:
1. Log into the game from menu.
a. Success
2. Check command usage from within the game options
a. Success
3. Move between rooms
a. Success
4. Find items and add them to inventory
a. Success
5. Use combat actions – either weapon or spell attacks
a. Success
6. Find the ending room.
a. Success
7. Solve the riddle
a. Success
Dan Sedano:
1. Log into the game from menu.
a. Success
D’Orazio, James, Oakes 38

2. Check command usage from within the game options


a. Success
3. Move between rooms
a. Success
4. Find items and add them to inventory
a. Success
5. Use combat actions – either weapon or spell attacks
a. Success
6. Find the ending room.
a. Success
7. Solve the riddle
a. Success
8.
Rocker D’Antonio:
1. Log into the game from menu.
a. Success
2. Check command usage from within the game options
a. Success
3. Move between rooms
a. Success
4. Find items and add them to inventory
a. Success
5. Use combat actions – either weapon or spell attacks
a. Success
6. Find the ending room.
a. Success
7. Solve the riddle
a. Success
8.
Roman Baca:
1. Create a new account on sign-up page
a. Failed due to bug/crash
2. Log into game from login page
a. Failed due to bug/crash
3. Take 4 items, then equip a weapon, then drop one item.
a. Success
4. Execute the “talk” command on a creature.
a. Success
5. Attack a creature
a. Success
D’Orazio, James, Oakes 39

6. Locate a “torn note” item, take it, and examine it.


a. Success
7. Cast a spell. (“invoke indra krata shuf at [target]”)
a. Success, with some difficulty
8. Experiment with magic words to cast another spell.
a. Failed due to a lack of info regarding spellcasting and the rigidity of the
spellcasting system.
9. Locate and examine the “giant vault”.
a. Success
10. Solve the riddle.
a. Success
Chris Johnson:
1. Create a new account on sign-up page
a. Failed due to bug/crash
2. Log into game from login page
a. Failed due to bug/crash
3. Take 4 items, then equip a weapon, then drop one item.
a. Success
4. Execute the “talk” command on a creature.
a. Success
5. Attack a creature
a. Success
6. Locate a “torn note” item, take it, and examine it.
a. Failed because testing ended due to an unrelated crash.
7. Cast a spell. (“invoke indra krata shuf at [target]”)
a. Success
8. Experiment with magic words to cast another spell.
a. Success with some difficulty
9. Locate and examine the “giant vault”.
a. Failed because testing ended due to an unrelated crash.
10. Solve the riddle.
a. Failed because testing ended due to an unrelated crash.

Focus-Group Testing

1. Although called a focus group, you can have one person test at a time. That is up to you
and your project. You should have at least 3 people in your target audience test your
product.
D’Orazio, James, Oakes 40

a. We selected 5 people to be included in a target audience for the focus group.

2. Set up a meeting(s) with your group to go over your work. This should ideally be
face-to-face so you can get their initial reactions and see how they navigate your product
in real time. If they test on your device, you may also be able to record your screen and
audio to capture their test to review later (with their permission). Other good alternatives
would be to have them share their screens over Hangouts, zoom, etc. while testing or
have them record themselves using the product and narrating what they're doing.
a. We set up individual meetings with each of our 5 testers.

3. Report on their feedback. Were they able to complete all of the tasks? Did they get stuck
along the way? What will you do to improve your project in the short term before the
festival? In the long term?
a. The signup and login pages were crashing, so Roman Baca and Chris Johnson
used the dev Kyle’s login credentials.
b. Many testers were stuck in figuring out how to cast spells. This was due to a lack
of in-game documentation and tutorialization for the magic system as well as an
overly strict spell-string interpreter with rigid word order.

Form Q&A

Link to form:
https://docs.google.com/forms/d/16jmjZkgwLpXv_jhXi5uvVDyrBGw1bNWtZ5Rud2uvO84/edit
D’Orazio, James, Oakes 41
D’Orazio, James, Oakes 42
D’Orazio, James, Oakes 43
D’Orazio, James, Oakes 44
D’Orazio, James, Oakes 45

Appendix D

Client-Side Javascript

function submitCommandForm() {
let isMultiplayer = $("#multiplayer").is(":checked");
let commandString = $("#input-window").val();
let username = $("#username").val();
lastCommand = commandString;
$("#console-screen-text").append("\n"+">"+commandString);
$.ajax({
type: "POST",
url: "/console",
data: {
commandString: commandString,
username: username,
multiplayer: isMultiplayer
},
success: function(resultObject) {

$("#console-screen-text").append("\n"+resultObject.commandOutput+"\n");
scrollConsoleDown();
updateLocationInfo(resultObject.locationInfo);
clearInputField();
updateMinimap(resultObject.mapDims, resultObject.playerCoords);
updatePlayerHp(resultObject.playerCurrentHp,
resultObject.playerMaxHp);
updatePlayerEquipment(resultObject.playerWeapon);
updatePlayerInventory(resultObject.playerInventoryItemNames);
},
error: function() {
appendError();
scrollConsoleDown();
updateLocationInfo();
clearInputField();
}
});
D’Orazio, James, Oakes 46

Appendix E
CommandInterpreter Code

package LairOfTheForgottenBeast.domain;

import java.util.ArrayList;
import java.util.HashMap;
/* Non-static Imports */
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;

public class CommandInterpreter {

CommandDictionary commandDictionary;

HashMap<String, List<String>> lastCommandUsedMap;

public CommandInterpreter(CommandDictionary commandDictionary) {


this.commandDictionary = commandDictionary;
this.lastCommandUsedMap = new HashMap<String, List<String>>();
}

public String processCommand(String username, GameState gameState,


List<String> cmdArr,
String multiplayer) {
if (cmdArr == null) {
System.out.println(
"CommandInterpreter.processCommand(...): " + "Received null
List<String> cmdArr");
return "Command received was null";
}

Map<String, BiFunction<GameState, CommandInfo, String>> cmdList =


commandDictionary.getDictionary();

String firstCommand = "";


List<String> lastCommandUsed = new ArrayList<String>();
// System.out.printf("firstCommand before try/catch block: ",
D’Orazio, James, Oakes 47

firstCommand);
try {
firstCommand = cmdArr.get(0).toUpperCase();
lastCommandUsed = cmdArr;
lastCommandUsedMap.put(username, lastCommandUsed);
} catch (IndexOutOfBoundsException e) {
// Do nothing...CommandDictionary has mapping for empty string.
// TODO: This is where repeat last command could go.
if (!lastCommandUsedMap.containsKey(username)) {
ArrayList<String> newLastCommand = new ArrayList<String>();
newLastCommand.add("help");
lastCommandUsedMap.put(username, newLastCommand);
}

lastCommandUsed = lastCommandUsedMap.get(username);
firstCommand = lastCommandUsed.get(0).toUpperCase();
cmdArr = lastCommandUsed;
System.out.println(lastCommandUsed);
}

CommandInfo commandInfo = new CommandInfo(username, cmdArr,


multiplayer);

BiFunction<GameState, CommandInfo, String> lambda =


cmdList.get(firstCommand);
if (lambda == null)
return "Unknown command. Type 'help' or '?' to get a list of
commands";
String returnString = lambda.apply(gameState, commandInfo);
return returnString;

}
}
D’Orazio, James, Oakes 48

Appendix F

CommandDictionary Code

package LairOfTheForgottenBeast.domain;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import LairOfTheForgottenBeast.domain.commands.Answer;
import LairOfTheForgottenBeast.domain.commands.Attack;
import LairOfTheForgottenBeast.domain.commands.Consume;
import LairOfTheForgottenBeast.domain.commands.Drop;
import LairOfTheForgottenBeast.domain.commands.Equip;
import LairOfTheForgottenBeast.domain.commands.Examine;
import LairOfTheForgottenBeast.domain.commands.Go;
import LairOfTheForgottenBeast.domain.commands.Help;
import LairOfTheForgottenBeast.domain.commands.Inventory;
import LairOfTheForgottenBeast.domain.commands.Invoke;
import LairOfTheForgottenBeast.domain.commands.Look;
import LairOfTheForgottenBeast.domain.commands.Say;
import LairOfTheForgottenBeast.domain.commands.Take;
import LairOfTheForgottenBeast.domain.commands.Talk;
import LairOfTheForgottenBeast.domain.commands.Unequip;

/**
* A dictionary of all the mapped commands for the game. Used to filter
user input.
*
* @author Nick D'Orazio
* @version 1.0.0
* @since 1.0.0
*/
public class CommandDictionary {
/**
* A map of all the verb commands for the game.
*
* @see List
D’Orazio, James, Oakes 49

* @see BiFunction
* @see Map
*/
Map<String, BiFunction<GameState, CommandInfo, String>>
commandDictionary;

/**
* Building the dictionary and putting all the commands in it
*
* @since 1.0.0
*/
public CommandDictionary() {
commandDictionary = new HashMap<>();
commandDictionary.put("", (gamestate, command) -> {
return "Enter a command";
});
commandDictionary.put("HELP", (gamestate, command) -> {
Help help = new Help();
return help.call(gamestate, command);
});
commandDictionary.put("?", (gamestate, command) -> {
Help help = new Help();
return help.call(gamestate, command);
});
commandDictionary.put("GO", (gamestate, command) -> {
Go go = new Go();
return go.call(gamestate, command);
});
commandDictionary.put("LOOK", (gamestate, command) -> {
Look look = new Look();
return look.call(gamestate, command);
});
commandDictionary.put("EXAMINE", (gamestate, command) -> {
Examine examine = new Examine();
return examine.call(gamestate, command);
});
commandDictionary.put("TAKE", (gamestate, command) -> {
Take take = new Take();
return take.call(gamestate, command);
});
commandDictionary.put("GET", (gamestate, command) -> {
Take take = new Take();
return take.call(gamestate, command);
D’Orazio, James, Oakes 50

});
commandDictionary.put("INVENTORY", (gamestate, command) -> {
Inventory inventory = new Inventory();
return inventory.call(gamestate, command);
});
commandDictionary.put("DROP", (gamestate, command) -> {
Drop drop = new Drop();
return drop.call(gamestate, command);
});
commandDictionary.put("CONSUME", (gamestate, command) -> {
Consume consume = new Consume();
return consume.call(gamestate, command);
});
commandDictionary.put("UNEQUIP", (gamestate, command) -> {
Unequip unequip = new Unequip();
return unequip.call(gamestate, command);
});
commandDictionary.put("DRINK", (gamestate, command) -> {
Consume consume = new Consume();
return consume.call(gamestate, command);
});
commandDictionary.put("EAST", (gamestate, command) -> {
Go go = new Go();
return go.call(gamestate, command);
});
commandDictionary.put("WEST", (gamestate, command) -> {
Go go = new Go();
return go.call(gamestate, command);
});
commandDictionary.put("SOUTH", (gamestate, command) -> {
Go go = new Go();
return go.call(gamestate, command);
});
commandDictionary.put("NORTH", (gamestate, command) -> {
Go go = new Go();
return go.call(gamestate, command);
});
commandDictionary.put("E", (gamestate, command) -> {
Go go = new Go();
return go.call(gamestate, command);
});
commandDictionary.put("W", (gamestate, command) -> {
Go go = new Go();
D’Orazio, James, Oakes 51

return go.call(gamestate, command);


});
commandDictionary.put("S", (gamestate, command) -> {
Go go = new Go();
return go.call(gamestate, command);
});
commandDictionary.put("N", (gamestate, command) -> {
Go go = new Go();
return go.call(gamestate, command);
});
commandDictionary.put("ATTACK", (gamestate, command) -> {
Attack attack = new Attack();
return attack.call(gamestate, command);
});
commandDictionary.put("FIGHT", (gamestate, command) -> {
Attack attack = new Attack();
return attack.call(gamestate, command);
});
commandDictionary.put("INVOKE", (gamestate, command) -> {
Invoke invoke = new Invoke();
return invoke.call(gamestate, command);
});
commandDictionary.put("EQUIP", (gamestate, command) -> {
Equip equip = new Equip();
return equip.call(gamestate, command);
});
commandDictionary.put("TALK", (gamestate, command) -> {
Talk talk = new Talk();
return talk.call(gamestate, command);
});
commandDictionary.put("ANSWER", (gamestate, command) -> {
Answer answer = new Answer();
return answer.call(gamestate, command);
});
commandDictionary.put("SAY", (gamestate, command) -> {
Say say = new Say();
return say.call(gamestate, command);
});
}

/**
* Retrieves the dictionary of commands where the keys are verbs.
*
D’Orazio, James, Oakes 52

* @since 1.0.0
* @see List
* @see BiFunction
* @see Map
*
* @return The map of all verb commands in the game
*/
public Map<String, BiFunction<GameState, CommandInfo, String>>
getDictionary() {
return commandDictionary;
}

/**
* Retrieves a value/lambda reference from the dictionary.
*
* @since 1.0.0
* @see List
* @see BiFunction
* @see Map
*
* @param command The key/verb to look up.
* @return A lambda reference for the command to execute.
*/
public BiFunction<GameState, CommandInfo, String> get(String command) {
BiFunction<GameState, CommandInfo, String> lambda =
commandDictionary.get(command);
return lambda;
}
}

You might also like