Ejemplo n.º 1
0
 def add_creature(template):
     #t = CreatureTemplate(template=template)
     #t.set_loadout(Loadout([WEAPON_CLUB]))
     c = Creature(template)
     try_equip_best_weapons(c)
     c.set_action_loop(loop)
     return c
Ejemplo n.º 2
0
def resolve_opposed_initiative(a: Creature, b: Creature) -> Optional[Creature]:
    a_initiative = a.get_initiative_modifier()
    b_initiative = b.get_initiative_modifier()

    a_roll = dice(1, 10).get_roll_result()
    b_roll = dice(1, 10).get_roll_result()
    a_total = a_roll + a_initiative
    b_total = b_roll + b_initiative

    a_crit = 1 if a_roll >= 10 else (-1 if a_roll <= 1 else 0)
    b_crit = 1 if b_roll >= 10 else (-1 if b_roll <= 1 else 0)

    winner = None
    if a_crit != b_crit:
        winner = a if a_crit > b_crit else b
    elif a_total != b_total:
        winner = a if a_total > b_total else b
    elif round(a_initiative) != round(b_initiative):
        winner = a if a_initiative > b_initiative else b

    success_text = f'{winner} takes initiative!' if winner is not None else 'Tie!'
    print(
        f'[Initiative] {a} vs {b} RESULT: {a_roll}{a_initiative:+.0f}={a_total:.0f} vs '
        f'{b_roll}{b_initiative:+.0f}={b_total:.0f} {success_text}')
    return winner
Ejemplo n.º 3
0
 def apply_loadout(self, creature: Creature) -> None:
     for group in self.loadout:
         for item in group:
             if isinstance(item, EquipmentTemplate):
                 creature.inventory.add(Equipment(item))
             if isinstance(item, CreatureTrait):
                 creature.add_trait(item)
Ejemplo n.º 4
0
 def get_attribute_modifier(self, protagonist: Creature) -> int:
     if protagonist.has_trait(FinesseTrait):
         return sum(
             max(protagonist.get_attribute(attr), protagonist.get_attribute(PrimaryAttribute.DEX))
             if attr == PrimaryAttribute.STR else protagonist.get_attribute(attr)
             for attr in self.key_attr
         )
     return super().get_attribute_modifier(protagonist)
Ejemplo n.º 5
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.º 6
0
    def _get_standing_bodyparts(creature: Creature) -> Iterable[BodyPart]:
        if creature.stance == Stance.Prone:
            return ()

        current, total = creature.get_stance_count()
        used = total
        if creature.stance == Stance.Crouching:
            used = int(total / 2)
        elif creature.stance == Stance.Standing:
            used = min(total / 2 + 1, total - 1)
        used = min(used, current)

        stance_parts = list(bp for bp in creature.get_bodyparts()
                            if bp.is_stance_part())
        return random.sample(stance_parts, used)
Ejemplo n.º 7
0
 def can_attack(self, combatant: Creature) -> bool:
     opponent = self.get_opponent(combatant)
     if opponent is None:
         return False
     return any(
         attack.can_attack(self.get_separation())
         for attack in combatant.get_melee_attacks())
Ejemplo n.º 8
0
    def get_melee_threat_value(self, opponent: Creature) -> float:
        threat_priority = get_melee_attack_priority(opponent, self.parent, opponent.get_melee_attacks())
        threat_value = max(threat_priority.values(), default=0.0)

        attack_priority = get_melee_attack_priority(self.parent, opponent, self.parent.get_melee_attacks())
        attack_value = max(attack_priority.values(), default=0.0)
        return threat_value * attack_value / (opponent.health + opponent.max_health)
Ejemplo n.º 9
0
def can_interrupt_action(combatant: Creature) -> bool:
    action = combatant.get_current_action()
    if action is None:
        return True  # idle
    if isinstance(action, CreatureAction):
        return action.can_interrupt
    return False
