common_game/protocols/
orchestrator_explorer.rs

1//! # Orchestrator and Explorer protocol messages
2//!
3//! Defines the types of messages exchanged of the full duplex communication channel
4//! between the Orchestrator and the Explorers
5//! For a more detailed view of the interactions between these two entities, visit the communications [diagrams](https://github.com/unitn-ap-2025/common/blob/main/MESSAGE_DIAGRAMS.md)
6use crate::components::resource::{BasicResourceType, ComplexResourceType};
7use crate::protocols::planet_explorer::ExplorerToPlanet;
8use crate::utils::ID;
9use crossbeam_channel::Sender;
10use enum_as_inner::EnumAsInner;
11use std::collections::HashSet;
12use strum_macros::EnumDiscriminants;
13
14#[cfg(doc)]
15use crate::components::resource::{BasicResource, ComplexResource};
16
17/// This enum describes all possible messages from the Orchestrator to an Explorer
18#[derive(Debug, EnumAsInner, EnumDiscriminants)]
19#[strum_discriminants(name(OrchestratorToExplorerKind))]
20#[strum_discriminants(derive(Hash))]
21pub enum OrchestratorToExplorer {
22    /// This variant is used to start an Explorer AI
23    ///
24    /// **Expected Response**: [`ExplorerToOrchestrator::StartExplorerAIResult`]
25    ///
26    /// **Use Case**: Starting the Explorer AI at game start
27    StartExplorerAI,
28    /// This variant is used to reset the Explorer AI and restart it if it is in manual mode
29    ///
30    /// **Expected Response**: [`ExplorerToOrchestrator::ResetExplorerAIResult`]
31    ///
32    /// **Use Case**: Reset the Explorer knowledge or restart the AI if it is in manual mode
33    ResetExplorerAI,
34    /// This variant is used to kill an Explorer
35    ///
36    /// **Expected Response**: [`ExplorerToOrchestrator::KillExplorerResult`]
37    ///
38    /// **Use Case**: Killing the explorer instantly
39    KillExplorer,
40    ///This variant is used to stop the Explorer AI from autonomous decision-making
41    ///
42    /// **Expected Response**: [`ExplorerToOrchestrator::StopExplorerAIResult`]
43    ///
44    /// **Use Case**: Stopping the autonomous decision-making and entering the manual mode
45    StopExplorerAI,
46    /// This variant is used to tell the Explorer to move to a different planet
47    ///
48    /// **Expected Response**: [`ExplorerToOrchestrator::MovedToPlanetResult`]
49    ///
50    /// **Use Case**
51    ///
52    /// When in manual mode, the orchestrator moves the explorer to a new planet and gives the new [Sender]
53    ///
54    /// When in normal mode, this is the response to [`ExplorerToOrchestrator::TravelToPlanetRequest`], in this case
55    /// the orchestrator checks that the explorer can move to the planet specified in the request and sends the optional new sender
56    MoveToPlanet {
57        ///The optional [Sender] to the new planet, [None] if explorer cannot move to the specified planet
58        sender_to_new_planet: Option<Sender<ExplorerToPlanet>>,
59        ///The ID of the planet to which the explorer will possibly move
60        planet_id: ID,
61    },
62    /// This variant is used to ask the ID of the Planet in which the Explorer is currently located
63    ///
64    /// **Expected Response**: [`ExplorerToOrchestrator::CurrentPlanetResult`]
65    CurrentPlanetRequest,
66    /// This variant is used to enforce the Explorer to ask the supported Resources on the Planet
67    ///
68    /// **Expected Response**: [`ExplorerToOrchestrator::SupportedResourceResult`]
69    ///
70    /// **Use Case**: In manual mode, ask the explorer to send a [`ExplorerToPlanet::SupportedResourceRequest`] to know the available [`BasicResourceType`] on its current planet
71    SupportedResourceRequest,
72    /// This variant is used to enforce the Explorer to ask the supported Combinations on the Planet
73    ///
74    /// **Expected Response**: [`ExplorerToOrchestrator::SupportedCombinationResult`]
75    ///
76    /// **Use Case**: In manual mode, ask the explorer to send a [`ExplorerToPlanet::SupportedCombinationRequest`] to know the available [`ComplexResourceType`] on its current planet
77    SupportedCombinationRequest,
78    /// This variant is used to enforce the Explorer to ask the Planet to Generate a [`BasicResource`]
79    ///
80    /// **Expected Response**: [`ExplorerToOrchestrator::GenerateResourceResponse`]
81    ///
82    /// **Use Case**: In manual mode, ask the explorer to send a [`ExplorerToPlanet::GenerateResourceRequest`] craft a [`BasicResource`]
83    GenerateResourceRequest {
84        ///The type of basic resource to craft
85        to_generate: BasicResourceType,
86    },
87    /// This variant is used to enforce the Explorer to ask the Planet to Generate a [`ComplexResource`] provided by [`ComplexResourceType`]
88    ///
89    /// **Expected Response**: [`ExplorerToOrchestrator::CombineResourceResponse`]
90    ///
91    /// **Use Case**: In manual mode, ask the explorer to send a [`ExplorerToPlanet::CombineResourceRequest`] to craft a [`ComplexResource`]
92    CombineResourceRequest {
93        ///The type of complex resource to generate
94        to_generate: ComplexResourceType,
95    },
96    /// This variant is used to ask the content of the Explorer Bag
97    ///
98    /// **Expected Response**: [`ExplorerToOrchestrator::BagContentResponse`]
99    ///
100    /// **Use Case**: Message used by the GUI to get information on the Explorer bag content to be shown
101    BagContentRequest,
102    /// This variant is used to send to the Explorer the IDs of the planets to which it can be moved
103    ///
104    /// **Response To**: [`ExplorerToOrchestrator::NeighborsRequest`]
105    NeighborsResponse {
106        ///The list of IDs of the planets to which it can be moved
107        neighbors: Vec<ID>,
108    },
109}
110/// This enum describes all possible messages from an Explorer to the Orchestrator
111#[derive(Debug, EnumAsInner, EnumDiscriminants)]
112#[strum_discriminants(name(ExplorerToOrchestratorKind))]
113#[strum_discriminants(derive(Hash))]
114pub enum ExplorerToOrchestrator<T> {
115    /// This variant is used to acknowledge the starting of the Explorer AI
116    ///
117    /// **Response To**: [`OrchestratorToExplorer::StartExplorerAI`]
118    StartExplorerAIResult {
119        ///The ID of the Explorer sending the message
120        explorer_id: ID,
121    },
122    /// This variant is used to acknowledge the killing of an Explorer
123    ///
124    /// **Response To**: [`OrchestratorToExplorer::KillExplorer`]
125    KillExplorerResult {
126        ///The ID of the Explorer sending the message
127        explorer_id: ID,
128    },
129    /// This variant is used to acknowledge the reset of the Explorer AI
130    ///
131    /// **Response To**: [`OrchestratorToExplorer::ResetExplorerAI`]
132    ResetExplorerAIResult {
133        ///The ID of the Explorer sending the message
134        explorer_id: ID,
135    },
136    /// This variant is used to acknowledge the stopping of the Explorer AI
137    ///
138    /// **Response To**: [`OrchestratorToExplorer::StopExplorerAI`]
139    StopExplorerAIResult {
140        ///The ID of the Explorer sending the message
141        explorer_id: ID,
142    },
143    /// This variant is used to acknowledge the transfer of an Explorer to a new Planet
144    ///
145    /// **Response To**: [`OrchestratorToExplorer::MoveToPlanet`]
146    MovedToPlanetResult {
147        ///The ID of the Explorer sending the message
148        explorer_id: ID,
149        ///The ID of the planet to which the explorer possibly moved
150        planet_id: ID,
151    },
152    /// This variant is used to send the ID of the current planet on which the Explorer is located
153    ///
154    /// **Response To**: [`OrchestratorToExplorer::CurrentPlanetRequest`]
155    CurrentPlanetResult {
156        ///The ID of the explorer sending the message
157        explorer_id: ID,
158        ///The ID of the planet it currently lives on
159        planet_id: ID,
160    },
161    /// This variant is used to send the list of the available [`BasicResourceType`] in the Explorer's current planet
162    ///
163    /// **Response To**: [`OrchestratorToExplorer::SupportedResourceRequest`]
164    SupportedResourceResult {
165        ///The ID of the explorer sending the message
166        explorer_id: ID,
167        ///The Set of [`BasicResourceType`] available in the Explorer's current planet
168        supported_resources: HashSet<BasicResourceType>,
169    },
170    /// This variant is used to send the list of the available [`ComplexResourceType`] in the Explorer's current planet
171    ///
172    /// **Response To**: [`OrchestratorToExplorer::SupportedCombinationRequest`]
173    SupportedCombinationResult {
174        ///The ID of the explorer sending the message
175        explorer_id: ID,
176        ///The Set of [`ComplexResourceType`] available in the Explorer's current planet
177        combination_list: HashSet<ComplexResourceType>,
178    },
179    /// This variant is used to send the generated Basic Resource asked by the Orchestrator
180    ///
181    /// **Response To**: [`OrchestratorToExplorer::GenerateResourceRequest`]
182    GenerateResourceResponse {
183        ///The ID of the Explorer sending the message
184        explorer_id: ID,
185        ///A Result consisting of: [Ok] if the requested resource has been generated and added to the Explorer Bag
186        ///
187        ///An [Err] String if the requested resource has not been generated
188        generated: Result<(), String>,
189    },
190    /// This variant is used to send the generated [`ComplexResource`] asked by the Orchestrator
191    ///
192    /// **Response To**: [`OrchestratorToExplorer::CombineResourceRequest`]
193    CombineResourceResponse {
194        ///The ID of the Explorer sending the message
195        explorer_id: ID,
196        ///A Result consisting of: [Ok] if the requested resource has been generated and added to the Explorer Bag
197        ///
198        ///An [Err] String if the requested resource has not been generated
199        generated: Result<(), String>,
200    },
201    /// This message is for passing around the bag content and has been implemented with a generic type to let the group the freedom to implement the methods on it
202    ///
203    /// **Response To**: [`OrchestratorToExplorer::BagContentRequest`]
204    BagContentResponse {
205        ///The ID of the explorer sending the message
206        explorer_id: ID,
207        ///The generic `bag_content` type
208        bag_content: T,
209    },
210    /// This variant asks the Orchestrator for the list of neighbors Planets to travel to
211    ///
212    /// **Expected Response**: [`OrchestratorToExplorer::NeighborsResponse`]
213    ///
214    /// **Use Case**: Knowing reachable planets from current planet
215    NeighborsRequest {
216        ///The ID of the Explorer sending the message
217        explorer_id: ID,
218        ///The ID of the current planet the Explorer lives on
219        current_planet_id: ID,
220    },
221    /// This variant asks the Orchestrator to be sent to the specified Planet
222    ///
223    /// **Expected Response**: [`OrchestratorToExplorer::MoveToPlanet`]
224    ///
225    /// **Use Case**: Autonomously asking to travel to a planet
226    TravelToPlanetRequest {
227        ///The ID of the Explorer sending the message
228        explorer_id: ID,
229        ///The ID of the current planet the Explorer lives on
230        current_planet_id: ID,
231        ///The ID of the planet the Explorer wants to travel to
232        dst_planet_id: ID,
233    },
234}
235
236impl<T> ExplorerToOrchestrator<T> {
237    /// Helper method to extract the `explorer_id` field from any message variant
238    /// without needing to match a specific one.
239    pub fn explorer_id(&self) -> ID {
240        match self {
241            Self::StartExplorerAIResult { explorer_id, .. }
242            | Self::KillExplorerResult { explorer_id, .. }
243            | Self::ResetExplorerAIResult { explorer_id, .. }
244            | Self::MovedToPlanetResult { explorer_id, .. }
245            | Self::CurrentPlanetResult { explorer_id, .. }
246            | Self::SupportedResourceResult { explorer_id, .. }
247            | Self::SupportedCombinationResult { explorer_id, .. }
248            | Self::GenerateResourceResponse { explorer_id, .. }
249            | Self::CombineResourceResponse { explorer_id, .. }
250            | Self::BagContentResponse { explorer_id, .. }
251            | Self::NeighborsRequest { explorer_id, .. }
252            | Self::TravelToPlanetRequest { explorer_id, .. }
253            | Self::StopExplorerAIResult { explorer_id, .. } => *explorer_id,
254        }
255    }
256}