Add ChessPosition that will handle position.

This commit is contained in:
Marco 2023-01-30 22:39:13 +01:00
parent 122731ac50
commit 8572aa73e6
6 changed files with 179 additions and 111 deletions

View File

@ -1,13 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:mchess/chess_bloc/chess_bloc.dart';
import '../connection/ws_connection.dart';
import '../chess_bloc/chess_events.dart';
import '../utils/chess_utils.dart';
int messageIndex = 0;
class ChessSquare extends StatelessWidget {
final ChessCoordinate coordinate;
final ChessPiece? containedPiece;
@ -60,33 +57,29 @@ class ChessSquare extends StatelessWidget {
draggableFdbSize = 0.15 * windowHeight;
}
return DragTarget<ChessMove>(
return DragTarget<PieceMovedFrom>(
onWillAccept: (move) {
if (move?.fromSquare == coordinate) {
return false;
}
return true;
},
onAccept: (move) {
if (coordinate != move.fromSquare) {
ChessBloc.getInstance().add(OwnPieceMoved(
startSquare: move.fromSquare, endSquare: coordinate));
}
},
builder: (context, candidateData, rejectedData) {
return Container(
color: color,
width: ChessSquare.pieceWidth,
height: ChessSquare.pieceWidth,
child: BlocBuilder<ChessBloc, ChessBoardState>(
builder: (context, state) {
int allowDrags = 0;
if (ChessBloc.myColor == null) {
allowDrags = 0;
} else {
if (containedPiece == null) {
allowDrags = 0;
} else if (containedPiece!.color == ChessBloc.myColor) {
if (ChessBloc.myColor == state.newTurnColor) {
allowDrags = 1;
} else {
allowDrags = 0;
}
}
}
return Draggable<ChessMove>(
child: Draggable<PieceMovedFrom>(
/* We create the move with the startSquare == endSquare. The receiving widget will give the correct value to end square. */
data: ChessMove(coordinate, coordinate, containedPiece),
maxSimultaneousDrags: allowDrags,
data: PieceMovedFrom(coordinate, containedPiece),
maxSimultaneousDrags:
ChessBloc.turnColor == ChessBloc.myColor ? 1 : 0,
feedback: FractionalTranslation(
translation: const Offset(-0.5, -0.75),
child: SizedBox(
@ -99,19 +92,9 @@ class ChessSquare extends StatelessWidget {
child: containedPiece ?? Container(),
onDragCompleted: () {},
onDragStarted: () {},
);
},
),
);
},
onAccept: (move) {
move.endSquare = coordinate;
if (move.endSquare != move.startSquare) {
ServerConnection.getInstance().send(
'mv ${move.startSquare.toString()} ${move.endSquare.toString()}');
}
},
);
}
}

View File

@ -1,10 +1,13 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:mchess/chess_bloc/chess_events.dart';
import 'package:mchess/chess_bloc/chess_position.dart';
import 'package:mchess/connection/ws_connection.dart';
import 'package:mchess/utils/chess_utils.dart';
import 'dart:developer';
class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
static final ChessBloc _instance = ChessBloc._internal();
static ChessColor turnColor = ChessColor.white;
static ChessColor? myColor;
static ChessColor? getSidesColor() {
@ -14,7 +17,8 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
ChessBloc._internal() : super(ChessBoardState.init()) {
on<InitBoard>(initBoard);
on<ColorDetermined>(flipBoard);
on<PieceMoved>(moveHandler);
on<OpponentPieceMoved>(opponentMoveHandler);
on<OwnPieceMoved>(ownMoveHandler);
}
factory ChessBloc.getInstance() {
@ -35,25 +39,32 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
emit(ChessBoardState(event.myColor, state.newTurnColor, state.position));
}
void moveHandler(PieceMoved event, Emitter<ChessBoardState> emit) {
Map<ChessCoordinate, ChessPiece> newPosition = state.position;
void opponentMoveHandler(
OpponentPieceMoved event, Emitter<ChessBoardState> emit) {
ChessPosition.getInstance().recordMove(event.startSquare, event.endSquare);
var newPosition = ChessPosition.getInstance().currentPosition;
newPosition[event.endSquare] = state.position[event.startSquare]!;
newPosition[event.startSquare] = const ChessPiece.none();
var newTurnColor = state.newTurnColor == ChessColor.white
turnColor = state.newTurnColor == ChessColor.white
? ChessColor.black
: ChessColor.white;
log('emitting new state with position $newPosition');
emit(
ChessBoardState(
state.bottomColor,
newTurnColor,
turnColor,
newPosition,
),
);
}
void ownMoveHandler(OwnPieceMoved event, Emitter<ChessBoardState> emit) {
ChessPosition.getInstance().recordMove(event.startSquare, event.endSquare);
ServerConnection.getInstance().send(
'mv ${event.startSquare.toString()} ${event.endSquare.toString()}');
}
}
class ChessBoardState {
@ -74,50 +85,10 @@ class ChessBoardState {
factory ChessBoardState.init() {
ChessColor bottomColor = ChessColor.white;
ChessColor turnColor = ChessColor.white;
Map<ChessCoordinate, ChessPiece> position = {};
Map<ChessCoordinate, ChessPiece> position =
ChessPosition.getInstance().currentPosition;
for (int i = 1; i <= 8; i++) {
position[ChessCoordinate(i, 7)] =
ChessPiece(ChessPieceName.blackPawn, ChessColor.black);
position[ChessCoordinate(i, 2)] =
ChessPiece(ChessPieceName.whitePawn, ChessColor.white);
}
position[ChessCoordinate(1, 8)] =
ChessPiece(ChessPieceName.blackRook, ChessColor.black);
position[ChessCoordinate(2, 8)] =
ChessPiece(ChessPieceName.blackKnight, ChessColor.black);
position[ChessCoordinate(3, 8)] =
ChessPiece(ChessPieceName.blackBishop, ChessColor.black);
position[ChessCoordinate(4, 8)] =
ChessPiece(ChessPieceName.blackQueen, ChessColor.black);
position[ChessCoordinate(5, 8)] =
ChessPiece(ChessPieceName.blackKing, ChessColor.black);
position[ChessCoordinate(6, 8)] =
ChessPiece(ChessPieceName.blackBishop, ChessColor.black);
position[ChessCoordinate(7, 8)] =
ChessPiece(ChessPieceName.blackKnight, ChessColor.black);
position[ChessCoordinate(8, 8)] =
ChessPiece(ChessPieceName.blackRook, ChessColor.black);
position[ChessCoordinate(1, 1)] =
ChessPiece(ChessPieceName.whiteRook, ChessColor.white);
position[ChessCoordinate(2, 1)] =
ChessPiece(ChessPieceName.whiteKnight, ChessColor.white);
position[ChessCoordinate(3, 1)] =
ChessPiece(ChessPieceName.whiteBishop, ChessColor.white);
position[ChessCoordinate(4, 1)] =
ChessPiece(ChessPieceName.whiteQueen, ChessColor.white);
position[ChessCoordinate(5, 1)] =
ChessPiece(ChessPieceName.whiteKing, ChessColor.white);
position[ChessCoordinate(6, 1)] =
ChessPiece(ChessPieceName.whiteBishop, ChessColor.white);
position[ChessCoordinate(7, 1)] =
ChessPiece(ChessPieceName.whiteKnight, ChessColor.white);
position[ChessCoordinate(8, 1)] =
ChessPiece(ChessPieceName.whiteRook, ChessColor.white);
return ChessBoardState._(bottomColor, turnColor, position);
return ChessBoardState(bottomColor, turnColor, position);
}
void logPosition(Map<ChessCoordinate, ChessPiece> pos) {

View File

@ -2,11 +2,18 @@ import 'package:mchess/utils/chess_utils.dart';
abstract class ChessEvent {}
class PieceMoved extends ChessEvent {
class OpponentPieceMoved extends ChessEvent {
final ChessCoordinate startSquare;
final ChessCoordinate endSquare;
PieceMoved({required this.startSquare, required this.endSquare});
OpponentPieceMoved({required this.startSquare, required this.endSquare});
}
class OwnPieceMoved extends ChessEvent {
final ChessCoordinate startSquare;
final ChessCoordinate endSquare;
OwnPieceMoved({required this.startSquare, required this.endSquare});
}
class InitBoard extends ChessEvent {

View File

@ -0,0 +1,89 @@
import 'dart:developer';
import 'package:mchess/utils/chess_utils.dart';
typedef ChessPositionType = Map<ChessCoordinate, ChessPiece>;
class ChessPosition {
static final ChessPosition _instance = ChessPosition._internal();
late ChessPositionType position;
static ChessPosition getInstance() {
return _instance;
}
ChessPosition({required this.position});
factory ChessPosition._internal() {
ChessPositionType pos = {};
for (int i = 1; i <= 8; i++) {
pos[ChessCoordinate(i, 7)] =
ChessPiece(ChessPieceName.blackPawn, ChessColor.black);
pos[ChessCoordinate(i, 2)] =
ChessPiece(ChessPieceName.whitePawn, ChessColor.white);
}
pos[ChessCoordinate(1, 8)] =
ChessPiece(ChessPieceName.blackRook, ChessColor.black);
pos[ChessCoordinate(2, 8)] =
ChessPiece(ChessPieceName.blackKnight, ChessColor.black);
pos[ChessCoordinate(3, 8)] =
ChessPiece(ChessPieceName.blackBishop, ChessColor.black);
pos[ChessCoordinate(4, 8)] =
ChessPiece(ChessPieceName.blackQueen, ChessColor.black);
pos[ChessCoordinate(5, 8)] =
ChessPiece(ChessPieceName.blackKing, ChessColor.black);
pos[ChessCoordinate(6, 8)] =
ChessPiece(ChessPieceName.blackBishop, ChessColor.black);
pos[ChessCoordinate(7, 8)] =
ChessPiece(ChessPieceName.blackKnight, ChessColor.black);
pos[ChessCoordinate(8, 8)] =
ChessPiece(ChessPieceName.blackRook, ChessColor.black);
pos[ChessCoordinate(1, 1)] =
ChessPiece(ChessPieceName.whiteRook, ChessColor.white);
pos[ChessCoordinate(2, 1)] =
ChessPiece(ChessPieceName.whiteKnight, ChessColor.white);
pos[ChessCoordinate(3, 1)] =
ChessPiece(ChessPieceName.whiteBishop, ChessColor.white);
pos[ChessCoordinate(4, 1)] =
ChessPiece(ChessPieceName.whiteQueen, ChessColor.white);
pos[ChessCoordinate(5, 1)] =
ChessPiece(ChessPieceName.whiteKing, ChessColor.white);
pos[ChessCoordinate(6, 1)] =
ChessPiece(ChessPieceName.whiteBishop, ChessColor.white);
pos[ChessCoordinate(7, 1)] =
ChessPiece(ChessPieceName.whiteKnight, ChessColor.white);
pos[ChessCoordinate(8, 1)] =
ChessPiece(ChessPieceName.whiteRook, ChessColor.white);
return ChessPosition(position: pos);
}
ChessPositionType get currentPosition => position;
void recordMove(ChessCoordinate from, ChessCoordinate to) {
position[to] = position[from] ?? const ChessPiece.none();
position[from] = const ChessPiece.none();
logPosition(position);
}
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);
}
}

View File

@ -67,8 +67,8 @@ class ServerConnection {
log('Move received : ${splitString[1]}:${splitString[2]}');
ChessBloc.getInstance()
.add(PieceMoved(startSquare: startSquare, endSquare: endSquare));
ChessBloc.getInstance().add(
OpponentPieceMoved(startSquare: startSquare, endSquare: endSquare));
}
});
}

View File

@ -36,6 +36,22 @@ Map<ChessPieceName, String> chessPiecesAssets = {
ChessPieceName.none: 'assets/empty.svg',
};
Map<ChessPieceName, String> chessPiecesShortName = {
ChessPieceName.whitePawn: 'P',
ChessPieceName.whiteBishop: 'B',
ChessPieceName.whiteKnight: 'N',
ChessPieceName.whiteRook: 'R',
ChessPieceName.whiteQueen: 'Q',
ChessPieceName.whiteKing: 'K',
ChessPieceName.blackPawn: 'p',
ChessPieceName.blackBishop: 'b',
ChessPieceName.blackKnight: 'n',
ChessPieceName.blackRook: 'r',
ChessPieceName.blackQueen: 'q',
ChessPieceName.blackKing: 'k',
ChessPieceName.none: 'X',
};
class ChessCoordinate {
final int column;
final int row;
@ -91,22 +107,26 @@ class ChessCoordinate {
class ChessPiece extends StatelessWidget {
final ChessColor color;
final ChessPieceName pieceName;
final String shortName;
final Widget? pieceImage;
const ChessPiece._(this.pieceName, this.color, this.pieceImage);
const ChessPiece._(
this.pieceName, this.color, this.pieceImage, this.shortName);
factory ChessPiece(ChessPieceName name, ChessColor color) {
Widget? pieceImage;
String pieceAssetUrl = chessPiecesAssets[name]!;
String shortName = chessPiecesShortName[name]!;
pieceImage = SvgPicture.asset(pieceAssetUrl);
return ChessPiece._(name, color, pieceImage);
return ChessPiece._(name, color, pieceImage, shortName);
}
const ChessPiece.none({super.key})
: pieceName = ChessPieceName.none,
color = ChessColor.white,
pieceImage = null;
pieceImage = null,
shortName = "-";
@override
Widget build(BuildContext context) {
@ -116,11 +136,9 @@ class ChessPiece extends StatelessWidget {
}
}
class ChessMove {
ChessCoordinate startSquare;
ChessCoordinate endSquare;
class PieceMovedFrom {
ChessCoordinate fromSquare;
ChessPiece? movedPiece;
ChessPiece? pieceOnEndSquare;
ChessMove(this.startSquare, this.endSquare, this.movedPiece);
PieceMovedFrom(this.fromSquare, this.movedPiece);
}