Beispiel #1
0
    def probableRangedAttack(self):
        """
        Return an action for a ranged attack on a target if such an attack is
        possible.  Otherwise, return None.
        """
        if "two_square_thrower" in self.tags:
            if self.currentLevel.player in self.fov \
                and coordinates.minimumPath(self.coords, self.currentLevel.player.coords) in range(1, 4):

                possible_directions = ((2, 0), (2, 2), (0, 2), (-2, 2),
                                       (-2, 0), (-2, -2), (0, -2), (2, -2))
                possible_targets = [
                    coordinates.add(self.coords, i)
                    for i in possible_directions if self.currentLevel.isEmpty(
                        coordinates.add(self.coords, i))
                ]
                visible_targets = [
                    coords for coords in possible_targets if coords in self.fov
                ]
                close_targets = [
                    coords for coords in visible_targets
                    if (coordinates.minimumPath(
                        coords, self.currentLevel.player.coords) <= 1)
                ]
                actual_targets = [
                    coords for coords in close_targets
                    if coords not in self.currentLevel.dudeLayer
                ]
                if len(actual_targets) == 0:
                    return None
                final_target = rng.choice(actual_targets)
                return action.ThrowGrenade(self, final_target)
            else:
                return None
        elif "straight_shooter" in self.tags:
            direction = coordinates.get_cardinal_direction(
                self.coords, self.currentLevel.player.coords)
            dist = coordinates.minimumPath(self.coords,
                                           self.currentLevel.player.coords)
            if self.currentLevel.player in self.fov \
                and direction is not None \
                and dist < 12:

                if self.spec == "ARROW":
                    return action.FireArrow(self, direction, 12)
                elif self.spec == "POUNCE":
                    return action.Pounce(self, direction, 12)
                else:
                    assert False
                    return None
            else:
                return None
        else:
            return None
Beispiel #2
0
 def do(self):
     if self.prev_summons < len(self.SUMMONS):
         self.level_.messages.append(self.message)
         enemy_list = self.SUMMONS[self.prev_summons]
         for (name, coords) in enemy_list:
             real_coords = coordinates.add(coords, self.CENTER)
             mon = self.level_.createMonster(name, real_coords)
Beispiel #3
0
    def do(self):
        cur_lev = self.source.currentLevel
        next_loc = self.source.coords

# Essentially a for loop, for i in range(self.distance).
        i = 0
        while True:
            if i >= self.distance:
                cur_lev.messages.append("%s pounced, but caught only air."
                    % self.source.getName())
                break

            i += 1

            next_loc = coordinates.add(self.source.coords, self.direction)
            display.refresh_screen()
            
            if not cur_lev.isEmpty(next_loc):
                cur_lev.messages.append("%s pounced at the wall."
                    % self.source.getName())
                break
            elif next_loc in cur_lev.dudeLayer:
                # The pouncer hit a dude.
                target = cur_lev.dudeLayer[next_loc]
                # Bounce off: behind the dude if possible, in front otherwise.
                behind = coordinates.add(next_loc, self.direction)
                in_front = coordinates.subtract(next_loc, self.direction)

                if (cur_lev.isEmpty(behind) and behind not in cur_lev.dudeLayer):
                    cur_lev.moveDude(self.source, behind)
# The pouncer should already be in front of the target, so if it is not going
# through them, no motion is necessary.

                damage_dealt = damage(self.source.attack, target.defense,
                               self.source.char_level, target.char_level)
                cur_lev.messages.append("%s pounced on %s! (%d)"
                    % (self.source.getName(), target.getName(), damage_dealt))
                target.cur_HP -= damage_dealt
                target.checkDeath()
                break

            else:
                cur_lev.moveDude(self.source, next_loc)

        display.refresh_screen()
        return self.source.speed
Beispiel #4
0
    def getAction(self, dude_):
        if dude_.canMove(coordinates.add(dude_.coords, self.direction)) \
            and len(dude_.fov.dudes) == 0:

            return action.Move(dude_, self.direction)
        else:
            self.time = -5
            return None
Beispiel #5
0
def do_special_melee(attack_type, source, target):
    """
    Have a Dude perform a special melee attack.

    attack_type - a string representing the type of special attack.
    source - the Dude attacking.
    target - the Dude being attacked.
    """

    if attack_type == "CRITICAL":
        damage_dealt = CRIT_MULTIPLIER * \
                       damage(source.attack, target.defense,
                              source.char_level, target.char_level)
        source.currentLevel.messages.append(
        "%(SOURCE_NAME)s runs %(TARGET_NAME)s all the way through! (%(DAMAGE)d)"
            % {"SOURCE_NAME": source.getName(),
               "DAMAGE": damage_dealt,
               "TARGET_NAME": target.getName()})
        target.cur_HP -= damage_dealt
        target.checkDeath()
    elif attack_type == "KNOCK":
        damage_dealt = KNOCK_DAMAGE
        direction = coordinates.subtract(target.coords, source.coords)
        source.currentLevel.messages.append(
        "%(SOURCE_NAME)s delivers a wicked punch to %(TARGET_NAME)s! (%(DAMAGE)d)"
            % {"SOURCE_NAME": source.getName(),
               "DAMAGE": damage_dealt,
               "TARGET_NAME": target.getName()})
        for i in range(KNOCK_DISTANCE):
            display.refresh_screen()
            destination = coordinates.add(target.coords, direction)
            if target.canMove(destination):
                target.currentLevel.moveDude(target, destination)
            else:
                break
        display.refresh_screen()
        target.cur_HP -= damage_dealt
        target.checkDeath()
    elif attack_type == "EXPLODE":
        explode_action = Explode(source.currentLevel, source.coords, 10)
        source.currentLevel.messages.append(
        "%(SOURCE_NAME)s explodes!"
            % {"SOURCE_NAME": source.getName()})
        explode_action.do()
    elif attack_type == "STICK":
        damage_dealt = damage(source.attack, target.defense,
                       source.char_level, target.char_level) / 5
        source.currentLevel.messages.append(
        "%(SOURCE_NAME)s spins a web around %(TARGET_NAME)s! (%(DAMAGE)d)"
            % {"SOURCE_NAME": source.getName(),
               "DAMAGE": damage_dealt,
               "TARGET_NAME": target.getName()})
        target.giveCondition(cond.Stuck(8))
        target.cur_HP -= damage_dealt
        target.checkDeath()
    else:
        raise exc.InvalidDataWarning("%s special ability used by %s on %s."
                                     % (attack_type, str(source), str(target)))
Beispiel #6
0
    def do(self):
        """
        Move the source of the action in the direction specified.
        Raise a ValueError if such a move is illegal.
        
        act - the action to be performed.

        Returns True if the move can be performed, and returns False if it
        cannot.
        """
        destination_coords = coordinates.add(self.source.coords, self.coords)

        if self.source.canMove(destination_coords):
            self.source.currentLevel.moveDude(self.source, destination_coords)
            return self.source.speed
        else:
            assert False
            return 0
Beispiel #7
0
def copy_array_subset(src_nw_corner, dst_nw_corner, block_dims, src_array, dst_array):
    """
    This function differs only from copy_array_subset_lenient in that it
    raises exceptions whenever the coordinates given refer to squares not
    actually in the arrays provided.
    """

    exc.check_in_array(src_nw_corner, src_array.shape)
    exc.check_in_array(dst_nw_corner, dst_array.shape)
    exc.check_in_array(coordinates.add(coordinates.add(src_nw_corner, block_dims), (-1, -1)), src_array.shape)
    exc.check_in_array(coordinates.add(coordinates.add(dst_nw_corner, block_dims), (-1, -1)), dst_array.shape)

    for x in range(block_dims[0]):
        for y in range(block_dims[1]):
            dst_array[coordinates.add(dst_nw_corner, (x, y))] = src_array[coordinates.add(src_nw_corner, (x, y))]

    return
Beispiel #8
0
    def do(self):
        current_location = self.source.coords
        self.source.currentLevel.addSolidEffect(current_location, ARROW_GLYPH)
        self.source.currentLevel.makeNoise(
            self.message % {"SOURCE_NAME": self.source.getName()},
            self.source.coords)

        i = 0
        while True:
            i += 1
            display.refresh_screen()
            self.source.currentLevel.removeSolidEffect(current_location, ARROW_GLYPH)
            current_location = coordinates.add(current_location, self.direction)
            self.source.currentLevel.addSolidEffect(current_location, ARROW_GLYPH)

            if not self.source.currentLevel.isEmpty(current_location):
                break # If the arrow runs into a wall, just stop.
            elif current_location in self.source.currentLevel.dudeLayer:
                # The arrow hit a dude!
                target = self.source.currentLevel.dudeLayer[current_location]
                damage_dealt = damage(self.source.attack, target.defense,
                               self.source.char_level, target.char_level)
                self.source.currentLevel.makeNoise(
                    "The arrow hit %s. (%d)"
                    % (target.getName(), damage_dealt),
                    self.source.coords)
                display.refresh_screen()
                target.cur_HP -= damage_dealt
                target.checkDeath()
                self.source.currentLevel.removeSolidEffect(current_location, ARROW_GLYPH)
                break
            else:
                if i >= 12:
                    self.source.currentLevel.removeSolidEffect(current_location, ARROW_GLYPH)
                    display.refresh_screen()
                    break

        return self.source.speed
