01
02
03
04
05
06
07
08
09
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
{
init: function(robots, warehouse, store) {
// No manual tracking needed - using locks!
},
update: function(robots, orders, warehouse, store) {
// COLLISION RESOLUTION with aggressive jitter
robots.forEach(robot => {
if (!robot.isStuck()) return;
if (robot.repath()) return;
const blocker = robot.getBlocker();
if (!blocker) return;
const yieldKey = 'yield_delay_' + robot.id;
const delay = store.get(yieldKey) || 0;
if (delay > 0) {
store.set(yieldKey, delay - 1);
return;
}
// Escalating probability + extra randomness to break sync
const stuckTicks = robot.stuckCount;
const baseChance = robot.id > blocker.id ? 0.5 : 0.3;
const escalation = Math.min(0.4, stuckTicks * 0.03);
const noise = rand() * 0.25;
const shouldYield = rand() < (baseChance + escalation + noise);
if (shouldYield) {
robot.yield();
// Longer delays that increase with stuck time (3-10 ticks)
const maxDelay = Math.min(10, 3 + Math.floor(stuckTicks / 3));
store.set(yieldKey, Math.floor(rand() * maxDelay) + 2);
} else {
// Even when not yielding, add random delay to desync
store.set(yieldKey, Math.floor(rand() * 4) + 1);
}
});
// Find idle robots
const idleRobots = robots.filter(r => r.state === 'idle');
// Find pending orders
const pendingOrders = orders.filter(o => o.status === 'pending');
// Assign orders to nearest idle robot
pendingOrders.forEach(order => {
if (idleRobots.length === 0) return;
// Try to acquire lock on this order
// Skip if another robot already has it
if (store.locks.isLocked(order.id)) return;
// Find item location
const item = warehouse.items.find(i => i.type === order.item);
if (!item) return;
// Find nearest idle robot
let nearest = null;
let nearestDist = Infinity;
idleRobots.forEach(robot => {
const dist = Math.abs(robot.x - item.pickupPos.x) +
Math.abs(robot.y - item.pickupPos.y);
if (dist < nearestDist) {
nearestDist = dist;
nearest = robot;
}
});
if (nearest && store.locks.acquire(order.id, nearest.id)) {
nearest.assignOrder(order);
// Remove from idle list
const idx = idleRobots.indexOf(nearest);
if (idx > -1) idleRobots.splice(idx, 1);
}
});
// Handle robots that need directions
robots.forEach(robot => {
if (robot.state === 'idle' || robot.path.length > 0) return;
if (robot.state === 'picking') {
// Go to item pickup location
const item = warehouse.items.find(i => i.type === robot.currentOrder.item);
if (item) {
robot.navigateTo(item.pickupPos.x, item.pickupPos.y);
}
} else if (robot.state === 'delivering') {
// Go to shipping zone
robot.navigateTo(warehouse.shippingZone.x + 1, warehouse.shippingZone.y);
}
});
}
}
{ init, update } → robot commandsJavaScriptPreview4 robots · 20 × 14 · seed 42
- Seed
- 42
- Elapsed
- 0ticks
- Fulfilled
- 0
- Pending orders
- 0
- Average time
- 0ticks
Building the warehouse…
0ticks
QuickJS sandbox
Activity
0- Events appear here once the simulation runs