Skip to content

Tutorial: Creating a TicTacToe Bot

Mike Leonard edited this page May 21, 2016 · 9 revisions

Introduction

As an introduction to Merknera this tutorial will guide you through creating a bot to play Tic-Tac-Toe in JavaScript using node.js. The aim of this tutorial is to give you an introduction into creating a bot, registering and having it play its first games - this should give you a good understanding of how JSON-RPC works in the context of Merknera and how to test your bot using ngrok and postman.

A simple an non-effective implementation will be implemented and it will be left as an exercise of the reader to improve upon this.

Prerequisites

You will need to have the following software download and installed before continuing with this tutorial:

Setting Up

  1. Create a new directory and navigate to it at the command line.
  2. Run npm init and following the on-screen instructions.
  3. Run npm install jayson --save to install and add the dependency to our package.json file created for us in step 2.

Server Implementation

When orchestrating a game Merknera acts as a client and makes calls to the bots participating in the game and the bots act as a server. We will start by implementing the 4 server methods required by Tic-Tac-Toe to play a game: Status.Ping, TicTacToe.NextMove, TicTacToe.Complete & TicTacToe.Error.

Status.Ping is the easiest so we will start with that.

Status.Ping

Status.Ping is called whenever the Merknera server starts to find out which bots are online and it also calls Status.Ping prior to any move being played, this enables Merknera to ensure the bot is still online and to wake up any bots that might be hosted on a free service such as Heroku that goes to sleep after periods of inactivity. Status.Ping is the same for all game types so its code can be reused. Full documentation can be found here

We need to be able to accept a method of Status.Ping with no parameters and return with a result of "ping": "OK".

  1. Create a file called `index.js
  2. Add the following contents.
// Import the jayson module into a variable names "jayson"
var jayson = require('jayson');

// Create a jayson server.
var server = jayson.server({
  // Register the Status.Ping method
  "Status.Ping": function(callback) {
    // Write a log message so we can see that this RPC method was called.
    console.log("Status.Ping");
    // Invoke the callback that will respond to the client.
    callback(
      null,
      { ping: "OK" } // Return an object with ping: "OK" that will be used in the response.
    );
  },
}, {
   // don't collect params in a single argument
   // More information can be found here: https://github.com/tedeh/jayson#named-parameters
  collect: false
});

// Start the server and listen on port 3000.
server.http().listen(3000);

This code registers the Status.Ping method and returns ping: "OK" when called.

We can now test this method using Postman.

  1. Launch your server by typing node index.js at the command line
  2. Launch Postman an create a new request.
  3. Click on the "GET" drop down and change it to "POST"
  4. In the request URL enter http://localhost:3000.
  5. Click on the "Headers" tab and add a header with a "key" of Content-Type and a "value" of application/json
  6. Click on the "Body" tab and select the "raw" radio button option.
  7. Paste the following into the body in Postman.
{
  "jsonrpc": "2.0",
  "method": "Status.Ping",
  "id": 1
}
  1. Click "Send" and you should get a result like the following. You can also check the command line and you should see a message written of Status.Ping.
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "ping": "OK"
  }
}

If you followed the above steps and got the above result then everything worked and you can move on to the next RPC call.

TicTacToe.NextMove

This method is responsible for taking in the current game state and returning your bots next move. Full documentation can be found here

  1. Add the following code to jayson.server alongside "Status.Ping"
var server = jayson.server({
  ...
  "TicTacToe.NextMove": function(gameid, mark, gamestate, callback) {
    // Write a log to the console so that we can see that this RPC method was
    // called and what the parameters.
    console.log("TicTacToe.NextMove: gameid: " + gameid + ", mark: " + mark + ", gamestate: " + gamestate);
    // Invoke the callback that will respond to the client.
    callback(
      null,
      { position: 0 } // For now hard code position one to play in.
    );
  }
  ...
}

When adding this, don't forget to add a comma after the closing } of "Status.Ping".

This code registers the TicTacToe.NextMove method. This method accepts the current game ID, the mark (either "X" or "O") that you are playing and the current game state as an array of each position on the board. See the GameBoard documentation for more information.

We can now test this method using Postman - this is mostly the same as when testing Status.Ping.

  1. Launch your server by typing node index.js at the command line
  2. Launch Postman an create a new request.
  3. Click on the "GET" drop down and change it to "POST"
  4. In the request URL enter http://localhost:3000.
  5. Click on the "Headers" tab and add a header with a "key" of Content-Type and a "value" of application/json
  6. Click on the "Body" tab and select the "raw" radio button option.
  7. Paste the following into the body in Postman.
{
  "jsonrpc": "2.0",
  "method": "TicTacToe.NextMove",
  "params": {
    "gameid": 78,
    "mark": "X",
    "gamestate": ["O", "X", "O", "", "O", "", "", "X", ""]
  },
  "id": 1
}
  1. Click "Send" and you should get a result like the following. You can also check the command line and you should see a message written of TicTacToe.NextMove: gameid: 78, mark: X, gamestate: O,X,O,,O,,,X,.
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "position": 0
  }
}

Enhancing the game play logic.

Currently the bot is hard-coded to always respond in position 0. This will cause an error if player has already played this move.

Clone this wiki locally