It is currently Sun May 04, 2025 12:00 pm

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 18 posts ] 
Author Message
Offline
 Post subject: the basics of creating a go bot
Post #1 Posted: Wed Feb 11, 2015 7:42 am 
Lives in gote

Posts: 322
Liked others: 4
Was liked: 39
Rank: 6k
GD Posts: 25
OGS: 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:
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

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #2 Posted: Wed Feb 11, 2015 2:37 pm 
Beginner

Posts: 1
Location: Vancouver, Canada
Liked others: 0
Was liked: 0
Rank: IGS 13k
KGS: seki
IGS: 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?

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #3 Posted: Wed Feb 11, 2015 4:07 pm 
Lives in gote

Posts: 677
Liked others: 6
Was liked: 31
KGS: 2d
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.

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #4 Posted: Wed Feb 11, 2015 4:20 pm 
Lives in gote

Posts: 322
Liked others: 4
Was liked: 39
Rank: 6k
GD Posts: 25
OGS: 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.

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #5 Posted: Wed Feb 11, 2015 11:18 pm 
Lives in sente
User avatar

Posts: 844
Liked others: 180
Was liked: 151
Rank: 3d
GD Posts: 422
KGS: komi
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?

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #6 Posted: Thu Feb 12, 2015 2:24 am 
Lives in gote
User avatar

Posts: 699
Location: Switzerland
Liked others: 485
Was liked: 166
Rank: DDK
KGS: aco
IGS: oca
OGS: 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.

_________________
Converting the book Shape UP! by Charles Matthews/Seong-June Kim
to the gobook format. last updated april 2015 - Index of shapes, p.211 / 216

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #7 Posted: Thu Feb 12, 2015 7:22 am 
Lives in sente

Posts: 1045
Liked others: 0
Was liked: 182
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.


This post by Mike Novack was liked by: oca
Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #8 Posted: Thu Feb 12, 2015 7:32 am 
Honinbo

Posts: 10905
Liked others: 3651
Was liked: 3374
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. :)

_________________
The Adkins Principle:
At some point, doesn't thinking have to go on?
— Winona Adkins

Visualize whirled peas.

Everything with love. Stay safe.

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #9 Posted: Thu Feb 12, 2015 10:24 am 
Oza
User avatar

Posts: 2777
Location: Seattle, WA
Liked others: 251
Was liked: 549
KGS: oren
Tygem: oren740, orenl
IGS: oren
Wbaduk: 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!

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #10 Posted: Sat Feb 14, 2015 5:29 pm 
Lives in gote

Posts: 322
Liked others: 4
Was liked: 39
Rank: 6k
GD Posts: 25
OGS: 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:
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.

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #11 Posted: Sun Feb 15, 2015 12:54 pm 
Oza

Posts: 2264
Liked others: 1180
Was liked: 553
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:
    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:
ABCDEFGHIJKLMNOPQRS
+++++++++++++++++++1
+++++++++++++++++++2
+++++++++++++++++++3
+++++++++++++++++++4
++++++++++++++++B++5
+++++++++++++++++++6
+++++++++++++++++++7
+++++++++++++++++++8
+++++++++++++++++++9
+++++++++++++++++++10
+++++++++++++++++++11
+++++++++++++++++++12
+++++++++++++++++++13
+++++++++++++++++++14
+++++++++++++++++++15
+++++++++++++++++++16
+++++++++++++++++++17
+++++++++B+++++++++18
+++++++++++++++++++19

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #12 Posted: Sun Feb 15, 2015 1:28 pm 
Oza

Posts: 2495
Location: DC
Liked others: 157
Was liked: 443
Universal go server handle: skydyr
Online playing schedule: When my wife is out.
xed_over wrote:

and your coordinates are way, way off...
D4 (upper right?) and P16 (lower middle?)
Code:
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.

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #13 Posted: Sun Feb 15, 2015 2:48 pm 
Oza

Posts: 2264
Liked others: 1180
Was liked: 553
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.

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #14 Posted: Sun Feb 15, 2015 3:34 pm 
Lives in gote

Posts: 322
Liked others: 4
Was liked: 39
Rank: 6k
GD Posts: 25
OGS: phillip1882
dubbing this version 1.02, minor visual changes. and score changes. makes white the first player after handi.
Code:
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"

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #15 Posted: Sun Feb 15, 2015 3:46 pm 
Lives in gote

Posts: 322
Liked others: 4
Was liked: 39
Rank: 6k
GD Posts: 25
OGS: phillip1882
i don't use the global empty, black, and white, because i wanted to make sure my program worked properly first.

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #16 Posted: Sun Feb 15, 2015 5:00 pm 
Oza

Posts: 2264
Liked others: 1180
Was liked: 553
phillip1882 wrote:
i don't use the global empty, black, and white, because i wanted to make sure my program worked properly first.

yeah, but now with your new visual changes, you've introduced more bugs, because elsewhere in your code you're still comparing the values to the hardcoded string "+" instead of "."

Just because someone asks for changes, doesn't mean you should try to implement them right away. Take your time and re/test everything.

And just like in go, try to look for more than one solution. The first solution that comes to mind, may not be the best. It may in fact paint you into a corner that'll be near impossible to get out of later.

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #17 Posted: Sun Feb 15, 2015 7:18 pm 
Lives in gote

Posts: 322
Liked others: 4
Was liked: 39
Rank: 6k
GD Posts: 25
OGS: phillip1882
Quote:
yeah, but now with your new visual changes, you've introduced more bugs, because elsewhere in your code you're still comparing the values to the hard coded string "+" instead of "."

no, i haven't. "." only applies to the print function as it should, nothing else has changed. making "." and "+" as my empty would make my code nearly 1/3 more complex.

Top
 Profile  
 
Offline
 Post subject: Re: the basics of creating a go bot
Post #18 Posted: Sat Mar 07, 2015 7:27 pm 
Lives in gote

Posts: 322
Liked others: 4
Was liked: 39
Rank: 6k
GD Posts: 25
OGS: phillip1882
so brief update, i tried writing two go bots, one using a sort of influence idea the other using a sort of neural net learning bot. both failed horribly. if anyone's interested in my code, let me know and i'll post it here. but yeah both are quite horrible, so not much point i figure.

Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 18 posts ] 

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group