Files @ 0cb3fbe06b5d
Branch filter:

Location: OneEye/src/go/engine.py - annotation

Laman
Go, Engine: some tests and numerous bugfixes
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()