from panopticon_swarm.pgfw.Setup import Setup

if __name__ == "__main__":
    Setup().setup()
from panopticon_swarm.pgfw.SetupWin import SetupWin

if __name__ == "__main__":
    SetupWin.setup()
from pprint import pprint

from panopticon_swarm.pgfw.Game import Game
from panopticon_swarm.pgfw.Configuration import TypeDeclarations
from panopticon_swarm.pytmx import pytmx

class PanopticonSwarm(Game):

    def __init__(self):
        Game.__init__(self, type_declarations=Types())
        print self.get_configuration().resources_path


class Types(TypeDeclarations):

    additional_defaults = {"joy": {"int": ["action", "rotate-right",
                                           "rotate-left", "advance", "retreat",
                                           "confirm", "pause"]}}
from sys import platform


if __name__ == "__main__":
    if platform == "darwin":
        from setuptools import setup, find_packages
        from lib.pgfw.pgfw.Configuration import Configuration
        from lib.pgfw.pgfw.Setup import Setup
        config = Configuration()
        setup_obj = Setup()
        version = config.get_section("setup")["version"]
        name = setup_obj.translate_title()
        plist = dict(
            CFBundleIconFile=name,
            CFBundleName=name,
            CFBundleShortVersionString=version,
            CFBundleGetInfoString=' '.join([name, version]),
            CFBundleExecutable=name,
            CFBundleIdentifier='org.' + name.lower())
        setup(name=name,
              version=version,
              app=[dict(script="OPEN-GAME", plist=plist)],
              setup_requires=["py2app"],
              options=dict(py2app=dict(arch="i386",)),
              data_files=["wisp", "resource", "lib", "config", "OFL.txt"])
    elif platform == "win32":
        from lib.pgfw.pgfw.SetupWin import SetupWin
        SetupWin().setup()
    else:
        from lib.pgfw.pgfw.Setup import Setup
        Setup().setup()
from os.path import basename, join
from random import random, randrange, choice, randint
from glob import glob
from array import array

from pygame import PixelArray, Surface, Color, joystick
from pygame.event import clear, Event
from pygame.image import load, save
from pygame.transform import flip, scale
from pygame.mixer import Sound, set_num_channels, get_num_channels
from pygame.locals import *

from lib.pgfw.pgfw.Game import Game
from lib.pgfw.pgfw.GameChild import GameChild
from lib.pgfw.pgfw.Animation import Animation
from lib.pgfw.pgfw.Sprite import Sprite
from lib.pgfw.pgfw.extension import (get_color_swapped_surface, get_delta,
                                     get_busy_channel_count)

class PictureProcessing(Game):

    SCALE = 3
    CHANNEL_COUNT = 16
    KEYBOARD, GAMEPAD = xrange(2)

    def __init__(self):
        Game.__init__(self)
        set_num_channels(self.CHANNEL_COUNT)
        self.sound_effects = SoundEffects(self)
        self.glyphs = Glyphs(self)
        self.levels = Levels(self)
        self.interface = Interface(self)
        self.title = Title(self)
        self.introduction = Introduction(self)
        self.ending = Ending(self)
        self.subscribe(self.respond)
        self.reset()
        clear()

    def respond(self, event):
        if self.delegate.compare(event, "reset-game"):
            self.reset()

    def reset(self):
        self.title.reset()
        self.levels.reset()
        self.interface.reset()
        self.introduction.reset()
        self.ending.reset()

    def get_progress(self):
        return map(int, open(self.get_resource("progress")).read().split())

    def write_progress(self, level_index, swap_count, update=False):
        if update:
            swap_count += self.get_progress()[1]
        open(self.get_resource("progress"), "w").write("%s %s\n" % (str(level_index),
                                                                    str(swap_count)))

    def select_text(self, texts):
        return texts[self.is_gamepad_mode()]

    def is_gamepad_mode(self):
        return not self.check_command_line("-keyboard") and joystick.get_count()

    def update(self):
        self.introduction.update()
        self.title.update()
        self.levels.update()
        self.interface.update()
        self.ending.update()


class SoundEffects(GameChild):

    def __init__(self, parent):
        GameChild.__init__(self, parent)
        effects = self.effects = []
        for path in glob(join(self.get_resource("aud/effect"), "*.wav")):
            effects.append(SoundEffect(self, path))

    def play(self, name, volume=None):
        for effect in self.effects:
            if effect.name == name:
                effect.play(volume=volume)


class SoundEffect(GameChild, Sound):

    DEFAULT_VOLUME = .5

    def __init__(self, parent, path, volume=DEFAULT_VOLUME):
        GameChild.__init__(self, parent)
        Sound.__init__(self, path)
        self.name = basename(path).split(".")[0]
        self.display_surface = self.get_display_surface()
        self.set_volume(volume)

    def play(self, loops=0, maxtime=0, fade_ms=0, position=None, x=None, volume=None):
                 
        channel = Sound.play(self, loops, maxtime, fade_ms)
        if x is not None:
            position = float(x) / self.display_surface.get_width()
	if position is not None and channel is not None:
            channel.set_volume(*self.get_panning(position))
        return channel

    def get_panning(self, position):
        return 1 - max(0, ((position - .5) * 2)), \
               1 + min(0, ((position - .5) * 2))


class Glyphs(GameChild):

    TILE_SIZE = 8
    TRANSPARENT_COLOR = (255, 0, 255)
    LETTER_COLOR = (255, 255, 255)

    def __init__(self, parent):
        GameChild.__init__(self, parent)
        sheet = load(self.get_resource("font.png")).convert()
        sheet.set_colorkey(sheet.get_at((0, 0)))
        tiles = self.tiles = []
        for y in xrange(0, sheet.get_height(), self.TILE_SIZE):
            surface = Surface([self.TILE_SIZE] * 2)
            surface.set_colorkey(self.TRANSPARENT_COLOR)
            surface.fill(self.TRANSPARENT_COLOR)
            surface.blit(sheet, (0, -y))
            surface = scale(surface, [surface.get_width() * \
                                      PictureProcessing.SCALE] * 2)
            tiles.append(surface)

    def get_surface_from_text(self, text, color=None, spacing=1,
                              key=TRANSPARENT_COLOR, background=None):
        tw, th = self.tiles[0].get_size()
        surface = Surface((len(text) * tw + spacing * len(text), th))
        if background is None:
            surface.set_colorkey(key)
            surface.fill(key)
        else:
            surface.fill(background)
        for ii, x in enumerate(xrange(0, surface.get_width(), tw + spacing)):
            surface.blit(self.get_tile(ord(text[ii]), color), (x, 0))
        return surface

    def get_tile(self, index, color=None):
        tile = self.tiles[index]
        if color is not None:
            tile = tile.copy()
            pixels = PixelArray(tile)
            pixels.replace(self.LETTER_COLOR, color)
            del pixels
        return tile


class Levels(GameChild):

    CLIP_SETTINGS = ((.325, 5512), (.25, 11025), (.5, 11025), (.75, 11025), (.75, 11025))

    def __init__(self, parent):
        GameChild.__init__(self, parent)
        levels = self.levels = []
        for directory in sorted(glob(join(self.get_resource("tiles"),
                                          "[0-9]*"))):
            levels.append(Level(self, directory))

    def reset(self):
        self.deactivate()
        self.current_level = self.levels[0]

    def deactivate(self):
        self.active = False
        self.stop_audio()
        self.get_game().interface.deactivate()

    def activate(self):
        self.active = True

    def stop_audio(self):
        for level in self.levels:
            level.stop_all_audio()

    def get_current_level_index(self):
        return self.levels.index(self.current_level)

    def is_final_level(self):
        return self.get_current_level_index() == len(self.levels) - 1

    def load_next_level(self):
        self.levels[self.get_current_level_index() + 1].load()

    def update(self):
        if self.active:
            self.current_level.update()


