Skip to content

Commit 9bbd733

Browse files
committed
- add difficulty selection
- add timer to increase pressure on the player - generate scenarios via gpt-API - add a weirdly hidden how to play button
1 parent e9fd377 commit 9bbd733

File tree

1 file changed

+133
-99
lines changed

1 file changed

+133
-99
lines changed

games/death_by_ai.html

Lines changed: 133 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2,122 +2,156 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8">
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
5+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
66
<title>Death by AI - Single Player</title>
7-
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>💀</text></svg>">
7+
<link rel="icon"
8+
href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>💀</text></svg>">
89
<script src="https://cdn.tailwindcss.com"></script>
910
</head>
1011
<body class="bg-gradient-to-r from-gray-800 to-gray-900 text-white min-h-screen flex items-center justify-center">
1112
<div id="appContainer" class="container mx-auto p-4 max-w-2xl"></div>
13+
<script>const appContainer = document.getElementById('appContainer');
14+
let currentRound = 0;
15+
let playerScore = 0;
16+
let streak = 0;
17+
let difficulty = 'medium';
18+
let playerName = '';
19+
let playerAvatar = '😀';
20+
let timerInterval;
21+
let timeLeft = 60;
22+
const sounds = {
23+
survival: new Audio('https://freesound.org/data/previews/172/172561_2796212-lq.mp3'),
24+
death: new Audio('https://freesound.org/data/previews/320/320496_5260872-lq.mp3'),
25+
transition: new Audio('https://freesound.org/data/previews/561/561660_7107484-lq.mp3')
26+
};
27+
const randomUsernames = ['SurvivalGuru', 'LuckyEscaper', 'DeathDefier', 'ChanceChaser', 'FateChallenger', 'RiskTaker', 'DangerDodger', 'ThrillerThriver', 'AdventureAce', 'PerilPro'];
1228

13-
<script>
14-
const appContainer = document.getElementById('appContainer');
15-
const scenarios = [
16-
"You are falling off a crumbling cliff",
17-
"You are trapped in a room with a black bear",
18-
"You're in a sinking ship",
19-
"You're caught in a tornado",
20-
"You're in a building on fire",
21-
"You're lost in a desert with no water",
22-
"You're facing a charging rhinoceros",
23-
"You're in a plane with failing engines",
24-
"You're caught in an avalanche",
25-
"You're in the path of a lava flow"
26-
];
29+
function startGame() {
30+
currentRound = 0;
31+
playerScore = 0;
32+
streak = 0;
33+
renderCharacterCreation();
34+
}
2735

28-
let currentRound = 0;
29-
let playerScore = 0;
36+
function renderCharacterCreation() {
37+
appContainer.innerHTML = `<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg"><h2 class="text-3xl mb-4 text-green-400">Create Your Character</h2><input id="player-name" class="bg-gray-800 text-white px-4 py-2 rounded focus:outline-none focus:ring-2 focus:ring-green-500 w-full mb-4" placeholder="Enter your name (optional)" value="${randomUsernames[Math.floor(Math.random() * randomUsernames.length)]}"><div class="mb-4"><label class="block mb-2">Choose your avatar:</label><div class="flex justify-center space-x-2">${['😀', '😎', '🤠', '🧐', '🥸', '🤓', '👻', '💀', '👽', '🤖'].map(emoji => `<button class="avatar-btn text-2xl p-2 rounded ${emoji === playerAvatar ? 'bg-green-500' : 'bg-gray-600'}" data-emoji="${emoji}">${emoji}</button>`).join('')}</div></div><button id="start-game" class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105 w-full">Start Game</button></div>`;
38+
document.querySelectorAll('.avatar-btn').forEach(btn => btn.addEventListener('click', (e) => {
39+
document.querySelectorAll('.avatar-btn').forEach(b => b.classList.remove('bg-green-500'));
40+
e.target.classList.add('bg-green-500');
41+
playerAvatar = e.target.dataset.emoji;
42+
}));
43+
document.getElementById('start-game').addEventListener('click', () => {
44+
playerName = document.getElementById('player-name').value || 'Player';
45+
renderDifficultySelection();
46+
});
47+
}
3048

