Life update (02/02/2026)

These last four days I’ve felt the darkness gathering at the edges of my being. Losing any intention of going outside. Lying in bed and hoping I wouldn’t get to wake up and endure any more.

A couple of hours ago I lay down, put on my VR headset, and tried to concentrate on watching a movie from the seventies (concretely Serpico). The other day was The Conversation. For whatever reason, I’ve always felt a pull toward the 1970s, even before Alicia Western. A feeling that somehow I belong to that time. Experiencing things from that era fills me with a nostalgia that hollows out my chest. The strong notion that I should have been there, should still be there. Another one of the many things in my life I haven’t understood about myself.

I’ve always felt uncomfortable among human beings, likely due to autism, and that doesn’t change much when I have to see people on a screen. To focus on a movie I have to get over a base ickiness, a discomfort. So much of what I see on a screen feels alien to me: how people interact with each other, how they react to things. Watching stuff from the 1970s adds a layer on top of that; it’s already been fifty fucking years, but it feels like it a whole different era. As if everyone from back then had been dead for a long, long time. And there are the absurd pains, like a moment when Al Pacino as this Serpico dude walks down the street and touches a girl’s head, and I wonder what happened to that person’s life. Her next fifty years of enduring on this earth. Is she alive or is she dead.

I haven’t been able to watch any of the movies I’ve tried recently for more than twenty minutes at a time or so. Maybe it’s depression-induced anhedonia. Maybe I’ve genuinely been losing my ability to enjoy things. Novels haven’t said much to me in a long time, and the only ones I cared for in the last few years or so were McCarthy’s works, someone whose soul was tragically anchored in the seventies. I’m no longer at an age in which I can lose myself in videogames; I know there are great stories waiting for me in stuff like Red Dead Redemption 2, but whenever I reinstall it, I play it once for like four hours, and then I can’t bring myself to launch it again.

I was born in Spain but I’ve never felt like I belong here. Technically I was born in the Basque Country region, but I’m not a separatist. I don’t connect with the locals. Things are so fucking bad here; we’re easily the most retarded country in Europe, that in no time will get even worse than the UK, France and Belgium when it comes to ethnic cleansing of the indigenous people. I have no hope for Spaniards, as I’ve had to work with your average one; all of them hooked to the state-sponsored media. They smugly spout the socialist garbage they’ve been fed as if they couldn’t conceive anyone thinking differently. They don’t even see it as politics; for them, that’s the natural state of things, and if you disagree, you’re a freak. The few times I’ve made the mistake of giving them an inch, hearing their thoughts beyond work-related matters reminded me again why I shouldn’t have.

In general, I feel like I’ve been dead for a long time and my body is taking decades to figure it out. Whenever that actually comes, I don’t think I’ll miss or feel any particular attachment to the stuff that at the time seemed so important to me: the stories I’ve written, the music I’ve loved, other projects of mine. It served its purpose while they happened, then they ceased being mine. I’m around because I’m around, then at some point I’ll cease to be and that’ll be that.

In a month or so I’ll have to start looking for a job. I don’t believe I’ll get hired as a forty-year-old programmer in this new era in which AI can do the work of a whole office of programmers. I’ll probably have to look for protected job as someone with a 52% disability. And I won’t do it for any other reason than the money. It seems there are people out there that get other benefits from the job: interacting with people, dealing with responsibilities… I want none of that. Working has always been a hell I had to get through merely to receive money at the end of the month.

Last time I spoke with my mother she asked me about work. I told her again that I don’t care about any of it. These “normal” people always try to deceive you, maybe because they deceive themselves, by going on about how jobs are more than things you endure because of money. And maybe it is for some people, but not for me. The last time they called me for a job in IT, which ended up falling through, I suffered a panic attack, my whole body telling me that I couldn’t return to that hell that put me thrice in the ER for heart and brain issues. I can’t allow myself to suffer the levels of stress I endured. No amount of money is worth that.

I guess that’s all I had to say at the moment. Not sure why I felt like saying any of it, who do I think is reading any of this, or why they would care about it.

LudoForge #4

Now that the evolutionary process to grow game definitions is progressing at a steady pace in my app, named LudoForge, I fed the architectural docs to ChatGPT so that it would write a good explanation on how it works. It may be interesting to those curious about how complex systems can grow organically through an evolutionary algorithm that mimics biological evolution.