class Level(GameChild):

    def __init__(self, parent, directory):
        GameChild.__init__(self, parent)
        self.display_surface = self.get_display_surface()
        tiles = self.tiles = []
        original = self.original_tiles = []
        for path in sorted(glob(join(directory, "*.png"))):
            original.append(load(path).convert_alpha())
            tiles.append(scale(original[-1], [original[-1].get_width() * \
                                              PictureProcessing.SCALE] * 2))
        colored = self.colored_tiles = {}
        rects = self.tile_rects = {}
        block = 0
        for line in open(join(directory, "map")):
            if line.strip() == "":
                block += 1
            elif block == 0:
                fields = line.split("-")
                if len(fields) == 1:
                    self.default_tile_index = int(fields[0])
                else:
                    for field in line.split("-"):
                        digits = map(int, field.split())
                        if len(digits) == 1:
                            index = digits[0]
                            rects[index] = []
                        elif len(digits) == 3:
                            surface = Surface(tiles[index].get_size())
                            surface.fill(digits)
                            surface.blit(tiles[index], (0, 0))
                            colored[index] = surface
                        else:
                            if len(digits) == 2:
                                digits *= 2
                            rects[index].append((digits[0:2], digits[2:4]))
        path = glob(join(self.get_resource("aud/level"), basename(directory) + "*"))[0]
        self.full_audio = Sound(path)
        self.clip_audio = None

    def load(self):
        self.parent.activate()
        self.parent.current_level = self
        self.set_audio()
        self.set_swap_status()
        self.parent.stop_audio()
        self.clip_audio.play(-1)
        self.get_game().interface.setup()

    def set_audio(self):
        samples = array("h", self.full_audio.get_buffer().raw)
        volume, count = Levels.CLIP_SETTINGS[self.parent.get_current_level_index()]
        index = randrange(0, len(samples) - count)
        clip = self.clip_audio = Sound(samples[index:index + count])
        clip.set_volume(volume)

    def set_swap_status(self):
        swap_status = self.swap_status = {}
        swapped = False
        indicies = set(self.tile_rects.keys() + [self.default_tile_index])
        while not swapped:
            available_swap_positions = indicies.copy()
            for index in indicies:
                if len(available_swap_positions) == 1 and \
                   list(available_swap_positions)[0] == index:
                    break
                while True:
                    swap_status[index] = choice(list(available_swap_positions))
                    if swap_status[index] != index:
                        break
                available_swap_positions.remove(swap_status[index])
                if not available_swap_positions:
                    swapped = True
                    break

    def stop_all_audio(self):
        if self.clip_audio:
            self.clip_audio.stop()
        self.full_audio.stop()

    def is_solved(self):
        return all(index == position for index, position in self.swap_status.iteritems())

    def update(self):
        ds = self.display_surface
        for xi, x in enumerate(xrange(0, ds.get_width(),
                                      self.tiles[0].get_width())):
            for yi, y in enumerate(xrange(0, ds.get_height(),
                                          self.tiles[0].get_height())):
                current_tile_index = self.default_tile_index
                for tile_index, rects in self.tile_rects.iteritems():
                    found = False
                    for rect in rects:
                        if rect[0][0] <= xi <= rect[1][0] and rect[0][1] <= yi \
                           <= rect[1][1]:
                            current_tile_index = tile_index
                            found = True
                            break
                    if found:
                        break
                swap_index = self.swap_status[current_tile_index]
                if swap_index in self.colored_tiles.keys():
                    tile = self.colored_tiles[swap_index]
                else:
                    tile = self.tiles[swap_index]
                ds.blit(tile, (x, y))


