Josh Smith / Mbed 2 deprecated MobileChessStation

Dependencies:   mbed mbed-rtos 4DGL-uLCD-SE

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 
00002 #include "mbed.h"
00003 #include "rtos.h"
00004 #include "uLCD_4DGL.h"
00005 #include "Speaker.h"
00006 
00007 //piece colors
00008 #define white true
00009 #define black false
00010 
00011 //button inputs
00012 #define SELECT 0
00013 #define FORWARD 1
00014 #define BACKWARD 2
00015 #define RIGHT 3
00016 #define LEFT 4
00017 #define MENU 5
00018 
00019 //piece types
00020 #define NONE 0
00021 #define KING 1
00022 #define QUEEN 2
00023 #define BISHOP 3
00024 #define KNIGHT 4
00025 #define ROOK 5
00026 #define PAWN 6
00027 
00028 //seven-segment display conversions
00029 #define ZERO 126
00030 #define ONE 48
00031 #define TWO 109
00032 #define THREE 121
00033 #define FOUR 51
00034 #define FIVE 91
00035 #define SIX 95
00036 #define SEVEN 112
00037 #define EIGHT 127
00038 #define NINE 123
00039 
00040 #define D1 7
00041 #define D2 11
00042 #define D3 13
00043 #define D4 14
00044 
00045 uLCD_4DGL uLCD(p28, p27, p29); // serial tx, serial rx, reset pin;
00046 
00047 Serial pc(USBTX, USBRX);
00048 
00049 //button control (directions optional)
00050 DigitalIn Select(p14);
00051 DigitalIn Menu(p15);
00052 DigitalOut led3(LED3);
00053 DigitalOut whiteLED(p12);
00054 DigitalOut blackLED(p13);
00055 Speaker speakerOut(p26);
00056 
00057 //Joystick variables
00058 AnalogIn JoyX(p19);
00059 AnalogIn JoyY(p20);
00060 
00061 
00062 volatile bool currentPlayer = white;
00063 volatile bool gameActive = false;
00064 
00065 bool menuOpen = false;
00066 int menuSelectionIndex = 0;
00067 
00068 bool playSound = true;
00069 
00070 int boxWidth = 16;
00071 
00072 int programTimeSetting = 600;
00073 
00074 bool pieceSelected = false;
00075 int currentPiece = NONE;
00076 int positionX = 0;
00077 int positionY = 0;
00078 int selectedX = 0;
00079 int selectedY = 0;
00080 int board[8][8] = {
00081     {ROOK, PAWN, NONE, NONE, NONE, NONE, PAWN, ROOK},
00082     {KNIGHT, PAWN, NONE, NONE, NONE, NONE, PAWN, KNIGHT},
00083     {BISHOP, PAWN, NONE, NONE, NONE, NONE, PAWN, BISHOP},
00084     {KING, PAWN, NONE, NONE, NONE, NONE, PAWN, KING},
00085     {QUEEN, PAWN, NONE, NONE, NONE, NONE, PAWN, QUEEN},
00086     {BISHOP, PAWN, NONE, NONE, NONE, NONE, PAWN, BISHOP},
00087     {KNIGHT, PAWN, NONE, NONE, NONE, NONE, PAWN, KNIGHT},
00088     {ROOK, PAWN, NONE, NONE, NONE, NONE, PAWN, ROOK}
00089 };
00090 
00091 bool color[8][8] = {
00092     {white, white, white, white, white, white, black, black},
00093     {white, white, white, white, white, white, black, black},
00094     {white, white, white, white, white, white, black, black},
00095     {white, white, white, white, white, white, black, black},
00096     {white, white, white, white, white, white, black, black},
00097     {white, white, white, white, white, white, black, black},
00098     {white, white, white, white, white, white, black, black},
00099     {white, white, white, white, white, white, black, black}
00100 };
00101 
00102 Timer timerWhite;
00103 Timer timerBlack;
00104 
00105 void drawGameBoard();
00106 int waitForInput();
00107 
00108 //TIMER FUNCTIONS---------------------------------------------------------------------------------------------------------------------------------
00109 
00110 void timer(void const *args) {
00111     //updates the small clock
00112     int time_left = programTimeSetting; // remaining time for either player
00113     int min2, min1, sec2, sec1; // decimal value for each digit
00114     int digits[10] = {ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE}; //contains bus words for each symbol
00115     
00116     BusOut digit_value(p18, p17, p9, p8, p7, p6, p5);
00117     BusOut digit_select(p21, p22, p23, p24);
00118     DigitalOut decimal_point(p25);
00119     
00120     while (true) {
00121         led3 = currentPlayer;
00122         whiteLED = currentPlayer;
00123         blackLED = !currentPlayer;
00124         if (!gameActive) {
00125             time_left = programTimeSetting;
00126         }
00127         else if (currentPlayer == black) {
00128             //output: programTimeSetting - whiteTime.read()
00129             time_left = programTimeSetting - timerBlack.read();
00130         }
00131         else {
00132             //output: programTimeSetting - blackTime.read()
00133             time_left = programTimeSetting - timerWhite.read();
00134         }
00135         
00136         // calculate digit values for display
00137         min2 = time_left / 600;
00138         min1 = (time_left - 600*min2) / 60;
00139         sec2 = (time_left - 600*min2 - 60*min1) / 10;
00140         sec1 = (time_left - 600*min2 - 60*min1 - 10*sec2) / 1;
00141         
00142         // write 7seg display digits
00143         digit_select = D4;
00144         digit_value = digits[min2];
00145         decimal_point = 0;
00146         Thread::wait(1);
00147         digit_select = D3;
00148         digit_value = digits[min1];
00149         decimal_point = 1;
00150         Thread::wait(1);
00151         digit_select = D2;
00152         digit_value = digits[sec2];
00153         decimal_point = 0;
00154         Thread::wait(1);
00155         digit_select = D1;
00156         digit_value = digits[sec1];
00157         decimal_point = 0;
00158         Thread::wait(1);
00159     }
00160 }
00161 
00162 //INITIALIZING FUNCTIONS--------------------------------------------------------------------------------------------------------------------------
00163 
00164 void initializeButtons() {
00165     blackLED = 0;
00166     whiteLED = 0;
00167     Select.mode(PullUp);
00168     Menu.mode(PullUp);
00169 }
00170 
00171 void initializeVariables() {
00172     currentPlayer = white;
00173     positionX = 0;
00174     positionY = 0;
00175     pieceSelected = false;
00176     timerWhite.stop();
00177     timerWhite.reset();
00178     timerBlack.stop();
00179     timerBlack.reset();
00180 }
00181 
00182 void initializeLCD() {
00183     uLCD.baudrate(BAUD_3000000); //jack up baud rate to max for fast display
00184     uLCD.display_control(PORTRAIT);
00185     uLCD.text_mode(TRANSPARENT);
00186     uLCD.cls();
00187     uLCD.printf("ChessDude");
00188     wait(1.0);
00189     uLCD.cls();
00190     drawGameBoard();
00191 }
00192 
00193 void initialize() {
00194     initializeButtons();
00195     initializeVariables();
00196     initializeLCD();
00197 }
00198 
00199 
00200 //DRAW FUNCTIONS----------------------------------------------------------------------------------------------------------------------------------
00201 
00202 void drawMenuLine(int line) {
00203     uLCD.filled_rectangle(1, 32*line+1, 127, 32*line+31, WHITE);
00204     uLCD.text_mode(TRANSPARENT);
00205     switch (line) {
00206         case 0: {
00207             if (playSound) 
00208                 uLCD.text_string("SOUND: ON", 4, 2, FONT_7X8, BLACK);
00209             else
00210                 uLCD.text_string("SOUND: OFF", 4, 2, FONT_7X8, BLACK);
00211             break;
00212         }
00213         case 1: {
00214             char text[13] = {"TIME: XX MIN"};
00215             text[6] = (char)(programTimeSetting/600);
00216             text[7] = (char)((programTimeSetting/60)%10);
00217             uLCD.text_string(text, 4, 6, FONT_7X8, BLACK);
00218             break;
00219         }
00220         case 2: {
00221             //unclear
00222             break;
00223         }
00224         case 3: {
00225             uLCD.text_string("RESTART", 4, 14, FONT_7X8, BLACK);
00226             break;
00227         }
00228     }
00229 }
00230 
00231 void drawMenuSelection(int color) {
00232     uLCD.line(0,32*menuSelectionIndex,128,32*menuSelectionIndex, color);
00233     uLCD.line(0,32*menuSelectionIndex,0,32*menuSelectionIndex+32, color);
00234     uLCD.line(0,32*menuSelectionIndex+32,128,32*menuSelectionIndex+32, color);
00235     uLCD.line(128,32*menuSelectionIndex+32,128,32*menuSelectionIndex, color);
00236 }
00237 
00238 
00239 void drawSelectionBox(int x, int y, int color) {
00240     //draw 4 lines around the box in the color selected
00241     if (x < 0 || x >= 8 || y < 0 || y >= 8) return;
00242     int startX = x*boxWidth + 1;
00243     int endX = (x+1)*boxWidth - 1;
00244     int startY = y*boxWidth + 1;
00245     int endY = (y+1)*boxWidth - 1;
00246     uLCD.line(startX, startY, startX, endY-y/7, color);
00247     uLCD.line(startX, endY-y/7, endX-x/7, endY-y/7, color);
00248     uLCD.line(endX-x/7, endY-y/7, endX-x/7, startY, color);
00249     uLCD.line(endX-x/7, startY, startX, startY, color);
00250 }
00251 
00252 void drawPiece(int x, int y, int piece) {
00253     //draws a piece in a specific box (including NONE, which draws a black rectangle to erase)
00254     uLCD.text_mode(TRANSPARENT);
00255     int textColor = WHITE;
00256     if (color[x][y] == black) textColor = RED;
00257     switch (piece) {
00258         case NONE: {
00259             uLCD.filled_rectangle(x*boxWidth+2, y*boxWidth+2, x*boxWidth+boxWidth-2, y*boxWidth+boxWidth-2, BLACK);
00260             break;
00261         }
00262         case KING: {
00263             //uLCD.text_char('K', x*2.3+1, y*2+1, textColor);
00264             int king[14*14] = {
00265                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00266                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00267                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, 
00268                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00269                 BLACK, BLACK, textColor, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00270                 BLACK, BLACK, textColor, textColor, BLACK, BLACK, textColor, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, 
00271                 textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00272                 textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00273                 BLACK, BLACK, textColor, textColor, BLACK, BLACK, textColor, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, 
00274                 BLACK, BLACK, textColor, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00275                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00276                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, 
00277                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00278                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK
00279             };
00280             uLCD.BLIT(x*boxWidth+1, y*boxWidth+1, boxWidth-2-x/8, boxWidth-2-y/8, king);
00281             break;
00282         }
00283         case QUEEN: {
00284             //uLCD.text_char('Q', x*2.3+1, y*2+1, textColor);
00285             int queen[14*14] = {
00286                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00287                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00288                 BLACK, BLACK, textColor, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, 
00289                 BLACK, BLACK, BLACK, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00290                 BLACK, BLACK, BLACK, textColor, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00291                 BLACK, BLACK, BLACK, textColor, textColor, BLACK, textColor, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, 
00292                 BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00293                 BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00294                 BLACK, BLACK, BLACK, textColor, textColor, BLACK, textColor, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, 
00295                 BLACK, BLACK, BLACK, textColor, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00296                 BLACK, BLACK, BLACK, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00297                 BLACK, BLACK, textColor, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, 
00298                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00299                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK
00300             };
00301             uLCD.BLIT(x*boxWidth+1, y*boxWidth+1, boxWidth-2-x/8, boxWidth-2-y/8, queen);
00302             break;
00303         }
00304         case BISHOP: {
00305             //uLCD.text_char('B', x*2.3+1, y*2+1, textColor);
00306             int bishop[14*14] = {
00307                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00308                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00309                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00310                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, 
00311                 BLACK, BLACK, BLACK, BLACK, BLACK, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00312                 BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, 
00313                 BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00314                 BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00315                 BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, 
00316                 BLACK, BLACK, BLACK, BLACK, BLACK, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00317                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, 
00318                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00319                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00320                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK
00321             };
00322             uLCD.BLIT(x*boxWidth+1, y*boxWidth+1, boxWidth-2-x/8, boxWidth-2-y/8, bishop);
00323             break;
00324         }
00325         case KNIGHT: {
00326             //uLCD.text_char('N', x*2.3+1, y*2+1, textColor);
00327             int knight[14*14] = {
00328                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00329                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00330                 BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, 
00331                 BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, 
00332                 BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00333                 BLACK, BLACK, BLACK, BLACK, textColor, BLACK, textColor, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, 
00334                 BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, 
00335                 BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00336                 BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00337                 BLACK, BLACK, BLACK, textColor, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00338                 BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, BLACK, textColor, textColor, 
00339                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, BLACK, BLACK, BLACK, BLACK, textColor, 
00340                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00341                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK
00342             };
00343             uLCD.BLIT(x*boxWidth+1, y*boxWidth+1, boxWidth-2-x/8, boxWidth-2-y/8, knight);
00344             break;
00345         }
00346         case ROOK: {
00347             //uLCD.text_char('R', x*2.3+1, y*2+1, textColor);
00348             int rook[14*14] = {
00349                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00350                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00351                 BLACK, BLACK, BLACK, textColor, textColor, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, 
00352                 BLACK, BLACK, BLACK, textColor, textColor, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00353                 BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00354                 BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00355                 BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00356                 BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00357                 BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00358                 BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00359                 BLACK, BLACK, BLACK, textColor, textColor, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, 
00360                 BLACK, BLACK, BLACK, textColor, textColor, textColor, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, 
00361                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00362                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK
00363             };
00364             uLCD.BLIT(x*boxWidth+1, y*boxWidth+1, boxWidth-2-x/8, boxWidth-2-y/8, rook);
00365             break;
00366         }
00367         case PAWN: {
00368             //uLCD.text_char('P', x*2.3+1, y*2+1, textColor);
00369             int pawn[14*14] = {
00370                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00371                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00372                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00373                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, 
00374                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, BLACK, BLACK, textColor, textColor, 
00375                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, 
00376                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00377                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, textColor, 
00378                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, textColor, textColor, textColor, textColor, 
00379                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, BLACK, BLACK, textColor, textColor, 
00380                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, textColor, textColor, 
00381                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00382                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, 
00383                 BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK
00384             };
00385             uLCD.BLIT(x*boxWidth+1, y*boxWidth+1, boxWidth-2-x/8, boxWidth-2-y/8, pawn);
00386             break;
00387         }
00388         default:
00389             return;
00390     }
00391 }
00392 
00393 void drawGameBoard() {
00394     uLCD.cls();
00395     for (int i = 0; i < 9; i++) {
00396         uLCD.line(i*boxWidth-i/8, 0, i*boxWidth-i/8, 128, 0xFFFFFF);
00397         uLCD.line(0, i*boxWidth-i/8, 128, i*boxWidth-i/8, 0xFFFFFF);
00398     }
00399     for (int i = 0; i < 8; i++) {
00400         for (int j = 0; j < 8; j++) {
00401             drawPiece(i, j, board[i][j]);
00402         }
00403     }
00404     if (pieceSelected) {
00405         drawSelectionBox(selectedX, selectedY, RED);
00406     }
00407     drawSelectionBox(positionX, positionY, GREEN);
00408 }
00409 
00410 
00411 //MENU FUNCTIONS----------------------------------------------------------------------------------------------------------------------------------
00412 
00413 void closeMenu() {
00414     uLCD.cls();
00415     drawGameBoard();
00416     menuOpen = false;
00417     menuSelectionIndex = 0;
00418 }
00419 
00420 void openMenu() {
00421     uLCD.cls();
00422     for (int i = 0; i < 4; i++) {
00423         drawMenuLine(i);
00424     }
00425     drawMenuSelection(GREEN);
00426     menuOpen = true;
00427 }
00428 
00429 void menuSelectHandler() {
00430     switch (menuSelectionIndex) {
00431         case 0:
00432             playSound = !playSound;
00433             break;
00434         case 1:
00435             switch (programTimeSetting) {
00436                 case 300:
00437                     programTimeSetting = 600;
00438                     break;
00439                 case 600:
00440                     programTimeSetting = 900;
00441                     break;
00442                 case 900:
00443                     programTimeSetting = 1200;
00444                     break;
00445                 case 1200:
00446                     programTimeSetting = 1800;
00447                     break;
00448                 case 1800:
00449                     programTimeSetting = 3600;
00450                     break;
00451                 case 3600:
00452                     programTimeSetting = 300;
00453                     break;
00454                 default:
00455                     programTimeSetting = 600;
00456                     break;
00457             }
00458             break;
00459         case 2:
00460             //unclear
00461         case 3:
00462             initialize();
00463             return;
00464         default:
00465             break;
00466     }
00467     drawMenuLine(menuSelectionIndex);
00468 }
00469 
00470 void moveMenuSelection(int direction) {
00471     if (direction == RIGHT || direction == LEFT) return;
00472     drawMenuSelection(BLACK);
00473     if (direction == FORWARD) {
00474         menuSelectionIndex++;
00475         if (menuSelectionIndex > 3) menuSelectionIndex = 0;
00476     }
00477     if (direction == BACKWARD) {
00478         menuSelectionIndex--;
00479         if (menuSelectionIndex < 0) menuSelectionIndex = 3;
00480     }
00481     drawMenuSelection(GREEN);
00482 }
00483 
00484 void menuHandler() {
00485     int move = waitForInput();
00486     if (move == MENU) {
00487         closeMenu();
00488         return;
00489     }
00490     if (move == SELECT) {
00491         menuSelectHandler();
00492         return;
00493     }
00494     moveMenuSelection(move);
00495 }
00496 
00497 //GAME FUNCTIONS----------------------------------------------------------------------------------------------------------------------------------
00498 
00499 void removeSelectionBox() {
00500     switch (currentPiece) {
00501         case KING:
00502             for (int i = selectedX - 1; i <= selectedX + 1; i++) {
00503                 for (int j = selectedY - 1; j <= selectedY + 1; j++) {
00504                     drawSelectionBox(i, j, BLACK);
00505                 }
00506             }
00507             break;
00508         case QUEEN:
00509             for (int i = 0; i < 8; i++) {
00510                 drawSelectionBox(selectedX, i, BLACK);
00511                 drawSelectionBox(i, selectedY, BLACK);
00512                 drawSelectionBox(selectedX + i, selectedY + i, BLACK);
00513                 drawSelectionBox(selectedX - i, selectedY - i, BLACK);
00514             }
00515             break;
00516         case BISHOP:
00517             for (int i = 0; i < 8; i++) {
00518                 drawSelectionBox(selectedX + i, selectedY + i, BLACK); 
00519                 drawSelectionBox(selectedX - i, selectedY - i, BLACK); 
00520             }
00521             break;
00522         case KNIGHT:
00523             drawSelectionBox(selectedX, selectedY, BLACK);
00524             drawSelectionBox(selectedX + 2, selectedY + 1, BLACK);
00525             drawSelectionBox(selectedX + 1, selectedY + 2, BLACK);
00526             drawSelectionBox(selectedX - 2, selectedY + 1, BLACK);
00527             drawSelectionBox(selectedX - 1, selectedY + 2, BLACK);
00528             drawSelectionBox(selectedX + 2, selectedY - 1, BLACK);
00529             drawSelectionBox(selectedX + 1, selectedY - 2, BLACK);
00530             drawSelectionBox(selectedX - 2, selectedY - 1, BLACK);
00531             drawSelectionBox(selectedX - 1, selectedY - 2, BLACK);
00532             break;
00533         case ROOK:
00534             for (int i = 0; i < 8; i++) {
00535                 drawSelectionBox(selectedX, i, BLACK);
00536                 drawSelectionBox(i, selectedY, BLACK);
00537             }
00538             break;
00539         case PAWN:
00540             drawSelectionBox(selectedX, selectedY, BLACK);
00541             drawSelectionBox(selectedX, selectedY + 1, BLACK);
00542             drawSelectionBox(selectedX, selectedY + 2, BLACK);
00543             drawSelectionBox(selectedX + 1, selectedY + 1, BLACK);
00544             drawSelectionBox(selectedX - 1, selectedY + 1, BLACK);
00545             break;
00546     }
00547     drawSelectionBox(positionX, positionY, GREEN);
00548 }
00549 
00550 int waitForInput() {
00551     //main loop which waits for input while in game
00552     float calx = 0.0;  // joystick hysteresis calibration (optional)
00553     float caly = 0.0;
00554     while (true) {
00555         if (JoyY > (0.6+caly)) {
00556             while (JoyY > (0.6+caly)) { Thread::wait(10); }
00557             return FORWARD;
00558         }
00559         if (JoyY < (0.4+caly)) {
00560             while (JoyY < (0.4+caly)) { Thread::wait(10); }
00561             return BACKWARD;
00562         }
00563         if (JoyX > (0.6+calx)) {
00564             while (JoyX > (0.6+calx)) { Thread::wait(10); }
00565             return RIGHT;
00566         }
00567         if (JoyX < (0.4+calx)) {
00568             while (JoyX < (0.4+calx)) { Thread::wait(10); }
00569             return LEFT;
00570         }
00571         if (!Select) {
00572             while (!Select) { Thread::wait(10); }
00573             return SELECT;
00574         }
00575         if (!Menu) {
00576             while (!Menu) { Thread::wait(10); }
00577             return MENU;
00578         }
00579         Thread::wait(10);
00580     }
00581 }
00582 
00583 void displayPossibleMoves() {
00584     //highlights squares where a selected piece can move
00585     //use a for loop to iterate over all possible positions (diagonals, lines, etc.)
00586         //if piece is already and not opposite team don't highlight
00587         //make sure not to highlight edge conditions (off board)
00588     /*switch (currentPiece) {
00589         case NONE:
00590             //return false;
00591         case KING:
00592             //make sure it's opposite player's team or none
00593             //check for castling (queenside and short)
00594             for (int i = positionX - 1; i <= positionX + 1; i++) {
00595                 for (int j = positionY - 1; j <= positionY + 1; j++) {
00596                     //if (checkValidMove(KING, i, j)) {
00597                     //    drawSelectionBox(i, j, YELLOW);
00598                     //}
00599                 }
00600             }
00601             if (board[positionX][positionY] == NONE)
00602                 //return true;
00603             if (color[positionX][positionY] != currentPlayer)
00604                 //return true;
00605             //return false;
00606         case QUEEN:
00607             //check it's on the lines
00608             //check it's on diagonal
00609             //make sure no pieces are in the way
00610             //return false;
00611         case BISHOP:
00612             //check it's on diagonals
00613             //make sure no pieces are in the way
00614             //return false;
00615         case KNIGHT:
00616             //check that it's knight position
00617             //make sure it's opposite player's team or none
00618             //return false;
00619         case ROOK:
00620             //check it's on the lines
00621             //make sure no pieces are in the way
00622             //return false;
00623         case PAWN:
00624             //check en passant
00625             //check no pieces in way
00626             //check for take on diagonal
00627             //return false;
00628         default:
00629             //return false;
00630     }*/
00631 }
00632 
00633 void showGameEnd() {
00634     //shows the end of the game
00635     uLCD.cls();
00636 }
00637 
00638 bool checkValidMove(int x, int y) {
00639     if (board[x][y] != NONE && color[x][y] == currentPlayer) return false;  //handles moving onto own piece (and same space)
00640     switch (currentPiece) {
00641         case NONE:
00642             return false;
00643         case KING:
00644             //make sure it's opposite player's team or none
00645             //check for castling (queenside and short)
00646             if (abs(x-selectedX) <= 1 && abs(y-selectedY) <= 1) {
00647                 if (board[x][y] == NONE || color[x][y] != currentPlayer) {
00648                     return true;
00649                 }
00650             }
00651             return false;
00652         case QUEEN:
00653             //check it's on the lines
00654             //check it's on diagonal
00655             //make sure no pieces are in the way
00656             if (x == selectedX) {
00657                 //check y direction in a line
00658                 if (selectedY < y) {
00659                     //if position is forward
00660                     for (int i = selectedY; i < y; i++) {
00661                         if (board[selectedX][i] != NONE) return false;
00662                     }
00663                 }
00664                 else {
00665                     //if position is backward
00666                     for (int i = selectedY; i > y; i--) {
00667                         if (board[selectedX][i] != NONE) return false;
00668                     }
00669                 } 
00670                 return true;
00671             }
00672             else if (y == selectedY) {
00673                 //check x direction in a line
00674                 if (selectedX < x) {
00675                     //if position is forward
00676                     for (int i = selectedX; i < x; i++) {
00677                         if (board[i][selectedY] != NONE) return false;
00678                     }
00679                 }
00680                 else {
00681                     //if position is backward
00682                     for (int i = selectedX; i > x; i--) {
00683                         if (board[i][selectedY] != NONE) return false;
00684                     }
00685                 }
00686                 return true;
00687             }
00688             else if (abs(x - selectedX) == abs(y - selectedY)) {
00689                 //check diagonals
00690                 if (selectedX < x) {
00691                     if (selectedY < y) {
00692                         for (int i = 1; i < x - selectedX; i++) {
00693                             if (board[selectedX + i][selectedY + i] != NONE) return false;
00694                         }
00695                     }
00696                     else {
00697                         for (int i = 1; i < x - selectedX; i++) {
00698                             if (board[selectedX + i][selectedY - i] != NONE) return false;
00699                         }
00700                     }
00701                 }
00702                 if (selectedX > x) {
00703                     if (selectedY < y) {
00704                         for (int i = 1; i < selectedX - x; i++) {
00705                             if (board[selectedX - i][selectedY + i] != NONE) return false;
00706                         }
00707                     }
00708                     else {
00709                         for (int i = 1; i < selectedX - x; i++) {
00710                             if (board[selectedX - i][selectedY - i] != NONE) return false;
00711                         }
00712                     }
00713                 }
00714                 return true;
00715             }
00716             else {
00717                 return true;
00718             }
00719         case BISHOP:
00720             //check it's on diagonals
00721             //make sure no pieces are in the way
00722             if (abs(x - selectedX) == abs(y - selectedY)) {
00723                 //check diagonals
00724                 if (selectedX < x) {
00725                     if (selectedY < y) {
00726                         for (int i = 1; i < x - selectedX; i++) {
00727                             if (board[selectedX + i][selectedY + i] != NONE) return false;
00728                         }
00729                     }
00730                     else {
00731                         for (int i = 1; i < x - selectedX; i++) {
00732                             if (board[selectedX + i][selectedY - i] != NONE) return false;
00733                         }
00734                     }
00735                 }
00736                 if (selectedX > x) {
00737                     if (selectedY < y) {
00738                         for (int i = 1; i < selectedX - x; i++) {
00739                             if (board[selectedX - i][selectedY + i] != NONE) return false;
00740                         }
00741                     }
00742                     else {
00743                         for (int i = 1; i < selectedX - x; i++) {
00744                             if (board[selectedX - i][selectedY - i] != NONE) return false;
00745                         }
00746                     }
00747                 }
00748                 return true;
00749             }
00750             else {
00751                 return false;
00752             }
00753         case KNIGHT:
00754             //check that it's knight position
00755             //make sure it's opposite player's team or none
00756             if (abs(y - selectedY) == 2) {
00757                 if (abs(x - selectedX) == 1) {
00758                     return true;
00759                 }
00760             }
00761             else if (abs(y - selectedY) == 1) {
00762                 if (abs(x - selectedX) == 2) {
00763                     return true;
00764                 }
00765             }
00766             return false;
00767         case ROOK:
00768             //check it's on the lines
00769             //make sure no pieces are in the way
00770             if (x == selectedX) {
00771                 //check y direction in a line
00772                 if (selectedY < y) {
00773                     //if position is forward
00774                     for (int i = selectedY; i < y; i++) {
00775                         if (board[selectedX][i] != NONE) return false;
00776                     }
00777                 }
00778                 else {
00779                     //if position is backward
00780                     for (int i = selectedY; i > y; i--) {
00781                         if (board[selectedX][i] != NONE) return false;
00782                     }
00783                 }
00784                 return true;
00785             }
00786             else if (y == selectedY) {
00787                 //check x direction in a line
00788                 if (selectedX < x) {
00789                     //if position is forward
00790                     for (int i = selectedX; i < x; i++) {
00791                         if (board[i][selectedY] != NONE) return false;
00792                     }
00793                 }
00794                 else {
00795                     //if position is backward
00796                     for (int i = selectedX; i > x; i--) {
00797                         if (board[i][selectedY] != NONE) return false;
00798                     }
00799                 }
00800                 return true;
00801             }
00802             else {
00803                 return false;
00804             }
00805         case PAWN:
00806             //check en passant
00807             //check no pieces in way
00808             //check for take on diagonal
00809             //check for 2 moves on first row
00810             if (currentPlayer == white && y <= selectedY) return false;
00811             if (currentPlayer == black && y >= selectedY) return false;
00812             if (x != selectedX) {
00813                 if (abs(x - selectedX) != 1) return false;  //must be one diagonal space away
00814                 if (abs(y - selectedY) != 1) return false; 
00815                 if (board[x][y] == NONE) return false;  //must be taking a piece
00816                 return true;
00817             }
00818             else {
00819                 if (currentPlayer == white) {
00820                     if (selectedY == 1) {
00821                         if (y == 2 && board[x][y] == NONE) return true;
00822                         else if (y == 3 && board[x][y] == NONE && board[x][y - 1] == NONE) return true;
00823                         else return false;
00824                     }
00825                     else {
00826                         if (y == selectedY + 1) {
00827                             if (board[x][y] == NONE) {
00828                                 return true;
00829                             }
00830                         }
00831                         return false;
00832                     }
00833                 }
00834                 else {
00835                     if (selectedY == 6) {
00836                         if (y == 5 && board[x][y] == NONE) return true;
00837                         else if (y == 4 && board[x][y] == NONE && board[x][y + 1] == NONE) return true;
00838                         else return false;
00839                     }
00840                     else {
00841                         if (y == selectedY - 1) {
00842                             if (board[x][y] == NONE) {
00843                                 return true;
00844                             }
00845                         }
00846                         return false;
00847                     }
00848                 }
00849             }
00850         default:
00851             return false;
00852     }
00853 }
00854 
00855 void movePiece() {
00856     //new position is viable, update location and change current player
00857     if (!gameActive) gameActive = true;
00858     if (board[positionX][positionY] == KING) {
00859         showGameEnd();
00860         return;
00861     }
00862     removeSelectionBox();
00863     drawPiece(selectedX, selectedY, NONE);
00864     board[positionX][positionY] = board[selectedX][selectedY];
00865     color[positionX][positionY] = currentPlayer;
00866     board[selectedX][selectedY] = NONE;
00867     drawPiece(positionX, positionY, board[positionX][positionY]);
00868     pieceSelected = false;
00869     if (currentPlayer == white) {
00870         timerWhite.stop();
00871         timerBlack.start();
00872     }
00873     if (currentPlayer == black) {
00874         timerBlack.stop();
00875         timerWhite.start();
00876     }
00877     if (playSound) speakerOut.PlayNote(2000, .1, .25);
00878     currentPlayer = !currentPlayer;
00879 }
00880 
00881 void moveSelectionBox(int direction) {
00882     if (direction == NONE) {
00883         drawSelectionBox(positionX, positionY, GREEN);
00884         return;
00885     }
00886     if (direction == FORWARD && positionY == 7) return;
00887     if (direction == BACKWARD && positionY == 0) return;
00888     if (direction == RIGHT && positionX == 7) return;
00889     if (direction == LEFT && positionX == 0) return;
00890     if (pieceSelected && positionX == selectedX && positionY == selectedY) {
00891         drawSelectionBox(positionX, positionY, RED);
00892     }
00893     else {
00894         drawSelectionBox(positionX, positionY, BLACK);
00895     }
00896     if (direction == FORWARD) {
00897         positionY++;
00898     }
00899     if (direction == BACKWARD) {
00900         positionY--;
00901     }
00902     if (direction == RIGHT) {
00903         positionX++;
00904     }
00905     if (direction == LEFT) {
00906         positionX--;
00907     }
00908     if (playSound) speakerOut.PlayNote(500, .1, .25);
00909     drawSelectionBox(positionX, positionY, GREEN);
00910 }
00911 
00912 bool checkValidSelection() {
00913     if (board[positionX][positionY] != NONE) {
00914         if (color[positionX][positionY] == currentPlayer) {
00915             return true;
00916         }
00917     }
00918     return false;
00919 }
00920 
00921 void selectPiece() {
00922     selectedX = positionX;
00923     selectedY = positionY;
00924     pieceSelected = true;
00925     currentPiece = board[positionX][positionY];
00926     displayPossibleMoves();
00927 }
00928 
00929 void deselectPiece() {
00930     pieceSelected = false;
00931     currentPiece = NONE;
00932     removeSelectionBox();
00933     moveSelectionBox(NONE);
00934 }
00935 
00936 void selectHandler() {
00937     if (pieceSelected) {
00938         if (positionX == selectedX && positionY == selectedY) {
00939             deselectPiece();
00940         }
00941         if (checkValidMove(positionX, positionY)) {
00942             movePiece();
00943         }
00944     }
00945     else {
00946         if (checkValidSelection()) {
00947             selectPiece();
00948         }
00949     }
00950 }
00951 
00952 void gameHandler() {
00953     if (menuOpen) return;
00954     int move = waitForInput();
00955     switch (move) {
00956         case MENU:
00957             openMenu();
00958             return;
00959         case SELECT:
00960             selectHandler();
00961             break;
00962         default:
00963             moveSelectionBox(move);
00964             break;
00965     }
00966 }
00967 
00968 //MAIN----------------------------------------------------------------------------------------------------------------------------------
00969 
00970 int main() {
00971     
00972     initialize();
00973     
00974     Thread timerThread(timer);
00975     
00976     while (true) {
00977         if (menuOpen) menuHandler();
00978         else gameHandler();
00979     }
00980  
00981 }