Ejemplo n.º 10
0
def join_melee_combat(a: Creature, b: Creature) -> MeleeCombat:
    """Used to setup a melee combat between two combatants"""
    a_mount = a.get_mount()
    a_base = a_mount or a

    b_mount = b.get_mount()
    b_base = b_mount or b

    separation = MeleeSeparation(a_base, b_base)
    a_combatants = [a_base, *a_base.get_riders()]
    b_combatants = [b_base, *b_base.get_riders()]
    for i in a_combatants:
        for j in b_combatants:
            if i is not None and j is not None:
                melee = MeleeCombat(i, j, separation)
                i.add_melee_combat(j, melee)
                j.add_melee_combat(i, melee)

    return a.get_melee_combat(b)
Ejemplo n.º 11
0
def get_combat_difficulty(creature: Creature) -> DifficultyGrade:
    grade = DifficultyGrade.Standard
    if creature.stance == Stance.Crouching:
        grade = DifficultyGrade.Hard
    elif creature.stance == Stance.Prone:
        grade = DifficultyGrade.Formidable

    if creature.is_seriously_wounded():
        grade = grade.get_step(+1)

    return grade
Ejemplo n.º 12
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.º 13
0
    def get_melee_range_priority(self, opponent: Creature, *, caution: float = 1.0) -> Mapping[MeleeRange, float]:
        range_priority = {}
        melee = self.parent.get_melee_combat(opponent)
        for reach in MeleeRange.between(melee.get_min_separation(), self.parent.get_melee_engage_distance()):
            pro_attacks = (attack for attack in self.parent.get_melee_attacks() if attack.can_attack(reach))
            attack_priority = get_melee_attack_priority(self.parent, opponent, pro_attacks)
            power = max(attack_priority.values(), default=0.0)

            ant_attacks = (attack for attack in opponent.get_melee_attacks() if attack.can_attack(reach))
            threat_priority = get_melee_attack_priority(opponent, self.parent, ant_attacks)
            threat = max(threat_priority.values(), default=0.0)

            health = self.parent.health + self.parent.max_health
            danger = (2 * caution * threat + health) / health

            range_priority[reach] = power/danger
        return range_priority
Ejemplo n.º 14
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.º 15
0
def get_expected_damage(attack: MeleeAttack, target: Creature) -> float:
    result = 0
    for bp in target.get_bodyparts():
        result += bp.exposure * bp.get_effective_damage(attack.damage.mean(), attack.armpen.mean())
    return result
Ejemplo n.º 16
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()
Ejemplo n.º 17
0
 def __init__(self, a: Creature, b: Creature):
     self._pair = (a, b)
     combatants = [a, *a.get_riders(), b, *b.get_riders()]
     self._separation = max(c.get_melee_engage_distance()
                            for c in combatants)
Ejemplo n.º 18
0
 def get_attribute_modifier(self, protagonist: Creature) -> int:
     return sum(protagonist.get_attribute(attr) for attr in self.key_attr)
Ejemplo n.º 19
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.º 20
0
def print_melee_attacks(creature: Creature) -> None:
    for attack in creature.get_melee_attacks():
        print(attack)
Ejemplo n.º 21
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.º 22
0
def get_random_hitloc(creature: Creature) -> Optional[BodyPart]:
    bodyparts = [(bp, bp.exposure) for bp in creature.get_bodyparts()]
    result = random.choices(*zip(*bodyparts))
    if len(result) > 0:
        return result[0]
    return None
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with this program; if not, write to the Free Software Foundation, Inc.,
#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from core.creature import Creature
from core import barf
import sys

#for arg in sys.argv:
#	cgtype = arg

barf.Barf("DEF", "-----------------------------------------------------", False)
barf.Barf("DEF", "roguekit-uniquecreatures (v0.0.1) Copyright (C) 2014", False)
barf.Barf("DEF", "-----------------------------------------------------", False)
barf.Barf("DEF", "Tristy H. \"KittyTristy\" <*****@*****.**>", False)
barf.Barf("DEF", "Sina Mashek \"CptMashek\" <*****@*****.**>", False)
barf.Barf("DEF", "-----------------------------------------------------", False)

creature = Creature()
try:
	creature.generate(sys.argv[1:][0])
except IndexError:
	creature.generate('humanoid')

barf.Barf("DEF", "------------------------------------------------------", False)
Ejemplo n.º 24
0
def get_block_difficulty(creature: Creature) -> DifficultyGrade:
    grade = DifficultyGrade.Standard
    if creature.is_seriously_wounded():
        grade = grade.get_step(+1)
    return grade