Teaching a computer to invent tabletop games (and occasionally rediscover the classics)

If you squint, evolving game designs is a lot like evolving creatures: you start with a messy ecosystem of “mostly viable” little organisms, you test which ones can survive in their environment, you keep the best survivors—but you also keep a diverse set of survivors so the whole population doesn’t collapse into one boring species.

In our system, the “organisms” are game definitions written in a small, strict game DSL (a structured way to describe rules: players, state variables, actions, effects, win/lose conditions, turn order, and so on). Each candidate game definition is wrapped in a genome: basically an ID plus the full definition.

From there, the evolutionary loop repeats: seed → simulate → score → place into niches → mutate elites → repeat.

1) Seeding: where the first games come from

Evolution needs a starting population. We can generate seeds automatically, or import them from disk, or mix both approaches. The important bit isn’t “are the seeds good?”—it’s “are they valid and diverse enough to start exploring?”

So seeds must pass two kinds of checks before they’re even allowed into the ecosystem:

  • Schema validation: does the JSON structure match the DSL’s required shape?
  • Semantic validation: does it make sense as a playable ruleset (no broken references, impossible requirements, etc.)?

And there’s a third, subtle filter: when we place games into “niches” (more on that below), seeds that land only in junk bins like unknown/under/over are rejected during seed generation, because they don’t help us cover the design space.

Think of this as: we don’t just want “a bunch of seeds,” we want seeds scattered across different climates so evolution has many directions to run in.

2) Playtesting at machine speed: simulation as the “environment”

A human can’t playtest 10,000 games a day. A simulation engine can.

For every candidate game, we run automated playthroughs using AI agents (simple ones like random and greedy are enough to expose lots of structural problems). The engine repeatedly:

  1. Lists the legal moves available right now
  2. Checks termination (win/lose/draw conditions, cutoffs, loop detection)
  3. Lets an agent pick an action (with concrete targets if needed)
  4. Applies costs and effects, recording what happened
  5. Advances the turn/phase according to the game’s turn scheduler

Crucially: when a complex game definition tries to do something illegal (like decrementing below a minimum, or targeting something that doesn’t exist), the engine records skipped effects/triggers instead of crashing, so the system can observe “this design is broken in these ways” rather than just failing outright.

This is the equivalent of an organism interacting with the world and leaving tracks: “it tried to fly, but its wings didn’t work.”

3) Turning playthroughs into numbers: metrics, degeneracy, and fitness

After simulation, we compute a set of analytics that act like proxies for design quality—things like:

  • Agency: did players have meaningful choices, or were they railroaded?
  • Strategic depth (proxy): how large is the typical decision space?
  • Variety: do many different actions get used, or does one dominate?
  • Interaction rate: are players affecting each other or only themselves?
  • Structural complexity: is this a tiny toy, or something richer?

These are not “fun detectors.” They’re sensors.

Then we run degeneracy detection: filters that catch the classic failure modes of randomly-generated rulesets:

  • infinite loops / repeated states
  • non-terminating games (hits max turns/steps)
  • games with no real choices
  • trivial wins, dominant actions, excessive skipped effects, etc.

Some degeneracy flags cause an outright reject (hard gate), others apply a penalty (soft pressure), and too many penalties at once can also trigger rejection.

Finally, all of this becomes a feature vector, and we compute an overall fitness score—the number evolution tries to increase.

4) “Growing in niches”: why we don’t keep only the top 1%

If you only keep the single highest-scoring game each generation, you get premature convergence: the population collapses into one design family and stops surprising you.

Instead, we use MAP-Elites, which you can picture as a big grid of “design neighborhoods.” Each neighborhood is defined by a few chosen descriptors (think: agency bucket, variety bucket, etc.). Each candidate game gets “binned” into a niche based on its descriptor values, and then it competes only with others in that same niche.

  • Each niche keeps its best resident (the “elite”).
  • Over time, the map fills with many different elites: fast games, slow games, chaotic games, skillful games, high-interaction games, and so on.

This is how you get a museum of interesting survivors, not one monoculture.

5) Reproduction: mutation (and why mutation is structured, not random noise)

