/*************************************************\ FILE: connect.cpp PURPOSE: Setup and display for the game. Created by Eric Akers, 15 Dec 2003 ChangeLog: ELA - - Initial Working Version Copyright (C) 2003 Eric Akers This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \**************************************************/ /* Header Files ############################################################# */ #include #include #include #ifdef WIN32 #include #endif #include #include #include "connectFive.h" #include "glfont2.h" #include "guiContainer.h" #include "guiButton.h" #include using namespace std; #include "eventHandler.h" #include "Board.h" #include "SimpleHeuristic.h" /* Macros ################################################################### */ // Textures #define DARK_MARBLE 0 #define LIGHT_MARBLE 1 // Interval to call the demo mode callback from #define DEMO_MODE_INTERVAL 300 // Initial start position for the computer #define INITIAL_MOVE_ROW 9 #define INITIAL_MOVE_COL 9 /* Structures ############################################################### */ /* Global Variables ######################################################### */ // Varibles for doing dynamic rotations extern GLdouble screenRotateX, screenRotateZ; extern GLdouble distanceEyeCenter; // The distance from eye to center extern GLdouble screenMoveX, screenMoveY; extern int lastScreenOffsetX, lastScreenOffsetY; extern bool mouseMotion; // Stores the textures static GLuint checkerTexture[2]; static GLuint woodTexture; // The display lists GLuint boardList, pieceList; // The mode the game is in static char gameMode = MODE_DEMO; // Demo mode timer ID static SDL_TimerID demoID; // Holds the current state of the game SimpleHeuristic * currentState = NULL; // Contains the current menu to draw guiContainer * currentMenu; // Keeps track of the players static char currentPlayer = PLAYER_1; static char playerOneType = HUMAN_PLAYER; static char playerTwoType = HUMAN_PLAYER; // Menus static guiContainer * mainMenu; // Main Menu static guiContainer * gameMenu; // Menu during game play // Labels to change during the game play static guiMenuItem * playerLabel, * lastMoveLabel; // The SDL Thread that determines the next move by the computer SDL_Thread * computerMoveThread; // The computer player(s) computerSearch * computerPlayers[2]; // The difficulty static int difficulty = 2; // Last moves static int lastMoveX = -1, lastMoveY = -1; /* Function Declarations #################################################### */ // TEMP STUFF extern void setupMenu( guiContainer & container ); /* Static Function Declarations ############################################# */ static void setupOpenGL(); static void drawBoard(); static void drawChecker( int pattern, GLdouble topX, GLdouble topY, GLdouble botX, GLdouble botY ); Uint32 demoModeCallback( Uint32 interval, void *param ); static void drawCube( GLdouble length, GLdouble height, GLdouble depth ); static void drawLetters( bool lettersOrNumbers, bool forwards ); static void displayBoardState( Board * currentState ); static void setDemoMode(); static void setupGUIMenus(); static char getLetterOfPlay( int col ); static int getNextMoveThread( void * data ); static void drawPiece( int row, int col ); /* Main ##################################################################### */ int main( int argc, char * argv[] ) { // Set up SDL if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO ) != 0 ) { printf( "Cannot Init SDL: Error: %s\n", SDL_GetError() ); return -1; } // Make sure the SDL_Quit is called when exiting atexit( SDL_Quit ); // Set the window title and icon name SDL_WM_SetCaption( "Connect Five", "Connect Five" ); // Get the bpp const SDL_VideoInfo * info; info = SDL_GetVideoInfo(); int bpp = info->vfmt->BitsPerPixel; // Make sure we can use double buffering SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // Set the video mode initializing OpenGL SDL_Surface * screen = SDL_SetVideoMode( WIN_WIDTH, WIN_HEIGHT, bpp, SDL_OPENGL ); if( screen == NULL ) { printf( "Error initializing video mode: %s\n", SDL_GetError() ); return -1; } // Setup the font to use GLuint fontTexture; glGenTextures( 1, &fontTexture ); if( font.Create( "data/times14.glf", fontTexture ) ) { printf( "Created\n" ); } else { printf( "Not created\n" ); } // Set up the viewing frustum and openGL setupView( WIN_WIDTH, WIN_HEIGHT, FOVY, ZNEAR, ZFAR ); setupOpenGL(); // Setup the menu guis printf( "Setup guis\n" ); setupGUIMenus(); // Setup the board for the current state printf( "Setup board\n" ); createNewBoard(); // Start the game in demo mode changeGameMode( MODE_DEMO ); // Initialize the computer players computerPlayers[0] = NULL; computerPlayers[1] = NULL; // Start the program display(); eventHandler(); return 0; } /* Function Definitions #################################################### */ void display() { setupModelViewMatrix(); // Draw the scene drawScene(); // Flush! glFlush(); SDL_GL_SwapBuffers( ); } void setupView( int width, int height, GLdouble fovy, GLdouble zNear, GLdouble zFar ) { // Setup the openGL view glMatrixMode( GL_MODELVIEW ); glViewport( 0, 0, width, height ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); setupProjectionMatrix( width, height, fovy, zNear, zFar ); } void setupProjectionMatrix( int width, int height, GLdouble fovy, GLdouble zNear, GLdouble zFar ) { gluPerspective( fovy, (float)width / (float)height, zNear, zFar ); } void setupModelViewMatrix() { glMatrixMode( GL_MODELVIEW ); // Clear the buffers glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Perform the transformations glLoadIdentity(); // Move the display left and right glTranslated( screenMoveX, screenMoveY, 0.0 ); // Allow rotation of the display glTranslated( 0.0, 0.0, -distanceEyeCenter ); glRotated( screenRotateX, 1.0, 0.0, 0.0 ); glRotated( screenRotateZ, 0.0, 0.0, 1.0 ); glTranslated( 0.0, 0.0, distanceEyeCenter ); gluLookAt( 0.0, 0.0, distanceEyeCenter, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 ); } void drawScene() { GLfloat highlightDiff[] = { 0.9, 0.9, 0.1, 1.0 }; GLfloat highlightShininess[] = { 2.0 }; // Draw the board glCallList( boardList ); // Draw the highlighted checker if necessary if( mousePick == true && highlightCheckerX != -1 ) { glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, highlightDiff ); glMaterialfv( GL_FRONT, GL_SHININESS, highlightShininess ); GLdouble topX = -95 + (highlightCheckerX * 10); GLdouble topY = 95 - (highlightCheckerY * 10); GLdouble botX = topX + 10.0; GLdouble botY = topY - 10.0; glBegin( GL_QUADS ); glNormal3d( 0.0, 0.0, 1.0 ); glVertex3d( topX, topY, 10.1 ); glVertex3d( topX, botY, 10.1 ); glVertex3d( botX, botY, 10.1 ); glVertex3d( botX, topY, 10.1 ); glEnd(); // Draw the piece highlighted for effect drawPiece( highlightCheckerX, highlightCheckerY ); } // Draw all the pieces displayBoardState( currentState ); // Draw the last move piece int lastX, lastY; if( getLastMove( &lastX, &lastY ) ) { glPushMatrix(); GLfloat lastMoveShininess[] = { 2.0 }; GLfloat lastMoveDiff[2][4] = { { 0.1, 0.1, 0.3, 1.0 }, { 0.1, 0.3, 0.1, 1.0 } }; // Draw the color based on the previous player int lastPlayer; if( getCurrentPlayer() == PLAYER_1 ) { lastPlayer = 1; } else { lastPlayer = 0; } glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lastMoveDiff[lastPlayer] ); glMaterialfv( GL_FRONT, GL_SHININESS, lastMoveShininess ); drawPiece( lastX, lastY ); glPopMatrix(); } // Display the menu currentMenu->display(); } void setLastMove( int row, int col ) { lastMoveX = row; lastMoveY = col; } bool getLastMove( int * row, int * col ) { if( lastMoveX != -1 ) { *row = lastMoveX; *col = lastMoveY; return true; } else { return false; } } void setNextPlay( int x, int y ) { if( currentState->getPlayerAt( x, y ) != Board::BLANK ) { // This move is already taken return; } // Set the last move setLastMove( x, y ); int oldPlayer = getCurrentPlayer(); // The location is blank. Set the move, and change player state int boardPlayer; if( currentPlayer == PLAYER_1 ) { boardPlayer = Board::PLAYER_ONE; setCurrentPlayer( PLAYER_2 ); } else { boardPlayer = Board::PLAYER_TWO; setCurrentPlayer( PLAYER_1 ); } // Set the movein the board currentState->setPlayerMove( x, y, boardPlayer ); // Set the labels for the last move setGameLabel( getCurrentPlayer(), x, y ); // See if the move caused a victory if( currentState->isWinningState() ) { setGameWinner( oldPlayer ); } else { // See if the computer needs to choose the next move if( getCurrentPlayerType() == COMPUTER_PLAYER ) { getNextComputerMove( x, y ); } } //////// TEMPORARY long int heuristic = currentState->getHeuristicValue( Board::PLAYER_ONE ); printf( "************ Heuristic Value: %ld\n", heuristic ); } void setGameLabel( char player, int row, int col ) { // Set the current player label if( player == PLAYER_1 ) { playerLabel->setLabel( "Player One" ); } else { playerLabel->setLabel( "Player Two" ); } // Set the last move if( row == -1 ) { // First move of the game lastMoveLabel->setLabel( "First Move" ); } else { char play[10]; sprintf( play, "Last Move: %c%d", getLetterOfPlay(row), col + 1 ); lastMoveLabel->setLabel( play ); } } void setGameWinner( char player ) { if( player == PLAYER_1 ) { playerLabel->setLabel( "Winner: Player One" ); } else { playerLabel->setLabel( "Winner: Player Two" ); } // Change to finished mode changeGameMode( MODE_GAME_FINISHED ); } void changeGameMode( char newMode ) { // Set the current menu and other misc things if( newMode == MODE_DEMO ) { // Start demo mode setDemoMode(); currentMenu = mainMenu; // Set the labels to be correct if( currentPlayer == PLAYER_1 ) { playerLabel->setLabel( "Player One" ); } else { playerLabel->setLabel( "Player Two" ); } } else{ currentMenu = gameMenu; } // Change the mode gameMode = newMode; } char getGameMode() { return gameMode; } void createNewBoard() { if( currentState != NULL ) { delete currentState; } currentState = new SimpleHeuristic(); if( currentState == NULL ) { printf( "Error alloc board\n" ); exit( -1 ); } } char getCurrentPlayerType() { if( currentPlayer == PLAYER_1 ) { return playerOneType; } else { return playerTwoType; } } char getCurrentPlayer() { return currentPlayer; } void setCurrentPlayer( char player ) { currentPlayer = player; } void setPlayerType( char player, char type ) { char * tempPlayer; // Get the player to set if( player == PLAYER_1 ) { tempPlayer = & playerOneType; } else { tempPlayer = & playerTwoType; } // Set the type for this player *tempPlayer = type; } void getNextComputerMove( int lastMoveRow, int lastMoveCol ) { printf( "getNextComputerMove\n" ); // Add the last move to the computer player if( lastMoveRow != -1 ) { // Set the other players move for this computer computerPlayers[getCurrentPlayer()]-> setOtherPlayerMove( lastMoveRow, lastMoveCol ); // Create the thread that finds the next move printf( "Create the thread\n" ); computerMoveThread = SDL_CreateThread( getNextMoveThread, NULL ); printf( "Finished\n" ); } else { printf( "SET FIRST COMPUTER MOVE\n" ); // Just set a default move for the dirst move of the game computerPlayers[getCurrentPlayer()]-> setOtherPlayerMove( INITIAL_MOVE_ROW, INITIAL_MOVE_COL ); // Create an event to set the next move. Since this is done in a // seperate thread, we must only use the SDL_PushEvent library function. SDL_Event newEvent; // Set the fields newEvent.type = PLAY_COMPUTER_MOVE; newEvent.user.code = 0; newEvent.user.data1 = new int( INITIAL_MOVE_ROW ); newEvent.user.data2 = new int( INITIAL_MOVE_COL ); // Put the event on the queue SDL_PushEvent( & newEvent ); } } void setDifficulty( int diff ) { difficulty = diff; } int getDifficulty() { return difficulty; } /* Static Function Declarations ############################################# */ static void setupOpenGL() { // Set a directional light GLfloat lightAmbient[] = { 0.1, 0.1, 0.1, 1.0 }; GLfloat lightDiffuse[] = { 0.8, 0.8, 0.8, 1.0 }; GLfloat lightSpecular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat lightDirection[] = { 200.0, 1000.0, 1500.0, 1.0 }; glLightfv( GL_LIGHT0, GL_POSITION, lightDirection ); glLightfv( GL_LIGHT0, GL_DIFFUSE, lightDiffuse ); glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular ); glLightfv( GL_LIGHT0, GL_AMBIENT, lightAmbient ); // Set the shade model glShadeModel( GL_SMOOTH ); // Set the background glClearColor( 1.0, 1.0, 1.0, 1.0 ); // Enable the basics glEnable( GL_LIGHTING ); glEnable( GL_DEPTH_TEST ); glEnable( GL_LIGHT0 ); // Blending is used by the fonts glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Load the textures for the checkerboard patter SDL_Surface *textureSurface[3]; textureSurface[DARK_MARBLE] = SDL_LoadBMP( "data/marble3.bmp" ); if( textureSurface[DARK_MARBLE] == NULL ) { cout << "Unable to load marble 2" << endl; exit( -1 ); } textureSurface[1] = SDL_LoadBMP( "data/marble1.bmp" ); if( textureSurface[1] == NULL ) { cout << "Unable to load marble 1" << endl; exit( -1 ); } textureSurface[2] = SDL_LoadBMP( "data/wood2.bmp" ); if( textureSurface[2] == NULL ) { cout << "Unable to load wood" << endl; exit( -1 ); } // Set the opengl texture parameters glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glGenTextures( 2, checkerTexture ); glGenTextures( 1, &woodTexture ); // Marble Texture 1 glBindTexture( GL_TEXTURE_2D, checkerTexture[DARK_MARBLE] ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, textureSurface[DARK_MARBLE]->w, textureSurface[DARK_MARBLE]->h, 0, GL_BGR, GL_UNSIGNED_BYTE, textureSurface[DARK_MARBLE]->pixels ); // Marble Texture 2 glBindTexture( GL_TEXTURE_2D, checkerTexture[LIGHT_MARBLE] ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, textureSurface[LIGHT_MARBLE]->w, textureSurface[LIGHT_MARBLE]->h, 0, GL_BGR, GL_UNSIGNED_BYTE, textureSurface[LIGHT_MARBLE]->pixels ); // Wood Texture glBindTexture( GL_TEXTURE_2D, woodTexture ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, textureSurface[2]->w, textureSurface[2]->h, 0, GL_BGR, GL_UNSIGNED_BYTE, textureSurface[2]->pixels ); // Delete the SDL Surfaces SDL_FreeSurface( textureSurface[DARK_MARBLE] ); SDL_FreeSurface( textureSurface[LIGHT_MARBLE] ); SDL_FreeSurface( textureSurface[2] ); // Setup the display lists boardList = glGenLists( 1 ); pieceList = glGenLists( 1 ); // The board glNewList( boardList, GL_COMPILE ); drawBoard(); glEndList(); // Draw a piece glNewList( pieceList, GL_COMPILE ); GLUquadricObj * piece = gluNewQuadric(); gluQuadricOrientation( piece, GLU_OUTSIDE ); gluQuadricDrawStyle( piece, GLU_FILL ); gluQuadricNormals( piece, GLU_SMOOTH ); gluCylinder( piece, 4.5, 4.5, 4.0, 15, 1 ); // Draw the top glTranslated( 0.0, 0.0, 3.9 ); gluDisk( piece, 0, 4.5, 20, 1 ); glEndList(); } static void drawBoard() { bool dark = false; // Set the textures to modulate glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); // The material values for the top GLfloat matSpec[] = { 0.1, 0.1, 0.1, 1.0 }; GLfloat matDiff[] = { 1.0, 1.0, 1.0, 1.0 }; // Material properties glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matDiff ); glMaterialfv( GL_FRONT, GL_SPECULAR, matSpec ); // Used to draw the textures facing different directions int darkPattern = 0, lightPattern = 0; // Draw the top with the checkerboard pattern for( int x=0; x<19; x++ ) { // Push the column name onto the selection stack glPushName( x ); for( int y=0; y<19; y++ ) { // Push the row name onto the selction stack glPushName( y ); double topX = -95 + (x * 10); double topY = 95 - (y * 10); double botX = topX + 10.0; double botY = topY - 10.0; glPushMatrix(); glEnable( GL_TEXTURE_2D ); if( dark ) { // Add the texture glBindTexture( GL_TEXTURE_2D, checkerTexture[DARK_MARBLE] ); glBegin( GL_QUADS ); glNormal3d( 0.0, 0.0, 1.0 ); drawChecker( darkPattern++ % 4, topX, topY, botX, botY ); glEnd(); } else { // Add the texture glBindTexture( GL_TEXTURE_2D, checkerTexture[LIGHT_MARBLE] ); glBegin( GL_QUADS ); glNormal3d( 0.0, 0.0, 1.0 ); drawChecker( lightPattern++ % 4, topX, topY, botX, botY ); glEnd(); } glDisable( GL_TEXTURE_2D ); glPopMatrix(); dark = !dark; // Remove the column name from the selction stack glPopName(); } // Remove the row name from the selection stack glPopName(); } // Draw the sides and back GLfloat matSidesDiff[] = { 1.0, 1.0, 1.0, 1.0 }; glPushMatrix(); glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matSidesDiff ); glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, woodTexture ); // Left Side glPushMatrix(); glTranslated( -105.0, 0.0, 1.0 ); glRotated( 90.0, 0.0, 0.0, 1.0 ); drawCube( 230.0, 20.0, 20.0 ); glPopMatrix(); // Right Side glPushMatrix(); glTranslated( 105.0, 0.0, 1.0 ); glRotated( 90.0, 0.0, 0.0, 1.0 ); drawCube( 230.0, 20.0, 20.0 ); glPopMatrix(); // Back Side glPushMatrix(); glTranslated( 0.0, 105.0, 1.0 ); drawCube( 190.0, 20.0, 20.0 ); glPopMatrix(); // Front Side glPushMatrix(); glTranslated( 0.0, -105.0, 1.0 ); drawCube( 190.0, 20.0, 20.0 ); glPopMatrix(); // Draw the text glDisable( GL_LIGHTING ); glEnable( GL_BLEND ); // Front glPushMatrix(); glTranslated( 0.0, -98.0, 11.2 ); drawLetters( true, true ); glPopMatrix(); // Back glPushMatrix(); glTranslated( 0.0, 98.0, 11.2 ); glRotated( 180.0, 0.0, 0.0, 1.0 ); drawLetters( true, false ); glPopMatrix(); // Left glPushMatrix(); glTranslated( -99.0, 0.0, 11.2 ); glRotated( -90.0, 0.0, 0.0, 1.0 ); drawLetters( false, true ); glPopMatrix(); // Right glPushMatrix(); glTranslated( 99.0, 0.0, 11.2 ); glRotated( 90.0, 0.0, 0.0, 1.0 ); drawLetters( false, false ); glPopMatrix(); glDisable( GL_TEXTURE_2D ); glDisable( GL_BLEND ); glEnable( GL_LIGHTING ); glPopMatrix(); } static void drawLetters( bool lettersOrNumbers, bool forwards ) { char letters1[] = "ABCDEFGHIJKLMNOPQRS"; char letters2[] = "SRQPONMLKJIHGFEDCBA"; float firstX; if( forwards ) { firstX = -92.0; } else { firstX = -94.0; } // Set the color glColor3f( 0.0, 0.0, 0.0 ); font.Begin(); for( int i=0; i<19; i++ ) { // printf( "X: %f\n", firstX ); string tmpLetter; if( lettersOrNumbers ) { if( forwards ) { tmpLetter += letters1[i]; } else { tmpLetter += letters2[i]; } } else { char num[5]; if( forwards ) { sprintf( num, "%d", i + 1 ); } else { sprintf( num, "%d", 19 - i ); } tmpLetter += num; } glPushMatrix(); glTranslatef( firstX, 0.0, 0.0 ); glScaled( 0.4, 0.4, 1.0 ); // Draw the font at 0,0 so that the scale does not shrink // the entire string font.DrawString( tmpLetter, 0.0, 0.0 ); glPopMatrix(); if( forwards && lettersOrNumbers == false && i == 8 ) { firstX += 8.0; } else if( !forwards && lettersOrNumbers == false && i == 9 ) { firstX += 12.5; } else { firstX += 10.0; } } } static void drawCube( GLdouble length, GLdouble height, GLdouble depth ) { double halfH = height / 2; double halfL = length / 2; double halfD = depth / 2; GLdouble leftX = 0.0 - halfL; GLdouble rightX = 0.0 + halfL; GLdouble topY = 0.0 + halfH; GLdouble botY = 0.0 - halfH; GLdouble frontZ = 0.0 + halfD; GLdouble backZ = 0.0 - halfD; glBegin( GL_QUADS ); // Back face glNormal3d( 0.0, 0.0, -1.0 ); glTexCoord2d( 1.0, 1.0 ); glVertex3d( leftX, topY, backZ ); glTexCoord2d( 0.0, 1.0 ); glVertex3d( rightX, topY, backZ ); glTexCoord2d( 0.0, 0.0 ); glVertex3d( rightX, botY, backZ ); glTexCoord2d( 1.0, 0.0 ); glVertex3d( leftX, botY, backZ ); // Front glNormal3d( 0.0, 0.0, 1.0 ); glTexCoord2d( 0.0, 0.0 ); glVertex3d( rightX, topY, frontZ ); glTexCoord2d( 1.0, 0.0 ); glVertex3d( leftX, topY, frontZ ); glTexCoord2d( 1.0, 1.0 ); glVertex3d( leftX, botY, frontZ ); glTexCoord2d( 0.0, 1.0 ); glVertex3d( rightX, botY, frontZ ); // Bottom glNormal3d( 0.0, -1.0, 0.0 ); glTexCoord2d( 0.0, 0.0 ); glVertex3d( rightX, botY, frontZ ); glTexCoord2d( 1.0, 0.0 ); glVertex3d( leftX, botY, frontZ ); glTexCoord2d( 1.0, 1.0 ); glVertex3d( leftX, botY, backZ ); glTexCoord2d( 0.0, 1.0 ); glVertex3d( rightX, botY, backZ ); // Top glNormal3d( 0.0, 1.0, 0.0 ); glTexCoord2d( 1.0, 0.0 ); glVertex3d( rightX, topY, frontZ ); glTexCoord2d( 1.0, 1.0 ); glVertex3d( rightX, topY, backZ ); glTexCoord2d( 0.0, 1.0 ); glVertex3d( leftX, topY, backZ ); glTexCoord2d( 1.0, 0.0 ); glVertex3d( leftX, topY, frontZ ); // Left glNormal3d( -1.0, 0.0, 0.0 ); glTexCoord2d( 0.0, 0.0 ); glVertex3d( leftX, topY, frontZ ); glTexCoord2d( 1.0, 0.0 ); glVertex3d( leftX, topY, backZ ); glTexCoord2d( 1.0, 3.0 ); glVertex3d( leftX, botY, backZ ); glTexCoord2d( 0.0, 3.0 ); glVertex3d( leftX, botY, frontZ ); // Right glNormal3d( 1.0, 0.0, 0.0 ); glTexCoord2d( 0.0, 0.0 ); glVertex3d( rightX, botY, frontZ ); glTexCoord2d( 1.0, 0.0 ); glVertex3d( rightX, botY, backZ ); glTexCoord2d( 1.0, 3.0 ); glVertex3d( rightX, topY, backZ ); glTexCoord2d( 0.0, 3.0 ); glVertex3d( rightX, topY, frontZ ); glEnd(); } static void drawChecker( int pattern, GLdouble topX, GLdouble topY, GLdouble botX, GLdouble botY ) { // Draw the same cube while changing which angle the texture // faces so that it isn't the same everywhere. GLfloat coords[4][4][2] = { { {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}, {1.0, 0.0} }, { {0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0} }, { {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0} }, { {0.0, 1.0}, {0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0} } }; // Set the tex coords and vertices with the given pattern glTexCoord2fv( coords[pattern][0] ); glVertex3d( topX, topY, 10.0 ); glTexCoord2fv( coords[pattern][1] ); glVertex3d( topX, botY, 10.0 ); glTexCoord2fv( coords[pattern][2] ); glVertex3d( botX, botY, 10.0 ); glTexCoord2fv( coords[pattern][3] ); glVertex3d( botX, topY, 10.0 ); } static void setDemoMode() { demoID = SDL_AddTimer( DEMO_MODE_INTERVAL, demoModeCallback, NULL ); } // Demo Mode timer callback Uint32 demoModeCallback( Uint32 interval, void *param ) { if( getGameMode() != MODE_DEMO ) { SDL_RemoveTimer( demoID ); return 0; } if( mouseMotion ) { // The mouse is rotating the image return interval; } // Rotate around z all the time lastScreenOffsetX -= 1; screenRotateZ = 360.0 / ROTATION_SCALE * lastScreenOffsetX; // See if need to rotate around X if( screenRotateX > -60.0 ) { lastScreenOffsetY -= 10; screenRotateX = 360.0 / ROTATION_SCALE * lastScreenOffsetY; } else if( screenRotateX < -64.1 ) { lastScreenOffsetY += 3; screenRotateX = 360.0 / ROTATION_SCALE * lastScreenOffsetY; } // Push an event so that the display can be redrawn SDL_Event newEvent; // Set the fields newEvent.type = SDL_USEREVENT; newEvent.user.code = 0; newEvent.user.data1 = NULL; newEvent.user.data2 = NULL; // Put the event on the queue SDL_PushEvent( & newEvent ); return interval; } // Displays the current state ofthe board static void displayBoardState( Board * currentState ) { GLfloat pieceDiff[2][4] = { { 0.1, 0.2, 0.5, 1.0 }, { 0.1, 0.5, 0.2, 1.0 } }; GLfloat pieceShininess[] = { 20.0 }; // Determine the last move location so that we do not draw it int lastX = -1, lastY = -1; getLastMove( &lastX, &lastY ); // Draw the pieces on the board for( int x=0; x<19; x++ ) { for( int y=0; y<19; y++ ) { // Determine which piece to draw int piece = currentState->getPlayerAt( x, y ); if( piece == Board::BLANK ) { continue; } // Do not draw the last played piece if( x == lastX && y == lastY ) { continue; } /* // Determine the coordinates of the piece to draw double centerX = -90.0 + (x * 10); double centerY = 90.0 - (y * 10); // Draw the correct piece glPushMatrix(); glTranslated( centerX, centerY, 10.0 ); */ glMaterialfv( GL_FRONT, GL_SHININESS, pieceShininess ); if( piece == Board::PLAYER_ONE ) { glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, pieceDiff[0] ); // glCallList( pieceList ); drawPiece( x, y ); } else { glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, pieceDiff[1] ); // glCallList( pieceList ); drawPiece( x, y ); } } } } static void drawPiece( int row, int col ) { // Determine the coordinates of the piece to draw double centerX = -90.0 + (row * 10); double centerY = 90.0 - (col * 10); glPushMatrix(); glTranslated( centerX, centerY, 10.0 ); glCallList( pieceList ); glPopMatrix(); } static void setupGUIMenus() { mainMenu = new guiContainer( WIN_WIDTH, WIN_HEIGHT ); gameMenu = new guiContainer( WIN_WIDTH, WIN_HEIGHT ); if( mainMenu == NULL || gameMenu == NULL ) { printf( "MENU ALLOC ERROR\n" ); exit( -1 ); } setupMenu( mainMenu ); // The game menu must be passed in the labels to use playerLabel = new guiMenuItem( "Player One" ); lastMoveLabel = new guiMenuItem( "First Move" ); setupGameMenu( gameMenu, playerLabel, lastMoveLabel ); } static char getLetterOfPlay( int col ) { switch( col ) { case 0: return 'A'; case 1: return 'B'; case 2: return 'C'; case 3: return 'D'; case 4: return 'E'; case 5: return 'F'; case 6: return 'G'; case 7: return 'H'; case 8: return 'I'; case 9: return 'J'; case 10: return 'K'; case 11: return 'L'; case 12: return 'M'; case 13: return 'N'; case 14: return 'O'; case 15: return 'P'; case 16: return 'Q'; case 17: return 'R'; case 18: return 'S'; } // oops return 'Z'; } static int getNextMoveThread( void * data ) { int newMoveRow, newMoveCol; printf( "CONNECT CALLING GETNEXTMOVE\n" ); computerPlayers[getCurrentPlayer()]->getNextMove( newMoveRow, newMoveCol ); printf( "***CONNECT: getNextMove finished (%d,%d)\n", newMoveRow, newMoveCol ); // Create an event to set the next move SDL_Event newEvent; // Set the fields newEvent.type = PLAY_COMPUTER_MOVE; newEvent.user.code = 0; newEvent.user.data1 = new int( newMoveRow ); newEvent.user.data2 = new int( newMoveCol ); // Put the event on the queue printf( "CONNECT: PushEvent\n" ); SDL_PushEvent( & newEvent ); printf( "CONNECT: Push Event finished\n" ); return 0; }