begin dora 07

This commit is contained in:
nemo 2025-02-17 09:35:46 +01:00
parent 238422cec2
commit e6840b03f4
4 changed files with 350 additions and 1 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
spaghetti-vs-bolognese
spaghetti-vs-bolognese.exe
dora
dora.exe

View File

@ -8,4 +8,4 @@ win:
x86_64-w64-mingw32-gcc -Wall -Wextra main.c -o spaghetti-vs-bolognese -I../lib -L../lib -l:../lib/windows-libraylib.a -lgdi32 -lwinmm
clean:
rm spaghetti-vs-bolognese
rm spaghetti-vs-bolognese spaghetti-vs-bolognese.exe

11
07-dora/Makefile Normal file
View File

@ -0,0 +1,11 @@
all:
gcc -Wall -Wextra main.c -o dora -I../lib -l:../lib/libraylib.a -lm
run: all
./dora
win:
x86_64-w64-mingw32-gcc -Wall -Wextra main.c -o dora -I../lib -L../lib -l:../lib/windows-libraylib.a -lgdi32 -lwinmm
clean:
rm dora dora.exe

336
07-dora/main.c Normal file
View File

@ -0,0 +1,336 @@
#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();
}
}