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(¢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); } } } }