Once we have elites across niches, we generate the next generation by mutating them.

Mutation operators aren’t “flip random bits.” They are rule-aware edits that make plausible changes to game structure, such as:

  • tweak a number (thresholds, magnitudes)
  • add/remove/duplicate actions (with safety guards so you can’t delete the last action)
  • add/remove variables (while rewriting dangling references)
  • change turn schedulers (round-robin ↔ simultaneous ↔ priority-based, etc.)
  • add triggers and conditional effects
  • modify termination rules (win/lose/draw conditions)

The key is: the operator library is rich enough to explore mechanics, not just parameters.

Mutation retries (because many mutations are duds)

Some mutations do nothing (“no-op”), or produce something that can’t be repaired. The runner will retry with a different operator a few times; if it still can’t produce a productive mutation, it falls back to keeping the parent for that offspring slot.

This keeps evolution moving without pretending every random change is meaningful.

6) Repair, rejection reasons, and staying honest about failure

After mutation, we may run repair (optional), then validation and safety gates. If a candidate fails, it’s not just dropped silently—the system classifies why it failed:

  • repair failure
  • validation failure
  • safety failure
  • evaluation error
  • evaluation returned null fitness/descriptors

And it persists these outcomes for observability and debugging.

This matters because “evolution” is only useful if you can tell whether the ecosystem is healthy—or if you’ve started breeding nonsense.

7) Adaptive evolution: learning which mutations are actually useful

Not all mutation operators are created equal. Some will be reliably productive; others will mostly create broken genomes.

So the runner tracks per-operator telemetry every generation: attempts, no-ops, repair failures, rejection counts, and how often an operator actually helped fill a new niche or improve an elite. evolution-runner

Those stats feed into adaptive operator weighting, so the system gradually shifts its mutation choices toward what’s working in the current region of the design space—without hardcoding that “operator X is always good.”

8) Optional superpower: motif mining (stealing good patterns from winners)

Sometimes an evolved game contains a little “mechanical phrase” that’s doing real work—like a neat resource exchange loop, or a repeating pattern of effects that creates tension.

When motif mining is enabled, we:

  1. select elites (top per niche + global best)
  2. re-simulate them to extract trajectories
  3. mine repeated effect sequences (“motifs”)
  4. convert those motifs back into DSL effects
  5. feed them into a special mutation operator that can inject those motifs into new games

That’s evolution discovering a useful mechanic, then turning it into reusable genetic material.

9) Human taste enters the loop (without turning it into manual curation)

Metrics are helpful, but “fun” is subjective. So we can add human feedback:

  • ratings (“how good is this?”)
  • pairwise comparisons (“A or B?”)

Rather than asking the human to judge random games, the system uses active learning to choose the most informative comparisons—especially cases where its preference model is uncertain, and it tries to include underrepresented niches so taste is learned across the map.

Under the hood, the preference model is an ensemble trained online (so it can update continuously) and its uncertainty controls how much feedback to request per generation (adaptive budget).

Fitness can then blend:

  • “objective-ish” signals (metrics/degeneracy)
  • “human preference” signals

So the system doesn’t just breed games that are non-broken—it breeds games that align with what you actually enjoy.

10) Why this can rediscover known games and invent new ones

If your DSL is expressive enough to describe the rules of an existing game, then in principle there exists a genome that encodes it. Evolution doesn’t need to “know” the game—it only needs:

  1. Search operators that can reach that region of the rulespace (structural mutations, not just numeric tweaks)
  2. Selection pressure that rewards the behaviors that make that game work (choice, balance, interaction, clean termination, etc.)
  3. Diversity preservation so the system keeps exploring many styles instead of collapsing early

Once those are in place, rediscovery becomes a side-effect of searching a huge space under the right constraints. And invention is what happens when evolution stumbles into combinations nobody tried on purpose—then keeps them because the ecosystem rewards them.

The simplest mental model

If you want the non-technical version in one breath:

We generate lots of small rulesets, machine-play them thousands of times, score them for “does this behave like a real game?”, sort the survivors into many different “design neighborhoods,” keep the best in each neighborhood, then make mutated children from those survivors—occasionally learning from human taste and reusing discovered mechanics—until the map fills with strong and varied games.

That’s the evolutionary process: not magic, not random, but a relentless loop of variation + playtesting + selection + diversity.

