/*
Read Sokoban levels from files and export in format usable by Stevedore.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
//#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdint.h>
#include <assert.h>
#define LINUX 1
#define uint8 unsigned char
#ifndef TRUE
#define TRUE (0==0)
#define FALSE (0!=0)
#endif
#define MAX_OBJECTS 16
static int lowindex, highindex; // command-line parameters to select puzzles from larger set.
#define MAX_LINE 1024
static char Id[MAX_LINE];
static int Width, Height;
static int xoffset, yoffset;
static int grabbing = FALSE;
static int blocks;
int map[18][18];
void floodfill_same(int x, int y, int same_ch, int replacement_ch) {
if ((x < 0) || (y < 0) || (x > 17) || (y > 17)) return;
if (map[x][y] == same_ch) map[x][y] = replacement_ch; else return;
floodfill_same(x-1,y, same_ch, replacement_ch);
floodfill_same(x+1,y, same_ch, replacement_ch);
floodfill_same(x,y-1, same_ch, replacement_ch);
floodfill_same(x,y+1, same_ch, replacement_ch);
}
void floodfill_hack(int x, int y) {
if ((x < 0) || (y < 0) || (x > 17) || (y > 17)) return;
if (map[x][y] == ' ') {
map[x][y] |= 0x80;
floodfill_hack(x-1,y);
floodfill_hack(x+1,y);
floodfill_hack(x,y-1);
floodfill_hack(x,y+1);
floodfill_hack(x-1,y-1);
floodfill_hack(x+1,y+1);
floodfill_hack(x+1,y-1);
floodfill_hack(x-1,y+1);
return;
} else if (((x == 0) || (y == 0) || (x == 17) || (y == 17)) && ((map[x][y] == '+') || (map[x][y] == '-') || (map[x][y] == '|'))) { // wall touches boundary
map[x][y] |= 0x80;
return;
} else if (map[x][y] == '+') {
map[x][y] |= 0x80;
return;
} else if (map[x][y] == '-') {
map[x][y] |= 0x80;
return;
} else if (map[x][y] == '|') {
map[x][y] |= 0x80;
return;
}
}
int hack(void) {
int count, x, y;
// completely surround playfield with blocks
for (x = 0, y = 0; x < 18; x++) floodfill_same(x, y, ' ', '#');
for (x = 0, y = 17; x < 18; x++) floodfill_same(x, y, ' ', '#');
for (y = 0, x = 0; y < 18; y++) floodfill_same(x, y, ' ', '#');
for (y = 0, x = 17; y < 18; y++) floodfill_same(x, y, ' ', '#');
// replace all surrounding blocks with 'ignore' codes
for (x = 0, y = 0; x < 18; x++) floodfill_same(x, y, '#', 'X');
for (x = 0, y = 17; x < 18; x++) floodfill_same(x, y, '#', 'X');
for (y = 0, x = 0; y < 18; y++) floodfill_same(x, y, '#', 'X');
for (y = 0, x = 17; y < 18; y++) floodfill_same(x, y, '#', 'X');
// For the innermost layer only of ignore codes surrounding the playfield,
// replace with 'wall' code
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
if (map[x][y] == 'X' && (((x < 17) && (map[x+1][y] != 'X') && (map[x+1][y] != 'Y') ) ||
((x > 0) && (map[x-1][y] != 'X') && (map[x-1][y] != 'Y')) ||
((y < 17) && (map[x][y+1] != 'X') && (map[x][y+1] != 'Y')) ||
((y > 0) && (map[x][y-1] != 'X') && (map[x][y-1] != 'Y'))) ) {
map[x][y] = 'Y';
}
}
}
// convert outside wall from 8-connected to 4-connected topology (ie fill in corners on diagonal wall paths)
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
// XY -> ZY
// Y Y
if ((x < 17) && (y < 17) && (map[x][y] == 'X') && (map[x+1][y] == 'Y') && (map[x][y+1] == 'Y') && (map[x+1][y+1] != 'Y')) map[x][y] = 'Z';
// YX YZ
// Y -> Y
if ((x > 0) && (y < 17) && (map[x][y] == 'X') && (map[x-1][y] == 'Y') && (map[x][y+1] == 'Y') && (map[x-1][y+1] != 'Y')) map[x][y] = 'Z';
// Y Y
// YX -> YZ
if ((x > 0) && (y > 0) && (map[x][y] == 'X') && (map[x-1][y] == 'Y') && (map[x][y-1] == 'Y') && (map[x-1][y-1] != 'Y')) map[x][y] = 'Z';
// Y Y
// XY -> ZY
if ((x < 17) && (y > 0) && (map[x][y] == 'X') && (map[x+1][y] == 'Y') && (map[x][y-1] == 'Y') && (map[x+1][y-1] != 'Y')) map[x][y] = 'Z';
}
}
// remove ignore codes (spaces look nicer) and mark corners
// (generation of vector walls much easier if corners are marked)
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
// and finally...
if (map[x][y] == 'X') map[x][y] = ' ';
if (map[x][y] == 'Z') map[x][y] = '+';
}
}
// fix up some more corners not previously handled
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
// Y+ -> ++
// + +
if ((x < 17) && (y < 17) && (map[x][y] == 'Y') && ((map[x+1][y] == 'Y') || (map[x+1][y] == '+')) && ((map[x][y+1] == 'Y') || (map[x][y+1] == '+'))) map[x][y] = '+';
// +Y ++
// + -> +
if ((x > 0) && (y < 17) && (map[x][y] == 'Y') && ((map[x-1][y] == 'Y') || (map[x-1][y] == '+')) && ((map[x][y+1] == 'Y') || (map[x][y+1] == '+'))) map[x][y] = '+';
// + +
// +Y -> ++
if ((x > 0) && (y > 0) && (map[x][y] == 'Y') && ((map[x-1][y] == 'Y') || (map[x-1][y] == '+')) && ((map[x][y-1] == 'Y') || (map[x][y-1] == '+'))) map[x][y] = '+';
// + +
// Y+ -> ++
if ((x < 17) && (y > 0) && (map[x][y] == 'Y') && ((map[x+1][y] == 'Y') || (map[x+1][y] == '+')) && ((map[x][y-1] == 'Y') || (map[x][y-1] == '+'))) map[x][y] = '+';
}
}
// replace vertical walls with |
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
if ((map[x][y] == 'Y') &&
(((y > 0) && ((map[x][y-1] == 'Y') || (map[x][y-1] == '+'))) ||
((y < 17) && ((map[x][y+1] == 'Y') || (map[x][y+1] == '+'))))
) map[x][y] = '|';
}
}
// and horizontal walls with -
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
if ((map[x][y] == 'Y') &&
(((x > 0) && ((map[x-1][y] == 'Y') || (map[x-1][y] == '+'))) ||
((x < 17) && ((map[x+1][y] == 'Y') || (map[x+1][y] == '+'))))
) map[x][y] = '-';
}
}
// Floodfill again to mark outer walls only
for (x = 0, y = 0; x < 18; x++) floodfill_hack(x,y);
for (x = 0, y = 17; x < 18; x++) floodfill_hack(x,y);
for (y = 0, x = 0; y < 18; y++) floodfill_hack(x,y);
for (y = 0, x = 17; y < 18; y++) floodfill_hack(x,y);
// replace all internal walls (unmarked) with fixed blocks
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
if ((map[x][y] == '+') || (map[x][y] == '-') || (map[x][y] == '|') ) {
map[x][y] = '#';
}
}
}
// And restore outer wall by removing marking
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
map[x][y] &= 0x7F;
}
}
// one last set of patching up to do...
//
// | | |
// + or + => |
// | + |
//
for (y = 0; y < 16; y++) {
for (x = 0; x < 18; x++) {
if (map[x][y] == '|' && map[x][y+1] == '+' &&
(map[x][y+2] == '+' || map[x][y+2] == '|')
) map[x][y+1] = '|';
if (map[x][y] == '+' && map[x][y+1] == '+' &&
(map[x][y+2] == '+' || map[x][y+2] == '|')
) map[x][y+1] = '|';
}
}
// and similarly for horizontal...
for (y = 0; y < 18; y++) {
for (x = 0; x < 16; x++) {
if (map[x][y] == '-' && map[x+1][y] == '+' &&
(map[x+2][y] == '+' || map[x+2][y] == '-')
) map[x+1][y] = '-';
if (map[x][y] == '+' && map[x+1][y] == '+' &&
(map[x+2][y] == '+' || map[x+2][y] == '-')
) map[x+1][y] = '-';
}
}
// WOW. That was quite a hack.
count = 0;
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
// count all blocks but not external wall
if (map[x][y] == '.' || map[x][y] == '$' || map[x][y] == '@' || map[x][y] == '#') count += 1;
}
}
// return count of blocks that need to be drawn explicitly
return count;
}
int wall(int x, int y) {
if ((x < 0) || (y < 0) || (x > 17) || (y > 17)) return FALSE;
return map[x][y] == '+' || map[x][y] == '|' || map[x][y] == '-' || map[x][y] == '#';
}
int eliminated(void) { // eliminate maps that we don't want to handle
int x, y; //, neighbours;
// problematic artefacts
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
if (map[x][y] == 'Y') return TRUE;
}
}
#ifdef NEVER
// outer walls which fork off segments inside the maze. Too much hassle to draw
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
if (map[x][y] == '+') {
neighbours = (wall(x-1,y)?1:0) + (wall(x+1,y)?1:0) + (wall(x,y-1)?1:0) + (wall(x,y+1)?1:0);
if (neighbours > 2) return TRUE;
}
}
}
#endif
// otherwise all good
return FALSE;
}
static int gameno = 0;
void output_title(char *s) {
int chars = 0;
while (*s == ' ') s++;
while (*s != '\0') {
if (isalpha(*s)) {
if (islower(*s)) {
putchar(toupper(*s)); chars++;
} else {
putchar(*s); chars++;
}
s += 1;
} else if (*s == ' ') {
putchar(*s); chars++;
while (*s == ' ') s++;
} else if (isdigit(*s)) {
putchar(*s); chars++;
s += 1;
} else s += 1;
}
while (chars < 4) {
putchar(' '); chars++;
}
}
int handle(char *s) {
static int ypos;
int x,y;
char Line[MAX_LINE];
//fprintf(stderr, "%s",s);
// <Level Id="yConnection" Width="9" Height="10">
// start of a level
if (sscanf(s, " <Level Id=\"%[^\"]\" Width=\"%d\" Height=\"%d\"> ", Id, &Width, &Height) == 3) {
//fprintf(stderr, "LEVEL! %s\n",s);
if ((Width <= 18) && (Height <= 18)) {
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
map[x][y] = ' ';
}
}
xoffset = (18-Width)/2;
ypos = yoffset = (18-Height)/2;
grabbing = TRUE;
}
// end of a level
} else if (grabbing && strstr(s, "</Level>")) {
//fprintf(stderr, "END LEVEL! %s\n",s);
// Erode thick wall layers with flood fill algorithm!
blocks = hack();
grabbing = FALSE;
if ((blocks > 7) && (blocks <= MAX_OBJECTS) && (!(eliminated()))) { // plausible size to be worth looking at
if (gameno >= lowindex) {
fprintf(stdout, "#define title%0d \"", gameno);
output_title(Id);
fprintf(stdout, "\"\n");
fprintf(stdout, "#define game%0d \\\n", gameno);
for (y = 0; y < 18; y++) {
putchar('"');
for (x = 0; x < 18; x++) {
putchar(map[x][y]);
}
putchar('"');
putchar(' ');
if (y!=17) putchar('\\');
putchar('\n');
}
}
return TRUE;
}
// row within a level
} else if (grabbing && (sscanf(s, " <L>%[^<]</L> ", Line) == 1)) {
int xpos;
//fprintf(stderr, "LINE! %s\n",s);
xpos = xoffset;
s = Line;
while (*s != '\0') {
if ((*s == '+') || (*s == '*')) grabbing = FALSE; // not handling these yet.
map[xpos++][ypos] = *s;
s += 1;
}
ypos += 1;
}
return FALSE;
}
#define MAX_VECS 100
int vecs;
int vectors[3*MAX_VECS];
void addvec(int a, int b, int c) {
int base = vecs*3;
int half, third;
if (b >= 14) {
third = b/3;
vectors[base++] = a;
vectors[base++] = third;
vectors[base++] = c;
vecs++;
vectors[base++] = a;
vectors[base++] = third;
vectors[base++] = c;
vecs++;
vectors[base++] = a;
vectors[base++] = b-third*2;
vectors[base++] = c;
} else if (b >= 7) {
half = b/2;
vectors[base++] = a;
vectors[base++] = half;
vectors[base++] = c;
vecs++;
vectors[base++] = a;
vectors[base++] = b-half;
vectors[base++] = c;
} else if (b <= -14) {
third = -b/3;
vectors[base++] = a;
vectors[base++] = -third;
vectors[base++] = c;
vecs++;
vectors[base++] = a;
vectors[base++] = -third;
vectors[base++] = c;
vecs++;
vectors[base++] = a;
vectors[base++] = b+third*2;
vectors[base++] = c;
} else if (b <= -7) {
half = -b/2;
vectors[base++] = a;
vectors[base++] = -half;
vectors[base++] = c;
vecs++;
vectors[base++] = a;
vectors[base++] = b+half;
vectors[base++] = c;
} else if (c >= 14) {
third = c/3;
vectors[base++] = a;
vectors[base++] = b;
vectors[base++] = third;
vecs++;
vectors[base++] = a;
vectors[base++] = b;
vectors[base++] = third;
vecs++;
vectors[base++] = a;
vectors[base++] = b;
vectors[base++] = c-third*2;
} else if (c >= 7) {
half = c/2;
vectors[base++] = a;
vectors[base++] = b;
vectors[base++] = half;
vecs++;
vectors[base++] = a;
vectors[base++] = b;
vectors[base++] = c-half;
} else if (c <= -14) {
third = -c/3;
vectors[base++] = a;
vectors[base++] = b;
vectors[base++] = -third;
vecs++;
vectors[base++] = a;
vectors[base++] = b;
vectors[base++] = -third;
vecs++;
vectors[base++] = a;
vectors[base++] = b;
vectors[base++] = c+third*2;
} else if (c <= -7) {
half = -c/2;
vectors[base++] = a;
vectors[base++] = b;
vectors[base++] = -half;
vecs++;
vectors[base++] = a;
vectors[base++] = b;
vectors[base++] = c+half;
} else {
vectors[base++] = a;
vectors[base++] = b;
vectors[base++] = c;
}
vecs++;
}
int startx, starty;
void dumpvecs(void) {
int i, base;
// may need to insert extra move_abs if too many vectors in perimeter, and wobble occurs...
if (startx-8-2 < -6) {
if (starty-8 < -6) {
fprintf(stdout, "const int wall%0d[%d] = {\n %d,\n", gameno, 1+vecs*3+3+3, vecs+1+1);
fprintf(stdout, " 0,%d*H,%d*W,\n", -4, -4); // check on code 0 - is it abs, or rel with a different scale?
fprintf(stdout, " 0,%d*H,%d*W,\n", starty-8+4, startx-8-2+4);
} else {
fprintf(stdout, "const int wall%0d[%d] = {\n %d,\n", gameno, 1+vecs*3+3+3, vecs+1+1);
fprintf(stdout, " 0,%d*H,%d*W,\n", starty-8, -4);
fprintf(stdout, " 0,0,%d*W,\n", startx-8-2+4);
}
} else {
if (starty-8 < -6) {
fprintf(stdout, "const int wall%0d[%d] = {\n %d,\n", gameno, 1+vecs*3+3+3, vecs+1+1);
fprintf(stdout, " 0,%d*H,%d*W,\n", -4, startx-8-2);
fprintf(stdout, " 0,%d*H,0,\n", starty-8+4);
} else {
fprintf(stdout, "const int wall%0d[%d] = {\n %d,\n", gameno, 1+vecs*3+3, vecs+1);
fprintf(stdout, " 0,%d*H,%d*W,\n", starty-8, startx-8-2);
}
}
for (i = 0; i < vecs; i++) {
base = i*3;
fprintf(stdout, " %d,%d*H,%d*W,\n", vectors[base], vectors[base+1], vectors[base+2]);
}
fprintf(stdout, "};\n\n");
}
void Convert(int x, int y, int lastx, int lasty, int tag) {
// walk around outline of play area, generating vectors suitable for universal drawlist format
if (tag == '!') {startx = x; starty = y; vecs = 0;}
map[x][y] = tag; // avoid accidental backtracking
if (map[x+1][y] == '-') {
assert(lasty == 0);
Convert(x+1,y, lastx+1,0, 'x');
} else if ((map[x+1][y] == '+') || (map[x+1][y] == '!')) {
//fprintf(stdout, " -1, 0, W*%d,\n", lastx+1);
addvec(-1,0,lastx+1);
Convert(x+1,y, 0,0, 'x');
} else if (map[x][y+1] == '|') {
assert(lastx == 0);
Convert(x,y+1, 0,lasty+1, 'x');
} else if ((map[x][y+1] == '+') || (map[x][y+1] == '!')) {
//fprintf(stdout, " -1, H*%d, 0,\n", lasty+1);
addvec(-1,lasty+1,0);
Convert(x,y+1, 0,0, 'x');
} else if (map[x-1][y] == '-') {
assert(lasty == 0);
Convert(x-1,y, lastx-1,0, 'x');
} else if ((map[x-1][y] == '+') || (map[x-1][y] == '!')) {
//fprintf(stdout, " -1, 0, W*%d,\n", lastx-1);
addvec(-1,0,lastx-1);
Convert(x-1,y, 0,0, 'x');
} else if (map[x][y-1] == '|') {
assert(lastx == 0);
Convert(x,y-1, 0,lasty-1, 'x');
} else if ((map[x][y-1] == '+') || (map[x][y-1] == '!')) {
//fprintf(stdout, " -1, H*%d, 0,\n", lasty-1);
addvec(-1,lasty-1,0);
Convert(x,y-1, 0,0, 'x');
}
return; //implicit 'else' is recursion stopper.
}
void gen_sok(FILE *SOK) {
int x, y;
char c;
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
c = map[x][y];
switch (c) {
case 'x':
case '+':
case '-':
case '|':
fputc('#', SOK);
break;
default:
fputc(c, SOK);
break;
}
}
fputc('\r', SOK); // essential for YASS
fputc('\n', SOK);
}
}
void gen_outline(FILE *sokfile) {
int x, y;
#ifdef NEVER
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
if (map[x][y] == '@') {
if (gameno >= lowindex) fprintf(stdout, "\n// Player start pos is y=%d x=%d\n", y, x);
}
}
}
#endif
for (y = 0; y < 18; y++) {
for (x = 0; x < 18; x++) {
if (map[x][y] == '+') {
if (gameno >= lowindex) {
Convert(x,y, 0,0, '!');
dumpvecs();
gen_sok(sokfile);
}
gameno++;
return;
}
}
}
}
int main (int argc, char **argv) {
char *fname, *s, line[MAX_LINE+1];
int i, num_games;
FILE *file, *sokfile;
if (argc == 2) {
lowindex = 0;
highindex = 10000;
} else if (argc == 3) {
if (!isdigit(*argv[2])) {
fprintf(stderr, "%s: low index (%s) must be an integer 0 or higher\n", argv[0], argv[2]);
exit(EXIT_FAILURE);
}
lowindex = atoi(argv[2]);
highindex = lowindex;
} else if (argc == 4) {
if (!isdigit(*argv[2])) {
fprintf(stderr, "%s: low index (%s) must be an integer 0 or higher\n", argv[0], argv[2]);
exit(EXIT_FAILURE);
}
lowindex = atoi(argv[2]);
if (!isdigit(*argv[3])) {
fprintf(stderr, "%s: high index (%s) must be an integer 0 or higher\n", argv[0], argv[3]);
exit(EXIT_FAILURE);
}
highindex = atoi(argv[3]);
} else {
fprintf (stderr, "syntax: %s levels/file.slc [lowindex] [highindex] > output.h\n", argv[0]);
exit(EXIT_FAILURE);
}
fname = argv[1];
sokfile = fopen("temp.sok", "wb");
if (sokfile == NULL) {
fprintf(stderr, "%s: cannot open temp.sok - %s\n", fname, strerror(errno));
exit(EXIT_FAILURE);
}
if (lowindex > highindex) {
fprintf(stderr, "%s: low index (%d) must not be greater than high index (%d).\n", argv[0], lowindex, highindex);
exit(EXIT_FAILURE);
}
file = fopen(fname, "r");
if (file == NULL) {
fprintf(stderr, "%s: cannot open %s - %s\n", argv[0], fname, strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(stdout, "#define COLLECTION \"");
{char *s = fname, *t;
t = strrchr(fname, '/');
if (t) s = t+1;
while (*s != '\0') {
if (*s == '.') break;
if (isalpha(*s)) {
if (isupper(*s)) putchar(*s); else putchar(toupper(*s));
} else if (isdigit(*s)) {
putchar(*s);
} else if (*s == ' ') {
putchar(' ');
} else {
// skip
}
s += 1;
}
}
fprintf(stdout, "\"\n");
for (;;) {
s = fgets(line, MAX_LINE, file); line[MAX_LINE] = '\0';
if (s == NULL) break;
if (handle(line)) {
gen_outline(sokfile);
}
if (gameno > highindex) break;
}
// if bounds not known, would be better to output this at end:
num_games = gameno-lowindex;
fprintf(stdout, "#define NUM_GAMES %d\n", num_games);
fprintf(stdout, "const char const *games[NUM_GAMES] __attribute__ ((section(\".text\"))) = {\n");
for (i = 0; i < num_games; i++) {
fprintf(stdout, " game%0d,\n", i+lowindex);
}
fprintf(stdout, "};\n\n");
fprintf(stdout, "const int const *walls[NUM_GAMES] __attribute__ ((section(\".text\"))) = {\n");
for (i = 0; i < num_games; i++) {
fprintf(stdout, " wall%0d,\n", i+lowindex);
}
fprintf(stdout, "};\n\n");
fprintf(stdout, "const char const *titles[NUM_GAMES] __attribute__ ((section(\".text\"))) = {\n");
for (i = 0; i < num_games; i++) {
fprintf(stdout, " title%0d,\n", i+lowindex);
}
fprintf(stdout, "};\n\n");
// now handle the generation of solutions...
fclose(sokfile);
system("echo | wine yass temp.sok > yass.out 2> yass.err");
remove("temp.sok");
remove("temp, YASS 2.142 Solutions, Statistics.txt");
sokfile = fopen("temp, YASS 2.142 Solutions.sok", "r");
if (sokfile) {
int c;
fprintf(stdout, "const char const *solutions[NUM_GAMES] __attribute__ ((section(\".text\"))) = {\n");
for (i = 0; i < num_games; i++) {
for (;;) {
s = fgets(line, MAX_LINE, sokfile); line[MAX_LINE] = '\0';
if (s == NULL) break;
if (strstr(line, "Solution/Pushes")) break;
}
if (s == NULL) break;
fprintf(stdout, " \"");
for (;;) {
c = fgetc(sokfile);
if (c == '\r') continue;
if (c == ' ') continue;
if (c == '\n') {
c = fgetc(sokfile);
if (c == '\r') c = fgetc(sokfile);
if (c == '\n') break;
if (c == EOF) break;
}
putchar(c);
}
fprintf(stdout, "\",\n");
if (c == EOF) break;
}
fprintf(stdout, "};\n\n");
fclose(sokfile);
if (i == num_games) remove("temp, YASS 2.142 Solutions.sok");
}
exit (EXIT_SUCCESS);
return EXIT_FAILURE;
}