home *** CD-ROM | disk | FTP | other *** search
/ BUG 15 / BUGCD1998_06.ISO / aplic / jbuilder / jsamples.z / ChessRules.java < prev    next >
Text File  |  1997-07-03  |  58KB  |  1,761 lines

  1. package borland.samples.apps.chess.client;
  2.  
  3. import java.io.*;
  4. import borland.samples.apps.chess.client.board.*;
  5. import java.util.Vector;
  6. import java.awt.Point;
  7. import borland.jbcl.model.*;
  8. import borland.jbcl.util.*;
  9.  
  10. public class ChessRules implements WritableMatrixModel {
  11.   String msg;    //diagnostic
  12.   String subroutine;      //diagnostic
  13.   String playerB = CVS.BLACK; //PGN tag value - black player's name
  14.   String playerW = CVS.WHITE; //PGN tag value - white player's name
  15.   String whiteElo;  //PGN tag value
  16.   String blackElo;  //PGN tag value
  17.   String result;    //PGN tag value
  18.   String date;      //PGN tag value
  19.   String round;     //PGN tag value
  20.   String site;      //PGN tag value
  21.   String event;     //PGN tag value
  22.   String info;      //extra game info
  23.   long[] playerTime = new long [2]; //private PGN tag value - time remaining
  24.   long lMoveTime;   //private PGN tag value - time increment to add per move
  25.   int maxmoves = 510;   //hack - use Vector instead of array
  26.   int piececount;
  27.   boolean isMate = false;
  28.   boolean isStalemate = false;
  29.   int piecetosq;
  30.   int legalmove;
  31.   KingPos[] kingPos = new KingPos[2]; //keep track of each kings position
  32.   MoveNode[][] Move = new MoveNode[maxmoves][2];   //the array of moves
  33.   int movecount = -1;
  34.   public static final int Black = 1;
  35.   public static final int White = 0;
  36.   static final String pieceChar[]  = {"","","N","B","R","Q","K"};
  37.   static final String fileChar[]  = {"a","b","c","d","e","f","g","h"}  ;
  38.   int count;
  39.   int color;
  40.   String reason;
  41.   Vector squares; //no good reason for class scope
  42.  
  43.   public ChessRules() {
  44.     kingPos[0] = new KingPos(Chessboard.WHITEPIECE);
  45.     kingPos[1] = new KingPos(Chessboard.BLACKPIECE);
  46.     Move[0][0] = new MoveNode();
  47.     Move[0][1] = new MoveNode();
  48.     squares = new Vector();
  49.     //System.out.println("ChessRules xtor");
  50.     init();
  51.   }
  52.   
  53.   public int addMove(int movesub,int clrsub,String moveNotation,int movenum,int prevsub) {
  54.     //System.out.println("ChessRules.addMove " + movesub + "clr=" + clrsub + " "+ moveNotation);
  55.     if (movesub != count ) {
  56.       count++;
  57.       Move[count][0] = new MoveNode();
  58.       Move[count][1] = new MoveNode();
  59.     }
  60.     movecount = count;
  61.     Move[count][clrsub].movenum = movenum;
  62.     if (determinePreviousPosition(clrsub,count,prevsub)== true) {
  63.       Move[movecount][clrsub].movetext = moveNotation;
  64.       int clr = Chessboard.WHITEPIECE;
  65.       int oppClr = 1;
  66.       if (clrsub != 0){
  67.         clr = Chessboard.BLACKPIECE;
  68.         oppClr = 0;
  69.       }
  70.       processmove(movecount,clr,Move[movecount][clrsub]);
  71.       //System.out.println("Added " + moveNotation + "clrsub=" + clrsub + "Move" + movecount);
  72.       kingCheckCount(kingPos[oppClr],Move[movecount][clrsub]) ;
  73.     }
  74.     color = clrsub;
  75.     if (color == White)
  76.        processModelEvent(new MatrixModelEvent(this, MatrixModelEvent.ROW_ADDED));
  77.     else
  78.       //processModelEvent(new MatrixModelEvent(this, MatrixModelEvent.ITEM_CHANGED, new MatrixLocation(movecount, 0)));
  79.       processModelEvent(new MatrixModelEvent(this, MatrixModelEvent.ITEM_CHANGED, new MatrixLocation(movecount-1, 1 + color)));
  80.  
  81.     return movecount;
  82.   }
  83.  
  84.   public String getInfo() {
  85.     return info;
  86.   }
  87.  
  88.   public void setInfo(String info) {
  89.     this.info = info;
  90.   }
  91.  
  92.   public int getLastMoveNumber() {
  93.     return movecount;
  94.   }
  95.  
  96.   public int getWhoMovedLast(){
  97.     return color;
  98.   }
  99.  
  100.   public String getPlayerB(){
  101.     return playerB;
  102.   }
  103.  
  104.   public void setPlayerB(String name) {
  105.     playerB = name;
  106.   }
  107.   public String getWhiteElo() {
  108.     return whiteElo;
  109.   }
  110.   public void setWhiteElo(String rating) {
  111.     this.whiteElo = rating;
  112.   }
  113.   public String getBlackElo() {
  114.     return blackElo;
  115.   }
  116.   public void setBlackElo(String rating) {
  117.     this.blackElo = rating;
  118.   }
  119.   public long getMoveTimeInterval() {
  120.     return lMoveTime;
  121.   }
  122.   public long getWhiteTimeRemaining() {
  123.     return playerTime[0];
  124.   }
  125.   public long getBlackTimeRemaining() {
  126.     return playerTime[1];
  127.   }
  128.   public void setResult(String result) {
  129.     this.result = result;
  130.   }
  131.   public String getResult() {
  132.     return result;
  133.   }
  134.   public void setDate(String date) {
  135.     this.date = date;
  136.   }
  137.   public void setEvent(String name) {
  138.     this.event = name;
  139.   }
  140.   public void setSite(String name) {
  141.     this.site = name;
  142.   }
  143.   public String getTags() {
  144.     String tag = "";
  145.     if (event != null && event.length() > 0)
  146.       tag = tag + "[Event \"" + event + "\"]\r\n";
  147.     if (site != null && site.length() > 0)
  148.       tag = tag + "[Site \"" + site + "\"]\r\n";
  149.     if (date != null && date.length() > 0)
  150.       tag = tag + "[Date \"" + date + "\"]\r\n";
  151.     if (round != null && round.length() > 0)
  152.       tag = tag + "[Round \"" + round + "\"]\r\n";
  153.     tag = tag + "[White \"" + playerW + "\"]\r\n[Black \"" + playerB +"\"]\r\n"  ;
  154.     if (whiteElo != null && whiteElo.length() > 0)
  155.       tag = tag + "[WhiteElo \"" + whiteElo + "\"]\r\n";
  156.     if (whiteElo != null && blackElo.length() > 0)
  157.       tag = tag + "[BlackElo \"" + blackElo + "\"]\r\n";
  158.     if (result != null && result.length() > 0)
  159.       tag = tag + "[Result \"" + result + "\"]\r\n" ;
  160.     return tag;  
  161.   }
  162.  
  163.   public void setRound(String round) {
  164.     this.round = round;
  165.   }
  166.   public String getPlayerW() {
  167.     return playerW;
  168.   }
  169.  
  170.   public void setPlayerW(String name) {
  171.     playerW = name;
  172.   }
  173.  
  174.   public void setPieceValues(int arraySub,int color,Boardsquares pos) {
  175.     Move[arraySub][color].pieceValue.init(pos);
  176.   }
  177.  
  178.   public void setPieceColors(int arraySub,int color,Boardsquares pos) {
  179.     Move[arraySub][color].pieceColor.init(pos);
  180.   }
  181.  
  182.   public String getComment(int arraySub,int color){
  183.     return Move[arraySub][color].comment;
  184.   }
  185.  
  186.   public int getPreviousSubscript(int arraySub,int color){
  187.     return Move[arraySub][color].prevsub;
  188.   }
  189.  
  190.   public int isGameOver() {
  191.     if (isMate)
  192.       return 1;
  193.     else
  194.     if (isStalemate)
  195.       return 2;
  196.     else
  197.       return 0;
  198.   }
  199.  
  200.   public String getMoveText(int arraySub,int color) {
  201.     return Move[arraySub][color].movetext;
  202.   }
  203.  
  204.   public void setComment(int arraySub,int color,String string) {
  205.     Move[arraySub][color].comment = string;
  206.     processModelEvent(new MatrixModelEvent(this, MatrixModelEvent.ITEM_CHANGED, new MatrixLocation(arraySub-1, 3)));
  207.   }
  208.  
  209.   public Boardsquares getPieceValues(int arraySub,int color){
  210.     return Move[arraySub][color].pieceValue;
  211.   }
  212.  
  213.   public Boardsquares getPieceColors(int arraySub,int color){
  214.     return Move[arraySub][color].pieceColor;
  215.   }
  216.  
  217.   public void init() {
  218.     isMate = false;
  219.     isStalemate = false;
  220.     movecount = 0;
  221.     Move[0][1].movenum = 0;
  222.     Move[0][1].nestlevel = 0;
  223.     Move[0][1].prevsub = 0;
  224.     playerTime[0] = 0;
  225.     playerTime[1] = 0;
  226.     lMoveTime = 0;
  227.     color = Black;
  228.     count = 0;
  229.     info = "";
  230.     whiteElo = "";
  231.     blackElo = "";
  232.     result=null;
  233.     date="";
  234.     round="";
  235.     site="";
  236.     event="";
  237.   }
  238.  
  239.   public int getMoveNumber(int arraySub,int color){
  240.     return Move[arraySub][color].movenum;
  241.   }
  242.  
  243.   public void setMove(int move,int color) {
  244.     movecount = move;
  245.     this.color = color;
  246.   }
  247.  
  248.   public int getArraySize() {
  249.     return count;
  250.   }
  251.  
  252.   // Fill Move array by parsing an input stream
  253.   public void parsePGNFile (Reader is) throws Exception {
  254.     count = 0;
  255.     StreamTokenizer st = new StreamTokenizer(is);
  256.     if (st != null)
  257.       subroutine = "parsePGN Read";
  258.     st.wordChars(91,93)   ;
  259.     st.wordChars(40,45) ;
  260.     st.wordChars(61,63);
  261.     st.wordChars('@','@');
  262.     st.wordChars('/','/');
  263.     st.wordChars('_','_');
  264.     st.wordChars('?','?');
  265.     st.wordChars('!','!');
  266.     st.wordChars('=','=');
  267.     st.whitespaceChars(10,13);
  268.     boolean boring = false;
  269.     String val = "?";
  270.     subroutine = "parsePGN loop ";
  271.     int nestlevel = 0;
  272.     int prevsub = -1;
  273.     info = "";
  274.     try {
  275.   scan:
  276.     while (true)
  277.       switch (st.nextToken()) {
  278.         case StreamTokenizer.TT_EOF:
  279.           break scan;
  280.         case StreamTokenizer.TT_WORD:
  281.           subroutine = "ParsePGN Word ";
  282.           val = st.sval;
  283.           //System.out.println("newword " + val);
  284.           Move[count][color].comment = Move[count][color].comment +" " +val;
  285.           if (val.charAt(0) == '{' ||
  286.               val.charAt(0) == '(' )
  287.             nestlevel++;
  288.           if (val.charAt(0) == ')' ||
  289.               val.charAt(0) == '}' )
  290.             nestlevel--;
  291.           if (val.charAt(0) == '[') {
  292.             boring = true;
  293.             if (val.equals ("[Black")) {
  294.               st.nextToken();
  295.               playerB = st.sval;
  296.               boring = false;
  297.             }
  298.             else
  299.             if (val.equals("[White")) {
  300.               st.nextToken();
  301.               playerW = st.sval;
  302.               //System.out.println("Set white to " + playerW);
  303.               boring = false;
  304.             }
  305.             else
  306.             if (val.equals("[Whitetime")) {
  307.               if (st.nextToken()==StreamTokenizer.TT_NUMBER)
  308.                 playerTime[0] = (long) st.nval;
  309.             }
  310.             else
  311.             if (val.equals("[Blacktime")) {
  312.               if (st.nextToken()==StreamTokenizer.TT_NUMBER)
  313.                 playerTime[1] = (long) st.nval;
  314.             }
  315.             else
  316.             if (val.equals("[Movetime")) {
  317.               if (st.nextToken()==StreamTokenizer.TT_NUMBER)
  318.                 lMoveTime = (long) st.nval ;
  319.                 lMoveTime = lMoveTime * 1000;
  320.             }
  321.             else {
  322.               if (val.equals("[Site")) {
  323.                 st.nextToken();
  324.                 site = st.sval;
  325.                 boring = false;
  326.               }
  327.               else
  328.               if (val.equals("[Event")) {
  329.                 st.nextToken();
  330.                 event = st.sval;
  331.                 boring = false;
  332.               }
  333.               else
  334.               if (val.equals("[Date")) {
  335.                 st.nextToken();
  336.                 date = st.sval;
  337.                 boring = false;
  338.               }
  339.               else
  340.               if (val.equals("[Round")) {
  341.                 st.nextToken();
  342.                 round = st.sval;
  343.                 boring = false;
  344.               }
  345.               else
  346.               if (val.equals("[WhiteElo")) {
  347.                 st.nextToken();
  348.                 whiteElo = st.sval;
  349.                 boring = false;
  350.               }
  351.               else
  352.               if (val.equals("[BlackElo")) {
  353.                 st.nextToken();
  354.                 blackElo = st.sval;
  355.                 boring = false;
  356.               }
  357.               else
  358.               if (val.equals("[Result")) {
  359.                 st.nextToken();
  360.                 result = st.sval;
  361.                 boring = false;
  362.               }
  363.               else {
  364.                 st.nextToken();
  365.               }
  366.               info = info + st.sval + "\r\n";
  367.             }
  368.             break;
  369.           }
  370.           if (val.endsWith("]") == true) {
  371.             boring = false;
  372.           }
  373.           break;
  374.         case StreamTokenizer.TT_NUMBER:
  375.           subroutine = "ParsePGN num ";
  376.             if (boring == true)
  377.               break;
  378.       int movenum = (int) st.nval;
  379.           if (movenum == 7)
  380.             boring = false;
  381.           count++ ;
  382.           Move[count][1] = new MoveNode();
  383.           Move[count][0] = new MoveNode();
  384.           //System.out.println("parsePGN num count = " + count);
  385.           if (count  >= movenum - 1 && movenum > 0) {
  386.             if (prevsub > 0) {
  387.               Move[count][0].prevsub = prevsub;
  388.               Move[count][1].prevsub = prevsub;
  389.               prevsub = -1;
  390.             }
  391.             else {
  392.               Move[count][0].prevsub = count -1;
  393.               Move[count][1].prevsub = count;
  394.             }
  395.             Move[count][0].movetext = "...";
  396.             Move[count][1].movetext = "...";
  397.             Move[count][0].nestlevel = nestlevel;
  398.             Move[count][1].nestlevel = nestlevel;
  399.             int i=0;
  400.             //System.out.println("parsePGN num movenum = " + movenum);
  401.             while (true) {
  402.               st.nextToken();
  403.               if (st.ttype == StreamTokenizer.TT_WORD) {
  404.                 if (!st.sval.equals("_") && i == 0)
  405.                   Move[count][1].prevsub = count;
  406.                 if (i < 2) {
  407.                   Move[count][i].movenum = movenum;
  408.               Move[count][i].movetext = st.sval;
  409.                   i++;
  410.                 }
  411.                 else {
  412.                   Move[count][color].comment = Move[count][color].comment +" " +st.sval;
  413.                 }
  414.                 if (st.sval.startsWith("@")){
  415.                   //System.out.println("found variation marker " + st.sval);
  416.                   if (st.sval.length() > 1){
  417.                     prevsub = Integer.parseInt(st.sval.substring(1));
  418.                     System.out.println("variation is a continuation of subscript " + prevsub);
  419.                   }
  420.                 }
  421.               }
  422.               else
  423.                 if (st.ttype == StreamTokenizer.TT_NUMBER &&
  424.                     st.nval == 0)  {
  425.                   if (i == 0 || Move[count][0].movenum != 0)
  426.                     i++;
  427.                 }
  428.                 else {
  429.                   st.pushBack()  ;
  430.                   break;
  431.                 }
  432.             }
  433.           }
  434.           default:
  435.           subroutine = "ParsePGN default ";
  436.           val =  " " + st.ttype;
  437.           //System.out.println("weird char" + val);
  438.              break;
  439.       }
  440.       if (Move[count][0].movetext.equals("...") && Move[count][1].movetext.equals("..."))
  441.         count--;//misinterpreted the result as a move?
  442.       is.close();
  443.       //System.out.println(subroutine + count);
  444.       }
  445.       catch (Exception e)   {
  446.          System.out.println(subroutine + e);
  447.       }
  448.       if (st.ttype != StreamTokenizer.TT_EOF)
  449.         throw new Exception(st.toString());
  450.       //GeneratePositions();
  451.   }
  452.  
  453.   boolean determinePreviousPosition(int clr,int sub,int prevsub) {
  454.     try{
  455.     //System.out.println("CV DeterminePP");
  456.     int previousSub;
  457.     int prevColor;
  458.     int adjustment;
  459.     int i;
  460.     if (clr + sub == 0)
  461.       return true;
  462.     if (clr == 0) {
  463.       adjustment = 1;
  464.       previousSub = sub -1 ;
  465.       prevColor = 1;
  466.     }
  467.     else {
  468.       adjustment = 0;
  469.       previousSub = sub;
  470.       prevColor = 0;
  471.     }
  472.     if (prevsub != sub)
  473.       previousSub = prevsub;
  474.     for (i = previousSub;i >= 0;i--) {
  475.       //System.out.println("CV DeterminePP  forloop "+ String.valueOf(sub)+ " " + String.valueOf(clr) );
  476.       if ((Move[i][prevColor].movenum == (Move[sub][clr].movenum - adjustment )) &&
  477.            Move[i][prevColor].nestlevel <= Move[sub][clr].nestlevel) {
  478.         Move[sub][clr].prevsub = i;
  479.         Move[sub][clr].copy(Move[i][prevColor]);
  480.         //System.out.println("prev move subscript is "  + i + "," + prevColor);
  481.         subroutine = "DeterminePositions" + sub;
  482.         return true;
  483.       }
  484.     }
  485.     }
  486.     catch(Exception e ) { System.out.println("Determine postions" + e);}
  487.     return false;
  488.   }
  489.  
  490.   void generatePositions() {
  491.     this.color = ChessRules.Black;
  492.     subroutine = "generatePositions";
  493.     //System.out.println(subroutine);
  494.     try {
  495.     int clr;
  496.     int movenum;
  497.     int rank;
  498.     int file;
  499.     int sub = 0;
  500.     int[] color = new int[2];
  501.     color[0] = Chessboard.WHITEPIECE;
  502.     color[1] = Chessboard.BLACKPIECE;
  503.     //initialize king positions for verifing legal moves
  504.     for (file = 0;file < 8;file++)
  505.       for (rank = 0;rank < 8;rank++) {
  506.         if (Move[0][1].pieceValue.value(file,rank) == Chessboard.KING){
  507.           clr = Move[0][1].pieceColor.value(file,rank);
  508.           if (clr != 0)
  509.             clr = 1;
  510.           kingPos[clr].SetKingPos(file,rank);
  511.       }
  512.     }
  513.     for (sub = 1;sub<=count;sub++) {
  514.       for (clr = 0;clr < 2;clr++) {
  515.         legalmove = 0;
  516.         piececount = 0;
  517.         piecetosq = 0;
  518.         if ( determinePreviousPosition(clr,sub,Move[sub][clr].prevsub)== true) {
  519.           processmove(sub,color[clr],Move[sub][clr]);
  520.           //statusLine.setText("fin "+sub);
  521.           if (legalmove == 0) { //diagnostic info  when illegal move encountered
  522.             System.out.println("Illegal move " + Move[sub][clr].movetext + Move[sub][clr].comment);
  523.             int prevclr = clr;
  524.             this.color = ChessRules.White;
  525.             if (clr == 0)
  526.               prevclr = 1;
  527.             Move[sub][clr].movenum = 0 ;
  528.             Move[sub][clr].prevsub = -1;
  529.             Move[sub+clr -1][prevclr].comment =  Move[sub][clr].movetext + Move[sub+clr -1][prevclr].comment  ;
  530.             Move[sub][clr].movetext = " "   ;
  531.           }
  532.         }
  533.       } //end inner for loop
  534.     } // end outer for loop
  535.     processModelEvent(new MatrixModelEvent(this, MatrixModelEvent.STRUCTURE_CHANGED));
  536.  
  537.     }
  538.     catch (Exception e ) {
  539.       System.out.println("Generate positions " + e);
  540.       e.printStackTrace();
  541.     }
  542.   }
  543.  
  544.   void processmove(int sub,int clr ,MoveNode Pos) {
  545.     String movestr = new String(Pos.movetext);
  546.     //System.out.println("P "+sub+" "+ clr+" " +movestr);
  547.     if (movestr.length() < 2)
  548.       return;
  549.     char tempchar;
  550.     char fromrank = ' ';
  551.     char fromfile = ' ';
  552.     char torank = ' ';
  553.     char tofile = ' ';
  554.     int clrsub = 0;
  555.     if (clr != 0)
  556.       clrsub = 1;
  557.     int oldpiece = 0; //first piece mentioned in move
  558.     int piecevalue = 0; //last piece mentioned in move e4Q
  559.     boolean take=false;
  560.     int charsub = 0;
  561.     int rank;
  562.     int file;
  563.   scan:
  564.     while (true)  {
  565.       tempchar = movestr.charAt(charsub);
  566.       charsub++;
  567.       switch(tempchar) {
  568.         case 'a':
  569.         case 'b':
  570.         case 'c':
  571.         case 'd':
  572.         case 'e':
  573.         case 'f':
  574.         case 'g':
  575.         case 'h':
  576.           fromfile = tofile;
  577.          tofile = tempchar;
  578.           break;
  579.         case '1':
  580.         case '2':
  581.         case '3':
  582.         case '4':
  583.         case '5':
  584.         case '6':
  585.         case '7':
  586.         case '8':
  587.           fromrank = torank;
  588.           torank = tempchar;
  589.           break;
  590.         case 'x':
  591.           take = true;
  592.           break;
  593.         case 'R':
  594.           oldpiece = piecevalue;
  595.           piecevalue = Chessboard.ROOK;
  596.           break;
  597.         case 'K':
  598.           piecevalue = Chessboard.KING;
  599.           break;
  600.         case 'Q':
  601.           oldpiece = piecevalue;
  602.           piecevalue = Chessboard.QUEEN;
  603.           break;
  604.         case 'N':
  605.           oldpiece = piecevalue;
  606.           piecevalue = Chessboard.KNIGHT;
  607.           break;
  608.         case 'B':
  609.           oldpiece = piecevalue;
  610.           piecevalue = Chessboard.BISHOP;
  611.           break;
  612.         case 'O':
  613.           if (clr == Chessboard.BLACKPIECE)
  614.             rank = 7;
  615.           else
  616.              rank = 0;
  617.           if (movestr.regionMatches(charsub-1,"O-O-O",0,5)) {
  618.             if (Pos.qCastleForfeited[clrsub]== false &&
  619.                 kingPos[clrsub].isInCheck() == false) {
  620.               Pos.assign(0,rank,0,0);
  621.               Pos.assign(3,rank,Chessboard.ROOK,clr);
  622.               Pos.assign(2,rank,Chessboard.KING,clr);
  623.               Pos.assign(4,rank,0,0);
  624.               Pos.qCastleForfeited[clrsub] = true;
  625.               kingPos[clrsub].SetKingPos(2,-1);
  626.               legalmove++;
  627.             }
  628.             return;
  629.           }
  630.           else
  631.           if (movestr.regionMatches(charsub-1,"O-O",0,3)){
  632.             if (Pos.kCastleForfeited[clrsub]== false &&
  633.                 kingPos[clrsub].isInCheck() == false) {
  634.               Pos.kCastleForfeited[clrsub] = true;
  635.               Pos.assign(4,rank,0,0);
  636.               Pos.assign(5,rank,Chessboard.ROOK,clr);
  637.               Pos.assign(6,rank,Chessboard.KING,clr);
  638.               Pos.assign(7,rank,0,0);
  639.               kingPos[clrsub].SetKingPos(6,-1);
  640.               legalmove++;
  641.             }
  642.             return;
  643.           }
  644.           break scan;
  645.        default:
  646.          break;
  647.       }
  648.       if (tempchar != ' '  && piecevalue == 0)
  649.         piecevalue = Chessboard.PAWN;
  650.       if (charsub == movestr.length() )
  651.         break scan;
  652.     }
  653.     if (oldpiece > Chessboard.PAWN)
  654.       return;
  655.     else
  656.       if (oldpiece == 0)
  657.         oldpiece = piecevalue;
  658.     if (tofile == ' ' || torank == ' ')
  659.       return;
  660.     rank = getRankSubscript(torank);
  661.     file = getFileSubscript(tofile);
  662.     if (oldpiece == Chessboard.KING){
  663.       kingPos[clrsub].SetKingPos(file,rank);
  664.     }
  665.     if (oldpiece == Chessboard.PAWN) {
  666.       if ( fromfile == ' ')
  667.         fromfile = tofile;
  668.     }
  669.     if (findFromSquare(Pos,kingPos[clrsub],piecevalue,oldpiece,clr,sub,fromrank,fromfile,rank,file))
  670.       Pos.assign(file,rank,piecevalue,clr);
  671.     else {
  672.       System.out.println("No move" + movestr);
  673.       //statusLine.setText("No move "+movestr);
  674.     }
  675.   }
  676.  
  677.   boolean findFromSquare(
  678.     MoveNode Pos,KingPos king,int piecevalue,int oldpiece,
  679.     int clr,int sub,char fromrank,char fromfile,
  680.     int toranksub,int tofilesub) {
  681.     //fromfile may or may not contain the file the piece came from
  682.     //fromrank may or may not contain the rank the piece came from
  683.     //System.out.println("FFromSquare "+oldpiece+clr+sub+fromrank+fromfile+toranksub+tofilesub);
  684.     int startrank = 0;
  685.     int startfile = 0;
  686.     int endfile = 7;
  687.     int endrank = 7;
  688.     int rank;
  689.     int file;
  690.     if (fromrank != ' ') {
  691.       startrank = getRankSubscript(fromrank);
  692.       endrank = startrank;
  693.     }
  694.     if (fromfile != ' ') {
  695.       startfile = getFileSubscript(fromfile);
  696.       endfile = startfile;
  697.     }
  698.     for (rank=startrank;rank <=endrank;rank++) {
  699.       for (file = startfile;file <=endfile;file++) {
  700.         if (Pos.pieceValue.value(file,rank) == oldpiece &&
  701.             Pos.pieceColor.value(file,rank) == clr) {
  702.           piececount++;
  703.           if (isLegalMove(Pos,king,sub,oldpiece,piecevalue,clr,rank,file,toranksub,tofilesub)) {
  704.             legalmove++;
  705.             Pos.assign(file,rank,0,0);
  706.             if (Pos.enpassantFile == -2)
  707.               Pos.assign(tofilesub,rank,0,0);
  708.             return true;
  709.           }
  710.         }
  711.       }
  712.     }
  713.     return false;
  714.   }
  715.  
  716. boolean isValidMove(MoveNode Pos,int sub,int piece,int clr,int rank,
  717.                     int file,int toranksub,int tofilesub) {
  718.   int rankdiff = rank-toranksub;
  719.   int rankdir = -1;
  720.   int filedir = -1;
  721.   int lowfile;
  722.   int highfile;
  723.   int ranksub;
  724.   int filesub;
  725.   int i,j;
  726.   int colorsub = 0 ;
  727.   int eprank = 5;
  728.   if (clr == Chessboard.BLACKPIECE){
  729.     eprank = 2;
  730.     colorsub = 1;
  731.   }
  732.   boolean returnval = false;
  733.   if (rankdiff < 0) {
  734.     rankdir = 1;
  735.     rankdiff = toranksub - rank;
  736.   }
  737.   int filediff = file-tofilesub;
  738.   if (filediff < 0) {
  739.     filediff = tofilesub - file;
  740.     filedir = 1;
  741.   }
  742.   int enpassantFile = -1;
  743.   if (Pos.pieceValue.value(tofilesub,toranksub) > 0 &&
  744.       Pos.pieceColor.value(tofilesub,toranksub) == clr)
  745.     return false; //can't take your own pieces
  746.   switch(piece) {
  747.     case Chessboard.PAWN:
  748.       if (filediff > 1)
  749.         break;
  750.       else
  751.         if (filediff == 1 && rankdiff == 1)
  752.           if (Pos.pieceValue.value(tofilesub,toranksub) == 0) {
  753.             //System.out.println("isValidMove - Pos.enpassantFile=" + Pos.enpassantFile);
  754.             if (toranksub == eprank &&
  755.                  clr != Pos.pieceColor.value(tofilesub,rank) &&
  756.                 Pos.pieceValue.value(tofilesub,rank) == Chessboard.PAWN &&
  757.                 Pos.enpassantFile == tofilesub) {
  758.                enpassantFile = -2;
  759.                returnval = true;
  760.                break;
  761.              }
  762.              else
  763.                break;
  764.           }
  765.       boolean capture = (Pos.pieceValue.value(tofilesub,toranksub) != 0);
  766.       if (filediff == 0 && capture)
  767.         break;
  768.       if (filediff == 1 && !capture )
  769.         break;
  770.       if (rankdiff != 1 && filediff == 1)
  771.         break;
  772.       if (capture && Pos.pieceColor.value(tofilesub,toranksub) == clr)
  773.         break;
  774.       if (clr == Chessboard.BLACKPIECE) {
  775.         if (rank -1 == toranksub) {
  776.           returnval = true;
  777.           break;
  778.         }
  779.         if (rank == 6 && toranksub ==4 &&
  780.             Pos.pieceValue.value(file,5)==0) {
  781.           enpassantFile = tofilesub;
  782.           //System.out.println("enpassant possibility next move");
  783.           returnval = true;
  784.           break;
  785.         }
  786.       }
  787.       else {
  788.         if (rank + 1 == toranksub) {
  789.           returnval = true;
  790.           break;
  791.         }
  792.         if (rank == 1 && toranksub == 3 &&
  793.             Pos.pieceValue.value(file,2)==0) {
  794.           enpassantFile = tofilesub;
  795.           //System.out.println("enpassant possibility next move");
  796.           returnval = true;
  797.           break;
  798.         }
  799.       }
  800.       break;
  801.     case Chessboard.KNIGHT:
  802.       if ((rankdiff ==2 && filediff == 1) ||
  803.           (rankdiff ==1 && filediff == 2))  {
  804.         returnval = true;
  805.         break;
  806.       }
  807.       break;
  808.     case Chessboard.KING:
  809.       if (rankdiff < 2 && filediff <2)
  810.         returnval = true;
  811.       else
  812.         if (rankdiff == 0 && filediff == 2 && (toranksub == 0 || toranksub == 7))
  813.           if (tofilesub == 2 && Pos.pieceValue.value(3,toranksub) == 0 &&
  814.               Pos.pieceValue.value(2,toranksub) == 0 &&
  815.               Pos.pieceValue.value(1,toranksub) == 0 &&
  816.               Pos.pieceValue.value(0,toranksub) == Chessboard.ROOK &&
  817.               Pos.qCastleForfeited[colorsub] == false &&
  818.               kingPos[colorsub].isInCheck() == false)
  819.             returnval = true;
  820.           else
  821.             if (tofilesub == 6 && Pos.pieceValue.value(5,toranksub) == 0 &&
  822.                 Pos.pieceValue.value(6,toranksub) == 0 &&
  823.                 Pos.pieceValue.value(7,toranksub) == Chessboard.ROOK &&
  824.                 Pos.kCastleForfeited[colorsub] == false &&
  825.                 kingPos[colorsub].isInCheck() == false)
  826.               returnval = true;
  827.         break;
  828.     case Chessboard.ROOK:
  829.       if (rankdiff == 0 ) {
  830.         for (i=file+filedir;i!=tofilesub;i=i+filedir) {
  831.           if (Pos.pieceValue.value(i,rank) != 0)
  832.             return false;
  833.         }
  834.         returnval = true;
  835.         break;
  836.       }
  837.       else {
  838.         if (filediff == 0) {
  839.           for (i=rank+rankdir;i!=toranksub;i=i+rankdir) {
  840.             if (Pos.pieceValue.value(file,i) != 0)
  841.               return false;
  842.           }
  843.           returnval = true;
  844.           break;
  845.         }
  846.       }
  847.       break;
  848.     case Chessboard.BISHOP:
  849.       if (filediff == rankdiff) {
  850.         for (i=1;i<filediff;i++) {
  851.           ranksub = rank + rankdir;
  852.           filesub = file + filedir;
  853.           if (Pos.pieceValue.value(filesub,ranksub) != 0)
  854.             return false;
  855.         }
  856.         returnval = true;
  857.       }
  858.       break;
  859.     case Chessboard.QUEEN:
  860.       if (filediff == rankdiff) {
  861.         for (i=1;i<filediff;i++) {
  862.           ranksub = rank + rankdir;
  863.           filesub = file + filedir;
  864.           if (Pos.pieceValue.value(filesub,ranksub) != 0)
  865.             return false;
  866.         }
  867.         returnval =  true;
  868.       }
  869.       else
  870.         if (rankdiff == 0) {
  871.           for (i=file+filedir;i!=tofilesub;i=i+filedir) {
  872.             if (Pos.pieceValue.value(i,rank) != 0)
  873.               return false;
  874.           }
  875.           returnval = true;
  876.         }
  877.         else {
  878.           if (filediff == 0) {
  879.             for (i=rank+rankdir;i!=toranksub;i=i+rankdir) {
  880.               if (Pos.pieceValue.value(file,i) != 0)
  881.                   return false;
  882.             }
  883.             returnval = true;
  884.           }
  885.         }
  886.         break;
  887.     }//end of switch statment
  888.     Pos.enpassantFile = enpassantFile;
  889.     return returnval;
  890.   }
  891.  
  892.   boolean isLegalMove(MoveNode Pos,KingPos king,int sub,int piece,
  893.                       int newpiece,int clr,int rank,int file,
  894.                       int toranksub,int tofilesub) {
  895.     boolean rc = true;
  896.     int tmpp = Pos.enpassantFile;
  897.     if (isValidMove(Pos,sub,piece,clr,rank,file,toranksub,tofilesub)){
  898.       int toPiece = Pos.pieceValue.value(tofilesub,toranksub);
  899.       int toColor = Pos.pieceColor.value(tofilesub,toranksub);
  900.       Pos.assign(file,rank,0,0);
  901.       Pos.assign(tofilesub,toranksub,newpiece,clr);
  902.       int pieceTaken  = 0;
  903.       int pieceColor = 0;
  904.       if (Pos.enpassantFile == -2) {
  905.         System.out.println("En Passant!");
  906.         pieceTaken = Pos.pieceValue.value(tofilesub,rank);
  907.         pieceColor = Pos.pieceColor.value(tofilesub,rank);
  908.         Pos.assign(tofilesub,rank,0,0);
  909.       }
  910.       if (isLegalPosition(Pos,king,sub,piece,clr,rank,file,toranksub,tofilesub))
  911.         rc = true;
  912.       else {
  913.         //System.out.println("isLegalPosition=false");
  914.         rc = false;
  915.       }
  916.       Pos.assign(file,rank,piece,clr);
  917.       Pos.assign(tofilesub,toranksub,toPiece,toColor);
  918.       if (Pos.enpassantFile == -2)
  919.         Pos.assign(tofilesub,rank,pieceTaken,pieceColor);
  920.     }
  921.     else {
  922.       //System.out.println("isValidMove=false");
  923.       rc = false;
  924.     }
  925.     //if (tmpp != Pos.enpassantFile)
  926.     //  System.out.println("ep file changed " + piece + clr + rank + file + toranksub + tofilesub);
  927.     return rc;
  928.   }
  929.  
  930.   boolean isLegalPosition(MoveNode Pos,KingPos king,int sub,int piece,int clr,
  931.                           int rank,int file,int toranksub,int tofilesub) {
  932.     int colorsub = 0;
  933.     if (clr == Chessboard.BLACKPIECE)
  934.       colorsub = 1;
  935.     //now make sure there is no discovered check created;
  936.     // System.out.println("legalm "+sub+piece+clr+rank+file+toranksub+tofilesub);
  937.     if (Pos.pieceValue.value(king.GetKingFile(),king.GetKingRank()) != Chessboard.KING )
  938.       findKing(clr,colorsub,Pos);
  939.     piecetosq++;
  940.     int rankdiff;
  941.     int rankdir;
  942.     int filediff;
  943.     int filedir;
  944.     if (piece != Chessboard.KING ) {
  945.       if (king.isInCheck()) { //was king in check ?
  946.         //System.out.println("King was in check");
  947.         if (kingCheckCount(king,Pos)) { //is it still in check?
  948.           System.out.println("King is still in check");
  949.           return false;
  950.         }
  951.         else
  952.           return true;
  953.       }
  954.       else {
  955.         //System.out.println("King was safe before");
  956.         //just need to make sure a discovered check was not created
  957.         rankdiff = rank-kingPos[colorsub].GetKingRank();
  958.          rankdir = 1;
  959.          filedir = 1;
  960.          if (rankdiff < 0) {
  961.           rankdir = -1;
  962.           rankdiff = kingPos[colorsub].GetKingRank() - rank;
  963.         }
  964.          filediff = file - kingPos[colorsub].GetKingFile();
  965.          if (filediff < 0) {
  966.           filediff = kingPos[colorsub].GetKingFile() - file;
  967.           filedir = -1;
  968.          }
  969.          int badpiece = 9;//just in case
  970.          if (filediff == 0) {
  971.           filedir = 0;
  972.           badpiece = Chessboard.ROOK;
  973.           }
  974.           if (rankdiff == 0) {
  975.           rankdir = 0;
  976.           badpiece = Chessboard.ROOK;
  977.           }
  978.          if (filediff == rankdiff)
  979.           badpiece = Chessboard.BISHOP;
  980.         if (filediff == rankdiff || rankdiff == 0 || filediff == 0) {
  981.           msg =  'K'+fileChar[kingPos[colorsub].GetKingFile()]+String.valueOf(kingPos[colorsub].GetKingRank()+1)  ;
  982.           return notInCheck(Pos,king,file,rank,tofilesub,toranksub,filedir,rankdir,kingPos[colorsub].getKingColor(),badpiece);
  983.          }
  984.       }//end looking for discovered check
  985.     }
  986.     else {
  987.       rankdir = toranksub - rank;
  988.       filedir = tofilesub - file;
  989.       if (filedir == 2) //king moves 2 squares when castling
  990.         filedir = 1;
  991.       if (filedir == -2)
  992.         filedir = -1;
  993.       while (true) {
  994.         rank = rank + rankdir;
  995.         file = file + filedir;
  996.         kingPos[colorsub].SetKingPos(file,rank);
  997.         if (kingCheckCount(kingPos[colorsub],Pos)) {
  998.           //System.out.println("King can't move there");
  999.           return false;
  1000.         }
  1001.         if (file == tofilesub)
  1002.           return true;
  1003.       }
  1004.     }
  1005.     return true;
  1006.   }
  1007.  
  1008.   boolean kingCheckCount(KingPos king,MoveNode Pos) {
  1009.     //System.out.println("Is King Safe at " + king.GetKingFile() + king.GetKingRank() + "?");
  1010.     king.KingInCheck(false); //initialize
  1011.     int file = king.GetKingFile();
  1012.     int rank = king.GetKingRank();
  1013.     msg =  fileChar[file]+String.valueOf(rank+1)  ;
  1014.     int clr = king.getKingColor();
  1015.     int filesub;
  1016.     int ranksub;
  1017.     int i;
  1018.     int j;
  1019.     int badpiece;
  1020.     for (i=-1;i<2;i++)
  1021.       for (j=-1;j<2;j++) {
  1022.         if (i!= 0 && j != 0) {
  1023.           filesub = file + i;
  1024.           ranksub = rank + (2* j);
  1025.           if (Pos.pieceValue.value(filesub,ranksub) == Chessboard.KNIGHT &&
  1026.               Pos.pieceColor.value(filesub,ranksub) !=  clr ) {
  1027.             king.SetAttacker(Chessboard.KNIGHT,filesub,ranksub);
  1028.           }
  1029.           else {
  1030.             filesub = file +(2 * i);
  1031.             ranksub = rank + j ;
  1032.             if (Pos.pieceValue.value(filesub,ranksub) == Chessboard.KNIGHT &&
  1033.                 Pos.pieceColor.value(filesub,ranksub) !=  clr )
  1034.               king.SetAttacker(Chessboard.KNIGHT,filesub,ranksub);
  1035.           }
  1036.         }
  1037.         if (i!= 0 || j!= 0) {
  1038.           if (i==0 || j == 0)
  1039.             badpiece = Chessboard.ROOK;
  1040.           else
  1041.             badpiece = Chessboard.BISHOP;
  1042.           if (notInCheck(Pos,king,file,rank,file,rank,i,j,clr,badpiece)==false) {
  1043.             filesub = file;
  1044.             ranksub = rank ;
  1045.             findattacker:
  1046.             while(true){
  1047.               filesub = filesub + i;
  1048.               ranksub = ranksub + j ;
  1049.               int attacker;
  1050.               if ((attacker = Pos.pieceValue.value(filesub,ranksub))!= 0)  {
  1051.                 king.SetAttacker(attacker,filesub,ranksub);
  1052.                 break findattacker;
  1053.               }
  1054.             }
  1055.           }
  1056.         }
  1057.       }
  1058.     //System.out.println("Is King Safe at " + king.GetKingFile() + king.GetKingRank() + "? " +!king.isInCheck());
  1059.     return king.isInCheck();
  1060.   }
  1061.  
  1062.   public void checkForStalemate(MoveNode pos,KingPos king,int clr) {
  1063.     if (clr != 0)
  1064.       clr = Chessboard.BLACKPIECE;
  1065.     for (int rank=0; rank < 8; rank++) {
  1066.       for (int file = 0; file < 8; file++) {
  1067.         if (pos.pieceColor.value(file,rank) == clr) {
  1068.           int piece = pos.pieceValue.value(file,rank);
  1069.           possibleSquares(file,rank,pos);
  1070.           for (int i = 0; i < squares.size(); i++) {
  1071.             Point potentialSquare = (Point) squares.elementAt(i);
  1072.             //System.out.println("is " + piece + "(" + file + "," + rank + ") to "
  1073.             //  + potentialSquare.x + "," + potentialSquare.y + "a legal move?" );
  1074.  
  1075.             if (isLegalMove(pos,king,0,piece,piece,clr,rank,file,potentialSquare.y,
  1076.              potentialSquare.x))
  1077.              return ;
  1078.           }
  1079.         }
  1080.       }
  1081.     }
  1082.     System.out.println("Stalemate");
  1083.     isStalemate = true;
  1084.   }
  1085.  
  1086.   void possibleSquares(int file,int rank,MoveNode pos) {
  1087.     int piece = pos.pieceValue.value(file,rank);
  1088.     int clr   = pos.pieceColor.value(file,rank);
  1089.     int rankLowLimit = 0;
  1090.     int rankHighLimit = 7;
  1091.     int fileLowLimit = 0;
  1092.     int fileHighLimit = 7;
  1093.     squares.removeAllElements();
  1094.     switch (piece) {
  1095.       case Chessboard.PAWN:
  1096.         int dir = 1;
  1097.         if (clr == Chessboard.BLACKPIECE)
  1098.           dir = -1;
  1099.         squares.addElement(new Point(file,rank + dir));
  1100.         if (file != 0)
  1101.           squares.addElement(new Point(file -1,rank + dir));
  1102.         if (rank != 7)
  1103.           squares.addElement(new Point(file +1,rank + dir));
  1104.         if ((rank == 6 && dir == -1) || (rank == 1 && dir == 1))
  1105.           squares.addElement(new Point(file,rank + dir + dir));
  1106.         break;
  1107.       case Chessboard.KNIGHT:
  1108.         int rankdiff;
  1109.         for (int i= file-2; i< file + 3; i++) {
  1110.           if (i >= 0 && i != file && i < 8) {
  1111.             rankdiff  = ((file + i + 1)/2) - ((file+i) /2) + 1;
  1112.             if (i >= 0 && i < 8 && rank + rankdiff  < 8)
  1113.               squares.addElement(new Point(i,rank + rankdiff));
  1114.             if (i >= 0 && i < 8 && rank - rankdiff  >= 0)
  1115.               squares.addElement(new Point(i,rank - rankdiff));
  1116.           }
  1117.         }
  1118.         break;
  1119.       case Chessboard.KING:
  1120.         rankLowLimit = 0;
  1121.         rankHighLimit = 7;
  1122.         fileLowLimit = 0;
  1123.         fileHighLimit = 7;
  1124.         if (rank > 0)
  1125.           rankLowLimit = rank -1;
  1126.         if (rank != 7)
  1127.           rankHighLimit = rank + 1;
  1128.         if (file > 0)
  1129.           fileLowLimit = file -1;
  1130.         if (file != 7)
  1131.           fileHighLimit = file + 1;
  1132.  
  1133.       case Chessboard.QUEEN:
  1134.  
  1135.       case Chessboard.ROOK:
  1136.         if (piece != Chessboard.KING) {
  1137.           rankLowLimit = 0;
  1138.           rankHighLimit = 7;
  1139.           fileLowLimit = 0;
  1140.           fileHighLimit = 7;
  1141.         }
  1142.         int i;
  1143.         for (i = rankLowLimit; i <= rankHighLimit; i++)
  1144.           if (i != rank)
  1145.             squares.addElement(new Point(file,i));
  1146.         for (i = fileLowLimit; i <= fileHighLimit; i++)
  1147.           if (i != file)
  1148.             squares.addElement(new Point(i,rank));
  1149.         if (piece == Chessboard.ROOK)
  1150.           break;
  1151.       case Chessboard.BISHOP:
  1152.         if (piece != Chessboard.KING) {
  1153.           rankLowLimit  = 0;
  1154.           rankHighLimit = 7;
  1155.           fileLowLimit  = 0;
  1156.           fileHighLimit = 7;
  1157.           if (rank > file)
  1158.             rankLowLimit = rank - file;
  1159.           else {
  1160.             fileLowLimit  = file - rank ;
  1161.             rankHighLimit = 7 - file + rank;
  1162.           }
  1163.         }
  1164.         int fileSub = fileLowLimit;
  1165.  
  1166.         for (i=rankLowLimit; i<= rankHighLimit; i++){
  1167.            if (i != rank && fileSub < 8)
  1168.             squares.addElement(new Point(fileSub,i));
  1169.           fileSub++;
  1170.         }
  1171.         if (piece != Chessboard.KING) {
  1172.           rankLowLimit = 0;
  1173.           rankHighLimit = 7;
  1174.           fileLowLimit = 0;
  1175.           fileHighLimit = 7;
  1176.           if (rank + file < 7) {
  1177.             rankHighLimit = rank + file;
  1178.             fileHighLimit = rank + file;
  1179.           }
  1180.           else
  1181.             rankLowLimit = file + rank - 7;
  1182.         }
  1183.         fileSub = fileHighLimit;
  1184.         for (i=rankLowLimit; i<= rankHighLimit; i++){
  1185.           if (i != rank && fileSub >= 0)
  1186.             squares.addElement(new Point(fileSub,i));
  1187.           fileSub--;
  1188.         }
  1189.         break;
  1190.     }
  1191.   }
  1192.  
  1193.   boolean isMated(KingPos king,MoveNode Pos) {
  1194.     boolean[][] safesquare = new boolean[3][3];
  1195.     //System.out.println("isMated?" + king.getKingColor());
  1196.     int rank = king.GetKingRank();
  1197.     int file = king.GetKingFile();
  1198.     int KRank;
  1199.     int KFile;
  1200.     int i;
  1201.     int j;
  1202.     KingPos temp = new KingPos(king.getKingColor());
  1203.     for (i= 0;i<3;i++){
  1204.       KRank = rank - 1 + i;
  1205.       for (j=0;j<3;j++){
  1206.         KFile = file - 1 + j;
  1207.         if (KRank < 0 || KRank > 7 || KFile < 0 || KFile > 7)
  1208.           safesquare [i][j] = false;//cannot flee off the board
  1209.         else
  1210.           if (Pos.pieceValue.value(KFile,KRank) != 0 &&
  1211.               Pos.pieceColor.value(KFile,KRank) == king.getKingColor())  {
  1212.             //System.out.println("cannot flee to" + KFile + KRank);
  1213.             safesquare [i][j] = false; //can't move there
  1214.           }
  1215.           else
  1216.             safesquare [i][j] = true; //so far
  1217.         if (safesquare [i][j] == true && (i !=1 || j!= 1)) {
  1218.           temp.SetKingPos(KFile,KRank);
  1219.           if (!kingCheckCount(temp,Pos))
  1220.             return false;
  1221.         }
  1222.       }
  1223.     }
  1224.     return !canBlock(king,Pos);
  1225.   }
  1226.  
  1227.   boolean canBlock(KingPos king,MoveNode Pos)  {
  1228.     //System.out.println("canBlock " + king.kingCheckCount);
  1229.     if (king.isDoubleCheck()) {
  1230.       return false;
  1231.     }
  1232.     int clr = king.getKingColor();
  1233.     KingPos temp = new KingPos(clr);
  1234.     temp.SetKingPos(king.GetKingFile(),king.GetKingRank());
  1235.     int attacker =  king.GetAttacker();
  1236.     int BlockRank = king.GetAttackerRank();
  1237.     int BlockFile = king.GetAttackerFile();
  1238.     int fileinc = king.GetKingFile() - BlockFile;
  1239.     int rankinc = king.GetKingRank() - BlockRank;
  1240.     if (fileinc > 1)  fileinc = 1;
  1241.     if (rankinc < -1) rankinc = -1;
  1242.     if (rankinc > 1)  rankinc = 1;
  1243.     if (fileinc < -1) fileinc = -1;
  1244.     //look on each square and see if there is a piece that can
  1245.     //make a legalmove to one of the squares that would block the check (or take the piece)
  1246.     for (int i=0;i<8;i++) {
  1247.       for (int j=0;j<8;j++){
  1248.         int piece = Pos.pieceValue.value(i,j);
  1249.         if (piece != 0 && Pos.pieceColor.value(i,j) == clr &&
  1250.             piece != Chessboard.KING)  {
  1251.           int rank = BlockRank;
  1252.           int file = BlockFile;
  1253.           //System.out.println("Can " + piece + " at " + i + j + " block at " + file + rank);
  1254.           while(true) {
  1255.             if (!temp.isInCheck())
  1256.               temp.SetAttacker(attacker,BlockFile,BlockRank);
  1257.             if (isLegalMove(Pos,temp,movecount,piece,piece,clr,j,i,rank,file)){
  1258.               //System.out.println("Can Block=yes" );
  1259.               return true;
  1260.             }
  1261.             if (attacker == Chessboard.KNIGHT)
  1262.               break;
  1263.             rank = rank + rankinc;
  1264.             file = file + fileinc;
  1265.             if (king.KingPosEquals(file,rank))
  1266.               break; //tried all the blocking squares
  1267.           }
  1268.         }//end if
  1269.       }
  1270.     }
  1271.     return false;
  1272.   }
  1273.  
  1274.   boolean notInCheck(MoveNode Pos,KingPos king,int file,int rank,int tofilesub,
  1275.                      int toranksub,int filedir,int rankdir,int clr,int badpiece){
  1276.     int i;
  1277.     int ranksub;
  1278.     int filesub;
  1279.     int pawnDir = -1;
  1280.     if (king.getKingColor() == Chessboard.BLACKPIECE)
  1281.       pawnDir = +1;
  1282.     ranksub = king.GetKingRank() + rankdir;
  1283.     filesub = king.GetKingFile() + filedir;
  1284.     for (i=0;i<7;i++){
  1285.       if (ranksub > 7 || ranksub < 0 || filesub < 0 || filesub > 7)
  1286.         return true;
  1287.       if (ranksub == toranksub && filesub == tofilesub)
  1288.         return true;
  1289.       msg = msg + " " +fileChar[filesub]+String.valueOf(ranksub+1);
  1290.       if (Pos.pieceValue.value(filesub,ranksub) != 0 &&
  1291.          (filesub != file || ranksub != rank)) {
  1292.         if (Pos.pieceColor.value(filesub,ranksub) != clr){
  1293.           if (Pos.pieceValue.value(filesub,ranksub) == Chessboard.QUEEN ||
  1294.           Pos.pieceValue.value(filesub,ranksub) == badpiece)  {
  1295.             msg = "Discovered check "+fileChar[filesub]+String.valueOf(ranksub+1)+
  1296.                   "-"+fileChar[file]+String.valueOf(rank+1);
  1297.             System.out.println(msg);
  1298.             return false;
  1299.           }
  1300.           else
  1301.             if (Pos.pieceValue.value(filesub,ranksub) == Chessboard.PAWN &&
  1302.                 ranksub + pawnDir == rank &&
  1303.                (filesub - king.GetKingFile() == 1 || king.GetKingFile() - filesub == 1))  {
  1304.                //System.out.println("Pawn Check?");
  1305.               return false;
  1306.             }
  1307.             else
  1308.               if (Pos.pieceValue.value(filesub,ranksub) == Chessboard.KING &&
  1309.                   filesub - king.GetKingFile() <= 1 && king.GetKingFile()-filesub <= 1  &&
  1310.                   ranksub - king.GetKingRank() <= 1 && king.GetKingRank()-ranksub <= 1) {
  1311.                 //System.out.println("Kings too close?");
  1312.                 return false;
  1313.               }
  1314.               else
  1315.                 return true;
  1316.         }
  1317.         else
  1318.           if (Pos.pieceValue.value(filesub,ranksub) != Chessboard.KING)
  1319.             return true;
  1320.       }
  1321.       ranksub = ranksub + rankdir;
  1322.       filesub = filesub + filedir;
  1323.     }
  1324.     return true;
  1325.   }
  1326.  
  1327.   void findKing(int Kcolor,int sub,MoveNode Pos)  {
  1328.     //find the king so we can tell what pieces are pinned
  1329.     int i = 0;
  1330.     int j = 0;
  1331.     for (i=0;i<8;i++) {
  1332.       for (j=0;j<8;j++) {
  1333.        if (Pos.pieceValue.value(i,j) == Chessboard.KING &&
  1334.             Pos.pieceColor.value(i,j) == Kcolor)  {
  1335.             kingPos[sub].SetKingPos(i,j);
  1336.           return;
  1337.         }
  1338.       }
  1339.     }
  1340.   }
  1341.  
  1342.   int getFileSubscript(int file) {
  1343.     switch (file) {
  1344.       case 'a':
  1345.         file = 0;
  1346.         break;
  1347.       case 'b':
  1348.         file = 1;
  1349.         break;
  1350.       case 'c':
  1351.         file = 2;
  1352.         break;
  1353.       case 'd':
  1354.         file = 3;
  1355.         break;
  1356.       case 'e':
  1357.         file = 4;
  1358.         break;
  1359.       case 'f':
  1360.         file = 5;
  1361.         break;
  1362.       case 'g':
  1363.         file = 6;
  1364.         break;
  1365.       case 'h':
  1366.         file = 7;
  1367.         break;
  1368.       default:
  1369.         file = 8;
  1370.         break;
  1371.     }
  1372.     return file;
  1373.   }
  1374.  
  1375.   int getRankSubscript(char rank) {
  1376.     switch (rank) {
  1377.       case '1':
  1378.         rank = 0;
  1379.         break;
  1380.       case '2':
  1381.         rank = 1;
  1382.         break;
  1383.       case '3':
  1384.         rank = 2;
  1385.         break;
  1386.       case '4':
  1387.         rank = 3;
  1388.         break;
  1389.       case '5':
  1390.         rank = 4;
  1391.         break;
  1392.       case '6':
  1393.         rank = 5;
  1394.         break;
  1395.       case '7':
  1396.         rank = 6;
  1397.         break;
  1398.       case '8':
  1399.         rank = 7;
  1400.         break;
  1401.       default:
  1402.         rank = 8;
  1403.         break;
  1404.     }
  1405.     return rank;
  1406.   }
  1407.  
  1408.   public boolean claimDraw() {
  1409.     int oppColor = Chessboard.WHITEPIECE;
  1410.     if (color == 0)
  1411.       oppColor = Chessboard.BLACKPIECE;
  1412.     reason = "because the applet screwed up";
  1413.     boolean rc = false;
  1414.     if (Move[movecount][color].PieceValues(oppColor) < 5) {
  1415.       rc = true;
  1416.       reason = "Insufficient material"  ;
  1417.     }
  1418.     else {
  1419.       int piececount = Move[movecount][color].PieceCount();
  1420.       int fiftyMoveCount = 1;
  1421.       int matchingPos = 1;
  1422.       String MatchingMsg= "Duplicate positions on moves " + movecount;
  1423.       for (int i= movecount-1;i>0;i--) {
  1424.         if (Move[movecount][color].MatchingPawnSkeleton(Move[i][color]) &&
  1425.             Move[i][color].PieceCount() == piececount)  {
  1426.           fiftyMoveCount++;
  1427.           if (Move[i][color].equals(Move[movecount][color])) {
  1428.             matchingPos++;
  1429.             MatchingMsg = MatchingMsg + ", " + i;
  1430.             //System.out.println("match-" + movecount + color + " " + i + color);
  1431.             if (matchingPos == 3) {
  1432.               reason = MatchingMsg;
  1433.               rc = true;
  1434.               break;
  1435.             }
  1436.           }
  1437.         }
  1438.         else
  1439.            break;
  1440.       }
  1441.       if (fiftyMoveCount > 50){
  1442.         rc = true;
  1443.         reason = "50 move rule" ;
  1444.       }
  1445.     }
  1446.     return rc;
  1447.   }
  1448.  
  1449.   public String getReason() {
  1450.     return reason;
  1451.   }
  1452.  
  1453.   public boolean moveInfo(MoveTuple tuple,int sideThatMadeMove,boolean mustMoveOwnPieces ,boolean checkOnly) {
  1454.     //System.out.println("ChessRules.moveInfo, sideThatMadeMove =" +  sideThatMadeMove + "mustMoveOwnPieces =" + mustMoveOwnPieces + "tuple=" + tuple.toString());
  1455.     if (tuple.fromFile == tuple.toFile &&
  1456.         tuple.fromRank == tuple.toRank)   {
  1457.       reason = "No move";
  1458.     }
  1459.     else {
  1460.       int slop = 0;
  1461.       int clr = 1;
  1462.       if (tuple.pieceColor == 0)  {
  1463.         slop = 1;
  1464.         clr = 0;
  1465.       }
  1466.       int sub = movecount;
  1467.       MoveNode  Pos = new MoveNode();
  1468.       Pos.copy(Move[movecount][color])  ;
  1469.       if (clr != color && (mustMoveOwnPieces == false || clr == sideThatMadeMove)){
  1470.         if (isLegalMove(Pos,kingPos[clr],sub,tuple.pieceValue,tuple.newpieceValue,tuple.pieceColor,
  1471.                         tuple.fromRank,tuple.fromFile,tuple.toRank,tuple.toFile)) {
  1472.           if (!checkOnly)
  1473.             newMove(tuple,Pos)  ;
  1474.           if (color == White)
  1475.             processModelEvent(new MatrixModelEvent(this, MatrixModelEvent.ROW_ADDED));
  1476.           else {
  1477.             //processModelEvent(new MatrixModelEvent(this, MatrixModelEvent.ITEM_CHANGED, new MatrixLocation(movecount, 0)));
  1478.             processModelEvent(new MatrixModelEvent(this, MatrixModelEvent.ITEM_CHANGED, new MatrixLocation(movecount-1, 1 + color)));
  1479.  
  1480.           }
  1481.           return true;
  1482.         }
  1483.         else  {
  1484.           reason = "not legal " + pieceChar[tuple.pieceValue]
  1485.                    + fileChar[tuple.toFile]
  1486.                    + String.valueOf(tuple.toRank+1) + " " + msg;
  1487.           msg = " ";
  1488.         }
  1489.       }
  1490.       else  {
  1491.         if (clr != color )
  1492.           reason = "not your turn "+ String.valueOf(clr)+String.valueOf(color)+String.valueOf(sideThatMadeMove);
  1493.         else  {
  1494.           String  whoseturn;
  1495.           if (color == White)
  1496.             whoseturn = new String("White's");
  1497.           else
  1498.             whoseturn = new String("Black's");
  1499.           reason ="It's " + whoseturn + " turn.  "+ pieceChar[tuple.pieceValue]+fileChar[tuple.toFile]+String.valueOf(tuple.toRank+1);
  1500.         }
  1501.       }
  1502.     }
  1503.     System.out.println("ChessRules.moveInfo returning false " + reason);
  1504.     return false;
  1505.   }
  1506.  
  1507.   public void newMove(MoveTuple tuple,MoveNode Pos) {
  1508.     try {
  1509.       //System.out.println("ChessRules.newMove");
  1510.       int slop = 0;
  1511.       int clr = 1;
  1512.       if (tuple.pieceColor == 0)  {
  1513.         slop = 1;
  1514.         clr = 0;
  1515.       }
  1516.       String moveChar=" ";
  1517.       int i;
  1518.       int j;
  1519.       int sub = movecount;
  1520.       //MoveNode  Pos = new MoveNode();
  1521.       //Pos.copy(Move[movecount][color])  ;
  1522.       String fromChar = "";
  1523.       String fromPiece = pieceChar[tuple.pieceValue];
  1524.       String takeChar = "";
  1525.       if (Move[movecount][color].pieceValue.value(tuple.toFile,tuple.toRank)!= 0)
  1526.         takeChar = "x";
  1527.       msg = " ";
  1528.       if (tuple.pieceValue == Chessboard.PAWN)  {
  1529.         //System.out.println("Enpassant possibility = " + Pos.enpassantFile);
  1530.         if (tuple.fromFile != tuple.toFile)  {
  1531.           takeChar = "x";
  1532.           fromChar = fileChar[tuple.fromFile]   ;
  1533.           if (Pos.enpassantFile == -2)
  1534.             Pos.assign(tuple.toFile,tuple.fromRank,0,0); //en passant
  1535.         }
  1536.         moveChar = fromChar + takeChar + fileChar[tuple.toFile] + String.valueOf(tuple.toRank + 1);
  1537.       }
  1538.       else {
  1539.         if (tuple.pieceValue == Chessboard.KING ) {
  1540.           Pos.qCastleForfeited[clr] = true;
  1541.           Pos.kCastleForfeited[clr] = true;
  1542.           if (tuple.toFile-tuple.fromFile == 2) {
  1543.             Pos.assign(7,tuple.fromRank,0,0);
  1544.             Pos.assign(5,tuple.fromRank,Chessboard.ROOK,tuple.pieceColor);
  1545.             moveChar = "O-O";
  1546.           }
  1547.           else {
  1548.             if (tuple.fromFile-tuple.toFile == 2) {
  1549.               Pos.assign(0,tuple.fromRank,0,0);
  1550.               Pos.assign(3,tuple.fromRank,Chessboard.ROOK,tuple.pieceColor);
  1551.               moveChar = "O-O-O";
  1552.             }
  1553.             else
  1554.               moveChar = fromPiece + takeChar + fileChar[tuple.toFile] + String.valueOf(tuple.toRank + 1);
  1555.           }
  1556.         }
  1557.         else {
  1558.           if (tuple.pieceValue == Chessboard.ROOK ) {
  1559.             if (tuple.fromFile == 0 )  {
  1560.               if (tuple.fromRank == 0)
  1561.                 Pos.qCastleForfeited[0] = true;
  1562.               else
  1563.                 if (tuple.fromRank == 7)
  1564.                   Pos.qCastleForfeited[1] = true;
  1565.             }
  1566.             else {
  1567.               if (tuple.fromFile == 7 )
  1568.                 if (tuple.fromRank == 0)
  1569.                   Pos.kCastleForfeited[0] = true;
  1570.                 else
  1571.                   if (tuple.fromRank == 7)
  1572.                     Pos.kCastleForfeited[1] = true;
  1573.             }
  1574.           }
  1575.           //System.out.println("Check for ambigous notation");
  1576.  forloops:
  1577.           for (i=0;i<8;i++) { //check if there are two pieces that can move to the ending square
  1578.             for (j=0;j<8;j++) {
  1579.               if (Pos.pieceValue.value(i,j) == tuple.pieceValue
  1580.                  && (i!=tuple.fromFile || j != tuple.fromRank)
  1581.                  && (Pos.pieceColor.value(i,j) == tuple.pieceColor))
  1582.                 if (isLegalMove(Pos,kingPos[clr],sub,tuple.pieceValue,tuple.newpieceValue,
  1583.                                 tuple.pieceColor,j,i,tuple.toRank,tuple.toFile)) {
  1584.                   if (tuple.fromFile == i)
  1585.                     fromChar = String.valueOf( 1+tuple.fromRank);
  1586.                   else
  1587.                     fromChar = fileChar[tuple.fromFile];
  1588.                   System.out.println("Supplemented the notation to avoid Ambiguous notation "  + fromChar);
  1589.                   break forloops;
  1590.                 }
  1591.             }
  1592.           }
  1593.           moveChar = fromPiece + fromChar + takeChar + fileChar[tuple.toFile] + String.valueOf(tuple.toRank + 1);
  1594.         }
  1595.       }
  1596.       Pos.assign(tuple.fromFile,tuple.fromRank,0,0);
  1597.       Pos.assign(tuple.toFile,tuple.toRank,tuple.newpieceValue,tuple.pieceColor);
  1598.       int newcount;
  1599.       if (movecount != count)
  1600.         newcount = count + 1; //a new line
  1601.       else
  1602.         newcount = count + slop;  //a new line if last move was by black
  1603.       //System.out.println(String.valueOf(newcount)+" "+String.valueOf(count)+" "+String.valueOf(clr)+" ");
  1604.       if (newcount > count)  {
  1605.         //System.out.println("initializing Move array at subscript "+ newcount);
  1606.         Move[newcount][0] = new MoveNode();
  1607.         Move[newcount][1] = new MoveNode();
  1608.         count++;
  1609.       }
  1610.       //System.out.println("bc Enpassant possibility = " + Pos.enpassantFile);
  1611.       Move[newcount][clr].copy(Pos);
  1612.       if (tuple.newpieceValue != tuple.pieceValue)
  1613.         moveChar = moveChar + pieceChar[tuple.newpieceValue] ;
  1614.       if (( kingCheckCount(kingPos[color],Pos))) {
  1615.         moveChar = moveChar + '+';
  1616.         if (isMate = isMated(kingPos[color],Pos))  {
  1617.           moveChar = moveChar + '+';
  1618.         }
  1619.       }
  1620.       else  {
  1621.         //System.out.println("cfs Enpassant possibility = " + Pos.enpassantFile);
  1622.         checkForStalemate(Pos,kingPos[color],color);
  1623.       }
  1624.       Move[newcount][clr].movenum = Move[movecount][slop].movenum + slop;
  1625.       Move[newcount][clr].nestlevel = Move[movecount][clr].nestlevel;
  1626.       Move[newcount][clr].prevsub = movecount;
  1627.       Move[newcount][clr].movetext = moveChar;
  1628.       //System.out.println("Enpassant possibility ("+ newcount + ","+clr+ ") = " + Move[newcount][clr].enpassantFile);
  1629.       int oldmovesub = newcount;
  1630.       if (movecount != count) // we be starting a variation
  1631.         oldmovesub = movecount;
  1632.       movecount = newcount;
  1633.       color = clr;
  1634.     }
  1635.     catch (Exception e) {
  1636.       e.printStackTrace();
  1637.     }
  1638.     return;
  1639.   }
  1640.  
  1641.   public boolean canSet(int row, int col, boolean edit) {
  1642.     if  (row == count &&(col == 1 || col == 2 ))
  1643.       return true;
  1644.     if (col ==3)
  1645.       return true;
  1646.     return false;
  1647.     //  borland.jbcl.model.WritableMatrixModel method;
  1648.   }
  1649.  
  1650.   public void set(int parm1, int parm2, Object parm3) {
  1651.     //  borland.jbcl.model.WritableMatrixModel method;
  1652.   }
  1653.  
  1654.   public void touched(int parm1, int parm2) {
  1655.     //  borland.jbcl.model.WritableMatrixModel method;
  1656.   }
  1657.  
  1658.   public boolean isVariableRows() {
  1659.     return true;
  1660.     // borland.jbcl.model.WritableMatrixModel method;
  1661.   }
  1662.  
  1663.   public void addRow() {
  1664.     // borland.jbcl.model.WritableMatrixModel method;
  1665.   }
  1666.  
  1667.   public void addRow(int parm1) {
  1668.     // borland.jbcl.model.WritableMatrixModel method;
  1669.   }
  1670.  
  1671.   public void removeRow(int parm1) {
  1672.     // borland.jbcl.model.WritableMatrixModel method;
  1673.   }
  1674.  
  1675.   public void removeAllRows() {
  1676.     // borland.jbcl.model.WritableMatrixModel method;
  1677.   }
  1678.  
  1679.   public boolean isVariableColumns() {
  1680.     return false;
  1681.   }
  1682.  
  1683.   public void addColumn() {
  1684.     //  borland.jbcl.model.WritableMatrixModel method;
  1685.   }
  1686.  
  1687.   public void addColumn(int parm1) {
  1688.     //  borland.jbcl.model.WritableMatrixModel method;
  1689.   }
  1690.  
  1691.   public void removeColumn(int parm1) {
  1692.     //  borland.jbcl.model.WritableMatrixModel method;
  1693.   }
  1694.  
  1695.   public void removeAllColumns() {
  1696.     //  borland.jbcl.model.WritableMatrixModel method;
  1697.   }
  1698.  
  1699.   public void enableModelEvents(boolean enable) {
  1700.     if (events != enable) {
  1701.       events = enable;
  1702.       if (enable)
  1703.         processModelEvent(new MatrixModelEvent(this, MatrixModelEvent.STRUCTURE_CHANGED));
  1704.     }
  1705.   }
  1706.  
  1707.   public Object get(int row, int col) {
  1708.     //  borland.jbcl.model.MatrixModel method;
  1709.     if (count > 0)
  1710.       row++;
  1711.     if (col == 0)
  1712.       return  String.valueOf(getMoveNumber(row,White)) + '.';
  1713.     if (col == 1)
  1714.       return  getMoveText(row,White);
  1715.     if (col == 2)
  1716.       return getMoveText(row,Black);
  1717.     if (col == 3)
  1718.       return getComment(row,White) ;
  1719.     if (col == 4)
  1720.       return Move[row][White];
  1721.     if (col == 5)
  1722.       return Move[row][Black];
  1723.       return null;
  1724.   }
  1725.  
  1726.   public MatrixLocation find(Object parm1) {
  1727.     //  borland.jbcl.model.MatrixModel method;
  1728.     return null;
  1729.   }
  1730.  
  1731.   public int getRowCount() {
  1732.     return count;
  1733.     //  borland.jbcl.model.MatrixModel method;
  1734.   }
  1735.  
  1736.   public int getColumnCount() {
  1737.     return 4;
  1738.     //  borland.jbcl.model.MatrixModel method;
  1739.   }
  1740.  
  1741.   public void addModelListener(MatrixModelListener listener) {
  1742.     modelListeners.add(listener);
  1743.     //  borland.jbcl.model.MatrixModel method;
  1744.   }
  1745.  
  1746.   public void removeModelListener(MatrixModelListener listener) {
  1747.     modelListeners.remove(listener);
  1748.     //  borland.jbcl.model.MatrixModel method;
  1749.   }
  1750.  
  1751.   protected void processModelEvent(MatrixModelEvent e) {
  1752.     if (events && modelListeners.hasListeners())
  1753.       modelListeners.dispatch(e);
  1754.   }
  1755.  
  1756.   private EventMulticaster modelListeners = new EventMulticaster();
  1757.   private boolean events = true;
  1758. }
  1759.  
  1760.  
  1761.