Beispiel #9
0
def randomDungeon():
    """
    Gets a random dungeon, using a very simple room/corridor model.
    
    The room/corridor model used is similar to that of Rogue; the map is
    divided into nine sectors, each of which is randomly called a room,
    a corridor, or empty.  Once this is done, rooms and corridors are connected
    to adjacent rooms and corridors.
    
    This is coded terribly because it will be replaced someday.
    """
    
    map_dimensions = (60, 60)
    map_nwcorner = (10, 10)
    sector_size = (12, 12)
    sector_nwcorners = {}
    for x in range(0, 3):
        for y in range(0, 3):
            sector_nwcorners[(x, y)] = (
                map_nwcorner[0] + sector_size[0] * x,
                map_nwcorner[1] + sector_size[1] * y
                )
                
    sector_types = {}
    for x in range(0, 3):
        for y in range(0, 3):
            percent = rng.randInt(1, 100)
            if percent <= 60:
                sector_types[(x, y)] = 1 # it's a room!
            elif percent <= 75:
                sector_types[(x, y)] = 2 # it's a corridor!
            else:
                sector_types[(x, y)] = 0 # it's empty!
    
    room_nwcoords = {}
    room_secoords = {}
    
    for sector_coords in sector_types.keys():
        if sector_types[sector_coords] == 1:
            room_created = False
            sector_nw = sector_nwcorners[sector_coords]
            sector_se = (sector_nw[0] + sector_size[0] - 1, sector_nw[1] + sector_size[1] - 1)
            while not room_created:
                room_nw = (rng.randInt(sector_nw[0], sector_se[0]),
                           rng.randInt(sector_nw[1], sector_se[1]))
                room_se = (room_nw[0] + rng.randInt(3, 8),
                           room_nw[1] + rng.randInt(3, 8))
            
                # check validity of room dimensions
                if room_se[0] <= sector_se[0] and room_se[1] <= sector_se[1]:
                    room_nwcoords[sector_coords] = room_nw
                    room_secoords[sector_coords] = room_se
                    room_created = True
                    
        elif sector_types[sector_coords] == 2:
            # A corridor is currently implemented as just a 1-space room.
            corridor_coords = (rng.randInt(sector_nwcorners[sector_coords][0],
                                           sector_nwcorners[sector_coords][0] + sector_size[0] - 1,),
                               rng.randInt(sector_nwcorners[sector_coords][1],
                                           sector_nwcorners[sector_coords][1] + sector_size[1] - 1,))
            room_nwcoords[sector_coords] = corridor_coords
            room_secoords[sector_coords] = corridor_coords
    
    # Check whether everywhere is accessible; if not, do a redo.
    sector_is_accessible = {}
    for x in range(3):
        for y in range(3):
            sector_is_accessible[(x, y)] = False
    
    for coord in ((0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)):
        if True not in sector_is_accessible.values() and sector_types[coord] != 0:
            sector_is_accessible[coord] = True
        
        if sector_is_accessible[coord] == True and sector_types[coord] != 0:
            for coord_adjustment in ((1, 0), (0, 1), (-1, 0), (0, -1)):
                adjacent_coord = coordinates.add(coord, coord_adjustment)
                if (adjacent_coord[0] >= 0 and
                    adjacent_coord[0] < 3 and
                    adjacent_coord[1] >= 0 and
                    adjacent_coord[1] < 3):
                    
                    sector_is_accessible[adjacent_coord] = True
    
    for accessible in sector_is_accessible.items():
        if sector_types[accessible[0]] != 0 and not accessible[1]:
            # Oops.  Give up and try again.
            return randomDungeon()
    
    entrance_sector = rng.choice([coords for coords in sector_types.keys() if sector_types[coords] == 1])
    exit_sector = rng.choice([coords for coords in sector_types.keys() if sector_types[coords] == 1])
    entrance_coords = rng.randomPointInRect(room_nwcoords[entrance_sector], room_secoords[entrance_sector])
    exit_coords = rng.randomPointInRect(room_nwcoords[exit_sector], room_secoords[exit_sector])
    
    ret_dungeon = level.empty_dungeon(map_dimensions)
    
    for coord in ((0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)):
        if sector_types[coord] != 0:
            for x in range(room_nwcoords[coord][0], room_secoords[coord][0] + 1):
                for y in range(room_nwcoords[coord][1], room_secoords[coord][1] + 1):
                    if sector_types[coord] == 1:
                        ret_dungeon[(x, y)] = level.ROOM_INTERIOR_GLYPH
                    else:
                        ret_dungeon[(x, y)] = level.CORRIDOR_GLYPH
            
            for coord_adjustment in ((1, 0), (0, 1)):
                adjacent_coord = coordinates.add(coord, coord_adjustment)
                if (adjacent_coord[0] < 3 and adjacent_coord[1] < 3 and sector_types[adjacent_coord] != 0):
                    make_corridor(ret_dungeon,
                        rng.randomPointInRect(room_nwcoords[coord], room_secoords[coord]),
                        rng.randomPointInRect(room_nwcoords[adjacent_coord], room_secoords[adjacent_coord]))
    
    ret_dungeon[entrance_coords] = level.UPSTAIRS_GLYPH
    ret_dungeon[exit_coords] = level.DOWNSTAIRS_GLYPH
    
    return ret_dungeon
