Updates rules to be closer to original Y.A.R.N

This commit is contained in:
Cam Spry 2026-03-02 02:42:54 -05:00
parent a65607b054
commit f1e9470710
3 changed files with 50 additions and 18 deletions

View File

@ -477,7 +477,10 @@
hasSubmitted = false;
hasVoted = false;
updateUI();
appendSystemMessage('New round started!');
appendSystemMessage(`Round ${gameState.currentRound} started!`);
if (gameState.currentRound === gameState.gameSettings.roundLimit) {
appendSystemMessage(`It's the final round. Points count double!`);
}
});
socket.on('gameOver', (data) => {
@ -553,9 +556,13 @@
case 'lobby':
if (isHost) {
gameBar.innerHTML = `
<div class="setting-group">
<label>Round Limit:</label>
<input type="number" id="round-limit" value="${gameState.gameSettings.roundLimit}" min="3" max="100">
</div>
<div class="setting-group">
<label>Score Limit:</label>
<input type="number" id="score-limit" value="${gameState.gameSettings.scoreLimit}" min="10" max="100">
<input type="number" id="score-limit" value="${gameState.gameSettings.scoreLimit}" min="0" max="100">
</div>
<div class="setting-group">
<label>Time per Round (sec):</label>
@ -576,8 +583,6 @@
} else {
gameBar.innerHTML = `
<span class="waiting-message">Waiting for host to start the game...</span>
<span>Score Limit: ${gameState.gameSettings.scoreLimit}</span>
<span>Time Limit: ${gameState.gameSettings.timeLimit}s</span>
`;
}
break;
@ -755,12 +760,14 @@
function startGame() {
const scoreLimit = parseInt(document.getElementById('score-limit').value) || 100;
const roundLimit = parseInt(document.getElementById('round-limit').value) || 15;
const timeLimit = parseInt(document.getElementById('time-limit').value) || 60;
const botCount = parseInt(document.getElementById('bot-count').value) || 0;
const startText = document.getElementById('start-text').value;
socket.emit('startGame', {
scoreLimit: Math.max(10, Math.min(9999, scoreLimit)),
scoreLimit: Math.max(0, Math.min(9999, scoreLimit)),
roundLimit: Math.max(0, Math.min(100, roundLimit)),
timeLimit: Math.max(15, Math.min(600, timeLimit)),
botCount: Math.max(0, Math.min(5, botCount)),
startText

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta property="og:title" content="Y.A.R.N HTML5" />
<meta property="og:description" content="A collaborative story-writing game. Remake of the 2000s GameSpy Arcade classic." />
<title>Y.A.R.N. 2026</title>
<title>Y.A.R.N. HTML5</title>
<!-- re-use the same CSS-variables and base look -->
<style>
@ -134,7 +134,8 @@
<ul>
<li>Players have a limited amount of time to write a sentence, selected by the host at game start.</li>
<li>Once all players have submitted their sentences, players have 30 seconds to vote for their favorite.</li>
<li>The player whose sentence is chosen receives 5 points, plus one point for each vote they received.</li>
<li>The player whose sentence is chosen receives 3 bonus points, and all players receive one point for each vote they received.</li>
<li>In the case of a tie, the longest sentence receives two extra points and the other sentences tied receive 1 point each.</li>
<li>When a player reaches the point limit, they win the game.</li>
</ul>
<p>Enjoy the story-writing!<br><br>

View File

@ -25,7 +25,8 @@ class YarnGame {
this.inProgress = false;
this.gameHost = null;
this.gameSettings = {
scoreLimit: 50,
scoreLimit: 0,
roundLimit: 15,
timeLimit: 60,
botCount: 0,
startText: "It was a dark and stormy night..."
@ -36,6 +37,7 @@ class YarnGame {
this.yarnStory = []; // { player: "", str: "" }
this.chat = []; // { id, name, msg }
this.round_data = []; // { entry_text, player_id, votes: [] }
this.roundCount = 0; // current round
this.currentPhase = 'lobby'; // lobby, writing, voting, gameOver
this.timer = null;
this.timeRemaining = 0;
@ -133,6 +135,7 @@ class YarnGame {
async startGame(settings) {
this.gameSettings = { ...this.gameSettings, ...settings };
this.roundCount = 0;
this.startBots(this.gameSettings.botCount);
this.inProgress = true;
this.yarnStory = [{ player: "Narrator", str: this.gameSettings.startText }];
@ -142,9 +145,13 @@ class YarnGame {
async processBotWriting() {
for (const botObj of this.bots) {
try {
const botText = await botObj.bot.Write(this.getStoryText());
console.log(`Bot text: ${botText}`)
this.submitEntry(botObj.bot_id, botText)
console.log(`Bot text: ${botText}`);
this.submitEntry(botObj.bot_id, botText);
} catch (err) {
console.warn(`Bot ${botObj.bot_id} failed to write:`, err.message || err);
}
}
}
@ -180,8 +187,13 @@ class YarnGame {
async processBotVoting() {
for (const botObj of this.bots) {
try {
const botVote = await botObj.bot.Vote(this.getStoryText(), this.round_data);
this.submitVote(botObj.bot_id, botVote)
this.submitVote(botObj.bot_id, botVote);
} catch (err) {
// One bot failing to vote is not critical; keep going
console.warn(`Bot ${botObj.bot_id} failed to vote:`, err.message || err);
}
}
}
@ -257,15 +269,26 @@ class YarnGame {
});
}
this.roundCount++; // increment round counter
return leaders.length === 1 ? leaders[0] : null; // return single winner or null on tie
}
checkGameOver() {
const winner = this.players.find(p => p.score >= this.gameSettings.scoreLimit);
if (winner) {
this.currentPhase = 'gameOver';
this.inProgress = false;
return winner;
// score limit win
if (this.gameSettings.scoreLimit) {
const scoreWinner = this.players.find(p => p.score >= this.gameSettings.scoreLimit);
if (scoreWinner) return scoreWinner;
}
// round limit win
if (this.roundCount >= this.gameSettings.roundLimit && this.gameSettings.roundLimit != 0) {
return this.players.reduce(
(best, p) => (p.score > best.score ? p : best),
this.players[0]
);
}
// if we're one before the round limit, append to the story
if (this.roundCount == this.gameSettings.roundLimit-1) {
this.yarnStory.push({ player: "Narrator", str: "The moral of this story: " });
}
return null;
}
@ -345,6 +368,7 @@ class YarnGame {
})),
yarnStory: this.yarnStory,
currentPhase: this.currentPhase,
currentRound: this.roundCount+1,
timeRemaining: this.timeRemaining,
round_data: this.currentPhase === 'voting' ? this.round_data.map((e, i) => ({
index: i,