Exemple #1
0
    def choose_size(self):
        """
        After interaction with the player, this method will return the
        selected board size. This method uses its own UI loop.
        """

        pygame.time.wait(300)
        toplay_orig = [
            #memory_text.choose_begin,
            memory_text.choose_small.format(memory_config.size['small']),
            #memory_text.choose_medium.format(memory_config.size['medium']),
            memory_text.choose_large.format(memory_config.size['large']),
            #memory_text.choose_huge.format(memory_config.size['huge']),
        ]
        toplay = toplay_orig[:]

        while True:
            self.audio.do_play()

            # get next pygame event in queue
            event = pygame.event.poll()

            if len(toplay) > 0:
                self.audio.synthesize_and_play(toplay.pop(0))

            if event.type == pygame.locals.QUIT:
                return 'terminate'

            if event.type == pygame.locals.KEYDOWN:
                # log key press
                keyname = pygame.key.name(event.key)
                liblog.log('key pressed: {}'.format(keyname))

                # any key press stops audio
                self.audio.stop_playback()
                self.audio.clear_queue()

                # arrow keys to select size
                if event.key == pygame.locals.K_LEFT:
                    return 'small'
                #if event.key == pygame.locals.K_UP:
                #    return 'medium'
                elif event.key == pygame.locals.K_RIGHT:
                    return 'large'
                #if event.key == pygame.locals.K_DOWN:
                #    return 'huge'

                if event.key == pygame.locals.K_F1:
                    self.tell_help()

                # escape to terminate
                elif event.key == pygame.locals.K_ESCAPE:
                    return 'terminate'

                # everything else to repeat
                #event.key == pygame.locals.K_SPACE:
                else:
                    toplay = toplay_orig[:]
Exemple #2
0
    def do_play(self):
        if pygame.mixer.get_busy():
            return

        if len(self.queue) > 0:
            soundfile = self.queue.pop(0)
            liblog.log('playing sound file "{}"'.format(soundfile))
            sound = pygame.mixer.Sound(soundfile)
            sound.play()
Exemple #3
0
 def change_speed(self, how, msg):
     minspeed = 0.6
     maxspeed = 2.0
     if how == 'faster':
         if self.speed < maxspeed:
             self.speed = min(self.speed + 0.2, maxspeed)
     else:
         if self.speed > minspeed:
             self.speed = max(self.speed - 0.2, minspeed)
     self.synthesize_and_play(msg)
     liblog.log('changed speaking rate to {:.1f}'.format(self.speed))
Exemple #4
0
    def run(self):
        self.ui.update_display()
        self.ui.welcome()
        self.ui.help()

        status = 'pre_game'

        while True:

            if status == 'pre_game':
                size = self.ui.choose_size()
                if size == 'terminate':
                    liblog.log('early termination during choose_size')
                    break

                self.init_game(size)
                status = self.logic.handle_event('begin')
                continue

            elif status == 'update':
                self.ui.walk()
                self.ui.tell_position(self.logic.curpos)
                self.ui.tell_options(self.logic.get_options())

            elif status == 'goal':
                self.ui.walk()
                self.ui.tell_position(self.logic.curpos)
                self.ui.tell_goal(self.logic.numsteps)
                self.log_seed_vector()
                again = self.ui.play_again()
                if again == 'new':
                    status = 'pre_game'
                    continue
                elif again == 'same':
                    status = self.logic.handle_event('begin')
                    continue
                elif again == 'terminate':
                    break

            elif status == 'invalid':
                self.ui.invalid()

            eventstring = self.ui.get_next_event()
            if eventstring == 'terminate':
                break
            elif eventstring == 'pre_game':
                status = eventstring
                continue
            else:
                status = self.logic.handle_event(eventstring)

        liblog.log('terminating')
Exemple #5
0
    def get_next_event(self):

        pygame.time.wait(10)

        self.audio.do_play()

        # get next pygame event in queue
        event = pygame.event.poll()

        if event.type == pygame.locals.QUIT:
            return 'hardterminate'

        if event.type == pygame.locals.KEYDOWN:

            # log key press
            keyname = pygame.key.name(event.key)
            if keyname == ';': keyname = '\xc3\xb6'
            liblog.log('key pressed: {}'.format(keyname))

            # any key press stops audio
            self.audio.stop_playback()
            self.audio.clear_queue()

            if event.key in self.allowed_field_keys:
                self.lastkey = keyname
                return 'field_' + str(self.allowed_field_keys.index(event.key))

            # space bar for repeating current position and options
            if event.key == pygame.locals.K_SPACE:
                return 'repeat'

            # escape for terminating
            if event.key == pygame.locals.K_ESCAPE:
                return 'terminate'

            if event.key == pygame.locals.K_F1:
                self.tell_help()
                return ''
            # F2 and F3 to change speaking rate
            if event.key == pygame.locals.K_F2:
                self.audio.change_speed('slower', memory_text.speed_slower)
                return ''
            if event.key == pygame.locals.K_F3:
                self.audio.change_speed('faster', memory_text.speed_faster)
                return ''

            # invalid key, play short sound
            self.audio.clear_queue()
            self.audio.priority_play('data/audio/effects/blop.wav')

        return ''
Exemple #6
0
    def handle_event(self, eventstring):

        if eventstring == '':
            return None

        #~ print 'eventstring: {}'.format(eventstring)

        if eventstring == 'begin':
            # put player in start node
            self.curpos = 0
            self.prevpos = None
            self.numsteps = 0
            self.starttime = datetime.datetime.now()
            return 'update'

        if eventstring in ('left', 'right', 'forward', 'back'):

            opts = self.get_options()

            # selected option might be invalid at current node
            if eventstring not in opts.keys():
                return 'invalid'

            # otherwise, update current and position
            self.prevpos = self.curpos
            self.curpos = opts[eventstring]

            # increment number of taken steps
            self.numsteps += 1

            # log player move
            liblog.log('player moved {:7s}: {}->{} ({} -> {})'.format(
                eventstring,
                self.prevpos,
                self.curpos,
                self.rooms[self.prevpos][0],
                self.rooms[self.curpos][0],
            ))

            # we might have reached the goal
            if self.curpos == self.goal:
                elapsedtime = datetime.datetime.now() - self.starttime
                liblog.log('goal reached after {} steps and {} seconds'.format(
                    self.numsteps, elapsedtime.total_seconds()))
                return 'goal'
            else:
                return 'update'
Exemple #7
0
    def __init__(self, gamenum, voice):
        
        if gamenum is not None:
            self.gamenum = gamenum
        else:
            # try to load game
            self.load_game()
        
        print "Beginne mit " + str(self.gamenum)
        
        # set up logging
        liblog.init_logging('memory')
        
        liblog.log('game starting with game number {}'.format(self.gamenum))

        # create audio processing object
        self.audio = libaudio.Audio(voice, 'memory')

        # create user interface object
        self.ui = memory_ui.UI(self.audio)
Exemple #8
0
 def log_seed_vector(self):
     liblog.log('-' * 54)
     msg = 'seed index vector (small,medium,large,huge) is '
     msg += '{},{},{},{}'.format(
         self.seed_indices['small'],
         self.seed_indices['medium'],
         self.seed_indices['large'],
         self.seed_indices['huge'],
     )
     liblog.log(msg)
     liblog.log('-' * 54)
Exemple #9
0
    def init_game(self, size):
        """
        Initializes a new game of the specified size.
        """

        liblog.log('initializing new game ({}) with number {}'.format(size, self.gamenum))
            
        nextseed = memory_config.seeds[self.gamenum]
        random.seed(nextseed)

        # initialize game logic, including creation of a random board
        self.logic = memory_logic.GameLogic(size)
        
        # now select game theme and random objects from theme for each board field
        self.init_theme(self.logic.board.size)
        self.ui.set_num_fields(self.logic.board.size)       
        self.logic.things = self.things 

        liblog.log('board = {}'.format(self.logic.board.fields))
        liblog.log('things = {}'.format(self.things))
        liblog.log('game initialization complete')
