diff --git a/Chess/nimfish/nimfishpkg/see.nim b/Chess/nimfish/nimfishpkg/see.nim new file mode 100644 index 0000000..7c091ea --- /dev/null +++ b/Chess/nimfish/nimfishpkg/see.nim @@ -0,0 +1,59 @@ +# Copyright 2024 Mattia Giambirtone & All Contributors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +## Implementation of Static Exchange Evaluation +import std/algorithm + + +import position +import pieces +import movegen +import board +import eval + + +proc getSmallestAttacker(position: Position, square: Square, side: PieceColor): Square = + ## Returns the square containing the lowest value piece of the + ## given side attacking the given square in the given position. + ## If the given square is not attacked by the given side, a null + ## piece is returned + var attackers: seq[tuple[score: Score, square: Square]] = @[] + for attacker in position.getAttacksTo(square, side): + attackers.add((position.getPieceScore(attacker), attacker)) + + if attackers.len() == 0: + return nullSquare() + + proc orderer(a, b: tuple[score: Score, square: Square]): int {.closure.} = + return cmp(a.score, b.score) + + + attackers.sort(orderer) + return attackers[0].square + + +proc SEE(board: var Chessboard, square: Square, side: PieceColor): Score = + ## Recursive implementation of static exchange evaluation + let source = board.position.getSmallestAttacker(square, side) + if source == nullSquare(): + return Score(0) + + let captured = board.position.getPieceScore(square) + + board.doMove(createMove(source, square, Capture)) + result = max(0, captured - SEE(board, square, side.opposite())) + board.unmakeMove() + + +