mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
Modify the enemy health rng by using a dice roll distribution (#438)
- [ ] Changelog updated / no changelog update needed
This commit is contained in:
commit
80051a163a
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue