For my turn-based game rules engine, I have a central trait that I use for game callbacks:
pub trait Rule<T> {
fn on_turn_start(&self, context: &RuleContext<T>) {}
}
This trait has different sub-implementations for different entity types:
pub trait CreatureRule: Rule<Creatue> {}
pub trait PlayerRule: Rule<Player> {}
which ensures that each Rule gets the correct type passed to it as context and allows for callbacks that are specific to one entity type. This is cool, and I can call the trait methods on the boxed rules pretty easily by doing something like:
for rule in player.rules { rule.on_turn_start(RuleContext(player)) }
for creature in creatures {
for rule in creature.rules { rule.on_turn_start(RuleContext(creature)) }
}
But now I have gotten to the point of having more different types of callbacks and different types of entities, so what I want to do is simplify things by making a helper function that invokes a callback on a configurable set of rules. I thought I could maybe do something like
pub fn execute_rules<T>(
rules: impl Iterator<Item = Box<dyn Rule<T>>>,
function: impl Fn(Box<dyn Rule<T>>, RuleContext<T>)) {
}
But this would only work for one specific type T, the type system (correctly) won't let us operate on a heterogeneous set of Rules because it can't know we are passing the correct type each time we call the function.
So what I'm wondering is whether there's a different design approach I could use here to let me safely operate over different sets of Rules without having to write out a bunch of boilerplate code each time I do it.