Genetic Algorithm RPG

GARPG

As a two week project for senior year’s Console Programming class, I chose to look into Genetic Algorithms.  In order to demonstrate some of the concept’s applications, I created a very simple text-based RPG which uses a genetic algorithm to create and decide on the monster the player must face.  The program is based on a ‘Hello World’ tutorial for genetic algorithms, which can be found here.

Download the game and source file here

Essentially, after the player beats a monster, the algorithm creates a new population of monsters by randomly mating the stats of two monsters together, followed by further mutating a single stat.  The monsters are then ordered by their fitness–the player faces the most fit monster–which is equal to the sum of all their stats.  However, greater fitness is granted to those stats which counter the player’s stats.  For example, if the player has been greatly increasing their attack stat, a monster’s defense stat will be rated as twice the fitness.  Effectively, this would see the player facing, and the monster population favoring, monsters with a high defense stat.

The function for calculating fitness can be seen below.


//Calculate fitness of creature
void CalculateFitness(creatureVector &population, Entity p, unsigned short gen)
{
 unsigned short fitness;
 for(int i = 0; i < populationSize; ++i)
 {
 fitness = 0;
 fitness += population[i].entity.health;
 fitness += population[i].entity.atk;
 fitness += population[i].entity.def;
 fitness += population[i].entity.magic;
 fitness += population[i].entity.mDef;

//Make the creature more fit if it has stats that counter the player's high stats
 if(p.atk > 5 + gen)// E.x. if player's attack is high, defense is more 'fit'
 fitness += population[i].entity.def;
 if(p.def > 5 + gen)
 fitness += population[i].entity.atk;
 if(p.magic > 5 + gen)
 fitness += population[i].entity.mDef;
 if(p.mDef > 5 + gen)
 fitness += population[i].entity.magic;

population[i].fitness = fitness;
 }
}

The function for mutation can be seen below.


//Increase a random stat by the number of the current generation
void Mutate(Creature &citizen, unsigned short mutateAmount)
{
 unsigned short stat = rand() % 5;
 switch(stat)
 {
 case(0):
 {
 citizen.entity.health += rand() % mutateAmount + 1;
 break;
 }
 case(1):
 {
 citizen.entity.atk += rand() % mutateAmount + 1;
 break;
 }
 case(2):
 {
 citizen.entity.def += rand() % mutateAmount + 1;
 break;
 }
 case(3):
 {
 citizen.entity.magic += rand() % mutateAmount + 1;
 break;
 }
 case(4):
 {
 citizen.entity.mDef += rand() % mutateAmount + 1;
 break;
 }
 }
}