Adds name changing feature. Tweaks timing rules.
This commit is contained in:
parent
f1e9470710
commit
2f5cdbfaa7
|
|
@ -332,7 +332,9 @@
|
||||||
<div id="layout">
|
<div id="layout">
|
||||||
|
|
||||||
<div id="header">
|
<div id="header">
|
||||||
Y.A.R.N. HTML5 - Spin a Story! - <span id="room-display"></span>
|
<img src="../images/yarnlogo.png" /> <span id="room-display"></span>
|
||||||
|
<button id="change-name-btn" style="margin-left:auto;margin-right:1rem;font-size:.9rem;padding:.3rem .6rem;">Change Name</button>
|
||||||
|
<button id="leave-game-btn" style="margin-right:1rem;font-size:.9rem;padding:.3rem .6rem;">Leave Game</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="main-text">
|
<div id="main-text">
|
||||||
|
|
@ -789,6 +791,21 @@
|
||||||
updateGameBar();
|
updateGameBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === Header Functions ===
|
||||||
|
|
||||||
|
document.getElementById('change-name-btn').addEventListener('click', () => {
|
||||||
|
const newName = prompt('Enter a new name (1-20 characters):', playerName);
|
||||||
|
if (newName && newName.trim() && newName.trim() !== playerName) {
|
||||||
|
socket.emit('setName', { name: newName.trim() });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('leave-game-btn').addEventListener('click', () => {
|
||||||
|
if (confirm('Are you sure you want to leave the game?')) {
|
||||||
|
window.location.href = '/';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// === Chat Functions ===
|
// === Chat Functions ===
|
||||||
|
|
||||||
document.getElementById('chat-input').addEventListener('keypress', function(e) {
|
document.getElementById('chat-input').addEventListener('keypress', function(e) {
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
<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. HTML5</title>
|
<title>Y.A.R.N. HTML5</title>
|
||||||
|
|
||||||
|
|
@ -104,8 +104,8 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="splash">
|
<div id="splash">
|
||||||
<h2>Y.A.R.N.</h2>
|
<img src="images/yarnlogo.png" />
|
||||||
<h4>HTML5 Edition</h4>
|
<h4 style="font-style: italic; color:orangered">HTML5 Edition</h4>
|
||||||
|
|
||||||
<!-- ENTER GAME -->
|
<!-- ENTER GAME -->
|
||||||
<div class="section">
|
<div class="section">
|
||||||
|
|
@ -127,14 +127,14 @@
|
||||||
<!-- ABOUT OVERLAY -->
|
<!-- ABOUT OVERLAY -->
|
||||||
<div id="about-overlay" class="hidden">
|
<div id="about-overlay" class="hidden">
|
||||||
<div id="about-box">
|
<div id="about-box">
|
||||||
<h3>What is Y.A.R.N HTML5?</h3>
|
<h3>What is Y.A.R.N. HTML5?</h3>
|
||||||
<p>Y.A.R.N (Yet Another Random Narrative) was a collaborative story-writing "parlor game" originally included in GameSpy Arcade in the early 2000s, but removed shortly thereafter due to security issues that were never resolved.</p>
|
<p>Y.A.R.N. (Yet Another Random Narrative) was a collaborative story-writing "parlor game" originally included in GameSpy Arcade in the early 2000s, but removed shortly thereafter due to security issues that were never resolved.</p>
|
||||||
<p><strong>Y.A.R.N. HTML5</strong> is a modern remake of (what I can remember from) the original, designed to run in-browser, and with extra features such as (optional) LLM-based bots.</p>
|
<p><strong>Y.A.R.N. HTML5</strong> is a modern remake of (what I can remember from) the original, designed to run in-browser, and with extra features such as (optional) LLM-based bots.</p>
|
||||||
<p><strong>The rules are simple:</strong></p>
|
<p style="text-align: left;"><strong>The rules are simple:</strong></p>
|
||||||
<ul>
|
<ul style="text-align: left;">
|
||||||
<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 3 bonus points, and all players receive one point for each vote they received.</li>
|
<li>All players receive one point for each vote their sentence receives. The player whose sentence receives the most votes is awarded 3 bonus points.</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>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>
|
||||||
|
|
|
||||||
23
server.js
23
server.js
|
|
@ -200,8 +200,9 @@ class YarnGame {
|
||||||
async startVotingPhase() {
|
async startVotingPhase() {
|
||||||
this.currentPhase = 'voting';
|
this.currentPhase = 'voting';
|
||||||
this.votedPlayers = new Set();
|
this.votedPlayers = new Set();
|
||||||
this.timeRemaining = 30; // 30 seconds for voting
|
const entriesCount = this.round_data.length
|
||||||
await this.processBotVoting()
|
this.timeRemaining = 10 * entriesCount; // 10 seconds * num of entries for voting
|
||||||
|
this.processBotVoting()
|
||||||
}
|
}
|
||||||
|
|
||||||
submitVote(playerId, entryIndex) {
|
submitVote(playerId, entryIndex) {
|
||||||
|
|
@ -226,10 +227,17 @@ class YarnGame {
|
||||||
tallyVotes() {
|
tallyVotes() {
|
||||||
if (this.round_data.length === 0) return null;
|
if (this.round_data.length === 0) return null;
|
||||||
|
|
||||||
|
// ----- helper to award points, possibly doubled -----
|
||||||
|
const givePoints = (player, pts) => {
|
||||||
|
if (!player) return;
|
||||||
|
const multiplier =
|
||||||
|
this.currentRound + 1 === this.gameSettings.roundLimit ? 2 : 1;
|
||||||
|
player.score += pts * multiplier;
|
||||||
|
};
|
||||||
|
|
||||||
// 1. Award 1 point per vote to every sentence
|
// 1. Award 1 point per vote to every sentence
|
||||||
for (const entry of this.round_data) {
|
for (const entry of this.round_data) {
|
||||||
const p = this.getPlayer(entry.player_id);
|
givePoints(this.getPlayer(entry.player_id), entry.votes.length);
|
||||||
if (p) p.score += entry.votes.length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Find the top vote count
|
// 2. Find the top vote count
|
||||||
|
|
@ -239,9 +247,7 @@ class YarnGame {
|
||||||
// 3. Decide bonus points
|
// 3. Decide bonus points
|
||||||
if (leaders.length === 1) {
|
if (leaders.length === 1) {
|
||||||
// Single winner: +3
|
// Single winner: +3
|
||||||
const winner = leaders[0];
|
givePoints(this.getPlayer(leaders[0].player_id), 3);
|
||||||
const p = this.getPlayer(winner.player_id);
|
|
||||||
if (p) p.score += 3;
|
|
||||||
} else {
|
} else {
|
||||||
// Tie: longest gets +2, rest +1
|
// Tie: longest gets +2, rest +1
|
||||||
const longest = leaders.reduce(
|
const longest = leaders.reduce(
|
||||||
|
|
@ -249,8 +255,7 @@ class YarnGame {
|
||||||
leaders[0]
|
leaders[0]
|
||||||
);
|
);
|
||||||
for (const l of leaders) {
|
for (const l of leaders) {
|
||||||
const p = this.getPlayer(l.player_id);
|
givePoints(this.getPlayer(l.player_id), l === longest ? 2 : 1);
|
||||||
if (p) p.score += l === longest ? 2 : 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue