def __init__(self, parent,multiplayer=False,HOST="99.66.147.56",PORT=3478,player=''): self.activeCard = 0 self.startTime = -1 self.multiplayer = multiplayer if self.multiplayer: self.client = KarutaClient(HOST, int(PORT), player) cards = self.client.cards self.cardsLeft = self.client.order else: self.client = KarutaSingleClient() cards = range(1,101) self.cardsLeft = range(1,101) random.shuffle(cards) random.shuffle(self.cardsLeft) self.queue = deque([]) self.fgrid = [[None for col in range(NUM_COLS)] for row in range(6)] self.model = [[None for col in range(NUM_COLS)] for row in range(6)] self.faultCount = 0 self.faults = [0,0] Frame.__init__(self, parent) self.parent = parent self.initUI(cards) self.changeState('waiting') if self.multiplayer: self.client.next = 0 self.opponentReady = False else: self.opponentReady = True self.client.nextMove = 0 self.pollForUpdates() self.processUpdates()
class Karuta(Frame): def pollForUpdates(self): try: #response = self.client.sendMessage('get,'+str(self.client.next)) responseMove = self.client.sendMessage('getmove,'+str(self.client.nextMove)) #if not response == '': #self.client.next = self.client.next + 1 #self.queue.append(response) if not responseMove == '': self.client.nextMove = self.client.nextMove + 1 self.queue.append(responseMove) finally: self.parent.after(200,self.pollForUpdates) def processUpdates(self): if not len(self.queue) == 0: item = self.queue[0] success = self.process(item) if success: self.queue.popleft() self.parent.after(200,self.processUpdates) def process(self,message): info = message.split(',') print(message) if info[1] == 'took' and not info[0] == self.client.player: timeTaken = float(info[2]) numFaults = info[3] if timeTaken < time.time() - self.startTime and timeTaken < self.delta: self.changeState('waiting') text = "Opponent won the card. Faults: you="+str(self.faultCount)+", opp="+numFaults self.client.sendMessage('took,'+str(self.delta)+','+str(self.faultCount)) self.infoLabel.config(text=text) pic = self.model[self.activeCardRow][self.activeCardCol] pic.pack_forget() pic.isNone = True return True elif timeTaken > self.delta: text = "You won the card. Faults: you="+str(self.faultCount)+", opp="+numFaults self.infoLabel.config(text=text) self.changeState('waiting') return True else: return False elif info[1] == 'ready' and not info[0] == self.client.player: self.opponentReady = True if self.state == 'ready': self.playButton.config(state=NORMAL) self.infoLabel.config(text="Both players are ready.") self.update() return True elif info[1] == 'ready' and info[0] == self.client.player: self.changeState('ready') if self.opponentReady: self.playButton.config(state=NORMAL) self.infoLabel.config(text="Both players are ready.") else: self.infoLabel.config(text="Waiting for opponent.") self.update() return True elif info[0] == 'swap': arr = [int(k) for k in info[1:]] self.doSwap((arr[0],arr[1]),(arr[2],arr[3])) return True elif info[0] == 'rerack': self.performRerack(info[1]) return True elif info[1] == 'play': if self.state == 'ready' and self.opponentReady: self.playNextAudio() return True elif info[1] == 'ghost' and not info[0] == self.client.player: numFaults = info[2] self.changeState('waiting') text = "Karufuda. Faults: you="+str(self.faultCount)+", opp="+numFaults self.infoLabel.config(text=text) return True elif info[0] == self.client.player: return True else: print(message) return True def __init__(self, parent,multiplayer=False,HOST="99.66.147.56",PORT=3478,player=''): self.activeCard = 0 self.startTime = -1 self.multiplayer = multiplayer if self.multiplayer: self.client = KarutaClient(HOST, int(PORT), player) cards = self.client.cards self.cardsLeft = self.client.order else: self.client = KarutaSingleClient() cards = range(1,101) self.cardsLeft = range(1,101) random.shuffle(cards) random.shuffle(self.cardsLeft) self.queue = deque([]) self.fgrid = [[None for col in range(NUM_COLS)] for row in range(6)] self.model = [[None for col in range(NUM_COLS)] for row in range(6)] self.faultCount = 0 self.faults = [0,0] Frame.__init__(self, parent) self.parent = parent self.initUI(cards) self.changeState('waiting') if self.multiplayer: self.client.next = 0 self.opponentReady = False else: self.opponentReady = True self.client.nextMove = 0 self.pollForUpdates() self.processUpdates() def playNextAudio(self): if self.state == 'ready' and self.opponentReady: self.delta = 100000 if self.multiplayer: self.opponentReady = False self.faultCount = 0 self.faults = [0,0] self.infoLabel.config(text='Now Playing') if self.cardsLeft: self.changeState('taking') previousCard = self.activeCard randomCard = self.cardsLeft.pop() self.activeCard = randomCard self.activeCardRow = -1 for row in range(6): for col in range(NUM_COLS): if self.model[row][col].card.number == self.activeCard and not self.model[row][col].isNone: self.activeCardRow = row self.activeCardCol = col break print(randomCard) def playCurrentVerse2(): call(['afplay','Audio/Verse2/Audio'+str(previousCard)+'.mp3']) t= threading.Thread(target=playCurrentVerse2, args=()) t.start() self.parent.after(verse2Durations[previousCard]+1000,self.playNextVerse1) self.startTime = time.time() + verse2Durations[previousCard]+1000 #estimate if self.activeCardRow == -1: self.parent.after(11000+verse2Durations[previousCard],self.sendFouls) elif self.state == 'taking': randomCard = self.activeCard def doInBackground(): call(['afplay','Audio/Verse1/Audio'+str(randomCard)+'.m4a']) t= threading.Thread(target=doInBackground, args=()) t.start() else: self.infoLabel.config(text='Not everyone is ready yet') def reveal(self): if self.activeCardRow == -1: self.infoLabel.config(text='karafuda') else: self.infoLabel.config(text='Row,Col = ('+str(self.activeCardRow)+','+str(self.activeCardCol)+')') self.update() def sendFouls(self): self.client.sendMessage('ghost,'+str(self.faultCount)) if not self.multiplayer: self.client.oppSendMessage('p2,ghost,0') def playNextVerse1(self): self.startTime = time.time() def doPlay(): call(['afplay','Audio/Verse1/Audio'+str(self.activeCard)+'.m4a']) t = threading.Thread(target=doPlay, args=()) t.start() def rerack(self): if self.state == 'waiting' or self.state == 'move-select-start' or self.state == 'move-select-stop': self.client.sendMessage('rerack,'+self.client.player) def performRerack(self,player): if self.multiplayer: self.opponentReady = False self.changeState('waiting') self.infoLabel.config(text='Reracking') if self.multiplayer: if player == 'p1': rows = [3,4,5] else: rows = [0,1,2] else: rows = range(6) moved = True while moved: moved = False for row in rows: for col in reversed(range(NUM_COLS/2)): if self.model[row][col].isNone and not self.model[row][col+1].isNone: self.doSwap((row,col),(row,col+1)) moved = True # self.model[row][col+1].isNone = True # self.model[row][col+1].pack_forget() # self.model[row][col].isNone = False # self.model[row][col].image = self.model[row][col+1].image # self.model[row][col].config(image=self.model[row][col].image) # self.model[row][col].pack(fill=BOTH) for col in reversed([NUM_COLS-i-1 for i in range(NUM_COLS/2)]): if self.model[row][col].isNone and not self.model[row][col-1].isNone: self.doSwap((row,col),(row,col-1)) moved = True # self.model[row][col-1].isNone = True # self.model[row][col-1].pack_forget() # self.model[row][col].isNone = False # self.model[row][col].image = self.model[row][col-1].image # self.model[row][col].config(image=self.model[row][col].image) # self.model[row][col].pack(fill=BOTH) self.update() def initUI(self,cards): self.parent.title("Karuta") Style().configure("TButton") p1,p2 = assignCards(cards,order) for row in range(6): for col in range(NUM_COLS): if (NUM_COLS-col,row+1) in p1: self.setCard(p1[(NUM_COLS-col,row+1)],row,col) elif (col+1,6-row) in p2: self.setCard(p2[(col+1,6-row)],row,col) else: self.setCard(-1,row,col) self.p1 = [i for i in p1.values()] self.p2 = [i for i in p2.values()] def move(): if self.state == 'move-select-start' or self.state == 'move-select-stop': self.changeState('waiting') self.moveButton.config(text='Move') self.infoLabel.config(text='Move cancelled') elif self.state == 'waiting': self.changeState('move-select-start') self.infoLabel.config(text='Select card to move') self.moveButton.config(text='Cancel') self.update() b = Button(self,text='Move',command=move) b.grid(row=0,column=8) self.moveButton = b def playNextAudio(): if self.state == 'taking': self.playNextAudio() else: self.client.sendMessage('play') b = Button(self,text='Play',command=playNextAudio) self.playButton = b b.grid(row=0, column=9) def reveal(): self.reveal() b = Button(self,text='Reveal',command=reveal) b.grid(row=0, column=10) self.revealButton = b if self.multiplayer: b.config(state=DISABLED) def rerack(): self.rerack() b = Button(self,text='Rerack',command=rerack) b.grid(row=0, column=11) self.rerackButton = b def ready(): if self.startTime < time.time() - 11: if self.state == 'taking' and not self.activeCardRow == -1: self.infoLabel.config(text="Card has not been found yet.") self.update() else: self.moveButton.config(text="Move") self.client.sendMessage('ready') self.update() b = Button(self,text='Ready',command=ready) b.grid(row=0, column=12) self.readyButton = b l = Label(self,text='') l.grid(row=0, column=0, columnspan=5) self.infoLabel = l self.pack() def setCard(self,cardnum,row,col): dodel = False if cardnum == -1: dodel = True cardnum = 1 card = Card(cardnum) f = Frame(self, height = card.height, width = card.width) if (row == 2 and self.client.player == 'p1') or (row == 3 and self.client.player == 'p2'): f.config(height = card.height+20) if self.client.player == 'p1': f.grid(row=row+1, column=col) else: f.grid(row=6-row, column=NUM_COLS-col) f.pack_propagate(0) self.fgrid[row][col] = f pic = Label(f) if row <= 2: card.flip() if self.client.player == 'p2': card.flip() pic.config(image=card.img) pic.image = card.img pic.row = row pic.col = col pic.card = card def clicked(pic,ins,card): if ins.state == 'taking' and not pic.isNone: if pic.card.number == ins.activeCard: endTime = time.time() ins.delta = round(endTime-self.startTime,2) print(ins.delta) print("Got in "+str(ins.delta)) ins.client.sendMessage('took,'+str(ins.delta)+','+str(ins.faultCount)) if not ins.multiplayer: ins.client.oppSendMessage('p2,took,20,0') ins.changeState('waiting') pic.pack_forget() ins.model[pic.row][pic.col].isNone = True elif ins.activeCardRow == -1 or not (pic.row <= 2) == (ins.activeCardRow <= 2): ins.faults[int(pic.row <= 2)] = 1 ins.faultCount = sum(ins.faults) elif ins.state == 'move-select-start': ins.movingPic = (pic.row, pic.col) print('moving card:') print(ins.movingPic) if (((self.client.player == 'p1' and pic.row > 2) or (self.client.player == 'p2' and pic.row <= 2))\ and not pic.isNone) or not ins.multiplayer: ins.infoLabel.config(text="Card chosen. Select destination.") ins.changeState('move-select-stop') else: ins.infoLabel.config(text="Can't move that. Select a different card to move.") ins.moveButton.config(text="Cancel") elif ins.state == 'move-select-stop': print('to:') print((pic.row, pic.col)) if ((self.client.player == 'p1' and pic.row <= 2) or (self.client.player == 'p2' and pic.row > 2))\ and not pic.isNone: ins.infoLabel.config(text="Illegal move. Select a different card to move.") else: ins.swapCards(self.movingPic,(pic.row, pic.col)) ins.infoLabel.config(text="Move completed. Select next card.") ins.changeState('move-select-start') f.bind("<Button-1>",lambda e,pic=pic,self=self,card=card:clicked(pic,self,card)) pic.bind("<Button-1>",lambda e,pic=pic,self=self,card=card:clicked(pic,self,card)) pic.pack(fill=BOTH) self.model[row][col] = pic if dodel: pic.pack_forget() self.model[row][col].isNone = True else: self.model[row][col].isNone = False def swapCards(self,pos1, pos2): row1,col1 = pos1 row2,col2 = pos2 self.client.sendMessage('swap,'+str(row1)+','+str(col1)+','+str(row2)+','+str(col2)) # if (self.client.player == 'p2' and row1 <=2 and row2 <=2) or\ # (self.client.player == 'p1' and row1 > 2 and row2 > 2): # self.client.sendMessage('swap,'+str(row1)+','+str(col1)+','+str(row2)+','+str(col2)) # elif (self.client.player == 'p2' and row1 <= 2 and row2 > 2 \ # and not self.model[row1][col1].isNone and self.model[row2][col2].isNone) or \ # (self.client.player == 'p1' and row1 > 2 and row2 <= 2 \ # and not self.model[row1][col1].isNone and self.model[row2][col2].isNone): # self.client.sendMessage('swap,'+str(row1)+','+str(col1)+','+str(row2)+','+str(col2)) def doSwap(self,pos1, pos2): if self.multiplayer: self.opponentReady = False if self.state == 'ready': self.changeState('waiting') self.infoLabel.config(text="Reconfirm when ready.") row1,col1 = pos1 row2,col2 = pos2 pic1 = self.model[row1][col1] pic2 = self.model[row2][col2] card1 , card2 = pic1.card , pic2.card if not (row1 <= 2) == (row2 <= 2): card1.flip() card2.flip() pic1.card , pic2.card = pic2.card , pic1.card pic1.image , pic2.image = pic1.card.img , pic2.card.img pic1.isNone , pic2.isNone = pic2.isNone , pic1.isNone if not pic1.isNone: pic1.config(image=pic1.image) pic1.pack(fill=BOTH) else: pic1.pack_forget() if not pic2.isNone: pic2.config(image=pic2.image) pic2.pack(fill=BOTH) else: pic2.pack_forget() self.update() def changeState(self,state): self.state = state if state == 'waiting': self.readyButton.config(state=NORMAL) self.rerackButton.config(state=NORMAL) self.playButton.config(state=DISABLED) self.moveButton.config(state=NORMAL,text="Move") elif state == 'ready': self.readyButton.config(state=ACTIVE) self.rerackButton.config(state=DISABLED) #self.playButton.config(state=NORMAL) #only activate when both players are ready self.moveButton.config(state=DISABLED,text="Move") elif state == 'move-select-start' or state == 'move-select-stop': self.playButton.config(state=DISABLED) self.moveButton.config(state=ACTIVE) elif state == 'taking': self.rerackButton.config(state=DISABLED) self.readyButton.config(state=DISABLED) self.moveButton.config(state=DISABLED,text="Move") self.playButton.config(state=NORMAL)