Skip to content

Santorini the Board Game

Published on
5 mins read
––– views

The physical version of board game Santorini made by Poxley

This is a course project of CMU 17-514 (17-214): Principles of Software Construction. The project is implemented in Java and React (TypeScript).

As per the school's integrity policy, I am not allowed to share any related code publicly. This post documents my design choices; the Learnings at the end cover what I would do differently if I were to start over.

At a glance

  • Course: CMU 17-514 Principles of Software Construction, Spring 2022
  • Stack: Java + NanoHTTPD backend, React + TypeScript + MUI frontend
  • Scope: the full Santorini rule set including god-card extensions, designed with OOA/D artifacts first
  • My role: solo project
  • Code: not public (course integrity policy)

Many thanks to Prof. Claire and Prof. Bogdan for the decent lectures.

Introduction

Santorini is a highly accessible pure-strategy game where you play as a youthful Greek God or Goddess competing to best aid the island's citizens in building a beautiful village in the middle of the Aegean sea. - Roxley

Santorini's basic rule is simple: each player has two workers, and the goal is to build a tower of three floors on a vacant square or move one of your workers onto the third floor. But all sorts of interesting game extensions are added to make the game, as well as the software design & development, more fun and challenging.

The detailed game rules can be found here.

The goal was to port the board game to the web while practicing the software-construction process shown in Fig-1. The project is complex enough to need real planning and design, and it offers plenty of places to apply the design patterns and principles from the course.

Fig-1 Software Construction Activities. Construction activities are shown inside the gray circle. Construction focuses on coding and debugging but also includes detailed design, unit testing, integration testing, and other activities. - Code Complete 2nd


Detailed Design

This section shows some key designs of the game, stressing the first-stage iteration of software construction as elaborated in Applying UML and Patterns. Here are some concise descriptions of the terminology:

  • Domain Model: the classic model of object-oriented analysis. It illustrates the important concepts in a domain and is a source of inspiration for the software objects.
  • System Sequence Diagram: for one scenario of a use case, shows the events external actors generate, their order, and inter-system events. Each system is a black box; the diagram is about events that cross the system boundary.
Fig-2 The First-Stage Iteration of Software Construction

Domain Model

Fig-3 Domain Model of the Game

System Sequence Diagram

Fig-4 System Sequence Diagram

Operation Contracts

This sample contract describes the "move worker" operation: a formal statement of its preconditions and postconditions, used to check that the implementation is correct.

  • Operation: WORKER.moveWorker(Worker worker, Grid dest)
  • Preconditions:
    • It's the turn of the player who will move the worker.
    • The worker is selected by current player.
    • The destination square is either empty or topped by a block at most one level higher than the worker.
    • The destination is one of the 8 squares adjacent to the worker.
  • Postconditions:
    • The worker is associated with the new square and dissociated from the old one.
    • The worker's position is updated: its x and y become those of the new square, and its z becomes the height of the top piece (zero if the square is empty) plus 1.
    • The game checks whether the current player has won. If so, the game stage becomes END and no further interaction is accepted.
    • Otherwise the stage changes to CHOOSE, where the player picks a square to build on.

Implementation

The backend is Java: it holds the game state and enforces the rules. The frontend is React with TypeScript: it renders the game and handles user interaction.

Showcase

Fig-5 Player 1 Choosing His Power

Fig-6 Players Done Choosing Their Power

Fig-7 A Sample Ongoing Game

Learnings

  • The up-front OOA/D artifacts paid for themselves the moment god cards arrived. Each god card bends one rule (movement, building, winning). Because the domain model and the operation contracts already named those rules, adding a card meant adding a strategy, not rewriting the game loop.
  • Keep the rules pure and the transport thin. Game state and rule checks live in plain Java objects that know nothing about HTTP; NanoHTTPD only serializes state in and out. The rules could be unit-tested without a server, and the front end became a pure renderer of whatever state it received.
  • TypeScript on the front end made the game's state machine explicit. Modelling the stage (CHOOSE, MOVE, BUILD, END) as a discriminated union turned a whole category of "clicked at the wrong time" bugs into compile errors.
  • Next time: fewer patterns, more tests. I reached for a design pattern at every hook point the course offered, and some of them (a factory for a class with two variants) added indirection without adding flexibility. The tests around the operation contracts were worth far more than the extra abstraction.