/*	ShogiBoard.java		a shogi board	97-feb-26 ped created*/import java.util.* ;public class ShogiBoard implements Enum_ShogiPieces{	public void dump( )	{		String piece[ ] = {			" -",			" P", " L", " N", " S", " G", " B", " R", " K",			"+P", "+L", "+N", "+S", "??", "+B", "+R", "??",			" p", " l", " n", " s", " g", " b", " r", " k",			"+p", "+l", "+n", "+s", "??", "+b", "+r", "??"		} ;		for( int j = 8 ; j >= 0 ; j -- ) {			for( int i = 0 ; i < 9 ; i ++ )				System.out.print( piece[ square[ i ][ j ] ] + " " ) ;			System.out.println( " : " + ( j + 1 ) ) ;		}				for( int i = 0 ; i < 2 ; i ++ ) {			for( int j = 0 ; j < 7 ; j ++ )				System.out.print( hand[ i ][ j ] ) ;			System.out.print( " " ) ;		}	}	private int square[ ][ ] = {		{ SL, EM, SP, EM, EM, EM, GP, EM, GL },		{ SN, SB, SP, EM, EM, EM, GP, GR, GN },		{ SS, EM, SP, EM, EM, EM, GP, EM, GS },		{ SG, EM, SP, EM, EM, EM, GP, EM, GG },		{ SK, EM, SP, EM, EM, EM, GP, EM, GK },		{ SG, EM, SP, EM, EM, EM, GP, EM, GG },		{ SS, EM, SP, EM, EM, EM, GP, EM, GS },		{ SN, SR, SP, EM, EM, EM, GP, GB, GN },		{ SL, EM, SP, EM, EM, EM, GP, EM, GL },	} ;	private int hand[ ][ ] = {  		{ 0, 0, 0, 0, 0, 0, 0 },		{ 0, 0, 0, 0, 0, 0, 0 }	} ;	private boolean senteToMove = true ;	static int globalPly = 0 ;		//	ugly kludge, set by constructor...	ShogiBoard( )	{		globalPly = 0 ;	}		ShogiBoard( String str )	{		String handicap[ ] = {			"Lance", "Right Lance", "Bishop", "Rook", "Rook and Lance", "2 Piece",			"3 Piece", "4 Piece", "5 Piece", "6 Piece", "7 Piece", "8 Piece"		} ;		for( int i = 0 ; i < 12 ; i ++ ) {			if( str.equalsIgnoreCase( handicap[ i ] ) ) {				senteToMove = false ;				globalPly	= 1 ;				switch( i ) {									case 11 :						//	8 piece						square[ 2 ][ 8 ] = EM ;					case 10 :						//	7 piece						square[ 6 ][ 8 ] = EM ;					case  9 :						//	6 piece						square[ 1 ][ 8 ] = EM ;					case  8 :						//	5 piece						square[ 7 ][ 8 ] = EM ;					case  7 :						//	4 piece						square[ 0 ][ 8 ] = EM ;					case  6 :						//	3 piece						square[ 8 ][ 8 ] = EM ;					case  5 :						//	2 piece						square[ 7 ][ 7 ] = EM ;					case  3 :						//	Rook						square[ 1 ][ 7 ] = EM ;						return ;					case  4 :						//	Rook and Lance						square[ 1 ][ 7 ] = EM ;					case  0 :						//	Lance						square[ 8 ][ 8 ] = EM ;						return ;											case  2 :						//	Bishop						square[ 7 ][ 7 ] = EM ;						return ;										case  1 :						//	Right Lance						square[ 0 ][ 8 ] = EM ;						return ;				}			}		}				//	process FEN		int	FENindex = 0 ;		hand[ 1 ][ 0 ] = 18 ;		hand[ 1 ][ 1 ] =  4 ;		hand[ 1 ][ 2 ] =  4 ;		hand[ 1 ][ 3 ] =  4 ;		hand[ 1 ][ 4 ] =  4 ;		hand[ 1 ][ 5 ] =  2 ;		hand[ 1 ][ 6 ] =  2 ;		for( int rank = 8 ; rank >= 0 ; rank -- ) {			//	debug			System.out.println( str.substring( FENindex ) ) ;						for( int file = 0 ; file <= 8 ; file ++ ) {				char ch = str.charAt( FENindex ++ ) ;				if( Character.isDigit( ch ) ) {					int count = ch - '0' ;					while( count -- > 0 )						square[ file ++ ][ rank ] = EM ;					if( file > 8 )						break ;					ch = str.charAt( FENindex ++ ) ;				}				boolean promoted = false ;				if( ch == '+' ) {					promoted = true ;					ch = str.charAt( FENindex ++ ) ;				}				switch( Character.toUpperCase( ch ) ) {					case 'P' :	square[ file ][ rank ] = SP ;	hand[ 1 ][ 0 ] -- ;		break ;					case 'L' :	square[ file ][ rank ] = SL ;	hand[ 1 ][ 1 ] -- ;		break ;					case 'N' :	square[ file ][ rank ] = SN ;	hand[ 1 ][ 2 ] -- ;		break ;					case 'S' :	square[ file ][ rank ] = SS ;	hand[ 1 ][ 3 ] -- ;		break ;					case 'G' :	square[ file ][ rank ] = SG ;	hand[ 1 ][ 4 ] -- ;		break ;					case 'B' :	square[ file ][ rank ] = SB ;	hand[ 1 ][ 5 ] -- ;		break ;					case 'R' :	square[ file ][ rank ] = SR ;	hand[ 1 ][ 6 ] -- ;		break ;					case 'K' :	square[ file ][ rank ] = SK ;							break ;				}				if( Character.isLowerCase( ch ) )					square[ file ][ rank ] += 16 ;				if( promoted )					square[ file ][ rank ] +=  8 ;			}			FENindex ++ ;	//	skip slash or space...		}		//	debug		System.out.println( str.substring( FENindex ) ) ;		for( int index = 0 ; index < 7 ; index ++ ) {			int count = str.charAt( FENindex++ ) - '0' ;			hand[ 0 ][ index ] = count ;			hand[ 1 ][ index ] -= count ;		}		FENindex ++ ;		//	skip slash		//	debug		System.out.println( str.substring( FENindex ) ) ;		if( Character.toLowerCase( str.charAt( FENindex ) ) == 't' )			FENindex ++ ;		else {			for( int index = 0 ; index < 7 ; index ++ )				hand[ 1 ][ index ] = str.charAt( FENindex ++ ) - '0' ;		}		FENindex ++ ;		//	skip space		//	debug		System.out.println( str.substring( FENindex ) ) ;		if( Character.toLowerCase( str.charAt( FENindex ++ ) ) == 'g' )			senteToMove = false ;		FENindex ++ ;		//	skip space		String s = str.substring( FENindex ) ;		globalPly = Integer.parseInt( s ) * 2 - 1 ;		if( senteToMove )			globalPly -- ;		//	debug		dump( ) ;	}	public int pieceAt( int file, int rank )	{		return square[ file ][ rank ] ;	}	public int inHand( int piece )	{		switch( piece ) {			case SP :	return hand[ 0 ][ 0 ] ;			case SL :	return hand[ 0 ][ 1 ] ;			case SN :	return hand[ 0 ][ 2 ] ;			case SS :	return hand[ 0 ][ 3 ] ;			case SG :	return hand[ 0 ][ 4 ] ;			case SB :	return hand[ 0 ][ 5 ] ;			case SR :	return hand[ 0 ][ 6 ] ;			case GP :	return hand[ 1 ][ 0 ] ;			case GL :	return hand[ 1 ][ 1 ] ;			case GN :	return hand[ 1 ][ 2 ] ;			case GS :	return hand[ 1 ][ 3 ] ;			case GG :	return hand[ 1 ][ 4 ] ;			case GB :	return hand[ 1 ][ 5 ] ;			case GR :	return hand[ 1 ][ 6 ] ;		}		//	throw exception		return 0 ;	}		public boolean isSenteToMove( )	{		return senteToMove ;	}		public void makeMove( ShogiMove move )	{		if( move.fromfile < 0 ) {	//	drop			int piece = - move.fromfile ;			switch( piece ) {				case SP :					if( hand[ 0 ][ 0 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 0 ][ 0 ] -- ;					break ;				case SL :					if( hand[ 0 ][ 1 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 0 ][ 1 ] -- ;					break ;				case SN :					if( hand[ 0 ][ 2 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 0 ][ 2 ] -- ;					break ;				case SS :					if( hand[ 0 ][ 3 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 0 ][ 3 ] -- ;					break ;				case SG :					if( hand[ 0 ][ 4 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 0 ][ 4 ] -- ;					break ;				case SB :					if( hand[ 0 ][ 5 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 0 ][ 5 ] -- ;					break ;				case SR :					if( hand[ 0 ][ 6 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 0 ][ 6 ] -- ;					break ;				case GP :					if( hand[ 1 ][ 0 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 1 ][ 0 ] -- ;					break ;				case GL :					if( hand[ 1 ][ 1 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 1 ][ 1 ] -- ;					break ;				case GN :					if( hand[ 1 ][ 2 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 1 ][ 2 ] -- ;							break ;				case GS :					if( hand[ 1 ][ 3 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 1 ][ 3 ] -- ;							break ;				case GG :					if( hand[ 1 ][ 4 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 1 ][ 4 ] -- ;							break ;				case GB :					if( hand[ 1 ][ 5 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 1 ][ 5 ] -- ;							break ;				case GR :					if( hand[ 1 ][ 6 ] <= 0 )						 throw new RuntimeException( "No piece to drop" ) ;					hand[ 1 ][ 6 ] -- ;							break ;			}			square[ move.tofile ][ move.torank ] = piece ;		} else {			int piece = square[ move.fromfile ][ move.fromrank ] ;			int torank = move.torank ;			if( torank >= 10 ) {	//	promotion				piece += 8 ;				torank -= 10 ;			}			int captured = square[ move.tofile ][ torank ] ;			switch( captured ) {				case GP :	case GPP :	hand[ 0 ][ 0 ] ++ ;		break ;				case GL :	case GPL :	hand[ 0 ][ 1 ] ++ ;		break ;				case GN :	case GPN :	hand[ 0 ][ 2 ] ++ ;		break ;				case GS :	case GPS :	hand[ 0 ][ 3 ] ++ ;		break ;				case GG :				hand[ 0 ][ 4 ] ++ ;		break ;				case GB :	case GPB :	hand[ 0 ][ 5 ] ++ ;		break ;				case GR :	case GPR :	hand[ 0 ][ 6 ] ++ ;		break ;				case SP :	case SPP :	hand[ 1 ][ 0 ] ++ ;		break ;				case SL :	case SPL :	hand[ 1 ][ 1 ] ++ ;		break ;				case SN :	case SPN :	hand[ 1 ][ 2 ] ++ ;		break ;				case SS :	case SPS :	hand[ 1 ][ 3 ] ++ ;		break ;				case SG :				hand[ 1 ][ 4 ] ++ ;		break ;				case SB :	case SPB :	hand[ 1 ][ 5 ] ++ ;		break ;				case SR :	case SPR :	hand[ 1 ][ 6 ] ++ ;		break ;			}			square[ move.tofile	][ torank ] = piece ;			square[ move.fromfile ][ move.fromrank ] = EM ;		}		senteToMove = ! senteToMove ;			}	public ShogiBoard copy( )	{		ShogiBoard copy = new ShogiBoard( ) ;		for( int i = 0 ; i < 9 ; i ++ ) {			for( int j = 0 ; j < 9 ; j ++ )				copy.square[ i ][ j ] = square[ i ][ j ] ;		}		for( int i = 0 ; i < 2 ; i ++ ) {			for( int j = 0 ; j < 7 ; j ++ )				copy.hand[ i ][ j ] = hand[ i ][ j ] ;		}		copy.senteToMove = senteToMove ;		return copy ;	}	public Vector generateLegalMoves( int piece )	{		Vector v = new Vector( ) ;		for( int fromfile = 0 ; fromfile < 9 ; fromfile ++ ) {			for( int fromrank = 0 ; fromrank < 9 ; fromrank ++ ) {				if( square[ fromfile ][ fromrank ] == piece ) { 					switch( piece ) {						case SP :							if( ! isSente( square[ fromfile ][ fromrank + 1 ] ) )								addMove( v, fromfile, fromrank, fromfile, fromrank + 1 ) ;							break ;						case SL :							for( int torank = fromrank + 1 ; torank < 9 ; torank ++ ) {								if( ! isSente( square[ fromfile ][ torank ] ) )									addMove( v, fromfile, fromrank, fromfile, torank ) ;								if( square[ fromfile ][ torank ] != EM )									break ;							}							break ;						case SN :							for( int i = 0 ; i < 2 ; i ++ ) {								int tofile = fromfile + knightMoves[ i ][ 0 ] ;								int torank = fromrank + knightMoves[ i ][ 1 ] ;								if( isOnBoard( tofile, torank ) &&									! isSente( square[ tofile][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;							} 							break ;						case SS :							for( int i = 0 ; i < 5 ; i ++ ) {								int tofile = fromfile + silverMoves[ i ][ 0 ] ;								int torank = fromrank + silverMoves[ i ][ 1 ] ;								if( isOnBoard( tofile, torank ) &&									! isSente( square[ tofile][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;							} 							break ;						case SG :						case SPP :						case SPL :						case SPN :						case SPS :							for( int i = 0 ; i < 6 ; i ++ ) {								int tofile = fromfile + goldMoves[ i ][ 0 ] ;								int torank = fromrank + goldMoves[ i ][ 1 ] ;								if( isOnBoard( tofile, torank ) &&									! isSente( square[ tofile][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;							} 							break ;						case SPB :							for( int i = 0 ; i < 4 ; i ++ ) {								int tofile = fromfile + rookMoves[ i ][ 0 ] ;								int torank = fromrank + rookMoves[ i ][ 1 ] ;								if( isOnBoard( tofile, torank ) &&									! isSente( square[ tofile][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;							} 							//	fall through							case SB :							for( int i = 0 ; i < 4 ; i ++ ) {								int dir[ ] = bishopMoves[ i ] ;								int tofile = fromfile + dir[ 0 ] ;								int torank = fromrank + dir[ 1 ] ;								while( isOnBoard( tofile, torank ) ) {									if( ! isSente( square[ tofile ][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;									if( square[ tofile ][ torank ] != EM )										break ;									tofile += dir[ 0 ] ;									torank += dir[ 1 ] ;								}							}							break ;						case SPR :							for( int i = 0 ; i < 4 ; i ++ ) {								int tofile = fromfile + bishopMoves[ i ][ 0 ] ;								int torank = fromrank + bishopMoves[ i ][ 1 ] ;								if( isOnBoard( tofile, torank ) &&									! isSente( square[ tofile][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;							} 							//	fall through							case SR :							for( int i = 0 ; i < 4 ; i ++ ) {								int dir[ ] = rookMoves[ i ] ;								int tofile = fromfile + dir[ 0 ] ;								int torank = fromrank + dir[ 1 ] ;								while( isOnBoard( tofile, torank ) ) {									if( ! isSente( square[ tofile ][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;									if( square[ tofile ][ torank ] != EM )										break ;									tofile += dir[ 0 ] ;									torank += dir[ 1 ] ;								}							}							break ;						case SK :							for( int i = 0 ; i < 8 ; i ++ ) {								int tofile = fromfile + kingMoves[ i ][ 0 ] ;								int torank = fromrank + kingMoves[ i ][ 1 ] ;								if( isOnBoard( tofile, torank ) &&									! isSente( square[ tofile][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;							} 							break ;						case GP :							if( ! isGote( square[ fromfile ][ fromrank - 1 ] ) )								addMove( v, fromfile, fromrank, fromfile, fromrank - 1 ) ;							break ;						case GL :							for( int torank = fromrank - 1 ; torank >= 0 ; torank -- ) {								if( ! isGote( square[ fromfile ][ torank ] ) )									addMove( v, fromfile, fromrank, fromfile, torank ) ;								if( square[ fromfile ][ torank ] != EM )									break ;							}							break ;						case GN :							for( int i = 0 ; i < 2 ; i ++ ) {								int tofile = fromfile - knightMoves[ i ][ 0 ] ;								int torank = fromrank - knightMoves[ i ][ 1 ] ;								if( isOnBoard( tofile, torank ) &&									! isGote( square[ tofile][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;							} 							break ;						case GS :							for( int i = 0 ; i < 5 ; i ++ ) {								int tofile = fromfile - silverMoves[ i ][ 0 ] ;								int torank = fromrank - silverMoves[ i ][ 1 ] ;								if( isOnBoard( tofile, torank ) &&									! isGote( square[ tofile][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;							} 							break ;						case GG :						case GPP :						case GPL :						case GPN :						case GPS :							for( int i = 0 ; i < 6 ; i ++ ) {								int tofile = fromfile - goldMoves[ i ][ 0 ] ;								int torank = fromrank - goldMoves[ i ][ 1 ] ;								if( isOnBoard( tofile, torank ) &&									! isGote( square[ tofile][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;							} 							break ;						case GPB :							for( int i = 0 ; i < 4 ; i ++ ) {								int tofile = fromfile - rookMoves[ i ][ 0 ] ;								int torank = fromrank - rookMoves[ i ][ 1 ] ;								if( isOnBoard( tofile, torank ) &&									! isGote( square[ tofile][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;							}							//	fall through						case GB :							for( int i = 0 ; i < 4 ; i ++ ) {								int dir[ ] = bishopMoves[ i ] ;								int tofile = fromfile + dir[ 0 ] ;								int torank = fromrank + dir[ 1 ] ;								while( isOnBoard( tofile, torank ) ) {									if( ! isGote( square[ tofile ][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;									if( square[ tofile ][ torank ] != EM )										break ;									tofile += dir[ 0 ] ;									torank += dir[ 1 ] ;								}							}							break ;						case GPR :							for( int i = 0 ; i < 4 ; i ++ ) {								int tofile = fromfile - bishopMoves[ i ][ 0 ] ;								int torank = fromrank - bishopMoves[ i ][ 1 ] ;								if( isOnBoard( tofile, torank ) &&									! isGote( square[ tofile][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;							}							//	fall through						case GR :							for( int i = 0 ; i < 4 ; i ++ ) {								int dir[ ] = rookMoves[ i ] ;								int tofile = fromfile + dir[ 0 ] ;								int torank = fromrank + dir[ 1 ] ;								while( isOnBoard( tofile, torank ) ) {									if( ! isGote( square[ tofile ][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;									if( square[ tofile ][ torank ] != EM )										break ;									tofile += dir[ 0 ] ;									torank += dir[ 1 ] ;								}							}							break ;						case GK :							for( int i = 0 ; i < 8 ; i ++ ) {								int tofile = fromfile - kingMoves[ i ][ 0 ] ;								int torank = fromrank - kingMoves[ i ][ 1 ] ;								if( isOnBoard( tofile, torank ) &&									! isGote( square[ tofile][ torank ] ) )										addMove( v, fromfile, fromrank, tofile, torank ) ;							} 							break ;					}				}			}		}		return v ;	}		private void addMove( Vector v, int fromfile, int fromrank, int tofile, int torank )	{		v.addElement( new ShogiMove( fromfile, fromrank, tofile, torank ) ) ;	}	private static boolean isOnBoard( int file, int rank )	{		return file >= 0 && file < 9 && rank >= 0 && rank < 9 ;	}		private static boolean isSente( int piece )	{		return piece >= SP && piece <= SPR ;	}	private static boolean isGote( int piece )	{		return piece >= GP && piece <= GPR ;	}		//	constant move tables	private static final int[ ][ ] knightMoves = {		{ -1,  2 }, {  1,  2 }	} ;	private static final int[ ][ ] silverMoves = {		{ -1,  1 }, {  0,  1 }, {  1,  1 }, { -1, -1 },		{  1, -1 }	} ;	private static final int[ ][ ] goldMoves = {		{ -1,  1 }, {  0,  1 }, {  1,  1 }, { -1,  0 },		{  1,  0 }, {  0, -1 }	} ;	private static final int[ ][ ] bishopMoves = {		{ -1, -1 }, { -1,  1 }, {  1, -1 }, {  1,  1 }	} ;	private static final int[ ][ ] rookMoves = {		{ -1,  0 }, {  0, -1 }, {  0,  1 }, {  1,  0 }	} ;	private static final int[ ][ ] kingMoves = {		{ -1, -1 }, { -1,  0 }, { -1,  1 }, {  0, -1 },		{  0,  1 }, {  1, -1 }, {  1,  0 }, {  1,  1 }	} ;}
