Guest User

Untitled

a guest
Jan 16th, 2019
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.30 KB | None | 0 0
  1. --[[
  2. 内藤九段将棋秘伝 (FC) 思考トレース for FCEUX
  3.  
  4. ログはサブディレクトリ trace/ 内に出力される(予め mkdir すること)
  5. --]]
  6.  
  7. ----------------------------------------------------------------------
  8. -- util
  9. ----------------------------------------------------------------------
  10.  
  11. local function mem_read_u8(addr)
  12. return memory.readbyte(addr)
  13. end
  14.  
  15. local out = nil
  16.  
  17. local function trace_init()
  18. local path = os.date("trace/%Y%m%d-%H%M%S.log")
  19. out = io.open(path, "w")
  20. assert(out)
  21. return out
  22. end
  23.  
  24. local function trace_fin()
  25. if out then
  26. out:close()
  27. out = nil
  28. end
  29. end
  30.  
  31. local function print(s)
  32. if s ~= nil then
  33. out:write(s)
  34. end
  35. out:write("\n")
  36. end
  37.  
  38.  
  39. ----------------------------------------------------------------------
  40. -- game
  41. ----------------------------------------------------------------------
  42.  
  43. -- sq: マス目 [12,108]
  44. -- pt: 駒種 [1,15] ただし 11 は無効
  45. -- pcp: PLAYER駒 [1,15] ただし 11 は無効
  46. -- pcc: COM駒 [16,30] ただし 26 は無効
  47. -- dropp: PLAYERが駒を打つ手の移動元マス目 [213,219] ((駒種)+211)
  48. -- dropc: COMが駒を打つ手の移動元マス目 [201,207] (209-(駒種))
  49.  
  50. local function sq2xy(sq)
  51. local x = sq % 11
  52. local y = math.floor(sq / 11)
  53. return x, y
  54. end
  55.  
  56. local function xy2sq(x, y)
  57. return x + 11*y
  58. end
  59.  
  60. local function sq_is_ok(sq)
  61. local x, y = sq2xy(sq)
  62. return 1 <= x and x <= 9 and 1 <= y and y <= 9
  63. end
  64.  
  65. local function pt_is_ok(pt)
  66. return 1 <= pt and pt <= 15 and pt ~= 11
  67. end
  68.  
  69. local function pt_unpromote(pt)
  70. if 9 <= pt and pt <= 15 and pt ~= 11 then
  71. pt = pt - 7
  72. end
  73. return pt
  74. end
  75.  
  76. local function pcp2pt(pcp)
  77. return pcp
  78. end
  79.  
  80. local function pcp_is_ok(pcp)
  81. return pt_is_ok(pcp2pt(pcp))
  82. end
  83.  
  84. local function pcc2pt(pcc)
  85. return pcc - 15
  86. end
  87.  
  88. local function pcc_is_ok(pcc)
  89. return pt_is_ok(pcc2pt(pcc))
  90. end
  91.  
  92. local function dropp_is_ok(dropp)
  93. return 213 <= dropp and dropp <= 219
  94. end
  95.  
  96. local function dropp2pt(dropp)
  97. return dropp - 211
  98. end
  99.  
  100. local function dropc_is_ok(dropc)
  101. return 201 <= dropc and dropc <= 207
  102. end
  103.  
  104. local function dropc2pt(dropc)
  105. return 209 - dropc
  106. end
  107.  
  108. local function board_player()
  109. local board = {}
  110. for i = 1, 121 do
  111. board[i] = mem_read_u8(0x03A9 + i-1)
  112. end
  113. return board
  114. end
  115.  
  116. local function board_com()
  117. local board = {}
  118. for i = 1, 121 do
  119. board[i] = mem_read_u8(0x049B + i-1)
  120. end
  121. return board
  122. end
  123.  
  124. local function hand_player()
  125. local hand = {}
  126. for i = 1, 7 do
  127. hand[i] = mem_read_u8(0x058D + i-1)
  128. end
  129. return hand
  130. end
  131.  
  132. local function hand_com()
  133. local hand = {}
  134. for i = 1, 7 do
  135. hand[i] = mem_read_u8(0x0594 + i-1)
  136. end
  137. return hand
  138. end
  139.  
  140. local function effect_player()
  141. local eff = {}
  142. for i = 1, 121 do
  143. eff[i] = mem_read_u8(0x0422 + i-1)
  144. end
  145. return eff
  146. end
  147.  
  148. local function effect_com()
  149. local eff = {}
  150. for i = 1, 121 do
  151. eff[i] = mem_read_u8(0x0514 + i-1)
  152. end
  153. return eff
  154. end
  155.  
  156. local function move_player()
  157. local is_promote = mem_read_u8(0x05BF) ~= 0
  158.  
  159. local src = mem_read_u8(0x05A2)
  160. local dst = mem_read_u8(0x05A1)
  161.  
  162. local board = board_player()
  163. local pt = pcp2pt(board[dst+1])
  164. if is_promote then
  165. pt = pt_unpromote(pt)
  166. end
  167.  
  168. local is_drop = dropp_is_ok(src)
  169. if is_drop then
  170. assert(dropp2pt(src) == pt)
  171. assert(not is_promote)
  172. end
  173.  
  174. return src, dst, pt, is_drop, is_promote
  175. end
  176.  
  177. local function move_cand()
  178. local is_promote = mem_read_u8(0x0279) ~= 0
  179.  
  180. local src = mem_read_u8(0x0277)
  181. local dst = mem_read_u8(0x0276)
  182. local pt = pcc2pt(mem_read_u8(0x5F))
  183.  
  184. local is_drop = dropc_is_ok(src)
  185. if is_drop then
  186. assert(dropc2pt(src) == pt)
  187. assert(not is_promote)
  188. end
  189.  
  190. return src, dst, pt, is_drop, is_promote
  191. end
  192.  
  193. local function move_best()
  194. local is_promote = mem_read_u8(0x028C) ~= 0
  195.  
  196. local src = mem_read_u8(0x0285)
  197. local dst = mem_read_u8(0x0284)
  198.  
  199. local board = board_com()
  200. local pt = pcc2pt(board[dst+1])
  201. if is_promote then
  202. pt = pt_unpromote(pt)
  203. end
  204.  
  205. local is_drop = dropc_is_ok(src)
  206. if is_drop then
  207. assert(dropc2pt(src) == pt)
  208. assert(not is_promote)
  209. end
  210.  
  211. return src, dst, pt, is_drop, is_promote
  212. end
  213.  
  214. local KANDIGIT = {
  215. "一", "二", "三", "四", "五", "六", "七", "八", "九",
  216. }
  217.  
  218. local PT_NAME = {
  219. "玉",
  220. "飛",
  221. "角",
  222. "金",
  223. "銀",
  224. "桂",
  225. "香",
  226. "歩",
  227. "竜",
  228. "馬",
  229. nil,
  230. "全",
  231. "圭",
  232. "杏",
  233. "と",
  234. }
  235.  
  236. local function sq_str(sq)
  237. local file, rank = sq2xy(sq)
  238. file = 10 - file -- 将棋の表記法に合わせる
  239. return string.format("%d%d", file, rank)
  240. end
  241.  
  242. local function hand_str(hand)
  243. local res = ""
  244. for i,n in ipairs(hand) do
  245. local pt = i + 1
  246. if n > 0 then
  247. res = res .. string.format("%s%d ", PT_NAME[pt], n)
  248. end
  249. end
  250. return res
  251. end
  252.  
  253. local function position_str(boardp, boardc, handp, handc)
  254. local res = ""
  255. local append = function(s)
  256. res = res .. s .. "\n"
  257. end
  258.  
  259. append("▽持駒: " .. hand_str(handc))
  260. append(" 9 8 7 6 5 4 3 2 1")
  261. append("┌──┬──┬──┬──┬──┬──┬──┬──┬──┐")
  262.  
  263. for y = 1, 9 do
  264. local line = "│"
  265. for x = 1, 9 do
  266. local sq = xy2sq(x,y)
  267. local pcp = boardp[sq+1]
  268. local pcc = boardc[sq+1]
  269. if pcp_is_ok(pcp) and pcc == 0 then
  270. line = line .. "▲" .. PT_NAME[pcp2pt(pcp)]
  271. elseif pcp == 0 and pcc_is_ok(pcc) then
  272. line = line .. "▽" .. PT_NAME[pcc2pt(pcc)]
  273. elseif pcp == 0 and pcc == 0 then
  274. line = line .. "__"
  275. else
  276. assert(false)
  277. end
  278. line = line .. "│"
  279. end
  280. line = line .. KANDIGIT[y]
  281. append(line)
  282.  
  283. if y ~= 9 then
  284. append("├──┼──┼──┼──┼──┼──┼──┼──┼──┤")
  285. end
  286. end
  287.  
  288. append("└──┴──┴──┴──┴──┴──┴──┴──┴──┘")
  289. append("▲持駒: " .. hand_str(handp))
  290.  
  291. return res
  292. end
  293.  
  294. local function effect_str(effp, effc)
  295. local res = ""
  296. local append = function(s)
  297. res = res .. s .. "\n"
  298. end
  299.  
  300. append(" 9 8 7 6 5 4 3 2 1")
  301. append("┌──┬──┬──┬──┬──┬──┬──┬──┬──┐")
  302.  
  303. for y = 1, 9 do
  304. local line = "│"
  305. for x = 1, 9 do
  306. local sq = xy2sq(x,y)
  307. line = line .. string.format("%d,%d ", effp[sq+1], effc[sq+1])
  308. line = line .. "│"
  309. end
  310. line = line .. KANDIGIT[y]
  311. append(line)
  312.  
  313. if y ~= 9 then
  314. append("├──┼──┼──┼──┼──┼──┼──┼──┼──┤")
  315. end
  316. end
  317.  
  318. append("└──┴──┴──┴──┴──┴──┴──┴──┴──┘")
  319.  
  320. return res
  321. end
  322.  
  323. local function move_str(src, dst, pt, is_drop, is_promote)
  324. local dst_file, dst_rank = sq2xy(dst)
  325. dst_file = 10 - dst_file -- 将棋の表記法に合わせる
  326.  
  327. if is_drop then
  328. return string.format("%d%d%s打", dst_file, dst_rank, PT_NAME[pt])
  329. else
  330. local src_file, src_rank = sq2xy(src)
  331. src_file = 10 - src_file
  332. local spromo = is_promote and "成" or ""
  333. return string.format("%d%d%s%s (%d%d)",
  334. dst_file, dst_rank, PT_NAME[pt], spromo,
  335. src_file, src_rank)
  336. end
  337. end
  338.  
  339. local function U8VAR(name, addr)
  340. return function()
  341. return string.format("%s: %d", name, mem_read_u8(addr))
  342. end
  343. end
  344.  
  345. local VARS = {
  346. adv_score = U8VAR("adv_score", 0x0272),
  347. adv_sq = function()
  348. local sq = mem_read_u8(0x0273)
  349. local s = sq_is_ok(sq) and sq_str(sq) or "NONE"
  350. return string.format("adv_sq: %d (%s)", sq, s)
  351. end,
  352. best_adv_score = U8VAR("best_adv_score", 0x0286),
  353. best_adv_sq = function()
  354. local sq = mem_read_u8(0x0287)
  355. local s = sq_is_ok(sq) and sq_str(sq) or "NONE"
  356. return string.format("best_adv_sq: %d (%s)", sq, s)
  357. end,
  358. best_disadv_score = U8VAR("best_disadv_score", 0x0288),
  359. best_disadv_sq = function()
  360. local sq = mem_read_u8(0x0289)
  361. local s = sq_is_ok(sq) and sq_str(sq) or "NONE"
  362. return string.format("best_disadv_sq: %d (%s)", sq, s)
  363. end,
  364. best_score = U8VAR("best_score", 0x028A),
  365. cand_offer = U8VAR("cand_offer", 0x027C),
  366. cand_score = U8VAR("cand_score", 0x0278),
  367. dangling_pawn_lance = U8VAR("dangling_pawn_lance", 0x05DF),
  368. disadv_score = U8VAR("disadv_score", 0x0274),
  369. disadv_sq = function()
  370. local sq = mem_read_u8(0x0275)
  371. local s = sq_is_ok(sq) and sq_str(sq) or "NONE"
  372. return string.format("disadv_sq: %d (%s)", sq, s)
  373. end,
  374. effect = function()
  375. return effect_str(effect_player(), effect_com())
  376. end,
  377. formation = U8VAR("formation", 0x05BE),
  378. mate_player = U8VAR("mate_player", 0x05DD),
  379. move_best = function()
  380. local src, dst, pt, is_drop, is_promote = move_best()
  381. return string.format("move_best: %s", move_str(src, dst, pt, is_drop, is_promote))
  382. end,
  383. move_cand = function()
  384. local src, dst, pt, is_drop, is_promote = move_cand()
  385. return string.format("move_cand: %s", move_str(src, dst, pt, is_drop, is_promote))
  386. end,
  387. move_player = function()
  388. local src, dst, pt, is_drop, is_promote = move_player()
  389. return string.format("move_player: %s", move_str(src, dst, pt, is_drop, is_promote))
  390. end,
  391. num_dragon_player = U8VAR("num_dragon_player", 0x05E8),
  392. num_loose_com = U8VAR("num_loose_com", 0x0297),
  393. num_move2 = U8VAR("num_move2", 0x05C1),
  394. num_promoted_com = U8VAR("num_promoted_com", 0x0293),
  395. player_offer = U8VAR("player_offer", 0x05DE),
  396. position = function()
  397. return position_str(board_player(), board_com(), hand_player(), hand_com())
  398. end,
  399. progress = U8VAR("progress", 0x028E),
  400. root_adv_score = U8VAR("root_adv_score", 0x0280),
  401. root_disadv_score = U8VAR("root_disadv_score", 0x0282),
  402. root_rbp_com = U8VAR("root_rbp_com", 0x05EA),
  403. root_power_com = U8VAR("root_power_com", 0x05E4),
  404. root_power_player = U8VAR("root_power_player", 0x05E7),
  405. safety_far_com = U8VAR("safety_far_com", 0x0295),
  406. surround_com = U8VAR("surround_com", 0x05E5),
  407. threat_far_com = U8VAR("threat_far_com", 0x0296),
  408. threat_far_player = U8VAR("threat_far_player", 0x0299),
  409. threat_near_com = U8VAR("threat_near_com", 0x05EB),
  410. zzz_02A4 = U8VAR("$02A4", 0x02A4),
  411. zzz_02A6 = U8VAR("$02A6 (best $02A4)", 0x02A6),
  412. zzz_05E0 = U8VAR("$05E0", 0x05E0),
  413. zzz_05E2 = U8VAR("$05E2 (best $05E0)", 0x05E2),
  414. }
  415.  
  416. local function dump(name)
  417. print(VARS[name]())
  418. end
  419.  
  420.  
  421. ----------------------------------------------------------------------
  422. -- hook
  423. ----------------------------------------------------------------------
  424.  
  425. local HOOKS = {
  426. {
  427. addr = 0xDD07,
  428. func = function()
  429. print("==== 思考開始 ====")
  430.  
  431. dump("num_move2")
  432. dump("progress")
  433. dump("formation")
  434. dump("move_player")
  435. print()
  436.  
  437. dump("position")
  438. dump("effect")
  439. end,
  440. },
  441. {
  442. addr = 0xF00A,
  443. func = function()
  444. print("---- ルート局面評価完了 ----")
  445.  
  446. dump("num_dragon_player")
  447. dump("root_rbp_com")
  448. dump("root_power_player")
  449. dump("root_power_com")
  450. dump("root_adv_score")
  451. dump("root_disadv_score")
  452. dump("player_offer")
  453. end,
  454. },
  455. {
  456. addr = 0xF282,
  457. func = function()
  458. print()
  459. dump("move_cand")
  460.  
  461. dump("cand_score")
  462. dump("cand_offer")
  463.  
  464. dump("adv_sq")
  465. dump("adv_score")
  466. dump("disadv_sq")
  467. dump("disadv_score")
  468.  
  469. dump("num_promoted_com")
  470. dump("num_loose_com")
  471. dump("dangling_pawn_lance")
  472.  
  473. dump("safety_far_com")
  474. dump("threat_far_player")
  475. dump("threat_far_com")
  476. dump("threat_near_com")
  477. dump("surround_com")
  478.  
  479. dump("zzz_02A4")
  480. dump("zzz_05E0")
  481.  
  482. print()
  483. end,
  484. },
  485. {
  486. addr = 0xF2AB,
  487. func = function()
  488. print("打ち歩詰めなので却下")
  489. end,
  490. },
  491. {
  492. addr = 0xF2C2,
  493. func = function()
  494. print("$F2C2: --$05E0")
  495. dump("zzz_05E0")
  496. end,
  497. },
  498. {
  499. addr = 0xF2D8,
  500. func = function()
  501. print("タダ捨てなので却下")
  502. end,
  503. },
  504. {
  505. addr = 0xF2E3,
  506. func = function()
  507. print("player_offer == 2 なので cand_score += 2")
  508. dump("cand_score")
  509. end,
  510. },
  511. {
  512. addr = 0xF2EE,
  513. func = function()
  514. print("垂れ歩/垂れ香あり。$05E0 += 4")
  515. dump("zzz_05E0")
  516. end,
  517. },
  518. {
  519. addr = 0xF31F,
  520. func = function()
  521. print("最大駒損マスがCOM玉から遠い。$05E0 -= disadv_score")
  522. dump("zzz_05E0")
  523. end,
  524. },
  525. {
  526. addr = 0xF674,
  527. func = function()
  528. print("---- 候補手評価完了 ----")
  529.  
  530. dump("mate_player")
  531. dump("cand_score")
  532. dump("adv_sq")
  533. dump("adv_score")
  534. dump("disadv_sq")
  535. dump("disadv_score")
  536. dump("zzz_02A4")
  537. dump("zzz_05E0")
  538. end,
  539. },
  540. {
  541. addr = 0xF768,
  542. func = function()
  543. print("---- 最善手更新 ----")
  544. dump("move_best")
  545.  
  546. dump("best_score")
  547. dump("best_adv_sq")
  548. dump("best_adv_score")
  549. dump("best_disadv_sq")
  550. dump("best_disadv_score")
  551. dump("zzz_02A6")
  552. dump("zzz_05E2")
  553. end
  554. },
  555. }
  556.  
  557. ----------------------------------------------------------------------
  558. -- main
  559. ----------------------------------------------------------------------
  560.  
  561. local function main()
  562. trace_init()
  563. emu.registerexit(trace_fin)
  564.  
  565. for _, hook in ipairs(HOOKS) do
  566. memory.registerexec(hook.addr, hook.func)
  567. end
  568. end
  569.  
  570. main()
Add Comment
Please, Sign In to add comment