Tag: rust

  • From Pong AI to Play Store: How a Childhood Hobby Became a Rust Game Engine

    The first game I wrote with any real ambition wasn’t a game. It was a NEAT implementation that learned to play Pong. I wasn’t trying to ship anything — I was trying to understand how a system could learn to do something I taught it.

    That question has been running in the background of everything I’ve built since.


    TurboShells came next. I took the NEAT studies from PyPong and asked: what if instead of teaching an AI to hit a ball, I bred turtles? Each turtle’s body was drawn entirely from its genes — no sprites, pure math. Shell radius, leg length, color — all expressed from a genetic sequence at render time. They raced. The faster ones bred. The slower ones didn’t.

    Nobody played TurboShells. But I learned something: the genetics loop — dispatch a breeding pair, wait for the outcome, observe the consequence — was more interesting to me than any game mechanic I’d seen. I wasn’t building a racing sim. I was building a system that made things happen without me.


    ChimeraLab was the first time I tried to give the genetics a body.

    Custom 3D creature rendering. SpineComponents — oblongs stacked together, body parts articulated from code. I got a humanoid assembled. I gave it a skeleton. I ran the simulation.

    It fell to the floor under its own weight.

    I never did fix the bipedal problem. But I got it to transition from two legs to four using a slider, and watching that happen — a creature renegotiating its relationship with gravity in real time — taught me more about 3D rendering than any tutorial I’d read. Sometimes the failure is the lesson.


    rpgCore was the foundation I should have built first. A thousand tests. Real ECS architecture. Genetics, lifecycle, dispatch — everything composable, everything verified. SlimeGarden put it to work: an astronaut crash-lands on an unusual planet and finds slimes. Breed them. Dispatch them. See what comes back.

    It sounds simple. It wasn’t. And it pointed somewhere.


    Seven projects in, I was staring at the Google Play Store submission checklist.

    OperatorGame ran on Android. Real Rust, real Bevy, real APK on a real phone. The combat worked. The UI was clean. I’d solved the hard problems.

    The submission required a 512×512 app icon, a 1024×500 feature graphic, and two screenshots.

    I didn’t have any of them.

    I could have made them. It would have taken an afternoon. But sitting there looking at that checklist, I realized the assets weren’t the problem.

    The problem was I had no audience. I was about to pay the Play Store’s attention tax — discoverability weighted toward downloads, downloads toward reviews, reviews toward players who found you somehow — with zero players behind me. I wasn’t Android Store money-ready. I was Itch.io audience-ready.

    Those are different things. Confusing them is expensive.


    Here’s what the journey looked like from the inside:

    PyPong AI taught me how systems learn. TurboShells taught me that genetics loops are more interesting than game mechanics. ChimeraLab taught me that creatures fall down and that’s instructive. rpgCore gave me the foundation. SlimeGarden gave the foundation a story. OperatorGame proved the Android pipeline. VoidDrift took the dispatch loop — Scout mines ore, returns, consequence — and dressed it in something people want to watch.

    Every project is the same loop. Something dispatches. It does its work. It returns with a result. Something changes.

    I’ve been building that loop for years. I just didn’t see it until I looked at the list.


    The lesson isn’t “don’t aim for the Play Store.”

    It’s: know what you’re ready for. The Play Store is a distribution problem you solve after you have players, not before. Itch.io is where you find out if anyone cares. If they do, the Play Store is a next step. If they don’t, you learned that cheaply instead of expensively.

    VoidDrift is on Itch right now. A small audience that keeps coming back. That’s the signal I was missing with OperatorGame.

    When the audience is real, the Play Store assets take an afternoon.


    There’s a story that keeps circling my mind. Someone in a ship, traveling through a black hole, becoming something else. They find a station. What follows is a macabre exploration of self — what survived the transit, what didn’t, what the new thing is capable of.

    VoidDrift is the ship and the void. SlimeGarden is the crash-landing after.

    The loop doesn’t end at the Play Store. It ends when the story does.

    The Scout dispatch loop in VoidDrift is the same loop TurboShells was running — breed, wait, observe — dressed in space mining clothes, nine projects later. Phase 5 is live. The Play Store listing is three PNGs away.

    The story is still circling. I’m still building toward it.

  • Building a Mobile Idle Game in Rust/Bevy Without a Game Engine Background

    Building a Mobile Idle Game in Rust/Bevy Without a Game Engine Background

    The line appeared one night and wouldn’t leave:

    The station has been here longer than you. It should have been consumed. It has not been. You don’t know why.

    I didn’t know what kind of game it belonged to. I spent months carrying it before I found out.


    VoidDrift is a mobile idle game where you mine asteroid debris at the edge of a black hole. You build a drone fleet. Factions you don’t understand start sending messages. There’s no win condition. The horizon is a one-way membrane.

    I had no game engine background when I started. I’d built systems — ECS architectures in Python, simulation loops, procedural generators — but I’d never shipped a game. I picked Rust and Bevy because the pipeline I needed (Android and WASM from a single codebase) pointed there. The ECS paradigm took time to click. My first systems were monolithic messes that tried to own too much.


    The breakthrough wasn’t a technical insight. It was administrative discipline.

    I forced myself to write an ADR — an Architecture Decision Record — before touching any major decision. ADR-003: bevy_egui for all HUD because Mali GPU stabilization on Android required it. ADR-007: system partitioning because Bevy’s scheduler hits a 20-tuple limit faster than you expect. Every constraint that would have sent me into a three-day refactor got documented before it became one.

    Bevy 0.15 with bevy_egui 0.33 has a specific problem nobody warns you about: egui::Window click events are broken in the Update schedule. The fix is painter + ui.interact(). I know that because I hit the wall, diagnosed it, and wrote it down. The ADR system means I don’t rediscover the same walls twice.


    What didn’t work: scope. I wanted branching faction storylines, a full three-ring resource economy, Mk II drone tiers, a complete Human-versus-Signal narrative arc. None of that is in the current version. What shipped is a focused mining loop, a production tree, and enough faction voice to suggest something larger without explaining it.

    The unexplained parts are intentional now. They weren’t when I started.


    VoidDrift is live on itch.io — Android and WASM from the same codebase. 505 views, 10.4K impressions. A small audience that keeps coming back.

    The Play Store is three assets away. An app icon, a feature graphic, two screenshots. Not a code problem. An afternoon problem I haven’t made time for yet.


    The station is still there. The factions are still watching. The black hole is still waiting.

    Some games tell you everything. VoidDrift tells you enough to make you wonder about the rest. That constraint — deliberate incompleteness — turned out to be the best decision I didn’t plan to make.

  • The Hybrid Engine: Rust Performance, Python Agility

    The Hybrid Engine: Rust Performance, Python Agility

    The problem with DeFi trading bots is speed. The problem with fast code is that it’s expensive to change.

    A pure-Rust bot wins the race to the block — compiled, deterministic, fast. When the market shifts and your strategy needs to change, you recompile. Overnight. While your edge evaporates.

    A pure-Python bot iterates in minutes. It also loses to anything compiled. In a system where the difference between capturing an arbitrage and missing it is milliseconds, interpreted code is a structural disadvantage.

    I needed both. So I built a bridge.


    The hybrid architecture splits responsibility at the right seam. The Rust core handles everything where latency matters: WebSocket connections, memory-safe transaction signing, packet serialization. Compiled, stable, rarely touched. The Python strategy layer sits above it, communicating through a lightweight interface. When the trading logic changes — when a pattern emerges, when a parameter needs tuning, when a strategy turns unprofitable — you change the Python. No recompile. The execution layer keeps running.

    Decoupling execution from intelligence meant iteration speed became unconstrained by compilation time. A new strategy at midnight, tested by 2am, discarded by morning without touching Rust.


    The bridge itself was the hard part. Any interface between two languages has a seam, and seams are where bugs live. Getting data structures consistent on both sides — ensuring what Rust serializes is exactly what Python expects — required more care than either side alone. When something went wrong, it could be Rust, Python, or the interface between them. You learn to test both sides independently before trusting the combination.


    PhantomArbiter ran 400 live trades on Solana in 2025. The architecture worked. The margin didn’t scale — the arbitrage windows were narrower in practice than in theory, and at volume the economics didn’t justify the infrastructure.

    But the pattern was correct. Compile what doesn’t change. Script what does. The intelligence layer should be easy to replace. The execution layer should be hard to break.

    That principle didn’t stay in trading. It’s in every complex system I’ve built since — MCP tools handle execution, the model handles intelligence, and the interface between them is where the design lives.

    I didn’t keep trading. I kept the pattern.

  • Solana Arbitrage: What I Learned From 400 Trades (And $4 in Losses)

    Solana Arbitrage: What I Learned From 400 Trades (And $4 in Losses)

    I built PhantomArbiter to detect and execute arbitrage on Solana. After 400 live trades across 3 months, I lost $4. Here’s what went wrong — and why the technology actually worked.


    The Setup

    Detect price divergence across Solana DEXes (Jupiter, Raydium, Orca, Meteora). Execute buy-low / sell-high atomically via JITO bundles for MEV protection.

    $500 initial capital. Real money. 3 months. 400 completed trades. Net result: -$4.23.


    Why It Failed

    RPC Latency

    Solana blocks come every 400ms. The system detects an opportunity, but by the time the bundle submits, 2-3 blocks have passed. The spread that looked profitable is now break-even or negative.

    Local detection: 10ms. RPC call: 50ms. Signature submission: 100ms. Next block: 400ms. Too slow.

    Professional MEV bots use validator infrastructure — direct connections, guaranteed inclusion. I used public RPC. Not competitive.

    Network Congestion

    Solana’s network is unpredictable. Sometimes transactions confirm in 1 block. Sometimes 10. Arbitraging on 1-2% margins, network variance turns winning trades into losing ones. My math said $2.50 profit. Slippage ate it before execution landed.

    Bundle Fees

    JITO bundles cost ~0.00005 SOL per transaction — $0.002-0.004 per trade. 400 trades, ~$1-1.50 in fees. The average arbitrage spread before costs was around $1.50. After slippage, fees, and MEV tax, nothing was left.


    Why It Actually Worked

    The system architecture was sound. 400 trades without a crash:

    Zero transaction failures. Zero contract bugs. Zero memory leaks. Stable WebSocket price feeds for 24/7 uptime.

    The software worked perfectly. The economic model didn’t. That’s an important distinction.

    Arbitrage at retail scale on Solana isn’t viable right now — not because the code is broken, but because professional operations have better infrastructure, lower fees, larger capital to absorb slippage, and faster access to the same opportunities. The edge isn’t available at the level I was operating.


    What I Kept

    The Rust/Python hybrid architecture — Rust handling the execution layer, Python handling strategy logic — transferred into other work. The execution core doesn’t know what it’s trading. The strategy layer doesn’t know how fast the core is running. That decoupling is the right design regardless of what market it’s applied to.

    The code got archived. The pattern didn’t.

    PhantomArbiter trades live markets, handles real network conditions, survives real slippage, and loses money honestly. Most trading systems are backtested and overfitted, profitable in theory but brittle in practice, or they don’t exist at all. A system that ran 400 live trades and lost four dollars is actually a reasonable outcome. It proved what it needed to prove.

    I didn’t keep trading. I kept the blueprint.