Nine Men's Morris
I separated the board logic from the game logic to make the game extensible and modular. The game logic implements parts like rule validation.
npm install morris
To use the
morris CLI program, install it globally.
npm install morris -g
The board is completely modular which means that you are not focused on the normal look of a Nine Men's Morris board.
By using the property
points in board options, you can define how many points exist on each side and wether they are connected with the upper row.
And the amount or rows can be defined with the property
rows in board options. More about the idea behind
points in Points.
To require the module you can browserify it simply with browserify. In the case of a browser's API the module will add the class
MorrisGame to the window object you can use instead.
As Node.js module, just require it:
const Morris = ;
To create a new game instance call:
var myGame =board:rows: 3points: false true falsepieces: 9rules: true;
Morris class will automatically create a new
MorrisBoard instance for itself. You find it at as
board property of your game instance.
As I already said, the
board is own class instance for controlling the board. Normally you do not need manipulating it directly but if you want to know how, have a look at Morris Board.
That is just good to know to understand why addressing a point will be done by defining a
row and a
position (Index within the row).
The reason why I separated board and game logic is, that this keeps the process completely clean extensible.
Please note that the board works with a circular coordinate system. What that means is described more detailed below.
Your instance should look like:
board: <MorrisBoard> // The instance of the board your game instance usespoints: Array // Array containing the template for points on each siderules: true || false // Wether rule validation is enabled// More information about the structure of a team and a 'piece' object you will find belowteams:name: "white"pieces: Array // Array containing your defined amount of pieces for each team as objectsname: "black"pieces: Array // Array containing your defined amount of pieces for each team as objects// Object containing some information to validate rules like 'nextTeam' or 'nextAction'__rule:nextTeam: Getter // Returns the next team using the information about the last changesetnextAction: Getter // Returns the next action using the information about the last changeset__lastChangeset: <ChangeSet> // The last successfull changeset. Used to get next team or action
The algorithms for validating rules and all related properties and methods are absolutely responsive which means, that your game instance will not modify more properties than needed. The only important property that will always be edited by your game instance is the
__lastChangeset property in
__rule (More about this below). All the other stuff like
points property of your instance is the same as you used as argument when creating the instance. If you did not specified one, the default one is used.
In detail this array describes, how many points your board has on each side and wether they are connected with each other.
For example, the default
points array looks like:
false true false
This means that the points left and right side are not connected with the upper and lower one but the point in the middle is. Because a Nine Men's Morris board normally looks like this, this is the default value.
teams array of your instance contains objects that represent each team.
Normally there exist exactly two teams, called
white but theoretically more teams would be possible. And also the algorithms behind rule validation and game logic are made for more than two teams.
But that is just the general theory behind it.
A team object looks like:
name: "teamName"pieces: Array // Array containing your defined amount of pieces for each team as objects
As you saw, the
pieces array within a
team object contains each piece as an object. You can define the amount of the pieces for each team in
pieces property when creating your game instance.
A piece object literal contains thre properties.
point whose value represents an index in
map array within the in game's board instance. If the piece is not set yet,
The other property is
removed that contains a boolean value. It is used to declare a piece as removed.
The third one is the Getter
activePieces that just returns an array with all pieces of the team that are not removed but still active.
name: "teamName" // "white" or "black"pieces:...point: null // null or the index of the point, the piece is standing onremoved: false // Wether the piece is already removed...
To handle internally with rules and the logic of a game, a object for rules, named
__rule exist in your game instance.
To get a list of all valid moves call:
This will return an
array containing objects representing each movement specially for the kind of movement. For example, a
remove movement only needs a
targetPoint property wether a
move movement usually has also a
startPoint property containing the point the movement is going to start from.
Movement Object Literal
action: "movementName" // "set", "move" or "remove"; String describing the kind of movementstartPoint: Object // Optional. Point object literal who refers to the start point within the 'board.map'targetPoint: Object // Point object literal who refers to the target point within the 'board.map'team: "teamName" // "white" or "black"
To get a piece that is related to a point's position, use the
// Returns the piece object literalvar piece = myGame;// Log the piece objectconsole;
If not piece is related to this point, the method will return
To set a new piece to the board use the
set method of your game instance.
(More about the coordinating system in MorrisBoard->Coordinating)
var changeset = myGame;// If an error occured (Set action was not allowed)if changeseterrorconsole;// The set action was successfullyelseconsole;
To move a piece from one point to another one, use the
move method of your game instance.
var changeset = myGame;// If an error occured (Movement was not allowed)if changeseterrorconsole;// The movement was successfullyelseconsole;
To remove a piece from the board, use the
remove method of your game instance.
var changeset = myGame;// If an error occured (Removement was not allowed)if changeseterrorconsole;// The removement was successfullyelseconsole;
To get the next team just get the property
nextTeam of your game instance.
Please keep in mind that this property is a getter and is related to the
__lastChangeset object of your game instance.
// Get the next teamvar nextTeam = myGamenextTeam;// Log itconsole;
Please keep in mind that after a created mill, the next action is normally
remove. But the next team is* not the team that is removing (Normally the same team that created the mill before) but the contrary team whose piece will be removed.
To get the next action that should be performed within the game, just get the property
nextAction of your game instance.
// Get the next actionvar nextAction = myGamenextAction;// Log itconsole;
phase property of your game instance returns the current phase of the match. (0-2) / (1-3)
// Get the current match's phasevar phase = myGamephase;// Log itconsole;
To get wether the game is over, just get the
gameOver property of your game instance.
// Get wether the game is overvar isGameOver = myGamegameOver;// Log itconsole;
To get wether the game is a draw, just get the
draw property of your game instance.
// Get wether the game is a drawvar isDraw = myGamedraw;// Log itconsole;