LudoForge #3

If you don’t know about LudoForge, you should probably read the previous posts. In summary: I’m developing an app to evolve tabletop game prototypes according to a “fun” factor made up of plenty of fun proxies like player agency, strategic depth, etc. The code is now mature enough to run X evolutionary generations on demand, produce shortlists of the best games, and finish. That’s great because it means the code works well, although there’s always room for improvement. But the shortlist of four winners is absolutely terrible in a way that has had me giggling for a while. I’ll let ChatGPT explain these “games.”


Game 1: “The Shared Counter Chicken”

Two players take turns. There’s a shared number on the table that starts at 0 and can be increased up to 15. The “win condition” is simple: whoever makes it hit 15 wins instantly.

The game also includes a couple of other buttons that change other numbers… but those numbers can never actually produce a win. They’re basically decorative dials. One of them always gets set to 12, but the victory threshold for it is 20, so it’s like having a “Launch Rocket” button that always fuels you to 60% and then stops forever.

So what do players really do? They increment the shared counter… and then start playing a tiny psychological game of chicken: “I could push the counter closer to 15… but then you might get the final move.” So the game hands them some useless actions that function as “stalling.” If both players are stubborn, they can just keep stalling until the match times out.

It’s not strategy so much as who blinks first.

Game 2: “The Game Where You Can’t Move”

This one is my favorite kind of failure because it’s so clean.

The game defines two counters. The only action in the entire game says: “Decrease both counters.”

But the action is only allowed if both counters are greater than zero.

And the game starts with both counters at zero.

So on turn one, a player looks at the rules and… there is literally nothing they’re allowed to do. No move exists. The game doesn’t even fail dramatically. It just sits there like a vending machine with the power unplugged.

In other words: it’s a tabletop game prototype that begins in a stalemate.

Game 3: “First Player Loses: The Speedrun”

This one actually runs, which makes it even funnier.

There are two counters. One counter is the only one that can possibly lead to a win — the other one only goes downward forever, so its “win condition” is a permanent lie.

The “real” counter starts at 0, and there’s an action that increases it by 2. The victory threshold is 4.

Here’s what happens:

  • Player 1 goes first. Their only sensible move is: 0 → 2.
  • Player 2 goes next and does the same move: 2 → 4.
  • Player 2 instantly wins.

So the entire “game” is basically:

“Player 1 sets up the win for Player 2.”

It’s like a sport where the first player is forced to place the ball on the penalty spot and then politely step aside.

Game 4: “The Unwinnable Ritual”

Three players this time. There’s one shared counter. Winning requires the counter to reach 4.

But the rules only let you do two things:

  • Set it to 2.
  • Decrease it by 2 (if it’s above zero).

Notice what’s missing: any way to make it bigger than 2.

So the win condition is a castle in the sky. The game is a ritual where players take turns setting the number to 2, or knocking it back down toward 0. It can never, ever reach 4. No amount of cleverness changes that.

It’s essentially a machine that cycles between “2” and “less than 2” until you get bored or the turn limit ends it.


ChatGPT finished its report with this note: “The first evolutionary run didn’t produce brilliant board games. It produced life, in the same way early evolution produced algae and sea foam. These were rule-sets that technically existed… but didn’t yet deserve to.”

These idiotic games already provided fun by existing, so as far as I care, this app has already been a success. The good thing is that I have code to handle degeneracy, fitness, etc., so I simply have to tighten that code so some of these nonsensical points would either kill a genome or penalize its fitness.

By the way, earlier tonight I was playing tennis in VR with people across Europe while I waited for Claude Code to work through the tickets of one of the app’s new features. And yet the world is terrible. We live in the lamest cyberpunk dystopia imaginable.

LudoForge #1

Two nights ago I was rolling around in bed trying to sleep when a notion came into my head, one that has returned from time to time: some of the most flow-like fun I’ve ever had was playing tabletop games. I’m a systems builder by nature, and I love to solve problems with a variety of tools. Tabletop games are complex problems to solve with specific series of tools. My favorite tabletop game is Arkham Horror LCG, although I’ve loved many more like Terraforming Mars, Ark Nova, Baseball Highlights: 2045, Core Worlds, Imperium, Labyrinth, Renegade… But none of them fully captured me. Like some potential game exists that has exactly every feature my brain yearns for, but that game doesn’t exist. I’ve cyclically thought that I should create that game, but I never know where to start. I don’t even know what exactly I want, other than knowing that what I’ve experienced isn’t enough.

