From 603da2e62005eafadefae450a67b800b79a253bc Mon Sep 17 00:00:00 2001 From: earthtraveller1 Date: Sun, 21 Sep 2025 19:19:22 -0400 Subject: [PATCH 1/8] Removed a dead branch - it appears that this is never executed. --- cmd/silverfish/main.go | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/cmd/silverfish/main.go b/cmd/silverfish/main.go index c323484..378e669 100644 --- a/cmd/silverfish/main.go +++ b/cmd/silverfish/main.go @@ -84,7 +84,6 @@ func main() { messageChannel := make(chan engine.UciClientMessage, 5) // Used for reporting if an action is done. actionAlertChannel := make(chan bool) - active := false position := engine.StartingPosition() @@ -99,30 +98,21 @@ mainloop: continue } - if active { - select { - case <-actionAlertChannel: - active = false - default: - // Do nothing :ye: - } - } else { - switch message.MessageType { - case engine.UciUciClientMessage: - engine.UciSetEngineName("Silverfish 0.0.0a") - engine.UciSetAuthor("李能和赵梁越") - engine.UciSetProtocol(2) - - engine.UciOk() - case engine.UciIsReadyClientMessage: - engine.UciReadyOk() - case engine.UciPositionClientMessage: - position = *message.Position - case engine.UciQuitClientMessage: - break mainloop - case engine.UciGoClientMessage: - go executeGoCommand(actionAlertChannel, &position, message.GoMessage) - } + switch message.MessageType { + case engine.UciUciClientMessage: + engine.UciSetEngineName("Silverfish 0.0.0a") + engine.UciSetAuthor("李能和赵梁越") + engine.UciSetProtocol(2) + + engine.UciOk() + case engine.UciIsReadyClientMessage: + engine.UciReadyOk() + case engine.UciPositionClientMessage: + position = *message.Position + case engine.UciQuitClientMessage: + break mainloop + case engine.UciGoClientMessage: + go executeGoCommand(actionAlertChannel, &position, message.GoMessage) } } } From 59b16f189fe4f26dc6fa43071d5d9099ddc22b7d Mon Sep 17 00:00:00 2001 From: earthtraveller1 Date: Sun, 21 Sep 2025 19:24:31 -0400 Subject: [PATCH 2/8] Changed the code to a more modern approach to make things easier. --- engine/search.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/engine/search.go b/engine/search.go index 59eb7f1..2e0e6a3 100644 --- a/engine/search.go +++ b/engine/search.go @@ -12,17 +12,19 @@ const MaxQuiescenceDepth = 8 // return number in milliseconds func TimeLimit(pos *Position, command *UciGoMessage) time.Duration { var ourTime, ourInc int32 //, theirTime, theirInc int32 - if pos.Turn == White { + switch pos.Turn { + case White: ourTime = command.WTime ourInc = command.WInc // theirTime = command.BTime // theirInc = command.BInc - } else if pos.Turn == Black { + case Black: ourTime = command.BTime ourInc = command.BInc // theirTime = command.WTime // theirInc = command.WInc } + estimatedMovesLeft := max(10, 100-pos.FullMoves()) // multiplying time.Miillisecond twice? return min(MaxMovetime, time.Duration(ourTime/int32(estimatedMovesLeft)+ourInc/4)) From aebcda81b26149c94f682ba5b4afdadccd4f6cf8 Mon Sep 17 00:00:00 2001 From: earthtraveller1 Date: Mon, 22 Sep 2025 12:25:29 -0400 Subject: [PATCH 3/8] Wrote a basic king safety score checker that just sees if a king is in check. --- engine/evaluation.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/engine/evaluation.go b/engine/evaluation.go index 18d3ace..a940898 100644 --- a/engine/evaluation.go +++ b/engine/evaluation.go @@ -152,6 +152,19 @@ func (pos *Position) EndgameMaterial(color uint8) int32 { return ans } +func (pos *Position) KingSafety(color uint8) int32 { + safetyScore := int32(1000) + + // Obviously, if the King is in check, it is not going to be safe. + checkers := pos.Checkers(color) + checkerCount := int32(bits.OnesCount64(uint64(checkers))) + safetyScore -= checkerCount * 100 + + // Pieces being close to the King might be a bit of an issue. + + return safetyScore +} + func Evaluate(pos *Position) int32 { us := pos.Turn them := pos.Turn ^ 1 From 27547d7e7d14b4ab658ecef4e398ebb7d1e2a24e Mon Sep 17 00:00:00 2001 From: earthtraveller1 Date: Mon, 22 Sep 2025 12:32:41 -0400 Subject: [PATCH 4/8] Changed the code to make it more self-documenting. --- engine/position.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/engine/position.go b/engine/position.go index bb66a65..1bc0281 100644 --- a/engine/position.go +++ b/engine/position.go @@ -109,8 +109,7 @@ func (pos *Position) Equals(otherPos Position) bool { pos.EnPassantSquare == otherPos.EnPassantSquare } -// (color, piece) -func (pos *Position) GetSquare(sq Square) (uint8, uint8) { +func (pos *Position) GetSquare(sq Square) (color uint8, piece uint8) { p := pos.Board[sq] if p == NoPiece { return NoColor, NoPiece From 0d1ff0f6947d7f4b11ec562ea7001c78dc88ed37 Mon Sep 17 00:00:00 2001 From: earthtraveller1 Date: Mon, 22 Sep 2025 12:43:12 -0400 Subject: [PATCH 5/8] Added a small utility function to obtain the King's square. --- engine/position.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/engine/position.go b/engine/position.go index 1bc0281..49d6c7a 100644 --- a/engine/position.go +++ b/engine/position.go @@ -85,6 +85,10 @@ func (pos *Position) PutPiecesBB(pieces [2][6]Bitboard) { } } +func (pos *Position) GetKingSquare(color uint8) Square { + return Lsb(pos.Pieces[color][King]) +} + func (pos *Position) RemovePiece(sq Square) { piece := pos.Board[sq] color := ColorOf(piece) From cf07e760f90a1c7a5144f9b152231adc4fef9b25 Mon Sep 17 00:00:00 2001 From: earthtraveller1 Date: Mon, 22 Sep 2025 13:11:35 -0400 Subject: [PATCH 6/8] Took the distance into account when calculating King safety. --- engine/evaluation.go | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/engine/evaluation.go b/engine/evaluation.go index a940898..8b8fc46 100644 --- a/engine/evaluation.go +++ b/engine/evaluation.go @@ -1,6 +1,9 @@ package engine -import "math/bits" +import ( + "math" + "math/bits" +) const Infinity int32 = 1000000 @@ -160,8 +163,41 @@ func (pos *Position) KingSafety(color uint8) int32 { checkerCount := int32(bits.OnesCount64(uint64(checkers))) safetyScore -= checkerCount * 100 - // Pieces being close to the King might be a bit of an issue. - + kingSquare := pos.GetKingSquare(color) + kingRank := RankOf(kingSquare) + kingFile := FileOf(kingSquare) + + // Enemy pieces being close to the King might be a bit of an issue. + // TODO: Have a more optimal way of doing this later. Probably by using the bitboards and stuff + for square := range NoSquare { + colorOfPiece, piece := pos.GetSquare(square) + + pieceRank := RankOf(square) + pieceFile := FileOf(square) + + rankDiff := Abs(int(pieceRank - kingRank)) + fileDiff := Abs(int(pieceFile - kingFile)) + + distance := math.Sqrt(float64(rankDiff*rankDiff + fileDiff*fileDiff)) + distanceWeight := 10.0 - distance // the closer it is the higher the weight + + if colorOfPiece != color { + switch piece { + case Queen: + safetyScore -= int32(20 * distanceWeight) + case Rook: + safetyScore -= int32(10 * distanceWeight) + case Bishop: + safetyScore -= int32(5 * distanceWeight) + case Knight: + safetyScore -= int32(5 * distanceWeight) + case Pawn: + // Not as small as a pawn storm could be dangerous, + safetyScore -= int32(3 * distanceWeight) + } + } + } + return safetyScore } From 8c0f463cc11db35bdcf01aee6642e5aea1a048fe Mon Sep 17 00:00:00 2001 From: earthtraveller1 Date: Mon, 22 Sep 2025 13:21:45 -0400 Subject: [PATCH 7/8] Took King safety into account in the evaluation. --- engine/evaluation.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/engine/evaluation.go b/engine/evaluation.go index 8b8fc46..a26614d 100644 --- a/engine/evaluation.go +++ b/engine/evaluation.go @@ -210,9 +210,12 @@ func Evaluate(pos *Position) int32 { ourEGMaterial := pos.EndgameMaterial(us) theirEGMaterial := pos.EndgameMaterial(them) + ourKingSafety := pos.KingSafety(us) + theirKingSafety := pos.KingSafety(them) + isEndgame := (ourEGMaterial + theirEGMaterial) <= 1400 - eval := ourMaterial - theirMaterial + eval := ourMaterial + ourKingSafety - theirMaterial - theirKingSafety for piece := Pawn; piece <= King; piece++ { bb := pos.Pieces[us][piece] From a243c559caffe3892579d34f7dff5425865f0d2b Mon Sep 17 00:00:00 2001 From: earthtraveller1 Date: Mon, 22 Sep 2025 13:46:04 -0400 Subject: [PATCH 8/8] Removed the stupid label. --- cmd/silverfish/main.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/silverfish/main.go b/cmd/silverfish/main.go index 378e669..44910ae 100644 --- a/cmd/silverfish/main.go +++ b/cmd/silverfish/main.go @@ -89,7 +89,6 @@ func main() { go HandleMessages(messageChannel) -mainloop: for { message := engine.UciClientMessage{} select { @@ -110,7 +109,7 @@ mainloop: case engine.UciPositionClientMessage: position = *message.Position case engine.UciQuitClientMessage: - break mainloop + return case engine.UciGoClientMessage: go executeGoCommand(actionAlertChannel, &position, message.GoMessage) }