31-
function startGame() {
32-
currentRound = 0;
33-
playerScore = 0;
49+
function renderDifficultySelection() {
50+
appContainer.innerHTML = `<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg"><h2 class="text-3xl mb-4 text-green-400">Select Difficulty</h2><div class="space-y-4">${['easy', 'medium', 'hard', 'certain death'].map(diff => `<button class="difficulty-btn bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105 w-full" data-difficulty="${diff}">${diff.charAt(0).toUpperCase() + diff.slice(1)}</button>`).join('')}</div></div>`;
51+
document.querySelectorAll('.difficulty-btn').forEach(btn => btn.addEventListener('click', (e) => {
52+
difficulty = e.target.dataset.difficulty;
3453
nextRound();
35-
}
36-
37-
function nextRound() {
38-
if (currentRound < 5) {
39-
currentRound++;
40-
const scenario = scenarios[Math.floor(Math.random() * scenarios.length)];
41-
renderPromptInput(scenario);
42-
} else {
43-
renderScoreboard();
44-
}
45-
}
54+
}));
55+
}
4656

47-
function renderPromptInput(scenario) {
48-
appContainer.innerHTML = `
49-
<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg">
50-
<h2 class="text-3xl mb-4 text-green-400">Round ${currentRound}/5: ${scenario}</h2>
51-
<textarea id="prompt-input" class="bg-gray-800 text-white px-4 py-2 rounded focus:outline-none focus:ring-2 focus:ring-green-500 w-full h-32 mb-4" placeholder="Enter your escape plan..."></textarea>
52-
<button id="submit-prompt" class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105 w-full">Submit</button>
53-
</div>
54-
`;
55-
document.getElementById('submit-prompt').addEventListener('click', () => submitPrompt(scenario));
57+
async function nextRound() {
58+
if (currentRound < 5) {
59+
currentRound++;
60+
const scenario = await generateScenario();
61+
renderPromptInput(scenario);
62+
} else {
63+
renderScoreboard();
5664
}
65+
}
5766

58-
async function submitPrompt(scenario) {
59-
const prompt = document.getElementById('prompt-input').value || "The player didn't submit a prompt";
60-
appContainer.innerHTML = `
61-
<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg">
62-
<h2 class="text-3xl mb-4 text-green-400">Resolving your fate</h2>
63-
<p class="text-xl">Please wait...</p>
64-
</div>
65-
`;
66-
67-
try {
68-
const response = await fetch('https://chatgpt.tobiasmue91.workers.dev/', {
69-
method: 'POST',
70-
headers: {"Content-Type": "application/json", "Accept": "*/*"},
71-
body: JSON.stringify({
72-
model: "gpt-3.5-turbo",
73-
max_tokens: 150,
74-
temperature: 0.7,
75-
messages: [
76-
{role: "system", content: "You are the AI judge in a game called 'Death by AI'. Your task is to determine if a player survives a given scenario based on their prompt. Respond with a JSON object containing 'survived' (boolean) and 'explanation' (string)."},
77-
{role: "user", content: `Scenario: ${scenario}\nPlayer's action: ${prompt}`}
78-
]
79-
})
80-
});
67+
async function generateScenario() {
68+
const response = await fetch('https://chatgpt.tobiasmue91.workers.dev/', {
69+
method: 'POST',
70+
headers: {"Content-Type": "application/json", "Accept": "*/*"},
71+
body: JSON.stringify({
72+
model: "gpt-3.5-turbo",
73+
max_tokens: 50,
74+
temperature: 0.7,
75+
messages: [{
76+
role: "system",
77+
content: `You are a creative scenario generator for a survival game. Generate a brief, challenging scenario based on the difficulty: ${difficulty}. The scenario should be a single sentence describing a dangerous situation.`
78+
}, {role: "user", content: `Generate a ${difficulty} scenario.`}]
79+
})
80+
});
81+
const data = await response.json();
82+
return data.choices[0].message.content;
83+
}
8184

82-
const data = await response.json();
83-
const fate = JSON.parse(data.choices[0].message.content);
84-
85-
if (fate.survived) playerScore++;
85+
function renderPromptInput(scenario) {
86+
timeLeft = 60;
87+
appContainer.innerHTML = `<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg"><h2 class="text-3xl mb-4 text-green-400">Round ${currentRound}/5</h2><p class="text-xl mb-4">${scenario}</p><p class="mb-2">Difficulty: ${difficulty.charAt(0).toUpperCase() + difficulty.slice(1)}</p><p class="mb-2">Current Streak: ${streak}</p><p id="timer" class="text-xl mb-4">Time left: 60s</p><textarea id="prompt-input" class="bg-gray-800 text-white px-4 py-2 rounded focus:outline-none focus:ring-2 focus:ring-green-500 w-full h-32 mb-4" placeholder="Enter your escape plan..."></textarea><button id="submit-prompt" class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105 w-full">Submit</button></div>`;
88+
document.getElementById('submit-prompt').addEventListener('click', () => submitPrompt(scenario));
89+
timerInterval = setInterval(() => {
90+
timeLeft--;
91+
document.getElementById('timer').textContent = `Time left: ${timeLeft}s`;
92+
if (timeLeft <= 0) {
93+
clearInterval(timerInterval);
94+
submitPrompt(scenario);
95+
}
96+
}, 1000);
97+
}
8698

87-
appContainer.innerHTML = `
88-
<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg">
89-
<h2 class="text-3xl mb-4 text-green-400">Your Fate</h2>
90-
<p class="text-xl mb-4">${fate.explanation}</p>
91-
<p class="text-2xl font-bold ${fate.survived ? 'text-green-400' : 'text-red-400'}">${fate.survived ? 'You survived!' : 'You died!'}</p>
92-
<button id="next-round" class="mt-4 bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105 w-full">Next Round</button>
93-
</div>
94-
`;
95-
document.getElementById('next-round').addEventListener('click', nextRound);
96-
} catch (error) {
97-
console.error('Error resolving fate:', error);
98-
appContainer.innerHTML = `
99-
<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg">
100-
<h2 class="text-3xl mb-4 text-red-400">Error</h2>
101-
<p class="text-xl">An error occurred while resolving your fate. Please try again.</p>
102-
<button id="retry" class="mt-4 bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105 w-full">Retry</button>
103-
</div>
104-
`;
105-
document.getElementById('retry').addEventListener('click', () => renderPromptInput(scenario));
99+
async function submitPrompt(scenario) {
100+
clearInterval(timerInterval);
101+
const prompt = document.getElementById('prompt-input').value || "The player didn't submit a prompt";
102+
appContainer.innerHTML = `<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg"><h2 class="text-3xl mb-4 text-green-400">Resolving your fate</h2><p class="text-xl">Please wait...</p></div>`;
103+
try {
104+
const response = await fetch('https://chatgpt.tobiasmue91.workers.dev/', {
105+
method: 'POST',
106+
headers: {"Content-Type": "application/json", "Accept": "*/*"},
107+
body: JSON.stringify({
108+
model: "gpt-3.5-turbo",
109+
max_tokens: 150,
110+
temperature: 0.7,
111+
messages: [{
112+
role: "system",
113+
content: `You are the AI judge in a game called 'Death by AI'. Your task is to determine if a player survives a given scenario based on their prompt. The current difficulty is ${difficulty}. Respond with a JSON object containing 'survived' (boolean) and 'explanation' (string). For 'easy' difficulty, be more lenient. For 'hard' difficulty, be more strict. For 'certain death', almost always result in death unless the solution is exceptionally clever.`
114+
}, {role: "user", content: `Scenario: ${scenario}\nPlayer's action: ${prompt}`}]
115+
})
116+
});
117+
const data = await response.json();
118+
const fate = JSON.parse(data.choices[0].message.content);
119+
if (fate.survived) {
120+
playerScore++;
121+
streak++;
122+
sounds.survival.play();
123+
} else {
124+
streak = 0;
125+
sounds.death.play();
106126
}
127+
appContainer.innerHTML = `<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg opacity-0 transition-opacity duration-1000" id="fate-container"><h2 class="text-3xl mb-4 text-green-400">Your Fate</h2><p class="text-xl mb-4">${fate.explanation}</p><p class="text-2xl font-bold ${fate.survived ? 'text-green-400' : 'text-red-400'}">${fate.survived ? 'You survived!' : 'You died!'}</p><button id="next-round" class="mt-4 bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105 w-full">Next Round</button></div>`;
128+
setTimeout(() => {
129+
document.getElementById('fate-container').classList.remove('opacity-0');
130+
}, 100);
131+
document.getElementById('next-round').addEventListener('click', () => {
132+
sounds.transition.play();
133+
nextRound();
134+
});
135+
} catch (error) {
136+
console.error('Error resolving fate:', error);
137+
appContainer.innerHTML = `<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg"><h2 class="text-3xl mb-4 text-red-400">Error</h2><p class="text-xl">An error occurred while resolving your fate. Please try again.</p><button id="retry" class="mt-4 bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105 w-full">Retry</button></div>`;
138+
document.getElementById('retry').addEventListener('click', () => renderPromptInput(scenario));
107139
}
140+
}
108141

109-
function renderScoreboard() {
110-
appContainer.innerHTML = `
111-
<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg">
112-
<h2 class="text-3xl mb-4 text-green-400">Game Over</h2>
113-
<p class="text-2xl mb-4">Your final score: ${playerScore}/5</p>
114-
<button id="new-game" class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105 w-full">New Game</button>
115-
</div>
116-
`;
117-
document.getElementById('new-game').addEventListener('click', startGame);
118-
}
142+
function renderScoreboard() {
143+
const highScore = Math.max(playerScore, parseInt(localStorage.getItem('highScore') || '0'));
144+
localStorage.setItem('highScore', highScore.toString());
145+
appContainer.innerHTML = `<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg"><h2 class="text-3xl mb-4 text-green-400">Game Over</h2><p class="text-2xl mb-2">${playerName} ${playerAvatar}</p><p class="text-xl mb-4">Your final score: ${playerScore}/5</p><p class="text-xl mb-4">High Score: ${highScore}/5</p><button id="new-game" class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105 w-full mb-4">New Game</button><button id="how-to-play" class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105 w-full">How to Play</button></div>`;
146+
document.getElementById('new-game').addEventListener('click', startGame);
147+
document.getElementById('how-to-play').addEventListener('click', showTutorial);
148+
}
149+
150+
function showTutorial() {
151+
appContainer.innerHTML = `<div class="text-center bg-gray-700 p-8 rounded-lg shadow-lg"><h2 class="text-3xl mb-4 text-green-400">How to Play</h2><ol class="text-left list-decimal list-inside mb-4"><li>Create your character (optional)</li><li>Choose the difficulty level</li><li>For each round, you'll be presented with a unique dangerous scenario</li><li>Type your escape plan within the time limit</li><li>The AI will judge if you survive based on your plan</li><li>Try to survive all 5 rounds!</li></ol><p class="mb-4">Tips:<br>- Be creative and detailed in your escape plans<br>- Consider the difficulty level when crafting your response<br>- Try to build a streak of survivals for bonus points</p><button id="back-to-menu" class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105 w-full">Back to Menu</button></div>`;
152+
document.getElementById('back-to-menu').addEventListener('click', startGame);
153+
}
119154

120-
startGame();
121-
</script>
155+
startGame();</script>
122156
</body>
123157
</html>

0 commit comments

Comments
 (0)