keleusma 0.2.0

Total Functional Stream Processor with definitive WCET and WCMU verification, targeting no_std + alloc embedded scripting
Documentation
// Combat resolution. Pure function that takes attacker and
// defender stats plus a d20 roll, returns the hit outcome and
// the damage to apply.
//
// The host samples the roll from its random number generator
// before dispatching this script. The script's body is pure
// arithmetic and pattern matching so the script-side logic is
// trivial to read and trivial to modify. A reader wanting to
// rebalance combat changes a single file.
//
// Inputs.
//   attacker_skill    Bonus added to the d20 roll.
//   attacker_damage   Base damage if the attack lands.
//   defender_evasion  Added to the target number (10).
//   defender_armor    Subtracted from damage, floored at one.
//   roll              The pre-rolled d20 value, in 1..=20.
//
// Output tuple `(hit, damage)`.
//   hit = 0   Miss. damage is zero.
//   hit = 1   Ordinary hit. damage is the post-armor value.
//   hit = 2   Critical hit. damage is the doubled value.
//
// Rules.
//   Natural 1 always misses regardless of skill or evasion.
//   Natural 20 always hits as a critical regardless of armor.
//   Otherwise the attack hits when roll + attacker_skill is
//   greater than or equal to 10 + defender_evasion.
//   Damage is max(1, attacker_damage - defender_armor) on an
//   ordinary hit, max(1, 2*attacker_damage - defender_armor)
//   on a critical hit.

fn main(
    attacker_skill: Word,
    attacker_damage: Word,
    defender_evasion: Word,
    defender_armor: Word,
    roll: Word,
) -> (Word, Word) {
    if roll == 1 {
        (0, 0)
    } else {
        let target = 10 + defender_evasion;
        let critical = roll == 20;
        let lands = critical or (roll + attacker_skill >= target);
        if lands {
            let dmg_input = if critical {
                attacker_damage * 2
            } else {
                attacker_damage
            };
            let raw = dmg_input - defender_armor;
            let dmg = if raw < 1 { 1 } else { raw };
            if critical { (2, dmg) } else { (1, dmg) }
        } else {
            (0, 0)
        }
    }
}