These past few weeks I’ve been implementing extremely-complex analytics reports generators for my repository Living Narrative Engine. I was surprised to find out that it’s feasible to mathematically find gaps in extremely complex spaces (dozens of dimensions) as long as they’re mathematically defined. I guess Alicia was justified to be obsessed with math. So I started wondering: what makes a tabletop game good? Surely, the fun you have with it. Can “fun” be mathematically defined? Is it the agency you have? The strategic depth? The variety? If any of such metrics could be mathematically defined, then “fun” is a fitness score that combines them.

And what if you didn’t need to design the game yourself? If you can map a simulated game’s activity to metrics such as the agency per player, the strategic depth, the variety… Then you can evolve a population of game definitions in a way that, generation after generation, the “fun” score improves. If you can turn all game mechanics into primitives, the primitives will mutate in and prove their worth throughout the generations, composing coherent mechanics or even inventing new ones. Initially, a human may need to score game definition variants according to how “fun” the playthrough of those games were, but in the end that could be automated as well.

Because this is the era of Claude Code and Codex, I’ve already implemented the first version of the app. I’ve fed ChatGPT the architectural docs and told it to write a report. You can read it down below.


LudoForge: evolving tabletop games with a deterministic “taste loop”

I’m building LudoForge, a system that tries to answer a pretty blunt question:

What if we treated tabletop game design like search—simulate thousands of candidates, kill the broken ones fast, and let a human “taste model” steer evolution toward what’s actually fun?

Under the hood, it’s a seeded-population evolution loop: you start with a set of game definitions (genomes), run simulations, extract metrics, filter degeneracy, blend in learned human preferences, and then evolve the population using MAP-Elites and genetic operators. Then you repeat.

The big picture: the loop

LudoForge is structured as a pipeline with clean seams so each layer can be tested and swapped without turning the whole thing into spaghetti. The stages look like this: seed → evaluate → simulate → analytics → (optional) human feedback → fitness → MAP-Elites → (optional) mutate/crossover/repair → next generation. pipeline-overview

A key design choice: the core expects a seeded population. There’s no “magic generator” hidden inside that invents games from scratch. If you want a generator, you build it outside and feed it in. That keeps the engine honest and debuggable. Note by me after rereading this part of the report: this will change soon enough.

Games as genomes: a DSL that can be validated and repaired

Each candidate game is a genome: { id, definition }, where definition is a DSL game definition. Before any evaluation happens, the definition goes through schema + semantic validation—and optionally a repair pass if you enable repair operators. Invalid DSL gets rejected before it can contaminate simulation or preference learning.

Repair is deliberately conservative: it’s mostly “DSL safety” (e.g., clamp invalid variable initial values to bounds). Anything that’s “this game is technically valid but dumb/unplayable” is handled by simulation + degeneracy detection, not by sweeping edits that hide the real problem.

The simulation engine: deterministic playthroughs with real termination reasons

The simulation layer runs a single playthrough via runSimulation(config) (or wrapped via createSimulationEngine). It builds initial state from the definition, picks the active agent, lists legal actions, applies costs/effects/triggers, advances turns/phases, and records a trajectory of step snapshots and events.

It’s also built to fail safely:

  • No legal actions → terminates as a draw with terminationReason = "stalemate".
  • Max turns exceededterminationReason = "max-turns" with an outcome computed in that cutoff mode.
  • Loop detection (optional hashing + repetition threshold) → terminationReason = "loop-detected".

Most importantly: runs are reproducible. The RNG is a seeded 32-bit LCG, so identical seeds give identical behavior.

Metrics: cheap proxies first, expensive rollouts only when you ask

After simulation, LudoForge summarizes trajectories into analytics: step/turn counts, action frequencies, unique state counts, termination reasons, and sampled “key steps” that include legalActionCount.

From there it computes core metrics like:

  • Agency (fraction of steps with >1 legal action)
  • Strategic depth (average legal actions per step)
  • Variety (action entropy proxy)
  • Pacing tension (steps per turn)
  • Interaction rate (turn-taking proxy)

