Page 1 of 2

the basics of creating a go bot

Posted: Wed Feb 11, 2015 7:42 am
by phillip1882
i'm not sure if these algorithms are correct but they look like they are. i programmed them myself in python so hopefully they are right. please comment.

Code: Select all

board = ["+"]*361
black = 'B'
white = 'W'
empty = '+'
turn = "B"
ko = -1
def liberties(n, t, boardc, turn):
    #check the current position n. if empty, mark it and increase counter by 1
    if n == '+':
        boardc[n] = '*'
        return t+1
    #if stone, mark it and recursively check left right top and bottom.
    elif boardc[n] == turn:
        if turn == "B"
            boardc[n] = 'b'
        else:
            boardc[n] = 'w'
        if n%19 < 18:
            t = t +liberties(n+1, t, boardc)
        if n%19 > 0:
            t = t +liberties(n-1, t, boardc)
        if n/19 > 0:
            t = t +liberties(n-19, t, boardc)
        if n/19 < 18:
            t = t +liberties(n+19, t, boardc)
    else:
        return t

def group(n,t,boardc,turn):
    same as liberty except count stones instead of empty.
    if boardc[n] == turn:
        if turn == "B"
            boardc[n] = 'b'
        else:
            boardc[n] = 'w'
        t += 1
        if n%19 < 18:
            group(n+1, t, boardc,turn)
        if n%19 > 0:
            group(n-1, t, boardc,turn)
        if n/19 > 0:
            group(n-19, t, boardc,turn)
        if n/19 < 18:
            group(n+19, t, boardc,turn)
    else:
        return t

def next(turn):
    if turn == 'B':
        turn = 'W'
    else:
        turn = 'B'
    return turn

def is_legal(n,board,ko,turn):
    if n =="pass":
        return True
    if n == "resign"
        return True
    if n == ko:
        return False
    #if you capture, its legal, if not, check suicide
    boardc = board[:]
    turn = next(turn)
    if n%19 <18 and liberties(n+1,0,boardc,turn)==0:
        return True
    boardc = board[:]
    if n%19 >0 and liberties(n-1,0,boardc,turn)==0:
        return True
    boardc = board[:]
    if n/19 >0 and liberties(n-19,0,boardc,turn) ==0:
        return True
    boardc = board[:]
    if n/19 <18 and liberties(n+19,0,boardc,turn) ==0:
        return True
    boardc = board[:]
    turn = next(turn)
    if liberties(n,0,boardc,turn) ==0:
        return False
    else:
        return True

def capture(board):
    #clear captured stones denoted b or w, return total captured
    total = 0
    for i in range(0,len(board)):
        if board[i] != '+':
            if board[i] != "W" or board[i] != "B":
                board[i] = '+'
                total += 1
    return total

def play(n,board,ko,turn):
    capture stones, detect ko (single capture with a group of size 1).
    new_ko = -1
    caps = 0
    if is_legal(n,board,ko,turn):
        boardc = board[:]
        turn = next(turn)
        if n%19 <18 and liberties(n+1,0,boardc,turn)==0:
            liberties(n+1,0,board,turn)
            caps += capture(board,turn)
            if caps == 1:
                new_ko = n+1
        boardc = board[:]
        if n%19 >0 and liberties(n-1,0,boardc,turn)==0:
            liberties(n+1,0,board,turn)
            caps += capture(board,turn)
            if caps == 1:
                new_ko = n-1
        boardc = board[:]
        if n/19 >0 and liberties(n-19,0,boardc,turn) ==0:
            liberties(n-19,0,board,turn)
            caps += capture(board,turn)
            if caps == 1:
                new_ko = n-19
        boardc = board[:]
        if n/19 <18 and liberties(n+19,0,boardc,turn) ==0:
            liberties(n+19,0,board,turn)
            caps += capture(board,turn)
            if caps == 1:
                new_ko = n+19
        boardc = board[:]
        if caps == 1:
            turn = next(turn)
            if group(n,0,boardc,turn) == 1:
                ko = new_ko
            turn = next(turn)
    turn = next(turn)
    board[n] = turn
    turn = next(turn)

