-
Notifications
You must be signed in to change notification settings - Fork 29
Randomness
While most things in Celeste follow a deterministic set of rules on how things should behave, not everything actually does so. Having non-deterministic behavior in a TAS can cause various issues while trying to TAS something, or play it back afterwards.
To solve that issue, this page tries to document all cases of known non-deterministic behavior and how to solve them.
Important
This page is not necessarily exhaustive! In case you encounter non-deterministic behavior or "unstable" randomness (i.e. randomness which is deterministic, but changes it's behavior with seemingly unrelated changes), please consider reporting that case.
- Ethics
- Common Randomness
- Vanilla
- Aura Helper
- Aurora's Helper
- Bosses Helper
- Pandora's Box
- Spekio's Toolbox
- Vortex Helper
The ability to seed randomness is a decision between accuracy and convenience. If randomness should be seeded and if yes, "when or how?" is a question left up for each individual project. Below are a few arguments for each side to help choosing a position on the topic for your own project:
The most accurate way to deal with randomness would be seeding Calc.Random once at the very beginning of a TAS and then never touching it again.
This however has the massive downside of basically any small change altering every instance of randomness after it.
Normally, Calc.Random is also used while rendering a frame. However, frames could be skipped depending on the current resource usage of the computer.
This makes it reasonable to say it's okay to re-seed Calc.Random "every once in a while" due to the uncertainty created by frames being skipped or not.
You could however also just not care too much about the possibility and rather focus on having fun. Then you could just seed everything individually, since each check is theoretically possible, even if the exact sequence is not possible, due to a limited amount of random seeds.
One thing which can become quickly annoying is the "unstable" behavior with Calc.Random. To avoid having find a new seed for every small movement change, you have the option of providing a unique random instance to specific features.
That decouples them from everything else which uses Calc.Random and therefore makes that randomness "stable".
A few things use their own random instance. These usually aren't affected by visual effects but that also means they don't have an uncertainty with frame skipping.
Depending on the random instance is used, consider using different seeding rules than for Calc.Random if you care about that.
This is the randomness which almost everything uses. It is primarily used for visual effects, such as particles, but sometimes also for gameplay.
Due to visual effects using it, almost every change in the player's movement will alter when and how things like dust particles are created. This is the reason, why everything using Calc.Random is considered "unstable".
It is deterministic and can be seeded with the SeedRandom,Update,[Seed] command.
Used rarely, but is something used for doing an "every n frames" check. It is incremented by one every frame globally, even while a TAS is paused.
The most legitimate way to control it is by setting it once at the beginning of the level with SeedRandom,FrameCounter,[Value].
Debris particles are created when Moving Block from Golden Ridge breaks for example. They don't really interact with the gameplay at all, however since they are considered an Actor, they can prevent certain entities from respawning.
They technically use Calc.Random, however, that was changed to a deterministic seed unique for each debris particle.
They can be seeded individually with SeedRandom,Debris,[Seed].
The collapsing bridge in prologue uses randomness to determine when the bridge tiles should fall. This usually isn't an issue since the TAS is fast enough anyway.
They use Calc.Random but can be individually seeded with SeedRandom,Celeste_PrologueBridge,[Seed].
The final Badeline boost which brings you into the next Summit section applies a random shake to the player's position. This usually doesn't matter since the final landing position in the next room is always the same, however, since the X position of the player is random when entering the room, a different respawn point might be selected. This can be observed in the transition from Golden Ridge to Mirror Temple in 7A.
It uses Calc.Random but can be individually seeded with SeedRandom,Celeste_SummitLaunch,[Seed].
Only the last random value before transitioning to the next room is relevant.
Spawns Generators and Lines with random positions.
It technically uses Calc.Random, however, that was changed to a deterministic seed unique for each lantern.
It can be individually seeded with SeedRandom,AuraHelper_Lantern,[Seed].
Spawns Crackers with a random direction and speed.
They technically use Calc.Random, however, that was changed to a deterministic seed unique for each lantern.
They can be individually seeded with SeedRandom,AuraHelper_Generator,[Seed].
Uses a single random value to determine one of various outcomes, by changing what flags are currently active.
It uses it's own random instance which is only used for the trigger.
The most legitimate way to control it is by setting it once at the beginning of the level with SeedRandom,AurorasHelper_Shared,[Seed].
This is an alias for the ah_set_seed [seed] console command.
Shares a random instance per room with a BossController to determine random patterns.
It is instantiated on room load and seeded with the floored Scene.TimeActive value, which makes it deterministic, but slightly unstable when entering the a second faster or slower.
The used seed can be controlled with SeedRandom,BossesHelper_Shared,[Seed].
This is an alias for the set_boss_seed [seed] console command.
Tile Glitchers randomly try to convert every solid tile into the target tile type, depending on if a probability check for each tile succeeds.
At creation they are deterministically assigned to one of four frame groups, which dictates when they should start after all conditions are met. This is done with a (Engine.FrameCounter % 4) == frameGroup check.
It uses Calc.Random but can be individually seeded with SeedRandom,PandorasBox_TileGlitcher,[Seed].
The "Random" shoot sequence of the Bullet Generator chooses a target node for the Badeline laser shots at random.
It uses it's own random instance which is only used for the trigger.
The most legitimate way to control it is by setting it once at the beginning of the level with SeedRandom,SpekioToolbox_Shooter,[Seed].
Hitting a Color Switch with the random option enabled, picks the next active color randomly.
It uses Calc.Random but can be individually seeded with SeedRandom,VortexHelper_ColorSwitch,[Seed].