Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- 内藤九段将棋秘伝 (FC) 思考トレース for FCEUX
- ログはサブディレクトリ trace/ 内に出力される(予め mkdir すること)
- --]]
- ----------------------------------------------------------------------
- -- util
- ----------------------------------------------------------------------
- local function mem_read_u8(addr)
- return memory.readbyte(addr)
- end
- local out = nil
- local function trace_init()
- local path = os.date("trace/%Y%m%d-%H%M%S.log")
- out = io.open(path, "w")
- assert(out)
- return out
- end
- local function trace_fin()
- if out then
- out:close()
- out = nil
- end
- end
- local function print(s)
- if s ~= nil then
- out:write(s)
- end
- out:write("\n")
- end
- ----------------------------------------------------------------------
- -- game
- ----------------------------------------------------------------------
- -- sq: マス目 [12,108]
- -- pt: 駒種 [1,15] ただし 11 は無効
- -- pcp: PLAYER駒 [1,15] ただし 11 は無効
- -- pcc: COM駒 [16,30] ただし 26 は無効
- -- dropp: PLAYERが駒を打つ手の移動元マス目 [213,219] ((駒種)+211)
- -- dropc: COMが駒を打つ手の移動元マス目 [201,207] (209-(駒種))
- 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 sq_is_ok(sq)
- local x, y = sq2xy(sq)
- return 1 <= x and x <= 9 and 1 <= y and y <= 9
- end
- local function pt_is_ok(pt)
- return 1 <= pt and pt <= 15 and pt ~= 11
- end
- local function pt_unpromote(pt)
- if 9 <= pt and pt <= 15 and pt ~= 11 then
- pt = pt - 7
- end
- return pt
- end
- local function pcp2pt(pcp)
- return pcp
- end
- local function pcp_is_ok(pcp)
- return pt_is_ok(pcp2pt(pcp))
- end
- local function pcc2pt(pcc)
- return pcc - 15
- end
- local function pcc_is_ok(pcc)
- return pt_is_ok(pcc2pt(pcc))
- end
- local function dropp_is_ok(dropp)
- return 213 <= dropp and dropp <= 219
- end
- local function dropp2pt(dropp)
- return dropp - 211
- end
- local function dropc_is_ok(dropc)
- return 201 <= dropc and dropc <= 207
- end
- local function dropc2pt(dropc)
- return 209 - dropc
- end
- local function board_player()
- local board = {}
- for i = 1, 121 do
- board[i] = mem_read_u8(0x03A9 + i-1)
- end
- return board
- end
- local function board_com()
- local board = {}
- for i = 1, 121 do
- board[i] = mem_read_u8(0x049B + i-1)
- end
- return board
- 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 effect_player()
- local eff = {}
- for i = 1, 121 do
- eff[i] = mem_read_u8(0x0422 + i-1)
- end
- return eff
- end
- local function effect_com()
- local eff = {}
- for i = 1, 121 do
- eff[i] = mem_read_u8(0x0514 + i-1)
- end
- return eff
- end
- local function move_player()
- local is_promote = mem_read_u8(0x05BF) ~= 0
- local src = mem_read_u8(0x05A2)
- local dst = mem_read_u8(0x05A1)
- local board = board_player()
- local pt = pcp2pt(board[dst+1])
- if is_promote then
- pt = pt_unpromote(pt)
- end
- local is_drop = dropp_is_ok(src)
- if is_drop then
- assert(dropp2pt(src) == pt)
- assert(not is_promote)
- end
- return src, dst, pt, is_drop, is_promote
- end
- local function move_cand()
- local is_promote = mem_read_u8(0x0279) ~= 0
- local src = mem_read_u8(0x0277)
- local dst = mem_read_u8(0x0276)
- local pt = pcc2pt(mem_read_u8(0x5F))
- local is_drop = dropc_is_ok(src)
- if is_drop then
- assert(dropc2pt(src) == pt)
- assert(not is_promote)
- end
- return src, dst, pt, is_drop, is_promote
- end
- local function move_best()
- local is_promote = mem_read_u8(0x028C) ~= 0
- local src = mem_read_u8(0x0285)
- local dst = mem_read_u8(0x0284)
- local board = board_com()
- local pt = pcc2pt(board[dst+1])
- if is_promote then
- pt = pt_unpromote(pt)
- end
- local is_drop = dropc_is_ok(src)
- if is_drop then
- assert(dropc2pt(src) == pt)
- assert(not is_promote)
- end
- return src, dst, pt, is_drop, is_promote
- end
- local KANDIGIT = {
- "一", "二", "三", "四", "五", "六", "七", "八", "九",
- }
- local PT_NAME = {
- "玉",
- "飛",
- "角",
- "金",
- "銀",
- "桂",
- "香",
- "歩",
- "竜",
- "馬",
- nil,
- "全",
- "圭",
- "杏",
- "と",
- }
- local function sq_str(sq)
- local file, rank = sq2xy(sq)
- file = 10 - file -- 将棋の表記法に合わせる
- return string.format("%d%d", file, rank)
- end
- local function hand_str(hand)
- local res = ""
- for i,n in ipairs(hand) do
- local pt = i + 1
- if n > 0 then
- res = res .. string.format("%s%d ", PT_NAME[pt], n)
- end
- end
- return res
- end
- local function position_str(boardp, boardc, handp, handc)
- local res = ""
- local append = function(s)
- res = res .. s .. "\n"
- end
- append("▽持駒: " .. hand_str(handc))
- append(" 9 8 7 6 5 4 3 2 1")
- append("┌──┬──┬──┬──┬──┬──┬──┬──┬──┐")
- for y = 1, 9 do
- local line = "│"
- for x = 1, 9 do
- local sq = xy2sq(x,y)
- local pcp = boardp[sq+1]
- local pcc = boardc[sq+1]
- if pcp_is_ok(pcp) and pcc == 0 then
- line = line .. "▲" .. PT_NAME[pcp2pt(pcp)]
- elseif pcp == 0 and pcc_is_ok(pcc) then
- line = line .. "▽" .. PT_NAME[pcc2pt(pcc)]
- elseif pcp == 0 and pcc == 0 then
- line = line .. "__"
- else
- assert(false)
- end
- line = line .. "│"
- end
- line = line .. KANDIGIT[y]
- append(line)
- if y ~= 9 then
- append("├──┼──┼──┼──┼──┼──┼──┼──┼──┤")
- end
- end
- append("└──┴──┴──┴──┴──┴──┴──┴──┴──┘")
- append("▲持駒: " .. hand_str(handp))
- return res
- end
- local function effect_str(effp, effc)
- local res = ""
- local append = function(s)
- res = res .. s .. "\n"
- end
- append(" 9 8 7 6 5 4 3 2 1")
- append("┌──┬──┬──┬──┬──┬──┬──┬──┬──┐")
- for y = 1, 9 do
- local line = "│"
- for x = 1, 9 do
- local sq = xy2sq(x,y)
- line = line .. string.format("%d,%d ", effp[sq+1], effc[sq+1])
- line = line .. "│"
- end
- line = line .. KANDIGIT[y]
- append(line)
- if y ~= 9 then
- append("├──┼──┼──┼──┼──┼──┼──┼──┼──┤")
- end
- end
- append("└──┴──┴──┴──┴──┴──┴──┴──┴──┘")
- return res
- end
- local function move_str(src, dst, pt, is_drop, is_promote)
- local dst_file, dst_rank = sq2xy(dst)
- dst_file = 10 - dst_file -- 将棋の表記法に合わせる
- if is_drop then
- 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
- local spromo = is_promote and "成" or ""
- return string.format("%d%d%s%s (%d%d)",
- dst_file, dst_rank, PT_NAME[pt], spromo,
- src_file, src_rank)
- end
- end
- local function U8VAR(name, addr)
- return function()
- return string.format("%s: %d", name, mem_read_u8(addr))
- end
- end
- local VARS = {
- adv_score = U8VAR("adv_score", 0x0272),
- adv_sq = function()
- local sq = mem_read_u8(0x0273)
- local s = sq_is_ok(sq) and sq_str(sq) or "NONE"
- return string.format("adv_sq: %d (%s)", sq, s)
- end,
- best_adv_score = U8VAR("best_adv_score", 0x0286),
- best_adv_sq = function()
- local sq = mem_read_u8(0x0287)
- local s = sq_is_ok(sq) and sq_str(sq) or "NONE"
- return string.format("best_adv_sq: %d (%s)", sq, s)
- end,
- best_disadv_score = U8VAR("best_disadv_score", 0x0288),
- best_disadv_sq = function()
- local sq = mem_read_u8(0x0289)
- local s = sq_is_ok(sq) and sq_str(sq) or "NONE"
- return string.format("best_disadv_sq: %d (%s)", sq, s)
- end,
- best_score = U8VAR("best_score", 0x028A),
- cand_offer = U8VAR("cand_offer", 0x027C),
- cand_score = U8VAR("cand_score", 0x0278),
- dangling_pawn_lance = U8VAR("dangling_pawn_lance", 0x05DF),
- disadv_score = U8VAR("disadv_score", 0x0274),
- disadv_sq = function()
- local sq = mem_read_u8(0x0275)
- local s = sq_is_ok(sq) and sq_str(sq) or "NONE"
- return string.format("disadv_sq: %d (%s)", sq, s)
- end,
- effect = function()
- return effect_str(effect_player(), effect_com())
- end,
- formation = U8VAR("formation", 0x05BE),
- mate_player = U8VAR("mate_player", 0x05DD),
- move_best = function()
- local src, dst, pt, is_drop, is_promote = move_best()
- return string.format("move_best: %s", move_str(src, dst, pt, is_drop, is_promote))
- end,
- move_cand = function()
- local src, dst, pt, is_drop, is_promote = move_cand()
- return string.format("move_cand: %s", move_str(src, dst, pt, is_drop, is_promote))
- end,
- move_player = function()
- local src, dst, pt, is_drop, is_promote = move_player()
- return string.format("move_player: %s", move_str(src, dst, pt, is_drop, is_promote))
- end,
- num_dragon_player = U8VAR("num_dragon_player", 0x05E8),
- num_loose_com = U8VAR("num_loose_com", 0x0297),
- num_move2 = U8VAR("num_move2", 0x05C1),
- num_promoted_com = U8VAR("num_promoted_com", 0x0293),
- player_offer = U8VAR("player_offer", 0x05DE),
- position = function()
- return position_str(board_player(), board_com(), hand_player(), hand_com())
- end,
- progress = U8VAR("progress", 0x028E),
- root_adv_score = U8VAR("root_adv_score", 0x0280),
- root_disadv_score = U8VAR("root_disadv_score", 0x0282),
- root_rbp_com = U8VAR("root_rbp_com", 0x05EA),
- root_power_com = U8VAR("root_power_com", 0x05E4),
- root_power_player = U8VAR("root_power_player", 0x05E7),
- safety_far_com = U8VAR("safety_far_com", 0x0295),
- surround_com = U8VAR("surround_com", 0x05E5),
- threat_far_com = U8VAR("threat_far_com", 0x0296),
- threat_far_player = U8VAR("threat_far_player", 0x0299),
- threat_near_com = U8VAR("threat_near_com", 0x05EB),
- zzz_02A4 = U8VAR("$02A4", 0x02A4),
- zzz_02A6 = U8VAR("$02A6 (best $02A4)", 0x02A6),
- zzz_05E0 = U8VAR("$05E0", 0x05E0),
- zzz_05E2 = U8VAR("$05E2 (best $05E0)", 0x05E2),
- }
- local function dump(name)
- print(VARS[name]())
- end
- ----------------------------------------------------------------------
- -- hook
- ----------------------------------------------------------------------
- local HOOKS = {
- {
- addr = 0xDD07,
- func = function()
- print("==== 思考開始 ====")
- dump("num_move2")
- dump("progress")
- dump("formation")
- dump("move_player")
- print()
- dump("position")
- dump("effect")
- end,
- },
- {
- addr = 0xF00A,
- func = function()
- print("---- ルート局面評価完了 ----")
- dump("num_dragon_player")
- dump("root_rbp_com")
- dump("root_power_player")
- dump("root_power_com")
- dump("root_adv_score")
- dump("root_disadv_score")
- dump("player_offer")
- end,
- },
- {
- addr = 0xF282,
- func = function()
- print()
- dump("move_cand")
- dump("cand_score")
- dump("cand_offer")
- dump("adv_sq")
- dump("adv_score")
- dump("disadv_sq")
- dump("disadv_score")
- dump("num_promoted_com")
- dump("num_loose_com")
- dump("dangling_pawn_lance")
- dump("safety_far_com")
- dump("threat_far_player")
- dump("threat_far_com")
- dump("threat_near_com")
- dump("surround_com")
- dump("zzz_02A4")
- dump("zzz_05E0")
- print()
- end,
- },
- {
- addr = 0xF2AB,
- func = function()
- print("打ち歩詰めなので却下")
- end,
- },
- {
- addr = 0xF2C2,
- func = function()
- print("$F2C2: --$05E0")
- dump("zzz_05E0")
- end,
- },
- {
- addr = 0xF2D8,
- func = function()
- print("タダ捨てなので却下")
- end,
- },
- {
- addr = 0xF2E3,
- func = function()
- print("player_offer == 2 なので cand_score += 2")
- dump("cand_score")
- end,
- },
- {
- addr = 0xF2EE,
- func = function()
- print("垂れ歩/垂れ香あり。$05E0 += 4")
- dump("zzz_05E0")
- end,
- },
- {
- addr = 0xF31F,
- func = function()
- print("最大駒損マスがCOM玉から遠い。$05E0 -= disadv_score")
- dump("zzz_05E0")
- end,
- },
- {
- addr = 0xF674,
- func = function()
- print("---- 候補手評価完了 ----")
- dump("mate_player")
- dump("cand_score")
- dump("adv_sq")
- dump("adv_score")
- dump("disadv_sq")
- dump("disadv_score")
- dump("zzz_02A4")
- dump("zzz_05E0")
- end,
- },
- {
- addr = 0xF768,
- func = function()
- print("---- 最善手更新 ----")
- dump("move_best")
- dump("best_score")
- dump("best_adv_sq")
- dump("best_adv_score")
- dump("best_disadv_sq")
- dump("best_disadv_score")
- dump("zzz_02A6")
- dump("zzz_05E2")
- end
- },
- }
- ----------------------------------------------------------------------
- -- main
- ----------------------------------------------------------------------
- local function main()
- trace_init()
- emu.registerexit(trace_fin)
- for _, hook in ipairs(HOOKS) do
- memory.registerexec(hook.addr, hook.func)
- end
- end
- main()
Add Comment
Please, Sign In to add comment