Restore native inference, card-bound readings and paged dialogue. Provide manual, checksum-verified model setup instead of Git LFS so source checkouts work without uploading multi-gigabyte weights. The game stays offline; complete release archives still bundle the model.
5.3 KiB
Seated Fortune Session
The room interaction opens a fixed first-person view across the table. No player
position, camera or bankroll state is modified. Escape or Exit returns to walking.
All runtime input, random card selection, state transitions and rendering are MASM
in src_graphics/fortune_dialog.inc; Python only compiles offline image assets.
Tarot
Enter a question (up to 240 CP1251 characters), then Ask or Enter. The question stays visible under the table for the entire reading and cannot change midway. Three distinct major arcana are selected in assembly, each with an orientation. The 22 symbolic illustrations have separately packed 180-degree reversed faces.
Sequence: shuffle 3.2 s; deal cards individually 1 s each; turn a card over 0.8 s; show its name, orientation and neural interpretation; repeat for the next two cards; show the overall advice; finish. Each explanation waits for the offline model and is paged with Continue, never skipping a deal or flip. Again clears the question only after completion; Selection can return to the choice of scenes at any time.
Speech is composited beside the teller, not an OS window. Its border grows with
the visible text. Characters reveal every 28 ms with a short upward pop. Rendering
does not advance timers: the session updates from the game clock, with bounded
steps after stalls. The offline worker interprets the exact cards and orientation
chosen in assembly. Missing weights and inference failures are visible errors.
See FORTUNE_AI.md for model packaging, timing and protocol.
Crystal Ball
The second selection is a fictional, theatrical student-themed lottery, separate from tarot and not an assessment of actual academic merit. The form asks for a first name, surname, birth date (DD.MM.YYYY), group and inclusive score bounds from 0 to 100. Tab cycles fields, clicking focuses one, Backspace edits, and Enter or the summon button submits. Empty fields, invalid calendar dates (including leap years), reversed bounds and scores above 100 are rejected.
Identity fields only dress the scene: they never seed or weight the draw. One native random draw is committed on valid submission. The ball rises for 1.4 s, hands circle through 32 poses with 16 mist frames for 5 s, then a glowing number appears inside the ball. Short typewriter speech accompanies the stages. The result fades into view and stays readable while the identity and chosen bounds remain at the bottom. Renders, duplicate submits and clicks during the ritual cannot reroll. After the reveal, Edit returns to the filled form for another session. No network, inference worker, profile or bankroll changes are involved. Fields are kept only in session memory and cleared on exit; nothing is saved.
The number uses baked, antialiased Cambria numeral sprites with translucent blue glow, not enlarged 3x5 block digits. Each of the 16 mist frames has its own measured glass-centre anchor, excluding the pedestal. One assembly resolver chooses both the ball frame and the matching number position, including the rising movement. Numerals stay at a constant size and the fog remains visible through their glow. The random draw and its probabilities are unchanged; identity never biases it.
Assets
Generated source art and production prompts: assets/sprites/fortune/.
Offline packers: tools/generators/pack_fortune_session.py and then
tools/generators/pack_fortune_orb.py (tracking metadata and numeral sprites).
Runtime packs: assets/animations/fortune/ (ANM1 format).
Forty authored poses are arranged on one shared anchored 8x5 sheet. Shared-canvas in-betweens yield 64 shuffle, 32 deal, 32 gesture and 32 orb-hand frames. Sixteen mist frames, 44 oriented card faces, a back and a 640x480 room complete the scene. Art loads only when seated and all eight packs are freed on exit/shutdown. The seated view is independent of the walking room's existing asset packs and map.
Verification
Run C:/Python314/python.exe tools/tests/check_hall_expansion.py after packing.
The fresh native x86 harness exercises real WM_CHAR input, length/backspace,
empty/double submission, all stage transitions, card uniqueness, speech growth,
question persistence, crystal-ball form validation, inclusive draws, fixed bounds,
input locking, duplicate submission, crystal-ball stages, exit during animation, asset cleanup
and unchanged player position/bank. It writes actual framebuffer BMP/PNG captures
and a 64-frame shuffle GIF under build/hall-expansion/. Python additionally checks
native-frame differences, question pixels, pack integrity and reversed artwork.
--parity checks these tested procedures against the shipping game object.
The orb regression captures each of the 16 native frames twice, with and without
the number. Pixel differences must stay centred on that frame's glass sphere;
this also checks that opacity is restored and the numeral pack is freed on exit.
--prove-fate-anchor-regression deliberately restores the old fixed coordinates
in a test-only module and must fail the native tracking assertions.
Distributions must include assets/animations/fortune/, the updated game and the
complete ai/ directory including the pinned weights. Use the offline ZIP packager
documented in FORTUNE_AI.md. After copying or cloning source, run the separate
root download_fortune_model.bat once; the game itself never downloads weights.