Chess game on the mbed.

Dependencies:   4DGL-uLCD-SE PinDetect SDFileSystem mbed

Revision:
0:a5f9535b6e3d
Child:
1:af3a896cd76d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Mar 14 02:45:47 2016 +0000
@@ -0,0 +1,618 @@
+#include "mbed.h"
+#include "uLCD_4DGL.h"
+#include "SDFileSystem.h"
+#include <algorithm>
+#include "PinDetect.h"
+#include "Speaker.h"
+
+
+uLCD_4DGL uLCD(p28,p27,p29); // serial tx, serial rx, reset pin;
+
+//need bluetooth https://developer.mbed.org/users/4180_1/notebook/adafruit-bluefruit-le-uart-friend---bluetooth-low-/
+Serial blue(p13,p14); //serial tx, rx
+
+
+//joystick - declare pins and then have interrupt functions for each one
+
+//speaker - declare pins, may want to use it as pwm out instead of wav? 
+Speaker mySpeaker(p21);
+
+//sd card - to hold the video file
+//SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card setup
+
+int board[8][8]={0};
+int current_player = 1;
+//pieces
+const int pawn=1;
+const int rook=2;
+const int knight=3;
+const int bishop=4;
+const int queen=5;
+const int king=6;
+
+int winner = 0;
+
+
+class Nav_Switch
+{
+public:
+    Nav_Switch(PinName up,PinName down,PinName left,PinName right,PinName fire);
+    int read();
+//boolean functions to test each switch
+    bool up();
+    bool down();
+    bool left();
+    bool right();
+    bool fire();
+//automatic read on RHS
+    operator int ();
+//index to any switch array style
+    bool operator[](int index) {
+        return _pins[index];
+    };
+private:
+    BusIn _pins;
+ 
+};
+Nav_Switch::Nav_Switch (PinName up,PinName down,PinName left,PinName right,PinName fire):
+    _pins(up, down, left, right, fire)
+{
+    _pins.mode(PullUp); //needed if pullups not on board or a bare nav switch is used - delete otherwise
+    wait(0.001); //delays just a bit for pullups to pull inputs high
+}
+inline bool Nav_Switch::up()
+{
+    return !(_pins[0]);
+}
+inline bool Nav_Switch::down()
+{
+    return !(_pins[1]);
+}
+inline bool Nav_Switch::left()
+{
+    return !(_pins[2]);
+}
+inline bool Nav_Switch::right()
+{
+    return !(_pins[3]);
+}
+inline bool Nav_Switch::fire()
+{
+    return !(_pins[4]);
+}
+inline int Nav_Switch::read()
+{
+    return _pins.read();
+}
+inline Nav_Switch::operator int ()
+{
+    return _pins.read();
+}
+ 
+Nav_Switch p1( p9, p6, p7, p5, p8); //pin order on Sparkfun breakout
+DigitalOut myLed1(LED1);
+DigitalOut myLed2(LED2);
+DigitalOut myLed3(LED3);
+DigitalOut myLed4(LED4);
+
+//I guess these need a color arguement too
+
+void drawPawn(int x, int y, int Color) {
+    uLCD.filled_circle(x*16+8,y*16+5,2,Color);
+    uLCD.triangle(x*16+8,y*16+5,x*16+4,y*16+12,x*16+12,y*16+12,Color);    
+}
+void drawQueen(int x, int y, int Color) {
+    uLCD.filled_rectangle(x*16+4,y*16+6, x*16+12, y*16+12, Color);
+    uLCD.triangle(x*16+4,y*16+6,x*16+4,y*16+2,x*16+7,y*16+6,Color);
+    uLCD.triangle(x*16+7,y*16+6,x*16+8.5,y*16+2,x*16+10,y*16+6,Color);
+    uLCD.triangle(x*16+10,y*16+6,x*16+12,y*16+6,x*16+12,y*16+2,Color);
+}
+void drawKing(int x,int y, int Color) {
+    uLCD.filled_rectangle(x*16+7,y*16+2,x*16+9,y*16+12,Color);
+    uLCD.filled_rectangle(x*16+4,y*16+6,x*16+12,y*16+8,Color);    
+}
+void drawKnight(int x, int y, int Color) {
+    //uLCD.filled_rectangle(x+3, y+2, x+8,y+4, RED);
+    uLCD.triangle(x*16+8,y*16+2,x*16+4,y*16+4,x*16+8,y*16+4,Color);
+    uLCD.filled_rectangle(x*16+7, y*16+2, x*16+9, y*16+10, Color);
+    uLCD.filled_rectangle(x*16+4, y*16+10, x*16+12, y*16+ 12, Color);
+}
+
+void drawRook(int x, int y, int Color) {
+    uLCD.filled_rectangle(x*16+2, y*16+4, x*16+ 14, y*16+6,Color);
+    uLCD.filled_rectangle(x*16+5, y*16+6, x*16+11, y*16+12, Color);
+    uLCD.filled_rectangle(x*16+2, y*16+12, x*16+14,y*16+14,Color);
+    uLCD.filled_rectangle(x*16+3, y*16+2, x*16+5, y*16+4,Color);
+    uLCD.filled_rectangle(x*16+7, y*16+2, x*16+9, y*16+4,Color);
+    uLCD.filled_rectangle(x*16+11, y*16+2,x*16+13,y*16+4,Color);
+}
+void drawBishop(int x, int y, int Color) {
+    uLCD.filled_rectangle(x*16+4,y*16+10, x*16+12, y*16+12,Color);
+    uLCD.filled_rectangle(x*16+7, y*16+4,x*16+9,y*16+10,Color);
+    uLCD.triangle(x*16+5,y*16+4,x*16+11,y*16+4,x*16+8,y*16,Color);    
+}
+void display_board(void)
+{
+    //uLCD.filled_rectangle(0, 0 , 127, 127, 0xefded1) ;
+    bool alternator = true;
+    for(int i=0; i<8; i++)//This loop will be executed for each row once
+    {
+        for(int j=0; j<8; j++) //This loop will be executed 7 times for each row
+        {
+            if (alternator) {
+                uLCD.filled_rectangle(j*16,i*16,(j*16)+16,(i*16)+16, 0xbcb6b8);
+                alternator = false;
+            } else {
+                uLCD.filled_rectangle(j*16,i*16,(j*16)+16,(i*16)+16, 0x645659);
+                alternator = true;
+            }
+        }
+        alternator = !alternator;
+    }
+    
+    //pawns
+    for(int i=0;i<8;i++)
+    {
+        drawPawn(i,1,BLACK);
+        board[i][1]= -pawn;
+        drawPawn(i,6,WHITE);
+        board[i][6]= pawn;
+    }
+    
+    drawRook(0,0,BLACK);
+    drawRook(7,0,BLACK);
+    board[0][0]=-rook;
+    board[7][0]=-rook;
+    
+    drawRook(0,7,WHITE);
+    drawRook(7,7,WHITE);
+    board[0][7]=rook;
+    board[7][7]=rook;
+  
+    drawKnight(1,0,BLACK);
+    drawKnight(6,0,BLACK);
+    board[1][0]=-knight;
+    board[6][0]=-knight;
+    
+    drawKnight(1,7,WHITE);
+    drawKnight(6,7,WHITE);
+    board[1][7]=knight;
+    board[6][7]=knight;
+    
+    drawBishop(2,0,BLACK);
+    drawBishop(5,0,BLACK);
+    board[2][0]=-bishop;
+    board[5][0]=-bishop;
+    
+    drawBishop(2,7,WHITE);
+    drawBishop(5,7,WHITE);
+    board[2][7]=bishop;
+    board[5][7]=bishop;
+    
+    drawQueen(3,0,BLACK);
+    board[3][0]=-queen;
+    
+    drawQueen(3,7,WHITE);
+    board[3][7]=queen;
+    
+    drawKing(4,0,BLACK);
+    board[4][0]=-king;
+    
+    drawKing(4,7,WHITE);
+    board[4][7]=king;    
+}
+//take in a piece coordinate and move it to the new spot
+void movePiece(int ox, int oy, int dx, int dy, int player) {
+
+    if(board[dx][dy] !=0) {
+        if( (dx+dy)%2==0) { //moving to a white square
+            uLCD.filled_rectangle(dx*16,dy*16,(dx*16)+16,(dy*16)+16, 0xbcb6b8);
+
+        }
+        else { //dark square
+            uLCD.filled_rectangle(dx*16,dy*16,(dx*16)+16,(dy*16)+16, 0x645659);
+        }
+    }
+
+    //blank out the old square
+    if( (ox+oy)%2==0) { //moving from a white square
+        uLCD.filled_rectangle(ox*16,oy*16,(ox*16)+16,(oy*16)+16, 0xbcb6b8);
+
+    }
+    else { //dark square
+        uLCD.filled_rectangle(ox*16,oy*16,(ox*16)+16,(oy*16)+16, 0x645659);
+    }   
+    
+    //draw piece in the new square
+    switch (abs(board[ox][oy])) {
+        case pawn:
+            drawPawn(dx,dy,player);
+        break;
+
+        case rook:
+            drawRook(dx,dy,player);
+       
+        break;    
+        
+        case knight:
+            drawKnight(dx,dy,player);
+        break; 
+        
+        case bishop:
+            drawBishop(dx,dy,player);
+        break;
+        
+        case queen:
+            drawQueen(dx,dy,player);
+        break; 
+        
+        case king:
+            drawKing(dx,dy,player);
+        break;         
+    }
+    if(board[dx][dy] !=0)
+    {
+        mySpeaker.PlayNote(500.0,0.1,0.05);
+        mySpeaker.PlayNote(700.0,0.1,0.05);
+    }
+    else
+        mySpeaker.PlayNote(600.0,0.1,0.05);
+
+ 
+    if(board[dx][dy] == 6)
+        winner = 2;
+    else if(board[dx][dy] == -6)
+        winner=1;
+    board[dx][dy] = board[ox][oy];
+    board[ox][oy] = 0;
+}
+
+
+//should look at what piece is in old spot, redraw the square there and then draw piece in new spot
+int validMove(int ox, int oy, int dx, int dy){
+  int source = board[ox][oy];
+  int target = board[dx][dy];
+  int typePiece = abs(source);
+  if (board[ox][oy] > 0 && board[dx][dy]>0 || board[ox][oy] < 0 && board[dx][dy]<0)
+    return 0;
+  if (typePiece == pawn){
+    if(current_player == 2 && dx==ox && dy-oy==1 && target==0) return 1;
+    if(current_player == 1 && dx==ox && dy-oy==-1 && target==0) return 1;
+    if(abs(dx-ox)==1 && current_player == 2 && dy-oy==1 && target > 0) return 1;
+    if(abs(dx-ox)==1 && current_player == 1 && dy-oy==-1 && target < 0) return 1;
+    if(current_player == 2 && oy==1 && (abs(ox-dx)==0) && abs(oy-dy)==2 && target == 0) return 1;
+    if(current_player == 1 && oy==6 && (abs(ox-dx)==0) &&(abs(oy-dy)==2) && target == 0) return 1;
+    
+  } else if (typePiece == rook) {
+    if(dx==ox){ // Moving vertically
+      if(dy>oy){ // Downards
+        for(size_t row = (unsigned)(oy+1); row < (unsigned)dy; ++row){
+          if(board[dx][row] != 0) return 0;
+        }
+      } else { // Upwards
+        for(size_t row = (unsigned)dy+1; row < (unsigned)(oy); ++row){
+          if(board[dx][row] != 0) return 0;
+        }
+      }
+      return 1;
+    }
+    if(dy==oy){ // Moving horizontally
+      if(dx>ox){ // Rightwards
+        for(size_t column = (unsigned)(ox+1); column < (unsigned)dx; ++column){
+          if(board[column][dy] != 0) return 0;
+        }
+      }
+      if(dx<ox){ // Leftwards
+        for(size_t column = (unsigned)dx+1; column < (unsigned)(ox); ++column){
+          if(board[column][dy] != 0) return 0;
+        }
+      }
+      return 1;
+    }
+    return 0;
+    } else if (typePiece == knight) {
+ 
+        if((abs(dy-oy)==2 && abs(dx-ox)==1) || (abs(dx-ox)==2 && abs(dy-oy)==1)){
+          return 1;
+        }
+        return 0;
+    } else if (typePiece ==bishop) {
+    // Bishop
+        if (abs(dx-ox) != abs(dy-oy))
+            return 0;
+    
+        int ymult = -1;
+        int xmult = -1;
+        if (dx>ox)
+            xmult = 1;
+        if (dy>oy)
+            ymult = 1;
+   
+        for(int i=1; i < abs(dx-ox); ++i)
+        {
+            if(board[ox + i*xmult][oy+i*ymult] != 0) return 0;
+        }
+        return 1;
+
+    } else if (typePiece ==queen) {
+ 
+    // Queen
+    if(abs(dx-ox) == abs(dy-oy)) {
+        int ymult = -1;
+        int xmult = -1;
+        if (dx>ox)
+            xmult = 1;
+        if (dy>oy)
+            ymult = 1;
+   
+        for(int i=1; i < abs(dx-ox); ++i)
+        {
+            if(board[ox + i*xmult][oy+i*ymult] != 0) return 0;
+        }
+        return 1;             
+        
+    }
+
+    if(dx==ox){ // Moving vertically
+      if(dy>oy){ // Downards
+        for(size_t row = (unsigned)(oy+1); row < (unsigned)dy; ++row){
+          if(board[dx][row] != 0) return 0;
+        }
+      } else { // Upwards
+        for(size_t row = (unsigned)dy+1; row < (unsigned)(oy); ++row){
+          if(board[dx][row] != 0) return 0;
+        }
+      }
+      return 1;
+    }
+    if(dy==oy){ // Moving horizontally
+      if(dx>ox){ // Rightwards
+        for(size_t column = (unsigned)(ox+1); column < (unsigned)dx; ++column){
+          if(board[column][dy] != 0) return 0;
+        }
+      }
+      if(dx<ox){ // Leftwards
+        for(size_t column = (unsigned)dx+1; column < (unsigned)(ox); ++column){
+          if(board[column][dy] != 0) return 0;
+        }
+      }
+      return 1;
+    }
+    return 0;
+    
+    } else if (typePiece ==king) {
+    if(abs(dy-oy)<=1 && abs(dx-ox)<=1) return 1;
+    return 0;
+    }
+  
+  return 0;
+}
+ 
+
+PinDetect up(p26);
+PinDetect center(p25);
+PinDetect left(p24);
+PinDetect down(p23);
+PinDetect right(p22);
+
+volatile int x = 4;
+volatile int y = 6;
+volatile int x2 = 4;
+volatile int y2 = 2;
+volatile bool center_hit = false;
+void up_hit_callback(void) {
+    --y;
+    if(y<0)
+        y=7;
+    }  
+void down_hit_callback(void) {
+    y = (y+1)%8;
+    }
+void left_hit_callback(void) {
+    --x;
+    if(x<0)
+        x=7;
+    }
+void right_hit_callback(void) {
+    x = (x+1)%8;
+    }
+void center_hit_callback(void) {
+    center_hit = true;
+    }
+
+
+
+int main() {
+       
+       center.attach_deasserted(&center_hit_callback);
+       left.attach_deasserted(&left_hit_callback);
+       right.attach_deasserted(&right_hit_callback);
+       up.attach_deasserted(&up_hit_callback);
+       down.attach_deasserted(&down_hit_callback);
+    
+       center.setSampleFrequency();
+       left.setSampleFrequency();
+       right.setSampleFrequency();
+       down.setSampleFrequency();
+       up.setSampleFrequency();
+
+       
+       display_board();
+       int oldx = 4;
+       int oldx2 = 4;
+       int oldy = 6;
+       int oldy2 = 1;
+       int selectedx;
+       int selectedy;
+       bool selected=false;
+       int selectedx2;
+       int selectedy2;
+       bool selected2 = false;
+       uLCD.rectangle(oldx*16,oldy*16,(oldx*16)+16,(oldy*16)+16, GREEN);
+    
+        while(1) {
+            while(current_player==1) {
+                //put a border around selected square
+                myLed4 = 0;
+                myLed1 = selected; 
+                if(x != oldx || y != oldy) {
+                    mySpeaker.PlayNote(969.0,0.05,0.05);
+                    if(oldx % 2 == oldy %2)
+                        uLCD.rectangle(oldx*16,oldy*16,(oldx*16)+16,(oldy*16)+16, 0xbcb6b8); 
+                    else
+                        uLCD.rectangle(oldx*16,oldy*16,(oldx*16)+16,(oldy*16)+16, 0x645659); 
+                    
+                    uLCD.rectangle(x*16,y*16,(x*16)+16,(y*16)+16, GREEN);
+                    oldx = x;
+                    oldy = y;  
+                }
+                    
+                if (center_hit) {
+                    if(board[oldx][oldy] > 0 || selected)
+                    {
+                       if(selected) {
+                        //check move, make move and change turn if valid
+                            if(selectedx == oldx && selectedy==oldy) { //deselect piece by clicking on it again
+                                selected = false;
+                            }
+                            else {
+                                if(validMove(selectedx, selectedy, oldx, oldy) ==1) {
+                                    movePiece(selectedx, selectedy, oldx, oldy, WHITE); 
+                                    selected = false;
+                                    current_player = 2;
+                                    if(oldx % 2 == oldy %2)
+                                        uLCD.rectangle(oldx*16,oldy*16,(oldx*16)+16,(oldy*16)+16, 0xbcb6b8); 
+                                    else
+                                        uLCD.rectangle(oldx*16,oldy*16,(oldx*16)+16,(oldy*16)+16, 0x645659); 
+                                    
+                                    uLCD.rectangle(oldx2*16,oldy2*16,(oldx2*16)+16,(oldy2*16)+16, BLUE);
+                                }
+                            }
+                        }
+                        else
+                        {
+                            selected = true;
+                            selectedx =  oldx;
+                            selectedy = oldy;
+                        }
+                           
+                    }    
+                    center_hit =false;
+                }    
+                
+            }
+            while(current_player==2 && winner!=1)
+            {
+                myLed4 = 1; 
+                char bnum=0;
+                char bhit=0;
+                myLed1 = selected2; 
+
+                bool one_hit = false; 
+                if (blue.getc()=='!') {
+                    if (blue.getc()=='B') { //button data packet
+                        bnum = blue.getc(); //button number
+                        bhit = blue.getc(); //1=hit, 0=release
+                        if (blue.getc()==char(~('!' + 'B' + bnum + bhit))) { //checksum OK?
+                            switch (bnum) {
+                                case '1': //number button 1
+                                    if (bhit=='1') {
+                                        one_hit = true; 
+                                    } 
+                                break;
+                                case '5': //button 5 up arrow
+                                    if (bhit=='1') {
+                                       //y2 = (y2-1)%8;
+                                        --y2;
+                                        if(y2<0)
+                                            y2=7;
+                                    }
+                                break;
+                                case '6': //button 6 down arrow
+                                    if (bhit=='1') {
+                                        y2 = (y2+1)%8;
+                                    } 
+                                break;
+                                case '7': //button 7 left arrow
+                                    if (bhit=='1') {
+                                        //x2 = (x2-1)%8;
+                                        --x2;
+                                        if(x2<0)
+                                            x2=7;
+                                    } 
+                                break;
+                                case '8': //button 8 right arrow
+                                    if (bhit=='1') {
+                                        x2 = (x2+1)%8;
+                                    } 
+                                break;
+
+                            }
+
+                                   
+                if(x2 != oldx2 || y2 != oldy2)
+                {
+                    mySpeaker.PlayNote(800.0,0.05,0.05);
+                    if(oldx % 2 == oldy2 %2)
+                        uLCD.rectangle(oldx2*16,oldy2*16,(oldx2*16)+16,(oldy2*16)+16, 0xbcb6b8); 
+                    else
+                        uLCD.rectangle(oldx2*16,oldy2*16,(oldx2*16)+16,(oldy2*16)+16, 0x645659); 
+                    
+                    uLCD.rectangle(x2*16,y2*16,(x2*16)+16,(y2*16)+16, BLUE);
+                    oldx2 = x2;
+                    oldy2 = y2;  
+                }
+                    
+                    if (one_hit) {
+                        if(board[oldx2][oldy2] < 0 || selected2) {
+                            if(selected2) {
+                                //check move, make move and change turn if valid
+                                if(selectedx2 == oldx2 && selectedy2 == oldy2) {
+                                    selected2 = false; 
+                                }
+                                else {
+                                    if(validMove(selectedx2, selectedy2, oldx2, oldy2)) {
+                                        movePiece(selectedx2, selectedy2, oldx2, oldy2, BLACK); 
+                                        selected2 = false;
+                                        current_player = 1;
+                                        if(oldx % 2 == oldy2 %2)
+                                            uLCD.rectangle(oldx2*16,oldy2*16,(oldx2*16)+16,(oldy2*16)+16, 0xbcb6b8); 
+                                        else
+                                            uLCD.rectangle(oldx2*16,oldy2*16,(oldx2*16)+16,(oldy2*16)+16, 0x645659); 
+                                        uLCD.rectangle(oldx*16,oldy*16,(oldx*16)+16,(oldy*16)+16, GREEN);
+                                    }
+                                }
+                            }
+                            else
+                            {
+                                selected2 = true;
+                                selectedx2 =  oldx2;
+                                selectedy2 = oldy2;
+                            }
+                            one_hit =false;   
+                        }
+                    } 
+
+                            
+                        
+                        }
+                    }
+                    
+                }
+               
+            } 
+  while(winner) {
+                    uLCD.cls();
+                    uLCD.printf("Player %i wins", winner);
+                    while(1) {
+
+    uLCD.media_init();
+    uLCD.set_sector_address(0x0000, 0x00);
+    uLCD.display_video(0,0);
+    }
+                }     
+            
+
+            
+    }
+}