Implementation

Most of this application was made in Java. However the logic part of the application was implemented in Prolog. In this section we will give a short description of how we made this application. All files can be downloaded from the download page. The gameplay is explained briefly with the screenshots which can be found on the screenshots page.

Go to:

> Prolog section
> Java section
> Bottom

Prolog

All of the knowledge in the game, is represented in the Prolog code. The Prolog code can deal with variable numbers of players. At the start of a game, Prolog receives the number of players and makes that many agents (see agents.pl). During the game, the knowledge of all players is modelled in Prolog, to be able to give hints to the players.

There are two rules that are used to determine the knowledge an agent has.

  • An agent knows the value of a tile, if the tile lies open on the table.


knows(_, is_stone(TargetAgent, Position, Colour, Number)) :-
  stones(TargetAgent, Stones),
  nth0(Position, Stones, stone(Colour, Number, open)).
	

  • An agent knows that certain values of a (hidden) tile are not possible if the tile already lies open on the table, or if the agent has the tile himself.


knows(Agent, not(is_stone(TargetAgent, Location, Colour, Number))) :-
  not(knows(Agent, is_stone(TargetAgent, Location, _, _))),
  (
    % Agent has tile himself
    has_stone(Agent, stone(Colour, Number, _))
    ;
    % Tile lies open on table
    stone_is_open(stone(Colour, Number))
  ).
			

Furthermore the game uses the rule that a black stone has to be put left of a white stone in the line, if the values for these stones are the same.

The most important Prolog file however is solve.pl. Here we calculate a code, consider whether it is possible and if so, we add it to our sequence of all possible codes.

The following code determines whether a certain code is possible:

possible(ReqAgent, Agent, Position, TillNow, stone(Colour, Number)) :-
% Generate the code
  code(Number),
  (
    % This code is possible if:
    % the agent knows the values for the stones
    knows(ReqAgent, is_stone(Agent, Position, Colour, Number))
    
    % or
    ;
    (
      % agent does not know the value/stone
      not(knows(ReqAgent, is_stone(Agent, Position, _, _))),
      
      % the code is not in the list yet
      not(listfind(TillNow, stone(Colour, Number))),
      
      % agent does not know that the a value is not correct
      not(knows(ReqAgent, not(is_stone(Agent, Position, Colour, 
                                                        Number)))),
      
      % stone cannot invalidate sequence
      can_sequence(stone(Colour, Number), TillNow)
    )
  ).

As can be seen above, a code can only be possible, if it is consistent with the knowledge of the agent (e.g. the values of the tiles the agent already knows and the knowledge of the agent about which values are not possible), or if the agent does not know the value of the tiles and the code has not been considered yet and the code is indeed possible (e.g. black tiles left to white tiles of same value).

Java

In our Java code, we use the list of all possible sequences as generated in Prolog. This can be used to give the players hints. For example all possible values for one stone can be viewed by a player or the game can give a hint that the player should be able to know the value of a stone, given its current knowledge. We will explain how this is implemented further below. First we will discuss the basic structures that were used in the Java code.

Basic components

We first made a class for players (see Player.java), containing their name, a boolean variable which indicates whether it is the player's turn to do an action, a vector with all the tiles a player has and an aside tile, where the tile that is taken from the pile on the table is stored. Furthermore it contains methods to add tiles to the tile vector of the player (this method is also used in the initiation of the game to fill the vector), methods to set and get the turn, a method to get the tiles, to get the name, to get and set the aside tile and a method to add the aside tile in the vector if the turn is done.

We also made a class for the tiles (see Tile.java). A tile has a value, representing whether its colour is black or not (thus white), a variable which states whether the tile lies open on the table or not and an integer value, which is the value that is set on the tile. Furthermore this class contains get and set methods for the open variable, and get methods for the colour and value variables.

A class for the game was made as well (see Game.java). In the game class, we have a vector filled with the Player objects and a vector filled with the tiles from the pile on the table and there also is a variable that stores which player is the active player. There are methods with which a player can be added to the game (used in the initialisation of the game), a method that initialises the pile with tiles, a method that can give a tile to a player (this methods puts a tile in the player's aside position and can give a tile with a preferred colour), methods to get the players or the active player, a method that switches the turn of the player, a method that returns all players except for the active player and a method that returns the number of stones of a given colour that is on the pile.

The Graphical User Interface

The game was made as an application, so that it can be played offline (without the need of an internet connection). The standard components that were used for the graphical user interface (GUI) are the JFrame and JPanel (see DaVinci.java). At the start of a game, the number of players is asked. A check will be performed to be sure that 2, 3 or 4 players are chosen (the amounts of players that can play the game, see the game page). Then the names of the players can be typed in, serially, and after this the game will be visualised.

To be able to visualise the game, several renderer classes are needed.
TableRenderer.java draws the table, the players (tiles and names) and the piles and it can update the table (redraw piles and numbers). It uses the PileRenderer, TileRenderer and NumberRenderer classes which draw respectively the pile, the player tiles and the numbers on the player tiles. These classes also use the SwingDragImages, ImageFactory, GhostedDragImage and AbstractComponentDecorator classes.

Coupling to Prolog

The coupling between java and prolog can be found in the file Prolog.java through the swi-prolog bindings for java (jpl). In this file we make sure that the players and tiles are created in Prolog. Furthermore the sequences with possible values for tiles are retrieved from Prolog. These are then used to create the hints (see TableRenderer.java). The hints give the possibility (in percentages) that a tile has a certain value. In the game, we show that hints are possible for a tile by showing a blue overlay. If for a certain tile the value should be known to the player, then a green overlay is given to the tile.

Go to:

> Prolog section
> Java section
> Top