Archive

Game

Mhess is a stupid messy chess game about giving your pieces superpowers and fighting robot masters. It’s been the center of my attention for the past month or so, and it seemed fitting to share a few of the things I’m learning about the good, the bad, and the ugly of chess engine programming.

As a caveat, I deliberately did not look at any existing implementations. I was hoping that avoiding them would prevent having any pre-conceived notions about the best approach and would lead to a more novel, interesting implementation. If you’re interested in writing your own chess game, I would recommend looking at The Chess Programming Wiki.

Implementing a chess game and a chess engine are very different problems, though a chess game needs a chess engine, the design rules for a fully functional game are slightly different than those of a pure chess engine. For starters, something I had not thought about when building out the engine component was how difficult keeping the internal board representation and external board representation in sync would be. I spent a significant amount of time debugging why things in the game world would disappear or refuse to move. This challenge was compounded, or perhaps made more subtle by what I think are, in hindsight, bad decisions.

Bad Decision 1: Game State representation.

I use the following to represent a game state. It’s designed to be light weight and quick to clone so that when we start looking at trees of depth 14 we don’t blow out our compute time.

#[derive(Clone, Eq, Hash)]
pub struct GameState {
	pub board_width: u8,
	pub board_height: u8,
	pub board_holes: vec![],
	pub board_state: Vec<(u8, u8, Piece)>,
	pub en_passant_space: Option<(u8, u8)>,
	pub black_can_queenside_castle: bool,
	pub white_can_queenside_castle: bool,
	pub black_can_kingside_castle: bool,
	pub white_can_kingside_castle: bool,
	pub halfmove_count: u8,
	pub fullmove_count: u8,
	pub current_player: PlayerColor,
}

The board_state is worth highlighting. I had started with a vector of tuples of u16,Piece. That proved to be an unnecessary optimization since we always immediately converted the idx into x,y. Note that there’s a deliberate choice to have x,y in the board state and NOT inside the piece. This is done to make cloning the board state a shallow operation and really fast. Generating 11 million moves takes less than 700ms in debug mode.

A piece does not know its position in the world. Instead, a move generator takes a game state and produces a bunch of “gamemove” items. A gamemove item takes a gamestate and produces from it a new state. If this whole thing seems roundabout, that’s because it is. Complexity of defining moves is generally localized to the gamemove.rs code, but there’s a LOT of complexity to be localized. Implementing castling has been a mess because checking whether pieces are being attacked involves generating all of the possible moves for the next state. Similarly, checking for checkmate (or check) involves basically first generating the next moves and then determining which result in the king being able to be captured. This is not a great solution.

The next experiment will be a lengthy one and will probably involve trying to switch from the current gamestate + move generator to a gamestate + heavy piece system. If that works out, or if it doesn’t, I’ll be sure to post an update here.

Team Dogpit is hosting Cultivation Jam! Full details are available on the itch.io page.

The special hidden theme is ‘Household Goods’.

The idea that keeps sticking in my head is a clone of Stardew Valley or Animal Crossing, but aboard a generation ship. You need to take care of the plants and fix pieces of the ship using only the tools you can scrounge up locally. Your goal is to prepare enough food to feed a set of 100 people for one season.

MVP:

  • Player can click to move around.
  • Clicking on nearby plants will give the option to tend to them, which means checking hydroponics levels, looking for signs of rot/blight, taking samples, and pollinating.
  • Plants have real life stages, seedling, sapling, grown, flowering, dying, dead.
  • Plants have real life needs, like sun, nutrients, space, temperature.

Part of the challenge might be in balancing time taking care of the plants with time spent exploring the ship’s waste and part recycling in the hopes of finding new and interesting components. Diving deeper into those depths will let you find more stuff but increases risk of getting squished by falling debris or maybe eaten by a sentient dishwasher or something. But that’s too far ahead. For now, let’s get a player walking around.

Day 1-3:

Well the click to move around turned out to be a little dumb. Not only does it require that we figure out pathing (not hard, but tricky to decide on things architecturally), it doesn’t make sense! If someone has to click on something to move to it, why can’t they just click on it!?

I replaced that with a character controller and the normal WASD + controller support.

I started and stopped the inventory a dozen times because every solution felt hacky. I have a single Inventory scene which holds a bunch of items. Each item has an InventoryItem sub-object. When something is in the inventory, the InventoryItem node gets pulled out and the parent (the actual world item) is shoved into the InventoryItem’s world object slot. I had each InventoryItem also inherit from a NinePatchRectangle because I wanted that to be a nice background, but this is a hassle, so I’m making them TextureButtons. Instead, the inventory itself will draw the boxes and will highlight the destination on mouse moves. That’s more sensible as far as I’m concerned.

And I made a robot:

Day 4-5:

Only had about 30 minutes per night to work on things. Spent most of the time working on the drag and drop and the cross-inventory dragging. There are still some bugs but now one can drag items from one inventory into another inventory. The inventory object emits a signal when the cursor moves out and when it moves back in. It feels messy, but it’s self contained at least and makes proper use of signals.

Left: Player inventory. Right: Some other inventory.

Day 6-8

An evening setback from an unexpected social outing (no regrets), followed by a productive stint of fixing things and changing around how the UI is connected together. My efforts to detach the UI display from the UI contents didn’t pan out because the UI contents still need position info, which means they need to be inside a tree, which means they need to be owned. Instead, I have a UI Exchange interface which takes two inventories and allows a user to click and drag things between them. This turned out to be really nice. I also added a Global which tracks which UI screen is open and prevents the player from moving if they’re looking at an inventory. I started work on saving and loading, since that will be required eventually anyway. While I’d intended to start on the dungeon crawling aspect, that got a little side tracked with stashing and unstashing the different parts of the level.

Happy Saturday! Let’s make a game.

Why

Freerunning and Parkour are pretty great. Speedruns of TitanFall 2 are pretty great. Tag is pretty great. A game that’s as mechanically simple as tag means I don’t have to mess with any tricky systems or item pickups. Get to focus on (1) movement systems that are easy and satisfying, and (2) making levels and maps that are fun to play. Feels like a good fit.

One sentence tagline: Parkour tag online with friends.

MVP Deliverables

  • Step 0: Fun movement, even over network.
  • Step 1: Easy matching with friends. (And the ability to kick bots/hackers.)
  • Step 2: Enjoyable environments.

Open questions

  • Start by defining movement or by defining network play?
    • I’m not good at (low-latency) UDP network stuff. I’ve only really worked in TCP-land.
    • Doing movement system first might mean changing it for network play, especially if we need to do things like input-replaying.
  • Freeze-tag? Horde mode? Face-off? All?
    • Freeze tag: tagging by the opponent means you’re frozen and can only witness until you’re unfrozen. Tagger wins when all people are frozen.
    • Horde mode: tagging means your color switches from blue team to red ream. Blue team wins when time runs out. Red team wins when there are no blue left.
    • Face-off: Freeze tag, but when you’re tagged you’re out. Tagger wins when there are no people left. Runners win when the time runs out.

Proposed Plan

  • [x] Movement
    • [x] MVP.
    • [_] Wall running.
    • [_] Tune acceleration and decelleration.
    • [_] ‘Speed’ artifacts when running fast (juice!).
  • [x] Tag when in-range
  • [_] Network the above
  • [_] Lobby / End of Game

Devlog

  • 10AM: Write up this document.
  • 11AM: Decide on how to implement control schemes – a Controller component (extending spatial) handles user inputs. Multiplayer can get done by having a remote controller and bots can get done with bot controller. Controller object reports heading and movement.
  • 12PM: Done with minimum viable product for moving around. Tweaking jumping, but going to put it on hold to do other things.
  • 1PM: On hold while domestic things are handled. :'(
  • NEXT DAY 6:00AM: Can’t sleep. Back to work. Finish tagging with a raycast and add dumb bots to test. (Progress Video)
  • Futzed about with assorted networking stuff until noon. Finished to do domestic things.

Repo

https://github.com/JosephCatrambone/GodotTag

It’s time for the first ever AI & Games Jam. Every word in the title is something near and dear to me, AI, Games, and Jam. This post is going to be updated a few times as I work my way through the weeklong jam. I’ll begin with the cursory ideas, some prototypes, and eventually will clean up the whole thing and make it into a coherent narrative.

First, let’s ideate:

The Jam is judged on three principle areas, originality, presentation, and fun. There is a theme: “Breaking the Rules”.

  • Initial impulse was a cliche: a detective that doesn’t play by the rules and wants to solve some kind of case by interviewing subjects. Lets me work in chatbots, which I know and love, and would probably score highly on originality, but probably wouldn’t be too much fun.
  • Maybe a Smash-TV knockoff where you play against an ever-evolving AI army that’s trained with reinforcement learning or NEAT. Gameplay wouldn’t be super original — shooter arenas are a dime a dozen, but how many actually evolve their AI as a difficulty mechanic.
  • You are an ant in a colony tasked with finding resources, as ants do. While all the others are happily gathering their materials as directed by pheromones and swarm behaviors, you’re left to your own devices. Can you emulate an ant well enough to avoid being rejected by the colony?
  • Papers, Please! but the Turing Test. You play a malware detector sitting on the edge of a network and need to talk to applications as they move past you: the firewall. Possibly really hard, but not impossible. Would be original, but perhaps not fun. High risk, because the core gameplay mechanic would revolve around an untested, possibly bad, chatbot system.
  • Dream Explorer: move though a latent space trying to find someone’s dream. Fancy GAN — steer through 3D or 4D latent space to find a matching image. Low theme adherence.
  • Crazy Self-Driving Taxi: Driving Sim where you break the rules of the road to get your pedestrian to their destination.

