C++用将棋ライブラリ"OpenShogiLib"の紹介
-
Upload
hiro-h -
Category
Technology
-
view
1.868 -
download
2
description
Transcript of C++用将棋ライブラリ"OpenShogiLib"の紹介
C++用将棋ライブラリ"OpenShogiLib"の紹介 H.Hiro (Sapporo.cpp)
http://hhiro.net/about/Twitter: @h_hiro_
2013.7.13 CLR/H & Sapporo.cpp 勉強会
自己紹介
H.Hiro•大学院生•現在は就活と研究が同時並行なので忙しめです•こんなアイコン使ってます→
H.Hiro• Sapporo.cpp• Ruby札幌•数学勉強会@札幌 :いろいろやってます
部分文字列の取得を
効率よく!楽に!~ fundoshi.hppの紹介と
今後の予定~
Photo by KAIZUKACreative Commons BY-NC-SA 2.0
http://www.flickr.com/photos/kaizuka/386511394/
http://www.slideshare.net/maraigue/20121117-clrhc-fundoshihpp
【前回の発表 (2012.11.17)】
宣伝
http://www.ospn.jp/osc2013-do/• 今年は 9月なのでお間違いなく!• 場所もコンベンションセンターなのでお間違いなく!• ブース・セミナー申込締切は
7月 22日(月)です
よろしくお願いします
本題
C++用将棋ライブラリ"OpenShogiLib"の紹介 H.Hiro (Sapporo.cpp)
http://hhiro.net/about/Twitter: @h_hiro_
ということでこれから将棋の話をするわけですが
第 2回電王戦(プロ棋士とコンピュータの五番勝
負 )http://ex.nicovideo.jp/denousen2013/
コンピュータ側の第 5局を
戦った「 GPS将棋」http://gps.tanaka.ecc.u-tokyo.ac.jp/gpsshogi/
このうち、汎用的な部分を切り出したのがOpenShogiLibです
さて
コンピュータに将棋を扱わせるに
は何が必要か
[質問 ]将棋をよく /たま
にやるよ!という方
[質問 ]将棋はあまりしないけど
何となくどんなゲームかは分かる
方
今日必要な前提知識 (1/3)将棋は、二人が順番に駒を動かすゲームです
駒の動かし方の表を別途配布しております
今日必要な前提知識 (1/3)将棋は、二人が順番に駒を動かすゲームです
取った駒は盤上に打つことができます
今日必要な前提知識 (2/3)駒にはそれぞれ動きが決められています
今日必要な前提知識 (3/3)勝利条件は、相手の玉(王 )を取ることです
右図のように、実際に玉を取らなくても、次に取れることが確定すれば勝ち (詰み )。
コンピュータ上で将棋を扱うのに必要そうなデータ
構造
•将棋盤 (81マス )•将棋駒 (40個 )•駒が動ける場所
•将棋盤 (81マス )→9×9の 2次元配列?•将棋駒 (40個 )→40個の配列?•駒が動ける場所→ 8種をハードコーディング→ルール上動けない場所
OpenShogiLibがこれらを全部
提供してくれます
導入方法&
簡単な利用方法
導入方法• # apt-get install libosl-dev
•ソースコードから導入の場合、 boostが必要•Windowsでは試してませんもしかしたら面倒かも
// 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);}
// 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);}
// 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);}
これで、とりあえず
将棋が指せることはわかった
では、もう少し凝ったことをしてみよう
詰将棋
こんなのが詰将棋です
こんなのが詰将棋です
詰将棋の目的 :王手のみを続けて相手の玉を詰める
まずは人手で解いてみる
人手だと何となく
「この手が正解っぽい」
と分かるけど
コンピュータにはどう解かせる?
詰将棋の目的 :王手のみを続けて相手の玉を詰める
コンピュータには王手になる手を総当りで指させる
コンピュータには王手になる手を総当りで指させる
(自分の立場 )
コンピュータには王手を回避する手
を総当りで指させる
(相手の立場 )
•詰みとなる条件相手がどう指そうとも自分の手によっては王手を回避できなくなる•詰まない条件自分がどう指そうとも相手の手によっては王手をかけられなくなる
ここから王手になる手は?
実は 4通りある
先に進めると手の数はすごいことになる
コンピュータに全部試させればよい
// [駒を動かして王手 ]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();
コンピュータに全部試させればよい
// [駒を動かして王手 ]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個 )についてループ
コンピュータに全部試させればよい
// [駒を動かして王手 ]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();
動かしてみる
コンピュータに全部試させればよい
// 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_; }}
コンピュータに全部試させればよい
// 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_; }}
成れるかどうか判定し成らないケースとともに試す
コンピュータに全部試させればよい
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; // 動かせない場合}
コンピュータに全部試させればよい
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; // 動かせない場合}
まず、将棋のルールとして動けるかをチェック
コンピュータに全部試させればよい
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; // 動かせない場合}
続いて、王手をかける /回避するという条件をチェック
実際に動かしてみる
https://github.com/maraigue/clrhsapporocpp-20130713
補足
•詰将棋を解くだけならOpenShogiLibに最初からコードがある•でも、それ以上のことをしたかったので自前で書いた
詰将棋制作支援のプログラムが欲しかった•回答が一意に定まる必要•余計な駒を使わない:
•そういう機能を持つソフトもあるのだが有料なうえに絶版•なので自分で作りたかった
おわりに
将棋は自身で遊ぶだけでなくてコンピュータ的にも奥が深いです
OpenShogiLibはドキュメントがあまり整
備されてないので
Tipsをブログとかに書くと
喜ばれるかも?
ありがとうございました