Changeset - 9ab11204b0f9
[Not reviewed]
default
0 6 0
Laman - 6 years ago 2018-12-03 22:08:58

StateBag exportuje záznam partie, BoardView zobrazuje pořadí tahů
6 files changed with 50 insertions and 16 deletions:
0 comments (0 inline, 0 general)
src/core.py
Show inline comments
 
@@ -46,17 +46,21 @@ class Core:
 
		self._guiMessages.send("setCurrentFrame",(self._frame.copy(),))
 
		self.analyze()
 

	
 
	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,))
 
				state=self.states.pushState(self.detector.board)
 
				rec=[]
 
				if state:
 
					rec=state.exportRecord()
 
					log.debug("progressive game record: %s",rec)
 
				self._guiMessages.send("setGameState", (self.detector.board,rec))
 

	
 
				self.go.transitionMove(self.detector.board)
 
				log.debug("game record: %s",self.go._record)
 
				log.debug("conservative game record: %s",self.go._record)
 
			else:
 
				log.info("illegal position detected")
 

	
 
	def listen(self):
 
		listenerThread=threading.Thread(target=lambda: self._ownMessages.listen())
 
		listenerThread.start()
src/go/engine.py
Show inline comments
 
@@ -4,12 +4,13 @@ from . import core
 

	
 

	
 
## Compute move sequence from state1 to state2.
 
#
 
# @param colorIn {BLACK,WHITE}: color to start the sequence
 
# @param colorOut {BLACK,WHITE}: color to close the sequence
 
# @return [(c,row,col), ...] or None. c in {BLACK,WHITE} == {1,-1}
 
def getTransitionSequence(state1,state2,colorIn,colorOut,diff):
 
	eng.load(state1)
 
	return eng.iterativelyDeepen(state2,diff,colorIn,colorOut)
 

	
 

	
 
class SpecGo(core.Go):
 
@@ -19,13 +20,15 @@ class SpecGo(core.Go):
 
	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."""
 
		There's no end to what could be theoretically relevant, but such sequences are long and we will pretend they won't happen.
 

	
 
		:return: (blackMoves,whiteMoves) == ({(row,col), ...}, {(row,col), ...})"""
 
		res=({PASS},{PASS})
 
		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))
 
@@ -61,13 +64,15 @@ class Engine:
 
		self._transpositions=TranspositionTable()
 

	
 
	def load(self,state1):
 
		self._g.load(state1)
 

	
 
	def iterativelyDeepen(self,state2,diff,colorIn,colorOut):
 
		"""Search for a move sequence from the loaded state to state2. Tries progressively longer sequences."""
 
		"""Search for a move sequence from the loaded state to state2. Tries progressively longer sequences.
 

	
 
		:return: [(c,row,col), ...] or None. c in {BLACK,WHITE} == {1,-1}"""
 
		self._moveList=self._g.listRelevantMoves(diff)
 
		startDepth=1 if colorIn==colorOut else 2
 
		self._g.toMove=colorIn
 

	
 
		for i in range(startDepth,5,2):
 
			seq=self._dfs(state2,i)
src/gui/__init__.py
Show inline comments
 
@@ -45,10 +45,11 @@ class GUI:
 
		return actions[actionName](*args,**kwargs)
 

	
 
	def _frameHandler(self,newFrame):
 
		self.mainWindow.setCurrentFrame(newFrame)
 
		self.root.event_generate("<<redrawImgView>>")
 

	
 
	def _stateHandler(self,gameState):
 
		self.mainWindow.boardView.redrawState(gameState)
 
	def _stateHandler(self,gameState,moves):
 
		labels={(row,col):(i+1) for (i,(c,row,col)) in enumerate(moves)}
 
		self.mainWindow.boardView.redrawState(gameState,labels)
 

	
 
gui=GUI()
src/gui/boardview.py
Show inline comments
 
@@ -4,25 +4,27 @@ from go.core import BLACK,WHITE
 

	
 
## Handles and presents the game state as detected by the program.
 
