Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

C++用将棋ライブラリ "OpenShogiLib"の紹介

4,012 views

Published on

2013.7.13 CLR/H & Sapporo.cpp 勉強会で発表

Published in: Technology
  • Be the first to comment

C++用将棋ライブラリ "OpenShogiLib"の紹介

  1. 1. C++用将棋ライブラリ "OpenShogiLib"の紹介 H.Hiro (Sapporo.cpp) http://hhiro.net/about/ Twitter: @h_hiro_ 2013.7.13 CLR/H & Sapporo.cpp 勉強会
  2. 2. 自己紹介
  3. 3. H.Hiro • 大学院生 • 現在は就活と研究が 同時並行なので忙しめです • こんなアイコン 使ってます→
  4. 4. H.Hiro • Sapporo.cpp • Ruby札幌 • 数学勉強会@札幌 : いろいろやってます
  5. 5. 部分文字列の取得を 効率よく!楽に! ~fundoshi.hppの紹介と 今後の予定~ Photo by KAIZUKA Creative Commons BY-NC-SA 2.0 http://www.flickr.com/photos/kaizuka/386511394/ http://www.slideshare.net/maraigue/ 20121117-clrhc-fundoshihpp 【前回の発表(2012.11.17)】
  6. 6. 宣伝
  7. 7. http://www.ospn.jp/osc2013-do/ • 今年は9月なのでお間違いなく! • 場所もコンベンションセンターなので お間違いなく! • ブース・セミナー申込締切は 7月22日(月)です
  8. 8. よろしく お願いします
  9. 9. 本題
  10. 10. C++用将棋ライブラリ "OpenShogiLib"の紹介 H.Hiro (Sapporo.cpp) http://hhiro.net/about/ Twitter: @h_hiro_
  11. 11. ということで これから将棋の話を するわけですが
  12. 12. 第2回電王戦 (プロ棋士とコンピュータの五番勝負) http://ex.nicovideo.jp/denousen2013/
  13. 13. コンピュータ側の第5局を 戦った「GPS将棋」 http://gps.tanaka.ecc.u-tokyo.ac.jp/gpsshogi/
  14. 14. このうち、汎用的な 部分を切り出したのが OpenShogiLibです
  15. 15. さて
  16. 16. コンピュータに 将棋を扱わせるには 何が必要か
  17. 17. [質問] 将棋をよく/たまに やるよ!という方
  18. 18. [質問] 将棋はあまり しないけど 何となくどんな ゲームかは分かる方
  19. 19. 今日必要な前提知識(1/3) 将棋は、二人が順番に 駒を動かすゲームです 駒の動かし方 の表を別途 配布して おります
  20. 20. 今日必要な前提知識(1/3) 将棋は、二人が順番に 駒を動かすゲームです 取った駒は 盤上に打つ ことができます
  21. 21. 今日必要な前提知識(2/3) 駒にはそれぞれ動きが 決められています
  22. 22. 今日必要な前提知識(3/3) 勝利条件は、相手の玉(王) を取ることです 右図のように、実際に 玉を取らなくても、次に 取れることが確定すれば 勝ち(詰み)。
  23. 23. コンピュータ上で 将棋を扱うのに 必要そうなデータ構造
  24. 24. •将棋盤(81マス) •将棋駒(40個) •駒が動ける場所
  25. 25. •将棋盤(81マス) →9×9の2次元配列? •将棋駒(40個) →40個の配列? •駒が動ける場所 →8種をハードコーディング →ルール上動けない場所
  26. 26. OpenShogiLibが これらを全部 提供してくれます
  27. 27. 導入方法 & 簡単な利用方法
  28. 28. 導入方法 • # apt-get install libosl-dev •ソースコードから導入の 場合、boostが必要 •Windowsでは試してません もしかしたら面倒かも
  29. 29. // http://blog.livedoor.jp/maraigue/archives/1711816.html // SimpleStateは盤面のみを保持するクラス state::SimpleState sstate(osl::HIRATE); // NumEffectStateは盤面+駒の動きを扱えるクラス state::NumEffectState nstate(sstate); Move move; // 先手(BLACK)の(7,7)にあるPAWN(歩兵)を、 // (7,6)という何もないマス(PTYPE_EMPTY)に動かす move = Move(Square(7,7), Square(7,6), PAWN, PTYPE_EMPTY, false, BLACK); if(nstate.isValidMove(move)){ nstate.makeMove(move); }
  30. 30. // http://blog.livedoor.jp/maraigue/archives/1711816.html // SimpleStateは盤面のみを保持するクラス state::SimpleState sstate(osl::HIRATE); // NumEffectStateは盤面+駒の動きを扱えるクラス state::NumEffectState nstate(sstate); Move move; // 先手(BLACK)の(7,7)にあるPAWN(歩兵)を、 // (7,6)という何もないマス(PTYPE_EMPTY)に動かす move = Move(Square(7,7), Square(7,6), PAWN, PTYPE_EMPTY, false, BLACK); if(nstate.isValidMove(move)){ nstate.makeMove(move); }
  31. 31. // http://blog.livedoor.jp/maraigue/archives/1711816.html // SimpleStateは盤面のみを保持するクラス state::SimpleState sstate(osl::HIRATE); // NumEffectStateは盤面+駒の動きを扱えるクラス state::NumEffectState nstate(sstate); Move move; // 先手(BLACK)の(7,7)にあるPAWN(歩兵)を、 // (7,6)という何もないマス(PTYPE_EMPTY)に動かす move = Move(Square(7,7), Square(7,6), PAWN, PTYPE_EMPTY, false, BLACK); if(nstate.isValidMove(move)){ nstate.makeMove(move); }
  32. 32. これで、とりあえず 将棋が指せる ことはわかった
  33. 33. では、もう少し 凝ったことを してみよう
  34. 34. 詰将棋
  35. 35. こんなのが詰将棋です
  36. 36. こんなのが詰将棋です
  37. 37. 詰将棋の目的: 王手のみを続けて 相手の玉を詰める
  38. 38. まずは人手で解いてみる
  39. 39. 人手だと 何となく 「この手が正解っぽい」 と分かるけど
  40. 40. コンピュータには どう解かせる?
  41. 41. 詰将棋の目的: 王手のみを続けて 相手の玉を詰める
  42. 42. コンピュータには 王手になる手を 総当りで指させる
  43. 43. コンピュータには 王手になる手を 総当りで指させる (自分の立場)
  44. 44. コンピュータには 王手を回避する手を 総当りで指させる (相手の立場)
  45. 45. • 詰みとなる条件 相手がどう指そうとも 自分の手によっては 王手を回避できなくなる • 詰まない条件 自分がどう指そうとも 相手の手によっては 王手をかけられなくなる
  46. 46. ここから王手になる手は?
  47. 47. 実は4通りある
  48. 48. 先に進めると 手の数はすごいことになる
  49. 49. コンピュータに 全部試させればよい // [駒を動かして王手] ActionTryMove acm(mt_new, nstate, depth, max_depth); for(int i = 0; i < osl::Piece::SIZE; ++i){ p = nstate.pieceOf(i); if(p.isOnBoardByOwner(osl::BLACK)){ // 盤上にある先手の駒の場合 nstate.forEachEffectOfPiece<ActionTryMove>(p, acm) } } valid_moves += acm.valid_moves();
  50. 50. コンピュータに 全部試させればよい // [駒を動かして王手] ActionTryMove acm(mt_new, nstate, depth, max_depth); for(int i = 0; i < osl::Piece::SIZE; ++i){ p = nstate.pieceOf(i); if(p.isOnBoardByOwner(osl::BLACK)){ // 盤上にある先手の駒の場合 nstate.forEachEffectOfPiece<ActionTryMove>(p, acm) } } valid_moves += acm.valid_moves(); 将棋で用いる全部の駒 (40個)についてループ
  51. 51. コンピュータに 全部試させればよい // [駒を動かして王手] ActionTryMove acm(mt_new, nstate, depth, max_depth); for(int i = 0; i < osl::Piece::SIZE; ++i){ p = nstate.pieceOf(i); if(p.isOnBoardByOwner(osl::BLACK)){ // 盤上にある先手の駒の場合 nstate.forEachEffectOfPiece<ActionTryMove>(p, acm) } } valid_moves += acm.valid_moves(); 動かしてみる
  52. 52. コンピュータに 全部試させればよい // class ActionTryMove の中身 template<osl::Player pl> void doAction (const osl::Piece & pc, const osl::Square & sq){ /*(中略)*/ if(osl::isPiece(pc.ptype()) && osl::canPromote(pc.ptype())){ // 成れる駒ならば、成ってみる if(recursive_search(/*(中略)*/) != -2){ ++valid_moves_; } } // 成らない場合 if(recursive_search(/*(中略)*/) != -2){ ++valid_moves_; } }
  53. 53. コンピュータに 全部試させればよい // class ActionTryMove の中身 template<osl::Player pl> void doAction (const osl::Piece & pc, const osl::Square & sq){ /*(中略)*/ if(osl::isPiece(pc.ptype()) && osl::canPromote(pc.ptype())){ // 成れる駒ならば、成ってみる if(recursive_search(/*(中略)*/) != -2){ ++valid_moves_; } } // 成らない場合 if(recursive_search(/*(中略)*/) != -2){ ++valid_moves_; } } 成れるかどうか判定し 成らないケースとともに試す
  54. 54. コンピュータに 全部試させればよい if(nstate.isValidMove(*p_move)){ // 動かせるか確認 nstate.makeMove(*p_move); // 動かす // (先手が指した結果の場合)後手玉が王手になっている // (後手が指した結果の場合)後手玉が王手になっていない if(logical_xor(depth % 2 == 1, nstate.inCheck(osl::WHITE))){ mt_new = MoveTree::createNewPtr(*p_move); mt->children.push_back(mt_new); }else{ return -2; } }else{ return -2; // 動かせない場合 }
  55. 55. コンピュータに 全部試させればよい if(nstate.isValidMove(*p_move)){ // 動かせるか確認 nstate.makeMove(*p_move); // 動かす // (先手が指した結果の場合)後手玉が王手になっている // (後手が指した結果の場合)後手玉が王手になっていない if(logical_xor(depth % 2 == 1, nstate.inCheck(osl::WHITE))){ mt_new = MoveTree::createNewPtr(*p_move); mt->children.push_back(mt_new); }else{ return -2; } }else{ return -2; // 動かせない場合 } まず、将棋のルールとして 動けるかをチェック
  56. 56. コンピュータに 全部試させればよい if(nstate.isValidMove(*p_move)){ // 動かせるか確認 nstate.makeMove(*p_move); // 動かす // (先手が指した結果の場合)後手玉が王手になっている // (後手が指した結果の場合)後手玉が王手になっていない if(logical_xor(depth % 2 == 1, nstate.inCheck(osl::WHITE))){ mt_new = MoveTree::createNewPtr(*p_move); mt->children.push_back(mt_new); }else{ return -2; } }else{ return -2; // 動かせない場合 } 続いて、王手をかける/ 回避するという条件をチェック
  57. 57. 実際に 動かしてみる https://github.com/maraigue/ clrhsapporocpp-20130713
  58. 58. 補足
  59. 59. •詰将棋を解くだけなら OpenShogiLibに最初から コードがある •でも、それ以上のことを したかったので 自前で書いた
  60. 60. 詰将棋制作支援の プログラムが欲しかった •回答が一意に定まる必要 •余計な駒を使わない :
  61. 61. •そういう機能を持つ ソフトもあるのだが 有料なうえに絶版 •なので自分で作りたかった
  62. 62. おわりに
  63. 63. 将棋は 自身で遊ぶだけでなくて コンピュータ的にも 奥が深いです
  64. 64. OpenShogiLibは ドキュメントがあまり整備 されてないので Tipsをブログとかに書くと 喜ばれるかも?
  65. 65. ありがとう ございました

×