Files
@ 0cb3fbe06b5d
Branch filter:
Location: OneEye/src/go/engine.py - annotation
0cb3fbe06b5d
2.8 KiB
text/x-python
Go, Engine: some tests and numerous bugfixes
077600f0c5f8 077600f0c5f8 7f1984280936 7f1984280936 7f1984280936 7f1984280936 7f1984280936 7f1984280936 7f1984280936 077600f0c5f8 077600f0c5f8 7f1984280936 7f1984280936 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 0cb3fbe06b5d 4e67f9e9f027 4e67f9e9f027 7f1984280936 7f1984280936 0cb3fbe06b5d 4e67f9e9f027 077600f0c5f8 4e67f9e9f027 4e67f9e9f027 7f1984280936 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 0cb3fbe06b5d 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 0cb3fbe06b5d 4e67f9e9f027 4e67f9e9f027 7f1984280936 7f1984280936 7f1984280936 7f1984280936 077600f0c5f8 077600f0c5f8 4e67f9e9f027 7f1984280936 7f1984280936 7f1984280936 4e67f9e9f027 7f1984280936 7f1984280936 7f1984280936 077600f0c5f8 077600f0c5f8 077600f0c5f8 077600f0c5f8 077600f0c5f8 077600f0c5f8 7f1984280936 7f1984280936 7f1984280936 0cb3fbe06b5d 077600f0c5f8 077600f0c5f8 077600f0c5f8 0cb3fbe06b5d 077600f0c5f8 0cb3fbe06b5d 077600f0c5f8 4e67f9e9f027 077600f0c5f8 077600f0c5f8 077600f0c5f8 077600f0c5f8 077600f0c5f8 7f1984280936 0cb3fbe06b5d 7f1984280936 7f1984280936 0cb3fbe06b5d 7f1984280936 077600f0c5f8 7f1984280936 7f1984280936 7f1984280936 | from util import EMPTY,BLACK,WHITE
from . import core
def transitionSequence(state1, state2, diff, limit=0):
return []
class SpecGo(core.Go):
def __init__(self,boardSize=19):
super().__init__(boardSize)
def listRelevantMoves(self,diff):
"""There can be 3 different changes in the diff: additions, deletions and replacements.
Additions can be taken as relevant right away.
Deletions and replacements had to be captured, so we add their liberties.
Also any non-missing stones of partially deleted (or replaced) groups had to be replayed, so add them too.
Needs to handle snapback.
There's no end to what could be theoretically relevant, but such sequences are long and we will pretend they won't happen."""
res=(set(),set())
for d in diff:
(r,c,action,color)=d
colorKey=(1-color)>>1 # {-1,1}->{1,0}
if action!="-" and (r,c) not in res[colorKey]:
res[colorKey].add((r,c))
# this is rather sloppy but correct. the time will show if it is effective enough
if action!="+" and (r,c) not in res[colorKey] and (r,c) not in res[1-colorKey]:
self._helper.clear()
self._helper.floodFill(color if action=="-" else 1-color, r, c)
res[colorKey].union(self._helper.getContinuousArea())
for (ri,ci) in self._helper.getContinuousArea():
res[colorKey].add((ri,ci))
res[1-colorKey].add((ri,ci))
if ri>0:
res[colorKey].add((ri-1,ci))
res[1-colorKey].add((ri-1,ci))
if ri+1<self.boardSize:
res[colorKey].add((ri+1,ci))
res[1-colorKey].add((ri+1,ci))
if ci>0:
res[colorKey].add((ri,ci-1))
res[1-colorKey].add((ri,ci-1))
if ci+1<self.boardSize:
res[colorKey].add((ri,ci+1))
res[1-colorKey].add((ri,ci+1))
return res
class Engine:
def __init__(self,g=None):
self._g=g or SpecGo()
self._moveList=(set(),set())
def load(self,state1,diff):
self._g.load(state1)
self._moveList=self._g.listRelevantMoves(diff)
def iterativelyDeepen(self,state2):
for i in range(1,10):
for color in [BLACK,WHITE]:
self._g.toMove=color
seq=self.dfs(state2,i)
if seq:
seq.reverse()
return seq
def dfs(self,state2,limit):
g=self._g
for (r,c) in self._moveList[(1-g.toMove)>>1]:
if g.board[r][c]!=EMPTY: continue
neighbours=(
g.board[r-1][c] if r>0 else None,
g.board[r+1][c] if r+1<g.boardSize else None,
g.board[r][c-1] if c>0 else None,
g.board[r][c+1] if c+1<g.boardSize else None
)
g.doMove(g.toMove,r,c)
captured=tuple(
coords for (i,coords) in enumerate(((r-1,c),(r+1,c),(r,c-1),(r,c+1)))
if neighbours[i] is not None and neighbours[i]!=EMPTY and g.board[coords[0]][coords[1]]==EMPTY
)
if g.hash()==state2.hash(): return [(-1*g.toMove,r,c)]
if limit>1:
toMove=-1*g.toMove
seq=self.dfs(state2,limit-1)
if seq:
seq.append((toMove,r,c))
return seq
g.undoMove(r,c,captured)
return False
eng=Engine()
|