Creating a Go Bot Part V -Coordinates system-

Note: Part of this article is copied from my old blog.

Note 2: The repo is here

Now that the engine knows how to play a random valid move, there is something more that we have to do previously to make the engine play “less” randomly.

Using GTP (in next posts we will talk a little more about Go Text Protocol that will be implemented in the project) the engine sends and receives coordinates, so we need something to translate from positions to coordinates and from coordinates to positions.

Right now, this convertion will be responsability of the board class, maybe in the future it can change, but I think it is board responsability to do that translation, what do you think about that?

My first idea is this one:

def posToCoordinate(self,position):
        column=['A','B','C','D','E','F','G','H','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
        finalCoord=""
        fPositionFound = False
        for row in range(1,self.boardSize):
            for col in range(0,self.boardSize):
                if col+self.boardSize+2+(row-1)*(self.boardSize+1) == position:
                    fPositionFound = True
                    finalCoord = column[col]+str(row)
                    break

        return finalCoord

Sure it works for boards until 25×25, to make bigger boards I would need to add more letters to the list, but for now let it be like this.

Now, the program will receive a coordinate, so I need to put it as a position to update my board array.

First I need to convert from a coordinate to a number. If we look at a 6×6 board with coordinates we see this:

    A    B   C    D    E   F
00 01 02 03 04 05 06
1 07 08 09 10 11 12 13
2 14 15 16 17 18 19 20
3 21 22 23 24 25 26 27
4 28 29 30 31 32 33 34
5 35 36 37 38 39 40 41
6 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56
Now, let’s think that letters have a numerical value A=0, B=1, C=2, D=3, E=4…
Using as reference: Row=r, Column=c, n=number of rows or columns
I can use:  c + n + 2 + (r-1)*(n+1) 
 
(I guess it is easy for people with good knowledge of mathematics, but for me, to get here was like hell).
For example (in 6×6 board):
  • D4 = 3 + 6 + 2 + (4-1)*(6+1) = 3 + 6 + 2 + 3*7 = 11 + 21 = 32
  • A6 = 0 + 6 + 2 + 5*7 = 8 + 35 = 43

But this position is starting in 1, but Python arrays stars in 0, so I have to rest 1 to the total:

def coordinateToPosition(self,coordinate):
        column = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U','V', 'W', 'X', 'Y', 'Z']
        return (column.index(coordinate[0])+self.boardSize+2+(int(coordinate[1])-1)*(self.boardSize+1))-1

 

 

Another thing I need to work with this is to make a better print of the board , to look like this:

Just to not loose time on this and to continue with the important part, I will make it with numbers starting from top, it is the same as it is rotated and mirrored.

This is a quick version:

class Printer:
    def printBoard(self,aBoard):
        column = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U','V', 'W', 'X', 'Y', 'Z']
        rowCounter=0
        cut=0
        line = ""
        colCounter = " "
        for i in range(0,aBoard.boardSize):
            colCounter=colCounter+column[i]
        print(colCounter)
        for i in range(0, aBoard.totalSize-1):
            if aBoard.boardList[i]==0:
                line = line+"."
            if aBoard.boardList[i]==1:
                line = line+"B"
            if aBoard.boardList[i]==2:
                line = line+"W"
            if aBoard.boardList[i]==3:
                line = line+"#"
            cut=cut+1
            if cut == aBoard.boardSize+1:
                if rowCounter>=1 and rowCounter<=aBoard.boardSize:
                    print(line+"#"+str(rowCounter))
                else:
                    print(line + "#")
                rowCounter=rowCounter+1
                line=""
                cut = 0

I changed the main script to print both convertions and this appeared:

Thanks for reading!

Creating a Go bot Part II -The board-

 

Note: Lots of this material was taken from my old go blog with some new text that I am adding now because some years passed since that, I am not the same, my coding skills are not the same and my vision and ideas are not the same.

Let’s begin with the development of the bot. First, it needs to understand that there is a go board (goban) and it has positions, but what is the best way to do this?

Long, long time ago there was a document at sensei’s library that I don’t see so, I will copy from my old blog:

Board representation
The most basic of all basics. In order to have a program that can play Go, we need a representation of a Go board in computer terms. Although Go is played on a variety of board sizes, the most popular by far is 19×19. For teaching purposes or for entertainment it also is occasionally played on 13×13 or 9×9. As far as I know, smaller sizes than that are only occasionally used as testing grounds for computer programs. Also boards larger than 19×19 are so rare that I choose to ignore them completely.

For now I will only assume that the board is square so rows == columns, nothing else, the game should be able to be played in any NxN board where N > 0 (well, let’s say N>1, because 1×1 needs to enable suicide move).

Since the board is always square (with an uneven number of lines), common sense would point to using a two-dimensional array to represent the board. Unfortunately computers take much longer to access a two-dimensional array than a one-dimensional array. For this reason most serious Go playing programs will use a one-dimensional array to represent the board. The one-dimensional position z of a board-point x,y is then arrived at by the following conversion: z = x + y *19 (for a 19×19 board represented by a one-dimensional array of size 361). From now on I’ll use xy instead of z as the one-dimensional equivalent of the two-dimensional coordinate x,y. Since the program will internally only use one-dimensional arrays, it will in practice not have to do such conversion often. A computer doesn’t care whether the coordinate is represented in a one dimension or two.

Ok, so as I assumed this board will always be square it follows at some point what I was thinking I should do. For computing pourposes I think it is the same if lines are even or uneven.

Two-dimensional array is a big mistake here, I want to save all the memory I can so I think it is fair to change to a simple array.

There’s a practical difficulty with representing the board in a one dimensional array however. How can the program distinguish between the borders of the board? This is still possible by looking at the coordinate. When xy%19 equals 1 or 19, or when xy/19 equals 1 or 19 we have a point on the 1st line.

I remember when I first red this, I thought that was the end even before starting, but let’s say that after a while I get the idea of how to do this. It seems to be a lot of trouble just to replace a two dimensional array by a simple array, but it is not. Let’s check what’s next:

Next to that is the edge of the board. This is a rather cumbersome way however, and such calculation will cancel out any performance gained by using a one-dimensional representation. The common way to solve this is by usig a bigger array and use border-points around the board to indicate the board boundaries. At first you may think this would lead to a 21×21 representation, and indeed in a two-dimensional board representation this would be the case. When this gets mapped to a one-dimensional array and you’d print out the information stored, you may notice something interesting however. Whenever a border-point is reached to mark the edge of the board, you see two consecutive border-points next to each other. For this reason, the one-dimensional representation can be a little smaller. Instead of 21×21=441 points, we can make do with 20×21+1=421 points. This has one more advantage: to convert a one-dimensional coordinate to two dimensions, the division is by 20 instead of 19 or 21, which is a lot easier for humans. As said before, computers don’t care about such things, but it’s a lot easier when seeing one-dimensional coordinates in your debugger this way. Trust me, it’s a lot easier! After this you should understand the reason behind the constant values defined at the top of the class tesuji.games.go.util.GoArray.

So, you can still imagine a 2 dimensional array using a one-dimensional array, it is just to quit one border x row, because from a row to another you only need one space that will be the border. Something like this:

#########
#*********   <—The next one will be a border.
#*********
#*********
#*********
#*********
#*********
#*********
#*********
#*********
##########

This is just a 9×9 board example, but this would work on any size.

Next point is what I will put in any position of the array, so for our convenience we can use:

  • 0 = empty
  • 1 = black
  • 2 = white
  • 3 = wall
  • 4 = ko

With this I think I am covering all posibilities, if not, I can add more values later.

In my next post I will add more information about this just to not make this post too long. I know this post was a lot about theory, but believe me, next one will show the Python solution for this.

See you then!

Creating a Twitter Bot II – Random Twits

 

Hello again, welcome back to this “tutorial” about creating a Twitter bot, if you missed first part, please read it here.

So, now that we can Twit, maybe we can do some interesting things with that.

Creating random Tweets

As I wrote in the last article, one problem of tweeting “Hello World” is that you can’t twit twice the same text. In the other hand, we want the program to run all the time, tweeting different things, so we will make our program twit every x seconds a random text.

First thing is to create a class that will have some common functionalities and in there create a method that will create random texts of x characters.

 

import random

class Common:
    def randomText(self,characters):
        posibleCharacters=['a','b','c','d','e','f','g','h','i','j','k','l','m','n','ñ','o','p','q','r','s','t','u','v','w','x','y','z',' ','1','2','3','4','5','6','7','8','9']
        returnedText = ""
        for i in range(0,characters):
            returnedText = returnedText+random.choice(posibleCharacters)
        return returnedText

Even if the code is easy, here is a little explanation of how this works:

I have an array of characters that can be used for the text, and then a for from 0 to the number of desired characters it concatenates a string with new random character. In the end that string is returned.

Now that we have the functionality to send some random text, we can post tweets with a fixed delay. Here is one way to do that. Remember main file we have? Let’s work on that file and do something like this:

from Twitter import *
import time
from Common import *

starttime=time.time()
twitter = Twitter()
common = Common()
twitter.connect()

while True:
    time.sleep(30.0 - ((time.time() - starttime) % 30.0))
    twitter.tweet(common.randomText(140))

We need time library to make it post every x time. time.time() returns the time as a floating point number expressed in seconds since the epoch, in UTC. For more information about Time library look here. Next step is to make objects of class Common and Twitter and connect to our Twitter account.

Now that we are connected we enter in an infinite loop and say sleep x seconds (in the example I putted 30, but you can put what you want) and then post a random tweet of 140 characters calling the randomText method.

If you want the code, fork it, review it, do whatever you want just clone it from here

Next time we will do some changes to our profile, see who follows us, follow people, etc. so stay tuned!

 

Creating a Twitter Bot

In this series of articles I will be creating a Twitter bot in Python (because, maybe I said this before, but Python is THE language). Creating a basic bot is something really easy and at the end of this article we will have a basic bot posting tweets.

All the code up to date is in a public repository in github, so you can freely clone it from here

What we need:

  • Python (the glorious computer language) 3.X
  • Tweepy (there are other libraries, but, this one is great).
  • A Twitter account (that will be the bot’s account)
  • A Twitter app (I will explain this in the first point of the article).

Create a Twitter App

First of all you need a Twitter app, this is a way to tell Twitter guys that you will be using their API. To do that you need to go to developers link in Twitter, then search for “Manage my apps” and there you will see a “Create new App” button.

From there is just to complete a form with some basic data about the application you want to create:

  • Name of the application
  • Description
  • Website (a place where people can download, use or get info about the app).
  • Callback URL (optional, it depends if you will use it or not).

Once you save, you will have a access token, access secret token, consumer key and a secret key to access your account and do things with your bot.

Get Tweepy

Ok, now Twitter know we are going to do something with his API, so we need a library to easily access that API. We are going to use Tweepy for this tutorial but there are plenty of other libraries out there. Simply pip install it (you may need sudo on Linux)

pip install tweepy

Now we can start programming!

Basic coding

Now, lets open our favorite python (the almighty) IDE (in my case is Pycharm), and lets start

The first class I will like to create is the connector class, I will call it Twitter.py

import tweepy

class Twitter:
    def __init__(self):
        self.key="your key code"
        self.secretKey="your secret key code"
        self.access = "your access token"
        self.secretAccess = "your secret access token"
        self.auth=""
        self.api =""
    def connect(self):
        self.auth = tweepy.OAuthHandler(self.key, self.secretKey)
        self.auth.set_access_token(self.access, self.secretAccess)
        self.api = tweepy.API(self.auth)
    def tweet(self,message):
        self.api.update_status(message)

Let me explain a little what we did here:

First I imported Tweepy so this class can use it (kind of obvious but I am here for all level of developers).

In the init part of the class I added the keys I get when I created the app in Twitter and two more variables for auth and the api manager.

The first method “connect” is self descriptive 🙂  it does the OAuth part, connecting to Twitter (if you want more info about OAuth please check this website) and sets the API manager for future use.

Now that we have this class (in future articles we will update this class, but for now it is a good start) we want to tweet something, so, lets create another class to do a main class to send a tweet (it is obvious that this will be updated as the project grows).

 

from Twitter import *
twitter = Twitter()
twitter.connect()
twitter.tweet("Hello World!")

This works, but, second time you run it, it will not post your message because you cannot duplicate twits. But the idea of this first article was just to understand how you can twit something as a bot, from here you can do lots of things. For example you can do a loop to twit different things with some time in the middle.

Stay tuned, next time we will do lots of fun stuff with Tweepy!

Python Tutorial Chapter 1 -Hello World!-

python logo

 

As I said in one of my first posts, there are plenty of good reasons to program in Python and as I love this language, I will try to do tutorials, kind of  “from zero to hero”. I wish this tutorial makes you learn about Python.

 

What you will need for this tutorial:

  • Python 3
  • PyCharm (well, any other IDE will work, I just chose this one for this because I feel it is the best one).
  • Eager to learn

So, any comments, ideas, questions, whatever, just comment here or in the video I will answer.

 

P.S.: Notice that I don´t have any script for the videos, so when I press “record” I only have the idea of what I am going to talk, so I am not sure of what I am going to say at the beggining of the video.

Let’s program the Game Of Life

gol1

Ok, this is the first “coding post” of the blog and it is not in Python! You red my first post and thought that this blog was going to be about Python, and then, a programming post using JavaScript. Well… here you will see a lot of things in a lot of languages.

Note: You can grab lots of game of life algorithms in different languages for free from Rosetta Code.

In this post we will start with the game of life coding by doing the logic in javascript, so, next time we can start programming the html part with canvas.

 

So, lets get started: first lets create our gameOfLife.js file, the logic of the game:

For a good start, our 2 dimensional array will be 10×10 positions:

var x = new Array(10);
for (var i = 0; i < 10; i++) {
    x[i]= new Array(10);
}

For now, all the positions will take a 0 or 1 in a random way:

for (var i = 0; i< 10;i++){
  for (var j=0;j<10;j++){
    x[i][j]=Math.floor(Math.random()*2);
  }
}

Until we have some good way to see it, lets put the output in the console, so I was thinking in a simple function like this:

function showOnLog(myArray){
  var line="";
  for (var i = 0; i< 10;i++){
    for (var j=0;j<10;j++){
      line = line+myArray[i][j].toString();
    }
    console.log(line+"\n");
    line = "";
  }
}

So, if we send the array there we should see our initial state.

And now let’s run this (for showing purpose I will run it with node, but any way to run your js is good):

gol1

Now, we have to change it in cycles so, we will enter in a new for and look for our 4 rules:

  1. Any live cell with fewer than two live neighbours dies, as if caused by under-population.
  2. Any live cell with two or three live neighbours lives on to the next generation.
  3. Any live cell with more than three live neighbours dies, as if by over-population.
  4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

To do so, we need a function to count the neighbours of a cell:

function neighboursCounter(myArray, posx,posy){
  counter = 0;
  if(posx>0){
    if (myArray[posx-1][posy]==1){
      counter++;
    }
    if(posy>0){
      if (myArray[posx-1][posy-1]==1){
        counter++;
      }
    }
    if(posy<myArray[posx].length-1){
      if (myArray[posx-1][posy+1]==1){
        counter++;
      }
    }
        
  }
  if(posy>0){
    if (myArray[posx][posy-1]==1){
      counter++;
    }
  }
  
  if(posy<myArray[posx].length-1){
    if (myArray[posx][posy+1]==1){
      counter++;
    }
  }
  if(posx<myArray[posx].length-1){
    if(posy>0){
      if (myArray[posx+1][posy-1]==1){
        counter++;
      }
    }
    if (myArray[posx+1][posy]==1){
      counter++;
    }
    if(posy<myArray[posx].length-1){
      if (myArray[posx+1][posy+1]==1){
        counter++;
      }
    }
  }
  
  return counter;
}

 

And, once you have the status you need a function to determine the status of the cell given the rules:

function newState(actualValue,neighbours){
  cellState=0
  if(actualValue==1){
    if(neighbours>1 && neighbours<4){
      cellState=1;
    }
  }else{
    if(neighbours==3){
      cellState=1;
    }
  }
  return cellState;
}

All these values will be put in a second auxiliar array (If I put them in the actual array the values of a cell will be calculated using the modified values, so, lets create a new function with an array that will receive the new values:

function arrayState(myArray){
  var x = new Array(10);
  for (var i = 0; i < 10; i++) {
    x[i] = new Array(10);
  }
  for(i=0;i<10;i++){
    for(j=0;j<10;j++){
      myNeighbours = neighboursCounter(myArray,i,j);
      x[i][j]=newState(myArray[i][j],myNeighbours);
    }
  }
  return x;
}

And at least, the loop with steps to make it work (for the example I will hardcode it to 5):

for (var steps = 0; steps< 5; steps++){
  x=arrayState(x);
  console.log("Step: "+steps.toString());
  showOnLog(x); 
}

This is all for this post, in the next one, we will add the web part and star quitting all the hardcoding.

If you want the latest code of this project, you can clone it from github