I have a game board that contains up to n allieds, which are stored in an array. Each of these units has an ability that can target itself or allies (or enemies, but I left those out for now).
#[derive(Debug)]
pub struct Board {
/// Allied units on the field. None means no unit is at that given position
allies: [Option<BoardUnit>; 6],
// snip...
}
The BoardUnit
struct just stores the current state of each unit like health, stamina, etc. It also stores what GameplayEffects
are applied to the unit. These are lightweight structs that contain changes in a unit's state which are applied to the unit at certain points in time (start, immediate end of turn).
#[derive(Debug, Default, Clone)]
pub struct BoardUnit {
pub id: UnitId,
pub health: UnitStat,
// snip...
pub current_effects: Vec<GameplayEffect>,
}
Now here's my problem: Every turn I iterate over each unit (allies only for now) and each of those uses an ability that can apply one or more effects to itself or other units.
Naturally Rust's borrowing rules prevent me from simply using a range based for loop, so I went doing it like this:
for i in 0..self.allies.len() {
let unit = self.allies[i].as_mut();
let Some(unit) = unit else {
continue;
};
// Do some ability related stuff here and create the effect that is applied to the target
let effect = GameplayEffect::default();
match ability.target {
Caster => {
unit.current_effects.push(effect);
}
Ally(multi) => {
match multi {
Single =>todo!(), // Single random ally, might also be the caster
Multi { min, max } => todo!(), // Between min and max random allies, might also be the caster
All => todo!(), // All allies on the board, including the caster
}
}
}
The problem is the application of the effect. The case where the ability target is the caster itself or the target is a single ally and the random roll chose the caster can be handled by using the existing mutable reference (I did this by randomly generating an index and compare it to i
, and if it's the same I used the existing reference). However, when other units are affected I run into problems. To change them I'd need to get another mutable reference to the allies
vector, which I isn't allowed by the borrowing rules.
Now, I read about interior mutability -- would that the the appropriate solution here? Or do I need to rethink my architecture?