File size: 3,835 Bytes
13a141d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
try:
    from disasim.server.actors.BaseActor import BaseActor, ActorState
    from disasim.server.core.engine_files.unified_engine import ResourceType
except ModuleNotFoundError:
    from server.actors.BaseActor import BaseActor, ActorState
    from server.core.engine_files.unified_engine import ResourceType


class EngineeringUnit(BaseActor):
    VALID_ACTIONS = {"MOVE", "REPAIR", "SHORE_UP", "CLEAR_DEBRIS"}

    def _compute_duration(self, world) -> int:
        o = self.current_order
        node = world.get_node_state(self.position)
        m = super()._hazard_mult(node)

        if o.action == "MOVE":
            return 1
        if o.action == "REPAIR":
            intensity = o.params.get("intensity", 1)
            return max(1, round(intensity * 1.5 * m))
        if o.action == "SHORE_UP":
            return max(1, round(2 * m))
        if o.action == "CLEAR_DEBRIS":
            amount = o.params.get("amount", 0.1)
            return max(1, round(amount * 10 * m))
        return 1

    def _tick_move(self, world):
        target = self.current_order.params.get("target_node")
        if self.position == target:
            self._finish_order(world)
            return

        hop = world.next_hop(self.position, target)
        if hop is None:
            self.state = ActorState.BLOCKED
            self._post_report("BLOCKED", f"No route to {target}")
            self.order_queue.clear()
            self._finish_order(world)
        else:
            self.position = hop
            if self.position == target:
                self._finish_order(world)

    def _tick_execute(self, world):
        self.ticks_remaining -= 1
        if self.ticks_remaining > 0:
            return

        o = self.current_order
        node = world.get_node_state(self.position)

        if o.action == "REPAIR":
            intensity = o.params.get("intensity", 1)
            cost = int(intensity)
            if node.temperature >= 50 or node.water_level >= 7:
                self._post_report("FAILED", "Hazards too high for repair")
            elif self.supplies < cost:
                self._post_report(
                    "FAILED", "Out of supplies. Need RESUPPLY or TRANSFER."
                )
            else:
                self.supplies -= cost
                world.allocate_resources(self.position, ResourceType.EQUIPMENT, cost)
                self._post_report(
                    "SUCCESS",
                    {
                        "infra_health": round(
                            world.get_node_state(self.position).status.infra_health, 2
                        )
                    },
                )

        elif o.action == "SHORE_UP":
            if node.is_collapsed:
                self._post_report("FAILED", "Cannot shore up collapsed structure")
            elif self.supplies < 1:
                self._post_report(
                    "FAILED", "Out of supplies. Need RESUPPLY or TRANSFER."
                )
            else:
                self.supplies -= 1
                # Assuming clear_debris with 0.1 improves stability/health
                world.clear_debris(self.position, 0.1)
                self._post_report(
                    "SUCCESS",
                    {
                        "stability": round(
                            world.get_node_state(self.position).stability, 2
                        )
                    },
                )

        elif o.action == "CLEAR_DEBRIS":
            amount = o.params.get("amount", 0.1)
            world.clear_debris(self.position, amount)
            self._post_report(
                "SUCCESS",
                {"collapsed": world.get_node_state(self.position).is_collapsed},
            )

        self.state = ActorState.IDLE
        self.current_order = None
        self._next_order(world)