<<

Masaryk University Faculty of Informatics

A Framework for Modelling Tabletop Rules

Bachelor’s Thesis

Jan Pokorný

Brno, Fall 2019

Masaryk University Faculty of Informatics

A Framework for Modelling Tabletop Game Rules

Bachelor’s Thesis

Jan Pokorný

Brno, Fall 2019

This is where a copy of the official signed thesis assignment and a copy ofthe Statement of an Author is located in the printed version of the document.

Declaration

Hereby I declare that this paper is my original authorial work, which I have worked out on my own. All sources, references, and literature used or excerpted during elaboration of this work are properly cited and listed in complete reference to the due source.

Jan Pokorný

Advisor: prof. RNDr. Jiří Barnat, Ph.D.

i Abstract

A framework for digitally describing game rules is proposed, implemented in a library, and evaluated on a case study of a real-world tabletop game. The framework uses a tree-like structure of tokens and fields to represent the physical aspects of the tabletop game. Custom dispatch logic is used for handling rules and their special cases. The framework was implemented as a JavaScript library and evaluated on a case study of a real-world game, Citadels (Faidutti 2000). Im- plementation turned out to provide a sufficient level of abstraction. Resulting digitized game rules are logically and semantically very close to the natural language counterparts. The library simplifies the process of tabletop game digitization and enables faster iteration in digital tabletop development.

ii Keywords tabletop games, board games, card games, rules, digitization, JavaScript

iii

Contents

1 Introduction 1 1.1 Context of digitizing tabletop games ...... 1 1.2 Goals of the developed framework and library ...... 2 1.3 Structure of this thesis ...... 3

2 Prior art in representing tabletop game rules digitally 5 2.1 Arena ...... 5 2.1.1 BGA Studio ...... 5 2.1.2 BGA Sandbox ...... 6 2.2 OCTGN ...... 7 2.3 Vassal Engine ...... 7

3 Analysis of requirements on the framework 9 3.1 Representing the game state ...... 9 3.1.1 Feasibility of recording the exact positions of tokens ...... 9 3.1.2 Using a flat field-token structure ...... 10 3.1.3 Using a tree-like structure ...... 10 3.1.4 Representing state not contained in tokens . . . 11 3.2 Representing rules ...... 11 3.2.1 Rule language ...... 11 3.2.2 Non-linearity ...... 12

4 Framework definition 13 4.1 Representation of physical state ...... 13 4.1.1 Example representation ...... 14 4.2 Representation of rules ...... 15 4.2.1 External framework behavior ...... 15 4.2.2 Rule definition ...... 15 4.2.3 Commands returned from rules ...... 15 4.2.4 Invocation types ...... 16 4.2.5 Interaction loop ...... 16

5 Library implementation 19 5.1 Technology used ...... 19 5.2 Installation ...... 20

v 5.3 Token definition ...... 21 5.4 Rule definition ...... 22 5.4.1 Command definition ...... 23 5.4.2 Special states ...... 24 5.4.3 Example rule ...... 24 5.5 API description ...... 25 5.5.1 GameManager ...... 26 5.5.2 Token ...... 27 5.5.3 Choice ...... 29

6 Case study on the board game Citadels 31 6.1 Structure of the case study code ...... 31 6.2 Rules ...... 31 6.2.1 Introduction ...... 32 6.2.2 Components ...... 32 6.2.3 Game round and player turns ...... 32 6.2.4 Game end and scoring ...... 32 6.2.5 Characters ...... 33 6.2.6 Special districts ...... 33 6.3 User interface ...... 34 6.4 Modelling tokens ...... 35 6.5 Modelling rules ...... 35 6.5.1 Core game loop ...... 36 6.5.2 Play of 2, 3, and 7 players ...... 37 6.5.3 Collecting taxes ...... 37 6.5.4 Character powers ...... 37 6.5.5 District powers ...... 38 6.5.6 Rule ambiguity ...... 39 6.6 Example rule explanation ...... 39

7 Evaluation of the case study 43 7.1 Library evaluation ...... 43 7.1.1 Generality and universality ...... 43 7.1.2 Closeness to the natural language rules . . . . . 43 7.1.3 Ease of writing rules ...... 44 7.2 Possible future improvements ...... 44 7.2.1 Direct support for client-server communication 44 7.2.2 Add debug visualizations ...... 45 vi 7.2.3 Rely on the programming language’s type system 45 7.2.4 Add direct integration with a presentation layer 45

8 Conclusion 47

Bibliography 49

vii

1 Introduction

This thesis aims to design and implement a general framework1 for programmatically describing tabletop2 game rules. A data model to represent game tokens and related metadata is defined, as well asa system for coherently expressing rules. The framework is then implemented in an embeddable library. The goal of the developed library is to simplify the process of digitizing tabletop games by providing useful abstractions and enabling the digital rule expression to be semantically close to the natural language version. The library is published to GitHub3. As a case study, the library is used for digitizing the rules of the tabletop game “Citadels”. The case study is then used to evaluate design and usefulness of the framework and the library.

1.1 Context of digitizing tabletop games

Many famous tabletop games were digitized [1, 2], including Settlers of Catan4, Carcassone5 and Agricola6. Game creators may decide to offer the digital versions for free, as a means of marketing forthe physical version. However, it is also common to sell digitized tabletop games in the same way as other video games. Most players prefer physical versions of tabletop games [3]. Fur- thermore, it has been confirmed by many studies that automating certain “boring” elements of tabletop gaming hinders enjoyment [4, 5, 6, 7]. Despite that, there is usually a demand for digital versions of popular tabletop games, sometimes even leading to the creation of unofficial ones by fans [1, p. 5, Digitising Agricola].

1. This thesis uses the word “framework” to represent the abstract system for formal description of tabletop game rules, and the word “library” to represent the actual source code implementation. 2. This is a blanket term for board games, card games, pen and paper games and other types of turn-based games usually played at a table using physical props. 3. 4. 5. 6.

1 1. Introduction

As of the date of this writing, many platforms are providing the possibility to digitize a tabletop game. Some of them, like Vassal En- gine7, OCTGN8 or BoardGameArena9, each use a different proprietary system of describing rules. Others, like Battlegrounds Gaming En- gine10, Tabletopia11, and Tabletop Simulator12, have no way of imple- menting game rules at all, leaving the burden of conforming to game rules to players. The absence of automatic rule enforcement is usu- ally marketed as a feature, allowing faster iterations when designing games. However, many digital ports of tabletop games are realized through a conventional game engine, such as Unity13 or Construct14. Using general game engines enables almost unlimited possibilities of but comes with a cost of high complexity, as these engines do not tailor to the specific limitations of tabletop games.

1.2 Goals of the developed framework and library

The developed framework aims to be general enough to allow digiti- zation of virtually all “traditional”15 tabletop games. A library is developed aiming to be an embeddable, cross-platform component enabling various game platforms to enforce tabletop game rules digitally. Separating the rules from the presentation layer enables different software components to use the same rule code internally. Components that may benefit from this approach include client-side rule checking, online games with server-side rule checking, or AI players.

7. 8. 9. 10. 11. 12. 13. 14. 15. Such games primarily use physical tokens to represent the game state and have a clear set of rules for players to follow. Games that focus on role-playing or physical player interaction may not be a good fit for this library.

2 1. Introduction

