Changeset - 231b6d9b9561
[Not reviewed]
default
0 1 0
Laman - 7 years ago 2017-12-16 15:56:41

engine: slightly enhanced handling movelist
1 file changed with 14 insertions and 4 deletions:
0 comments (0 inline, 0 general)
src/go/engine.py
Show inline comments
 
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]:
 
		moveSet=self._moveList[(1-g.toMove)>>1]
 
		for (r,c) in moveSet.copy():
 
			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
 
			moveSet.remove((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 g.hash()==state2.hash():
 
				g.undoMove(r,c,captured)
 
				moveSet.add((r,c))
 
				return [(g.toMove,r,c)]
 

	
 
			if limit>1:
 
				toMove=-1*g.toMove
 
				seq=self.dfs(state2,limit-1)
 
				if seq:
 
					seq.append((toMove,r,c))
 
					g.undoMove(r,c,captured)
 
					moveSet.add((r,c))
 
					seq.append((g.toMove,r,c))
 
					return seq
 

	
 
			g.undoMove(r,c,captured)
 
			moveSet.add((r,c))
 
		return False
 

	
 
eng=Engine()
0 comments (0 inline, 0 general)