Beispiel #10
0
def randomDungeon():
    """
    Gets a random dungeon, using a very simple room/corridor model.
    
    The room/corridor model used is similar to that of Rogue; the map is
    divided into nine sectors, each of which is randomly called a room,
    a corridor, or empty.  Once this is done, rooms and corridors are connected
    to adjacent rooms and corridors.
    
    This is coded terribly because it will be replaced someday.
    """
    
    map_dimensions = (MAX_SIZE_X, MAX_SIZE_Y)
    map_nwcorner = (NW_CORNER_X, NW_CORNER_Y)
    sector_size = (SECTOR_SIZE_X, SECTOR_SIZE_Y)
    sector_list = [(x, y) for x in range(NUM_SECTORS_X) 
                          for y in range(NUM_SECTORS_Y)]
    sector_nwcorners = {}
    for x in range(NUM_SECTORS_X):
        for y in range(NUM_SECTORS_Y):
            sector_nwcorners[(x, y)] = (
                map_nwcorner[0] + sector_size[0] * x,
                map_nwcorner[1] + sector_size[1] * y
                )
                
    sector_types = {}
    for x in range(NUM_SECTORS_X):
        for y in range(NUM_SECTORS_Y):
            percent = rng.randInt(1, 100)
            if percent <= 25:
                sector_types[(x, y)] = st.ROOM
            elif percent <= 60:
                sector_types[(x, y)] = st.DOUBLE_ROOM
            elif percent <= 75:
                sector_types[(x, y)] = st.CORRIDOR
            else:
                sector_types[(x, y)] = st.EMPTY
    
    room_nwcoords = {}
    room_secoords = {}
    
    for sector_coords in sector_types.keys():
        sector_nw = sector_nwcorners[sector_coords]
        sector_se = (sector_nw[0] + sector_size[0] - 1,
                     sector_nw[1] + sector_size[1] - 1)

        if sector_types[sector_coords] in (st.ROOM, st.DOUBLE_ROOM):
            (room_nwcoords[sector_coords], room_secoords[sector_coords]) \
                = choose_room_corners(sector_nw, sector_se)
                    
        elif sector_types[sector_coords] == st.CORRIDOR:
            # A corridor is currently implemented as just a 1-space room.
            corridor_coords = (rng.randInt(sector_nw[0], sector_se[0]),
                rng.randInt(sector_nw[1], sector_se[1]))

            room_nwcoords[sector_coords] = corridor_coords
            room_secoords[sector_coords] = corridor_coords
    
    # Check whether everywhere is accessible; if not, do a redo.
    sector_is_accessible = {}
    for x in range(NUM_SECTORS_X):
        for y in range(NUM_SECTORS_Y):
            sector_is_accessible[(x, y)] = False
    
    for coord in sector_list:

        if True not in sector_is_accessible.values() \
            and sector_types[coord] != 0:

            sector_is_accessible[coord] = True
        
        if sector_is_accessible[coord] == True \
            and sector_types[coord] != st.EMPTY:

            for coord_adjustment in ((1, 0), (0, 1), (-1, 0), (0, -1)):
                adjacent_coord = coordinates.add(coord, coord_adjustment)
                if (adjacent_coord[0] >= 0 and
                    adjacent_coord[0] < NUM_SECTORS_X and
                    adjacent_coord[1] >= 0 and
                    adjacent_coord[1] < NUM_SECTORS_Y):
                    
                    sector_is_accessible[adjacent_coord] = True
    
    for accessible in sector_is_accessible.items():
        if sector_types[accessible[0]] != 0 and not accessible[1]:
            # Oops.  Give up and try again.
            return randomDungeon()
    
    entrance_sector = rng.choice([coords for coords in sector_types.keys() 
                                 if sector_types[coords] in 
                                 (st.ROOM, st.DOUBLE_ROOM)])
    exit_sector = rng.choice([coords for coords in sector_types.keys() 
                              if sector_types[coords] in
                              (st.ROOM, st.DOUBLE_ROOM)])
    entrance_coords = rng.randomPointInRect(room_nwcoords[entrance_sector], 
                                            room_secoords[entrance_sector])
    exit_coords = rng.randomPointInRect(room_nwcoords[exit_sector], 
                                        room_secoords[exit_sector])
    
    ret_dungeon = level.empty_dungeon(map_dimensions)
    
    for coord in sector_list:
        if sector_types[coord] != st.EMPTY:
            if sector_types[coord] == st.CORRIDOR:
                fill_glyph = level.CORRIDOR_GLYPH
            else:
                fill_glyph = level.ROOM_INTERIOR_GLYPH

            arrays.fill_rect(ret_dungeon, room_nwcoords[coord], 
                room_secoords[coord], fill_glyph)
            
