/* * PP.java * Assignment for the Path planning part of the ZSB lab course. * * This you will work on writing a function called highPath() to move a * chesspiece across the board at a safe height. By raising the gripper 20 cm * above the board before moving it over the board you don't risk hitting any * other pieces on the board. This means you don't have to do any pathplanning * yet. * * Input of this program are two commandline arguments, the first one * describing the human (white) move and the second denoting the computer * (black) move. The human has been executed by the human and can be ignored. * Your job is to find the correct sequence of GripperPositions (stored in * Vector p) to pick up the correct black piece and deposit it at its desired * new location. Read file /opt/stud/robotics/hints/HIGHPATH_POSITIONS to see * what intermediate positions you should calculate. * * To run your program, fire up playchess and the umirtxsimulator. In * the simulator you can see the effect of your path planning although * the board itself is not simulated. When you think you've solved * this assignment ask one of the lab assistents to verify it and let * it run on the real robot arm. * * Nikos Massios, Matthijs Spaan * $Id: Week2.java,v 1.9 2004/05/31 19:49:35 mtjspaan Exp $ */ import java.io.*; import java.lang.*; import java.util.Vector; import tio.*; public class PP { public static void main(String[] args){ ChessBoard b = new ChessBoard(); DamBord d = new DamBord(); Vector p = new Vector(); /* Read the board state*/ b.read(); /* print the board state*/ // b.print(); System.out.println("\n\n===================="); System.out.println("Dammen:"); System.out.println("===================="); System.out.println("Huidig bord:"); d.Read(); d.Display(); String move; boolean valid = false; while (!valid) { System.out.println("Geef U move..."); move = Console.in.readWord(); valid = d.isLegal(move, "white"); if (!valid) System.out.println("Invalid move!"); } d.commit(move, "white", p, b); d.generate(p, b); System.out.println("**** The board after the move was:"); /* print the board state*/ d.Display(); d.Write(); System.out.println("\n\n===================="); System.out.println("Klaar met zetten; negeer schaken A.U.B. =P "); System.out.println("===================="); /* after done write the gripper positions */ GripperPosition.write(p); } } class DamBord { private static double SAFE_HEIGHT=200; private static double LOW_HEIGHT=40; private static double OPEN_GRIP=30; private static double CLOSED_GRIP=0; private static double LOW_PATH_HEIGHT=20; /** Creates a new instance of DamBord */ public DamBord() { bord = new int[8][8]; for(int a = 0; a<8;a++) for(int b = 0; b<8; b++) bord[a][b] = 0; } public boolean isLegal(String move, String side) { int direction = 0; if (side == "white") direction = 1; // Legal moves are up else if (side == "black") direction = -1; // Legal moves are down else return false; // No side; can't be legal Vector moveList; makeLoc(move, moveList); // moveList is all the moves, in BoardLocations /* Check for each step, if it is legal. A step consists of two * BoardLocations: To, and From. We start at index 0, and move * to moveList.size() - 1, because we skip the last index. We * check in pairs of two. */ BoardLocation2 from = (BoardLocation2) moveList.get(0); BoardLocation2 to; int tX; int tY; int status = 0; // Check if start is legal. column + row must be an even number if ((from.column + from.row) % 2 != 0) return false; // Check if we are moving a piece of our own if (side == "black" && bord[from.column][from.row] != 2) return false; if (side == "white" && bord[from.column][from.row] != 1) return false; // Iterate through move list for (int x = 0; x < moveList.size() - 1; x++) { from = (BoardLocation2) moveList.get(x); to = (BoardLocation2) moveList.get(x+1); // Are positions legal? if ((to.column + to.row) %2 != 0) return false; // Single steps if (from.row - to.row == -1 || from.row - to.row == 1) { // Have we taken any step before? If yes; illegal if (status != 0) return false; // Do we move 1 step amongst X as well? If not; illegal if (from.column - to.column != -1 && from.column - to.column != 1) return false; // Then... is it forward? If not; illegal if (from.row - to.row != direction) return false; // Otherwise, is target square empty? If not; illegal if (bord[to.column][to.row] != 0) return false; // Well, this step is legal. Continue =) status = 1; // We have taken a single step } // Jumps else if (from.row - to.row == -2 || from.row - to.row == 2) { // Have we taken a single step before? If yes; illegal if (status == 1) return false; // Do we move 2 steps amongst X as well? If not; illegal if (from.column - to.column != -2 && from.column - to.column != 2) return false; // Forward is not an issue... but an opponent has to be in between // So first, we need the 'in between' square tX = (from.column - to.column) / 2; tY = (from.row - to.row) / 2; if (side == "white" && bord[tX][tY] != 2) return false; if (side == "black" && bord[tX][tY] != 1) return false; // Is target square empty? if (bord[to.column][to.row] != 0) return false; status = 2; // We have taken a double step } // Not a legal move... thus. Move is not allowed. else return false; } // Every move has been deemed legal, thus, the entire set is legal return true; } public void commit(String move, String side, Vector p, ChessBoard b) { // Turn the move list into a BoardLocation vector Vector l; makeLoc(move, l); BoardLocation2 from; BoardLocation2 to; for (int a = 0; a < l.size() - 1; a++) { from = (BoardLocation2) l.get(a); to = (BoardLocation2) l.get(a+1); highPath(sPos(from, to, b, p)); if (from.row - to.row == 2 || from.row - to.row == -2) { // Something has to be thrown into garbage from = new BoardLocation2(sPos(from.row-to.row, from.column-to.column)); toGarbage(from, b, p); } } // We already know the move is legal; otherwise, it shouldn't be committed =P } private static String sPos(int row, int column) { char c = (char)(column + 97); char r = (char)(row + 49); String s = String.valueOf(c) + String.valueOf(r); return s; } private void makeLoc(String move, Vector l) { String temp; BoardLocation2 t; for (int a = 0; a < move.length() - 2 ; a += 2) { temp = move.substring(a, a + 2); // Take an 'e4' pair t = new BoardLocation2(temp); // Make it a BoardLocation '3,4' l.add(t); // Stuff in Vector =P } } public void Reset() { boolean even = true; for(int a = 0; a<3; a++) { for(int b = 0; b<7; b = b + 2) { if(even) bord[a][b + 1] = 1; else bord[a][b] = 1; } if(even) even = false; else even = true; } for(int a = 5; a<8; a++) { for(int b = 0; b<7; b = b + 2) { if(even) bord[a][b + 1] = 2; else bord[a][b] = 2; } if(even) even = false; else even = true; } } public void Write() { try { DataOutputStream out = new DataOutputStream(new FileOutputStream("board.dat")); for(int a = 0; a<8; a++) for(int b = 0; b<8; b++) out.writeInt(bord[a][b]); out.close(); } catch ( IOException iox ) { System.out.println("Problem writing"); } } public void Read() { try { DataInputStream in = new DataInputStream(new FileInputStream("board.dat")); for(int a = 0; a<8; a++) for(int b = 0; b<8; b++) { bord[a][b] = in.readInt(); //System.out.println(bord[a][b]); } in.close(); } catch(IOException EOFException) { System.out.println("EOF Error!!!"); System.out.println("Nieuw bord wordt gemaakt..."); Reset(); System.out.println("Nieuw bord wordt naar bestand geschreven..."); Write(); } } public void Display() { System.out.println(); System.out.println(); for (int a = 0; a<8; a++) { for(int b = 0; b < 8; b++) System.out.print(" " + bord[a][b]); System.out.println(); } } public void generate(Vector p, ChessBoard b) { // The goal is to call GenMove for every square on the board. // Each GenMove tree will return a score value for the best move, // and a vector that has the steps of said move. Gen Move only // looks for doublesteps. Vector bestMoves; Vector tL; int bS = 0; int tS; BoardLocation2 current; BoardLocation2 old; BoardLocation2 best; int a, b; for (a = 0; a < 8; a++) { for (b = 0; b < 8; b++) { if (bord[a][b] == 2) { current = new BoardLocation2(a, b); old = new BoardLocation2(-1, -1); tS = GenMove(current, old, 0, tL); if (tS > bS) { bS = tS; bestMoves = tL; best = new BoardLocation2(a, b); } } } } boolean s = false; if (bS == 0) // No pieces can be taken! { bestMoves = new Vector(); for (a = 0; a < 8 && !s ; a++) { for (b = 0; b < 8 && !s; b++) { if (bord[a][b] == 2) { if (bord[a-1][b-1] == 0) { s = true; best = new BoardLocation2(a-1, b-1); bestMoves = new Vector(); bestMoves.add(best); } else if (bord[a+1][b-1] == 0) { s = true; best = new BoardLocation2(a+1, b-1); bestMoves = new Vector(); bestMoves.add(best); } } } } } // Alright. We have a vector now, 'bestMoves', that consists of a // list of BoardLocation2's that we want to visit. Now we just have // to turn this into a string, and pass this string on to the // commit function ^-^;;; String compMove = makeMove(bestMoves); commit(compMove, "black", p, b); } private String makeMove(Vector l) { if (l.size() == 0) return(" "); BoardLocation2 b; String r; // Moves are put in the list backwards! First move is at the end for (int a = l.size(); a >= 0; a++) { b = (BoardLocation2) l.get(a); r += sPos(b.row, b.column); } return r; } private int GenMove(BoardLocation2 current, BoardLocation2 old, int ply, Vector list) { BoardLocation2 next; // 'Killswitch' if (ply == 100) return 0; int bD = 0; int bS = 0; Vector moveList; Vector temp; int tS; for (int a = 1; a <= 4; a++) { next = new BoardLocation2(current.column, current.row); GenNew(next, a); if (next.column != current.column && next.row != current.row) { if (bord[next.column][next.row] == 1) { // Possible jump! GenNew(next, a); if (bord[next.column][next.row] == 0) { // Jump! temp = new Vector(); tS = GenMove(next, current, ply+1, temp); if (tS > bS) { bS = tS; bD = a; moveList = temp; } } } } } // bD is now the most successful direction. bS the highest score // No move can be made if (bD == 0) { list = new Vector(); return 0; } // A move can be made! The vector list will have all the moves. // The return value is the score attached to this list else { list = moveList; next = new BoardLocation2(current.column, current.row); GenNew(next, bD); list.add(next); return bS; } } // Turn a location and a direction into a new location private void GenNew(BoardLocation2 a, int d) { if (d == 1) { a.row++; a.column++; } else if (d == 2) { a.row--; a.column++; } else if (d == 3) { a.row--; a.column--; } else if (d == 4) { a.row++; a.column--; } } private static void highPath(String from, String to, ChessBoard b, Vector p){ System.out.println("**** In high path"); try { BoardLocation2 f_pos = new BoardLocation2(from); BoardLocation2 t_pos = new BoardLocation2(to); Point tPoint; double pHeight = 15; double bH = b.board_thickness; double bDX = -b.sur_x; double bDY = b.sur_y; GripperPosition tGripper; // Step one tPoint = b.toCartesian(f_pos.row, f_pos.column); tPoint.x += bDX; tPoint.y += bDY; tPoint.z = SAFE_HEIGHT+bH; tGripper = new GripperPosition(tPoint, 0, OPEN_GRIP); p.add(tGripper); // Step two tPoint.z = LOW_HEIGHT+bH; tGripper = new GripperPosition(tPoint, 0, OPEN_GRIP); p.add(tGripper); // Step three tPoint.z = pHeight+bH; tGripper = new GripperPosition(tPoint, 0, OPEN_GRIP); p.add(tGripper); // Step four tGripper = new GripperPosition(tPoint, 0, CLOSED_GRIP); p.add(tGripper); // Step five tPoint.z = SAFE_HEIGHT+bH; tGripper = new GripperPosition(tPoint, 0, CLOSED_GRIP); p.add(tGripper); // Step six tPoint = b.toCartesian(t_pos.row, t_pos.column); tPoint.x += bDX; tPoint.y += bDY; tPoint.z = SAFE_HEIGHT+bH; tGripper = new GripperPosition(tPoint, 0, CLOSED_GRIP); p.add(tGripper); // Step seven tPoint.z = LOW_HEIGHT+bH; tGripper = new GripperPosition(tPoint, 0, CLOSED_GRIP); p.add(tGripper); // Step eight tPoint.z = pHeight+bH; tGripper = new GripperPosition(tPoint, 0, CLOSED_GRIP); p.add(tGripper); // Step nine tGripper = new GripperPosition(tPoint, 0, OPEN_GRIP); p.add(tGripper); // Step ten tPoint.z = SAFE_HEIGHT+bH; tGripper = new GripperPosition(tPoint, 0, OPEN_GRIP); p.add(tGripper); } catch (ChessBoard.NoPieceAtPositionException e) { System.out.println(e); System.exit(1); } // ???? Write this function // Use the boardLocation and toCartesian methods you wrote last week. /* Example of adding a gripperposition to Vector p. * Point tempPoint; * GripperPosition temp; * tempPoint = new Point(x-coordinate, y-coordinate, z-coordinate); * temp = new GripperPosition(tempPoint, angle, CLOSED_GRIP/OPEN_GRIP); * Now you only have to add it at the end of Vector p. */ } private static void moveToGarbage(String from, ChessBoard b, Vector g){ /* When you're done with highPath(), incorporate this function. * It should remove a checked piece from the board. * In main() you have to detect if the computer move checks a white * piece, and if so call this function to remove the white piece from * the board first. */ // Bit of additional code, to determine number of // dead pieces. There should be 16 pieces on the board // and any not on the board, are to the side. int z = 0; for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { if (bord[x][y] > 0) z++; } } z = 16 - z; System.out.println("**** In moveToGarbage"); int number = z; int offset; for (offset = 9; number > 7; number = number - 8) { offset++; } String to = sPos(number, offset); highPath(from, to, b, g); } int[][] bord; } class BoardLocation2{ public int row; public int column; public BoardLocation2(int x, int y) { column = x; row = y; } public BoardLocation2(String position) { // write this function column = position.charAt(0) - 97; row = position.charAt(1) - 49; } }