Skip to content

Instantly share code, notes, and snippets.

Created April 30, 2016 16:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/166eda49cad4549f89f2c59587f81c78 to your computer and use it in GitHub Desktop.
Save anonymous/166eda49cad4549f89f2c59587f81c78 to your computer and use it in GitHub Desktop.
--[[
内藤九段将棋秘伝 (FC) 思考ログ出力
--]]
----------------------------------------------------------------------
-- utility
----------------------------------------------------------------------
local function mem_read_u8(addr)
return memory.readbyte(addr)
end
----------------------------------------------------------------------
-- log
----------------------------------------------------------------------
local out = nil
local function out_init()
local path = os.date("log/%Y%m%d-%H%M%S.log")
out = io.open(path, "w")
return out and true or false
end
local function out_fin()
if out then
out:close()
out = nil
end
end
local function info(msg)
out:write(msg)
out:write("\n")
end
----------------------------------------------------------------------
-- game utility
----------------------------------------------------------------------
-- pt: 駒種
-- pcp: PLAYER駒
-- pcc: COM駒
local KANDIGIT = {
"一", "二", "三", "四", "五", "六", "七", "八", "九"
}
--[[
local PT_NAME = {
"KING",
"ROOK",
"BISHOP",
"GOLD",
"SILVER",
"KNIGHT",
"LANCE",
"PAWN",
"DRAGON",
"HORSE",
nil,
"PRO_SILVER",
"PRO_KNIGHT",
"PRO_LANCE",
"PRO_PAWN",
}
--]]
local PT_NAME = {
"玉",
"飛",
"角",
"金",
"銀",
"桂",
"香",
"歩",
"竜",
"馬",
nil,
"全",
"圭",
"杏",
"と"
}
local function sq_is_ok(sq)
return 12 <= sq and sq <= 108
end
local function drop_pt(drop)
return 209 - drop
end
local function drop_is_ok(drop)
return 201 <= drop and drop <= 207
end
local function pt_is_ok(pt)
return 1 <= pt and pt <= #PT_NAME and PT_NAME[pt]
end
local function pcp_type(pcp)
return pcp
end
local function pcp_is_ok(pcp)
return pt_is_ok(pcp_type(pcp))
end
local function pcc_type(pcc)
return pcc - 0x0F
end
local function pcc_is_ok(pcc)
return pt_is_ok(pcc_type(pcc))
end
local function sq2xy(sq)
local x = sq % 11
local y = math.floor(sq / 11)
return x, y
end
local function xy2sq(x, y)
return x + 11 * y
end
local function board_player(sq)
return mem_read_u8(0x03A9 + sq)
end
local function board_com(sq)
return mem_read_u8(0x049B + sq)
end
local function hand_player()
local hand = {}
for i = 1, 7 do
hand[i] = mem_read_u8(0x058D + i-1)
end
return hand
end
local function hand_com()
local hand = {}
for i = 1, 7 do
hand[i] = mem_read_u8(0x0594 + i-1)
end
return hand
end
local function move_str(src, dst, pt)
local dst_file, dst_rank = sq2xy(dst)
dst_file = 10 - dst_file -- 将棋の表記法に合わせる
if drop_is_ok(src) then
--return string.format("%d%d %s DROP", dst_file, dst_rank, PT_NAME[pt])
return string.format("%d%d%s打", dst_file, dst_rank, PT_NAME[pt])
else
local src_file, src_rank = sq2xy(src)
src_file = 10 - src_file
--return string.format("%d%d %s (%d%d)", dst_file, dst_rank, PT_NAME[pt], src_file, src_rank)
return string.format("%d%d%s (%d%d)", dst_file, dst_rank, PT_NAME[pt], src_file, src_rank)
end
end
local function hand_str(hand)
local s = ""
for i, n in ipairs(hand) do
if n > 0 then
s = s .. string.format("%s%d ", PT_NAME[i+1], n)
end
end
return s
end
local function print_position()
info("▽持駒: " .. hand_str(hand_com()))
info(" 9 8 7 6 5 4 3 2 1")
info("┌──┬──┬──┬──┬──┬──┬──┬──┬──┐")
for y = 1, 9 do
local line = "│"
for x = 1, 9 do
local pcp = board_player(xy2sq(x, y))
local pcc = board_com(xy2sq(x, y))
assert(pcp == 0 or pcc == 0, "pcp && pcc")
if pcp_is_ok(pcp) then
line = line .. "▲" .. PT_NAME[pcp_type(pcp)]
elseif pcc_is_ok(pcc) then
line = line .. "▽" .. PT_NAME[pcc_type(pcc)]
else
line = line .. "__"
end
line = line .. "│"
end
line = line .. KANDIGIT[y]
info(line)
if y ~= 9 then info("├──┼──┼──┼──┼──┼──┼──┼──┼──┤") end
end
info("└──┴──┴──┴──┴──┴──┴──┴──┴──┘")
info("▲持駒: " .. hand_str(hand_player()))
end
----------------------------------------------------------------------
-- callback
----------------------------------------------------------------------
-- ルート局面を出力
-- 候補手生成ループ直前に呼び出される
local function log_root()
info("[ルート局面]")
local move_src_player = mem_read_u8(0x05A2)
local move_dst_player = mem_read_u8(0x05A1)
local move_pt_player = pcp_type(board_player(move_dst_player))
info(string.format("num_move2: %d", mem_read_u8(0x05C1)))
info(string.format("progress: %d", mem_read_u8(0x028E)))
info(string.format("formation: %d", mem_read_u8(0x05BE)))
info(string.format("player move: %s",
move_str(move_src_player, move_dst_player, move_pt_player)))
info("")
print_position()
info("")
info(string.format("root_power_player: %d", mem_read_u8(0x05E7)))
info(string.format("root_rbp_com: %d", mem_read_u8(0x05EA)))
info(string.format("root_power_com: %d", mem_read_u8(0x05E4)))
info(string.format("root_adv_score: %d", mem_read_u8(0x0280)))
info(string.format("root_disadv_score: %d", mem_read_u8(0x0282)))
info(string.format("root_player_offer: %s", tostring(mem_read_u8(0x05DE) == 2)))
info("")
info("[候補手生成開始]")
end
-- 1つの候補手を出力
-- 候補手生成後それが評価される直前に呼び出される
-- よって出力は全ての合法手となるはず
-- ただし完全な合法手というわけではない。以下のものも含まれる:
-- * 自殺手
-- * 打ち歩詰め
-- 以下のものは含まれない:
-- * 不成 (COMは成れるときは必ず成る)
-- * 行き所のない駒
-- * 二歩
local function log_cand()
local src = mem_read_u8(0x0277)
local dst = mem_read_u8(0x0276)
local pt = pcc_type(mem_read_u8(0x5F))
assert(sq_is_ok(src) or drop_is_ok(src), "invalid src")
assert(sq_is_ok(dst), "invalid dst")
assert(pt_is_ok(pt), "invalid pt")
if drop_is_ok(src) then assert(drop_pt(src) == pt, "drop_pt(src) ~= pt") end
info(move_str(src, dst, pt))
info(string.format(" cand_score: %d", mem_read_u8(0x0278)))
info(string.format(" cand_offer: %d", mem_read_u8(0x027C)))
info(string.format(" adv_score: %d", mem_read_u8(0x0272)))
info(string.format(" adv_sq: %d", mem_read_u8(0x0273)))
info(string.format(" disadv_score: %d", mem_read_u8(0x0274)))
info(string.format(" disadv_sq: %d", mem_read_u8(0x0275)))
info(string.format(" num_promoted_com: %d", mem_read_u8(0x0293)))
info(string.format(" dist_dst_kp: %d", mem_read_u8(0x0294)))
info(string.format(" dist_src_kc: %d", mem_read_u8(0x0298)))
info(string.format(" threat_far_player: %d", mem_read_u8(0x0299)))
info(string.format(" safety_far_com: %d", mem_read_u8(0x0295)))
info(string.format(" threat_far_com: %d", mem_read_u8(0x0296)))
info(string.format(" threat_near_com: %d", mem_read_u8(0x05EB)))
info(string.format(" surround_com: %d", mem_read_u8(0x05E5)))
info(string.format(" num_loose_com: %d", mem_read_u8(0x0297)))
info(string.format(" dangling_pawn_lance: %d", mem_read_u8(0x05DF)))
info(string.format(" $02A4: %d", mem_read_u8(0x02A4)))
info(string.format(" $05E0: %d", mem_read_u8(0x05E0)))
end
-- 候補手評価完了時の評価値を出力
-- 一部のタダ捨て、および打ち歩詰めは評価完了前に切り捨てられる
local function log_eval()
info(" [評価完了]")
info(string.format(" mate_player: %d", mem_read_u8(0x05DD)))
info(string.format(" cand_score: %d", mem_read_u8(0x0278)))
info(string.format(" adv_score: %d", mem_read_u8(0x0272)))
info(string.format(" disadv_score: %d", mem_read_u8(0x0274)))
info(string.format(" $02A4: %d", mem_read_u8(0x02A4)))
info(string.format(" $05E0: %d", mem_read_u8(0x05E0)))
end
-- 最善手更新時にその旨出力
local function log_best()
info(" [最善手更新]")
end
----------------------------------------------------------------------
-- main
----------------------------------------------------------------------
local function main()
if not out_init() then
print("Can't open file")
return
end
emu.registerexit(out_fin)
memory.registerexec(0xF045, log_root)
memory.registerexec(0xF282, log_cand)
memory.registerexec(0xF674, log_eval)
memory.registerexec(0xF6F9, log_best)
end
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment