Beispiel #1
0
    def endGame(self, success):
        """
        Finish the game.
        """

        self.gameOver = True # avoids recursion issues during cleardown

        # clear down the grid
        for button in self.buttons:
            if button.exposed: continue

            elif button.flagged:
                if button.mined: # button correctly flagged
                    button.set_sensitive(False)

                else: # incorrect flag - remove it
                    button.flagged = False
                    button.set_active(True)
                    self.updateFlags(False)
                    button.leftMouse(button)

            else:  # 'press' the button
                button.leftMouse(button)

        # update the start button image
        if success:
            updateImage(self.parent.startImage, 'Win', TOOL_SIZE)
        else:
            updateImage(self.parent.startImage, 'Lose', TOOL_SIZE)

        # update the sensitivity of the other toolbar buttons
        self.parent.hintButton.set_sensitive(False)
        self.parent.pbcButton.set_sensitive(True)
        self.parent.configurationBox.set_button_sensitivity(
                                                        Gtk.SensitivityType.ON)
Beispiel #2
0
    def resize(self, imageSize):
        """
        Resize the grid button's child (image or text) to match the current
        window size. (The button looks after itself.)
        """

        self.imageSize = imageSize
        updateImage(self.image, self.imageKey, self.imageSize)
Beispiel #3
0
    def on_button_press_event(self, widget, event):
        """
        Event handler for button presses. The handler must decide which
        mouse button was clicked. We are only interested in leftMouse clicks.
        """

        # determine left- or right- click, feed the appropriate method.
        if event.get_button()[1] == 1:  # left-mouse
            updateImage(self.parent.parent.startImage, 'Click', TOOL_SIZE)
Beispiel #4
0
    def on_pbcButton_toggled(self, widget):
        """
        Handler for the periodic boundary condition button.
        """

        if self.pbcButton.get_active():
            updateImage(self.pbcImage, 'PBC_On', TOOL_SIZE)
        else:
            updateImage(self.pbcImage, 'PBC_Off', TOOL_SIZE)
Beispiel #5
0
    def setupStatusBarIcon(self, iconName, imageName):
        """
        Add an icon image to a status bar button.
        """

        icon = self.builder.get_object(iconName)
        image = getImage(imageName)
        updateImage(image, imageName, STATUS_SIZE)
        icon.add(image)
        return icon
Beispiel #6
0
    def start(self):
        """
        Start a new game.
        """

        self.saveConfiguration()

        # reset the start button image
        updateImage(self.startImage, 'Start', TOOL_SIZE)

        # get the grid information from the configuration box.
        activeConfiguration = self.configurationBox.get_active_iter()
        cols, rows, nMines = tuple(self.configurations[activeConfiguration])[2:]

        mines = [True] * nMines
        mines.extend([False] * (cols * rows - nMines))
        random.shuffle(mines)

        # reset the status bar
        self.exposedCount.set_text('0')
        self.exposedLabel.set_text('/ ' + str(cols * rows - nMines))
        self.hintCount.set_text('0')
        self.flagCount.set_text('0')
        self.flagLabel.set_text('/ ' + str(nMines))

        # destroy any pre-existing game
        if self.gameGrid != None: self.gameGrid.destroy()

        # 'force' re-size at the start of the game
        self.previousAllocation = None

        # make the new game
        self.gameGrid = GridWindow(parent=self,
                                   cols=cols, rows=rows, mines=mines)
        self.gridContainer.add_with_viewport(self.gameGrid)

        # configure the toolbar widgets sensitivity
        self.hintButton.set_sensitive(True)  # enable hints during a game
        self.pbcButton.set_sensitive(False)  # can't change pbc during a game
        self.configurationBox.set_button_sensitivity(Gtk.SensitivityType.OFF)

        # start the game
        self.gameGrid.start()
        self.gameGrid.giveHint()
        self.window.show_all()
Beispiel #7
0
    def __init__(self, parent=None, pos=None, mined=False):
        """
        Do the class initialization and prepare the game-specific
        attributes.
        """

        super().__init__()

        # the game grid parent
        self.parent = parent

        # give the button a name for css styling
        self.set_name("gridButton")

        # this button's grid position.
        self.pos = pos

        # is this button mined?
        self.mined = mined
        self.exploded = False

        # is this button flagged? - initialize to False
        self.flagged = False

        # initialize the mine count to zero
        self.neighbourMines = 0

        # initialize the neighbour flag count to zero
        self.neighbourFlags = 0

        # flag to emulate disabled when mines are exposed
        self.exposed = False

        # initialize the image to empty at 20 pixels
        self.imageKey = 'Empty'
        self.imageSize = GRID_SIZE
        self.image = getImage(self.imageKey)
        self.add(self.image)
        updateImage(self.image, self.imageKey, self.imageSize)

        # set up the GTK event handlers
        self.connect("button_press_event", self.on_button_press_event)
        self.connect("button_release_event", self.on_button_release_event)
Beispiel #8
0
    def explodeGame(self):
        """
        Make an explosion effect on the screen as the grid is destroyed.
        """

        # obtain the size of the playing area
        size = (self.gridContainer.get_allocated_width(),
                self.gridContainer.get_allocated_height())

        # make the explosion flashImage
        flashImage = getImage('Explosion')
        updateImage(flashImage, 'Explosion', size)
        self.gridContainer.add_with_viewport(flashImage)

        # flash the explosion 5 times
        for i in range(5):

            # display the explosion
            updateImage(self.startImage, 'Click', TOOL_SIZE)
            flashImage.show()
            pause(100)  # wait 200ms without blocking the Gtk event loop

            # hide the explosion
            updateImage(self.startImage, 'Lose', TOOL_SIZE)
            flashImage.hide()
            pause(100)  # wait 200ms without blocking the Gtk event loop

        # ... then destroy the explosion image
        flashImage.destroy()
