A few days ago I set a World record Any% time for Lorelei and the Laser Eyes.
The previous WR was 1h 49m 15s, held by speedrunner Ucci.
My time is 11m 41s.
I didn’t find any glitches, escape from the geometry, or abuse some broken logic. I ran on a stock PS5, started a fresh game like everyone else, and solved the minimum required puzzles to see the credits. So where did almost 90% of the run go?
The short answer: there are only 1024 possible games of Lorelei, and the first puzzle you meet tells you which one you’re playing. After that, every answer in the game can be computed in advance.
The long answer is this post.
The speedrun defences
Puzzle games are usually easy prey for speedrunners – if a little dull to watch – because the answers don’t change. Solve everything once, write it down, and your second playthrough is a typing test.
Lorelei was built to be immune to this. Two design decisions do the work:
The puzzles are randomised. If you boil it down, the crux of the game is learning the inputs to log into a Supercomputer (whoops – spoiler). But it’s a multi-layered puzzle, and every new game rerolls the various prior puzzles needed to learn those inputs. Your notes from last run might tell you how to solve a puzzle, but never give the exact answer.
Progress is gated behind items. Even if you know how to solve every puzzle on the way to the Supercomputer, getting the solutions forces you to visit places, use objects, and do stuff. There’s enough physicality required that a 10-hour second playthrough is admirable. Obviously items like cranks want you to put them somewhere, but even pure information documents like the phonebook randomise key parts and require you to pick them up and read them.
Progress is an elegant balance of scavenger hunt and logic. Things you have, and things you know. Come to think of it, completing Lorelei does feel like some elaborate multi-factor authentication dance. Which is a fitting analogy for a game whose ending is literally logging into a computer.
But, exactly like real authentication, if the foundations aren’t solid, the whole thing falls apart.
Part 1 – The machine behind the curtain
Lorelei on PC is a Unity game with a Mono scripting backend, and its entire game logic ships as readable .NET bytecode in a file called Assembly-CSharp.dll. No source code leaks – the shipped instructions themselves, disassemblable with open-source tools. I used Python (Mandiant’s dnfile + dncil) to walk the bytecode and UnityPy to read the scene data.
Deep in a class the developers named FuzzyLogic sits the orchestrator – one function, run once at the start of a session, deals every puzzle in the game:
// FuzzyLogic.RandomizeGameSession - reconstructed from the shipped CILpublicvoid RandomizeGameSession() { int master = LoreleiState.GetSessionMagicSeed(); // the seed Random.State saved = Random.state; // don't disturb gameplay RNG Random.InitState(master); // Every puzzle in the scene, room by room. Each view salts the master // with its room's floored world position, then with its own. foreach (var room in m_hRoomParentsInScene) foreach (var view in room.GetPuzzleViewsInRoom()) view.RandomizeSolution(master ^ room.GetRoomPositionSeed()); // The scene-wide passes take the master raw, unsalted. RandomizeBoltLocksInScene(master); RandomizeSafeBoxesInScene(master); // ...posters, and the furniture-shuffling HierarchyScramblers // The singletons each re-seed from the SAME master, so every one of them // reads an identical random stream from position zero. Random.InitState(master); m_hCrystalBallLogic.RandomizeSolution(); Random.InitState(master); ConsoleLogic.Instance.RandomizeSolution(); // ...word input, quiz input, catacomb maze, the retro game's scenarios Random.state = saved; // restore - invisible to the player}
Everything the game will ever ask you flows deterministically from that single integer, master.
And “everything” is close to literal. That one number decides:
- The front gate panel – the three dial numbers
- The phonebook – three numbers are randomised
- The shortcut doors – which puzzle goes on which door
- The magic posters – the poster glyphs
- The LASER-I console error codes
- The Quiz Club – which question each keeper picks
- The OCU-3 login – the username glyphs, the password, and the memory board switch positions
- …and about thirty more.
And underneath all of that, the HierarchyScrambler pass quietly rearranges objects around the rooms themselves. The furniture is dealt from the same deck as the puzzles.
So what is master? Here’s GetSessionMagicSeed(), reconstructed from the bytecode:
seed = 106207311 ^ (Year ^ Month ^ Day ^ Hour ^ Minute ^ Millisecond)
This takes the timestamp you pressed New Game, chops it into six numbers, XORs them all together, then XORs that with a fixed constant. That’s the seed. That’s the entire foundation.
(Note what’s missing, incidentally: seconds. The millisecond field is in there – the 0 to 999 part – but the seconds field isn’t. Pressing New Game at 12:00:01.500 and 12:00:59.500 gives the same seed. Pressing it one millisecond later doesn’t.)
Now, how many different values can that actually produce?
The constant is a red herring. XORing everything by a fixed number just relabels the outputs – it’s a one-to-one renaming that can’t create variety. So all the real variety has to come from the timestamp itself.
And here’s the thing about XOR: it never carries. Each column is worked out on its own, so the answer can never use a column that none of the inputs used. Line the six fields up in binary and the question answers itself:
1024 512 256 128 64 32 16 8 4 2 1
Year 2026 1 1 1 1 1 1 0 1 0 1 0
Month 8 0 0 0 0 0 0 0 1 0 0 0
Day 25 0 0 0 0 0 0 1 1 0 0 1
Hour 11 0 0 0 0 0 0 0 1 0 1 1
Minute 33 0 0 0 0 0 1 0 0 0 0 1
Millisec 847 0 1 1 0 1 0 0 1 1 1 1
Only the year row ever puts a 1 in the 1024 column – and it always does, and will until 2048. Everything else is penned into the ten columns to its right, which between them cover every value from 0 to 1023.
Ten columns of real variety, and one bit permanently stuck on.
Milliseconds only reach 999, which leaves the top 24 values looking unreachable – the minute field fills them in. Landing on 1023 needs a minute of at least 24; minutes run to 59. Hours would have missed it, stopping at 23.
There are only 1024 possible games of Lorelei and the Laser Eyes.
Every player who has ever started the game – received one of the same 1024 decks. The authentication protocol guarding the credits has a 10-bit key.
Keep that number in mind. It’s small enough to search.
Downstream, the seed fans out in two families, which you can see in the orchestrator above:
Raw master. The scene-wide passes and the singletons seed the RNG with master directly.
Position-salted. Each interactive “puzzle view” derives master ^ roomSeed ^ localSeed – the XOR of its room’s floored world coordinates and its own position within that room. The furniture is the salt.
Underneath both is Unity’s stock RNG – xorshift128 – with two primitives worth writing down, because everything in Part 3 is built from them:
Range(min, max) = min + Get() % (max − min)value = (Get() & 0x7FFFFF) / 2²³
That’s it. Two lines. I verified them against real playthroughs – a single seed correctly predicting all twenty shortcut-door codes at once is not a coincidence.
Part 2 – The key-disclosure oracle
Everything so far is worthless.
The seed is derived from the exact game start time – down to the millisecond. I can’t observe that without introspecting the game. I know there are only 1024 possible games, I can compute all of them, but I can’t tell which one I’m holding. The key is secret, and the console is a locked box. This is where the project should have died.
Except… while sweeping the bytecode for everything that consumes the seed I found this, in the pause menu’s UI class:
// FuzzyLogicUI.ProcessHiddenInfoRequest — from the shipped CIL, boilerplate elidedprivate void ProcessHiddenInfoRequest(){ if (SGFW.GameInput.GetButton("HiddenInfo_Primary") && // two buttons, SGFW.GameInput.GetButton("HiddenInfo_Secondary")) // both held down { m_fHiddenInfoTrigger += Time.unscaledDeltaTime; // count up while held if (m_fHiddenInfoTrigger > 10.0f) // for ten whole seconds { int seed = LoreleiState.GetSessionMagicSeed(); // …then take the seed m_hGameSessionSeedString.text = // …and draw it on screen string.Format("[Seed: 0x{0}]", seed.ToString("X8")); m_bHiddenInfoVisible = true; } } else m_fHiddenInfoTrigger = 0.0f; // let go for one frame and it starts over}
THE GAME PRINTS THE MASTER SEED TO THE SCREEN?!?!
This must have been found already, I thought. Nope.
The developers shipped a key-disclosure oracle in the pause menu. That’s a perfectly sensible thing to build for testing. It’s a less sensible thing to ship.
There was one problem: on PC, those two buttons – HiddenInfo_Primary and HiddenInfo_Secondary – exist in the input system’s action list but are bound to nothing on keyboard. The function runs every frame in the pause menu, patiently checking two buttons that don’t exist. The code shipped; its buttons didn’t.
But bindings are data, not code, and gamepad control schemes are a different set of data. The spidey sense was tingling. So, in a moment of pure empiricism, I sat down with the PS5 version of the game instead, paused, and started holding button combinations for ten seconds at a time like a safecracker with a stethoscope.
L3 + R3. Both sticks, clicked and held. Ten seconds later:

[Seed: 0x06549D29]. Look in the bottom left – it’s tiny.
That proved the code path was alive on PS5 – but not yet that it mattered. The seed on screen could have been derived differently, feeding puzzles randomised differently; it would have been a cruel world to be able to compute every PC puzzle from a seed, and to read the seed on PS5, but for neither to be compatible. Then I typed those eight digits into my tooling, walked up to a puzzle, and the prediction matched. And kept matching. One platform reverse engineered, the other one played.
My best guess is that the debug bindings were cleaned out of the keyboard scheme before release and simply survived in the gamepad defaults. Nobody re-enabled anything – the door was always there, it just had no handle on PC.
I had the key. Hold that thought, because it turns out I didn’t need it.
Part 3 – The rainbow table
Knowing the seed is only useful if you can run each puzzle’s solution-generating algorithm, and the algorithms live in bytecode. So the third phase was translation: reimplement Unity’s xorshift128 in JavaScript, then port every puzzle’s randomiser, one by one, into a basic web front-end.
Type in a seed. Get every solution for that game.
For example:
The front gate keypad. A panel with two numbered dials and a switch, where you pick the number from each input so the three sum to a target (2014). The generator for this is surprisingly elegant: it rolls the first number (for dial 1), then constructs the second (dial 2) and third (the switch) so the sum works out, then buries those answers among six decoys generated afterwards. Replaying the arithmetic tells you exactly which numbers to pick.
The shortcut doors. Twenty numbered doors across the hotel – BoltLock in the code, if you go looking. The game doesn’t roll twenty codes – it rolls one Fisher-Yates shuffle over the set of doors, so each door displays the code that another door needs, and then reshuffles until several fairness constraints hold (certain doors’ codes mustn’t end up too close together, one special door must land late in the permutation). To predict it you don’t just replay the shuffle – you replay the rejections. My implementation reports how many reshuffles the constraints forced, because getting that count wrong by one desynchronises every prediction after it.
Porting solution randomisers was slow work, with one enormous safety net: that 10-bit keyspace. With only 1024 reachable seeds, verification inverts. If an observed puzzle state matches no reachable seed, your observation is wrong – go re-read the bytecode. The tiny keyspace supported the debugged process.
Each port was tested against a real session whose seed I could read off the screen.
Part 4 – Flipping the table
With the app built, I started planning the run, and the plan looked like this: start the game, pause, hold both sticks for ten seconds, read the seed, type it in. Ten seconds of standing still at the start of a speedrun. Ugly, but it works.
Then something nagged at me.
The first seed-dependent thing the game shows you is the front gate panel – nine numbers across the three inputs; three correct positions and six decoys.

