← Back to context

Comment by coldstartops

11 days ago

Hi ogig, funilly enough I was also running this boids experiment a few months ago. Managed to get around 8k at 60 fps on 1 thread on my cpu, using golang.

My goal for this experiment was to encode the optimal cache data structures into meta programming generators such that claude can write high level DSL and generate down to this level of simulations. I am curious if you had such an approach also.

That's very interesting, thanks for commenting. Not my approach, I have a multithreaded Rust kernel (SoA, spatial hash, bounded-kNN, rayon on some passes). The agents sit on top of several diffuse fields, an econ layer and combat logic, all of it needing bit-determinism for the netcode.

I do use some metaprogramming, but as safety rather than generation: a declarative macro derives the modifier struct, defaults, parsing and wire order from a single list, and feeds hash/save/resync so I can add mechanics at a high level without being able to desync the sim. Also a set of probes help me test for correctness and speed after a change. So seems like I'm taking an iteration speed approach with safeguards, checking after the fact, while yours is optimizing beforehand by trying to encode optimal structs. That's fascinating, it will probably occupy my head for a good portion of the day, thanks again.

  • I went full meme, and stacked like 3 level of generators on top of eachother.

    Level 1: A basic generator does the same stuff: Raw Structs to SoA + Wire Codecs + Bitfields to not waste space.

    Level 2: Then on top of this one, I got a generator for relation between entities.

    Level 3: And on top of this one one for "game" design and schema behavior.

    And then all this runs on the simluator engine that handles Collision, Flow Fields, Events, Genetic Algorithms, Networking, etc.

    The flow is something like this:

    You ask claude to read a story, novel, w/e and extract relations, entities, etc.

    Then it edits a Schema.go with the High Level DSL adnotations, like 10 lines per entity.

    Then I run the Level 2 Generator: That creates the primitives and a high level API.

    Then it combines the high level API rules in main.go and just compiles it to the final gamestate.

    And runs benchmarks to see how many allocs/ops per entity are.

    And one more fun thing, it encodes the gamestate on 1400 bytes, in order to fit on a UDP datagram such that it can support networking, quite fun. Once you get the primitives correct.

    For all this + networking + disk i/o; works on 4 cores (threds) only. But the simulation in itself is on 1 core 1 thread. The networking offloaded to 1 core (1 thread), and disk i/o to a different core (thread), and the painting on screen (to a different core (thread))