← Back
Play

Task Master Relay

A task-sequencing game where players arrange construction tasks in the correct order under time pressure. Covers three topics (Residential, Commercial, Renovation) across four difficulty tiers. Features change orders that mid-run reorder the sequence, a streak chain bonus system, and a unified 12-level progression with cumulative scoring.

Game Flow

Menu → Level Selection → Job Intro → Countdown → Playing → [Change Order] → Job Activated → ... → Game Over → Results
  • Menu: Hero screen with game description, how-to-play instructions, and a Play button
  • Level Selection: 12 levels grouped by difficulty (Easy/Medium/Hard/Expert), 3 topics per group. Shows stars, best score, best time, and cumulative total
  • Job Intro: Shows job card with image, title, description, and tile count. First job triggers countdown; subsequent jobs resume the timer
  • Countdown: 3-2-1-GO via shared Countdown component
  • Playing: Tiles are shuffled in a bank. Drag or tap tiles into sequence slots to arrange them in correct order. Timer runs continuously across all 3 jobs. A "Review Change Order" button appears after a change order for the current job has been acknowledged
  • Change Order: Mid-job interruption — a change order modal appears when 50% of slots are filled. Affected tiles return to the bank and the correct order changes
  • Job Activated: Brief celebration animation (checkmark + "JOB X ACTIVATED") between jobs
  • Game Over: After all 3 jobs, timer stops
  • Results: Score breakdown with time score, perfect bonus, chain bonus, per-job breakdown with chain multipliers, star rating, grade, accuracy, and navigation to next level

Unlock Logic

  • Level 1 always unlocked
  • Completing any level unlocks the next (linear progression across topics)
  • Stars: 3 stars (under par, zero penalties), 2 stars (under 1.5x par), 1 star (completed)

Topics & Content

Unified Level Map

LevelDifficultyTopicTitlePool
1EasyResidential ConstructionApprentice Projects8 jobs
2EasyCommercial ConstructionTenant Basics6 jobs
3EasyRenovation & RemodelQuick Upgrades6 jobs
4MediumResidential ConstructionJourneyman Projects8 jobs
5MediumCommercial ConstructionFit-Out Projects6 jobs
6MediumRenovation & RemodelRoom Makeovers6 jobs
7HardResidential ConstructionMaster Builder Projects8 jobs
8HardCommercial ConstructionFull Buildout6 jobs
9HardRenovation & RemodelMajor Renovations6 jobs
10ExpertResidential ConstructionExpert Projects6 jobs
11ExpertCommercial ConstructionExpert Buildouts6 jobs
12ExpertRenovation & RemodelExpert Renovations6 jobs

Each run selects 3 jobs randomly from the level's pool and shuffles their order.

Content Structure

Level (globalId, topicId, topicName, level config)
└─ Job (id, title, description, imageUrl)
   ├─ Tiles[] (id, title, description, tradeIcon, imageUrl)
   ├─ correctOrder[] (tile IDs in sequence)
   └─ changeOrder? (description, affectedTileIds, newCorrectOrder)

Topics

TopicSlugColorDescription
Residential Constructionresidential-constructionAmberFraming, electrical, plumbing, roofing, HVAC for houses
Commercial Constructioncommercial-constructionBlueOffice buildouts, retail spaces, fire systems, elevators
Renovation & Remodelrenovation-remodelGreenBathroom remodels, kitchen renovations, basement finishing

Content stays at the "junior project coordinator" level — sequencing tasks across trades, not deep technical knowledge.

Difficulty Scaling

SettingEasyMediumHardExpert
Tiles per job57911
Par time (sec)90150240360
Jobs per run3333
Change order coverage~60-70% of jobs~60-70%~60-70%~67%

Scoring

Config (single source of truth)

All values are centralized in config.ts:

JOBS_PER_LEVEL = 3
PENALTY_SECONDS = 8          // seconds added to timer per wrong activation
MAX_SCORE = 10000
TIME_PENALTY_FACTOR = 10     // -10 pts per second elapsed
PENALTY_SCORE_DEDUCTION = 350 // -350 pts per wrong activation
ACCURACY_BONUS = 500          // +500 if zero penalties
CHANGE_ORDER_TRIGGER_PERCENT = 0.5
CHAIN_MULTIPLIERS = [1.0, 1.25, 1.5]

