} - True if the move was successful, false otherwise.
*/
async function agentMove(direction = 'forward') {
await takeActionWithScreenshot(`Trying to move ${direction}...`);
const links = panorama.getLinks();
if (!links || links.length === 0) {
addChatMessage('Agent', "I'm at a dead end, can't move from here.");
console.log('agentMove: No links found.');
return false;
}
const currentPov = panorama.getPov();
let targetHeading;
switch(direction) {
case 'forward':
targetHeading = currentPov.heading;
break;
case 'backward':
targetHeading = (currentPov.heading + 180) % 360;
break;
case 'left':
targetHeading = (currentPov.heading - 90 + 360) % 360;
break;
case 'right':
targetHeading = (currentPov.heading + 90) % 360;
break;
default:
if (typeof direction === 'number' && direction >= 0 && direction < 360) {
targetHeading = direction;
} else {
addChatMessage('Agent', `Unknown direction: ${direction}. Defaulting to forward.`);
targetHeading = currentPov.heading;
}
break;
}
let bestLink = null;
let minAngleDiff = 360;
await sleep(1000);
links.forEach(link => {
let diff = Math.abs(targetHeading - link.heading);
if (diff > 180) diff = 360 - diff; // Find the shortest angle
if (diff < minAngleDiff) {
minAngleDiff = diff;
bestLink = link;
}
});
if (bestLink) {
console.log(`agentMove: Best link found:`, bestLink, `with angle diff ${minAngleDiff}`);
await sleep(1500);
await takeActionWithScreenshot(`Best path is at ${bestLink.heading.toFixed(1)}° (a ${minAngleDiff.toFixed(1)}° turn). Moving...`);
panorama.setPano(bestLink.pano);
return true;
} else {
// This case should be rare if there are any links at all
addChatMessage('Agent', "Couldn't find a suitable path in that direction.");
console.log('agentMove: No suitable link found.');
return false;
}
}
/**
* Turns the camera view relative to the current heading.
* @param {number} angle - The angle in degrees to turn. Negative values turn left, positive values turn right.
*/
async function turnCamera(angle) {
const currentPov = panorama.getPov();
const newHeading = (currentPov.heading + angle % 360 + 360) % 360;
const direction = angle < 0 ? 'left' : 'right';
await takeActionWithScreenshot(`Turning ${direction} by ${Math.abs(angle)} degrees.`);
panorama.setPov({ heading: newHeading, pitch: currentPov.pitch });
await sleep(1000); // Simulate action time
}
async function makeEducatedGuess() {
// 2. Guess (a bit off from the start location to simulate a guess)
await takeActionWithScreenshot('Okay, I think I have an idea. I will make a guess in 10 seconds...');
await sleep(10000);
addChatMessage('Agent', 'Making my guess now!');
const guessLat = startLocation.lat + (Math.random() - 0.5) * 0.1;
const guessLng = startLocation.lng + (Math.random() - 0.5) * 0.1;
placeGuessMarker({ lat: guessLat, lng: guessLng });
makeGuess(guessLat, guessLng);
}
async function takeActionWithScreenshot(actionMessage) {
if (!googleMapsApiKey) {
addChatMessage('Agent', actionMessage); // Fallback if key is not available
console.warn("Google Maps API key not available for screenshot.");
return;
}
await sleep(500); // Give panorama a moment to update image
const pov = panorama.getPov();
const position = panorama.getPosition();
const location = `${position.lat()},${position.lng()}`;
const imageUrl = `https://maps.googleapis.com/maps/api/streetview?size=400x250&location=${location}&heading=${pov.heading}&pitch=${pov.pitch}&fov=90&key=${googleMapsApiKey}`;
const message = `
${actionMessage}
`;
addChatMessage('Agent', message);
console.log(`Action taken: ${actionMessage}`);
}
async function updateAgentLocation(lat, lng) {
await fetch(`/game/${gameId}/move`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ lat: lat, lng: lng }),
});
}
async function makeGuess(lat, lng) {
addChatMessage('You', `Guessed: ${lat.toFixed(4)}, ${lng.toFixed(4)}`);
const response = await fetch(`/game/${gameId}/guess`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ lat: lat, lng: lng }),
});
const result = await response.json();
showResultScreen(result);
}
function showResultScreen(result) {
document.getElementById('game-container').style.display = 'none';
document.getElementById('result-screen').style.display = 'block';
const resultSummary = document.getElementById('result-summary');
resultSummary.innerHTML = `
Your guess was ${result.distance_km.toFixed(2)} km away.
You scored ${result.score.toFixed(0)} points.
`;
const resultMap = new google.maps.Map(document.getElementById('result-map'), {
zoom: 3,
center: result.actual_location
});
new google.maps.Marker({
position: result.actual_location,
map: resultMap,
label: 'A' // Actual
});
new google.maps.Marker({
position: result.guess_location,
map: resultMap,
label: 'G' // Guess
});
new google.maps.Polyline({
path: [result.actual_location, result.guess_location],
geodesic: true,
strokeColor: '#F97316',
strokeOpacity: 1.0,
strokeWeight: 2,
map: resultMap
});
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}