The library is developed to be a black-box, providing only the game state to the outside and accepting player choices. There are no assumptions made on how the player input is obtained (live player, AI, ...) and how the game state is presented to the player (rendered in a 2D/3D canvas, serialized and sent over the network, ...). Separation of the rule logic allows the game designer to focus on implementing the game rules and to stop worrying about things like user input or network code. Another aim of this library is to make the digitized tabletop game rules more human-readable and closer to the natural language version. A clear correspondence between the two simplifies the process of digitizing a board game as a whole. Having a close-to-reality digital representation may also allow easier prototyping and development of the rules themselves, by using the digitized version to evaluate different rule variants. The framework and the corresponding library are focused on pro- viding a black-box programmatic interface, with no assumptions on the presentation layer. The library thus does not provide any form of human interface.

1.3 Structure of this thesis

This thesis first briefly examines the prior art in the field ofboard games digitization, focusing on the different systems to describe rules. Then, requirements for the framework are decided based on an analy- sis of general principles in board games. A framework for representing the internal state of tabletop games, as well as simulating the rules, is proposed. This framework is then implemented in a library, and the library’s programmatic interface is described. A case study is devel- oped, implementing digital rules of the tabletop game Citadels [8]. Finally, the case study is used to evaluate how well the framework and the library fulfill the goals outlined in the introductory chapter and propose future developments.

3

2 Prior art in representing tabletop game rules digitally

This chapter goes over the prior art in the area of digitizing tabletop game rules. At the time of this writing, there does not seem to be a library with similar principles and goals as the one created in this thesis. There are, however, applications for digitizing tabletop games, that sometimes contain similar functionality [9]. The following sections go through examples that have some mechanic of rule-enforcement built-in. The majority of available options are sandbox only and offer no rule enforcement at all. However, as none of the projects listed below come reasonably close to what the developed framework and library are trying to achieve, the description does not go very in-depth. This chapter is, thus, relatively short.

2.1 Board Game Arena

Board Game Arena1 is a web platform, offering many tabletop games playable in the browser with other live players over the internet. Most of the games are free to play. Almost all of the games have full rules implemented, which are checked server-side. The games use HTML to render, and game elements are realized through regular HTML elements. Dojo framework2 is used for manip- ulating HTML DOM client-side. There are two main modes of developing new games for this plat- form. Both use web technologies and offer some level of abstraction over game logic.

2.1.1 BGA Studio BGA Studio [10] uses a HTML, CSS, JavaScript, PHP and MySQL stack to implement games. JavaScript contains only the UI logic, and

1. 2.

5 2. Prior art in representing tabletop game rules digitally the game ruleset itself is implemented server-side in PHP. The game developer has to manually implement UI and networking logic in addition to the game rules themselves. The included tutorials often encourage to mix UI, database, and game logic. This mode offers little to no abstraction over the underlying tech- nologies. There are some pre-made components for the rule logic – like the Deck, to simplify working with decks of cards – and also some UI components. In general, however, there is no concept of “token” and the logic of storing game state is almost completely game-defined. Rule logic is implemented server-side in PHP. The core element is a centrally defined state machine, where each state is oftype "game" (no players are active, automatic game-defined actions hap- pen), "activeplayer" (a player is active and chooses a move) or "multiactive" (several players may be active and choose a move). States where a player is active must define "possibleactions", which is an array of all the possibilities. The states have PHP procedures associated with them, which have access to an application interface for database access and state manipulation. As the provided API spans several technologies, it is quite complex. Despite that, the documentation seems incomplete, even stating it explicitly at several places. There are also some questionable parts of the documentation, for example constructing SQL queries by string concatenation, or insisting that randomness-generating functions used for rolls must be cryptographically secure.

2.1.2 BGA Sandbox BGA Sandbox [11] is the more modern one out of the two modes. It uses a combination of a GUI designer and JavaScript executed server- side to describe game rules and automate some piece moves. The actual HTML mapping, player input handling, and networking are abstracted from the game developer. The GUI designer allows for games to be implemented to the point they are fully playable, but with no rule enforcement. It is encour- aged first to create a game using the GUI designer, and then addrule checking using the scripting functionality. This mode uses a simple state-machine to manage the rules of the implemented game. It mostly focuses on providing tools for validating

6 2. Prior art in representing tabletop game rules digitally player actions (drag and dropping pieces), and canceling them if they are found to be against the rules. The provided API is rather short, mostly consisting of methods for checking positions of game elements and moving game elements to specified locations.

2.2 OCTGN

OCTGN [12] is a Windows desktop app allowing creation and network play of virtual tabletop games. It focuses primarily on trading card games3, and mechanics for implementing other types of games are very limited. Game definition for OCTGN consists of an XML file that defines resources for the game (game modes, game phases, cards, game board, decks, ...) and scripts. Scripts are written in Python and executed in a secure sandbox environment. A comprehensive API is offered for examining and manipulating cards.

2.3 Vassal Engine

Vassal Engine [13] is a multi-platform tabletop game engine written in Java. It is primarily focused on war games and miniatures. Games are created through the GUI and are expected to be played in a “sandbox” mode with no rule enforcement. It provides an API in Java, but it is intended only for creating pieces with custom logic attached, not for rule enforcement.

3. Like “Magic: The Gathering”, for example.

7

3 Analysis of requirements on the framework

For a representation, a theoretical model must be created, which is used to describe the immediate state of the game and the game rules to change it. Defining such a model is necessary as nearly all tabletop game rules are defined to be human-readable, rather than mathematically precise. This chapter focuses on analyzing the features needed in such a model. The main aim of this model is to allow both rule description and game state representation to be as close as possible to the "human- readable" form of rules, while still being precise enough to allow digitized rule enforcement. The task is logically split into two parts: modelling the immediate game state and representing the rules of modifying such a game state.

3.1 Representing the game state

In a physical tabletop game, the game state is represented by a specific spatial configuration of a finite set of physical tokens. “Tokens” here refers to any physical object that is a part of the game – card, tile, counter, game board, or similar. Additionally, there may be some information not stored physically, but only in the memory of the players. This applies mainly to the organization of player rounds (for example, what player should play their round next), and to information shared verbally between players (for example, what color should be played after the Wild card is played in the UNO1). Such information can be, in most cases, replaced by physical tokens.

3.1.1 Feasibility of recording the exact positions of tokens A straightforward approach would be to record the precise positions and rotations of the game pieces in 3D space. This way would accu- rately emulate the corresponding physical representation. There are some tabletop games where sub-millimeter-precise posi- tions of tokens matter, for example, in “: X-Wing Miniature

1. 9 3. Analysis of requirements on the framework

Game”2, which uses rulers and precise measurements in specifying the rules. However, for most games, slight changes in game piece positions carry no meaning from the rules’ perspective. Instead, tokens have well-defined areas where they can be placed, such as “field F4ofthe chessboard” or “player 1’s hand”. Recording the exact positions of tokens as a game state representation would lead to a loss of abstraction and overall complications in defining the ruleset. Thus, a decision was made to focus on games where rules differ- entiate only finitely many configurations of tokens.

3.1.2 Using a flat field-token structure The word “field” is used to describe an area on which a token canbe placed. Unlike tokens, which are the physical parts of a tabletop game, fields need not have a physical representation. For simple games, positions of tokens can be recorded by merely naming all tokens and all the fields a game token can be placed at, and then listing which tokens are placed on which field. An example of this approach is the standard algebraic notation [14], where fields of the chessboard are labeled by their coordinates (a combination of letter A-F and number 1-8) and chess pieces are given identifiers based on the type of the piece. However, the chess notation is not strict in assigning unique identifiers to all the pieces, as the format of recording moves allows them to be always unambiguous.

3.1.3 Using a tree-like structure Treating tokens and fields as separate entities with one-to-one map- ping is easily shown to be insufficient in converting even simple games. The first problem with this approach is that some games require placing more tokens in one logical space and preserving their order — for example, card decks in card games. Fields thus should instead be ordered collections of tokens. Another obstacle is that in some games, the physical tokens can be placed one on top of the other, and then moved as one logical

2.

10 3. Analysis of requirements on the framework

unit. Furthermore, there may be different ways to place one token on top of another, for example, a character card having two “slots”. This observation leads to the idea that fields should not be independent, but instead, each part of a specific token. The resulting structure is tree-like, consisting of tokens, of which each belongs to at most one field, and has zero or more fields itself. For example, when representing chess, there would be a token representing a chessboard with 64 fields. Finally, some games store information in the physical state and properties of the tokens. Tokens may be rotated, for example, but different types of modifications may also occur.

3.1.4 Representing state not contained in tokens

As mentioned previously, there is a need to record immediate infor- mation that is not already encoded in the physical game token. Such information may include what player’s turn it currently is, or what game action just happened. Thus, the framework needs to offer ways to store information not already contained in the token tree.

3.2 Representing rules

A typical tabletop game advances between states by player moves. In some states, players face a decision of what moves to make. The library thus should present the possible choices to the player, and then modify the internal states accordingly after a player makes a choice.

3.2.1 Rule language

Tabletop game rules are defined in natural language, and as such, have no limitations on what is expressable. For this reason, representing the rules as snippets of source code was found ideal, rather than constructing a custom format for declaring rules. Additionally, these code snippets may have metadata associated.

11 3. Analysis of requirements on the framework

3.2.2 Non-linearity There are many different approaches to explaining rules to the players. Most are informal. As such, most written game rules start with ex- plaining the general game loop. Later, other mechanics are explained in terms of deviation from the general structure. A popular theme is writing special rules directly on physical game objects – for example, cards. The non-linear nature of such a rule definition makes it hard to represent directly as a program source code. For a game implemented in a naïve way, such deviations would result in added branching at arbitrary parts of code. For example, a card stating “If you hold this card, you take three gold instead of two at the beginning of your turn” might result in an extra if condition in the part of rules responsible for taking gold at the beginning of player’s turn. Explicitly accompanying such deviations from the core game loop obscures the original code, and mixes the code responsible for the specific card with the code responsible for the core game loop. Thus, to achieve the goal of close mapping of the resulting source code of the digital rules and the original rule text, the framework must provide enough expressivity. Rules should be able to specifically refer to other rules, alter their results, or completely replace them. The other rule should require little or no modifications to allow this.

12 4 Framework definition

This chapter describes the framework used to represent and store the internal state of the digitized tabletop game, as well as to accept player input and progress the game according to the rules. The framework is designed based on the analysis in the previous chapter. This chapter gives a general overview of what the framework consists of and how the parts interact. The technical details of the actual implementation are then described in the following chapter.

4.1 Representation of physical state

The physical state of a game can be described as a configuration of tokens. A token is an abstract representation of a physical object that is part of the converted physical game. It may have arbitrary properties associated with it, like text, color, rotation, or similar. Each token may also define zero or many fields, which act as “mount-points” (or “slots”) for other tokens. Fields can be viewed as ordered collections of tokens. Tokens thus form a tree-like structure. Each token is located on a field of some other token, except for the so-called “root token”. Root token is a special token defined by the framework. It has two fields, called “table” and “box”. These are somehow analogous to their real-world counterparts: at the beginning of the game, all the non-root tokens are located in the field “box”; the field “table” is empty. It is expected that game rules move appropriate tokens to the “table”. The immediate game state is stored in the “state object”, which is a game-defined structure storing arbitrary data. The state object dictates which rules are run next1. The state object is usually replaced on every state change, and thus stores only short-lived information: who’s turn is it, what phases of player’s round already passed, and similar. Similarly, there is the “global state object” for storing global in- formation. It is not replaced as the game progresses, and thus fit to store persistent information. Note that the global state object should

1. The rule dispatch logic is more thoroughly explained in the second half of this chapter.

13 4. Framework definition be used sparingly – it is preferred to store information in the token tree.

4.1.1 Example representation In order to illustrate the concept of a token tree, a small instance is visualized below. The visualized game is a simple 3 by 3 physical version of Tic-Tac- Toe. The game contents are a 3 by 3 game board, 5 X-stones and 5 O-stones. The following situation on the game board:

OX OOX XX

...is stored in the token tree as visualized by figure 4.1.

root box table

board 0,0 1,0 2,0 O O X 0,1 1,1 2,1 0,2 1,2 2,2

O O X O X X X

Figure 4.1: Token tree for a specific game state of the game Tic-Tac-Toe. Labels outside represent token names, labels inside represent field names. The X and O tokens are the exception: they have no fields, so the name label is inside for clarity.

14 4. Framework definition 4.2 Representation of rules

4.2.1 External framework behavior External behavior of the framework can be summarized as: ∙ Possible moves are presented to the player(s). ∙ A player chooses a move to make. ∙ The game’s internal state is modified accordingly. ∙ A new set of possible moves is presented. Internally, this behavior is controlled by a set of “rules”, which are snippets of code with accompanying metadata defining in what phase of the game loop they are invoked.

4.2.2 Rule definition A rule is defined with the following properties: ∙ rule name: A string. No two rules with the same name can be run at the same time. They may, however, coexist – just when both become active, the one with the higher priority wins. ∙ predicate: A predicate determining whether this rule is invoked. ∙ procedure: The core procedure of the rule, carrying out the logic. ∙ priority: An order defined relatively to other rules2. ∙ invocation type: Described in section 4.2.4. At specific stages of the interaction loop, a “rule scan” is performed. During a rule scan, all rules are scanned, and predicates are used to choose rules that are invoked. If multiple rules have the same name, only the one with the highest priority is invoked. Qualifying rules are then invoked from the highest to the lowest priority.

4.2.3 Commands returned from rules On the invocation of a rule, the corresponding procedure is executed and may modify the game state. Additionally, the procedure may return any number of the following commands: ∙ change state: After a rule scan is performed, and at least one rule commanded to change state, the state object is changed to the

2. In the resulting library, this property is implicit, defined by the definition order of the rules.

15 4. Framework definition

one specified by the rule with the highest priority. Changing state has precedence over offering the player a choice. ∙ add choices: Specifies a set of moves the player is allowed to perform. If no rule commanded to change state, the player is offered all the choices produced by the rules in the lastrule scan. ∙ filter choices: Imposes a new condition on the moves player is allowed to perform, possibly forbidding some moves allowed by a different rule.

4.2.4 Invocation types There are three main types of rules, divided by how and when the rule is considered to be invoked: ∙ entry rules: Rules that are invoked right after a state change, and also at the very beginning of the game. These rules usually produce choices for the player. However, a state change can also be requested, resulting in another run of entry rules with the new state. ∙ choice rules: Rules that are invoked after a player chooses a move. They usually modify the token tree according to the player-requested move (for example, moving a figure), but any arbitrary action can be taken. Rules with this invocation type may request a state change, or offer more choices to the player. ∙ call rules: Rules that are invoked directly by other rules, not as a part of a rule scan. They may receive arbitrary arguments from the calling rule and return arbitrary values back.

