Example #1
0
    def _hit(self, caster, target):
        defense_roll = GameRules.roll_saving_spell_throw(self, target)
        attack_roll = GameRules.roll_spell_attack_score(self, caster)
        caster.notify_observers_log("{} - cast {}".format(caster.class_name, self.class_name))
        caster.notify_observers_log('Defense: {}({}), Attack: {}({})'.format(defense_roll.total,defense_roll.roll,attack_roll.total,attack_roll.roll))

        hit = defense_roll.roll < 20 and attack_roll.total >= defense_roll.total
        if not hit:
            caster.notify_observers_log("{} - {} missed {}".format(caster.class_name, self.class_name, target.class_name))
            caster.notify_observers_reply(ReplyHelpers.render_action_template(caster.get_reply_key('cast_miss'), spell_text=self.description,
                attacker_name=caster.name, defender_name=target.name, mana_points=caster.mana_points))
        return hit
Example #2
0
    def throw(self, player, item, target_text):
        
        with Observer(player) as ob:
            if not player.is_carrying(item):
                player.notify_observers_reply('not_carrying', template=ReplyHelpers.TEMPLATE_ACTION, action=Actions.get_action_text(Actions.THROW), item_prefix=item.text_prefix, item_text=item.description)
                return self.__build_reply(ob)

        target = None
        if target_text is None:
            target = self.get_next_monster()
        else:
            for m in self.get_monsters():
                if m.is_match(target_text):
                    target = m
                    break
        #Ok probably room item
        if not target:
            target = self.get_room_item_by_text(target_text)
        if not target:
            return ReplyHelpers.render_action_template('no_such_target', item_text=item.description)

        #Either throw at a room item or a monster
        is_monster = isinstance(target, players.Monster)
        is_player = isinstance(target, players.Player) and not is_monster
        is_weapon = isinstance(item, weapons.Weapon)
        is_item = isinstance(target, items.Item) or isinstance(target, RoomItem)

        floor_text = self.__get_room_text()[1]
        with Observer(player) as ob:
            is_hit = player.throw(item, target)

            if is_hit and is_item:
                player.notify_observers_reply('throw_item_hit', template=ReplyHelpers.TEMPLATE_ACTION, item_text=item.description, target_text=target.description, floor_text=floor_text)
            elif is_item:
                player.notify_observers_reply('throw_item_miss', template=ReplyHelpers.TEMPLATE_ACTION, item_text=item.description, target_text=target.description, floor_text=floor_text)

            if is_hit and is_monster and is_weapon:
                #Hit and lodged in monster
                if not GameRules.is_thrown_item_lost():
                    target.pickup(item)
            elif is_hit and is_player:
                #Hit and lodged in player
                pass
            else:
                #Miss or hit and on floor
                if not GameRules.is_thrown_item_lost():
                    self.add_floor_item(item.one_of())

            if is_monster and is_weapon and not target.is_dead:
                target.strike(player)

            return self.__build_reply(ob)
Example #3
0
    def wound(self, points, critical_hit=False):
        if points <= 0 or self.is_dead: return False
        self.notify_observers_log("{} wounded {}".format(
            self.__class__.__name__, points))

        #Dead if massive damage, otherwise unconsious
        #10 - 20 = -10 - dead
        if (self.hit_points - points) <= -self.max_hit_points:
            self.__is_dead = True
            self.notify_observers_log("{} - DIED!".format(self.class_name))

        starting_health = self.hit_points
        self.__set_hit_points(self.hit_points - points)

        if self.is_unconscious:
            death_saves = 3
            if starting_health == 0:
                death_saves -= 1
                if critical_hit:
                    death_saves -= 1
            else:
                self.notify_observers_log("{} - UNCONSCIOUS!".format(
                    self.class_name))
            #Roll saves
            saved = next((True for x in range(death_saves)
                          if GameRules.roll_death_save(self)), False)
            if not saved:
                self.__is_dead = True
                self.notify_observers_log("{} - DIED!".format(self.class_name))

        return True
Example #4
0
 def get_attribute_modifier(self, attrs):
     if not isinstance(attrs, list):
         attrs = [attrs]
     #If multiple select max
     if len(attrs) == 0: return 0
     max_attr_val = max(map(self.get_attribute_current, attrs))
     return GameRules.get_attribute_modifier(max_attr_val)
Example #5
0
 def check_for_trap(self, player, trap):
     '''
     Player checks to determine if trap is set or not
     Perception check
     '''
     roll = GameRules.roll_perception_check(player)
     return roll.total >= trap.difficulty_class.value
Example #6
0
 def test_GameRules(self):
     self.assertEqual(-5, GameRules.get_attribute_modifier(0))
     self.assertEqual(-5, GameRules.get_attribute_modifier(1))
     self.assertEqual(1, GameRules.get_attribute_modifier(12))
     self.assertEqual(1, GameRules.get_attribute_modifier(13))
     self.assertEqual(2, GameRules.get_attribute_modifier(14))
     self.assertEqual(2, GameRules.get_attribute_modifier(15))
     self.assertEqual(10, GameRules.get_attribute_modifier(30))
     self.assertEqual(10, GameRules.get_attribute_modifier(31))
Example #7
0
 def _miss(self, player, defender):
     Weapon._miss(self, player, defender)
     #Drop arrow
     #TODO: Arrow should be left on ground
     if GameRules.is_thrown_item_lost():
         player.inventory.remove(self.__ammo.__class__())
     else:
         player.get_rid_of_one(self.__ammo.__class__())
Example #8
0
    def test_Attack(self):
        player = Thief()  #+2 attack bonus at level 1
        player.strength_base = 17  #+3 strength modifier
        player.equip_weapon(weapons.Dagger())  #+2 proficiency
        for _i in range(100):
            dice_roll = GameRules.roll_weapon_attack_score(player)
            #critical_strike = player.get_equipped_weapon().is_critical_strike(dice_roll.roll)
            print("Player Attack score: {}".format(dice_roll.total))
            if not player.get_equipped_weapon().is_critical_miss(
                    dice_roll.roll):
                self.assertGreaterEqual(dice_roll.total, 7)
            self.assertLessEqual(dice_roll.total, 27)

        player.add_bonus('POTION', PlayerAttributes.STRENGTH,
                         4)  #21 strength, +5 strength modifer
        for _i in range(100):
            dice_roll = GameRules.roll_weapon_attack_score(player)
            #critical_strike = player.get_equipped_weapon().is_critical_strike(dice_roll.roll)
            print("Player Attack score: {}".format(dice_roll.total))
            if not player.get_equipped_weapon().is_critical_miss(
                    dice_roll.roll):
                self.assertGreaterEqual(dice_roll.total, 9)
            self.assertLessEqual(dice_roll.total, 29)

        player.remove_bonus('POTION')
        player.equip_weapon(weapons.LongBow())  #0 proficiency
        player.dexterity_base = 0  #-5 dexterity modifier, +2 attack bonus
        for _i in range(100):
            dice_roll = GameRules.roll_weapon_attack_score(player)
            #critical_strike = player.get_equipped_weapon().is_critical_strike(dice_roll.roll)
            print("Player Attack score: {}".format(dice_roll.total))
            if not player.get_equipped_weapon().is_critical_miss(
                    dice_roll.roll):
                self.assertGreaterEqual(dice_roll.total, -2)
            self.assertLessEqual(dice_roll.total, 17)

        player.dexterity_base = 12  #+1 dexterity modifier
        for _i in range(100):
            dice_roll = GameRules.roll_weapon_attack_score(player)
            #critical_strike = player.get_equipped_weapon().is_critical_strike(dice_roll.total)
            print("Player Attack score: {}".format(dice_roll.total))
            if not player.get_equipped_weapon().is_critical_miss(
                    dice_roll.roll):
                self.assertGreaterEqual(dice_roll.total, 4)
            self.assertLessEqual(dice_roll.total, 23)
Example #9
0
 def __check_for_monster(self, player):
     #Has a monster appeared?
     monster = self.get_next_monster()
     result = ''
     if monster is None:
         player._end_battle()
     else:
         #Yikes a monster!
         if not player.is_in_battle:
             player._start_battle()
             with Observer(player) as ob:
                 if GameRules.roll_initiative_check(monster) > GameRules.roll_initiative_check(player):
                     #Monster strikes first
                     result = ReplyHelpers.render_action_template('monster_detects_you',monster_name=monster.class_name)
                     monster.strike(player)
                 else:
                     #Player gets to attack first
                     result = ReplyHelpers.render_action_template('monster_detected',monster_name=monster.class_name)
                 result += ' ' + self.__build_reply(ob)
     return result
Example #10
0
    def unlock(self, player, key=False, spell=False):

        if not self.is_locked:
            self.notify_observers_log('{} is not locked'.format(self.name))
            self.notify_observers_reply(
                ReplyHelpers.render_room_template('not_locked',
                                                  item=self.name))
            return False

        if key:
            if key.id == self._key_id:
                self._is_locked = False
                self.notify_observers_log('{} is unlocked'.format(self.name))
                return True
            #Wrong key
            self.notify_observers_log('Wrong key used for {}'.format(
                self.name))
            return False

        if spell:
            if spell.__class__ == spells.UnlockSpell:
                self._is_locked = False
                self.notify_observers_log('{} is unlocked'.format(self.name))
                self.notify_observers_reply(
                    ReplyHelpers.render_room_template('spell_success',
                                                      action='unlocked',
                                                      target_name=self.name))
                return True
            #Wrong spell
            self.notify_observers_log('Wrong spell used for {}'.format(
                self.name))

        #Picklock
        if not player.current_action == Actions.PICK_LOCK:
            #Logic error
            self.notify_observers_log('Can'
                                      't pick lock, player doesn'
                                      't seem to be performing this action')
            return False

        #pick lock
        skill_roll = GameRules.roll_skill_check(player, skills.LockPicking())
        if skill_roll.total >= self.lock_resistance.value:
            self._is_locked = False
            self.notify_observers_reply(
                ReplyHelpers.render_room_template('picklock_success',
                                                  item=self.name))
            return True
        #pick failed
        self.notify_observers_reply(
            ReplyHelpers.render_room_template('picklock_fail', item=self.name))
        return False
Example #11
0
 def _hit(self, caster, target):
     #If casting on one self it always hits
     if caster == target: return True
     defense_target = self.spell_difficulty_class(caster)
     saving_roll = GameRules.roll_saving_spell_throw(self, target)
     from questgame.players.players import Player
     if isinstance(target, Player):
         save = saving_roll.total
         caster.notify_observers_log('Defense: {}, Saving: {}({})'.format(defense_target, saving_roll.total, saving_roll.roll))
     else:
         save = target.spell_resistance
         caster.notify_observers_log('Defense: {}, Saving: {}'.format(defense_target, save))
     hit = save < 20 and save <= defense_target
     if not hit:
         caster.notify_observers_log('{} failed on {}'.format(self.__class__.__name__,target.__class__.__name__))
     return hit
Example #12
0
    def __init__(self, character_class):
        super(Player, self).__init__(None)
        Observable.__init__(self)
        self.__hit_points = 0
        self.__max_hit_points = 0
        self.__mana_points = 0
        self.__max_mana_points = 0
        self.__attributes = {}
        self.__learned_spells = []
        self.__default_weapon = PlayerStats.get_weapon(self)
        self.__default_armor = PlayerStats.get_armor(self)
        self.__armor = None
        self.__weapon = None
        self.__character_class = character_class
        self.__experience = 0
        self.__level = Level()
        self.__is_stunned = False
        self.__is_in_battle = False
        self.__is_dead = False
        self.__is_looted = False
        self.__current_action = False
        self.__inventory = Inventory(self)

        attrs = PlayerStats.get_attributes(self)
        self.strength_base = attrs[PlayerAttributes.STRENGTH]
        self.dexterity_base = attrs[PlayerAttributes.DEXTERITY]
        self.constitution_base = attrs[PlayerAttributes.CONSITUTION]
        self.wisdom_base = attrs[PlayerAttributes.WISDOM]
        self.intelligence_base = attrs[PlayerAttributes.INTELLIGENCE]
        self.charisma_base = attrs[PlayerAttributes.CHARISMA]
        self.equip_weapon(self.__default_weapon)
        self.equip_armor(self.__default_armor)

        hp_dice = PlayerStats.get_hp_dice(self)
        hp_sides = PlayerStats.get_hp_sides(self)
        hp_bonus = PlayerStats.get_hp_bonus(self)
        self.max_hit_points = GameRules.determine_hit_points(
            hp_dice, hp_sides, hp_bonus)
        self.max_mana_points = self.character_class.get_mana_points(self)
Example #13
0
 def spell_difficulty_class(self, caster):
     """ Determines DC saving throw is made against """
     return GameRules.determine_spell_difficulty_class(self, caster)
Example #14
0
 def test_determine_carry_capacity(self):
     player = Mock()
     player.strength = 10
     self.assertEqual(GameRules.determine_carry_capacity(player),
                      player.strength * 15)
Example #15
0
    def strike(self, attacker, defender, is_throw=False):
        '''
        Return Strike object
        Representing hiut or miss and damage (and critical of not)
        '''
        player = attacker
        if attacker.is_monster:
            player = defender

        if not self.is_throwable and is_throw:
            player.notify_observers_reply(
                ReplyHelpers.render_action_template(
                    'not_throwable', weapon_text=self.description))
            return False

        defender_name = defender.__class__.__name__
        attacker_name = attacker.__class__.__name__
        defender_ac = defender.get_defense()
        attacker.notify_observers_log("{} - defense {}".format(
            defender_name, defender_ac))
        if is_throw:
            dice_roll = GameRules.roll_weapon_throw_score(attacker)
        else:
            dice_roll = GameRules.roll_weapon_attack_score(attacker)
        is_critical_strike = self.is_critical_strike(dice_roll.roll)
        is_critical_miss = self.is_critical_miss(dice_roll.roll)
        attacker.notify_observers_log("{} - attack roll: {}({})".format(
            attacker_name, dice_roll.total, dice_roll.roll))
        strike_type = 'miss'
        if is_critical_miss or dice_roll.total < defender_ac:
            #Miss!
            if is_critical_miss:
                strike_type = 'critical_miss'
            if is_throw: strike_type = 'throw_' + strike_type
            player.notify_observers_reply(
                ReplyHelpers.render_action_template(
                    attacker.get_reply_key(strike_type),
                    attacker_name=attacker_name,
                    defender_name=defender_name,
                    attack_type=self.get_attack_type()))
            self._miss(attacker, defender)
            return Strike(False, is_critical_miss)

        #Hit
        dmg = 0
        strike_type = 'strike'
        if is_critical_strike:
            dmg = self._critical_strike(attacker)
            strike_type = 'critical_strike'
        else:
            dmg = self._normal_strike(attacker)
        if is_throw:
            strike_type = 'throw_' + strike_type

        attacker.notify_observers_log("{} - damage roll: {}".format(
            attacker_name, dmg))
        defender.affect(attacker, Effects.Damage, dmg)
        player.notify_observers_reply(
            ReplyHelpers.render_action_template(
                player.get_reply_key(strike_type),
                attacker_name=attacker_name,
                defender_name=defender_name,
                damage=dmg,
                hit_points=defender.hit_points,
                attack_type=self.get_attack_type()))
        attacker.notify_observers_log(
            "{} - DAMAGED {} {}, {} HP now {}!".format(attacker_name,
                                                       defender_name, dmg,
                                                       defender_name,
                                                       defender.hit_points))
        if defender.is_dead:
            player.notify_observers_reply(
                ReplyHelpers.render_action_template(
                    player.get_reply_key('killed'),
                    attacker_name=attacker_name,
                    defender_name=defender_name))
        return Strike(True, is_critical_strike, dmg)
Example #16
0
 def get_defense(self):
     """ Determines current armor class - base and any modifiers """
     return GameRules.get_player_defense(self)
Example #17
0
    def test_goblin(self):
        player = players.Thief()
        player.equip_weapon(weapons.Dagger())
        player.equip_armor(armor.LightArmor())
        player.strength_base = 15
        player.dexterity_base = 10

        player.max_hit_points = 100

        goblin = players.Goblin()
        goblin.affect(player, players.Effects.Heal, 0)
        self.assertGreaterEqual(goblin.hit_points, 2, "Hit points set")

        goblin.max_hit_points = 100

        player_def = player.get_defense()
        goblin_def = goblin.get_defense()
        print("Player Hit Points: {}".format(player.hit_points))
        print("Player def: {}".format(player_def))
        print("Player ability modifier: {}".format(
            player.determine_ability_modifier()))
        print("Player proficiency modifier: {}".format(
            player.determine_proficiency_bonus()))
        print("---")
        print("Goblin Hit Points: {}".format(goblin.hit_points))
        print("Goblin def: {}".format(goblin_def))
        print("Goblin ability modifier: {}".format(
            goblin.determine_ability_modifier()))
        print("Goblin proficiency modifier: {}".format(
            goblin.determine_proficiency_bonus()))
        print("---")
        dice_roll = GameRules.roll_initiative_check(goblin)
        gob_init_check = dice_roll.total
        dice_roll = GameRules.roll_initiative_check(player)
        player_init_check = dice_roll.total
        print("Goblin Initiative: {} ({})".format(gob_init_check,
                                                  goblin.initiative_bonus))
        print("Player Initiative: {} ({})".format(player_init_check,
                                                  player.initiative_bonus))
        if gob_init_check > player_init_check:
            print("Goblin was quicker to react, and starts first")
        else:
            print("Player was quicker to react, and starts first")
        print("---")

        #Attacks
        a = base_classes.Observer(goblin)
        b = base_classes.Observer(player)

        done_sneak_attack = False

        while not goblin.is_dead and not player.is_dead:
            if gob_init_check < player_init_check:
                player.strike(goblin)
                if not done_sneak_attack:
                    player.skill_attack(skills.SneakAttack(), goblin)
                    done_sneak_attack = True
                goblin.strike(player)
            else:
                goblin.strike(player)
                player.strike(goblin)
                if not done_sneak_attack:
                    player.skill_attack(skills.SneakAttack(), goblin)
                    done_sneak_attack = True
Example #18
0
 def carry_capacity(self):
     return GameRules.determine_carry_capacity(self)