Use position to build board
Now the client considers the position sent by the server to build the position on the board.
This commit is contained in:
parent
a281d2acfa
commit
c213d9b1f3
@ -22,12 +22,15 @@ class ApiWebsocketMessage {
|
|||||||
final ApiMove? move;
|
final ApiMove? move;
|
||||||
final ApiColor? color;
|
final ApiColor? color;
|
||||||
final String? reason;
|
final String? reason;
|
||||||
|
final String? position;
|
||||||
|
|
||||||
ApiWebsocketMessage(
|
ApiWebsocketMessage({
|
||||||
{required this.type,
|
required this.type,
|
||||||
required this.move,
|
required this.move,
|
||||||
required this.color,
|
required this.color,
|
||||||
required this.reason});
|
required this.reason,
|
||||||
|
required this.position,
|
||||||
|
});
|
||||||
|
|
||||||
factory ApiWebsocketMessage.fromJson(Map<String, dynamic> json) {
|
factory ApiWebsocketMessage.fromJson(Map<String, dynamic> json) {
|
||||||
final type = MessageType.fromJson(json['messageType']);
|
final type = MessageType.fromJson(json['messageType']);
|
||||||
@ -38,14 +41,18 @@ class ApiWebsocketMessage {
|
|||||||
type: type,
|
type: type,
|
||||||
move: null,
|
move: null,
|
||||||
color: ApiColor.fromJson(json['color']),
|
color: ApiColor.fromJson(json['color']),
|
||||||
reason: null);
|
reason: null,
|
||||||
|
position: null,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case MessageType.move:
|
case MessageType.move:
|
||||||
ret = ApiWebsocketMessage(
|
ret = ApiWebsocketMessage(
|
||||||
type: type,
|
type: type,
|
||||||
move: ApiMove.fromJson(json['move']),
|
move: ApiMove.fromJson(json['move']),
|
||||||
color: null,
|
color: null,
|
||||||
reason: null);
|
reason: null,
|
||||||
|
position: json['position'],
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case MessageType.invalidMove:
|
case MessageType.invalidMove:
|
||||||
ret = ApiWebsocketMessage(
|
ret = ApiWebsocketMessage(
|
||||||
@ -53,6 +60,7 @@ class ApiWebsocketMessage {
|
|||||||
move: ApiMove.fromJson(json['move']),
|
move: ApiMove.fromJson(json['move']),
|
||||||
color: null,
|
color: null,
|
||||||
reason: json['reason'],
|
reason: json['reason'],
|
||||||
|
position: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -21,7 +21,7 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
|
|||||||
on<InitBoard>(initBoard);
|
on<InitBoard>(initBoard);
|
||||||
on<ColorDetermined>(flipBoard);
|
on<ColorDetermined>(flipBoard);
|
||||||
on<ReceivedMove>(moveHandler);
|
on<ReceivedMove>(moveHandler);
|
||||||
on<ReceivedPromotion>(promotionHandler);
|
on<ReceivedPosition>(positionHandler);
|
||||||
on<OwnPieceMoved>(ownMoveHandler);
|
on<OwnPieceMoved>(ownMoveHandler);
|
||||||
on<OwnPromotionPlayed>(ownPromotionHandler);
|
on<OwnPromotionPlayed>(ownPromotionHandler);
|
||||||
on<InvalidMovePlayed>(invalidMoveHandler);
|
on<InvalidMovePlayed>(invalidMoveHandler);
|
||||||
@ -49,96 +49,18 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void moveHandler(ReceivedMove event, Emitter<ChessBoardState> emit) {
|
void moveHandler(ReceivedMove event, Emitter<ChessBoardState> emit) {
|
||||||
log('opponentMoveHandler()');
|
|
||||||
|
|
||||||
var move = ChessMove(from: event.startSquare, to: event.endSquare);
|
|
||||||
bool wasEnPassant = move.wasEnPassant();
|
|
||||||
bool wasCastling = move.wasCastling();
|
|
||||||
|
|
||||||
var oldPosition = ChessPosition.getInstance().copyOfCurrentPosition;
|
|
||||||
ChessPosition.getInstance().recordMove(event.startSquare, event.endSquare);
|
ChessPosition.getInstance().recordMove(event.startSquare, event.endSquare);
|
||||||
var newPosition = ChessPosition.getInstance().currentPosition;
|
|
||||||
|
|
||||||
if (wasEnPassant) {
|
|
||||||
if (turnColor == ChessColor.white) {
|
|
||||||
newPosition[ChessCoordinate(
|
|
||||||
event.endSquare.column, event.endSquare.row - 1)] =
|
|
||||||
const ChessPiece.none();
|
|
||||||
} else {
|
|
||||||
newPosition[ChessCoordinate(
|
|
||||||
event.endSquare.column, event.endSquare.row + 1)] =
|
|
||||||
const ChessPiece.none();
|
|
||||||
}
|
|
||||||
} else if (wasCastling) {
|
|
||||||
ChessPiece rookToMove;
|
|
||||||
ChessPiece kingToMove;
|
|
||||||
if (move.to.column == 7) {
|
|
||||||
rookToMove = oldPosition[ChessCoordinate(8, move.to.row)]!;
|
|
||||||
newPosition[ChessCoordinate(6, move.to.row)] = rookToMove;
|
|
||||||
newPosition[ChessCoordinate(8, move.to.row)] = const ChessPiece.none();
|
|
||||||
|
|
||||||
kingToMove = oldPosition[ChessCoordinate(5, move.to.row)]!;
|
|
||||||
newPosition[ChessCoordinate(7, move.to.row)] = kingToMove;
|
|
||||||
newPosition[ChessCoordinate(5, move.to.row)] = const ChessPiece.none();
|
|
||||||
}
|
|
||||||
if (move.to.column == 3) {
|
|
||||||
rookToMove = oldPosition[ChessCoordinate(1, move.to.row)]!;
|
|
||||||
newPosition[ChessCoordinate(4, move.to.row)] = rookToMove;
|
|
||||||
newPosition[ChessCoordinate(1, move.to.row)] = const ChessPiece.none();
|
|
||||||
|
|
||||||
kingToMove = oldPosition[ChessCoordinate(5, move.to.row)]!;
|
|
||||||
newPosition[ChessCoordinate(3, move.to.row)] = kingToMove;
|
|
||||||
newPosition[ChessCoordinate(5, move.to.row)] = const ChessPiece.none();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
turnColor = state.newTurnColor == ChessColor.white
|
void positionHandler(
|
||||||
? ChessColor.black
|
ReceivedPosition event,
|
||||||
: ChessColor.white;
|
|
||||||
|
|
||||||
emit(
|
|
||||||
ChessBoardState(
|
|
||||||
state.bottomColor,
|
|
||||||
turnColor,
|
|
||||||
newPosition,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void promotionHandler(
|
|
||||||
ReceivedPromotion event,
|
|
||||||
Emitter<ChessBoardState> emit,
|
Emitter<ChessBoardState> emit,
|
||||||
) {
|
) {
|
||||||
var pieceAtStartSquare = ChessPosition.getInstance().getPieceAt(
|
|
||||||
ChessCoordinate(event.startSquare.column, event.startSquare.row));
|
|
||||||
if (pieceAtStartSquare == null) {
|
|
||||||
log('received a promotion but start square was empty');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChessPieceClass pieceClass = ChessPieceClass.none;
|
|
||||||
for (var piece in chessPiecesShortName.entries) {
|
|
||||||
if (piece.value == event.piece) {
|
|
||||||
pieceClass = piece.key.pieceClass;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var newPosition = ChessPosition.getInstance().currentPosition;
|
|
||||||
newPosition[
|
|
||||||
ChessCoordinate(event.startSquare.column, event.startSquare.row)] =
|
|
||||||
const ChessPiece.none();
|
|
||||||
newPosition[ChessCoordinate(event.endSquare.column, event.endSquare.row)] =
|
|
||||||
ChessPiece(pieceClass, pieceAtStartSquare.color);
|
|
||||||
|
|
||||||
turnColor = state.newTurnColor == ChessColor.white
|
turnColor = state.newTurnColor == ChessColor.white
|
||||||
? ChessColor.black
|
? ChessColor.black
|
||||||
: ChessColor.white;
|
: ChessColor.white;
|
||||||
|
|
||||||
emit(ChessBoardState(
|
emit(ChessBoardState(state.bottomColor, turnColor, event.position));
|
||||||
state.bottomColor,
|
|
||||||
turnColor,
|
|
||||||
newPosition,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ownMoveHandler(OwnPieceMoved event, Emitter<ChessBoardState> emit) {
|
void ownMoveHandler(OwnPieceMoved event, Emitter<ChessBoardState> emit) {
|
||||||
@ -146,7 +68,12 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
|
|||||||
var apiMove =
|
var apiMove =
|
||||||
ChessMove(from: event.startSquare, to: event.endSquare).toApiMove();
|
ChessMove(from: event.startSquare, to: event.endSquare).toApiMove();
|
||||||
var apiMessage = ApiWebsocketMessage(
|
var apiMessage = ApiWebsocketMessage(
|
||||||
type: MessageType.move, move: apiMove, color: null, reason: null);
|
type: MessageType.move,
|
||||||
|
move: apiMove,
|
||||||
|
color: null,
|
||||||
|
reason: null,
|
||||||
|
position: null,
|
||||||
|
);
|
||||||
|
|
||||||
ServerConnection.getInstance().send(jsonEncode(apiMessage));
|
ServerConnection.getInstance().send(jsonEncode(apiMessage));
|
||||||
|
|
||||||
@ -176,6 +103,7 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
|
|||||||
move: apiMove,
|
move: apiMove,
|
||||||
color: null,
|
color: null,
|
||||||
reason: null,
|
reason: null,
|
||||||
|
position: null,
|
||||||
);
|
);
|
||||||
log(jsonEncode(message));
|
log(jsonEncode(message));
|
||||||
ServerConnection.getInstance().send(jsonEncode(message));
|
ServerConnection.getInstance().send(jsonEncode(message));
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:mchess/chess_bloc/chess_position.dart';
|
||||||
import 'package:mchess/utils/chess_utils.dart';
|
import 'package:mchess/utils/chess_utils.dart';
|
||||||
|
|
||||||
abstract class ChessEvent {}
|
abstract class ChessEvent {}
|
||||||
@ -9,15 +10,10 @@ class ReceivedMove extends ChessEvent {
|
|||||||
ReceivedMove({required this.startSquare, required this.endSquare});
|
ReceivedMove({required this.startSquare, required this.endSquare});
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReceivedPromotion extends ChessEvent {
|
class ReceivedPosition extends ChessEvent {
|
||||||
final ChessCoordinate startSquare;
|
final ChessPositionType position;
|
||||||
final ChessCoordinate endSquare;
|
|
||||||
final String piece;
|
|
||||||
|
|
||||||
ReceivedPromotion(
|
ReceivedPosition({required this.position});
|
||||||
{required this.startSquare,
|
|
||||||
required this.endSquare,
|
|
||||||
required this.piece});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class OwnPieceMoved extends ChessEvent {
|
class OwnPieceMoved extends ChessEvent {
|
||||||
|
@ -1,31 +1,96 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:mchess/utils/chess_utils.dart';
|
import 'package:mchess/utils/chess_utils.dart';
|
||||||
|
|
||||||
typedef ChessPositionType = Map<ChessCoordinate, ChessPiece>;
|
|
||||||
typedef ChessMoveHistory = List<ChessMove>;
|
typedef ChessMoveHistory = List<ChessMove>;
|
||||||
|
typedef ChessPositionType = Map<ChessCoordinate, ChessPiece>;
|
||||||
|
|
||||||
class ChessPosition {
|
class ChessPosition {
|
||||||
static ChessPosition _instance = ChessPosition._internal();
|
static ChessPosition _instance = ChessPosition._internal();
|
||||||
static ChessMoveHistory history = ChessMoveHistory.empty(growable: true);
|
static ChessMoveHistory history = ChessMoveHistory.empty(growable: true);
|
||||||
final ChessPositionType position;
|
final ChessPositionType position;
|
||||||
|
|
||||||
static ChessPosition getInstance() {
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChessPosition({required this.position});
|
ChessPosition({required this.position});
|
||||||
|
|
||||||
factory ChessPosition._internal() {
|
factory ChessPosition._internal() {
|
||||||
return ChessPosition(position: _getStartingPosition());
|
return ChessPosition(position: _getStartingPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
ChessPositionType get currentPosition => position;
|
|
||||||
ChessPositionType get copyOfCurrentPosition => Map.from(position);
|
ChessPositionType get copyOfCurrentPosition => Map.from(position);
|
||||||
|
|
||||||
|
ChessPositionType get currentPosition => position;
|
||||||
ChessMove? get lastMove {
|
ChessMove? get lastMove {
|
||||||
if (history.isEmpty) return null;
|
if (history.isEmpty) return null;
|
||||||
return history.last;
|
return history.last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChessPositionType fromPGNString(String pgn) {
|
||||||
|
ChessPositionType pos = {};
|
||||||
|
List<String> rowStrings;
|
||||||
|
|
||||||
|
rowStrings = pgn.split('/');
|
||||||
|
|
||||||
|
for (int row = 1; row <= 8; row++) {
|
||||||
|
for (int col = 1; col <= 8; col++) {
|
||||||
|
var piece = rowStrings.elementAt(row - 1)[col - 1];
|
||||||
|
if (piece == '-') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pos[ChessCoordinate(col, row)] = pieceFromShortname[piece]!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChessPiece? getPieceAt(ChessCoordinate coordinate) {
|
||||||
|
return position[ChessCoordinate(coordinate.column, coordinate.row)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void logHistory(ChessMoveHistory hist) {
|
||||||
|
for (var element in hist) {
|
||||||
|
log('${element.from.toAlphabetical()} -> ${element.to.toAlphabetical()}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void logPosition(ChessPositionType p) {
|
||||||
|
String logString = '';
|
||||||
|
|
||||||
|
for (int row = 8; row > 0; row--) {
|
||||||
|
for (int col = 1; col <= 8; col++) {
|
||||||
|
var coord = ChessCoordinate(col, row);
|
||||||
|
if (p.containsKey(coord)) {
|
||||||
|
logString = '$logString ${p[coord]?.shortName}';
|
||||||
|
} else {
|
||||||
|
logString = '$logString .';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logString = '$logString\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
log(logString);
|
||||||
|
}
|
||||||
|
|
||||||
|
void recordMove(ChessCoordinate from, ChessCoordinate to) {
|
||||||
|
position[to] = position[from] ?? const ChessPiece.none();
|
||||||
|
position[from] = const ChessPiece.none();
|
||||||
|
|
||||||
|
history.add(ChessMove(from: from, to: to));
|
||||||
|
|
||||||
|
logPosition(position);
|
||||||
|
|
||||||
|
logHistory(history);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetToStartingPosition() {
|
||||||
|
history = ChessMoveHistory.empty(growable: true);
|
||||||
|
_instance = ChessPosition(position: _getStartingPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
static ChessPosition getInstance() {
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
static ChessPositionType _getStartingPosition() {
|
static ChessPositionType _getStartingPosition() {
|
||||||
ChessPositionType pos = {};
|
ChessPositionType pos = {};
|
||||||
|
|
||||||
@ -72,48 +137,4 @@ class ChessPosition {
|
|||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChessPiece? getPieceAt(ChessCoordinate coordinate) {
|
|
||||||
return position[ChessCoordinate(coordinate.column, coordinate.row)];
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetToStartingPosition() {
|
|
||||||
history = ChessMoveHistory.empty(growable: true);
|
|
||||||
_instance = ChessPosition(position: _getStartingPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
void recordMove(ChessCoordinate from, ChessCoordinate to) {
|
|
||||||
position[to] = position[from] ?? const ChessPiece.none();
|
|
||||||
position[from] = const ChessPiece.none();
|
|
||||||
|
|
||||||
history.add(ChessMove(from: from, to: to));
|
|
||||||
|
|
||||||
logPosition(position);
|
|
||||||
|
|
||||||
logHistory(history);
|
|
||||||
}
|
|
||||||
|
|
||||||
void logPosition(ChessPositionType p) {
|
|
||||||
String logString = '';
|
|
||||||
|
|
||||||
for (int row = 8; row > 0; row--) {
|
|
||||||
for (int col = 1; col <= 8; col++) {
|
|
||||||
var coord = ChessCoordinate(col, row);
|
|
||||||
if (p.containsKey(coord)) {
|
|
||||||
logString = '$logString ${p[coord]?.shortName}';
|
|
||||||
} else {
|
|
||||||
logString = '$logString .';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logString = '$logString\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
log(logString);
|
|
||||||
}
|
|
||||||
|
|
||||||
void logHistory(ChessMoveHistory hist) {
|
|
||||||
for (var element in hist) {
|
|
||||||
log('${element.from.toAlphabetical()} -> ${element.to.toAlphabetical()}');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'package:mchess/api/websocket_message.dart';
|
|||||||
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
||||||
import 'package:mchess/chess_bloc/chess_events.dart';
|
import 'package:mchess/chess_bloc/chess_events.dart';
|
||||||
import 'package:mchess/api/register.dart';
|
import 'package:mchess/api/register.dart';
|
||||||
|
import 'package:mchess/chess_bloc/chess_position.dart';
|
||||||
import 'package:mchess/connection_cubit/connection_cubit.dart';
|
import 'package:mchess/connection_cubit/connection_cubit.dart';
|
||||||
import 'package:mchess/utils/chess_utils.dart';
|
import 'package:mchess/utils/chess_utils.dart';
|
||||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||||
@ -86,16 +87,14 @@ class ServerConnection {
|
|||||||
void handleIncomingMoveMessage(ApiWebsocketMessage apiMessage) {
|
void handleIncomingMoveMessage(ApiWebsocketMessage apiMessage) {
|
||||||
var move = ChessMove.fromApiMove(apiMessage.move!);
|
var move = ChessMove.fromApiMove(apiMessage.move!);
|
||||||
|
|
||||||
if (apiMessage.move?.promotionToPiece?.isNotEmpty ?? false) {
|
if (apiMessage.position != null) {
|
||||||
ChessBloc.getInstance().add(ReceivedPromotion(
|
ChessBloc.getInstance().add(ReceivedPosition(
|
||||||
startSquare: move.from,
|
position:
|
||||||
endSquare: move.to,
|
ChessPosition.getInstance().fromPGNString(apiMessage.position!)));
|
||||||
piece: apiMessage.move!.promotionToPiece!));
|
}
|
||||||
} else {
|
|
||||||
ChessBloc.getInstance()
|
ChessBloc.getInstance()
|
||||||
.add(ReceivedMove(startSquare: move.from, endSquare: move.to));
|
.add(ReceivedMove(startSquare: move.from, endSquare: move.to));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void handleInvalidMoveMessage(ApiWebsocketMessage apiMessage) {
|
void handleInvalidMoveMessage(ApiWebsocketMessage apiMessage) {
|
||||||
log("invalid move message received, with move: ${apiMessage.move.toString()}");
|
log("invalid move message received, with move: ${apiMessage.move.toString()}");
|
||||||
|
@ -13,25 +13,6 @@ class LobbySelector extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
//We deactivate random lobbies for now.
|
|
||||||
// ElevatedButton(
|
|
||||||
// onPressed: () {
|
|
||||||
// context.push('/prepareRandom');
|
|
||||||
// },
|
|
||||||
// child: const Row(
|
|
||||||
// mainAxisSize: MainAxisSize.min,
|
|
||||||
// children: [
|
|
||||||
// Icon(Icons.question_mark),
|
|
||||||
// SizedBox(
|
|
||||||
// width: 10,
|
|
||||||
// ),
|
|
||||||
// Text('Random')
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// const SizedBox(
|
|
||||||
// height: 25,
|
|
||||||
// ),
|
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_dialogBuilder(context);
|
_dialogBuilder(context);
|
||||||
@ -43,7 +24,7 @@ class LobbySelector extends StatelessWidget {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: 10,
|
width: 10,
|
||||||
),
|
),
|
||||||
Text('Private')
|
Text('Private game')
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -4,57 +4,6 @@ import 'package:mchess/api/move.dart';
|
|||||||
import 'package:mchess/api/websocket_message.dart';
|
import 'package:mchess/api/websocket_message.dart';
|
||||||
import 'package:quiver/core.dart';
|
import 'package:quiver/core.dart';
|
||||||
|
|
||||||
import '../chess_bloc/chess_position.dart';
|
|
||||||
|
|
||||||
enum ChessPieceClass {
|
|
||||||
none,
|
|
||||||
pawn,
|
|
||||||
bishop,
|
|
||||||
knight,
|
|
||||||
rook,
|
|
||||||
queen,
|
|
||||||
king,
|
|
||||||
}
|
|
||||||
|
|
||||||
class ChessPieceAssetKey {
|
|
||||||
final ChessPieceClass pieceClass;
|
|
||||||
final ChessColor color;
|
|
||||||
|
|
||||||
ChessPieceAssetKey({required this.pieceClass, required this.color});
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return (other is ChessPieceAssetKey &&
|
|
||||||
(pieceClass == other.pieceClass) &&
|
|
||||||
(color == other.color));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode {
|
|
||||||
return hash2(pieceClass, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ChessColor {
|
|
||||||
black,
|
|
||||||
white;
|
|
||||||
|
|
||||||
static ChessColor fromApiColor(ApiColor color) {
|
|
||||||
if (color == ApiColor.black) {
|
|
||||||
return black;
|
|
||||||
} else {
|
|
||||||
return white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChessColor getOpposite() {
|
|
||||||
if (name == 'black') {
|
|
||||||
return white;
|
|
||||||
} else {
|
|
||||||
return black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<ChessPieceAssetKey, String> chessPiecesAssets = {
|
Map<ChessPieceAssetKey, String> chessPiecesAssets = {
|
||||||
ChessPieceAssetKey(
|
ChessPieceAssetKey(
|
||||||
@ -166,12 +115,56 @@ Map<ChessPieceAssetKey, String> chessPiecesShortName = {
|
|||||||
): '-',
|
): '-',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Map<String, ChessPiece> pieceFromShortname = {
|
||||||
|
'P': ChessPiece(ChessPieceClass.pawn, ChessColor.white),
|
||||||
|
'R': ChessPiece(ChessPieceClass.rook, ChessColor.white),
|
||||||
|
'N': ChessPiece(ChessPieceClass.knight, ChessColor.white),
|
||||||
|
'B': ChessPiece(ChessPieceClass.bishop, ChessColor.white),
|
||||||
|
'K': ChessPiece(ChessPieceClass.king, ChessColor.white),
|
||||||
|
'Q': ChessPiece(ChessPieceClass.queen, ChessColor.white),
|
||||||
|
'p': ChessPiece(ChessPieceClass.pawn, ChessColor.black),
|
||||||
|
'r': ChessPiece(ChessPieceClass.rook, ChessColor.black),
|
||||||
|
'n': ChessPiece(ChessPieceClass.knight, ChessColor.black),
|
||||||
|
'b': ChessPiece(ChessPieceClass.bishop, ChessColor.black),
|
||||||
|
'k': ChessPiece(ChessPieceClass.king, ChessColor.black),
|
||||||
|
'q': ChessPiece(ChessPieceClass.queen, ChessColor.black),
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ChessColor {
|
||||||
|
black,
|
||||||
|
white;
|
||||||
|
|
||||||
|
ChessColor getOpposite() {
|
||||||
|
if (name == 'black') {
|
||||||
|
return white;
|
||||||
|
} else {
|
||||||
|
return black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ChessColor fromApiColor(ApiColor color) {
|
||||||
|
if (color == ApiColor.black) {
|
||||||
|
return black;
|
||||||
|
} else {
|
||||||
|
return white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ChessCoordinate {
|
class ChessCoordinate {
|
||||||
final int column;
|
final int column;
|
||||||
final int row;
|
final int row;
|
||||||
|
|
||||||
ChessCoordinate(this.column, this.row);
|
ChessCoordinate(this.column, this.row);
|
||||||
|
|
||||||
|
ChessCoordinate.copyFrom(ChessCoordinate original)
|
||||||
|
: column = original.column,
|
||||||
|
row = original.row;
|
||||||
|
|
||||||
|
factory ChessCoordinate.fromApiCoordinate(ApiCoordinate apiCoordinate) {
|
||||||
|
return ChessCoordinate(apiCoordinate.col, apiCoordinate.row);
|
||||||
|
}
|
||||||
|
|
||||||
factory ChessCoordinate.fromString(String coordString) {
|
factory ChessCoordinate.fromString(String coordString) {
|
||||||
var column = int.parse(coordString[0]);
|
var column = int.parse(coordString[0]);
|
||||||
var row = int.parse(coordString[1]);
|
var row = int.parse(coordString[1]);
|
||||||
@ -179,38 +172,16 @@ class ChessCoordinate {
|
|||||||
return ChessCoordinate(column, row);
|
return ChessCoordinate(column, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
factory ChessCoordinate.fromApiCoordinate(ApiCoordinate apiCoordinate) {
|
@override
|
||||||
return ChessCoordinate(apiCoordinate.col, apiCoordinate.row);
|
int get hashCode {
|
||||||
}
|
return hash2(column, row);
|
||||||
|
|
||||||
ApiCoordinate toApiCoordinate() {
|
|
||||||
return ApiCoordinate(col: column, row: row);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChessCoordinate.copyFrom(ChessCoordinate original)
|
|
||||||
: column = original.column,
|
|
||||||
row = original.row;
|
|
||||||
|
|
||||||
static String columnIntToColumnString(int col) {
|
|
||||||
String colStr;
|
|
||||||
|
|
||||||
colStr = String.fromCharCode(col + 96);
|
|
||||||
|
|
||||||
return colStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int columnStringToColumnInt(String col) {
|
|
||||||
int colInt;
|
|
||||||
colInt = col.codeUnitAt(0) - 96;
|
|
||||||
return colInt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
operator ==(other) {
|
||||||
String rowStr = row.toString();
|
return other is ChessCoordinate &&
|
||||||
String colStr = column.toString();
|
other.column == column &&
|
||||||
|
other.row == row;
|
||||||
return '$colStr$rowStr';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String toAlphabetical() {
|
String toAlphabetical() {
|
||||||
@ -230,16 +201,61 @@ class ChessCoordinate {
|
|||||||
return '$colStr$rowStr';
|
return '$colStr$rowStr';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApiCoordinate toApiCoordinate() {
|
||||||
|
return ApiCoordinate(col: column, row: row);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
operator ==(other) {
|
String toString() {
|
||||||
return other is ChessCoordinate &&
|
String rowStr = row.toString();
|
||||||
other.column == column &&
|
String colStr = column.toString();
|
||||||
other.row == row;
|
|
||||||
|
return '$colStr$rowStr';
|
||||||
|
}
|
||||||
|
|
||||||
|
static String columnIntToColumnString(int col) {
|
||||||
|
String colStr;
|
||||||
|
|
||||||
|
colStr = String.fromCharCode(col + 96);
|
||||||
|
|
||||||
|
return colStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int columnStringToColumnInt(String col) {
|
||||||
|
int colInt;
|
||||||
|
colInt = col.codeUnitAt(0) - 96;
|
||||||
|
return colInt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChessMove {
|
||||||
|
ChessCoordinate from;
|
||||||
|
ChessCoordinate to;
|
||||||
|
|
||||||
|
ChessMove({required this.from, required this.to});
|
||||||
|
|
||||||
|
factory ChessMove.fromApiMove(ApiMove apiMove) {
|
||||||
|
final start = ChessCoordinate.fromApiCoordinate(apiMove.startSquare);
|
||||||
|
final end = ChessCoordinate.fromApiCoordinate(apiMove.endSquare);
|
||||||
|
|
||||||
|
return ChessMove(from: start, to: end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
return hash2(column, row);
|
return hash2(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
operator ==(other) {
|
||||||
|
return other is ChessMove && other.from == from && other.to == to;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiMove toApiMove() {
|
||||||
|
var toSquare = to.toApiCoordinate();
|
||||||
|
var fromSquare = from.toApiCoordinate();
|
||||||
|
return ApiMove(
|
||||||
|
startSquare: fromSquare, endSquare: toSquare, promotionToPiece: null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,9 +265,6 @@ class ChessPiece extends StatelessWidget {
|
|||||||
final String shortName;
|
final String shortName;
|
||||||
final Widget? pieceImage;
|
final Widget? pieceImage;
|
||||||
|
|
||||||
const ChessPiece._(
|
|
||||||
this.pieceClass, this.color, this.pieceImage, this.shortName);
|
|
||||||
|
|
||||||
factory ChessPiece(ChessPieceClass pieceClass, ChessColor color) {
|
factory ChessPiece(ChessPieceClass pieceClass, ChessColor color) {
|
||||||
Widget? pieceImage;
|
Widget? pieceImage;
|
||||||
String pieceAssetUrl = chessPiecesAssets[
|
String pieceAssetUrl = chessPiecesAssets[
|
||||||
@ -269,6 +282,9 @@ class ChessPiece extends StatelessWidget {
|
|||||||
pieceImage = null,
|
pieceImage = null,
|
||||||
shortName = "-";
|
shortName = "-";
|
||||||
|
|
||||||
|
const ChessPiece._(
|
||||||
|
this.pieceClass, this.color, this.pieceImage, this.shortName);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
@ -277,58 +293,33 @@ class ChessPiece extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChessMove {
|
class ChessPieceAssetKey {
|
||||||
ChessCoordinate from;
|
final ChessPieceClass pieceClass;
|
||||||
ChessCoordinate to;
|
final ChessColor color;
|
||||||
|
|
||||||
ChessMove({required this.from, required this.to});
|
ChessPieceAssetKey({required this.pieceClass, required this.color});
|
||||||
|
|
||||||
factory ChessMove.fromApiMove(ApiMove apiMove) {
|
|
||||||
final start = ChessCoordinate.fromApiCoordinate(apiMove.startSquare);
|
|
||||||
final end = ChessCoordinate.fromApiCoordinate(apiMove.endSquare);
|
|
||||||
|
|
||||||
return ChessMove(from: start, to: end);
|
|
||||||
}
|
|
||||||
|
|
||||||
ApiMove toApiMove() {
|
|
||||||
var toSquare = to.toApiCoordinate();
|
|
||||||
var fromSquare = from.toApiCoordinate();
|
|
||||||
return ApiMove(
|
|
||||||
startSquare: fromSquare, endSquare: toSquare, promotionToPiece: null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
operator ==(other) {
|
|
||||||
return other is ChessMove && other.from == from && other.to == to;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
return hash2(from, to);
|
return hash2(pieceClass, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wasEnPassant() {
|
@override
|
||||||
var pieceMoved = ChessPosition.getInstance().getPieceAt(from);
|
bool operator ==(Object other) {
|
||||||
var pieceAtEndSquare = ChessPosition.getInstance().getPieceAt(to);
|
return (other is ChessPieceAssetKey &&
|
||||||
if (pieceMoved != null &&
|
(pieceClass == other.pieceClass) &&
|
||||||
pieceMoved.pieceClass == ChessPieceClass.pawn &&
|
(color == other.color));
|
||||||
pieceAtEndSquare == null &&
|
|
||||||
from.column != to.column) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool wasCastling() {
|
enum ChessPieceClass {
|
||||||
var pieceMoved = ChessPosition.getInstance().getPieceAt(from);
|
none,
|
||||||
if (pieceMoved != null && pieceMoved.pieceClass == ChessPieceClass.king) {
|
pawn,
|
||||||
var colDiff = (from.column - to.column).abs();
|
bishop,
|
||||||
if (colDiff == 2) {
|
knight,
|
||||||
return true;
|
rook,
|
||||||
}
|
queen,
|
||||||
}
|
king,
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PieceDragged {
|
class PieceDragged {
|
||||||
|
Loading…
Reference in New Issue
Block a user