Updates rules to be closer to original Y.A.R.N
This commit is contained in:
parent
a65607b054
commit
f1e9470710
|
|
@ -477,7 +477,10 @@
|
||||||
hasSubmitted = false;
|
hasSubmitted = false;
|
||||||
hasVoted = false;
|
hasVoted = false;
|
||||||
updateUI();
|
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) => {
|
socket.on('gameOver', (data) => {
|
||||||
|
|
@ -553,9 +556,13 @@
|
||||||
case 'lobby':
|
case 'lobby':
|
||||||
if (isHost) {
|
if (isHost) {
|
||||||
gameBar.innerHTML = `
|
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">
|
<div class="setting-group">
|
||||||
<label>Score Limit:</label>
|
<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>
|
||||||
<div class="setting-group">
|
<div class="setting-group">
|
||||||
<label>Time per Round (sec):</label>
|
<label>Time per Round (sec):</label>
|
||||||
|
|
@ -576,8 +583,6 @@
|
||||||
} else {
|
} else {
|
||||||
gameBar.innerHTML = `
|
gameBar.innerHTML = `
|
||||||
<span class="waiting-message">Waiting for host to start the game...</span>
|
<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;
|
break;
|
||||||
|
|
@ -755,12 +760,14 @@
|
||||||
|
|
||||||
function startGame() {
|
function startGame() {
|
||||||
const scoreLimit = parseInt(document.getElementById('score-limit').value) || 100;
|
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 timeLimit = parseInt(document.getElementById('time-limit').value) || 60;
|
||||||
const botCount = parseInt(document.getElementById('bot-count').value) || 0;
|
const botCount = parseInt(document.getElementById('bot-count').value) || 0;
|
||||||
const startText = document.getElementById('start-text').value;
|
const startText = document.getElementById('start-text').value;
|
||||||
|
|
||||||
socket.emit('startGame', {
|
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)),
|
timeLimit: Math.max(15, Math.min(600, timeLimit)),
|
||||||
botCount: Math.max(0, Math.min(5, botCount)),
|
botCount: Math.max(0, Math.min(5, botCount)),
|
||||||
startText
|
startText
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<meta property="og:title" content="Y.A.R.N HTML5" />
|
<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." />
|
<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 -->
|
<!-- re-use the same CSS-variables and base look -->
|
||||||
<style>
|
<style>
|
||||||
|
|
@ -134,7 +134,8 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li>Players have a limited amount of time to write a sentence, selected by the host at game start.</li>
|
<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>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>
|
<li>When a player reaches the point limit, they win the game.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>Enjoy the story-writing!<br><br>
|
<p>Enjoy the story-writing!<br><br>
|
||||||
|
|
|
||||||
46
server.js
46
server.js
|
|
@ -25,7 +25,8 @@ class YarnGame {
|
||||||
this.inProgress = false;
|
this.inProgress = false;
|
||||||
this.gameHost = null;
|
this.gameHost = null;
|
||||||
this.gameSettings = {
|
this.gameSettings = {
|
||||||
scoreLimit: 50,
|
scoreLimit: 0,
|
||||||
|
roundLimit: 15,
|
||||||
timeLimit: 60,
|
timeLimit: 60,
|
||||||
botCount: 0,
|
botCount: 0,
|
||||||
startText: "It was a dark and stormy night..."
|
startText: "It was a dark and stormy night..."
|
||||||
|
|
@ -36,6 +37,7 @@ class YarnGame {
|
||||||
this.yarnStory = []; // { player: "", str: "" }
|
this.yarnStory = []; // { player: "", str: "" }
|
||||||
this.chat = []; // { id, name, msg }
|
this.chat = []; // { id, name, msg }
|
||||||
this.round_data = []; // { entry_text, player_id, votes: [] }
|
this.round_data = []; // { entry_text, player_id, votes: [] }
|
||||||
|
this.roundCount = 0; // current round
|
||||||
this.currentPhase = 'lobby'; // lobby, writing, voting, gameOver
|
this.currentPhase = 'lobby'; // lobby, writing, voting, gameOver
|
||||||
this.timer = null;
|
this.timer = null;
|
||||||
this.timeRemaining = 0;
|
this.timeRemaining = 0;
|
||||||
|
|
@ -133,6 +135,7 @@ class YarnGame {
|
||||||
|
|
||||||
async startGame(settings) {
|
async startGame(settings) {
|
||||||
this.gameSettings = { ...this.gameSettings, ...settings };
|
this.gameSettings = { ...this.gameSettings, ...settings };
|
||||||
|
this.roundCount = 0;
|
||||||
this.startBots(this.gameSettings.botCount);
|
this.startBots(this.gameSettings.botCount);
|
||||||
this.inProgress = true;
|
this.inProgress = true;
|
||||||
this.yarnStory = [{ player: "Narrator", str: this.gameSettings.startText }];
|
this.yarnStory = [{ player: "Narrator", str: this.gameSettings.startText }];
|
||||||
|
|
@ -142,9 +145,13 @@ class YarnGame {
|
||||||
|
|
||||||
async processBotWriting() {
|
async processBotWriting() {
|
||||||
for (const botObj of this.bots) {
|
for (const botObj of this.bots) {
|
||||||
const botText = await botObj.bot.Write(this.getStoryText());
|
try {
|
||||||
console.log(`Bot text: ${botText}`)
|
const botText = await botObj.bot.Write(this.getStoryText());
|
||||||
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() {
|
async processBotVoting() {
|
||||||
for (const botObj of this.bots) {
|
for (const botObj of this.bots) {
|
||||||
const botVote = await botObj.bot.Vote(this.getStoryText(), this.round_data);
|
try {
|
||||||
this.submitVote(botObj.bot_id, botVote)
|
const botVote = await botObj.bot.Vote(this.getStoryText(), this.round_data);
|
||||||
|
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
|
return leaders.length === 1 ? leaders[0] : null; // return single winner or null on tie
|
||||||
}
|
}
|
||||||
|
|
||||||
checkGameOver() {
|
checkGameOver() {
|
||||||
const winner = this.players.find(p => p.score >= this.gameSettings.scoreLimit);
|
// score limit win
|
||||||
if (winner) {
|
if (this.gameSettings.scoreLimit) {
|
||||||
this.currentPhase = 'gameOver';
|
const scoreWinner = this.players.find(p => p.score >= this.gameSettings.scoreLimit);
|
||||||
this.inProgress = false;
|
if (scoreWinner) return scoreWinner;
|
||||||
return winner;
|
}
|
||||||
|
// 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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -345,6 +368,7 @@ class YarnGame {
|
||||||
})),
|
})),
|
||||||
yarnStory: this.yarnStory,
|
yarnStory: this.yarnStory,
|
||||||
currentPhase: this.currentPhase,
|
currentPhase: this.currentPhase,
|
||||||
|
currentRound: this.roundCount+1,
|
||||||
timeRemaining: this.timeRemaining,
|
timeRemaining: this.timeRemaining,
|
||||||
round_data: this.currentPhase === 'voting' ? this.round_data.map((e, i) => ({
|
round_data: this.currentPhase === 'voting' ? this.round_data.map((e, i) => ({
|
||||||
index: i,
|
index: i,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue