encounter/resolution/
single.rs1use crate::scoring::{AcceptanceEval, ScoredAffordance};
4use crate::types::{Beat, EncounterResult};
5
6pub struct SingleExchange;
9
10impl SingleExchange {
11 pub fn resolve<P>(
13 &self,
14 initiator: &str,
15 responder: &str,
16 available: &[ScoredAffordance<P>],
17 acceptance: &dyn AcceptanceEval<P>,
18 ) -> EncounterResult {
19 let mut result = EncounterResult::new(vec![initiator.into(), responder.into()], None);
20
21 let Some(best) = available.iter().max_by(|a, b| {
22 a.score
23 .partial_cmp(&b.score)
24 .unwrap_or(std::cmp::Ordering::Equal)
25 }) else {
26 return result;
27 };
28
29 let accepted = acceptance.evaluate(responder, best);
30 let effects = if accepted {
31 best.entry.spec.effects_on_accept.clone()
32 } else {
33 best.entry.spec.effects_on_reject.clone()
34 };
35
36 let beat = Beat {
37 actor: initiator.into(),
38 action: best.entry.spec.name.clone(),
39 accepted,
40 effects,
41 };
42 result.push_beat(beat);
43 if let Some(esc) = crate::escalation::check_escalation(
44 result.beats.last().unwrap(),
45 result.beats.len() - 1,
46 ) {
47 result.escalation_requested = true;
48 result.escalation_requests.push(esc);
49 }
50 result
51 }
52}