From f5759cfbe64606ca7b48faec5eae88ef1450760f Mon Sep 17 00:00:00 2001 From: Marco Date: Fri, 25 Aug 2023 12:11:23 +0200 Subject: [PATCH] Groundwork for move history --- lib/chess_bloc/chess_position.dart | 1 + lib/pages/chess_game.dart | 20 ++++- lib/utils/chess_utils.dart | 60 ++++++++++----- lib/utils/widgets/move_history_widget.dart | 90 +++++++++++++++------- 4 files changed, 124 insertions(+), 47 deletions(-) diff --git a/lib/chess_bloc/chess_position.dart b/lib/chess_bloc/chess_position.dart index c392f74..3788495 100644 --- a/lib/chess_bloc/chess_position.dart +++ b/lib/chess_bloc/chess_position.dart @@ -23,6 +23,7 @@ class ChessPositionManager { if (history.isEmpty) return null; return history.last; } + ChessMoveHistory get allMoves => history; ChessPosition fromPGNString(String pgn) { ChessPosition pos = {}; diff --git a/lib/pages/chess_game.dart b/lib/pages/chess_game.dart index dc0180f..6c1b68e 100644 --- a/lib/pages/chess_game.dart +++ b/lib/pages/chess_game.dart @@ -6,6 +6,7 @@ import 'package:mchess/chess_bloc/chess_bloc.dart'; import 'package:mchess/chess/chess_board.dart'; import 'package:mchess/chess_bloc/promotion_bloc.dart'; import 'package:mchess/utils/chess_utils.dart'; +import 'package:mchess/utils/widgets/move_history_widget.dart'; import 'package:mchess/utils/widgets/promotion_dialog.dart'; import 'package:uuid/uuid.dart'; @@ -43,8 +44,23 @@ class _ChessGameState extends State { }, child: BlocBuilder( builder: (context, state) { - return ChessBoard( - boardState: state, + return Row( + children: [ + Expanded( + flex: 1, + child: Container(), + ), + Expanded( + flex: 3, + child: ChessBoard(boardState: state), + ), + const Expanded( + flex: 1, + child: Align( + alignment: Alignment.centerLeft, + child: MoveHistory()), + ), + ], ); }, ), diff --git a/lib/utils/chess_utils.dart b/lib/utils/chess_utils.dart index 43aa019..3599aa1 100644 --- a/lib/utils/chess_utils.dart +++ b/lib/utils/chess_utils.dart @@ -115,30 +115,54 @@ Map chessPiecesShortName = { }; Map pieceCharacter = { - ChessPieceAssetKey(pieceClass: ChessPieceClass.pawn, color: ChessColor.white): - "♙", - ChessPieceAssetKey(pieceClass: ChessPieceClass.rook, color: ChessColor.white): - "♖", ChessPieceAssetKey( - pieceClass: ChessPieceClass.knight, color: ChessColor.white): "♘", + pieceClass: ChessPieceClass.pawn, + color: ChessColor.white, + ): "♙", ChessPieceAssetKey( - pieceClass: ChessPieceClass.bishop, color: ChessColor.white): "♗", - ChessPieceAssetKey(pieceClass: ChessPieceClass.king, color: ChessColor.white): - "♔", + pieceClass: ChessPieceClass.rook, + color: ChessColor.white, + ): "♖", ChessPieceAssetKey( - pieceClass: ChessPieceClass.queen, color: ChessColor.white): "♕", - ChessPieceAssetKey(pieceClass: ChessPieceClass.pawn, color: ChessColor.black): - "♟︎", - ChessPieceAssetKey(pieceClass: ChessPieceClass.rook, color: ChessColor.black): - "♜", + pieceClass: ChessPieceClass.knight, + color: ChessColor.white, + ): "♘", ChessPieceAssetKey( - pieceClass: ChessPieceClass.knight, color: ChessColor.black): "♞", + pieceClass: ChessPieceClass.bishop, + color: ChessColor.white, + ): "♗", ChessPieceAssetKey( - pieceClass: ChessPieceClass.bishop, color: ChessColor.black): "♝", - ChessPieceAssetKey(pieceClass: ChessPieceClass.king, color: ChessColor.black): - "♚", + pieceClass: ChessPieceClass.king, + color: ChessColor.white, + ): "♔", ChessPieceAssetKey( - pieceClass: ChessPieceClass.queen, color: ChessColor.black): "♛", + pieceClass: ChessPieceClass.queen, + color: ChessColor.white, + ): "♕", + ChessPieceAssetKey( + pieceClass: ChessPieceClass.pawn, + color: ChessColor.black, + ): "♟︎", + ChessPieceAssetKey( + pieceClass: ChessPieceClass.rook, + color: ChessColor.black, + ): "♜", + ChessPieceAssetKey( + pieceClass: ChessPieceClass.knight, + color: ChessColor.black, + ): "♞", + ChessPieceAssetKey( + pieceClass: ChessPieceClass.bishop, + color: ChessColor.black, + ): "♝", + ChessPieceAssetKey( + pieceClass: ChessPieceClass.king, + color: ChessColor.black, + ): "♚", + ChessPieceAssetKey( + pieceClass: ChessPieceClass.queen, + color: ChessColor.black, + ): "♛", }; Map pieceFromShortname = { diff --git a/lib/utils/widgets/move_history_widget.dart b/lib/utils/widgets/move_history_widget.dart index 5c76587..507775c 100644 --- a/lib/utils/widgets/move_history_widget.dart +++ b/lib/utils/widgets/move_history_widget.dart @@ -12,42 +12,78 @@ class MoveHistory extends StatefulWidget { } class _MoveHistoryState extends State { - late List entries; + ChessMoveHistory allMoves = []; + List entries = []; @override void initState() { - entries = []; super.initState(); } @override Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) { - List newEntries = []; - var positionManager = ChessPositionManager.getInstance(); - var allMoves = positionManager.allMoves; + return BlocBuilder(builder: (context, state) { + //We do not use the state, we just use the ChessBloc as a trigger + var positionManager = ChessPositionManager.getInstance(); + if (positionManager.lastMove == null) return Container(); + var pieceMoved = positionManager.getPieceAt(positionManager.lastMove!.to); + var pieceChar = pieceCharacter[ChessPieceAssetKey( + //we take the opposite color because we use dark theme. White pieces appear black and vice versa. + pieceClass: pieceMoved!.pieceClass, + color: pieceMoved.color.getOpposite())]; - for (ChessMove move in allMoves) { - var movedPiece = positionManager.getPieceAt(move.to); - var char = pieceCharacter[ChessPieceAssetKey( - pieceClass: movedPiece!.pieceClass, - color: movedPiece.color.getOpposite())]; + if (pieceMoved.color == ChessColor.white) { + var entry = HistoryEntry(); + entry.setWhite( + pieceChar!, positionManager.lastMove!.to.toAlphabetical()); + entries.add(entry); + } else { + var entry = entries.last; + entry.setBlack( + pieceChar!, positionManager.lastMove!.to.toAlphabetical()); + } - if (movedPiece.color == ChessColor.white) { - newEntries.add("$char ${move.to.toAlphabetical()}"); - } else { - newEntries.last = - "${newEntries.last}\t\t$char${move.to.toAlphabetical()}"; - } - } - setState(() { - entries = newEntries; - }); - }, - child: ListView(children: [ - for (var entry in entries) Text(entry), - ]), - ); + return ListView.builder( + itemCount: entries.length, + itemBuilder: (context, index) { + return Text( + entries[index].toString(), + style: const TextStyle(fontSize: 20), + ); + }, + ); + }); + } +} + +class HistoryEntry { + String? wChar; + String? wTo; + String? bChar; + String? bTo; + + HistoryEntry(); + + void setWhite(String char, to) { + wChar = char; + wTo = to; + } + + void setBlack(String char, to) { + bChar = char; + bTo = to; + } + + @override + String toString() { + String entry = ""; + if (wChar != null) { + entry = "$entry$wChar$wTo"; + } + if (bChar != null) { + entry = "$entry\t\t$bChar$bTo"; + } + + return entry; } }