Beispiel #1
0
 def trial(self, cutoff):
     """Play automatically, without display.  Return the number of
     rounds played (before GameOver raised).  If there is no
     GameOver before cutoff is reached, stop anyway."""
     log("trial with cutoff %s" % cutoff)
     self.finalise_rules()
     log("finalised")
     self.reset()
     log("reset")
     self.play_state = config.STATE_TRIAL
     self.player_score = 0
     PLAYING = config.PLAYING
     DYING = config.DYING
     log("trial with types %s" % self.types)
     self.game_over = False
     for r in range(cutoff):
         for s in self.sprites:
             if s.state == PLAYING:
                 s.decide()
         for s in self.sprites:
             if s.state == PLAYING:
                 s.update()
             elif s.state == DYING:
                 s.die2()
         self.track_play(r)
         if self.game_over:
             break
     return (r, self.player_score)
Beispiel #2
0
    def apply_rules(self, rules):
        self.rules = rules
        self.rule_suitability = self.suitabilities[rules.name]

        self.steps = self.rules.steps
        self.original_steps = self.steps
        self.directions = self.rules.directions
        self.type_name = rules.name
        #XXX more, surely?

        self.inputs_per_type, self.zones = self._mind_lut[self.rules.mind]

        self.block_bits = 0xff
        self.die_bits = 0
        log("applied rules to %s" % self)
Beispiel #3
0
    def apply_rules(self, rules):
        self.rules = rules
        self.rule_suitability = self.suitabilities[rules.name]

        self.steps = self.rules.steps
        self.original_steps = self.steps
        self.directions = self.rules.directions
        self.type_name = rules.name
        #XXX more, surely?

        self.inputs_per_type, self.zones = self._mind_lut[self.rules.mind]

        self.block_bits = 0xff
        self.die_bits = 0
        log("applied rules to %s" % self)
Beispiel #4
0
 def finalise_rules(self):
     self.food_sprites = []
     self.enemy_sprites = []
     self.ally_sprites = []
     for t in self.teams:
         log('about to finalise %s' %t)
         t.finalise()
         if t.rules.sprite_group == 'monster':
             self.enemy_sprites.extend(t.sprites)
         if t.rules.sprite_group == 'food':
             self.food_sprites.extend(t.sprites)
         if t.rules.sprite_group == 'ally':
             self.ally_sprites.extend(t.sprites)
     s = self.player_sprite
     self.player_extremes = (s.y, s.x, s.y, s.x)
Beispiel #5
0
    def _grow_rules(self):
        """get some rules, and tune them until they work"""
        stop = time.time() + config.RULE_GROWING_TIMEOUT
        results = []
        #start off with an arbitrary set
        #XXXXXX
        # add_rules can be moved here (only used here)
        #can be made invincible to suitability imbalance?

        rules.add_rules(self.player_team, self.other_teams)
        log("added rules")

        for i in range(config.RULE_GROWING_ATTEMPTS):
            log("attempt %s" % i)
            self.types = ['wall'] + [x.rules.name for x in self.teams]
            r, score = self.trial(config.CUTOFF_LENGTH + 2)
            score = score // 8
            log("trial with %s lasted %s" % (self.types, r))
            # diff from ideal matters, but overshooting is penalised
            if r > config.CUTOFF_LENGTH:
                error = config.OVERSHOOT_PENALTY
            else:
                error = abs(config.IDEAL_LENGTH - r)
            results.append((max(error - score, 0), self.types))
            if r > config.TARGET_LENGTH[1]:
                rules.mutate_rules(self.other_teams, -1)
            elif r < config.TARGET_LENGTH[0]:
                rules.mutate_rules(self.other_teams, 1)
            else:
                self.mutate_rules_meta()

            if time.time() > stop:
                log("stopping due to timeout")
                break


        log(*reversed(sorted(results)))
        return min(results)
Beispiel #6
0
 def grow():
     try:
         log("hello")
         best = self._grow_rules()
         log("got rules")
         fn = os.path.join(config.DATA_ROOT, "rules-%s.pickle" % os.getpid())
         utils.pickle(best, fn)
         log("pickled rules")
     except Exception, e:
         traceback.print_exc()
         os._exit(os.EX_SOFTWARE)
Beispiel #7
0
def add_rules(player, others):
    """each passed in team gets appended with a set of rules"""
    #cycle until no conflicts found (conflicts are quite rare)
    types = random.sample(NON_PLAYER_TYPES, len(others))
    while find_conflicts(types):
        types = random.sample(NON_PLAYER_TYPES, len(others))
    #initial optimisation is simple and greedy
    unassigned = others[:]
    for x in types:
        s, team = max((t.suitabilities[x.name], t) for t in unassigned)
        log("picked %s for %s (suitability %s) out of %s" % (team, x, s, unassigned))
        team.apply_rules(x)
        unassigned.remove(team)
    log("now the player")
    player.apply_rules(random.choice(PLAYER_TYPES))
    log("returning")
Beispiel #8
0
def add_rules(player, others):
    """each passed in team gets appended with a set of rules"""
    #cycle until no conflicts found (conflicts are quite rare)
    types = random.sample(NON_PLAYER_TYPES, len(others))
    while find_conflicts(types):
        types = random.sample(NON_PLAYER_TYPES, len(others))
    #initial optimisation is simple and greedy
    unassigned = others[:]
    for x in types:
        s, team = max((t.suitabilities[x.name], t) for t in unassigned)
        log("picked %s for %s (suitability %s) out of %s" %
            (team, x, s, unassigned))
        team.apply_rules(x)
        unassigned.remove(team)
    log("now the player")
    player.apply_rules(random.choice(PLAYER_TYPES))
    log("returning")
Beispiel #9
0
class Game:
    """Represents a game.  The game forks into two processes, and
    evolves in one (the child).  After a while, the evolved game saves
    key details to disk, and the game in the parent process picks them
    up.

    Saved attributes are:

    * sprite minds

    (This list should be growing, so is likely out of date).
    """
    game_over = True
    play_state = False
    nothing_happening = 0
    def __init__(self, background, blobs, window=None, entropy=None):
        if entropy:
            #seed the neural networks' RNG.
            self.random_holder = weights.seed_nets(entropy)

        self.background = background
        self.blobs = blobs
        self.map = Gamemap(config.WORKING_SIZE[0], config.WORKING_SIZE[1], config.PIXEL_SIZE)
        self.entropy = entropy
        if entropy:
            self.identity = "game-%x-%x" % tuple(entropy[:2])
        else:
            self.identity = "game-%x" % id(self)
        self.score = 0
        self.player_score = 0
        self.set_window(window)
        self.sort_sprites(blobs)
        self.effects = {}
        self.invisible_player = False
        self.high_score = 0
        self.score_redraw = False
        self.food_repopulation_constant = config.FOOD_REPOPULATION_CONSTANT
        self.enemy_repopulation_constant = config.ENEMY_REPOPULATION_CONSTANT
        self.ally_repopulation_constant = config.ALLY_REPOPULATION_CONSTANT
        self.resuscitate_in_packs = False

    def set_window(self, window):
        """separate from init for (legacy?) evolution reasons -- game
        can set window after it is formed"""
        self.window = window
        if window is not None:
            window.display(self.background)

    def sort_sprites(self, blobs):
        """Organise sprites into teams.  There will be at least one
        team of one, which becomes the player.
        """
        sorter = assort.TeamFinder(blobs, entropy=self.entropy)
        arrangement = sorter.find_teams()
        sorter.print_stats()

        self.teams = [actor.Team(v, i, self) for i, v in zip(config.TEAM_BITS, arrangement.vectors)]
        #print self.teams
        self.player_team = self.teams[0]
        self.other_teams = self.teams[1:]
        self.n_teams = len(self.teams) #needed for bootstrapping actors
        self.sprites = []
        #XXX possibly indeterminacy sneaking in, if sprites have ever been a set
        for t in self.teams:
            self.sprites.extend(t.sprites)
        self.nonplayer_sprites = self.sprites[1:]
        self.player_sprite = self.sprites[0]
        #so, now, there are teams of sprites, but no minds or rules.

    def mutate_rules_meta(self):
        #alter constant aspects of the game.
        for x in ('food_repopulation_constant',
                  'enemy_repopulation_constant',
                  'ally_repopulation_constant'):
            c = getattr(self, x)
            a, b = random.sample(range(30,40), 2)
            c = c * a // b
            setattr(self, x, c)
        if random.random() > 0.8:
            self.resuscitate_in_packs = not self.resuscitate_in_packs


    def _grow_rules(self):
        """get some rules, and tune them until they work"""
        stop = time.time() + config.RULE_GROWING_TIMEOUT
        results = []
        #start off with an arbitrary set
        #XXXXXX
        # add_rules can be moved here (only used here)
        #can be made invincible to suitability imbalance?

        rules.add_rules(self.player_team, self.other_teams)
        log("added rules")

        for i in range(config.RULE_GROWING_ATTEMPTS):
            log("attempt %s" % i)
            self.types = ['wall'] + [x.rules.name for x in self.teams]
            r, score = self.trial(config.CUTOFF_LENGTH + 2)
            score = score // 8
            log("trial with %s lasted %s" % (self.types, r))
            # diff from ideal matters, but overshooting is penalised
            if r > config.CUTOFF_LENGTH:
                error = config.OVERSHOOT_PENALTY
            else:
                error = abs(config.IDEAL_LENGTH - r)
            results.append((max(error - score, 0), self.types))
            if r > config.TARGET_LENGTH[1]:
                rules.mutate_rules(self.other_teams, -1)
            elif r < config.TARGET_LENGTH[0]:
                rules.mutate_rules(self.other_teams, 1)
            else:
                self.mutate_rules_meta()

            if time.time() > stop:
                log("stopping due to timeout")
                break


        log(*reversed(sorted(results)))
        return min(results)


    def grow_rules_in_fork(self):
        """make rules, in background processes"""
        #utils.make_dir(config.DATA_ROOT)

        def grow():
            try:
                log("hello")
                best = self._grow_rules()
                log("got rules")
                fn = os.path.join(config.DATA_ROOT, "rules-%s.pickle" % os.getpid())
                utils.pickle(best, fn)
                log("pickled rules")
            except Exception, e:
                traceback.print_exc()
                os._exit(os.EX_SOFTWARE)
            os._exit(0)

        def display():
            self.window.twiddle(0.5, self)

        finishers = utils.process_in_fork(grow, display, config.PROCESSES, config.PROCESS_TIMEOUT)
        results = []
        for pid in finishers:
            try:
                fn = os.path.join(config.DATA_ROOT, "rules-%s.pickle" % pid)
                results.append(utils.unpickle(fn))
                if config.TIDY_FILES:
                    os.remove(fn)
            except IOError, e:
                log("missing out on pid %s", e)
Beispiel #10
0
    def play(self, hz=config.PLAY_HERTZ, replay=False):
        self.reset()
        w = self.window
        w.blank_screen(self)
        self.dead_rects = []
        dying_rects = []
        if replay: # replay is flag and duration combined
            self.play_state = config.STATE_REPLAY
            self.player_sprite.auto_mode()
            replay *= hz
            for s in w.sounds.values():
                s.set_volume(0.3)
        else:
            self.play_state = config.STATE_PLAYING
            self.player_sprite.manual_mode()
            for s in w.sounds.values():
                s.set_volume(1)

        start = time.time()
        self.player_score = 0
        self.game_over = False
        r = 0
        frame = -1
        DYING = config.DYING
        PLAYING = config.PLAYING
        try:
            while True:
                w.clock.tick(hz)
                if not frame:
                    r += 1
                    w.interpret_events(self.do_extra_keys)
                    for s in self.sprites:
                        if s.state == PLAYING:
                            s.decide()
                    if config.DRAW_FINDS:
                        self.sprites[3].draw_finds()
                    #XXX reduce sounds a bit more.
                    sounds = set()
                    for s in self.sprites:
                        if s.state == PLAYING:
                            s.update()
                            sounds.add(s.chatter())
                        elif s.state == DYING:
                            s.die2()

                    w.speak(sounds)
                    self.track_play(r)

                    #XXX with replay, also want to stop for button press
                    if replay:
                        if r > replay or w.fire_button:
                            raise GameStop("replay is over")

                for s in self.sprites:
                    if s.state == PLAYING:
                        s.slither(frame)
                    elif s.state == DYING:
                        s.dying_animation()
                        dying_rects.append(s.rect)
                w.redraw(self)
                self.dead_rects = dying_rects
                dying_rects = []
                frame = (frame + 1) % config.FRAMES_PER_UPDATE
                if self.game_over and config.GAME_ENDS:
                    raise GameOver

        except Exception, e:
            self.playing = False
            t = time.time() - start
            log("%s ticks in %s seconds: ~ %s per sec" % (r, t, (r + 0.5)/t))
            self.save_map(r)
            if not isinstance(e, (GameEscape, GameOver, GameStop)):
                raise
            if isinstance(e, GameOver):
                w.write("G A M E  O V E R")
                if self.player_score > self.high_score:
                    self.high_score = self.player_score
                if not replay:
                    self.pause(3)
Beispiel #11
0
 def end(self):
     self.game_over = True
     log("player is down!")
Beispiel #12
0
                    os.remove(fn)
            except IOError, e:
                log("missing out on pid %s", e)
        if not results:
            # the game is crashing
            raise ParseError("Sorry. The artist was lazy and stupid, and the machine can't handle your picture.")

        error, self.types = min(results)
        if error > config.REALLY_BAD_GAME_ERROR:
            # the game is hardly lasting very long at all.
            # send out an apology, which has no actual effect
            self.window.text_cycle(config.GROVEL_CYCLE)

        rules.apply_rules(self.teams, self.types[1:])

        log("%s teams:" % len(self.teams))
        for t in self.teams:
            log(t.size, t, t.rules)


    def reset(self):
        """Start the game again"""
        self.map.clear()
        for x in self.sprites:
            x.reset()


    def trial(self, cutoff):
        """Play automatically, without display.  Return the number of
        rounds played (before GameOver raised).  If there is no
        GameOver before cutoff is reached, stop anyway."""