Module:Chessboard: Difference between revisions

Content deleted Content added
m Frietjes moved page Module:Chess from fen to Module:Chessboard without leaving a redirect: expanding this to make it work for more than just FEN
revised version, tested in the sandbox, which can be used for both chess diagram and chess diagram-fen, and converts fen to ascii or ascii to fen
Line 1:
local p = {}
function chessboard( fen, size, reverse )
 
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:match,'^.*( '%u' w) and (%w).*$'l' or, 'd%2')
piece = mw.ustring.gsub(piece:lower,'^.*(%w)(%w).*$', '%1')
local alt = string.format("%s%s %s %s", filechar( file ), rowchar( row ), colornames[color] or 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) )
end
 
function oneRow( s, row, res )
local file = 1
for piece in s:gmatch( "%w" ) do -- if a digit, increment "file" by the digit. else, add the piece _and_ increment file by 1
file = file + ( piece:match("%d") or piecediv( piece, row, file, res ) or 1 )
end
end
 
local result = {}
table.insert(result, string.format([=[
<div class="chess-fenboard" style="position:relative;">
[[File:Chessboard480.png|%dx%dpx|link=]]
]=], size * 8, size * 8))
 
localfor row = 01,8 do
for srow in string.gmatch("/"for ..file fen,= "/%w+")1,8 do
row local piece = position[8*(row-1) + 1file]
oneRow(srow, row, result)if piece
then
if (piece:match("%a%w"))
then
piecediv( piece, row, file, result )
end
end
end
end
table.insert(result, '</div>')
Line 37 ⟶ 39:
end
 
function convertFenToPosition( fen )
--[[
-- converts FEN notation to 64 entry array of positions
this function is to be used only from Template:Chess diagram.
local res = {}
it provides part of the FEN string - the part that describes the board itself.
-- Loop over rows, which are delimited by /
unfortunately, the template does not carry enough information to create the 2nd
for srow in string.gmatch("/" .. fen, "/%w+") do
part of the FEN, which includes information about whose turn is it, en-passant state,
-- Loop over all letters and numbers in the row
castling, etc.
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
 
function convertArgsToPosition( args, offset )
-- copies args to 64 entry array of positions
local res = {}
-- Loop over rows, which are delimited by /
for row = 1,8 do
for file = 1,8 do
table.insert(res, args[8*(row-1) + file + offset])
end
end
return res
end
 
function diagramToFenconvertPositionToFen( frameargs, offset )
-- converts a position array to Fen
function nullOrWhitespace( s ) return not s or s:match( '^%s*(.-)%s*$' ) == '' end
function piece( s )
Line 52 ⟶ 82:
end
local args = frame:getParent().args
local res = ''
for rowoffset = 0,offset 7or do0
for filerow = 01, 78 do
for resfile = res .. piece( args[3 + row *1, 8 + file] )do
res = res .. piece( args[8*(row - 1) + file + offset] )
end
if row < 78 then res = res .. '/' end
end
return ( resmw.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 offset = 0
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, 2)
end
 
return table.concat( chessboard(position, size, reverse), "\n")
end
 
function p.fen2ascii(frame)
-- {{#invoke:Chessboard|fen2ascii|fen=...}}
local b = convertFenToPosition( frame.args.fen )
local res = ''
for row = 1,8 do
res = res .. '|' .. table.concat(b, '|', 8*(row-1) + 1, 8*(row-1) + 8) .. '|=\n'
end
res = mw.ustring.gsub(res,'\| \|', '| |')
res = mw.ustring.gsub(res,'\| \|', '| |')
return res
end
 
function p.ascii2fen(frame)
-- {{#invoke:Chessboard|ascii2fen|kl|....}}
return diagramToFen( frame.args, frame.args.offset or 1 )
end
 
return {p
f = function( frame )
local args = frame.args
local t = chessboard( args.fen, args.size or 30, ( args.reverse or '' ):lower() == "true" )
return table.concat( t, "\n" )
end,
['extract fen'] = diagramToFen,
}