async def main_loop(queue): """Processes events from server and display's.""" global SPRITES, SCREEN main_group = pygame.sprite.LayeredUpdates() boxes_group = pygame.sprite.OrderedUpdates() logging.info("Waiting for map information from server") state = await queue.get() # first state message includes map information logging.debug("Initial game status: %s", state) newgame_json = json.loads(state) GAME_SPEED = newgame_json["fps"] try: mapa = Map(newgame_json["map"]) except (KeyError, FileNotFoundError): mapa = Map("levels/1.xsb") # Fallback to initial map SCREEN = pygame.display.set_mode(scale(mapa.size)) SPRITES = pygame.image.load("data/sokoban.png").convert_alpha() BACKGROUND = draw_background(mapa) SCREEN.blit(BACKGROUND, (0, 0)) main_group.add(Keeper(pos=mapa.keeper)) state = { "score": 0, "player": "player1", "keeper": mapa.keeper, "boxes": mapa.boxes, } new_event = True while True: SCREEN.blit(BACKGROUND, (0, 0)) pygame.event.pump() if pygame.key.get_pressed()[pygame.K_ESCAPE]: asyncio.get_event_loop().stop() main_group.clear(SCREEN, clear_callback) boxes_group.clear(SCREEN, clear_callback) if "score" in state and "player" in state: text = f"m, p, s: {state['score']}" draw_info(SCREEN, text.zfill(6), (5, 1)) text = str(state["player"]).rjust(32) draw_info(SCREEN, text, (4000, 1)) if "level" in state: w, _ = draw_info(SCREEN, "level: ", (SCREEN.get_width() / 2, 1)) draw_info( SCREEN, f"{state['level']}", (SCREEN.get_width() / 2 + w, 1), color=(200, 20, 20), ) if "boxes" in state: boxes_group.empty() for box in state["boxes"]: boxes_group.add( Box( pos=box, stored=mapa.get_tile(box) in [Tiles.GOAL, Tiles.BOX_ON_GOAL], )) boxes_group.draw(SCREEN) main_group.draw(SCREEN) # Highscores Board if "highscores" in state and "player" in state: if new_event: highscores = state["highscores"] highscores.append( (f"<{state['player']}>", reduce_score(state["score"]))) highscores = sorted(highscores, key=lambda s: s[1]) highscores = highscores[:len(RANKS)] HIGHSCORES = pygame.Surface((256, 280)) HIGHSCORES.fill((30, 30, 30)) COLS = [20, 80, 150] draw_info(HIGHSCORES, "THE 10 BEST PLAYERS", (20, 10), COLORS["white"]) for value, column in zip(["RANK", "SCORE", "NAME"], COLS): draw_info(HIGHSCORES, value, (column, 30), COLORS["orange"]) for i, highscore in enumerate(highscores): color = ( random.randrange(66, 222), random.randrange(66, 222), random.randrange(66, 222), ) for value, column in zip( [RANKS[i + 1], str(highscore[1]), highscore[0]], COLS): draw_info(HIGHSCORES, value, (column, 60 + i * 20), color) SCREEN.blit( HIGHSCORES, ( (SCREEN.get_width() - HIGHSCORES.get_width()) / 2, (SCREEN.get_height() - HIGHSCORES.get_height()) / 2, ), ) if "keeper" in state: main_group.update(state["keeper"]) pygame.display.flip() try: state = json.loads(queue.get_nowait()) new_event = True if "map" in state: logger.debug("New Level!") # New level! lets clean everything up! try: mapa = Map(state["map"]) except FileNotFoundError: logger.error( "Can't find levels/%s.xsb, means we have a WINNER!", state["level"], ) continue SCREEN = pygame.display.set_mode(scale(mapa.size)) BACKGROUND = draw_background(mapa) SCREEN.blit(BACKGROUND, (0, 0)) boxes_group.empty() main_group.empty() main_group.add(Keeper(pos=mapa.keeper)) pygame.display.flip() except asyncio.queues.QueueEmpty: await asyncio.sleep(1.0 / GAME_SPEED) new_event = False continue
class Game: """Representation of a Game run.""" def __init__(self, level=1, timeout=TIMEOUT, player=None): logger.info("Game(level=%s)", level) self.puzzles = 0 #puzzles completed self.level = level if player: self._running = True self._player_name = player else: self._running = False self._timeout = timeout self._step = 0 self._total_steps = 0 self._state = {} self._papertrail = "" # keeps track of all steps made by the player self._moves = 0 self._pushes = 0 self.map = None self._lastkeypress = "" self.next_level(self.level) def info(self): """Initial Static information about the game.""" return { "fps": GAME_SPEED, "timeout": self._timeout, "map": f"levels/{self.level}.xsb", } @property def papertrail(self): """String containing all pressed keys by agent.""" return self._papertrail @property def running(self): """Status on game.""" return self._running @property def score(self): """Calculus of the current score.""" return self.puzzles, self._moves, self._pushes, self._total_steps + self._step, self.map.on_goal def stop(self): """Stop the game.""" if self._step: logger.info("GAME OVER at %s", self._step) self._running = False def next_level(self, level): """Update all state variables to a new level.""" self.puzzles += 1 self._total_steps += self._step self._step = 0 self._lastkeypress = "" self._papertrail += "," self.level = level try: self.map = Map(f"levels/{level}.xsb") logger.info("NEXT LEVEL: %s", level) except FileNotFoundError: logger.info("No more levels... You WIN!") self.stop() return def keypress(self, key): """Update locally last key pressed.""" self._lastkeypress = key def move(self, cur, direction): """Move an entity in the game.""" assert direction in "wasd", f"Can't move in {direction} direction" cx, cy = cur ctile = self.map.get_tile(cur) npos = cur if direction == "w": npos = cx, cy - 1 if direction == "a": npos = cx - 1, cy if direction == "s": npos = cx, cy + 1 if direction == "d": npos = cx + 1, cy # test blocked if self.map.is_blocked(npos): logger.debug("Blocked ahead") return False if self.map.get_tile(npos) in [ Tiles.BOX, Tiles.BOX_ON_GOAL, ]: # next position has a box? if ctile & Tiles.MAN == Tiles.MAN: # if you are the keeper you can push if not self.move(npos, direction): # as long as the pushed box can move return False else: # you are not the Keeper, so no pushing return False self._moves += 1 # actually update map self.map.set_tile(npos, ctile) self.map.clear_tile(cur) return True def update_keeper(self): """Update the location of the Keeper.""" if self._lastkeypress == "": return GameStatus.NO_OPERATION try: # Update position self.move(self.map.keeper, self._lastkeypress) self._papertrail += self._lastkeypress except AssertionError: logger.error( "Invalid key <%s> pressed. Valid keys: w,a,s,d", self._lastkeypress ) finally: self._lastkeypress = "" # remove inertia if self.map.completed: logger.info("Level %s completed", self.level) self.next_level(self.level + 1) return GameStatus.NEW_MAP return GameStatus.RUNNING async def next_frame(self): """Calculate next frame.""" await asyncio.sleep(1.0 / GAME_SPEED) if not self._running: logger.info("Waiting for player 1") return self._step += 1 if self._step >= self._timeout: self.stop() if self._step % 100 == 0: logger.debug("[%s] SCORE %s", self._step, self.score) game_status = self.update_keeper() self._state = { "player": self._player_name, "level": self.level, "step": self._step, "score": self.score, "keeper": self.map.keeper, "boxes": self.map.boxes, } return game_status @property def state(self): """Contains the state of the Game.""" # logger.debug(self._state) return json.dumps(self._state)
class SokobanDomain(SearchDomain): def __init__(self, filename): self.level = filename self.map = Map(filename) self.states = [] self.emptyMap() def fillMap(self, state): for box in state["boxes"]: self.map.set_tile(box, Tiles.BOX) self.map.set_tile(state["player"], Tiles.MAN) def emptyMap(self): self.map.clear_tile(self.map.keeper) boxs = self.map.boxes for box in boxs: self.map.clear_tile(box) def actions(self, state): self.fillMap(state) actions = [] for direction in ["w", "a", "s", "d"]: if (self.can_move(self.map.keeper, direction)): actions += [direction] self.emptyMap() return actions def can_move(self, cur, direction): """Move an entity in the game.""" assert direction in "wasd", f"Can't move in {direction} direction" cx, cy = cur ctile = self.map.get_tile(cur) npos = cur if direction == "w": npos = cx, cy - 1 if direction == "a": npos = cx - 1, cy if direction == "s": npos = cx, cy + 1 if direction == "d": npos = cx + 1, cy # test blocked if self.map.is_blocked(npos): return False if self.map.get_tile(npos) in [ Tiles.BOX, Tiles.BOX_ON_GOAL, ]: # next position has a box? if ctile & Tiles.MAN == Tiles.MAN: # if you are the keeper you can push if not self.move( npos, direction): # as long as the pushed box can move return False else: # you are not the Keeper, so no pushing return False return True def move(self, cur, direction): """Move an entity in the game.""" assert direction in "wasd", f"Can't move in {direction} direction" cx, cy = cur ctile = self.map.get_tile(cur) npos = cur if direction == "w": npos = cx, cy - 1 if direction == "a": npos = cx - 1, cy if direction == "s": npos = cx, cy + 1 if direction == "d": npos = cx + 1, cy # test blocked if self.map.is_blocked(npos): return False if self.map.get_tile(npos) in [ Tiles.BOX, Tiles.BOX_ON_GOAL, ]: # next position has a box? if ctile & Tiles.MAN == Tiles.MAN: # if you are the keeper you can push if not self.move( npos, direction): # as long as the pushed box can move return False else: # you are not the Keeper, so no pushing return False # actually update map self.map.set_tile(npos, ctile) self.map.clear_tile(cur) return True def result(self, state, action): self.fillMap(state) self.move(self.map.keeper, action) newstate = {} newstate["player"] = self.map.keeper newstate["boxes"] = self.map.boxes self.emptyMap() return newstate def cost(self, state, action): return 1 def heuristic(self, state, goal): sum = 0 list1 = state["boxes"] list2 = goal["boxes"] for i in range(len(list1)): sum += minimal_distance(list1[i], list2[i]) return sum def satisfies(self, state, goal): self.fillMap(state) return self.map.completed def satisfies_box(self, box, goal): boxes = goal["boxes"] if box in boxes: return True return False
async def main_loop(queue): """Processes events from server and display's.""" global SPRITES, SCREEN main_group = pygame.sprite.LayeredUpdates() boxes_group = pygame.sprite.OrderedUpdates() logging.info("Waiting for map information from server") state = await queue.get() # first state message includes map information logging.debug("Initial game status: %s", state) newgame_json = json.loads(state) GAME_SPEED = newgame_json["fps"] try: mapa = Map(newgame_json["map"]) except (KeyError, FileNotFoundError): mapa = Map("levels/1.xsb") # Fallback to initial map map_x, map_y = mapa.size SCREEN = pygame.display.set_mode(scale((map_x+MAP_X_INCREASE, map_y+MAP_Y_INCREASE))) SPRITES = pygame.image.load("data/sokoban.png").convert_alpha() BACKGROUND = draw_background(mapa) SCREEN.blit(BACKGROUND, (0, 0)) main_group.add(Keeper(pos=mapa.keeper)) state = { "score": 0, "player": "player1", "keeper": mapa.keeper, "boxes": mapa.boxes, } new_event = True player = last_player = state['player'] hs = HighScoresFetch(name=state['player']) best_entry = None while True: if "player" in state: curr_player = state['player'] SCREEN.blit(BACKGROUND, (0, 0)) pygame.event.pump() if pygame.key.get_pressed()[pygame.K_ESCAPE]: asyncio.get_event_loop().stop() main_group.clear(SCREEN, clear_callback) boxes_group.clear(SCREEN, clear_callback) # size of each square map_square_size = (SCREEN.get_width()/(map_x+MAP_X_INCREASE), SCREEN.get_height()/(map_y+MAP_Y_INCREASE)) # width of extra space added to the map, except the separating black wall extra_available_space_width = map_square_size[0]*(MAP_X_INCREASE-1) if "score" in state and "player" in state: if last_player != curr_player: hs = HighScoresFetch(name=state['player']) if hs.data != []: best_entry = hs.get_best_entry(type="max", key="score") split_timestamp = best_entry["timestamp"].split("T") # adjust best_entry dict best_entry["timestamp"] = split_timestamp[0] best_entry["timestamp2"] = split_timestamp[1] formated_col_l, formated_col_r = [SCORE_INFO[d] for d in DATA_INDEX_BEST_ROUND], [str(best_entry[info]) for info in DATA_INDEX_BEST_ROUND] fixed_width = get_largest_width_for_table(formated_col_l, formated_col_r, BEST_ROUND_TITLE)+RIGHT_INFO_MARGIN_RIGHT player = state['player'] last_player = curr_player # draw player info player_h_from_top = SCREEN.get_height() - RIGHT_INFO_MARGIN_BOTTOM player_w, _ = get_draw_size(player) draw_info(SCREEN, player, (SCREEN.get_width()-player_w-RIGHT_INFO_MARGIN_RIGHT, player_h_from_top), COLORS["light_blue"]) draw_info(SCREEN, "Player: ", (SCREEN.get_width()-player_w-get_draw_size("Player: ")[0]-RIGHT_INFO_MARGIN_RIGHT-5, player_h_from_top), COLORS["white"]) current_height = RIGHT_INFO_MARGIN_TOP if hs != None and hs.data != []: # table for best round current_height = draw_table_right_top(SCREEN, extra_available_space_width, (formated_col_l, COLORS["black"]), (formated_col_r, COLORS["white"]), (BEST_ROUND_TITLE, COLORS["yellow"]), fixed_width, (RIGHT_INFO_MARGIN_LEFT, current_height, RIGHT_INFO_MARGIN_RIGHT)) # some conditions to coop with state['score'] if not isinstance(state['score'], int) and len(state['score']) > len(DATA_INDEX_CURR_ROUND): curr_round_data_fetch = [str(state['score'][i+1]) for i in range(len(DATA_INDEX_CURR_ROUND))] # if there is no data from best round, adapt the fixed size to the data of current round if hs.data == []: fixed_width = get_largest_width_for_table(curr_round_data_fetch, DATA_INDEX_CURR_ROUND, CURR_ROUND_TITLE)+RIGHT_INFO_MARGIN_RIGHT else: # if there is best round table, then create a separation with the current round table current_height+= RIGHT_INFO_MARGIN_TOP # table for current round current_height = draw_table_right_top(SCREEN, extra_available_space_width, (DATA_INDEX_CURR_ROUND, COLORS["black"]), (curr_round_data_fetch, COLORS["white"]), (CURR_ROUND_TITLE, COLORS["red"]), fixed_width, (RIGHT_INFO_MARGIN_LEFT, current_height, RIGHT_INFO_MARGIN_RIGHT)) if "level" in state: draw_info( SCREEN, f"{state['level']}", (SCREEN.get_width()-extra_available_space_width+RIGHT_INFO_MARGIN_LEFT, current_height+RIGHT_INFO_MARGIN_TOP), color=COLORS["white"], size=50 ) if "level" not in state and "highscores" not in state: for i, word in enumerate(["Run a client ", "to see scores!"]): word_w, word_h = get_draw_size(word) draw_info(SCREEN, word, (SCREEN.get_width()-center_text_margin(extra_available_space_width, word_w), RIGHT_INFO_MARGIN_TOP+word_h+i*20), COLORS["white"]) if "boxes" in state: boxes_group.empty() for box in state["boxes"]: boxes_group.add( Box( pos=box, stored=mapa.get_tile(box) in [Tiles.GOAL, Tiles.BOX_ON_GOAL], ) ) boxes_group.draw(SCREEN) main_group.draw(SCREEN) # Highscores Board if "highscores" in state and "player" in state: if new_event: highscores = state["highscores"] highscores.append( (f"<{state['player']}>", reduce_score(*state["score"])) ) highscores = sorted(highscores, key=lambda s: s[1]) highscores = highscores[: len(RANKS)] HIGHSCORES = pygame.Surface((256, 280)) HIGHSCORES.fill((30, 30, 30)) COLS = [20, 80, 150] draw_info(HIGHSCORES, "THE 10 BEST PLAYERS", (20, 10), COLORS["white"]) for value, column in zip(["RANK", "SCORE", "NAME"], COLS): draw_info(HIGHSCORES, value, (column, 30), COLORS["orange"]) for i, highscore in enumerate(highscores): color = ( random.randrange(66, 222), random.randrange(66, 222), random.randrange(66, 222), ) for value, column in zip( [RANKS[i + 1], str(highscore[1]), highscore[0]], COLS ): draw_info(HIGHSCORES, value, (column, 60 + i * 20), color) SCREEN.blit( HIGHSCORES, ( (SCREEN.get_width() - HIGHSCORES.get_width()) / 2, (SCREEN.get_height() - HIGHSCORES.get_height()) / 2, ), ) if "keeper" in state: main_group.update(state["keeper"]) pygame.display.flip() try: state = json.loads(queue.get_nowait()) new_event = True if "map" in state: logger.debug("New Level!") # New level! lets clean everything up! try: mapa = Map(state["map"]) except FileNotFoundError: logger.error( "Can't find levels/%s.xsb, means we have a WINNER!", state["level"], ) continue map_x, map_y = mapa.size SCREEN = pygame.display.set_mode(scale((map_x+MAP_X_INCREASE, map_y+MAP_Y_INCREASE))) BACKGROUND = draw_background(mapa) SCREEN.blit(BACKGROUND, (0, 0)) boxes_group.empty() main_group.empty() main_group.add(Keeper(pos=mapa.keeper)) pygame.display.flip() except asyncio.queues.QueueEmpty: await asyncio.sleep(1.0 / GAME_SPEED) new_event = False continue
async def main_loop(queue): """Processes events from server and display's.""" global SPRITES, SCREEN main_group = pygame.sprite.LayeredUpdates() boxes_group = pygame.sprite.OrderedUpdates() logging.info("Waiting for map information from server") state = await queue.get() # first state message includes map information logging.debug("Initial game status: %s", state) newgame_json = json.loads(state) GAME_SPEED = newgame_json["fps"] try: mapa = Map(newgame_json["map"]) except (KeyError, FileNotFoundError): mapa = Map("levels/1.xsb") # Fallback to initial map map_x, map_y = mapa.size SCREEN = pygame.display.set_mode( scale((map_x + MAP_X_INCREASE, map_y + MAP_Y_INCREASE))) SPRITES = pygame.image.load("data/sokoban.png").convert_alpha() BACKGROUND = draw_background(mapa) SCREEN.blit(BACKGROUND, (0, 0)) main_group.add(Keeper(pos=mapa.keeper)) state = { "score": 0, "player": "player1", "keeper": mapa.keeper, "boxes": mapa.boxes, } new_event = True margin_top = 30 margin_right = 30 space_between_cols = 5 last_player = state['player'] data_index = [ "level", "timestamp", "", "score", "total_moves", "total_pushes", "total_steps" ] hs = "" best_entry = "" while True: if "player" in state: curr_player = state['player'] SCREEN.blit(BACKGROUND, (0, 0)) pygame.event.pump() if pygame.key.get_pressed()[pygame.K_ESCAPE]: asyncio.get_event_loop().stop() main_group.clear(SCREEN, clear_callback) boxes_group.clear(SCREEN, clear_callback) if "score" in state and "player" in state: if last_player != curr_player: print("here") hs = HighScoresFetch(name=state['player']) last_player = curr_player best_entry = hs.get_best_entry(type="max", key="score") player = state['player'] player_h = SCREEN.get_height() - 40 player_w, _ = draw_info(SCREEN, player, (-4000, player_h)) draw_info(SCREEN, player, (SCREEN.get_width() - player_w - margin_right, player_h), (58, 240, 240)) player_title_w, _ = draw_info(SCREEN, "Player: ", (-4000, player_h)) draw_info(SCREEN, "Player: ", (SCREEN.get_width() - player_w - player_title_w - margin_right - space_between_cols, player_h), (255, 255, 255)) if hs != "" and hs.data != []: bestround_pos = margin_top bestround_w, _ = draw_info(SCREEN, "Best Round", (-4000, bestround_pos)) draw_info(SCREEN, "Best Round", (SCREEN.get_width() - bestround_w - margin_right - 22, bestround_pos), (255, 242, 0)) info_pos = bestround_pos + 35 splitted = best_entry['timestamp'].split("T") info_w, _ = draw_info(SCREEN, splitted[0], (-4000, 0)) title_info_w, _ = draw_info(SCREEN, "Data: ", (-4000, 0)) title_fixed_size = info_w + title_info_w + margin_right + space_between_cols for i, info in enumerate(data_index): curr_data_index = data_index[i] if curr_data_index == "": continue else: content = best_entry[info] if curr_data_index == "timestamp": splitted = content.split("T") info_w, _ = draw_info(SCREEN, splitted[0], (-4000, info_pos + i * 20)) draw_info(SCREEN, splitted[0], (SCREEN.get_width() - info_w - margin_right, info_pos + i * 20), (255, 255, 255)) title_info_w, _ = draw_info(SCREEN, "Data: ", (-4000, info_pos + i * 20)) draw_info(SCREEN, "Data: ", (SCREEN.get_width() - title_fixed_size, info_pos + i * 20)) info_w, _ = draw_info(SCREEN, splitted[1], (-4000, info_pos + i * 20)) draw_info(SCREEN, splitted[1], (SCREEN.get_width() - info_w - margin_right, info_pos + (i + 1) * 20), (255, 255, 255)) continue if curr_data_index == "total_moves": curr_data_index = "moves" if curr_data_index == "total_pushes": curr_data_index = "pushes" if curr_data_index == "total_steps": curr_data_index = "steps" info_w, _ = draw_info(SCREEN, str(content), (-4000, info_pos + i * 20)) draw_info(SCREEN, str(content), (SCREEN.get_width() - info_w - margin_right, info_pos + i * 20), (255, 255, 255)) title_info_w, _ = draw_info( SCREEN, format_string(curr_data_index) + ": ", (-4000, info_pos + i * 20)) draw_info(SCREEN, format_string(curr_data_index) + ": ", (SCREEN.get_width() - title_fixed_size, info_pos + i * 20)) curr_round_pos = 230 curr_round_w, _ = draw_info(SCREEN, "Current Round", (-4000, curr_round_pos)) draw_info(SCREEN, "Current Round", (SCREEN.get_width() - curr_round_w - margin_right - 10, curr_round_pos), (255, 0, 0)) info_pos = curr_round_pos + 35 for i, curr_info in enumerate(["Moves", "Pushes", "Steps"]): info_w, _ = draw_info(SCREEN, str(state['score'][i + 1]), (-4000, info_pos + i * 20)) draw_info(SCREEN, str(state['score'][i + 1]), (SCREEN.get_width() - info_w - margin_right, info_pos + i * 20), (255, 255, 255)) title_info_w, _ = draw_info(SCREEN, curr_info + ": ", (-4000, info_pos + i * 20)) draw_info(SCREEN, curr_info + ": ", (SCREEN.get_width() - title_fixed_size, info_pos + i * 20)) if "level" in state: draw_info(SCREEN, f"{state['level']}", (SCREEN.get_width() - 162, 335), color=(255, 255, 255), size=50) if "boxes" in state: boxes_group.empty() for box in state["boxes"]: boxes_group.add( Box( pos=box, stored=mapa.get_tile(box) in [Tiles.GOAL, Tiles.BOX_ON_GOAL], )) boxes_group.draw(SCREEN) main_group.draw(SCREEN) # Highscores Board if "highscores" in state and "player" in state: if new_event: highscores = state["highscores"] highscores.append( (f"<{state['player']}>", reduce_score(*state["score"]))) highscores = sorted(highscores, key=lambda s: s[1]) highscores = highscores[:len(RANKS)] HIGHSCORES = pygame.Surface((256, 280)) HIGHSCORES.fill((30, 30, 30)) COLS = [20, 80, 150] draw_info(HIGHSCORES, "THE 10 BEST PLAYERS", (20, 10), COLORS["white"]) for value, column in zip(["RANK", "SCORE", "NAME"], COLS): draw_info(HIGHSCORES, value, (column, 30), COLORS["orange"]) for i, highscore in enumerate(highscores): color = ( random.randrange(66, 222), random.randrange(66, 222), random.randrange(66, 222), ) for value, column in zip( [RANKS[i + 1], str(highscore[1]), highscore[0]], COLS): draw_info(HIGHSCORES, value, (column, 60 + i * 20), color) SCREEN.blit( HIGHSCORES, ( (SCREEN.get_width() - HIGHSCORES.get_width()) / 2, (SCREEN.get_height() - HIGHSCORES.get_height()) / 2, ), ) if "keeper" in state: main_group.update(state["keeper"]) pygame.display.flip() try: state = json.loads(queue.get_nowait()) new_event = True if "map" in state: logger.debug("New Level!") # New level! lets clean everything up! try: mapa = Map(state["map"]) except FileNotFoundError: logger.error( "Can't find levels/%s.xsb, means we have a WINNER!", state["level"], ) continue map_x, map_y = mapa.size SCREEN = pygame.display.set_mode( scale((map_x + MAP_X_INCREASE, map_y + MAP_Y_INCREASE))) BACKGROUND = draw_background(mapa) SCREEN.blit(BACKGROUND, (0, 0)) boxes_group.empty() main_group.empty() main_group.add(Keeper(pos=mapa.keeper)) pygame.display.flip() except asyncio.queues.QueueEmpty: await asyncio.sleep(1.0 / GAME_SPEED) new_event = False continue