/*	ShogiViewer.java	shogi board display applet	97-feb-26 ped created*/import java.applet.* ;import java.awt.* ;import java.io. * ;import java.net.* ;import java.util.* ;public class ShogiViewer extends Applet implements Enum_ShogiPieces{	private static final int imageCount = GPR + 1 ;	private static final int sqwidth	= 29 ;	private static final int sqheight	= 31 ;	private static final int boardOffset = ( sqwidth * 3 ) / 2 ;	private static final int infoOffset = sqwidth * 13 ;  	private static final Rectangle advanceButtonRect		= new Rectangle( sqwidth * 6 + 2,   sqheight * 9 + 25, 58, 20 ) ;	private static final Rectangle backButtonRect		= new Rectangle( sqwidth * 6 - 60,  sqheight * 9 + 25, 58, 20 ) ;	private static final Rectangle ffButtonRect		= new Rectangle( sqwidth * 6 + 64,  sqheight * 9 + 25, 58, 20 ) ;	private static final Rectangle rewButtonRect		= new Rectangle( sqwidth * 6 - 122, sqheight * 9 + 25, 58, 20 ) ;	private static final int arrowSize = 12 ;	private static final Rectangle menuButtonRect		= new Rectangle( infoOffset, sqheight * 9 + 25, 58, 20 ) ;	private Vector		games = new Vector( ) ;	private ShogiGame	game ;	private Image[ ]	image = new Image[ imageCount ] ;	private Image		boardImage ;	private boolean		menuMode = false ;	public void init( )	{		setBackground( Color.white ) ;		showStatus( "Loading Images... please wait" ) ;		boardImage	 = getImage( getCodeBase( ), "images/board.gif" ) ;		image[ EM  ] = getImage( getCodeBase( ), "images/em.gif" ) ;		image[ SP  ] = getImage( getCodeBase( ), "images/sp.gif" ) ;		image[ SL  ] = getImage( getCodeBase( ), "images/sl.gif" ) ;		image[ SN  ] = getImage( getCodeBase( ), "images/sn.gif" ) ;		image[ SS  ] = getImage( getCodeBase( ), "images/ss.gif" ) ;		image[ SG  ] = getImage( getCodeBase( ), "images/sg.gif" ) ;		image[ SB  ] = getImage( getCodeBase( ), "images/sb.gif" ) ;		image[ SR  ] = getImage( getCodeBase( ), "images/sr.gif" ) ;		image[ SK  ] = getImage( getCodeBase( ), "images/sk.gif" ) ;		image[ SPP ] = getImage( getCodeBase( ), "images/spp.gif" ) ;		image[ SPL ] = getImage( getCodeBase( ), "images/spl.gif" ) ;		image[ SPN ] = getImage( getCodeBase( ), "images/spn.gif" ) ;		image[ SPS ] = getImage( getCodeBase( ), "images/sps.gif" ) ;		image[ SPB ] = getImage( getCodeBase( ), "images/spb.gif" ) ;		image[ SPR ] = getImage( getCodeBase( ), "images/spr.gif" ) ;		image[ GP  ] = getImage( getCodeBase( ), "images/gp.gif" ) ;		image[ GL  ] = getImage( getCodeBase( ), "images/gl.gif" ) ;		image[ GN  ] = getImage( getCodeBase( ), "images/gn.gif" ) ;		image[ GS  ] = getImage( getCodeBase( ), "images/gs.gif" ) ;		image[ GG  ] = getImage( getCodeBase( ), "images/gg.gif" ) ;		image[ GB  ] = getImage( getCodeBase( ), "images/gb.gif" ) ;		image[ GR  ] = getImage( getCodeBase( ), "images/gr.gif" ) ;		image[ GK  ] = getImage( getCodeBase( ), "images/gk.gif" ) ;		image[ GPP ] = getImage( getCodeBase( ), "images/gpp.gif" ) ;		image[ GPL ] = getImage( getCodeBase( ), "images/gpl.gif" ) ;		image[ GPN ] = getImage( getCodeBase( ), "images/gpn.gif" ) ;		image[ GPS ] = getImage( getCodeBase( ), "images/gps.gif" ) ;		image[ GPB ] = getImage( getCodeBase( ), "images/gpb.gif" ) ;		image[ GPR ] = getImage( getCodeBase( ), "images/gpr.gif" ) ;		//	force images to load		MediaTracker tracker = new MediaTracker( this ) ;		tracker.addImage( boardImage, 0 ) ;		for( int i = 0 ; i < imageCount	; i ++ ) {			if( image[ i ] != null )				tracker.addImage( image[ i ], 0 ) ;		}		try {			tracker.waitForID( 0 ) ;		}		catch( InterruptedException e ) {			return ;		}		try {			String dataFileName = getParameter( "datafile" ) ;			URL dataURL	= new URL( getCodeBase( ), dataFileName ) ;			URLConnection connection = dataURL.openConnection( ) ;			InputStream is = connection.getInputStream( ) ;			game = new ShogiGame( is ) ;			while( game.getMoveCount( ) > 0 ) {				games.addElement( game ) ;				game = new ShogiGame( is ) ;			}			game = ( ShogiGame ) games.firstElement( ) ;		}		catch( MalformedURLException e ) {			System.out.println( "Malformed URL" ) ;		}		catch( IOException e ) {			System.out.println( "IOException" ) ;		}	}	public void paint( Graphics g )	{		g.drawImage( boardImage, boardOffset, 0, null ) ;		drawBoard( g ) ;									//	draw advance button		{			g.setColor( Color.lightGray ) ;			Rectangle r = advanceButtonRect ;			g.fill3DRect( r.x, r.y, r.width, r.height, true ) ;			g.setColor( Color.red ) ;			int leftx = r.x + r.width / 2 - arrowSize / 2 ;			int rightx = leftx + arrowSize ;			int xpoints[ ] = { leftx, leftx, rightx } ;			int midy	= r.y + r.height / 2 ;			int topy	= midy - arrowSize / 2 ;			int bottomy = midy + arrowSize / 2 ;			int ypoints[ ] = { topy, bottomy, midy } ;			g.fillPolygon( xpoints, ypoints, 3 ) ;		}				//	draw back button		{			g.setColor( Color.lightGray ) ;			Rectangle r = backButtonRect ;			g.fill3DRect( r.x, r.y, r.width, r.height, true ) ;			g.setColor( Color.red ) ;			int rightx = r.x + r.width / 2 + arrowSize / 2 ;			int leftx = rightx - arrowSize ;			int xpoints[ ] = { rightx, rightx, leftx } ;			int midy	= r.y + r.height / 2 ;			int topy	= midy - arrowSize / 2 ;			int bottomy	= midy + arrowSize / 2 ;			int ypoints[ ] = { topy, bottomy, midy } ;			g.fillPolygon( xpoints, ypoints, 3 ) ;		}		//	draw ff button		{			g.setColor( Color.lightGray ) ;			Rectangle r = ffButtonRect ;			g.fill3DRect( r.x, r.y, r.width, r.height, true ) ;			g.setColor( Color.red ) ;			int leftx = r.x + r.width / 2 - arrowSize ;			int midx = leftx + arrowSize ;			int rightx = midx + arrowSize ; 			int leftxpoints[ ] = { leftx, leftx, midx } ;			int rightxpoints[ ] = { midx, midx, rightx } ;			int midy	= r.y + r.height / 2 ;			int topy	= midy - arrowSize / 2 ;			int bottomy = midy + arrowSize / 2 ;			int ypoints[ ] = { topy, bottomy, midy } ;			g.fillPolygon( leftxpoints, ypoints, 3 ) ;			g.fillPolygon( rightxpoints, ypoints, 3 ) ;		}				//	draw rewind button		{			g.setColor( Color.lightGray ) ;			Rectangle r = rewButtonRect ;			g.fill3DRect( r.x, r.y, r.width, r.height, true ) ;			g.setColor( Color.red ) ;			int rightx = r.x + r.width / 2 + arrowSize ;			int midx = rightx - arrowSize ;			int leftx = midx - arrowSize ;			int rightxpoints[ ] = { rightx, rightx, midx } ;			int leftxpoints[ ] = { midx, midx, leftx } ;			int midy	= r.y + r.height / 2 ;			int topy	= midy - arrowSize / 2 ;			int bottomy	= midy + arrowSize / 2 ;			int ypoints[ ] = { topy, bottomy, midy } ;			g.fillPolygon( leftxpoints, ypoints, 3 ) ;			g.fillPolygon( rightxpoints, ypoints, 3 ) ;		}		drawRightHalf( ) ;	}	private void drawRightHalf( )	{		if( menuMode )			drawGameMenu( ) ;					else {			Graphics g = getGraphics( ) ;			drawInfoPanel( g ) ;			drawCaption( g ) ;			if( games.size( ) > 1 ) {		//	draw menu button				g.setColor( Color.lightGray ) ;				Rectangle r = menuButtonRect ;				g.fill3DRect( r.x, r.y, r.width, r.height, true ) ;				g.setColor( Color.red ) ;				String menuString = "Menu" ;				FontMetrics fm = g.getFontMetrics( ) ;				int x = r.x + ( r.width - fm.stringWidth( menuString ) ) / 2 ;				int y = r.y + ( r.height + fm.getHeight( ) ) / 2 - fm.getDescent( ) ;				g.drawString( menuString, x, y ) ;			}		}	}		private void drawInfoPanel( Graphics g )	{		Properties info = game.getGameComments( ) ;		g.setColor( Color.black ) ;		if(	drawInfoItem( g, info, "Sente", 30 ) )			drawInfoItem( g, info, "Gote", 44 ) ;		else if( drawInfoItem( g, info, "Uwate", 30 ) )			drawInfoItem( g, info, "Shitate", 44 ) ;		else			drawInfoItem( g, info, "Composer", 30 ) ;				drawInfoItem( g, info, "Event",  64 ) ;		drawInfoItem( g, info, "Round",  78 ) ;		drawInfoItem( g, info, "Site",   92 ) ;		drawInfoItem( g, info, "Date",  106 ) ;		if( ! drawInfoItem( g, info, "Opening", 126 ) )			drawInfoItem( g, info, "Handicap", 126 ) ;		drawInfoItem( g, info, "Result",  140 ) ;	}	private boolean drawInfoItem( Graphics g, Properties info, String key, int yPos )	{		String value = info.getProperty( key.toLowerCase( ) ) ;		if( value == null )			return false ;		g.drawString( key + ": " + value, infoOffset, yPos ) ;		return true ;	}	public boolean mouseDown( Event evt, int x, int y )	{		if( advanceButtonRect.inside( x, y ) ) {			ShogiBoard saveboard = game.getBoard( ).copy( ) ;			if( game.advance( ) )				drawDiff( saveboard ) ;			if( menuMode ) {				menuMode = false ;				drawRightHalf( ) ;			}		}		else if( backButtonRect.inside( x, y ) ) {			ShogiBoard saveboard = game.getBoard( ).copy( ) ;			if( game.back( ) )				drawDiff( saveboard ) ;			if( menuMode ) {				menuMode = false ;				drawRightHalf( ) ;			}		}		else if( ffButtonRect.inside( x, y ) ) {			ShogiBoard saveboard = game.getBoard( ).copy( ) ;			if( game.toEnd( ) )				drawDiff( saveboard ) ;			if( menuMode ) {				menuMode = false ;				drawRightHalf( ) ;			}		}		else if( rewButtonRect.inside( x, y ) ) {			ShogiBoard saveboard = game.getBoard( ).copy( ) ;			if( game.toStart( ) )				drawDiff( saveboard ) ;			if( menuMode ) {				menuMode = false ;				drawRightHalf( ) ;			}		}		else if( ! menuMode && menuButtonRect.inside( x, y ) && games.size( ) > 1 ) {			menuMode = true ;			drawGameMenu( ) ;		}		else if( menuMode ) {			int gamecount = games.size( ) ;			if( gamecount > 10 )				gamecount = 10 ;			for( int i = 0 ; i < gamecount ; i ++ ) {				Rectangle mr = menuButtonRect ;				Rectangle r  = new Rectangle( mr.x, mr.y, mr.width, mr.height ) ;				r.y -= 24 * ( gamecount - i - 1 ) ;				if( r.inside( x, y ) ) {					ShogiBoard saveboard = game.getBoard( ).copy( ) ;					game = ( ShogiGame ) games.elementAt( i ) ;					drawDiff( saveboard ) ;					menuMode = false ;					drawRightHalf( ) ;					break ;				}			}		}		return true ;	}		public void drawGameMenu( )	{		Graphics g = getGraphics( ) ;		//	clear info, caption area		g.clearRect( infoOffset, 0, 500, 500 ) ;		int gamecount = games.size( ) ;		if( gamecount > 10 )			gamecount = 10 ;		for( int i = 0 ; i < gamecount ; i ++ ) {			g.setColor( Color.lightGray ) ;			Rectangle r = menuButtonRect ;			int y = r.y - ( gamecount - i - 1 ) * 24 ;			g.fill3DRect( r.x, y, r.width, r.height, true ) ;			g.setColor( games.elementAt( i ) == game ? Color.black : Color.red ) ;			String caption = "Game " + ( i + 1 ) ;			FontMetrics fm = g.getFontMetrics( ) ;			int x = r.x + ( r.width - fm.stringWidth( caption ) ) / 2 ;			y += ( r.height + fm.getHeight( ) ) / 2 - fm.getDescent( ) ;			g.drawString( caption, x, y ) ;		}	}		public boolean keyDown( Event evt, int key )	{		if( key == 'd' )			game.getBoard( ).dump( ) ;		return true ;	}		private void drawBoard( Graphics g )	{		for( int rank = 8 ; rank >= 0 ; rank -- ) {			for( int file = 0 ; file <= 8 ; file ++ )				drawSquare( g, file, rank ) ;		}		drawHand( g ) ;	}	private void drawHand( Graphics g )	{		drawHandSente( g ) ;		drawHandGote( g ) ;		}	private void drawHandSente( Graphics g )	{		g.clearRect( sqwidth * 12 - 15, sqheight * 2 + 15, sqwidth + 12, sqheight * 7 ) ;		int pos = 0 ;		for( int i = 0 ; i < 7 ; i ++ ) {			int count = game.getBoard( ).inHand( senteHandPiece[ i ] ) ;			if( count > 0 ) {				Point p = new Point( sqwidth * 12 - 15, ( 8 - pos ) * sqheight + 15 ) ;				g.drawImage( image[ senteHandPiece[ i ] ], p.x, p.y, null ) ;				if( count > 1 )					g.drawString( new Integer( count ).toString( ), p.x + sqwidth, p.y + 17 ) ;				pos ++ ;			}					}	} 	private void drawHandGote( Graphics g )	{		g.clearRect( 0, 15, sqwidth + 12, sqheight * 7 ) ;		int pos = 0 ;		for( int i = 0 ; i < 7 ; i ++ ) {			int count = game.getBoard( ).inHand( goteHandPiece[ i ] ) ;			if( count > 0 ) {				Point p = new Point( 0, sqheight * pos + 15 ) ;				g.drawImage( image[ goteHandPiece[ i ] ], p.x, p.y, null ) ;				if( count > 1 )					g.drawString( new Integer( count ).toString( ), p.x + sqwidth, p.y + 17 ) ;				pos ++ ;			}					}	}	private void drawSquare( Graphics g, int file, int rank )	{		Point p = gcoords( file, rank ) ;						//	draw piece		int piece = game.getBoard( ).pieceAt( file, rank ) ;		if( image[ piece ] != null )			g.drawImage( image[ piece ], p.x, p.y, null ) ;	}	private void drawDiff( ShogiBoard old )	{		ShogiBoard board = game.getBoard( ) ;				Graphics g = getGraphics( ) ;				for( int rank = 8 ; rank >= 0 ; rank -- ) {			for( int file = 0 ; file <= 8 ; file ++ ) {				if( board.pieceAt( file, rank ) != old.pieceAt( file, rank ) )					drawSquare( g, file, rank ) ;			}		}		for( int i = 0 ; i < 7 ; i ++ ) {			if( board.inHand( senteHandPiece[ i ] ) != old.inHand( senteHandPiece[ i ] ) ) {				drawHandSente( g ) ;				break ;			}		}				for( int i = 0 ; i < 7 ; i ++ ) {			if( board.inHand( goteHandPiece[ i ] ) != old.inHand( goteHandPiece[ i ] ) ) {				drawHandGote( g ) ;				break ;			}		}				drawCaption( g ) ;	}	private void drawCaption( Graphics g )	{		g.clearRect( infoOffset, 146, 200, sqheight * 9 + 25 - 146 ) ;		ShogiMove move = game.getLastMove( ) ;		if( move != null ) {			int moveCount = game.getCurrentMoveCount( ) ;			String str = move.getString( ) ;			if( str != null ) {				if( ( moveCount % 2 ) == 1 )					str = new Integer( moveCount / 2 + 1 ).toString( ) + ". " + str ;				else					str = new Integer( moveCount / 2 ).toString( ) + "... " + str ;				g.drawString( "After " + str, infoOffset, 180 ) ;			}						str = move.getComment( ) ;			if( str != null )				drawWrappedText( g, str, infoOffset, 200, 200 ) ;		}	}	private void drawWrappedText( Graphics g, String str, int x, int y, int maxwidth )	{		//	dirty and clumsy ...		//	this belongs in a separate class...		FontMetrics fm = g.getFontMetrics( ) ;	newline:		while( true ) {			str = str.trim( ) ;			//	debug			//	System.out.println( '"' + str + '"' ) ;			int nextSpace = str.indexOf( ' ' ) ;			if( nextSpace == -1 ) {				g.drawString( str, x, y ) ;				return ;			}			while( true ) {				String line = str.substring( 0, nextSpace ) ;				int nextNextSpace = str.indexOf( ' ', nextSpace + 1 ) ;				String attempt ;				if( nextNextSpace == -1 )					attempt = str.substring( 0 ) ;				else					attempt = str.substring( 0, nextNextSpace ) ;				if( fm.stringWidth( attempt ) > maxwidth ) {					g.drawString( line, x, y ) ;					y += fm.getHeight( ) ;					str = str.substring( nextSpace ) ;					continue newline ;				}				if( nextNextSpace == -1 ) {					g.drawString( attempt, x, y ) ;					return ;				}				nextSpace = nextNextSpace ;			}			}	}	private Point gcoords( int file, int rank )	{		return new Point( file * sqwidth + boardOffset + 2, ( 8 - rank ) * sqheight + 15 ) ;	}	private static final int senteHandPiece[ ] = { SP, SL, SN, SS, SG, SB, SR } ;	private static final int  goteHandPiece[ ] = { GP, GL, GN, GS, GG, GB, GR } ;}