class Interface(Animation):

    BLINK_INTERVAL = 400
    OPEN_TEXT = "ENTER: EDIT MEMORY", "A: EDIT MEMORY"
    CELL_ALPHA = 240
    OPEN_TEXT_OFFSET = 36
    MAX_TILE_COUNT = 16
    CELL_INDENT = 32
    CELL_MARGIN = 56
    CELL_VERTICAL_PADDING = 8
    BACKGROUND = 0, 0, 0
    TEXT_COLOR = 255, 255, 255
    NAME_CHARACTER = "$"
    CELL_INDICATOR = 16
    CELL_INDICATOR_OFFSET = 2
    SHADOW_COLOR = 255, 255, 255
    SHADOW_OFFSET = -1, 1
    SWAP_INDICATOR = 16
    ADVANCE_TEXT = "PRESS ENTER", "PRESS START"
    SWAP_TEXT = "ENT: SWAP", "A: SWAP"
    HIDE_TEXT = "ESC: HIDE", "B: HIDE"
    MOVE_TEXT = ": MOVE"
    PLAY_SONG_DELAY = 1000
    UNSUPPRESS_ADVANCE_DELAY = 2000
    MOVE_ICONS = 24, 25, 26, 27

    def __init__(self, parent):
        Animation.__init__(self, parent)
        ds = self.display_surface = self.get_display_surface()
        glyphs = self.get_game().glyphs
        open_plate = self.open_plate = Sprite(self)
        open_plate.add_frame(glyphs.get_surface_from_text(self.get_game().select_text(self.OPEN_TEXT),
                                                          background=(0, 0, 0)))
        open_plate.location.midbottom = ds.get_rect().centerx, ds.get_height() - \
                                        self.OPEN_TEXT_OFFSET
        self.cell_frames = cell_frames = []
        tile_size = glyphs.get_tile(0).get_width()
        for ii in xrange(self.MAX_TILE_COUNT):
            title = ("%s%02x" % (self.NAME_CHARACTER, ii)).upper()
            title_surface = glyphs.get_surface_from_text(title, self.TEXT_COLOR)
            frame = Surface((self.CELL_INDENT * 2 + title_surface.get_width() + \
                             self.CELL_MARGIN + tile_size,
                             self.CELL_VERTICAL_PADDING * 2 + tile_size))
            frame.fill(self.BACKGROUND)
            frame.blit(title_surface, (self.CELL_INDENT, self.CELL_VERTICAL_PADDING))
            cell_frames.append(Sprite(self))
            cell_frames[-1].add_frame(frame)
            cell_frames[-1].set_alpha(self.CELL_ALPHA)
        indicator = self.cell_indicator = Sprite(self)
        indicator.add_frame(glyphs.get_tile(self.CELL_INDICATOR, self.TEXT_COLOR))
        indicator = self.swap_indicator = Sprite(self)
        indicator.add_frame(glyphs.get_tile(self.SWAP_INDICATOR, self.TEXT_COLOR))
        shadow = self.tile_shadow = Surface([tile_size] * 2)
        shadow.fill(self.SHADOW_COLOR)
        advance_plate = self.advance_plate = Sprite(self)
        advance_plate.add_frame(glyphs.get_surface_from_text(self.get_game().select_text(self.ADVANCE_TEXT),
                                                             background=(0, 0, 0)))
        advance_plate.location.midbottom = open_plate.location.midbottom
        swap_plate = self.swap_plate = Sprite(self)
        text = self.SWAP_TEXT[1] 
        swap_plate.add_frame(glyphs.get_surface_from_text(self.get_game().select_text(self.SWAP_TEXT),
                                                          background=(0, 0, 0)))
        swap_plate.set_alpha(self.CELL_ALPHA)
        move_plate = self.move_plate = Sprite(self)
        text_surface = glyphs.get_surface_from_text(self.MOVE_TEXT,
                                                    background=(0, 0, 0))
        frame = Surface((tile_size * len(self.MOVE_ICONS) + text_surface.get_width(),
                         tile_size))
        x = 0
        for index in self.MOVE_ICONS:
            frame.blit(glyphs.get_tile(index), (x, 0))
            x += tile_size
        frame.blit(text_surface, (x, 0))
        move_plate.add_frame(frame)
        move_plate.set_alpha(self.CELL_ALPHA)
        move_plate.location.midtop = ds.get_width() / 2, 0
        hide_plate = self.hide_plate = Sprite(self)
        hide_plate.add_frame(glyphs.get_surface_from_text(self.get_game().select_text(self.HIDE_TEXT),
                                                          background=(0, 0, 0)))
        hide_plate.set_alpha(self.CELL_ALPHA)
        hide_plate.location.topright = ds.get_width(), 0
        self.register(self.blink, interval=self.BLINK_INTERVAL)
        self.register(self.play_song)
        self.register(self.unsuppress_advance)
        self.subscribe(self.respond)

    def blink(self):
        if self.closed and not self.solved:
            self.open_plate.toggle_hidden()
        if not self.closed and self.swapping_index is not None:
            self.swap_indicator.toggle_hidden()
        if self.solved and not self.suppressing_commands:
            self.advance_plate.toggle_hidden()

    def respond(self, event, suppress_sound=False):
        if self.active and not self.suppressing_commands:
            delegate = self.get_game().delegate
            effects = self.get_game().sound_effects
            is_pad_mode = self.get_game().is_gamepad_mode()
            if self.closed and not self.solved and delegate.compare(event, "action"):
                effects.play("memory")
                self.unclose()
            elif self.closed and self.solved and (delegate.compare(event, "advance") or \
               (not is_pad_mode and delegate.compare(event, "action"))):
                effects.play("go")
                if self.get_game().levels.is_final_level():
                    self.get_game().ending.activate()
                    self.get_game().levels.deactivate()
                else:
                    self.get_game().levels.load_next_level()
            elif not self.closed:
                if delegate.compare(event, "cancel"):
                    effects.play("cancel")
                    self.close()
                elif delegate.compare(event, "action"):
                    if self.swapping_index is None:
                        effects.play("start")
                        self.swapping_index = self.cell_index
                        self.set_indicator_position(False)
                        self.respond(Event(delegate.command_event_id,
                                           {"command": "down", "cancel": False}), True)
                    else:
                        if self.cell_index == self.swapping_index:
                            effects.play("cancel")
                        else:
                            level = self.get_game().levels.current_level
                            status = level.swap_status
                            temp = status[self.swapping_index]
                            status[self.swapping_index] = status[self.cell_index]
                            status[self.cell_index] = temp
                            self.swap_count += 1
                            if not level.is_solved():
                                effects.play("swap")
                            else:
                                effects.play("clear")
                                if not self.get_game().levels.is_final_level():
                                    self.get_game().write_progress(self.get_game().levels.\
                                                                   get_current_level_index() + 1,
                                                                   self.swap_count, True)
                                else:
                                    self.get_game().ending.\
                                        set_swap_count(self.get_game().get_progress()[1] + \
                                                       self.swap_count)
                                    self.get_game().write_progress(0, 0)
                                self.suppressing_commands = True
                                self.solved = True
                                self.play(self.play_song, delay=self.PLAY_SONG_DELAY, play_once=True)
                        self.swapping_index = None
                elif delegate.compare(event, ["up", "down", "left", "right"]):
                    if not suppress_sound:
                        effects.play("menu-move")
                    cell_count = self.get_cell_count()
                    bp = (cell_count - 1) / 2
                    if delegate.compare(event, "up"):
                        self.cell_index -= 1
                        if self.cell_index == -1:
                            self.cell_index = bp
                        elif self.cell_index == bp:
                            self.cell_index = cell_count - 1
                    elif delegate.compare(event, "down"):
                        self.cell_index += 1
                        if self.cell_index == bp + 1:
                            self.cell_index = 0
                        elif self.cell_index == cell_count:
                            self.cell_index = bp + 1
                    elif delegate.compare(event, "left"):
                        if self.cell_index == 0:
                            self.cell_index = bp + 1
                        elif self.cell_index > bp:
                            self.cell_index -= bp + 1
                        else:
                            self.cell_index += bp
                            if self.cell_index == cell_count:
                                self.cell_index -= 1
                    elif delegate.compare(event, "right"):
                        if self.cell_index == cell_count - 1:
                            self.cell_index = bp
                        elif self.cell_index <= bp:
                            self.cell_index += bp + 1
                            if self.cell_index == cell_count:
                                self.cell_index -= 1
                        else:
                            self.cell_index -= bp
                    self.set_indicator_position()

    def play_song(self):
        self.close()
        level = self.get_game().levels.current_level
        level.clip_audio.stop()
        level.full_audio.play(-1)
        self.play(self.unsuppress_advance, delay=self.UNSUPPRESS_ADVANCE_DELAY,
                  play_once=True)

    def unsuppress_advance(self):
        self.suppressing_commands = False
        self.advance_plate.unhide()

    def set_indicator_position(self, cell=True):
        if cell:
            indicator = self.cell_indicator
        else:
            indicator = self.swap_indicator
        indicator.location.midleft = self.cell_frames[self.cell_index].location.\
                                     midleft
        indicator.location.left += self.CELL_INDICATOR_OFFSET

    def get_cell_count(self):
        return len(self.get_game().levels.current_level.swap_status)

    def reset(self):
        self.deactivate()
        self.solved = False
        self.close()
        self.halt()
        self.suppressing_commands = False

    def deactivate(self):
        self.active = False

    def setup(self):
        self.activate()
        self.close()
        cell_count = self.get_cell_count()
        left_count = cell_count / 2 + cell_count % 2
        right_count = cell_count / 2
        sw, sh = self.display_surface.get_size()
        step = sh / (left_count + 1)
        frames = self.cell_frames
        index = 0
        for y in xrange(step, step * (left_count + 1), step):
            frames[index].location.midleft = 0, y
            index += 1
        step = sh / (right_count + 1)
        for y in xrange(step, step * (right_count + 1), step):
            frames[index].location.midright = sw, y
            index += 1
        self.cell_index = 0
        self.set_indicator_position()
        self.swapping_index = None
        self.swap_count = 0
        self.suppressing_commands = False
        self.solved = False
        self.advance_plate.hide()
        self.play(self.blink)

    def activate(self):
        self.active = True

    def close(self):
        self.closed = True
        if not self.solved:
            self.open_plate.unhide()

    def unclose(self):
        self.closed = False
        self.open_plate.hide()

    def update(self):
        Animation.update(self)
        if self.active:
            self.open_plate.update()
            self.advance_plate.update()
            if not self.closed:
                for frame in self.cell_frames[:self.get_cell_count()]:
                    frame.update()
                self.cell_indicator.update()
                if self.swapping_index is not None:
                    self.swap_indicator.update()
                level = self.get_game().levels.current_level
                for index, position in level.swap_status.iteritems():
                    if position in level.colored_tiles.keys():
                        tile = level.colored_tiles[position]
                    else:
                        tile = level.tiles[position]
                    rect = tile.get_rect()
                    frame = self.cell_frames[index]
                    rect.topright = frame.location.right - self.CELL_INDENT, \
                                    frame.location.top + self.CELL_VERTICAL_PADDING
                    self.display_surface.blit(self.tile_shadow, rect.move(self.SHADOW_OFFSET))
                    self.display_surface.blit(tile, rect)
                self.swap_plate.update()
                self.hide_plate.update()
                self.move_plate.update()