Day 1:

Most of this is predicated on chatbot systems. Those are fairly tricky, and integrating Torch with C# can be a mess. Even training a decent model in the given time could prove impossible. That means tonight, goal one has to be getting a steerable language model to run end-to-end. If I can’t do that in the next two hours, I have to fall back to the Smash-TV knockoff. Let’s get started.

End of Day 1 status:

Tried chat bots for an hour, decided it was too high risk, and went with the SmashTV approach. Movement and shooting:

Day 2:

I have from now (10:00AM) until 6:00 PM tonight to get my stuff done. After that I’ve got social and work obligations for the rest of the week, plus whatever time I can squeak out between 10:00PM and 11:00PM next week.

My initial impulse is that I’m not really liking the interaction between the theme and the game idea. There has to be a way to make the theme a _core_ of the mechanic and not just an afterthought. I’m thinking back to a game I tried making a while back, Terminus. The big hook of that game was the CPU and being able to program robots oneself. Hacking systems is pretty within the idea of breaking the rules, and the gameplay will be more novel. Going to take everything I have and just try to apply it here.

End of Day 2:

Well I’m pretty sure I focused on the wrong thing. I find it personally fun to program these tiny robots in assembly but once again I’m not sure how much anyone else is going to want to do this, and if we need a variety of creatures in the game then this may be time prohibitive. Really was hoping to have something more substantive by EOD today, but that’s life.

Day 3:

Didn’t get home until a little later. Worked on things for about an hour or so. Added some camera follow with smoothing and lookahead. Threw in a tileset that has collision. Need to get back to focusing on gameplay. At least I need to figure out a win and lose condition or something that resembles a mechanic. In hindsight, I really didn’t plan enough there.

Day 4:

A bit of a pivot. Again. I have a less nebulous idea about finishing. Didn’t even realize that I was forgetting about an end state until I started thinking about the “why” of the player’s actions. The new goal is to find your lost dog. That’s simple enough and lets me iteratively improve the game while always keeping a complete build.

Steps: first you just find the dog on the map. Add a win condition when the player is within range.

Bonus: add a ‘restricted’ area that the player needs to enter to find their dog. Open it using the hacking technique above OR finding a keycard in the map.

Bonus: chat bots to ask where the dog is.

Bonus: more curated level.

Bonus: random levels.

Bonus: dog moves around depending on hunger and thirst.

Day 5:

Had an unexpected opening in the evening to work on things. Made a bunch of procedurally generated people and gave them a bunch of waypoints around the map that they’d move between. There’s a bug in the pathfinding, though, and all of them seem to move to strange places. I also have the trigger for win, but haven’t done a screen with winning on it yet.

Day 7:

Didn’t have time to work on day six. Day seven was a bit of a frantic wrap up. Mostly wanted to get the game packaged and uploaded. Added the title screen and the final page, fixed the nav bug (relative position for movement target). I also had to draw the nav mesh separately and clear out all the navigations added to the tilemap because characters were getting stuck on the wall.

Closing Thoughts:

That was okay. In hindsight, I should have done something with more options to demo some fancy AI. If I could do it again I’d make a chess game were you can break a single rule (and have a piece move like a queen) once per game.

Itch.io Link: https://xoana.itch.io/find-your-dog

GitHub page: https://github.com/JosephCatrambone/AIAndGamesJam2021

Overview

Goose Game, but instead of a horrible goose you are a good dog whose job it is to break up fights at holiday parties. Let’s game it out.

Gameplay

Simulated people will run through the motions for a party. Each guest will have a set of desires and some personal goals to achieve. For the sake of gameplay, everyone that can see the dog (player) will attempt to intervene when the player is misbehaving, rather than deferring to a host or someone else.

Visuals

Something visually simple with bright colors and simple geometry. This game should be very easy on system resources and should operate smoothly on low-resource machines or mobile devices. One option:

Low Poly pack by @Quaternius

Audio

High-fidelity, cheerful music with cute sound effects. Human speech and communication should _not_ be real human speech, but should be some sort of non-lexical vocalization like Simlish.

Interesting Challenges

Fundamentally, the interpersonal interactions will drive the game. For replayability (and developer sanity) it is desirable to have conflicts emerge naturally from NPC interactions. Additional household events can add color or fun as discoverables, but the most fundamental piece of the game is the temperature of discourse.