Skip to content

Instantly share code, notes, and snippets.

@ddugovic
Created March 19, 2021 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ddugovic/45fdacacedd7c3c13b9c5f88ca5addc7 to your computer and use it in GitHub Desktop.
Save ddugovic/45fdacacedd7c3c13b9c5f88ca5addc7 to your computer and use it in GitHub Desktop.
Encodes pawns as a bitwise-AND-comparable index (from a SFEN)
# Encodes pawns as a bitwise-AND-comparable index (from a SFEN)
# Usage: ruby pawn_encoder.rb "lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL"
def encode(fen)
board = fen.gsub("9"," 8").gsub("8"," 7").gsub("7"," 6").gsub("6"," 5").gsub("5"," 4").gsub("4"," 3").gsub("3"," 2").gsub("2"," 1").gsub("1"," ")
# replace 'P' with '1' and replace 'p' with '1'
bpawnsA = board.gsub(/[^P\/]/,"0").gsub(/P/,"1").split("/")
wpawnsA = board.gsub(/[^p\/]/,"0").gsub(/p/,"1").split("/")
# shift black pawns upwards a rank (rotate left) etc.
bpawnsB = bpawnsA.rotate(-1)
wpawnsB = wpawnsA.rotate
# replace '1' with 1
bpawns1 = bpawnsA.join.split(//).map {|c| c.ord - '0'.ord}
wpawns1 = wpawnsA.join.split(//).map {|c| c.ord - '0'.ord}
bpawns2 = bpawnsB.join.split(//).map {|c| c.ord - '0'.ord}
wpawns2 = wpawnsB.join.split(//).map {|c| c.ord - '0'.ord}
# average the shifted and unshifted pawn masks
bpawns = bpawns1.zip(bpawns2).map {|i, j| (i+j+1)/2}
wpawns = wpawns1.zip(wpawns2).map {|i, j| (i+j+1)/2}
# concatenate computed value into a single index
# which has the property that bitwise-AND computes similarity
# instead of relying upon an "ECO" code/transposition table
[bpawns.map {|i| i.to_s}.join.slice(36, 36), wpawns.map {|i| i.to_s}.join.slice(9, 36)].join
end
puts encode(ARGV[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment