def end_game(game, game_state): # Finalize the game game.stats = generate_stats_object(game, game_state) game.state = Game.STATE_DONE game.save() # Notify snakes urls = [] for snake in game_state.snakes: urls.append('%s/end' % snake['url']) payload = {'game_id': game_state.game_id} responses = AsyncCall(payload, urls, game.turn_time * 5) # Ignore responses. Suckers. if (len(game_state.snakes + game_state.dead_snakes) > 1): lose_phrase = 'loses' if len(game_state.dead_snakes) == 1 else 'lose' _update_slack( game.id, 'has been decided. %s wins after %d turns! %s %s.' % (game.stats['winner'], game_state.turn, ', '.join( [snake['name'] for snake in game_state.dead_snakes]), lose_phrase)) return
def get_moves(game_state, timeout): urls = [] for snake in game_state.snakes: urls.append('%s/move' % snake['url']) payload = { 'game_id': game_state.game_id, 'turn': game_state.turn, 'board': game_state.board, 'food': game_state.food, 'snakes': game_state.snakes } responses = AsyncCall(payload, urls, timeout).start() moves = [] # For all snakes for snake in game_state.snakes: # Find the response for that snake for url, response in responses.items(): # We matched! Now handle the response if url.startswith(snake['url']): if response is None: # Too bad for that snake. Engine should keep it moving # in current direction moves.append({ 'snake_name': snake['name'], # Don't trust id from response 'move': None, 'taunt': '...zzz...' }) _log('%s timed out' % snake['name']) else: moves.append({ 'snake_name': snake['name'], # Don't trust id from response 'move': response['move'], 'taunt': response.get('taunt', '') }) return moves
def get_moves(game_state, timeout): urls = [] for snake in game_state.snakes: urls.append('%s/move' % snake['url']) payload = { 'game_id': game_state.game_id, 'turn': game_state.turn, 'board': game_state.board, 'food': game_state.food, 'snakes': game_state.snakes } responses = AsyncCall(payload, urls, timeout).start() moves = [] # For all snakes for snake in game_state.snakes: # Find the response for that snake for url, response in responses.items(): # We matched! Now handle the response if url.startswith(snake['url']): if response is None: # Too bad for that snake. Engine should keep it moving # in current direction moves.append({ 'snake_name': snake['name'], # Don't trust id from response 'move': None, 'taunt': '!! SNAKE ERROR !!' }) _log('%s timed out' % snake['name']) else: moves.append({ 'snake_name': snake['name'], # Don't trust id from response 'move': response.get('move', 'no_move'), 'taunt': response.get('taunt', '') }) return moves
def end_game(game, game_state): # Finalize the game game.stats = generate_stats_object(game, game_state) game.state = Game.STATE_DONE game.save() # Notify snakes urls = [] for snake in game_state.snakes: urls.append('%s/end' % snake['url']) payload = {'game_id': game_state.game_id} responses = AsyncCall(payload, urls, game.turn_time * 5) # Ignore responses. Suckers. return
def create_game(snake_urls, width, height, turn_time): game = Game(width=width, height=height, turn_time=turn_time) # Fetch snakes start_urls = [('%s/start' % url) for url in snake_urls] responses = AsyncCall( payload={ 'game_id': game.id, 'width': width, 'height': height }, urls=start_urls, timeout=10 # Enough time for Heroku apps to wake up ).start() # Any errors? for url, response in responses.items(): if not response: raise Exception('%s failed to respond' % url) params = ['name', 'color'] for param in params: if param not in response: raise Exception('%s missing %s' % (url, param)) # Build snakes snakes = [] for snake_url in snake_urls: # Find the response for that snake for url, response in responses.items(): # We matched! Now handle the response if url.startswith(snake_url): if response is None: # FREAK OUT raise Exception('failed to contact snake: %s' % url) snakes.append({ 'url': snake_url, 'color': response['color'], 'head_url': response.get( 'head_url', 'http://www.battlesnake.io/static/img/default_head.gif' ), 'name': response['name'], 'taunt': response['taunt'] }) game.insert() # Create the first GameState game_state = Engine.create_game_state(game.id, game.width, game.height) # Init the first GameState Engine.add_random_snakes_to_board(game_state, snakes) Engine.add_starting_food_to_board(game_state) # Save the first GameState game_state.insert() return (game, game_state)
def create_game(snake_urls, width, height, turn_time): if not snake_urls or len(snake_urls) == 0: raise Exception('No snake urls added. You need at least one...') game = Game(width=width, height=height, turn_time=turn_time) # Fetch snakes start_urls = [('%s/start' % url) for url in snake_urls] responses = AsyncCall( payload={ 'game_id': game.id, 'width': width, 'height': height }, urls=start_urls, timeout=10 # Enough time for Heroku apps to wake up ).start() # Any errors? for url, response in responses.items(): if not response: raise Exception('%s failed to respond' % url) params = ['name', 'color'] for param in params: if param not in response: raise Exception('%s missing %s' % (url, param)) # Build snakes snakes = [] for snake_url in snake_urls: # Find the response for that snake for url, response in responses.items(): # We matched! Now handle the response if url.startswith(snake_url): if response is None: # FREAK OUT raise Exception('failed to contact snake: %s' % url) snake = { 'url': snake_url, 'color': response['color'], 'head_url': response.get('head_url', 'http://www.battlesnake.io/static/img/default_head.gif'), 'name': response['name'], 'taunt': response['taunt'] } if snake in snakes: raise Exception('cannot snake name "%s" more than once' % (snake['name'])) snakes.append(snake) game.insert() # Create the first GameState game_state = Engine.create_game_state(game.id, game.width, game.height) # Init the first GameState Engine.add_random_snakes_to_board(game_state, snakes) Engine.add_starting_food_to_board(game_state) # Save the first GameState game_state.insert() if (len(snakes) > 1): _update_slack(game.id, '%d brave snakes enter the grid: %s' % ( len(snakes), ', '.join([s['name'] for s in snakes])) ) return (game, game_state)