Add legal chess captures exercise
This commit is contained in:
parent
ec9d9b2a38
commit
5f57627225
340
20_legal_captures.lua
Normal file
340
20_legal_captures.lua
Normal file
@ -0,0 +1,340 @@
|
||||
-- Write a function which takes a description of a chess position and
|
||||
-- returns a list of all legal captures from that position.
|
||||
--
|
||||
-- The position will be given as a table, containing the keys "turn",
|
||||
-- indicating which player it is to move, "board", which will contain
|
||||
-- a rank-major grid of pieces (that is, a list of ranks/rows). Each
|
||||
-- piece will be indicated by its unicode symbol. The lack of a piece
|
||||
-- will be indicated by nil. If the previous move was a pawn moving
|
||||
-- two places, the key "en_passant_target" will be set to a table with
|
||||
-- "rank" and "file" keys set to the (1-based) rank and file indices
|
||||
-- of the square passed over by the pawn.
|
||||
--
|
||||
-- For example, the starting position would be given as:
|
||||
--
|
||||
-- {
|
||||
-- turn = "white",
|
||||
-- board = {
|
||||
-- {"♖", "♘", "♗", "♕", "♔", "♗", "♘", "♖"},
|
||||
-- {"♙", "♙", "♙", "♙", "♙", "♙", "♙", "♙"},
|
||||
-- {nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
-- {nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
-- {nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
-- {nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
-- {"♟︎", "♟︎", "♟︎", "♟︎", "♟︎", "♟︎", "♟︎", "♟︎"},
|
||||
-- {"♜", "♞", "♝", "♛", "♚", "♝", "♞", "♜"},
|
||||
-- },
|
||||
-- }
|
||||
--
|
||||
-- Moves should be returned in figurine algebraic notation, without
|
||||
-- indicators for en passant, check or checkmate (i.e. no "e.p.", "+"
|
||||
-- or "#"). For example, "♞xc6" for a black night capturing on c6 and
|
||||
-- "exd7" for an e-file pawn capturing on d7. For the sake of
|
||||
-- simplicity, there's no requirement to disambiguate between two
|
||||
-- pieces of the same type when the notation for the capture would
|
||||
-- otherwise be the same (e.g. if two rooks can capture on the same
|
||||
-- square). However, there should be duplicate entries in the results
|
||||
-- list for each.
|
||||
--
|
||||
-- Solution --------------------------------------------------------------------
|
||||
function legal_captures(position)
|
||||
-- Your implementation here
|
||||
end
|
||||
|
||||
-- Tests -----------------------------------------------------------------------
|
||||
|
||||
local luaunit = require("luaunit.luaunit")
|
||||
|
||||
function test_starting_position()
|
||||
local position = {
|
||||
turn = "white",
|
||||
board = {
|
||||
{"♖", "♘", "♗", "♕", "♔", "♗", "♘", "♖"},
|
||||
{"♙", "♙", "♙", "♙", "♙", "♙", "♙", "♙"},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{"♟︎", "♟︎", "♟︎", "♟︎", "♟︎", "♟︎", "♟︎", "♟︎"},
|
||||
{"♜", "♞", "♝", "♛", "♚", "♝", "♞", "♜"},
|
||||
},
|
||||
}
|
||||
local expected = {}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_queens_gambit()
|
||||
local position = {
|
||||
turn = "black",
|
||||
board = {
|
||||
{"♖", "♘", "♗", "♕", "♔", "♗", "♘", "♖"},
|
||||
{"♙", "♙", nil, nil, "♙", "♙", "♙", "♙"},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, "♙", "♙", nil, nil, nil, nil},
|
||||
{nil, nil, nil, "♟︎", nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{"♟︎", "♟︎", "♟︎", nil, "♟︎", "♟︎", "♟︎", "♟︎"},
|
||||
{"♜", "♞", "♝", "♛", "♚", "♝", "♞", "♜"},
|
||||
},
|
||||
}
|
||||
local expected = {"dxc4"}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_scandinavian_defense()
|
||||
local position = {
|
||||
turn = "white",
|
||||
board = {
|
||||
{"♖", "♘", "♗", "♕", "♔", "♗", "♘", "♖"},
|
||||
{"♙", "♙", "♙", "♙", nil, "♙", "♙", "♙"},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, "♙", nil, nil, nil},
|
||||
{nil, nil, nil, "♟︎", nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{"♟︎", "♟︎", "♟︎", nil, "♟︎", "♟︎", "♟︎", "♟︎"},
|
||||
{"♜", "♞", "♝", "♛", "♚", "♝", "♞", "♜"},
|
||||
},
|
||||
}
|
||||
local expected = {"exd5"}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_knight_captures()
|
||||
local position = {
|
||||
turn = "black",
|
||||
board = {
|
||||
{"♙", "♙", "♙", "♙", "♙", "♙", "♙", "♙"},
|
||||
{"♙", "♙", "♙", nil, "♙", "♙", "♙", "♙"},
|
||||
{"♙", "♙", nil, nil, nil, "♙", "♙", "♙"},
|
||||
{"♙", nil, nil, "♞", nil, nil, "♙", "♙"},
|
||||
{"♙", "♙", nil, nil, nil, "♙", "♙", "♙"},
|
||||
{"♙", "♙", "♙", nil, "♙", "♙", "♙", "♙"},
|
||||
{"♙", "♙", "♙", "♙", "♙", "♙", "♙", "♙"},
|
||||
{"♙", "♙", "♙", "♙", "♙", "♙", "♙", "♙"},
|
||||
},
|
||||
}
|
||||
local expected = {
|
||||
"♞xb3", "♞xb5", "♞xc2", "♞xc6", "♞xe2", "♞xe6", "♞xf3", "♞xf5",
|
||||
}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_knight_not_blocked()
|
||||
local position = {
|
||||
turn = "white",
|
||||
board = {
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, "♟︎", "♟︎", "♟︎", nil, nil},
|
||||
{nil, nil, nil, nil, "♟︎", nil, nil, nil},
|
||||
{nil, nil, "♟︎", "♟︎", "♘", nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
},
|
||||
}
|
||||
local expected = {"♘xd3", "♘xf3"}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_bishop_captures()
|
||||
local position = {
|
||||
turn = "black",
|
||||
board = {
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{"♙", nil, nil, nil, nil, nil, "♙", nil},
|
||||
{nil, nil, nil, "♙", nil, nil, "♙", nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, "♙", "♝", nil, nil, nil, "♙"},
|
||||
{nil, nil, nil, nil, "♙", nil, nil, nil},
|
||||
{nil, "♙", nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, "♙", nil, nil, nil, nil},
|
||||
},
|
||||
}
|
||||
local expected = {"♝xa2", "♝xb7", "♝xe6", "♝xg2"}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_bishop_blocked()
|
||||
local position = {
|
||||
turn = "black",
|
||||
board = {
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, "♙", nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, "♞", nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, "♝", nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
},
|
||||
}
|
||||
local expected = {}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_rook_captures()
|
||||
local position = {
|
||||
turn = "white",
|
||||
board = {
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{"♟︎", nil, nil, nil, nil, nil, "♟︎", nil},
|
||||
{nil, nil, nil, "♟︎", nil, nil, "♟︎", nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, "♟︎", "♖", nil, nil, nil, "♟︎"},
|
||||
{nil, nil, nil, nil, "♟︎", nil, nil, nil},
|
||||
{nil, "♟︎", nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, "♟︎", nil, nil, nil, nil},
|
||||
},
|
||||
}
|
||||
local expected = {"♖xc5", "♖xd3", "♖xd8", "♖xh5"}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_rook_blocked()
|
||||
local position = {
|
||||
turn = "white",
|
||||
board = {
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, "♖", "♙", nil, nil, nil, "♟︎", nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
},
|
||||
}
|
||||
local expected = {}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_queen_captures()
|
||||
local position = {
|
||||
turn = "black",
|
||||
board = {
|
||||
{nil, "♙", "♙", "♙", "♙", "♙", nil, "♙"},
|
||||
{"♙", "♙", "♙", nil, "♙", "♙", "♙", "♙"},
|
||||
{"♙", "♙", nil, nil, nil, "♙", "♙", "♙"},
|
||||
{"♙", nil, nil, "♛", nil, nil, "♙", nil},
|
||||
{"♙", "♙", nil, nil, nil, "♙", "♙", "♙"},
|
||||
{"♙", "♙", "♙", nil, "♙", "♙", "♙", "♙"},
|
||||
{nil, "♙", "♙", "♙", "♙", "♙", nil, "♙"},
|
||||
{"♙", "♙", "♙", nil, "♙", "♙", "♙", nil},
|
||||
},
|
||||
}
|
||||
local expected = {
|
||||
"♛xa4", "♛xb2", "♛xb6", "♛xd1", "♛xd7", "♛xf2", "♛xf6", "♛xg4",
|
||||
}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_queen_blocked()
|
||||
local position = {
|
||||
turn = "white",
|
||||
board = {
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, "♟︎", nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, "♙", nil, nil, nil, nil, nil},
|
||||
{nil, "♕", "♙", nil, nil, nil, "♟︎", nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
},
|
||||
}
|
||||
local expected = {}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_king_captures()
|
||||
local position = {
|
||||
turn = "black",
|
||||
board = {
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, "♙", "♙", "♙", nil, nil, nil},
|
||||
{nil, nil, "♙", "♚", "♙", nil, nil, nil},
|
||||
{nil, nil, "♙", "♙", "♙", nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
},
|
||||
}
|
||||
local expected = {"♚xc3","♚xc4","♚xc5","♚xd3","♚xd5","♚xe3","♚xe4","♚xe5",}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_en_passant()
|
||||
local position = {
|
||||
turn = "white",
|
||||
board = {
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, "♟︎", "♙", nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
},
|
||||
en_passant_target = {rank = 6, file = 4},
|
||||
}
|
||||
local expected = {"exd6"}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_cannot_capture_if_leads_to_check()
|
||||
local position = {
|
||||
turn = "white",
|
||||
board = {
|
||||
{nil, nil, nil, nil, "♔", nil, nil, nil},
|
||||
{nil, nil, nil, nil, "♗", nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, "♟︎", nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, "♜", nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
},
|
||||
en_passant_target = {rank = 6, file = 4},
|
||||
}
|
||||
local expected = {}
|
||||
luaunit.assertItemsEquals(legal_captures(position), expected)
|
||||
end
|
||||
|
||||
function test_position_with_lots_of_captures()
|
||||
local position = {
|
||||
turn = "white",
|
||||
board = {
|
||||
{"♚", nil, nil, "♔", "♝", nil, nil, "♖"},
|
||||
{nil, "♖", "♜", "♕", "♞", "♕", "♘", nil},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{"♗", "♛", "♕", "♝", "♕", "♛", "♕", "♞"},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, "♕", "♝", "♕", "♛", "♕", "♘", "♗"},
|
||||
{nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
{nil, nil, nil, "♜", "♕", "♛", nil, nil},
|
||||
},
|
||||
en_passant_target = {rank = 6, file = 4},
|
||||
}
|
||||
local expected = {
|
||||
"♔xe1", "♔xe2", "♔xc2", "♖xh4", "♖xe1",
|
||||
"♖xb4", "♖xc2", "♕xf4", "♕xb4", "♕xe1",
|
||||
"♕xd4", "♕xe2", "♕xc2", "♕xh4", "♕xd4",
|
||||
"♕xe1", "♕xf4", "♕xe2", "♘xh4", "♘xf4",
|
||||
"♘xe1", "♗xc6", "♗xc2", "♕xe6", "♕xe2",
|
||||
"♕xc6", "♕xc2", "♕xd4", "♕xb4", "♕xc6",
|
||||
"♕xc2", "♕xe6", "♕xe2", "♕xf4", "♕xd4",
|
||||
"♕xe6", "♕xe2", "♕xh4", "♕xf4", "♕xd8",
|
||||
"♕xd4", "♕xb4", "♕xc6", "♕xf8", "♕xf4",
|
||||
"♕xb4", "♕xd8", "♕xd4", "♕xe6", "♕xc6",
|
||||
"♕xd8", "♕xh4", "♕xd4", "♕xf8", "♕xf4",
|
||||
"♕xe6", "♘xf8", "♘xh4", "♘xf4", "♗xf8",
|
||||
"♗xf4", "♕xc6", "♕xe6", "♕xf8", "♕xd8",
|
||||
}
|
||||
local captures = legal_captures(position)
|
||||
luaunit.assertItemsEquals(captures, expected)
|
||||
end
|
||||
|
||||
os.exit(luaunit.LuaUnit.run())
|
Loading…
x
Reference in New Issue
Block a user