local p = {}
function chessboard( position, size, reverse )
local piecenames = { p = 'Pawn', r = 'Rook', n = 'Knight', b = 'Bishop', q = 'Queen', k = 'King' }
local colornames = { l = 'White', d = 'Black' }
function rowchar( row ) return 9 - row end
function filechar( file ) return ( "abcdefgh" ):sub( file, file ) end
function coord( ind ) return ( reverse and ( 8 - ind ) * size ) or ( ind - 1 ) * size end
function piecediv( piece, row, file, res )
local color = mw.ustring.gsub(piece,'^.*(%w)(%w).*$', '%2')
piece = mw.ustring.gsub(piece,'^.*(%w)(%w).*$', '%1')
-- local alt = string.format("%s%s %s %s", filechar( file ), rowchar( row ), colornames[color], piecenames[piece] or piece)
-- local img = string.format('[[File:Chess %s%st45.svg|%dx%dpx|alt=%s|%s]]', piece, color, size, size, alt, alt)
-- table.insert( res, string.format('<div style="position:absolute;z-index:3;top:%dpx;left:%dpx;">%s</div>', coord( row ), coord( file ), img) )
table.insert(res, '<div>' .. piece .. ' ' .. color .. '</div>')
end
local result = {}
table.insert(result, string.format([=[
<div class="chess-fen" style="position:relative;">
[[File:Chessboard480.png|%dx%dpx|link=]]
]=], size * 8, size * 8))
for row = 1,8 do
for file = 1,8 do
local piece = position[8*(row-1) + file]
if piece
then
if (piece:match("%a%a"))
then
piecediv( piece, row, file, result )
end
end
end
end
table.insert(result, '</div>')
return result
end
function convertArgsToPosition( args )
local res = args
-- Remove the first two args
table.remove(res,1)
table.remove(res,1)
return res
end
function convertFenToPosition( fen )
local res = {}
-- Loop over rows, which are delimited by /
for srow in string.gmatch("/" .. fen, "/%w+") do
-- Loop over all letters and numbers in the row
for piece in srow:gmatch( "%w" ) do
if (piece:match("%d"))
then -- if a digit
for k=1,piece do
table.insert(res,' ')
end
else -- not a digit
local color = piece:match( '%u' ) and 'l' or 'd'
piece = piece:lower()
table.insert(res, piece .. color )
end
end
end
return res
end
--[[
this function is to be used only from Template:Chess diagram.
it provides part of the FEN string - the part that describes the board itself.
unfortunately, the template does not carry enough information to create the 2nd
part of the FEN, which includes information about whose turn is it, en-passant state,
castling, etc.
]]
function diagramToFen( args )
function nullOrWhitespace( s ) return not s or s:match( '^%s*(.-)%s*$' ) == '' end
function piece( s )
return nullOrWhitespace( s ) and 1
or s:gsub( '%s*(%a)(%a)%s*', function( a, b ) return b == 'l' and a:upper() or a end )
end
local res = ''
for row = 0, 7 do
for file = 0, 7 do
res = res .. piece( args[3 + row * 8 + file] )
end
if row < 7 then res = res .. '/' end
end
return mw.ustring.gsub(res, '1+', function( s ) return #s end )
end
function p.board(frame)
local args = frame.args
local pargs = frame:getParent().args
local size = (args.size or pargs.size) or '26px'
local reverse = ( (args.reverse or pargs.reverse) or '' ):lower() == "true"
local fen = args.fen or pargs.fen
local position = {}
size = mw.ustring.gsub(size, '^[^%d]*(%d[%d]*)[^%d]*$', '%1') -- remove px from size
if (fen)
then position = convertFenToPosition( fen )
else position = convertArgsToPosition( pargs )
end
-- return table.concat( position, '|')
return table.concat( chessboard(position, size, reverse), "\n")
end
function p.fen2ascii(frame)
local b = convertFenToPosition( frame.args.fen )
local res = ''
for row = 0,7 do
res = res .. '|' .. table.concat(b, '|', 8*row + 1, 8*row + 8) .. '|=\n'
end
res = mw.ustring.gsub(res,'\| \|', '| |')
res = mw.ustring.gsub(res,'\| \|', '| |')
return res
end
return p