new: usr: add rules page #4
This commit is contained in:
@@ -33,3 +33,11 @@ main div.txt a {
|
|||||||
|
|
||||||
&:hover { color: #c5e8ff; }
|
&:hover { color: #c5e8ff; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main div.txt img {
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main div.txt .img-container {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|||||||
BIN
public/images/privileges/battle.png
Normal file
BIN
public/images/privileges/battle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
BIN
public/images/privileges/history.png
Normal file
BIN
public/images/privileges/history.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
public/images/privileges/security.png
Normal file
BIN
public/images/privileges/security.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
public/images/privileges/shared-battle.png
Normal file
BIN
public/images/privileges/shared-battle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
public/images/privileges/stat.png
Normal file
BIN
public/images/privileges/stat.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@@ -111,6 +111,12 @@ class GameController extends AbstractController
|
|||||||
return $this->render('Official/landing.html.twig');
|
return $this->render('Official/landing.html.twig');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route('/rules', name: 'MineSeekerBundle_rules')]
|
||||||
|
public function rules(): Response
|
||||||
|
{
|
||||||
|
return $this->render('Official/rules.html.twig');
|
||||||
|
}
|
||||||
|
|
||||||
public function sendMail(MailerInterface $mailer, ContactMessage $contactMessage): void
|
public function sendMail(MailerInterface $mailer, ContactMessage $contactMessage): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -254,6 +254,7 @@
|
|||||||
<p class="footer-nav-label">Navigate</p>
|
<p class="footer-nav-label">Navigate</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{{ path('MineSeekerBundle_homepage') }}">Homepage</a></li>
|
<li><a href="{{ path('MineSeekerBundle_homepage') }}">Homepage</a></li>
|
||||||
|
<li><a href="{{ path('MineSeekerBundle_rules') }}">Game Rules</a></li>
|
||||||
<li><a href="{{ path('MineSeekerBundle_terms') }}">Terms of Use</a></li>
|
<li><a href="{{ path('MineSeekerBundle_terms') }}">Terms of Use</a></li>
|
||||||
<li><a href="{{ path('MineSeekerBundle_privacy') }}">Privacy Policy</a></li>
|
<li><a href="{{ path('MineSeekerBundle_privacy') }}">Privacy Policy</a></li>
|
||||||
<li><a href="{{ path('MineSeekerBundle_contact') }}">Contact</a></li>
|
<li><a href="{{ path('MineSeekerBundle_contact') }}">Contact</a></li>
|
||||||
|
|||||||
144
templates/Official/rules.html.twig
Normal file
144
templates/Official/rules.html.twig
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
{% extends 'Game/index.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %} - Game Rules{% endblock %}
|
||||||
|
|
||||||
|
{% block metas %}
|
||||||
|
{%- set _ogImage = 'https://' ~ app.request.host ~ asset('/images/mine-1600x627.png') -%}
|
||||||
|
<meta property="og:url" content="{{ url('MineSeekerBundle_rules') | replace({'http://': 'https://'}) }}"/>
|
||||||
|
<meta property="og:type" content="website"/>
|
||||||
|
<meta property="og:site_name" content="MineSeeker"/>
|
||||||
|
<meta property="og:title" content="Game Rules · MineSeeker"/>
|
||||||
|
<meta property="og:description" content="Learn how to play MineSeeker and discover what you unlock by creating a free account."/>
|
||||||
|
<meta property="og:image" content="{{ _ogImage }}"/>
|
||||||
|
<meta property="og:image:width" content="1600"/>
|
||||||
|
<meta property="og:image:height" content="627"/>
|
||||||
|
<meta name="twitter:card" content="summary_large_image"/>
|
||||||
|
<meta name="twitter:title" content="Game Rules · MineSeeker"/>
|
||||||
|
<meta name="twitter:description" content="Learn how to play MineSeeker and discover what you unlock by creating a free account."/>
|
||||||
|
<meta name="twitter:image" content="{{ _ogImage }}"/>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div class="txt">
|
||||||
|
<h2>MineSeeker Game Rules</h2>
|
||||||
|
|
||||||
|
<p>MineSeeker is a real-time 1v1 twist on the classic minesweeper formula. Two players — <strong>Red</strong> and <strong>Blue</strong> — race over the same hidden minefield, taking turns to <strong>hunt the mines</strong>. Each mine you detonate is claimed in your colour and scores a point. The first player to claim the majority of the mines wins.</p>
|
||||||
|
|
||||||
|
<h3>1. The Board</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>The playing field is a <strong>16×16 grid</strong> of covered cells.</li>
|
||||||
|
<li><strong>51 mines</strong> are hidden randomly across the board at the start of each match.</li>
|
||||||
|
<li>Every non-mine cell displays a number indicating how many of its eight neighbours contain a mine — these numbers are your clues. Cells with no adjacent mines are empty.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>2. Turn Order</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Players alternate turns. On your turn the status bar reads <em>“It is your turn! Make a move”</em>; while you wait it reads <em>“Your buddy is making a move”</em>.</li>
|
||||||
|
<li>On your turn you must perform exactly one action: reveal a cell, flag/unflag a cell, or deploy your bomb.</li>
|
||||||
|
<li><strong>If you hit a mine, you keep your turn</strong> and may click again. Your turn only ends when you reveal a safe cell (or use your bomb).</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>3. Revealing Cells</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><strong>Left-click</strong> a covered cell to reveal it.</li>
|
||||||
|
<li>Revealing a <strong>numbered cell</strong> just uncovers the clue — no points are awarded — and your turn ends.</li>
|
||||||
|
<li>Revealing an <strong>empty cell</strong> triggers a <strong>flood-fill</strong> that opens all connected empty cells and their numbered borders in a single move. Flood-fill will never step onto a mine, so empty-area sweeps are always safe.</li>
|
||||||
|
<li><strong>Right-click</strong> a covered cell to place a flag where you suspect a mine. Flagged cells cannot be revealed until unflagged.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>4. Claiming Mines & Scoring</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Clicking a mine is the <strong>goal</strong> of the game, not a failure. The mine is marked with your colour’s flag and scores <strong>one point</strong> for you.</li>
|
||||||
|
<li>You keep the turn and may click again — rack up a streak while you’re hot.</li>
|
||||||
|
<li>Your turn only ends when you finally reveal a safe cell (or deploy your bomb).</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>5. The Bomb</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Each player carries <strong>one bomb</strong> per match.</li>
|
||||||
|
<li>Detonating your bomb clears a <strong>5×5 blast radius</strong> (25 cells) around the target. <strong>Every mine inside the radius is claimed for your colour and adds to your score.</strong> Numbered cells in the radius are also revealed.</li>
|
||||||
|
<li>The bomb consumes your turn and can only be used once. Save it for a dense patch of suspected mines to burst ahead on the scoreboard.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>6. Winning the Match</h3>
|
||||||
|
|
||||||
|
<p>A match ends in one of three ways:</p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Majority reached</strong> — the first player to claim more than half of the mines (26 of 51) wins immediately.</li>
|
||||||
|
<li><strong>A player resigns</strong> — the remaining player wins.</li>
|
||||||
|
<li><strong>Draw</strong> — if neither player reaches the majority and scores end up equal, the match is recorded as a draw.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>7. Playing as a Guest</h3>
|
||||||
|
|
||||||
|
<p>No account is required to play. Just open the game, share the match link with a friend, and play. Guest matches are not saved to a history and carry no stats.</p>
|
||||||
|
|
||||||
|
<h2 style="margin-top: 40px;">Registered User Privileges</h2>
|
||||||
|
|
||||||
|
<p>Creating a free account unlocks everything the guest experience leaves behind. Registration takes under a minute and your email is only used for account recovery.</p>
|
||||||
|
|
||||||
|
<h3>1. Persistent Game History</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Every match you play is recorded with timestamps, the full move list, the final grid, and your opponent’s name.</li>
|
||||||
|
<li>Replay past battles cell-by-cell and share them with a public UUID link so friends can watch your finest detonations.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="img-container">
|
||||||
|
<img style="margin-top: 15px;" src="{{ asset('images/privileges/history.png') }}" alt="Recent Game History" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>2. Player Statistics</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Total games, wins, losses, and draws.</li>
|
||||||
|
<li>Win rate percentage, average score, personal best score, and total mines hit.</li>
|
||||||
|
<li>A 6-month trend dashboard charting wins, losses, and draws per month.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="img-container">
|
||||||
|
<img style="margin-top: 15px;" src="{{ asset('images/privileges/stat.png') }}" alt="Statistics" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>3. Profile & Identity</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Upload a custom <strong>avatar</strong> that appears next to your username on the board and in the shared battles.</li>
|
||||||
|
<li>Your username is reserved — no one else can take it.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>4. Account Security</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><strong>Two-factor authentication (TOTP):</strong> Protect your account with an authenticator app and a set of one-time backup codes.</li>
|
||||||
|
<li><strong>WebAuthn passkeys:</strong> Register one or more hardware/biometric security keys for passwordless sign-in.</li>
|
||||||
|
<li>A dedicated <strong>Security</strong> dashboard to manage backup codes, review registered credentials, and rotate them at any time.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="img-container">
|
||||||
|
<img style="margin-top: 15px;" src="{{ asset('images/privileges/security.png') }}" alt="Security Dashboard" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>5. Shareable Battle Pages</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Each recorded match gets a public page with both players’ names, avatars, final scores, the outcome, and a compact summary of how it played out.</li>
|
||||||
|
<li>Perfect for proving that impossible last-turn comeback.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="img-container">
|
||||||
|
<img style="margin-top: 15px;" src="{{ asset('images/privileges/battle.png') }}" alt="Shareable Battle Pages" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="img-container">
|
||||||
|
<img style="margin-top: 15px;" src="{{ asset('images/privileges/shared-battle.png') }}" alt="Shared Battle Page" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p style="margin-top: 32px;">Ready to level up? <a href="{{ path('MineSeekerBundle_register') }}">Create your free account</a> or <a href="{{ path('MineSeekerBundle_gamePlay') }}">jump straight into a match</a>.</p>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user