Skip to content

Commit

Permalink
Merge pull request #3 from Dpbm/qubo-version
Browse files Browse the repository at this point in the history
Qubo version
  • Loading branch information
Dpbm authored May 31, 2024
2 parents afc7593 + 8a33481 commit e49c98b
Show file tree
Hide file tree
Showing 12 changed files with 458 additions and 3 deletions.
8 changes: 6 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ add_subdirectory(game)
add_subdirectory(genetic)
add_subdirectory(matrix)
add_subdirectory(machine)
add_subdirectory(qubo)
add_subdirectory(nativefiledialog-extended)

file(GLOB HELPERS_FILES "helpers/*.cpp")
Expand All @@ -38,6 +39,9 @@ target_link_libraries(genetic players matrix machine board helpers)
file(GLOB MATRIX_FILES "matrix/*.cpp")
add_library(matrix ${MATRIX_FILES})

file(GLOB QUBO_FILES "qubo/*.cpp")
add_library(qubo ${QUBO_FILES})

file(GLOB MACHINE_FILES "machine/*.cpp")
add_library(machine ${MACHINE_FILES})
target_link_libraries(machine helpers matrix)
Expand All @@ -48,8 +52,8 @@ file(GLOB PLAYERS_FILES "game/players/*.cpp")
add_library(board ${BOARD_FILE})
add_library(screens ${SCREENS_FILES})
add_library(players ${PLAYERS_FILES})
target_link_libraries(players machine matrix genetic helpers ${SDL2_LIBRARIES})
target_link_libraries(screens players board helpers genetic matrix ${SDL2_LIBRARIES} SDL2_ttf nfd)
target_link_libraries(players machine matrix genetic helpers qubo ${SDL2_LIBRARIES})
target_link_libraries(screens players board helpers genetic matrix qubo ${SDL2_LIBRARIES} SDL2_ttf nfd)
target_link_libraries(board helpers players)

target_link_libraries(snake PRIVATE helpers board screens players ${SDL2_LIBRARIES} SDL2_ttf)
Expand Down
170 changes: 170 additions & 0 deletions game/players/qubo_player.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#include <cstdint>
#include "qubo_player.h"
#include "../../qubo/qubo.h"
#include "../../helpers/utils.h"

using Qubo::QuboFunc;
using Utils::vec2;
using Utils::distance;

namespace Players {
QuboPlayer::QuboPlayer(uint8_t board_w, uint8_t board_h) : Player(board_w, board_h){
this->board_w = board_w;
this->board_h = board_h;
this->qubo = new QuboFunc((board_h*board_h) + 10);
}

bool QuboPlayer::will_collide_itself(int16_t x, int16_t y){
bool will_collide = false;
Node* actual_bpart = this->head->next;
while(actual_bpart != nullptr){

if(actual_bpart->value.x == x &&
actual_bpart->value.y == y){
will_collide = true;
break;
}
actual_bpart = actual_bpart->next;
}
return will_collide;
}

bool QuboPlayer::will_collide_top_border(){
return this->get_x() <= 0;
}

bool QuboPlayer::will_collide_bottom_border(){
return this->get_x() >= this->board_h-1;
}

bool QuboPlayer::will_collide_left_border(){
return this->get_y() <= 0;
}

bool QuboPlayer::will_collide_right_border(){
return this->get_y() >= this->board_w-1;
}

void QuboPlayer::next_mov(const vec2& food){
double q0 = 10000.0; //distance forward
double q1 = 10000.0; //distance down/right
double q2 = 10000.0; //distance up/left

switch (this->dir) {
case RIGHT:
this->get_distances_right(food.x, food.y, &q0, &q1, &q2);
break;
case LEFT:
this->get_distances_left(food.x, food.y, &q0, &q1, &q2);
break;
case UP:
this->get_distances_up(food.x, food.y, &q0, &q1, &q2);
break;
case DOWN:
this->get_distances_up(food.x, food.y, &q0, &q1, &q2);
break;
default:
break;
}


uint8_t* next_mov = this->qubo->minimize(q0, q1, q2);


if(next_mov[0] == 0 && next_mov[1] == 0 && next_mov[2] == 1)
this->move_up_left();
else if(next_mov[0] == 0 && next_mov[1] == 1 && next_mov[2] == 0)
this->move_down_right();

delete next_mov;
}

void QuboPlayer::get_distances_right(int16_t fx, int16_t fy, double* q0, double* q1, double* q2){
if(!this->will_collide_itself(this->get_x(), this->get_y()+1) && !this->will_collide_right_border())
*q0 = distance(this->get_x(), this->get_y()+1, fx, fy);

if(!this->will_collide_itself(this->get_x()+1, this->get_y()) && !this->will_collide_bottom_border())
*q1 = distance(this->get_x()+1, this->get_y(), fx, fy);

if(!this->will_collide_itself(this->get_x()-1, this->get_y()) && !this->will_collide_top_border())
*q2 = distance(this->get_x()-1, this->get_y(), fx, fy);
}


void QuboPlayer::get_distances_left(int16_t fx, int16_t fy, double* q0, double* q1, double* q2){
if(!this->will_collide_itself(this->get_x(), this->get_y()-1) && !this->will_collide_left_border())
*q0 = distance(this->get_x(), this->get_y()-1, fx, fy);

if(!this->will_collide_itself(this->get_x()+1, this->get_y()) && !this->will_collide_bottom_border())
*q1 = distance(this->get_x()+1, this->get_y(), fx, fy);

if(!this->will_collide_itself(this->get_x()-1, this->get_y()) && !this->will_collide_top_border())
*q2 = distance(this->get_x()-1, this->get_y(), fx, fy);
}

void QuboPlayer::get_distances_up(int16_t fx, int16_t fy, double* q0, double* q1, double* q2){
if(!this->will_collide_itself(this->get_x()-1, this->get_y()) && !this->will_collide_top_border())
*q0 = distance(this->get_x()-1, this->get_y(), fx, fy);

if(!this->will_collide_itself(this->get_x(), this->get_y()+1) && !this->will_collide_right_border())
*q1 = distance(this->get_x(), this->get_y()+1, fx, fy);

if(!this->will_collide_itself(this->get_x(), this->get_y()-1) && !this->will_collide_left_border())
*q2 = distance(this->get_x(), this->get_y()-1, fx, fy);
}

void QuboPlayer::get_distances_down(int16_t fx, int16_t fy, double* q0, double* q1, double* q2){
if(!this->will_collide_itself(this->get_x()+1, this->get_y()) && !this->will_collide_bottom_border())
*q0 = distance(this->get_x()+1, this->get_y(), fx, fy);

if(!this->will_collide_itself(this->get_x(), this->get_y()+1) && !this->will_collide_right_border())
*q1 = distance(this->get_x(), this->get_y()+1, fx, fy);

if(!this->will_collide_itself(this->get_x(), this->get_y()-1) && !this->will_collide_left_border())
*q2 = distance(this->get_x(), this->get_y()-1, fx, fy);
}


void QuboPlayer::move_down_right(){
switch (this->dir) {
case RIGHT:
this->direction_down();
break;
case LEFT:
this->direction_down();
break;
case UP:
this->direction_right();
break;
case DOWN:
this->direction_right();
break;
default:
break;
}
}

void QuboPlayer::move_up_left(){
switch (this->dir) {
case RIGHT:
this->direction_up();
break;
case LEFT:
this->direction_up();
break;
case UP:
this->direction_left();
break;
case DOWN:
this->direction_left();
break;
default:
break;
}
}

QuboPlayer::~QuboPlayer(){
delete this->qubo;
}

}
40 changes: 40 additions & 0 deletions game/players/qubo_player.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include "player.h"
#include "../../qubo/qubo.h"
#include "../../helpers/utils.h"
#include <cstdint>

using Qubo::QuboFunc;
using Utils::vec2;

namespace Players{
class QuboPlayer : public Player {
public:
QuboPlayer(uint8_t board_w, uint8_t board_h);
~QuboPlayer();

void next_mov(const vec2& food);

private:
QuboFunc* qubo = nullptr;
uint8_t board_w = 0;
uint8_t board_h = 0;

bool will_collide_itself(int16_t x, int16_t y);

bool will_collide_top_border();
bool will_collide_bottom_border();
bool will_collide_left_border();
bool will_collide_right_border();

void get_distances_right(int16_t fx, int16_t fy, double* q0, double* q1, double* q2);
void get_distances_left(int16_t fx, int16_t fy, double* q0, double* q1, double* q2);
void get_distances_up(int16_t fx, int16_t fy, double* q0, double* q1, double* q2);
void get_distances_down(int16_t fx, int16_t fy, double* q0, double* q1, double* q2);

void move_down_right();
void move_up_left();
};

};
115 changes: 115 additions & 0 deletions game/screens/qubo_screen.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#include <SDL2/SDL_timer.h>
#include <cstddef>
#include <SDL2/SDL_keycode.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL_surface.h>
#include <SDL2/SDL_stdinc.h>
#include <string>
#include "../../helpers/constants.h"
#include "qubo_screen.h"
#include "start_screen.h"

using std::to_string;
using std::cout;
using std::endl;
using std::size_t;

namespace Screens {
QuboScreen::QuboScreen(SDL_Renderer* render) : Screen(render){
if(!this->font){
cout << "Failed on getting font!" << TTF_GetError() << endl;
exit(1);
}

SDL_Surface* score_text_surface = TTF_RenderText_Solid(this->font, "Score", this->text_color);
this->score_text_texture = SDL_CreateTextureFromSurface(render, score_text_surface);
this->score_text_shape = SDL_Rect{20, 20, score_text_surface->w, score_text_surface->h};
SDL_FreeSurface(score_text_surface);

if(this->score_text_texture == nullptr){
cout << "Failed on creating score text texture!" << SDL_GetError() << endl;
exit(1);
}
this->board.add_player(this->player);
this->left_padding = 10 * SQUARE_SIDE;
}

void QuboScreen::execute(bool& game_loop){
bool won = this->player->get_score() >= this->max_score;
this->finished_game = won || this->player->is_dead();
if(this->finished_game){
SDL_Surface* game_over_surface = TTF_RenderText_Solid(this->title_font, won ? "QUBO Wins!!!" : "Game Over", this->text_color);
SDL_Texture* game_over_texture = SDL_CreateTextureFromSurface(this->render, game_over_surface);
SDL_Rect game_over_shape = SDL_Rect{(WIDTH/2)-(game_over_surface->w/2), (HEIGHT/2)-(game_over_surface->h), game_over_surface->w, game_over_surface->h};
SDL_FreeSurface(game_over_surface);

SDL_Surface* reset_surface = TTF_RenderText_Solid(this->font, "Press 'r' to reset", this->text_color);
SDL_Texture* reset_texture = SDL_CreateTextureFromSurface(this->render, reset_surface);
SDL_Rect reset_shape = SDL_Rect{(WIDTH/2)-(reset_surface->w/2), (HEIGHT/2)+(reset_surface->h)+20, reset_surface->w, reset_surface->h};
SDL_FreeSurface(reset_surface);

SDL_Surface* back_surface = TTF_RenderText_Solid(this->font, "Press 'g' to back to the start screen", this->text_color);
SDL_Texture* back_texture = SDL_CreateTextureFromSurface(this->render, back_surface);
SDL_Rect back_shape = SDL_Rect{(WIDTH/2)-(back_surface->w/2), (HEIGHT/2)+(back_surface->h)+50, back_surface->w, back_surface->h};
SDL_FreeSurface(back_surface);

SDL_SetRenderDrawColor(this->render, 0, 0, 0, 255);
SDL_RenderCopy(this->render, game_over_texture, NULL, &game_over_shape);
SDL_RenderCopy(this->render, reset_texture, NULL, &reset_shape);
SDL_RenderCopy(this->render, back_texture, NULL, &back_shape);
SDL_DestroyTexture(game_over_texture);
SDL_DestroyTexture(back_texture);
SDL_DestroyTexture(reset_texture);
return;
}
this->player->next_mov(this->board.get_food());
this->board.update_player_pos();
this->render_board(&this->board);

SDL_SetRenderDrawColor(this->render, 0, 0, 0, 255);
SDL_RenderCopy(this->render, this->score_text_texture, NULL, &this->score_text_shape);

if(this->score_texture != nullptr)
SDL_DestroyTexture(this->score_texture);
SDL_Surface* score_surface = TTF_RenderText_Solid(this->font, to_string(this->player->get_score()).c_str(), this->text_color);
this->score_texture = SDL_CreateTextureFromSurface(this->render, score_surface);
this->score_shape = SDL_Rect{20, 60, score_surface->w, score_surface->h};
SDL_FreeSurface(score_surface);

SDL_RenderCopy(this->render, this->score_texture, NULL, &this->score_shape);
}

Screen* QuboScreen::key_event(const SDL_Keycode& key){
switch (key) {
case SDLK_g:
if(this->finished_game)
return new StartScreen(this->render);

case SDLK_r:
if(this->finished_game)
this->reset();

default:
break;
}
return nullptr;
}

void QuboScreen::close_event(){
}

void QuboScreen::reset(){
this->finished_game = false;
delete this->player;
this->player = new QuboPlayer(this->board_w, this->board_h);
this->board.add_player(this->player);
this->board.random_food();
}

QuboScreen::~QuboScreen(){
delete this->player;
SDL_DestroyTexture(this->score_texture);
SDL_DestroyTexture(this->score_text_texture);
}
}
Loading

0 comments on commit e49c98b

Please sign in to comment.