use weasel::character::{StatisticId, StatisticsAlteration};
use weasel::rules::entropy::UniformDistribution;
use weasel::rules::{ability::SimpleAbility, statistic::SimpleStatistic};
use weasel::{
battle_rules, rules::empty::*, Action, ActorRules, AlterStatistics, ApplyImpact, BattleRules,
BattleState, Character, CharacterRules, Conclusion, EntityId, Entropy, EventQueue,
EventTrigger, FightRules, Id, ReadMetrics, Team, TeamRules, Transmutation, WriteMetrics,
};
pub(crate) static STAT_HULL: StatisticId<PiratesRules> = 0;
pub(crate) static STAT_CREW: StatisticId<PiratesRules> = 1;
pub(crate) const ABILITY_CANNONBALL: &str = "cannonballs";
pub(crate) const ABILITY_GRAPESHOT: &str = "grapeshots";
#[derive(Default)]
pub struct PiratesTeamRules {}
impl TeamRules<PiratesRules> for PiratesTeamRules {
type Id = String;
type Power = EmptyPower;
type PowersSeed = ();
type Invocation = ();
type PowersAlteration = ();
type ObjectivesSeed = Self::Id;
type Objectives = Self::ObjectivesSeed;
fn generate_objectives(&self, seed: &Option<Self::ObjectivesSeed>) -> Self::Objectives {
seed.as_ref().unwrap().clone()
}
fn check_objectives_on_turn(
&self,
state: &BattleState<PiratesRules>,
team: &Team<PiratesRules>,
_metrics: &ReadMetrics<PiratesRules>,
) -> Option<Conclusion> {
let enemy_id = team.objectives();
if state
.entities()
.team(&enemy_id)
.unwrap()
.creatures()
.count()
== 0
{
Some(Conclusion::Victory)
} else {
None
}
}
}
#[derive(Default)]
pub struct PiratesCharacterRules {}
impl CharacterRules<PiratesRules> for PiratesCharacterRules {
type CreatureId = u8;
type ObjectId = ();
type Statistic = SimpleStatistic<u8, i16>;
type StatisticsSeed = ();
type StatisticsAlteration = (i16, i16);
type Status = EmptyStatus;
type StatusesAlteration = ();
fn generate_statistics(
&self,
_seed: &Option<Self::StatisticsSeed>,
_entropy: &mut Entropy<PiratesRules>,
_metrics: &mut WriteMetrics<PiratesRules>,
) -> Box<dyn Iterator<Item = Self::Statistic>> {
let v = vec![
SimpleStatistic::new(STAT_HULL, 100),
SimpleStatistic::new(STAT_CREW, 100),
];
Box::new(v.into_iter())
}
fn alter_statistics(
&self,
character: &mut dyn Character<PiratesRules>,
alteration: &Self::StatisticsAlteration,
_entropy: &mut Entropy<PiratesRules>,
_metrics: &mut WriteMetrics<PiratesRules>,
) -> Option<Transmutation> {
let (delta_hull, delta_crew) = alteration;
character
.statistic_mut(&STAT_HULL)
.unwrap()
.add(*delta_hull);
character
.statistic_mut(&STAT_CREW)
.unwrap()
.add(*delta_crew);
if character.statistic(&STAT_HULL).unwrap().value() <= 0 {
Some(Transmutation::REMOVAL)
} else {
None
}
}
}
#[derive(Default)]
pub struct PiratesActorRules {}
impl ActorRules<PiratesRules> for PiratesActorRules {
type Ability = SimpleAbility<String, ()>;
type AbilitiesSeed = ();
type Activation = EntityId<PiratesRules>;
type AbilitiesAlteration = ();
fn generate_abilities(
&self,
_seed: &Option<Self::AbilitiesSeed>,
_entropy: &mut Entropy<PiratesRules>,
_metrics: &mut WriteMetrics<PiratesRules>,
) -> Box<dyn Iterator<Item = Self::Ability>> {
let v = vec![
SimpleAbility::new(ABILITY_CANNONBALL.to_string(), ()),
SimpleAbility::new(ABILITY_GRAPESHOT.to_string(), ()),
];
Box::new(v.into_iter())
}
fn activate(
&self,
_state: &BattleState<PiratesRules>,
action: Action<PiratesRules>,
mut event_queue: &mut Option<EventQueue<PiratesRules>>,
entropy: &mut Entropy<PiratesRules>,
_metrics: &mut WriteMetrics<PiratesRules>,
) {
let target = action.activation.as_ref().unwrap();
let crew = action.actor.statistic(&STAT_CREW).unwrap().value();
let damage = 10 + entropy.generate(crew / 20, crew / 5);
let alteration = if action.ability.id() == ABILITY_CANNONBALL {
(-damage, 0)
} else {
(0, -damage)
};
ApplyImpact::trigger(&mut event_queue, (*target, alteration)).fire();
}
}
#[derive(Default)]
pub struct PiratesFightRules {}
impl FightRules<PiratesRules> for PiratesFightRules {
type Impact = (EntityId<PiratesRules>, StatisticsAlteration<PiratesRules>);
type Potency = ();
fn apply_impact(
&self,
_state: &BattleState<PiratesRules>,
impact: &Self::Impact,
mut event_queue: &mut Option<EventQueue<PiratesRules>>,
_entropy: &mut Entropy<PiratesRules>,
_metrics: &mut WriteMetrics<PiratesRules>,
) {
let target = &impact.0;
AlterStatistics::trigger(&mut event_queue, *target, impact.1).fire();
}
}
battle_rules! {
PiratesTeamRules,
PiratesCharacterRules,
PiratesActorRules,
PiratesFightRules,
EmptyUserRules,
EmptySpaceRules,
EmptyRoundsRules,
UniformDistribution<i16>
}
pub(crate) type PiratesRules = CustomRules;