def scoresection(board, que, color, n)
    #mark each empty space until you get to a stone. if it's different color, no territory.
    if board[n] == "+":
        board[n] = "*"
        que += [n]
        if n%19 < 18:
             k,c  = scoresection(board,que,color,n+1)
             if c == "":
                 return k,c
        if n%19 > 0:
             k,c  = scoresection(board,que,color,n-1)
             if c == "":
                 return k,c
        if n/19 < 18:
            k,c  = scoresection(board,que,color,n+19)
            if c == "":
                return k,c
        if n/19 > 0:
            k,c  = scoresection(board,que,color,n-19)
            if c == "":
                return k,c
    elif board[n] == "B" and color = "":
        color = "B"
    elif board[n] == "W" and color = "":
        color = "W"
    elif color == board[n]:
        return que,color
    elif n not in que:
        return [],""

def evaluatescore(board,komi,handicap):
    #score the section of all 361 points. return total.
    que = []
    color =""
    totalBlack = 0
    totalWhite = 0
    boardC = board[:]
    for i in range(0,361):
        que,color = scoresection(boardC,que,color,n)
        if color != "":
            for i in range(0,len(que)):
                board[que[i]] = color
    for i in range(0,361):
        if boardC[i] == "B":
            totalBlack += 1
        if boardC[i] == "W":
            totalWhite += 1
    return totalBlack -totalWhite -komi -handicap

Re: the basics of creating a go bot

Posted: Wed Feb 11, 2015 2:37 pm
by seki
Fun times :study:

What are you planning for the "Finding the best move" part? It feels like going Object-Oriented would make it easier to build the move finding logic?

For instance, you could parse the board into Group objects and check their liberty/eye count/potential territory value to help find the best move?

I have never written a GoBot myself yet, so I am curious to see what others are doing. I guess looking into Open Source projects like GNU Go would be a good resource too?

Re: the basics of creating a go bot

Posted: Wed Feb 11, 2015 4:07 pm
by Pippen
Is that code or pseudo code? Could that program play a game of Go already if I let it run?

p.s. I have no idea about programming besides some very very basic stuff, but I always hoped I could learn more by looking at basic go program and learn from there.

Re: the basics of creating a go bot

Posted: Wed Feb 11, 2015 4:20 pm
by phillip1882
What are you planning for the "Finding the best move" part?
i'm not sure yet. i have a general idea of what i want: some kind of monte carlo approach, but focusing on the influence of each group rather than the final score. but how exactly to program that will take me some time.
is this code or pseudo-code?
yes its runnable code but it can't really do anything yet. i have no code calling the functions i'm declaring, so this won't actaully play go yet. getting there.

Re: the basics of creating a go bot

Posted: Wed Feb 11, 2015 11:18 pm
by quantumf
phillip1882 wrote:i'm not sure yet. i have a general idea of what i want: some kind of monte carlo approach, but focusing on the influence of each group rather than the final score. but how exactly to program that will take me some time.
Interesting idea. Two questions

1. Influence becomes zero at the end of the game, and tends towards zero as you approach the end. This suggests that the bot's endgame will be hopeless, unless some kind of hybrid approach is chosen.

2. Do you have in mind an monte carlo algorithm that does playouts with each a move more or less at random and then chooses the move that leads to the highest average influence (either highest absolute value or highest average) instead of highest winning percentage?

Re: the basics of creating a go bot

Posted: Thu Feb 12, 2015 2:24 am
by oca
If I had to do a go engine, I will neither do a monte-carlo, nor a machine learning one.
Not that these approach are wrong, that's just that I'm not interested in build a strong computer, I'm interested as getting "a bit" stronger myself [edit]with no illusions however[/edit].

