Esempio n. 1
0
 def __init__(self):
     pygame.display.set_caption("SNAKE by Qelery")
     pygame.mouse.set_visible(False)
     self.window_dimensions = DEFAULT_WINDOW_DIMENSIONS
     self.screen = pygame.display.set_mode(self.window_dimensions)
     self.start_menu = StartMenu(self.window_dimensions, self.screen)
     self.clock_speed = 0
     self.stats_banner = None
     self.grid = None
     self.color_palettes = (
         GREEN_PALETTE,
         RED_PALETTE,
         BLUE_PALETTE,
         BROWN_PALETTE,
         PURPLE_PALETTE,
     )
Esempio n. 2
0
def main():
    """
    The main launch function.
    """
    window = Window(GAME_NAME, WINDOW_SIZE, fullscreen=FULLSCREEN)
    window.handler = StartMenu(window)

    window.show()
Esempio n. 3
0
	def __init__(self):
		ShowBase.__init__(self)

		#PStatClient.connect()

		#self.lookPoint = NodePath(PandaNode("floater"))
		self.lookPoint = self.loader.loadModel("models/cone")
		self.lookPoint.reparentTo(render)

		self.menu = StartMenu(self)
Esempio n. 4
0
class TestStartMenu(unittest.TestCase):
    def setUp(self):
        self.start_menu = StartMenu('Tasapeli')

    def test_constructor(self):
        self.assertEqual(self.start_menu.num_squares, 0)
        self.assertEqual(self.start_menu.player1, '')
        self.assertEqual(self.start_menu.player2, '')
        self.assertEqual(self.start_menu.name_max_size, 10)
        self.assertEqual(self.start_menu.window_width, 600)
        self.assertEqual(self.start_menu.window_height, 450)
        self.assertEqual(self.start_menu.previous_result, 'Tasapeli')

    def test_set_num_squares_is_working(self):
        slider = Scale(self.start_menu.root,
                       from_=5,
                       to=30,
                       orient=HORIZONTAL,
                       sliderlength=200,
                       length=500,
                       width=30)
        slider.pack()
        player1_name = Entry(width=30)
        player1_name.pack()
        player2_name = Entry(width=30)
        player2_name.pack()
        self.start_menu.player1 = 'Testi'
        self.start_menu.player2 = 'Testi2'
        self.start_menu.set_num_squares(slider, player1_name, player2_name)
        self.assertTrue(self.start_menu.num_squares == 5)
        self.assertEqual(self.start_menu.player1, '')
        self.assertEqual(self.start_menu.player2, '')

    def test_set_window(self):
        self.start_menu.set_window()
        self.assertEqual(self.start_menu.root.title(),
                         'Aloita uusi ristinolla-peli')

    def test_set_players(self):
        player1, player2 = self.start_menu.set_players()
        self.assertEqual(player1.get(), '')
        self.assertEqual(player2.get(), '')
Esempio n. 5
0
    def start_game(self):
        """Call Tkinter Class where the user sets the names of the players and number of squares.
        If one of player names are incorrect, starts again with error message.
        Else calls set_game function
        """

        self.start_menu = StartMenu(self.result_text)

        num_squares, player1, player2 = self.get_game_variables()

        self.tictactoeboard = TicTacToeBoard(num_squares, player1, player2)

        if self.tictactoeboard.num_squares == 0:
            return

        if self.players_name_ok(self.start_menu.name_max_size) is False:
            self.result_text = 'Virheellinen pelaajan nimi'
            self.start_game()
        else:
            self.set_game()
Esempio n. 6
0
    def build(self):

        self.screen_manager = ScreenManager()

        self.start_menu = StartMenu(events_callback=self.events_program)

        self.type_menu = GameTypeMenu(events_callback=self.events_program)

        self.screen_manager.add_widget(self.start_menu)
        self.screen_manager.add_widget(self.type_menu)
        self.init_game()

        #game type variables
        self.isTwoPlayers = False
        self.isFirstArranged = False
        self.message_data = None

        return self.screen_manager
Esempio n. 7
0
class Game:
    """"
    Snake game.

    Move the snake to collect apples, score points, and level up. 10 levels total.

    ...

    Attributes
    ----------
    window_dimensions : tuple of int
        dimension in pixels of the game window
    screen : pygame.Surface
        the surface on which all of the game's sprites are displayed
    start_menu : StartMenu
        the game's start menu
    clock_speed : int
        the game's frame rate
    stats_banner : StatsBanner
        displays the points and current level
    grid : Grid
        the board on which the game is played
    color_palettes : tuple of tuple
        tuples of rgb color values

    Methods
    -------
    play()
        the main loop of the game

    """

    def __init__(self):
        pygame.display.set_caption("SNAKE by Qelery")
        pygame.mouse.set_visible(False)
        self.window_dimensions = DEFAULT_WINDOW_DIMENSIONS
        self.screen = pygame.display.set_mode(self.window_dimensions)
        self.start_menu = StartMenu(self.window_dimensions, self.screen)
        self.clock_speed = 0
        self.stats_banner = None
        self.grid = None
        self.color_palettes = (
            GREEN_PALETTE,
            RED_PALETTE,
            BLUE_PALETTE,
            BROWN_PALETTE,
            PURPLE_PALETTE,
        )

    def play(self):
        self._run_start_menu()
        clock = pygame.time.Clock()
        self.stats_banner.announce_level_change()

        while True:
            clock.tick(self.clock_speed)
            self._handle_input_events()
            self._update()
            self._draw()
            self._checks()
            pygame.display.flip()
            if self.grid.check_snake_collision():
                self._game_lost()
                break

    def _update(self):
        self.stats_banner.update()
        self.grid.update()

    def _draw(self):
        self.grid.draw(self.screen)
        self.stats_banner.draw(self.screen)
        pygame.display.flip()

    def _checks(self):
        is_collision = self.grid.check_apple_eaten()
        if is_collision:
            self.stats_banner.score += 1
            if self.stats_banner.score == POINTS_PER_LEVEL:
                self._update_level()

    def _run_start_menu(self):
        settings = self.start_menu.get_users_settings()
        self.clock_speed = settings[0]
        snake = Snake(settings[1], settings[2])
        dimensions = (settings[3][0] * TILE_WIDTH_PIXELS, settings[3][1] * TILE_WIDTH_PIXELS)
        self.grid = Grid(dimensions, GREEN_PALETTE, snake)
        self.window_dimensions = self.grid.dimensions[0], self.grid.dimensions[1] + BANNER_DIMENSIONS[1]
        self.stats_banner = StatsBanner(self.grid.dimensions, GREEN_PALETTE[2])
        self.start_menu.show_directions()
        wait_for_keypress()
        self.screen = pygame.display.set_mode((self.grid.dimensions[0], self.grid.dimensions[1] + BANNER_DIMENSIONS[1]))

    def _update_level(self):
        if self.stats_banner.level == 10:
            self._game_won()
        self.grid.level_up()
        self.stats_banner.level += 1
        self.stats_banner.score = 0
        self.stats_banner.announce_level_change()

        if self.stats_banner.level == 10:  # final level
            self.grid.snake.color = YARN_COLOR
            palette = GREY_PALETTE
        else:
            palette = self.color_palettes[(self.stats_banner.level - 1) % len(self.color_palettes)]
        self.grid.change_color(palette[0], palette[1])
        self.stats_banner.change_color(palette[2])

    def _handle_input_events(self):
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == KEYDOWN and event.key == K_ESCAPE:
                pygame.quit()
                sys.exit()
            elif event.type == KEYDOWN and event.key in ARROW_KEYS:
                self.grid.snake.head.command_pending = event.key

    def _game_lost(self):
        pygame.mixer.Sound(SOUND_PATH + LOSS_SOUND).play()
        time.sleep(3.5)

        font_huge = pygame.font.Font(FONT_PATH + STANDARD_FONT, FONT_SIZE_HUGE)
        font_large = pygame.font.Font(FONT_PATH + STANDARD_FONT, FONT_SIZE_LARGE)

        you_lost_text = font_huge.render("YOU LOST", True, DARK_GRAY)
        you_lost_rect = you_lost_text.get_rect()
        you_lost_rect.center = self.grid.dimensions[0] * 0.5, (self.grid.dimensions[1] * 0.45) + BANNER_DIMENSIONS[1]

        play_again_text = font_large.render("Play again? Y / N", True, DARK_GRAY)
        play_again_rect = play_again_text.get_rect()
        play_again_rect.center = self.grid.dimensions[0] * 0.5, (self.grid.dimensions[1] * 0.55) + BANNER_DIMENSIONS[1]

        self.screen.blit(you_lost_text, you_lost_rect)
        self.screen.blit(play_again_text, play_again_rect)
        pygame.display.flip()

    def _game_won(self):
        pygame.mixer.Sound(SOUND_PATH + VICTORY_SOUND).play()
        font_huge = pygame.font.Font(FONT_PATH + STANDARD_FONT, FONT_SIZE_HUGE)
        text = font_huge.render("YOU WON!", True, DARK_GRAY)
        text_rect = text.get_rect()
        text_rect.center = self.grid.dimensions[0] * 0.5, (self.grid.dimensions[1] * 0.5) + BANNER_DIMENSIONS[1]
        self.screen.blit(text, text_rect)
        pygame.display.flip()
        time.sleep(3)
        wait_for_keypress()
        pygame.quit()
        sys.exit()
