#include #include #include "raylib.h" #include "raymath.h" #define MAP_WIDTH_MAX 5 #define MAP_HEIGHT_MAX 5 #define MAX_ATOUT (4*4 - 3) #define MAX_PLAYER 6 #define MAX_PIOCHE (4*13 + 2 - 6) #define MAX_MAIN (MAX_PIOCHE - 3*5) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) typedef enum CarteType { CARTE_COEUR, CARTE_TREFLE, CARTE_CARREAU, CARTE_PIQUE, CARTE_TYPE_COUNT, } CarteType; typedef enum CarteValue { CARTE_VALET = 11, CARTE_REINE, CARTE_ROI, CARTE_AS, CARTE_JOKER, CARTE_VALUE_COUNT, } CarteValue; typedef struct Carte { CarteValue value; CarteType type; } Carte; typedef struct Map { int width, height; int spawn_x, spawn_y; Carte cartes[MAP_WIDTH_MAX*MAP_HEIGHT_MAX]; } Map; #define O (Carte) {.value = -1, .type = -1} #define X (Carte) {.value = 2, .type = 0} Map default_map = {3, 3, 1, 1, { X, X, X, X, X, X, X, X, X, }}; Map grande_map = {5, 5, 2, 2, { O, O, X, O, O, O, X, X, X, O, X, X, X, X, X, O, X, X, X, O, O, O, X, O, O, }}; #undef O #undef X typedef struct Player { int x, y; Carte role; int nb_atout; Carte atouts[MAX_ATOUT]; int nb_cartes; Carte cartes[MAX_MAIN]; } Player; typedef struct Game { int nb_player; Player players[MAX_PLAYER]; int pioche_len; Carte pioche[MAX_PIOCHE]; Map map; } Game; // name = 7C, TK JK // will write only 2 char in buff void carte_name(Carte carte, char* buff) { if (carte.value < 10 && carte.value > 1) { buff[0] = '0' + carte.value; } else { switch (carte.value) { case 10: buff[0] = 'T'; break; case CARTE_VALET: buff[0] = 'V'; break; case CARTE_REINE: buff[0] = 'Q'; break; case CARTE_ROI: buff[0] = 'K'; break; case CARTE_AS: buff[0] = 'A'; break; case CARTE_JOKER: buff[0] = 'J'; break; default: buff[0] = '?'; break; } } switch (carte.type) { case CARTE_COEUR: buff[1] = 'C'; break; case CARTE_TREFLE: buff[1] = 'T'; break; case CARTE_CARREAU: buff[1] = 'K'; break; case CARTE_PIQUE: buff[1] = 'P'; break; default: buff[1] = '?'; break; } } int valid_carte(Carte carte) { return !(carte.value < 2 || carte.value > CARTE_JOKER || carte.type < CARTE_COEUR || carte.type >= CARTE_TYPE_COUNT); } Vector2 window = {1920, 1080}; void game_init(Game* game, Map map, int nb_player) { if (nb_player < 3) return; Carte roles[] = { {CARTE_REINE, CARTE_COEUR}, // dora, always in game {CARTE_VALET, CARTE_CARREAU}, // babouche {CARTE_REINE, CARTE_TREFLE}, // chipeur {CARTE_ROI, CARTE_PIQUE}, // grumpy {CARTE_VALET, CARTE_COEUR}, // malveillant {CARTE_ROI, CARTE_CARREAU}, // diego }; int len = sizeof(roles)/sizeof(*roles); if (nb_player > len) return; // pioche int count = 0; for (CarteType type = 0; type < CARTE_TYPE_COUNT; type++) { for (CarteValue value = 2; value <= CARTE_AS; value++) { int i; for (i = 0; i < len; i++) { if (roles[i].value == value && roles[i].type == type) break; } if (i < len) continue; game->pioche[count] = (Carte) {value, type}; count++; } } game->pioche[count++] = (Carte) {CARTE_JOKER, CARTE_COEUR}; game->pioche[count++] = (Carte) {CARTE_JOKER, CARTE_PIQUE}; game->pioche_len = count; for (int i = 0; i < game->pioche_len; i++) { int idx = GetRandomValue(0, game->pioche_len-1); Carte swap = game->pioche[i]; game->pioche[i] = game->pioche[idx]; game->pioche[idx] = swap; } // player int picked[sizeof(roles)/sizeof(*roles)] = {0}; int nb_atout[MAX_PLAYER] = {0}; int dora_idx = GetRandomValue(0, nb_player-1); game->players[dora_idx].role = roles[0]; picked[0] = 1; game->players[dora_idx].x = map.spawn_x; game->players[dora_idx].y = map.spawn_y; for (int i = 0; i < nb_player; i++) { if (i == dora_idx) continue; int idx; do { idx = GetRandomValue(1, len-1); } while (picked[idx]); picked[idx] = 1; game->players[i].role = roles[idx]; game->players[i].x = map.spawn_x; game->players[i].y = map.spawn_y; } for (int i = 0; i < nb_player; i++) { for (int c = 0; c < 5; c++) { game->players[i].cartes[c] = game->pioche[--game->pioche_len]; } game->players[i].nb_cartes = 5; } game->nb_player = nb_player; // map for (int i = 0; i < map.width*map.height; i++) { if (!valid_carte(map.cartes[i])) { game->map.cartes[i] = (Carte) {-1, -1}; } else { game->map.cartes[i] = game->pioche[--game->pioche_len]; } } game->map.width = map.width; game->map.height = map.height; game->map.spawn_x = map.spawn_x; game->map.spawn_y = map.spawn_y; } void attack(Game* game, int player, int carte, int x, int y) { if (x < 0 || x >= game->map.width || y < 0 || y >= game->map.height) return; Carte c = game->players[player].cartes[carte]; switch (c.type) { case CARTE_PIQUE: // attaquer joueur break; case CARTE_TREFLE: // poser piege break; case CARTE_COEUR: case CARTE_CARREAU: default: return; } // Player p = game->players[player]; Carte to = game->map.cartes[y*game->map.width + x]; char buff[3]; carte_name(to, buff); buff[2] = 0; printf("to %s\n", buff); (void) game; } int main() { InitWindow(window.x, window.y, "DORA"); SetWindowState(/*FLAG_FULLSCREEN_MODE|*/FLAG_WINDOW_RESIZABLE); SetTargetFPS(60); Game game = {0}; game_init(&game, grande_map, 5); while (!WindowShouldClose()) { // update if (IsWindowResized()) { window.x = GetScreenWidth(); window.y = GetScreenHeight(); } static int player = 0; if (IsKeyPressed(KEY_SPACE)) player = (player+1)%game.nb_player; if (IsKeyPressed(KEY_S)) game.players[player].y++; if (IsKeyPressed(KEY_W)) game.players[player].y--; if (IsKeyPressed(KEY_D)) game.players[player].x++; if (IsKeyPressed(KEY_A)) game.players[player].x--; static unsigned int carte = 4269+1; if (IsKeyPressed(KEY_E)) carte++; if (IsKeyPressed(KEY_Q)) carte--; // code skibidi degeu, parti draw() a refaire plus tard BeginDrawing(); { ClearBackground(GRAY); Vector2 off = {0, 0}; int size = 0; if (window.x < window.y) { size = window.x / game.map.width; off.y = (window.y - window.x) / 2; } else { size = window.y / game.map.height; off.x = (window.x - window.y) / 2; } for (int y = 0; y < game.map.height; y++) { for (int i = 0; i < game.map.width; i++) { Carte carte = game.map.cartes[y*game.map.width+i]; if (!valid_carte(carte)) continue; Rectangle tile = {off.x+size*i, off.y+size*y, size, size}; DrawRectangleRec(tile, BLACK); char buff[3]; carte_name(carte, buff); buff[2] = 0; DrawText(buff, tile.x, tile.y, size/5, ORANGE); } } Vector2 mouse = GetMousePosition(); Vector2 hover = {mouse.x * game.map.height / window.y, mouse.y * game.map.height / window.y}; hover.x -= 2; Rectangle tile = {off.x+size*(int)hover.x, off.y+size*(int)hover.y, size, size}; DrawRectangleRec(tile, IsMouseButtonDown(MOUSE_BUTTON_LEFT) ? RED : WHITE); if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) attack(&game, player, carte%game.players[player].nb_cartes, hover.x, hover.y); for (int i = 0; i < game.nb_player; i++) { char buff[3]; carte_name(game.players[i].role, buff); buff[2] = 0; Rectangle tile = {off.x+size*(game.players[i].x), off.y+size*(game.players[i].y), size, size}; DrawText(buff, tile.x+size-MeasureText(buff, size/5)-5, tile.y+size-size/5, i == player ? size/4 : size/5, i == player ? WHITE : ColorFromHSV(((float)i/MAX_PLAYER)*360, 1, 1) ); } for (int i = 0; i < game.players[player].nb_cartes; i++) { char buff[3]; carte_name(game.players[player].cartes[i], buff); buff[2] = 0; DrawText(buff, 0, size/5*i, size/5, i == (int)carte%game.players[player].nb_cartes ? WHITE : RED); } } EndDrawing(); } }