Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ missclasification issue in the GDELT data analysis.
-->

## Citations
For citations, see our list of [Logica publications](https://logica-web.github.io/publications/).
For citations, see our list of [Logica publications](https://logica-lang.github.io/publications/).

## Feedback

Expand Down
2 changes: 1 addition & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
</div>
</div>
</a>
<a href="https://logica-web.github.io/" style="text-decoration: none; color: inherit;">
<a href="https://logica-lang.github.io/" style="text-decoration: none; color: inherit;">
<div class="github_button" style="float: none; margin-top: 0px; padding: 5px;" onclick="openBook()">
<div style="float: none; text-align: center; display: flex; flex-direction: row;">
<div id="closed_book" style="font-size: 4em; display:flex; margin: 0px; width: 80px; text-align: center; justify-content: center;"><span>📘</span></div>
Expand Down
53 changes: 53 additions & 0 deletions docs/robots/Level12.json

Large diffs are not rendered by default.

98 changes: 98 additions & 0 deletions docs/robots/charger.l
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# NEW PREDICATE: Creates a table of all robots with an empty battery.
DeadBot(robot_name:) :-
# Find the sensor data for every robot in the simulation.
Sensor(robot_name: , sensor:),
# Check if that robot has a battery and its level is zero.
sensor.self.has_battery == true,
sensor.self.battery_level == 0;

# HELPER FUNCTION: Returns true if a radar ping 'r' is a charging station.
IsChargingStation(r) = (
r.object == "beacon" && EndsWith(r.label, "_ChargingStation")
);

# HELPER FUNCTION: Finds the ANGLE of the closest DEAD BOT.
ClosestDeadBotAngle(radar) = ArgMin{
r.angle -> r.distance :-
r in radar,
r.object == "robot",
# We check if the name of the robot we see (r.label)
# exists in our table of dead bots.
DeadBot(robot_name: r.label)
};

# HELPER FUNCTION: Finds the ANGLE of the closest CHARGING STATION.
ClosestChargingStationAngle(radar) = ArgMin{
r.angle -> r.distance :-
r in radar,
IsChargingStation(r)==true
};

# A helper function to steer towards a target angle.
SteerTo(target_angle, speed) = {
left_engine: speed - target_angle,
right_engine: speed + target_angle
};

# Standard obstacle avoidance logic.
WeightedAverage(k->v) = Sum(k * v) / Sum(k);
FreedomMotion(radar) = WeightedAverage{
x.distance -> x.angle :- x in radar
};

# Returns true if the robot should be helping a dead bot.
ShouldHelpDeadBot(sensor) = (
sensor.self.can_charge == true &&
sensor.self.battery_level > 0 &&
# We count how many of the robots we see in our radar
# have a name that is in the DeadBot table.
Count{ 1 :-
r in sensor.radar,
r.object == "robot",
DeadBot(robot_name: r.label)
} > 0
);

# Returns true if the robot should be seeking a charging station.
ShouldSeekCharger(sensor) = (
sensor.self.can_charge == true &&
sensor.self.battery_level == 0 &&
Count{1 :- r in sensor.radar, IsChargingStation(r)==true} > 0
);

# --- Main Logic Starts Here (Now Explicit) ---

# PRIORITY 1: A robot that can_charge will go help a dead robot it sees.
Robot(robot_name:, desire:, memory:) :-
Sensor(robot_name:, sensor:),
# Check if the conditions for this priority are met.
ShouldHelpDeadBot(sensor)==true,
# Find the angle to the closest one.
dead_bot_angle = ClosestDeadBotAngle(sensor.radar),
desire = SteerTo(dead_bot_angle, 1),
memory = "Going to help a robot in need!";


# PRIORITY 2: If a robot that can_charge has no battery, it seeks a station.
Robot(robot_name:, desire:, memory:) :-
Sensor(robot_name:, sensor:),
# Check if the conditions for this priority are met.
ShouldSeekCharger(sensor)==true,
# Find the angle to the closest one.
station_angle = ClosestChargingStationAngle(sensor.radar),
desire = SteerTo(station_angle, 1),
memory = "My battery is empty! Seeking a charging station.";


# PRIORITY 3 (DEFAULT): All other robots will just wander around avoiding walls.
Robot(robot_name:, desire:, memory:) :-
Sensor(robot_name:, sensor:),
ShouldHelpDeadBot(sensor)==false,
ShouldSeekCharger(sensor)==false,
freedom = FreedomMotion(sensor.radar),
speed = 0.5,
desire = {
left_engine: speed - freedom+0.1,
right_engine: speed + freedom
},
memory = "Exploring the labyrinth.";
95 changes: 94 additions & 1 deletion docs/robots/editor5.html
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,70 @@
border-radius: 50%;
cursor: pointer;
}

/* The switch container */
.switch {
position: relative;
display: inline-block;
width: 50px; /* Smaller width */
height: 28px; /* Smaller height */
margin-left: auto; /* Aligns it to the right */
}

/* Hide the default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}

/* The slider track */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #555; /* Off color to match your theme */
-webkit-transition: .4s;
transition: .4s;
}

/* The slider handle (the circle) */
.slider:before {
position: absolute;
content: "";
height: 20px; /* Adjusted size */
width: 20px; /* Adjusted size */
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}

/* --- The Magic: What happens when the checkbox is checked --- */

/* Change the background of the track to green */
input:checked + .slider {
background-color: #34c759; /* Green to match your 'Download' button */
}

/* Move the handle to the right */
input:checked + .slider:before {
-webkit-transform: translateX(22px); /* Adjusted distance */
-ms-transform: translateX(22px);
transform: translateX(22px);
}

/* Rounded sliders */
.slider.round {
border-radius: 28px;
}

.slider.round:before {
border-radius: 50%;
}
/* Modal styles for alerts and editing */
.modal-backdrop {
position: fixed;
Expand Down Expand Up @@ -352,6 +415,36 @@ <h3 id="editTitle">Edit Object</h3>
<label for="editOffBeacon">Off Beacon:</label>
<select id="editOffBeacon"></select>
</div>
<div class="edit-row" id="editChargingStationRow" style="display: none;">
<label for="editChargingStation">Charging Station:</label>
<label class="switch">
<input type="checkbox" id="editChargingStation">
<span class="slider round"></span>
</label>
</div>
<div class="edit-row" id="hasBatteryRow" style="display: none;">
<label for="hasBatteryToggle">Has Battery:</label>
<label class="switch">
<input type="checkbox" id="hasBatteryToggle">
<span class="slider round"></span>
</label>
</div>
<div class="edit-row" id="canChargeRow" style="display: none;">
<label for="canChargeToggle">Can Charge:</label>
<label class="switch">
<input type="checkbox" id="canChargeToggle">
<span class="slider round"></span>
</label>
</div>
<div class="edit-row" id="batteryConsumptionRow" style="display: none;">
<label for="batteryConsumptionSlider">Consumption Rate:</label>
<input type="range" id="batteryConsumptionSlider" min="0" max="1" step="0.01" value="1">
<span id="batteryConsumptionValue" style="width: 40px; text-align: right;">1.00</span>
</div>
<div class="edit-row" id="batteryCapacityRow" style="display: none;">
<label for="batteryCapacityInput">Battery Capacity:</label>
<input type="number" id="batteryCapacityInput" value="100" min="0">
</div>
<div class="edit-row" id="editStickySwitchRow" style="display: none;">
<label for="editStickySwitch">Sticky Switch:</label>
<input type="checkbox" id="editStickySwitch">
Expand Down
Loading