Jump to content

Module:Chessboard: Difference between revisions

From Wikipedia, the free encyclopedia
No edit summary
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
(No difference)

Revision as of 15:52, 10 May 2013

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('[[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-fen" style="position:relative;">
[[File:Chessboard480.png|%dx%dpx|link=]]
	]=], 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, '</div>')
    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,
}