Game Functions
void spawn_players(PLAY** players_list) { for (int index=0;index<numberPlayers; index++) { players_list[index]->Xpos=215; players_list[index]->Ypos=120; players_list[index]->score=0; players_list[index]->jump=10; //Arbitrary value that can't be obtain naturally in the program players_list[index]->jumpTime=0; players_list[index]->alive=TRUE; players_list[index]->keyboard=0; for (int index2=0; index2<3; index2++) { players_list[index]->color[index2]=random_int_generator(0,255); } } } void move_player(PLAY* player) { if (player->keyboard==0) //No movements { player->Xpos=player->Xpos; } if (player->keyboard==1 && player->Xpos+50<largeurFenetre()) // to right { player->Xpos=player->Xpos+lateralSpeed; } if (player->keyboard==2 && player->Xpos>0) //to left { player->Xpos=player->Xpos-lateralSpeed; } } void platform_bounce(PLAY* player, PLA** platforms_list) { for (int index=0;index<6;index++) { if ((((platforms_list[index]->Ypos)+15<=player->Ypos)&&((platforms_list[index]->Ypos)+25>=player->Ypos))&&(((platforms_list[index]->Xpos)-48<=player->Xpos)&&((platforms_list[index]->Xpos)+69>=player->Xpos))) { player->jump=index; player->Ypos=player->Ypos+jumpSpeed; player->jumpTime=1; score_up(player); break; } } if (player->jumpTime!=0) { player->Ypos=player->Ypos+jumpSpeed; player->jumpTime=player->jumpTime+1; if (player->jumpTime>=40) { player->jumpTime=0; } rafraichisFenetre(); } else { player->Ypos=player->Ypos-fallSpeed; rafraichisFenetre(); } } void score_up(PLAY* player) { player->score=player->score+1; } int death_player(PLAY* player, int playersCount) { if (player->Ypos<=0) { player->alive=FALSE; playersCount=playersCount-1; } return(playersCount); }
Genome
PLAY** malloc_players_list(void) { PLAY** players_list; players_list=(PLAY**)malloc(sizeof(PLAY*)*numberPlayers); for (int index=0; index<numberPlayers; index++) { players_list[index]=(PLAY*)malloc(sizeof(PLAY)); } spawn_players(players_list); for (int index=0; index<numberPlayers; index++) { for (int indexDepth=0; indexDepth<3; indexDepth++) { for (int indexLine=0; indexLine<3;indexLine++) { for (int indexColumn=0; indexColumn<3;indexColumn++) { players_list[index]->genome[indexDepth][indexLine][indexColumn]=random_float_generator(1); } } } } return(players_list); }
Crossovers and Mutations
PLAY crossover(PLAY** players_list) { PLAY playerTempo; //Used to easily return the nex genome at the end of the function int mask[3][3][3]; int maskInverted[3][3][3]; int indexPlayer1; int indexPlayer2; // generation of a random mask for (int indexDepth=0; indexDepth<3; indexDepth++) { for (int indexLine=0;indexLine<3;indexLine++) { for (int indexColumn=0; indexColumn<3; indexColumn++) { mask[indexDepth][indexLine][indexColumn]=random_int_generator(0,1); } } } // creation of an inverted mask for (int indexDepth=0; indexDepth<3; indexDepth++) { for (int indexLine=0;indexLine<3;indexLine++) { for (int indexColumn=0; indexColumn<3; indexColumn++) { switch(mask[indexDepth][indexLine][indexColumn]) { case 0: maskInverted[indexDepth][indexLine][indexColumn]=1; break; case 1: maskInverted[indexDepth][indexLine][indexColumn]=0; break; } } } } //Selection of the two best players by their score indexPlayer1=0; indexPlayer2=1; for (int index=0;index<numberPlayers;index++) { if ((players_list[indexPlayer1]->score<=players_list[index]->score)&&(players_list[index]->score!=players_list[indexPlayer2]->score)) { indexPlayer1=index; } if ((players_list[indexPlayer2]->score<=players_list[index]->score)&&(players_list[index]->score!=players_list[indexPlayer1]->score)) { indexPlayer2=index; } } //Application of the mask for (int indexDepth=0; indexDepth<3; indexDepth++) { for (int indexLine=0;indexLine<3;indexLine++) { for (int indexColumn=0;indexColumn<3;indexColumn++) { playerTempo.genome[indexDepth][indexLine][indexColumn]=((players_list[indexPlayer1]->genome[indexDepth][indexLine][indexColumn])*(mask[indexDepth][indexLine][indexColumn])+(players_list[indexPlayer2]->genome[indexDepth][indexLine][indexColumn])*(maskInverted[indexDepth][indexLine][indexColumn])); } } } return(playerTempo); } void mutation(PLAY** players_list) { int mutationsNumber; int randomDepthIndex; int randomLineIndex; int randomColumnIndex; int mutationChances; float slightMutationTemp; mutationsNumber=random_int_generator(2,10); //Random selection of the number of potential mutations int toMutateIndexes[mutationsNumber-1]; for (int index=0; index<mutationsNumber-1; index++) { toMutateIndexes[index]=random_int_generator(0, numberPlayers-1); //Random selection of the player to potentially mutate } for (int index=0; index<mutationsNumber-1; index++) { randomLineIndex=random_int_generator(0,2); //Those three are for choosing randomly a randomColumnIndex=random_int_generator(0,2); // gene from a player and mutate it randomDepthIndex=random_int_generator(0,2); mutationChances=random_int_generator(0,2); switch(mutationChances) { case 0: //no mutations break; case 1: //Slight mutation, adapted from the algogen one slightMutationTemp=(random_float_generator(1)-0.05)+(players_list[toMutateIndexes[index]]->genome[randomDepthIndex][randomLineIndex][randomColumnIndex]); if (slightMutationTemp<=0) { slightMutationTemp=0; } if (slightMutationTemp>=1) { slightMutationTemp=1; } players_list[toMutateIndexes[index]]->genome[randomDepthIndex][randomLineIndex][randomColumnIndex]=slightMutationTemp; break; case 2: //Random mutation players_list[toMutateIndexes[index]]->genome[randomDepthIndex][randomLineIndex][randomColumnIndex]=random_float_generator(1); break; } } } int natural_selection(PLAY** players_list) { PLAY storeNewGenome; int minimalValue; int mediumValue; int maximalValue; int playersExtinction; //Used to print the number of changed players playersExtinction=0; storeNewGenome=crossover(players_list); minimalValue=32000; //Arbitrary value that can't be reach by a mistrained player maximalValue=0; //Determination of a medium score value for (int index=0; index<numberPlayers;index++) { if (players_list[index]->score<=minimalValue) { minimalValue=players_list[index]->score; } if (players_list[index]->score>=maximalValue) { maximalValue=players_list[index]->score; } } mediumValue=(0.99*maximalValue-1.22*minimalValue)/2; //Values chosen after some tests //Determination of all the indexes of players whose genomes must be changed by the crossover one and replacement of those genomes for (int index=0; index<numberPlayers;index++) { if (players_list[index]->score<mediumValue) { for (int indexDepth=0; indexDepth<3; indexDepth++) { for (int indexLine=0;indexLine<3;indexLine++) { for (int indexColumn=0;indexColumn<3;indexColumn++) { players_list[index]->genome[indexDepth][indexLine][indexColumn]=storeNewGenome.genome[indexDepth][indexLine][indexColumn]; } } } playersExtinction=playersExtinction+1; } } mutation(players_list); return(playersExtinction); }
1 thought on “Code from my Doodle Jump Genetic Algorithm”
Comments are closed.