#include <stdio.h>
#define NB_JOUEUR 4
#include <string.h>
#include <stdlib.h>
#include <time.h>
int input[5]= {0,0,0,0,0};
void _init_jeu ();
struct card_action{
char nom[32];
int indice;
int nombre;
};
struct card_adresse{
int adresse;
int indice;
int nombre;
};
struct card_plan{
int est_valide[NB_JOUEUR];
int points[2];
int condition[25];
void (*test)(struct card_plan*, int);
int numero;
int indice;
int est_VA;
};
struct scarte{
int len_action;
int len_adresse;
int len_plan;
struct card_action action[6];
struct card_adresse adresse[15];
struct card_plan plan[28];
int carte_tire[6];
int (*tirage)(struct scarte*);
};
typedef struct scarte S_cartes;
struct maison{
int indice;
int adresse;
int status;
int geometrie;
};
struct plt_allee{
int nb_maison;
int indice_piscine[3];
int parcs[2];
struct maison Maison[13];
};
struct plt{
struct plt_allee allee[3];
int indice_bis[9][3];
int rond_point[2][3];
int bonus_immo[6];
int geo[6];
int interim;
int cpt_refus;
int (*cpt_bis)(struct plt*);
int (*cpt_geo)(struct plt*);
};
typedef struct plt S_Plateau;
struct game {
S_Plateau Plateaux[NB_JOUEUR];
S_cartes Cartes;
int (*update)(struct game*);
};
typedef struct game S_Jeu;
S_Jeu Jeu;
void verif_plan(struct card_plan*, int);
void verif_plan1(struct card_plan*, int);
void verif_plan2(struct card_plan*, int);
void verif_plan3(struct card_plan*, int);
int compter_bis(S_Plateau*);
int compter_geometre(S_Plateau*);
int update_jeu(S_Jeu*);
int nouv_tirage(S_cartes*);
void _init_jeu () {
srand(time(NULL));
//###########################################################################################################################################################################################
// INIT sCARTES
//###########################################################################################################################################################################################
Jeu.Cartes.len_action=81;
Jeu.Cartes.len_adresse=81;
Jeu.Cartes.len_plan=28;
char cardname[6][32]={"Géomètre","Agent immobilier","Paysagiste","Fabricant de piscine","Agence d’intérim","Numéro Bis"};
int i,j;
for (i=0;i<6;i++){
strcpy(Jeu.Cartes.action[i].nom, cardname[i]);Jeu.Cartes.action[i].indice=i;
if (i<3)
Jeu.Cartes.action[i].nombre=18;
else
Jeu.Cartes.action[i].nombre=9;
}
for (i=0;i<15;i++){
Jeu.Cartes.adresse[i].indice=i;Jeu.Cartes.adresse[i].adresse=i+1;
if (i<2)
Jeu.Cartes.adresse[i].nombre=3;
else {
if (i<8)
Jeu.Cartes.adresse[i].nombre=i+2;
else
Jeu.Cartes.adresse[i].nombre=16-i;
}
}
Jeu.Cartes.adresse[14].nombre=3;
const int lst_condition[18][6] = {
// --- Plans N°1 (Indices 0 à 5) ---
{6, 0, 0, 0, 0, 0}, // Indice 0 : Six lotissements de 1
{0, 4, 0, 0, 0, 0}, // Indice 1 : Quatre lotissements de 2
{0, 0, 3, 0, 0, 0}, // Indice 2 : Trois lotissements de 3
{0, 0, 0, 2, 0, 0}, // Indice 3 : Deux lotissements de 4
{0, 0, 0, 0, 2, 0}, // Indice 4 : Deux lotissements de 5
{0, 0, 0, 0, 0, 2}, // Indice 5 : Deux lotissements de 6
// --- Plans N°2 (Indices 6 à 11) ---
{3, 0, 0, 0, 0, 1}, // Indice 6 : Trois de 1 + Un de 6
{0, 2, 0, 0, 1, 0}, // Indice 7 : Deux de 2 + Un de 5
{0, 0, 1, 1, 0, 0}, // Indice 8 : Un de 3 + Un de 4
{0, 0, 0, 1, 1, 0}, // Indice 9 : Un de 4 + Un de 5
{4, 0, 0, 1, 0, 0}, // Indice 10: Quatre de 1 + Un de 4
{0, 0, 2, 1, 0, 0}, // Indice 11: Deux de 3 + Un de 4
// --- Plans N°3 (Indices 12 à 17) ---
{1, 1, 0, 0, 0, 1}, // Indice 12: Un de 1 + Un de 2 + Un de 6
{1, 2, 1, 0, 0, 0}, // Indice 13: Un de 1 + Deux de 2 + Un de 3
{2, 1, 1, 0, 0, 0}, // Indice 14: Deux de 1 + Un de 2 + Un de 3
{0, 1, 1, 0, 1, 0}, // Indice 15: Un de 2 + Un de 3 + Un de 5
{1, 0, 0, 1, 1, 0}, // Indice 16: Un de 1 + Un de 4 + Un de 5
{0, 1, 1, 1, 0, 0} // Indice 17: Un de 2 + Un de 3 + Un de 4
};//nb quartier de {1,2,3,4,5,6} habitation
for (i=0;i<28;i++){
for (j=0;j<NB_JOUEUR;j++){
Jeu.Cartes.plan[i].est_valide[j]=0;
}
if (i<18) {
memcpy(Jeu.Cartes.plan[i].condition, lst_condition[i], sizeof(lst_condition[i]));
Jeu.Cartes.plan[i].test=verif_plan;
}
else {
switch (i) {
case 18:{
Jeu.Cartes.plan[i].test=verif_plan1;
memcpy(Jeu.Cartes.plan[i].condition, (int[25]){25,
10, 50, 70, 90,
1, 21, 31, 41, 51, 61, 91, 101,
2, 12, 22, 32, 42, 52, 62, 72, 82, 92, 102, 112
}, 25 * sizeof(int));
break;
}
case 19: {
Jeu.Cartes.plan[i].test=verif_plan1;
memcpy(Jeu.Cartes.plan[i].condition, (int[24]){24,
0, 10, 20, 30, 40, 50, 60, 70, 80, 90,
1, 21, 31, 41, 51, 61, 91,
2, 22, 62, 82, 102, 112
}, 24 * sizeof(int));
break;
}
case 20: {
Jeu.Cartes.plan[i].test=verif_plan2;
memcpy(Jeu.Cartes.plan[i].condition, (int[24]){
5,
0
}, 2 * sizeof(int));
break;
}
case 21: {
Jeu.Cartes.plan[i].test=verif_plan2;
memcpy(Jeu.Cartes.plan[i].condition, (int[24]){
0,
7
}, 2 * sizeof(int));
break;
}
case 22: {
Jeu.Cartes.plan[i].test=verif_plan1;
memcpy(Jeu.Cartes.plan[i].condition, (int[24]){22,
0, 10, 50, 70, 90,
1, 21, 31, 41, 51, 61, 91, 101,
2, 12, 32, 52, 62, 92, 102, 112
}, 22 * sizeof(int));
break;
}
case 23: {
Jeu.Cartes.plan[i].test=verif_plan3;
memcpy(Jeu.Cartes.plan[i].condition, (int[24]){
4,
0,
2,
0
}, 4 * sizeof(int));
break;
}
case 24: {
Jeu.Cartes.plan[i].test=verif_plan3;
memcpy(Jeu.Cartes.plan[i].condition, (int[24]){
4,
1,
1,
1
}, 4 * sizeof(int));
break;
}
case 25: {
Jeu.Cartes.plan[i].test=verif_plan3;
memcpy(Jeu.Cartes.plan[i].condition, (int[24]){
4,
2,
0,
0
}, 4 * sizeof(int));
break;
}
case 26: {
Jeu.Cartes.plan[i].test=verif_plan3;
memcpy(Jeu.Cartes.plan[i].condition, (int[24]){
3,
1,
1,
0
}, 4 * sizeof(int));
break;
}
case 27: {
Jeu.Cartes.plan[i].test=verif_plan3;
memcpy(Jeu.Cartes.plan[i].condition, (int[24]){
2,
1,
1,
0
}, 4 * sizeof(int));
break;
}
}
}
Jeu.Cartes.plan[i].indice=i;
if (i<6){
Jeu.Cartes.plan[i].numero=1;
Jeu.Cartes.plan[i].est_VA=0;
}
else {
if (i<12){
Jeu.Cartes.plan[i].numero=2;
Jeu.Cartes.plan[i].est_VA=0;
}
else{
if (i<18){
Jeu.Cartes.plan[i].numero=3;
Jeu.Cartes.plan[i].est_VA=0;
}
else{
if (i<23){
Jeu.Cartes.plan[i].numero=1;
Jeu.Cartes.plan[i].est_VA=1;
}
else{
Jeu.Cartes.plan[i].numero=2;
Jeu.Cartes.plan[i].est_VA=1;
}
}
}
}
int valeurs_points[28][2] = {
{8,4}, {10,6}, {8,3}, {6,3}, {8,4}, {10,6},
{10,6}, {12,7}, {8,4}, {9,5}, {9,5}, {12,7},
{13,7}, {7,3}, {7,3}, {11,6}, {13,7}, {8,4},
{6,3}, {7,4}, {10,6}, {8,4}, {6,3},
{5,3}, {7,4}, {12,5}, {7,4}, {12,7}
};
Jeu.Cartes.plan[i].points[0] = valeurs_points[i][0];
Jeu.Cartes.plan[i].points[1] = valeurs_points[i][1];
}
for(i=0; i<6; i++)
Jeu.Cartes.carte_tire[i] = 0;
Jeu.Cartes.tirage=nouv_tirage;
//###########################################################################################################################################################################################
// INIT sPLATEAUX
//###########################################################################################################################################################################################
const int piscines_init[3][3] = {
{2, 3, 7}, // Valeurs pour j = 0
{3, 7, 10}, // Valeurs pour j = 1
{1, 5, 10} // Valeurs pour j = 2
};
int k;
for (i=0;i<NB_JOUEUR;i++) {
for (j=0;j<3;j++) {
Jeu.Plateaux[i].allee[j].nb_maison=j+10;
memcpy(Jeu.Plateaux[i].allee[j].indice_piscine, piscines_init[j], sizeof(piscines_init[j]));
Jeu.Plateaux[i].allee[j].parcs[0]=0;Jeu.Plateaux[i].allee[j].parcs[1]=j+3;
for (k=0;k<13;k++){
Jeu.Plateaux[i].allee[j].Maison[k].indice=k;Jeu.Plateaux[i].allee[j].Maison[k].status=0;Jeu.Plateaux[i].allee[j].Maison[k].adresse=0;Jeu.Plateaux[i].allee[j].Maison[k].geometrie=0;
}
Jeu.Plateaux[i].allee[j].Maison[0].geometrie=1; Jeu.Plateaux[i].allee[j].Maison[13].geometrie=1;
}
for (j=0;j<9;j++) {
for (k=0;k<3;k++){
Jeu.Plateaux[i].indice_bis[j][k]=0;
}
}
for (j=0;j<3;j++){
Jeu.Plateaux[i].rond_point[0][j]=0;Jeu.Plateaux[i].rond_point[1][j]=0;
}
for (j=0;j<6;j++){
Jeu.Plateaux[i].bonus_immo[0]=0;
Jeu.Plateaux[i].geo[j]=0;
}
Jeu.Plateaux[i].cpt_bis=compter_bis;
Jeu.Plateaux[i].cpt_geo=compter_geometre;
Jeu.Plateaux[i].interim=0;
Jeu.Plateaux[i].cpt_refus=0;
}
Jeu.update=update_jeu;
}
void verif_plan (struct card_plan *P, int plr) {
if (P->est_valide[plr]!=0)
return;
int i;
for (i=0;i<6;i++){
if (P->condition[i]>Jeu.Plateaux[plr].geo[i])
return;
}
for (i=0;i<NB_JOUEUR;i++) {
if (P->est_valide[i]!=0) {
P->est_valide[plr]=P->points[1];
return;
}
}
P->est_valide[plr]=P->points[0];
}
void verif_plan1 (struct card_plan *P, int plr) {
if (P->est_valide[plr]!=0)
return;
int i;
for (i=1;i<P->condition[0];i++) {
if (Jeu.Plateaux[plr].allee[P->condition[i]%10].Maison[((P->condition[i])-(P->condition[i]%10))/10].adresse==0)
return;
}
for (i=0;i<NB_JOUEUR;i++) {
if (P->est_valide[i]!=0) {
P->est_valide[plr]=P->points[1];
return;
}
}
P->est_valide[plr]=P->points[0];
}
void verif_plan2 (struct card_plan *P, int plr) {
if (P->est_valide[plr]!=0)
return;
int i;
int lst[2]={Jeu.Plateaux[plr].cpt_bis(&Jeu.Plateaux[plr]),Jeu.Plateaux[plr].cpt_geo(&Jeu.Plateaux[plr])};
for (i=0;i<2;i++) {
if (P->condition[i]>lst[i])
return;
}
for (i=0;i<NB_JOUEUR;i++) {
if (P->est_valide[i]!=0) {
P->est_valide[plr]=P->points[1];
return;
}
}
P->est_valide[plr]=P->points[0];
}
void verif_plan3 (struct card_plan *P, int plr) {
if (P->est_valide[plr]!=0)
return;
int i;
if (P->condition[0]==4) {
int j, lst[3]={0,0,0};
for (i=0;i<3;i++) {
for (j=0;j<12;j++)
if (Jeu.Plateaux[plr].allee[i].Maison[j].status==2)
lst[0]+=1;
lst[1]+=Jeu.Plateaux[plr].allee[i].parcs[0];
}
for (i=0;i<2;i++)
if (Jeu.Plateaux[plr].rond_point[i][0]==1)
lst[2]+=1;
for (i=0;i<3;i++)
if (P->condition[i+1]>lst[i])
return;
}
else {
int lst[3]={0,0,0};
for (i=0;i<12;i++)
if (Jeu.Plateaux[plr].allee[P->condition[0]].Maison[i].status==2)
lst[0]+=1;
lst[1]+=Jeu.Plateaux[plr].allee[P->condition[0]].parcs[0];
for (i=0;i<3;i++)
if (P->condition[i+1]>lst[i])
return;
}
for (i=0;i<NB_JOUEUR;i++) {
if (P->est_valide[i]!=0) {
P->est_valide[plr]=P->points[1];
return;
}
}
P->est_valide[plr]=P->points[0];
}
int compter_bis(S_Plateau *P) {
int cpt;
for (cpt=0;cpt<9;cpt++) {
if (P->indice_bis[cpt][0]==0)
return cpt;
}
return 9;
}
int compter_geometre(S_Plateau *P) {
int i,nb=0;
for (i=0;i<6;i++) {
nb+=P->geo[i];
}
return nb;
}
int nouv_tirage(S_cartes *P) {
if (P->len_action < 3)
return 0;
int i,j;
for (i=0;i<3;i++) {
int cpt=0, nb=(rand()%(P->len_action));
for (j=0;j<6;j++){
cpt+=P->action[j].nombre;
if (cpt>nb){
P->carte_tire[i]=P->action[j].indice;
P->action[j].nombre-=1;
P->len_action-=1;
break;
}
}
cpt=0;nb=(rand()%(P->len_adresse));
for (j=0;j<15;j++){
cpt+=P->adresse[j].nombre;
if (cpt>nb){
P->carte_tire[i+3]=P->adresse[j].indice;
P->adresse[j].nombre-=1;
P->len_adresse-=1;
break;
}
}
}
return 1;
}
int update_est_valide(S_Jeu *P, int ijoueur, int iallee, int imaison, int iadresse) {
int i;
for (i=imaison ; i < P->Plateaux[ijoueur].allee[iallee].nb_maison ; i++) {
if (P->Plateaux[ijoueur].allee[iallee].Maison[i].status) {
if (P->Plateaux[ijoueur].allee[iallee].Maison[i].status==3)
break;
if (P->Plateaux[ijoueur].allee[iallee].Maison[i].adresse > P->Cartes.adresse[iadresse].adresse)
return 0;
}
}
for (i = imaison ; i >= 0 ; i--) {
if (P->Plateaux[ijoueur].allee[iallee].Maison[i].status) {
if (P->Plateaux[ijoueur].allee[iallee].Maison[i].status==3)
break;
if (P->Plateaux[ijoueur].allee[iallee].Maison[i].adresse < P->Cartes.adresse[iadresse].adresse)
return 0;
}
}
P->Plateaux[ijoueur].allee[iallee].Maison[i].adresse = P->Cartes.adresse[iadresse].adresse;
P->Plateaux[ijoueur].allee[iallee].Maison[i].status = 1;
return 1;
}
int update_jeu(S_Jeu *P) { //format input[5]={indice joueur, indice allee, indice maison, indice action, action}
int i, ijoueur=input[0],iallee=input[1],imaison=input[2],iaction=P->Cartes.carte_tire[input[3]],iadresse=P->Cartes.carte_tire[input[3]+3];
if (P->Plateaux[ijoueur].allee[iallee].Maison[imaison].status!=0)
return 0;
switch (iaction) {
case 0: {
if ((P->Plateaux[ijoueur].allee[input[4]%10].Maison[((input[4])-(input[4]%10))/10].geometrie==0) && update_est_valide(P, ijoueur, iallee, imaison, iadresse)) {
P->Plateaux[ijoueur].allee[input[4]%10].Maison[((input[4])-(input[4]%10))/10].geometrie=1;
}
else
return 0;
break;
}
case 1: {
if (((P->Plateaux[ijoueur].bonus_immo[input[4]]<=input[4]) && (P->Plateaux[ijoueur].bonus_immo[input[4]] < 4)) && update_est_valide(P, ijoueur, iallee, imaison, iadresse)) {
P->Plateaux[ijoueur].bonus_immo[input[4]]+=1;
}
else
return 0;
break;
}
case 2: {
if ((P->Plateaux[ijoueur].allee[iallee].parcs[0]!=P->Plateaux[ijoueur].allee[iallee].parcs[1]) && update_est_valide(P, ijoueur, iallee, imaison, iadresse))
P->Plateaux[ijoueur].allee[iallee].parcs[0]+=1;
else
return 0;
break;
}
case 3: {
for (i=0;i<3;i++) {
if ((P->Plateaux[ijoueur].allee[iallee].indice_piscine[i]==imaison) && update_est_valide(P, ijoueur, iallee, imaison, iadresse))
P->Plateaux[ijoueur].allee[iallee].Maison[imaison].status=2;
}
if (P->Plateaux[ijoueur].allee[iallee].Maison[imaison].status!=2)
return 0;
return 1;
}
case 4: {
if (input[4]==3)
return 0;
int nouv_adresse=P->Cartes.adresse[iadresse].adresse + input[4] - 3;
if (!update_est_valide(P, ijoueur, iallee, imaison, nouv_adresse))
return 0;
P->Plateaux[ijoueur].interim+=1;
return 1;
}
case 5: {
if (!update_est_valide(P, ijoueur, iallee, imaison, iadresse))
return 0;
if ((((input[4])-(input[4]%10))/10>0) && (P->Plateaux[ijoueur].allee[input[4]%10].Maison[(((input[4])-(input[4]%10))/10)-1].status!=0)) {
P->Plateaux[ijoueur].indice_bis[P->Plateaux[ijoueur].cpt_bis(&P->Plateaux[ijoueur])][0]=1;
P->Plateaux[ijoueur].indice_bis[P->Plateaux[ijoueur].cpt_bis(&P->Plateaux[ijoueur])][1]=input[4]%10;
P->Plateaux[ijoueur].indice_bis[P->Plateaux[ijoueur].cpt_bis(&P->Plateaux[ijoueur])][2]=((input[4])-(input[4]%10))/10;
P->Plateaux[ijoueur].allee[input[4]%10].Maison[(((input[4])-(input[4]%10))/10)].adresse=P->Plateaux[ijoueur].allee[input[4]%10].Maison[(((input[4])-(input[4]%10))/10)-1].adresse;
P->Plateaux[ijoueur].allee[input[4]%10].Maison[(((input[4])-(input[4]%10))/10)].status=4;
}
else {
if ((((input[4])-(input[4]%10))/10<11) && (P->Plateaux[ijoueur].allee[input[4]%10].Maison[(((input[4])-(input[4]%10))/10)+1].status!=0)) {
P->Plateaux[ijoueur].indice_bis[P->Plateaux[ijoueur].cpt_bis(&P->Plateaux[ijoueur])][0]=1;
P->Plateaux[ijoueur].indice_bis[P->Plateaux[ijoueur].cpt_bis(&P->Plateaux[ijoueur])][1]=input[4]%10;
P->Plateaux[ijoueur].indice_bis[P->Plateaux[ijoueur].cpt_bis(&P->Plateaux[ijoueur])][2]=((input[4])-(input[4]%10))/10;
P->Plateaux[ijoueur].allee[input[4]%10].Maison[(((input[4])-(input[4]%10))/10)].adresse=P->Plateaux[ijoueur].allee[input[4]%10].Maison[(((input[4])-(input[4]%10))/10)+1].adresse;
P->Plateaux[ijoueur].allee[input[4]%10].Maison[(((input[4])-(input[4]%10))/10)].status=4;
}
else {
P->Plateaux[ijoueur].allee[iallee].Maison[i].adresse = 0;
P->Plateaux[ijoueur].allee[iallee].Maison[i].status = 0;
return 0;
}
}
return 1;
}
}
P->Plateaux[ijoueur].allee[iallee].Maison[imaison].adresse=P->Cartes.adresse[iadresse].adresse;
if (P->Plateaux[ijoueur].allee[iallee].Maison[imaison].status==0)
P->Plateaux[ijoueur].allee[iallee].Maison[imaison].status=1;
return 1;
}
// ======================================================================
// ======================================================================
// DEBUT FONCTION DE TESTS (CORRIGEE)
// ======================================================================
// ======================================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define TEST_ASSERT_INT(actual, expected, msg) \
do { \
int _a = (actual); \
int _e = (expected); \
if (_a != _e) { \
printf("[ECHEC] %s\n -> Attendu: %d, Obtenu: %d\n", msg, _e, _a); \
} else { \
printf("[SUCCES] %s\n", msg); \
} \
} while(0)
// Fonction utilitaire pour truquer la pioche (index_choix = de 0 à 2)
void forcer_tirage(int index_choix, int indice_action, int adresse_valeur) {
Jeu.Cartes.carte_tire[index_choix] = indice_action;
// On cherche l'indice de la carte adresse qui correspond à la valeur voulue
int target_idx = 0;
for(int i=0; i<15; i++) {
if(Jeu.Cartes.adresse[i].adresse == adresse_valeur) {
target_idx = Jeu.Cartes.adresse[i].indice;
break;
}
}
Jeu.Cartes.carte_tire[index_choix + 3] = target_idx;
}
#include <stdio.h>
// On simule une rue de 12 maisons.
// 0 = vide, 1 = construit, 3 = rond-point
//int status[12] = { 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 };
//int adresse[12] = { 0, 13, 0, 10, 0, 0, 0, 6, 0, 0, 0, 3 };
// Index mémoires: 0 1 2 3 4 5 6 7 8 9 10 11
// Fonction d'affichage visuel (car le cerveau lit mieux les dessins que les chiffres)
void afficher_rue(int allee, int joueur) {
printf("\n============= AFFICHAGE PHYSIQUE DE LA RUE =============\n");
printf(" <-- GAUCHE (Debut) DROITE (Fin) -->\n\n");
printf("Index : ");
for(int i = 11; i >= 0; i--) printf("[%2d] ", i);
printf("\nNum : ");
for(int i = 11; i >= 0; i--) {
if(Jeu.Plateaux[joueur].allee[allee].Maison[i].status == 0) printf(" - ");
else if (Jeu.Plateaux[joueur].allee[allee].Maison[i].status == 3) printf(" (R) ");
else printf(" %2d ", Jeu.Plateaux[joueur].allee[allee].Maison[i].adresse);
}
printf("\n========================================================\n");
}
// ======================================================================
// L'AUDITEUR ABSOLU (Vérification des Invariants)
// ======================================================================
// Cette fonction scanne le plateau et vérifie que la réalité physique
// du jeu Welcome To est respectée, quoi qu'il arrive.
int auditer_plateau(S_Jeu *P, int ijoueur) {
for (int a = 0; a < 3; a++) {
int val_droite = 999; // On commence à droite (Index 0), la valeur max théorique
int status_droite = 0;
for (int m = 0; m < P->Plateaux[ijoueur].allee[a].nb_maison; m++) {
int status_actuel = P->Plateaux[ijoueur].allee[a].Maison[m].status;
int val_actuelle = P->Plateaux[ijoueur].allee[a].Maison[m].adresse;
if (status_actuel == 3) {
// C'est un rond-point. La rue est coupée, on réinitialise la valeur max.
val_droite = 999;
status_droite = 3;
continue;
}
if (status_actuel != 0) { // Si la maison est construite (Normal, Piscine ou Bis)
// REGLE 1 : L'ordre croissant (lu de droite à gauche, donc décroissant)
if (val_actuelle > val_droite) {
printf("[AUDIT FATAL] Allee %d : %d a l'index %d est > %d a sa droite !\n", a, val_actuelle, m, val_droite);
return 0; // ECHEC !
}
// REGLE 2 : L'unicité des numéros (sauf Numéro Bis)
if (val_actuelle == val_droite) {
if (status_actuel != 4 && status_droite != 4) {
printf("[AUDIT FATAL] Allee %d : Doublon illegal de %d a l'index %d sans status Bis !\n", a, val_actuelle, m);
return 0; // ECHEC !
}
}
val_droite = val_actuelle;
status_droite = status_actuel;
}
}
}
return 1; // Le plateau est structurellement parfait
}
// ======================================================================
// LE TEST DU SINGE (FUZZING)
// ======================================================================
// On va simuler 10 000 coups complètement aléatoires (légaux et illégaux).
// Si update_jeu() plante ou si l'auditeur trouve une faille, le test échoue.
void test_fuzzing_infaillible() {
printf("\n--- SCENARIO GLOBAL : FUZZING (10 000 COUPS ALEATOIRES) ---\n");
_init_jeu();
int coups_valides = 0;
int coups_refuses = 0;
int crash = 0;
for (int i = 0; i < 100000; i++) {
// 1. On remplit le deck artificiellement si besoin (car on va piocher beaucoup)
if (Jeu.Cartes.len_action < 3) _init_jeu();
nouv_tirage(&Jeu.Cartes); // Tirage normal
for (i=0;i<4;i++) {
// 2. Génération d'un input 100% aléatoire
input[0] = i; // Joueur au hasard
input[1] = rand() % 3; // Allée au hasard (0 à 2)
input[2] = rand() % 12; // Maison au hasard (0 à 11, on inclut le 11 pour tester les limites)
input[3] = rand() % 3; // Carte choisie (0 à 2)
// Pour input[4] (l'action spéciale), on génère aussi du chaos
int action_actuelle = Jeu.Cartes.carte_tire[input[3]];
if (action_actuelle == 5) {
input[4] = (rand() % 13) * 10 + (rand() % 3); // Format Bis (Maison*10 + Allée)
} else if (action_actuelle == 4) {
input[4] = rand() % 7; // Intérim (0 à 6)
} else if (action_actuelle == 0) {
input[4] = (rand() % 13) * 10 + (rand() % 3); // Géomètre
} else {
input[4] = rand() % 6; // Immo ou autre
}
// 3. On tente de jouer ce coup absurde
// L'astuce : On se fiche de savoir si update_jeu renvoie 0 ou 1.
// On veut juste s'assurer qu'il ne CRASH pas.
int res = update_jeu(&Jeu);
if (res == 1) coups_valides++;
else coups_refuses++;
// 4. VERIFICATION ABSOLUE
// Après CE coup, le plateau du joueur est-il toujours physiquement cohérent ?
if (auditer_plateau(&Jeu, input[0]) == 0) {
printf("\n[!!!] FAIL : LE FUZZER A CASSE LE JEU AU COUP %d [!!!]\n", i);
printf("Input fautif : J=%d, Allee=%d, Maison=%d, Choix=%d, Spé=%d\n", input[0], input[1], input[2], input[3], input[4]);
crash = 1;
break;
}
}
if (auditer_plateau(&Jeu, input[0]) == 0) break;
}
TEST_ASSERT_INT(crash, 0, "Le Fuzzer n'a pas reussi a corrompre le plateau !");
printf(" -> Stats du Singe : %d coups legaux trouves, %d coups bloques par le moteur.\n\n", coups_valides, coups_refuses);
afficher_rue(input[1],input[0]);
}
// ======================================================================
// PARTIE PARFAITE (E2E)
// ======================================================================
// Un scénario E2E (End-to-End) qui simule une vraie partie stratégique
// pour valider qu'on peut remplir une rue entièrement et marquer les points.
void test_partie_parfaite() {
printf("\n--- SCENARIO GLOBAL : LA PARTIE PARFAITE ---\n");
_init_jeu();
int j = 0; // Joueur 0
int allee = 0; // On va remplir l'allée 0 (10 maisons) de 15 à 6
// On va forcer un placement de la maison index 0 à l'index 9 (Droite à Gauche)
int valeurs[10] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6};
for (int i = 0; i < 10; i++) {
forcer_tirage(0, 2, valeurs[i]); // Action Paysagiste, numéro décroissant
input[0] = j; input[1] = allee; input[2] = i; input[3] = 0; input[4] = 0;
int res = update_jeu(&Jeu);
if(res == 0) {
printf("Echec inattendu a l'index %d pour la valeur %d\n", i, valeurs[i]);
TEST_ASSERT_INT(res, 1, "Remplissage parfait de la rue a echoue");
return;
}
}
TEST_ASSERT_INT(1, 1, "La rue de 10 maisons a ete remplie sans erreur");
// Vérification de la validation d'un plan
// Le plan 1 (Indice 1) demande : Quatre lotissements de 2.
// L'allée 0 a 10 maisons consécutives.
// Mettons des barrières pour couper en lotissements de 2.
Jeu.Plateaux[j].allee[allee].Maison[1].geometrie = 1;
Jeu.Plateaux[j].allee[allee].Maison[3].geometrie = 1;
Jeu.Plateaux[j].allee[allee].Maison[5].geometrie = 1;
Jeu.Plateaux[j].allee[allee].Maison[7].geometrie = 1;
// Simulation comptage externe (si pas appelé ailleurs)
Jeu.Plateaux[j].geo[1] = 4; // Triche pour simuler les 4 lotissements de taille 2
verif_plan(&Jeu.Cartes.plan[1], j);
TEST_ASSERT_INT(Jeu.Cartes.plan[1].est_valide[j], Jeu.Cartes.plan[1].points[0], "Le joueur valide le plan grace a sa partie parfaite !");
}
int main() {
printf("=================================================\n");
printf(" BANC DE TESTS DE NIVEAU INGENIERIE \n");
printf("=================================================\n");
test_partie_parfaite();
test_fuzzing_infaillible();
printf("\n=================================================\n");
printf(" FIN DES TESTS \n");
printf("=================================================\n");
return 0;
}
To embed this project on your website, copy the following code and paste it into your website's HTML: