mchess-client/lib/chess_bloc/chess_bloc.dart

225 lines
7.1 KiB
Dart
Raw Normal View History

2023-06-02 21:28:40 +00:00
import 'dart:convert';
2022-11-13 00:03:09 +00:00
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:mchess/api/websocket_message.dart';
import 'package:mchess/chess_bloc/chess_events.dart';
import 'package:mchess/chess_bloc/chess_position.dart';
import 'package:mchess/connection/ws_connection.dart';
2022-12-25 15:16:23 +00:00
import 'package:mchess/utils/chess_utils.dart';
import 'dart:developer';
2022-11-13 00:03:09 +00:00
class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
static final ChessBloc _instance = ChessBloc._internal();
static ChessColor turnColor = ChessColor.white;
2023-07-01 07:29:43 +00:00
static ChessColor? myColor = ChessColor.white;
static ChessColor? getSidesColor() {
return myColor;
}
2022-11-13 00:03:09 +00:00
ChessBloc._internal() : super(ChessBoardState.init()) {
2022-12-18 00:04:08 +00:00
on<InitBoard>(initBoard);
on<ColorDetermined>(flipBoard);
on<ReceivedMove>(moveHandler);
2023-07-03 17:41:12 +00:00
on<ReceivedPromotion>(promotionHandler);
on<OwnPieceMoved>(ownMoveHandler);
2023-07-03 17:41:12 +00:00
on<OwnPromotionPlayed>(ownPromotionHandler);
on<InvalidMovePlayed>(invalidMoveHandler);
2022-11-13 00:03:09 +00:00
}
factory ChessBloc.getInstance() {
return ChessBloc();
}
factory ChessBloc() {
return _instance;
}
2022-12-18 00:04:08 +00:00
void initBoard(InitBoard event, Emitter<ChessBoardState> emit) {
turnColor = ChessColor.white;
ChessPosition.getInstance().resetToStartingPosition();
emit(ChessBoardState(ChessColor.white, ChessColor.white,
ChessPosition.getInstance().currentPosition));
2022-12-18 00:04:08 +00:00
}
void flipBoard(ColorDetermined event, Emitter<ChessBoardState> emit) {
log("My Color is $myColor");
myColor = event.myColor;
2022-12-18 00:04:08 +00:00
emit(ChessBoardState(event.myColor, state.newTurnColor, state.position));
}
void moveHandler(ReceivedMove event, Emitter<ChessBoardState> emit) {
log('opponentMoveHandler()');
2023-07-05 19:16:01 +00:00
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);
var newPosition = ChessPosition.getInstance().currentPosition;
2023-07-05 19:16:01 +00:00
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
2022-12-18 00:04:08 +00:00
? ChessColor.black
: ChessColor.white;
2022-12-18 00:04:08 +00:00
emit(
ChessBoardState(
state.bottomColor,
turnColor,
2022-12-18 00:04:08 +00:00
newPosition,
),
);
}
2023-07-03 17:41:12 +00:00
void promotionHandler(
2023-07-05 19:16:01 +00:00
ReceivedPromotion event,
Emitter<ChessBoardState> emit,
) {
2023-07-03 17:41:12 +00:00
var pieceAtStartSquare = ChessPosition.getInstance().getPieceAt(
ChessCoordinate(event.startSquare.column, event.startSquare.row));
if (pieceAtStartSquare == null) {
log('received a promotion but start square was empty');
2023-07-03 17:41:12 +00:00
return;
}
ChessPieceClass pieceClass = ChessPieceClass.none;
for (var piece in chessPiecesShortName.entries) {
if (piece.value == event.piece) {
2023-07-03 17:41:12 +00:00
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
? ChessColor.black
: ChessColor.white;
2023-07-03 17:41:12 +00:00
emit(ChessBoardState(
state.bottomColor,
turnColor,
newPosition,
));
}
void ownMoveHandler(OwnPieceMoved event, Emitter<ChessBoardState> emit) {
log('ownMoveHandler()');
2023-07-03 17:41:12 +00:00
var apiMove =
ChessMove(from: event.startSquare, to: event.endSquare).toApiMove();
var apiMessage = ApiWebsocketMessage(
type: MessageType.move, move: apiMove, color: null, reason: null);
2023-06-08 15:10:48 +00:00
ServerConnection.getInstance().send(jsonEncode(apiMessage));
2023-06-08 15:10:48 +00:00
2023-06-29 23:49:18 +00:00
//Temporary chess position until server responds with acknowledgement
var move = ChessMove.fromApiMove(apiMove);
var tempPosition = ChessPosition.getInstance().copyOfCurrentPosition;
tempPosition[move.to] = tempPosition[move.from] ?? const ChessPiece.none();
tempPosition[move.from] = const ChessPiece.none();
2023-06-08 15:10:48 +00:00
emit(
ChessBoardState(
state.bottomColor,
turnColor,
tempPosition,
2023-06-08 15:10:48 +00:00
),
);
}
2023-07-03 17:41:12 +00:00
void ownPromotionHandler(
OwnPromotionPlayed event, Emitter<ChessBoardState> emit) {
var apiMove = event.move.toApiMove();
var shorNameForPiece = chessPiecesShortName[
ChessPieceAssetKey(pieceClass: event.pieceClass, color: myColor!)]!;
2023-07-03 17:41:12 +00:00
apiMove.promotionToPiece = shorNameForPiece;
var message = ApiWebsocketMessage(
type: MessageType.move,
move: apiMove,
color: null,
reason: null,
);
log(jsonEncode(message));
ServerConnection.getInstance().send(jsonEncode(message));
}
void invalidMoveHandler(
InvalidMovePlayed event, Emitter<ChessBoardState> emit) {
2023-07-01 07:29:43 +00:00
emit(
ChessBoardState(
state.bottomColor,
turnColor,
ChessPosition.getInstance().currentPosition,
),
);
}
2022-11-13 00:03:09 +00:00
}
class ChessBoardState {
2022-12-18 00:04:08 +00:00
late ChessColor bottomColor;
final ChessColor newTurnColor;
2022-11-13 00:03:09 +00:00
final Map<ChessCoordinate, ChessPiece> position;
2022-12-18 00:04:08 +00:00
ChessBoardState._(this.bottomColor, this.newTurnColor, this.position);
factory ChessBoardState(
2022-12-18 00:04:08 +00:00
ChessColor bottomColor,
ChessColor turnColor,
Map<ChessCoordinate, ChessPiece> position,
) {
2022-12-18 00:04:08 +00:00
return ChessBoardState._(bottomColor, turnColor, position);
}
factory ChessBoardState.init() {
2022-12-18 00:04:08 +00:00
ChessColor bottomColor = ChessColor.white;
ChessColor turnColor = ChessColor.white;
ChessPosition.getInstance().resetToStartingPosition();
return ChessBoardState(
bottomColor, turnColor, ChessPosition.getInstance().currentPosition);
}
void logPosition(Map<ChessCoordinate, ChessPiece> pos) {
// for (int i = 0; i < 7; i++)
}
2022-11-13 00:03:09 +00:00
}