def _compute_winner(self, use_cards=True, player_filter=None): maxpoints = 0 top_players = [] player_filter = player_filter or set(range(self.players_number)) for i, p in enumerate(self.players): if i not in player_filter: continue if use_cards: c = self._compute_cards_points(p['cards']) pt = p['points'] + c ref_logger.info('player %s got %s points (%s from cards)', i + 1, pt, c) else: pt = p['points'] ref_logger.info('at tie-breaker player %s got %s points', i + 1, pt) if pt > maxpoints: maxpoints = pt top_players = [i] elif pt == maxpoints: top_players.append(i) if len(top_players) == 1: return top_players[ 0] + 1 # winning player count goes from 1: 0 is "no winner" if not use_cards: ref_logger.error( 'players %s are tied with and witout cards, returing draw', [pi + 1 for pi in top_players]) return DRAW return self._compute_winner(use_cards=False)
def _check_deaths(self): ''' set players status to DEAD if it is time ''' g_reds = 0 n_ind = COMMON_TRACKS_NAMES.index(NOISE_TRACK_NAME) s_ind = PLAYER_TRACKS_NAMES.index(SOCIAL_TRACK_NAME) c_ind = COMMON_TRACKS_NAMES.index(CASH_TRACK_NAME) if COMMON_TRACKS_EFFECT[n_ind][2].get(self.common_tracks[n_ind], (None, ))[0] == RED: g_reds += 1 ref_logger.debug('a red for everyone, noise is high') for i, p in enumerate(self.players): if p['status'] == DEAD: continue p_reds = sum(1 for v, (_, _, e) in zip(p['tracks'], PLAYER_TRACKS_EFFECT) if e.get(v, (None, ))[0] == RED) ref_logger.debug('player %s has %s red dots', i + 1, p_reds) if COMMON_TRACKS_EFFECT[c_ind][2].get(self.common_tracks[c_ind], (None, ))[0] == RED: social_value = p['tracks'][s_ind] for j, p2 in enumerate(self.players): if j != i and p2['status'] == ALIVE and p2['tracks'][ s_ind] < social_value: break else: ref_logger.debug( 'plus the cash one, because it\'s the worst') p_reds += 1 if p_reds >= REDS_TO_DIE: ref_logger.info('player %s dies with %s red dots', i + 1, p_reds) p['status'] = DEAD
def execute_turn(self, moves): ''' each move is two values separed by space. each of them is either an int between 1 and 6, or wc{n} with n in AVAILABLE_WCS ''' wcs = tuple('wc{}'.format(n) for n in AVAILABLE_WCS) cards = [DECK[c] for c in self.cards_on_the_table] dices = [[] for _ in cards] ref_logger.info('received moves %s', moves) for i, (m, p) in enumerate(zip(moves, self.players)): pl = i + 1 if p['status'] == DEAD: ref_logger.debug('player %s is DEAD, ignoring input', pl) expected_values = 2 - len(p['wc_dices']) values = [v for v in m.split(' ') if v] if (l := len(values)) != expected_values: raise InvalidMove('expected {} values, got {}'.format( expected_values, l)) modifiers = [0] * len(PLAYER_TRACKS_NAMES) for v in values: if v in wcs: self._send_to_wc(pl, p, int(v[-1])) elif not v.isdigit(): raise InvalidMove('unexpected value: {}'.format(v)) else: v = int(v) if v < 1 or v > 6: raise InvalidMove( 'numeric value not in range 1-6: {}'.format(v)) dices[v - 1].append(i) c = cards[v - 1] p['points'] += c[2] for ind, val in enumerate(c[3]): modifiers[ind] += val ref_logger.debug( 'player %s puts a dice on card %s, for %s points and modifiers %s', pl, v, c[2], c[3]) for tind, mod in enumerate(modifiers): trackmax = PLAYER_TRACKS_LENGTH[tind] - 1 currval = p['tracks'][tind] p['tracks'][tind] += max(min(mod, trackmax - currval), -currval) ref_logger.debug('player %s modified status: %s', pl, [ti + 1 for ti in p['tracks']])
def _shift_wc(self): ''' scrolls every waiting player in the wc ''' l_ind = PLAYER_TRACKS_NAMES.index(LIQUID_TRACK_NAME) for i, p in enumerate(self.players): to_remove = [] if p['status'] == DEAD: continue for j, d in enumerate(p['wc_dices']): if d[1] == 1: q = min(d[0], p['tracks'][l_ind]) p['tracks'][l_ind] -= q to_remove.append(j) ref_logger.info( 'a dice for player %s reaches wc, %s liquid removed. current liquid: %s', i + 1, q, p['tracks'][l_ind]) else: d[1] -= 1 while to_remove: j = to_remove.pop() p['wc_dices'].pop(j)
def check_mate(self, player_id): ''' returns 2 if player {player_id} made checkmate with last move, 1 if stalemate, 0 if none ''' pp = self.player_pieces other_player = (player_id % 2) + 1 other_king = self.kings[other_player] ref_logger.debug( 'looking available moves of next player to detect mate') available_moves = any(self.available_moves(other_player)) if not available_moves: ref_logger.info( 'no available moves, checking whether is stalemate or checkmate' ) check = self.check_menace(other_king, player_id=player_id, pieces=pp[player_id]) if check: # check ref_logger.info('opposing king %s under check from %s, mate!', other_king, check) return 2 return 1 return 0
def setup(self): ref_logger.info('starting game') return [['WHITE'], ['BLACK']]
def setup(self): ref_logger.info('starting game') p = len(self.players) return [[str(p)] for _ in range(p)]
def setup(self): ref_logger.info('starting game') return [[c] for c in COLORS]
def setup(self): ref_logger.info('starting game; board:\n%s', self.draw_board()) return [[s] for s in SYMBOLS[1:]]