class BoardView(ResizableCanvas):
 
	def __init__(self, master=None):
 
		super().__init__(master)
 

	
 
		self._padding=24
 
		self.configure(width=360,height=360,background="#ffcc00")
 

	
 
		self._padding=24
 
		self._cellWidth=(self._width-2*self._padding)/18
 
		self._cellHeight=(self._height-2*self._padding)/18
 

	
 
		self._drawGrid()
 

	
 
	def redrawState(self,gameState):
 
		self.delete("black","white")
 
	def redrawState(self,gameState,labels=dict()):
 
		self.delete("black","white","label")
 
		for r,row in enumerate(gameState):
 
			for c,point in enumerate(row):
 
				self._drawStone(r, c, point)
 
				self._drawStone(r, c, point, labels.get((r,c)))
 

	
 
	def configure(self,*args,**kwargs):
 
		super().configure(*args,**kwargs)
 
		self._cellWidth=(self._width-2*self._padding)/18
 
		self._cellHeight=(self._height-2*self._padding)/18
 

	
 
	def _drawGrid(self):
 
		padding=self._padding
 
		for i in range(19):
 
			self.create_line(padding,self._cellHeight*i+padding,self._width-padding,self._cellHeight*i+padding,tags="row",fill="#000000") # rows
 
			self.create_line(self._cellWidth*i+padding,padding,self._cellWidth*i+padding,self._height-padding,tags="col",fill="#000000") # cols
 
@@ -54,24 +56,28 @@ class BoardView(ResizableCanvas):
 
	#
 
	#  For an unknown color draws nothing and returns False.
 
	#
 
	#  @param r row coordinate, [0-18], counted from top
 
	#  @param c column coordinate, [0-18], counted from left
 
	#  @param color color indicator, go.BLACK or go.WHITE
 
	def _drawStone(self, r, c, color):
 
	def _drawStone(self, r, c, color, label=""):
 
		if color==BLACK:
 
			hexCode='#000000'
 
			altCode='#ffffff'
 
			tag="black"
 
		elif color==WHITE:
 
			hexCode='#ffffff'
 
			altCode='#000000'
 
			tag="white"
 
		else: return False
 

	
 
		x=c*self._cellWidth+self._padding
 
		y=r*self._cellHeight+self._padding
 
		radius=self._cellWidth/2
 
		self.create_oval(x-radius,y-radius,x+radius,y+radius,tags=tag,fill=hexCode)
 
		if label:
 
			self.create_text(x,y,text=label,tags="label",fill=altCode)
 

	
 
	def _onResize(self,event):
 
		super()._onResize(event)
 
		self._cellWidth=(self._width-2*self._padding)/18
 
		self._cellHeight=(self._height-2*self._padding)/18
src/statebag/__init__.py
Show inline comments
 
@@ -57,13 +57,13 @@ class StateBag:
 
	def __init__(self):
 
		self._states=[]
 

	
 
	def pushState(self,board):
 
		sn=BoardState(board)
 
		if len(self._states)>0:
 
			if sn==self._states[-1]: return None # no change
 
			if sn==self._states[-1]: return self._states[-1] # no change
 
			sn.cachedDiff=sn-self._states[-1]
 
		else: sn.setWeight(1)
 

	
 
		diff=sn.cachedDiff
 
		for s in reversed(self._states):
 
			sn.tryConnect(s,diff)
src/statebag/boardstate.py
Show inline comments
 
@@ -28,12 +28,25 @@ class GameTreeNode:
 
		w=v.weight+2-len(moves) # proper one move transition increases the weight by 1
 
		if w>self.weight:
 
			self.moves=moves
 
			self.prev=v
 
			self.weight=w
 

	
 
	def exportRecord(self):
 
		""":return: [(c,row,col), ...]. c in {BLACK,WHITE} == {1,-1}"""
 
		sequence=[]
 
		v=self
 
		while v is not None:
 
			sequence.append(v)
 
			v=v.prev
 

	
 
		res=[]
 
		for v in reversed(sequence):
 
			res.extend(v.moves)
 
		return res
 

	
 

	
 
class BoardState:
 
	def __init__(self,board):
 
		self._board=tuple(tuple(x for x in row) for row in board)
 
		self.nodes=(GameTreeNode(self,BLACK),GameTreeNode(self,WHITE))
 
		self.cachedDiff=[]
 
@@ -56,12 +69,17 @@ class BoardState:
 
	def export(self):
 
		return exportBoard(self._board)
 

	
 
	def exportDiff(self,s2):
 
		return "vvv\n{0}\n=== {1} ===\n{2}\n^^^".format(self.export(), s2-self, s2.export())
 

	
 
	def exportRecord(self):
 
		""":return: [(c,row,col), ...]. c in {BLACK,WHITE} == {1,-1}"""
 
		v=self.nodes[0] if self.nodes[0].weight>self.nodes[1].weight else self.nodes[1]
 
		return v.exportRecord()
 

	
 
	def __iter__(self): return iter(self._board)
 

	
 
	def __getitem__(self,key): return self._board[key]
 

	
 
	## Compute difference self-s.
 
	def __sub__(self,s):
0 comments (0 inline, 0 general)