Extended metrics exist too, and some are intentionally opt-in because they’re expensive:

  • Meaningful choice spread via per-action rollouts at sampled decision points
  • Comeback potential via correlation between early advantage and final outcome

Here’s the honest stance: these metrics are not “fun”. They’re proxies. They become powerful when you combine them with learned human preference.

Degeneracy detection: kill the boring and the broken early

This is one of the parts I’m most stubborn about. Evolution will happily optimize garbage if you let it.

So LudoForge explicitly detects degeneracy patterns like:

  • loops / non-termination
  • stalemates
  • forced-move and no-choice games
  • dominant-action spam
  • trivial wins metrics-and-fitness

By default, those flags can reject candidates outright, and degeneracy flags also become part of the feature vector so the system can learn to avoid them even when they slip through.

Human feedback: turning taste into a model

Metrics get you a feature vector. Humans supply the missing ingredient: taste.

LudoForge supports two feedback modes:

  1. Ratings (1–5) with optional tags and rationale
  2. Pairwise comparisons (A/B/Tie) with optional tags and rationale

Pairwise comparisons are the main signal: they’re cleaner than ratings and train a preference model using a logistic/Bradley–Terry style update. Ratings still matter, but they’re weighted lower by default.

There’s also active learning: it selects comparison pairs where the model is most uncertain (predicted preference closest to 0.5), while reserving slots to ensure underrepresented MAP-Elites niches get surfaced. That keeps your feedback from collapsing into “I only ever see one genre of game.”

Fitness: blending objective proxies, diversity pressure, and learned preference

Fitness isn’t a single magic number pulled from the void. It’s a blend:

  • Base composite score from metrics (weighted sum/objectives)
  • Diversity contribution (pressure toward exploring niches)
  • Preference contribution from the learned preference model (centered/capped, with bootstrap limits early on)

Feature vectors are keyed by metric id (not positional arrays), which matters a lot: adding a new metric doesn’t silently scramble your model weights. Renaming metrics, though, becomes a migration event (and that’s correct—you should feel that pain explicitly).

Evolution: MAP-Elites + mutation/crossover that respect DSL validity

Instead of selecting “top N” and converging into a monoculture, LudoForge uses MAP-Elites: it bins candidates into descriptor niches and keeps the best elite per niche.

Descriptor binning is explicit and deterministic (normalize → floor into bin count; clamp to range), and niche ids serialize coordinates like descriptorId:bin|....

Then you can evolve elites with genetic operators:

  • Mutations like numeric tweaks, boolean toggles, enum cycling, duplicating/removing actions, nudging effect magnitudes, adding/removing phases, rewriting token/zone references safely, etc.
  • Crossover via subtree swaps of state.variables or actions, followed by DSL re-validation.

Optional “shortlisting” exists too: it picks a diversified subset of elites for human review using a max-min distance heuristic over descriptor coordinates.

What’s already proven (and what isn’t yet)

This isn’t vaporware; the end-to-end tests already prove key behaviors like:

  • the ordered phases of the pipeline
  • invalid DSL rejection before evaluation
  • safety cutoffs (max-turns) and deterministic seeded outputs
  • human prompt loops and legality enforcement
  • deterministic state transitions
  • MAP-Elites producing stable ids
  • active learning selection behavior
  • mutation + repair at scale, including crossover

And there are explicitly documented gaps—like extended metrics aggregation and worker-thread batch simulations.

The point of LudoForge

I’m not trying to build a “game designer replacement.” I’m building a design pressure cooker:

  • Simulate hard
  • Reject degeneracy ruthlessly
  • Measure what you can
  • Ask humans the right questions
  • Let evolution explore breadth, not just a single hill

If you’re into procedural design, evolutionary search, or just enjoy the idea of treating “fun” as something you can iteratively approximate with a human-in-the-loop model, that’s what this project is for.

Living Narrative Engine #19

I have quite the treat for you fuckers. I’ve recorded myself playing through my test scenario involving Alicia Western. More than an hour of me speaking in my accented English even though I rarely speak in real life, and showing off a fun, frustrating playthrough that made me hungry.

This is, of course, related to my beloved Living Narrative Engine. Repo here.

