/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        P L A C E M E N T   A L E A T O I R E   D E   D O M I N O S   D A N S   L E   P L A N  :                                   */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '\$xtc/dominos.11\$vv\$c' :                                                                                         */
/*                                                                                                                                   */
/*                    Jean-Francois COLONNA (LACTAMME, 20230804113616).                                                              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

#include  "INCLUDES.01.I"

extern    void      *malloc();

extern    void      srand48();
extern    double    drand48();

static    int       dimX=0;
#define   Xmin      0
#define   Xmax      (Xmin + (dimX-1))
/* Definition des abscisses.                                                                 */
static    int       dimY=0;
#define   Ymin      0
#define   Ymax      (Ymin + (dimY-1))
/* Definition des ordonnees.                                                                 */

#define   dimX_reduite                                                                                                                  \
(dimX/PAS_X)
#define   dimY_reduite                                                                                                                  \
(dimY/PAS_Y)

#define   PAS_X                                                                                                                         \
(8)
#define   PAS_Y                                                                                                                         \
(8)

#define   IMAGE(x,y)                                                                                                                    \
(*(image + ((((y)-Ymin)*dimY) + ((x)-Xmin))))                                                                       \
/* Acces a un point de l'image.                                                              */

#define   store(n,x,y)                                                                                                                  \
{                                                                                                                   \
if        ((x >= Xmin) && (x <= Xmax) && (y >= Ymin) && (y <= Ymax))                                                \
{                                                                                                         \
IMAGE(x,y) = n;                                                                                           \
}                                                                                                         \
else                                                                                                                \
{                                                                                                         \
}                                                                                                         \
}                                                                                                                   \
/* Rangement d'un point valide d'une image.                                                  */

#define   GRAINE_DU_GENERATEUR_ALEATOIRE                                                                                                \
1789
#define   SEUIL_CHOIX_ORIENTATION                                                                                                       \
0.5

#define   NIVEAU_VIDE______                                                                                                             \
NOIR
#define   NIVEAU_HORIZONTAL                                                                                                             \
(BLANC/1)
#define   NIVEAU_VERTICAL__                                                                                                             \
(BLANC/2)
#define   NIVEAU_GRILLE____                                                                                                             \
(BLANC/4)

enum      ModesDisponibles
{
LigneLigne_HV=1
,LigneLigne_VH
,ColonneColonne_HV
,ColonneColonne_VH
,SpiraleCarree
,Aleatoire
};
int       mode=LigneLigne_HV;
/* Definition du mode de parcours du domaine :                                               */
/*                                                                                           */
/*                  mode=1  : Ligne apres ligne (HV),                                        */
/*                  mode=2  : Ligne apres ligne (VH),                                        */
/*                  mode=3  : Colonne apres colonne (HV),                                    */
/*                  mode=4  : Colonne apres colonne (VH),                                    */
/*                  mode=5  : Suivant une spirale "caree",                                   */
/*                  mode=6  : Mode aleatoire.                                                */
/*                                                                                           */

#define   FACTEUR_ALEATOIRE                                                                                                             \
100

#define   TEST_IMAGE(x,y)                                                                                                               \
IMAGE((MIN2((x)+(PAS_X/2),Xmax)),((MIN2((y)+(PAS_Y/2),Ymax))))

#define   TRACE_RECTANGLE(x,y,nx,ny,niveau)                                                                                             \
{                                                                                                                   \
int       xc;                                                                                                       \
int       yc;                                                                                                       \
int       xcm=(x);                                                                                                  \
int       ycm=(y);                                                                                                  \
int       xcM=(x+(nx*PAS_X))-1;                                                                                     \
int       ycM=(y+(ny*PAS_Y))-1;                                                                                     \
\
for       (xc=xcm ; xc <= xcM ; xc++)                                                                               \
{                                                                                                         \
for       (yc=ycm ; yc <= ycM ; yc++)                                                                     \
{                                                                                               \
IMAGE(xc,yc) =                                                                                  \
COND(IFOU(IFOU(IFEQ(xc,xcm),IFEQ(xc,xcM))                                                       \
,IFOU(IFEQ(yc,ycm),IFEQ(yc,ycM))                                                       \
)                                                                                     \
,NIVEAU_GRILLE____                                                                          \
,niveau                                                                                     \
);                                                                                         \
}                                                                                               \
}                                                                                                         \
\
if        (niveau == NIVEAU_HORIZONTAL)                                                                             \
{                                                                                                         \
CompteurH++;                                                                                              \
}                                                                                                         \
else                                                                                                                \
{                                                                                                         \
if        (niveau == NIVEAU_VERTICAL__)                                                                   \
{                                                                                               \
CompteurV++;                                                                                    \
}                                                                                               \
else                                                                                                      \
{                                                                                               \
fprintf(stderr,"Le niveau %d n'est pas reconnu\n",niveau);                                      \
}                                                                                               \
}                                                                                                         \
}

#define   TENTATIVE_HORIZONTALE(x,y)                                                                                                    \
{                                                                                                                   \
if        (((x+PAS_X+1) <= Xmax) && (TEST_IMAGE(x+PAS_X+1,y) == NIVEAU_VIDE______))                                 \
{                                                                                                         \
TRACE_RECTANGLE(x,y,2,1,NIVEAU_HORIZONTAL);                                                               \
/* Trace d'un rectangle horizontal 2x1.                                                      */ \
}                                                                                                         \
else                                                                                                                \
{                                                                                                         \
if        (((y+PAS_Y+1) <= Ymax) && (TEST_IMAGE(x,y+PAS_Y+1) == NIVEAU_VIDE______))                       \
{                                                                                               \
TRACE_RECTANGLE(x,y,1,2,NIVEAU_VERTICAL__);                                                     \
/* Trace d'un rectangle vertical 1x1.                                                        */ \
}                                                                                               \
else                                                                                                      \
{                                                                                               \
}                                                                                               \
}                                                                                                         \
}

#define   TENTATIVE_VERTICALE__(x,y)                                                                                                    \
{                                                                                                                   \
if        (((y+PAS_Y+1) <= Ymax) && (TEST_IMAGE(x,y+PAS_Y+1) == NIVEAU_VIDE______))                                 \
{                                                                                                         \
TRACE_RECTANGLE(x,y,1,2,NIVEAU_VERTICAL__);                                                               \
/* Trace d'un rectangle vertical 1x1.                                                        */ \
}                                                                                                         \
else                                                                                                                \
{                                                                                                         \
if        (((x+PAS_X+1) <= Xmax) && (TEST_IMAGE(x+PAS_X+1,y) == NIVEAU_VIDE______))                       \
{                                                                                               \
TRACE_RECTANGLE(x,y,2,1,NIVEAU_HORIZONTAL);                                                     \
/* Trace d'un rectangle horizontal 2x1.                                                      */ \
}                                                                                               \
else                                                                                                      \
{                                                                                               \
}                                                                                               \
}                                                                                                         \
}

#define   DEFINITION_TUILE_1x2(x,y,test,tentative_1,tentative_2)                                                                        \
{                                                                                                                   \
if        (TEST_IMAGE(x,y) == NIVEAU_VIDE______)                                                                    \
{                                                                                                         \
double    random=drand48();                                                                               \
\
if        test                                                                                            \
{                                                                                               \
tentative_1;                                                                                    \
}                                                                                               \
else                                                                                                      \
{                                                                                               \
tentative_2;                                                                                    \
}                                                                                               \
}                                                                                                         \
else                                                                                                                \
{                                                                                                         \
}                                                                                                         \
}

#define   PARCOURS_SEQUENTIEL(boucle1,boucle2,test,tentative_1,tentative_2)                                                             \
{                                                                                                                   \
for       boucle1                                                                                                   \
{                                                                                                         \
for       boucle2                                                                                         \
{                                                                                               \
DEFINITION_TUILE_1x2(x,y,test,tentative_1,tentative_2);                                         \
}                                                                                               \
}                                                                                                         \
}

int       editer_les_statistiques=VRAI;

void      main(int argc,char *argv[])
{
int                 x,y;
/* Definition des coordonnees.                                                               */
unsigned  char      *image;
/* Definition de l'image a generer...                                                        */

int                 CompteurH=0;
int                 CompteurV=0;

if        (argc > 1)
{
mode=atoi(argv[1]);
/* Recuperation du mode de remplissage...                                                    */
}
else
{
}

Get(dimX,"dimX");
Get(dimY,"dimY");
/* Recuperation des dimensions en 'X' et en 'Y' de l'image a generer.                        */

image=malloc(dimX*dimY);
/* Definition de l'image a generer...                                                        */

srand48(GRAINE_DU_GENERATEUR_ALEATOIRE);

for       (y=Ymin ; y<=Ymax ; y++)
{
for       (x=Xmin ; x<=Xmax ; x++)
{
store(NIVEAU_VIDE______,x,y);
}
}

switch    (mode)
{
case      LigneLigne_HV:
/* Mode ligne par ligne (HORIZONTALE,VERTICALE__) :                                          */
{
PARCOURS_SEQUENTIEL((y=Ymin ; y<=Ymax ; y=y+PAS_Y)
,(x=Xmin ; x<=Xmax ; x=x+PAS_X)
,(random < SEUIL_CHOIX_ORIENTATION)
,TENTATIVE_HORIZONTALE(x,y)
,TENTATIVE_VERTICALE__(x,y)
);
break;
}
case      LigneLigne_VH:
/* Mode ligne par ligne (VERTICALE__,HORIZONTALE) :                                          */
{
PARCOURS_SEQUENTIEL((y=Ymin ; y<=Ymax ; y=y+PAS_Y)
,(x=Xmin ; x<=Xmax ; x=x+PAS_X)
,(random < SEUIL_CHOIX_ORIENTATION)
,TENTATIVE_VERTICALE__(x,y)
,TENTATIVE_HORIZONTALE(x,y)
);
break;
}
case      ColonneColonne_HV:
/* Mode colonne par colonne (HORIZONTALE,VERTICALE__) :                                      */
{
PARCOURS_SEQUENTIEL((x=Xmin ; x<=Xmax ; x=x+PAS_X)
,(y=Ymin ; y<=Ymax ; y=y+PAS_Y)
,(random < SEUIL_CHOIX_ORIENTATION)
,TENTATIVE_HORIZONTALE(x,y)
,TENTATIVE_VERTICALE__(x,y)
);
break;
}
case      ColonneColonne_VH:
/* Mode colonne par colonne (VERTICALE__,HORIZONTALE) :                                      */
{
PARCOURS_SEQUENTIEL((x=Xmin ; x<=Xmax ; x=x+PAS_X)
,(y=Ymin ; y<=Ymax ; y=y+PAS_Y)
,(random < SEUIL_CHOIX_ORIENTATION)
,TENTATIVE_VERTICALE__(x,y)
,TENTATIVE_HORIZONTALE(x,y)
);
break;
}
case      SpiraleCarree:
/* Mode spirale "carre" :                                                                    */
{
int       x = Xmin+(dimX / 2);
int       y = Ymin+(dimY / 2);

int       SdeltaX = 1;
int       SdeltaY = 0;
int       Slongueur_du_bras = 1;
int       Snombre_de_points = 0;
int       index;

for       (index = 1 ;
index <= ((dimX_reduite * dimY_reduite) + ((dimX_reduite + dimY_reduite) * 2)) ;
index++
)
{
if        ((x >= Xmin) && (x <= Xmax) && (y >= Ymin) && (y <= Ymax))
{
DEFINITION_TUILE_1x2(x
,y
,(random < SEUIL_CHOIX_ORIENTATION)
,TENTATIVE_HORIZONTALE(x,y)
,TENTATIVE_VERTICALE__(x,y)
);
}
else
{
}

if        (Snombre_de_points == 0)
{
Snombre_de_points = Slongueur_du_bras;
}
else
{
}

x +=  SdeltaX*PAS_X;
y +=  SdeltaY*PAS_Y;

Snombre_de_points--;

if        (Snombre_de_points == 0)
{
int       intermediaire;

if        (SdeltaX == 0)
{
Slongueur_du_bras++;
}
else
{
}

intermediaire = SdeltaX ^ SdeltaY;

SdeltaX ^= intermediaire;
SdeltaY ^= intermediaire;
SdeltaX = - SdeltaX;
/* Parcours de la spirale "carre" : ...                                                      */
}
else
{
}
}

Snombre_de_points++;
break;
}
case      Aleatoire:
/* Mode aleatoire :                                                                          */
{
int       index;

for       (index = 1 ; index <= (FACTEUR_ALEATOIRE*(dimX_reduite * dimY_reduite)) ; index++)
{
int       x = Xmin+((((int)(Xmax*drand48()))/PAS_X)*PAS_X);
int       y = Ymin+((((int)(Ymax*drand48()))/PAS_Y)*PAS_Y);

if        ((x >= Xmin) && (x <= Xmax) && (y >= Ymin) && (y <= Ymax))
{
DEFINITION_TUILE_1x2(x
,y
,(random < SEUIL_CHOIX_ORIENTATION)
,TENTATIVE_HORIZONTALE(x,y)
,TENTATIVE_VERTICALE__(x,y)
);
}
else
{
}
}
break;
}
default:
{
fprintf(stderr,"Le mode %d n'est pas reconnu\n",mode);
break;
}
}

write(1,image,dimX*dimY);
/* Sortie de l'image...                                                                      */

if        (editer_les_statistiques == VRAI)
{
fprintf(stderr,"NombreRectanglesH=%d\n",CompteurH);
fprintf(stderr,"NombreRectanglesV=%d\n",CompteurV);
fprintf(stderr,"NombreSitesInaccessibles=%d\n",(dimX_reduite*dimY_reduite)-(2*(CompteurH+CompteurV)));
}
else
{
}
}