# If there is another room to the south or east, make a corridor from this room
# to it.
            for coord_adjustment in ((1, 0), (0, 1)):
                adjacent_coord = coordinates.add(coord, coord_adjustment)
                if (adjacent_coord[0] < NUM_SECTORS_X 
                    and adjacent_coord[1] < NUM_SECTORS_Y
                    and sector_types[adjacent_coord] != 0):

                    make_corridor(ret_dungeon,
                        rng.randomPointInRect(room_nwcoords[coord], 
                                              room_secoords[coord]),
                        rng.randomPointInRect(room_nwcoords[adjacent_coord], 
                                              room_secoords[adjacent_coord]))

# If the room type is DOUBLE_ROOM, bolt on a second room to the first.
# This room can overflow! That is intentional.
            if sector_types[coord] == st.DOUBLE_ROOM:
                max_second_se = (room_secoords[coord][0] + MIN_ROOM_SIZE,
                                 room_secoords[coord][1] + MIN_ROOM_SIZE)
                (second_nw, second_se) = choose_room_corners(
                    room_nwcoords[coord], max_second_se)

                arrays.fill_rect(ret_dungeon, second_nw, second_se, 
                    level.ROOM_INTERIOR_GLYPH)
    
    ret_dungeon[entrance_coords] = level.UPSTAIRS_GLYPH
    ret_dungeon[exit_coords] = level.DOWNSTAIRS_GLYPH
    
    return ret_dungeon
Beispiel #11
0
    def useCard(self, card_id):
        """
        Use a card (asking the player for required information).

        card_id - the ID (CARD_1, CARD_2, etc.) of the card to be used.
        
        Returns the action decided upon.
        """

        if card_id == -1 or card_id >= len(self.deck.hand):
            return action.DoNothing()
        else:
            card_to_use = self.deck.hand[card_id]

# If the card is directional, get the direction to use it in.
            if card_to_use.is_directional:
                direction_of_target_square = kb.direction_question(
                    self.currentLevel.messages,
                    "In which direction would you like to use the %s card?"
                    % card_to_use.ability_name)
                if direction_of_target_square is None:
                    self.currentLevel.messages.say("Never mind.")
                    return action.DoNothing()
            if card_to_use.is_melee:
                target_square = coordinates.add(
                    self.coords, direction_of_target_square)
                if target_square in self.currentLevel.dudeLayer:
                    del self.deck.hand[card_id]
                    return action.SpecialMelee(self,
                        self.currentLevel.dudeLayer[target_square],
                        card_to_use.action_code)
                else:
                    self.currentLevel.messages.say("You whiff completely!")
                    del self.deck.hand[card_id]
                    return action.Wait(self)
            else:
                if card_to_use.action_code == "GRENTHROW":
                    target_square = coordinates.add(self.coords, 
                        coordinates.multiply(direction_of_target_square, 2))
                    if self.currentLevel.isEmpty(target_square):
# Note that the player can, in fact, throw grenades on top of monsters.
                        del self.deck.hand[card_id]
                        return action.ThrowGrenade(self, target_square)
                    else:
                        self.currentLevel.messages.say(
                            "There's something in the way!")
                        return action.DoNothing()
                elif card_to_use.action_code == "ARROW":
                    del self.deck.hand[card_id]
                    return action.FireArrow(
                        self, direction_of_target_square, 12)
                elif card_to_use.action_code == "POUNCE":
                    del self.deck.hand[card_id]
                    return action.Pounce(self, direction_of_target_square, 12)
                elif card_to_use.action_code == "HASTE":
                    del self.deck.hand[card_id]
                    return action.HasteMonster(self, self, 12)
                elif card_to_use.action_code == "HASTEALL":
                    del self.deck.hand[card_id]
                    return action.HasteAll(self, 8, True, True)
                assert False
            assert False