With that goal, building a program that eats tons of pro games and learn from them will certainly improve my computer skills, but not my go skills...

building a go engine that plays "like me" would be more the idea for me, the program would certainly never be a strong one, but I'm sure I can discover more things realated to go with that kind of approach.

Once again, in your case, buidling a monte carlo engine may be just fine, it just depend what we are looking for.

Re: the basics of creating a go bot

Posted: Thu Feb 12, 2015 7:22 am
by Mike Novack
For those new to the game (programming)

You won't believe this, but the place to start is not by diving in with code of real programming languages. At the design stage, you shouldn't be at the level of language, should all still be abstract. Starting right away with code will not save you time in the long run. It will not make it easier.

Nor is a "go playing program" the right place to start gaining experience with software design. Even very experienced programmers have failed at this. For example --- just prior to programs using MCTS evaluation, the two strongest go playing AIs were go++7 and mfog 11 in that order (they were close, but go++7 maybe a stone stronger at that point). But MCTS changed everything, and since a very computationally intensive approach, the ability to design so could efficiently use the crunch power of multi-core CPUs important.

Fotland had that expertise (multi-core) but Mick Reiss did not. I was doing beta testing on go++8 as Mick struggled and failed to keep up in the race (he never got go++8 fast enough to be competitive and eventually gave up).

Seriously, start with problems that are simple and well defined. Hone your software designing on those. Especially learning how to divide problems up into parts even simpler and more well defined that you can test independently of the whole.

Re: the basics of creating a go bot

Posted: Thu Feb 12, 2015 7:32 am
by Bill Spight
quantumf wrote:
phillip1882 wrote:i'm not sure yet. i have a general idea of what i want: some kind of monte carlo approach, but focusing on the influence of each group rather than the final score. but how exactly to program that will take me some time.
Interesting idea. Two questions

1. Influence becomes zero at the end of the game, and tends towards zero as you approach the end. This suggests that the bot's endgame will be hopeless, unless some kind of hybrid approach is chosen.
Influence is ambiguous. In the context of a computer algorithm, influence becomes territory at the end of the game. It is neither necessary nor desirable for influence in a go program to be what go players call outside influence, which indeed becomes zero at the end of the game, when there is no outside to influence. :)

Re: the basics of creating a go bot

Posted: Thu Feb 12, 2015 10:24 am
by oren
Mike Novack wrote:For those new to the game (programming)

You won't believe this, but the place to start is not by diving in with code of real programming languages. At the design stage, you shouldn't be at the level of language, should all still be abstract. Starting right away with code will not save you time in the long run. It will not make it easier.
I'll disagree with this. If you know how to program and what you're doing, start with a plan and design. If you're getting started, just start coding and having fun and learn what's going on with the system. Look up other examples and read how to do it online.

Of course to come back to go, it's exactly the same. I will get a beginner to play some 9x9 and keep playing until they have some idea what's going on. Then you can sit back and plan out deep strategies.

So go have fun!

Re: the basics of creating a go bot

Posted: Sat Feb 14, 2015 5:29 pm
by phillip1882
I'm tentatively calling this version 1. I've done some very basic error checking, and as far as i can tell, everything is now in working order. I have officially programmed the rules of the game, as far as i can tell.

Code: Select all

import sys
def liberties(n, t, boardc, turn):
    #check the current position n. if empty, mark it and increase counter by 1
    if boardc[n] == '+':
        boardc[n] = '*'
        return 1
    #if stone, mark it and recursively check left right top and bottom.
    elif boardc[n] == turn:
        if turn == "B":
            boardc[n] = 'b'
        else:
            boardc[n] = 'w'
        if n%19 < 18:
            t = t +liberties(n+1, t, boardc, turn)
        if n%19 > 0:
            t = t +liberties(n-1, t, boardc, turn)
        if n/19 > 0:
            t = t +liberties(n-19, t, boardc, turn)
        if n/19 < 18:
            t = t +liberties(n+19, t, boardc, turn)
    else:
        return 0
    return t
    
def group(n,t,boardc,turn):
    #same as liberty except count stones instead of empty.
    if boardc[n] == turn:
        if turn == "B":
            boardc[n] = 'b'
        else:
            boardc[n] = 'w'
        t += 1
        if n%19 < 18:
            group(n+1, t, boardc,turn)
        if n%19 > 0:
            group(n-1, t, boardc,turn)
        if n/19 > 0:
            group(n-19, t, boardc,turn)
        if n/19 < 18:
            group(n+19, t, boardc,turn)
    else:
        return t

def printBoard(board):
    for i in range(0,19):
        sys.stdout.write(chr(i+65))
    sys.stdout.write("\n")
    for i in range(0,19):
        for j in range(0,19):
            sys.stdout.write(board[19*i+j])
        sys.stdout.write(str(i+1)+"\n")

def clearLibMark(board):
    for i in range(0,361):
        if board[i] == "*":
            board[i] = "+"
        if board[i] == "w":
            board[i] = "W"
        if board[i] == "b":
            board[i] = "B"
            
def posToInt(v):
   x = v[0]
   v = v[1:]
   y = int(v)
   x = ord(x)-65
   return 19*(y-1)+x

def next(turn):
    if turn == 'B':
        turn = 'W'
    else:
        turn = 'B'
    return turn

def is_legal(n,board,koState,turn):
    if n =="PASS":
        return True
    if n == "RESIGN":
        return True
    if board[n] !="+":
        return False
    boardc = board[:] 
    #if you capture, check ko, if not ko, its legal, if no capture, check suicide
    boardc[n] = turn
    turn = next(turn)
    if n%19 <18 and liberties(n+1,0,boardc,turn)==0:
        capture(boardc)
    clearLibMark(boardc)
    if n%19 >0 and liberties(n-1,0,boardc,turn)==0:
        capture(boardc)
    clearLibMark(boardc)
    if n/19 >0 and liberties(n-19,0,boardc,turn) ==0:
        capture(boardc)
    clearLibMark(boardc)
    #printBoard(boardc)
    if n/19 <18 and liberties(n+19,0,boardc,turn) ==0:
        capture(boardc)
    clearLibMark(boardc)
    check = [False]*5
    for i in range(0,361):
        if boardc[i] != koState[0][i]:
            check[0] = True
        if boardc[i] != koState[1][i]:
            check[1] = True
        if boardc[i] != koState[2][i]:
            check[2] = True
        if boardc[i] != koState[3][i]:
            check[3] = True
        if boardc[i] != koState[4][i]:
            check[4] = True
    if not (check[0] and check[1] and check[2] and check[3] and check[4]):
        print check[0],check[1],check[2],check[3],check[4]
        return False
    turn = next(turn)
    if liberties(n,0,boardc,turn) ==0:
        return False
    else:
        return True

def capture(board):
    #clear captured stones denoted b or w, return total captured
    total = 0
    for i in range(0,len(board)):
        if board[i] != '+':
            if board[i] == "w" or board[i] == "b":
                board[i] = '+'
                total += 1
    return total

def play(n,board,koState,turn):
    if is_legal(n,board,koState,turn):            
        board[n] = turn
        turn = next(turn)
        if n%19 <18 and liberties(n+1,0,board,turn)==0:
            capture(board)
        clearLibMark(board)
        if n%19 >0 and liberties(n-1,0,board,turn)==0:
            capture(board)
        clearLibMark(board)
        if n/19 >0 and liberties(n-19,0,board,turn) ==0:
            capture(board)
        clearLibMark(board)
        if n/19 <18 and liberties(n+19,0,board,turn) ==0:
            capture(board)
        clearLibMark(board)
        updateKoState(koState,board)
    return turn

