def verify_card(self,cards,card_num): '''Verifica se la carta card_num puo' essere giocata nel turno corrente.''' # di mano, carta valida if self.table.count(0) == len(self.table): return True # verifica se possiamo rispondere ver = [] for c in cards: ver.append(deck.get_card(c)[0]) prev = deck.get_card(self.table[self.current_order[0]]) this = deck.get_card(card_num) # possiamo rispondere, verifica se la carta precedente e' dello stesso seme print "Verification seems:",ver,"starting seem of",self.table[self.current_order[0]],"is",prev[0],"my seem for card",card_num,"is",this[0] if prev[0] in ver: if prev[0] == this[0]: return True # non possiamo rispondere else: return True return False
def _next_round(r, k, players): """ PLAYER:: CAMP => UNDECIDED Clear the table, move everyone from CAMP to UNDECIDED, and deal an artifact and a card. """ # push everything on the table and captured back into the deck return_to_deck = r.lrange(path(k, TABLE), 0, -1) + r.lrange(path(k, CAPTURED), 0, -1) if len(return_to_deck): r.sadd(path(k, DECK), *return_to_deck) r.delete(path(k, TABLE), path(k, CAPTURED)) r.set(path(k, POT), 0) for player in players: r.hset(path(k, PLAYERS, player[NAME]), STATE, UNDECIDED) new_artifact = r.spop(path(k, ARTIFACTS_UNSEEN)) _round = r.incr(path(k, ROUND)) _save_update(r, k, { ROUND: int(_round) } ) _save_update(r, k, { ARTIFACTS_IN_PLAY: get_card(new_artifact).name } ) assert r.sadd(path(k, DECK), new_artifact) == 1 r.rpush(path(k, ARTIFACTS_IN_PLAY), new_artifact) _deal_card(r, k)
def _deal_card(r, k, hans=[]): """ PLAYER:: HAN => UNDECIDED | CAMP This will deal another card and push any hans either back to camp (death) or back to undecided. A single card is moved from a random point in the deck onto the right side of the table. """ prior_card_names = [get_card(idx).name for idx in r.lrange(path(k, TABLE), 0, -1)] card_idx = r.spop(path(k, DECK)) r.rpush(path(k, TABLE), card_idx) card = get_card(card_idx) _save_update(r, k, { CARD : card.name }) if isinstance(card, Hazard) and card.name in prior_card_names: _save_update(r, k, { DEATH : { PLAYERS: sorted([h[NAME] for h in hans]), CARD: card.name } }) # save intermediate game state for death for han in hans: r.hset(path(k, PLAYERS, han[NAME]), STATE, DEATH) _save_game_state(r, k, True) _publish_update(r, k) coro_sleep(DEATH_SLEEP) new_state = CAMP else: new_state = UNDECIDED if hans: _save_update(r, k, { HAN : { PLAYERS : sorted([h[NAME] for h in hans])}}) if isinstance(card, Artifact): artifacts_seen_count = r.incr(path(k, ARTIFACTS_SEEN_COUNT)) _save_update(r, k, { ARTIFACTS_SEEN_COUNT: int(artifacts_seen_count) }) for han in hans: r.hset(path(k, PLAYERS, han[NAME]), STATE, new_state)
def _save_game_state(r, k, reveal=False): """ Saves a JSON representation of the game's current state. If reveal is true, the players hash will reveal everyone's move. """ players = _get_players(r, k) update_id = r.incr(path(k, UPDATE_ID)) for player in players: r.rpush(path(k, PLAYERS, player[NAME], SAVED), json.dumps(player)) game_state = { UPDATE_ID: update_id, PLAYERS: [ p if p[STATE] in [WON, LOST] else { NAME: p[NAME], STATE: MOVED if (p[STATE] in [HAN, LANDO] and not reveal) else p[STATE] } for p in players], TABLE: [get_card(idx).name for idx in r.lrange(path(k, TABLE), 0, -1)], CAPTURED: [get_card(idx).name for idx in r.lrange(path(k, CAPTURED), 0, -1)], POT: int(r.get(path(k, POT)) or 0), ARTIFACTS_DESTROYED: [get_card(idx).name for idx in r.lrange(path(k, ARTIFACTS_DESTROYED), 0, -1)], ARTIFACTS_SEEN_COUNT: int(r.get(path(k, ARTIFACTS_SEEN_COUNT)) or 0), ARTIFACTS_IN_PLAY: [get_card(idx).name for idx in r.lrange(path(k, ARTIFACTS_IN_PLAY), 0, -1)] } if r.exists(path(k, ROUND)): game_state[ROUND] = r.get(path(k, ROUND)) r.rpush(path(k, SAVED), json.dumps(game_state))
def _get_players(r, k): """ Get a list of all players in the game formed as dictionaries. Notates them with their artifacts. """ players = [r.hgetall(path(k, PLAYERS, name)) for name in sorted(r.smembers(path(k, PLAYERS)))] for player in players: player[player[STATE]] = True # a bit hacky, but this makes templating easier player[ARTIFACTS_CAPTURED] = [ get_card(idx).name for idx in r.lrange(path(k, PLAYERS, player[NAME], ARTIFACTS_CAPTURED), 0, -1)] return players
def _take_loot(r, k, landos): """ PLAYER:: LANDO => CAMP This will move all Landos back to CAMP, giving them loot. """ loot = int(r.get(path(k, POT)) or 0) for card_idx in r.lrange(path(k, TABLE), 0, -1): card = get_card(card_idx) if isinstance(card, Treasure): loot += card.value r.lrem(path(k, TABLE), 1, card_idx) r.rpush(path(k, CAPTURED), card_idx) elif isinstance(card, Artifact): r.lrem(path(k, TABLE), 1, card_idx) artifact_value = ARTIFACT_VALUES[int(r.get(path(k, ARTIFACTS_SEEN_COUNT))) - 1] r.lrem(path(k, ARTIFACTS_IN_PLAY), 1, card_idx) if len(landos) == 1: # lucky lando _save_update(r, k, { ARTIFACTS_CAPTURED : { PLAYERS : landos[0][NAME], CARD: card.name, VALUE: artifact_value } }) loot += artifact_value r.rpush(path(k, PLAYERS, landos[0][NAME], ARTIFACTS_CAPTURED), card_idx) else: _save_update(r, k, { ARTIFACTS_DESTROYED : { PLAYERS : sorted([l[NAME] for l in landos]), CARD: card.name, VALUE: artifact_value } }) r.rpush(path(k, ARTIFACTS_DESTROYED), card_idx) remainder = loot % len(landos) payout = (loot - remainder) / len(landos) r.set(path(k, POT), remainder) for lando in landos: r.hset(path(k, PLAYERS, lando[NAME]), STATE, CAMP) # LANDO => CAMP r.hincrby(path(k, PLAYERS, lando[NAME]), LOOT, payout) _save_update(r, k, { LANDO : { PLAYERS : sorted([l[NAME] for l in landos]), VALUE : payout, POT: remainder }})
def _round_points_to_team(self, position, cards): '''Consegna il punteggio delle carte alla squadra del giocatore in position.''' team = position % 2 # calcola punteggio cumul = self.hand_points[team][0] third = self.hand_points[team][1] for c in cards: s,v = deck.get_card(c) if v == 1: cumul = cumul + 1 if v == 2 or v == 3 or (v >= 8 and v <= 10): third = third + 1 if third == 3: cumul = cumul + 1 third = 0 print "(SERVER) Giving",cumul,"points to team",team self.hand_points[team][0] = cumul self.hand_points[team][1] = third
def turn_next(self, card_num): '''Continua il giro al giocatore successivo. card_num: carta giocata in questo turno ''' # rilascia il turno dal giocatore precedente position = self.current_order[len(self.table)-self.table.count(0)] self.players[position].set_state(player.STATE_TURNWAIT) self.table[position] = card_num print "(SERVER) Cards on table:",self.table if self.table.count(0) == 0: # fine giro, determina chi prende e dichiara print "(SERVER) End round!" # elimina ogni chat pendente for p in self.players: p.cancel_chat_pending() primary = deck.get_card(self.table[self.current_order[0]]) take = self.current_order[0] print "(SERVER) Commanding seem is",primary for c in self.table: s,v = deck.get_card(c) print "(SERVER) Card value:",(v,CARDS_VALUE.index(v)),(primary[1],CARDS_VALUE.index(primary[1])) if s == primary[0] and CARDS_VALUE.index(v) > CARDS_VALUE.index(primary[1]): print "(SERVER) Found major card:",c take = self.table.index(c) primary = s,v print "(SERVER) Position",take,"takes the head" # consegna i punti alla squdra del giocatore self._round_points_to_team(take,self.table) self.conn.send_all(interfaces.NetMethod(protocol.TAKES,take)) self.conn.send_all(interfaces.NetMethod(protocol.POINTS,self.hand_points)) self.turn_count = self.turn_count + 1 if self.turn_count >= ROUNDS: # fine mano! print "(SERVER) End hand!" self._update_game_points(take) time.sleep(3.0) self.conn.send_all(interfaces.NetMethod(protocol.GAME_POINTS,self.points)) if self.points[0] >= MAX_POINTS or self.points[1] >= MAX_POINTS: # fine partita! raggiunto 41... ret = self.points.index(max(self.points)) if self.points[0] == self.points[1]: # mitici... solo voi ce potete riusci! ret = -1 # dichiara fine partita... self.conn.send_all(interfaces.NetMethod(protocol.END_GAME,ret)) else: self.conn.send_all(interfaces.NetMethod(protocol.END_HAND)) # inizia nuova mano... # dovrebbe funzionare... self._make_deck() for p in self.players: p.conn.user_data['state'] = PSTATE_JOINED p.set_state(player.STATE_WAIT) else: # ricomincia giro dalla posizione di take time.sleep(3.0) self.turn(take) else: # dai il turno al giocatore successivo if position >= 3: position = -1 # dichiarazione pubblica accusi if ( len(self.table) - self.table.count(0) ) == 1 and self.turn_count == 1: for p in self.players: if len(p.accusations) > 0: self.conn.send_all(interfaces.NetMethod(protocol.ACCUSATIONS,p.position,p.accusations)) self.players[position+1].set_state(player.STATE_TURN)
print "Verification seems:",ver,"starting seem of",self.table[self.current_order[0]],"is",prev[0],"my seem for card",card_num,"is",this[0] if prev[0] in ver: if prev[0] == this[0]: return True # non possiamo rispondere else: return True return False if __name__ == '__main__': table = [3, 2, 1, 8] print "(SERVER) Table:",table primary = deck.get_card(table[0]) take = 0 print "Commanding:",primary for c in table: s,v = deck.get_card(c) print "(SERVER) Card value:",(v,CARDS_VALUE.index(v)),(primary[1],CARDS_VALUE.index(primary[1])) if s == primary[0] and CARDS_VALUE.index(v) > CARDS_VALUE.index(primary[1]): #print "(SERVER) Found major card:",c take = table.index(c) print "(SERVER) Position",take,"takes the head" team = take % 2