omnichess/lib/classes/best_move_searcher.dart

76 lines
2.2 KiB
Dart

import 'dart:collection';
import 'package:omnichess/classes/position.dart';
import 'package:omnichess/constants/piece.dart';
import 'package:omnichess/functions/legal_moves.dart';
class BestMoveSearcher {
bool _isRunning = false;
bool _isStopped = false;
Future<int> getPositionBaseValue(Position position) async {
if (await LegalMoves.isCheckmate(position)) {
return position.isWhiteTurn
? -(1 << 63) // min int (white is checkmated)
: ((1 << 63) - 1); // max int (black is checkmated)
}
int value = 0;
for (int i = 0; i < 64; i++) {
value += switch (position.board[i]) {
Piece.whiteQueen => 900,
Piece.whiteRook => 500,
Piece.whiteBishop => 300,
Piece.whiteKnight => 300,
Piece.whitePawn => 100,
Piece.blackQueen => -900,
Piece.blackRook => -500,
Piece.blackBishop => -300,
Piece.blackKnight => -300,
Piece.blackPawn => -100,
_ => 0,
};
}
return value;
}
Future<String?> search(Position position) async {
_isRunning = true;
(int, String, Position)? bestMove;
Queue<(int, String, Position)> evaluatedMoves = Queue();
await for (final (String, Position) move in LegalMoves.getLegalMoves(position)) {
final (int, String, Position) evaluatedMove = (await getPositionBaseValue(move.$2), move.$1, move.$2);
if (
null == bestMove ||
(bestMove.$1 < evaluatedMove.$1 && position.isWhiteTurn) ||
(bestMove.$1 > evaluatedMove.$1 && !position.isWhiteTurn)
) {
bestMove = evaluatedMove;
}
evaluatedMoves.add(evaluatedMove);
await Future.delayed(Duration.zero);
if (_isStopped) {
break;
}
// TODO evaluate checkmate
}
if (evaluatedMoves.isEmpty) {
_isRunning = false;
_isStopped = false;
return null;
}
// TODO search
// IDEA implement a BFS with pruning on the ones that give suboptimal values
_isRunning = false;
_isStopped = false;
return bestMove?.$2;
}
Future<void> stop() async {
if (!_isRunning) {
return;
}
_isStopped = true;
}
}