Modul:Schachbrett

Dies ist eine alte Version dieser Seite, zuletzt bearbeitet am 28. Mai 2013 um 19:02 Uhr durch Frietjes (Diskussion | Beiträge) (update to better match default image thumb format, see if this fixes some margin issues). Sie kann sich erheblich von der aktuellen Version unterscheiden.

Die Dokumentation für dieses Modul kann unter Modul:Schachbrett/Doku erstellt werden

local p = {}

function chessboard(args, size, rev, letters, numbers, header, footer, align, clear)
    function image_square( pc, row, col, size )
        local colornames = { l = 'white', d = 'black' }
        local piecenames = { 
            p = 'pawn', 
            r = 'rook', 
            n = 'knight', 
            b = 'bishop', 
            q = 'queen', 
            k = 'king', 
            a = 'archbishop',
            c = 'chancelor', 
            z = 'champion', 
            w = 'wizard', 
            t = 'fool', 
            h = 'upside-down pawn', 
            m = 'upside-down rook', 
            s = 'upside-down knight', 
            f = 'upside-down king',  
            e = 'upside-down bishop', 
            g = 'upside-down queen',
            }
        local symnames = { 
            xx = 'black cross', 
            ox = 'white cross', 
            xo = 'black circle', 
            oo = 'white circle',
            ul = 'up-left arrow', 
            ua = 'up arrow', 
            ur = 'up-right arrow', 
            la = 'left arrow', 
            ra = 'right arrow',
            dl = 'down-left arrow', 
            da = 'down arrow', 
            dr = 'down-right arrow', 
            lr = 'left-right arrow', 
            ud = 'up-down arrow',
            x0 = 'zero', 
            x1 = 'one', 
            x2 = 'two', 
            x3 = 'three', 
            x4 = 'four', 
            x5 = 'five', 
            x6 = 'six', 
            x7 = 'seven', 
            x8 = 'eight', 
            x9 = 'nine',
        }
        
        function colchar( col ) 
            return ( 'abcdefgh' ):sub( col, col ) 
        end
        
        local color = mw.ustring.gsub( pc, '^.*(%w)(%w).*$', '%2' ) or ''
        local piece = mw.ustring.gsub( pc, '^.*(%w)(%w).*$', '%1' ) or ''
        local alt = colchar( col ) .. row .. ' '
        if colornames[color] and piecenames[piece] then
            alt = alt .. colornames[color] .. ' ' .. piecenames[piece]
        else
            alt = alt .. ( symnames[piece .. color] or piece .. ' ' .. color )
        end
        
        return string.format( '[[File:Chess %s%st45.svg|%dx%dpx|alt=%s|%s]]', piece, color, size, size, alt, alt )
    end

    function letters_row( rev, num_lt, num_rt )
        local res  = '<tr style="vertical-align:middle">' .. ( num_lt and '<td></td>' or '' )
        if ( rev ) then
            res = res .. '<td style="height:18px">h</td><td>g</td><td>f</td><td>e</td><td>d</td><td>c</td><td>b</td><td>a</td>'
        else
            res = res .. '<td style="height:18px">a</td><td>b</td><td>c</td><td>d</td><td>e</td><td>f</td><td>g</td><td>h</td>'
        end
        if ( num_rt ) then
            res= res .. '<td></td>'
        end
        res = res .. '</tr>'
        return res
    end
    local letters_tp = letters:match( 'both' ) or letters:match( 'top' )
    local letters_bt = letters:match( 'both' ) or letters:match( 'bottom' )
    local numbers_lt = numbers:match( 'both' ) or numbers:match( 'left' )
    local numbers_rt = numbers:match( 'both' ) or numbers:match( 'right' )
    local width = 8 * size + 6
    if ( numbers_lt ) then width = width + 18 end
    if ( numbers_rt ) then width = width + 18 end

    local b = ''
    local caption = ''
    
    if ( letters_tp ) then b = b .. letters_row( rev, numbers_lt, numbers_rt ) .. '\n' end
    b = b .. '<tr style="vertical-align:middle">'
    if ( numbers_lt ) then b = b .. '<td style="width:18px;height:' .. size .. 'px">' .. (rev and 1 or 8) .. '</td>' end
    b = b .. '<td colspan=8 rowspan=8><div class="chess-board" style="position:relative;">'
    b = b .. string.format( '[[File:Chessboard480.png|%dx%dpx|link=]]', 8 * size, 8 * size )
    for trow = 1,8 do
        local row = rev and trow or ( 9 - trow )
        for tcol = 1,8 do
            local col = rev and ( 9 - tcol ) or tcol
            local piece = args[8 * ( 8 - row ) + col + 2] or ''
            if piece:match( '%w%w' ) then
               local img = image_square(piece:match('%w%w'), row, col, size )
               b = b .. string.format(
                   '<div style="position:absolute;z-index:3;top:%dpx;left:%dpx;">%s</div>\n', 
                   ( trow - 1 ) * size, ( tcol - 1 ) * size, img )
            end
        end
    end
    b = b .. '</div></td>'
    if ( numbers_rt ) then b = b .. '<td style="width:18px;height:' .. size ..'px">' .. (rev and 1 or 8) .. '</td>' end
    if ( numbers_lt or numbers_rt ) then
       for trow = 2, 8 do
          local row = rev and trow or ( 9 - trow )
          b = b .. '<tr style="vertical-align:middle">'
          if ( numbers_lt ) then b = b .. '<td style="height:' .. size .. 'px">' .. row .. '</td>' end
          if ( numbers_rt ) then b = b .. '<td style="height:' .. size .. 'px">' .. row .. '</td>' end
          b = b .. '</tr>\n'
       end
    end
    if ( letters_bt ) then b = b .. letters_row( rev, numbers_lt, numbers_rt ) .. '\n' end

    if footer:match( '^%s*$' )
    then
    else    
        caption = '<div class="thumbcaption">' .. footer .. '</div>\n'
    end
    
    return '<div class="thumb ' .. align .. '" style="clear:' .. clear .. ';">'
        .. header .. '\n<div class="thumbinner" style="width:' .. width .. 'px; text-align:center">\n' 
        .. '<table cellpadding=0 cellspacing=0 style="background:white; font-size:88%; border:1px #b0b0b0 solid; padding:0; '
        .. 'margin:auto;">\n' .. b .. '\n</table>\n' .. caption .. '</div></div>'
