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 |
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.
knows(_, is_stone(TargetAgent, Position, Colour, Number)) :- stones(TargetAgent, Stones), nth0(Position, Stones, stone(Colour, Number, open)).
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).
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.
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 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.
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 |