Modify the enemy health rng by using a dice roll distribution (#438)

- [ ] Changelog updated / no changelog update needed
This commit is contained in:
Corwin 2023-06-05 21:01:04 +01:00 committed by GitHub
commit 80051a163a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 1 deletions

View file

@ -1,3 +1,4 @@
use crate::level_generation::generate_enemy_health;
use crate::sfx::Sfx;
use crate::{
graphics::SELECT_BOX, level_generation::generate_attack, Agb, EnemyAttackType, Face, PlayerDice,
@ -499,7 +500,7 @@ pub(crate) fn battle_screen(
let num_dice = player_dice.dice.len();
let enemy_health = 5 + current_level * agb::rng::gen().rem_euclid(4) as u32;
let enemy_health = generate_enemy_health(current_level);
let mut current_battle_state = CurrentBattleState {
player: PlayerState {

View file

@ -8,6 +8,57 @@ pub struct GeneratedAttack {
pub cooldown: u32,
}
fn roll_dice(number_of_dice: u32, bits_per_dice: u32) -> u32 {
assert!(
32 % bits_per_dice == 0,
"the number of bits per dice should be a multiple of 32"
);
assert!(
number_of_dice % (32 / bits_per_dice) == 0,
"number of dice should be a multiple of 32 / bits per dice"
);
fn roll_dice_inner(number_of_random_values: u32, bits_per_dice: u32) -> u32 {
let mut count = 0;
let bit_mask = 1u32.wrapping_shl(bits_per_dice).wrapping_sub(1);
for _ in 0..number_of_random_values {
let n = agb::rng::gen() as u32;
for idx in 0..(32 / bits_per_dice) {
count += (n >> (bits_per_dice * idx)) & bit_mask;
}
}
count
}
roll_dice_inner(number_of_dice / (32 / bits_per_dice), bits_per_dice)
}
// uses multiple dice rolls to generate a random value with a specified mean and width
fn roll_dice_scaled(number_of_dice: u32, bits_per_dice: u32, width: u32) -> i32 {
let dice = roll_dice(number_of_dice, bits_per_dice) as i32;
let current_width = (number_of_dice * ((1 << bits_per_dice) - 1)) as i32;
let current_mean = current_width / 2;
let dice_around_zero = dice - current_mean;
fn divide_nearest(numerator: i32, denominator: i32) -> i32 {
if (numerator < 0) ^ (denominator < 0) {
(numerator - denominator / 2) / denominator
} else {
(numerator + denominator / 2) / denominator
}
}
divide_nearest(dice_around_zero * width as i32, current_width)
}
fn default_roll(width: u32) -> i32 {
roll_dice_scaled(2, 16, width)
}
pub fn generate_attack(current_level: u32) -> Option<GeneratedAttack> {
if (rng::gen().rem_euclid(1024) as u32) < current_level * 2 {
Some(GeneratedAttack {
@ -19,6 +70,10 @@ pub fn generate_attack(current_level: u32) -> Option<GeneratedAttack> {
}
}
pub fn generate_enemy_health(current_level: u32) -> u32 {
(5 + current_level as i32 * 2 + default_roll(current_level * 4)) as u32
}
fn generate_enemy_attack(current_level: u32) -> EnemyAttack {
let attack_id = rng::gen().rem_euclid(10) as u32;