Модуль:Произвольная шахматная доска

Из Википедии, бесплатной энциклопедии

Документация
local p = {}  function chessboard(args, size, rows, cols, offsetx, offsety, rev, trans, lightdark, altprefix, letters, numbers, header, footer, align, clear, noframe, numeration)     function colchar( col )         return (col <= 26) and ( "abcdefghijklmnopqrstuvwxyz" ):sub( col, col )          	or ( "abcdefghijklmnopqrstuvwxyz" ):sub( math.floor((col-1)/26), math.floor((col-1)/26) )          		.. ( "abcdefghijklmnopqrstuvwxyz" ):sub( col-math.floor((col-1)/26)*26, col-math.floor((col-1)/26)*26)     end     function image_square(pc, row, col, offsetx, offsety, size, t, flip, altprefix, numeration)         local colornames = { l = 'бел', d = 'чёрн'}         local piecenames = { -- при добавлении фигур необходимо определить их грамматический род, добавив в соответствующую строку (ниже по тегу #gender) 		p = 'пешка', 		r = 'ладья', 		n = 'конь', 		b = 'слон', 		q = 'ферзь', 		k = 'король', 		a = 'архиепископ', 		c = 'канцлер', 		z = 'чемпион', 		w = 'колдун', 		t = 'шут', 		h = 'перевёрнутая пешка', 		m = 'перевёрнутая ладья', 		s = 'перевёрнутый конь', 		f = 'перевёрнутый король', 		e = 'перевёрнутый слон', 		g = 'перевёрнутый ферзь', 		G = 'жираф', 		U = 'единорог', 		Z = 'зебра'             }         local symnames = {  		xx = 'чёрный крест', 		ox = 'белый крест', 		xo = 'чёрный круг', 		oo = 'белый круг', 		ul = 'стрелка вверх-влево', 		ua = 'стрелка вверх', 		ur = 'стрелка вверх-вправо', 		la = 'стрелка влево', 		ra = 'стрелка вправо', 		dl = 'стрелка вниз-влево', 		da = 'стрелка вниз', 		dr = 'стрелка вниз-вправо', 		lr = 'стрелка влево-вправо', 		ud = 'стрелка вверх-вниз', 		db = 'стрелки вверх-вправо и вниз-влево', 		dw = 'стрелки вверх-влево и вниз-вправо', 		x0 = 'ноль', 		x1 = 'один', 		x2 = 'два', 		x3 = 'три', 		x4 = 'четыре', 		x5 = 'пять', 		x6 = 'шесть', 		x7 = 'семь', 		x8 = 'восемь', 		x9 = 'девять', 		j0 = 'чёрная шашка', 		j1 = 'белая шашка', 		D0 = 'чёрная дамка', 		D1 = 'белая дамка', 		O0 = 'чёрный круг', 		O1 = 'белый круг', 		O2 = 'красный круг', 		O3 = 'зелёный круг', 		O4 = 'синий круг', 		O5 = 'бирюзовый круг', 		O6 = 'жёлтый круг', 		O7 = 'розовый круг', 		O8 = 'коричневый круг', 		O9 = 'фиолетовый круг',     	}     	if (pc=='x') then pc = 'j0' end     	if (pc=='o') then pc = 'j1' end     	if (pc=='X') then pc = 'D0' end     	if (pc=='O') then pc = 'D1' end         local color = mw.ustring.gsub( pc, '^.*(%w)(%w).*$', '%2' ) or ''         local piece = mw.ustring.gsub( pc, '^.*(%w)(%w).*$', '%1' ) or ''         local ld = t and 't' or ((((row + col + flip) % 2) == 0) and 'd' or 'l')         local alt = ''         if (numeration=='chess') then alt = alt .. colchar( col+offsetx ) .. row+offsety .. ' ' -- нумерация при наведении на клетку         elseif (numeration=='continuous') then alt = alt .. col+(rows-row)*cols .. ' '         elseif (numeration=='draughts') then     	if (ld=='d') then alt = alt ..  math.floor((col+(rows-row)*cols+1)/2) .. ' ' end 		elseif (numeration=='swapdraughts') then 		if (ld=='l') then alt = alt ..  math.floor((col+(rows-row)*cols+1)/2) .. ' ' end 		end         if ( colornames[color] and piecenames[piece] ) then -- Согласовываем род прилагательного, обозначающего цвет #gender         		alt = alt .. colornames[color]         		if (string.find('nbqkaczwtsfegGU',piece)) then alt = alt .. 'ый ' -- Коды фигур мужского рода     				elseif (string.find('prhmZ',piece)) then alt = alt .. 'ая ' -- Коды фигур женского рода     					else alt = alt ..'. ' end         		alt = alt .. piecenames[piece]   		else             alt = alt .. ( symnames[piece .. color] or piece .. ' ' .. color )         end                          return string.format( '[[File:Chess %s%s%s45.svg|%dx%dpx|alt=%s|%s]]', piece, color, ld, size, size, alt, alt)     end      function letters_row( rev, num_lt, num_rt, cols, rows, offsetx, numeration, rev, lightdark, bottomline)     	blisblack = 1     	if (lightdark==true) then blisblack = 1 - blisblack end     	if (((cols+rows)%2==1)and(rev==true)) then blisblack = 1 - blisblack end        	tlisblack = blisblack     	if (rows%2==0) then tlisblack = 1- blisblack end        local res = '<tr style="vertical-align:middle">' .. ( num_lt and '<td style="padding:0; vertical-align:inherit"></td>' or '' ) .. '<td style="padding:0; vertical-align:inherit; height:18px">'         for k = 1, cols do               	if (numeration=='chess') then res = res .. colchar(rev and (cols - k + 1+offsetx) or k+offsetx) 	-- шахматы     		elseif (numeration=='continuous') then 												   			-- сквозная     			if (rev) then res = res .. (cols-k+1)+(1-bottomline)*(rows-1)*cols     				else res = res .. k+bottomline*(cols*(rows-1)) end     		elseif (numeration=='draughts') then																--черные     			if not(rev) then     			if (bottomline==0)and(k % 2 == tlisblack) then res = res ..  math.floor((k+1)/2) 							-- верх 				elseif (bottomline==1)and(k % 2 == blisblack) then res = res ..  math.floor((cols*(rows-1)+k+1)/2) end		-- низ 				else 					if (bottomline==0)and(k % 2 == tlisblack) then res = res ..  math.floor((rows*cols-k)/2)+1			-- верх 				elseif (bottomline==1)and(k % 2 == blisblack) then res = res ..  math.floor((cols-k)/2)+1 end			-- низ 					end 				elseif (numeration=='swapdraughts') then															--белые 				if not(rev) then     			if (bottomline==0)and not(k % 2 == tlisblack) then res = res .. math.floor((k+1)/2)								--верх 				elseif (bottomline==1)and not (k % 2 == blisblack) then res = res ..  math.floor((cols*(rows-1)+k+1)/2) end		-- низ 				else 				if (bottomline==0)and not (k % 2 == tlisblack) then res = res ..  math.floor((rows*cols-k)/2)+1			-- верх 				elseif (bottomline==1)and not (k % 2 == blisblack) then res = res ..  math.floor((cols-k)/2)+1 end			-- низ 				end 			end              res = res ..'</td><td style="padding:0; vertical-align:inherit">'         end         res = res .. '</td>' .. ( num_lt and '<td style="padding:0; vertical-align:inherit"></td>' or '' ) .. '</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 = cols * size + 2     local flip = lightdark and 1 or 0     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, cols, rows, offsetx, numeration, rev, lightdark, 0) .. '\n' end -- 1 - флаг верхней строки для шашечной нумерации     for trow = 1,rows do         local row = rev and trow or (rows - trow + 1)         b = b .. '<tr style="vertical-align:middle">'       if ( numbers_lt ) then b = b .. '<td style="padding:0; vertical-align:inherit; width:18px">' -- левая колонка цифр         	if (numeration=='chess') then b = b .. row+offsety     		elseif (numeration=='continuous') then     			if not(rev) then b = b .. (trow-1)*cols+1     				else b = b .. (rows-trow+1)*cols end     		elseif (numeration=='draughts') then      			if (trow%2==tlisblack) then      				if not(rev) then b = b .. math.floor((trow-1)*cols/2+1) 					else 					b = b .. math.floor((cols*(rows-trow+1)+1)/2) 					end 				end 		elseif (numeration=='swapdraughts') then 			if not (trow%2==tlisblack) then      				if not(rev) then b = b .. math.floor((trow-1)*cols/2+1) 					else 					b = b .. math.floor((cols*(rows-trow+1)+1)/2) 					end 			end 			end         	b = b .. '</td>'         	end         for tcol = 1,cols do             local col = rev and (cols - tcol + 1) or tcol             local idx = cols*(rows - row) + col + 2             if (args[idx] == nil) then args[idx] = '  ' end             local img = image_square((args[idx]:match('%w%w') or args[idx]:match('%w')) or '', row, col, offsetx, offsety, size, trans, flip, altprefix, numeration)             local bg = (((trow + tcol + flip) % 2) == 0) and '#ffce9e' or '#d18b47'             b = b .. '<td style="padding:0; vertical-align:inherit; background-color: ' .. bg .. ';">' .. img .. '</td>'         end 			if ( numbers_rt ) then b = b .. '<td style="padding:0; vertical-align:inherit; width:18px">' -- правая колонка цифр         	if (numeration=='chess') then b = b .. row+offsety     		elseif (numeration=='continuous') then     			if not(rev) then b = b .. trow*cols 				else b = b .. (rows-trow)*cols +1 end     		elseif (numeration=='draughts') then      			if ((trow+cols+1)%2==tlisblack) then      				if not(rev) then b = b .. math.floor((trow*cols+1)/2) 					else 					b = b .. math.floor((cols*(rows-trow))/2)+1 					end 				end 				elseif (numeration=='swapdraughts') then 				if ((trow+cols)%2==tlisblack) then      				if not(rev) then b = b .. math.floor((trow*cols+1)/2) 					else 					b = b .. math.floor((cols*(rows-trow))/2)+1 					end 			end 			end         	b = b .. '</td>'         	end     end     if ( letters_bt ) then b = b .. letters_row(rev, numbers_lt, numbers_rt, cols, rows, offsetx, numeration, rev, lightdark,  1) .. '\n' end -- 2 - флаг нижней строки для шашечной нумерации     if footer:match('^%s*$')     then     else             caption = '<div class="thumbcaption">' .. footer .. '</div>\n'     end     b = '<table cellpadding=0 cellspacing=0 style="line-height: 0; background:white; font-size:88%; border:1px #b0b0b0 solid;'         .. 'padding:0; margin:auto">\n' .. b .. '\n</table>'      if noframe then         return b     else          return '<div class="thumb ' .. align .. '" style="clear:' .. clear .. '; text-align:center; width:' .. width + 8 .. 'px">'          .. header .. '\n<div class="thumbinner" style="width:' .. width .. 'px;">\n'           .. b .. '\n' .. caption .. '</div></div>'      end      end  function convertFenToArgs( fen )     -- converts FEN notation to an 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 p.board(frame) 	local args = frame.args     local pargs = frame:getParent().args     local offsetx = args.offsetx or pargs.offsetx or 0 -- смещение начала координат доски по оси Х вправо (цифры)     local offsety = args.offsety or pargs.offsety or 0 -- смещение начала координат доски по оси Y вверх (буквы)     local size = (args.size or pargs.size) or '26'     local reverse = (args.reverse or pargs.reverse or '' ):lower() == "true"     local trans = (args.transparent or pargs.transparent or '' ):lower() == "true"     local lightdark = (args.lightdark or pargs.lightdark or '' ):lower() == "swap"     if (offsetx+offsety %2 ==1) then lightdark = not lightdark end -- инвертирование цветов клеток доски при смещении     local altprefix = args.altprefix or pargs.altprefix or ''     local rows = pargs.rows or args.rows or 8     local cols = pargs.cols or args.cols or 8     local letters = ( pargs.letters or args.letters or 'both' ):lower()      local numbers = ( pargs.numbers or args.numbers or 'both' ):lower()      local header =  mw.ustring.gsub( args[2] or pargs[2] or '', '^%s*(.-)%s*$', '%1' )     local numeration = (args.numeration or pargs.numeration or 'chess'):lower()     if not (numeration:match('draughts') or numeration:match('swapdraughts') or numeration:match('continuous')) then numeration = 'chess' end     -- тип нумерации клеток доски: chess - шахматный, draughts - шашечный со второй клетки,     -- swapdraughts - шашечный с первой клетки, continuous - шашечный сквозной     local footer = args[3 + rows*cols] or pargs[3 + rows*cols] 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 noframe = (args.noframe or pargs.noframe or ''):lower() == "true"     local fen = args.fen or pargs.fen     size = mw.ustring.match(size, '[%d]+') or '26' -- remove px from size     if (fen) then         footer = args[3] or pargs[3] or ''         return chessboard(convertFenToArgs( fen ), size, rows, cols, offsetx, offsety, reverse, trans, lightdark, altprefix, letters, numbers, header, footer, align, clear, noframe, numeration)     end     if args[3] then         return chessboard(args, size, rows, cols, offsetx, offsety, reverse, trans, lightdark, altprefix, letters, numbers, header, footer, align, clear, noframe, numeration)     else         return chessboard(pargs, size, rows, cols, offsetx, offsety, reverse, trans, lightdark, altprefix, letters, numbers, header, footer, align, clear, noframe, numeration)     end      end  return p