An Uncanny Moat

Back in the early days of computer animation, the technology at the time really struggled with realism. The first cartoons were necessarily abstract, or cartoony.

As time progressed, the technology caught up. CGI now can be all but indistinguishable from real life. But there was a brief period, as seen in films like The Polar Express or Final Fantasy: The Spirits Within, when the artists aimed for realism and didn’t quite get there.

These films were often critically panned. Eventually, it became clear that the cause was quite deep in the human psyche. These films were realistic enough that we’d mentally classify the characters as real humans, but not so realistic that they actually looked normal. On an instinctive level, people reject these imposters far harder than more stylised graphics that don’t have the pretence of reality.

This phenomenon is known as the Uncanny Valley and has influenced visual design of fake people in films, robots, games etc.

For a time, the recent crop of image generators and LLMs fell into the same boat. Twisting people with the wrong number of fingers or teeth was a common source of derision. People are still puzzling over chatbots that can speak very coherently and yet make wild mistakes with none of the inner light you might expect from a real conversationalist.

Now, or at least very soon, AI threatens to cross that valley and advance up the gentle hills on the opposite side. Not only are we faced with a disinformation storm like nothing before, but AI is going to start challenging exactly how we consider personhood itself.

This is something we need to fight, in addition to all the other worries about AI. I don’t want to get into philosophical weeds about whether LLMs could be considered moral patients. But I think our society and thinking are structured around a clear human/non-human divide. Chatbots threaten to unravel that.

Continue reading

PuzzleScript Rules

I was watching ThinkyCon, a conference on making puzzle games, and many designers mentioned that they use PuzzleScript to prototype their ideas. PuzzleScript is a puzzle design environment created by increpare, the designer behind Stephen’s Sausage Roll and many other puzzle games.

PuzzleScript is a marvel of economic design. A single text file specifies, all the graphics, levels, sound effects, and all the rules of the puzzle. It uses a custom system to concisely express rules. So concise that the rules of Sokoban can be expressed in a single line.

This efficiency comes because rules are expressed as find-replace rules. That makes it a grammar replacement system, which I last discussed when looking at Ludoscope and Unexplored. But it has many pragmatic features geared toward puzzle design, which I’ll explore in this article.

Continue reading

Defining Chess Piece Moves using Regular Expressions

Suppose you wanted to code a simple chess game. One key bit of game logic is to describe what are legal moves for each piece. There’s only 6 types of piece (pawn, knight, bishop, rook, queen, king) so this isn’t exactly a hard task. You can write rules such as:

def canRookMove(from, to):
  # Ignores questions about colliding with other pieces
  return (from.x == to.x or from.y == to.y) and from is not to

But these days, I’ve been thinking a lot about grids, and the above approach just doesn’t generalize. What if you wanted to play chess on a stranger grid?

Three player chess (CC BY 2.0, source)

What would it mean to play chess on the grid above, or a hexagonal grid, and so on? You’d have to write a whole new set of rules, and they could get very complicated depending on the grid in question. What I want is a language that describes how pieces move, which generalizes to any board. And I think I’ve found it, using regular expressions.

Continue reading

Using Unity’s TextGenerator.verts

TextGenerator.verts is meant to give the position information of every character in a given string. This is useful in Unity if you need to align something with exactly where some particular text is occuring, if for some reason you are not already using TextMeshPro.

Older Unity versions created 4 verts for every character, which made life easy. But now many non-rendering characters don’t have verts generated for them, and the relationship between verts and characters is undocumented. I’ve reverse engineered it, as best as I can tell:

int? GetVertForPosition(int position, string text, TextGenerator textGenerator)
{
    var c = 0;
    var vert = 0;
    for (var i = 0; i < position; i++)
    {
        if (textGenerator.characters.Count <= c)
            return null;
        if (!char.IsWhiteSpace(text[i]) && textGenerator.characters[c].charWidth > 0)
            vert += 4;
        if (text[i] != '\n')
            c++;
    }
    return vert;
}

New Discord Server

Let’s face it, running your own WordPress blog is a sign you are woefully out of date. I can see plenty of readers, but never hear from them.

So I’ve created a Discord server. Feel free to log on and ask me support questions about my projects, suggest new article ideas, or just to hang out.

Don’t worry, the blog isn’t going anwhere. I think the jump might kill me if I leaped fully into the 21st century.