int Narrator::script(int st, PRNG &prng) { static ChaosParticles chaosA(flow, runner.config["chaosParticles"]); static ChaosParticles chaosB(flow, runner.config["chaosParticles"]); static OrderParticles orderParticles(flow, runner.config["orderParticles"]); static Precursor precursor(flow, runner.config["precursor"]); static RingsEffect ringsA(flow, runner.config["ringsA"]); static RingsEffect ringsB(flow, runner.config["ringsB"]); static RingsEffect ringsC(flow, runner.config["ringsC"]); static PartnerDance partnerDance(flow, runner.config["partnerDance"]); static CameraFlowDebugEffect flowDebugEffect(flow, runner.config["flowDebugEffect"]); static Forest forest(flow, runner.config["forest"]); static DarknessEffect darkness; rapidjson::Value& config = runner.config["narrator"]; Sampler s(prng.uniform32()); switch (st) { ////////////////////////////////////////////////////////////////////////////////////////////// // Special states case 1: { // Darkness only ("off") crossfade(&darkness, 1); delayForever(); } case 2: { // Precursor only (sleep mode) precursor.reseed(prng.uniform32()); crossfade(&precursor, 1); delayForever(); } case 3: { // Debugging the computer vision system crossfade(&flowDebugEffect, 1); delayForever(); } ////////////////////////////////////////////////////////////////////////////////////////////// // Opening sequence case 0: { // Darkness until opening crossfade(&darkness, 1); delayUntilDate(config["opening"]["date"]); return config["opening"]["nextState"].GetInt(); } ////////////////////////////////////////////////////////////////////////////////////////////// // Cyclic states default: { endCycle(); return 10; } case 10: { // Order trying to form out of the tiniest sparks; runs for an unpredictable time, fails. precursor.reseed(prng.uniform32()); crossfade(&precursor, s.value(config["precursorCrossfade"])); // Bootstrap delay(s.value(config["precursorBootstrap"])); // Wait for darkness while (!precursor.isDone) { doFrame(); } return 20; } case 20: { // Bang. Explosive energy, hints of self-organization ChaosParticles *pChaosA = &chaosA; ChaosParticles *pChaosB = &chaosB; int bangCount = s.value(config["bangCount"]); for (int i = 0; i < bangCount; i++) { pChaosA->reseed(prng.circularVector() * s.value(config["bangSeedRadius"]), prng.uniform32()); crossfade(pChaosA, s.value(config["bangCrossfadeDuration"])); delay((1 << i) * s.value(config["bangDelayBasis"])); std::swap(pChaosA, pChaosB); } attention(s, config["bangAttention"]); return 30; } case 30: { // Textures of light, exploring something formless. Slow crossfade in ringsA.reseed(prng.uniform32()); crossfade(&ringsA, s.value(config["ringsA-Crossfade"])); attention(s, config["ringsA-Attention"]); return 40; } case 40: { // Add energy, explore another layer. ringsB.reseed(prng.uniform32()); crossfade(&ringsB, s.value(config["ringsB-Crossfade"])); attention(s, config["ringsB-Attention"]); return 50; } case 50: { // Biology happens, order emerges. Cellular look, emergent order. orderParticles.reseed(prng.uniform32()); orderParticles.symmetry = 10; crossfade(&orderParticles, s.value(config["orderCrossfade"])); while (orderParticles.symmetry > 4) { attention(s, config["orderStepAttention"]); orderParticles.symmetry--; } attention(s, config["orderStepAttention"]); return 60; } case 60: { // Two partners, populations of particles. // Spiralling inwards. Depression. Beauty on the edge of destruction, // pressing forward until nothing remains. partnerDance.reseed(prng.uniform32()); crossfade(&partnerDance, s.value(config["partnerCrossfade"])); attention(s, config["partnerAttention"]); return 70; } case 70: { // Sinking deeper. Interlude before a change. ringsC.reseed(prng.uniform32()); crossfade(&ringsC, s.value(config["ringsC-Crossfade"])); attention(s, config["ringsC-Attention"]); return 80; } case 80: { // Continuous renewal and regrowth. Destruction happens unintentionally, // regrowth is quick and generative. The only way to lose is to stagnate. forest.reseed(prng.uniform32()); crossfade(&forest, s.value(config["forestCrossfade"])); attention(s, config["forestAttention"]); return 90; } } }