Beispiel #12
0
    def getAction(self):
        while 1:
            key = kb.getKey()
# If the key is the quit key, quit.
            if key == kp.QUIT:
                sys.exit(0)
# If the key is the save key, ask if the player wants to save, and do so.
            elif key == kp.SAVE:
                if self.currentLevel.elements[self.coords] == level.UPSTAIRS_GLYPH:
                    decision = kb.boolean_question(self.currentLevel.messages,
                        "Do you really want to save and quit the game?")
                    if decision:
                        raise exc.SavingLevelChange()
                    else:
                        self.currentLevel.messages.say("Never mind, then.")
                        return action.DoNothing()
                else:
                    self.currentLevel.messages.say("You can only save when on the stairs (<).")
# If the key is the wait key, wait.
            elif key == kp.WAIT:
                return action.Wait(self)
# If the key is a movement key, move or attack, as is appropriate.
            elif key in config.DIRECTION_SWITCH:
                target = coordinates.add(self.coords,
                                         config.DIRECTION_SWITCH[key])
                if target in self.currentLevel.dudeLayer:
                    return action.Attack(self, 
                                         self.currentLevel.dudeLayer[target])
                elif self.canMove(target):
 # If the player is stuck, he cannot move!
                    if self.hasCondition("stuck"):
                        self.currentLevel.messages.append("You are stuck and cannot move!")
                        return action.DoNothing()
                    else:
                        return action.Move(self, config.DIRECTION_SWITCH[key])
                else:
# A move is illegal!
                    return action.DoNothing()
            elif key in config.RUN_DIRECTION_SWITCH:
                direction = config.RUN_DIRECTION_SWITCH[key]
                target = coordinates.add(self.coords, direction)
                if len(self.fov.dudes) != 0:
                    self.currentLevel.messages.append("Not with enemies in view!")
                    return action.DoNothing()
                elif self.canMove(target):
# If the player is stuck, he cannot move.
                    if self.hasCondition("stuck"):
                        self.currentLevel.messages.append("You are stuck and cannot move!")
                        return action.DoNothing()
                    else:
                        self.giveCondition(cond.Running(direction))
                        return action.Move(self, direction)
# If the key requests that a card be used, prompt for a card, then use it.
            elif key == kp.FIRE:
                if len(self.deck.hand) == 0:
                    self.currentLevel.messages.append(
                        "You have no cards to use!")
                    return action.DoNothing()
                else:
                    card_id = kb.card_question(self.currentLevel.messages,
                        "Which card do you want to evoke?", self.deck)
                    if card_id == -1:
                        return action.DoNothing()
                    else:
                        return self.useCard(card_id)

            elif key == kp.HEAL:
# Have the player use a card to heal wounds.
                card_id = kb.card_question(self.currentLevel.messages, 
                            "Which card will you sacrifice for your health?",
                            self.deck)
                if card_id == -1:
                    return action.DoNothing()
                else:
                    del self.deck.hand[card_id]
                    return action.Heal(self, self, 
                        rng.XdY(2, 7 + self.char_level), False)
# If the key is the "go upstairs" key, try to go up a level.
            elif key == kp.UP:
                if self.currentLevel.elements[self.coords] == level.UPSTAIRS_GLYPH:
        	        return action.Up()
Beispiel #13
0
    def getAction(self):
        while 1:
            key = kb.getKey()
# If the key is the quit key, quit.
            if key == kp.QUIT:
                sys.exit(0)
# If the key is the save key, ask if the player wants to save, and do so.
            elif key == kp.SAVE:
                if self.currentLevel.elements[self.coords] == level.UPSTAIRS_GLYPH:
                    decision = kb.boolean_question(self.currentLevel.messages,
                        "Do you really want to save and quit the game?")
                    if decision:
                        raise exc.SavingLevelChange()
                    else:
                        self.currentLevel.messages.say("Never mind, then.")
                        return action.DoNothing()
                else:
                    self.currentLevel.messages.say("You can only save when on the stairs (<).")
