Continued network mode implementation

This commit is contained in:
Anna Rose 2012-04-15 19:52:58 -04:00
parent 4f5227cd82
commit f4680cc631
4 changed files with 126 additions and 38 deletions

View File

@ -19,11 +19,11 @@ class GTPSocket:
# #
# dispatcher = {'command1': function_1, 'command_2': function_2, 'command_3': function_3} # dispatcher = {'command1': function_1, 'command_2': function_2, 'command_3': function_3}
# gtp_socket = GTPSocket(socket) # gtp_socket = GTPSocket(socket)
# GTPSocket.known_cmds.extend(dispatcher.keys()) # GTPSocket.known_cmds = GTPSocket.known_cmds & set(dispatcher.keys())
# gtp = gtp_socket.get() # gtp = gtp_socket.get()
# if gtp.type == 'command': # if gtp.type == 'command':
# dispatcher[gtp.command](gtp) # dispatcher[gtp.command](gtp)
known_cmds = ['protocol_version', 'name', 'version', 'known_command', 'list_commands'] known_cmds = set(['protocol_version', 'name', 'version', 'known_command', 'list_commands'])
def __init__(self, socket): def __init__(self, socket):
self.socket = None self.socket = None
@ -51,12 +51,15 @@ class GTPSocket:
# Some gtp commands should be handled internally # Some gtp commands should be handled internally
if gtp.command == 'protocol_version': if gtp.command == 'protocol_version':
self.send_response('2', gtp.id) self.send_response('2', gtp.id)
return None
elif gtp.command == 'name': elif gtp.command == 'name':
self.send_response('pygo', gtp.id) self.send_response('pygo', gtp.id)
return None
elif gtp.command == 'version': elif gtp.command == 'version':
self.send_response('', gtp.id) self.send_response('', gtp.id)
return None
elif gtp.command == 'known_command': elif gtp.command == 'known_command':
if gtp.arguments[0] in GTPSocket.known_cmds: if gtp.arguments[0] in GTPSocket.known_cmds:
@ -64,9 +67,14 @@ class GTPSocket:
else: else:
resp = 'false' resp = 'false'
self.send_response(resp, gtp.id) self.send_response(resp, gtp.id)
return None
elif gtp.command == 'list_commands': elif gtp.command == 'list_commands':
self.send_response(''.join(GTPSocket.known_cmds, '\n'), gtp.id) self.send_response(''.join(GTPSocket.known_cmds, '\n'), gtp.id)
return None
else:
return gtp

View File

@ -11,12 +11,12 @@ import threading
class NetworkThread(threading.Thread): class NetworkThread(threading.Thread):
dispatcher = { dispatcher = {
'quit': None, 'quit': do_quit,
'boardsize': None, 'boardsize': do_boardsize,
'clear_board': None, 'clear_board': do_clear_board,
'komi': None, 'komi': do_komi,
'play': None, 'play': do_play,
'genmove': None 'genmove': do_genmove
} }
@ -26,8 +26,33 @@ class NetworkThread(threading.Thread):
self.socket = GTPSocket(socket) self.socket = GTPSocket(socket)
self.send_lock = threading.Lock() self.send_lock = threading.Lock()
GTPSocket.known_cmds.extend(dispatcher.keys()) GTPSocket.known_cmds = GTPSocket.known_cmds & set(dispatcher.keys())
def run(self): def run(self):
pass pass
def do_quit(self, gtp):
pass
def do_boardsize(self, gtp):
pass
def do_clear_board(self, gtp):
pass
def do_komi(self, gtp):
pass
def do_play(self, gtp):
pass
def do_genmove(self, gtp):
pass

View File

