def create_game(self): password = randint(1000, 10000) self.game = GameRoom(self.player, password) self.game_rooms[password] = self.game self.out_msg.send(ProtocolCommand.PASS_CREATED, { 'password': self.game.password })
def __init__(self, nickname): self.master_player = Player(nickname) self.date = None #Создадим объекты внутри мастера, отвечающие за игровые события и историю self.event = game_event.GameEvent() self.history = game_history.History() #Мастер создает игровую комнату ожидания self.wait_room = WaitRoom() #Мастер создает игровую комнату набора игроков в игру self.game_room = GameRoom() #И игровая комната self.play_room = PlayRoom()
async def new_handler(self, request: web.Request, session: Session): if request.method == 'POST': post_data = await request.post() name = post_data.get('name') size = post_data.get('size') player_positions = post_data.get('player-positions') try: size = int(size) positions = json.loads(player_positions) if 2 <= size <= 20 and name.strip() and len(positions) >= 2: room = GameRoom(size, name, positions) else: raise ValueError() except ValueError: error_message = '名称 必须非空,2 <= 尺寸 <= 20,玩家数量 >= 2' else: raise web.HTTPFound(f'/{room.id}/') else: name = '' size = 7 error_message = '' player_positions = '' return self.render('new.html', name=name, size=size, error_message=error_message, session=session, player_positions=player_positions)
def test_new_game_exceptions(self, user_get): def new_room(body): return self.client.fetch( self.get_url('/games?token={}'.format(TOKEN)), method='POST', body=json.dumps(body), ) bad_params = { 'empty post data': {}, 'board_size too large': { 'board_size': 15 }, 'board_size too small': { 'board_size': 1 }, 'board_size type mismatch': { 'board_size': '1' }, 'title too short': { 'title': 't' }, 'title too long': { 'title': 't'.join([str(x) for x in range(0, 101)]) }, 'title duplicated': { 'title': 'duplicated title' }, } for msg, params in bad_params.items(): with self.assertRaises(tornado.httpclient.HTTPError) as ex: yield new_room(params) self.assertEqual(ex.exception.code, 400, msg=msg) server.game_rooms['5'] = GameRoom(author=LOGIN) with self.assertRaises(tornado.httpclient.HTTPError) as ex: yield new_room({'title': 'rooms limit reached'}) self.assertEqual(ex.exception.code, 400)
def handle_init_file(self, fname, isDebug): info = Room.find_all(exchange=self.exchange) for room in info: room.remove() # if os.path.isfile(fname): print len(fname) print os.getcwd() with open(fname) as f: for line in f: if line[0] == '#': continue (roomType, blind, max_stake, min_stake, max_player) = (int(x) for x in line.strip().split(',')) newRoom = Room.new(self.exchange, blind, max_player, max_stake, min_stake, roomType) self.room_list[newRoom.id] = GameRoom(newRoom, 1, self, max_player, blind, min_stake, max_stake) self.info.rooms += 1 print newRoom
def cmd_create_room(self, args): print "creating room" blind = int(args["blind"]) max_stake = int(args["max_stake"]) min_stake = int(args["min_stake"]) max_player = int(args["max_player"]) routing_key = args['source'] roomType = int(args["roomType"]) newRoom = Room.new(self.exchange, blind, max_player, max_stake, min_stake, roomType) self.room_list[newRoom.id] = GameRoom(newRoom, args["user_id"], self, max_player, blind, min_stake, max_stake) print newRoom message = {"room_id": newRoom.id} self.channel.basic_publish(exchange=self.exchange, routing_key=routing_key, body=json.dumps(message)) self.info.rooms += 1
class Master: def __init__(self, nickname): self.master_player = Player(nickname) self.date = None #Создадим объекты внутри мастера, отвечающие за игровые события и историю self.event = game_event.GameEvent() self.history = game_history.History() #Мастер создает игровую комнату ожидания self.wait_room = WaitRoom() #Мастер создает игровую комнату набора игроков в игру self.game_room = GameRoom() #И игровая комната self.play_room = PlayRoom() #Мастер добавляет новопришедших игроков на вечер def add_player_to_wait_room(self, nick_name): player = Player(nick_name) self.wait_room.append_player(player) def delete_player_from_wait_room(self, row): self.wait_room.delete_player(row) ############################################### def register_player_to_game_room(self, nick_name): #Регистрация идет с уже добавленных игроков. Найдем его for wait_player in self.wait_room.players: if wait_player.nick_name == nick_name: self.game_room.append_player(wait_player) def delete_from_game_room(self, row): self.game_room.delete_player(row) def shake_player_at_game_room(self): self.game_room.shake_players() def set_player_playroom(self): #Метод получает всех игроков из настройки игры GameRoom в PlayRoom players = self.game_room.get_players() self.play_room.set_players(players) """Функциональные Методы playroom""" def add_vote(self, nickname): for player in self.play_room.players: if nickname == player.nick_name: self.play_room.players_at_vote.append(player) def return_vote(self, nickname): for player in self.play_room.players: if nickname == self.play_room.players_at_vote: self.play_room.players_at_vote.remove(player) def shoot_player(self, nickname): #Застреливаем игрока (Меняем его статус на "Застрелян") #Ищем игрока for player in self.play_room.players: if player.nick_name == nickname: player.condition = "Застрелян" def vote_player(self, nickname): #Заголосуем игрока (Меняем его статус на "Заголосован") # Ищем игрока for player in self.play_room.players: if player.nick_name == nickname: player.condition = "Заголосован" def lift_player(self, nickname): # Ищем игрока for player in self.play_room.players: if player.nick_name == nickname: player.condition = "Поднят" def back_player(self, nickname): # Ищем игрока for player in self.play_room.players: if player.nick_name == nickname: player.drop_condition()
import asyncio import json import websockets import traceback from game_room import GameRoom from wizard.wizard import Wizard wizard = GameRoom(Wizard) async def serve(websocket, path): name = None try: async for message in websocket: try: data = json.loads(message) if 'action' in data and data['action'] == 'join': name = data['name'] if not name: await wizard.send_error(websocket, 'Name must not be empty!', 'empty_name') else: await wizard.join(name, websocket) elif name: await wizard.on_message(name, message) except json.JSONDecodeError as e: await wizard.send_error(websocket, 'Malformed message! Ignoring.') except Exception as e: await wizard.send_error(websocket, str(e)) traceback.print_exc() finally: if name:
class Connection: def __init__(self, selector, sock, addr, game_rooms): self.game_rooms = game_rooms self.selector = selector self.sock: socket = sock self.addr = addr self.in_msg = IncomingMessage(sock, self) self.out_msg = OutgoingMessage(sock) self.player: Optional[Player] = None self.game: Optional[GameRoom] = None self.cmd_handlers = { ProtocolCommand.SEND_NAME: self.create_player, ProtocolCommand.NEW_ROOM: self.create_game, ProtocolCommand.JOIN_ROOM: lambda: self.out_msg.send(ProtocolCommand.WAIT_PASS), ProtocolCommand.SEND_PASS: self.handle_join_try, ProtocolCommand.START_GAME: self.start_game, ProtocolCommand.TAKE_CARD: self.make_turn, } def process_events(self, mask): if mask & selectors.EVENT_READ: self.read() def read(self): if self.in_msg.is_loaded: self.in_msg = IncomingMessage(self.sock, self) self.in_msg.read() if not self.in_msg.is_loaded: return print(f'cmd: {self.in_msg.cmd}, args: {self.in_msg.body}, from: {self.addr}, {self.player}') self.cmd_handlers[self.in_msg.cmd](**self.in_msg.body) def create_player(self, name): self.player = Player(name, self) return self.player def create_game(self): password = randint(1000, 10000) self.game = GameRoom(self.player, password) self.game_rooms[password] = self.game self.out_msg.send(ProtocolCommand.PASS_CREATED, { 'password': self.game.password }) def handle_join_try(self, password): game: GameRoom = self.game_rooms.get(password, None) if game: game.add_player(self.player) self.game = game self.out_msg.send(ProtocolCommand.ACCEPT_JOIN, { 'participants': list(map(lambda p: p.name, game.players)) }) game.send_to_all_except(self.player, ProtocolCommand.PLAYER_JOINED, { 'player_name': self.player.name }) if len(game.players) == 2: game.admin.send(ProtocolCommand.GAME_CAN_BEGIN) else: self.out_msg.send(ProtocolCommand.REJECT_JOIN) def start_game(self): self._start_round() def _start_round(self): self.game.made_choice_count = 0 self.game.round += 1 for i, p in enumerate(self.game.active_players): p.send(ProtocolCommand.ROUND_STARTED, { 'round': self.game.round, 'points': p.points, 'player_name': p.name }) def make_turn(self, take_card): self.game.made_choice_count += 1 if take_card: self._take_card() self.game.send_to_all_except(self.player, ProtocolCommand.PLAYER_TURNED, { 'player_name': self.player.name }) if self.game.made_choice_count == len(self.game.active_players): self._handle_winners_and_losers() self._start_round() def _take_card(self): card = deck.get_random_card() self.player.points += card.points self.out_msg.send(ProtocolCommand.CARD_TAKEN, { 'suit': card.suit, 'rank': card.rank, 'points': self.player.points }) def _handle_winners_and_losers(self): winner_found = False for i, p in enumerate(self.game.active_players): if p.points == 21: self._player_wins(p) winner_found = True elif p.points > 21: self._player_loses(p) if len(self.game.active_players) == 1: if winner_found: self._player_loses(self.game.active_players[0]) else: self._player_wins(self.game.active_players[0]) if len(self.game.active_players) == 0: self.game.send_to_all(ProtocolCommand.GAME_OVER) def _player_wins(self, player): player.send(ProtocolCommand.YOU_WIN) self.game.send_to_all_except(player, ProtocolCommand.PLAYER_WINS, { 'player_name': player.name, 'points': player.points }) self.game.deactivate_player(player) def _player_loses(self, player): player.send(ProtocolCommand.YOU_LOSE) self.game.send_to_all_except(player, ProtocolCommand.PLAYER_LOSES, { 'player_name': player.name, 'points': player.points }) self.game.deactivate_player(player) def close(self): print("closing connection to", self.addr) if self.game: self.game.remove_player(self.player) self.selector.unregister(self.sock) self.sock.close()
def post(self): """ Create new game room. """ data = json.loads(self.request.body.decode()) if not data: raise tornado.web.HTTPError(http.client.BAD_REQUEST.value) def get_value(name, types, default=None, minimum=None, maximum=None): if name in data: val = data[name] if not isinstance(val, types): raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, 'Wrong type of {}.'.format(name) ) if isinstance(val, (int, float)): if minimum and val < minimum: raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, 'Value of {} is too small.'.format(name) ) if maximum and val > maximum: raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, 'Value of {} is too big.'.format(name) ) if isinstance(val, str): if minimum and len(val) < minimum: raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, '{} is too short.'.format(name) ) if maximum and len(val) > maximum: raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, '{} is too long.'.format(name) ) return val return default none = type(None) board_size = get_value('board_size', int, 5, 3, 10) title = get_value('title', (str, none), None, 5, 100) max_players = get_value('max_players', int, 15, 2, 100) auto_start = get_value('auto_start', (int, none), 5, 1, 60) auto_restart = get_value('auto_restart', (int, none), 5, 1, 60) with_bot = get_value('with_bot', bool, False) allow_multi = get_value('allow_multi', bool, False) author = self.current_user.login if auto_start: auto_start *= 60 if auto_restart: auto_restart *= 60 authors = [room.author for room in game_rooms.values()] if not self.current_user.admin and authors.count(author) >= 5: raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, 'Maximum number of rooms per user reached. ' 'Remove old rooms before creating new ones.' ) titles = [room.title for room in game_rooms.values()] if not self.current_user.admin and title in titles: raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, 'Title already in use. Use unique title.' ) game_room = GameRoom(board_size, title, max_players, auto_start, auto_restart, with_bot, allow_multi, author) yield game_room.put() game_rooms[game_room.room_id] = game_room self.write({'room_id': game_room.room_id})
application = tornado.web.Application( [ (r'/static/(.*)', tornado.web.StaticFileHandler, {'path': 'static'}), (r'/', IndexHandler), (r'/gh-oauth', OAuthHandler), (r'/games', GamesHandler), (r'/games/([0-9a-f]{24})', GameHandler), (r'/games/([0-9a-f]{24})/board', GameBoardHandler), (r'/games/([0-9a-f]{24})/players/?', GamePlayersHandler), (r'/games/([0-9a-f]{24})/players/(\w+)', GamePlayerHandler), (r'/games/([0-9a-f]{24})/results/?', GameResultsHandler), (r'/hall-of-fame', HallOfFameHandler), (r'/hall-of-fame/(\d+)', HallOfFameHandler), ], debug=settings.DEBUG, cookie_secret=settings.COOKIE_SECRET, db=settings.db, ) if __name__ == '__main__': tornado.options.parse_command_line() log.warn('Starting server http://127.0.0.1:8080') application.listen(8080) tornado.ioloop.IOLoop.instance().add_future( GameRoom.get_all(), lambda future: game_rooms.update(future.result()) ) tornado.ioloop.IOLoop.instance().start()
class UserTestCase(GrotTestCase): @unittest.mock.patch('server.GameRoom.collection.remove', return_value=future_wrap(None)) @unittest.mock.patch('server.GameRoom.collection.save', return_value=future_wrap(ID)) @unittest.mock.patch('server.User.collection.find_one', return_value=future_wrap({ '_id': ID, 'login': LOGIN, 'token': TOKEN, })) @tornado.testing.gen_test def test_new_game_room(self, user_get, save_method, remove_method): data = {'title': 'Test game_room', 'token': TOKEN} response = yield self.client.fetch( self.get_url('/games'), method='POST', body=json.dumps(data), ) response = json.loads(response.body.decode()) self.assertDictEqual({'room_id': ID}, response) args, kwargs = save_method.call_args save_data = kwargs['to_save'] self.assertAlmostEqual(save_data.pop('timestamp'), datetime.datetime.now(), delta=datetime.timedelta(seconds=1)) expected = { 'author': LOGIN, 'auto_restart': 300, 'auto_start': 300, 'board_size': 5, 'max_players': 15, 'results': None, 'title': data['title'], 'with_bot': False, 'allow_multi': False, } self.assertDictEqual(expected, save_data) self.assertEqual(len(server.game_rooms), 1) deleted = yield self.client.fetch( self.get_url('/games/{}?token={}'.format(ID, TOKEN)), method='DELETE', ) self.assertEqual(deleted.code, 200) self.assertEqual(len(server.game_rooms), 0) @unittest.mock.patch( 'server.game_rooms', { 1: GameRoom(author=LOGIN, title='duplicated title'), 2: GameRoom(author=LOGIN), 3: GameRoom(author=LOGIN), 4: GameRoom(author=LOGIN) }) @unittest.mock.patch('server.User.collection.find_one', return_value=future_wrap({ '_id': ID, 'login': LOGIN, 'token': TOKEN, })) @tornado.testing.gen_test def test_new_game_exceptions(self, user_get): def new_room(body): return self.client.fetch( self.get_url('/games?token={}'.format(TOKEN)), method='POST', body=json.dumps(body), ) bad_params = { 'empty post data': {}, 'board_size too large': { 'board_size': 15 }, 'board_size too small': { 'board_size': 1 }, 'board_size type mismatch': { 'board_size': '1' }, 'title too short': { 'title': 't' }, 'title too long': { 'title': 't'.join([str(x) for x in range(0, 101)]) }, 'title duplicated': { 'title': 'duplicated title' }, } for msg, params in bad_params.items(): with self.assertRaises(tornado.httpclient.HTTPError) as ex: yield new_room(params) self.assertEqual(ex.exception.code, 400, msg=msg) server.game_rooms['5'] = GameRoom(author=LOGIN) with self.assertRaises(tornado.httpclient.HTTPError) as ex: yield new_room({'title': 'rooms limit reached'}) self.assertEqual(ex.exception.code, 400) @unittest.mock.patch('tornado.locks.Event.is_set', return_value=False) @unittest.mock.patch( 'server.game_rooms', { ID: GameRoom( _id=ID, author=LOGIN, allow_multi=True, max_players=2, ) }) @unittest.mock.patch('server.User.collection.find_one', return_value=future_wrap({ '_id': ID, 'login': LOGIN, 'token': TOKEN, })) @unittest.mock.patch('server.GameRoom.collection.remove', return_value=future_wrap(None)) @tornado.testing.gen_test def test_join_and_play(self, *args): active_players = ['player1', 'player2'] join1, join2 = yield [ self.client.fetch(self.get_url( '/games/{}/board?token={}&alias={}'.format(ID, TOKEN, player)), method='GET') for player in active_players ] self.assertEqual(join1.code, 200) self.assertEqual(join2.code, 200) board = (yield self.client.fetch( self.get_url('/games/{}?token={}'.format(ID, TOKEN)), method='GET', )).body.decode() self.assertTrue("id: '{}{}'".format(ID, 'player1') in board) self.assertTrue("id: '{}{}'".format(ID, 'player2') in board) with self.assertRaises(tornado.httpclient.HTTPError) as ex: # try to join after start yield self.client.fetch( self.get_url('/games/{}/board?token={}'.format(ID, TOKEN)), method='GET', ) self.assertEqual(ex.exception.code, 403) player_board = json.loads(join1.body.decode()) expected_game = { 'score': 0, 'moves': 5, 'moved': None, } for key, value in expected_game.items(): self.assertTrue(key in player_board) self.assertEqual(player_board[key], value) scores = {} while len(active_players) > 0: for player in active_players: move = yield self.client.fetch( self.get_url('/games/{}/board?alias={}&token={}'.format( ID, player, TOKEN)), method='POST', body=json.dumps({ 'x': randrange(1, 5), 'y': randrange(1, 5), }), ) move = json.loads(move.body.decode()) if move['moves'] == 0: active_players.remove(player) scores[player] = move['score'] round_result = yield self.client.fetch(self.get_url( '/games/{}'.format(ID)), method='GET', headers={'Accept': 'html'}) self.assertTrue(round_result.code, 200) round_result_page = round_result.body.decode() for player, score in scores.items(): self.assertTrue( "id: '{}{}'".format(ID, player) in round_result_page) self.assertTrue("score: '{}'".format(score) in round_result_page) deleted = yield self.client.fetch( self.get_url('/games/{}?token={}'.format(ID, TOKEN)), method='DELETE', ) self.assertEqual(deleted.code, 200) self.assertEqual(len(server.game_rooms), 0) @unittest.mock.patch('server.game_rooms', {ID: GameRoom(_id=ID, author=LOGIN)}) @tornado.testing.gen_test def test_games_list(self): result = yield self.client.fetch(self.get_url('/games'), method='GET', headers={'Accept': 'html'}) body_str = result.body.decode() expected = '<a href="/games/{}">'.format(ID) self.assertTrue(expected in body_str) @tornado.testing.gen_test def test_wrong_game(self): with self.assertRaises(tornado.httpclient.HTTPError): response = yield self.client.fetch(self.get_url( '/games/{}'.format(ID)), method='GET') self.assertEqual(response.code, 404) @tornado.testing.gen_test def test_oauth_login(self): index_page = yield self.client.fetch( self.get_url('/'), method='GET', ) index_html = index_page.body.decode().replace('&', '&') root = fromstring(index_html) auth_url = root.findall(".//a")[-1].attrib['href'] expected = "https://github.com/login/oauth/authorize?client_id={}&scope=user:email".format( settings.GH_OAUTH_CLIENT_ID) self.assertEqual(expected, auth_url) @unittest.mock.patch('server.User.collection.save', return_value=future_wrap(ID)) @unittest.mock.patch('server.User.collection.find_one', return_value=future_wrap(None)) @unittest.mock.patch('server.OAuth.get_user_data', return_value=future_wrap( {'login': '******'})) @unittest.mock.patch('server.OAuth.set_access_token', return_value=future_wrap(None)) @unittest.mock.patch('server.OAuth.access_token', return_value='1234567890') @tornado.testing.gen_test def test_oauth_first_login(self, access_token, set_access_token, get_user_data, find_user, save_user): yield self.client.fetch( self.get_url('/gh-oauth?code=test'), method='GET', ) args, kwargs = save_user.call_args self.assertEqual(args[0]['login'], 'Grzegorz Brzeczyszczykiewicz') self.assertRegex( args[0]['token'], r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') self.assertEqual(args[0]['gh_token'], access_token)
game_select_screen.event(event) elif state.in_game_lobby: game_lobby_screen.event(event) # make things happen if not state.logged_in: login_screen.update() elif state.in_game_select: game_select_screen.update() elif state.in_game_lobby: if game_lobby_screen == None: game_lobby_screen = GameRoom(screen, width = WIDTH, height = HEIGHT) game_lobby_screen.update() elif state.in_game: world.run() # Set the screen background screen.fill(GREY) # draw world world.draw() # Limit to 20 frames per second clock.tick( FPS ) # Go ahead and update the screen with what we've drawn. pygame.display.flip()
def exited(self, new_room): GameRoom.exited(self, new_room) # clear message line when exiting if self.world.hud: self.world.hud.post_msg('')
def post(self): """ Create new game room. """ data = json.loads(self.request.body.decode()) if not data: raise tornado.web.HTTPError(http.client.BAD_REQUEST.value) def get_value(name, types, default=None, minimum=None, maximum=None): if name in data: val = data[name] if not isinstance(val, types): raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, 'Wrong type of {}.'.format(name)) if isinstance(val, (int, float)): if minimum and val < minimum: raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, 'Value of {} is too small.'.format(name)) if maximum and val > maximum: raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, 'Value of {} is too big.'.format(name)) if isinstance(val, str): if minimum and len(val) < minimum: raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, '{} is too short.'.format(name)) if maximum and len(val) > maximum: raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, '{} is too long.'.format(name)) return val return default none = type(None) board_size = get_value('board_size', int, 5, 3, 10) title = get_value('title', (str, none), None, 5, 100) max_players = get_value('max_players', int, 15, 2, 100) auto_start = get_value('auto_start', (int, none), 5, 1, 60) auto_restart = get_value('auto_restart', (int, none), 5, 1, 60) with_bot = get_value('with_bot', bool, False) allow_multi = get_value('allow_multi', bool, False) author = self.current_user.login if auto_start: auto_start *= 60 if auto_restart: auto_restart *= 60 authors = [room.author for room in game_rooms.values()] if not self.current_user.admin and authors.count(author) >= 5: raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, 'Maximum number of rooms per user reached. ' 'Remove old rooms before creating new ones.') titles = [room.title for room in game_rooms.values()] if not self.current_user.admin and title in titles: raise tornado.web.HTTPError( http.client.BAD_REQUEST.value, 'Title already in use. Use unique title.') game_room = GameRoom(board_size, title, max_players, auto_start, auto_restart, with_bot, allow_multi, author) yield game_room.put() game_rooms[game_room.room_id] = game_room self.write({'room_id': game_room.room_id})
application = tornado.web.Application( [ (r'/static/(.*)', tornado.web.StaticFileHandler, { 'path': 'static' }), (r'/', IndexHandler), (r'/gh-oauth', OAuthHandler), (r'/games', GamesHandler), (r'/games/([0-9a-f]{24})', GameHandler), (r'/games/([0-9a-f]{24})/board', GameBoardHandler), (r'/games/([0-9a-f]{24})/players/?', GamePlayersHandler), (r'/games/([0-9a-f]{24})/players/(\w+)', GamePlayerHandler), (r'/games/([0-9a-f]{24})/results/?', GameResultsHandler), (r'/hall-of-fame', HallOfFameHandler), (r'/hall-of-fame/(\d+)', HallOfFameHandler), ], debug=settings.DEBUG, cookie_secret=settings.COOKIE_SECRET, db=settings.db, ) if __name__ == '__main__': tornado.options.parse_command_line() log.warn('Starting server http://127.0.0.1:8080') application.listen(8080) tornado.ioloop.IOLoop.instance().add_future( GameRoom.get_all(), lambda future: game_rooms.update(future.result())) tornado.ioloop.IOLoop.instance().start()