diplomacy/judge/
mod.rs

1//! Contains the logic needed to adjudicate a turn.
2
3pub mod build;
4mod calc;
5mod convoy;
6mod outcome;
7mod resolver;
8pub mod retreat;
9mod rulebook;
10mod state_type;
11mod strength;
12pub mod support;
13
14pub use self::outcome::{IllegalOrder, OrderOutcome, Outcome};
15pub use self::state_type::OrderState;
16
17pub use self::convoy::ConvoyOutcome;
18pub use self::rulebook::AttackOutcome;
19pub use self::rulebook::HoldOutcome;
20use self::strength::Prevent;
21pub use self::support::SupportOutcome;
22
23pub use self::resolver::{Context, ResolverState, Submission};
24pub use self::rulebook::Rulebook;
25use crate::UnitType;
26use crate::geo::{Border, RegionKey, Terrain};
27use crate::order::{BuildOrder, MainCommand, Order, RetreatOrder};
28
29pub type MappedMainOrder = Order<RegionKey, MainCommand<RegionKey>>;
30pub type MappedBuildOrder = BuildOrder<RegionKey>;
31pub type MappedRetreatOrder = RetreatOrder<RegionKey>;
32
33/// A clonable container for a rulebook which can be used to adjudicate a turn.
34pub trait Adjudicate: Sized {
35    /// Determines and returns the success of an order.
36    ///
37    /// Calling this MUST leave the `resolver` in the same state as if [`Adjudicate::explain`] was called.
38    ///
39    /// Adjudicators MAY customize this method to be more memory-efficient by avoiding allocation of explanatory data.
40    fn adjudicate<'a>(
41        &self,
42        context: &Context<'a, Self>,
43        resolver: &mut ResolverState<'a>,
44        order: &'a MappedMainOrder,
45    ) -> OrderState {
46        self.explain(context, resolver, order).into()
47    }
48
49    /// Determines and returns the outcome of an order.
50    ///
51    /// The outcome contains enough information to determine both _whether_ the order succeeds or fails and _why_ the order succeeds or fails.
52    fn explain<'a>(
53        &self,
54        context: &Context<'a, Self>,
55        resolver: &mut ResolverState<'a>,
56        order: &'a MappedMainOrder,
57    ) -> OrderOutcome<&'a MappedMainOrder>;
58}
59
60/// Checks if an order will use an offered convoy route.
61///
62/// Different editions of the rules have different policies on when a convoy is taken.
63pub trait WillUseConvoy: Sized {
64    /// Returns if the given order will accept the offered convoy route.
65    ///
66    /// This function will only be called with convoy routes that get the order to its destination;
67    /// the implementer should not recheck that.
68    fn will_use_convoy(&self, order: &MappedMainOrder, route: &[&MappedMainOrder]) -> bool;
69}
70
71impl Border {
72    fn is_passable_by(&self, unit_type: UnitType) -> bool {
73        unit_type.can_occupy(self.terrain())
74    }
75}
76
77impl UnitType {
78    fn can_occupy(self, terrain: Terrain) -> bool {
79        match terrain {
80            Terrain::Coast => true,
81            Terrain::Land => self == UnitType::Army,
82            Terrain::Sea => self == UnitType::Fleet,
83        }
84    }
85}