@ -10,7 +10,7 @@ from sgc.locals import *
class GUI: class GUI:
def __init__(self, goban): def __init__(self, goban, settings):
# Basic screen init # Basic screen init
pygame.init() pygame.init()
# screen = pygame.display.set_mode((1000, 800)) # screen = pygame.display.set_mode((1000, 800))
@ -28,16 +28,34 @@ class GUI:
# Build the dict of image objects # Build the dict of image objects
self.img_res = _build_img_res() self.img_res = _build_img_res()
self.goban = goban
self.settings = settings
# Network-related settings
self.net_thread = None
self.socket = None
self.network_mode = False
self.our_color = None
self.board_size = 800 self.board_size = 800
self.board_inc = self.board_size / 19 self.board_inc = self.board_size / 19
self.screen.fill((250, 250, 250)) self.screen.fill((250, 250, 250))
self.pass_btn = sgc.widgets.Button(label="Pass", pos=(850,500)) self.join_btn = sgc.widgets.Button(label="Join Game", pos=(850,400))
self.join_btn.activate = self.join_game
self.join_btn.add()
self.wait_btn = sgc.widgets.Button(label="Listen", pos=(850,475))
self.wait_btn.activate = self.wait_for_game
self.wait_btn.add()
self.pass_btn = sgc.widgets.Button(label="Pass", pos=(850,550))
self.pass_btn.activate = goban.pass_move self.pass_btn.activate = goban.pass_move
self.pass_btn.add() self.pass_btn.add()
self.resign_btn = sgc.widgets.Button(label="Resign", pos=(850,600)) self.resign_btn = sgc.widgets.Button(label="Resign", pos=(850,625))
self.resign_btn.activate = goban.resign self.resign_btn.activate = goban.resign
self.resign_btn.add() self.resign_btn.add()
@ -45,33 +63,46 @@ class GUI:
self.quit_btn.activate = sys.exit self.quit_btn.activate = sys.exit
self.quit_btn.add() self.quit_btn.add()
# self.waiting
# pygame.time.set_timer(USEREVENT, 1000) # pygame.time.set_timer(USEREVENT, 1000)
def do_event(self):
def do_event(self, goban, network_mode, our_color):
event = pygame.event.wait() event = pygame.event.wait()
sgc.widgets.event(event) sgc.widgets.event(event)
if event.type == QUIT: if event.type == QUIT:
return return
# This set of events should only be called if we can currently play
if network_mode == False or goban.to_move == our_color: if self.network_mode:
# This set of events should only be called if we can currently play
if self.goban.to_move == self.our_color:
# Hover a transparent stone over our
# cursor position, assuming play is legal
if event.type == MOUSEMOTION:
with self.net_thread.goban_lock:
self.do_hover(event)
if event.type == MOUSEBUTTONDOWN:
x, y = event.pos
row = y / self.board_inc
col = x / self.board_inc
if x <= self.board_size:
if event.button == 1:
with self.net_thread.send_lock:
col_letter = chr(col + 96)
self.socket.send(col_letter + str(row))
self.goban.play_move((row, col))
# Local play mode
else:
# Hover a transparent stone over our # Hover a transparent stone over our
# cursor position, assuming play is legal # cursor position, assuming play is legal
if event.type == MOUSEMOTION: if event.type == MOUSEMOTION:
x, y = event.pos self.do_hover(event)
row = y / self.board_inc
col = x / self.board_inc
if _magnitude(event.rel) < 3:
if x <= self.board_size:
goban.set_hover((row,col))
else:
goban.clear_hover()
elif goban.hover != goban._real_pos((row,col)):
goban.clear_hover()
# Place a stone on left-click # Place a stone on left-click
if event.type == MOUSEBUTTONDOWN: if event.type == MOUSEBUTTONDOWN:
@ -81,7 +112,7 @@ class GUI:
if x <= self.board_size: if x <= self.board_size:
if event.button == 1: if event.button == 1:
goban.play_move((row, col)) self.goban.play_move((row, col))
# if event.type == USEREVENT: # if event.type == USEREVENT:
# goban.elapsed_time += 1 # goban.elapsed_time += 1
@ -92,18 +123,42 @@ class GUI:
# dialogs.remove(widget) # dialogs.remove(widget)
def update(self):
def update(self, goban): board = self.goban.draw_board(self.board_size, self.img_res)
board = goban.draw_board(self.board_size, self.img_res)
self.screen.blit(board, (0,0)) self.screen.blit(board, (0,0))
text = goban.draw_info() text = self.goban.draw_info()
self.screen.blit(text, (815, 25)) self.screen.blit(text, (815, 25))
sgc.widgets.update(0) sgc.widgets.update(0)
pygame.display.flip() pygame.display.flip()
# fixme: this uses localhost as a stub
def join_game(self):
pass
# fixme: this uses localhost as a stub
def wait_for_game(self):
pass
def do_hover(self, event):
x, y = event.pos
row = y / self.board_inc
col = x / self.board_inc
if _magnitude(event.rel) < 3:
if x <= self.board_size:
self.goban.set_hover((row,col))
else:
self.goban.clear_hover()
elif self.goban.hover != self.goban._real_pos((row,col)):
self.goban.clear_hover()
def _magnitude(vector): def _magnitude(vector):
x,y = vector x,y = vector

12
pygo.py
View File

@ -18,15 +18,15 @@ def main():
# Data # Data
gb = goban.Goban() gb = goban.Goban()
network_mode = False gui = pygogui.GUI(gb, settings)
our_color = None
gui = pygogui.GUI(gb)
gui.update(gb) gui.update()
while True: while True:
gui.do_event(gb, network_mode, our_color) # All of the real work happens in pygogui
gui.update(gb) # It keeps a copy of all the relevant data
gui.do_event()
gui.update()