Exemple #10
0
    def init_game(self, size):
        """
        Initializes a new game of the specified size (number of rooms).
        """

        liblog.log('initializing new game ({})'.format(size))

        i = self.seed_indices[size]
        nextseed = labyrinth_config.seeds[size][i]
        random.seed(nextseed)
        liblog.log('seed number {} for {} size is {}'.format(
            i, size, nextseed))
        self.seed_indices[size] += 1

        # initialize game logic, including creation of a random labyrinth
        self.logic = labyrinth_logic.GameLogic(size)

        # assign random names to rooms for player interaction
        self.ui.shuffle_rooms()
        self.logic.rooms = self.ui.rooms

        liblog.log('game initialization complete')
Exemple #11
0
    def create_graph(self):
        """Creates a random undirected graph, the actual labyrinth
        
        The graph is represented by a (symmetrical, because the graph is
        undirected) incidence matrix (a numpy.ndarray), which this function
        returns.
        """

        n = self.size

        # create empty incidence matrix
        graph = numpy.zeros((n, n), dtype=numpy.int8)

        # set a number of rooms aside, they will be added as dead ends at the
        # end
        m = n - self.dead_ends

        # create random tree by attaching each node to a randomly selected
        # earlier node which doesn't have too many neighbors yet
        for i in range(1, m):

            # potential neighbors
            nodes = [x for x in range(i) if sum(graph[x]) < 3]

            j = random.choice(nodes)
            graph[i, j] = 1
            graph[j, i] = 1

        #print graph

        blacklist = []

        # add dead ends
        # all nodes whose degree is less than 4
        nodes = [x for x in range(m) if sum(graph[x]) < 4 and x != 0]
        random.shuffle(nodes)
        for i in range(m, n):

            j = nodes.pop(0)
            graph[i, j] = 1
            graph[j, i] = 1
            blacklist.append(i)

        # randomly add edges, as long as no node's degree gets too large
        #~ blacklist = []
        while True:

            # all nodes whose degree is less than 3
            nodes = [
                x for x in range(m) if sum(graph[x]) < 3 and x not in blacklist
            ]

            if len(nodes) == 0:
                #print 'I couldn\'t find a node with degree less than 3'
                break

            i = random.choice(nodes)

            #print 'I\'ll try to add an edge to node {}'.format(i)

            # all nodes
            #  - except the start node
            #  - and i itself
            #  - whose degree is less than 4
            #  - and which are not already connected to i
            nodes = [
                x for x in range(1, m)
                if x != i and sum(graph[x]) < 4 and graph[i, x] == 0
            ]
            if len(nodes) == 0:
                #print 'I couldn\'t find one, blacklisting node {}'.format(i)
                blacklist.append(i)
                continue

            j = random.choice(nodes)

            #print 'adding edge ({},{})'.format(i, j)
            graph[i, j] = 1
            graph[j, i] = 1
            #print graph

        #self.draw_graph(graph)
        #print graph

        # write labyrinth info to log
        numedges = graph.sum() / 2
        liblog.log(
            'labyrinth generated. number of nodes: {} number of edges: {}'.
            format(n, numedges))
        msg = 'labyrinth node adjacency matrix:\n'
        opts = numpy.get_printoptions()
        numpy.set_printoptions(threshold='nan')
        msg += numpy.array_str(graph, max_line_width=500)
        numpy.set_printoptions(**opts)
        liblog.log(msg)

        return graph