Living Narrative Engine #18

I’m building a browser-based app to play immersive sims, RPGs and the likes. In practice, I use it to set up short story scenarios or elaborate gooning sessions. I dared myself to build the most comprehensive psychological system imaginable, so that Sibylle Brunne, a 34-year-old orphan living in her parents rustic home somewhere in the Swiss mountains, while controlled by a large language model, would realistically bring her blue-eyed, blonde-hair-braided, full-breasted self to seduce my teenage avatar who is backpacking through the country, eventually convincing me to stay in her house so she can asphyxiate me with her mommy milkers.

Here’s a visual glimpse of the current complexity:

Alicia has become my test subject, as if she didn’t have enough with freezing to death. The system works like this: at the base you have mood axes (like pleasant <-> unpleasant), which change throughout a scene. Actors also have permanent biological or personality-based traits like aversion to harm. Together, mood axes and affect traits serve as weights and gates to specific emotion prototypes like disappointment, suspicion, grief. Delta changes to those polar mood axes naturally intensify or lessen the emotions. I also have sexual state prototypes, which work the same as the emotional states.

These emotional and sexual states serve as the prerequisites for certain expressions to trigger during play. An expression is a definition that tells you “when disappointment is very high and suspicion is high, but despair is relatively low, trigger this narrative beat.” Then, the program would output some text like “{actor} seems suspicious but at the same time as if they had been let down.” The descriptions are far better than that, though. The actors themselves receive in their internal log a first-person version of the narrative beat, which serves as an internal emotional reaction they need to process.

It all works amazingly well. However, to determine if I was truly missing mood axes, affect traits or prototypes, I had to create extremely complex analytics tools. I’ve learned far too much about statistical analysis recently, and I don’t really care about it other than for telling a system, “hey, here are my prototype sets. Please figure out if we have genuine gaps to cover.” Turns out that to answer such a request, some complex calculations need to map 20-dimensional spaces and find out diagonal vectors that run through them.

Anyway, I guess at some point I’ll run my good ol’ test scenario involving Alicia, with her now showing far more emotion than she used to before I implemented this system. That’s a win in my book.

Life update (01/25/2026)

I had lunch with my parents earlier today, and ended up having a nasty political argument. My father is already about 76 years old and looking the part. As far as I can tell, he sits all day hooked up to socialist political talk shows. Barely talks to anyone, let alone his wife, on account of her psychological abusing him for decades. Anyway, during lunch, they had the local socialist radio on going on about disinformation. Basically that anything you see online that the government disagrees with are malicious lies, often AI-generated. In fact, the utter piece of garbage, traitorous bastard we have for a president (who likely stole the elections) was at Davos claiming that we should have a digital ID to end online anonymity.

I pointed out that a recent government organization had said that, according to an autopsy report regarding the forty-something people dead in a recent train crash (we had four in like five days), they all had died on impact. As if the WTC towers had fallen on them instead of these people being in different train cars. That whole thing about them dying on impact is a blatant lie, if only because survivors of the accident are on video and radio speaking about how they tried to assist others and had to leave behind folks who they know ended up dying. My mother mentioned that this was to hide the fact that help came about an hour later. Some recent report had even blamed the train conductor, even though several previous train conductors had alerted about the fact that the track involved in the accident had serious issues.

My father got this irate tone on and spoke up, which he rarely does, and asked where I got the information. I repeated the fact that victims are on video saying this, so the autopsy report must be either incompetence or deliberate lies. Then he brought up how when some natural disaster hit a part of the country governed by a non-socialist leader, their response wasn’t questioned this much. Then he got onto the US, as in “look what that piece of shit nutcase is doing, they’re the same ones that stormed the Capitol, they’re now shooting innocent people who were just trying to take photos, and this lady who they believe had guns in her car, but she only had a teddy bear.” Pretty sure there’s a video of the woman trying to run over an ICE agent after having led a movement to prevent them from deporting people who had no business being in the country. And although I’m not sure on the latest shooting, the video does show him reaching wildly for something in his pocket as the agents are trying to reduce him.

