-- 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())