home *** CD-ROM | disk | FTP | other *** search
/ PC World 1998 October / PCWorld_1998-10_cd.bin / software / prehled / inprise / JSAMPLES.Z / ChessRules.java < prev    next >
Text File  |  1998-05-08  |  59KB  |  1,782 lines

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