chess.js
chess.js copied to clipboard
How to find defended and attacked pieces?
What´s the best way to get the number of defenders and attackers for each square? I want to show in the board what pieces are unguarded and the "influence" for each square, this is the number of attackers - defenders for that square. Maybe if the legal moves method had an option to include the squares that already have an own piece it could work.
I would like to have that functionality as well, I will give it a try. I see the following options (with different possible implementations then):
- 2 different calls, one for defended pieces (or squares), one for attacked pieces (or squares).
- each time the option to do that for the turn color, the other color, or both. Here an example
- Searching for defended pieces, you have to simulate that first an attack is done, and then the defenders are computed. Currently, chess.js does not support defending moves.
- Searching for attacking pieces, this will normally work in the current position for the color that has the turn. To get attacking pieces for the other color, you have to change the turn of the current position.
So the API could look like this:
-
attacked_pieces(color = null, attack_square = false)
- color: default is null ==> denotes the one that has the turn.
- BLACK | WHITE: defines for which color to search for attacked_pieces
-
defended_pieces(color)
with the same semantics - Both return something like
{'bd8': ['ne6', 'rd1'], 'qc7': ['ne6', 'bf4'], 'nf7': []}
==> Bishop on d8 is attacked by Knight on e6 and by Rook on d1 ...
I did it in a hacky way and used it here https://jsfiddle.net/m5q6fgtb/859/ (When you move a piece it show number of defenders and attackers per square).
To know the numbers of defenders for my piece (Same method can be used to know the attackers), I will remove that piece and put the enemy queen and then check how many of my pieces can capture it, so that's the number of defenders. Is not tested much so maybe it's wrong,but it can help someone.
function countSquareDefenders(boardElement, fen, square, me) {
var chess = new Chess(fenForOtherSide(fen));
var oppositeColor = chess.turn() == 'w' ? 'b' : 'w'
var queenSquare = squaresOfPiece(fen, oppositeColor, 'q');
var somePiece = chess.remove(square); // remove my piece if any
chess.remove(queenSquare); // remove his queen
chess.put({ // put queen in the square
type: 'q',
color: oppositeColor
}, square);
var moves = chess.moves({verbose: true, legal: false})
var defendersCount = moves.filter(m => m.to == square && m.flags =='c').length
if (somePiece && somePiece.color != oppositeColor) // count our own piece as controlling that square
defendersCount = parseInt(defendersCount)+1
return defendersCount
}
I tried a different approach. I checked carefully the (internal) function generate_moves
. All the logic is there, but by allowing defending moves
, you get the moves that defend your pieces (or squares if you want). Not sure if that is the right way, but the unit tests are promising. I will hopefully commit my solution tomorrow, so you can check the pull request, if that is easier to use.
The number of attackers and defenders may be sufficient sometimes, but sometimes not, so I would like to have that information complete.
I'd also love to have this information. I'm not sure using generate_moves
is necessarily the right approach though? It seems if there are checks involved, there could be very few valid moves, but still a rather complex "influence" map.
Should attacking and defending be based on a more naive move generation algorithm that doesn't account for check? In other words, look at all potential moves for all pieces, rather than just valid moves? Does that make any sense?
Has there been any progress on this since *checks date* February? I am working on a chess game project and it would be awesome if there were a drop-in library that could tell what pieces are being attacked in a position. (I don't know much about this project. Can I do this with the current state of this project?)
I need this so bad. I made a game that is based around select undefended pieces and I have isAttacked to see if a piece is defended, but I need to know what it's defended by because a king can't defend if the opponent threatens that square.
@chao-mu I could supply something generic returning a list of attacking square. It's up to the user to filter out which pieces they don't want in the list (in your case the king). So something like:
chess.load('r1bqkbnr/ppp2ppp/2np4/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 0 4')
chess.attackers('d2', WHITE)
// -> ['c1', 'd1', 'e1', 'f3']
chess.attackers('d2', BLACK)
// -> []
How about the pinned knight on c6, does that get included?
chess.attackers('d4', BLACK)
// -> ['c6', 'e5'] <-- should the c6 knight be included?
How about en-passant?
Whoops, deleted my post before seeing the response. There was a ton of bugs in it.
List of attacking squares would be perfect. I think attackers are only ones that can legally attack, so absolutely pinned pieces can't attack.
The problem with this is that defending is not a valid move unless there is a capture.
function getAttackers(chess, square: string, color: string) {
const attackers = Array.from(ALL_SQUARES).filter((attackerSquare) => {
const moves = chess.moves({ square: attackerSquare, verbose: true, color: color })
if (moves.length == 0) {
return false
}
console.log(attackerSquare, square, moves.map((move) => move.to))
return moves.some((move) => move.to == square)
})
return new Set<string>(attackers)
}
What I ended up doing was just checking the list of legal moves for captures and using those destination squares.
As far as additions to the API, perhaps there could be separate methods to get a list of legal captures and a list of pieces “aiming” at a square (even if pinned). Maybe it would make sense to also have a list of squares a pieces is aiming at
I am not concerned with captures, just defenders. I'm expecting "attackers" to return white attacking itself if specified by color
Essentially I want the contract for isAttacked where I can choose the color and therefore can use it to detect defenders.
This is what I'm working on: https://tactical-elements.netlify.app/