V5 is one open world worn five ways — Urban Crime, Period Drama, Frontier, Monster Hunter, Sci-Fi — and the Mind Palace is the single screen that refuses to let those five cells drift into five disconnected games. It is the detective deduction layer the design calls V5's signature: a graph of evidence orbs collected anywhere in the world, a circular "memory room" the player rotates to manipulate them, deduction threads drawn between clues that genuinely connect, and an accusation system that resolves a case into a branching outcome. Pick up a brass-key clue in a 1947 noir case, examine a faction badge in the Sci-Fi cell, and — if you have earned the Bureau XP to unlock cross-era reasoning — drag the two orbs together and watch a gold thread snap across two hundred years. That cross-cell "aha" is the whole pitch, and it is the one mechanic that makes the anthology feel like a universe instead of a menu.
This is a cross-cell system, not a sixth cell. Every cell's investigation gameplay pushes its clues into the same graph through one interface; the Mind Palace owns the reasoning and the verdict. Crucially, it allows wrong deductions and wrong accusations — there is no game-over for a bad hypothesis — and it proves the right one with a real proof-of-work gate rather than a coin flip. This page is the player-facing tour of how that works, grounded in the committed Unreal C++ behind each verb; the deep data-contract companion (and the in-editor Case Author that authors the cases the Mind Palace solves) is ../architecture/creator-suite-and-mind-palace.md. For the full mode taxonomy and the scope this slots into, start at the hub: ../V5_features.md.
What ships, honestly#
The logic is real, compiled, and tested. The Mind Palace is the
V5MindPalace Unreal module — 36 source files under
V5/ue/Source/V5MindPalace/ with a Public//Private/ split, a .Build.cs,
and a Private/Tests/ automation spec — and the linker has been through it on
this box: libUnrealEditor-V5MindPalace.so sits in V5/ue/Binaries/Linux/,
built by the ueagent user. The architecture is a core state-and-algorithm
object, UV5_MindPalace_Graph (Public/V5MindPalaceGraph.h), wrapped by a
suite of thin UBlueprintFunctionLibrary classes that expose each verb
statically to Blueprint (UV5_MindPalace_AttemptDeduction,
…_BuildHypothesisChain, …_MakeAccusation, …_AddEvidenceNode,
…_CrossEraGate, …_FilterRail, …_View_Volumetric, …_CrossEraCinematic,
…_CloudSync, …_CompanionAppRead, …_Catalog). Four
IMPLEMENT_SIMPLE_AUTOMATION_TEST suites
(Private/Tests/V5MindPalaceTests.cpp) assert specific authored counts and
computed verdicts — a Tier-1 ledger is blocked, a Tier-5 ledger unlocks, an
incomplete chain collapses to the wrong branch — not truthiness.
Authored content is JSON, validated on load. The 110 deduction pairs and 15
accusation outcomes are committed data
(V5/ue/Content/V5MindPalace/Data/deduction_pairs.json,
accusation_outcomes.json), parsed and schema-checked at load behind a
schemaVersion gate, not hard-coded.
Honest fail-loud seams. Mind-Palace cloud-sync builds a real FHttpModule
POST, but its backend is a seam: an unhealthy service yields a 503, a missing
JWT short-circuits to 401 rather than POSTing an unauthenticated diff, and the
live round-trip test is gated on V5_ONLINE_LIVE=1. These refuse to fabricate a
success they did not get.
Art is referenced, not committed. The memory-orb meshes, the rendered
threads and cinematic, and the examinable 3-D evidence the Detective mode counts
are asset paths (FSoftObjectPath) named by the logic here — the UE-art
surface V5 keeps out of git. V5MindPalace computes the room (orb positions,
scales, colors, thread intensities, camera keyframes); the UMG/Niagara rendering
of it is the UI layer.
Evidence enters the room — one push interface, five cells#
Conceptually the Mind Palace is a side-car to all five cells: each cell's
exploration mode supports "examine" on a pick-up clue, and examining pushes a
notebook entry into the shared graph. That push is a single interface.
IV5_Investigation_MindPalacePush declares one method,
EmitEvidenceNodeEvent(FV5InvestigationEvidenceNodeEvent), and the graph
implements it (V5MindPalaceGraph.cpp:21): it translates an in-cell evidence
event — ClueId, SceneId, Tags, EvidenceTitle, EvidenceBody,
bFalseClue — into an FV5MindPalaceEvidenceNode tagged to the MindPalace
cell, then upserts it. That is how a clue examined in any cell becomes an orb in
the room.
The node type is the design's V5_Evidence_Node (Public/V5MindPalaceTypes.h):
a NodeId, CaseId, source id, source Cell, LocationId, a
TimestampInFiction string, a Tags array, a Description, a soft Image
path, the ExaminedDetails the player has uncovered, and a bFalseLead flag
for diegetic red herrings. AddEvidenceNode (V5MindPalaceGraph.cpp:38) is the
gate into the graph and it is not a blind append: it rejects a node with an
empty NodeId, CaseId, or Description, and when a node id already exists it
upserts — refreshing the metadata and merging new tags and examined
details onto the existing orb rather than duplicating it. So re-examining a clue
deepens it; it never clones it.
The deduction mechanic — authored-first, weak fallback, cross-era gate#
AttemptDeduction(NodeA, NodeB, BureauLedger) (V5MindPalaceGraph.cpp:78) is
the "drag two orbs onto the pedestal" action, and its logic is specific rather
than generic. After rejecting a same-node, none, or non-existent pair, it looks
up an authored edge for the unordered pair via FindAuthoredEdge
(matching from→to or to→from, :247). If an authored insight exists, that
is the candidate. If not, it falls back to BuildWeakEdge (:271), which only
succeeds when the two nodes share at least one tag: it computes the tag
intersection, and if that intersection is empty it returns nothing and the
attempt reports "No meaningful connection found." (:91). The system refuses
to invent a deduction the data does not support.
When the shared tag exists, the weak edge is honestly weak: id weak.<a>.<b>,
Confidence 0.35, Kind = Weak, with DeductionText reading "A weak thematic
connection is visible, but it needs stronger corroboration." The cross-era
nuance is encoded right here: the weak edge is marked bCrossEra when the two
nodes come from different cells, and in that case it is stamped
RequiredBureauTier 5 and UnlockFlag MindPalace.CrossEraPairs (:303-305). A
same-cell weak link is tier 1 and always passes; a cross-cell weak link is gated
exactly like an authored cross-era thread.
Every candidate — authored or weak — then passes the cross-era gate before
it is committed. UV5_MindPalace_CrossEraGate::CanUnlockDeduction
(V5MindPalaceCrossEraGate.cpp:3) is the spine connecting the Mind Palace to
progression: a non-cross-era edge is always allowed; a cross-era edge is allowed
only when BureauLedger.CurrentTier >= max(1, RequiredBureauTier) or the
ledger's Unlocks already contains the edge's UnlockFlag. If the gate blocks,
AttemptDeduction returns bGateBlocked = true with the candidate edge
attached for the UI to tease — but it is not added to State.Edges. The
graph stays unchanged until the player earns the unlock, and the cross-cell
epiphanies are paid for in Bureau XP, the same ledger (FV5BureauXPLedger,
V5/ue/Source/V5Core/Public/V5Types.h) whose Tier-5 milestone grants
MindPalace.CrossEraPairs. Only a cleared candidate is appended to state
(deduped by edge id), and the result reports bSuccess with the resolved
Edge.
From a thread to an accusation — chains, the gate, and outcomes#
A single thread is rarely the case. BuildHypothesisChain(start, maxDepth)
(V5MindPalaceGraph.cpp:112) is a real breadth-first traversal over the
committed edges: a frontier expands outward (depth clamped to 1–12),
collecting every reachable node and edge id and accumulating an
AverageConfidence across the threads it walks. It is the UI helper for
visualizing a line of reasoning, and the test pins that an authored chain
carries real strength — AverageConfidence >= 0.80 (V5MindPalaceTests.cpp:99)
— because the authored cross-era threads ship at confidence 0.86 and per-cell
threads at 0.74, while weak guesses drag the average down toward 0.35.
MakeAccusation(case, accused, chain) (:165) is the proof-of-work gate that
closes a case, and it defaults to the worst outcome. It seeds the result as
Wrong / Unproven with the summary "filed without a complete supporting
chain," then searches the authored catalog for an outcome matching the
(case, accused) pair. A match only "sticks" with its authored Rating
(Brilliant/Good/Doubtful/Wrong) and OutcomeBranch
(TruthRevealed/PlausibleConviction/PoliticalCoverup/Unproven) if the
player's EvidenceChain contains every RequiredEdgeId the outcome
demands. A chain missing even one required link collapses straight back to
Wrong / Unproven with "lacked the required evidence chain" (:196). The
outcome is always backed by the deductions the player actually assembled — you
cannot brute-force a conviction by naming the right culprit without the
reasoning that indicts them. Every resolved accusation, right or wrong, is
appended to State.Accusations and logged by
UV5_MindPalace_OutcomesArchive::LogOutcome into the reviewable Outcomes
Archive.
How a player actually solves a case#
Stitch the verbs together and the loop is exactly the Sherlock-style fantasy the design promises — examine, theorize, chain, accuse — with the cross-era gate as the long-game unlock.
The player examines clues across cells; each becomes an orb. In the room they filter the clutter, pick two orbs, and attempt a deduction. Most early pairings resolve inside a single cell; the cross-era pairings stay gated until Bureau Tier 5, at which point dragging a 1947 orb against a 2078 orb fires a four-second "thread connects" cinematic. They chain threads into a hypothesis, read its confidence, and at case-close accuse one suspect — but the accusation only lands its authored branch if the required threads are in the chain. Get it wrong and the case still resolves, to the wrong branch, logged to the Archive for a New Game+ replay. No penalty, no soft-lock, just a worse outcome you can see you earned.
The volumetric memory room and the filter rail#
UV5_MindPalace_View_Volumetric::BuildViewState
(V5MindPalaceViewVolumetric.cpp:33) renders the design's "circular memory room
with evidence orbs in concentric rings by cell of origin." It first filters the
node set through the rail, then places each surviving node on a ring whose
radius is a function of its cell — RingForCell = 220 + cellIndex·70 cm, so
Urban orbs sit on the inner 220 cm ring and Sci-Fi orbs on a 500 cm ring — at an
angle evenly distributed around the circle (2π·i/N), lifted in z by index. The
selected orb scales up to 1.35 and glows at full intensity while the rest sit
at 0.45; each orb takes a per-cell accent color (ColorForCell — Urban cyan,
Period amber, Hunter rust, Sci-Fi indigo). Deduction threads are drawn only
between two visible orbs; an authored thread's intensity tracks its confidence
(clamped to 0.25–1.0) while a weak thread reads flat at 0.25, and a
cross-era thread is gold where an in-cell thread is blue-grey. The whole layout
is deterministic geometry the UI consumes; nothing about it is random.
UV5_MindPalace_FilterRail::FilterNodes (V5MindPalaceFilterRail.cpp:19) is
the left rail: filter by cell, by case, by an in-fiction timestamp range, and by
required tags (a node must carry all of them). The timestamp range is a string
comparison that works precisely because the in-fiction timestamps are written
ISO-ordered ("1947-06-14T21:00:00" sorts before "2078-…"), so a date window
is a lexical bound. The automation test drives this end-to-end: filter to a
single node by cell+tag, then build a view that resolves to exactly two orbs and
one thread (V5MindPalaceTests.cpp:106-110). The cross-era reveal is itself
code: UV5_MindPalace_CrossEraCinematic::BuildThreadConnectCinematic
(V5MindPalaceCrossEraCinematic.cpp:19) returns a four-second camera move whose
ThreadAlpha eases in over the duration (FMath::InterpEaseInOut) and whose
camera lerps to the midpoint between the two orbs — the test asserts the
duration is 4.0 s and the alpha advances strictly between 0 and 1.
Authored content is data, validated on load#
The 110 deduction pairs and 15 outcomes are not hard-coded.
UV5_MindPalace_Catalog::LoadDeductionPairs (V5MindPalaceCatalog.cpp:121)
reads deduction_pairs.json and validates it hard: schemaVersion must be 1,
the file is a compact generator spec of pairGroups, and the generated edges
are de-duplicated by id, rejected on self-loops or non-positive confidence
(AddDeductionIfValid, :103). The spec is one crossEra group of count: 30
spanning all five cells at requiredBureauTier 5, plus five perCell groups of
count: 16 (Urban, Period, Frontier, Hunter, Sci-Fi) = 80, and the validator
counts: it errors unless cross-era pairs total exactly 30 and per-cell pairs
total exactly 80 (:269-276), matching the test's Deductions.Num() == 110,
CrossEraCount == 30, PerCellCount == 80. ValidateAccusationCatalogJson
(:280) requires at least three outcomes, each with a non-empty
requiredEdgeIds and a unique id; accusation_outcomes.json ships 15 — five
anchor cases × three authored branches, an even Truth-Revealed /
Plausible-Conviction / Political-Coverup split, each branch demanding its own
pair of cross-era edges. The accusation test completes each outcome's required
deductions and asserts the verdict resolves the expected branch, covering
three distinct branches across the arc (V5MindPalaceTests.cpp:179-202).
Cloud sync, the companion app, and the live seam#
Mind-Palace state follows the account across devices, and that path is a real
request with an honest backend seam.
UV5_MindPalace_CloudSync::BuildGraphDiffPayload
(V5MindPalaceCloudSync.cpp:16) serializes a graph diff — nodes (id/case/cell)
and edges (id/from/to/cross-era) plus counts — targeting
@v5/service-mindpalace-cloud-sync at /v5/mindpalace-cloud-sync/graph-diff.
FV5MindPalaceCloudSyncHttp::BuildHttpRequest
(V5MindPalaceCloudSyncHttp.cpp:35) turns that into a genuine FHttpModule
POST on port :4220 with a Bearer JWT and application/json, and the latent
UV5_MindPalace_CloudSyncRequest::Activate (:75) fails loud —
short-circuiting to 401 auth.jwt.required when no token is present rather than
transmitting an unauthenticated diff, and reporting service.unreachable on a
connection failure. ParseResult maps 2xx→success and 503→failure; the
request-construction test pins the verb, URL, port, headers, and body, and a
second test does a real round-trip behind V5_ONLINE_LIVE=1, asserting the
response acknowledges the merged diff (V5MindPalaceTests.cpp:246-318).
The companion-app path (V5MindPalaceCompanionAppRead.cpp) is the Year-1
Companion-App Mind Palace Editor: BuildReadOnlySnapshot exposes the graph for
an AR/touch overlay, and BuildEditableSnapshot flips on the editor with two
operations — add-clue and annotate-clue. ApplyCompanionEdit (:72)
validates each draft (it requires a graph, a clue id, a case id, and an
annotation body), creates or annotates the targeted node — an annotation must
target an existing clue — and queues an append-only mindpalace-edit upload for
cloud-sync. The companion can add to your case file from your phone, offline,
and it merges back through the same seam.
Edge cases & connections#
- A pairing with no authored edge and no shared tag yields "No meaningful
connection found" — never a fabricated certainty. Shared-tag pairings produce
only a
0.35-confidence weak thread, and a cross-cell weak thread is gated exactly like an authored cross-era one. - A cross-era deduction below Bureau Tier 5 returns
bGateBlockedwith the candidate attached but not committed to state — the gate fails loud and leaves the graph untouched until the XP is earned. - An accusation with an incomplete chain can never reach an authored
conviction branch; the missing-link path is the explicit
Wrong/Unprovencollapse, so wrong answers ship (and are archived) without penalty — there is no deduction-graph game-over. - Offline / unhealthy backends surface as
503or, with no JWT,401; the live cloud-sync round-trip is opt-in behindV5_ONLINE_LIVE, so the default test run never depends on a service being up. - The Detective Mind Palace mode — the ten-hour main arc, the
deterministic daily-puzzle rotation, the leaderboard scoring, and the
count-validated 100 examinable 3-D evidence assets — is a separate runtime
module (
V5DetectiveMindPalace, also compiled on this box) built on top of this graph; its dailies-and-scoring internals are documented in the architecture companion rather than re-cited here. - Where cases are authored and where the spine lives. The in-editor Case Author that validates a case under the runtime's own rules is the matched pair to this system — ../architecture/creator-suite-and-mind-palace.md. The Bureau-XP ledger this gates against, the online backbone the cloud-sync targets, and the roster every cell shares are inventoried in ./shared-cross-cell-systems.md. One of the five cells feeding evidence into the room is detailed in ./urban-crime-cell.md.
- The feature hub: ../V5_features.md.