|
| 1 | +# NEW PREDICATE: Creates a table of all robots with an empty battery. |
| 2 | +DeadBot(robot_name:) :- |
| 3 | + # Find the sensor data for every robot in the simulation. |
| 4 | + Sensor(robot_name: , sensor:), |
| 5 | + # Check if that robot has a battery and its level is zero. |
| 6 | + sensor.self.has_battery == true, |
| 7 | + sensor.self.battery_level == 0; |
| 8 | + |
| 9 | +# HELPER FUNCTION: Returns true if a radar ping 'r' is a charging station. |
| 10 | +IsChargingStation(r) = ( |
| 11 | + r.object == "beacon" && EndsWith(r.label, "_ChargingStation") |
| 12 | +); |
| 13 | + |
| 14 | +# HELPER FUNCTION: Finds the ANGLE of the closest DEAD BOT. |
| 15 | +ClosestDeadBotAngle(radar) = ArgMin{ |
| 16 | + r.angle -> r.distance :- |
| 17 | + r in radar, |
| 18 | + r.object == "robot", |
| 19 | + # We check if the name of the robot we see (r.label) |
| 20 | + # exists in our table of dead bots. |
| 21 | + DeadBot(robot_name: r.label) |
| 22 | +}; |
| 23 | + |
| 24 | +# HELPER FUNCTION: Finds the ANGLE of the closest CHARGING STATION. |
| 25 | +ClosestChargingStationAngle(radar) = ArgMin{ |
| 26 | + r.angle -> r.distance :- |
| 27 | + r in radar, |
| 28 | + IsChargingStation(r)==true |
| 29 | +}; |
| 30 | + |
| 31 | +# A helper function to steer towards a target angle. |
| 32 | +SteerTo(target_angle, speed) = { |
| 33 | + left_engine: speed - target_angle, |
| 34 | + right_engine: speed + target_angle |
| 35 | +}; |
| 36 | + |
| 37 | +# Standard obstacle avoidance logic. |
| 38 | +WeightedAverage(k->v) = Sum(k * v) / Sum(k); |
| 39 | +FreedomMotion(radar) = WeightedAverage{ |
| 40 | + x.distance -> x.angle :- x in radar |
| 41 | +}; |
| 42 | + |
| 43 | +# Returns true if the robot should be helping a dead bot. |
| 44 | +ShouldHelpDeadBot(sensor) = ( |
| 45 | + sensor.self.can_charge == true && |
| 46 | + sensor.self.battery_level > 0 && |
| 47 | + # We count how many of the robots we see in our radar |
| 48 | + # have a name that is in the DeadBot table. |
| 49 | + Count{ 1 :- |
| 50 | + r in sensor.radar, |
| 51 | + r.object == "robot", |
| 52 | + DeadBot(robot_name: r.label) |
| 53 | + } > 0 |
| 54 | +); |
| 55 | + |
| 56 | +# Returns true if the robot should be seeking a charging station. |
| 57 | +ShouldSeekCharger(sensor) = ( |
| 58 | + sensor.self.can_charge == true && |
| 59 | + sensor.self.battery_level == 0 && |
| 60 | + Count{1 :- r in sensor.radar, IsChargingStation(r)==true} > 0 |
| 61 | +); |
| 62 | + |
| 63 | +# --- Main Logic Starts Here (Now Explicit) --- |
| 64 | + |
| 65 | +# PRIORITY 1: A robot that can_charge will go help a dead robot it sees. |
| 66 | +Robot(robot_name:, desire:, memory:) :- |
| 67 | + Sensor(robot_name:, sensor:), |
| 68 | + # Check if the conditions for this priority are met. |
| 69 | + ShouldHelpDeadBot(sensor)==true, |
| 70 | + # Find the angle to the closest one. |
| 71 | + dead_bot_angle = ClosestDeadBotAngle(sensor.radar), |
| 72 | + desire = SteerTo(dead_bot_angle, 1), |
| 73 | + memory = "Going to help a robot in need!"; |
| 74 | + |
| 75 | + |
| 76 | +# PRIORITY 2: If a robot that can_charge has no battery, it seeks a station. |
| 77 | +Robot(robot_name:, desire:, memory:) :- |
| 78 | + Sensor(robot_name:, sensor:), |
| 79 | + # Check if the conditions for this priority are met. |
| 80 | + ShouldSeekCharger(sensor)==true, |
| 81 | + # Find the angle to the closest one. |
| 82 | + station_angle = ClosestChargingStationAngle(sensor.radar), |
| 83 | + desire = SteerTo(station_angle, 1), |
| 84 | + memory = "My battery is empty! Seeking a charging station."; |
| 85 | + |
| 86 | + |
| 87 | +# PRIORITY 3 (DEFAULT): All other robots will just wander around avoiding walls. |
| 88 | +Robot(robot_name:, desire:, memory:) :- |
| 89 | + Sensor(robot_name:, sensor:), |
| 90 | + ShouldHelpDeadBot(sensor)==false, |
| 91 | + ShouldSeekCharger(sensor)==false, |
| 92 | + freedom = FreedomMotion(sensor.radar), |
| 93 | + speed = 0.5, |
| 94 | + desire = { |
| 95 | + left_engine: speed - freedom+0.1, |
| 96 | + right_engine: speed + freedom |
| 97 | + }, |
| 98 | + memory = "Exploring the labyrinth."; |
0 commit comments