Changeset - 2fcaffe8cb70
[Not reviewed]
default
0 2 2
Laman - 8 years ago 2017-04-17 20:28:13

checking for a legal position
4 files changed with 70 insertions and 8 deletions:
0 comments (0 inline, 0 general)
src/core.py
Show inline comments
 
@@ -6,7 +6,7 @@ import PIL
 
from util import MsgQueue
 
from gui import gui
 
from imageanalyzer import ImageAnalyzer
 
from go import Go
 
from go import Go, isLegalPosition
 
import config as cfg
 

	
 

	
 
@@ -47,7 +47,10 @@ class Core:
 

	
 
	def analyze(self):
 
		if self.detector.analyze(self._frame):
 
			if isLegalPosition(self.detector.board):
 
			self._guiMessages.send("setGameState",(self.detector.board,))
 
			else:
 
				log.info("illegal position detected")
 

	
 
	def listen(self):
 
		listenerThread=threading.Thread(target=lambda: self._ownMessages.listen())
src/go.py
Show inline comments
 
EMPTY=0
 
EMPTY=0
 
BLACK=1
 
WHITE=-1
 

	
 
@@ -7,7 +7,8 @@ class Go:
 
	## Initializes self.board to a list[r][c]=EMPTY.
 
	def __init__(self,boardSize=19):
 
		self.boardSize=boardSize
 
		self.board=[[EMPTY]*self.boardSize for x in range(boardSize)]
 
		self.board=[[EMPTY]*boardSize for x in range(boardSize)]
 
		self._temp=[[EMPTY]*boardSize for x in range(boardSize)]
 

	
 
	## Executes a move.
 
	#
 
@@ -22,11 +23,11 @@ class Go:
 

	
 
		# capture neighbors
 
		for r,c in ((-1,0),(1,0),(0,-1),(0,1)):
 
			self.temp=[[False]*self.boardSize for x in self.board]
 
			self._clearTemp()
 
			if not self._floodFill(-color,row+r,col+c): self._remove()
 

	
 
		# check for suicide
 
		self.temp=[[False]*self.boardSize for x in self.board]
 
		self._clearTemp()
 
		if not self._floodFill(color,row,col):
 
			self.board[row][col]=EMPTY
 
			return False
 
@@ -39,19 +40,52 @@ class Go:
 
	#  @return True if alive, False if captured
 
	def _floodFill(self,color,row,col):
 
		if col<0 or col>=self.boardSize or row<0 or row>=self.boardSize: return False # out of range
 
		if self.temp[row][col]: return False # already visited
 
		if self._temp[row][col]: return False # already visited
 
		if self.board[row][col]==EMPTY: return True # found a liberty
 
		if self.board[row][col]!=color: return False # opponent's stone
 
		self.temp[row][col]=True # set visited
 
		self._temp[row][col]=True # set visited
 
		return self._floodFill(color,row,col-1) or self._floodFill(color,row,col+1) or self._floodFill(color,row-1,col) or self._floodFill(color,row+1,col) # check neighbors
 

	
 
	## Removes stones at coordinates marked with True in self.temp.
 
	def _remove(self):
 
		for r in range(self.boardSize):
 
			for c in range(self.boardSize):
 
				if self.temp[r][c]: self.board[r][c]=EMPTY
 
				if self._temp[r][c]: self.board[r][c]=EMPTY
 

	
 
	def _clearTemp(self):
 
		for i in range(self.boardSize):
 
			for j in range(self.boardSize):
 
				self._temp[i][j]=EMPTY
 

	
 
def exportBoard(board):
 
	substitutions={EMPTY:".", BLACK:"X", WHITE:"O"}
 
	return "\n".join("".join(substitutions.get(x,"?") for x in row) for row in board)
 

	
 

	
 
def isLegalPosition(board):
 
	boardSize=len(board)
 
	temp=[[None]*boardSize for x in range(boardSize)]
 

	
 
	for r in range(boardSize):
 
		for c in range(boardSize):
 
			if board[r][c]==EMPTY: continue
 
			if temp[r][c]: continue
 
			if not dfs([(r,c)],board,temp): return False
 
	return True
 

	
 

	
 
def dfs(stack,board,mask):
 
	boardSize=len(board)
 
	(r,c)=stack[0]
 
	color=board[r][c]
 

	
 
	while len(stack)>0:
 
		(r,c)=stack.pop()
 
		if board[r][c]==EMPTY: return True
 
		elif board[r][c]!=color: continue
 
		elif mask[r][c]: return True
 
		mask[r][c]=True
 
		for (x,y) in ((0,-1),(-1,0),(0,1),(1,0)):
 
			if 0<=r+y<boardSize and 0<=c+x<boardSize:
 
				stack.append((r+y,c+x))
 
	return False
src/tests/__init__.py
Show inline comments
 
new file 100644
src/tests/testGo.py
Show inline comments
 
new file 100644
 
from unittest import TestCase
 

	
 
from go import isLegalPosition
 

	
 

	
 
class TestLegal(TestCase):
 
	def testLegal(self):
 
		board=[
 
			[0,0,0,0,0],
 
			[1,1,1,1,1],
 
			[-1,-1,0,1,0],
 
			[0,0,0,-1,-1],
 
			[0,-1,0,-1,0]
 
		]
 
		self.assertTrue(isLegalPosition(board))
 

	
 
	def testIllegal(self):
 
		board=[
 
			[0,1,0,0,0],
 
			[1,-1,1,0,0],
 
			[0,1,0,0,0],
 
			[0,0,0,0,0],
 
			[0,0,0,0,0]
 
		]
 
		self.assertFalse(isLegalPosition(board))
0 comments (0 inline, 0 general)