Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions Games/Relay_Rift/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Relay Rift

**Relay Rift** is a production-grade signal-routing puzzle game built for [GameZone](https://github.com/kunjgit/GameZone). Players rotate conductive wire tiles to route power from a source node through the grid to every receiver โ€” before the move budget runs out.

## โœจ Features

- **30 hand-crafted levels** โ€” grids grow from 3ร—3 to 7ร—7 with 1โ€“6 receivers per level
- **Mathematically verified solvable** โ€” every puzzle is built from a proven solution path
- **Varied path shapes** โ€” L, U, zigzag, snake, spiral, W, staircase, diagonal wave, and more
- **Progressive difficulty** โ€” budgets tighten and grid complexity increases level-by-level
- **Smart Hint system** โ€” highlights the next tile and tells you exactly how many rotations it needs
- **"How to Play" tutorial** โ€” 5-step illustrated modal on first visit, reopenable via `?`
- **Full keyboard support** โ€” Arrow keys to navigate, Space/Enter to rotate, `H` hint, `R` reset
- **Score system** โ€” bonus points for efficiency, persistent best score via `localStorage`
- **Particle explosion** on level completion
- **No build step** โ€” pure HTML, CSS, and vanilla JavaScript

## ๐ŸŽฎ How to Play

1. **Click** (or press `Space`) a tile to rotate it 90ยฐ clockwise
2. Connect wires so signal flows from the **cyan source** node through the grid
3. Light up every **red receiver** before using all your moves
4. Press **`H`** for a hint or **`R`** to reset the level

### Keyboard Shortcuts

| Key | Action |
|-----|--------|
| `Click` / `Space` | Rotate focused tile |
| `Arrow keys` | Navigate between tiles |
| `H` | Show hint |
| `R` | Reset level |
| `?` | Re-open tutorial |

## ๐Ÿ—‚๏ธ File Structure

```
Games/Relay_Rift/
โ”œโ”€โ”€ index.html โ€” game layout, HUD, win overlay, how-to-play modal
โ”œโ”€โ”€ style.css โ€” cyberpunk dark theme, responsive grid, tile animations
โ””โ”€โ”€ script.js โ€” 30 levels, BFS power propagation, hint engine, tutorial
```

## ๐Ÿ”ง Technical Notes

- **BFS power routing** โ€” signal propagates from source via connected wire ports each click
- **Tile encoding** โ€” `L`=straight, `C`=corner, `T`=tee, `X`=cross, `S`=source, `R`=receiver; digit = rotation (0โ€“3)
- **Verified solvability** โ€” each level's solution path is traced manually; path tiles are scrambled exactly 1 step back, guaranteeing a minimum-click solution exists
- **Google Fonts** โ€” Orbitron (display) + DM Mono (body)
- **Responsive** โ€” adapts from 320px mobile to 1240px desktop

## ๐Ÿš€ Running Locally

Open `Games/Relay_Rift/index.html` directly in any modern browser, or serve the repository root:

```bash
python -m http.server 3000
# then open http://localhost:3000/Games/Relay_Rift/
```
221 changes: 221 additions & 0 deletions Games/Relay_Rift/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Relay Rift โ€” rotate conductive tiles to route the signal from the generator to every receiver. 30 levels, vanilla HTML/CSS/JS.">
<title>Relay Rift ยท Signal Routing Puzzle</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=DM+Mono:ital,wght@0,400;0,500;1,400&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>

<!-- โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
HOW TO PLAY MODAL
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• -->
<div id="tutorialOverlay" class="tutorial-overlay" hidden>
<div class="tutorial-card">

<!-- Step 1 -->
<div class="tut-step active" data-step="1">
<div class="tut-icon">โšก</div>
<h2 class="tut-title">Welcome to<br><span>Relay Rift</span></h2>
<p class="tut-body">A signal-routing puzzle game. Route electricity from the <strong>source</strong> through wire tiles to light up every <strong>receiver</strong>.</p>
<div class="tut-visual tut-grid-demo">
<div class="demo-tile source-tile"><div class="demo-wire demo-cross"></div><div class="demo-node src"></div></div>
<div class="demo-arrow">โšก</div>
<div class="demo-tile"><div class="demo-wire demo-horiz"></div><div class="demo-node"></div></div>
<div class="demo-arrow">โ†’</div>
<div class="demo-tile rx-tile"><div class="demo-wire demo-cross"></div><div class="demo-node rx"></div></div>
</div>
<p class="tut-caption">Cyan glowing tiles = powered &nbsp;ยท&nbsp; Red tiles = offline receivers</p>
</div>

<!-- Step 2 -->
<div class="tut-step" data-step="2">
<div class="tut-icon">๐Ÿ”„</div>
<h2 class="tut-title">Rotate Tiles</h2>
<p class="tut-body"><strong>Click</strong> (or tap) any tile to rotate it 90ยฐ clockwise. Line up the wire arms so the signal can flow through.</p>
<div class="tut-visual tut-rotate-demo">
<div class="rotate-seq">
<div class="demo-tile dim"><div class="demo-wire demo-vert"></div><div class="demo-node"></div></div>
<div class="rot-arrow">โ†’ click โ†’</div>
<div class="demo-tile lit"><div class="demo-wire demo-horiz"></div><div class="demo-node powered-node"></div></div>
</div>
<p class="tut-caption-sm">Same tile, different rotation โ€” now the signal flows east/west instead of north/south.</p>
</div>
<p class="tut-body">Use <kbd>Arrow keys</kbd> to navigate and <kbd>Space</kbd> to rotate. Press <kbd>H</kbd> for a hint, <kbd>R</kbd> to reset.</p>
</div>

<!-- Step 3 -->
<div class="tut-step" data-step="3">
<div class="tut-icon">๐Ÿ”ง</div>
<h2 class="tut-title">Tile Types</h2>
<p class="tut-body">Four wire shapes โ€” each connects different directions:</p>
<div class="tut-tile-grid">
<div class="tile-type-row">
<div class="demo-tile sm"><div class="demo-wire demo-vert"></div><div class="demo-node"></div></div>
<div class="tile-type-info"><strong>Straight</strong><br>North โ†” South (or East โ†” West)</div>
</div>
<div class="tile-type-row">
<div class="demo-tile sm"><div class="demo-wire demo-corner-ne"></div><div class="demo-node"></div></div>
<div class="tile-type-info"><strong>Corner</strong><br>Turns 90ยฐ โ€” two adjacent sides</div>
</div>
<div class="tile-type-row">
<div class="demo-tile sm"><div class="demo-wire demo-tee"></div><div class="demo-node"></div></div>
<div class="tile-type-info"><strong>T-Junction</strong><br>Splits to three directions</div>
</div>
<div class="tile-type-row">
<div class="demo-tile sm source-tile"><div class="demo-wire demo-cross"></div><div class="demo-node src"></div></div>
<div class="tile-type-info"><strong>Source / Cross</strong><br>Connects all four sides</div>
</div>
</div>
</div>

<!-- Step 4 -->
<div class="tut-step" data-step="4">
<div class="tut-icon">๐Ÿ†</div>
<h2 class="tut-title">Win the Level</h2>
<p class="tut-body">Power <strong>every receiver</strong> before using up your move budget. The fewer rotations you use, the higher your score bonus!</p>
<div class="tut-visual win-demo">
<div class="win-demo-row">
<div class="pill offline-pill">โ— RX-01 OFFLINE</div>
<div class="pill offline-pill">โ— RX-02 OFFLINE</div>
</div>
<div class="win-arrow">โ†“ solve the grid โ†“</div>
<div class="win-demo-row">
<div class="pill online-pill">โ— RX-01 ONLINE</div>
<div class="pill online-pill">โ— RX-02 ONLINE</div>
</div>
</div>
<p class="tut-body">30 levels โ€” grids grow from <strong>3ร—3</strong> all the way to <strong>7ร—7</strong> with up to 6 receivers!</p>
</div>

<!-- Step 5 -->
<div class="tut-step" data-step="5">
<div class="tut-icon">๐ŸŽฎ</div>
<h2 class="tut-title">You're Ready!</h2>
<p class="tut-body">Quick tips before you start:</p>
<ul class="tut-tips">
<li>๐Ÿ” Press <kbd>H</kbd> or click <strong>Hint</strong> โ€” it highlights the next tile AND tells you how many rotations it needs.</li>
<li>โ†ฉ Press <kbd>R</kbd> or click <strong>Reset</strong> to restore the original arrangement.</li>
<li>โŒจ๏ธ Use <kbd>Arrow keys</kbd> + <kbd>Space</kbd> for full keyboard play.</li>
<li>๐Ÿ’พ Your best score is saved automatically.</li>
</ul>
<button type="button" id="startGameBtn" class="tut-start-btn">Start Playing โ†’</button>
</div>

<!-- Navigation -->
<div class="tut-nav">
<div class="tut-dots" id="tutDots"></div>
<div class="tut-nav-btns">
<button type="button" id="tutPrev" class="tut-btn">โ† Back</button>
<button type="button" id="tutNext" class="tut-btn primary">Next โ†’</button>
</div>
</div>

<button type="button" id="tutSkip" class="tut-skip">Skip tutorial</button>
</div>
</div>

<!-- โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
WIN OVERLAY
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• -->
<div id="winOverlay" class="win-overlay" hidden aria-live="assertive">
<canvas id="particleCanvas" class="particle-canvas"></canvas>
<div class="win-card">
<p class="win-kicker">Grid Stabilized</p>
<h2 class="win-title">Signal Locked</h2>
<p class="win-score" id="winScoreText">+0 pts</p>
<div class="win-actions">
<button type="button" id="winNextBtn">Next Level</button>
<button type="button" id="winRetryBtn">Replay</button>
</div>
</div>
</div>

<!-- Toast -->
<div id="toast" class="toast" hidden role="status" aria-live="polite"></div>

<main class="shell">
<!-- Header -->
<header class="topbar">
<a href="../../index.html" class="back-link" aria-label="Back to GameZone">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
GameZone
</a>
<div class="topbar-brand">
<span class="brand-kicker">Signal Routing Puzzle</span>
<span class="brand-name">RELAY RIFT</span>
</div>
<button type="button" id="helpBtn" class="help-btn" title="How to play">?</button>
</header>

<!-- HUD -->
<div class="hud" aria-label="Game status">
<div class="hud-cell">
<span class="hud-label">Level</span>
<strong class="hud-value" id="levelLabel">1</strong>
</div>
<div class="hud-cell">
<span class="hud-label">Progress</span>
<strong class="hud-value dim" id="progressLabel">1 / 30</strong>
</div>
<div class="hud-cell">
<span class="hud-label">Moves</span>
<strong class="hud-value" id="movesLabel">0 / 0</strong>
</div>
<div class="hud-cell">
<span class="hud-label">Score</span>
<strong class="hud-value accent" id="scoreLabel">0</strong>
</div>
<div class="hud-cell">
<span class="hud-label">Best</span>
<strong class="hud-value dim" id="bestLabel">0</strong>
</div>
</div>

<!-- Game area -->
<div class="game-area">
<section class="board-panel" aria-labelledby="boardHeading">
<h1 id="boardHeading" class="sr-only">Relay grid</h1>
<div id="board" class="board" role="grid" aria-label="Relay puzzle grid"></div>
<p id="message" class="message" role="status" aria-live="polite"></p>
</section>

<aside class="console" aria-label="Game console">
<div class="console-section">
<p class="console-label">Objective</p>
<p id="objectiveText" class="console-body">Power all receivers.</p>
</div>
<div class="console-section">
<p class="console-label">Receivers</p>
<div id="receiverList" class="receiver-list" aria-label="Receiver status"></div>
</div>
<div class="console-section">
<p class="console-label">Controls</p>
<div class="btn-grid">
<button type="button" id="hintButton" title="Hint (H)">Hint</button>
<button type="button" id="resetButton" title="Reset (R)">Reset</button>
<button type="button" id="nextButton" title="Next level" disabled>Next โ†’</button>
</div>
</div>
<div class="console-section keys-section">
<p class="console-label">Keyboard</p>
<div class="key-legend">
<span><kbd>Click</kbd> / <kbd>Space</kbd> rotate tile</span>
<span><kbd>Arrows</kbd> navigate</span>
<span><kbd>H</kbd> hint &nbsp; <kbd>R</kbd> reset</span>
</div>
</div>
</aside>
</div>
</main>

<script src="script.js"></script>
</body>
</html>
Loading
Loading