Star Trek 3D Chess Data Model

Emil Drkušić, Database designer and developer, financial analyst

Emil Drkušić
Database designer and developer, financial analyst

Posted: January 4, 2018

model design, database design, star trek, 3d data model

If you’re a Star Trek fan, you likely know that Captain Kirk and Mr. Spock frequently play a variant of chess called Tri-Dimensional Chess, or 3D chess, a game that’s similar to standard chess but with notable differences. In this article, we’ll build a data model for a 3D chess application that allows players to compete against each other. Beam us up, Scotty!

The Concept of 3D Chess

While chess itself is already a complex game, combining boards and multiple sets of pieces can significantly increase the game’s complexity.

In 3D chess, boards are stacked in parallel layers, and special movement rules apply to certain pieces, depending on where they’re located. For instance, pawns on the middle board can mimic the behavior of a queen. Pieces can also move from one board to another, with certain restrictions applied, and the boards themselves can even move around and rotate. No wonder Kirk and Spock enjoyed 3D chess so much—it requires quite a lot of tactical finesse!

Tri-Dimensional chess also deviates from standard chess in terms of the properties of its boards. In 3D chess, there are seven distinct boards with different properties. Three of these boards are 4x4, while the remaining four boards are 2x2. You can move these smaller boards around.

Our data model will hopefully cover everything we need to play a game of 3D chess in a web app. We’ll work under the assumption that everything can move around and that boards can impose different movement restrictions on the same pieces. This should be sufficient to cover all possible 3D chess variants. Let’s jump right into the data model!

The Data Model

Our data model consists of three sections:

  1. Players and Games
  2. Game Setup
  3. Matches

We’ll now discuss each of these areas in greater detail.

Section 1: Players and Games

Section 1: Players and Games

Everything in our model is either directly or indirectly related to games. Of course, a game can’t proceed without players!

The list of all players is stored in the player table. In our model, players are all the registered users of our application. For each player, we’ll store the following information:

  • first_name and last_name – the first and last names of the player, respectively.
  • user_name – the username the player selected, which must be unique.
  • password – a hash value of the player’s password.
  • nickname – the player’s screen name, which, like their username, must be unique.
  • email – the player’s email address, which they’ll supply during the registration process. The code required to complete the registration process will be sent to this email.
  • confirmation_code – the code that was sent to the player’s email address in order to complete their registration process.
  • confirmation_date – the timestamp of when the player confirmed their email address. This attribute will store NULL until the player confirms their email.
  • current_rating – the current rating of the player, calculated based on their performance against other players. Players will start with some initial value, and their ratings will increase or decrease according to the ranks of their opponents and their game outcomes.

The result table is a dictionary that stores the values of all possible unique game outcomes, namely “in_progress”, “draw”, “win”, and “lose”.

Perhaps the most important table in the entire data model is game, which stores information about each game of 3D chess. In this model, we’ll assume that two human players will compete against each other and that they may choose to save their current game state and resume at a later time (such as if they’d like to make one move per day, in which case the players will log in to the app, see their opponent’s most recent move, think of their own move, execute their move, and then log out). We’ll store the following values in this table:

  • player_id_1 and player_id_2 – references to the player table denoting both participants of a game. As mentioned, we’re assuming a game will strictly occur between two human players.
  • number_of_moves – denotes the number of moves that have been executed so far in the current game. When the game starts, this number is set to 0 and increases by 1 each time a player makes a move.
  • player_id_next – a reference to the player who must make the next move in the current game.
  • result_id_1 and result_id_2 – references to the result table that store the outcome of the game for each player.
  • player_1_points_won and player_2_points_won – denote the number of points the players were awarded, in accordance with the result of the game.

We’ll discuss how players can keep track of all moves in the Matches section near the end of this article. For now, we’ll move on to the Game Setup.

Section 2: Game Setup

Section 2: Game Setup

The Game Setup section contains a description of all boards and pieces in 3D chess, as well as a list of all legal moves players can make.

As we mentioned earlier, 3D chess often involves more than one board. These boards can adhere to the standard 8x8 dimensions with fixed positions, but that need not be the case. The list of all boards is stored in the board table. For each board, we’ll store a unique board_name, the starting_position of the board in relation to our chosen 3D coordinates, and all additional details.

Next, we’ll define all possible types of pieces that could appear on our chess boards. To do so, we’ll use the piece_type dictionary. In addition to its primary key, this dictionary contains only one unique value, type_name. For a standard chess set, we expect to see the values “pawn”, “rook”, “knight”, “bishop”, “king”, and “queen” in this dictionary.

The list of all individual pieces that are used in a game of 3D chess is stored in the piece table. For each piece, we’ll store the following information:

  • piece_name – a unique name describing the piece type and its starting position.
  • starting_position – a value denoting the precise board and square on which the piece is initially positioned.
  • board_id – a reference to the board on which the piece is originally positioned.
  • piece_type_id – a reference denoting the piece’s type.

Finally, we’ll use the move_type table to store the list of all possible moves the pieces can make on our boards (as well as any moves the boards themselves can make). Recall from the introduction that certain boards apply special movement rules to their pieces. For each move, we’ll define the following:

  • type_name – a name we’ll use to denote the move that was made, which won’t be a unique value (e.g., we can have “pawn advanced 1 square forward” as many times as needed).
  • piece_type_id – a reference to the type of piece that was moved. If this value happens to be NULL, then the movement concerns an entire board and not a particular piece.
  • board_id – denotes the board on which this move will take place (if a chess piece is moving). If the board itself is moving, this value will naturally represent the board that is being moved. Together with two previous attributes, this forms the unique key for this table.
  • is_piece_move and is_board_move – denote whether a move concerns a chess piece or a board. Only one of these flags may be set to true for a particular move.

Since there are too many piece moves and rotations to consider, we won’t store all such possibilities in our database. Instead, we’ll just store the move names and implement the actual logic in the application itself. For example, we’ll define that pawns can either advance forward a single square, advance two squares from their starting position, claim pieces diagonally, move from one board to another, and move as a queen on the central board. So, we’ll have five possible move types defined for pawns, depending on the board they are placed on and their current position.

Section 3: Matches

Section 3: Matches

We’re nearly finished! The last section of our model is named Matches and contains three new tables that we’ll use to keep track of the movement history in a game of 3D chess. The remaining tables are just copies of other tables from our data model, which helps avoid overlapping relations. We’ll also store the current positions of all boards and their pieces in this area. Let’s dive right in.

The move table is actually the most complex table in this section. It contains the list of all moves executed during a game. This table will display the list of all moves to players, which can later be used to review or analyze the match. For each move, we’ll store the following:

  • game_id – a reference to the game in which the move was made.
  • player_id – a reference to the player who made the move.
  • move_in_the_game – the ordinal number of the move. This number, combined with a piece’s starting position and all other moves, can be used to recreate the whole game. The idea is to allow players to simulate the game once it’s completed so they can analyze the results of the match.
  • piece_id – a reference to the piece that was moved. This makes it easy to track a piece’s movement from beginning to end (mainly for analysis purposes).
  • piece_type_id – a reference to the type of piece that was moved. While a piece’s reference will always remain constant, its type may change throughout the game (such as if a pawn is promoted). If we’re moving the board, this attribute will contain a value of NULL.
  • board_id – a reference to the board on which the move took place.
  • move_notation – an agreed-upon notation that we’ll use to represent moves.

The remaining two tables allow us to store a snapshot of the current game state in the database, which is helpful if the players wish to resume the game at a later time.

The current_board_position is used to store the position of all boards in our 3D coordinate system. This is necessary for 3D chess games in which at least one board can change its position. For each record in this table, we’ll store a reference to the related game and board, as well the notation of a board’s position. Two specific attribute pairs, game_id + board_id and game_id + position_notation, form the unique keys for this table.

Our last table is current_piece_position, which stores references to the related game, a particular piece, the piece’s type, and a position notation for the piece. We’ll again have two pairs of attributes that serve as the unique keys for this table: the game_id and piece_id pair and the game_id and position_notation pair.


That’s about it for this data model—we’re proud to announce that Captain Kirk and Mr. Spock can now play 3D chess on a computer!

Do you have any suggestions for improving our data model? Feel free to leave your comments down below. Live long and prosper ??


Try our online database modeler. No registration. No commitments.

Subscribe to our newsletter

If you find this article useful, join our weekly newsletter to be notified about the latest posts.

New SQL Course! Find out how to identify all the factors of a successful visualization: think like your audience, find the right chart type, and take out the meaning of the data. View course Discover our other courses: