Chess game on the mbed.

Dependencies:   4DGL-uLCD-SE PinDetect SDFileSystem mbed

main.cpp

Committer:
mbavare
Date:
2016-03-14
Revision:
0:a5f9535b6e3d
Child:
1:af3a896cd76d

File content as of revision 0:a5f9535b6e3d:

#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);
    }
                }     
            

            
    }
}