Exemple #12
0
    def get_next_event(self):

        pygame.time.wait(50)
        
        self.audio.do_play()

        # get next pygame event in queue
        event = pygame.event.poll()

        if event.type == pygame.locals.QUIT:
            return 'terminate'

        if event.type == pygame.locals.KEYDOWN:

            # log key press
            keyname = pygame.key.name(event.key)
            liblog.log('key pressed: {}'.format(keyname))

            # any key press stops audio
            self.audio.stop_playback()
            self.audio.clear_queue()

            # arrow keys for moving through the labyrinth
            if event.key == pygame.locals.K_LEFT:
                return 'left'
            if event.key == pygame.locals.K_RIGHT:
                return 'right'
            if event.key == pygame.locals.K_UP:
                return 'forward'
            if event.key == pygame.locals.K_DOWN:
                return 'back'

            # space bar for repeating current position and options
            if event.key == pygame.locals.K_SPACE:
                self.tell_position(self.last_curpos)
                self.tell_options(self.last_options)
                return ''

            # escape for terminating
            if event.key == pygame.locals.K_ESCAPE:
                return 'terminate'

            # F2 and F3 to change speaking rate
            if event.key == pygame.locals.K_F2:
                self.audio.change_speed('faster', labyrinth_text.speed_changed)
                return ''
            if event.key == pygame.locals.K_F3:
                self.audio.change_speed('slower', labyrinth_text.speed_changed)
                return ''

            # F4 for aborting current labyrinth
            if event.key == pygame.locals.K_F4:
                self.audio.synthesize_and_play(labyrinth_text.abort)
                liblog.log('labyrinth aborted')
                return 'pre_game'

            # F1 for help
            if event.key == pygame.locals.K_F1:
                self.help()
                return ''


            # invalid key, play short sound
            self.audio.clear_queue()
            self.audio.priority_play('data/audio/effects/blop.wav')

        return ''
Exemple #13
0
    def play_again(self):
        """
        After completing one game, asks the player if she wants to play again.
        If yes, go to choose size. If no, terminate.
        Like choose_size, this uses its own UI loop
        """
        
        toplay_orig = [
            labyrinth_text.left_play_again,
            labyrinth_text.right_play_same_again,
            labyrinth_text.escape_terminate
        ]
        toplay = toplay_orig[:]
        
        while True:
            self.audio.do_play()

            if len(toplay) > 0:
                self.audio.synthesize_and_play(toplay.pop(0))

            # get next pygame event in queue
            event = pygame.event.poll()

            if event.type == pygame.locals.QUIT:
                return 'terminate'
        
            if event.type == pygame.locals.KEYDOWN:
                # log key press
                keyname = pygame.key.name(event.key)
                liblog.log('key pressed: {}'.format(keyname))
                
                # any key press stops audio
                self.audio.stop_playback()
                self.audio.clear_queue()
                
                # arrow keys to select new game, same game or quit
                if event.key == pygame.locals.K_LEFT:
                    return 'new'
                if event.key == pygame.locals.K_RIGHT:
                    liblog.log('restarting same labyrinth')
                    return 'same'

                # space bar to repeat options
                if event.key == pygame.locals.K_SPACE:
                    toplay = toplay_orig[:]
                    continue
                
                # escape to terminate
                if event.key == pygame.locals.K_ESCAPE:
                    return 'terminate'

                # F2 and F3 to change speaking rate
                if event.key == pygame.locals.K_F2:
                    self.audio.change_speed('slower', labyrinth_text.speed_changed)
                    continue
                if event.key == pygame.locals.K_F3:
                    self.audio.change_speed('faster', labyrinth_text.speed_changed)
                    continue

                # F1 for help
                if event.key == pygame.locals.K_F1:
                    self.help()
                    continue
                    
                # unknown key    
                self.audio.play_sound_file('data/audio/effects/blop.wav')
