예제 #1
0
def handle_user_input(player):
    '''
        continuously gets the command from user
        for move, also simulates the position change
        move command can be rejected (player re-prompted) if it would move player out of the map
        in that case, user is reprompted until a valid command is issued

        :param player: Player

        :returns 
            Save if save command was issued
            Load is load command was issued
            None if move command was issued (and successfully simulated)
    '''
    while True:
        command = parse_user_input()

        if command == Save or command == Load:
            return command

        delta = command

        if player.try_move(delta):
            dlog.debug(f'moved to {player.position}')
            return None
        else:
            olog.info("Can't move there - a wall blocks the path")
    def __init__(self, size):
        '''
        creates a size * size dungeon map
        where 1/10 tiles are treasures and other 2/10 - traps
        :param size: int, > 0
        '''
        if size <= 0:
            raise ValueError('size must be > 0')
        self.size = size

        count = size * size
        trap_count = floor(count * TRAP_QUOTA)
        treasure_count = floor(count * TREASURE_QUOTA)
        empty_count = count - trap_count - treasure_count

        treasures = [Treasure] * treasure_count
        traps = [Trap] * trap_count
        empties = [Empty] * empty_count
        dlog.debug(
            f'Created {treasure_count} treasures, {trap_count} traps, {empty_count} empties'
        )

        combined = treasures
        combined.extend(traps)
        combined.extend(empties)

        shuffle(combined)

        self.tiles = list(chunks(combined, size))
        dlog.debug(
            f'Created a map of {len(combined)} elements (with size {size})')
 def try_attack_player(self, player):
     '''
         unleashes the whole might of our 1 dmg attack 
         on the unsuspecting player, if he is in reach (on the same tile as enemy)
     '''
     if self.gotcha_player(player):
         dlog.debug('damaged player')
         olog.info('the grue\'s got you!')
         player.lose_health()
    def get_random_empty_tile(self):
        '''
            :param map: dungeon map object
            :returns: random Tile with empty type
        '''
        dlog.debug('get_random_empty_tile')
        rand_index = lambda: randint(0, len(self.tiles) - 1)

        while True:
            maybe_empty = (rand_index(), rand_index())
            dlog.debug(f'randomed tile: {maybe_empty}')

            if self.at(maybe_empty) == Empty:
                return maybe_empty
    def move_randomly(self):
        '''
            moves one delta in the random direction
            (not going into walls)
        '''
        if not self.dungeon_map.in_bounds(self.position):
            ValueError(
                'enemie\'s position is out of bounds of argument DungeonMap')

        while True:
            rand_move_dt = move_directions[randrange(len(move_directions))]

            new_pos = tuple_add(self.position, rand_move_dt)
            if self.dungeon_map.in_bounds(new_pos):
                self.position = new_pos
                dlog.debug(f'enemy moved to {self.position}')
                break
예제 #6
0
def handle_load():
    '''
        tries to load, telling user if the savefile does not exist
        :returns: tuple (dmap, player) - deserialized DungeonMap and Player
            or None if the load was unsuccessful
    '''
    if not save_exists():
        dlog.debug('Tried to load when savefile does not exist')
        olog.info('You haven\'t saved it yet!')
        return None

    try:
        deserialized = load()
        dlog.debug('changed state to loaded:')
        olog.info('Loaded your game!\n')

        return deserialized

    except UnpicklingError:
        olog.info('Could not load the save, savefile corrupted')
        return None
예제 #7
0
def play_game(size):
    dmap = DungeonMap(size)

    player_dead = Event()
    player_won = Event()

    player = Player(TREAUSURES_FOR_WIN, dmap, lambda: player_dead.set())

    start = dmap.get_random_empty_tile()
    dlog.debug(f'Starting at {start}')

    olog.info(
        'Note: you can input \'save\' any time to save the game, or \'load\' to load last saved one'
    )
    player.position = start

    enemy = Enemy(dmap)
    enemy.start_patroling(player)

    print(dmap.map_to_str(player.position, enemy.position))

    while not player_dead.is_set() and not player_won.is_set():
        run_turn(player_dead, player_won, player, dmap)
        # uncomment for perfect debug experience
        print(dmap.map_to_str(player.position, enemy.position))

    enemy.stop_patroling()

    won = player_won.is_set()
    lost = player_dead.is_set()
    assert won != lost

    if won:
        win(dmap, player.position, enemy.position)
    else:
        assert lost
        lose(dmap, player.position, enemy.position)
    def patrol(self, player):
        '''
            a single turn of patrol
            attacks player if standing on the same tile, moves randomly and tries to attack again
        '''
        self.try_attack_player(player)
        self.move_randomly()
        self.try_attack_player(player)

        tile_val = self.dungeon_map.at(self.position)
        if tile_val == dm.Treasure:
            dlog.debug(f'enemy ate treasure at {self.position}')

        elif tile_val == dm.Trap:
            dlog.debug(f'enemy died from a trap at {self.position}')
            self.position = self.dungeon_map.get_random_empty_tile()
            dlog.debug(f'enemy respawned to {self.position}')

        # eats our treasure, or destroys the trap by activating it
        self.dungeon_map.set_tile(self.position, dm.Empty)