def deadStones(board,n):
    if board[n] == "W":
        group(n,0,board,"W")
    if board[n] == "B":
        group(n,0,board,"B")
    capture(board)

def updateKoState(koState,board):
    koState[0],koState[1],koState[2],koState[3],koState[4] = (
    board[:],koState[0][:],koState[1][:],koState[2][:],koState[3][:])
    
def scoreSection(board, que, color, n):
    if board[n] == "+":
        board[n] = "*"
        que += [n]
        if n%19 > 0:
            que, color = scoreSection(board, que, color, n-1)
        if n%19 <18:
            que, color = scoreSection(board, que, color, n+1)
        if n/19 >0:
            que, color = scoreSection(board, que, color, n-19)
        if n/19 <18:
            que, color = scoreSection(board, que, color, n+19)
    elif board[n] == "W" or board[n] == "B":
        if color == "Neutral":
            color = board[n]
            return que,color
        elif color == board[n]:
            return que,color
        else:
            return [],"None"
    return que,color
        
def evaluateScore(board,komi,handicap):
    #score the section of all 361 points. return total.
    que = []
    color ="Neutral"
    totalBlack = 0
    totalWhite = 0
    boardC = board[:]
    for i in range(0,361):
        que,color = scoreSection(boardC,que,color,i)
        if que != [] and color != "None":
            for j in range(0,len(que)):
                boardC[que[j]] = color
        que, color = [],"Neutral"
    for i in range(0,361):
        if boardC[i] == "B":
            totalBlack += 1
        if boardC[i] == "W":
            totalWhite += 1
    return totalBlack -totalWhite -komi -handicap

board = ["+"]*361
black = 'B'
white = 'W'
empty = '+'
turn = "B"
koState = [board[:]]+[board[:]]+[board[:]]+[board[:]]+[board[:]]
handicap = int(raw_input("handicap?"))
for i in range(0,handicap):
    printBoard()
    n = raw_input("position of handi-stone?")
    n = posToInt(n)
    play(n,board,koState,turn)
komi = float(raw_input("komi?"))
check = 0
while check < 2:
    printBoard(board)
    n = raw_input("position of move? (or PASS RESIGN) ")
    if n == "PASS":
        check += 1
        koState = [board[:]]+[board[:]]+[board[:]]+[board[:]]+[board[:]]
        turn = next(turn)
    elif n == "RESIGN":
        break
    else:
        check = 0
        n = posToInt(n)
        print n
        turn = play(n,board,koState,turn)

while True:
    n = raw_input("dead stone(s) coordinate? DONE to stop ")
    if n == "DONE":
        break
    n = posToInt(n)
    deadStones(board,n)
    printBoard(board)

k = evaluateScore(board,komi,handicap)
print(k)
if n == "RESIGN":
   turn = next(turn)
   print turn, "wins"
else:
   if k > 0:
       print "B wins"
   else:
       print "W wins"
you can use this program to play against yourself in console. not very visual but its a step by step process.

Re: the basics of creating a go bot

Posted: Sun Feb 15, 2015 12:54 pm
by xed_over
phillip1882 wrote: I've done some very basic error checking, and as far as i can tell, everything is now in working order.
line 211, you forgot to pass the board object to the printBoard() function.

and I'd recommend using a diagram similar to what GnuGo uses:

Code: Select all

    A B C D E F G H J K L M N O P Q R S T
 19 . . . . . . . . . . . . . . . . . . . 19
 18 . . . . . . . . . . . . . . . . . . . 18
 17 . . . . . . . . . . . . . . . . . . . 17
 16 . . . + . . . . . + . . . . . + . . . 16
 15 . . . . . . . . . . . . . . . . . . . 15
 14 . . . . . . . . . . . . . . . . . . . 14
 13 . . . . . . . . . . . . . . . . . . . 13
 12 . . . . . . . . . . . . . . . . . . . 12
 11 . . . . . . . . . . . . . . . . . . . 11
 10 . . . + . . . . . + . . . . . + . . . 10
  9 . . . . . . . . . . . . . . . . . . .  9
  8 . . . . . . . . . . . . . . . . . . .  8
  7 . . . . . . . . . . . . . . . . . . .  7
  6 . . . . . . . . . . . . . . . . . . .  6
  5 . . . . . . . . . . . . . . . . . . .  5
  4 . . . + . . . . . + . . . . . + . . .  4
  3 . . . . . . . . . . . . . . . . . . .  3
  2 . . . . . . . . . . . . . . . . . . .  2
  1 . . . . . . . . . . . . . . . . . . .  1
    A B C D E F G H J K L M N O P Q R S T
its easier to read than yours...

and your coordinates are way, way off...
D4 (upper right?) and P16 (lower middle?)

Code: Select all

ABCDEFGHIJKLMNOPQRS
+++++++++++++++++++1
+++++++++++++++++++2
+++++++++++++++++++3
+++++++++++++++++++4
++++++++++++++++B++5
+++++++++++++++++++6
+++++++++++++++++++7
+++++++++++++++++++8
+++++++++++++++++++9
+++++++++++++++++++10
+++++++++++++++++++11
+++++++++++++++++++12
+++++++++++++++++++13
+++++++++++++++++++14
+++++++++++++++++++15
+++++++++++++++++++16
+++++++++++++++++++17
+++++++++B+++++++++18
+++++++++++++++++++19

Re: the basics of creating a go bot

Posted: Sun Feb 15, 2015 1:28 pm
by skydyr
xed_over wrote:
and your coordinates are way, way off...
D4 (upper right?) and P16 (lower middle?)

Code: Select all

ABCDEFGHIJKLMNOPQRS
+++++++++++++++++++1
+++++++++++++++++++2
+++++++++++++++++++3
+++++++++++++++++++4
++++++++++++++++B++5
+++++++++++++++++++6
+++++++++++++++++++7
+++++++++++++++++++8
+++++++++++++++++++9
+++++++++++++++++++10
+++++++++++++++++++11
+++++++++++++++++++12
+++++++++++++++++++13
+++++++++++++++++++14
+++++++++++++++++++15
+++++++++++++++++++16
+++++++++++++++++++17
+++++++++B+++++++++18
+++++++++++++++++++19
I would recommend skipping the letter I as well.

Re: the basics of creating a go bot

Posted: Sun Feb 15, 2015 2:48 pm
by xed_over
I don't have a problem with using the letter "I". Its more difficult to program around it. I wouldn't worry about it for a first program.


I figured out my problem with the coordinates... you're expecting uppercase, and I'm typing lower.
Adding a .upper() to your raw_input fixes that. You've got to do better at sanitizing your inputs.

you're next problem seems to be... when setting handicap, you still play black next, but it should be white.
and when resigning, you need to skip marking the dead stones.


And I'd suggest using a 2-dimentional array 19x19, or perhaps even better, maybe a 2-dimentional hash, instead of a single 361 array. Then you'll be closer to matching standard sgf coordinates, in order to read/write games.

and why are you defining a global 'empty', but you don't use it? Instead, you hardcode the "+" string everywhere, instead of using the global where you can then actually change the value in only one place.

Re: the basics of creating a go bot

Posted: Sun Feb 15, 2015 3:34 pm
by phillip1882
dubbing this version 1.02, minor visual changes. and score changes. makes white the first player after handi.

Code: Select all

import sys
def liberties(n, t, boardc, turn):
    #check the current position n. if empty, mark it and increase counter by 1
    if boardc[n] == '+':
        boardc[n] = '*'
        return 1
    #if stone, mark it and recursively check left right top and bottom.
    elif boardc[n] == turn:
        if turn == "B":
            boardc[n] = 'b'
        else:
            boardc[n] = 'w'
        if n%19 < 18:
            t = t +liberties(n+1, t, boardc, turn)
        if n%19 > 0:
            t = t +liberties(n-1, t, boardc, turn)
        if n/19 > 0:
            t = t +liberties(n-19, t, boardc, turn)
        if n/19 < 18:
            t = t +liberties(n+19, t, boardc, turn)
    else:
        return 0
    return t
    
def group(n,t,boardc,turn):
    #same as liberty except count stones instead of empty.
    if boardc[n] == turn:
        if turn == "B":
            boardc[n] = 'b'
        else:
            boardc[n] = 'w'
        t += 1
        if n%19 < 18:
            group(n+1, t, boardc,turn)
        if n%19 > 0:
            group(n-1, t, boardc,turn)
        if n/19 > 0:
            group(n-19, t, boardc,turn)
        if n/19 < 18:
            group(n+19, t, boardc,turn)
    else:
        return t

def printBoard(board):
    i = 0
    while i < 20:
        if i == 8:
            i += 1
        sys.stdout.write(chr(i+65)+" ")
        i += 1
    sys.stdout.write("\n")
    for i in range(0,19):
        for j in range(0,19):
            if board[19*i+j] == "B" or board[19*i+j] == "W":
                sys.stdout.write(board[19*i+j]+" ")
                #print "Got here 1"
            else:
                check1 = False
                check2  = False
                if i == 3 or i == 9 or i == 15:
                    check1 = True 
                if j == 3 or j == 9 or j == 15:
                    check2  = True
                if check1 and check2:
                    sys.stdout.write(board[19*i+j]+" ")
                    #print "got here2"
                else:
                    sys.stdout.write(". ")
        sys.stdout.write(str(19-i)+"\n")

def clearLibMark(board):
    for i in range(0,361):
        if board[i] == "*":
            board[i] = "+"
        if board[i] == "w":
            board[i] = "W"
        if board[i] == "b":
            board[i] = "B"
            
def posToInt(v):
   x = v[0]
   v = v[1:]
   y = int(v)
   x = ord(x.upper())-65
   if x>=8:
       x-=1
   return 19*(18-(y-1))+x

def next(turn):
    if turn == 'B':
        turn = 'W'
    else:
        turn = 'B'
    return turn

def is_legal(n,board,koState,turn):
    if n =="PASS":
        return True
    if n == "RESIGN":
        return True
    if board[n] !="+":
        return False
    boardc = board[:] 
    #if you capture, check ko, if not ko, its legal, if no capture, check suicide
    boardc[n] = turn
    turn = next(turn)
    if n%19 <18 and liberties(n+1,0,boardc,turn)==0:
        capture(boardc)
    clearLibMark(boardc)
    if n%19 >0 and liberties(n-1,0,boardc,turn)==0:
        capture(boardc)
    clearLibMark(boardc)
    if n/19 >0 and liberties(n-19,0,boardc,turn) ==0:
        capture(boardc)
    clearLibMark(boardc)
    #printBoard(boardc)
    if n/19 <18 and liberties(n+19,0,boardc,turn) ==0:
        capture(boardc)
    clearLibMark(boardc)
    check = [False]*5
    for i in range(0,361):
        if boardc[i] != koState[0][i]:
            check[0] = True
        if boardc[i] != koState[1][i]:
            check[1] = True
        if boardc[i] != koState[2][i]:
            check[2] = True
        if boardc[i] != koState[3][i]:
            check[3] = True
        if boardc[i] != koState[4][i]:
            check[4] = True
    if not (check[0] and check[1] and check[2] and check[3] and check[4]):
        print check[0],check[1],check[2],check[3],check[4]
        return False
    turn = next(turn)
    if liberties(n,0,boardc,turn) ==0:
        return False
    else:
        return True

def capture(board):
    #clear captured stones denoted b or w, return total captured
    total = 0
    for i in range(0,len(board)):
        if board[i] != '+':
            if board[i] == "w" or board[i] == "b":
                board[i] = '+'
                total += 1
    return total

