22
33import android .graphics .drawable .PictureDrawable ;
44import android .os .Bundle ;
5+ import android .util .Log ;
56import android .view .MotionEvent ;
67import android .view .View ;
78import android .widget .ImageView ;
89import android .widget .Toast ;
910import androidx .appcompat .app .AppCompatActivity ;
1011
1112import com .caverock .androidsvg .SVG ;
13+ import com .caverock .androidsvg .PreserveAspectRatio ;
14+ import com .caverock .androidsvg .SVGParseException ;
15+ import com .chaquo .python .PyObject ;
16+ import com .chaquo .python .Python ;
17+ import com .chaquo .python .android .AndroidPlatform ;
18+
19+ import java .util .ArrayList ;
20+ import java .util .List ;
1221
1322public class PlayActivity extends AppCompatActivity {
1423
15- private ChessEngine chessEngine ;
24+ private Python py ;
25+ private PyObject chessLogic ;
1626 private String currentFEN ;
1727 private ImageView chessBoardImage ;
18-
19- private String selectedSquare = null ; // Track the square being touched
28+ private String selectedSquare = null ;
29+ private List < String > legalMoves = null ;
2030
2131 @ Override
2232 protected void onCreate (Bundle savedInstanceState ) {
2333 super .onCreate (savedInstanceState );
2434 setContentView (R .layout .activity_play );
2535
26- chessEngine = new ChessEngine ();
36+ if (!Python .isStarted ()) {
37+ Python .start (new AndroidPlatform (this ));
38+ }
39+ py = Python .getInstance ();
40+ chessLogic = py .getModule ("chess_logic" );
41+
2742 chessBoardImage = findViewById (R .id .chess_board );
2843
29- // Initialize board state
30- currentFEN = chessEngine .createBoard ();
44+ currentFEN = chessLogic .callAttr ("create_board" ).toString ();
3145 updateBoard ();
3246
33- // Set touch listener on the chessboard
3447 chessBoardImage .setOnTouchListener (new View .OnTouchListener () {
3548 @ Override
3649 public boolean onTouch (View v , MotionEvent event ) {
@@ -42,61 +55,116 @@ public boolean onTouch(View v, MotionEvent event) {
4255 }
4356 });
4457
45- // Back arrow functionality
4658 ImageView backArrow = findViewById (R .id .back_arrow );
4759 backArrow .setOnClickListener (v -> finish ());
4860 }
4961
5062 private void handleTouch (float x , float y ) {
51- // Map touch coordinates to a chess square
5263 String square = getSquareFromTouch (x , y );
53-
64+ if (square == null ) {
65+ return ;
66+ }
5467 if (selectedSquare == null ) {
55- // First touch: select the piece
5668 selectedSquare = square ;
57- Toast .makeText (this , "Selected: " + selectedSquare , Toast .LENGTH_SHORT ).show ();
69+ try {
70+ PyObject legalMovesPy = chessLogic .callAttr ("get_legal_moves_from_square" , currentFEN , selectedSquare );
71+ List <String > legalMoves = new ArrayList <>();
72+ for (PyObject move : legalMovesPy .asList ()) {
73+ legalMoves .add (move .toString ());
74+ }
75+ if (legalMoves .isEmpty ()) {
76+ Toast .makeText (this , "No legal moves from " + selectedSquare , Toast .LENGTH_SHORT ).show ();
77+ selectedSquare = null ;
78+ } else {
79+ this .legalMoves = legalMoves ;
80+ updateBoard ();
81+ }
82+ } catch (Exception e ) {
83+ Toast .makeText (this , "Error finding legal moves: " + e .getMessage (), Toast .LENGTH_SHORT ).show ();
84+ selectedSquare = null ;
85+ }
5886 } else {
59- // Second touch: move the piece
60- String move = selectedSquare + square ; // e.g., "e2e4"
87+ String move = selectedSquare + square ;
88+ Log . d ( "ChessApp" , "Attempting move: " + move );
6189 try {
62- currentFEN = chessEngine .makeMove (currentFEN , move ); // Update the board state
63- updateBoard (); // Redraw the board
64- selectedSquare = null ; // Reset selection
90+ PyObject result = chessLogic .callAttr ("make_move" , currentFEN , move );
91+ currentFEN = result .toString ();
92+ selectedSquare = null ;
93+ this .legalMoves = null ;
94+ updateBoard ();
6595 } catch (Exception e ) {
66- Toast .makeText (this , "Invalid move" , Toast .LENGTH_SHORT ).show ();
67- selectedSquare = null ; // Reset selection
96+ Toast .makeText (this , "Invalid move: " + e .getMessage (), Toast .LENGTH_SHORT ).show ();
97+ selectedSquare = null ;
98+ this .legalMoves = null ;
99+ updateBoard ();
68100 }
69101 }
70102 }
71103
72104 private String getSquareFromTouch (float x , float y ) {
73- // Calculate board square based on touch coordinates
74- int boardSize = chessBoardImage .getWidth (); // Assuming square layout
105+ int boardSize = chessBoardImage .getWidth ();
75106 int squareSize = boardSize / 8 ;
76107
77108 int col = (int ) (x / squareSize );
78- int row = 7 - (int ) (y / squareSize ); // Flip Y-axis for chess notation
109+ int row = 7 - (int ) (y / squareSize );
110+
111+ if (col < 0 || col > 7 || row < 0 || row > 7 ) {
112+ return null ;
113+ }
79114
80115 char file = (char ) ('a' + col );
81116 int rank = row + 1 ;
82117
83- return "" + file + rank ; // Chess notation, e.g., "e2"
118+ return "" + file + rank ;
84119 }
85120
86121 private void updateBoard () {
87- try {
88- // Fetch the SVG representation of the chessboard from the Python code
89- String boardSvg = chessEngine .renderBoard (currentFEN );
90-
91- // Use AndroidSVG to render the SVG
92- SVG svg = SVG .getFromString (boardSvg );
93- PictureDrawable drawable = new PictureDrawable (svg .renderToPicture ());
94-
95- // Display the drawable in the ImageView
96- chessBoardImage .setLayerType (View .LAYER_TYPE_SOFTWARE , null ); // Required for SVG rendering
97- chessBoardImage .setImageDrawable (drawable );
98- } catch (Exception e ) {
99- Toast .makeText (this , "Error rendering board: " + e .getMessage (), Toast .LENGTH_SHORT ).show ();
122+ new Thread (() -> {
123+ try {
124+ PyObject svgData ;
125+ if (selectedSquare != null && legalMoves != null ) {
126+ String [] legalMovesArray = legalMoves .toArray (new String [0 ]);
127+ svgData = chessLogic .callAttr ("render_board" , currentFEN , selectedSquare , (Object ) legalMovesArray );
128+ } else {
129+ svgData = chessLogic .callAttr ("render_board" , currentFEN );
130+ }
131+ String boardSvg = svgData .toString ();
132+ runOnUiThread (() -> {
133+ try {
134+ SVG svg = SVG .getFromString (boardSvg );
135+ svg .setDocumentWidth ("100%" );
136+ svg .setDocumentHeight ("100%" );
137+ svg .setDocumentPreserveAspectRatio (PreserveAspectRatio .LETTERBOX );
138+ chessBoardImage .setLayerType (View .LAYER_TYPE_SOFTWARE , null );
139+ chessBoardImage .setImageDrawable (new PictureDrawable (svg .renderToPicture ()));
140+ } catch (SVGParseException e ) {
141+ Toast .makeText (this , "Error rendering board: " + e .getMessage (), Toast .LENGTH_SHORT ).show ();
142+ e .printStackTrace ();
143+ }
144+ });
145+ } catch (Exception e ) {
146+ runOnUiThread (() -> {
147+ Toast .makeText (this , "Error rendering board: " + e .getMessage (), Toast .LENGTH_LONG ).show ();
148+ });
149+ e .printStackTrace ();
150+ }
151+ }).start ();
152+ }
153+ @ Override
154+ protected void onSaveInstanceState (Bundle outState ) {
155+ super .onSaveInstanceState (outState );
156+ outState .putString ("currentFEN" , currentFEN );
157+ outState .putString ("selectedSquare" , selectedSquare );
158+ if (legalMoves != null ) {
159+ outState .putStringArrayList ("legalMoves" , new ArrayList <>(legalMoves ));
100160 }
101161 }
162+ @ Override
163+ protected void onRestoreInstanceState (Bundle savedInstanceState ) {
164+ super .onRestoreInstanceState (savedInstanceState );
165+ currentFEN = savedInstanceState .getString ("currentFEN" );
166+ selectedSquare = savedInstanceState .getString ("selectedSquare" );
167+ legalMoves = savedInstanceState .getStringArrayList ("legalMoves" );
168+ updateBoard ();
169+ }
102170}
0 commit comments