Implement per-prompt metadata filtering and fix battleship feedback system

Major improvements to battleship game feedback accuracy and user experience:

## New Multi-Prompt Feedback System
- Replaced single feedback with 3 specialized prompts: Shot Report, Ship Status, Game Over
- Each prompt has individual metadata filtering to see only relevant data
- Shot Report only sees hit/miss data, Ship Status only sees ship destruction data
- Added STFU token system to suppress empty messages (filtered out automatically)

## Technical Implementation
- Added per-prompt metadata_filter support in YAML structure
- Updated app.py and guarded_ai.py to handle prompt-specific filtering
- Legacy single-prompt system still works with transition-level filtering
- Added comprehensive test suite for feedback system validation

## User Experience Fixes
- Fixed TTS queue blocking JavaScript execution (async promises instead of await)
- Ship Status now correctly reports who destroyed which ship (role confusion fixed)
- Game Over only appears when game actually ends (no more random messages)
- Maintained dramatic storytelling while ensuring factual accuracy

## Battleship-Specific Improvements
- Ship destruction messages only appear when ships actually sink
- Clear separation of concerns: hits/misses vs ship destruction vs game over
- Eliminated false positive ship destruction reports
- Fixed role reversal where wrong player got credit for destruction

The battleship narrator now provides accurate, contextual feedback while preserving the dramatic naval warfare atmosphere.
This commit is contained in:
Russell Ballestrini 2025-08-11 11:39:49 -04:00
parent e28dc11f04
commit d4d697db59
10 changed files with 1448 additions and 107 deletions

View file

@ -472,7 +472,7 @@ function queueTTS(text, playButton, messageId) {
}
// Function to process the next TTS in queue
async function processNextTTS() {
function processNextTTS() {
if (isPlayingTTS || ttsQueue.length === 0) {
return;
}
@ -481,15 +481,19 @@ async function processNextTTS() {
const { text, playButton, messageId } = ttsQueue.shift();
console.log("Processing TTS from queue:", messageId);
try {
await speakTextQueued(text, playButton, messageId);
} catch (error) {
console.error("TTS error:", error);
}
isPlayingTTS = false;
// Process next item in queue
setTimeout(processNextTTS, 100);
// Use non-blocking async processing
speakTextQueued(text, playButton, messageId)
.then(() => {
console.log("TTS completed successfully for:", messageId);
})
.catch((error) => {
console.error("TTS error:", error);
})
.finally(() => {
isPlayingTTS = false;
// Schedule next item with minimal delay to prevent blocking
setTimeout(processNextTTS, 10);
});
}
// Function to update auto-play TTS button display
@ -521,6 +525,23 @@ function toggleAutoPlayTTS() {
// Save to localStorage
localStorage.setItem('autoPlayTTS', autoPlayTTS.toString());
// If turning off, clear the queue and stop current audio
if (!autoPlayTTS) {
console.log("Clearing TTS queue, had", ttsQueue.length, "items");
ttsQueue = [];
isPlayingTTS = false;
// Stop any currently playing audio
if (currentAudio) {
currentAudio.pause();
currentAudio.currentTime = 0;
if (currentAudio.playButton) {
currentAudio.playButton.textContent = "Play";
}
currentAudio = null;
}
}
updateAutoPlayTTSDisplay();
}
@ -626,7 +647,7 @@ socket.on("chat_message", (data) => {
console.log("Queueing TTS for message:", data.id);
queueTTS(data.content, playButton, data.id);
}
}, 100); // Short delay to let buttons be created
}, 10); // Very short delay to let buttons be created
}
}
});
@ -799,7 +820,7 @@ socket.on("message_chunk", (data) => {
setTimeout(() => {
const fullText = targetMessageElement.textContent || targetMessageElement.innerText;
queueTTS(fullText, playButton, data.id);
}, 500); // Small delay to let the message render
}, 50); // Small delay to let the message render
}
}
}
@ -1018,11 +1039,15 @@ function addLineNumbers(block) {
// Socket event for setting the chat background
socket.on("set_background", (data) => {
const chat = document.getElementById("chat");
chat.style.backgroundImage = `url('data:image/png;base64,${data.image_data}')`;
chat.style.backgroundRepeat = "no-repeat";
chat.style.backgroundPosition = "right center";
chat.style.backgroundSize = "auto"; // Ensures the image is not stretched
// Use setTimeout to ensure background updates don't get blocked by TTS
setTimeout(() => {
const chat = document.getElementById("chat");
chat.style.backgroundImage = `url('data:image/png;base64,${data.image_data}')`;
chat.style.backgroundRepeat = "no-repeat";
chat.style.backgroundPosition = "right center";
chat.style.backgroundSize = "auto"; // Ensures the image is not stretched
console.log("Background image updated");
}, 0);
});
// Activity management functions