Method to interpret the third field of a FEN string in a program playing FRC
Posted: Thu May 16, 2019 9:47 pm
Hello!
I tried to solve the following problem. For a program playing Fischer random chess, how to read the third field of a FEN string, without knowing what the notation style will be ("KQkq" or "HAha").
Here is my solution. I would be glad to know what you think about the method I found. I feel that it is too complicated, but I didn't find something simpler.
The function returns for each color and each side the position of the king and of the rook, or nil value if the castling isn't available.
If you want to try the Lua script, you need the module chess.lua from the Luciole projet.
Thank you.
I tried to solve the following problem. For a program playing Fischer random chess, how to read the third field of a FEN string, without knowing what the notation style will be ("KQkq" or "HAha").
Here is my solution. I would be glad to know what you think about the method I found. I feel that it is too complicated, but I didn't find something simpler.
The function returns for each color and each side the position of the king and of the rook, or nil value if the castling isn't available.
Code: Select all
-- Lua function for an engine playing Fischer random chess.
-- Extracts castling data from a FEN string, accepting both notation style.
function EncodeCastling(
AFen3,
ABoard -- The chessboard is needed as second parameter
)
function GetRookFile(
AColor, -- Piece color
APattern, -- Regular expression for character detection
AFrom, -- Where to start searching for the rook
ATo, -- Where to stop
AStep, -- In which direction to search
AKey -- K, Q, k, q
)
local LResult = 0
for LMatch in string.gmatch(AFen3, APattern) do
local LRook = AColor and 'r' or 'R'
local LFile = AColor and 'a' or 'A'
local LRank = AColor and 8 or 1
for x = AFrom, ATo, AStep do
if LResult == 0 then
if (ABoard[x][LRank] == LRook) and (
(LMatch == string.char(string.byte(LFile) + x - 1)) -- B-H, A-G, b-h, a-g
or (LMatch == AKey) -- K, Q, k, q
) then
LResult = x
break
end
end
end
end
return LResult
end
local K, Q, k, q, X = nil, nil, nil, nil, nil
local IsWhiteCastlingAvailable = string.match(AFen3, "[ABCDEFGHKQ]")
if IsWhiteCastlingAvailable then
for x = 1, 8 do
if ABoard[x][1] == 'K' then
X = x
break
end
end
end
local IsBlackCastlingAvailable = string.match(AFen3, "[abcdefghkq]")
if IsBlackCastlingAvailable and (X == nil) then
for x = 1, 8 do
if ABoard[x][8] == 'k' then
X = x
break
end
end
end
if IsWhiteCastlingAvailable then
K = GetRookFile(false, "[BCDEFGHK]", 8, X, -1, "K")
Q = GetRookFile(false, "[ABCDEFGQ]", 1, X, 1, "Q")
end
if IsBlackCastlingAvailable then
k = GetRookFile(true, "[bcdefghk]", 8, X, -1, "k")
q = GetRookFile(true, "[abcdefgq]", 1, X, 1, "q")
end
return {K = K, Q = Q, k = k, q = q, X = X}
end
-- demo
require('chess')
function Test(AFen)
local LPos = EncodePosition(AFen)
local LCastling = EncodeCastling(LPos.castlingAvailability, LPos.piecePlacement)
print("white k. side", LCastling.K) -- Rook file or nil when no castling is available
print("white q. side", LCastling.Q) -- Idem
print("black k. side", LCastling.k) -- Idem
print("black q. side", LCastling.q) -- Idem
print("king", LCastling.X) -- King file or nil when no castling is available
end
local LSample = {
"rknbbqnr/pppppppp/8/8/8/8/PPPPPPPP/RKNBBQNR w HAha - 0 1",
"nrbkqbnr/pppppppp/8/8/8/8/PPPPPPPP/NRBKQBNR w KQkq - 0 1",
"qrbknbrn/pppppppp/8/8/8/8/PPPPPPPP/QRBKNBRN w GBgb - 0 1",
"nrbkqrnb/pppppppp/8/8/8/8/PPPPPPPP/NRBKQRNB w FBfb - 0 1",
"qnrbbknr/pppppppp/8/8/8/8/PPPPPPPP/QNRBBKNR w HChc - 0 1",
"rnb1k1nr/p1pp1ppp/4p3/1p6/1P6/P1N1PN2/2P2P1P/R1BQKB1q b Qkq - 1 10",
"rnb1k2r/pppp1pp1/4p2p/8/8/2bPPN2/P2B1PqP/R2QKR2 b Qkq - 1 13"
}
for i = 1, #LSample do
Test(LSample[i])
end
Code: Select all
white k. side 8
white q. side 1
black k. side 8
black q. side 1
king 2
white k. side 8
white q. side 2
black k. side 8
black q. side 2
king 4
white k. side 7
white q. side 2
black k. side 7
black q. side 2
king 4
white k. side 6
white q. side 2
black k. side 6
black q. side 2
king 4
white k. side 8
white q. side 3
black k. side 8
black q. side 3
king 6
white k. side 0
white q. side 1
black k. side 8
black q. side 1
king 5
white k. side 0
white q. side 1
black k. side 8
black q. side 1
king 5
Thank you.