Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multipart moves #68

Draft
wants to merge 5 commits into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions example/json/marseillais.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"name": "Marseillais Chess",
"description": "",
"bishopVersion": "1.4.0",
"boardSize": "8x8",
"pieceTypes": {
"P": {
"betza": "fmWfceFifmnD",
"promoOptions": {
"canPromote": true,
"canPromoteTo": false
},
"enPassantable": true,
"noSanSymbol": true,
"value": 100
},
"N": {"betza": "N", "value": 300},
"B": {"betza": "B", "value": 300},
"R": {"betza": "R", "value": 500},
"Q": {"betza": "Q", "value": 900},
"K": {
"betza": "K",
"royal": true,
"promoOptions": {
"canPromote": false,
"canPromoteTo": false
}
}
},
"castlingOptions": {
"enabled": true,
"kTarget": 6,
"qTarget": 2,
"fixedRooks": true,
"kRook": 7,
"qRook": 0,
"rookPiece": "R",
"useRookAsTarget": false
},
"promotionOptions": "bishop.promo.standard",
"materialConditions": {
"enabled": true,
"soloMaters": ["P", "Q", "R", "A", "C"],
"pairMaters": ["N"],
"combinedPairMaters": ["B"],
"specialCases": [["B", "N"]]
},
"startPosition": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
"enPassant": true,
"halfMoveDraw": 100,
"repetitionDraw": 3,
"turnEndCondition": {
"id": "bishop.turn.moveCount",
"count": 2,
"firstMoveCount": 1
}
}
53 changes: 53 additions & 0 deletions example/json/progressive.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"name": "Progressive Chess",
"description": "",
"bishopVersion": "1.4.0",
"boardSize": "8x8",
"pieceTypes": {
"P": {
"betza": "fmWfceFifmnD",
"promoOptions": {
"canPromote": true,
"canPromoteTo": false
},
"enPassantable": true,
"noSanSymbol": true,
"value": 100
},
"N": {"betza": "N", "value": 300},
"B": {"betza": "B", "value": 300},
"R": {"betza": "R", "value": 500},
"Q": {"betza": "Q", "value": 900},
"K": {
"betza": "K",
"royal": true,
"promoOptions": {
"canPromote": false,
"canPromoteTo": false
}
}
},
"castlingOptions": {
"enabled": true,
"kTarget": 6,
"qTarget": 2,
"fixedRooks": true,
"kRook": 7,
"qRook": 0,
"rookPiece": "R",
"useRookAsTarget": false
},
"promotionOptions": "bishop.promo.standard",
"materialConditions": {
"enabled": true,
"soloMaters": ["P", "Q", "R", "A", "C"],
"pairMaters": ["N"],
"combinedPairMaters": ["B"],
"specialCases": [["B", "N"]]
},
"startPosition": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
"enPassant": true,
"halfMoveDraw": 10,
"repetitionDraw": 3,
"turnEndCondition": "bishop.turn.moveCountInc"
}
2 changes: 2 additions & 0 deletions lib/src/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ enum Variants {
racingKings(CommonVariants.racingKings),
antichess(CommonVariants.antichess),
shatranj(CommonVariants.shatranj),
marseillais(CommonVariants.marseillais),
progressive(CommonVariants.progressive),
musketeer(Musketeer.variant),
xiangqi(Xiangqi.xiangqi),
miniXiangqi(Xiangqi.mini),
Expand Down
3 changes: 2 additions & 1 deletion lib/src/fen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,9 @@ ParseFenResult parseFen({
final state = BishopState(
board: board,
turn: turn,
moveNumber: (int.parse(fullMoves) - 1) * 2 + (turn == Bishop.black ? 1 : 0),
movePart: 0, // TODO: figure this out
halfMoves: int.parse(halfMoves),
fullMoves: int.parse(fullMoves),
epSquare: ep,
castlingRights: castling.castlingRights,
royalSquares: royalSquares,
Expand Down
26 changes: 24 additions & 2 deletions lib/src/game/game_movement.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,28 @@ extension GameMovement on Game {
);
}

// TODO: this should come after check calculation, needs refactor
if (variant.turnEndCondition != null) {
final bool newTurn = variant.turnEndCondition!(
newState,
state.moveNumber,
state.movePart,
state.turn,
);
newState = newState.copyWith(
turn: newTurn ? 1 - state.turn : state.turn,
moveNumber: newTurn ? state.moveNumber + 1 : state.moveNumber,
movePart: newTurn ? 0 : state.movePart + 1,
);
} else {
// TODO: OPTIMISE
newState = newState.copyWith(
turn: 1 - state.turn,
moveNumber: state.moveNumber + 1,
movePart: 0,
);
}

final moveMeta = generateMeta
? MoveMeta(
algebraic: toAlgebraic(move),
Expand Down Expand Up @@ -343,8 +365,8 @@ extension GameMovement on Game {
move: move,
turn: 1 - state.turn,
halfMoves: halfMoves,
fullMoves:
state.turn == Bishop.black ? state.fullMoves + 1 : state.fullMoves,
moveNumber: state.moveNumber, // TODO: optimise later
movePart: state.movePart,
castlingRights: castlingRights,
royalSquares: royalSquares,
virginFiles: virginFiles,
Expand Down
31 changes: 31 additions & 0 deletions lib/src/regions/not_region.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
part of 'regions.dart';

class NotRegion extends BoardRegion {
final BoardRegion region;

const NotRegion(this.region);

factory NotRegion.fromJson(Map<String, dynamic> json) =>
NotRegion(BoardRegion.fromJson(json['region']));

@override
bool contains(int file, int rank) => !region.contains(file, rank);

@override
Set<int> squares(BoardSize size) =>
RectRegion.lrbt(0, size.maxFile, 0, size.maxRank)
.squares(size)
.difference(region.squares(size).toSet());

@override
NotRegion translate(int x, int y) => NotRegion(region.translate(x, y));

@override
Map<String, dynamic> toJson() => {
'type': 'not',
'region': region.toJson(),
};

@override
String toString() => 'Not($region)';
}
16 changes: 14 additions & 2 deletions lib/src/regions/regions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ part 'area.dart';
part 'built_region.dart';
part 'rect_region.dart';
part 'intersect_region.dart';
part 'not_region.dart';
part 'region_effect.dart';
part 'set_region.dart';
part 'subtract_region.dart';
Expand Down Expand Up @@ -36,6 +37,7 @@ abstract class BoardRegion extends Region {
'xor': XorRegion.fromJson,
'set': SetRegion.fromJson,
'dset': DirectionSetRegion.fromJson,
'not': NotRegion.fromJson,
};

Map<String, dynamic> toJson();
Expand All @@ -56,15 +58,25 @@ abstract class BoardRegion extends Region {
BuiltRegion(squares(size).toList(), size);

UnionRegion operator +(BoardRegion other) => UnionRegion([
this,
if (this is UnionRegion) ...(this as UnionRegion).regions else this,
if (other is UnionRegion) ...other.regions else other,
]);
IntersectRegion operator &(BoardRegion other) => IntersectRegion([
this,
if (this is IntersectRegion)
...(this as IntersectRegion).regions
else
this,
if (other is IntersectRegion) ...other.regions else other,
]);
SubtractRegion operator -(BoardRegion other) => SubtractRegion(this, other);
XorRegion operator ^(BoardRegion other) => XorRegion(this, other);
NotRegion operator ~() => NotRegion(this);

bool equals(BoardRegion other, [BoardSize size = BoardSize.standard]) {
final s1 = squares(size).toSet();
final s2 = other.squares(size).toSet();
return s1.length == s2.length && s1.difference(s2).isEmpty;
}
}

class BoardRegionAdapter extends BishopTypeAdapter<BoardRegion> {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/serialisation/promo_adapters.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class StandardPromotionAdapter extends BishopTypeAdapter<StandardPromotion> {
);

@override
Map<String, dynamic>? export(StandardPromotion e) => {
Map<String, dynamic> export(StandardPromotion e) => {
if (e.pieceLimits != null) 'pieceLimits': e.pieceLimits,
if (e.ranks != null) 'ranks': e.ranks,
if (e.optional != false) 'optional': e.optional,
Expand Down
7 changes: 7 additions & 0 deletions lib/src/serialisation/serialisation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ part 'first_move_adapters.dart';
part 'pass_adapters.dart';
part 'promo_adapters.dart';
part 'state_transform_adapters.dart';
part 'turn_end_adapters.dart';
part 'type_adapter.dart';

class BishopSerialisation {
Expand All @@ -17,6 +18,7 @@ class BishopSerialisation {
...baseActionAdapters,
...baseFirstMoveAdapters,
...baseStateTransformAdapters,
...baseTurnEndAdapters,
];
return _baseAdapters!;
}
Expand Down Expand Up @@ -74,6 +76,11 @@ class BishopSerialisation {
VisionAreaAdapter(),
];

static List<BishopTypeAdapter> get baseTurnEndAdapters => [
MoveCountTurnAdapter(),
MoveCountIncTurnAdapter(),
];

static List<T> buildMany<T>(
List input, {
List<BishopTypeAdapter> adapters = const [],
Expand Down
37 changes: 37 additions & 0 deletions lib/src/serialisation/turn_end_adapters.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
part of 'serialisation.dart';

class MoveCountTurnAdapter extends BishopTypeAdapter<TurnEndMoveCount> {
@override
String get id => 'bishop.turn.moveCount';

@override
TurnEndMoveCount build(Map<String, dynamic>? params) => TurnEndMoveCount(
params!['count'],
firstMoveCount: params['firstMoveCount'],
);

@override
Map<String, dynamic> export(TurnEndMoveCount e) => {
'count': e.count,
if (e.firstMoveCount != null) 'firstMoveCount': e.firstMoveCount,
};
}

class MoveCountIncTurnAdapter
extends BishopTypeAdapter<TurnEndIncrementingMoveCount> {
@override
String get id => 'bishop.turn.moveCountInc';

@override
TurnEndIncrementingMoveCount build(Map<String, dynamic>? params) =>
TurnEndIncrementingMoveCount(
initial: params?['initial'] ?? 1,
increment: params?['increment'] ?? 1,
);

@override
Map<String, dynamic> export(TurnEndIncrementingMoveCount e) => {
if (e.initial != 1) 'initial': e.initial,
if (e.increment != 1) 'increment': e.increment,
};
}
15 changes: 10 additions & 5 deletions lib/src/state/masked_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ class MaskedState extends BishopState {
super.move,
super.meta,
required super.turn,
required super.moveNumber,
required super.movePart,
required super.halfMoves,
required super.fullMoves,
required super.castlingRights,
super.epSquare,
required super.royalSquares,
Expand All @@ -44,8 +45,9 @@ class MaskedState extends BishopState {
move: state.move,
meta: state.meta,
turn: state.turn,
moveNumber: state.moveNumber,
movePart: state.movePart,
halfMoves: state.halfMoves,
fullMoves: state.fullMoves,
castlingRights: state.castlingRights,
epSquare: state.epSquare,
royalSquares: state.royalSquares,
Expand Down Expand Up @@ -73,8 +75,9 @@ class MaskedState extends BishopState {
move: state.move,
meta: state.meta,
turn: state.turn,
moveNumber: state.moveNumber,
movePart: state.movePart,
halfMoves: state.halfMoves,
fullMoves: state.fullMoves,
castlingRights: state.castlingRights,
epSquare: state.epSquare,
royalSquares: state.royalSquares,
Expand All @@ -95,8 +98,9 @@ class MaskedState extends BishopState {
Move? move,
StateMeta? meta,
Colour? turn,
int? moveNumber,
int? movePart,
int? halfMoves,
int? fullMoves,
CastlingRights? castlingRights,
int? epSquare,
List<int>? royalSquares,
Expand All @@ -114,8 +118,9 @@ class MaskedState extends BishopState {
move: move ?? this.move,
meta: meta ?? this.meta,
turn: turn ?? this.turn,
moveNumber: moveNumber ?? this.moveNumber,
movePart: movePart ?? this.movePart,
halfMoves: halfMoves ?? this.halfMoves,
fullMoves: fullMoves ?? this.fullMoves,
castlingRights: castlingRights ?? this.castlingRights,
epSquare: epSquare ?? this.epSquare,
royalSquares: royalSquares ?? this.royalSquares,
Expand Down
Loading