class Title(Animation):

    BLINK_INTERVAL = 400
    MENU_OFFSET = 100
    MENU_WIDTH = 440
    BACKGROUND_SIZE = 40
    ADVANCE_TEXT = "PRESS ENTER", "PRESS START"
    MENU_OPTIONS = "NEW GAME", "CONTINUE"
    MENU_MARGIN = 12
    MENU_PADDING = 16
    TRANSPARENT_COLOR = (128, 128, 128)
    TURN_PROBABILITY = .0001
    SCROLL_SPEED = 2
    BACKGROUND_BACKGROUND = (0, 0, 0)
    BACKGROUND_FRAME_COUNT = 1
    BACKGROUND_FRAMERATE = 200
    MENU_INDICATOR_LOCATION = 224
    CHUNK_PROBABILITY = .5
    CHUNK_VOLUME = .1

    def __init__(self, parent):
        Animation.__init__(self, parent)
        self.display_surface = self.get_display_surface()
        self.set_audio()
        self.set_advance_plate()
        self.register(self.blink, interval=self.BLINK_INTERVAL)
        self.subscribe(self.respond)
        self.play(self.blink)

    def set_audio(self):
        self.audio_loop = Sound(self.get_resource("aud/title.wav"))
        chunks = self.audio_chunks = []
        for path in glob(join(self.get_resource("aud/chunk"), "*.ogg")):
            chunks.append(Sound(path))
            chunks[-1].set_volume(self.CHUNK_VOLUME)
        self.advance_effect = SoundEffect(self, "start")
        self.move_effect = SoundEffect(self, "menu-move")
        self.cancel_effect = SoundEffect(self, "cancel")

    def set_advance_plate(self):
        offset = 0
        plate = self.advance_plate = Sprite(self, self.BLINK_INTERVAL)
        plate.add_frame(self.get_game().glyphs.\
                        get_surface_from_text(self.get_game().select_text(self.ADVANCE_TEXT),
                                              (255, 255, 255), background=(0, 0, 0)))
        rect = self.display_surface.get_rect()
        plate.location.center = rect.centerx, rect.bottom - self.MENU_OFFSET

    def blink(self):
        self.advance_plate.toggle_hidden()
        
    def reset(self):
        self.set_background()
        self.activate()
        self.advance_pressed = False
        self.advance_plate.unhide()
        self.set_scroll_step()
        self.menu_index = 0

    def set_background(self):
        tiles = []
        for level in self.get_game().levels.levels:
            tiles.extend(level.tiles)
        background = self.background = Sprite(self, self.BACKGROUND_FRAMERATE)
        tw = tiles[0].get_width()
        frames = []
        for _ in xrange(self.BACKGROUND_FRAME_COUNT):
            frames.append(Surface([self.BACKGROUND_SIZE * tw] * 2))
            frames[-1].fill(self.BACKGROUND_BACKGROUND)
        for x in xrange(0, frames[0].get_width(), tw):
            for y in xrange(0, frames[0].get_width(), tw):
                for frame in frames:
                    tile = choice(tiles)
                    if random() >= .5:
                        inverted = Surface((tw, tw))
                        inverted.fill((255, 255, 255))
                        inverted.blit(tile, (0, 0), None, BLEND_SUB)
                        tile = inverted
                    fx, fy = random() >= .5, random() >= .5
                    if fx or fy:
                        tile = flip(tile, fx, fy)
                    frame.blit(tile, (x, y))
        for frame in frames:
            background.add_frame(frame)
        background.add_location(offset=(background.location.w, 0))
        background.add_location(offset=(0, background.location.h))
        background.add_location(offset=(background.location.w,
                                        background.location.h))

    def activate(self):
        self.active = True
        # self.audio_loop.play(-1)
        self.set_menu()

    def set_menu(self):
        glyphs = self.get_game().glyphs
        if self.get_game().get_progress()[0] > 0:
            option_texts = self.MENU_OPTIONS
        else:
            option_texts = self.MENU_OPTIONS[:1]
        height = glyphs.get_tile(0).get_height() * len(option_texts) + \
                 self.MENU_MARGIN * (len(option_texts) - 1) + \
                 self.MENU_PADDING * 2 + 3
        background = self.menu_background = Surface((int(self.MENU_WIDTH),
                                                     height))
        background.fill((0, 0, 0))
        rect = self.menu_rect = background.get_rect()
        rect.center = self.advance_plate.location.center
        options = self.options = []
        for option in option_texts:
            options.append(Sprite(self))
            options[-1].add_frame(glyphs.get_surface_from_text(option))
            options[-1].location.centerx = rect.centerx
            options[-1].location.top = rect.top + self.MENU_PADDING + \
                                       (len(options) - 1) * options[0].location.h + \
                                       (len(options) - 1) * self.MENU_MARGIN
        indicator = self.indicator = Sprite(self)
        indicator.add_frame(self.get_game().glyphs.get_tile(16))

    def set_scroll_step(self):
        self.scroll_step = get_delta(randrange(0, 360), self.SCROLL_SPEED)

    def respond(self, event):
        if self.active:
            delegate = self.get_game().delegate
            if not self.advance_pressed:
                if delegate.compare(event, "advance") or not self.get_game().is_gamepad_mode() and \
                   delegate.compare(event, "action"):
                    self.advance_pressed = True
                    self.get_game().sound_effects.play("start")
                elif delegate.compare(event, "cancel"):
                    self.get_game().sound_effects.play("cancel")
            else:
                if delegate.compare(event, "cancel"):
                    self.get_game().sound_effects.play("cancel")
                    self.advance_pressed = False
                elif delegate.compare(event, "up"):
                    self.get_game().sound_effects.play("menu-move")
                    self.menu_index -= 1
                elif delegate.compare(event, "down"):
                    self.get_game().sound_effects.play("menu-move")
                    self.menu_index += 1
                elif delegate.compare(event, "advance") or not self.get_game().is_gamepad_mode() and \
                   delegate.compare(event, "action"):
                    self.get_game().sound_effects.play("start")
                    if self.menu_index == 0:
                        self.deactivate()
                        self.get_game().introduction.load()
                        self.get_game().write_progress(0, 0)
                    elif self.menu_index == 1:
                        self.deactivate()
                        self.get_game().levels.\
                            levels[self.get_game().get_progress()[0]].load()
                    else:
                        pass
                    event.dict["command"] = ""
                if self.menu_index < 0:
                    self.menu_index = len(self.options) - 1
                elif self.menu_index >= len(self.options):
                    self.menu_index = 0

    def deactivate(self):
        self.active = False
        self.audio_loop.stop()

    def update(self):
        Animation.update(self)
        if self.active:
            if random() < self.TURN_PROBABILITY:
                self.set_scroll_step()
            self.background.move(*self.scroll_step)
            if self.background.location.top > 0:
                self.background.move(dy=-self.background.location.h)
            if self.background.location.right < 0:
                self.background.move(self.background.location.w)
            if self.background.location.bottom < 0:
                self.background.move(dy=self.background.location.h)
            if self.background.location.left > 0:
                self.background.move(-self.background.location.w)
            self.background.update()
            if not self.advance_pressed:
                self.advance_plate.update()
            else:
                self.display_surface.blit(self.menu_background, self.menu_rect)
                for option in self.options:
                    option.update()
                self.indicator.location.centery = self.options[self.menu_index]\
                                                      .location.centery
                self.indicator.location.right = self.MENU_INDICATOR_LOCATION
                self.indicator.update()
            if random() < self.CHUNK_PROBABILITY and \
               get_busy_channel_count() < get_num_channels() - 5:
                for _ in xrange(randint(1, 4)):
                    chunk = choice(self.audio_chunks)
                    channel = chunk.play()
                    if channel is not None:
                        channel.set_volume(random(), random())


class Introduction(Animation):

    BACKGROUND = (0, 0, 0)
    TEXT_COLOR = (255, 255, 255)
    INDICATOR_INDEX = 31
    TEXT = "MEDITATING.", "MEDITATING..", "MEDITATING...", \
           "MANIPULATION OF THE/SYSTEM'S PPU GRANTED"
    INDENT = 48
    OFFSET = 128
    MARGIN = 12
    BLINK_INTERVAL = 400

    def __init__(self, parent):
        Animation.__init__(self, parent)
        ds = self.display_surface = self.get_display_surface()
        background = self.background = Surface(ds.get_size())
        background.fill(self.BACKGROUND)
        blocks = self.blocks = []
        glyphs = self.get_game().glyphs
        tile_height = glyphs.get_tile(0).get_height()
        for block in self.TEXT:
            blocks.append([])
            for ii, line in enumerate(block.split("/")):
                plate = Sprite(self)
                plate.add_frame(glyphs.\
                                get_surface_from_text(line, self.TEXT_COLOR,
                                                      background=self.BACKGROUND))
                plate.location.left = self.INDENT
                plate.location.top = ds.get_height() - self.OFFSET + ii * \
                                     (tile_height + self.MARGIN)
                blocks[-1].append(plate)
        indicator = self.indicator = Sprite(self)
        indicator.add_frame(glyphs.get_tile(self.INDICATOR_INDEX, self.TEXT_COLOR))
        indicator.location.top = ds.get_height() - self.OFFSET + 2 * \
                                 (tile_height + self.MARGIN)
        indicator.location.right = ds.get_width() - self.INDENT
        self.register(self.blink, interval=self.BLINK_INTERVAL)
        self.subscribe(self.respond)
        self.play(self.blink)

    def respond(self, event):
        if self.active:
            if self.get_game().delegate.compare(event, "action"):
                self.block_index += 1
                if self.block_index == len(self.blocks):
                    self.get_game().sound_effects.play("go")
                    self.deactivate()
                    self.get_game().levels.levels[0].load()
                elif self.block_index == len(self.blocks) - 1:
                    self.get_game().sound_effects.play("granted")
                else:
                    self.get_game().sound_effects.play("next")

    def deactivate(self):
        self.active = False

    def load(self):
        self.activate()
        self.block_index = 0
        self.indicator.unhide()

    def activate(self):
        self.active = True

    def blink(self):
        self.indicator.toggle_hidden()

    def reset(self):
        self.deactivate()

    def update(self):
        Animation.update(self)
        if self.active:
            ds = self.display_surface
            ds.blit(self.background, (0, 0))
            for block in self.blocks[self.block_index]:
                block.update()
            self.indicator.update()