Exemple #14
0
    def choose_size(self):
        """
        After interaction with the player, this method will return the
        selected labyrinth size. This method uses its own UI loop.
        """

        pygame.time.wait(500)
        toplay_orig = [
            labyrinth_text.choose_size_begin,
            labyrinth_text.choose_size.format(
                labyrinth_text.sizes['small'][0],
                labyrinth_text.sizes['small'][1],
                labyrinth_config.size['small']
            ),
            labyrinth_text.choose_size.format(
                labyrinth_text.sizes['medium'][0],
                labyrinth_text.sizes['medium'][1],
                labyrinth_config.size['medium']
            ),
            labyrinth_text.choose_size.format(
                labyrinth_text.sizes['large'][0],
                labyrinth_text.sizes['large'][1],
                labyrinth_config.size['large']
            ),
            labyrinth_text.choose_size.format(
                labyrinth_text.sizes['huge'][0],
                labyrinth_text.sizes['huge'][1],
                labyrinth_config.size['huge']
            ),
        ]
        toplay = toplay_orig[:]

        while True:
            self.audio.do_play()

            # get next pygame event in queue
            event = pygame.event.poll()

            if len(toplay) > 0:
                self.audio.synthesize_and_play(toplay.pop(0))

            if event.type == pygame.locals.QUIT:
                return 'terminate'
        
            if event.type == pygame.locals.KEYDOWN:
                # log key press
                keyname = pygame.key.name(event.key)
                liblog.log('key pressed: {}'.format(keyname))
                
                # any key press stops audio
                self.audio.stop_playback()
                self.audio.clear_queue()
                
                # arrow keys to select size
                if event.key == pygame.locals.K_LEFT:
                    self.audio.synthesize_and_play(
                        labyrinth_text.selected_size.format(
                                labyrinth_text.sizes['small'][1]))
                    return 'small'
                if event.key == pygame.locals.K_UP:
                    self.audio.synthesize_and_play(
                        labyrinth_text.selected_size.format(
                                labyrinth_text.sizes['medium'][1]))
                    return 'medium'
                if event.key == pygame.locals.K_RIGHT:
                    self.audio.synthesize_and_play(
                        labyrinth_text.selected_size.format(
                                labyrinth_text.sizes['large'][1]))
                    return 'large'
                if event.key == pygame.locals.K_DOWN:
                    self.audio.synthesize_and_play(
                        labyrinth_text.selected_size.format(
                                labyrinth_text.sizes['huge'][1]))
                    return 'huge'

                # space bar to repeat options
                if event.key == pygame.locals.K_SPACE:
                    toplay = toplay_orig[:]
                
                # escape to terminate
                if event.key == pygame.locals.K_ESCAPE:
                    return 'terminate'

                # F2 and F3 to change speaking rate
                if event.key == pygame.locals.K_F2:
                    self.audio.change_speed('slower', labyrinth_text.speed_changed)
                    continue
                if event.key == pygame.locals.K_F3:
                    self.audio.change_speed('faster', labyrinth_text.speed_changed)
                    continue

                # F1 for help
                if event.key == pygame.locals.K_F1:
                    self.help()
                    continue
Exemple #15
0
    def run(self):
        self.ui.update_display()
        self.ui.welcome()

        self.ui.tell_round(self.gamenum+1)
        size = self.choose_size()
        if size == 'terminate':
            liblog.log('early termination during choose_size')
            return

        self.init_game(size)                   
        self.ui.tell_size(size)        
        self.ui.tell_theme(self.themeidx)

        laststatus = status = self.logic.handle_event('begin')

        while not self.logic.terminate:
                        
            # user has to select field 1
            if status == 'select1':
                # tell user which field she selected as #2
                if self.logic.current_thing  is not None:
                    self.ui.tell_thing_selected( self.things[ self.logic.current_thing - 1 ] )
                # tell user if both fields matched
                if self.logic.last_correct  is not None:
                    self.ui.tell_correct( self.logic.last_correct )
                # tell user to selected a #1 field                
                self.ui.tell_select_field( 1 )
                
            # user has to select field 2
            elif status == 'select2':                
                # tell user the field #1 she selected
                if self.logic.current_thing is not None:
                    self.ui.tell_thing_selected( self.things[ self.logic.current_thing - 1 ] )
                # sell user to select field #2                
                self.ui.tell_select_field( 2 )
                
            elif status == 'wrongfield':
                self.ui.tell_wrongfield()
                                
            elif status == 'finished':
                self.ui.tell_thing_selected( self.things[ self.logic.current_thing - 1 ] )
                                
                # all games done?                
                #if self.gamenum == 7: self.ui.tell_goal_all8(self.logic.numsteps)
                self.ui.tell_goal(self.logic.numsteps)
                
                self.gamenum += 1
                self.save_game()
                self.ui.tell_round(self.gamenum+1)                
                size = self.choose_size()
                if size == 'terminate':
                    break
                else:                                        
                    self.init_game(size)          
                    self.ui.tell_size(size)
                    self.ui.tell_theme( self.themeidx )                    
                    status = self.logic.handle_event('begin')
                    pygame.event.clear()
                    continue

            eventstring = self.ui.get_next_event()
            # repeat last status
            if eventstring == 'repeat':    
                status = laststatus                            
                continue
            # don't allow quitting too early ;)
            #if eventstring == 'terminate' and self.gamenum < 8:
            #    eventstring = ''
            status = self.logic.handle_event(eventstring)
            # save last status message
            if status is not None and status is not "wrongfield": laststatus = status

        liblog.log('terminating')
