Skip to content

How to Snap ~25% of the World away

Neofox: floof_mug MMMH, REAL CODE

This RUNS! Playful premises aside, this is a functioning showcase of fennecs principles.

Get comfy, grab a cup of Java CoffeeScript Visual J# whatever, and get your paws dirty playing around in the code! It's good fun!

All .csproj and .cs files are over here on Github!

Premise

Hey there, mighty Titan (who flunked probabilitics)! Ready to bring perfect balance to your fennecs.World?

In this example, we'll show you how to use fennecs' Query.Subset and Query.Exclude methods to snap away Despawn half the entities in your world.

SPOILER

Well... randomly half of randomly half!

How it works

First we create a bunch of entities, give some of them a "Lucky" and some of them a "Unlucky" component, then we filter our Query to target the Unlucky and move the Lucky ones out of harm's way.

Finally, we unleash the power of the Infinity Gauntlet Stream<>.Despawn() to bring an awkward balance to the Universe.

I'm sure you already see that nothing can go wrong! Let's get snapping!

cs
// Thanos.cs (type declarations at bottom of file)

using fennecs;

if (!Console.IsOutputRedirected) Console.Clear();

// The universe is vast, but finite. Its resources, finite.
using var world = new World();

// Oh don't be dramatic! It's not that finite.
// (fennecs can handle millions of entities)
const int initialPopulation = 1_000_000;
using var entities = world.Entity()
    .Add<Alive>()
    .Spawn(initialPopulation);

// Life. Unchecked, it will cease to exist. It needs correcting.
var population = world.Query().Has<Alive>().Compile();  
Console.WriteLine($"Entities before Thanos Snap: {population.Count}");

// The hardest choices require the strongest wills. (and two dumb coin flips?) 
var random = new Random(2018);

using (var _ = world.Lock())
{
    // We can also use LINQ to iterate Entities: Slower, but sooo convenient.
    foreach (var entity in population)
    {
        // *mumbles* 50% chance of being Lucky or Unlucky... right?
        if (random.NextDouble() < 0.5) entity.Add<Lucky>();
        if (random.NextDouble() < 0.5) entity.Add<Unlucky>();
    }
}

var thanosStream = population.Stream<Alive>() with
{
    // I'm the only one who knows that. The Unlucky must go! (mkay...)
    Subset = [Component.PlainComponent<Unlucky>()],
    
    // ... the Lucky, I'll leave to chance. (uh oh!?)
    Exclude = [Component.PlainComponent<Lucky>()],
};


// (Aside: Thanos flunked probabilistics. Here's what's truly going on!)
var unluckyQuery = world.Query().Has<Unlucky>().Compile();  
var luckyQuery = world.Query().Has<Lucky>().Compile();
var bothQuery = world.Query().Has<Unlucky>().Not<Lucky>().Compile();

Console.WriteLine($"Lucky Entities: {luckyQuery.Count} ({Math.Round(luckyQuery.Count * 100f / initialPopulation)}%)");
Console.WriteLine($"Unlucky Entities: {unluckyQuery.Count} ({Math.Round(unluckyQuery.Count * 100f / initialPopulation)}%)");
Console.WriteLine($"Unlucky Entities that AREN'T ALSO Lucky: {bothQuery.Count} ({Math.Round(bothQuery.Count * 100f / initialPopulation)}%)");
Console.WriteLine($"Targeted by Thanos: {thanosStream.Count} (seen this number before?)");


// I could simply snap my fingers, and they would all cease to exist.
Console.WriteLine("OH SNAP!");
thanosStream.Despawn();

// I call that... mercy.
Console.WriteLine($"Entities surviving after Thanos Snap: {world.Count} ({Math.Round(world.Count * 100f / initialPopulation)}%)");
Console.WriteLine($"Directed by Robert B. Weide.");

// Component tags
internal readonly struct Alive;
internal readonly struct Lucky;
internal readonly struct Unlucky;
txt
Entities before Thanos Snap: 1000000
Lucky Entities: 500096 (50%)
Unlucky Entities: 500396 (50%)
Unlucky Entities that AREN'T ALSO Lucky: 250046 (25%)
Targeted by Thanos: 250046 (seen this number before?)
OH SNAP!
Entities surviving after Thanos Snap: 749954 (75%)
Directed by Robert B. Weide.

fennecs is released under the MIT License. Neofox is released under the CC BY-NC-SA 4.0 License.