Esempio n. 8
0
class NewGame:
    def __init__(self, cli=False):
        """Setup the game"""

        # Misc Variables - all attributes registered in __init__()
        self.image_dir = 'images'
        self.cli = cli
        self.image_buffer = {}

        # Board Grid (x right, y down)
        self.board = Board({
            (0, 0): None,
            (1, 0): None,
            (2, 0): None,
            (3, 0): None,
            (4, 0): None,
            (5, 0): None,
            (6, 0): None,
            (0, 1): None,
            (1, 1): None,
            (2, 1): None,
            (3, 1): None,
            (4, 1): None,
            (5, 1): None,
            (6, 1): None,
            (0, 2): None,
            (1, 2): None,
            (2, 2): None,
            (3, 2): None,
            (4, 2): None,
            (5, 2): None,
            (6, 2): None,
            (0, 3): None,
            (1, 3): None,
            (2, 3): None,
            (3, 3): None,
            (4, 3): None,
            (5, 3): None,
            (6, 3): None,
            (0, 4): None,
            (1, 4): None,
            (2, 4): None,
            (3, 4): None,
            (4, 4): None,
            (5, 4): None,
            (6, 4): None,
            (0, 5): None,
            (1, 5): None,
            (2, 5): None,
            (3, 5): None,
            (4, 5): None,
            (5, 5): None,
            (6, 5): None,
            (0, 6): None,
            (1, 6): None,
            (2, 6): None,
            (3, 6): None,
            (4, 6): None,
            (5, 6): None,
            (6, 6): None,
        })

        # List of items in game
        self.items = [
            'genie', 'map', 'book', 'bat', 'skull', 'ring', 'sword', 'candles',
            'gem', 'lizzard', 'spider', 'purse', 'chest', 'beetle', 'owl',
            'keys', 'dwarf', 'helmet', 'fairy', 'moth', 'dragon', 'mouse',
            'ghost', 'crown'
        ]
        self.actions = [
            'second_push', 'two_turns', 'swap_figures', 'see_two_cards',
            'swap_card', 'through_wall'
        ]
        self.player_home_colors = [
            'home-red', 'home-yellow', 'home-green', 'home-blue'
        ]

        # Game state
        self.num_human_players = 1  #2,3,4 players
        self.num_computer_players = 1  #2,3,4 players
        if not (2 <=
                (self.num_human_players + self.num_computer_players) <= 4):
            raise Exception("2 - 4 players allowed only")

        self.game_phase = 'start'  #start -> (rotate) + "push" -> "move" ->
        self.text_message_box = {
            'start': 'Click start to begin!',
            'push':
            'Hover the mouse over the push-in square. Rotate the tile with left-click. Right-Click to push tile in.',
            'move': 'Click a square to move there.',
            'won': 'You Won!!'
        }
        self.game_history = []
        self.move_number = 0

        if self.cli == False:
            self.setup_pygame()
            self.game_loop()

    def setup_pygame(self):
        """Setup Variables, Surfaces ,etc. for pygame"""

        # Initialise PyGame Variables
        pygame.init()
        self.mainscreen_size = (1100, 900)
        self.background_color = (160, 217, 92)
        self.menu_background_color = (71, 163, 255)
        self.start_button_color = (255, 0, 0)
        self.menu_button_color = (71, 163, 255)
        self.color_push_in_rect = (153, 255, 179)
        self.color_no_push_in = (204, 0, 0)
        self.is_hover = False

        self.screen = pygame.display.set_mode(
            self.mainscreen_size, HWSURFACE | DOUBLEBUF | RESIZABLE)

        self.game_area_x_offset = 200
        self.game_area_y_offset = 0
        self.game_area = self.screen.subsurface(
            Rect(self.game_area_x_offset, self.game_area_y_offset, 900, 900))

        self.board_area_x_offset = 100
        self.board_area_y_offset = 100
        self.board_area = self.game_area.subsurface(
            Rect(self.board_area_x_offset, self.board_area_y_offset, 700, 700))

        self.menu_area_x_offset = 0
        self.menu_area_y_offset = 0
        self.menu_area = self.screen.subsurface(
            Rect(self.menu_area_x_offset, self.menu_area_y_offset, 200, 900))

        self.tilerect = {}
        for square in self.board.keys():
            self.tilerect[square] = Rect(square[0] * 100, square[1] * 100, 100,
                                         100)

        self.game_push_in_map = {
            (400, 800): (3, 6),
            (800, 600): (6, 5),
            (200, 0): (1, 0),
            (200, 800): (1, 6),
            (800, 400): (6, 3),
            (0, 600): (0, 5),
            (0, 200): (0, 1),
            (0, 400): (0, 3),
            (800, 200): (6, 1),
            (400, 0): (3, 0),
            (600, 800): (5, 6),
            (600, 0): (5, 0)
        }
        self.inv_push_in_map = {v: k for k, v in self.game_push_in_map.items()}
        self.game_push_in_rects = (Rect(400, 800, 100,
                                        100), Rect(800, 600, 100, 100),
                                   Rect(200, 0, 100,
                                        100), Rect(200, 800, 100, 100),
                                   Rect(800, 400, 100,
                                        100), Rect(0, 600, 100, 100),
                                   Rect(0, 200, 100,
                                        100), Rect(0, 400, 100, 100),
                                   Rect(800, 200, 100,
                                        100), Rect(400, 0, 100, 100),
                                   Rect(600, 800, 100,
                                        100), Rect(600, 0, 100, 100))

        self.menu = StartMenu(self.screen)

    def game_loop(self):
        """Game loop for capturing user input, displaying screens,
        updating players and squares.
        """
        def process_human_move():
            pygame.time.wait(100)
            for event in pygame.event.get():
                if event.type not in [
                        pygame.QUIT, MOUSEBUTTONDOWN, MOUSEMOTION
                ]:
                    continue
                if event.type == pygame.QUIT:
                    sys.exit()
                elif event.type == MOUSEBUTTONDOWN:
                    if event.button == 1:
                        if self.game_phase == "push":
                            if self.mouse_over_push_in(event.pos)[0]:
                                self.board.current_tile.rotate()
                        elif self.game_phase == "move":
                            square = self.mouse_over_board(event.pos)
                            if square:
                                #TODO function for this?
                                if self.board.path_exists(
                                        self.board.current_player.location,
                                        square):
                                    self.board.update_player_location(
                                        self.board.current_player, square)
                                    if self.board.update_player_item(
                                            self.board.current_player,
                                            square) == "winner":
                                        self.game_phase == "won"
                                    self.board.next_active_player()
                                    self.game_phase = "push"
                                    self.game_history.append(self.board)
                                    self.move_number += 1
                    elif event.button == 3:
                        if self.game_phase == "push":
                            if self.mouse_over_push_in(event.pos)[0]:
                                if self.mouse_over_push_in(
                                        event.pos
                                )[2] != self.board.last_pushed_out:
                                    self.board.push_in(
                                        self.mouse_over_push_in(event.pos)[2])
                                    self.game_phase = "move"

                elif event.type == MOUSEMOTION:
                    is_hover = self.mouse_over_push_in(event.pos)
                    if is_hover[0]:
                        self.is_hover = is_hover[1]
                    else:
                        self.is_hover = False
            self.display_everything()

        def process_computer_move():
            if self.game_phase == "push":

                #do push and move together
                #~ print "before find_move", hash(self.board)
                rotation, push_in, new_square = self.board.current_player.find_move(
                    self.board)
                #~ rotation, push_in, new_square = (0, (1,0), self.board.current_player.location)
                #~ print "after find_move", hash(self.board)

                self.board.current_tile.rotate_n_times(rotation)
                self.board.push_in(push_in)
                #~ pygame.time.wait(2000)
                self.board.update_player_location(self.board.current_player,
                                                  new_square)
                if self.board.update_player_item(self.board.current_player,
                                                 new_square) == "winner":
                    self.game_phase = "won"
                self.board.next_active_player()
                self.game_history.append(self.board)
                self.move_number += 1
                self.display_everything()

        def collect_start_screen_input():
            pygame.time.wait(100)
            for event in pygame.event.get():
                if event.type not in [
                        pygame.QUIT, MOUSEBUTTONDOWN, MOUSEMOTION
                ]:
                    continue
                if event.type == pygame.QUIT:
                    sys.exit()
                elif event.type == MOUSEBUTTONDOWN:
                    if event.button == 1:
                        if self.menu.mouse_click_button(event.pos) is True:
                            self.num_computer_players = self.menu.n_players
                            self.num_players = (self.num_human_players +
                                                self.num_computer_players)
                            #~ print self.num_players, self.num_human_players, self.num_computer_players
                            # Initialise Game
                            self.setup_tiles()
                            #players must be setup after tiles
                            self.init_players()
                            self.load_images()
                            self.game_phase = "push"
            self.menu.display_menu()

        self.game_history.append(self.board)
        self.menu.display_menu()
        # Game Loop
        while 1:
            if self.game_phase == "start":
                collect_start_screen_input()
            elif self.game_phase == "won":
                self.display_everything().game_over_screen()
            elif (self.game_phase == "move"
                  and not self.board.possible_moves_exist(
                      self.board.current_player)):
                self.board.next_active_player()
                self.game_phase = "push"
                self.game_history.append(self.board)
                self.move_number += 1
            elif self.board.current_player.iscomputer is False:
                process_human_move()
            elif self.board.current_player.iscomputer is True:
                process_computer_move()

    def display_everything(self):
        """Draw everything to the screen"""
        def blit_tile(tile_obj, tile_rect, surface):
            """Blit a single tile with image
            tile_obj is a BoardTile instance
            tile_rect is the Rect obj
            surface is the surface to blit to
            """
            tile_image = pygame.image.fromstring(
                self.image_buffer[tile_obj.tile_type], (100, 100), "RGBA")
            tile_rotation = tile_obj.tile_image_rotation()
            final_tile = pygame.transform.rotate(tile_image, tile_rotation)
            surface.blit(final_tile, tile_rect)

            if tile_obj.item:
                item = tile_obj.item
                item_image = pygame.image.fromstring(self.image_buffer[item],
                                                     (100, 100), "RGBA")
                surface.blit(item_image, tile_rect)

        def blit_card(card, card_rect, surface):
            """Blit a single card
            str card
            Rect card_rect
            Surface surface
            """
            basecard_image = pygame.image.fromstring(
                self.image_buffer['basecard'], (100, 100), "RGBA")
            surface.blit(basecard_image, card_rect)
            card_image = pygame.image.fromstring(self.image_buffer[card],
                                                 (100, 100), "RGBA")
            surface.blit(card_image, card_rect)

        def blit_player(player_obj, surface, coords=None):
            """Blit a player figure to the board"""
            if coords == None:
                coords = (player_obj.location[0] * 100,
                          player_obj.location[1] * 100)
            dims = (100, 100)

            player_color = player_obj.color
            player_figure = player_obj.player_images[player_color]
            player_image = pygame.image.fromstring(
                self.image_buffer[player_figure], (100, 100), "RGBA")
            player_square = player_obj.location
            player_rect = Rect((coords), (dims))
            surface.blit(player_image, player_rect)

        def blit_text(surface, text, color, rect, font, aa=False, bkg=None):
            """Draw some text into an area of a surface
            automatically wraps words
            returns any text that didn't get blitted
            """
            rect = Rect(rect)
            y = rect.top
            lineSpacing = -2

            # get the height of the font
            fontHeight = font.size("Tg")[1]

            while text:
                i = 1

                # determine if the row of text will be outside our area
                if y + fontHeight > rect.bottom:
                    break

                # determine maximum width of line
                while font.size(text[:i])[0] < rect.width and i < len(text):
                    i += 1

                # if we've wrapped the text, then adjust the wrap to the last word
                if i < len(text):
                    i = text.rfind(" ", 0, i) + 1

                # render the line and blit it to the surface
                if bkg:
                    image = font.render(text[:i], 1, color, bkg)
                    image.set_colorkey(bkg)
                else:
                    image = font.render(text[:i], aa, color)

                surface.blit(image, (rect.left, y))
                y += fontHeight + lineSpacing

                # remove the text we just blitted
                text = text[i:]
            return text

        def blit_push_in_rect(surface, color, rect):
            """push in rects are green
            except the one where you may not push!
            """
            pygame.draw.rect(surface, color, rect)

        def game_over_screen():
            """Blit a final screen for game over"""
            self.screen.fill(self.background_color)
            blit_text(self.screen, "Game Over!", (0, 0, 0),
                      (400, 500, 190, 190), myfont)
            raw_input()

        # Background
        self.screen.fill(self.background_color)
        self.menu_area.fill(self.menu_background_color)

        # Board
        for square in self.board:
            #TODO Perf improve?: only blit rects where obj hash has changed
            # Tiles
            tile = self.board[square]
            rect = Rect(square[0] * 100, square[1] * 100, 100, 100)
            surf = self.board_area
            blit_tile(tile, rect, surf)

        # Player Figures
        for player in self.board.active_players:
            blit_player(player, self.board_area)

        # Push-In Squares at edges
        if self.board.last_pushed_out:
            last_pushed_out = self.board.last_pushed_out
            last_pushed_out_rect = Rect(
                (self.inv_push_in_map[last_pushed_out]), (100, 100))
            blit_push_in_rect(self.game_area, self.color_no_push_in,
                              last_pushed_out_rect)
        else:
            last_pushed_out_rect = None

        for rect in self.game_push_in_rects:
            if ((rect != self.is_hover) and (rect != last_pushed_out_rect)):
                blit_push_in_rect(self.game_area, self.color_push_in_rect,
                                  rect)

        if (self.is_hover and self.is_hover != last_pushed_out_rect):
            tile = self.board.current_tile
            rect = self.is_hover
            surf = self.game_area
            blit_tile(tile, rect, surf)

        # Labels
        myfont = pygame.font.SysFont("monospace", 15, bold=True)
        card_label = myfont.render("Current Card", 1, (0, 0, 0))
        tile_label = myfont.render("Current Tile", 1, (0, 0, 0))
        player_label = myfont.render(
            "Current Player: {}".format(self.board.current_player.color), 1,
            (0, 0, 0))
        player_remaining_cards = myfont.render(
            "Cards: {}".format(self.board.current_player.remaining_cards()), 1,
            (0, 0, 0))
        self.menu_area.blit(card_label, (50, 130))
        self.menu_area.blit(tile_label, (50, 255))
        self.menu_area.blit(player_label, (5, 380))
        self.menu_area.blit(player_remaining_cards, (5, 395))

        # Current Card
        card = self.board.current_player.current_card
        rect = Rect(50, 25, 100, 100)
        surf = self.menu_area
        blit_card(card, rect, surf)

        # Current Tile
        tile = self.board.current_tile
        rect = Rect(50, 150, 100, 100)
        surf = self.menu_area
        blit_tile(tile, rect, surf)

        # Current Player in menu
        blit_player(self.board.current_player, self.menu_area, (50, 275))

        # Text box
        blit_text(self.menu_area, self.text_message_box[self.game_phase],
                  (0, 0, 0), (5, 500, 190, 190), myfont)

        # Game Border
        border_color = (0, 0, 0)
        game_area_rect = (0, 0, 900, 900)
        border_width = 4
        pygame.draw.rect(self.game_area, border_color, game_area_rect,
                         border_width)

        # Update display
        pygame.display.flip()

    def mouse_over_push_in(self, mouse_location):
        """Test if mouse hovering over a push in location
        Return (True|False, tilerect, square)
        """
        mouse_x, mouse_y = mouse_location
        for _rect in self.game_push_in_rects:
            if _rect.collidepoint(mouse_x - 200, mouse_y):
                _rectpos = (_rect.left, _rect.top)
                return (True, _rect, self.game_push_in_map[_rectpos])
        return (False, False, False)

    def mouse_over_board(self, mouse_location):
        """Test if mouse over the board
        Return square or False
        """
        mouse_x, mouse_y = mouse_location
        if not ((300 <= mouse_x < 1000) and (100 <= mouse_y < 800)):
            return False
        else:
            x_pos = (mouse_x - 300) / 100
            y_pos = (mouse_y - 100) / 100
            return (x_pos, y_pos)

    def setup_tiles(self):
        """Initialise all tile objects
        Allocate tile objects to board positions
        """

        items_list = [i for i in self.items]  #each item once
        actions_list = [j for k in [[i, i] for i in self.actions]
                        for j in k]  #each action twice
        colors_list = [i for i in self.player_home_colors]  #each color once
        shuffle(items_list)
        shuffle(actions_list)

        ## Fixed Cards
        #corners
        self.board[(0, 0)] = BoardTile([False, True, True, False])
        self.board[(0, 6)] = BoardTile([True, True, False, False])
        self.board[(6, 6)] = BoardTile([True, False, False, True])
        self.board[(6, 0)] = BoardTile([False, False, True, True])

        #edges
        self.board[(0, 2)] = BoardTile([True, True, True, False],
                                       item=items_list.pop())
        self.board[(2, 0)] = BoardTile([False, True, True, True],
                                       item=items_list.pop())
        self.board[(4, 0)] = BoardTile([False, True, True, True],
                                       item=items_list.pop())
        self.board[(0, 4)] = BoardTile([True, True, True, False],
                                       item=items_list.pop())
        self.board[(6, 2)] = BoardTile([True, False, True, True],
                                       item=items_list.pop())
        self.board[(2, 6)] = BoardTile([True, True, False, True],
                                       item=items_list.pop())
        self.board[(6, 4)] = BoardTile([True, False, True, True],
                                       item=items_list.pop())
        self.board[(4, 6)] = BoardTile([True, True, False, True],
                                       item=items_list.pop())

        #centers
        self.board[(2, 2)] = BoardTile([False, True, True, True],
                                       item=items_list.pop(),
                                       random_orientation=True)
        self.board[(4, 2)] = BoardTile([False, True, True, True],
                                       item=items_list.pop(),
                                       random_orientation=True)
        self.board[(2, 4)] = BoardTile([False, True, True, True],
                                       item=items_list.pop(),
                                       random_orientation=True)
        self.board[(4, 4)] = BoardTile([False, True, True, True],
                                       item=items_list.pop(),
                                       random_orientation=True)
        ## Distributed Cards
        tiles = []
        #6 with three exits, all contain item, no actions
        for i in xrange(0, 6):
            tiles.append(
                BoardTile([False, True, True, True],
                          item=items_list.pop(),
                          random_orientation=True))
        #6 straight through exits, no items, actions
        for i in xrange(0, 6):
            tiles.append(
                BoardTile([False, True, False, True],
                          action=actions_list.pop(),
                          random_orientation=True))
        #6 straight through exits, no items, no actions
        for i in xrange(0, 6):
            tiles.append(
                BoardTile([False, True, False, True], random_orientation=True))
        #6 corner exits, no items, contain actions
        for i in xrange(0, 6):
            tiles.append(
                BoardTile([True, True, False, False],
                          action=actions_list.pop(),
                          random_orientation=True))
        #4 corner exits, no items, no actions
        for i in xrange(0, 4):
            tiles.append(
                BoardTile([True, True, False, False], random_orientation=True))
        #6 corner exits, items, no actions
        for i in xrange(0, 6):
            tiles.append(
                BoardTile([True, True, False, False],
                          item=items_list.pop(),
                          random_orientation=True))

        #Check all items and actions assigned
        if len(items_list) != 0:
            raise Exception("Leftover tiles!")
        if len(actions_list) != 0:
            raise Exception("Leftover actions!")

        #shuffle tiles before distributing to remaining board positions
        shuffle(tiles)

        #Assign tiles to remaining squares
        for square in self.board.movable_squares:
            self.board[square] = tiles.pop()

        #Remaining tile is the start tile
        self.board.current_tile = tiles.pop()

        # Set player home squares
        for square in ((0, 0), (0, 6), (6, 6), (6, 0)):
            self.board[square].item = colors_list.pop()

    def init_players(self):
        """Initialise the human and computer player objects
        2 <= (Human players + Computer players) <= 4
        """
        ## Setup players
        available_color_locations = [('blue', (0, 0)), ('red', (6, 0)),
                                     ('green', (0, 6)), ('yellow', (6, 6))]
        human_players = []
        computer_players = []

        for i in xrange(0, self.num_human_players):
            player = Player(available_color_locations.pop())
            player.isactive = True
            human_players.append(player)

        for i in xrange(0, self.num_computer_players):
            player = ComputerPlayer(available_color_locations.pop())
            player.isactive = True
            computer_players.append(player)

        self.board.active_players = computer_players + human_players

        # Setup Cards
        self.cards_per_player = len(self.items)
        shuffle(self.items)
        hands = [
            self.items[i::self.num_players]
            for i in range(0, self.num_players)
        ]

        for player in self.board.active_players:
            player.cards = hands.pop()
            player.draw_card()

        # Set squares to occupied
        for player in self.board.active_players:
            self.board[player.location].add_resident(player)

        # Current Player to go
        self.board.current_player = self.board.active_players[0]

        # Generate test object for unittest - remove later
        #~ _f = open("testPlayer2.pickle", "a")
        #~ self.board.next_active_player()
        #~ pickle.dump(self.board.current_player, _f, pickle.HIGHEST_PROTOCOL)
        #~ _f.close
        #~ print self.board.current_player.isactive
        #~ print self.board.current_player.name
        #~ print self.board.current_player.color
        #~ print self.board.current_player.cards
        #~ print self.board.current_player.location
        #~ print self.board.current_player.home
        #~ print self.board.current_player.current_card
        #~ print self.board.current_player.found_cards
        #~ print self.board.current_player.iscomputer
        #~ print self.board.current_player.__str__()
        #~ print self.board.current_player.__hash__()
        #~ print hash(self.board.current_player)

    def load_images(self):
        """Load tile images into string buffers
        store buffers in the dict self.image_buffer
        """
        image_filename = {
            'genie': 'item-genie-100px.png',
            'map': 'item-map-100px.png',
            'book': 'item-book-100px.png',
            'bat': 'item-bat-100px.png',
            'skull': 'item-skull-100px.png',
            'ring': 'item-ring-100px.png',
            'sword': 'item-sword-100px.png',
            'candles': 'item-candles-100px.png',
            'gem': 'item-gem-100px.png',
            'lizzard': 'item-lizzard-100px.png',
            'spider': 'item-spider-100px.png',
            'purse': 'item-purse-100px.png',
            'chest': 'item-chest-100px.png',
            'beetle': 'item-beetle-100px.png',
            'owl': 'item-owl-100px.png',
            'keys': 'item-keys-100px.png',
            'dwarf': 'item-dwarf-100px.png',
            'helmet': 'item-helmet-100px.png',
            'fairy': 'item-fairy-100px.png',
            'moth': 'item-moth-100px.png',
            'dragon': 'item-dragon-100px.png',
            'mouse': 'item-mouse-100px.png',
            'ghost': 'item-ghost-100px.png',
            'crown': 'item-crown-100px.png',
            'straight': 'tile-tftf-100px.png',
            'corner': 'tile-ttff-100px.png',
            'tee': 'tile-ttft-100px.png',
            'home-red': 'home-red-100px.png',
            'home-green': 'home-green-100px.png',
            'home-blue': 'home-blue-100px.png',
            'home-yellow': 'home-yellow-100px.png',
            'basecard': 'basecard-100px.png',
            'player-yellow': 'player-yellow-100px.png',
            'player-blue': 'player-blue-100px.png',
            'player-green': 'player-green-100px.png',
            'player-red': 'player-red-100px.png'
        }
        image_surface = {}
        for image in image_filename.keys():
            image_surface[image] = pygame.image.load(
                os.path.join(self.image_dir, image_filename[image]))
        for surface in image_surface.keys():
            self.image_buffer[surface] = pygame.image.tostring(
                image_surface[surface], "RGBA")