Beispiel #9
0
    def rightMouse(self):
        """
        Right-Mouse handler. We use this to toggle mine flags.
        """

        # action exclusions
        if not self.get_sensitive(): return
        if self.exposed: return

        # toggle the flag state
        self.flagged = not self.flagged
        self.set_active(self.flagged)

        # update the button image
        if self.flagged:
            self.imageKey = 'Flag'
        else:
            self.imageKey = 'Empty'
        updateImage(self.image, self.imageKey, self.imageSize)

        # notify neighbours and parent of the change
        self.parent.updateFlags(self.flagged)
        for neighbour in self.neighbourList:
            neighbour.updateNeighbourFlags(self.flagged)
Beispiel #10
0
    def leftMouse(self, widget):
        """
        Left-Mouse handler. We use this to clear the area.
        """

        # action exclusions
        if self.flagged:
            if widget == self and not self.parent.exploded:
                self.set_active(False)  # TODO: not sure why this works
                updateImage(self.parent.parent.startImage, 'Start', TOOL_SIZE)
            return False
        if self.exposed or self.exploded:
            return False

        # disable the button and change its colour once it has been left-clicked
        self.set_sensitive(False)
        if not self.parent.exploded: self.set_active(True)

        exposedNeighbours = 0

        # end game - we hit a mine - lose
        if self.mined:
            self.exploded = True

            # choose the image
            if self.parent.exploded:  # cleardown mode
                self.imageKey = 'UXB'
            else:  # normal mode
                self.set_active(True)
                self.imageKey = 'Explosion'  # lose

            updateImage(self.image, self.imageKey, self.imageSize)

            # short pause to let gtk events sort themselves out
            if not self.parent.exploded:
                pause(200)
                self.parent.exploded = True  # notify end-game

        else:  # expose the button, display the number of neighbour mines
            self.exposed = True

            # update the image
            self.imageKey = 'Empty'
            if self.neighbourMines > 0:
                self.imageKey = str(self.neighbourMines)
            updateImage(self.image, self.imageKey, self.imageSize)

            # propagate exposure to the neighbours if mines = flags
            if self.neighbourFlags == self.neighbourMines:
                for neighbour in self.neighbourList:
                    exposedNeighbours += neighbour.leftMouse(widget)

        # update count of exposed buttons - potential win end game
        exposedNeighbours += 1  # add self to the count
        if widget == self:
            self.parent.incrementExposedCount(exposedNeighbours)

            # reset the start button image
            if not self.parent.gameOver:
                updateImage(self.parent.parent.startImage, 'Start', TOOL_SIZE)

        else: return exposedNeighbours
Beispiel #11
0
    def initializeGUI(self):
        """
        Load the main GUI elements from the .glade file.
        """

        self.builder = Gtk.Builder()
        self.builder.add_from_file(UI_BUILD_FILE)
        self.builder.connect_signals(self)

        # these are the toolbar widgets...

        # game start
        self.startButton = self.builder.get_object('startButton')
        self.startImage = getImage('Start')
        updateImage(self.startImage, 'Start', TOOL_SIZE)
        self.startButton.add(self.startImage)

        # hint request
        self.hintButton = self.builder.get_object('hintButton')
        self.hintImage = getImage('Hint')
        updateImage(self.hintImage, 'Hint', TOOL_SIZE)
        self.hintButton.add(self.hintImage)
        self.hintButton.set_sensitive(False)

        # periodic boundary condition toggle
        self.pbcButton = self.builder.get_object('pbcButton')
        self.pbcImage = getImage('PBC_Off')
        updateImage(self.pbcImage, 'PBC_Off', TOOL_SIZE)
        self.pbcButton.add(self.pbcImage)
        self.pbcButton.set_sensitive(True)

        # the configurationBox and its model
        self.configurations = self.builder.get_object('configurations')
        self.configurationBox = self.builder.get_object('configurationBox')

        # an alternative quit button
        self.resetButton = self.builder.get_object('resetButton')
        self.resetImage = getImage('Reset')
        updateImage(self.resetImage, 'Reset', TOOL_SIZE)
        self.resetButton.add(self.resetImage)

        # these are the status bar widgets...

        # ...exposed count
        self.exposedIcon = self.setupStatusBarIcon('exposedIcon', 'Exposed')
        self.exposedCount = self.builder.get_object('exposedCount')
        self.exposedLabel = self.builder.get_object('exposedLabel')

        # ...hint count
        self.hintIcon = self.setupStatusBarIcon('hintIcon', 'Query')
        self.hintCount = self.builder.get_object('hintCount')

        # ...flag count
        self.flagIcon = self.setupStatusBarIcon('flagIcon', 'Flag')
        self.flagCount = self.builder.get_object('flagCount')
        self.flagLabel = self.builder.get_object('flagLabel')

        # the game grid (blank for now)
        self.gridContainer = self.builder.get_object('gridContainer')
        self.gameGrid = None
        self.previousAllocation = self.gridContainer.get_allocation()

        # get references to the toolbar and status bar for size data.
        self.toolbar = self.builder.get_object('toolBox')
        self.statusbar = self.builder.get_object('statusBox')

        # get a reference to the main window itself and display the window
        self.window = self.builder.get_object('window')