Formula

baseScore = max(0, 10000 - elapsedSeconds × 10) - penaltyCount × 350 + (penaltyCount === 0 ? 500 : 0)
chainBonus = baseScore × (chainMultiplier - 1)
finalScore = max(0, baseScore + chainBonus)
FactorValue
Max score10,000 (before chain bonus)
Time penalty-10 per second elapsed
Wrong activation penalty-350 per incorrect activation + 8 seconds added to timer
Accuracy bonus+500 if zero penalties across all 3 jobs

Streak Chain Bonus

Consecutive perfect jobs (zero penalties) within a run build a chain. The chain multiplier applies to the base score as a bonus.

ChainMultiplierBonus
0-11.0xNone
21.25x+25% of base score
31.5x+50% of base score

Any penalty resets the chain to 0.

Stars

StarsCondition
3Under par time AND zero penalties
2Under 1.5× par time
1Completed

Accuracy

accuracy = penaltyCount === 0 ? 100 : max(0, 100 - penaltyCount × 20)

Grade Thresholds

Both minimum score AND minimum accuracy must be met:

GradeMin ScoreMin Accuracy
S+8,500100%
S6,500100%
A4,50070%
B2,50040%
C1,0000%
D00%

Results Breakdown

The results screen shows:

  • Time Score: Base score minus perfect bonus component
  • Perfect Bonus: +500 if zero penalties (highlighted)
  • Chain Bonus: Chain multiplier applied to base score (highlighted when > 0)
  • Per-job breakdown: Each job with title, completion time, chain multiplier (if > 1), and penalty time added

Platform Score

Uses the cumulative score model. After each level completion, the sum of best scores across all 12 levels is posted to the platform's score table. Per-level score is preserved in metadata. Leaderboard shows total progression via MAX(score).

TNW_COMPLETE fires once — on the player's first-ever level completion.

Change Orders

Change orders simulate real-world project disruptions. When a player fills 50% of the sequence slots, the game checks if the current job has a change order defined. If so:

  1. Timer pauses
  2. A modal describes the change (e.g., "Inspector requires a separate vent for the shower")
  3. Affected tiles are returned to the bank
  4. The correct order updates to newCorrectOrder
  5. Timer resumes — player must re-sequence with the new constraints

After acknowledging a change order, a "Change Order" button (with a document icon) appears in the playfield, allowing the player to review the change order details at any time during that job.

Not every job has a change order (~60-70% do). Since jobs are randomly selected and shuffled, change order timing is unpredictable across runs.

Technical Architecture

Key Files

AreaFilePurpose
Typesgames/task-master-relay/types.tsGamePhase, TaskTile, JobCard, ChangeOrder, JobResult, RunState, LevelConfig, TopicConfig, TopicData, GlobalLevel, LevelProgress
Configgames/task-master-relay/config.tsScoring constants, difficulty configs, chain multipliers, par times, calculateFinalScore(), calculateChainBonus(), calculateAccuracy(), calculateStars(), getChainMultiplier()
Storegames/task-master-relay/store.tsZustand store: tile placement, slot management, timer, penalties, chain tracking, change order state machine, tap selection
Content APIgames/task-master-relay/content.tsgetGlobalLevel(), getAllGlobalLevels(), selectRandomJobs(), TOTAL_LEVELS
Content Indexgames/task-master-relay/content/index.tsALL_LEVELS array, ALL_TILE_PROMPTS, ALL_JOB_PROMPTS (image generation)
Topicsgames/task-master-relay/content/topics.tsTopic configs (id, name, description, icon, color, tradeName)
Levelsgames/task-master-relay/content/levels/12 individual level files (level-01.ts through level-12.ts) with job definitions, tile data, change orders
Helpersgames/task-master-relay/content/helpers.tsimg(), shared(), jobImg() — image path helpers
Shared Imagesgames/task-master-relay/content/shared-images.tsTILE_STYLE, JOB_STYLE, SHARED_IMAGES — image generation prompts
Formatgames/task-master-relay/format.tsformatElapsedTime() — time display formatting
Utilsgames/task-master-relay/utils.tsshuffleArray()
Barrelgames/task-master-relay/index.tsPublic exports for config, store selectors, content API, and types
Hookgames/task-master-relay/hooks/use-game-actions.tsupdateLevelProgress(), getProgress(), getCumulativeScore() — wraps shared base
Audiogames/task-master-relay/hooks/use-game-audio.tsPhase-aware SFX management