Esempio n. 9
0
    def setup_pygame(self):
        """Setup Variables, Surfaces ,etc. for pygame"""

        # Initialise PyGame Variables
        pygame.init()
        self.mainscreen_size = (1100, 900)
        self.background_color = (160, 217, 92)
        self.menu_background_color = (71, 163, 255)
        self.start_button_color = (255, 0, 0)
        self.menu_button_color = (71, 163, 255)
        self.color_push_in_rect = (153, 255, 179)
        self.color_no_push_in = (204, 0, 0)
        self.is_hover = False

        self.screen = pygame.display.set_mode(
            self.mainscreen_size, HWSURFACE | DOUBLEBUF | RESIZABLE)

        self.game_area_x_offset = 200
        self.game_area_y_offset = 0
        self.game_area = self.screen.subsurface(
            Rect(self.game_area_x_offset, self.game_area_y_offset, 900, 900))

        self.board_area_x_offset = 100
        self.board_area_y_offset = 100
        self.board_area = self.game_area.subsurface(
            Rect(self.board_area_x_offset, self.board_area_y_offset, 700, 700))

        self.menu_area_x_offset = 0
        self.menu_area_y_offset = 0
        self.menu_area = self.screen.subsurface(
            Rect(self.menu_area_x_offset, self.menu_area_y_offset, 200, 900))

        self.tilerect = {}
        for square in self.board.keys():
            self.tilerect[square] = Rect(square[0] * 100, square[1] * 100, 100,
                                         100)

        self.game_push_in_map = {
            (400, 800): (3, 6),
            (800, 600): (6, 5),
            (200, 0): (1, 0),
            (200, 800): (1, 6),
            (800, 400): (6, 3),
            (0, 600): (0, 5),
            (0, 200): (0, 1),
            (0, 400): (0, 3),
            (800, 200): (6, 1),
            (400, 0): (3, 0),
            (600, 800): (5, 6),
            (600, 0): (5, 0)
        }
        self.inv_push_in_map = {v: k for k, v in self.game_push_in_map.items()}
        self.game_push_in_rects = (Rect(400, 800, 100,
                                        100), Rect(800, 600, 100, 100),
                                   Rect(200, 0, 100,
                                        100), Rect(200, 800, 100, 100),
                                   Rect(800, 400, 100,
                                        100), Rect(0, 600, 100, 100),
                                   Rect(0, 200, 100,
                                        100), Rect(0, 400, 100, 100),
                                   Rect(800, 200, 100,
                                        100), Rect(400, 0, 100, 100),
                                   Rect(600, 800, 100,
                                        100), Rect(600, 0, 100, 100))

        self.menu = StartMenu(self.screen)
Esempio n. 10
0
    def back(self, btn: Button, pos: Vector):
        from startmenu import StartMenu

        btn.window.handler = StartMenu(btn.window)
Esempio n. 11
0
class TicTacToe:
    """Ui class for TicTacToe game.

    Attributes:
        start_menu: Starting menu for setting game parameters
        tictactoeboard: Tictactoe board data structure
        screen: Pygame window
        x_image: X image for player 1
        o_image: O image for player 2
        square_size: How big is one square in pixels (grid size / number of squares).
        grid_size: Pygame window size in pixels
        result_text: Result of the game
        whose_turn: Whose turn is it (text message)
        background_color: Background color of the board and the status window
        grid color: Color of grid lines
        bottom_height: How long is the window below the grid (Status window and buttons)
        buttom_width: How long is buttons width
        running: Is game still running or not
    """
    def __init__(self):
        """Class constructor, which initializes the variables
        and final values are set later, because they depend on user input
        """

        self.start_menu = None
        self.tictactoeboard = None

        self.screen = None
        self.x_image = None
        self.o_image = None
        self.square_size = 0
        self.grid_size = 800
        self.result_text = ''
        self.whose_turn = ''
        self.background_color = (210, 210, 210)
        self.grid_color = (0, 0, 0)
        self.bottom_height = 100
        self.button_width = self.grid_size / 3
        self.running = True

    def run(self):
        """Function where game runs in infinite loop
        until game ends or player press quit
        """

        self.start_game()

        if self.tictactoeboard.num_squares == 0:
            return

        while self.running and self.tictactoeboard.num_squares > 0:
            self.play_game()

            if self.tictactoeboard.result == Result.ONGOING and self.running:
                pygame.display.flip()

        pygame.quit()  # pylint: disable=no-member

    def play_game(self):
        """Infinite loop for reading user mouse events. Break after running is set to False"""

        for event in pygame.event.get():

            if event.type == pygame.MOUSEBUTTONDOWN:  # pylint: disable=no-member
                self.check_button_pressed(event.pos[0], event.pos[1])
                if self.running is False:
                    break
                if event.pos[0] > self.grid_size or event.pos[
                        1] > self.grid_size:
                    continue
                self.set_xo(event.pos[0], event.pos[1])

            if self.tictactoeboard.result != Result.ONGOING:

                self.set_result()
                pygame.quit()  # pylint: disable=no-member

                self.start_game()

                if self.tictactoeboard.num_squares == 0:
                    self.running = False
                    break

    def start_game(self):
        """Call Tkinter Class where the user sets the names of the players and number of squares.
        If one of player names are incorrect, starts again with error message.
        Else calls set_game function
        """

        self.start_menu = StartMenu(self.result_text)

        num_squares, player1, player2 = self.get_game_variables()

        self.tictactoeboard = TicTacToeBoard(num_squares, player1, player2)

        if self.tictactoeboard.num_squares == 0:
            return

        if self.players_name_ok(self.start_menu.name_max_size) is False:
            self.result_text = 'Virheellinen pelaajan nimi'
            self.start_game()
        else:
            self.set_game()

    def get_game_variables(self):
        """Show Tkinter menu and set num_squares, player1 and player2 to what user gave it in
        Tkinter window

        Returns:
            Number of squares in board, player 1 name and player 2 name
        """

        self.start_menu.show()
        return self.start_menu.num_squares, self.start_menu.player1, self.start_menu.player2

    def players_name_ok(self, max_size):
        """Check if the player names are the correct size

        Args:
            max_size: what is players name max length

        Returns:
            True, if names length are correct (1-max_size). Otherwise returns False
        """

        player1_len = len(self.tictactoeboard.player1)
        player2_len = len(self.tictactoeboard.player2)
        names_ok = True
        if player1_len > max_size or player1_len < 1:
            names_ok = False
        if player2_len > max_size or player2_len < 1:
            names_ok = False
        return names_ok

    def set_game(self):
        """Sets game variables right with right num_squares and then calls:
        - draw_grid function which draws board.
        - draw_status function which draws whose turn is it (first time player 1)
        - draw_buttons function which draws save, load and quit buttons
        """

        self.square_size = int(self.grid_size /
                               self.tictactoeboard.num_squares)
        self.grid_size = self.grid_size - (self.grid_size %
                                           self.tictactoeboard.num_squares)
        self.button_width = math.floor(self.grid_size / 3)

        self.x_image = pygame.transform.scale(pygame.image.load\
        ("src/images_xo/x.png"), (self.square_size, self.square_size))
        self.o_image = pygame.transform.scale(pygame.image.load\
        ("src/images_xo/o.png"), (self.square_size, self.square_size))

        os.environ['SDL_VIDEO_WINDOW_POS'] = "center"
        pygame.init()  # pylint: disable=no-member
        window_size = [self.grid_size, self.grid_size + self.bottom_height]
        self.screen = pygame.display.set_mode(window_size, pygame.NOFRAME,
                                              pygame.SHOWN)  # pylint: disable=no-member

        self.draw_grid()
        self.draw_status()
        self.draw_buttons()

    def set_xo(self, mouse_x, mouse_y):
        """Add x or o in tictactoeboard data structure to the square that user clicked

        Args:
            mouse_x: X coordinate which position user click with mouse
            mouse_y: Y coordinate which position user click with mouse
        """

        x_square = math.floor(mouse_x / self.square_size)
        y_square = math.floor(mouse_y / self.square_size)

        if self.tictactoeboard.whose_turn == 1 and not \
                                         self.tictactoeboard.is_taken(y_square, x_square):
            self.tictactoeboard.add_x(x_square, y_square)
        elif self.tictactoeboard.whose_turn == 2 and not \
                                            self.tictactoeboard.is_taken(y_square, x_square):
            self.tictactoeboard.add_o(x_square, y_square)

        self.update_board()
        self.draw_status()

    def update_board(self):
        """Draw empty grid and then draw all x and o to the grid.
        Function gets x and o positions from the tictactoeboard data structure"""

        self.draw_grid()

        for x_square in range(0, self.tictactoeboard.num_squares):
            for y_square in range(0, self.tictactoeboard.num_squares):
                x_coordinate = self.square_size * x_square
                y_coordinate = self.square_size * y_square
                if self.tictactoeboard.board[y_square][x_square] == 'x':
                    self.screen.blit(self.x_image,
                                     (x_coordinate, y_coordinate))
                elif self.tictactoeboard.board[y_square][x_square] == 'o':
                    self.screen.blit(self.o_image,
                                     (x_coordinate, y_coordinate))

    def draw_grid(self):
        """Draws empty grid for the game"""

        self.screen.fill((self.background_color),
                         (0, 0, self.grid_size, self.grid_size))

        for x_int in range(0, self.grid_size, self.square_size):
            for y_int in range(0, self.grid_size, self.square_size):
                rect = pygame.Rect(x_int, y_int, self.square_size,
                                   self.square_size)
                pygame.draw.rect(self.screen, self.grid_color, rect, 1)

    def draw_status(self):
        """Draws a status of the game (whose turn is it) and also calls function draw_buttons
        which draws save, load and quit buttons
        """

        my_font = 'arial'
        status_font_size = 45
        font_color = (0, 0, 0)
        status_coordinates = (0, self.grid_size, self.grid_size,
                              self.bottom_height / 2)
        status_text_center = (self.grid_size / 2,
                              self.grid_size + int(self.bottom_height / 4))

        if self.tictactoeboard.whose_turn == 1:
            self.whose_turn = f"Vuoro: {self.tictactoeboard.player1}"
        else:
            self.whose_turn = f"Vuoro: {self.tictactoeboard.player2}"

        font = pygame.font.SysFont(my_font, status_font_size)
        text = font.render(self.whose_turn, 1, font_color)
        self.screen.fill((self.background_color), status_coordinates)
        text_rect = text.get_rect(center=status_text_center)
        self.screen.blit(text, text_rect)

        pygame.display.update()

    def draw_buttons(self):
        """draws save, load and quit buttons to bottom of window"""

        save_button_coordinates = (0, self.grid_size + self.bottom_height/2, \
                                   self.button_width, self.bottom_height/2)
        save_button_center = (0 + self.button_width/2, \
                            self.grid_size + int(self.bottom_height * 0.75))
        self.draw_one_button('Tallenna peli', save_button_coordinates,
                             save_button_center)


        download_button_coordinates = (self.button_width, self.grid_size + self.bottom_height/2,\
                                       self.button_width, self.bottom_height/2)
        download_button_center = (self.grid_size / 2,\
                                self.grid_size + int(self.bottom_height * 0.75))
        self.draw_one_button('Lataa peli', download_button_coordinates,
                             download_button_center)


        quit_button_coordinates = (self.button_width * 2, self.grid_size + self.bottom_height/2,\
                                       self.grid_size - 2 * self.button_width, self.bottom_height/2)
        quit_button_center = (self.grid_size - self.button_width/2,\
                                self.grid_size + int(self.bottom_height * 0.75))
        self.draw_one_button('Lopeta peli', quit_button_coordinates,
                             quit_button_center)

        pygame.display.update()

    def draw_one_button(self, button_text, button_coordinates, button_center):
        """Auxiliary function for drawing buttons

        Args:
            button_text: Button text
            button_coordinates: Where to draw button and what are buttons width and height
            button_center: Where is center of button
        """

        button_font = 'arial'
        button_font_size = 24
        button_color = (150, 150, 150)
        font_color = (50, 50, 50)
        border_color = (120, 120, 120)

        font = pygame.font.SysFont(button_font, button_font_size)
        text = font.render(button_text, 1, font_color)
        pygame.draw.rect(self.screen, (button_color), button_coordinates)

        # Draws button borders and text
        pygame.draw.rect(self.screen, border_color,
                         pygame.Rect(button_coordinates), 4, 0)
        text_rect = text.get_rect(center=button_center)
        self.screen.blit(text, text_rect)

    def check_button_pressed(self, mouse_x, mouse_y):
        """Check if user press one of buttons

        Args:
            mouse_x: Check x coordinate which position user clicked with mouse
            mouse_y: Check y coordinate which position user clicked with mouse
        """

        if 0 < mouse_x < self.button_width and\
           self.grid_size + self.bottom_height/2 < mouse_y < self.grid_size + self.bottom_height:
            self.save_game()

        elif self.button_width < mouse_x < self.button_width * 2 and\
             self.grid_size + self.bottom_height/2 < mouse_y < self.grid_size + self.bottom_height:
            self.load_game()

        elif self.button_width * 2 < mouse_x < self.grid_size and\
             self.grid_size + self.bottom_height/2 < mouse_y < self.grid_size + self.bottom_height:
            self.running = False

    def save_game(self):
        """Function for saving game and printing result message"""

        message = 'Tallennus onnistui'
        window_title = 'Tallennus'
        try:
            save_menu = tk.Tk()
            save_menu.withdraw()
            save_filename = tkinter.filedialog.asksaveasfilename(title= "Tallenna tiedosto"\
                            ,filetypes=[("Tictactoe tiedostot", "*.ttt")])
            save_menu.destroy()
            with open(save_filename, "wb") as save_file:
                pickle.dump(self.tictactoeboard, save_file)
        except (IOError, TypeError, AttributeError, pickle.PicklingError):
            message = 'Tallennus epäonnistui'
        finally:
            self.print_message(message, window_title)

    def load_game(self):
        """Function for loading game and printing result message"""

        message = 'Lataus onnistui'
        window_title = 'Lataus'
        try:
            load_menu = tk.Tk()
            load_menu.withdraw()
            load_filename = tkinter.filedialog.askopenfilename(parent=load_menu, \
                            title= "Lataa tiedosto", \
                            filetypes=[("Tictactoe tiedostot", "*.ttt")])
            load_menu.destroy()
            with open(load_filename, "rb") as load_file:
                self.tictactoeboard = pickle.load(load_file)
        except (IOError, TypeError, AttributeError, pickle.UnpicklingError):
            message = 'Lataus epäonnistui'
        else:
            self.set_game()
            self.update_board()
        finally:
            self.print_message(message, window_title)

    def print_message(self, message, window_title):
        """Function that print message if needed. Uses Tkinter popup window

        Args:
            message: Message that is shown to user
            window_title: Window title
        """

        errorwindow = tk.Tk()
        errorwindow.overrideredirect(1)
        errorwindow.withdraw()
        tkinter.messagebox.showinfo(window_title, message)
        errorwindow.destroy()

    def set_result(self):
        """Set result text who wins or is it draw"""

        if self.tictactoeboard.result == Result.FIRST_WIN:
            self.result_text = f"{self.tictactoeboard.player1} voittaa"
        elif self.tictactoeboard.result == Result.SECOND_WIN:
            self.result_text = f"{self.tictactoeboard.player2} voittaa"
        elif self.tictactoeboard.result == Result.DRAW:
            self.result_text = 'Tasapeli'
Esempio n. 12
0
 def setup_pygame(self):
     """Setup Variables, Surfaces ,etc. for pygame"""
     
     # Initialise PyGame Variables
     pygame.init()
     self.mainscreen_size = (1100, 900)
     self.background_color = (160,217,92)
     self.menu_background_color = (71,163,255)
     self.start_button_color = (255,0,0)
     self.menu_button_color = (71,163,255)
     self.color_push_in_rect = (153,255,179)
     self.color_no_push_in = (204,0,0)
     self.is_hover = False
     
     self.screen = pygame.display.set_mode(
         self.mainscreen_size, HWSURFACE | DOUBLEBUF | RESIZABLE)
     
     self.game_area_x_offset = 200
     self.game_area_y_offset = 0
     self.game_area = self.screen.subsurface(
         Rect(self.game_area_x_offset,self.game_area_y_offset,900,900))
     
     self.board_area_x_offset = 100
     self.board_area_y_offset = 100
     self.board_area = self.game_area.subsurface(
         Rect(self.board_area_x_offset,self.board_area_y_offset,700,700))
         
     self.menu_area_x_offset = 0
     self.menu_area_y_offset = 0
     self.menu_area = self.screen.subsurface(
         Rect(self.menu_area_x_offset,self.menu_area_y_offset,200,900))
     
     self.tilerect = {}
     for square in self.board.keys():
         self.tilerect[square] = Rect(square[0]*100,square[1]*100,100,100)
         
     self.game_push_in_map = {
         (400, 800): (3, 6),
         (800, 600): (6, 5),
         (200, 0):   (1, 0),
         (200, 800): (1, 6),
         (800, 400): (6, 3),
         (0, 600):   (0, 5),
         (0, 200):   (0, 1),
         (0, 400):   (0, 3),
         (800, 200): (6, 1),
         (400, 0):   (3, 0),
         (600, 800): (5, 6),
         (600, 0):   (5, 0) }
     self.inv_push_in_map = {v:k for k, v in self.game_push_in_map.items()}
     self.game_push_in_rects = (
         Rect(400, 800, 100, 100),
         Rect(800, 600, 100, 100),
         Rect(200, 0, 100, 100),
         Rect(200, 800, 100, 100),
         Rect(800, 400, 100, 100),
         Rect(0, 600, 100, 100),
         Rect(0, 200, 100, 100),
         Rect(0, 400, 100, 100),
         Rect(800, 200, 100, 100),
         Rect(400, 0, 100, 100),
         Rect(600, 800, 100, 100),
         Rect(600, 0, 100, 100) )
         
     self.menu = StartMenu(self.screen)
Esempio n. 13
0
class NewGame:
    def __init__(self, cli=False):
        """Setup the game"""
        
        # Misc Variables - all attributes registered in __init__()
        self.image_dir = 'images'
        self.cli = cli
        self.image_buffer = {}
        
        # Board Grid (x right, y down)       
        self.board = Board({
            (0,0): None, (1,0): None, (2,0): None, (3,0): None, (4,0): None, (5,0): None, (6,0): None,
            (0,1): None, (1,1): None, (2,1): None, (3,1): None, (4,1): None, (5,1): None, (6,1): None,
            (0,2): None, (1,2): None, (2,2): None, (3,2): None, (4,2): None, (5,2): None, (6,2): None,
            (0,3): None, (1,3): None, (2,3): None, (3,3): None, (4,3): None, (5,3): None, (6,3): None,
            (0,4): None, (1,4): None, (2,4): None, (3,4): None, (4,4): None, (5,4): None, (6,4): None,
            (0,5): None, (1,5): None, (2,5): None, (3,5): None, (4,5): None, (5,5): None, (6,5): None,
            (0,6): None, (1,6): None, (2,6): None, (3,6): None, (4,6): None, (5,6): None, (6,6): None,})
        
        # List of items in game
        self.items = [
            'genie', 'map', 'book', 'bat', 'skull', 'ring', 'sword',
            'candles', 'gem', 'lizzard', 'spider', 'purse', 'chest',
            'beetle', 'owl', 'keys', 'dwarf', 'helmet', 'fairy',
            'moth', 'dragon', 'mouse', 'ghost', 'crown']
        self.actions = [
            'second_push', 'two_turns', 'swap_figures',
            'see_two_cards', 'swap_card', 'through_wall']
        self.player_home_colors = [
            'home-red', 'home-yellow', 'home-green', 'home-blue']
        
        # Game state
        self.num_human_players = 1          #2,3,4 players
        self.num_computer_players = 1       #2,3,4 players
        if not (2 <= (self.num_human_players + self.num_computer_players) <= 4):
            raise Exception("2 - 4 players allowed only")
        
        self.game_phase = 'start'            #start -> (rotate) + "push" -> "move" ->
        self.text_message_box = {
            'start': 'Click start to begin!',
            'push': 'Hover the mouse over the push-in square. Rotate the tile with left-click. Right-Click to push tile in.',
            'move': 'Click a square to move there.',
            'won': 'You Won!!' }
        self.game_history = []
        self.move_number = 0
        
        if self.cli == False:
            self.setup_pygame()
            self.game_loop()
        
    def setup_pygame(self):
        """Setup Variables, Surfaces ,etc. for pygame"""
        
        # Initialise PyGame Variables
        pygame.init()
        self.mainscreen_size = (1100, 900)
        self.background_color = (160,217,92)
        self.menu_background_color = (71,163,255)
        self.start_button_color = (255,0,0)
        self.menu_button_color = (71,163,255)
        self.color_push_in_rect = (153,255,179)
        self.color_no_push_in = (204,0,0)
        self.is_hover = False
        
        self.screen = pygame.display.set_mode(
            self.mainscreen_size, HWSURFACE | DOUBLEBUF | RESIZABLE)
        
        self.game_area_x_offset = 200
        self.game_area_y_offset = 0
        self.game_area = self.screen.subsurface(
            Rect(self.game_area_x_offset,self.game_area_y_offset,900,900))
        
        self.board_area_x_offset = 100
        self.board_area_y_offset = 100
        self.board_area = self.game_area.subsurface(
            Rect(self.board_area_x_offset,self.board_area_y_offset,700,700))
            
        self.menu_area_x_offset = 0
        self.menu_area_y_offset = 0
        self.menu_area = self.screen.subsurface(
            Rect(self.menu_area_x_offset,self.menu_area_y_offset,200,900))
        
        self.tilerect = {}
        for square in self.board.keys():
            self.tilerect[square] = Rect(square[0]*100,square[1]*100,100,100)
            
        self.game_push_in_map = {
            (400, 800): (3, 6),
            (800, 600): (6, 5),
            (200, 0):   (1, 0),
            (200, 800): (1, 6),
            (800, 400): (6, 3),
            (0, 600):   (0, 5),
            (0, 200):   (0, 1),
            (0, 400):   (0, 3),
            (800, 200): (6, 1),
            (400, 0):   (3, 0),
            (600, 800): (5, 6),
            (600, 0):   (5, 0) }
        self.inv_push_in_map = {v:k for k, v in self.game_push_in_map.items()}
        self.game_push_in_rects = (
            Rect(400, 800, 100, 100),
            Rect(800, 600, 100, 100),
            Rect(200, 0, 100, 100),
            Rect(200, 800, 100, 100),
            Rect(800, 400, 100, 100),
            Rect(0, 600, 100, 100),
            Rect(0, 200, 100, 100),
            Rect(0, 400, 100, 100),
            Rect(800, 200, 100, 100),
            Rect(400, 0, 100, 100),
            Rect(600, 800, 100, 100),
            Rect(600, 0, 100, 100) )
            
        self.menu = StartMenu(self.screen)
            
    def game_loop(self):
        """Game loop for capturing user input, displaying screens,
        updating players and squares.
        """
        
        def process_human_move():
            pygame.time.wait(100)
            for event in pygame.event.get():
                if event.type not in [pygame.QUIT, MOUSEBUTTONDOWN, MOUSEMOTION]:
                    continue 
                if event.type == pygame.QUIT:
                    sys.exit()
                elif event.type == MOUSEBUTTONDOWN:
                    if event.button == 1:
                        if self.game_phase == "push":
                            if self.mouse_over_push_in(event.pos)[0]:
                                self.board.current_tile.rotate()
                        elif self.game_phase == "move":
                            square = self.mouse_over_board(event.pos)
                            if square:
                                #TODO function for this?
                                if self.board.path_exists(
                                    self.board.current_player.location, square):
                                    self.board.update_player_location(
                                        self.board.current_player, square)
                                    if self.board.update_player_item(self.board.current_player, square) == "winner":
                                        self.game_phase == "won"
                                    self.board.next_active_player()
                                    self.game_phase = "push"
                                    self.game_history.append(self.board)
                                    self.move_number += 1
                    elif event.button == 3:
                        if self.game_phase == "push":
                            if self.mouse_over_push_in(event.pos)[0]:
                                if self.mouse_over_push_in(event.pos)[2] != self.board.last_pushed_out:
                                    self.board.push_in(self.mouse_over_push_in(event.pos)[2])
                                    self.game_phase = "move"
                            
                elif event.type == MOUSEMOTION:
                    is_hover = self.mouse_over_push_in(event.pos)
                    if is_hover[0]:
                        self.is_hover = is_hover[1]
                    else:
                        self.is_hover = False    
            self.display_everything()
            
        def process_computer_move():
            if self.game_phase == "push":
                
                #do push and move together
                #~ print "before find_move", hash(self.board)
                rotation, push_in, new_square = self.board.current_player.find_move(self.board)
                #~ rotation, push_in, new_square = (0, (1,0), self.board.current_player.location)
                #~ print "after find_move", hash(self.board)
                
                self.board.current_tile.rotate_n_times(rotation)
                self.board.push_in(push_in)
                #~ pygame.time.wait(2000)
                self.board.update_player_location(self.board.current_player, new_square)
                if self.board.update_player_item(self.board.current_player, new_square) == "winner":
                    self.game_phase = "won"
                self.board.next_active_player()
                self.game_history.append(self.board)
                self.move_number += 1
                self.display_everything()
            
        def collect_start_screen_input():
            pygame.time.wait(100)
            for event in pygame.event.get():
                if event.type not in [pygame.QUIT, MOUSEBUTTONDOWN, MOUSEMOTION]:
                    continue 
                if event.type == pygame.QUIT:
                    sys.exit()
                elif event.type == MOUSEBUTTONDOWN:
                    if event.button == 1:
                        if self.menu.mouse_click_button(event.pos) is True:
                            self.num_computer_players = self.menu.n_players
                            self.num_players = (
                                self.num_human_players + self.num_computer_players)
                            #~ print self.num_players, self.num_human_players, self.num_computer_players
                            # Initialise Game
                            self.setup_tiles()
                            #players must be setup after tiles
                            self.init_players()
                            self.load_images()
                            self.game_phase = "push"
            self.menu.display_menu()
        
        self.game_history.append(self.board)    
        self.menu.display_menu()
        # Game Loop
        while 1:
            if self.game_phase == "start":
                collect_start_screen_input()
            elif self.game_phase == "won":
                self.display_everything().game_over_screen()
            elif (self.game_phase == "move" and not
                  self.board.possible_moves_exist(self.board.current_player)):
                self.board.next_active_player()
                self.game_phase = "push"
                self.game_history.append(self.board)
                self.move_number += 1
            elif self.board.current_player.iscomputer is False:
                process_human_move()
            elif self.board.current_player.iscomputer is True:
                process_computer_move()
        
    def display_everything(self):
        """Draw everything to the screen"""
        
        def blit_tile(tile_obj, tile_rect, surface):
            """Blit a single tile with image
            tile_obj is a BoardTile instance
            tile_rect is the Rect obj
            surface is the surface to blit to
            """
            tile_image = pygame.image.fromstring(
                self.image_buffer[tile_obj.tile_type], (100,100), "RGBA")
            tile_rotation = tile_obj.tile_image_rotation()
            final_tile = pygame.transform.rotate(tile_image, tile_rotation)
            surface.blit(final_tile, tile_rect)
            
            if tile_obj.item:
                item = tile_obj.item
                item_image = pygame.image.fromstring(
                    self.image_buffer[item], (100,100), "RGBA")
                surface.blit(item_image, tile_rect)
                
        def blit_card(card, card_rect, surface):
            """Blit a single card
            str card
            Rect card_rect
            Surface surface
            """
            basecard_image = pygame.image.fromstring(
                self.image_buffer['basecard'], (100,100), "RGBA")
            surface.blit(basecard_image, card_rect)
            card_image = pygame.image.fromstring(
                self.image_buffer[card], (100,100), "RGBA")
            surface.blit(card_image, card_rect)
            
        def blit_player(player_obj, surface, coords=None):
            """Blit a player figure to the board"""
            if coords == None:
                coords = (player_obj.location[0]*100, player_obj.location[1]*100)
            dims = (100,100)
            
            player_color = player_obj.color
            player_figure = player_obj.player_images[player_color]
            player_image = pygame.image.fromstring(
                self.image_buffer[player_figure], (100,100), "RGBA")
            player_square = player_obj.location
            player_rect = Rect((coords),(dims))
            surface.blit(player_image, player_rect)
            
        def blit_text(surface, text, color, rect, font, aa=False, bkg=None):
            """Draw some text into an area of a surface
            automatically wraps words
            returns any text that didn't get blitted
            """
            rect = Rect(rect)
            y = rect.top
            lineSpacing = -2
         
            # get the height of the font
            fontHeight = font.size("Tg")[1]
         
            while text:
                i = 1
         
                # determine if the row of text will be outside our area
                if y + fontHeight > rect.bottom:
                    break
         
                # determine maximum width of line
                while font.size(text[:i])[0] < rect.width and i < len(text):
                    i += 1
         
                # if we've wrapped the text, then adjust the wrap to the last word      
                if i < len(text): 
                    i = text.rfind(" ", 0, i) + 1
         
                # render the line and blit it to the surface
                if bkg:
                    image = font.render(text[:i], 1, color, bkg)
                    image.set_colorkey(bkg)
                else:
                    image = font.render(text[:i], aa, color)
         
                surface.blit(image, (rect.left, y))
                y += fontHeight + lineSpacing
         
                # remove the text we just blitted
                text = text[i:]
            return text
            
        def blit_push_in_rect(surface, color, rect):
            """push in rects are green
            except the one where you may not push!
            """
            pygame.draw.rect(surface, color, rect)
            
        def game_over_screen():
            """Blit a final screen for game over"""
            self.screen.fill(self.background_color)
            blit_text(
                self.screen,
                "Game Over!",
                (0,0,0),
                (400,500,190,190),
                myfont )
            raw_input()
        
        # Background
        self.screen.fill(self.background_color)
        self.menu_area.fill(self.menu_background_color)
        
        # Board
        for square in self.board:
            #TODO Perf improve?: only blit rects where obj hash has changed
            # Tiles
            tile = self.board[square]
            rect = Rect(square[0]*100,square[1]*100,100,100)
            surf = self.board_area
            blit_tile(tile, rect, surf)
                
        # Player Figures
        for player in self.board.active_players:
            blit_player(player, self.board_area)
             
        # Push-In Squares at edges
        if self.board.last_pushed_out:
            last_pushed_out = self.board.last_pushed_out
            last_pushed_out_rect = Rect(
                (self.inv_push_in_map[last_pushed_out]), (100,100))
            blit_push_in_rect(
                self.game_area, self.color_no_push_in, last_pushed_out_rect)
        else:
            last_pushed_out_rect = None
            
        for rect in self.game_push_in_rects:
            if ((rect != self.is_hover) and (rect != last_pushed_out_rect)):
                blit_push_in_rect(self.game_area, self.color_push_in_rect, rect)
                
        if (self.is_hover and self.is_hover != last_pushed_out_rect):
            tile = self.board.current_tile
            rect = self.is_hover
            surf = self.game_area
            blit_tile(tile, rect, surf)
        
        # Labels
        myfont = pygame.font.SysFont("monospace", 15, bold=True)
        card_label = myfont.render("Current Card", 1, (0,0,0))
        tile_label = myfont.render("Current Tile", 1, (0,0,0))
        player_label = myfont.render(
            "Current Player: {}".format(self.board.current_player.color), 1, (0,0,0))
        player_remaining_cards = myfont.render(
            "Cards: {}".format(
                self.board.current_player.remaining_cards()), 1, (0,0,0))
        self.menu_area.blit(card_label, (50, 130))
        self.menu_area.blit(tile_label, (50, 255))
        self.menu_area.blit(player_label, (5, 380))
        self.menu_area.blit(player_remaining_cards, (5, 395))
        
        # Current Card
        card = self.board.current_player.current_card
        rect = Rect(50,25,100,100)
        surf = self.menu_area
        blit_card(card, rect, surf)
        
        # Current Tile
        tile = self.board.current_tile
        rect =  Rect(50,150,100,100)
        surf = self.menu_area
        blit_tile(tile, rect, surf)
        
        # Current Player in menu
        blit_player(self.board.current_player, self.menu_area, (50,275))
        
        # Text box
        blit_text(self.menu_area, self.text_message_box[self.game_phase],
            (0,0,0), (5,500,190,190), myfont)
            
        # Game Border
        border_color = (0,0,0)
        game_area_rect = (0,0,900,900)
        border_width = 4
        pygame.draw.rect(self.game_area, border_color, game_area_rect, border_width)
        
        # Update display
        pygame.display.flip()
            
    def mouse_over_push_in(self, mouse_location):
        """Test if mouse hovering over a push in location
        Return (True|False, tilerect, square)
        """
        mouse_x, mouse_y = mouse_location
        for _rect in self.game_push_in_rects:
            if _rect.collidepoint(mouse_x-200, mouse_y):
                _rectpos = (_rect.left,_rect.top)
                return (True, _rect, self.game_push_in_map[_rectpos])
        return (False,False,False)
        
    def mouse_over_board(self, mouse_location):
        """Test if mouse over the board
        Return square or False
        """
        mouse_x, mouse_y = mouse_location
        if not ((300 <= mouse_x < 1000) and (100 <= mouse_y < 800)):
            return False
        else:
            x_pos = (mouse_x - 300) / 100
            y_pos = (mouse_y - 100) / 100
            return (x_pos,y_pos)
        
    def setup_tiles(self):
        """Initialise all tile objects
        Allocate tile objects to board positions
        """
        
        items_list = [i for i in self.items]                                   #each item once
        actions_list = [j for k in [[i,i] for i in self.actions] for j in k]   #each action twice
        colors_list = [i for i in self.player_home_colors]                          #each color once
        shuffle(items_list)
        shuffle(actions_list)
        
        ## Fixed Cards
        #corners
        self.board[(0,0)] = BoardTile([False,True,True,False])
        self.board[(0,6)] = BoardTile([True,True,False,False])
        self.board[(6,6)] = BoardTile([True,False,False,True])
        self.board[(6,0)] = BoardTile([False,False,True,True])
        
        #edges
        self.board[(0,2)] = BoardTile([True,True,True,False], item=items_list.pop())
        self.board[(2,0)] = BoardTile([False,True,True,True], item=items_list.pop())
        self.board[(4,0)] = BoardTile([False,True,True,True], item=items_list.pop())
        self.board[(0,4)] = BoardTile([True,True,True,False], item=items_list.pop())
        self.board[(6,2)] = BoardTile([True,False,True,True], item=items_list.pop())
        self.board[(2,6)] = BoardTile([True,True,False,True], item=items_list.pop())
        self.board[(6,4)] = BoardTile([True,False,True,True], item=items_list.pop())
        self.board[(4,6)] = BoardTile([True,True,False,True], item=items_list.pop())
        
        #centers
        self.board[(2,2)] = BoardTile([False,True,True,True], item=items_list.pop(), random_orientation=True)
        self.board[(4,2)] = BoardTile([False,True,True,True], item=items_list.pop(), random_orientation=True)
        self.board[(2,4)] = BoardTile([False,True,True,True], item=items_list.pop(), random_orientation=True)
        self.board[(4,4)] = BoardTile([False,True,True,True], item=items_list.pop(), random_orientation=True)
        ## Distributed Cards
        tiles = []
        #6 with three exits, all contain item, no actions
        for i in xrange(0,6):
            tiles.append(BoardTile([False,True,True,True], item=items_list.pop(), random_orientation=True))
        #6 straight through exits, no items, actions
        for i in xrange(0,6):
            tiles.append(BoardTile([False,True,False,True], action=actions_list.pop(), random_orientation=True))
        #6 straight through exits, no items, no actions
        for i in xrange(0,6):
            tiles.append(BoardTile([False,True,False,True], random_orientation=True))
        #6 corner exits, no items, contain actions
        for i in xrange(0,6):
            tiles.append(BoardTile([True,True,False,False], action=actions_list.pop(), random_orientation=True))
        #4 corner exits, no items, no actions
        for i in xrange(0,4):
            tiles.append(BoardTile([True,True,False,False], random_orientation=True))
        #6 corner exits, items, no actions
        for i in xrange(0,6):
            tiles.append(BoardTile([True,True,False,False], item=items_list.pop(), random_orientation=True))
            
        #Check all items and actions assigned
        if len(items_list) != 0:
            raise Exception("Leftover tiles!")
        if len(actions_list) != 0:
            raise Exception("Leftover actions!")
            
        #shuffle tiles before distributing to remaining board positions
        shuffle(tiles)

        #Assign tiles to remaining squares
        for square in self.board.movable_squares:
            self.board[square] = tiles.pop()
        
        #Remaining tile is the start tile
        self.board.current_tile = tiles.pop()
        
        # Set player home squares
        for square in ( (0,0), (0,6), (6,6), (6,0) ):
            self.board[square].item = colors_list.pop()
        
    def init_players(self):
        """Initialise the human and computer player objects
        2 <= (Human players + Computer players) <= 4
        """
        ## Setup players
        available_color_locations = [('blue',   (0,0)),
                                     ('red',    (6,0)),
                                     ('green',  (0,6)),
                                     ('yellow', (6,6)) ]
        human_players = []
        computer_players = []
        
        for i in xrange(0, self.num_human_players):
            player = Player(available_color_locations.pop())
            player.isactive = True
            human_players.append(player)
            
        for i in xrange(0, self.num_computer_players):
            player = ComputerPlayer(available_color_locations.pop())
            player.isactive = True
            computer_players.append(player)
            
        self.board.active_players = computer_players + human_players
            
        # Setup Cards
        self.cards_per_player = len(self.items)
        shuffle(self.items)
        hands = [self.items[i::self.num_players] for i in range(0, self.num_players)]
        
        for player in self.board.active_players:
            player.cards = hands.pop()
            player.draw_card()
                
        # Set squares to occupied
        for player in self.board.active_players:
            self.board[player.location].add_resident(player)
        
        # Current Player to go
        self.board.current_player = self.board.active_players[0]
        
        # Generate test object for unittest - remove later
        #~ _f = open("testPlayer2.pickle", "a")
        #~ self.board.next_active_player()
        #~ pickle.dump(self.board.current_player, _f, pickle.HIGHEST_PROTOCOL)
        #~ _f.close
        #~ print self.board.current_player.isactive
        #~ print self.board.current_player.name
        #~ print self.board.current_player.color
        #~ print self.board.current_player.cards
        #~ print self.board.current_player.location
        #~ print self.board.current_player.home
        #~ print self.board.current_player.current_card
        #~ print self.board.current_player.found_cards
        #~ print self.board.current_player.iscomputer
        #~ print self.board.current_player.__str__()
        #~ print self.board.current_player.__hash__()
        #~ print hash(self.board.current_player)
        
        
    def load_images(self):
        """Load tile images into string buffers
        store buffers in the dict self.image_buffer
        """
        image_filename = {
                            'genie': 'item-genie-100px.png',
                            'map': 'item-map-100px.png',
                            'book': 'item-book-100px.png',
                            'bat': 'item-bat-100px.png',
                            'skull': 'item-skull-100px.png',
                            'ring': 'item-ring-100px.png',
                            'sword': 'item-sword-100px.png',
                            'candles': 'item-candles-100px.png',
                            'gem': 'item-gem-100px.png',
                            'lizzard': 'item-lizzard-100px.png',
                            'spider': 'item-spider-100px.png',
                            'purse': 'item-purse-100px.png',
                            'chest': 'item-chest-100px.png',
                            'beetle': 'item-beetle-100px.png',
                            'owl': 'item-owl-100px.png',
                            'keys': 'item-keys-100px.png',
                            'dwarf': 'item-dwarf-100px.png',
                            'helmet': 'item-helmet-100px.png',
                            'fairy': 'item-fairy-100px.png',
                            'moth': 'item-moth-100px.png',
                            'dragon': 'item-dragon-100px.png',
                            'mouse': 'item-mouse-100px.png',
                            'ghost': 'item-ghost-100px.png',
                            'crown': 'item-crown-100px.png',
                            'straight': 'tile-tftf-100px.png',
                            'corner': 'tile-ttff-100px.png',
                            'tee': 'tile-ttft-100px.png',
                            'home-red': 'home-red-100px.png',
                            'home-green': 'home-green-100px.png',
                            'home-blue': 'home-blue-100px.png',
                            'home-yellow': 'home-yellow-100px.png',
                            'basecard': 'basecard-100px.png',
                            'player-yellow': 'player-yellow-100px.png',
                            'player-blue': 'player-blue-100px.png',
                            'player-green': 'player-green-100px.png',
                            'player-red': 'player-red-100px.png' }
        image_surface = {}
        for image in image_filename.keys():
            image_surface[image] = pygame.image.load(
                os.path.join(self.image_dir, image_filename[image]))
        for surface in image_surface.keys():
            self.image_buffer[surface] = pygame.image.tostring(image_surface[surface], "RGBA")
Esempio n. 14
0
 def setUp(self):
     self.start_menu = StartMenu('Tasapeli')
Esempio n. 15
0
def main():
    #pygame.display.set_mode((800,600))
    e = Engine()
    e.current_state = StartMenu()
    e.run()