#define LNT2LOTOS_EXPERT_FNT 7.5 #include /*---------------------------------------------------------------------------*/ /* Selectors and constructors for cell lists */ #define EXCEPTION \ ADT_EXCEPTION__EXIT__CONSTRUCTOR (ADT_EXCEPTION__EXIT__NAME__UNEXPECTED ()) #define GET_I(L) GET_I_CELL (EXCEPTION, GET_C_CELL_LIST (EXCEPTION, L)) #define GET_J(L) GET_J_CELL (EXCEPTION, GET_C_CELL_LIST (EXCEPTION, L)) #define GET_NEXT(L) GET_L_CELL_LIST (EXCEPTION, L) #define CELL(I, J) MAKE_CELL (I, J) #define CONS(C, L) CONS_CELL_LIST (C, L) #define NIL NIL_CELL_LIST () /*---------------------------------------------------------------------------*/ /* Matrix type of Boolean values representing the puzzle grid * (free cells are TRUE, occupied cells are FALSE) */ typedef ADT_BOOL MATRIX[7][7]; /*---------------------------------------------------------------------------*/ /* Explore and compute the size of the free grid region around a given cell */ void EXPLORE (MATRIX M, ADT_NAT I, ADT_NAT J, ADT_NAT *SIZE) { CELL_LIST CELL, VISITED; *SIZE = 1; M[I][J] = ADT_FALSE (); VISITED = CONS (CELL (I, J), NIL); /* Explore and count all free cells reachable from the current cell * by horizontal or vertical moves */ while (VISITED != NIL) { I = GET_I (VISITED); J = GET_J (VISITED); CELL = VISITED; VISITED = GET_NEXT (VISITED); (void) free (CELL); if ((I > 0) && M[I - 1][J]) { VISITED = CONS (CELL (I - 1, J), VISITED); M[I - 1][J] = ADT_FALSE (); (*SIZE)++; } if ((I < 6) && M[I + 1][J]) { VISITED = CONS (CELL (I + 1, J), VISITED); M[I + 1][J] = ADT_FALSE (); (*SIZE)++; } if ((J > 0) && M[I][J - 1]) { VISITED = CONS (CELL (I, J - 1), VISITED); M[I][J - 1] = ADT_FALSE (); (*SIZE)++; } if ((J < 6) && M[I][J + 1]) { VISITED = CONS (CELL (I, J + 1), VISITED); M[I][J + 1] = ADT_FALSE (); (*SIZE)++; } } } /*---------------------------------------------------------------------------*/ /* Check if a grid may be valid for the placement of the remaining pieces * (i.e., the size of every free region of the grid is a multiple of 5) */ ADT_BOOL VALID_GRID (CELL_LIST FREE) { MATRIX M; ADT_NAT I, J, SIZE; /* Set all grid matrix cells as occupied */ for (I = 0; I < 7; I++) for (J = 0; J < 7; J++) M[I][J] = ADT_FALSE (); /* Set the list cells as free */ while (FREE != NIL) { M[GET_I (FREE) - 1][GET_J (FREE) - 1] = ADT_TRUE (); FREE = GET_NEXT (FREE); } #ifdef PUZZLE_DEBUG for (I = 0; I < 7; I++) { for (J = 0; J < 7; J++) { (void) fprintf (stdout, "[%d]", M[I][J]); } (void) fprintf (stdout, "\n"); } (void) fprintf (stdout, "\n"); #endif /* Explore the free regions of the grid and check their consistency */ for (I = 0; I < 7; I++) { for (J = 0; J < 7; J++) { if (M[I][J]) { /* The current cell is free: explore the grid region * of free cells reachable from it */ EXPLORE (M, I, J, &SIZE); if ((SIZE % 5) != 0) { /* The size of the current free region is not a * multiple of 5, so it cannot be covered with the * remaining puzzle pieces: the grid is invalid */ return ADT_FALSE (); } } } } /* All free regions of the grid have a size multiple of 5: * the grid may be valid */ return ADT_TRUE (); } /*---------------------------------------------------------------------------*/ /* Get the current month and day */ ADT_NAT GET_CURRENT_MONTH () { time_t TIME; struct tm CRT_TIME; TIME = time (NULL); CRT_TIME = *localtime (&TIME); return CRT_TIME.tm_mon + 1; } ADT_NAT GET_CURRENT_DAY () { time_t TIME; struct tm CRT_TIME; TIME = time (NULL); CRT_TIME = *localtime (&TIME); return CRT_TIME.tm_mday; } /*---------------------------------------------------------------------------*/