Changeset - 0cb3fbe06b5d
[Not reviewed]
default
0 5 1
Laman - 7 years ago 2017-12-13 13:41:29

Go, Engine: some tests and numerous bugfixes
6 files changed with 89 insertions and 17 deletions:
0 comments (0 inline, 0 general)
src/go/core.py
Show inline comments
 
@@ -35,7 +35,7 @@ class Go:
 
			self._helper.clear()
 
			if not self._helper.floodFill(-color,row+r,col+c,EMPTY): self._remove()
 

	
 
		# check for suicide
 
		# check for suicide and prevent it
 
		self._helper.clear()
 
		if not self._helper.floodFill(color,row,col,EMPTY):
 
			self.board[row][col]=EMPTY
 
@@ -46,7 +46,7 @@ class Go:
 
		return True
 

	
 
	def undoMove(self,r,c,captures):
 
		assert self.board[r][c]==-1*self.toMove
 
		assert self.board[r][c]==-1*self.toMove, "{0}!={1}".format(self.board[r][c],-1*self.toMove)
 
		self.toMove*=-1
 
		self.board[r][c]=self.toMove
 
		if len(captures)>0:
 
@@ -62,6 +62,11 @@ class Go:
 
		(r,c,color)=res
 
		return self.doMove(color,r,c)
 

	
 
	def load(self,board):
 
		for (r,row) in enumerate(board):
 
			for (c,x) in enumerate(row):
 
				self.board[r][c]=x
 

	
 
	def hash(self):
 
		return hashBoard(self.board)
 

	
src/go/engine.py
Show inline comments
 
@@ -10,22 +10,17 @@ class SpecGo(core.Go):
 
	def __init__(self,boardSize=19):
 
		super().__init__(boardSize)
 

	
 
	def load(self,state):
 
		for (r,row) in enumerate(state):
 
			for (c,x) in enumerate(row):
 
				self.board[r][c]=x
 

	
 
	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: Take n, return 1. Snapback.
 
		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}
 
			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
 
@@ -39,13 +34,13 @@ class SpecGo(core.Go):
 
					if ri>0:
 
						res[colorKey].add((ri-1,ci))
 
						res[1-colorKey].add((ri-1,ci))
 
					if ri<self.boardSize:
 
					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<self.boardSize:
 
					if ci+1<self.boardSize:
 
						res[colorKey].add((ri,ci+1))
 
						res[1-colorKey].add((ri,ci+1))
 
		return res
 
@@ -71,13 +66,13 @@ class Engine:
 

	
 
	def dfs(self,state2,limit):
 
		g=self._g
 
		for (r,c) in self._moveList[(g.toMove-1)>>1]:
 
		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<g.boardSize 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<g.boardSize else None
 
				g.board[r][c+1] if c+1<g.boardSize else None
 
			)
 
			g.doMove(g.toMove,r,c)
 
			captured=tuple(
 
@@ -86,9 +81,10 @@ class Engine:
 
			)
 
			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((-1*g.toMove,r,c))
 
					seq.append((toMove,r,c))
 
					return seq
 
			g.undoMove(r,c,captured)
 
		return False
src/go/helperboard.py
Show inline comments
 
@@ -49,6 +49,6 @@ class HelperBoard:
 
			self._board[r][c]=EMPTY
 
		self._visitedCount=0
 
		for i in range(self._libCount):
 
			(r,c)=(self._libs[i*2],self._visited[i*2+1])
 
			(r,c)=(self._libs[i*2],self._libs[i*2+1])
 
			self._board[r][c]=EMPTY
 
		self._libCount=0
src/tests/testEngine.py
Show inline comments
 
@@ -20,3 +20,36 @@ class TestTransitions(TestCase):
 
		eng=Engine(g)
 
		eng.load(s1,s2-s1)
 
		self.assertEqual(eng.dfs(s2,1),[(1,1,1)])
 

	
 
	def testCapture(self):
 
		s1=BoardState([
 
			[0,-1,0],
 
			[-1,1,0],
 
			[0,-1,0]
 
		])
 
		s2=BoardState([
 
			[0,-1,0],
 
			[-1,0,-1],
 
			[0,-1,0]
 
		])
 
		g=SpecGo(3)
 
		g.toMove=-1
 
		eng=Engine(g)
 
		eng.load(s1,s2-s1)
 
		self.assertEqual(eng.dfs(s2,1),[(-1,1,2)])
 

	
 
	def testMulti(self):
 
		s1=BoardState([
 
			[0,0,0],
 
			[0,0,0],
 
			[0,0,0]
 
		])
 
		s2=BoardState([
 
			[0,0,0],
 
			[0,1,-1],
 
			[0,0,0]
 
		])
 
		g=SpecGo(3)
 
		eng=Engine(g)
 
		eng.load(s1,s2-s1)
 
		self.assertEqual(eng.dfs(s2,2),[(-1,1,2),(1,1,1)])
src/tests/testGo.py
Show inline comments
 
from unittest import TestCase
 

	
 
from go.core import isLegalPosition
 
from go.core import isLegalPosition, Go
 

	
 

	
 
class TestLegal(TestCase):
 
@@ -23,3 +23,25 @@ class TestLegal(TestCase):
 
			[0,0,0,0,0]
 
		]
 
		self.assertFalse(isLegalPosition(board))
 

	
 

	
 
class TestMove(TestCase):
 
	def testCapture(self):
 
		g=Go(3)
 
		g.load([
 
			[0,1,0],
 
			[1,-1,0],
 
			[0,1,0]
 
		])
 
		g.toMove=1
 
		g.doMove(1,1,2)
 
		self.assertEqual(g.board,[
 
			[0,1,0],
 
			[1,0,1],
 
			[0,1,0]
 
		])
 

	
 
		g._helper.clear()
 
		for row in g._helper._board:
 
			for x in row:
 
				self.assertEqual(x,0)
src/tests/testHelper.py
Show inline comments
 
new file 100644
 
from unittest import TestCase
 

	
 
from go.helperboard import HelperBoard
 

	
 

	
 
class TestFlood(TestCase):
 
	def testCapture(self):
 
		b=[
 
			[0,1,0],
 
			[1,-1,1],
 
			[0,1,0]
 
		]
 
		h=HelperBoard(b)
 
		self.assertEqual(h.floodFill(-1,1,1,0), False)
 
		captured=set(h.getContinuousArea())
 
		self.assertEqual(captured, {(1,1)})
0 comments (0 inline, 0 general)