Skip to content

Commit afb1728

Browse files
committed
Incredible hihg speed
1 parent 46098bf commit afb1728

File tree

5 files changed

+105
-29
lines changed

5 files changed

+105
-29
lines changed

.vscode/launch.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
"name": "example",
1414
"cwd": "example",
1515
"request": "launch",
16-
"type": "dart"
16+
"type": "dart",
17+
"program": "example.dart",
18+
"args": []
1719
}
1820
]
1921
}

lib/src/game/game.dart

+30-27
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ class Game {
108108
(target.colour == colour || target.colour == Bishop.neutralPassive)) {
109109
List<Move> pieceMoves = generatePieceMoves(i, options);
110110
moves.addAll(pieceMoves);
111+
if (options.onlyOne && moves.isNotEmpty) return moves;
111112
}
112113
}
113114
if (variant.handsEnabled && options.quiet && !options.onlyPiece) {
@@ -209,11 +210,40 @@ class Game {
209210
}
210211
}
211212

213+
void addMove(StandardMove m) {
214+
final mm = variant.generatePromotionMoves(
215+
base: m,
216+
state: state,
217+
pieceType: pieceType,
218+
);
219+
if (mm != null) moves.addAll(mm);
220+
if (mm == null) moves.add(m);
221+
if (variant.gating) {
222+
int gRank = size.rank(m.from);
223+
if ((gRank == Bishop.rank1 && colour == Bishop.white) ||
224+
(gRank == size.maxRank && colour == Bishop.black)) {
225+
final gatingMoves = generateGatingMoves(m);
226+
moves.addAll(gatingMoves);
227+
if (gatingMoves.isNotEmpty &&
228+
variant.gatingMode == GatingMode.fixed) {
229+
moves.remove(m);
230+
}
231+
}
232+
}
233+
if (options.onlySquare != null && m.to == options.onlySquare) {
234+
exit = true;
235+
}
236+
}
237+
212238
// Generate normal moves
213239
for (MoveDefinition md in pieceType.moves) {
214240
if (exit) break;
215241
if (!md.capture && !options.quiet) continue;
216242
if (!md.quiet && !options.captures) continue;
243+
if (options.onlySquare != null &&
244+
md.excludeMove(square, options.onlySquare!, dirMult, size)) {
245+
continue;
246+
}
217247
if (md is TeleportMoveDefinition) {
218248
generateTeleportMoves(md);
219249
continue;
@@ -271,33 +301,6 @@ class Game {
271301
}
272302
}
273303

274-
void addMove(StandardMove m) {
275-
final mm = variant.generatePromotionMoves(
276-
base: m,
277-
state: state,
278-
pieceType: pieceType,
279-
);
280-
if (mm != null) moves.addAll(mm);
281-
// bool removeBase = false;
282-
if (mm == null) moves.add(m);
283-
if (variant.gating) {
284-
int gRank = size.rank(m.from);
285-
if ((gRank == Bishop.rank1 && colour == Bishop.white) ||
286-
(gRank == size.maxRank && colour == Bishop.black)) {
287-
final gatingMoves = generateGatingMoves(m);
288-
moves.addAll(gatingMoves);
289-
if (gatingMoves.isNotEmpty &&
290-
variant.gatingMode == GatingMode.fixed) {
291-
moves.remove(m);
292-
}
293-
}
294-
}
295-
// if (!addBase) moves.remove(m);
296-
if (options.onlySquare != null && m.to == options.onlySquare) {
297-
exit = true;
298-
}
299-
}
300-
301304
if (target.isEmpty) {
302305
// TODO: prioritise ep? for moves that could be both ep and quiet
303306
if (md.quiet) {

lib/src/move/move_definition.dart

+46
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ abstract class MoveDefinition {
2525

2626
bool get quiet => modality == Modality.both || modality == Modality.quiet;
2727
bool get capture => modality == Modality.both || modality == Modality.capture;
28+
29+
/// Used to rapidly exclude moves in cases where we're looking for attacks.
30+
bool excludeMove(int from, int to, int dirMult, BoardSize size) => false;
2831
}
2932

3033
class TeleportMoveDefinition extends MoveDefinition {
@@ -65,6 +68,8 @@ class StandardMoveDefinition extends MoveDefinition {
6568
final int? lameNormalised;
6669

6770
bool get slider => range != 1;
71+
bool get unlimitedSlider => range == 0;
72+
bool get limitedSlider => range > 1;
6873
bool get hopper => slider && hopDistance > -1;
6974
bool get limitedHopper => slider && hopDistance > 0;
7075

@@ -139,6 +144,19 @@ class StandardMoveDefinition extends MoveDefinition {
139144
);
140145
}
141146

147+
@override
148+
bool excludeMove(int from, int to, int dirMult, BoardSize size) {
149+
if (!slider) {
150+
return from + (normalised * dirMult) != to;
151+
}
152+
final n = normalised * dirMult;
153+
if (n > 0 != to > from) return true;
154+
if (n == 0) return from == to; // idk could happen
155+
// There might be optimisations for limited sliders that
156+
// could go here, but this is pretty fast.
157+
return (to - from) % n != 0;
158+
}
159+
142160
@override
143161
String toString() {
144162
String string = '$direction [${modality.name}] [$normalised]';
@@ -168,6 +186,7 @@ class Direction {
168186
}
169187

170188
static const none = Direction(0, 0);
189+
static const unit = Direction(1, 1);
171190

172191
String get simpleString => '$h,$v';
173192

@@ -215,6 +234,33 @@ class Direction {
215234
bool operator ==(Object other) =>
216235
other is Direction && h == other.h && v == other.v;
217236

237+
Direction operator +(Direction other) => Direction(h + other.h, v + other.v);
238+
Direction operator -(Direction other) => Direction(h - other.h, v - other.v);
239+
240+
Direction operator *(Object other) {
241+
if (other is Direction) {
242+
return Direction(h * other.h, v * other.v);
243+
}
244+
if (other is int) {
245+
return other == 1 ? this : Direction(h * other, v * other);
246+
}
247+
throw Exception('Direction can only be multiplied by an int or another'
248+
'Direction (tried to use ${other.runtimeType}).');
249+
}
250+
251+
Direction operator ~/(Object other) {
252+
if (other is Direction) {
253+
return Direction(h ~/ other.h, v ~/ other.v);
254+
}
255+
if (other is int) {
256+
return other == 1 ? this : Direction(h ~/ other, v ~/ other);
257+
}
258+
throw Exception('Direction can only be divided by an int or another'
259+
'Direction (tried to use ${other.runtimeType}).');
260+
}
261+
262+
Direction operator -() => Direction(-h, -v);
263+
218264
@override
219265
int get hashCode => (h << 8) + v;
220266
}

lib/src/move_gen_params.dart

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class MoveGenParams {
66
final bool ignorePieces;
77
final int? pieceType;
88
final int? onlySquare;
9+
final bool onlyOne;
910

1011
bool get onlyPiece => pieceType != null;
1112

@@ -17,6 +18,7 @@ class MoveGenParams {
1718
this.ignorePieces = false,
1819
this.pieceType,
1920
this.onlySquare,
21+
this.onlyOne = false,
2022
});
2123
static const normal = MoveGenParams(
2224
captures: true,
@@ -49,12 +51,14 @@ class MoveGenParams {
4951
legal: false,
5052
pieceType: pieceType,
5153
);
52-
factory MoveGenParams.squareAttacks(int square) => MoveGenParams(
54+
factory MoveGenParams.squareAttacks(int square, [bool onlyOne = true]) =>
55+
MoveGenParams(
5356
captures: true,
5457
quiet: false,
5558
castling: false,
5659
legal: false,
5760
onlySquare: square,
61+
onlyOne: onlyOne,
5862
);
5963
static const premoves = MoveGenParams(
6064
captures: true,

lib/src/variant/board_size.dart

+21
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,27 @@ class BoardSize {
6464
/// Returns true if [a] and [b] are on the same rank.
6565
bool squaresOnSameRank(int a, int b) => rank(a) == rank(b);
6666

67+
/// Whether [a] and [b] are connected by a rook move.
68+
bool orthogonallyConnected(int a, int b) =>
69+
squaresOnSameFile(a, b) || squaresOnSameRank(a, b);
70+
71+
/// Whether [a] and [b] are connected by a bishop move.
72+
bool diagonallyConnected(int a, int b) =>
73+
rank(b) - rank(a) == file(b) - file(a);
74+
75+
/// Whether [a] and [b] are connected by a move in [direction].
76+
bool connected(int a, int b, Direction direction) {
77+
int fileDiff = file(b) - file(a);
78+
if (direction.h == 0 && fileDiff != 0) return false;
79+
int rankDiff = rank(b) - rank(a);
80+
if (direction.v == 0 && rankDiff != 0) return false;
81+
if (direction.h != 0 && fileDiff % direction.h != 0) return false;
82+
if (direction.v != 0 && rankDiff % direction.v != 0) return false;
83+
return true;
84+
return ((file(b) - file(a)).abs() % direction.h == 0) &&
85+
(rank(b) - rank(a)).abs() % direction.v == 0;
86+
}
87+
6788
/// Get the first rank for player [colour].
6889
int firstRank(int colour) => colour == Bishop.white ? Bishop.rank1 : maxRank;
6990

0 commit comments

Comments
 (0)