4.2.5 Interaction loop The interaction loop consists of the following steps: 1. A new state is entered. A rule scan of entry rules is performed. 2. Choices returned from the rule scan are presented to the player. 3. Player makes a choice. A rule scan of choice rules is performed. If any new choices are returned, go back to the previous step. Additionally, any rule scan can return a state change command, which results in a new state object and return to the first step. Other- wise, the rule scan returns choices for the player. If rules in one rule

16 4. Framework definition scan return both choices and state change commands, state change takes precedence. In the beginning, an “initial state” is entered, which results in a rule scan of state entry rules. The steps are visualized in a graph on figure 4.2.

Run state entry rules State changed

Choices returned

Present choices State changed

User input Choices returned

Run choice rules

Figure 4.2: Rule loop of the framework

17

5 Library implementation

This chapter concerns the specifics of the library implementation ofthe framework described in the previous chapter. First, the technologies used are briefly introduced, followed by information on how to install and import the library. The format to describe tokens and rules is then outlined, followed by a documentation of the interface of the developed library. The name of the library was decided to be tabletop-engine.

5.1 Technology used

The library is implemented in JavaScript. This language was chosen mainly because of the number of platforms it is available on, running out of the box on virtually all devices, and being able to be embedded in common game creation frameworks. Also, the dynamic nature of the language allows fast prototyping. The library is distributed as a module in the CommonJS format. (Installation information is in section 5.2.) CommonJS is a widely used module format popularized by Node.js, but also well-suited for use browsers and embedded script engines. Though, only Node.js has direct CommonJS support, other platforms usually use a bundler to pre-process CommonJS modules. As the library uses features from the EcmaScript 2015 standard, it is incompatible with some older browsers1. However, as those browsers require bundling of the CommonJS module anyway, it is sufficient to translate the code to an older version of the standard during the bundling process, by using a library like Babel2. The library depends on the package lodash3, which provides bet- ter functional programming support and additional utility functions for JavaScript, and is widely popular. This library provides its inter- face under the object _ (an underscore). For example, the function _.isMatch(obj, pattern) checks if obj matches the pattern pattern – that is, all of the key-value pairs in pattern are also present in obj.

1. 2. 3. 19 5. Library implementation

No other runtime dependencies are used – however, there are two development dependencies that are useful for the development of the library: ∙ The tool eslint4 is used in order to check that the standard EcmaScript 2015 is used, and for general code quality improve- ments using static analysis. It is using the configuration file .eslintrc.json. ∙ The tool prettier5 is used for code formatting. It uses the uni- versal configuration file .editorconfig6. The functionality of the library is contained within three classes: GameManager, Token and Choice, of which only the first is user- constructible. As the JavaScript language support for private fields7 is currently in an experimental phase, this library opted to use the “classic” way: private8 methods and fields have names prefixed with an underscore.

5.2 Installation tabletop-engine can be installed into the current folder with the following command9:

npm i https://github.com/JanPokorny/tabletop-engine

The library is then available to .js files in the same folder, and the GameManager can be imported simply by:

const {GameManager} = require(’tabletop-engine’);

4. 5. 6. 7. 8. Private by convention. The privateness is not actually enforced, analogically to Python. 9. Requires npm, the Node.js package manager. The tabletop-engine package is, at the time of this writing, not available in the central npm repository. An attempt to publish it there was made, but it was automatically blocked without explanation.

20 5. Library implementation

Example usage of GameManager can be found later in this chapter in section 5.5.1. The .js file can then be executed by node, or bundled by a bundler.

5.3 Token definition

Tokens, as described in the previous chapter, are defined by plain JavaScript objects with the following keys:

∙ fields: An object where keys are the field names and values are objects with the following keys:

– type: Required. "single" for a simple field, "array" for an n-dimensional array of fields. – dimensions: Tuple of numbers defining the size of each dimension (not present for "single" fields).

∙ props: An arbitrary object defining default properties of the token. Two keys have special treatment:

– name: Default key to match against when a string is pro- vided. – owner: Intended to mark the player controlling the token, the function .owner() uses it to look up the chain.

∙ count: Number of instances of this token.

All properties except for type of fields are optional. For example, a token definition object may look like listing 5.1. Token definitions are passed to the GameManager constructor, de- scribed later. The root token, returned by calling root() on a GameManager in- stance, has two fields called10 "!box" and "!table", with every token except the root one initially being in the "!box".

10. Exclamation mark was used to denote that these fields are not user-defined.

21 5. Library implementation

1 { 2 fields:{ 3 field:{ type:"array", dimensions: [8, 8] } 4 }, 5 props:{ 6 name:"chessboard", 7 type:"basic", 8 colors:["black","white"] 9 }, 10 count: 1 11 } Listing 5.1: Example token definition

5.4 Rule definition

Rules, as described in the previous chapter, are defined by plain JavaScript objects with the following keys: ∙ name: Required. String label, grouping rules concerning the same task. No two rules with the same name are invoked in a single rule scan. ∙ on: Required. Invocation type of the rule. "entry" to run right after a state change, "choice" to run after a player selects a move, "call" to be callable manually. ∙ callName: Required if on: "call". A string identifier for call- ing this rule. It is different from name, as multiple rules may deliberately be called under one callName. ∙ fn: Required. The procedure11 of the rule. A standard JavaScript function (possibly with side effects). It receives the instance of GameManager as the first argument. Rules with on: "choice" additionally receive the complete Choice object as the second argument. Rules with on: "call" additionally receive the user- specified extra arguments. The procedure may return an array of commands, described later. ∙ stateName: Part of the rule predicate, requiring the current state to have the specified name12.

11. The name fn was chosen as every procedure in JavaScript is called a function, and to make the property visually distinct from pred. 12. Essentially a syntactic sugar, as the same could be achieved with pred only.

22 5. Library implementation

∙ pred: Function, part of the rule predicate. The rule is skipped if this function returns false. This function receives the same arguments as fn. Note that pred should avoid causing side effects. Required keys are marked as such. Rule priority is determined by definition order: rules that are de- fined later have higher priority, and thus are invoked sooner in arule scan. This approach has been chosen for simplicity and clarity. Al- though some games may require changing the order of rules to get the priorities right, this covers the most common case, which starts with general rules and follows with exceptions. Rule definitions are passed to the GameManager constructor, de- scribed later.

5.4.1 Command definition fn may return an array of commands. A command is defined by a plain JavaScript object. The one com- mon property is type, which can be one of: ∙ "changeState": After all rules are run, before offering choices to the player, the state is changed to the specified one. A rule of higher priority may override this command. ∙ "addChoices": After all rules are run, a Choice object is pre- sented to the player. This object represents a parametrized move. The parameters are to be chosen from a closed set, determined by the provided functions. ∙ "filterChoices: Filters choices provided by "addChoices" us- ing a predicate. Depending on the type of the command, other properties could or must be provided.

For type: "changeState", the required property newState de- fines the new state object. A state object should contain the property name to match with stateName of rule definitions, other properties can be arbitrary.

For type: "addChoices", the following additional properties can be provided:

23 5. Library implementation

∙ name: Required. This property defines the name of the choice. Usually, the name of the in-game action performed. ∙ player: Required. Identifier of the player responsible for carry- ing out this choice. ∙ params: An object with arbitrary keys and values. ∙ choices: An object with arbitrary keys. The keys represent the parameters of this move. The corresponding values should be functions with no side effects taking one argument – the current Choice object – and returning an array of possible values for this parameter. Note that the order of keys matters, as the choices are fulfilled in this order13.

