The agent receives a 2D matrix representing the observable world. Each cell is ONE single letter:
Letter
Meaning
A
Adventurer - you are here
E
Empty - safe cell (visited, no dangers)
U
Unknown - unvisited cell (could be anything)
L
Limit/Wall - boundary or wall
B
Breeze - safe but adjacent to a pit (warning!)
S
Stench - safe but adjacent to a wumpus
8
Both sensors - adjacent to pit AND wumpus
P
Pit - game over (you fell here)
W
Wumpus - game over (you died here)
Return Actions
Action
Description
U
Move Up
D
Move Down
L
Move Left
R
Move Right
SU
Shoot Arrow Up
SD
Shoot Arrow Down
SL
Shoot Arrow Left
SR
Shoot Arrow Right
Example Agent
// This agent explores the world avoiding pits
// It has basic survival logic but doesn't hunt wumpuses
function agent(world) {
// Find your position
for (let y = 0; y < world.length; y++) {
for (let x = 0; x < world[y].length; x++) {
if (world[y][x].includes('A')) {
// EXPLORATION PRIORITY:
// 1. If we feel a breeze (B), be extra careful
// 2. Find unvisited adjacent cells to explore
// 3. Default: pick a random unvisited direction
// Check adjacent cells (up, right, down, left)
const dirs = [
{dx: 0, dy: -1, name: 'U'},
{dx: 1, dy: 0, name: 'R'},
{dx: 0, dy: 1, name: 'D'},
{dx: -1, dy: 0, name: 'L'}
];
// Breeze detection: adjacent to pit danger!
// When we feel B (breeze), avoid moving into unknown
// cells that could be pits
// Stench (S) means wumpus is nearby
// Currently we ignore it - could shoot randomly
let safeMoves = [];
let unknownMoves = [];
let unknownCount = 0;
for (let d of dirs) {
const nx = x + d.dx;
const ny = y + d.dy;
const cell = world[ny]?.[nx] || 'L';
if (cell === 'L') continue; // Wall
if (cell.includes('P') || cell.includes('W')) continue; // Death
if (cell === 'U') {
unknownMoves.push(d.name);
unknownCount++;
} else {
safeMoves.push(d.name);
}
}
// STRATEGY: Explore unknown cells first to map the world
// Then fall back to safe moves if no unknowns available
// PRIORITY: Unknown > Safe > Shoot > Random
if (unknownMoves.length > 0) {
return unknownMoves[Math.floor(Math.random() * unknownMoves.length)];
}
if (safeMoves.length > 0) {
return safeMoves[Math.floor(Math.random() * safeMoves.length)];
}
// No valid moves - shoot randomly
const shootDirs = ['SU', 'SR', 'SD', 'SL'];
return shootDirs[Math.floor(Math.random() * shootDirs.length)];
}
}
}
return 'U'; // Default fallback
}
Tips
The world array has Y rows and X columns
World[0] is the top row, world[world.length-1] is bottom
Out of bounds returns 'L' (limit)
8 means both Breeze and Stench present
The agent function is called after each action
Use Step for debugging, Play for continuous simulation