Files
@ f9ab2070bd69
Branch filter:
Location: OneEye/src/go/engine.py - annotation
f9ab2070bd69
3.1 KiB
text/x-python
Engine: more tests and fixes
077600f0c5f8 077600f0c5f8 7f1984280936 7f1984280936 7f1984280936 7f1984280936 7f1984280936 7f1984280936 7f1984280936 077600f0c5f8 077600f0c5f8 7f1984280936 7f1984280936 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 f9ab2070bd69 4e67f9e9f027 4e67f9e9f027 7f1984280936 7f1984280936 0cb3fbe06b5d 4e67f9e9f027 077600f0c5f8 f9ab2070bd69 f9ab2070bd69 4e67f9e9f027 f9ab2070bd69 4e67f9e9f027 7f1984280936 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 4e67f9e9f027 f9ab2070bd69 f9ab2070bd69 f9ab2070bd69 7f1984280936 7f1984280936 f9ab2070bd69 f9ab2070bd69 f9ab2070bd69 f9ab2070bd69 f9ab2070bd69 f9ab2070bd69 7f1984280936 7f1984280936 077600f0c5f8 077600f0c5f8 4e67f9e9f027 7f1984280936 7f1984280936 7f1984280936 4e67f9e9f027 7f1984280936 f9ab2070bd69 7f1984280936 f9ab2070bd69 077600f0c5f8 077600f0c5f8 077600f0c5f8 077600f0c5f8 077600f0c5f8 7f1984280936 7f1984280936 7f1984280936 0cb3fbe06b5d 077600f0c5f8 077600f0c5f8 077600f0c5f8 0cb3fbe06b5d 077600f0c5f8 0cb3fbe06b5d 077600f0c5f8 f9ab2070bd69 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, throw-in.
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))
for (ri,ci) in self.listNeighbours(r,c): # in case a stone was played and captured. !! might want to add even more
res[1-colorKey].add((ri,ci))
# this is rather sloppy but correct. the time will show if it is effective enough
# just floodFill from the current intersection, add everything you find and also all the neighbours to be sure
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))
for (rj,cj) in self.listNeighbours(ri,ci):
res[colorKey].add((rj,cj))
res[1-colorKey].add((rj,cj))
return res
def listNeighbours(self,r,c):
if r>0: yield (r-1,c)
if r+1<self.boardSize: yield (r+1,c)
if c>0: yield (r,c-1)
if c+1<self.boardSize: yield (r,c+1)
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,toMove=None):
for i in range(1,10):
for color in [toMove] if toMove else [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
)
if not g.doMove(g.toMove,r,c): continue
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()
|