I disagree with Trump on many accounts, but not on which most people seem to from both sides of the political aisle, particularly what we see in the US. He’s right that illegal immigrants and even legal immigrants who are a detriment to the country (criminals for sure, but not necessarily) should get deported. We should do it all over the West. We’ve been deliberately ethnically cleansed for the last couple of decades; it’s been organized in a distributed, systematic manner to make this happen. In many major European capitals, ethnic Europeans are the minorities. In Spain, about 40% of under 18, if not more, are of foreign origin. This has never happened before in the history of mankind unless it was an overt genocide, like in the case of the Bell Beaker culture invading Iberia from somewhere in Europe, taking all women for themselves and preventing the local men from reproducing; the influence of male genes from those ancient Iberian peoples went down to damn near zero. Same thing is happening now. “Don’t have children; for the environment! Also, mass import violent third-world men while promoting miscegenation!”

Marxists implanted in the culture this whole racism nonsense, a word they invented. Human populations are biologically different, and therefore are better at some things and worse at others. Then, they declared that all ethnic Europeans are racist, from which follows that ethnic Europeans, the male ones at least, need to disappear. Again, overt ethnic cleansing. The existence and prosperity of ethnic Europeans should not be argued nor negotiated.

My issue with Trump is that he’s supposedly a christian, which I don’t like to begin with because it’s utter nonsense, but that in practice he’s a jew. It’s not Make America Great Again, but Make Israel Great Again. Israel and jews in general have been busy with propaganda these last hundred years or so to paint themselves as these blameless, put-upon group, but they hate our guts even more than they hate muslims, and they’ll eagerly join forces with muslims to Gaza us all. They aren’t our friends. Look up that recent video in Davos about a rabbi referring to us ethnic Europeans as “old Europeans,” and how jews and muslims should join forces against “antisemitism” and “islamophobia.”

I don’t believe in arguing because there’s no point. Ultimately people are built to hold the moral, political, philosophical positions they have. There was a study that surfaced somewhat recently that proved, although without a massive number of participants, that men’s empathy for someone decreased massively and their satisfaction increased when a cheater was punished, while in the case of women, their empathy was completely unrelated to the behavior, including crimes, of their targets of empathy. This was proven with neuroimaging or shit like that. In such feminized societies as ours have become, you only have to watch how they keep marching for mass immigration and the poor military-age browns even after thousands upon thousands of ethnic European girls have been raped at an industrial scale by gangs of muslims. Girls who wandered bloodied and dripping out of gang dens, having been raped by several men, and asked for help to the first man they saw in the streets, only for that other man, a muslim, to lock her in his flat and call over his cousins to rape her again for hours.

I remember an incident in a course I attended. I’ve mentioned it several times already. The organizers had implanted in the course a muslim male of about twenty years old, who was seemingly “in risk of societal exclusion,” which is how the traitors in charge label these individuals who are here to deliberately ruin the country. During a forced talk, a local non-attractive man, who was disabled, said that if he could choose whom to date, he would prefer not to date a disabled woman, because he already had a lot to deal with regarding his own disability, and it would be hard for him to handle. Two women in the course immediately berated him, saying how that was insensitive and offensive of him. Then the muslim man started talking about how in the weekends he went to clubs and accosted women. “They say no, but when a woman says no, more often than not they mean yes.” The same women who had berated the first local man were now giggling at the foreign invader who was spouting something that supposedly these same women have been up-in-arms against for decades.

None of this has any solution other than segregation. And I don’t mean necessarily of races (although yes, we should). You have to segregate yourself alongside other people whose brain wiring produce results that don’t screw up yours, then build walls around you so that outsiders can’t ruin it. 99,999% of humanity throughout the last 200,000 years or so we’ve had an anatomically modern brain already knew this.

manga2cbz: read manga in VR

I’ve been reading manga for a long time, usually relying on my old-ass tablet and scanlations (or whatever they’re called). I came across the Livro app for the Meta Quest 3, and I intended to read manga on it. However, I found out you can’t move the manga folders like you would on a tablet.

So, this morning I had Claude Code create a Go app that can be baked into a Linux/Windows exec to compress manga chapters into corresponding cbz files. Those files can just be copied into the Quest 3 through a link cable, and opened on Livro. Because Livro has trouble rendering WebP files, my app also converts WebP to PNG. As you can see in the video, it works.

Here’s the repo for the app:

https://github.com/joeloverbeck/manga2cbz