# If the key is the wait key, wait.
            elif key == kp.WAIT:
                return action.Wait(self)
# If the key is a movement key, move or attack, as is appropriate.
            elif key in config.DIRECTION_SWITCH:
                target = coordinates.add(self.coords,
                                         config.DIRECTION_SWITCH[key])
                if target in self.currentLevel.dudeLayer:
                    return action.Attack(self, 
                                         self.currentLevel.dudeLayer[target])
                elif self.canMove(target):
 # If the player is stuck, he cannot move!
                    if self.hasCondition("stuck"):
                        self.currentLevel.messages.append("You are stuck and cannot move!")
                        return action.DoNothing()
                    else:
                        return action.Move(self, config.DIRECTION_SWITCH[key])
                else:
# A move is illegal!
                    return action.DoNothing()
            elif key in config.RUN_DIRECTION_SWITCH:
                direction = config.RUN_DIRECTION_SWITCH[key]
                target = coordinates.add(self.coords, direction)
                if len(self.fov.dudes) != 0:
                    self.currentLevel.messages.append("Not with enemies in view!")
                    return action.DoNothing()
                elif self.canMove(target):
# If the player is stuck, he cannot move.
                    if self.hasCondition("stuck"):
                        self.currentLevel.messages.append("You are stuck and cannot move!")
                        return action.DoNothing()
                    else:
                        self.giveCondition(cond.Running(direction))
                        return action.Move(self, direction)
# If the key is a card key, use the card.
            elif key in kb.card_values:
                card_id = kb.card_values[key]
                
                if card_id >= len(self.deck.hand):
                    return action.DoNothing()
                card_to_use = self.deck.hand[card_id]

# If the card is directional, get the direction to use it in.
                if card_to_use.is_directional:
                    direction_of_target_square = kb.direction_question(
                        self.currentLevel.messages,
                        "In which direction would you like to use the %s card?"
                        % card_to_use.ability_name)
                if card_to_use.is_melee:
                    target_square = coordinates.add(self.coords, direction_of_target_square)
                    if target_square in self.currentLevel.dudeLayer:
                        del self.deck.hand[card_id]
                        return action.SpecialMelee(self,
                            self.currentLevel.dudeLayer[target_square],
                            card_to_use.action_code)
                    else:
                        self.currentLevel.messages.say("You whiff completely!")
                        del self.deck.hand[card_id]
                        return action.Wait(self)
                else:
                    if card_to_use.action_code == "GRENTHROW":
                        target_square = coordinates.add(self.coords, coordinates.multiply(direction_of_target_square, 2))
                        if self.currentLevel.isEmpty(target_square) and (not events.is_grenade_at_coords(target_square, self.currentLevel)):
                            del self.deck.hand[card_id]
                            return action.ThrowGrenade(self, target_square)
                        else:
                            self.currentLevel.messages.say("There's something in the way!")
                            return action.DoNothing()
                    elif card_to_use.action_code == "ARROW":
                        del self.deck.hand[card_id]
                        return action.FireArrow(self, direction_of_target_square, 12)
                    elif card_to_use.action_code == "HASTE":
                        del self.deck.hand[card_id]
                        return action.HasteMonster(self, self, 12)
                    elif card_to_use.action_code == "HASTEALL":
                        del self.deck.hand[card_id]
                        return action.HasteAll(self, 8)
                    assert False
                assert False
            elif key == kp.REST:
# Give the player the "rest" status, so she waits until healed fully.
                self.giveCondition(cond.Resting())
                return action.Wait(self)
# If the key is the "go upstairs" key, try to go up a level.
            elif key == kp.UP:
                if self.currentLevel.elements[self.coords] == level.UPSTAIRS_GLYPH:
        	        return action.Up()