Modulo:mchessboard
Aspekto
MODULO | ||
Memtesto disponeblas sur la paĝo Ŝablono:ŝakdiagramo. |
- uzata far
{{ŝakdiagramo}}
--[===[
MODULE "MCHESS" (chessboard)
"eo.wiktionary.org/wiki/Modulo:mchessboard" <!--2022-Oct-18-->
"sv.wiktionary.org/wiki/Modul:schackdiagram"
Purpose: brews a chessboard with pieces
Utilo: kreas sxakatabulon kun sxakpecoj
Manfaat: memperlihatkan ...
Syfte: skapar ett schackbraede med pjaeser
Used by templates / Uzata far sxablonoj:
- "Mall:schackdiagram"
Required submodules / Bezonataj submoduloj:
- none / neniuj
Required images:
- many from "commons.wikimedia.org/wiki/Category:SVG_chess_piec
es/Standard" dark background and from "commons.wikimedia.org/wiki/Ca
tegory:SVG_chess_pieces/Standard_light" light background, 4
licenses apply: GPL GFDL CC BSD
This module can accept parameters whether sent to itself (own frame) or
to the caller (caller's frame). If there is a parameter "caller=true"
on the own frame then that own frame is discarded in favor of the
caller's one.
Incoming: * named and optional
* "dim=" (for example "2x26", integer values 2...26,
X-size -- lowercase "x" -- Y-size, no spaces, default "8x8",
special value "all" to show all possible images, all
other parameters prohibited then and board size is 2x7x4,
special value "def" for default beginning position, anonymous
parameters prohibited then)
* "btm=" (length 2...200 or empty -- text below the board)
* anonymous
* either as many parameters as there are fields (hor * ver),
every of them exactly 2 char:s long, "--" for empty field,
"++" for highlighted empty field, or no anonymous parameters
for empty chessboard, absence of parameters
required for "dim=all" and "dim=def"
* 1 hidden parameter
* "nocat=true" no error possible
{{chess
|--|--|--|--|kd|--|--|rd
|--|--|--|--|--|--|--|--
|--|--|--|--|--|bl|--|pl
|--|--|--|rl|--|kl|pd|pl
|--|--|--|--|--|--|--|--
|--|--|--|--|--|--|--|--
|--|--|--|--|--|--|--|--
|--|--|--|--|--|--|--|--
|btm = deliver checkmate in two moves
}}
Pagename is never accessed.
Naming at commons:
"Chess bdd45.svg" bishop dark, field dark
"Chess bDd45.svg" bishop dark, field dark highlighted
"Chess bdl45.svg" bishop dark, field light
"Chess d45.svg" empty field dark
"Chess HLd45.svg" empty field dark highlighted
"Chess l45.svg" empty field light
Core part of the filename has 3 letters:
* type of piece (r,n,b,q,k,p) always lowercase for standard chess
* colour of piece (l,d,L,D) uppercase to highlight the field (!!!)
* colour of field (l,d) always lowercase, further "t" is
neutral / transparent, but the field cannot be highlighted then
Pieces:
r rook
n knight
b bishop
q consilor
k king
p pawn
Number of image files required:
* genuine types of pieces -> 6
* every piece can be light or dark, mul by two -> 12
* plus empty field (no colour of piece) add one -> 13
* for any of above the field can be light or dark and
highlighted or not, mul by 4 -> 52
The top left field is "a8" and is light.
Error codes:
* #E01 internal
* #E02 parameter "dim=" is bad
* #E03 parameter "btm=" is bad
* #E04 wrong number of anonymous parameters
* #E05 wrong content of anonymous parameter
* #E06 "dim=def" used together with anon parameter
* #E07 "dim=all" used together with other parameter
]===]
local exporttable = {}
------------------------------------------------------------------------
---- CONSTANTS [O] ----
------------------------------------------------------------------------
local file_prefix = 'Chess '
local file_suffix = '45.svg'
local const_tab_six_pieces = {['r']=true,['n']=true,['b']=true,['q']=true,['k']=true,['p']=true}
local const_tab_col_piece = {['l']=true,['d']=true,['L']=true,['D']=true}
local const_tab_col_bckg = {[0]='l',[1]='d'}
local const_tab_standard = {'rd','nd','bd','qd','kd','bd','nd','rd',
'pd','pd','pd','pd','pd','pd','pd','pd',
'--','--','--','--','--','--','--','--',
'--','--','--','--','--','--','--','--',
'--','--','--','--','--','--','--','--',
'--','--','--','--','--','--','--','--',
'pl','pl','pl','pl','pl','pl','pl','pl',
'rl','nl','bl','ql','kl','bl','nl','rl'} -- 8x8
local const_tab_all = {'rl','nl','bl','ql','kl','pl','--',
'rd','nd','bd','qd','kd','pd','--',
'rL','nL','bL','qL','kL','pL','++',
'rD','nD','bD','qD','kD','pD','++'} -- 2x7x4
local const_tracking = "[[Kategorio:Erara uzo de ".. string.char(0xC5,0x9D) .."ablono]]"
------------------------------------------------------------------------
---- NUMBER CONVERSION FUNCTIONS [N] ----
------------------------------------------------------------------------
-- Convert 1 decimal ASCII digit to integer 0...9 (255 if invalid).
local function lfdec1digit (num1digit)
num1digit = num1digit - 48 -- may become invalid
if ((num1digit<0) or (num1digit>9)) then
num1digit = 255
end--if
return num1digit
end--function lfdec1digit
------------------------------------------------------------------------
-- Convert 1 or 2 decimal ASCII digits to integer 0...99 (255 if invalid).
-- Depends on functions :
-- [N] lfdec1digit
local function lfstr12dig2int (strmasuk)
local numleen = 0
local numaa = 255 -- preassign to "error"
local numbb = 0
numleen = string.len (strmasuk)
if ((numleen==1) or (numleen==2)) then
numaa = string.byte (strmasuk,1,1)
numaa = lfdec1digit (numaa) -- 255 if invalid, ZERO would be valid
end--if
if ((numaa~=255) and (numleen==2)) then
numbb = string.byte (strmasuk,2,2)
numbb = lfdec1digit (numbb) -- 255 if invalid, ZERO would be valid
if (numbb==255) then
numaa = 255 -- 255 is invalid, note that ZERO would be valid
else
numaa = numaa * 10 + numbb -- valid integer number 0...99 now
end--if
end--if
return numaa
end--function lfstr12dig2int
------------------------------------------------------------------------
---- HIGH LEVEL STRING FUNCTIONS [I] ----
------------------------------------------------------------------------
function iIntegerToCssHeight (num_height) -- called from iTrStyle only
return 'line-height:' .. tostring(num_height-2) .. 'px;' -- this is obscure !!!FIXME!!!
end--function iIntegerToCssHeight
function iTrStyle (num_tr_height, boo_omit_tr_style)
local my_tr = ''
if (boo_omit_tr_style) then
my_tr = '<tr>' -- for "show all" only
else
my_tr = '<tr style="' .. iIntegerToCssHeight(num_tr_height) .. '">'
end--if
return my_tr
end--function iTrStyle
------------------------------------------------------------------------
function iIntegerToCssWidth (num_width) -- also called from main
return 'width:' .. tostring(num_width) .. 'px;'
end--function iIntegerToCssWidth
function iTdStyle (num_td_width, boo_omit_td_style)
local my_td = ''
if (boo_omit_td_style) then
my_td = '<td style="text-align:center;">' -- for "show all" only
else
my_td = '<td style="' .. iIntegerToCssWidth(num_td_width) .. 'padding:0; font-size:12px; text-align:center;">'
end--if
return my_td
end--function iTdStyle
------------------------------------------------------------------------
---- HIGH LEVEL FUNCTIONS [H] ----
------------------------------------------------------------------------
-- Split string like "26x2" into 2 integers (here
-- values 0...99 are accepted).
-- Depends on functions :
-- [N] lfstr12dig2int
function hiSplitDimIntoTwoIntegers (str_combo_dim)
local var_tnp = 0
local in_len_min_three_max_five = 0
local dim_xx = 255
local dim_yy = 255
while true do -- fake loop
in_len_min_three_max_five = string.len(str_combo_dim)
if ((in_len_min_three_max_five<3) or (in_len_min_three_max_five>5)) then
break
end--if
var_tnp = string.find(str_combo_dim, "x", 1, true) -- plain text search
if (type(var_tnp)~="number") then
break
end--if
if ((var_tnp<=1) or (var_tnp>=in_len_min_three_max_five)) then
break
end--if
dim_xx = lfstr12dig2int(string.sub(str_combo_dim,1,(var_tnp-1)))
dim_yy = lfstr12dig2int(string.sub(str_combo_dim,(var_tnp+1),-1))
if ((dim_xx>99) or (dim_yy>99)) then
dim_xx = 255
dim_yy = 255
end--if
break -- finally to join mark
end--while
return dim_xx, dim_yy
end--function hiSplitDimIntoTwoIntegers
------------------------------------------------------------------------
-- Brew one HTML table row using "tr" and "td" with index
-- letters from "a" to "h" or other.
function hiBrewTopBottom (num_field_dimension, num_outer_dimension, num_hor_size)
local line_top_bottom = ''
local str_nbsp_cell = ''
local letter_index = 0
str_nbsp_cell = iTdStyle(num_outer_dimension,false) .. ' </td>'
line_top_bottom = iTrStyle(num_outer_dimension,false) .. str_nbsp_cell
while true do
line_top_bottom = line_top_bottom .. iTdStyle(num_field_dimension,false) .. string.char(97+letter_index) .. '</td>'
letter_index = letter_index + 1
if (letter_index==num_hor_size) then
break
end--if
end--while
line_top_bottom = line_top_bottom .. str_nbsp_cell .. '</tr>'
return line_top_bottom
end--function hiBrewTopBottom
------------------------------------------------------------------------
-- Convert two letters to bare filename on commons, "?" on error.
function hiTypeToCommonsBareName (str_two_letters, num_background_one_dark)
local str_name_core_out = ''
local str_colour_of_piece = ''
while true do -- fake loop
if (str_two_letters=='++') then
str_name_core_out = 'HL'
break
end--if
if (str_two_letters=='--') then
break -- leave it empty
end--if
if (not const_tab_six_pieces[string.sub(str_two_letters,1,1)]) then
str_name_core_out = '?' -- invalid
break
end--if
if (not const_tab_col_piece[string.sub(str_two_letters,2,2)]) then
str_name_core_out = '?' -- invalid
break
end--if
str_name_core_out = str_two_letters
break -- finally to join mark
end--while -- fake loop -- join mark
if (str_name_core_out~='?') then
str_name_core_out = file_prefix .. str_name_core_out .. (const_tab_col_bckg[num_background_one_dark] or '!') .. file_suffix
end--if
return str_name_core_out
end--function hiTypeToCommonsBareName
------------------------------------------------------------------------
-- Convert filename on commons to full image syntax, optionally
-- with link below.
function hiNameToFullCell (str_name_in, str_two_lett_in, num_size_xy_px, boo_add_link_below)
local str_full_wiki_image = ''
str_full_wiki_image = '[[File:' .. str_name_in .. '|' .. tostring(num_size_xy_px) .. 'x' .. tostring(num_size_xy_px) .. 'px|link=|alt=' .. str_two_lett_in .. ']]'
if (boo_add_link_below) then
str_full_wiki_image = str_full_wiki_image .. '<br>[[:File:' .. str_name_in .. '|' .. str_two_lett_in .. ']]'
end--if
return str_full_wiki_image
end--function hiNameToFullCell
------------------------------------------------------------------------
---- VARIABLES [R] ----
------------------------------------------------------------------------
function exporttable.ek (arxframent)
-- special type "args" AKA "arx"
local arxsomons = 0 -- metaized "args" from our own or caller's "frame"
-- general table
local tab_input_anon = {} -- all fields, empty for empty board
-- general str
local str_dim = '' -- from "dim=" NOT for "dim=all" or "dim=def"
local str_btm = '' -- from "btm="
local strvisgud = '' -- visible good output
local strviserr = '' -- visible error message
local strtrakat = '' -- invisible tracking categories
local str_return = ''
-- general num
local num_err = 0
local size_inr_field_std_px = 26
local size_inr_field_all_px = 60
local size_outr_desc_px = 20
local size_hor = 0
local size_ver = 0
local anon_param_eval = 0
-- general boo
local boo_have_dim = false -- NOT "true" for "dim=all" or "dim=def"
local boo_have_btm = false
local boo_have_anony = false
local boo_show_def = false -- from "dim=def"
local boo_show_all = false -- from "dim=all"
local boo_nocat = false -- from "nocat=true"
---- GET THE ARX (ONE OF TWO) ----
arxsomons = arxframent.args -- "args" from our own "frame"
if (type(arxsomons)~="table") then
arxsomons = {} -- guard against indexing error from our own
num_err = 1 -- #E01 internal
end--if
if (arxsomons['caller']=="true") then
arxsomons = arxframent:getParent().args -- "args" from caller's "frame"
end--if
if (type(arxsomons)~="table") then
arxsomons = {} -- guard against indexing error again
num_err = 1 -- #E01 internal
end--if
---- GET NAMED PARAM:S ----
if (num_err==0) then
do -- scope
local var_3_temp = 0
var_3_temp = arxsomons["dim"]
if (type(var_3_temp)=="string") then
boo_show_def = (var_3_temp=="def")
boo_show_all = (var_3_temp=="all")
if ((not boo_show_def) and (not boo_show_all)) then
str_dim = var_3_temp
boo_have_dim = true
end--if
end--if
var_3_temp = arxsomons["btm"]
if (type(var_3_temp)=="string") then
str_btm = var_3_temp
boo_have_btm = true
end--if
end--do scope
end--if
---- GET HIDDEN PARAM:S ----
boo_nocat = (arxsomons['nocat']=='true')
---- GET AND CHECK ANONYMOUS PARAM:S ----
if (num_err==0) then
anon_param_eval = 0 -- result needed far below
do -- scope
local var_4_temp = 0
while true do
var_4_temp = arxsomons[anon_param_eval+1]
if (type(var_4_temp)~="string") then
break
end--if
var_4_temp = mw.text.trim (var_4_temp)
if (string.len(var_4_temp)~=2) then
num_err = 5 -- #E05
break
end--if
anon_param_eval = anon_param_eval + 1
tab_input_anon[anon_param_eval] = var_4_temp
boo_have_anony = true
end--while
end--do scope
end--if
---- SOME PREPARATIONS AND CHECKS ----
while true do -- fake loop
if (num_err~=0) then
break
end--if
if (boo_have_dim) then
size_hor, size_ver = hiSplitDimIntoTwoIntegers(str_dim)
if ((size_hor<2) or (size_hor>26) or (size_ver<2) or (size_ver>26)) then
num_err = 2 -- #E02
break
end--if
else
size_hor = 8
size_ver = 8
end--if
do -- scope
local num_len_btm = 0
if (boo_have_btm) then
num_len_btm = string.len(str_btm)
if ((num_len_btm<2) or (num_len_btm>200)) then
num_err = 3 -- #E03
break
end--if
end--if
end--do scope
if (boo_show_def and boo_have_anony) then
num_err = 6 -- #E06 -- "show def" excludes anon ("dim=" impossible)
break
end--if
if (boo_show_all and (boo_have_anony or boo_have_btm)) then
num_err = 7 -- #E07 -- "show all" excludes anon and "btm=" ("dim=" impossible)
break
end--if
if (boo_show_all) then
tab_input_anon = const_tab_all
size_hor = 7 -- 2x7 -- !!! here 7 but we will get 14 columns !!!
size_ver = 4
end--if
if (boo_show_def) then
tab_input_anon = const_tab_standard
end--if
if ((not boo_show_all) and (not boo_show_def) and boo_have_anony and (anon_param_eval~=(size_hor*size_ver))) then
num_err = 4 -- #E04
break
end--if
break -- finally to join mark
end--while
---- BREW THE BOARD ----
if (num_err==0) then
do -- scope
local inner_border_and_padding = ''
local top_and_bottom_line = ''
local left_and_right_cell = ''
local our_two_letters = ''
local name_or_bad_quest = ''
local size_inr_field_final_px = 0
local index_xx = 0
local index_yy = 0
local index_zz = 0
local index_one_dim_input_table = 0
local num_bckg_color = 0 -- alternate between 0 and 1 also for "dim=all"
if (boo_show_all) then
size_inr_field_final_px = size_inr_field_all_px
inner_border_and_padding = 'border:3px solid #909090; padding:4px;'
strvisgud = '<table style="margin:0.3em auto 0.3em auto; border:1px solid #909090; padding:4px;"><tr><td>'
else
size_inr_field_final_px = size_inr_field_std_px
inner_border_and_padding = 'border-collapse:collapse; border:1px solid #909090; padding:0;'
strvisgud = '<table style="clear:right; float:right; margin:0.3em 0 0.3em auto; ' .. iIntegerToCssWidth(size_hor * size_inr_field_final_px + 2 * size_outr_desc_px + 10) .. ' border:1px solid #909090; padding:4px;"><tr><td>'
end--if
strvisgud = strvisgud .. '<table style="' .. inner_border_and_padding .. ' vertical-align:middle;">' -- inner table
if (not boo_show_all) then
top_and_bottom_line = hiBrewTopBottom (size_inr_field_final_px, size_outr_desc_px, size_hor)
strvisgud = strvisgud .. top_and_bottom_line -- string is reused one time below
end--if
index_yy = 0
while true do -- outer YY from "8" or other down to "1"
if (not boo_show_all) then
left_and_right_cell = iTdStyle(size_outr_desc_px,false) .. tostring(size_ver-index_yy) .. '</td>' -- string is reused one time below
end--if
strvisgud = strvisgud .. iTrStyle(size_inr_field_final_px,boo_show_all)
if (not boo_show_all) then
strvisgud = strvisgud .. left_and_right_cell
end--if
index_xx = 0
if (not boo_show_all) then
num_bckg_color = index_yy % 2 -- "a8" is light
end--if
while true do -- inner XX from "a" up to "h" or other
index_one_dim_input_table = index_one_dim_input_table + 1
our_two_letters = tab_input_anon[index_one_dim_input_table] or '--'
index_zz = 0
while true do -- deep -- for "dim=all" generate 2 fields for 1 pick
name_or_bad_quest = hiTypeToCommonsBareName(our_two_letters,num_bckg_color)
if (name_or_bad_quest=="?") then
num_err = 5 -- #E05 -- no break
end--if
strvisgud = strvisgud .. iTdStyle(size_inr_field_final_px,boo_show_all) .. hiNameToFullCell(name_or_bad_quest,our_two_letters,size_inr_field_final_px,boo_show_all) .. '</td>'
num_bckg_color = 1 - num_bckg_color -- alternate
index_zz = index_zz + 1
if ((index_zz==2) or (not boo_show_all)) then
break
end--if
end--while -- deep
index_xx = index_xx + 1
if (index_xx==size_hor) then
break
end--if
end--while -- inner XX
if (not boo_show_all) then
strvisgud = strvisgud .. left_and_right_cell
end--if
strvisgud = strvisgud .. '</tr>'
index_yy = index_yy + 1
if (index_yy==size_ver) then
break
end--if
end--while -- outer YY
if (not boo_show_all) then
strvisgud = strvisgud .. top_and_bottom_line
end--if
strvisgud = strvisgud .. '</table>' -- inner table
if (boo_have_btm) then
strvisgud = strvisgud .. '</td></tr><tr><td><table><tr><td style="text-align:left;">' .. str_btm .. '</td></tr></table>'
end--if
strvisgud = strvisgud .. '</td></tr></table>' -- outer table
end--do scope
end--if
---- WHINE IF YOU MUST #E02...#E99 ----
if (num_err~=0) then
strviserr = 'ERROR'
if (num_err==2) then
strviserr = 'parameter "dim=" is bad'
end--if
if (num_err==3) then
strviserr = 'parameter "btm=" is bad'
end--if
if (num_err==4) then
strviserr = 'wrong number of anon parameters (found ' .. tostring (anon_param_eval) .. ')'
end--if
if (num_err==5) then
strviserr = 'wrong content of anon parameter'
end--if
if (num_err==6) then
strviserr = '"dim=def" used together with anon parameter'
end--if
if (num_err==7) then
strviserr = '"dim=all" used together with other parameter'
end--if
strviserr = '<b>!!! ' .. strviserr .. ' in "Template:chess" !!!</b>' -- !!!FIXME!!!
if (not boo_nocat) then
strtrakat = const_tracking -- !!!FIXME!!!
end--if
end--if
---- RETURN THE JUNK STRING ----
if (num_err==0) then
str_return = strvisgud
else
str_return = strviserr .. strtrakat
end--if
return str_return
end--function
---- RETURN THE JUNK OUTER TABLE ----
return exporttable