end

function convertFenToArgs( fen )
    -- converts FEN notation to 64 entry array of positions, offset by 2
    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

function convertArgsToFen( args, offset )
    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 = ''
    offset = offset or 0
    for row = 1, 8 do
        for file = 1, 8 do
            res = res .. piece( args[8*(row - 1) + file + offset] )
        end
        if row < 8 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 '26'
    local reverse = ( args.reverse or pargs.reverse or '' ):lower() == "true"
    local letters = ( args.letters or pargs.letters or 'both' ):lower() 
    local numbers = ( args.numbers or pargs.numbers or 'both' ):lower() 
    local header = args[2] or pargs[2] or ''
    local footer = args[67] or pargs[67] or ''
    local align = ( args[1] or pargs[1] or 'tright' ):lower()
    local clear = args.clear or pargs.clear or ( align:match('tright') and 'right' ) or 'none'
    local fen = args.fen or pargs.fen
        
    size = mw.ustring.match( size, '[%d]+' ) or '26' -- remove px from size
    if (fen) then
        align = args.align or pargs.align or 'tright'
        clear = args.clear or pargs.clear or ( align:match('tright') and 'right' ) or 'none'
        header = args.header or pargs.header or ''
        footer = args.footer or pargs.footer or ''
        return chessboard( convertFenToArgs( fen ), size, reverse, letters, numbers, header, footer, align, clear )
    end
    if args[3] then
        return chessboard(args, size, reverse, letters, numbers, header, footer, align, clear)
    else
        return chessboard(pargs, size, reverse, letters, numbers, header, footer, align, clear)
    end
end

function p.fen2ascii(frame)
    -- {{#invoke:Chessboard|fen2ascii|fen=...}}
    local b = convertFenToArgs( frame.args.fen )
    local res = '|=\n'
    local offset = 2
    for row = 1,8 do
        local n = (9 - row)
        res = res .. n .. ' |' .. 
            table.concat(b, '|', 8*(row-1) + 1 + offset, 8*(row-1) + 8 + offset) .. '|=\n'
    end
    res = mw.ustring.gsub( res,'\| \|', '|  |' )
    res = mw.ustring.gsub( res,'\| \|', '|  |' )
    res = res .. '   a  b  c  d  e  f  g  h'
    return res
end

function p.ascii2fen( frame )
    -- {{#invoke:Chessboard|ascii2fen|kl| | |....}}
    return convertArgsToFen( frame.args, frame.args.offset or 1 )
end

return p