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/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:mchess/chess_bloc/chess_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'; import '../utils/chess_utils.dart';
int messageIndex = 0;
class ChessSquare extends StatelessWidget { class ChessSquare extends StatelessWidget {
final ChessCoordinate coordinate; final ChessCoordinate coordinate;
final ChessPiece? containedPiece; final ChessPiece? containedPiece;
@ -60,58 +57,44 @@ class ChessSquare extends StatelessWidget {
draggableFdbSize = 0.15 * windowHeight; 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) { builder: (context, candidateData, rejectedData) {
return Container( return Container(
color: color, color: color,
width: ChessSquare.pieceWidth, width: ChessSquare.pieceWidth,
height: ChessSquare.pieceWidth, height: ChessSquare.pieceWidth,
child: BlocBuilder<ChessBloc, ChessBoardState>( child: Draggable<PieceMovedFrom>(
builder: (context, state) { /* We create the move with the startSquare == endSquare. The receiving widget will give the correct value to end square. */
int allowDrags = 0; data: PieceMovedFrom(coordinate, containedPiece),
if (ChessBloc.myColor == null) { maxSimultaneousDrags:
allowDrags = 0; ChessBloc.turnColor == ChessBloc.myColor ? 1 : 0,
} else { feedback: FractionalTranslation(
if (containedPiece == null) { translation: const Offset(-0.5, -0.75),
allowDrags = 0; child: SizedBox(
} else if (containedPiece!.color == ChessBloc.myColor) { height: draggableFdbSize,
if (ChessBloc.myColor == state.newTurnColor) { width: draggableFdbSize,
allowDrags = 1; child: containedPiece),
} else { ),
allowDrags = 0; childWhenDragging: Container(),
} dragAnchorStrategy: pointerDragAnchorStrategy,
} child: containedPiece ?? Container(),
} onDragCompleted: () {},
onDragStarted: () {},
return Draggable<ChessMove>(
/* 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,
feedback: FractionalTranslation(
translation: const Offset(-0.5, -0.75),
child: SizedBox(
height: draggableFdbSize,
width: draggableFdbSize,
child: containedPiece),
),
childWhenDragging: Container(),
dragAnchorStrategy: pointerDragAnchorStrategy,
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:flutter_bloc/flutter_bloc.dart';
import 'package:mchess/chess_bloc/chess_events.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 'package:mchess/utils/chess_utils.dart';
import 'dart:developer'; import 'dart:developer';
class ChessBloc extends Bloc<ChessEvent, ChessBoardState> { class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
static final ChessBloc _instance = ChessBloc._internal(); static final ChessBloc _instance = ChessBloc._internal();
static ChessColor turnColor = ChessColor.white;
static ChessColor? myColor; static ChessColor? myColor;
static ChessColor? getSidesColor() { static ChessColor? getSidesColor() {
@ -14,7 +17,8 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
ChessBloc._internal() : super(ChessBoardState.init()) { ChessBloc._internal() : super(ChessBoardState.init()) {
on<InitBoard>(initBoard); on<InitBoard>(initBoard);
on<ColorDetermined>(flipBoard); on<ColorDetermined>(flipBoard);
on<PieceMoved>(moveHandler); on<OpponentPieceMoved>(opponentMoveHandler);
on<OwnPieceMoved>(ownMoveHandler);
} }
factory ChessBloc.getInstance() { factory ChessBloc.getInstance() {
@ -35,25 +39,32 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
emit(ChessBoardState(event.myColor, state.newTurnColor, state.position)); emit(ChessBoardState(event.myColor, state.newTurnColor, state.position));
} }
void moveHandler(PieceMoved event, Emitter<ChessBoardState> emit) { void opponentMoveHandler(
Map<ChessCoordinate, ChessPiece> newPosition = state.position; OpponentPieceMoved event, Emitter<ChessBoardState> emit) {
ChessPosition.getInstance().recordMove(event.startSquare, event.endSquare);
var newPosition = ChessPosition.getInstance().currentPosition;
newPosition[event.endSquare] = state.position[event.startSquare]!; turnColor = state.newTurnColor == ChessColor.white
newPosition[event.startSquare] = const ChessPiece.none();
var newTurnColor = state.newTurnColor == ChessColor.white
? ChessColor.black ? ChessColor.black
: ChessColor.white; : ChessColor.white;
log('emitting new state with position $newPosition'); log('emitting new state with position $newPosition');
emit( emit(
ChessBoardState( ChessBoardState(
state.bottomColor, state.bottomColor,
newTurnColor, turnColor,
newPosition, 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 { class ChessBoardState {
@ -74,50 +85,10 @@ class ChessBoardState {
factory ChessBoardState.init() { factory ChessBoardState.init() {
ChessColor bottomColor = ChessColor.white; ChessColor bottomColor = ChessColor.white;
ChessColor turnColor = ChessColor.white; ChessColor turnColor = ChessColor.white;
Map<ChessCoordinate, ChessPiece> position = {}; Map<ChessCoordinate, ChessPiece> position =
ChessPosition.getInstance().currentPosition;
for (int i = 1; i <= 8; i++) { return ChessBoardState(bottomColor, turnColor, position);
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);
} }
void logPosition(Map<ChessCoordinate, ChessPiece> pos) { void logPosition(Map<ChessCoordinate, ChessPiece> pos) {

View File

@ -2,11 +2,18 @@ import 'package:mchess/utils/chess_utils.dart';
abstract class ChessEvent {} abstract class ChessEvent {}
class PieceMoved extends ChessEvent { class OpponentPieceMoved extends ChessEvent {
final ChessCoordinate startSquare; final ChessCoordinate startSquare;
final ChessCoordinate endSquare; 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 { 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]}'); log('Move received : ${splitString[1]}:${splitString[2]}');
ChessBloc.getInstance() ChessBloc.getInstance().add(
.add(PieceMoved(startSquare: startSquare, endSquare: endSquare)); OpponentPieceMoved(startSquare: startSquare, endSquare: endSquare));
} }
}); });
} }

View File

@ -36,6 +36,22 @@ Map<ChessPieceName, String> chessPiecesAssets = {
ChessPieceName.none: 'assets/empty.svg', 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 { class ChessCoordinate {
final int column; final int column;
final int row; final int row;
@ -91,22 +107,26 @@ class ChessCoordinate {
class ChessPiece extends StatelessWidget { class ChessPiece extends StatelessWidget {
final ChessColor color; final ChessColor color;
final ChessPieceName pieceName; final ChessPieceName pieceName;
final String shortName;
final Widget? pieceImage; 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) { factory ChessPiece(ChessPieceName name, ChessColor color) {
Widget? pieceImage; Widget? pieceImage;
String pieceAssetUrl = chessPiecesAssets[name]!; String pieceAssetUrl = chessPiecesAssets[name]!;
String shortName = chessPiecesShortName[name]!;
pieceImage = SvgPicture.asset(pieceAssetUrl); pieceImage = SvgPicture.asset(pieceAssetUrl);
return ChessPiece._(name, color, pieceImage); return ChessPiece._(name, color, pieceImage, shortName);
} }
const ChessPiece.none({super.key}) const ChessPiece.none({super.key})
: pieceName = ChessPieceName.none, : pieceName = ChessPieceName.none,
color = ChessColor.white, color = ChessColor.white,
pieceImage = null; pieceImage = null,
shortName = "-";
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -116,11 +136,9 @@ class ChessPiece extends StatelessWidget {
} }
} }
class ChessMove { class PieceMovedFrom {
ChessCoordinate startSquare; ChessCoordinate fromSquare;
ChessCoordinate endSquare;
ChessPiece? movedPiece; ChessPiece? movedPiece;
ChessPiece? pieceOnEndSquare;
ChessMove(this.startSquare, this.endSquare, this.movedPiece); PieceMovedFrom(this.fromSquare, this.movedPiece);
} }