337 lines
9.1 KiB
C
337 lines
9.1 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#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();
|
|
}
|
|
}
|