Skip to content

Commit 5b70068

Browse files
committed
feat: Implement DefaultExtendActionMove class for extending action move functionality
1 parent 3182e34 commit 5b70068

File tree

2 files changed

+360
-0
lines changed

2 files changed

+360
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
from typing import Optional, cast
2+
3+
from rcrs_core.entities.area import Area
4+
from rcrs_core.entities.blockade import Blockade
5+
from rcrs_core.entities.entity import Entity
6+
from rcrs_core.entities.human import Human
7+
from rcrs_core.worldmodel.entityID import EntityID
8+
9+
from adf_core_python.core.agent.action.common.action_move import ActionMove
10+
from adf_core_python.core.agent.communication.message_manager import MessageManager
11+
from adf_core_python.core.agent.develop.develop_data import DevelopData
12+
from adf_core_python.core.agent.info.agent_info import AgentInfo
13+
from adf_core_python.core.agent.info.scenario_info import Mode, ScenarioInfo
14+
from adf_core_python.core.agent.info.world_info import WorldInfo
15+
from adf_core_python.core.agent.module.module_manager import ModuleManager
16+
from adf_core_python.core.agent.precompute.precompute_data import PrecomputeData
17+
from adf_core_python.core.component.extaction.ext_action import ExtAction
18+
from adf_core_python.core.component.module.algorithm.path_planning import PathPlanning
19+
20+
21+
class DefaultExtendActionMove(ExtAction):
22+
def __init__(
23+
self,
24+
agent_info: AgentInfo,
25+
world_info: WorldInfo,
26+
scenario_info: ScenarioInfo,
27+
module_manager: ModuleManager,
28+
develop_data: DevelopData,
29+
) -> None:
30+
super().__init__(
31+
agent_info, world_info, scenario_info, module_manager, develop_data
32+
)
33+
self._target_entity_id: Optional[EntityID] = None
34+
self._threshold_to_rest: int = develop_data.get_value("threshold_to_rest", 100)
35+
36+
match self.scenario_info.get_mode():
37+
case Mode.NON_PRECOMPUTE:
38+
self._path_planning: PathPlanning = cast(
39+
PathPlanning,
40+
self.module_manager.get_module(
41+
"DefaultExtendActionMove.PathPlanning",
42+
"adf_core_python.implement.module.astar_path_planning.AStarPathPlanning",
43+
),
44+
)
45+
case Mode.PRECOMPUTATION:
46+
pass
47+
case Mode.PRECOMPUTED:
48+
pass
49+
50+
def precompute(self, precompute_data: PrecomputeData) -> ExtAction:
51+
super().precompute(precompute_data)
52+
if self.get_count_precompute() > 1:
53+
return self
54+
self._path_planning.precompute(precompute_data)
55+
return self
56+
57+
def resume(self, precompute_data: PrecomputeData) -> ExtAction:
58+
super().resume(precompute_data)
59+
if self.get_count_resume() > 1:
60+
return self
61+
self._path_planning.resume(precompute_data)
62+
return self
63+
64+
def prepare(self) -> ExtAction:
65+
super().prepare()
66+
if self.get_count_prepare() > 1:
67+
return self
68+
self._path_planning.prepare()
69+
return self
70+
71+
def update_info(self, message_manager: MessageManager) -> ExtAction:
72+
super().update_info(message_manager)
73+
if self.get_count_update_info() > 1:
74+
return self
75+
self._path_planning.update_info(message_manager)
76+
return self
77+
78+
def set_target_entity_id(self, target_entity_id: EntityID) -> ExtAction:
79+
entity: Optional[Entity] = self.world_info.get_entity(target_entity_id)
80+
self._target_entity_id = None
81+
82+
if entity is None:
83+
return self
84+
85+
if isinstance(entity, Blockade):
86+
entity = self.world_info.get_entity(cast(Blockade, entity).get_position())
87+
elif isinstance(entity, Human):
88+
entity = entity.get_position()
89+
90+
if entity is None and isinstance(entity, Area):
91+
self._target_entity_id = None
92+
93+
return self
94+
95+
def calc(self) -> ExtAction:
96+
self._result = None
97+
agent: Human = cast(Human, self.agent_info.get_myself())
98+
99+
path: list[EntityID] = self._path_planning.get_path(
100+
agent.get_position(), self._target_entity_id
101+
)
102+
103+
if path is not None or len(path) != 0:
104+
self.result = ActionMove(path)
105+
106+
return self
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
from typing import Optional, Union, cast
2+
3+
from rcrs_core.entities.ambulanceTeam import AmbulanceTeamEntity
4+
from rcrs_core.entities.area import Area
5+
from rcrs_core.entities.civilian import Civilian
6+
from rcrs_core.entities.entity import Entity
7+
from rcrs_core.entities.human import Human
8+
from rcrs_core.entities.refuge import Refuge
9+
from rcrs_core.worldmodel.entityID import EntityID
10+
11+
from adf_core_python.core.agent.action.ambulance.action_load import ActionLoad
12+
from adf_core_python.core.agent.action.ambulance.action_unload import ActionUnload
13+
from adf_core_python.core.agent.action.common.action_move import ActionMove
14+
from adf_core_python.core.agent.action.common.action_rest import ActionRest
15+
from adf_core_python.core.agent.communication.message_manager import MessageManager
16+
from adf_core_python.core.agent.develop.develop_data import DevelopData
17+
from adf_core_python.core.agent.info.agent_info import AgentInfo
18+
from adf_core_python.core.agent.info.scenario_info import Mode, ScenarioInfo
19+
from adf_core_python.core.agent.info.world_info import WorldInfo
20+
from adf_core_python.core.agent.module.module_manager import ModuleManager
21+
from adf_core_python.core.agent.precompute.precompute_data import PrecomputeData
22+
from adf_core_python.core.component.extaction.ext_action import ExtAction
23+
from adf_core_python.core.component.module.algorithm.path_planning import PathPlanning
24+
25+
26+
class DefaultExtendActionTransport(ExtAction):
27+
def __init__(
28+
self,
29+
agent_info: AgentInfo,
30+
world_info: WorldInfo,
31+
scenario_info: ScenarioInfo,
32+
module_manager: ModuleManager,
33+
develop_data: DevelopData,
34+
) -> None:
35+
super().__init__(
36+
agent_info, world_info, scenario_info, module_manager, develop_data
37+
)
38+
self._target_entity_id: Optional[EntityID] = None
39+
self._threshold_to_rest: int = develop_data.get_value("threshold_to_rest", 100)
40+
41+
match self.scenario_info.get_mode():
42+
case Mode.NON_PRECOMPUTE:
43+
self._path_planning: PathPlanning = cast(
44+
PathPlanning,
45+
self.module_manager.get_module(
46+
"DefaultExtendActionMove.PathPlanning",
47+
"adf_core_python.implement.module.astar_path_planning.AStarPathPlanning",
48+
),
49+
)
50+
case Mode.PRECOMPUTATION:
51+
pass
52+
case Mode.PRECOMPUTED:
53+
pass
54+
55+
def precompute(self, precompute_data: PrecomputeData) -> ExtAction:
56+
super().precompute(precompute_data)
57+
if self.get_count_precompute() > 1:
58+
return self
59+
self._path_planning.precompute(precompute_data)
60+
return self
61+
62+
def resume(self, precompute_data: PrecomputeData) -> ExtAction:
63+
super().resume(precompute_data)
64+
if self.get_count_resume() > 1:
65+
return self
66+
self._path_planning.resume(precompute_data)
67+
return self
68+
69+
def prepare(self) -> ExtAction:
70+
super().prepare()
71+
if self.get_count_prepare() > 1:
72+
return self
73+
self._path_planning.prepare()
74+
return self
75+
76+
def update_info(self, message_manager: MessageManager) -> ExtAction:
77+
super().update_info(message_manager)
78+
if self.get_count_update_info() > 1:
79+
return self
80+
self._path_planning.update_info(message_manager)
81+
return self
82+
83+
def set_target_entity_id(self, target_entity_id: EntityID) -> ExtAction:
84+
entity: Optional[Entity] = self.world_info.get_world_model().get_entity(
85+
target_entity_id
86+
)
87+
self._target_entity_id = None
88+
89+
if entity is None:
90+
return self
91+
92+
if isinstance(entity, Human) or isinstance(entity, Area):
93+
self._target_entity_id = target_entity_id
94+
95+
return self
96+
97+
def calc(self) -> ExtAction:
98+
self._result = None
99+
agent: AmbulanceTeamEntity = cast(
100+
AmbulanceTeamEntity, self.agent_info.get_myself()
101+
)
102+
transport_human: Human = self.agent_info.some_one_on_board()
103+
if transport_human is not None:
104+
self.result = self.calc_unload(
105+
agent, self._path_planning, transport_human, self._target_entity_id
106+
)
107+
if self.result is not None:
108+
return self
109+
110+
if self._target_entity_id is not None:
111+
self.result = self.calc_rescue(
112+
agent, self._path_planning, self._target_entity_id
113+
)
114+
115+
return self
116+
117+
def calc_rescue(
118+
self,
119+
agent: AmbulanceTeamEntity,
120+
path_planning: PathPlanning,
121+
target_id: EntityID,
122+
) -> Optional[Union[ActionMove, ActionLoad]]:
123+
target_entity = self.world_info.get_entity(target_id)
124+
if target_entity is None:
125+
return None
126+
127+
agent_position = agent.get_position()
128+
if isinstance(target_entity, Human):
129+
human = target_entity
130+
if human.get_position() is None:
131+
return None
132+
if human.get_hp() is None or human.get_hp() == 0:
133+
return None
134+
135+
target_position = human.get_position()
136+
if agent_position == target_position:
137+
if isinstance(human, Civilian) and (
138+
human.get_buriedness() is not None and human.get_buriedness() > 0
139+
):
140+
return ActionLoad(human.get_id())
141+
else:
142+
path = path_planning.get_path(agent_position, target_position)
143+
if path is not None and len(path) > 0:
144+
return ActionMove(path)
145+
return None
146+
147+
if isinstance(target_entity, Area):
148+
path = path_planning.get_path(agent_position, target_entity.get_id())
149+
if path is not None and len(path) > 0:
150+
return ActionMove(path)
151+
152+
return None
153+
154+
def calc_unload(
155+
self,
156+
agent: AmbulanceTeamEntity,
157+
path_planning: PathPlanning,
158+
transport_human: Optional[Human],
159+
target_id: Optional[EntityID],
160+
) -> Optional[ActionMove | ActionUnload | ActionRest]:
161+
if transport_human is None:
162+
return None
163+
164+
if not transport_human.get_hp() or transport_human.get_hp() == 0:
165+
return ActionUnload()
166+
167+
agent_position = agent.get_position()
168+
if (
169+
target_id is None
170+
or transport_human.get_id().get_value() == target_id.get_value()
171+
):
172+
position = self.world_info.get_entity(agent_position)
173+
if position is None:
174+
return None
175+
176+
if isinstance(position, Refuge):
177+
return ActionUnload()
178+
else:
179+
path = path_planning.get_path(
180+
agent_position, self.world_info.get_entity_ids_of_type(Refuge)
181+
)
182+
if path is not None and len(path) > 0:
183+
return ActionMove(path)
184+
185+
if target_id is None:
186+
return None
187+
188+
target_entity = self.world_info.get_entity(target_id)
189+
190+
if isinstance(target_entity, Human):
191+
human = cast(Human, target_entity)
192+
if human.get_position() is not None:
193+
return self.calc_refuge_action(
194+
agent, path_planning, [human.get_position()], True
195+
)
196+
path = self.get_nearest_refuge_path(agent, path_planning)
197+
if path is not None and len(path) > 0:
198+
return ActionMove(path)
199+
200+
return None
201+
202+
def calc_refuge_action(
203+
self,
204+
human: Human,
205+
path_planning: PathPlanning,
206+
target_entity_id: EntityID,
207+
is_unload: bool,
208+
) -> Optional[ActionMove | ActionUnload | ActionRest]:
209+
position = human.get_position()
210+
refuges = self.world_info.get_entity_ids_of_type(Refuge)
211+
size = len(refuges)
212+
213+
if position in refuges:
214+
return ActionUnload() if is_unload else ActionRest()
215+
216+
first_result = None
217+
while len(refuges) > 0:
218+
path = path_planning.get_path(position, refuges[0])
219+
220+
if path is not None and len(path) > 0:
221+
if first_result is None:
222+
first_result = path.copy()
223+
224+
refuge_id = path[-1]
225+
from_refuge_to_target = path_planning.get_path(
226+
refuge_id, target_entity_id
227+
)
228+
229+
if from_refuge_to_target is not None and len(from_refuge_to_target) > 0:
230+
return ActionMove(path)
231+
232+
refuges.remove(refuge_id)
233+
if size == len(refuges):
234+
break
235+
size = len(refuges)
236+
else:
237+
break
238+
239+
return ActionMove(first_result) if first_result is not None else None
240+
241+
def get_nearest_refuge_path(
242+
self, human: Human, path_planning: PathPlanning
243+
) -> list[EntityID]:
244+
position = human.get_position()
245+
refuges = self.world_info.get_entity_ids_of_type(Refuge)
246+
nearest_path = None
247+
248+
for refuge_id in refuges:
249+
path: list[EntityID] = path_planning.get_path(position, refuge_id)
250+
if len(path) > 0:
251+
if nearest_path is None or len(path) < len(nearest_path):
252+
nearest_path = path
253+
254+
return nearest_path if nearest_path is not None else []

0 commit comments

Comments
 (0)