Esempio n. 1
0
    def save_highscores(self, score):
        """Update highscores, storing to file."""
        logger.debug("Save highscores")
        logger.info(
            "FINAL SCORE <%s>: %s moves and %s pushes in %s steps",
            "FINAL SCORE <%s>: %s puzzles with %s moves and %s pushes in %s steps, currently %s boxes on goal",
            self.current_player.name,
            *score,
        )

        self._highscores.append((
            self.current_player.name,
            reduce_score(score),
        ))
        self._highscores.append((
            self.current_player.name,
            reduce_score(*score),
        ))
        self._highscores = sorted(self._highscores,
                                  key=lambda s: s[1])[:MAX_HIGHSCORES]

        with open(HIGHSCORE_FILE, "w") as outfile:
            json.dump(self._highscores, outfile)
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
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