User:Decimus Schomer/Projects/Chess/Move-check scripts
< User:Decimus Schomer | Projects | Chess
Decimus' user page | Decimus' talk page | Decimus' scripts | Decimus' script libraries | Decimus' projects
Main projects page | Chess | Connect-4
Main chess page | Script | Move-check scripts
About
This script consists of two parts, each extremely long. One checks whether a move is legal in itself, and the other checks for either king being in check. They must both be put into the same prim, so that they will be able to communicate. They do not place pieces in a position physically, and currently commands are given by touching it and stating the move. I may try to improve this in future, as well as adding comments. A final note: if there are any bugs please contact me and I'll try to fix them, or try to fix them yourselves.
Main script
integer repeats = 0; list square=[" "]; integer xstart=0; integer ystart=0; integer xend=0; integer yend; integer handle; integer listennum; integer messagenum; integer faults; integer check; list castle=[0,0,0,0]; list king=[60,4]; string memstart; string memend; integer x; integer y; integer i; /////////////////////////////////////////Sets a listen command and says which player's move it is///////// initialise() { faults = 0; listennum = 0; llSay(0,"Player "+(string)(repeats%2+1)+"'s move"); handle = llListen(0,"",NULL_KEY,""); } //////////////////////////////////////////Does the basic move checking//////////////////////////////////// faultcheck() { messagenum=0; memstart= llList2String(square,ystart*8+xstart); memend= llList2String(square,yend*8+xend); llSay(0,memstart+" "+memend); ///////////////////////////////////////////Checks for basic errors//////////////////////////////////////// if(llList2String(square,ystart*8+xstart) == " ") { llSay(0,"No piece at starting coordinates"); faults++; } if(!(repeats%2)) { if(llToLower(memstart) != memstart) { llSay(0,"Cannot move black piece"); faults++; } } else if(llToUpper(memstart) != memstart) { llSay(0,"Cannot move white piece"); faults++; } ///////////////////////////////////////////Checks the legality of movement for pawns///////////////////// if(llToLower(memstart) == "p") { if(yend != ystart-((repeats%2)*2- 1) && yend != ystart-((repeats%2)*4- 2))faults++; else if(yend == ystart+2 || yend == ystart- 2) { if(ystart!=1 && ystart!=6)faults++; else if(xstart!=xend)faults++; else if(memend != " ")faults++; else if(llList2String(square,((ystart+yend)/2)*8+xend) != " ")faults++; } else if(xend==xstart){ if(memend != " ")faults++; } else if(xend!=xstart+1&&xend!=xstart- 1)faults++; if(faults == 0 && yend == 1)llListReplaceList(square,["Q"],xend,xend); else if(faults == 0 && yend == 1)llListReplaceList(square,["q"],56+xend,56+xend); } /////////////////////////////////////////////Checks the legality of movement for rooks//////////////////// if(llToLower(memstart) == "r") { /////////////////////////////////////////////Horizontal moves///////////////////////////////////////////// if(xstart!=xend) { if(ystart!=yend)faults++; else for(i=xstart;i!=xend;) { if(llList2String(square,yend*8+i)!=" ")faults++; if(i==xstart)faults--; if(xstart<xend)i++; else i--; } } //////////////////////////////////////////////Vertical moves/////////////////////////////////////////////// else { if(ystart==yend)faults++; else for(i=ystart;i!=yend;) { if(llList2String(square,i*8+xend)!=" ")faults++; if(i==ystart)faults--; if(ystart<yend)i++; else i--; } } if(ystart==1&&xstart==1)llListReplaceList(castle,[1],0,0); else if(ystart==1&&xstart==8)llListReplaceList(castle,[1],1,1); else if(ystart==8&&xstart==1)llListReplaceList(castle,[1],2,2); else if(ystart==8&&xstart==8)llListReplaceList(castle,[1],3,3); } /////////////////////////////////////////////////Checks the legality of movement for bishops///////////////// if(llToLower(memstart) == "b") { //////////////////////////////////////////////////Moves forwards right and backwards left//////////////////// if(xend-xstart==yend-ystart&&xend-xstart!=0) { for(i=xstart;i!=xend;) { if(llList2String(square,(ystart-xstart-i)*8+i)!=" ")faults++; if(i==xstart)faults--; if(xstart<xend)i++; else i--; } } ///////////////////////////////////////////////////Moves forwards right and backwards left//////////////////////// else if(xend-xstart==((yend-ystart)*-1)&&xend-xstart!=0) { for(i=xstart;i!=xend;) { if(llList2String(square,(ystart-xstart+i)*8+i)!=" ")faults++; if(i==xstart)faults--; if(xstart<xend)i++; else i--; } } else faults++; } ///////////////////////////////Checks the legality of movement for knights-basically checks all legal positions//////////////////// if(llToLower(memstart) == "h") { if((yend-ystart==1||yend-ystart==-1)&&(xend-xstart==2||xend-xstart==-2)); else if((yend-ystart==2||yend-ystart==-2)&&(xend-xstart==1||xend-xstart==-1)); else faults++; } ///////////////////////Checks the legality of movement for queens- legal moves for rooks plus those for bishops//////////////// if(llToLower(memstart) == "q") { if(xend-xstart==yend-ystart&&xend-xstart!=0) { for(i=xstart;i!=xend;) { if(llList2String(square,(ystart-xstart-i)*8+i)!=" ")faults++; if(i==xstart)faults--; if(xstart<xend)i++; else i--; } } else if(xend-xstart==((yend-ystart)*-1)&&xend-xstart!=0) { for(i=xstart;i!=xend;) { if(llList2String(square,(ystart-xstart+i)*8+i)!=" ")faults++; if(i==xstart)faults--; if(xstart<xend)i++; else i--; } } else { if(xstart!=xend) { if(ystart!=yend)faults++; else for(i=xstart;i!=xend;) { if(llList2String(square,yend*8+i)!=" ")faults++; if(i==xstart)faults--; if(xstart<xend)i++; else i--; } } else { if(ystart==yend)faults++; else for(i=ystart;i!=yend;) { if(llList2String(square,i*8+xend)!=" ")faults++; if(i==ystart)faults--; if(ystart<yend)i++; else i--; } } } } //////////////////////////Checks the legality of movement for kings- checks all legal positions//////////////////////////// if(llToLower(memstart) == "k") { if(yend-ystart>1||yend-ystart<-1||xend-xstart>1||xend-xstart<-1)faults++; else if(!(yend-ystart)&&!(xend-xstart))faults++; else if((xend==7||xend==3)&¥d==ystart&&!llList2Integer(castle,repeats%2*2+1)) { /////////////////Specific section for castling, involving sending messages to check for certain positions being in check/////////// faults--; float z=1.25*xend- 1.75; for(i=(integer)z;i!=5;) { if(llList2String(square,yend*8+i) != " ")faults++; llMessageLinked(LINK_THIS,(integer)(yend*8+xend*(-0.75)+i+5.25),llList2CSV(square),NULL_KEY); } llMessageLinked(LINK_THIS,yend*8+5,llList2CSV(square),NULL_KEY); if(xend>xstart&&check)faults++; if(!faults) { llListReplaceList(square,[" "],(integer)(yend*8+xend*1.75-(4.25)),(integer)(yend*8+xend*1.75-(4.25))); if(!(repeats%2))llListReplaceList(square,["r"],(integer)(xend/2+10.5),(integer)(xend/2+10.5)); else llListReplaceList(square,["R"],(integer)(xend/2+66.5),(integer)(xend/2+66.5)); } if(xend>xstart)i++; else i--; } llListReplaceList(king,[yend*8+xend],repeats%2,repeats%2); llListReplaceList(castle,[1,1],repeats%2*2,repeats%2*2+1); } /////////////////////////////////////////Checks that the square isn't the player's own piece////////////////////////////////////// if(repeats%2)if(llToLower(memend)!=memend){faults++;} else if(llToUpper(memend)!=memend){faults++;} ///////////////////////////////If there have been any faults so far, says that there's been an illegal move/////////////////////// if(faults)llSay(0,"Illegal move."); ////////////Otherwise moves the piece virtually, and sends a mesage to check if the king is in check in the new situation///////// else { llListReplaceList(square,[" "],ystart*8+xstart,ystart*8+xstart); llListReplaceList(square,[memstart],yend*8+xend,yend*8+xend); llMessageLinked(LINK_THIS,llList2Integer(king,repeats%2),llList2CSV(square),NULL_KEY); } } faultcheck2() { /////////////////////////////When a message is recieved from the other script, says whether the king is in check/////////////////// if(check) { llSay(0,"Illegal move. Would place king in check."); //////////////////If so, moves the virtual pieces back to where they were before the move, including any castling//////////////// llListReplaceList(square,[memstart],ystart*8+xstart,ystart*8+xstart); llListReplaceList(square,[memend],yend*8+xend,yend*8+xend); if(llToLower(memstart)=="k" && (xstart-xend>1||xstart-xend<(-1))) { llListReplaceList(king,[8*ystart+xstart],repeats%2,repeats%2); llListReplaceList(castle,[0,0],repeats%2*2,repeats%2*2+1); llListReplaceList(square,[" "],(integer)(yend*8+xend/2+2.5),(integer)(yend*8+xend/2+2.5)); if(!(repeats%2))llListReplaceList(square,["r"],(integer)(xend*1.75+3.75),(integer)(xend*1.75+3.75)); else llListReplaceList(square,["R"],(integer)(xend*1.75+57.75),(integer)(xend*1.75+59.75)); } faults++; } ///////////////////////////////////////////Says whether castling has taken place////////////////////////////////////////////////// else if(memstart=="k"&&(xstart-xend>1||xstart-xend<(-1)))llSay(0,"White castles"); else if(memstart=="k"&&(xstart-xend>1||xstart-xend<(-1)))llSay(0,"Black castles"); repeats++; /////////////////////////////Sends message to check whether move has placed opponent in check////////////////////////////////////// llMessageLinked(LINK_THIS,llList2Integer(king,repeats%2),llList2CSV(square),NULL_KEY); messagenum++; } default { ////////////////////////////////Sets up the virtual board and tells players how to state moves////////////////////////////////////// state_entry() { integer x; integer y; square = square +["r","h","b","q","k","b","h","r"]; for(x=0;x<8;x++)square = square+["p"]; for(x=0;x<8;x++) { for(y=2;y<6;y++)square = square+[" "]; } for(x=0;x<8;x++)square = square+["P"]; square = square +["R","H","B","Q","K","B","H","R"]; //////////////////////Here is where the physical representations of the pieces must be put in place///////////////////////////////// llSay(0,"Move commands must take the form:\n \50 start x\n \50 start y\n \50 end x\n \50 end y"); //Set positions of pieces (not done) } touch_start(integer num_detected) { initialise(); } listen(integer channel,string name,key id,string message) { /////////////////////Waits until it has recieved full information about the move, then calls the faultcheck1 function/////////////// if(listennum == 0)xstart = (integer)message; if(listennum == 1)ystart = (integer)message- 1; if(listennum == 2)xend = (integer)message; if(listennum == 3) { yend = (integer)message- 1; listennum= -1; llListenRemove(handle); faultcheck(); } listennum++; } ///////////////////////////////////////////Interprets the message from the other script///////////////////////////////////// link_message(integer sender_num,integer recieved,string str,key id) { if(str==NULL_KEY) { llSay(0,"Message"); if(recieved)check=1; else check=0; if(!messagenum)faultcheck2(); else if(recieved)llSay(0,"Check"); } } }
Check-detection script
default { link_message(integer sender_num, integer pos, string square1, key id) { llSay(0,"Message"); if(square1 != NULL_KEY) { integer control1 = 0; integer i; integer x=pos%8; integer y=(pos-(pos%8))/8; list square=llCSV2List(square1); if(llList2String(square,y*8+x)!=llToUpper(llList2String(square,y*8+x))) { if(llList2String(square,(y- 1)*8+x+1)=="P"||llList2String(square,(y- 1)*8+x- 1)=="P")jump return1; if(llList2String(square,(y- 1)*8+x- 2)=="H"||llList2String(square,(y- 1)*8+x+1)=="H")jump return1; if(llList2String(square,(y+1)*8+x- 2)=="H"||llList2String(square,(y+1)*8+x+1)=="H")jump return1; if(llList2String(square,(y- 2)*8+x- 1)=="H"||llList2String(square,(y- 2)*8+x+1)=="H")jump return1; if(llList2String(square,(y+2)*8+x- 1)=="H"||llList2String(square,(y+2)*8+x+1)=="H")jump return1; for(i=x- 1;i>0;i--) { if(llList2String(square,y*8+i)=="R"||llList2String(square,y*8+i)=="Q")jump return1; if(llList2String(square,y*8+i)!=" ")jump a; } @a; for(i=x+1;i<9;i++) { if(llList2String(square,y*8+i)=="R"||llList2String(square,y*8+i)=="Q")jump return1; if(llList2String(square,y*8+i)!=" ")jump b; } @b; for(i=y- 1;i>0;i--) { if(llList2String(square,i*8+x)=="R"||llList2String(square,i*8+x)=="Q")jump return1; if(llList2String(square,i*8+x)!=" ")jump c; } @c; for(i=y+1;i<9;i++) { if(llList2String(square,i*8+x)=="R"||llList2String(square,i*8+x)=="Q")jump return1; if(llList2String(square,i*8+x)!=" ")jump d; } @d; // // // // // // // for(i=1;x-i>0&&y-i>0;i++) { if(llList2String(square,(y-i)*8+x-i)=="B"||llList2String(square,(y-i)*8+x-i)=="Q")jump return1; if(llList2String(square,(y-i)*8+x-i)!=" ")jump e; } @e; for(i=1;x+i<9&&y-i>0;i++) { if(llList2String(square,(y-i)*8+x+i)=="B"||llList2String(square,(y-i)*8+x+i)=="Q")jump return1; if(llList2String(square,(y-i)*8+x+i)!=" ")jump f; } @f; for(i=1;x-i>0&&y+i>0;i++) { if(llList2String(square,(y+i)*8+x-i)=="B"||llList2String(square,(y+i)*8+x-i)=="Q")jump return1; if(llList2String(square,(y+i)*8+x-i)!=" ")jump g; } @g; for(i=1;x+i<9&&y+i>0;i++) { if(llList2String(square,(y+i)*8+x+i)=="B"||llList2String(square,(y+i)*8+x+i)=="Q")jump return1; if(llList2String(square,(y+i)*8+x+i)!=" ")jump h; } @h; // // // // // // // if(llList2String(square,(y- 1)*8+x- 1)=="K"||llList2String(square,(y- 1)*8+x)=="K")jump return1; if(llList2String(square,(y- 1)*8+x+1)=="K"||llList2String(square,y*8+x- 1)=="K")jump return1; if(llList2String(square,(y+1)*8+x- 1)=="K"||llList2String(square,(y+1)*8+x)=="K")jump return1; if(llList2String(square,(y+1)*8+x+1)=="K"||llList2String(square,y*8+x+1)=="K")jump return1; } else { if(llList2String(square,(y- 1)*8+x+1)=="p"||llList2String(square,(y- 1)*8+x- 1)=="p")jump return1; if(llList2String(square,(y- 1)*8+x- 2)=="h"||llList2String(square,(y- 1)*8+x+1)=="h")jump return1; if(llList2String(square,(y+1)*8+x- 2)=="h"||llList2String(square,(y+1)*8+x+1)=="h")jump return1; if(llList2String(square,(y- 2)*8+x- 1)=="h"||llList2String(square,(y- 2)*8+x+1)=="h")jump return1; if(llList2String(square,(y+2)*8+x- 1)=="h"||llList2String(square,(y+2)*8+x+1)=="h")jump return1; for(i=x- 1;i>0;i--) { if(llList2String(square,y*8+i)=="r"||llList2String(square,y*8+i)=="q")jump return1; if(llList2String(square,y*8+i)!=" ")jump j; } @j; for(i=x+1;i<9;i++) { if(llList2String(square,y*8+i)=="r"||llList2String(square,y*8+i)=="q")jump return1; if(llList2String(square,y*8+i)!=" ")jump k; } @k; for(i=y- 1;i>0;i--) { if(llList2String(square,i*8+x)=="r"||llList2String(square,i*8+x)=="q")jump return1; if(llList2String(square,i*8+x)!=" ")jump l; } @l; for(i=y+1;i<9;i++) { if(llList2String(square,i*8+x)=="r"||llList2String(square,i*8+x)=="q")jump return1; if(llList2String(square,i*8+x)!=" ")jump m; } @m; // // // // // // // for(i=1;x-i>0&&y-i>0;i++) { if(llList2String(square,(y-i)*8+x-i)=="b"||llList2String(square,(y-i)*8+x-i)=="q")jump return1; if(llList2String(square,(y-i)*8+x-i)!=" ")jump n; } @n; for(i=1;x+i<9&&y-i>0;i++) { if(llList2String(square,(y-i)*8+x+i)=="b"||llList2String(square,(y-i)*8+x+i)=="q")jump return1; if(llList2String(square,(y-i)*8+x+i)!=" ")jump o; } @o; for(i=1;x-i>0&&y+i>0;i++) { if(llList2String(square,(y+i)*8+x-i)=="b"||llList2String(square,(y+i)*8+x-i)=="q")jump return1; if(llList2String(square,(y+i)*8+x-i)!=" ")jump p; } @p; for(i=1;x+i<9&&y+i>0;i++) { if(llList2String(square,(y+i)*8+x+i)=="b"||llList2String(square,(y+i)*8+x+i)=="q")jump return1; if(llList2String(square,(y+i)*8+x+i)!=" ")jump q; } @q; // // // // // // // if(llList2String(square,(y- 1)*8+x- 1)=="k"||llList2String(square,(y- 1)*8+x)=="k")jump return1; if(llList2String(square,(y- 1)*8+x+1)=="k"||llList2String(square,y*8+x- 1)=="k")jump return1; if(llList2String(square,(y+1)*8+x- 1)=="k"||llList2String(square,(y+1)*8+x)=="k")jump return1; if(llList2String(square,(y+1)*8+x+1)=="k"||llList2String(square,y*8+x+1)=="k")jump return1; } llMessageLinked(LINK_THIS,0,NULL_KEY,NULL_KEY); control1 = 1; @return1; if(!control1)llMessageLinked(LINK_THIS,1,NULL_KEY,NULL_KEY); llSay(0,"Checked for check"); } } }