Changeset - bc96e653888e
[Not reviewed]
default
0 3 1
Laman - 7 years ago 2017-12-26 00:56:18

GUI: added window menu
4 files changed with 26 insertions and 1 deletions:
0 comments (0 inline, 0 general)
src/go/engine.py
Show inline comments
 
@@ -19,88 +19,88 @@ class SpecGo(core.Go):
 
		"""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=({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))
 
				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,colorIn,colorOut):
 
		startDepth=1 if colorIn==colorOut else 2
 
		self._g.toMove=colorIn
 

	
 
		for i in range(startDepth,10,2):
 
		for i in range(startDepth,6,2):
 
			seq=self.dfs(state2,i)
 
			if seq:
 
				seq.reverse()
 
				return seq
 
		return None
 

	
 
	def dfs(self,state2,limit):
 
		g=self._g
 
		moveSet=self._moveList[(1-g.toMove)>>1]
 
		for m in moveSet.copy():
 
			if not g.doMove(g.toMove,*m): continue
 
			captured=g.captures[:g.captureCount]
 
			moveSet.remove(m)
 
			if m==PASS: # no reason for both players to pass
 
				self._moveList[(1-g.toMove)>>1].remove(m)
 

	
 
			if limit>1:
 
				seq=self.dfs(state2,limit-1)
 
				if seq:
 
					self._undoMove(m,captured)
 
					seq.append((g.toMove,*m))
 
					return seq
 

	
 
			if limit==1 and g.hash()==state2.hash():
 
				self._undoMove(m,captured)
 
				return [(g.toMove,*m)]
 

	
 
			self._undoMove(m,captured)
 
		return None
 

	
 
	def _undoMove(self,move,captured):
 
		g=self._g
 
		g.undoMove(*move,captured)
 
		k=(1-g.toMove)>>1
 
		self._moveList[k].add(move)
 
		if move==PASS:
 
			self._moveList[1-k].add(move)
 

	
 
eng=Engine()
src/gui/__init__.py
Show inline comments
 
import threading
 
import tkinter as tk
 

	
 
import config
 
from .mainwindow import MainWindow
 
from .boardview import BoardView
 

	
 

	
 
class GUI:
 
	def __init__(self):
 
		self.root = tk.Tk()
 
		self.root.title("OneEye {0}.{1}.{2}".format(*config.misc.version))
 
		self.root.option_add('*tearOff',False) # for menu
 

	
 
		self._coreMessages=None
 

	
 
		self.mainWindow = MainWindow(self, master=self.root)
 
		self.root.columnconfigure(0,weight=1)
 
		self.root.rowconfigure(0,weight=1)
 

	
 
		self.root.bind("<<redrawImgView>>", lambda e: self.mainWindow.redrawImgView())
 
		self.root.bind("<Left>",lambda e: self.sendMsg("prevFrame"))
 
		self.root.bind("<Right>",lambda e: self.sendMsg("nextFrame"))
 

	
 
	def __call__(self,ownMessages,coreMessages):
 
		self._coreMessages=coreMessages
 

	
 
		self.listenerThread=threading.Thread(target=lambda: ownMessages.listen(self._handleEvent))
 
		self.listenerThread.start()
 

	
 
		self.mainWindow.mainloop()
 

	
 
	def sendMsg(self,actionName,args=tuple(),kwargs=None):
 
		self._coreMessages.send(actionName,args,kwargs)
 

	
 
	def _handleEvent(self,e):
 
		actions={"setCurrentFrame":self._frameHandler, "setGameState":self._stateHandler}
 
		(actionName,args,kwargs)=e
 

	
 
		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)
 

	
 
gui=GUI()
src/gui/mainwindow.py
Show inline comments
 
import tkinter as tk
 
from tkinter import N,S,E,W
 

	
 
from . import menu
 
from .boardview import BoardView
 
from .imgview import ImgView
 

	
 

	
 
class MainWindow(tk.Frame):
 
	def __init__(self,parent,master=None):
 
		self.parent=parent
 

	
 
		tk.Frame.__init__(self, master)
 
		self.grid(column=0,row=0,sticky=(N,S,E,W))
 
		self._createWidgets()
 

	
 
		self.bind("<Left>",lambda e: self.sendMsg("prevFrame"))
 
		self.bind("<Right>",lambda e: self.sendMsg("nextFrame"))
 

	
 
	def setCurrentFrame(self,frame):
 
		self.imgView.setImg(frame)
 

	
 
	def _createWidgets(self):
 
		# menu
 
		self.parent.root.option_add('*tearOff',False)
 
		menubar=menu.createTopBar(self.parent.root)
 
		menu.createMainMenu(menubar)
 

	
 
		# a captured frame with overlay graphics
 
		self._imgWrapper=tk.Frame(self,width=480,height=360)
 
		self.imgView=ImgView(self._imgWrapper,self)
 

	
 
		self._imgWrapper.grid(column=0,row=0,sticky=(N,S,E,W))
 

	
 
		# board with detected stones
 
		self._boardWrapper=tk.Frame(self,width=360,height=360)
 
		self.boardView=BoardView(self._boardWrapper)
 
		self._boardWrapper.grid(column=1,row=0,sticky=(N,S,E,W))
 

	
 
		# more controls below the board
 
		self.scaleTresB=tk.Scale(self, orient=tk.HORIZONTAL, length=200, from_=0.0, to=100.0, command=self.refreshTresholds)
 
		self.scaleTresW=tk.Scale(self, orient=tk.HORIZONTAL, length=200, from_=0.0, to=100.0, command=self.refreshTresholds)
 
		self.scaleTresB.set(30.0) # !! proper defaults
 
		self.scaleTresW.set(60.0)
 
		self.scaleTresB.grid(column=0,row=1,columnspan=2)
 
		self.scaleTresW.grid(column=0,row=2,columnspan=2)
 

	
 
		self.columnconfigure(0,weight=1)
 
		self.columnconfigure(1,weight=1)
 
		self.rowconfigure(0,weight=1)
 

	
 
		# render everything
 
		self.imgView.redraw()
 

	
 
	## Redraws the current image and its overlay.
 
	def redrawImgView(self):
 
		self.imgView.redraw()
 

	
 
	def refreshTresholds(self,_):
 
		self.parent.sendMsg("setTresholds",tuple(),{"tresB":self.scaleTresB.get(), "tresW":self.scaleTresW.get()})
 

	
 
	def sendMsg(self,actionName,args=tuple(),kwargs=None):
 
		self.parent.sendMsg(actionName,args,kwargs)
src/gui/menu.py
Show inline comments
 
new file 100644
 
from tkinter import Menu
 

	
 

	
 
def createTopBar(root):
 
	menubar = Menu(root)
 
	root['menu'] = menubar
 
	return menubar
 

	
 

	
 
def createMainMenu(menubar):
 
	file = Menu(menubar)
 
	_help = Menu(menubar)
 
	menubar.add_cascade(menu=file, label='File')
 
	menubar.add_cascade(menu=_help, label='Help')
 

	
 
	file.add_command(label="Settings")
 

	
 
	_help.add_command(label="About")
0 comments (0 inline, 0 general)