Race Up Stair-Case Mountain
By Christopher Williams
This was a project I did with some of my classmates to create a small game. It is a 2d platformer called "Race Up Stair-Case Mountain" and what sets this game different from others is the AI itself. It is a self learning AI using an evolution algorithm called NEAT, Neuroevolution of Augmenting Topologies. The goal of the game is to reach the ending platform before the rest of the opponents by jumping on or through the platforms. Here is the code so you can read all of the comments or eventry the game out! Lets take a step back though and first discuss about making the game itself
The first step was to decide what language to use and we decided to use Python in order to use the very capable PyGame to create the gamespace. Python is also used a lot with self learning algorithms so it was generally just a nice fit.
You will also see there is three general states of the game, the starting main menu, the pause menu and the game level. The main menu allows you to start the game or quit out of the menu. The pause menu can be used by pressing esc button and allows you to quit out of the game or resume the game.
When you start the game you will see the level design. You can go into the code to change the frame size and because the platforms are based on the relative position to the screen. On one side of the top of the screen will be the round number and the other side is the timer for the current timer.
We do not really need to go into the platform nor the player because the code notes make it clear so lets instead go into some detail about the opponents.
The variable ORG_POPULATION controls how many opponents are created in the first place. Each opponent is controlled by a thing called by the organism. The function get_input will use the sensor nodes, such as how far the next higher platoform, and generates a set of outputs. The highest output will then be used to generate a choice, such as moving left, which then will be used by the opponent.
Lets now discuss about that organism. This is where NEAT comes in. The organism consists of a set of input, hidden and output nodes with weighted edges between those nodes. Input nodes are sensor nodes that take in infomation, the output nodes are muscle nodes that create outputs and hidden nodes are simply nodes between these nodes. To get these outputs we do forward propogation by using the recurse_node function to go through each nodes through the weighted edges and then passing along the value. After the round ends, the organism will generate a fitness level, based on how close they are to the ending flag, which will be used for the next step. This next step is called selection and crossover in order to generate new organisms. We do this to try to generate better solutions by replacing the lower fitness valued organisms with better ones. We first sort the organisms and simply keep the bext one and also randomly keep one half of the old population. We will then randomly select two different organisms and preform crossover until we have generated the other half of the old population Crossover is when we combine the edge and node patterns from both parent organisms to generate a new organism. Now that we have our population we then do mutation in order to generate completly new patterns in the organisms. We will mutate one half of the population by either disable/enable edges, changing the value of the edges with a shift or completly new value, creating new edges or adding in new hidden nodes.
It sounds hard in the beginning but once you start working on it, it makes more sense and each part flows into the next.
I this inspires you to create a game of your own and try making a self learning AI like this!