モジュール:Shogi diagram
表示
モジュールの解説[作成]
require('strict')
-- these are the column coordinate labels 9-1
local colLabels = {'9', '8', '7', '6', '5', '4', '3', '2', '1', ' '}
-- these are the row coordinate labels 1-9 (Japanese notation)
local rowLabels = {'一', '二', '三', '四', '五', '六', '七', '八', '九'}
-- letter to character mapping (hash table)
local pieces = {
p = {'歩'},
t = {'と', true},
l = {'香'},
pl = {'杏', true},
n = {'桂'},
pn = {'圭', true},
s = {'銀'},
ps = {'全', true},
g = {'金'},
b = {'角'},
h = {'馬', true},
r = {'飛'},
d = {'龍', true},
gyoku = {'玉'},
ou = {'王'},
tx = {'个', true},
plx = {'仝', true},
pnx = {'今', true},
dx = {'竜', true},
e = {'象'},
a = {'太', true}
}
local arrows = {'yy', 'gr', 'rat', 'lat', 'uat', 'dat',
'lra', 'las', 'ras', 'uda', 'das', 'uas',
'da', 'dau', 'dad', 'daus', 'dads', 'daa',
'daad', 'daau', 'daaus', 'daads', 'kar', 'kal',
'kadr', 'kadl', 'rah', 'lah', 'dah', 'uah',
'durh', 'dulh', 'ddrh', 'ddlh', 'ddl', 'ddr',
'dul', 'dur'}
-- function separates out the piece, the side, and the boldness info present in the string argument
-- it returns an array with these three values plus the color (for promoted pieces)
-- this info is passed to the makeTD() function
local function processString(ss)
-- 先頭・末尾の空白文字類(全角空白なども含む)を除去する
ss = mw.text.trim(ss or '', '%s')
if ss == '' then
return ' '
end
-- 'da', 'ddl', 'dul', 'gr', 'kal' に対しては69行以下の判定が正しく動作しないため、ここで個別に判定
if ss == 'da' then
return '[[File:shogi_da22.svg|22px]]'
end
if ss == 'ddl' then
return '[[File:shogi_ddl22.svg|22px]]'
end
if ss == 'dul' then
return '[[File:shogi_dul22.svg|22px]]'
end
if ss == 'gr' then
return '[[File:shogi_gr22.svg|22px]]'
end
if ss == 'kal' then
return '[[File:shogi_kal22.svg|22px]]'
end
-- get the last character of the string
local lastchar = mw.ustring.sub(ss, -1)
-- default is normal font
-- but if the string ends with 'l' for 'last move',
-- then the font should be bold and we need to get a new string with the this 'l' chopped off (with a new last character)
local bold = false
local side = lastchar
local pieceabbr = mw.ustring.sub(ss, 1, -2)
if lastchar == 'l' then
bold = true
side = mw.ustring.sub(ss, -2, -2)
pieceabbr = mw.ustring.sub(ss, 1, -3)
end
local gote = (side == 'g')
-- this is an exceptional bit:
-- gote's king is usually 王 instead of 玉 by convention,
-- but it's convenient to use the 'k' code for both sente and gote and let the default character be side-dependent
if pieceabbr == 'k' then
if gote then
pieceabbr = 'ou'
else
pieceabbr = 'gyoku'
end
elseif pieceabbr == 'ak' then
if gote then
pieceabbr = 'gyoku'
else
pieceabbr = 'ou'
end
end
-- convert abbreviation to Japanese character
local piece = pieces[pieceabbr]
if not piece then
for _, v in ipairs(arrows) do
if ss == v then
return '[[File:shogi_' .. ss .. '22.svg|22px]]'
end
end
error(ss, 0)
end
return piece[1], piece[2], gote, bold
end
-- function makes a <td> containing the piece with CSS stuff
-- uses the info from processString() to customize the CSS based on which side, color, and boldness
local function makeTD(stringarg)
-- got to process the string argument into its informational bits
local piecechar, promoted, gote, bold = processString(stringarg)
-- the default <td>
local td = mw.html.create('td')
td:addClass('shogi-piece')
:wikitext( piecechar )
-- g = gote
-- gote should be upside down text
if gote then
td:addClass('piece-gote')
end
-- for promoted pieces
if promoted then
td:addClass('piece-promoted')
end
-- for bold pieces
if bold then
td:addClass('piece-bold')
end
return td
end
-- function makes the shogi diagram
-- this is basically a <div> enclosing a .css <div> wrapper with a <table> inside
local function shogiboard(args)
-- <div> wrapper
local shogiboardwrapper = mw.html.create('div')
:addClass('shogiboard-wrapper')
-- the diagram header/caption
shogiboardwrapper:tag('div')
:addClass('shogiboard-header')
:wikitext(mw.text.trim(args[2] or ''))
-- the shogi table
local shogitable = shogiboardwrapper:tag('table')
:addClass('shogiboard-table')
:attr('border', '1')
-- the row for the column coordinate labels
local columnlabelrow = shogitable:tag('tr')
:addClass('shogiboard-collabel')
-- iterating over the column label to put each label in a <td>
for _, v in ipairs(colLabels) do
columnlabelrow:tag('td')
:wikitext( v )
end
-- iterate over the 81 shogi piece arguments (left to right, top to bottom)
-- i couldn't figure out how to do this is in a clever loopy way as i couldn't figure out how to close the html tags
-- whatever, it's repetitive, but it works
-- index number displacement/offset
-- this is just the number of arguments that precede the 81 shogi piece arguments that are in the html <table>
-- i just keep the piece arguments as indexes 1-81, then add nx to the index value
local nx = 2
-- the row for the shogi pieces
for irow = 1,9 do
local trow = shogitable:tag('tr')
-- put a single piece into a <td>
for icol = 1, 9 do
local result, td = pcall(makeTD, args[(irow - 1) * 9 + icol + nx])
if not result then
return string.format(
'<strong class="error">%s%sの位置で不明な値"%s"が指定されました。</strong>',
colLabels[icol],
rowLabels[irow],
td
)
end
trow:node(td)
end
-- add row coordinate label <td>
trow:tag('td')
:addClass('shogiboard-rowlabel')
:wikitext( rowLabels[irow] )
end
-- the diagram footer
shogiboardwrapper:tag('div')
:addClass('shogiboard-footer', 'bold')
:wikitext(mw.text.trim(args[84] or ''))
return tostring(shogiboardwrapper)
end
local valueFunc = function(_, value)
if value then
return mw.text.trim(value)
else
return false
end
end
-----------------------
-- output
-----------------------
return {
board = function(frame)
return shogiboard(frame:getParent().args)
end
}