def play(n,board,koState,turn):
    if is_legal(n,board,koState,turn):            
        board[n] = turn
        turn = next(turn)
        if n%19 <18 and liberties(n+1,0,board,turn)==0:
            capture(board)
        clearLibMark(board)
        if n%19 >0 and liberties(n-1,0,board,turn)==0:
            capture(board)
        clearLibMark(board)
        if n/19 >0 and liberties(n-19,0,board,turn) ==0:
            capture(board)
        clearLibMark(board)
        if n/19 <18 and liberties(n+19,0,board,turn) ==0:
            capture(board)
        clearLibMark(board)
        updateKoState(koState,board)
    return turn

def deadStones(board,n):
    if board[n] == "W":
        group(n,0,board,"W")
    if board[n] == "B":
        group(n,0,board,"B")
    capture(board)

def updateKoState(koState,board):
    koState[0],koState[1],koState[2],koState[3],koState[4] = (
    board[:],koState[0][:],koState[1][:],koState[2][:],koState[3][:])
    
def scoreSection(board, que, color, n):
    if board[n] == "+":
        board[n] = "*"
        que += [n]
        if n%19 > 0:
            que, color = scoreSection(board, que, color, n-1)
        if n%19 <18:
            que, color = scoreSection(board, que, color, n+1)
        if n/19 >0:
            que, color = scoreSection(board, que, color, n-19)
        if n/19 <18:
            que, color = scoreSection(board, que, color, n+19)
    elif board[n] == "W" or board[n] == "B":
        if color == "Neutral":
            color = board[n]
            return que,color
        elif color == board[n]:
            return que,color
        else:
            return [],"None"
    return que,color
        
def evaluateScore(board,komi,handicap):
    #score the section of all 361 points. return total.
    que = []
    color ="Neutral"
    totalBlack = 0
    totalWhite = 0
    boardC = board[:]
    for i in range(0,361):
        que,color = scoreSection(boardC,que,color,i)
        if que != [] and color != "None":
            for j in range(0,len(que)):
                boardC[que[j]] = color
        que, color = [],"Neutral"
    for i in range(0,361):
        if boardC[i] == "B":
            totalBlack += 1
        if boardC[i] == "W":
            totalWhite += 1
    return totalBlack -totalWhite -komi -handicap
    
board = ["+"]*361
black = 'B'
white = 'W'
empty = '+'
turn = "B"
koState = [board[:]]+[board[:]]+[board[:]]+[board[:]]+[board[:]]
handicap = int(raw_input("handicap?"))
for i in range(0,handicap):
    printBoard(board)
    n = raw_input("position of handi-stone?")
    n = posToInt(n)
    play(n,board,koState,turn)
if handicap > 0:
    turn = next(turn)
komi = float(raw_input("komi?"))
check = 0
while check < 2:
    printBoard(board)
    n = raw_input("position of move? (or PASS RESIGN) ")
    if n == "PASS":
        check += 1
        koState = [board[:]]+[board[:]]+[board[:]]+[board[:]]+[board[:]]
        turn = next(turn)
    elif n == "RESIGN":
        break
    else:
        check = 0
        n = posToInt(n)
        print n
        turn = play(n,board,koState,turn)
if n !=  "RESIGN":
    while True:
        n = raw_input("dead stone(s) coordinate? DONE to stop ")
        if n == "DONE":
            break
        n = posToInt(n)
        deadStones(board,n)
        printBoard(board)
    
    k = evaluateScore(board,komi,handicap)
    print(k)
if n == "RESIGN":
   turn = next(turn)
   print turn, "wins"
else:
   if k > 0:
       print "B wins"
   else:
       print "W wins"

Re: the basics of creating a go bot

Posted: Sun Feb 15, 2015 3:46 pm
by phillip1882
i don't use the global empty, black, and white, because i wanted to make sure my program worked properly first.