Module:Chess from fen

function chessboard( fen, 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 = piece:match( '%u' ) and 'l' or 'd'       piece = piece:lower local alt = string.format("%s%s %s %s", filechar( file ), rowchar( row ), colornames[color], piecenames[piece] or piece) local img = string.format('', piece, color, size, size, alt, alt) table.insert( res, string.format(' %s ', 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(, size * 8, size * 8))

local row = 0 for srow in string.gmatch("/" .. fen, "/%w+") do       row = row + 1 oneRow(srow, row, result) end table.insert(result, ' ') return result 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( frame ) 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 args = frame:getParent.args 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 ( res.gsub('1+', function( s ) return #s end ) ) end

return { 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, }