Skip to content

Commit fb91fbe

Browse files
committed
ai v1
1 parent c433736 commit fb91fbe

File tree

6 files changed

+76
-16
lines changed

6 files changed

+76
-16
lines changed

game/players/ai_player.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
#include <ctime>
12
#include <cstdint>
3+
#include <sstream>
24
#include "ai_player.h"
35
#include "../../machine/weights.h"
46
#include "../../genetic/chromosome.h"
57
#include "../../helpers/utils.h"
68
#include "../../helpers/constants.h"
79
#include "player.h"
810

11+
using std::stringstream;
912
using Machine::Weights;
1013
using Chromosomes::Chromosome;
1114
using Utils::vec2;
@@ -100,6 +103,17 @@ namespace Players{
100103
this->set_dir((Directions)new_dir);
101104
}
102105

106+
void AIPlayer::save_weights(){
107+
time_t now = time(0);
108+
string time = asctime(localtime(&now));
109+
//remove the $\n at the end of the string
110+
time.pop_back();
111+
112+
stringstream filename;
113+
filename << time;
114+
filename << ".wg";
115+
this->nn->save_weights(filename.str());
116+
}
103117

104118
AIPlayer::~AIPlayer(){
105119
delete this->chromosome;

game/players/ai_player.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace Players{
2121
AIPlayer(uint8_t board_w, uint8_t board_h, Chromosome* chromosome);
2222
~AIPlayer();
2323

24+
void save_weights();
2425
void load_genes_into_weights();
2526
void update_input_data(const vec2& food, uint16_t w, uint16_t h);
2627
void compute_next_dir();

game/screens/ai_screen.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ using Genetic::Individual;
2222
namespace Screens {
2323

2424
AIScreen::AIScreen(SDL_Renderer* render){
25-
if(!this->font){
25+
if(!this->font || !this->tiny_font){
2626
cout << "Failed on getting font!" << TTF_GetError() << endl;
2727
exit(1);
2828
}
@@ -58,13 +58,20 @@ namespace Screens {
5858
this->timer_text_texture = SDL_CreateTextureFromSurface(render, timer_text_surface);
5959
this->timer_text_shape = SDL_Rect{20, 370, timer_text_surface->w, timer_text_surface->h};
6060
SDL_FreeSurface(timer_text_surface);
61+
62+
63+
SDL_Surface* weights_text_surface = TTF_RenderText_Solid(this->tiny_font, "'S' save weights", this->text_color);
64+
this->weights_text_texture = SDL_CreateTextureFromSurface(render, weights_text_surface);
65+
this->weights_text_shape = SDL_Rect{20, 530, weights_text_surface->w, weights_text_surface->h};
66+
SDL_FreeSurface(weights_text_surface);
6167

6268
if(this->score_text_texture == nullptr ||
6369
this->gen_text_texture == nullptr ||
6470
this->alive_text_texture == nullptr ||
6571
this->win_text_texture == nullptr ||
6672
this->fitness_text_texture == nullptr ||
67-
this->timer_text_texture == nullptr){
73+
this->timer_text_texture == nullptr ||
74+
this->weights_text_texture == nullptr){
6875
cout << "Failed on creating text textures!" << SDL_GetError() << endl;
6976
exit(1);
7077
}
@@ -115,6 +122,7 @@ namespace Screens {
115122
SDL_RenderCopy(render, this->win_text_texture, NULL, &this->win_text_shape);
116123
SDL_RenderCopy(render, this->fitness_text_texture, NULL, &this->fitness_text_shape);
117124
SDL_RenderCopy(render, this->timer_text_texture, NULL, &this->timer_text_shape);
125+
SDL_RenderCopy(render, this->weights_text_texture, NULL, &this->weights_text_shape);
118126

119127
if(this->score_texture != nullptr)
120128
SDL_DestroyTexture(this->score_texture);
@@ -178,10 +186,19 @@ namespace Screens {
178186
}
179187

180188
Screen* AIScreen::key_event(const SDL_Keycode& key){
189+
if(key == SDLK_s)
190+
this->save_weights();
191+
181192
return nullptr;
182193
}
183194

184195
void AIScreen::close_event(){
196+
this->save_weights();
197+
}
198+
199+
void AIScreen::save_weights(){
200+
cout << "Saving weights!..." << endl;
201+
this->population.get_best_individual()->player->save_weights();
185202
}
186203

187204
AIScreen::~AIScreen(){
@@ -197,5 +214,6 @@ namespace Screens {
197214
SDL_DestroyTexture(this->fitness_text_texture);
198215
SDL_DestroyTexture(this->timer_texture);
199216
SDL_DestroyTexture(this->timer_text_texture);
217+
SDL_DestroyTexture(this->weights_text_texture);
200218
}
201219
}

game/screens/ai_screen.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ namespace Screens{
3333
uint8_t gen_time = 30; //in seconds
3434
uint32_t control_tick = 0;
3535

36-
Population population{2000, board_w, board_h, 20};
36+
Population population{3000, board_w, board_h, 20};
3737

3838
SDL_Renderer* render;
3939
TTF_Font* font = TTF_OpenFont("./assets/pressstart.ttf", 20);
40+
TTF_Font* tiny_font = TTF_OpenFont("./assets/pressstart.ttf", 12);
4041
SDL_Color text_color{ 255, 255, 255 };
4142

4243
SDL_Rect score_text_shape;
@@ -68,5 +69,10 @@ namespace Screens{
6869
SDL_Rect timer_shape;
6970
SDL_Texture* timer_text_texture = nullptr;
7071
SDL_Texture* timer_texture = nullptr;
72+
73+
SDL_Rect weights_text_shape;
74+
SDL_Texture* weights_text_texture = nullptr;
75+
76+
void save_weights();
7177
};
7278
};

genetic/population.cpp

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -125,28 +125,50 @@ namespace Genetic{
125125
// fitness for catching the food
126126
if(board->get_caught_the_food())
127127
ind->fitness += 5000;
128-
129-
if(player->get_score() >= this->total_food){
128+
129+
uint16_t score = player->get_score();
130+
if(score > this->best_score)
131+
this->best_score = score;
132+
133+
if(score >= this->total_food){
130134
player->set_died();
131135
this->total_win++;
132136
this->total_alive--;
133137
ind->fitness += 20000;
138+
this->update_best_fitness(ind);
139+
continue;
140+
}
141+
142+
if(player->is_dead()){
143+
ind->fitness += -1000;
144+
this->update_best_fitness(ind);
134145
continue;
135146
}
136147

148+
this->update_best_fitness(ind);
137149
this->update_individual_food_position(ind);
138150
}
139151
}
140152

153+
void Population::update_best_fitness(Individual* ind){
154+
if(ind->fitness > this->best_fitness)
155+
this->best_fitness = ind->fitness;
156+
}
157+
141158
void Population::next_gen(){
142159
this->gen++;
160+
this->best_score = 0;
161+
std::cout << "next gen: " << this->gen << "\n";
143162
Individual** parents = this->select_parents();
144163
Chromosome* offspring = this->generate_offspring(parents[0]->player->get_chromossome(), parents[1]->player->get_chromossome());
164+
delete parents;
145165
Gene* offspring_genes = offspring->get_genes();
146166

147167
uint64_t offspring_ch_size = offspring->get_size();
148168

149169
this->clear();
170+
std::cout << "no segmentaion fault\n";
171+
this->individuals.clear();
150172
this->food_positions.clear();
151173
this->generate_food_positions(total_food, board_w, board_h);
152174
vec2 first_food_pos = this->food_positions.at(0);
@@ -161,7 +183,7 @@ namespace Genetic{
161183
else{
162184
Chromosome* player_chromosome = new Chromosome(offspring_ch_size);
163185
player_chromosome->copy_genes(offspring_genes);
164-
player_chromosome->mutate(0.02);
186+
player_chromosome->mutate(0.3);
165187

166188
ind->player = new AIPlayer(board_w, board_h, player_chromosome);
167189
}
@@ -175,7 +197,6 @@ namespace Genetic{
175197

176198
this->individuals.push_back(ind);
177199
}
178-
delete parents;
179200
}
180201

181202
Individual** Population::select_parents(){
@@ -238,13 +259,7 @@ namespace Genetic{
238259
}
239260

240261
uint16_t Population::get_best_score(){
241-
uint16_t best_score = this->individuals.at(0)->player->get_score();
242-
for(Individual* ind: this->individuals){
243-
uint16_t ind_score = ind->player->get_score();
244-
if(ind_score > best_score)
245-
best_score = ind_score;
246-
}
247-
return best_score;
262+
return this->best_score;
248263
}
249264

250265
uint16_t Population::get_total_alive(){
@@ -256,7 +271,7 @@ namespace Genetic{
256271
}
257272

258273
int64_t Population::get_best_fitness(){
259-
return this->get_best_individual()->fitness;
274+
return this->best_fitness;
260275
}
261276

262277
void Population::clear(){

genetic/population.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ namespace Genetic {
2828
public:
2929
Population(uint16_t total, uint8_t board_w, uint8_t board_h, uint8_t total_food);
3030
Individual* get_best_alive_individual();
31+
Individual* get_best_individual();
3132
void next_gen();
3233
void run();
3334
uint32_t get_gen();
@@ -53,10 +54,15 @@ namespace Genetic {
5354
uint16_t total_win = 0;
5455
uint8_t board_w = 0;
5556
uint8_t board_h = 0;
57+
58+
uint16_t best_score = 0;
59+
int64_t best_fitness = -1000000000000;
60+
61+
void update_best_fitness(Individual* ind);
62+
5663
vector<Individual*> individuals;
5764
vector<vec2> food_positions;
5865

59-
Individual* get_best_individual();
6066
void generate_food_positions(uint8_t total, uint8_t w, uint8_t h);
6167
void update_individual_food_position(Individual *ind);
6268
void clear();

0 commit comments

Comments
 (0)