You have to walk up to it. You have to look at it. It’s the first lock with a randomised key, and you physically cannot proceed without standing in front of it.
Nine numbers is a lot of information. And there are only 1024 games.
So I flipped the table around. Instead of seed-in, answers-out, I pre-computed the gate panel for all 1024 seeds and indexed them by what’s on the grid. Now the lookup goes the other way: read the nine numbers off the screen, find the seed that produces them, and the rest of the game falls out as before.
Then the obvious question: how much of the panel do you actually need? Across all 1024 seeds, I measured how few of its numbers identify the seed with certainty:
| Which numbers you provide | Unique | Worst case |
| Any two of the nine | 87.6% | 12 |
| Two from dial 2 | 95.9% | 3 |
| Two from dial 1 | 98.9% | 2 |
| All three of dial 1 | 100.0% | 1 seed – never ambiguous |
Read the bottom row again. Just the three numbers from the first dial – identify the seed uniquely, every single time, across all 1024 games. You don’t need nine numbers. You need three.
For that exact panel image above, the one (and only) valid seed is: 0x06549E15
My section title turns out to have been literal. This is a rainbow table in the actual sense: precompute every key, index by output, look up the key from what the panel shows you.
And it changes everything about the run:
- No pause. The panel is on the critical path anyway, so reading it costs nothing beyond a quick lookup in the web app.
- No hidden feature. No reliance on a debug hook the developers forgot to unbind.
- No PS5. This works on every platform, because every platform shows you the gate panel and the master seed is generated identically everywhere.
The oracle was how I got in, and it’s how I verified every port. But it was a crutch – the game hands you the key in plain sight before you’ve solved a single thing.
One consequence worth sitting with: since the whole run now reduces to the gate panel, the phone number, and the OCU-3 login, you could print the complete solution to every one of the 1024 games in a booklet of about fifteen pages. Walk up to the gate, find your first dial in the index, turn to the page. The entire game, as a lookup.
Part 5 – 11 minutes
The run itself, then.
Start a new game on the PS5. Walk to the gate. Open the gatehouse padlock, open the gate-control padlock, and look at the panel.
Three numbers – the first dial is all it takes. I read them into the web app – and the seed comes back. From that moment the run is pre-computed: every dial, every sequence, every door. What remains is execution.
Lorelei and the Laser Eyes – Any% Speedrun WR 🏆 [11m 41s 253ms]
And there is far less of it than you would think. Strip Lorelei down to the critical path and the entire game is this:
- Open the gatehouse padlock.
- Open the padlock on the gate control.
- Read the panel, look up the seed, solve the three-dial summation – the gate opens.
- Go up to the third floor, then straight back down to reception. That triggers the cutscene with the man.
- Enable the elevator: open the phonebook to the right page, call the Hausmeister, then take the call back from the man telling you it’s repaired.
- Take the elevator straight down to the basement.
- Enter the pre-computed OCU-3 login.
- Enter the nine answers inside the supercomputer. Done.
And that’s it. That’s the game. Three locks, a lap of the hotel, two phone calls, and two sets of typed answers.
What’s interesting is how little of that route the seed actually touches. The two padlocks are static – 1963 and 1847 – and so are the nine answers at the end. Those you simply memorise once. The seed is doing its work in exactly three places: the gate-panel, the Hausmeister’s phone number, and the OCU-3 login.
Of those:
- The gate-panel is trivial to solve quickly in your head
- The Hausmeister’s number takes an instant to commit to memory from the phonebook.
However, reaching the OCU-3 inputs honestly means working through the whole chain of: posters, safe boxes, disks, bug reports, mausoleum, red maze, quiz club, and red gallery. That’s the 90% difference versus a normal speedrun.
Eleven minutes is what’s left of Lorelei when deduction costs nothing – just the walking, and inputting. The previous record and mine are measurements of two different quantities. Ucci measured how fast a human can solve the game. I measured how long the game is.
Part 6 – The speedrun trophy
The game’s speedrun trophy ‘Augenwaldburg Race Winner’ (Augenwaldburg being the town the game is set in) is known to require finishing the game in under ten hours.
I finished well under that and the trophy didn’t pop. Searching online, I saw that another Lorelei speedrunner, soggytoast, suggested there was a second requirement: “getting to the centre of the quiz club”.
Rather than leave it to chance, I went back to the code. Here is the trigger in full:
- FuzzyAchievementHandler.OnGameComplete:public static void OnGameComplete(float playTime) // arg0 = playTime{ if (l_hInstance == null) return; if (playTime >= (float)(3600 * l_hInstance.speedRunAchievementHours)) return; if (l_hInstance.speedRunRoomRequirement != null && !l_hInstance.speedRunRoomRequirement.HasVisitedRoom()) return; if (l_hInstance.m_nSpeedRunAchievementID == -1) return; SGFW.GameProfile.SetAchievement(l_hInstance.m_nSpeedRunAchievementID, 1); l_hInstance.CheckAchievementState_Internal();}
They’re basically right. The room you need to have visited at least once is ‘RedGallery_Center’ – the central chamber of the red gallery. The trigger is just setting foot in it.
Without this requirement, a player could leisurely work their way through the game… accruing the OCU-3 login… and then reload to an earlier save to complete the game ‘early’. The Red Gallery is a late-game area that can’t be accessed at any time – so having to go there largely enforces that a run that earns the trophy will look far more normal than the 11m run.
But being able to pre-compute the puzzles… we can still create a pretty unusual path to the trophy doing the following:
- Gatehouse padlock, gate-control padlock, gate-control puzzle
- Floor 3, back to reception, trigger the man cutscene, key cabinet padlock
- Fix the elevator (phonebook page, call the number, receive the man’s call)
- Go to room 2014, leave, trigger the second man cutscene (opening the outside)
- Puzzle at the back door to enter the garden, get the crank
- Elevator to F2, lower the chandelier with the crank, back to F1
- Get the W key from the chandelier, open the W side, open the Mirror Door
- Solve the required eight maze men, and the minotaur
- Walk into the Red Gallery centre
- Back out through the mirror, exit the maze, down to the basement
- Supercomputer login, nine questions. Done.
Even this skips over 90% of the game. You never see the red maze, the mausoleum, the church, or the tent. You never take part in an interrogation, never get either laser eye, never solve a card door. Had I not found the shorter route, this alone would have been a new Any% record by over an hour.
So I decided to speedrun this route. And for this one I did something different.
Start a new game. Immediately pause. Click both sticks and hold.
The seed appears. I read eight hex digits off the screen, type them in, and play the rest from the table.
Lorelei and the Laser Eyes – “Augenwaldburg Race Winner” Speedrun WR 🏆 [23m 21s 083ms]
Those ten seconds are deliberate. I didn’t need them – the gate panel would have told me the same thing a minute later – but the fast run deliberately never shows the oracle, and I wanted it on camera somewhere for the community to see.
Part 7 – Things I learned along the way
The tampon.
There’s a tampon in your inventory the whole game that never gets used. The devs said in an interview that it’s a joke – simple commentary on the fact that women often have tampons in their bags. I was so sure this would turn out to hold a bigger secret that I started reverse engineering the game specifically to find out. I can tell you, sadly, that the tampon is not a usable item anywhere.
New Year’s Day 2048.
On 1 January 2048 the year’s top bit moves up a place, and the game starts dealing from a completely different block of 1024 games – while every game played before then becomes unreachable forever. The seed logic is a weak area of the code; most of the entropy the devs appear to have wanted simply isn’t reachable.
Save at least once.
If you complete the game without saving, you lose the ability to revisit that session after the credits roll. You’re kicked back to the title screen and it’s gone. It’s like it never happened.
Hidden loot room.
Every closeup view in the game – the panels, padlocks and keypads you zoom into — sits offscreen in a single room at world position (0, 200, -500). The map’s origin is the middle of the hotel, so this one is parked high above it and a long way behind.
A closeup’s solution comes from the master seed salted twice: once with its room’s position, once with its own position inside that room. What’s interesting is that the room in question is where the view lives, not the room you trigger the puzzle in. So every closeup in the game shares one room salt: 0 ^ 200 ^ -500 = -316.
No harm done: the views sit at different spots inside the room, so the position salt still tells them apart and every puzzle stays properly random. But that middle layer is a constant, and constants add no variety – the same reason the 106207311 in the master seed was a red herring. The room salt is decoration.
The elevator guard.
There are only a few checks in the game stopping you from doing a thing before it makes sense. If you know something early, it probably just works. The elevator is an exception: you cannot simply call the Hausmeister immediately – even with the number pre-computed, it won’t ring. You must either view the note on the elevator or open the phonebook to the exact page where the entry lives. For one of very few guards it’s odd that it doesn’t quite make sense – how could seeing the note give you the number when it’s bloodied over? Presumably the number was legible on the note at some point in development.
The turd 💩
There is a turd item out of bounds in the forest prototype game. You can pick it up like dollars – but it does nothing. There are no other hidden items like this.
Cut Mechanics
- There is code for a constellation puzzle… where Lorelei would have had to link points by looking at them in first-person.
- There is also a body recoil animation and some code bits left from when Lorelei’s literal laser eyes could shoot laser beams.
- There’s a fully programmed articulating arm puzzle that is unused. I guess it may be related to the mannequins.
- There is a ‘needs to pee’ animation that Lorelei would have made if stood still and her caffeine level was high.
The inevitable argument
This won’t sit well with everyone, and Pandora’s Box is open regardless: validating runs is going to be harder from here. Even a normal-looking playthrough might leverage… let’s call it ‘heightened awareness’.
The category rules, as written today, don’t prohibit any of this. No memory editing, no glitches, no game modification – the console and the game are stock, end to end. Notes and routing prepared outside the run have always been legal; my notes are unusually good.
The record run uses no hidden feature. The pause-menu oracle is how I first got the key, and it’s on camera in the trophy run so the community has it. But the record never touches it – the gate panel, which every player has to look at, gives up the seed on its own.
Everything is reproducible without my tools. The maths is public in this post. 1024 games, two RNG primitives. Anyone can rebuild the table.
Whether this counts as ‘official’ Any% or wants its own category is for the community to sort out, and I don’t have strong feelings either way. What I would say is that none of this is specific to Lorelei: the weakness is a small keyspace plus early disclosure – the game tells you which of its 1024 decks you’re holding before you’ve solved anything. Plenty of games have both. If it needs a name, I’d go with:
Seedrunning.
-hiburn8

Leave a comment