Changeset - b197a19e4afe
[Not reviewed]
default
0 2 2
Laman - 7 years ago 2017-11-29 12:17:09

chaining the states to a record
4 files changed with 108 insertions and 0 deletions:
0 comments (0 inline, 0 general)
src/core.py
Show inline comments
 
@@ -7,6 +7,7 @@ from util import MsgQueue
 
from gui import gui
 
from imageanalyzer import ImageAnalyzer
 
from go import Go, isLegalPosition
 
from statebag import StateBag
 
import config as cfg
 

	
 

	
 
@@ -15,6 +16,7 @@ class Core:
 
		self.grid=None
 
		self.go=Go()
 
		self.detector=ImageAnalyzer()
 
		self.states=StateBag()
 

	
 
		self._ownMessages=MsgQueue(self._handleEvent)
 
		self._guiMessages=MsgQueue()
 
@@ -48,7 +50,10 @@ class Core:
 
	def analyze(self):
 
		if self.detector.analyze(self._frame):
 
			if isLegalPosition(self.detector.board):
 
				self.states.pushState(self.detector.board)
 
				self._guiMessages.send("setGameState",(self.detector.board,))
 

	
 
				self.go.transitionMove(self.detector.board)
 
			else:
 
				log.info("illegal position detected")
 

	
src/gamerecord.py
Show inline comments
 
new file 100644
 
import logging as log
 

	
 

	
 
colorNames={1:"B",-1:"W"}
 

	
 

	
 
class Point:
 
	def __init__(self,c,r):
 
		self.r=r
 
		self.c=c
 

	
 
	def __iter__(self):
 
		yield self.c
 
		yield self.r
 

	
 
	def __str__(self):
 
		a=ord("a")
 
		return chr(a+self.c)+chr(a+self.r)
 

	
 

	
 
class GameRecord:
 
	def __init__(self):
 
		self.playerB=""
 
		self.playerW=""
 
		self.root=Node()
 
		self.currNode=self.root
 

	
 
	def move(self,color,row,col):
 
		if color not in colorNames:
 
			raise ValueError("invalid color: {0}".format(color))
 
		colorName=colorNames[color]
 
		res=Node()
 
		res.properties[colorName]=Point(col,row)
 
		self.currNode.children.append(res)
 
		self.currNode=res
 
		return res
 

	
 
	def __str__(self):
 
		res=["("]
 
		stack=[self.root]
 
		while len(stack)!=0:
 
			v=stack.pop()
 
			res.append(v)
 
			if v==")": continue
 
			if len(v.children)>1:
 
				res.append("(")
 
				stack.append(")")
 
			stack.extend(reversed(v.children))
 
		res.append(")")
 
		return "".join(str(x) for x in res)
 

	
 

	
 
class Node:
 
	def __init__(self):
 
		self.properties=dict()
 
		self.parent=None
 
		self.children=[]
 

	
 
	## Returns textual representation of the Node itself, but disregards its children.
 
	def __str__(self):
 
		return ";" + "".join("{0}[{1}]".format(k,str(p)) for (k,p) in self.properties.items())
src/go.py
Show inline comments
 
import logging as log
 

	
 
from gamerecord import GameRecord
 

	
 

	
 
EMPTY=0
 
BLACK=1
 
WHITE=-1
 
@@ -9,6 +14,8 @@ class Go:
 
		self.boardSize=boardSize
 
		self.board=[[EMPTY]*boardSize for x in range(boardSize)]
 
		self._temp=[[EMPTY]*boardSize for x in range(boardSize)]
 
		self.toMove=BLACK
 
		self._record=GameRecord()
 

	
 
	## Executes a move.
 
	#
 
@@ -17,6 +24,7 @@ class Go:
 
	#  @param color BLACK or WHITE
 
	#  @return True on success, False on failure (illegal move)
 
	def move(self,color,row,col):
 
		if color!=self.toMove: log.warning("move by %s out of order",color)
 
		if self.board[row][col]!=EMPTY: return False
 

	
 
		self.board[row][col]=color
 
@@ -31,8 +39,17 @@ class Go:
 
		if not self._floodFill(color,row,col):
 
			self.board[row][col]=EMPTY
 
			return False
 
		self._record.move(color,row,col)
 
		self.toMove=-1*color
 
		return True
 

	
 
	def transitionMove(self,board):
 
		res=transitionMove(self.board,board)
 
		if not res: return res
 
		(r,c,color)=res
 
		return self.move(color,r,c)
 

	
 

	
 
	## Checks for liberties of a stone at given coordinates.
 
	#
 
	#  The stone's group is marked with True in self.temp, ready for capture if needed. Recursively called for stone's neighbors.
 
@@ -57,6 +74,7 @@ class Go:
 
			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)
 
@@ -74,6 +92,24 @@ def isLegalPosition(board):
 
	return True
 

	
 

	
 
def transitionMove(state1,state2):
 
	moves=[]
 
	for (r,(row1,row2)) in enumerate(zip(state1,state2)):
 
		for (c,(item1,item2)) in enumerate(zip(row1,row2)):
 
			if item1==EMPTY and item2!=EMPTY:
 
				moves.append((r,c,item2))
 

	
 
	if len(moves)==0:
 
		log.info("no new stone")
 
		return None
 
	elif len(moves)==1:
 
		log.info("new stone: %s",moves[0])
 
		return moves[0]
 
	else:
 
		log.warning("too many new stones: %s",moves)
 
		return False
 

	
 

	
 
def dfs(stack,board,mask):
 
	boardSize=len(board)
 
	(r,c)=stack[0]
src/statebag.py
Show inline comments
 
new file 100644
 
class StateBag:
 
	def __init__(self):
 
		self._states=[]
 

	
 
	def pushState(self,board):
 
		self._states.append(board)
0 comments (0 inline, 0 general)