-
Notifications
You must be signed in to change notification settings - Fork 25
/
SwarmKingPlayer.js
65 lines (54 loc) · 1.68 KB
/
SwarmKingPlayer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
const ChessUtils = require("../utils/ChessUtils")
/**
* Move pieces closer to own king - mate and check if possible.
*/
class SwarmKingPlayer {
getNextMove(moves) {
const chess = new ChessUtils()
chess.applyMoves(moves)
let legalMoves = chess.legalMoves()
const forcing = chess.filterForcing(legalMoves)
if (forcing.length) {
return chess.pickRandomMove(forcing)
}
legalMoves = this.removeReverseMoves(moves, legalMoves)
if (legalMoves.length) {
const colour = chess.turn()
// get distance to king in all successor states
legalMoves.forEach((m) => {
chess.move(m)
const squareOfKing = chess.squareOfOpponentsKing()
m.metric = this.distanceMetric(chess, squareOfKing, colour)
chess.undo()
})
// choose move that maximises metric
return chess.uci(legalMoves.reduce(this.randomMax))
}
}
randomMax(a, b) {
return a.metric + Math.random() > b.metric + Math.random() ? a : b
}
removeReverseMoves(previousUciMoves, legalMoves) {
const filtered = legalMoves.filter(
(move) => !previousUciMoves.includes(move.to + move.from)
)
return filtered.length === 0 ? legalMoves : filtered
}
/**
* Sum of (16 - manhattan distance to king) for each piece of given colour.
*/
distanceMetric(chess, targetSquare, colour) {
const target = chess.coordinates(targetSquare)
const distances = chess
.squaresOf(colour)
.map(
(square) =>
16 - chess.manhattanDistance(target, chess.coordinates(square))
)
return distances.reduce((a, b) => a + b, 0)
}
getReply(chat) {
return "swarm the king!"
}
}
module.exports = SwarmKingPlayer