Ejemplo n.º 1
0
    def get_opposed_chance(protagonist: Creature, pro_contest: Contest,
                           antagonist: Creature, ant_contest: Contest = None,
                           modifier: int = 0):
        ant_contest = ant_contest or pro_contest
        pro_level = protagonist.get_skill_level(pro_contest)
        pro_mod = pro_contest.get_attribute_modifier(protagonist) + pro_contest.get_skill_modifier(pro_level)

        ant_level = antagonist.get_skill_level(ant_contest)
        ant_mod = ant_contest.get_attribute_modifier(antagonist) + ant_contest.get_skill_modifier(ant_level)

        target = ant_mod - pro_mod - modifier
        roll_table = get_opposed_roll_table(pro_level.bonus_dice, ant_level.bonus_dice)
        return sum(p for result, p in roll_table.items() if result > target)
Ejemplo n.º 2
0
    def get_range_change_desire(self, opponent: Creature, from_range: MeleeRange, to_range: MeleeRange) -> float:
        """-1.0 to 1.0 scale rating how favorable the given range change is"""
        range_scores = self.get_melee_range_priority(opponent)
        from_score = range_scores.get(from_range, 0)
        to_score = range_scores.get(to_range, 0)
        if from_score == 0:
            return 1.0

        modifier = ChangeMeleeRangeAction.get_contest_modifier(self.parent) - ChangeMeleeRangeAction.get_contest_modifier(opponent)
        success_chance = Contest.get_opposed_chance(self.parent, SKILL_EVADE, opponent, SKILL_EVADE, modifier.contest)
        score = min(max(-1.0, (to_score/from_score - 1.0) * success_chance), 1.0)

        # account for possible attack of opportunity
        if score > 0 and from_range > to_range and can_interrupt_action(opponent):
            attack_ranges = list(MeleeRange.between(from_range, to_range))
            attacks = (attack for attack in opponent.get_melee_attacks() if any(attack.can_attack(r) for r in attack_ranges))
            attack = max(attacks, key=lambda a: opponent.get_skill_level(a.combat_test), default=None)
            safety = 1.0 - Contest.get_opposed_chance(opponent, attack.combat_test, self.parent, SKILL_EVADE)
            if attack is not None:
                return min(score, safety**2)
        return score
Ejemplo n.º 3
0
def get_melee_attack_value(attack: MeleeAttack, attacker: Creature, target: Creature) -> float:
    expected_damage = get_expected_damage(attack, target)
    skill_factor = SKILL_FACTOR[attacker.get_skill_level(attack.combat_test)]
    return expected_damage * skill_factor
Ejemplo n.º 4
0
def get_attack_value(creature: Creature, attack: MeleeAttackTemplate) -> float:
    return attack.damage.mean() * SKILL_FACTOR[creature.get_skill_level(attack.combat_test)]
Ejemplo n.º 5
0
    def get_success_chance(self, protagonist: Creature, target: int) -> float:
        skill_level = protagonist.get_skill_level(self)
        target -= self.get_attribute_modifier(protagonist) + self.get_skill_modifier(skill_level)

        roll_table = get_roll_table(skill_level.bonus_dice)
        return sum(p for roll, p in roll_table.items() if roll > target)
Ejemplo n.º 6
0
 def __init__(self, protagonist: Creature, contest: Contest, modifier: ContestModifier = ContestModifier()):
     self.contest = contest
     self.protagonist = protagonist
     self.skill_level = protagonist.get_skill_level(contest)
     self.modifier = modifier
     self.reroll()