Exemple #16
0
    def handle_event(self, eventstring):

        if eventstring == '':
            return None

        #print 'eventstring: {}'.format(eventstring)

        if eventstring == 'terminate':
            self.terminate = True
            return None

        if eventstring == 'hardterminate':
            self.terminate = True
            return None

        # get started
        if eventstring == 'begin':
            self.current_state = self.States.SELECT_1
            self.field1 = None
            self.field2 = None
            self.current_thing = None
            self.last_correct = None
            self.starttime = datetime.datetime.now()
            self.numsteps = 0
            return 'select1'

        # user selected a field
        if eventstring.startswith("field_"):
            fieldsel = int(eventstring[6:])

            if self.board.fields[fieldsel] < 1 or fieldsel == self.field1:
                liblog.log(
                    'user selected field {} which is already finished.'.format(
                        fieldsel))
                return 'wrongfield'

            # user selected the first field
            if self.current_state == self.States.SELECT_1:
                liblog.log('user selected field1: {} ({}).'.format(
                    fieldsel, self.things[self.board.fields[fieldsel] - 1]))
                self.field1 = fieldsel
                self.current_thing = self.board.fields[fieldsel]
                self.current_state = self.States.SELECT_2
                return 'select2'

            # user selected the second field
            if self.current_state == self.States.SELECT_2:
                liblog.log('user selected field2: {} ({}).'.format(
                    fieldsel, self.things[self.board.fields[fieldsel] - 1]))
                self.field2 = fieldsel
                self.current_thing = self.board.fields[fieldsel]

                self.numsteps += 1

                # see if fields match
                if self.board.fields[self.field1] == self.board.fields[
                        self.field2]:
                    liblog.log(
                        'user was correct with field1: {} ({}) and field2: {} ({}).'
                        .format(
                            self.field1,
                            self.things[self.board.fields[self.field1] - 1],
                            self.field2,
                            self.things[self.board.fields[self.field2] - 1]))
                    self.board.fields[self.field1] = self.board.fields[
                        self.field2] = 0
                    self.last_correct = True

                    if sum(self.board.fields) == 0:
                        elapsedtime = datetime.datetime.now() - self.starttime
                        liblog.log(
                            'goal reached after {} steps and {} seconds'.
                            format(self.numsteps, elapsedtime.total_seconds()))
                        self.current_state = self.States.FINISH
                        return 'finished'

                else:
                    liblog.log(
                        'user was wrong with field1: {} ({}) and field2: {} ({}).'
                        .format(
                            self.field1,
                            self.things[self.board.fields[self.field1] - 1],
                            self.field2,
                            self.things[self.board.fields[self.field2] - 1]))
                    self.last_correct = False

                self.field1 = None
                self.field2 = None
                self.current_state = self.States.SELECT_1
                return 'select1'

        return None