Components

ComponentPurpose
playfield.tsxGame area: header (pause, mute, timer, penalties, chain, job dots), job card, sequence board, tile bank, Reset/Activate buttons, change order review button
sequence-board.tsx"Critical Path" drop zone with numbered slots, drag-and-drop and tap-to-place support, shake animation on wrong tiles
task-tile.tsxIndividual draggable/tappable tile with image (or wrench fallback), title, description, selection highlight
results.tsxScore breakdown using shared ResultsScreen: time score, perfect bonus, chain bonus, per-job breakdown with chain multipliers and penalty times
job-card-intro.tsxJob briefing card with image, title, description, tile count. "Start Run" / "Continue" and optional "Back"
change-order-modal.tsxChange order interruption modal with description and affected tiles. Supports review mode ("Got It" button)
activation-indicator.tsxFull-screen success animation (checkmark + particles + "JOB X ACTIVATED") between jobs
level-list.tsx12-level grid grouped by difficulty, with topic context (icon, color, name), progress stats, cumulative score
how-to-play.tsxThree-step instructions: Build Critical Path, Race the Clock (+8s per penalty), Chain Bonus
topic-button.tsxTopic selection card (legacy, kept for routing compatibility)

Uses shared components: LevelCard, Countdown, PauseMenu, GameError, LoadingScreen, GameShell, GameHeader.

Routing

/task-master-relay/              → Menu (hero + Play button)
/task-master-relay/levels/       → Level selection (12 levels)
/task-master-relay/play/[level]/ → Gameplay (level = 1-12)

Old topic-based routes (/[topic]/, /[topic]/play/[level]/) redirect to /task-master-relay/.

Persistence

Storage key: task-master-relay-state

Save data:

{
  levelProgress: {
    level_1: { bestTimeMs, stars, unlocked, completedAt, attempts, bestScore, bestAccuracy, bestChain },
    level_2: { ... },
    ...
  },
  lastPlayedLevel
}

Score submitted via submitScore(cumulativeScore, metadata). Completion signaled via signalComplete() on first-ever level completion only.

Notable Mechanics

Random Job Selection

Each level has a pool of 6-8 jobs. Each run selects 3 randomly and shuffles the presentation order, so no two runs are identical even on the same level.

Penalty Mechanics

When the player activates an incorrect sequence:

  1. Score deduction: -350 points per wrong activation
  2. Time penalty: +8 seconds added directly to the elapsed timer
  3. Visual feedback: Wrong tiles shake (red shake animation)
  4. Chain reset: Streak chain resets to 0

Both the score deduction and time addition compound — the 8 seconds also reduces the time-based score component.

Change Order State Machine

Per-job tracking with changeOrderTriggered and changeOrderAcknowledged booleans. Each job independently manages its own change order state. The trigger fires when filledSlots / totalSlots >= 0.5 and the current job defines a changeOrder. After acknowledgement, a review button allows re-reading the change order during gameplay.

Tile Interaction Modes

Supports both drag-and-drop and tap-to-place:

  • Drag: Drag tile from bank to slot, or between slots
  • Tap: Tap tile in bank to select, then tap slot to place. Tap two slots to swap.
  • Displacement: Dropping a tile on an occupied slot returns the displaced tile to the bank

Chain Indicator

During gameplay, a chain counter appears when the streak is active. Shows the current chain multiplier (e.g., "×1.25") with a flame icon near the job progress dots.

Cumulative Score Display

The level selection screen shows both per-level stats (stars, best score, best time, accuracy, best chain) and a cumulative total across all completed levels, displayed with a trophy icon in the header.