For type: "filterChoices", the following additional properties can be provided: ∙ name: Required. Identifies the choice to be filtered. ∙ requiredParams: Required. An array of strings. All provided strings must be present in the params of the filtered choice, in order to evaluate the filter. The purpose of this parameter isto prevent running the filter on incomplete Choice instances. ∙ pred: Predicate function with no side effects. It receives the Choice instance as an argument. If it returns false, this partic- ular configuration of choice params is not permitted.

5.4.2 Special states In the beginning, after starting the GameManager, the initial state called ’!init’ is entered14. Similarly, the game may end by entering the state ’!end’, although this is just convention, and the framework contains no concept of an “end” – it is simply a state to which no rules react.

5.4.3 Example rule This section presents an example rule – listing 5.2 – taken from a hypothetical implementation of chess. The rule provides the player

13. The order of object keys in modern JavaScript is guaranteed, and is used for example in the React.js API. 14. Exclamation mark was used to denote that this state is not user-defined.

24 5. Library implementation

1 { 2 name:"addPieceMoves", 3 stateName:"playerChooseMove", 4 on:"entry", 5 fn: function (g){ 6 return [{ 7 type:"addChoices", 8 name:"movePiece", 9 player:g.state.player, 10 choices:{ 11 piece: () =>g.root() 12 .findToken("chessboard") 13 .findAllTokens({ 14 type:"piece", 15 owner:g.state.player 16 }), 17 destination:(m) =>g.callRule( 18 "getPieceMoves", 19 g.getToken(m.params.piece) 20 ) 21 } 22 }] 23 } 24 } Listing 5.2: Example rule

with a choice of moving their figures. The player first chooses oneof their pieces and is then offered possible destinations (received from a sub-rule call) depending on the piece they chose. This example illustrates how the chosen design prevents from needing to list all combinations of possibilities – that is, all the possible pairs of a figure and a move destination. Although the body of the procedure fn only returns a value, it may do any kind of operation with the GameManager instance in the argument g. (The interface of which is described later.)

5.5 API description

This section describes the available interface. The module tabletop-engine exports one symbol – the GameManager class.

25 5. Library implementation

There are also the classes Token and Choice, whose constructors are not exported, but instances of which can be returned from some methods.

5.5.1 GameManager

GameManager is the core class of the framework. It stores the token tree, state objects, as well as the rules and is responsible for processing input. It has the following methods: ∙ new GameManager(gameInfo, tokens, rules): The argument gameInfo should be an arbitrary game-defined object contain- ing information like the number of players. tokens should be an array of token definitions as described above. Similarly, rules should be an array of rule definitions as described above, in order of increasing priority. ∙ start(): Enters the initial state and executes the first rule scan. After calling this, GameManager is ready to offer choices to play- ers. ∙ root(): Returns the root token Token instance. ∙ getChoices(): Returns an array of Choice instances, represent- ing the possible moves players can take at this stage. ∙ performMove(move): Commits the move – a complete Choice instance. This operation results in one or more rule scans, after which the GameManager is again ready to offer new choices to the player. ∙ callRule(callName, ...args): Does a manual rule scan, with callable rules with matching callName. The results of rules ran, in order of decreasing priority, are returned as an array. Usually, when only one result is required, the caller should simply take the first element of the returned array. Additionally, there are the following properties: ∙ gameInfo: An arbitrary, game-defined global object, intended for defining game-related parameters like the number of play- ers. ∙ globalState: An arbitrary, game-defined global object, in- tended for storing game state that is impractical to store in

26 5. Library implementation

1 constg= new GameManager( 2 gameDefinition.gameInfo, 3 gameDefinition.tokens, 4 gameDefinition.rules 5 ); 6 7 g.start(); 8 9 while ( true ){ 10 const choices=g.getChoices(); 11 /*... interact with players...*/ 12 g.performMove(choice); 13 } Listing 5.3: Typical usage of the game manager

tokens or in state. May be used for information like scoring or round number. ∙ state: Object set by the "changeState" command from rules. Its name is matched against rules’ stateName; other properties can store arbitrary data. Listing 5.3 contains a typical usage of GameManager. GameManager instance is also passed to rules, allowing them to access its interface.

5.5.2 Token

Token instances represent an abstraction over physical tokens. They allow traversing and modifying the token tree. Each token, except for the root token, belongs to a field of some another token. The field is defined by the field name and, optionally, coordinates. Token instances are created upon constructions and held internally by GameManager from the passed token definitions. There is exactly one instance of Token representing a given physical token per instance of GameManager. For example, if some token definition contains count: 50, there are 50 instances of Token created. The following methods are available. ? denotes an optional argu- ment, which can be omitted if all the following optional arguments are also omitted.

27 5. Library implementation

∙ matchesPattern(pattern): If pattern is callable, calls it with the parameter this.props and returns the result. If pattern is a string, compares it for equality to this.props.name and returns the result. If pattern is an object, tests that all keys present in both pattern and this.props have the same value. ∙ moveTo(token, field, coords?): Moves this token to token’s field field, on coordinates coords. If the field requires coordi- nates, they must be provided. ∙ findAllTokens(pattern?, field?, coords?): Returns array of all tokens in the subtree. If pattern is provided, returns only those that match it with matchesPattern(pattern). If field is provided, returns only tokens in the subtree of the given field. If coords is also provided, it limits the returned tokens to the given coordinates. Otherwise operates with all coordinates. ∙ findToken(pattern?, field?, coords?): Same as above, but returns only the first result, or undefined if there are none. ∙ children(field, coords?): Lists all immediate children of this token, located in the specified field. If the field requires coordinates, coords must be provided. ∙ coords(): Returns current coordinates within the field on which the token is located. ∙ parentField(): Returns name of the field on which the token is located. ∙ parentToken(): Returns the Token instance of the parent token in the token tree. ∙ validCoords(field, coords): Checks if there is a field field with coords coords. Useful for checking if possible moves are within boundaries. ∙ order(): Returns the index of this token amongst all tokens located on the same field and coordinates. ∙ reorder(index): Changes the index of this token amongst all tokens located on the same field and coordinates to index. ∙ shuffleField(field, coords?): Order of tokens, located on the given field and coordinates, is randomized. If the field re- quires coordinates, they must be provided. ∙ owner(): Returns this.props.owner. If it is not defined, searches up the token tree until it finds a token with this.props.owner set. The owner of the root token is null.

28 5. Library implementation

Additionally, there are the following properties: ∙ id: Automatically generated numerical identifier. ∙ props: Object storing properties of the token. Initially copied from props in the token definition. It can be modified per token instance.

5.5.3 Choice A Choice instance represents a parametrized move players can per- form. Its purpose is to present action possibilities to the players and val- idate players’ choices. Choice instances are created by a GameManager instance from commands of type "addChoices" or "filterChoices" returned from a rule scan. The following methods are available: ∙ nextChoice(): Returns an object with two keys, name and values. name is a string name of the choice to be made, and values is an array of possible values. The caller then makes a choice by setting choiceInstance.params[name] to some value contained in values. Once all choices are made, this method returns null. ∙ complete(): Tests if all choices were made. The boolean result is returned. All choices are made if all of the keys in choices are also keys in this.params. ∙ valid(): Tests if all choices that were made were made correctly. The boolean result is then returned. The choice is made correctly if the value is one of the values returned from .nextChoice() for the appropriate choice. Note that it is possible to put a Choice instance in a state that is valid and incomplete, but no next choices are offered. The functions used to generate choices may try to prevent this, but in a general case, fulfilling a Choice instance may require backtracking.

29

6 Case study on the board game Citadels

This chapter concerns a case study of the created framework on a non-trivial game. Paper game rules were converted into a digital rep- resentation, and a rudimentary command line prompt interface was used to test the result. The game chosen for this case study is Citadels [8]. It is a card game focused on strategy and bluffing. This game was chosen because while the core gameplay loop is rather simple, there are many rule modifiers present. Note that the game was not chosen until the framework and library were developed. The framework and the library do not accommodate to this specific game in any way.

6.1 Structure of the case study code

The case study implementation is located in the files citadels.js (rules) and runCitadels.js (run and input loop). The code is pre- pared to run in Node.js and uses npm packages. npm install must be ran first in order to install dependencies from package.json. The command line interface (see section 6.3) is then accessed by running node runCitadels.js.

6.2 Rules

Here, a summary of the Citadels game rules is offered. Full rules of the “Citadels Classic” edition, which mostly corre- spond to the original rules, can be downloaded from the publisher’s webpage1.

1.

31 6. Case study on the board game Citadels

6.2.1 Introduction In Citadels, each player is building a city. The goal of the game is to be the first to build a city with 8 districts, and to be the one with the most beautiful2 one.

6.2.2 Components The main components of the game are: ∙ Gold coins. Used to pay for building districts. ∙ District cards. Each depicts the gold cost to build it, as well as the associated color (income). ∙ Character cards. Each depicts a different character with a dif- ferent ability.

6.2.3 Game round and player turns At the beginning of each round, each player secretly chooses one3 of eight characters. The characters are then revealed in a pre-defined order. After each one is revealed, the player controlling the character plays their turn. Each turn, the player first chooses to either receive two gold orto look at the top two cards of the district deck and choose to take one of them. Next, the player may build one district from their hand: place it on the table and pay the associated gold cost. The player may also use their character’s unique ability if it has one. All active special abilities are to be used at most once per turn. The player may also collect taxes once per turn if the current char- acter allows it. After all the characters are called, character cards are collected, and a new round begins.

6.2.4 Game end and scoring If a player builds their eighth district, the game ends at the end of the current round. The final score of a player is decided by adding up:

2. The notion of “beautiful” is rule-defined. 3. Two for some variants. 32 6. Case study on the board game Citadels

∙ Costs of all the districts built in their citadel. ∙ 4 points if they were the first to build 8 districts. ∙ 2 points if they managed to build 8 districts, but were not the first to do so. ∙ 3 points if this player’s city contains districts of all 5 colors.

6.2.5 Characters Each character has a unique ability. Some of the abilities are active, some are passive. ∙ Assassin: Selects a character to murder. The murdered character skips their turn silently. ∙ Thief : Selects a character to rob. Once the turn of this character begins, the player playing the robbed character must give all their gold to the Thief player. ∙ Magician: May exchange districts in hand with other players or the deck. ∙ King: Next turn, this player will be the first to select a character. May collect taxes from yellow districts. ∙ Bishop: The Warlord cannot destroy Bishop’s districts. May col- lect taxes from blue districts. ∙ Merchant: Receives one extra gold. May collect taxes from green districts. ∙ Architect: Receives two extra cards. May build up to 3 districts in one round. ∙ Warlord: At the end of their turn, they may destroy an already built district. The destroyed district can be in their city. They may not destroy a district in a city of a player who played as Bishop this round, or in a city that already has 8 districts. To destroy a district, Warlord must pay one less gold than the district’s original price. May collect taxes from red districts.

6.2.6 Special districts Some districts alter the game rules once built, providing an advantage to the owning player. ∙ Dragon gate and University: Count for 2 more points at the end of the game than their original cost.

33 6. Case study on the board game Citadels

∙ Great wall: The Warlord has to pay one more gold for destroy- ing other districts in this city. Thus, they pay the full district price. This ability does not cover the Great wall itself. ∙ Library: At the beginning of the player’s turn, if they choose to take cards, they take both. ∙ School of magic: When collecting taxes, the player gets one extra gold. ∙ Graveyard: The owner of this district may pay 1 gold to receive the district destroyed by Warlord and put it in their hand. This ability may not be used if the owner is the Warlord. ∙ Laboratory: The owner of this district may, once per turn, dis- card a district card from hand and earn one gold. ∙ Observatory: At the beginning of the player’s turn, if you choose to take cards, you choose from three instead of two. ∙ Smithy: The owner of this district may, once per turn, pay two gold and receive three district cards. ∙ Keep: Cannot be destroyed by the Warlord. ∙ Haunted city: Counts as a color of player’s choice for endgame scoring. This ability may not be used if built in the last round.

6.3 User interface

Creating a user interface was not the point of this case study. Thus, a rudimentary interface created using the prompts module4 was used. It interacts with the user through the command line, letting the user choose an option from the list using arrow keys and the Enter key. This solution is for demonstration and debugging purposes only, as the library purposefully does not provide a direct human interface. The state of the game is presented as a text serialization of the cur- rent token tree. Of course, this provides all information to all players and is not suited for actually playing the game. An actual GUI for the game would render only the information visible by each player.

4.

34 6. Case study on the board game Citadels 6.4 Modelling tokens

Citadels tokens are described trivially. Characters have their name and calling order, district cards have their name, income specification, and cost to build. Gold and counters are trivial. None of these have any fields. One feature was borrowed from a later edition of the game: char- acter tokens. In the classic rules of Citadels, the murdered and robbed characters are remembered by players. This information could be mod- eled by using state or globalState. However, a more elegant solution is to use dedicated counters that physically represent this information. There are also two utility tokens defined. First one is the game board, which holds the fields for district deck, character deck, burned characters (hidden and visible), character counters, and counters for assassinated and robbed characters. Second one is the player boards, which hold the fields for: ∙ Citadel (the built districts) ∙ Gold ∙ Districts in hand ∙ The districts player chooses from when they chose to take a card ∙ Character(s) (hidden and revealed) ∙ Counters (for marking the player who first selects the character, as well as points for building 8 districts)

6.5 Modelling rules

There was an attempt to model rules as directly as possible. Also, it was mostly avoided to create rules with exceptions in mind. In some places, this could not be avoided, but at least the “hooks” for later exceptions were made as unobtrusive as possible. As the whole rules are over 2000 lines, it is not feasible to thor- oughly explain all of the code here. The next sections thus focus mainly on compelling principles or approaches that were used and could be used as a guide for reading the code of the actual implementation. The core game mechanics are implemented expectedly, using the primitives described in previous chapters. The parts worth going

35 6. Case study on the board game Citadels through, which the created library aims to simplify, are the exceptions to the core rules.

6.5.1 Core game loop

The “core” loop of Citadels is as follows: ∙ Players choose characters. ∙ Each character is called. If it is in game: ∙ The player controlling this character chooses either gold or card. ∙ The player then may build a district Figure 6.1 captures how the game state changes during the core loop. For simplicity, this figure contains only the state names.

startNewRound

Prepare new round

playerChooseCharacter Next player chooses

Characters chosen Finish round

callCharacter Call next

Player reveals the called character All characters called

playerTurnBegin End turn endRound

Take gold Take card

Build district playerTurnContinue

Figure 6.1: Core loop of the game Citadels. Labels inside are state names.

36 6. Case study on the board game Citadels

6.5.2 Play of 2, 3, and 7 players For the play of 2 or 3 players, each player selects two characters in- stead of one. This change is achieved simply, as the core rules simply continue selecting characters until there are only two left for the last player to choose. The rules of burning cards are constructed for this to happen with the last player to choose a card. Additionally, for a game of 2 players, an extra card is chosen to be “burned” (discarded from selection). The rule defining a two-player game thus has a predicate to check gameInfo.numPlayers == 2, and a higher priority than the “core” rule for the same. For a game of 7 players, the last player takes the burned character to have two characters for their choice. This is achieved by an addi- tional rule (not overriding an existing rule), which is invoked once the second-to-last player has chosen a character. This section illustrates two approaches for modifying core rules: overriding a rule entirely, and adding a new rule while running all the original rules. The second approach is usually preferred, as it often results in shorter code. It is, however, not always applicable.

6.5.3 Collecting taxes Collecting taxes is a power common to four of the characters. Two rules implement it: one adding the choice to collect taxes at an appropriate phase, and a second one that is invoked when the player chooses to collect taxes and carries out the procedure. The approach of adding two rules, one offering a new choice and one executing it, is used several times in this implementation. It is a common thing “extra rules” in tabletop games might do.

6.5.4 Character powers The character powers are implemented in the following ways: ∙ Assassin: Three rules: one offers to commit murder, one executes the choice, the third one replaces the phase where this character would be revealed by skipping it, in case the given character was murdered. ∙ Thief : Analogous to Assassin.

37 6. Case study on the board game Citadels

∙ Magician: Rules offering either exchanging with the deck or with another player. The interesting thing is that the Magician may choose any subset of their cards to exchange with the deck. Instead of generating all subsets and letting the player choose, the implementation simply makes the player choose for each card separately whether to exchange it. This approach may not be the best for more complicated choices, so this brings up the question of whether choosing subsets instead of just one element should be supported directly by the framework. ∙ King: Quite trivial passive ability, implemented by two addi- tional rules. ∙ Bishop: Bishop’s passive power is mentioned in the rules in the section on the Warlord, so it is implemented there. A new rule could implement it, however, by a command of type "filterChoices" filtering out the districts belonging to the Bishop. ∙ Merchant: Trivial passive ability. ∙ Architect: Receiving extra cards is trivial. Upping the limit for districts would require overriding the corresponding rules. For simplicity of implementation, the earlier rules were modified to receive the upper limit on districts built from a rule call. The called rule than can be overridden easily. This approach should not be used very often, as it contributes to breaking up the core rules. ∙ Warlord: The cost to destroy a district was delegated to a new rule. The rest of the rule implementation is straightforward. However, there are many exceptions to this rule that are de- scribed later.

6.5.5 District powers The districts’ special powers were implemented as follows: ∙ Dragon gate and University: A new rule adding two points for each of these districts. ∙ Great wall: Overrides the utility rule for the cost to destroy a district, checking if the district is located next to a Great wall. ∙ Library: Overrides the rule responsible for taking cards at the beginning.

38 6. Case study on the board game Citadels

∙ School of magic: A new rule adding one more gold after the player chooses tax collection. ∙ Graveyard: Overrides the code responsible for Warlord destroy- ing a district, offering the Graveyard owner to take the card instead. ∙ Laboratory: Trivial pair of choice+execute rules. ∙ Observatory: Overrides the rule responsible for taking cards at the beginning. ∙ Smithy: Trivial pair of choice+execute rules. ∙ Keep: Overrides the utility rule for the price of destroying a district, setting its price to be infinite (and thus not destroyable). ∙ Haunted city: Adds a new rule for endgame scoring, detecting the case where the player did not receive the bonus for 5 differ- ent colors, but changing the color of this card would achieve it.

6.5.6 Rule ambiguity Rules of Citadels are ambiguous to some degree, as all tabletop game rules are. However, there is one direct contradiction: when a player builds both a Library and an Observatory (described in the previous section), the action of taking cards is not well-defined. Possible inter- pretations include letting the player choose two cards out of three, letting the player decide whether to use the Library or the Observatory this round, or merely defining that one of the effects win. In this case study, it was decided that the Observatory takes precedence.

6.6 Example rule explanation

For completeness, an example rule is explained thoroughly, including the used library functions. The chosen rule is the one invoked once a player chooses to use the Laboratory. Laboratory, as mentioned previously, allows the owner to, once per turn, discard a district card from hand and earn one gold. The example rule code is on the listing 6.1. The name of this rule is "playerTurnContinue_useLaboratory". The name serves identification purposes only.

39 6. Case study on the board game Citadels

1 { 2 name:"playerTurnContinue_useLaboratory", 3 stateName:"playerTurnContinue", 4 on:"choice", 5 pred:(g, move) => move.name =="useLaboratory", 6 fn:(g, move) => { 7 const board=g.root().findToken( 8 "gameBoard", 9 "!table" 10 ); 11 const currentPlayerBoard=g.root() 12 .findToken( 13 { 14 name:"playerBoard", 15 owner:g.state.player 16 }, 17 "!table" 18 ); 19 20 move.params.district 21 .moveTo(board,"districtDeck"); 22 23 g.root() 24 .findToken("gold","!box") 25 .moveTo(currentPlayerBoard,"gold"); 26 27 return [ 28 { 29 type:"changeState", 30 newState: Object.assign( 31 {}, 32 g.state, 33 { laboratoryUsed: true } 34 ) 35 } 36 ]; 37 } 38 } Listing 6.1: Example rule implementation

40 6. Case study on the board game Citadels

stateName is "playerTurnContinue", which is the second phase of each player’s turn, after taking either gold or a card. on: "choice" defines that this rule is run once player has made a choice. pred checks that the move player has chosen is the one corresponding to the Labo- ratory. Otherwise, the rule is skipped. The rule body is located in fn. First, the game board and current player board are retrieved using findToken. While the game board is retrieved by a string pattern (matching name), the player board matches both name and owner. The only parameter of the move is district, which is a Token in- stance. The method moveTo is then used to place the card to the end (bottom) of the district deck. Similarly, one piece of gold is retrieved from the box and moved to the "gold" field on the player’s board. Finally, a state change is triggered. Note that the object defining the state change is wrapped in an array, as fn returns an array of objects. The only change over the current state is that laboratoryUsed is now true. This state property is used to remember if the Laboratory was already used this round. Notice that this property was not defined before on the state – the dynamic nature of JavaScript allows this simple extension. How the rule5 affects the core loop is visualized on figure 6.2.The extra edge over figure 6.1 is marked bold.

5. Together with the companion rule that presents the choice to the player first.

41 6. Case study on the board game Citadels

startNewRound

Prepare new round

playerChooseCharacter Next player chooses

Characters chosen Finish round

callCharacter Call next

Player reveals the called character All characters called

playerTurnBegin End turn endRound

Take gold Take card

Build district playerTurnContinue Use Laboratory

Figure 6.2: Core loop of the game Citadels after inclusion of the card Laboratory. Labels inside are state names.

42 7 Evaluation of the case study

This chapter focuses on evaluating the created framework and library on the previously created case study. It also suggests possible future improvements.

7.1 Library evaluation

The developed library is a cross-platform black-box component pro- viding rule enforcement of tabletop games. This section evaluates the fulfillment of the main aims and goals outlined in the introductory chapter.

7.1.1 Generality and universality Even though the framework and library were not created with a spe- cific game in mind (the game Citadels was chosen after the library implementation was complete), there were no non-trivial obstacles encountered while developing the case study. It is thus expected that any game with the complexity of core principles and severity of “ex- ceptional rules” comparable to Citadels will be implementable with approximately the same effort. A single case study is an unfit metric for evaluating generality, though. There were even some library/framework features unused by the case study – for example, coordinates. However, it is obvious that any game is implementable by using two rules and a global state only – essentially avoiding the framework. Thus, it is expected that any game implementable in raw JavaScript is also implementable in this library, with possibly varying degrees of library utilization.

7.1.2 Closeness to the natural language rules Comparing the natural language rules and the digitized rules code side-by-side, they appear to have very similar logical flow and seman- tics. This is achieved thanks to the system of rule dispatch, where later rules can override earlier rules and thus modify the core loop

43 7. Evaluation of the case study separately. The digitized version is, however, much longer for any given rule than the natural language description. This disparity is partly expected because the natural language descriptions are often incomplete or ambiguous. However, the library also forces the user to write a lot of boilerplate lines. One of the most apparent offenders from the case study code is the repeating lines for getting the game board and current player board, as those need to be accessed in almost every rule1.

7.1.3 Ease of writing rules The library abstractions over tokens, their retrieval and manipulation, turned out to be sufficient for the case study. The approach used in this library turned out to work well with rule exceptions. There are very few cases in the case study where an earlier rule needed to accommodate a later exception. This property suggests that the library may be useful for games where the ruleset is still in development, allowing the addition of exceptional rules without modifying the core gameplay loop. There are some shortcomings with the current state, however. Since the library uses a custom dispatch system for rules, there is very little IDE support, namely in the areas of code suggestions and typo protection.

7.2 Possible future improvements

7.2.1 Direct support for client-server communication The library as-is does not have direct support for client-server commu- nication, where it is desired to hide some game state information from users to prevent cheating. The current system works well with local applications, where the presentation layer can take in mind that some fields may not be visible to all players. However, for networked play, it is desired to not send the secret information at all to the player’s computers.

1. The library user might decide to define a function to simplify this. However, the case study tried to keep as close to the created library’s interface as possible.

44 7. Evaluation of the case study

7.2.2 Add debug visualizations Both the token tree and the dispatch algorithm could benefit from a visual representation. It could even be possible to create a purely visual editor for the game tokens and rules.

7.2.3 Rely on the programming language’s type system JavaScript’s exceptionally dynamic and weak type system might be a limitation. Incorporating the rule dispatch system within the type sys- tem of a strongly-typed language, and then translating that language to JavaScript, seems like a reasonable solution to explore. Candidate languages are Kotlin and TypeScript, which both have strong type systems and can compile to JavaScript.

7.2.4 Add direct integration with a presentation layer Providing direct integration with a GUI layer (for example, some existing game framework) could vastly simplify the complete process of the creation of digital versions of tabletop games.

45

8 Conclusion

In this thesis, a framework for digitally describing tabletop game rules is proposed, implemented in a library1, and evaluated on a case study of a real-world tabletop game, Citadels [8]. A tree-like structure is used to represent the state of game tokens. A custom dispatch system is used for rules, which allows the core rules to be defined separately from later exceptions. The resulting implementation turned out to provide a sufficient level of abstraction. The resulting digital game rules are logically and semantically close to the natural language counterparts. The created library may be useful especially for tabletop games with rulesets still in development, or for rulesets with a high number of exceptions to the core rules. However, it is also discovered that the resulting rule code might be unnecessarily verbose and that the lack of IDE support hinders debugging. It is thus needed to evaluate the possibilities of reworking the application interface, possibly taking advantage of a strong type system.

1.

47

Bibliography

1. ROGERSON, Melissa J.; GIBBS, Martin R.; SMITH, Wally. Digitis- ing Boardgames: Issues and Tensions. In: DiGRA ’15 - Proceedings of the 2015 DiGRA International Conference. Digital Games Re- search Association, 2015. Available also from: http://www.digra. org/wp- content/uploads/digital- library/66_Rogerson- etal_Digitising-Boardgames.pdf. 2. TULLIS, Ryan. The Exhaustive You Can Play Online for Free | BoardGameGeek [online] [visited on 2018-11-19]. Available from: https://boardgamegeek.com/geeklist/140673/ exhaustive-list-board-games-you-can-play-online-fr? titlesonly=1. 3. ROGERSON, Melissa J.; GIBBS, Martin; SMITH, Wally. "I Love All the Bits": The Materiality of Boardgames. In: Proceedings of the 2016 CHI Conference on Human Factors in Computing Systems [online]. New York, NY, USA: ACM, 2016, pp. 3956–3969 [visited on 2018-11-19]. CHI ’16. ISBN 978-1-4503-3362-7. Available from DOI: 10.1145/2858036.2858433. 4. YAN, Xu; EVAN, Barba; IULIAN, Radu; MARIBETH, Gandy; BLAIR, Macintyre. Chores Are Fun: Understanding Social Play in Board Games for Digital Tabletop . In: DiGRA ’11 - Proceedings of the 2011 DiGRA International Conference: Think Design Play. DiGRA/Utrecht School of the Arts, 2011. ISBN ISSN 2342-9666. Available also from: http://www.digra.org/wp- content/uploads/digital-library/11307.16031.pdf. 5. KRZYWINSKI, Aleksander; CHEN, Weiqin; RØSJØ, Erlend. Dig- ital Board Games: Peripheral Activity Eludes Ennui. In: Proceed- ings of the ACM International Conference on Interactive Tabletops and Surfaces - ITS ’11 [online]. Kobe, Japan: ACM Press, 2011, pp. 280– 281 [visited on 2019-12-11]. ISBN 978-1-4503-0871-7. Available from DOI: 10.1145/2076354.2076415. 6. PAPE, Joseph A. The Effects of Digitization and Automation on Board Games for Digital Tabletops [online]. 2012 [visited on 2019-12-11]. Available from: https://qspace.library.queensu.ca/handle/ 1974/6946. thesis.

49 BIBLIOGRAPHY

7. STENROS, Jaakko; WAERN, Annika. Games as Activity: Cor- recting the Digital Fallacy. In: 2nd Conference on Video Gaming and the Future of Interactive Entertainment : Stockholm University, Department of Computer and Systems Sciences, 2010. 8. FAIDUTTI, Bruno. Citadels. 1st ed. MultiSim, 2000. Board game. 9. Virtual Tabletop Programs for Wargames, Boardgames & Card Games [online]. 2016 [visited on 2018-11-19]. Available from: http:// battlegroundsgames.com/links/#anchor7. 10. Studio - Board Game Arena [online] [visited on 2018-11-19]. Avail- able from: http://en.doc.boardgamearena.com/Studio. 11. SandboxScripts - Board Game Arena [online] [visited on 2018-11- 19]. Available from: http : / / en . doc . boardgamearena . com / SandboxScripts. 12. OCTGN: Online Card and Tabletop Gaming Network [online]. 2018 [visited on 2018-11-19]. Available from: https://github.com/ octgn/OCTGN/wiki. 13. Programming Tutorial - VASSAL [online] [visited on 2018-11-19]. Available from: http://vassalengine.org/wiki/Programming_ Tutorial. 14. SCHILLER, Eric. The Official Rules of Chess: Professional, Scholastic & Internet Chess Rules. New, rev. ed. New York: Cardoza Pub, 2003. ISBN 978-1-58042-092-1.

50