from os import write
from time import time

from esp_hadouken.GameChild import *

class HighScores(GameChild, list):

    def __init__(self, parent):
        GameChild.__init__(self, parent)
        list.__init__(self, [])
        self.read()

    def read(self):
        for line in open(self.get_path()):
            line = line.strip()
            if line:
                self.append(Score(*line.split(" ")))

    def get_path(self):
        return self.get_resource("scoreboard-scores-path")

    def add(self, player):
        timer = self.get_timer()
        values = (timer["octo"], timer["horse"], timer["diortem"],
                  timer["circulor"], timer["tooth"])
        score = Score(time(), player, timer.total(), *values)
        self.append(score)
        self.write(score)

    def write(self, score):
        scores = open(self.get_path(), "a")
        scores.write(str(score) + "\n")

    def get_most_recent_player(self):
        return self[-1].player


class Score:

    def __init__(self, *args):
        self.date = int(args[0])
        self.player = args[1]
        self.total, self.octo, self.horse, self.diortem, self.circulor, \
                    self.tooth = map(float, args[2:])

    def __str__(self):
        return "%i %s %.3f %.3f %.3f %.3f %.3f %.3f" % \
               (self.date, self.player, self.total, self.octo, self.horse,
                self.diortem, self.circulor, self.tooth)

    def __lt__(self, other):
        return self.total < other.total

    def __repr__(self):
        return self.__str__()
from pygame import Surface

from esp_hadouken.GameChild import *
from esp_hadouken.Input import *
from Row import *
from Heading import *

class Scoreboard(GameChild, Surface):

    active_interval = 0

    def __init__(self, parent):
        GameChild.__init__(self, parent)
        self.init_surface()
        self.set_rect()
        self.heading = Heading(self)
        self.add_rows()
        self.subscribe_to(Input.command_event, self.respond_to_command)
        self.deactivate()

    def init_surface(self):
        config = self.get_configuration()
        step = self.get_step()
        padding = self.get_padding()
        row_height = self.get_row_height()
        height = step * row_height + padding + self.get_heading_height()
        Surface.__init__(self, (config["scoreboard-width"], height))
        self.set_alpha(config["scoreboard-alpha"])

    def get_step(self):
        return self.get_configuration()["scoreboard-interval-length"]

    def get_row_height(self):
        return self.get_configuration()["scoreboard-row-height"]

    def get_padding(self):
        return self.get_configuration()["scoreboard-padding"]

    def get_heading_height(self):
        return self.get_configuration()["scoreboard-heading-height"]
    
    def get_column_widths(self):
        return self.get_configuration()["scoreboard-column-widths"]

    def set_rect(self):
        rect = self.get_rect()
        rect.center = self.get_screen().get_rect().center
        self.rect = rect

    def add_rows(self):
        rows = []
        for ii in range(self.get_step()):
            rows.append(Row(self, ii))
        self.rows = rows

    def respond_to_command(self, event):
        if self.active:
            command = event.command
            if command == "next":
                self.set_active_interval(1)
                self.populate()
            elif command == "previous":
                self.set_active_interval(-1)
                self.populate()

    def set_active_interval(self, increment=0, interval=None):
        if interval is None:
            interval = self.active_interval + increment
        max_interval = self.get_max_interval()
        if interval < 0:
            interval = 0
        elif interval > max_interval:
            interval = max_interval
        self.active_interval = interval

    def get_max_interval(self):
        return len(self.get_high_scores()) / self.get_step()

    def populate(self):
        self.disable_highlights()
        step = self.get_step()
        low = step * self.active_interval
        high = low + step
        interval = self.get_ordered_scores()[low:high]
        interval += [None] * (step - len(interval))
        rows = self.rows
        for ii, score in enumerate(interval):
            score_index = low + ii
            row = rows[ii]
            if score_index == self.get_highlit_score_index():
               row.enable_highlight() 
            row.set_score(score, score_index)
        self.parent.update()

    def disable_highlights(self):
        for row in self.rows:
            row.disable_highlight()

    def get_ordered_scores(self):
        return sorted(self.get_high_scores())

    def activate(self, highlight=True):
        self.active = True
        if highlight:
            self.show_recent_score_interval()
        self.populate()

    def show_recent_score_interval(self):
        ordered = self.get_ordered_scores()
        interval = self.get_highlit_score_index() / self.get_step()
        self.set_active_interval(interval=interval)

    def get_highlit_score_index(self):
        return self.get_ordered_scores().index(self.get_high_scores()[-1])

    def deactivate(self):
        self.active = False

    def update(self):
        if self.active:
            self.clear()
            self.heading.update()
            for row in self.rows:
                row.update()
            self.draw()

    def clear(self):
        self.fill(Color(self.get_configuration()["scoreboard-bg"]))

    def draw(self):
        self.parent.blit(self, self.rect)
