#include #include #include #include #include #include #include #include #include #include /***********************************************************/ /* PROTOTYPES */ /***********************************************************/ void TEXT_9_X_15(GLint xs, GLint ys, char text[]); void TEXT_8_X_13(GLint xs, GLint ys, char text[]); void TEXT_COPYRIGHT(void); void TEXT_MOVE_COUNT(void); void TEXT_DIFFICULTY(void); void BUTTON_DRAW(GLint xs, GLint ys); void BUTTON_CLICK(GLint xs, GLint ys); void WINDOW_DRAW(GLint xs, GLint ys, GLint xe, GLint ye); void WINDOW_CLEAR(GLint xs, GLint ys, GLint xe, GLint ye); int SCAN_FOR_IMAGES(char Extension[4]); void SCAN_WINDOW(void); void SCAN_FILE_DISPLAY(int start, int puzzles); void pgmCommentClear(FILE *disk); int NEW_LOAD(char FileName[80]); void NEW_DRAW(void); void NEW_HELPVIEW_RECORD(void); void NEW_CUTUP_IMAGE(void); void NEW_RANDOMIZE_IMAGE(void); void PUZZLE_SAVE(char FileName[80]); void PUZZLE_LOAD(void); void REDRAW_BLANK_PIECE(GLint x, GLint y); void PLAY_WINNER(void); void PLAY_ISWINNER(int x, int y); void PLAY(int x, int y); void HELP_UNDO(void); void HELP_VIEW(void); void HELP_NUMBER(void); void RESIZE_COPY(void); void RESIZE_RESTORE(void); /***********************************************************/ /* GLOBAL VARIABLES */ /***********************************************************/ #define version "6.1" struct RGB { unsigned char r, g, b; }; GLint window; GLint winHeight = 480; int drawFlag = 1; int scanFlag = 0; int scanStart = 0; int puzzles = 0; int loadFlag = 0; int playFlag = 0; int winFlag = 0; int difficulty = 1; int movesMade = 0; int movesToSolve = 0; int PuzzleMoves[6][500]; int PuzzleBoard[5][5]; char PuzzleName[80]; char PuzzleNames[100][80]; RGB PuzzleView[74][90]; RGB PuzzleData[425][520]; /***********************************************************/ /* TEXT ROUTINES */ /***********************************************************/ /****************************************/ /* Draws 9x15 text on screen. */ /****************************************/ void TEXT_9_X_15(GLint xs, GLint ys, char text[]) { int i; char letter; glDrawBuffer(GL_FRONT_AND_BACK); glColor3f(1.0, 1.0, 1.0); glPixelTransferi(GL_MAP_COLOR, true); glRasterPos2i(xs, ys); for (i = 0; i < strlen(text); i++) { letter = text[i]; glutBitmapCharacter(GLUT_BITMAP_9_BY_15, GLint(letter)); } } /****************************************/ /* Draws 8x13 text on screen. */ /****************************************/ void TEXT_8_X_13(GLint xs, GLint ys, char text[]) { int i; char letter; glDrawBuffer(GL_FRONT_AND_BACK); glColor3f(1.0, 1.0, 1.0); glPixelTransferi(GL_MAP_COLOR, true); glRasterPos2i(xs, ys); for (i = 0; i < strlen(text); i++) { letter = text[i]; glutBitmapCharacter(GLUT_BITMAP_8_BY_13, GLint(letter)); } } /****************************************/ /* Draws copyright data on screen. */ /****************************************/ void TEXT_COPYRIGHT(void) { char text[80]; strcpy(text, "PUZZ-R.A.M. ("); strcat(text, version); strcat(text, ")"); TEXT_9_X_15(250, 240, text); TEXT_9_X_15(250, 220, "Copyright (C), Ronald Marsh, 2001."); TEXT_9_X_15(250, 200, "All rights reserved."); } /****************************************/ /* Draws # of puzzle moves on screen. */ /****************************************/ void TEXT_MOVE_COUNT(void) { char text[20]; char move[10]; sprintf(move, "%d", movesMade); strcpy(text, "Moves:"); strcat(text, move); WINDOW_CLEAR( 7, 450, 107, 470); TEXT_8_X_13( 15, 455, text); } /****************************************/ /* Draws difficulty level on screen. */ /****************************************/ void TEXT_DIFFICULTY(void) { char text[20]; char level[10]; sprintf(level, "%d", difficulty); strcpy(text, "Level:"); strcat(text, level); WINDOW_CLEAR(533, 450, 633, 470); TEXT_8_X_13(541, 455, text); } /***********************************************************/ /* WINDOW ROUTINES */ /***********************************************************/ /****************************************/ /* Draws sub-windows on screen. */ /****************************************/ void WINDOW_DRAW(GLint xs, GLint ys, GLint xe, GLint ye) { glDrawBuffer(GL_BACK); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glColor3f(0.4, 0.4, 0.4); glBegin(GL_QUADS); // Window top border. glVertex2i(xs, ye); glVertex2i(xe, ye); glVertex2i(xe-2, ye-2); glVertex2i(xs+2, ye-2); // Window left border. glVertex2i(xs, ye); glVertex2i(xs+2, ye-2); glVertex2i(xs+2, ys+2); glVertex2i(xs, ys); glEnd(); glColor3f(0.8, 0.8, 0.8); glBegin(GL_QUADS); // Window bottom border. glVertex2i(xs+2, ys+2); glVertex2i(xs, ys); glVertex2i(xe, ys); glVertex2i(xe-2, ys+2); // Window right border. glVertex2i(xe-2, ye-2); glVertex2i(xe, ye); glVertex2i(xe, ys); glVertex2i(xe-2, ys+2); glEnd(); glutSwapBuffers(); } /****************************************/ /* Clears sub-windows. */ /****************************************/ void WINDOW_CLEAR(GLint xs, GLint ys, GLint xe, GLint ye) { glDrawBuffer(GL_BACK); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glColor3f(0.0, 0.0, 0.0); glBegin(GL_QUADS); glVertex2i(xs+3, ye-3); glVertex2i(xe-3, ye-3); glVertex2i(xe-3, ys+3); glVertex2i(xs+3, ys+3); glEnd(); glutSwapBuffers(); } /****************************************/ /* PGM file scan sub-window display. */ /****************************************/ void SCAN_WINDOW(void) { glDrawBuffer(GL_BACK); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glColor3f(0.8, 0.8, 0.8); glBegin(GL_QUADS); // Window top border. glVertex2i(225, 420); glVertex2i(525, 420); glVertex2i(523, 418); glVertex2i(227, 418); // Window left border. glVertex2i(225, 420); glVertex2i(227, 418); glVertex2i(227, 24); glVertex2i(225, 20); glEnd(); glColor3f(0.4, 0.4, 0.4); glBegin(GL_QUADS); // Window bottom border. glVertex2i(227, 22); glVertex2i(225, 20); glVertex2i(525, 20); glVertex2i(523, 22); // Window right border. glVertex2i(523, 418); glVertex2i(525, 420); glVertex2i(525, 20); glVertex2i(523, 22); glEnd(); glColor3f(0.6, 0.6, 0.6); glBegin(GL_QUADS); glVertex2i(227, 418); glVertex2i(523, 418); glVertex2i(523, 22); glVertex2i(227, 22); glEnd(); glutSwapBuffers(); WINDOW_DRAW( 235, 30, 410, 410); WINDOW_CLEAR(235, 30, 410, 410); // Draw buttons. BUTTON_DRAW( 420, 385); BUTTON_DRAW( 420, 360); BUTTON_DRAW( 420, 310); // Label buttons. TEXT_8_X_13( 435, 390, " UP "); TEXT_8_X_13( 435, 365, " DOWN "); TEXT_8_X_13( 435, 315, " CANCEL"); } /****************************************/ /* Main window display. */ /****************************************/ void MAIN_WINDOW(void) { glDrawBuffer(GL_BACK); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glColor3f(0.6, 0.6, 0.6); glBegin(GL_QUADS); glVertex2i( 0, 0); glVertex2i(640, 0); glVertex2i(640, 6); glVertex2i( 0, 6); glEnd(); glBegin(GL_QUADS); glVertex2i( 0, 0); glVertex2i(112, 0); glVertex2i(112, 480); glVertex2i( 0, 480); glEnd(); glBegin(GL_QUADS); glVertex2i(112, 438); glVertex2i(640, 438); glVertex2i(640, 480); glVertex2i(112, 480); glEnd(); glBegin(GL_QUADS); glVertex2i(639, 438); glVertex2i(640, 438); glVertex2i(640, 6); glVertex2i(639, 6); glEnd(); // Draw etched lines. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glColor3f(0.8, 0.8, 0.8); glBegin(GL_LINES); glVertex2i( 0, 440); glVertex2i(649, 440); glVertex2i( 0, 5); glVertex2i(649, 5); glVertex2i( 0, 200); glVertex2i(110, 200); glVertex2i(110, 440); glVertex2i(110, 5); glEnd(); glColor3f(0.0, 0.0, 0.0); glBegin(GL_LINES); glVertex2i( 0, 441); glVertex2i(649, 441); glVertex2i( 0, 6); glVertex2i(649, 6); glVertex2i( 0, 201); glVertex2i(110, 201); glVertex2i(109, 440); glVertex2i(109, 6); glEnd(); glutSwapBuffers(); // Draw windows. WINDOW_DRAW( 7, 450, 107, 470); //Moves window WINDOW_CLEAR( 7, 450, 107, 470); WINDOW_DRAW( 533, 450, 633, 470); //Level window WINDOW_CLEAR(533, 450, 633, 470); WINDOW_DRAW( 7, 14, 103, 95); //Help window WINDOW_CLEAR( 7, 14, 103, 95); WINDOW_DRAW( 112, 6, 639, 438); //Main window WINDOW_CLEAR(112, 6, 639, 438); // Misc. Text. TEXT_COPYRIGHT(); TEXT_MOVE_COUNT(); TEXT_DIFFICULTY(); // Draw buttons. BUTTON_DRAW( 10, 385); BUTTON_DRAW( 10, 360); BUTTON_DRAW( 10, 335); BUTTON_DRAW( 10, 310); BUTTON_DRAW( 10, 285); BUTTON_DRAW( 10, 260); BUTTON_DRAW( 10, 220); BUTTON_DRAW( 10, 150); BUTTON_DRAW( 10, 125); BUTTON_DRAW( 10, 100); // Label buttons. TEXT_8_X_13( 14, 420, "Game Menu"); TEXT_8_X_13( 18, 390, " NEW "); TEXT_8_X_13( 23, 365, " LEVEL +"); TEXT_8_X_13( 23, 340, " LEVEL -"); TEXT_8_X_13( 23, 315, " PLAY "); TEXT_8_X_13( 23, 290, " LOAD "); TEXT_8_X_13( 23, 265, " SAVE "); TEXT_8_X_13( 23, 225, " EXIT "); TEXT_8_X_13( 14, 180, "Help Menu"); TEXT_8_X_13( 23, 155, " UNDO "); TEXT_8_X_13( 23, 130, " NUMBER "); TEXT_8_X_13( 23, 105, " VIEW "); } /***********************************************************/ /* BUTTON ROUTINES */ /***********************************************************/ /****************************************/ /* Draws buttons on screen. */ /****************************************/ void BUTTON_DRAW(GLint xs, GLint ys) { GLint xe = (xs + 90); GLint ye = (ys + 20); glDrawBuffer(GL_BACK); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glColor3f(0.0, 0.0, 0.0); glBegin(GL_QUADS); // Button hole. glVertex2i(xs-1, ye+1); glVertex2i(xe+2, ye+1); glVertex2i(xe+2, ys-2); glVertex2i(xs-1, ys-2); glEnd(); glColor3f(0.6, 0.6, 0.6); glBegin(GL_QUADS); // Button. glVertex2i(xs, ye); glVertex2i(xe, ye); glVertex2i(xe, ys); glVertex2i(xs, ys); glEnd(); glColor3f(0.8, 0.8, 0.8); glBegin(GL_QUADS); // Button top border. glVertex2i(xs, ye); glVertex2i(xe, ye); glVertex2i(xe-2, ye-2); glVertex2i(xs+2, ye-2); // Button left border. glVertex2i(xs, ye); glVertex2i(xs+2, ye-2); glVertex2i(xs+2, ys+2); glVertex2i(xs, ys); glEnd(); glColor3f(0.4, 0.4, 0.4); glBegin(GL_QUADS); // Button bottom border. glVertex2i(xs+2, ys+2); glVertex2i(xs, ys); glVertex2i(xe, ys); glVertex2i(xe-2, ys+2); // Button right border. glVertex2i(xe-2, ye-2); glVertex2i(xe, ye); glVertex2i(xe, ys); glVertex2i(xe-2, ys+2); glEnd(); glutSwapBuffers(); } /****************************************/ /* Animates button clicks. */ /****************************************/ void BUTTON_CLICK(GLint xs, GLint ys) { RGB Button[2200]; glDrawBuffer(GL_FRONT); glPixelTransferi(GL_MAP_COLOR, false); glReadPixels(xs-1, ys-1, 92, 22, GL_RGB, GL_UNSIGNED_BYTE, Button); glRasterPos2i(xs, ys-2); glDrawPixels(92, 22, GL_RGB, GL_UNSIGNED_BYTE, Button); system("usleep 5000"); glRasterPos2i(xs-1, ys-1); glDrawPixels(92, 22, GL_RGB, GL_UNSIGNED_BYTE, Button); } /***********************************************************/ /* DISK SCAN ROUTINES */ /***********************************************************/ /****************************************/ /* PGM file scan. */ /****************************************/ int SCAN_FOR_IMAGES(char Extension[4]) { int i; char sysCmd[80]; FILE *disk; // Scan disk for files. strcpy(sysCmd, "ls *"); strcat(sysCmd, Extension); strcat(sysCmd, " > puzzleList"); system(sysCmd); if ((disk = fopen("puzzleList", "r")) != NULL) { for (i = 0; ; i++) { fscanf(disk, "%s", PuzzleNames[i]); if (feof(disk)) break; } } fclose(disk); system("rm puzzleList"); if (i == 0) return 0; else return --i; } /****************************************/ /* PGM file scan display. */ /****************************************/ void SCAN_FILE_DISPLAY(int start, int puzzles) { int i, j = start; WINDOW_CLEAR(235, 30, 410, 410); for (i = 0; i < 350; i+=20) { TEXT_8_X_13( 245, (385-i), PuzzleNames[j]); if (j == puzzles) break; j++; } } /***********************************************************/ /* NEW PUZZLE ROUTINES */ /***********************************************************/ /****************************************/ /* PGM file comment clear. */ /****************************************/ void pgmCommentClear(FILE *disk) { int errorSet; // These are required, but I don't understand why. int errorGet; // These are required, but I don't understand why. unsigned char ch; fpos_t *pos; fread(&ch, 1, 1, disk); errorGet = fgetpos(disk, pos); fread(&ch, 1, 1, disk); if (ch == '#') { while (ch == '#') { while (ch != '\n') fread(&ch, 1, 1, disk); errorGet = fgetpos(disk, pos); fread(&ch, 1, 1, disk); } errorSet = fsetpos(disk, pos); } else { errorSet = fsetpos(disk, pos); } } /****************************************/ /* PGM file load (new puzzle image). */ /****************************************/ int NEW_LOAD(char FileName[80]) { int x, y; int xmax, ymax, pmax; char ch; char type[3]; char command[256]; FILE *disk; // Scale file. // strcpy(command, "./convert -scale 520x425! "); // strcat(command, FileName); // strcat(command, " temp.jpg"); // system(command); // Convert JPG file to PPM format. // system("./convert temp.jpg temp.ppm"); // Open temporary file. if ((disk = fopen(FileName, "rb")) == NULL) { TEXT_9_X_15(250, 220, "ERROR:"); TEXT_9_X_15(250, 200, "- The file can not be opened."); return 1; } // Read in file header. fscanf(disk, "%s", &type); pgmCommentClear(disk); fscanf(disk, "%d", &xmax); fscanf(disk, "%d", &ymax); fscanf(disk, "%d", &pmax); fread(&ch, 1, 1, disk); // Check file size. if (xmax != 520 || ymax != 425) { TEXT_9_X_15(250, 220, "ERROR:"); TEXT_9_X_15(250, 200, "- The file did not convert correctly."); fclose(disk); return 1; } // Load B/W image data. if (strcmp(type, "P5") == 0) { for (y = 0; y < ymax; y++) { for (x = 0; x < xmax; x++) { PuzzleData[y][x].r = getc(disk); PuzzleData[y][x].g = PuzzleData[y][x].r; PuzzleData[y][x].b = PuzzleData[y][x].r; } } fclose(disk); // Load color image. } else if (strcmp(type, "P6") == 0) { for (y = 0; y < ymax; y++) { for (x = 0; x < xmax; x++) { PuzzleData[y][x].r = getc(disk); PuzzleData[y][x].g = getc(disk); PuzzleData[y][x].b = getc(disk); } } fclose(disk); } // Remove temporary files. // system("rm temp.ppm"); // system("rm temp.jpg"); return 0; } /****************************************/ /* Draw puzzle image. */ /****************************************/ void NEW_DRAW(void) { GLint xp, yp; glDrawBuffer(GL_BACK); glPointSize(2); glBegin(GL_POINTS); yp = 433; for (int y = 0; y < 424; y++) { xp = 115; for (int x = 0; x < 519; x++) { glColor3ub(PuzzleData[y][x].r, PuzzleData[y][x].g, PuzzleData[y][x].b); glVertex2i(xp, yp); xp++; } yp--; } glEnd(); glPointSize(1); glutSwapBuffers(); } /****************************************/ /* Record puzzle help view */ /****************************************/ void NEW_HELPVIEW_RECORD(void) { RGB PuzzleTemp[520][425]; glPixelTransferi(GL_MAP_COLOR, false); glReadPixels(115, 10, 520, 425, GL_RGB, GL_UNSIGNED_BYTE, PuzzleTemp); gluScaleImage(GL_RGB, 520, 425, GL_UNSIGNED_BYTE, PuzzleTemp, 90, 74, GL_UNSIGNED_BYTE, PuzzleView); } /****************************************/ /* Cut puzzle into pieces. */ /****************************************/ void NEW_CUTUP_IMAGE(void) { int x, y; int piece = 0; GLint xs, xe, ys, ye; glDrawBuffer(GL_BACK); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); for (y = 0; y < 5; y++) { ys = (10 + (y * 85)); ye = (ys + 85); for (x = 0; x < 5; x++) { xs = (115 + (x * 104)); xe = (xs + 104); glColor3f(0.8, 0.8, 0.8); glBegin(GL_QUADS); // Piece top border. glVertex2i(xs, ye); glVertex2i(xe, ye); glVertex2i(xe-2, ye-2); glVertex2i(xs+2, ye-2); // Piece left border. glVertex2i(xs, ye); glVertex2i(xs+2, ye-2); glVertex2i(xs+2, ys+2); glVertex2i(xs, ys); glEnd(); glColor3f(0.4, 0.4, 0.4); glBegin(GL_QUADS); // Piece bottom border. glVertex2i(xs+2, ys+2); glVertex2i(xs, ys); glVertex2i(xe, ys); glVertex2i(xe-2, ys+2); // Piece right border. glVertex2i(xe-2, ye-2); glVertex2i(xe, ye); glVertex2i(xe, ys); glVertex2i(xe-2, ys+2); glEnd(); // Record puzzle piece locations. PuzzleBoard[y][x] = piece++; } } // Remove bottom-left corner piece. glColor3f(0.0, 0.0, 0.0); glBegin(GL_QUADS); glVertex2i(531, 10); glVertex2i(635, 10); glVertex2i(635, 95); glVertex2i(531, 95); glEnd(); PuzzleBoard[4][4] = -1; glutSwapBuffers(); } /****************************************/ /* Randomize pieces. */ /****************************************/ void NEW_RANDOMIZE_IMAGE(void) { int i; int x1, x2, y1, y2; int temp; GLint xs1, ys1, xs2, ys2; RGB *pieceA, *pieceB; pieceA = new RGB[9000]; pieceB = new RGB[9000]; srand((int)(time(NULL)%42)); glDrawBuffer(GL_FRONT_AND_BACK); glPixelTransferi(GL_MAP_COLOR, false); for (i = 0; i < (difficulty*4); i++) { x1 = (int)(5.0 * rand() / (RAND_MAX + 1.0)); y1 = (int)(5.0 * rand() / (RAND_MAX + 1.0)); ys1 = (10 + (y1 * 85)); xs1 = (115 + (x1 * 104)); glReadPixels(xs1, ys1, 104, 85, GL_RGB, GL_UNSIGNED_BYTE, pieceA); x2 = (int)(5.0 * rand() / (RAND_MAX + 1.0)); y2 = (int)(5.0 * rand() / (RAND_MAX + 1.0)); ys2 = (10 + (y2 * 85)); xs2 = (115 + (x2 * 104)); glReadPixels(xs2, ys2, 104, 85, GL_RGB, GL_UNSIGNED_BYTE, pieceB); glRasterPos2i(xs2, ys2); glDrawPixels(104, 85, GL_RGB, GL_UNSIGNED_BYTE, pieceA); glRasterPos2i(xs1, ys1); glDrawPixels(104, 85, GL_RGB, GL_UNSIGNED_BYTE, pieceB); // Record new piece locations. y1 = (4 - y1); y2 = (4 - y2); temp = PuzzleBoard[y1][x1]; PuzzleBoard[y1][x1] = PuzzleBoard[y2][x2]; PuzzleBoard[y2][x2] = temp; } delete[] pieceA; delete[] pieceB; } /***********************************************************/ /* PUZZLE IO ROUTINES */ /***********************************************************/ /****************************************/ /* Save puzzle to disk. */ /****************************************/ void PUZZLE_SAVE(char FileName[80]) { int x, y; char FName[80]; GLint xs = 115; GLint ye = 434; RGB *pieces; FILE *disk; // Save filename. strcpy(FName, FileName); strcat(FName, ".puz"); disk = fopen(".recoverData", "w"); fprintf(disk, "%s\n", FName); fclose(disk); // Write undo data. disk = fopen(FName, "wb"); fprintf(disk, "%d\n", movesMade); fprintf(disk, "%d\n", movesToSolve); for (y = 0; y < 6; y++) { for (x = 0; x < movesToSolve; x++) { fprintf(disk, "%d\n", PuzzleMoves[y][x]); } } // Write game board data. fprintf(disk, "%d\n", difficulty); for (y = 0; y < 5; y++) { for (x = 0; x < 5; x++) { fprintf(disk, "%d\n", PuzzleBoard[y][x]); } } // Write game image. pieces = new RGB[1600]; glPixelTransferi(GL_MAP_COLOR, false); for (y = 0; y < 425; y++) { glReadPixels(xs, ye, 520, 1, GL_RGB, GL_UNSIGNED_BYTE, pieces); ye--; for (x = 0; x < 520; x++) { fprintf(disk, "%c%c%c", pieces[x].r, pieces[x].g, pieces[x].b); } } delete[] pieces; // Write game help image. for (y = 0; y < 74; y++) { for (x = 0; x < 90; x++) { fprintf(disk, "%c%c%c", PuzzleView[y][x].r, PuzzleView[y][x].g, PuzzleView[y][x].b); } } fclose(disk); } /****************************************/ /* Load puzzle from disk. */ /****************************************/ void PUZZLE_LOAD(void) { int x, y; char FName[80]; GLint xs = 115; GLint ye = 434; RGB *pieces; FILE *disk; // Recover saved filename. if ((disk = fopen(".recoverData", "r")) == NULL) return; fscanf(disk, "%s", FName); fclose(disk); // Read undo data. if ((disk = fopen(FName, "rb")) == NULL) return; fscanf(disk, "%d", &movesMade); fscanf(disk, "%d", &movesToSolve); for (y = 0; y < 6; y++) { for (x = 0; x < movesToSolve; x++) { fscanf(disk, "%d", &PuzzleMoves[y][x]); } } // Read game board data. fscanf(disk, "%d", &difficulty); for (y = 0; y < 5; y++) { for (x = 0; x < 5; x++) { fscanf(disk, "%d\n", &PuzzleBoard[y][x]); } } // Read game image. pieces = new RGB[1600]; glDrawBuffer(GL_BACK); glPixelTransferi(GL_MAP_COLOR, false); for (y = 0; y < 425; y++) { for (x = 0; x < 520; x++) { fscanf(disk, "%c%c%c", &pieces[x].r, &pieces[x].g, &pieces[x].b); } glRasterPos2i(xs, ye); glDrawPixels(520, 1, GL_RGB, GL_UNSIGNED_BYTE, pieces); ye--; } glutSwapBuffers(); delete[] pieces; // Read game help image. for (y = 0; y < 74; y++) { for (x = 0; x < 90; x++) { fscanf(disk, "%c%c%c", &PuzzleView[y][x].r, &PuzzleView[y][x].g, &PuzzleView[y][x].b); } } fclose(disk); } /***********************************************************/ /* PLAY PUZZLE ROUTINES */ /***********************************************************/ /****************************************/ /* Redraw blank piece. */ /****************************************/ void REDRAW_BLANK_PIECE(GLint x, GLint y) { glDrawBuffer(GL_BACK); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glColor3f(0.0, 0.0, 0.0); glBegin(GL_QUADS); glVertex2i(x, y); glVertex2i(x+104, y); glVertex2i(x+104, y+85); glVertex2i(x, y+85); glEnd(); glutSwapBuffers(); } /****************************************/ /* A winner. */ /****************************************/ void PLAY_WINNER(void) { if (winFlag == 0) return; WINDOW_CLEAR( 7, 14, 103, 95); system("usleep 500000"); TEXT_8_X_13( 18, 70, "You "); system("usleep 500000"); TEXT_8_X_13( 50, 70, "are "); system("usleep 500000"); TEXT_8_X_13( 82, 70, "a"); system("usleep 500000"); TEXT_9_X_15( 26, 40, "WINNER!"); system("usleep 500000"); system("usleep 500000"); } /****************************************/ /* Is it a winner? */ /****************************************/ void PLAY_ISWINNER(int x, int y) { int winner; winner = 1; for (y = 0; y < 5; y++) if (PuzzleBoard[y][0] != (0 + (y * 5))) winner = 0; for (y = 0; y < 5; y++) if (PuzzleBoard[y][1] != (1 + (y * 5))) winner = 0; for (y = 0; y < 5; y++) if (PuzzleBoard[y][2] != (2 + (y * 5))) winner = 0; for (y = 0; y < 5; y++) if (PuzzleBoard[y][3] != (3 + (y * 5))) winner = 0; for (y = 0; y < 4; y++) if (PuzzleBoard[y][4] != (4 + (y * 5))) winner = 0; if (winner == 1) { winFlag = 1; PLAY_WINNER(); } } /****************************************/ /* Play puzzle. */ /****************************************/ /****************************************/ void PLAY(int x, int y) { int i, j; int x1, x2, y1, y2; int moveX = 0; int moveY = 0; int temp; GLint xp = 115; GLint yp = 10; GLint xP, yP, xB, yB; RGB *piece = new RGB[9000]; glDrawBuffer(GL_FRONT_AND_BACK); // Determine piece picked. x = ((x - 116) / 104); y = ((y - 10) / 85); x1 = x; y1 = (4 - y); // Determine if piece can move right. j = 0; for (i = x; i < 5; i++) { if (PuzzleBoard[y1][i] == -1) moveX = j; j++; } // Move piece(s). while (moveX != 0) { yP = (yp + (y * 85)); xP = (xp + ((x + moveX) * 104)); yB = yP; xB = (xP - 104); moveX--; glPixelTransferi(GL_MAP_COLOR, false); glReadPixels(xB, yB, 104, 85, GL_RGB, GL_UNSIGNED_BYTE, piece); glRasterPos2i(xP, yP); glDrawPixels(104, 85, GL_RGB, GL_UNSIGNED_BYTE, piece); REDRAW_BLANK_PIECE(xB, yB); // Record new piece locations. x1 = (x + moveX + 1); x2 = (x + moveX); y1 = (4 - y); y2 = (4 - y); temp = PuzzleBoard[y1][x1]; PuzzleBoard[y1][x1] = PuzzleBoard[y2][x2]; PuzzleBoard[y2][x2] = temp; // Record moves. PuzzleMoves[0][movesToSolve] = y; PuzzleMoves[1][movesToSolve] = x1; PuzzleMoves[2][movesToSolve] = PuzzleBoard[y1][x1]; PuzzleMoves[3][movesToSolve] = y; PuzzleMoves[4][movesToSolve] = x2; PuzzleMoves[5][movesToSolve] = PuzzleBoard[y2][x2]; // Update moves counters. movesToSolve++; movesMade++; TEXT_MOVE_COUNT(); // Do we have a winner? PLAY_ISWINNER(x, y); } // Determine if piece can move left. j = 0; for (i = x; i >= 0; i--) { if (PuzzleBoard[y1][i] == -1) moveX = j; j--; } // Move piece(s). while (moveX != 0) { yP = (yp + (y * 85)); xP = (xp + ((x + moveX) * 104)); yB = yP; xB = (xP + 104); moveX++; glPixelTransferi(GL_MAP_COLOR, false); glReadPixels(xB, yB, 104, 85, GL_RGB, GL_UNSIGNED_BYTE, piece); glRasterPos2i(xP, yP); glDrawPixels(104, 85, GL_RGB, GL_UNSIGNED_BYTE, piece); REDRAW_BLANK_PIECE(xB, yB); // Record new piece locations. x1 = (x + moveX - 1); x2 = (x + moveX); y1 = (4 - y); y2 = (4 - y); temp = PuzzleBoard[y1][x1]; PuzzleBoard[y1][x1] = PuzzleBoard[y2][x2]; PuzzleBoard[y2][x2] = temp; // Record moves. PuzzleMoves[0][movesToSolve] = y; PuzzleMoves[1][movesToSolve] = x1; PuzzleMoves[2][movesToSolve] = PuzzleBoard[y1][x1]; PuzzleMoves[3][movesToSolve] = y; PuzzleMoves[4][movesToSolve] = x2; PuzzleMoves[5][movesToSolve] = PuzzleBoard[y2][x2]; // Update moves counters. movesToSolve++; movesMade++; TEXT_MOVE_COUNT(); // Do we have a winner? PLAY_ISWINNER(x, y); } // Determine if piece can move down. j = 0; for (i = (4-y); i < 5; i++) { if (PuzzleBoard[i][x1] == -1) moveY = j; j--; } // Move piece(s). while (moveY != 0) { yP = (yp + ((y + moveY) * 85)); xP = (xp + (x * 104)); yB = (yP + 85); xB = xP; moveY++; glPixelTransferi(GL_MAP_COLOR, false); glReadPixels(xB, yB, 104, 85, GL_RGB, GL_UNSIGNED_BYTE, piece); glRasterPos2i(xP, yP); glDrawPixels(104, 85, GL_RGB, GL_UNSIGNED_BYTE, piece); REDRAW_BLANK_PIECE(xB, yB); // Record new piece locations. x1 = x; x2 = x; y1 = (4 - y) - (moveY - 1); y2 = (4 - y) - moveY; temp = PuzzleBoard[y1][x1]; PuzzleBoard[y1][x1] = PuzzleBoard[y2][x2]; PuzzleBoard[y2][x2] = temp; // Record moves. PuzzleMoves[0][movesToSolve] = 4 - y1; PuzzleMoves[1][movesToSolve] = x; PuzzleMoves[2][movesToSolve] = PuzzleBoard[y1][x1]; PuzzleMoves[3][movesToSolve] = 4 - y2; PuzzleMoves[4][movesToSolve] = x; PuzzleMoves[5][movesToSolve] = PuzzleBoard[y2][x2]; // Update moves counters. movesToSolve++; movesMade++; TEXT_MOVE_COUNT(); // Do we have a winner? PLAY_ISWINNER(x, y); } // Determine if piece can move up. j = 0; for (i = (4-y); i >= 0; i--) { if (PuzzleBoard[i][x1] == -1) moveY = j; j++; } // Move piece(s). while (moveY != 0) { yP = (yp + ((y + moveY) * 85)); xP = (xp + (x * 104)); yB = (yP - 85); xB = xP; moveY--; glPixelTransferi(GL_MAP_COLOR, false); glReadPixels(xB, yB, 104, 85, GL_RGB, GL_UNSIGNED_BYTE, piece); glRasterPos2i(xP, yP); glDrawPixels(104, 85, GL_RGB, GL_UNSIGNED_BYTE, piece); REDRAW_BLANK_PIECE(xB, yB); // Record new piece locations. x1 = x; x2 = x; y1 = (4 - y) - (moveY + 1); y2 = (4 - y) - moveY; temp = PuzzleBoard[y1][x1]; PuzzleBoard[y1][x1] = PuzzleBoard[y2][x2]; PuzzleBoard[y2][x2] = temp; // Record moves. PuzzleMoves[0][movesToSolve] = 4 - y1; PuzzleMoves[1][movesToSolve] = x; PuzzleMoves[2][movesToSolve] = PuzzleBoard[y1][x1]; PuzzleMoves[3][movesToSolve] = 4 - y2; PuzzleMoves[4][movesToSolve] = x; PuzzleMoves[5][movesToSolve] = PuzzleBoard[y2][x2]; // Update moves counters. movesToSolve++; movesMade++; TEXT_MOVE_COUNT(); // Do we have a winner? PLAY_ISWINNER(x, y); } delete[] piece; } /***********************************************************/ /* HELP PUZZLE ROUTINES */ /***********************************************************/ /****************************************/ /* Undo last move(s). */ /****************************************/ void HELP_UNDO(void) { int x1, y1, x2, y2; GLint xP, yP, xB, yB; RGB *piece = new RGB[9000]; if (movesToSolve == 0) return; // Swap pieces. glDrawBuffer(GL_FRONT_ANDesToSolve]; // Update moves made counter. movesMade += 2; TEXT_MOVE_COUNT(); } /****************************************/ /* Draw sub-puzzle. */ /****************************************/ void HELP_VIEW(void) { glDrawBuffer(GL_FRONT_AND_BACK); glPixelTransferi(GL_MAP_COLOR, false); glRasterPos2i(10, 18); glDrawPixels(90, 73, GL_RGB, GL_UNSIGNED_BYTE, PuzzleView); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glColor3f(0.0, 0.0, 0.0); glBegin(GL_LINES); glVertex2i(10, 91); glVertex2i(10, 17); glVertex2i(100, 91); glVertex2i(100, 17); glEnd(); } /***********************************************************/ /* NUMBER PUZZLE ROUTINES */ /***********************************************************/ /****************************************/ /* Number pieces. */ /****************************************/ void HELP_NUMBER(void) { int i, j; char number[4]; GLint xp, yp; glDrawBuffer(GL_FRONT_AND_BACK); for (j = 0; j < 5; j++) { yp = (431 - (j * 85)); for (i = 0; i < 5; i++) { xp = (119 + (i * 104)); // Space. if (PuzzleBoard[j][i] != -1) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glColor3f(0.0, 0.0, 0.0); glBegin(GL_QUADS); glVertex2i(xp, yp); glVertex2i(xp+20, yp); glVertex2i(xp+20, yp-20); glVertex2i(xp, yp-20); glEnd(); // Border. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glColor3f(1.0, 1.0, 1.0); glBegin(GL_QUADS); glVertex2i(xp, yp); glVertex2i(xp+20, yp); glVertex2i(xp+20, yp-20); glVertex2i(xp, yp-20); glEnd(); // Number. sprintf(number, "%d", PuzzleBoard[j][i]); TEXT_9_X_15(xp+1, yp-20+5, number); } } } } /***********************************************************/ /* CALLBACK FUNTIONS. */ /***********************************************************/ /****************************************/ /* Mouse control. */ /****************************************/ void myMouse(int button, int state, int x, int y) { int filePicked; y = (winHeight - y); if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { // Control buttons. if (x >= 10 && x <= 100) { glFinish(); winFlag = 0; if (y >= 385 && y <= 405) { // new Button BUTTON_CLICK(10, 385); playFlag = 0; loadFlag = 0; scanFlag = 1; WINDOW_CLEAR(112, 6, 639, 438); WINDOW_CLEAR( 7, 14, 103, 95); puzzles = SCAN_FOR_IMAGES("ppm"); SCAN_WINDOW(); SCAN_FILE_DISPLAY(scanStart, puzzles); } if (y >= 360 && y <= 380) { // Level Up Button if (playFlag == 0 && loadFlag == 1) { BUTTON_CLICK(10, 360); difficulty++; TEXT_DIFFICULTY(); } } if (y >= 335 && y <= 355) { // Level Down Button if (playFlag == 0 && loadFlag == 1) { BUTTON_CLICK(10, 335); if (difficulty > 1) difficulty--; TEXT_DIFFICULTY(); } } if (y >= 310 && y <= 330) { // Play Button if (loadFlag == 1) { BUTTON_CLICK(10, 310); playFlag = 1; NEW_CUTUP_IMAGE(); NEW_RANDOMIZE_IMAGE(); } } if (y >= 285 && y <= 305) { // Load Button BUTTON_CLICK(10, 285); WINDOW_CLEAR( 7, 14, 103, 95); PUZZLE_LOAD(); playFlag = 1; TEXT_MOVE_COUNT(); TEXT_DIFFICULTY(); } if (y >= 260 && y <= 280) { // Save Button if (playFlag == 1) { BUTTON_CLICK(10, 260); PUZZLE_SAVE(PuzzleName); } } if (y >= 220 && y <= 240) { // Exit Button BUTTON_CLICK(10, 220); glutDestroyWindow(window); exit(0); } if (y >= 150 && y <= 170) { // Undo Button if (playFlag == 1) { BUTTON_CLICK(10, 150); HELP_UNDO(); } } if (y >= 125 && y <= 145) { // Number Button if (playFlag == 1) { BUTTON_CLICK(10, 125); HELP_NUMBER(); } } if (y >= 100 && y <= 120) { // View Button if (playFlag == 1) { BUTTON_CLICK(10, 100); HELP_VIEW(); } } } // Puzzle pieces. if (x >= 116 && x <= 635 && y >= 10 && y <= 434) { if (playFlag == 1 && winFlag == 0) { PLAY(x, y); } } // Puzzle name scroll. if (x >= 420 && x <= 510 && scanFlag == 1) { if (y >= 385 && y <= 405) { // Up Button BUTTON_CLICK(420, 385); if (scanStart <= (puzzles-18)) { scanStart++; SCAN_FILE_DISPLAY(scanStart, puzzles); } } if (y >= 360 && y <= 380) { // Down Button BUTTON_CLICK(420, 360); if (scanStart > 0) { scanStart--; SCAN_FILE_DISPLAY(scanStart, puzzles); } } if (y >= 310 && y <= 330) { // Cancel Button BUTTON_CLICK(420, 310); WINDOW_CLEAR(112, 6, 639, 438); scanFlag = 0; } } // Puzzle name selection. if (x >= 235 && x <= 410 && scanFlag == 1) { filePicked = -1; if (y >= 380 && y <= 400) filePicked = scanStart; if (y >= 360 && y <= 380) filePicked = scanStart+1; if (y >= 340 && y <= 360) filePicked = scanStart+2; if (y >= 320 && y <= 340) filePicked = scanStart+3; if (y >= 300 && y <= 320) filePicked = scanStart+4; if (y >= 280 && y <= 300) filePicked = scanStart+5; if (y >= 260 && y <= 280) filePicked = scanStart+6; if (y >= 240 && y <= 260) filePicked = scanStart+7; if (y >= 220 && y <= 240) filePicked = scanStart+8; if (y >= 200 && y <= 220) filePicked = scanStart+9; if (y >= 180 && y <= 200) filePicked = scanStart+10; if (y >= 160 && y <= 180) filePicked = scanStart+11; if (y >= 140 && y <= 160) filePicked = scanStart+12; if (y >= 120 && y <= 140) filePicked = scanStart+13; if (y >= 100 && y <= 120) filePicked = scanStart+14; if (y >= 80 && y <= 100) filePicked = scanStart+15; if (y >= 60 && y <= 80) filePicked = scanStart+16; if (y >= 40 && y <= 60) filePicked = scanStart+17; if (filePicked != -1) { if (filePicked > puzzles) return; WINDOW_CLEAR(112, 6, 639, 438); strcpy(PuzzleName, PuzzleNames[filePicked]); if (NEW_LOAD(PuzzleName) == 0) { loadFlag = 1; movesToSolve = 0; movesMade = 0; TEXT_MOVE_COUNT(); difficulty = 1; TEXT_DIFFICULTY(); WINDOW_CLEAR( 7, 14, 103, 95); NEW_DRAW(); NEW_HELPVIEW_RECORD(); } scanFlag = 0; } } } } /****************************************/ /* Display. */ /****************************************/ void myDisplay(void) { if (drawFlag == 0) { glutSwapBuffers(); } else { MAIN_WINDOW(); drawFlag = 0; } } /****************************************/ /* Reshape. */ /****************************************/ void myResize(int h, int w){ if (drawFlag == 0) { glutDestroyWindow(window); exit(0); } } /****************************************/ /* Init. */ /****************************************/ void myInit(void) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glPointSize(1); gluOrtho2D(0.0, 640.0, 0.0, 480.0); glShadeModel(GL_SMOOTH); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glClear(GL_COLOR_BUFFER_BIT); } /* Display *glutDisplay; Window *glutCurrentWindow; XSizeHints hints; void freeze_win(int width, int height, Window glutCurrentWindow) { long suppl; XGetWMNormalHints (glutDisplay, glutCurrentWindow, &hints, &suppl); hints.min_width = width; hints.max_width = width; hints.min_height = height; hints.max_height = height; hints.flags |= PMaxSize | PMinSize; XSetWMNormalHints (glutDisplay, glutCurrentWindow, &hints); } / /***********************************************************/ /* MAIN. */ /***********************************************************/ void main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutInitWindowSize(640, 480); glutInitWindowPosition(100, 100); window = glutCreateWindow("Puzz-R.A.M. by Ron Marsh"); // freeze_win(640, 480, (Window)window); glutDisplayFunc(myDisplay); glutIdleFunc(PLAY_WINNER); // glutReshapeFunc(myResize); glutReshapeFunc(NULL); glutMouseFunc(myMouse); myInit(); glutMainLoop(); }