def __init__(self,name,options,server=False,id=str(uuid4())): self.name = name self.names = [name] pygame.init() self.windowsize = (1024,768) self.menuback = pygame.image.load("./cards/titlescreen.gif").convert() self.screen = pygame.display.set_mode(self.windowsize) self.g = CanastaRound() self.p = HumanPlayer() self.factory = ReconnectingPBClientFactory() self.port = 7171 self.server = server self.id = UUID(id) self.clock = pygame.time.Clock() self.rejected = False self.connected = False self.controller = False self.options = options self.positions = [None]*4 self.pause = False self.starting = False self.start_game = False self.start_match = False self.cancel = False self.started = False self.initialized = False self.new_players = True self.shut_down = False self.shutting_down = False self.CommandQueue = [] self.desktop = Desktop()
class CanastaClient(pb.Referenceable): """ Handles all user input and graphical display. Connects to a server to make plays. All games, including the one-player game, use the client. """ def __init__(self,name,options,server=False,id=str(uuid4())): self.name = name self.names = [name] pygame.init() self.windowsize = (1024,768) self.menuback = pygame.image.load("./cards/titlescreen.gif").convert() self.screen = pygame.display.set_mode(self.windowsize) self.g = CanastaRound() self.p = HumanPlayer() self.factory = ReconnectingPBClientFactory() self.port = 7171 self.server = server self.id = UUID(id) self.clock = pygame.time.Clock() self.rejected = False self.connected = False self.controller = False self.options = options self.positions = [None]*4 self.pause = False self.starting = False self.start_game = False self.start_match = False self.cancel = False self.started = False self.initialized = False self.new_players = True self.shut_down = False self.shutting_down = False self.CommandQueue = [] self.desktop = Desktop() def callDebug(self,obj): if DEBUGGER: obj.callRemote("debug") def remote_debug(self): self.g.roundOver=True def Connect(self,obj): if DEBUGGER: print "Connection established with server" obj.callRemote("joinServer",self,self.name,str(self.id),VERSION).addCallback(self.isController) def Disconnect(self,obj): if DEBUGGER: print "Hanging up connection" obj.callRemote("hangUp",str(self.id)).addCallback(self.isDisconnected) def isDisconnected(self,obj): if DEBUGGER: print "Closed connection with server:",obj self.shut_down = True def failConnect(self,obj): if self.cancel: return "cancel" else: if DEBUGGER: print "Failed to connect, retrying..." sleep(1) reactor.connectTCP("localhost",self.port, self.factory) self.factory.getRootObject().addCallbacks(self.Connect,self.failConnect) def isController(self,obj): if isinstance(obj,str): print obj self.rejected = True reactor.stop() else: self.connected = True self.controller = obj def remote_lookAlive(self): return True def getNames(self,obj): obj.callRemote("Names").addCallback(self.gotNames) def remote_updateNames(self,namelist): self.names = namelist if self.initialized: print "got a new name",namelist if self.initialized: self.g.playernames.append(namelist[-1]) self.new_players = True def remote_removeName(self,name): if DEBUGGER: print "removing " + name + " from name list" if self.initialized: self.g.playernames.remove(name) self.names.remove(name) try: self.positions.remove(name) except: pass self.new_players = True def gotNames(self,obj): self.names = obj def startServer(self,obj): self.oneRef = obj self.oneRef.callRemote("Start",str(self.id),self.player_positions,self.options).addCallbacks(self.didStart,self.failStart) def didStart(self,obj): if DEBUGGER: print "Game started on the server" self.start_match = True if not self.server: self.factory.getRootObject().addCallbacks(self.blockClients) def failStart(self,obj): if DEBUGGER: print "Failed to start game on the server, retrying..." sleep(1) self.factory.getRootObject().addCallbacks(self.startServer,self.failStart) def blockClients(self,obj): obj.callRemote("blockConnections") def notClosed(self,obj): if DEBUGGER: print "Server did not close correctly:",obj self.shut_down = True def isClosed(self,obj): if DEBUGGER: print "Server closed correctly:",obj self.shut_down = True def stopServer(self,obj): self.shutting_down = True self.oneRef = obj self.oneRef.callRemote("Shutdown",str(self.id)).addCallbacks(self.isClosed,self.notClosed) def reportReady(self,obj): self.started=False self.initialized=False self.oneRef = obj if self.g.human in [0,1,2,3]: self.oneRef.callRemote("isReady",str(self.id)) def SendCommand(self,obj): self.oneRef = obj self.oneRef.callRemote("takeCanastaCommand",str(self.id),self.lastplay) def clearCommand(self,obj): self.lastplay=CanastaCommand(NO_PLAY,[],[]) def SendChat(self,obj): if DEBUGGER: print "sending chat" if len(self.chatwin.chattxt.text)>0: self.lastchat = CanastaCommand(CHAT,[self.chatwin.chattxt.text,self.g.myPos]) self.chatwin.chattxt.text = "" self.oneRef = obj self.oneRef.callRemote("takeChat",str(self.id),self.lastchat) def remote_initGame(self,players,human,options): if DEBUGGER: print "client game initialized" if options.animation == None: options.animation = self.options.animation self.g.gameStart(players,human,options) try: self.chatwin.close() except: pass self.genChat(self.g.CHATX[0],self.g.CHATX[1]) self.g.initCanasta(nextround=False) self.chatwin.enabled = True self.screen = pygame.display.set_mode(self.windowsize,RESIZABLE) def remote_resetRound(self): self.started = False self.initialized = False def remote_resetGame(self): self.starting = False self.start_game = False self.start_match = False self.cancel = False self.started = False self.initialized = False self.new_players = True self.shut_down = False self.shutting_down = False self.CommandQueue = [] def remote_newGame(self): if DEBUGGER: print "client game reset" self.g.newGame() def remote_initRound(self): try: self.desktop.query.close() except: pass if DEBUGGER: print "client round initialized" self.g.initCanasta() try: self.chatwin.close() except: pass self.genChat(self.g.curchatx,self.g.CHATX[1]) self.chatwin.enabled = True self.started = True def remote_readInit(self,status): if not self.initialized: if DEBUGGER: print "client got status" self.g.readInit(status) self.initialized = True def remote_readCommand(self,command): """ Read a command from the server. Chats are executed immediately, everything else is queued for execution later. """ if command.action==CHAT: self.g.execCode(command) return else: self.CommandQueue.append(command) retcode = True return [self.g.lastCommand,retcode] def execCommand(self,command): """ Execute a command on the local game object. Uses items that have previously been queued from the server. """ if self.g.turn==self.g.myPos: invis = False else: invis = True self.g.execCode(command,invisible=invis) retcode = self.g.lastReturn if DEBUGGER: print "result was",self.g.lastReturn if self.g.lastReturn: if self.g.roundOver: if DEBUGGER: print "ROUND OVER *** client updating score" team1round = self.g.cardPoints(1) + self.g.specialPoints(1,params=False) - self.g.handPoints(1) team2round = self.g.cardPoints(2) + self.g.specialPoints(2,params=False) - self.g.handPoints(2) self.g.team1score += team1round self.g.team2score += team2round self.genEndRound() self.clearCommand(None) if DEBUGGER & (not retcode): print "WARNING: command failed" return [self.g.lastCommand,retcode] def remote_lostPlayer(self,name): def ComputerOnClick(button): self.result = True self.desktop.query.close() self.desktop.query.position = (0,0) self.desktop.query.size = (0,0) def ResetOnClick(button): self.result = False self.desktop.query.close() self.desktop.query.position = (0,0) self.desktop.query.size = (0,0) self.result = None try: self.desktop.query.close() except: pass defaultStyle.init(gui) endStyle = {'font-color': (255,255,255), 'font': font.Font(None,20), 'autosize': True, "antialias": True,'border-width': False, 'border-color': (0,0,0), 'wordwrap': False} self.desktop.query = Window(position = (250,180), size = (500,200), parent = self.desktop, text = "Lost Player", closeable = False, shadeable = False) labelStyleCopy = gui.defaultLabelStyle.copy() Label(position = (30,50),size = (100,0), parent = self.desktop.query, text = str(name) + " has disconnected", style = endStyle) Label(position = (30,75),size = (100,0), parent = self.desktop.query, text = "Do you want to replace them with a computer player?", style = endStyle) Label(position = (30,100),size = (100,0), parent = self.desktop.query, text = "Or end this game and start a new one?", style = endStyle) Label(position = (30,125),size = (100,0), parent = self.desktop.query, text = "If you replace them, you can add them back in if they reconnect", style = endStyle) Computer_button = Button(position = (30,170), size = (175,0), parent = self.desktop.query, text = "Replace with computer") Computer_button.onClick = ComputerOnClick Reset_button = Button(position = (270,170), size = (175,0), parent = self.desktop.query, text = "Start over with a new game") Reset_button.onClick = ResetOnClick while self.result == None: self.defaultInput() self.DrawQuery() return self.result def remote_waitPlayer(self,name): defaultStyle.init(gui) endStyle = {'font-color': (255,255,255), 'font': font.Font(None,20), 'autosize': True, "antialias": True,'border-width': False, 'border-color': (0,0,0), 'wordwrap': False} self.desktop.query = Window(position = (250,180), size = (500,200), parent = self.desktop, text = "Lost Player", closeable = False, shadeable = False) labelStyleCopy = gui.defaultLabelStyle.copy() Label(position = (30,50),size = (100,0), parent = self.desktop.query, text = str(name) + " has disconnected", style = endStyle) Label(position = (30,100),size = (100,0), parent = self.desktop.query, text = "Waiting for the game host to replace them or restart the game", style = endStyle) self.pause = True return def askReset(self): def YesOnClick(button): self.pause = False def1 = self.factory.getRootObject() def1.addCallback(self.gameReset) self.desktop.query.close() self.desktop.query.position = (0,0) self.desktop.query.size = (0,0) def NoOnClick(button): self.pause = False self.desktop.query.close() self.desktop.query.position = (0,0) self.desktop.query.size = (0,0) defaultStyle.init(gui) endStyle = {'font-color': (255,255,255), 'font': font.Font(None,24), 'autosize': True, "antialias": True,'border-width': False, 'border-color': (0,0,0), 'wordwrap': False} self.desktop.query = Window(position = (350,250), size = (300,200), parent = self.desktop, text = "Reset", closeable = False, shadeable = False) labelStyleCopy = gui.defaultLabelStyle.copy() Label(position = (100,50),size = (100,0), parent = self.desktop.query, text = "Reset the game", style = endStyle) Label(position = (100,100),size = (100,0), parent = self.desktop.query, text = "Are you sure?", style = endStyle) Yes_button = Button(position = (50,150), size = (40,0), parent = self.desktop.query, text = "Yes") No_button = Button(position = (200,150), size = (40,0), parent = self.desktop.query, text = "No") Yes_button.onClick = YesOnClick No_button.onClick = NoOnClick self.pause = True return def gameReset(self,obj): obj.callRemote("Reset",str(self.id)) def remote_unPause(self): try: self.desktop.query.close() self.desktop.query.position = (0,0) self.desktop.query.size = (0,0) except: pass self.pause = False def remote_goOut(self): """ Called remotely by the server when the client's partner has asked to go out. Waits for user input. """ self.done = False def OKOnClick(button): self.done = True self.response = True def cancelOnClick(button): self.done = True self.response = False defaultStyle.init(gui) defaultStyle.init(gui) desktop_main = Desktop() desktop = Window(position = (300,220), size = (400,200), parent = desktop_main, text = "Go Out", closeable = False, shadeable = False) desktop.onClose = cancelOnClick labelStyleCopy = gui.defaultLabelStyle.copy() Label(position = (100,100),size = (200,0), parent = desktop, text = 'Your partner asked: "May I go out?"', style = labelStyleCopy) OK_button = Button(position = (100,140), size = (50,0), parent = desktop, text = "Yes") cancel_button = Button(position = (200,140), size = (50,0), parent = desktop, text = "No") OK_button.onClick = OKOnClick cancel_button.onClick = cancelOnClick while not self.done: #Handle Input Events for event in gui.setEvents(): if event.type == QUIT: return elif event.type == KEYDOWN and event.key == K_ESCAPE: return self.DrawGame(flip=False) desktop_main.update() desktop_main.draw() pygame.display.flip() return self.response def remote_endGame(self): """ Called by the server on all non-controlling clients after the controller sends the kill signal. Should send a confirmation and then kill the reactor in the next input loop. """ if DEBUGGER: print "quitting client" pygame.quit() self.shut_down = True def overWindow(self): result = False try: temp = self.desktop.assign assign = True assign_pos = self.desktop.assign.position assign_size = self.desktop.assign.size except: assign = False try: temp = self.desktop.query query = True query_pos = self.desktop.query.position query_size = self.desktop.query.size except: query = False try: temp = self.chatwin chat = True chat_pos = self.chatwin.position chat_size = self.chatwin.size except: chat = False if gui.events != None: for event in gui.events: if event.type in [MOUSEBUTTONUP,MOUSEBUTTONDOWN,MOUSEMOTION]: if assign: if (event.pos[0] > assign_pos[0]) & (event.pos[0]<assign_pos[0]+assign_size[0]) & (event.pos[1] > assign_pos[1]) & (event.pos[1]<assign_pos[1]+assign_size[1]): result = True if query: if (event.pos[0] > query_pos[0]) & (event.pos[0]<query_pos[0]+query_size[0]) & (event.pos[1] > query_pos[1]) & (event.pos[1]<query_pos[1]+query_size[1]): result = True if chat: if (event.pos[0] > chat_pos[0]) & (event.pos[0]<chat_pos[0]+chat_size[0]) & (event.pos[1] > chat_pos[1]) & (event.pos[1]<chat_pos[1]+chat_size[1]): result = True return result def defaultInput(self,chat=True): if self.chatwin.chattxt.hasFocus: self.g.enterchat = True else: self.g.enterchat = False play = self.p.getPlay(self.g,gui.events) if play.action == QUIT_GAME: def1 = self.factory.getRootObject() if self.controller: def1.addCallbacks(self.stopServer) else: def1.addCallbacks(self.Disconnect) play = CanastaCommand(NO_PLAY,[],[]) elif (play.action == CHAT) & chat: self.lastchat = play def1 = self.factory.getRootObject() def1.addCallback(self.SendChat) play = CanastaCommand(NO_PLAY,[],[]) elif play.action == RESIZE: self.screen = pygame.display.set_mode(play.arglist[0],RESIZABLE) self.windowsize = play.arglist[0] self.chatwin.close() self.genChat(self.g.curchatx,self.g.CHATX[1]) play = CanastaCommand(NO_PLAY,[],[]) if self.g.animating: self.g.animate() else: try: self.execCommand(self.CommandQueue.pop(0)) except: pass return play def getInput(self): """ The main user input loop. Runs concurrently with Twisted's main reactor, so that the user can enter commands whenever they want. Game commands are sent to the server for execution. If valid, the server will call back to execute them locally. Chats are sent to the server through the special back channel that allows them to be distributed even if it's someone else's turn. Cards can be moved or selected at any time, but commands will not be executed unless it's the client's turn. For efficiency, the client is coded to only submit commands on its turn. For stability, however, the server is programmed to check for the turn before executing any non-chat command it receives. """ self.clock.tick(40) if self.overWindow(): self.p.over_window = True else: self.p.over_window = False if self.cancel: reactor.stop() if self.shut_down: try: pygame.quit() except: pass try: reactor.stop() except: pass elif self.pause: self.defaultInput() self.DrawQuery() elif self.shutting_down: pass elif self.started & self.initialized: if self.chatwin.chattxt.hasFocus: self.g.enterchat = True else: self.g.enterchat = False play = self.defaultInput() if (self.g.roundOver) | (self.p.viewhelp==1): if self.p.viewhelp==1: try: if self.desktop.query.wintype != "help": try: self.desktop.query.close() self.desktop.query.position = (0,0) self.desktop.query.size = (0,0) self.genHelp() except: self.genHelp() except: self.genHelp() self.DrawQuery() else: self.DrawGame() if play.action == RESET: if self.controller: self.askReset() elif play.action != NO_PLAY: if self.g.turn==self.g.myPos: self.lastplay = play def1 = self.factory.getRootObject() def1.addCallback(self.SendCommand) if self.p.viewhelp==0: try: if self.desktop.query.wintype == "help": self.desktop.query.close() self.desktop.query.position = (0,0) self.desktop.query.size = (0,0) except: pass elif (not self.start_match) & self.controller & (not self.server): for event in pygame.event.get(): if event.type == QUIT: self.cancel = True elif event.type == KEYDOWN and event.key == K_ESCAPE: self.cancel = True if self.connected: self.DrawWait("Waiting for game to start...") else: self.DrawWait("Connecting to the game server...") if not self.starting: if DEBUGGER: print "Starting the server" self.factory.getRootObject().addCallbacks(self.startServer,self.failStart) self.starting = True elif (not self.server) | self.start_match: if self.connected: if self.chatwin.chattxt.hasFocus: self.g.enterchat = True else: self.g.enterchat = False self.DrawWait("Waiting for game to start...") play = self.p.getPlay(self.g,gui.events) if play.action == QUIT_GAME: def1 = self.factory.getRootObject() if self.controller: def1.addCallbacks(self.stopServer) else: def1.addCallbacks(self.Disconnect) elif play.action == CHAT: self.lastchat = play def1 = self.factory.getRootObject() def1.addCallback(self.SendChat) else: for event in pygame.event.get(): if event.type == QUIT: self.shut_down = True elif event.type == KEYDOWN and event.key == K_ESCAPE: self.shut_down = True self.DrawWait("Connecting to the game server...") elif not self.connected: self.DrawWait("Setting up the game server...") else: if not self.start_game: if self.chatwin.chattxt.hasFocus: self.g.enterchat = True else: self.g.enterchat = False play = self.p.getPlay(self.g,gui.events) #Handle Input Events for event in gui.events: if event.type == KEYDOWN and event.key == 13: if not self.g.enterchat: self.start_game = True else: pass if play.action == QUIT_GAME: def1 = self.factory.getRootObject() def1.addCallbacks(self.stopServer) elif play.action == CHAT: self.lastchat = play def1 = self.factory.getRootObject() def1.addCallback(self.SendChat) elif not self.starting: playernames=[] for index, p in enumerate(self.positions): playernames.append(p) self.player_positions = playernames self.factory.getRootObject().addCallback(self.startServer) self.starting = True self.DrawAssign() def readyStartGame(self): self.start_game = True ##################################### #Drawing routines ##################################### def DrawAssign(self): def OKOnClick(button): self.start_game = True self.desktop.assign.close() self.desktop.assign.position = (0,0) self.desktop.assign.size = (0,0) def assignPlayer(arg): which = self.glist.index(arg.name) last = self.gr[which] if DEBUGGER: print arg.name,self.glist,which,last if arg.value==None: return loc = posnames.index(arg.text) #Assign an observer. Allows starting a game with no human players only if the debugger is on. if (loc == 4) & ((positions != [None]*4) | DEBUGGER): try: self.gr[which].value = False except: pass for i in range(len(positions)): if positions[i]==arg.name: positions[i]=None self.gr[which] = arg #Reject the assign if it conflicts with another player's assignment or leaves no human players with the debugger off. elif (positions[loc]!=None) | ((loc==4) & (positions==[None]*4) & (not DEBUGGER)): print "BZZT!" arg.value = False self.gr[which].value = True #Otherwise, assign the position else: try: self.gr[which].value = False except: pass for i in range(len(positions)): if positions[i]==arg.name: positions[i]=None positions[loc] = arg.name self.gr[which] = arg if DEBUGGER: print positions self.positions = positions playernames=self.names if self.new_players: try: self.desktop.assign.close() self.desktop.query.position = (0,0) self.desktop.query.size = (0,0) except: pass optionsurf = pygame.image.load("./art/optionbox.png").convert_alpha() self.desktop_main = Desktop() self.desktop.assign = Window(position = (100,100), size = (800,600), parent = self.desktop, text = "Assign players", closeable = False, shadeable = False) self.gr = [] self.glist = [] defaultStyle.init(gui) labelStyleCopy = gui.defaultLabelStyle.copy() labelStyleCopy['wordwrap'] = True if self.positions == [None]*4: default = True else: default = False positions = self.positions posnames = ["Bottom","Left","Top","Right","Observer"] for index, p in enumerate(self.names): if index<4: def_pos = posnames[index] else: def_pos = None if index==0: label1 = Label(position = (125,125),size = (200,0), parent = self.desktop.assign, text = "Players will appear here when they connect to your game.", style = labelStyleCopy) label2 = Label(position = (125,145),size = (200,0), parent = self.desktop.assign, text = "Assign them to a player position and press the start button when ready.", style = labelStyleCopy) label3 = Label(position = (125,165),size = (200,0), parent = self.desktop.assign, text = "Unfilled positions will be filled with computer players.", style = labelStyleCopy) label3 = Label(position = (125,185),size = (200,0), parent = self.desktop.assign, text = "Observers can watch the game and use the chat window, and may be included in the next round.", style = labelStyleCopy) label_name = Label(position = (125,220 + index*25),size = (200,0), parent = self.desktop.assign, text = p, style = labelStyleCopy) if (index<4) & default: positions[index] = p self.gr.append(None) self.glist.append(p) for index2, pos in enumerate(posnames): o = CheckBox(position = (200+index2*75,220+index*25), parent = self.desktop.assign, text = pos, style = gui.createOptionBoxStyle(gui.defaultFont, optionsurf, 12, (255,255,255), (100,100,100), autosize = True)) o.name = p print p o.index = index2 try: if positions[index2]==p: o.value = True self.gr[index] = o except: pass if (index2==4) & (self.gr[index]==None): o.value = True o.onValueChanged = assignPlayer OK_button = Button(position = (125,400), size = (50,0), parent = self.desktop.assign, text = "Start") OK_button.onClick = OKOnClick self.positions = positions self.new_players = False self.DrawGame() def DrawWait(self,message): defaultStyle.init(gui) desktop_main = Desktop() desktop = Window(position = (300,220), size = (400,200), parent = desktop_main, text = "Waiting", closeable = False, shadeable = False) labelStyleCopy = gui.defaultLabelStyle.copy() Label(position = (100,75),size = (50,0), parent = desktop, text = message, style = labelStyleCopy) if not self.connected: font = pygame.font.Font("FreeSans.ttf", 30) self.titletext = font.render("Play against the computer",1,(255,255,255)) self.titletext2 = font.render("Start a network game",1,(255,255,255)) self.titletext3 = font.render("Join a network game",1,(255,255,255)) self.titletext4 = font.render("Options",1,(255,255,255)) self.titlepos = self.titletext.get_rect() self.titlepos.centerx = 512 self.titlepos.centery = 350 self.titlepos2 = self.titletext2.get_rect() self.titlepos2.centerx = 512 self.titlepos2.centery = 450 self.titlepos3 = self.titletext3.get_rect() self.titlepos3.centerx = 512 self.titlepos3.centery = 550 self.titlepos4 = self.titletext4.get_rect() self.titlepos4.centerx = 512 self.titlepos4.centery = 650 self.screen.fill((0,0,255)) #YOUR RENDERING HERE!!! self.screen.blit(self.menuback, (0,0)) self.screen.blit(self.titletext,self.titlepos) self.screen.blit(self.titletext2,self.titlepos2) self.screen.blit(self.titletext3,self.titlepos3) self.screen.blit(self.titletext4,self.titlepos4) else: self.DrawGame(flip=False) #Last thing to draw, desktop try: desktop_main.update() desktop_main.draw() except: pass #Flips! pygame.display.flip() def DrawGame(self,flip=True): screen = self.screen g = self.g p = self.p playernames = self.g.playernames # DRAWING screen.fill((0x00, 0xb0, 0x00)) #Stage area pygame.draw.rect(screen,(0,0,0),(g.curstagexy[0]-5,g.curstagexy[1]-5,g.curstagexy[2]+10,g.curstagexy[3]+10)) pygame.draw.rect(screen,(0,255,0),g.curstagexy) sr = screen.get_rect() centerx = sr.centerx centery = sr.centery #Turn arrows arrow_length = 30 headw = 10 headl = 15 if g.turn==0: fl = [[(centerx,centery+20),(centerx,centery+20+arrow_length)], [(centerx-headw,centery+20+arrow_length-headl),(centerx,centery+20+arrow_length)], [(centerx+headw,centery+20+arrow_length-headl),(centerx,centery+20+arrow_length)]] elif g.turn==1: fl = [[(centerx-90,centery-50),(centerx-90-arrow_length,centery-50)], [(centerx-90-arrow_length+headl,centery-50-headw),(centerx-90-arrow_length,centery-50)], [(centerx-90-arrow_length+headl,centery-50+headw),(centerx-90-arrow_length,centery-50)]] elif g.turn==2: fl = [[(centerx,centery-90),(centerx,centery-90-arrow_length)], [(centerx-headw,centery-90-arrow_length+headl),(centerx,centery-90-arrow_length)], [(centerx+headw,centery-90-arrow_length+headl),(centerx,centery-90-arrow_length)]] elif g.turn==3: fl = [[(centerx+100,centery-50),(centerx+100+arrow_length,centery-50)], [(centerx+100+arrow_length-headl,centery-headw-50),(centerx+100+arrow_length,centery-50)], [(centerx+100+arrow_length-headl,centery+headw-50),(centerx+100+arrow_length,centery-50)]] for points in fl: pygame.draw.aaline(screen,(200,0,0), points[0], points[1]) if g.roundOver: for c in g.cardGroup.cards: if (c.side==0) & c.location in range(3,401): c.flip() pygame.draw.rect(screen,(0,0,0),(g.curlocxy[1][0]+2,g.curlocxy[1][1]+2,70,90),2) g.cardGroup.draw(screen) if g.selectionRect.width > 0 and g.selectionRect.height > 0: pygame.draw.rect(screen,(0xff,0xff,0x00),g.selectionRect,3) if g.curState().turnState == PRE_DRAW: state_text = "Draw or pick up" else: state_text = "Meld or discard" #Score area pygame.draw.rect(screen,(0,0,0),(g.curscorex-5,5,280,60)) pygame.draw.rect(screen,(0,0,255),(g.curscorex,10,270,50)) font = pygame.font.Font("freesansbold.ttf", 14) font2 = pygame.font.Font("FreeSans.ttf", 14) roundtext = font.render("%s%s" % ("ROUND ",g.round),1,(255,255,255)) team1text = font.render("%s%s" % ("Team 1: ",g.team1score),1,(255,255,255)) team2text = font.render("%s%s" % ("Team 2: ",g.team2score),1,(255,255,255)) curteamtext = font2.render("%s%s%s" % (playernames[g.turn],": ",state_text),1,(255,255,255)) roundpos = roundtext.get_rect() roundpos.centerx = g.curscorex + 40 roundpos.centery = 23 team1pos = roundtext.get_rect() team1pos.centerx = g.curscorex + 110 team1pos.centery = 23 team2pos = roundtext.get_rect() team2pos.centerx = g.curscorex + 210 team2pos.centery = 23 curteampos = roundtext.get_rect() curteampos.centerx = g.curscorex + 40 curteampos.centery = 43 screen.blit(roundtext,roundpos) screen.blit(team1text,team1pos) screen.blit(team2text,team2pos) screen.blit(curteamtext,curteampos) #Chat window self.chatwin.chatdisplay.text = "" if not self.chatwin.shaded: for i in range(-1,-8,-1): try: text = self.g.chatlist[i] count = 0 rendered = gui.wrapText(text + "\n" + self.chatwin.chatdisplay.text,self.chatwin.chatdisplay.style['font'],self.chatwin.chatdisplay.size[0]) for char in rendered: if char=="\n": count += 1 if count<9: self.chatwin.chatdisplay.text = self.g.chatlist[i] + "\n" +self.chatwin.chatdisplay.text except: pass gui.setEvents() try: self.desktop.update() except: pass self.desktop.draw() if flip: pygame.display.flip() def genEndRound(self): self.next_round = False def ContinueOnClick(button): self.desktop.query.close() self.desktop.query.position = (0,0) self.desktop.query.size = (0,0) def1 = self.factory.getRootObject() def1.addCallback(self.reportReady) team1round = self.g.cardPoints(1) + self.g.specialPoints(1,params=False) - self.g.handPoints(1) team2round = self.g.cardPoints(2) + self.g.specialPoints(2,params=False) - self.g.handPoints(2) font2 = pygame.font.Font("FreeSans.ttf", 20) team1specials = self.g.specialPoints(1,params=True) team2specials = self.g.specialPoints(2,params=True) if team1specials[2]==8: team1specials[2]=4 if team2specials[2]==8: team2specials[2]=4 if team1specials[3]==1: team1out = "Went out first" elif team1specials[3]==2: team1out = "Went out concealed" else: team1out = "" if team2specials[3]==1: team2out = "Went out first" elif team2specials[3]==2: team2out = "Went out concealed" else: team2out = "" endtext1 = ["Team 1:", str(team1round)+ " points", str(self.g.cardPoints(1)) + " face value", "-" + str(self.g.handPoints(1)) + " points in hand", str(team1specials[0])+" red canastas", str(team1specials[1])+" black canastas", str(team1specials[2])+" red threes", str(team1specials[4])+" wild card canastas", team1out] endtext2 = ["Team 2:", str(team2round)+ " points", str(self.g.cardPoints(2)) + " face value", "-" + str(self.g.handPoints(2)) + " points in hand", str(team2specials[0])+" red canastas", str(team2specials[1])+" black canastas", str(team2specials[2])+" red threes", str(team2specials[4])+" wild card canastas", team2out] if (self.g.team1score>=5000) & (self.g.team1score>self.g.team2score): endtext1.append("Team 1 is the winner!") if (self.g.team2score>=5000) & (self.g.team2score>self.g.team1score): endtext2.append("Team 2 is the winner!") defaultStyle.init(gui) endStyle = {'font-color': (255,255,255), 'font': font.Font(None,24), 'autosize': True, "antialias": True,'border-width': False, 'border-color': (0,0,0), 'wordwrap': False} self.desktop.query = Window(position = (250,180), size = (500,400), parent = self.desktop, text = "Round Over", closeable = False, shadeable = False) labelStyleCopy = gui.defaultLabelStyle.copy() Label(position = (200,40),size = (100,0), parent = self.desktop.query, text = "Round " + str(self.g.round) + " over", style = endStyle) for pos, t in enumerate(endtext1): Label(position = (50,80+25*pos),size = (200,0), parent = self.desktop.query, text = t, style = endStyle) for pos, t in enumerate(endtext2): Label(position = (300,80+25*pos),size = (200,0), parent = self.desktop.query, text = t, style = endStyle) Cont_button = Button(position = (200,350), size = (70,0), parent = self.desktop.query, text = "Continue") Cont_button.onClick = ContinueOnClick def genHelp(self): def helpClose(button): self.p.viewhelp = 0 self.desktop.query.wintype = None self.desktop.query.position = (0,0) self.desktop.query.size = (0,0) text = [ "Canasty v0.1", "-----------------------", "F1 - Display this help text.", "ESC - Quit.", "Click the scoreboard to re-sort your cards", "Click the pile to draw a card", "Click the discard pile to pick it up", "(first stage or select cards", "that you need to meld)", "Drag a card to the pile to discard it", "Select cards and right-click to meld", "(or drag them onto an existing meld)", "Drag melds to the stage area to stage them", "Left-click the stage to meld it", "(right-click to clear it)", "-----------------------", "See manual for alternate keyboard controls"] defaultStyle.init(gui) helpStyle = {'font-color': (255,255,255), 'font': font.Font(None,24), 'autosize': True, "antialias": True,'border-width': False, 'border-color': (0,0,0), 'wordwrap': False} self.desktop.query = Window(position = (300,120), size = (400,500), parent = self.desktop, text = "Help", closeable = True, shadeable = False) self.desktop.query.onClose = helpClose self.desktop.query.wintype = "help" labelStyleCopy = gui.defaultLabelStyle.copy() for pos, t in enumerate(text): Label(position = (30,35+25*pos),size = (200,0), parent = self.desktop.query, text = t, style = helpStyle) def genChat(self,x,y): defaultStyle.init(gui) self.chatwin = Window(position = (x,y), size = (280,130), parent = self.desktop, text = "", closeable = False, shadeable = True) labelStyleCopy = gui.defaultLabelStyle.copy() labelStyleCopy['autosize'] = False labelStyleCopy['wordwrap'] = True labelStyleCopy['font'] = pygame.font.Font("FreeSans.ttf", 12) textboxStyleCopy = gui.defaultTextBoxStyle.copy() textboxStyleCopy['border-width'] = 1 textboxStyleCopy['font'] = pygame.font.Font("FreeSans.ttf", 12) self.chatwin.chatdisplay = Label(position = (5,5),size = (270,105), parent = self.chatwin, text = "", style = labelStyleCopy) self.chatwin.chattxt = TextBox(position = (5,107), size = (270, 0), parent =self.chatwin, text = "", style = textboxStyleCopy) self.chatwin.enabled = True def DrawQuery(self): self.DrawGame(flip=False) #Flips! pygame.display.flip()