Cantors Angels - Project - Paused

GitHub

What is this game?

A Deterministic Turn-based Stratagy Game set in a Religous Sci-fi world. Emulating the fun you get from proving a math formula with induction, more specifically the binomial theorem and bernoulli's inequality. Taking gameplay inspiration from the games Into the Breach, Civilization Games, Starcraft 2, They Are Billions, Chess. Taking visuals and world building inspiration from the media, Pacific Rim, Warhammer - Drop Chapel, Foundation. The core gameplay mechanic this hopes to explore is the ability to have perfect information about the world while being able to undo moves and try new possibilities. Though it sounds like a puzzle game, it plays much more like a strategy game.

Player Promises

You can move backwards in time in major and minor steps to fix and try new paths. There must be many different unique approaches and strategies. Every seed grants a new play through and repeatability. The is no information is purposely hidden from the player. Therefore it must be very easy to explore different logic and strategy paths. There are be many different strategies, battle strategies, economic strategies, key decisions, and general play style. Each of these strategies have a place where players cannot just have one they always stick to. High information availability and density, if you want you can toggle on all the UI elements and hotkey your way through victory.

Artistic direction

Brutalist architecture, nuclear fallout, dystopian orange landscapes.

Yugoslavia ww2 memorial.
Cologne Cathedral.
Dune.

TODOs

Perfect Consistency

A very important feature is that the game is state based. When a player plays a move, they modify the board and the delta is what is stored. Given the same state, the delta should only ever generate one unique new state, the current state cannot have any knowledge of the previous state. This means there cannot be a concept of unit memory as all required information must be known at every state.

Theoretically you could have unit memory be considered part of the world state. While sometimes I do this, I avoid it as it becomes too hard to visually communicate. This is the difference between the idea of "I will always go to the closest unit" vs "I will find a target and chase it down". Enemy actions must be understandable and predictable, where it can't be something like "this unit's path is slightly weird because a unit that spawned a turn before was going to run into the path" instead it will be "This next unit's next move will be weird because the unit next to you moved first and is blocking the path so you must move around".

If that explanation didn't work. Imagine a poker bot where it either gives you the mathematically best possible move vs a bot that analysis how people behave and plays to predict a statistically best move.

Hexagonal Tile World Generation

I originally had a 2D grid, but I realized that it did not match the visual readability I wanted and it also did not achieve the about of strategic possibilities I wanted. I made the decision to change the game to use a hexagonal grid during development, forcing me to reimplement the world generation system, pathfinder system, serialization systems and world state systems. To make this process easier I used this post detailing best ways to implement a hexagonal world. Explored how to extrapolate this method to render a 2d hexagonal world with a fake 3D feeling, similar to 2D isometric games.

Hexagonal PathFinding

The path-finding system had to be heavily modified and optimized to have unique looking paths that makes sense while also being always consistent. One big struggle was how I can make multiple enemies trying to go to the same place not overlap in their paths while also having no information on the other paths and previous paths. The paths are calculated tile by tile across a very big map, where it is hard to optimize without losing the perfect consistency. I ended up using a cache method to optimize the system, and plan to eventually make it async.

Git-like "Version Control" for Strategy Exploration

To properly serialize and support perfect consistency, I took a book out of how some delta based version control systems work. There exists a seed that generates a origin board, each board state is hashed to generate a unique id for a state. As you play through each time you add a turn, the game will store your turn as a set of deltas applied to a board state hash. This system allows me to check consistency very easily as if the hashes of the calculated board hash does not match with the saved board hash, there is a inconsistency. This is also my least favorite bug to have to fix.

Save Files

The git-like system allows me to build very dense and data efficient save systems where I only need to store deltas and hashes. Each time you load a save file, you just have to use the seed to generate the origin, then apply all the deltas In-Order to generate the entire rest of the world and all the states. One important feature is that during runtime, recent board states are all cached where switching between recent states is instantaneous, but trying out a new far branch requires recalculating deltas from a state checkpoint.

Particle Compute Shaders

The game was lacking in the visuals department and I wanted to add ambient particles to enhance the world. I had first tried to just do it will cpu particles and do a very good job with culling. Eventually I switched to full compute shader particles, allowing me to generate a very large amount of particles on low end computers, even being able to add a parallax effect to give a stronger illusion of 3D.

Graph Drawing Compute Shader

I wanted a very intuitive and efficient way to traverse your history and try new strategies. This required me to be able to visually render out the graph, I opted to use a compute shader to do this as I wanted the ability for the game to automatically fetch all the histories of all the other players that have tried the level/seed which would involve millions of deltas/nodes. I wanted to make sure that these graphs and branches look very organic while making sure each player's branch also visually has a identity. I had tried using a system derived from L-Systems to try and create this effect.

Steamworks Leaderboard

WIP