from pygame import Surface, Color
from pygame.locals import *

from esp_hadouken.GameChild import *
from esp_hadouken.Font import *

class Row(GameChild, Surface):

    def __init__(self, parent, index):
        GameChild.__init__(self, parent)
        self.index = index
        self.disable_highlight()
        self.init_surface()
        self.set_rect()
        self.set_column_surfaces()

    def enable_highlight(self):
        self.highlit = True

    def disable_highlight(self):
        self.highlit = False

    def init_surface(self):
        parent = self.parent
        width = parent.get_width() - parent.get_padding()
        Surface.__init__(self, (width, parent.get_row_height()))
        self.fill(self.get_color())

    def get_color(self):
        config = self.get_configuration()
        if self.highlit:
            color = config["scoreboard-highlight-color"]
        elif not self.index % 2:
            color = config["scoreboard-row-color-1"]
        else:
            color = config["scoreboard-row-color-2"]
        return Color(color)

    def set_rect(self):
        rect = self.get_rect()
        parent = self.parent
        index = self.index
        padding = parent.get_padding()
        heading = parent.get_heading_height()
        rect.top = padding / 2 + index * parent.get_row_height() + heading
        rect.centerx = parent.get_rect().centerx
        self.rect = rect

    def set_column_surfaces(self):
        self.rank_surf, self.rank_surf_r = self.set_column_surface(0)
        self.initials_surf, self.initials_surf_r = self.set_column_surface(1)
        self.total_surf, self.total_surf_r = self.set_column_surface(2)
        self.split_surfs, self.split_surfs_rs = [], []
        for ii in range(3, 8):
            surf, rect = self.set_column_surface(ii)
            self.split_surfs.append(surf)
            self.split_surfs_rs.append(rect)

    def set_column_surface(self, index):
        ratios = self.parent.get_column_widths()
        relative = self.get_size()
        surf = Surface((relative[0] * ratios[index], relative[1]))
        surf.fill(self.get_color())
        indent = 0
        for ratio in ratios[:index]:
            indent += ratio * relative[0]
        rect = surf.get_rect()
        rect.left = indent
        return surf, rect

    def set_score(self, score, rank):
        self.render_rank(rank)
        self.render_initials(score)
        self.render_total(score)
        if score is None:
            splits = [None] * 5
        else:
            splits = [score.octo, score.horse, score.diortem, score.circulor,
                      score.tooth]
        for ii, split in enumerate(splits):
            self.render_split(ii, split)

    def render_rank(self, rank):
        size = self.get_configuration()["scoreboard-rank-size"]
        rend = Font(self, size).render(str(rank + 1), True, self.get_text_color(),
                                       self.get_color())
        rect = rend.get_rect()
        dest = self.rank_surf
        dest.fill(self.get_color())
        rect.center = dest.get_rect().center
        dest.blit(rend, rect)

    def get_text_color(self):
        return Color(self.get_configuration()["scoreboard-text-color"])

    def render_initials(self, score):
        self.initials_surf.fill(self.get_color())
        if score is None:
            return
        x = 0
        margin = self.get_configuration()["scoreboard-initials-margin"]
        size = self.get_height() - margin * 2
        for letter in score.player:
            self.render_initial(letter, x, size)
            x += size + margin

    def get_blank_char(self):
        return self.get_configuration()["scoreboard-blank-char"]

    def render_initial(self, letter, x, size):
        square = Surface((size, size))
        if letter == self.get_blank_char():
            color = self.get_configuration()["scoreboard-initials-blank-color"]
            color = Color(color)
        else:
            color = self.get_glyph_palette()[ord(letter.lower()) - K_a]
        square.fill(color)
        font_size = self.get_configuration()["scoreboard-initials-size"]
        rend = Font(self, font_size).render(letter, True, self.get_text_color(),
                                            color)
        square_rect = square.get_rect()
        rend_rect = rend.get_rect()
        rend_rect.center = square_rect.center
        square.blit(rend, rend_rect)
        square_rect.centery = self.get_rect().centery
        square_rect.left = x
        self.initials_surf.blit(square, square_rect)

    def render_total(self, score):
        dest = self.total_surf
        dest.fill(self.get_color())
        if score is None:
            return
        text = self.build_time_string(score.total)
        size = self.get_configuration()["scoreboard-total-size"]
        rend = Font(self, size).render(text, True, self.get_text_color(),
                                       self.get_color())
        rect = rend.get_rect()
        rect.center = dest.get_rect().center
        dest.blit(rend, rect)

    def build_time_string(self, time):
        return "%i:%02i" % divmod(int(time), 60)

    def get_blank_time(self):
        return self.get_blank_char()

    def render_split(self, index, time):
        dest = self.split_surfs[index]
        dest.fill(self.get_color())
        if time is None:
            return
        text = self.build_time_string(time)
        size = self.get_configuration()["scoreboard-split-size"]
        rend = Font(self, size).render(text, True, self.get_text_color(),
                                       self.get_color())
        rect = rend.get_rect()
        rect.center = dest.get_rect().center
        dest.blit(rend, rect)

    def update(self):
        self.clear()
        self.draw()

    def clear(self):
        self.fill(self.get_color())

    def draw(self):
        self.blit(self.rank_surf, self.rank_surf_r)
        self.blit(self.initials_surf, self.initials_surf_r)
        self.blit(self.total_surf, self.total_surf_r)
        for ii, surf in enumerate(self.split_surfs):
            self.blit(surf, self.split_surfs_rs[ii])
        self.parent.blit(self, self.rect)
13.59.54.188
13.59.54.188
13.59.54.188
 
September 13, 2013

from array import array
from time import sleep

import pygame
from pygame.mixer import Sound, get_init, pre_init

class Note(Sound):

    def __init__(self, frequency, volume=.1):
        self.frequency = frequency
        Sound.__init__(self, self.build_samples())
        self.set_volume(volume)

    def build_samples(self):
        period = int(round(get_init()[0] / self.frequency))
        samples = array("h", [0] * period)
        amplitude = 2 ** (abs(get_init()[1]) - 1) - 1
        for time in xrange(period):
            if time < period / 2:
                samples[time] = amplitude
            else:
                samples[time] = -amplitude
        return samples

if __name__ == "__main__":
    pre_init(44100, -16, 1, 1024)
    pygame.init()
    Note(440).play(-1)
    sleep(5)

This program generates and plays a 440 Hz tone for 5 seconds. It can be extended to generate the spectrum of notes with a frequency table or the frequency formula. Because the rewards in Send are idealized ocean waves, they can also be represented as tones. Each level has a tone in its goal and a tone based on where the player's disc lands. Both play at the end of a level, sounding harmonic for a close shot and discordant for a near miss. The game can dynamically create these tones using the program as a basis.

I'm also building an algorithmically generated song: Silk Routes (Scissored). Here is an example of how it sounds so far.