Skip to main content

Bounty Board (Daily)

Bounty Board (Daily)

Status: SHIPPED (E5 of the shared Daily framework). The DT theming of the shared Daily framework; the framework owns selection, streak,

Last updated: October 27, 2026

Dark Tower — Bounty Board (Daily)

Status: SHIPPED (E5 of the shared Daily framework). The DT theming of the shared Daily framework; the framework owns selection, streak, reward delivery, the NLU surface, and the regression shape — this doc is only DT's theme.

Parent: index.md. Framework: engine/daily-framework.md. Currency path: economy.md. Counters: combat.md.

Thesis

A returning Dark Tower player always has one small fresh thing to do today: the Bounty Board. It is a single daily bounty drawn from a stable pool, themed to DT and built entirely on counters the game already maintains — no new gameplay telemetry.

The daily (what it IS)

  • Title: "Bounty Board" (the stable, hermetic-assertable themed label).
  • Selection: SHARED, date-seeded (DailySelector.pickForDate) — everyone gets the same bounty today, so the per-day standing is comparable. Resets at the UTC date boundary; no cron, no stored cursor (the framework's deterministic-rotation model).
  • Objective pool (stable order):
    Key Spoken objective Tracker Target Mode
    DT_BOUNTY_KILLS_TEN defeat ten enemies in combat enemyKills 10 DELTA_SINCE_DAY_START
    DT_BOUNTY_CLUES_THREE discover three clues in your travels cluesDiscovered 3 DELTA_SINCE_DAY_START
    DT_BOUNTY_ENCOUNTER win a combat encounter enemyKills 1 DELTA_SINCE_DAY_START

Where a returning player hears it

On the first launch of each UTC day, a returning player hears today's bounty as one line right after the welcome: "Today's bounty: defeat ten enemies in combat, for 200 gold." A later launch the same day does not repeat it. The line is , read from the pool and the completion reward above, and the once-a-day marker is (a daily marker in the player's timeouts). The marker and the bounty pick read one clock's one UTC day, so the line turns over when the board does. On a launch that offers the recap, the line sits between the welcome back and the recap question. A player still naming a hero does not hear it.

Objectives reuse existing trackers (no new counter)

Every bounty reads an EXISTING lifetime counter on as a DELTA_SINCE_DAY_START (the framework snapshots the lifetime value when the day's bounty is first viewed, then progress = current − snapshot):

  • Enemies defeated — sum of every per-type count in enemyKills (incremented by DarkTowerStatsUtility on each kill; the same total reports).
  • Clues discovered — the size of the cluesDiscovered set (added by on discovery).

"Win a combat encounter" is the lightweight bounty — a kill target of one off the same kill counter, the "complete an encounter" objective from the framework's DT row.

Reward model

  • Completion: GOLD (soft) — base 200, +25 per consecutive-day streak (capped at the framework's 7-day bonus cap, so a 7-day streak pays 350). Delivered through (the DT soft-currency branch in , with DARK_TOWER in SOFT_WIRED_GAMES). Soft gold intentionally skips the premium audit ledger (economy.md § soft-currency carve-out); it is double-money-weekend and money-cap aware like every other DT gold reward.
  • Streak milestone: earned SPECIAL TOKENS (premium) — a flat 5 special tokens on every 7th consecutive completed day (getStreakMilestoneInterval() == 7). Delivered ONLY through with source PremiumCurrencySource.DAILY_CHALLENGE, which writes the mandatory game_log.purchase_transactions audit row in the same call. The milestone is an EARNED faucet, so it pays the DARK_TOWER_TOKEN currency (ledger key dark_tower_tokens), NOT purchase-only Diamonds (epic 24205, 2026-07-13 — no free faucet may credit Diamonds).
  • Boot-time wiring assertion: (@PostConstruct) validates BOTH the completion gold and the milestone special tokens are deliverable, so a half-wired DT daily cannot ship.

NLU surface

Inherits the framework's always-available Tier-5 BASELINE_DAILY* commands (daily, claim daily, daily challenge streak, ...) routed by to this provider in any DARK_TOWER session.

Two DT-specific NLU adjustments were needed:

  • Retired the daily shadow. A legacy tier-4 DARK_TOWER_DAILY_PACKS -> "daily" synonym shadowed the Tier-5 baseline, so in Dark Tower daily reached the daily-packs shop ("nothing to collect right now") instead of the Bounty Board. The row is DELETED. Note the synonym mapper getSynonymsToCompareTo does NOT honor the enabled flag, so a shadowing synonym must be removed, not merely disabled. Bare daily now reaches the Bounty Board; the daily-packs shop stays reachable via daily packs / daily rewards.
  • Added a themed bounty board synonym. A tier-4 DARK_TOWER BASELINE_DAILY -> "bounty board" row lets a player reach the board by its own name. bounty alone stays mapped to MESSAGE_BOARD_BOUNTY (the separate message-board feature).

Guarded by scenario_tests 2174 (daily reaches the Bounty Board) and 2175 (bounty board reaches it).

Code

Component Path
Provider engines/handlers/darktower/daily/.java
Soft gold branch engines/handlers/common/daily/.deliverSoft (DARK_TOWER)
Reward JUnit test/.../darktower/daily/DarkTowerDailyProviderTest.java