Chess game on the mbed.
Dependencies: 4DGL-uLCD-SE PinDetect SDFileSystem mbed
Diff: main.cpp
- 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(¢er_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); + } + } + + + + } +}