ajouts des fichiers perso
Le plagiat c'est mal donc gare à vos culs
This commit is contained in:
496
game/game_VM.c
Normal file
496
game/game_VM.c
Normal file
@@ -0,0 +1,496 @@
|
||||
#include "game.h"
|
||||
|
||||
#include <sys/random.h>
|
||||
|
||||
#include "maze_2.h"
|
||||
|
||||
#define CHECK_ALLOC(ptr) do { if (ptr == NULL) { fprintf(stderr, "Erreur d'allocation\n"); exit(EXIT_FAILURE); } } while(0)
|
||||
|
||||
/****************************/
|
||||
/*+ Création et libération +*/
|
||||
/****************************/
|
||||
|
||||
// Génération d'un nouveau jeu
|
||||
game* create_newgame(const int sh, const int sv, mask *m, const generator f, const objgenerator fo, const int nb_minotaure, const int tressage)
|
||||
{
|
||||
maze *p_maze;
|
||||
if(m != NULL)
|
||||
{
|
||||
resize_mask(m, sh, sv);
|
||||
p_maze = create_proto_maze(m);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_maze = create_proto_maze_nomask(sh, sv);
|
||||
}
|
||||
gen_minotaurs_maze(p_maze, nb_minotaure);
|
||||
(*gen_funs[f]) (p_maze);
|
||||
(*obj_funs[fo]) (p_maze);
|
||||
braid_maze(p_maze, tressage);
|
||||
game *p_game = malloc(sizeof(game));
|
||||
CHECK_ALLOC(p_game);
|
||||
p_game->m = p_maze;
|
||||
p_game->score = 0;
|
||||
p_game->nbombs = 0;
|
||||
p_game->npolys = 0;
|
||||
p_game->player_alive = true;
|
||||
p_game->player_dir = NORTH;
|
||||
p_game->minotaurs_alive = malloc(nb_minotaure * sizeof(bool));
|
||||
CHECK_ALLOC(p_game->minotaurs_alive);
|
||||
for(int i = 0; i < nb_minotaure; i++)
|
||||
{
|
||||
p_game->minotaurs_alive[i] = true;
|
||||
}
|
||||
p_game->minotaurs_dirs = calloc(nb_minotaure, sizeof(cardinal));
|
||||
CHECK_ALLOC(p_game->minotaurs_dirs);
|
||||
p_game->nb_deadends = count_dead_ends(p_maze);
|
||||
p_game->exits = get_exits_maze(p_maze);
|
||||
p_game->turns = 0;
|
||||
p_game->log = create_history();
|
||||
int start = p_maze->player;
|
||||
cardinal useless;
|
||||
while ((game_try_kill_player(p_game, &useless) != -1 && p_game->m->nb_minotaurs < p_game->m->nb_reachable - 10)
|
||||
|| get_object_maze(p_game->m, start) == EXIT || !can_be_used(p_game->m, start))
|
||||
{
|
||||
//on évite le spawn kill et le spawn win (cntraite du nombre de minotaures car faut pas forcer non plus)
|
||||
getrandom(&start, sizeof(start), 0);
|
||||
start %= p_game->m->hsize * p_game->m->vsize;
|
||||
}
|
||||
free_occupied_maze(p_game->m, p_game->m->player);
|
||||
p_game->m->player = start;
|
||||
make_occupied_maze(p_game->m, start);
|
||||
return p_game;
|
||||
}
|
||||
|
||||
void free_game(game *g) {
|
||||
free_history(g->log);
|
||||
free(g->minotaurs_alive);
|
||||
free(g->minotaurs_dirs);
|
||||
free_maze(g->m);
|
||||
free(g);
|
||||
}
|
||||
|
||||
/***********************************************/
|
||||
/*+ Implémentation des attaques de minotaures +*/
|
||||
/***********************************************/
|
||||
|
||||
// ReSharper disable CppDFANullDereference
|
||||
|
||||
int game_try_kill_player(game *g, cardinal *card) {
|
||||
const int cell = g->m->player;
|
||||
int neighbour = get_adj_maze(g->m, cell, NORTH);
|
||||
if(neighbour != -1) {
|
||||
const int mino = has_minotaur_maze(g->m, neighbour);
|
||||
if(mino != -1 && g->minotaurs_alive[mino] && !has_wall_maze(g->m, cell, NORTH)) {
|
||||
*card = SOUTH;
|
||||
g->minotaurs_dirs[mino] = NORTH;
|
||||
g->player_alive = false;
|
||||
return mino;
|
||||
}
|
||||
}
|
||||
neighbour = get_adj_maze(g->m, cell, EAST);
|
||||
if(neighbour != -1) {
|
||||
const int mino = has_minotaur_maze(g->m, neighbour);
|
||||
if(mino != -1 && g->minotaurs_alive[mino] && !has_wall_maze(g->m, cell, EAST)) {
|
||||
*card = WEST;
|
||||
g->minotaurs_dirs[mino] = EAST;
|
||||
g->player_alive = false;
|
||||
return mino;
|
||||
}
|
||||
}
|
||||
neighbour = get_adj_maze(g->m, cell, SOUTH);
|
||||
if(neighbour != -1) {
|
||||
const int mino = has_minotaur_maze(g->m, neighbour);
|
||||
if(mino != -1 && g->minotaurs_alive[mino] && !has_wall_maze(g->m, cell, SOUTH)) {
|
||||
*card = NORTH;
|
||||
g->player_alive = false;
|
||||
g->minotaurs_dirs[mino] = SOUTH;
|
||||
return mino;
|
||||
}
|
||||
}
|
||||
neighbour = get_adj_maze(g->m, cell, WEST);
|
||||
if(neighbour != -1) {
|
||||
const int mino = has_minotaur_maze(g->m, neighbour);
|
||||
if(mino != -1 && g->minotaurs_alive[mino] && !has_wall_maze(g->m, cell, WEST)) {
|
||||
*card = EAST;
|
||||
g->minotaurs_dirs[mino] = WEST;
|
||||
g->player_alive = false;
|
||||
return mino;
|
||||
}
|
||||
}
|
||||
//on n'a pas trouvé de minotaure
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ReSharper restore CppDFANullDereference
|
||||
|
||||
/***************************/
|
||||
/*+ Traitement des objets +*/
|
||||
/***************************/
|
||||
|
||||
void game_consume_object(game *g, const int iter, const object obj) {
|
||||
switch (obj) {
|
||||
case SMALLT:
|
||||
g->score += iter * VALSMALL;
|
||||
break;
|
||||
case MEDT:
|
||||
g->score += iter * VALMED;
|
||||
break;
|
||||
case LARGET:
|
||||
g->score += iter * VALLARGE;
|
||||
break;
|
||||
case BOMB:
|
||||
g->nbombs += iter;
|
||||
break;
|
||||
case POLY:
|
||||
g->npolys += iter;
|
||||
break;
|
||||
default: //inclue EXIT et NONE
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
object game_treat_object(game *g) {
|
||||
const int cell = g->m->player;
|
||||
const object obj = get_object_maze(g->m, cell);
|
||||
game_consume_object(g, 1, obj);
|
||||
if(obj != EXIT)
|
||||
{
|
||||
add_object_maze(g->m, cell, NONE);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
/*+ Implémentation d'une demande de mouvement du joueur +*/
|
||||
/**********************************************************/
|
||||
|
||||
bool implement_game_move(game *g, const move mv, const strategy strat) {
|
||||
if (mv != M_WAIT)
|
||||
{
|
||||
g->player_dir = (cardinal)mv;
|
||||
}
|
||||
if (!g->player_alive || !valid_move_maze(g->m, g->m->player, mv))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (mv != M_WAIT)
|
||||
{
|
||||
free_occupied_maze(g->m, g->m->player);
|
||||
g->m->player = get_adj_maze(g->m, g->m->player, g->player_dir);
|
||||
make_occupied_maze(g->m, g->m->player);
|
||||
}
|
||||
move *mino_move = malloc(g->m->nb_minotaurs * sizeof(move));
|
||||
str_funs[strat](g->m, mv, mino_move);
|
||||
for (int i = 0; i < g->m->nb_minotaurs; i++)
|
||||
{
|
||||
if (mino_move[i] != M_WAIT)
|
||||
{
|
||||
g->minotaurs_dirs[i] = (cardinal)mino_move[i];
|
||||
}
|
||||
if (g->minotaurs_alive[i] && valid_move_maze(g->m, g->m->minotaurs[i], mino_move[i]))
|
||||
{
|
||||
//si le mino veut et peut bouger
|
||||
if (mino_move[i] != M_WAIT)
|
||||
{
|
||||
free_occupied_maze(g->m, g->m->minotaurs[i]);
|
||||
g->m->minotaurs[i] = get_adj_maze(g->m, g->m->minotaurs[i], g->minotaurs_dirs[i]);
|
||||
make_occupied_maze(g->m, g->m->minotaurs[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mino_move[i] = M_WAIT; //on corrige le mouvement pour l'historique
|
||||
}
|
||||
}
|
||||
const t_type typ = T_MOVE;
|
||||
t_move *tmove = malloc(sizeof(t_move));
|
||||
CHECK_ALLOC(tmove);
|
||||
tmove->obj = game_treat_object(g);
|
||||
tmove->playermove = mv;
|
||||
tmove->minomoves = mino_move;
|
||||
cardinal card = NORTH;
|
||||
tmove->killer = game_try_kill_player(g, &card);
|
||||
tmove->dirkill = card;
|
||||
const turn t = {typ, .tmove = tmove};
|
||||
add_entry_history(t, g->log);
|
||||
g->turns++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************/
|
||||
/*+ Implémentation des bombes +*/
|
||||
/*******************************/
|
||||
|
||||
bool game_bomb_wall(game *g) {
|
||||
if (g->nbombs == 0 || !g->player_alive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const int neighbour = get_adj_maze(g->m, g->m->player, g->player_dir);
|
||||
if (!can_be_used(g->m, neighbour) || !has_wall_maze(g->m, g->m->player, g->player_dir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
g->nbombs--;
|
||||
g->turns++;
|
||||
del_wall_maze(g->m, g->m->player, g->player_dir);
|
||||
const t_type typ = T_BOMB;
|
||||
t_bomb *tbomb = malloc(sizeof(t_bomb));
|
||||
CHECK_ALLOC(tbomb);
|
||||
tbomb->bombdir = g->player_dir;
|
||||
tbomb->destroyed = true;
|
||||
cardinal card = NORTH;
|
||||
tbomb->killer = game_try_kill_player(g, &card);
|
||||
tbomb->dirkill = card;
|
||||
const turn t = {typ, .tbomb = tbomb};
|
||||
add_entry_history(t, g->log);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*************************************/
|
||||
/*+ Implémentation des polys d'algo +*/
|
||||
/*************************************/
|
||||
|
||||
static bool mino_reachable(maze *p_maze, const int mino, const int cell, const int d)
|
||||
{
|
||||
if (!can_be_used(p_maze, cell))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (mino == cell)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (d == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int c = get_adj_maze(p_maze, cell, NORTH);
|
||||
if (mino_reachable(p_maze, mino, c, d - 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
c = get_adj_maze(p_maze, c, EAST);
|
||||
if (mino_reachable(p_maze, mino, c, d - 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
c = get_adj_maze(p_maze, c, SOUTH);
|
||||
if (mino_reachable(p_maze, mino, c, d - 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
c = get_adj_maze(p_maze, c, SOUTH);
|
||||
if (mino_reachable(p_maze, mino, c, d - 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
c = get_adj_maze(p_maze, c, WEST);
|
||||
if (mino_reachable(p_maze, mino, c, d - 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
c = get_adj_maze(p_maze, c, WEST);
|
||||
if (mino_reachable(p_maze, mino, c, d - 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
c = get_adj_maze(p_maze, c, NORTH);
|
||||
if (mino_reachable(p_maze, mino, c, d - 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
c = get_adj_maze(p_maze, cell, NORTH);
|
||||
return mino_reachable(p_maze, mino, c, d - 1);
|
||||
}
|
||||
|
||||
bool game_kill_minotaurs(game *g, const int d) {
|
||||
if (g->npolys == 0 || !g->player_alive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const int cell = g->m->player;
|
||||
bool done = false;
|
||||
bool *minokilled = calloc(g->m->nb_minotaurs, sizeof(bool));
|
||||
for (int i = 0; i < g->m->nb_minotaurs; i++)
|
||||
{
|
||||
if (g->minotaurs_alive[i] && mino_reachable(g->m, g->m->minotaurs[i], cell, d))
|
||||
{
|
||||
g->minotaurs_alive[i] = false;
|
||||
free_occupied_maze(g->m, g->m->minotaurs[i]);
|
||||
done = true;
|
||||
minokilled[i] = true;
|
||||
}
|
||||
}
|
||||
if (!done)
|
||||
{
|
||||
free(minokilled);
|
||||
return false;
|
||||
}
|
||||
g->npolys--;
|
||||
g->turns++;
|
||||
const t_type typ = T_POLY;
|
||||
const turn t = {typ, .minokilled = minokilled};
|
||||
add_entry_history(t, g->log);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*****************************/
|
||||
/*+ Gestion de l'historique +*/
|
||||
/*****************************/
|
||||
|
||||
bool game_undo(game *g) {
|
||||
const turn *t = last_move_history(g->log);
|
||||
if (t == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (t->type == T_POLY)
|
||||
{
|
||||
g->npolys++;
|
||||
for (int i = 0; i < g->m->nb_minotaurs; i++)
|
||||
{
|
||||
if (t->minokilled[i])
|
||||
{
|
||||
g->minotaurs_alive[i] = true;
|
||||
make_occupied_maze(g->m, g->m->minotaurs[i]);
|
||||
}
|
||||
}
|
||||
g->turns--;
|
||||
rewind_history(g->log); //on note que le tour a été annulé
|
||||
return true;
|
||||
}
|
||||
if (t->type == T_BOMB)
|
||||
{
|
||||
if (t->tbomb->destroyed)
|
||||
{
|
||||
build_wall_maze(g->m, g->m->player, t->tbomb->bombdir);
|
||||
g->nbombs++;
|
||||
}
|
||||
if (t->tbomb->killer != -1)
|
||||
{
|
||||
g->player_alive = true;
|
||||
make_occupied_maze(g->m, g->m->player);
|
||||
}
|
||||
g->turns--;
|
||||
rewind_history(g->log); //on note que le tour a été annulé
|
||||
return true;
|
||||
}
|
||||
if (t->type == T_MOVE)
|
||||
{
|
||||
if (t->tmove->obj != NONE)
|
||||
{
|
||||
add_object_maze(g->m, g->m->player, t->tmove->obj);
|
||||
game_consume_object(g, -1, t->tmove->obj);
|
||||
}
|
||||
if (t->tmove->killer != -1)
|
||||
{
|
||||
g->player_alive = true;
|
||||
}
|
||||
if (t->tmove->playermove != M_WAIT)
|
||||
{
|
||||
free_occupied_maze(g->m, g->m->player);
|
||||
g->m->player = get_adj_maze(g->m, g->m->player, (cardinal)((t->tmove->playermove + 2) % 4));
|
||||
make_occupied_maze(g->m, g->m->player);
|
||||
}
|
||||
g->minotaurs_dirs = (cardinal*)t->tmove->minomoves;
|
||||
for (int i = 0; i < g->m->nb_minotaurs; i++)
|
||||
{
|
||||
if (t->tmove->minomoves[i] != M_WAIT)
|
||||
{
|
||||
g->minotaurs_dirs[i] = (cardinal)t->tmove->minomoves[i]; //on met à jour les directions des minotaures
|
||||
if (g->minotaurs_alive[i])
|
||||
{
|
||||
free_occupied_maze(g->m, g->m->minotaurs[i]);
|
||||
g->m->minotaurs[i] = get_adj_maze(g->m, g->m->minotaurs[i], (cardinal)((g->minotaurs_dirs[i] + 2) % 4));
|
||||
make_occupied_maze(g->m, g->m->minotaurs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
g->turns--;
|
||||
rewind_history(g->log); //on note que le tour a été annulé
|
||||
return true;
|
||||
}
|
||||
fprintf(stderr, "Erreur d'historique, type inconnu\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
bool game_redo(game *g) {
|
||||
const turn *t = next_move_history(g->log);
|
||||
if (t == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (t->type == T_POLY)
|
||||
{
|
||||
g->npolys--;
|
||||
for (int i = 0; i < g->m->nb_minotaurs; i++)
|
||||
{
|
||||
if (t->minokilled[i])
|
||||
{
|
||||
g->minotaurs_alive[i] = false;
|
||||
free_occupied_maze(g->m, g->m->minotaurs[i]);
|
||||
}
|
||||
}
|
||||
g->turns++;
|
||||
continue_history(g->log); //on note que le tour a été rejoué
|
||||
return true;
|
||||
}
|
||||
if (t->type == T_BOMB)
|
||||
{
|
||||
if (t->tbomb->destroyed)
|
||||
{
|
||||
del_wall_maze(g->m, g->m->player, t->tbomb->bombdir);
|
||||
g->player_dir = t->tbomb->bombdir;
|
||||
g->nbombs--;
|
||||
}
|
||||
if (t->tbomb->killer != -1)
|
||||
{
|
||||
g->minotaurs_dirs[t->tbomb->killer] = t->tbomb->dirkill;
|
||||
g->player_alive = false;
|
||||
free_occupied_maze(g->m, g->m->player);
|
||||
}
|
||||
g->turns++;
|
||||
continue_history(g->log); //on note que le tour a été rejoué
|
||||
return true;
|
||||
}
|
||||
if (t->type == T_MOVE)
|
||||
{
|
||||
if (t->tmove->obj != NONE)
|
||||
{
|
||||
game_treat_object(g);
|
||||
}
|
||||
if (t->tmove->killer != -1)
|
||||
{
|
||||
g->player_alive = false;
|
||||
}
|
||||
if (t->tmove->playermove != M_WAIT)
|
||||
{
|
||||
free_occupied_maze(g->m, g->m->player);
|
||||
g->m->player = get_adj_maze(g->m, g->m->player, (cardinal)t->tmove->playermove);
|
||||
make_occupied_maze(g->m, g->m->player);
|
||||
}
|
||||
for (int i = 0; i < g->m->nb_minotaurs; i++)
|
||||
{
|
||||
if (t->tmove->minomoves[i] != M_WAIT)
|
||||
{
|
||||
g->minotaurs_dirs[i] = (cardinal)t->tmove->minomoves[i]; //on met à jour les directions des minotaures
|
||||
if (g->minotaurs_alive[i])
|
||||
{
|
||||
free_occupied_maze(g->m, g->m->minotaurs[i]);
|
||||
g->m->minotaurs[i] = get_adj_maze(g->m, g->m->minotaurs[i], (cardinal)t->tmove->minomoves[i]);
|
||||
make_occupied_maze(g->m, g->m->minotaurs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
g->turns++;
|
||||
continue_history(g->log); //on note que le tour a été rejoué
|
||||
return true;
|
||||
}
|
||||
fprintf(stderr, "Erreur d'historique, type inconnu\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
Reference in New Issue
Block a user