class Ending(Animation):

    GLYPH_RANGE = 1, 31
    SCROLL_SPEED = 2
    TURN_PROBABILITY = .0001
    PLATE_SIZE = 312, 72
    PLATE_BACKGROUND = 0, 0, 0
    TEXT_COLOR = 255, 255, 255
    END_TEXT = "THE END!"
    SWAP_COUNT_TEXT = "SWAPS:"
    UNSUPPRESS_DELAY = 1000

    def __init__(self, parent):
        Animation.__init__(self, parent)
        ds = self.display_surface = self.get_display_surface()
        end_plate = self.end_plate = Sprite(self)
        frame = Surface(self.PLATE_SIZE)
        frame.fill(self.PLATE_BACKGROUND)
        text_surface = self.get_game().glyphs.get_surface_from_text(self.END_TEXT,
                                                                    self.TEXT_COLOR)
        rect = text_surface.get_rect()
        rect.center = frame.get_rect().center
        frame.blit(text_surface, rect)
        end_plate.add_frame(frame)
        end_plate.location.center = ds.get_rect().centerx, 3 * ds.get_height() / 8
        self.audio = Sound(self.get_resource("aud/end.ogg"))
        self.subscribe(self.respond)
        self.register(self.unsuppress_advance)

    def respond(self, event):
        if self.active and not self.suppress_commands and \
           ((self.get_game().is_gamepad_mode() and self.get_game().delegate.compare(event, "advance")) or \
            (not self.get_game().is_gamepad_mode() and self.get_game().delegate.compare(event, "action"))):
            self.deactivate()
            self.get_game().reset()

    def unsuppress_advance(self):
        self.suppress_commands = False

    def set_swap_count(self, count):
        self.swap_count = count

    def reset(self):
        self.deactivate()
        self.halt()

    def deactivate(self):
        self.active = False
        self.audio.stop()

    def activate(self):
        self.active = True
        self.set_swap_plate()
        self.set_background()
        self.set_scroll_step()
        self.suppress_commands = True
        self.play(self.unsuppress_advance, delay=self.UNSUPPRESS_DELAY,
                  play_once=True)
        self.audio.play(-1)

    def set_swap_plate(self):
        swap_count_plate = self.swap_count_plate = Sprite(self)
        frame = Surface(self.PLATE_SIZE)
        frame.fill(self.PLATE_BACKGROUND)
        text_surface = self.get_game().glyphs.\
                       get_surface_from_text("%s %i" % (self.SWAP_COUNT_TEXT,
                                                        self.swap_count), self.TEXT_COLOR)
        rect = text_surface.get_rect()
        rect.center = frame.get_rect().center
        frame.blit(text_surface, rect)
        swap_count_plate.add_frame(frame)
        swap_count_plate.location.center = self.display_surface.get_rect().centerx, \
                                           5 * self.display_surface.get_height() / 8

    def set_background(self):
        background = self.background = Sprite(self)
        glyphs = self.get_game().glyphs
        tw = glyphs.get_tile(0).get_width()
        ds = self.get_display_surface()
        frame = Surface(ds.get_size())
        for xi, x in enumerate(xrange(0, ds.get_width(), tw)):
            for yi, y in enumerate(xrange(0, ds.get_height(), tw)):
                background_color = Color(0, 0, 0)
                background_color.hsla = randrange(0, 360), 100, 50, 100
                foreground_color = Color(0, 0, 0)
                foreground_color.hsla = (background_color.hsla[0] + 180) % 360, \
                                        100, 50, 100
                surface = Surface([tw] * 2)
                surface.fill(background_color)
                surface.blit(glyphs.get_tile(randint(*self.GLYPH_RANGE)), (0, 0))
                frame.blit(surface, (x, y))
        background.add_frame(frame)
        background.add_location(offset=(background.location.w, 0))
        background.add_location(offset=(0, background.location.h))
        background.add_location(offset=(background.location.w,
                                        background.location.h))
                
    def set_scroll_step(self):
        self.scroll_step = get_delta(randrange(0, 360), self.SCROLL_SPEED)

    def update(self):
        Animation.update(self)
        if self.active:
            if random() < self.TURN_PROBABILITY:
                self.set_scroll_step()
            self.background.move(*self.scroll_step)
            if self.background.location.top > 0:
                self.background.move(dy=-self.background.location.h)
            if self.background.location.right < 0:
                self.background.move(self.background.location.w)
            if self.background.location.bottom < 0:
                self.background.move(dy=self.background.location.h)
            if self.background.location.left > 0:
                self.background.move(-self.background.location.w)
            self.background.update()
            self.end_plate.update()
            self.swap_count_plate.update()
54.224.168.206
54.224.168.206
54.224.168.206
 
November 9, 2013


Food Spring - Watermelon Stage

Getting the fruit as far as possible is the object of each level, collecting bigger, more valuable guns. The final result is determined by the size of the fruits' collection when the monkey arrives in North America and either survives or perishes in the fruits' attack.

Watermelon Peach
Pineapple Grapes

↠ RSS Feed ↞