def on_special(): # Get room R.connection_lock.acquire() room_id = get_room_id(rooms, request.sid) # Make sure room and game still exist if room_id and rooms[room_id]['gc']: player = [p for p in rooms[room_id] ['gc'].players if p.socket_id == request.sid][0] else: R.connection_lock.release() return R.connection_lock.release() # Use special R.reveal_lock.acquire() if player.state == C.PlayerState.Revealed and not player.special_active: player.special_active = True # Guard R.reveal_lock.release() msg = "You've activated your special ability." msg += " It will take effect next time its use conditions are met." player.gc.tell_h(msg, [], request.sid) player.character.special(rooms[room_id]['gc'], player, turn_pos='now') rooms[room_id]['gc'].update_h() else: R.reveal_lock.release()
def on_message(json): # Message fields connection_lock.acquire() room_id = get_room_id(rooms, request.sid) if not room_id: connection_lock.release() return json['name'] = rooms[room_id]['connections'][request.sid] # If player is not in game, or spectating, their color is grey if (rooms[room_id]['status'] != 'GAME') or (request.sid not in [ p.socket_id for p in rooms[room_id]['gc'].players ]): json['color'] = constants.TEXT_COLORS['server'] else: json['color'] = [ p.color for p in rooms[room_id]['gc'].players if p.socket_id == request.sid ][0] connection_lock.release() # Broadcast non-empty message if 'data' in json and json['data'].strip(): socketio.emit('message', json, room=room_id)
def on_reveal(): # Get room connection_lock.acquire() room_id = get_room_id(rooms, request.sid) # Make sure room and game still exist if room_id and rooms[room_id]['gc']: player = [ p for p in rooms[room_id]['gc'].players if p.socket_id == request.sid ][0] else: connection_lock.release() return # Reveal them (if they're alive and unrevealed) connection_lock.release() concurrency.reveal_lock.acquire() if player.state == 2: player.state = 1 # Guard concurrency.reveal_lock.release() player.reveal() else: concurrency.reveal_lock.release()
def on_disconnect(): # Get room_id, name, and game context room_id = get_room_id(rooms, request.sid) name = rooms[room_id]['connections'][request.sid] gc = rooms[room_id]['gc'] socket_tell('{} has left the room', [name], gc, room_id) # Remove user from the room connection_lock.acquire() rooms[room_id]['connections'].pop(request.sid) # Close room if it is now empty, or replace player with AI if it's in game if not rooms[room_id]['connections'].keys(): # Close the room if gc and [p for p in gc.players if p.socket_id == request.sid]: [p for p in gc.players if p.socket_id == request.sid][0].ai = True gc.tell_h = lambda x, y, *z: 0 gc.show_h = lambda x, *y: 0 gc.update_h = lambda: 0 socketio.close_room(room_id) rooms.pop(room_id) connection_lock.release() elif gc and not gc.game_over: # If disconnected person was spectating, or dead, or if the game is # over, don't swap them for an AI player_in_game = [p for p in gc.players if p.socket_id == request.sid] if (not player_in_game) or (not player_in_game[0].state): connection_lock.release() return # Swap player for AI player_in_game[0].ai = True # TODO: make actual browser cookie rooms[room_id]['reconnections'][player_in_game[0].user_id] = 'cookie' connection_lock.release() socket_tell('A computer player has taken their place!', [], gc, room_id) else: # Always release lock! connection_lock.release()
def on_answer(json): # Make sure an answer isn't already being processed R.connection_lock.acquire() room_id = get_room_id(rooms, request.sid) # Define some checks (functions, not booleans, to preserve short-circuit) def not_in_game(rid): return rooms[rid]['status'] != 'GAME' def room_bin_answered(rid): rooms[room_id]['gc'].answer_bin['answered'] if not room_id or not_in_game(room_id) or room_bin_answered(room_id): R.connection_lock.release() return bin = rooms[room_id]['gc'].answer_bin # Fill answer bin bin['data'] = json bin['sid'] = request.sid bin['answered'] = True R.connection_lock.release()
def on_reveal(): # Get room R.connection_lock.acquire() room_id = get_room_id(rooms, request.sid) # Make sure room and game still exist if room_id and rooms[room_id]['gc']: player = [p for p in rooms[room_id] ['gc'].players if p.socket_id == request.sid][0] else: R.connection_lock.release() return # Reveal them (if they're alive and unrevealed) R.connection_lock.release() R.reveal_lock.acquire() if player.state == C.PlayerState.Hidden: player.state = C.PlayerState.Revealed # Guard R.reveal_lock.release() player.reveal() else: R.reveal_lock.release()
def on_start(json): # Get room and players in it R.connection_lock.acquire() room_id = get_room_id(rooms, request.sid) if not room_id: R.connection_lock.release() return people_in_room = rooms[room_id]['connections'] names_and_sids = [(people_in_room[x], x) for x in people_in_room.keys()] # Check for false start n_players = max(min(int(json['n_players']), 8), 4) if len(names_and_sids) > n_players: R.connection_lock.release() packet = {'field': n_players, 'actual': len(names_and_sids)} socketio.emit('false_start', packet, room=request.sid) return # Initialize human and AI players rgb = ['rgb(245,245,245)', 'rgb(100,100,100)', 'rgb(79,182,78)', 'rgb(62,99,171)', 'rgb(197,97,163)', 'rgb(219,62,62)', 'rgb(249,234,48)', 'rgb(239,136,43)'] human_players = [Player(n[0], n[1], rgb.pop(0), False) for n in names_and_sids] ai_players = [Player("CPU_{}".format(i), str(i), rgb.pop(0), True) for i in range(1, n_players - len(human_players) + 1)] players = human_players + ai_players # Initialize game context with players and emission functions ef = ElementFactory() gc = GameContext( players=players, characters=ef.CHARACTERS, black_cards=ef.BLACK_DECK, white_cards=ef.WHITE_DECK, hermit_cards=ef.HERMIT_DECK, areas=ef.AREAS, ask_h=lambda x, y, z: socket_ask(x, y, z, room_id), tell_h=None, show_h=None, update_h=None ) gc.tell_h = lambda x, y, *z: socket_tell(x, y, gc, room_id, z) gc.show_h = lambda x, *y: socket_show(x, gc, room_id, y) gc.update_h = lambda: socket_update(gc.dump()[0], room_id) # Assign game to room if rooms[room_id]['status'] == 'GAME': R.connection_lock.release() return rooms[room_id]['gc'] = gc rooms[room_id]['status'] = 'GAME' R.connection_lock.release() # Send public and private game states to frontend gc.tell_h("Loading game...", []) public_state, private_state = gc.dump() for priv in private_state: data = { 'public': public_state, 'private': priv } socketio.emit('game_start', data, room=priv['socket_id']) socketio.sleep(1) gc.tell_h("Started a game with players {}".format( ", ".join(['{}'] * len(players))), [p.user_id for p in players]) # Initiate gameplay loop gc.play()