Add ChessPosition that will handle position.
This commit is contained in:
parent
122731ac50
commit
8572aa73e6
@ -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,58 +57,44 @@ 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>(
|
||||
/* 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: () {},
|
||||
);
|
||||
},
|
||||
child: Draggable<PieceMovedFrom>(
|
||||
/* We create the move with the startSquare == endSquare. The receiving widget will give the correct value to end square. */
|
||||
data: PieceMovedFrom(coordinate, containedPiece),
|
||||
maxSimultaneousDrags:
|
||||
ChessBloc.turnColor == ChessBloc.myColor ? 1 : 0,
|
||||
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()}');
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
89
lib/chess_bloc/chess_position.dart
Normal file
89
lib/chess_bloc/chess_position.dart
Normal 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);
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user