/////////////////////////////////////// // MuehleState.java // Position und Zuege fuer M|hle import java.awt.*; import java.applet.*; import GameState; //import muehleCoordinate; class muehleCoordinate { int x; int y; int z; // muehleCoordinate () { // } public muehleCoordinate get_muehleCoordinate ( int field ){ muehleCoordinate point = new muehleCoordinate (); switch ( field ){ case 1: point.x = 0; point.y = 0; point.z = 0; break; case 2: point.x = 1; point.y = 0; point.z = 0; break; case 3: point.x = 2; point.y = 0; point.z = 0; break; case 4: point.x = 0; point.y = 0; point.z = 1; break; case 5: point.x = 1; point.y = 0; point.z = 1; break; case 6: point.x = 2; point.y = 0; point.z = 1; break; case 7: point.x = 0; point.y = 0; point.z = 2; break; case 8: point.x = 1; point.y = 0; point.z = 2; break; case 9: point.x = 2; point.y = 0; point.z = 2; break; case 10: point.x = 0; point.y = 1; point.z = 0; break; case 11: point.x = 0; point.y = 1; point.z = 1; break; case 12: point.x = 0; point.y = 1; point.z = 2; break; case 13: point.x = 2; point.y = 1; point.z = 2; break; case 14: point.x = 2; point.y = 1; point.z = 1; break; case 15: point.x = 2; point.y = 1; point.z = 0; break; case 16: point.x = 0; point.y = 2; point.z = 2; break; case 17: point.x = 1; point.y = 2; point.z = 2; break; case 18: point.x = 2; point.y = 2; point.z = 2; break; case 19: point.x = 0; point.y = 2; point.z = 1; break; case 20: point.x = 1; point.y = 2; point.z = 1; break; case 21: point.x = 2; point.y = 2; point.z = 1; break; case 22: point.x = 0; point.y = 2; point.z = 0; break; case 23: point.x = 1; point.y = 2; point.z = 0; break; case 24: point.x = 2; point.y = 2; point.z = 0; break; } return point; } public int get_field ( muehleCoordinate point ){ int field = 0; switch ( point.x ){ case 0: switch ( point.y ){ case 0: switch ( point.z ){ case 0: field = 1; break; case 1: field = 4; break; case 2: field = 7; break; } break; case 1: switch ( point.z ){ case 0: field = 10; break; case 1: field = 11; break; case 2: field = 12; break; } break; case 2: switch ( point.z ){ case 0: field = 22; break; case 1: field = 19; break; case 2: field = 16; break; } break; } break; case 1: switch ( point.y ){ case 0: switch ( point.z ){ case 0: field = 2; break; case 1: field = 5; break; case 2: field = 8; break; } break; case 1: switch ( point.z ){ case 0: field = 0; break; case 1: field = 0; break; case 2: field = 0; break; } break; case 2: switch ( point.z ){ case 0: field = 23; break; case 1: field = 20; break; case 2: field = 17; break; } break; } break; case 2: switch ( point.y ){ case 0: switch ( point.z ){ case 0: field = 3; break; case 1: field = 6; break; case 2: field = 9; break; } break; case 1: switch ( point.z ){ case 0: field = 15; break; case 1: field = 14; break; case 2: field = 13; break; } break; case 2: switch ( point.z ){ case 0: field = 24; break; case 1: field = 21; break; case 2: field = 18; break; } break; } break; } return field; } } class MuehleState extends GameState { static final int EMPTY = 0; static final int WHITE = 1; static final int BLACK = -1; static final int SET = 1; static final int MOVE = 0; static final int DEL = -1; static final int Mensch=1, Computer=-1; protected int[][][] A; // x, y, z (0 = leer, 1, -1), 3d-Reprdsentation // des Spielfeldes protected int activeColor; // "Farbe" (1 bzw. -1) am Zug protected int nmoves; protected int status; protected int lastMove; protected int nstones[] = new int[2]; // Anzahl der Steine auf Brett protected int nbunker[] = new int[2]; // Anzahl der Steine im Bunker MuehleState () { A = new int[3][3][3]; status = SET; nmoves = 24; // 24 mvgliche Z|ge am Anfang } private int sigma ( int x ){ if ( x < 0 ){ return 0; } else { return 1; } } public void reset (int color) { for (int x=0; x<3; x++) { for (int y=0; y<3; y++){ for ( int z=0; z<3; z++){ A[x][y][z] = EMPTY; } } } activeColor = color; nmoves = 24; status = SET; nstones[0] = 0; nstones[1] = 0; nbunker[0] = 9; nbunker[1] = 9; } private boolean muehle ( muehleCoordinate position ) { boolean result = false; if ( position.x != 1 ) { result = result || ( sumOfRow ( position, 'y', A[position.x][position.y][position.z] ) == 3); } else { if ( position.y != 1 ) { result = result || ( sumOfRow ( position, 'z', A[position.x][position.y][position.z] ) == 3); } } if ( position.y != 1 ) { result = result || ( sumOfRow ( position, 'x', A[position.x][position.y][position.z] ) == 3); } else { if ( position.x != 1 ) { result = result || ( sumOfRow ( position, 'z', A[position.x][position.y][position.z] ) == 3); } } return result; } private int sumOfRow ( muehleCoordinate position, char direction, int color ) { int sum = 0; switch ( direction ) { case 'x': for ( int run = 0; run < 3; run++ ) { if ( A[run][position.y][position.z] == color ) { sum++; } } break; case 'y': for ( int run = 0; run < 3; run++ ) { if ( A[position.x][run][position.z] == color ) { sum++; } } break; case 'z': for ( int run = 0; run < 3; run++ ) { if ( A[position.x][position.y][run] == color ) { sum++; } } break; } return sum; } private int numberOfRemovables (int color) { int x, y, z, counter = 0; muehleCoordinate position = new muehleCoordinate (); for ( x = 0; x < 3; x++ ) { for ( y = 0; y < 3; y++ ) { for ( z = 0; z < 3; z++ ) { if ( ( (x != 1) || (y != 1) ) && ( A[x][y][z] == color ) ) { position.x = x; position.y = y; position.z = z; if ( ! muehle ( position ) ) { counter++; } } } } } return counter; } private muehleCoordinate positionOfRemovable (int color, int number) { int x, y, z, counter = 0; muehleCoordinate position = new muehleCoordinate (); for ( x = 0; x < 3; x++ ) { for ( y = 0; y < 3; y++ ) { for ( z = 0; z < 3; z++ ) { if ( ( (x != 1) || (y != 1) ) && ( A[x][y][z] == color ) ) { position.x = x; position.y = y; position.z = z; if ( ! muehle ( position ) ) { counter++; if ( counter == number ) { return position; } } } } } } position.x = position.y = position.z = 9; return position; } private int numberOfFreeCells () { int x, y, z, counter = 0; muehleCoordinate position = new muehleCoordinate (); for ( x = 0; x < 3; x++ ) { for ( y = 0; y < 3; y++ ) { for ( z = 0; z < 3; z++ ) { if ( ( (x != 1) || (y != 1) ) && ( A[x][y][z] == EMPTY ) ) { counter++; } } } } return counter; } private muehleCoordinate positionOfFreeCell ( int number) { int x, y, z, counter = 0; muehleCoordinate position = new muehleCoordinate (); for ( x = 0; x < 3; x++ ) { for ( y = 0; y < 3; y++ ) { for ( z = 0; z < 3; z++ ) { if ( ( (x != 1) || (y != 1) ) && ( A[x][y][z] == EMPTY ) ) { position.x = x; position.y = y; position.z = z; counter++; if ( counter == number ) { return position; } } } } } position.x = position.y = position.z = 9; return position; } private int numberOfStones (int color) { int x, y, z, counter = 0; muehleCoordinate position = new muehleCoordinate (); for ( x = 0; x < 3; x++ ) { for ( y = 0; y < 3; y++ ) { for ( z = 0; z < 3; z++ ) { if ( ( (x != 1) || (y != 1) ) && ( A[x][y][z] == color ) ) { counter++; } } } } return counter; } private muehleCoordinate positionOfStone (int color, int number) { int x, y, z, counter = 0; muehleCoordinate position = new muehleCoordinate (); for ( x = 0; x < 3; x++ ) { for ( y = 0; y < 3; y++ ) { for ( z = 0; z < 3; z++ ) { if ( ( (x != 1) || (y != 1) ) && ( A[x][y][z] == color ) ) { position.x = x; position.y = y; position.z = z; counter++; if ( counter == number ) { position.x = x; position.y = y; position.z = z; return position; } } } } } position.x = position.y = position.z = 9; return position; } public int nMoves () { int i, j, nStones, nFree, counter, fromField, toField = 0; counter = 0; muehleCoordinate from, to; boolean ismuehle; if ( nbunker [sigma ( activeColor )] == 0 ) { nStones = numberOfStones ( activeColor ); nFree = numberOfFreeCells (); for ( i = 1; i <= nStones; i++ ) { from = positionOfStone ( activeColor, i ); fromField = from.get_field ( from ); for ( j = 1; j <= nFree; j++ ) { to = positionOfFreeCell ( j ); toField = to.get_field ( to ); if ( isValidMove ( fromField, toField ) ) { ismuehle = false; if ( to.x != 1 ) { if ( sumOfRow ( to, 'y', activeColor ) == 2 ) { ismuehle = true; } } else { if ( to.y != 1 ) { if ( sumOfRow ( to, 'z', activeColor ) == 2 ) { ismuehle = true; } } } if ( to.y != 1 ) { if ( sumOfRow ( to, 'x', activeColor ) == 2 ) { ismuehle = true; } } else { if ( to.x != 1 ) { if ( sumOfRow ( to, 'z', activeColor ) == 2 ) { ismuehle = true; } } } if ( ismuehle ) { counter = counter + numberOfRemovables ( -activeColor ); } else { counter++; } } } } } else { nFree = numberOfFreeCells (); for ( j = 1; j <= nFree; j++ ) { to = positionOfFreeCell ( j ); ismuehle = false; if ( to.x != 1 ) { if ( sumOfRow ( to, 'y', activeColor ) == 2 ) { ismuehle = true; } } else { if ( to.y != 1 ) { if ( sumOfRow ( to, 'z', activeColor ) == 2 ) { ismuehle = true; } } } if ( to.y != 1 ) { if ( sumOfRow ( to, 'x', activeColor ) == 2 ) { ismuehle = true; } } else { if ( to.x != 1 ) { if ( sumOfRow ( to, 'z', activeColor ) == 2 ) { ismuehle = true; } } } if ( ismuehle ) { counter = counter + numberOfRemovables ( -activeColor ); } else { counter++; } } } return counter; } public muehleCoordinate movePosition (int number) { int i, j, nStones, nFree, fromField, toField, counter = 0; muehleCoordinate from = new muehleCoordinate (); muehleCoordinate to = new muehleCoordinate (); muehleCoordinate result = new muehleCoordinate (); boolean ismuehle; number++; if ( nbunker [sigma ( activeColor )] == 0 ) { nStones = numberOfStones ( activeColor ); nFree = numberOfFreeCells (); for ( i = 1; i <= nStones; i++ ) { from = positionOfStone ( activeColor, i ); fromField = from.get_field ( from ); for ( j = 1; j <= nFree; j++ ) { to = positionOfFreeCell ( j ); toField = to.get_field ( to ); if ( isValidMove ( fromField, toField ) ) { ismuehle = false; if ( to.x != 1 ) { if ( sumOfRow ( to, 'y', activeColor ) == 2 ) { ismuehle = true; } } else { if ( to.y != 1 ) { if ( sumOfRow ( to, 'z', activeColor ) == 2 ) { ismuehle = true; } } } if ( to.y != 1 ) { if ( sumOfRow ( to, 'x', activeColor ) == 2 ) { ismuehle = true; } } else { if ( to.x != 1 ) { if ( sumOfRow ( to, 'z', activeColor ) == 2 ) { ismuehle = true; } } } if ( ismuehle ) { if ( number <= counter + numberOfRemovables ( -activeColor ) ) { result.x = from.get_field ( from ); result.y = to.get_field ( to ); result.z = result.get_field ( positionOfRemovable ( -activeColor, number - counter ) ); return result; } counter = counter + numberOfRemovables ( -activeColor ); } else { counter++; if ( number == counter ) { result.x = from.get_field ( from ); result.y = to.get_field ( to ); result.z = 0; return result; } } } } } } else { nFree = numberOfFreeCells (); for ( j = 1; j <= nFree; j++ ) { to = positionOfFreeCell ( j ); ismuehle = false; if ( to.x != 1 ) { if ( sumOfRow ( to, 'y', activeColor ) == 2 ) { ismuehle = true; } } else { if ( to.y != 1 ) { if ( sumOfRow ( to, 'z', activeColor ) == 2 ) { ismuehle = true; } } } if ( to.y != 1 ) { if ( sumOfRow ( to, 'x', activeColor ) == 2 ) { ismuehle = true; } } else { if ( to.x != 1 ) { if ( sumOfRow ( to, 'z', activeColor ) == 2 ) { ismuehle = true; } } } if ( ismuehle ) { if ( number <= counter + numberOfRemovables ( -activeColor ) ) { result.x = 0; result.y = to.get_field ( to ); result.z = result.get_field ( positionOfRemovable ( -activeColor, number - counter ) ); return result; } counter = counter + numberOfRemovables ( -activeColor ); } else { counter++; if ( number == counter ) { result.x = 0; result.y = to.get_field ( to ); result.z = 0; return result; } } } } return result; } private int lineValue (int a, int b, int c, int mode ){ int val = 0; muehleCoordinate a3d = new muehleCoordinate (); a3d = a3d.get_muehleCoordinate ( a ); muehleCoordinate b3d = new muehleCoordinate (); b3d = b3d.get_muehleCoordinate ( b ); muehleCoordinate c3d = new muehleCoordinate (); c3d = c3d.get_muehleCoordinate ( c ); int num = ( A[a3d.x][a3d.y][a3d.z] ) + ( A[b3d.x][b3d.y][b3d.z] ) + ( A[c3d.x][c3d.y][c3d.z] ); if ( num == ( 3 * WHITE ) ){ val += 100; // weisse M|hle an dieser Position } if ( num == ( 2 * WHITE ) ){ val += 20; // weisse Chance auf M|hle } if ( num == ( 1 * WHITE ) ){ val += 5; // 1 Stein von Wei_, oder 2 von Weiss und 1 von Schwarz } if ( num == ( 1 * BLACK ) ){ val -= 5; // 1 Stein von Schwarz, oder 1 von Weiss und 2 von Schwarz } if ( num == ( 2 * BLACK ) ){ val -= 20; // Chance auf M|hle f|r Schwarz } if ( num == ( 3 * BLACK ) ){ val -= 100; // M|hle an dieser Position f|r Schwarz } return val; } protected int value (int mode) { int val = 0; if ( won () == WHITE ){ val = 10000; } else { if ( won () == BLACK ){ val = -10000; } } // 16 mvgliche M|hlepositionen durchlaufen val += lineValue ( 1, 2, 3, mode ); val += lineValue ( 4, 5, 6, mode ); val += lineValue ( 7, 8, 9, mode ); val += lineValue ( 10, 11, 12, mode ); val += lineValue ( 13, 14, 15, mode ); val += lineValue ( 16, 17, 18, mode ); val += lineValue ( 19, 20, 21, mode ); val += lineValue ( 22, 23, 24, mode ); val += lineValue ( 1, 10, 22, mode ); val += lineValue ( 4, 11, 19, mode ); val += lineValue ( 7, 12, 16, mode ); val += lineValue ( 2, 5, 8, mode ); val += lineValue ( 17, 20, 23, mode ); val += lineValue ( 9, 13, 18, mode ); val += lineValue ( 6, 14, 21, mode ); val += lineValue ( 3, 15, 24, mode ); // Anzahl Steine auf Brett val += 50 * nstones[ sigma ( WHITE ) ]; // weisse Steine val -= 50 * nstones[ sigma ( BLACK ) ]; // schwarze Steine return -val; } public int value () {return value (0);} public void copy (MuehleState source) { for (int x=0; x<3; x++) { for (int y=0; y<3; y++){ for ( int z=0; z<3; z++) A[x][y][z] = source.A[x][y][z]; } } nmoves = source.nmoves; activeColor = source.activeColor; nbunker[0] = source.nbunker[0]; nbunker[1] = source.nbunker[1]; nstones[0] = source.nstones[0]; nstones[1] = source.nstones[1]; } public GameState move (int i) { MuehleState state = new MuehleState (); state.copy (this); muehleCoordinate move_v_n_l = new muehleCoordinate (); move_v_n_l = movePosition ( i ); state.doMove ( move_v_n_l.x, move_v_n_l.y ); if ( state.status == DEL ){ state.doRemove ( move_v_n_l.z ); } return state; } public void doMove (int von, int nach) { muehleCoordinate von3d = new muehleCoordinate (); muehleCoordinate nach3d = new muehleCoordinate (); von3d = von3d.get_muehleCoordinate ( von ); nach3d = nach3d.get_muehleCoordinate ( nach ); if ( von != 0 ){ A[von3d.x][von3d.y][von3d.z] = EMPTY; } else { nstones[sigma(activeColor)]++; nbunker[sigma(activeColor)]--; } A[nach3d.x][nach3d.y][nach3d.z] = activeColor; if ( muehle ( nach3d ) ) { status = DEL; } else { activeColor = - activeColor; if ( nbunker[sigma(activeColor)] > 0 ) { status = SET; } else { status = MOVE; } } } public boolean isValidMove (int von, int nach) { muehleCoordinate nach3d = new muehleCoordinate (); muehleCoordinate von3d = new muehleCoordinate (); muehleCoordinate diff = new muehleCoordinate (); // Differenzvektor nach3d = nach3d.get_muehleCoordinate ( nach ); von3d = von3d.get_muehleCoordinate ( von ); if ( A[nach3d.x][nach3d.y][nach3d.z] != EMPTY ) { return false; } if ( ( nbunker[sigma(activeColor)] > 0 ) && ( A[nach3d.x][nach3d.y][nach3d.z] == EMPTY ) ) { return true; } if ( ( nstones[sigma(activeColor)] == 3 ) && ( A[nach3d.x][nach3d.y][nach3d.z] == EMPTY ) ) { return true; } diff.x = Math.abs ( von3d.x - nach3d.x ); diff.y = Math.abs ( von3d.y - nach3d.y ); diff.z = Math.abs ( von3d.z - nach3d.z ); if ( ( diff.x + diff.y + diff.z ) != 1 ) { return false; } if ( diff.z != 1 ) { return true; } if ( ( ( von3d.x == 0 ) || ( von3d.x == 2 ) ) && ( ( von3d.y == 0 ) || ( von3d.y == 2 ) ) ) { return false; } return true; } public boolean doRemove (int position) { muehleCoordinate position3d = new muehleCoordinate (); position3d = position3d.get_muehleCoordinate ( position ); if ( muehle (position3d) ) { // aus M|hlen darf nicht weggenommen werden! if ( nstones[ sigma (activeColor) ] > 3) { return false; } else { activeColor = -activeColor; if ( nbunker[sigma(activeColor)] == 0 ) { status = MOVE; } else { status = SET; } // nstones[sigma(activeColor)]--; return true; } } else { activeColor = -activeColor; A[position3d.x][position3d.y][position3d.z] = EMPTY; if ( nbunker[sigma(activeColor)] == 0 ) { status = MOVE; } else { status = SET; } nstones[sigma(activeColor)]--; return true; } } public int won () { if ( ( nbunker[0] != 0 ) || ( nbunker[1] != 0 ) ) { return EMPTY; } if ( nstones[sigma(WHITE)] < 3 ) { return BLACK; } if ( nstones[sigma(BLACK)] < 3 ) { return WHITE; } return EMPTY; } public int positionColor (int position) { muehleCoordinate position3d = new muehleCoordinate (); position3d = position3d.get_muehleCoordinate ( position ); return A[position3d.x][position3d.y][position3d.z]; } public int getState () { return status; } // Funktionen paint und column kommen in Muehle.java // int column (Applet app, int x) { // public void paint (Applet app, Graphics g) { }