enterKing.cc
Go to the documentation of this file.
00001 /* enterKing.cc
00002  */
00003 #include "osl/enter_king/enterKing.h"
00004 
00005 bool osl::enter_king::EnterKing::canDeclareWin(const NumEffectState& state)
00006 {
00007   if (state.turn() == BLACK)
00008     return canDeclareWin<BLACK>(state);
00009   else
00010     return canDeclareWin<WHITE>(state);
00011 }
00012 
00013 template <osl::Player Turn>
00014 bool
00015 osl::enter_king::EnterKing::canDeclareWin(const NumEffectState& state)
00016 {
00017   //手番, 持時間は省略
00018   assert(Turn == state.turn());
00019   const Square myKingSquare
00020     = state.kingSquare(Turn);
00021 
00022   //王手がかかっていないか
00023   if ( state.hasEffectAt(alt(Turn), myKingSquare) )
00024     return false;
00025 
00026   //自玉が敵陣にいるか
00027   //先手なら1~3
00028   //後手なら7~9
00029   const int y = myKingSquare.y();
00030   const int enemyCampMin = (Turn==BLACK) ? 1 : 7;
00031   const int enemyCampMax = enemyCampMin + 2;
00032 
00033   if( (y < enemyCampMin) || (y > enemyCampMax) )
00034     return false;
00035 
00036   // 敵陣に自分の駒が10枚以上 (自玉を除いて) あるか
00037   // 駒の点数を勘定する.  (対象: 敵陣の駒 + 持駒)
00038   // 大駒を5点として, 先手は28点, 後手なら27点必要
00039   int countPiece = 0;
00040   int onEnemyCamp = -1; // 自玉の分を予め引いておく
00041 
00042   for (int i = enemyCampMin; i <= enemyCampMax; i++)
00043     for (int j=1; j<=9; j++){
00044       Piece pieceOnEnemyCamp = state.pieceOnBoard(Square(j,i));
00045       if (pieceOnEnemyCamp.isOnBoardByOwner<Turn>()) {
00046         ++countPiece;
00047         onEnemyCamp += 1 + 4 * isMajor(pieceOnEnemyCamp.ptype());
00048       }
00049     }
00050 
00051   if (countPiece < 11)
00052     return false;
00053 
00054   int onStand =
00055     5 * state.countPiecesOnStand<ROOK>(Turn)
00056     + 5 * state.countPiecesOnStand<BISHOP>(Turn)
00057     + state.countPiecesOnStand<GOLD>(Turn)
00058     + state.countPiecesOnStand<SILVER>(Turn)
00059     + state.countPiecesOnStand<KNIGHT>(Turn)
00060     + state.countPiecesOnStand<LANCE>(Turn)
00061     + state.countPiecesOnStand<PAWN>(Turn);
00062 
00063   if ( onEnemyCamp + onStand < 27 + (Turn==BLACK) )
00064     return false;
00065 
00066   return true;
00067 }
00068 
00069 bool osl::enter_king::EnterKing::canDeclareWin(const NumEffectState& state, int &distance)
00070 {
00071   if (state.turn() == BLACK)
00072     return canDeclareWin<BLACK>(state, distance);
00073   else
00074     return canDeclareWin<WHITE>(state, distance);
00075 }
00076 
00077 template <osl::Player Turn>
00078 bool
00079 osl::enter_king::EnterKing::canDeclareWin(const NumEffectState& state, int &drops)
00080 {
00081   // 宣言勝ちの条件を
00082   //「敵陣に(自玉を除いて)10枚以上いる」
00083   // 以外満たしている時に
00084   // 敵陣にあと何枚駒を打てば良いかをdrops で返す
00085   // 他の条件を満たしていない場合何枚打っても勝てないので41を返す
00086   
00087   //手番, 持時間は省略
00088   assert(Turn == state.turn());
00089   const Square myKingSquare
00090     = state.kingSquare(Turn);
00091   drops = 41;
00092 
00093   //王手がかかっていないか
00094   if ( state.hasEffectAt(alt(Turn), myKingSquare) )
00095     return false;
00096 
00097   //自玉が敵陣にいるか
00098   //先手なら1~3
00099   //後手なら7~9
00100   const int y = myKingSquare.y();
00101   const int enemyCampMin = (Turn==BLACK) ? 1 : 7;
00102   const int enemyCampMax = enemyCampMin + 2;
00103 
00104   if( (y < enemyCampMin) || (y > enemyCampMax) )
00105     return false;
00106 
00107   // 敵陣に自分の駒が10枚以上 (自玉を除いて) あるか
00108   // 駒の点数を勘定する.  (対象: 敵陣の駒 + 持駒)
00109   // 大駒を5点として, 先手は28点, 後手なら27点必要
00110   int countPiece = 0;
00111   int onEnemyCamp = -1; // 自玉の分を予め引いておく
00112 
00113   for (int i = enemyCampMin; i <= enemyCampMax; i++)
00114     for (int j=1; j<=9; j++){
00115       Piece pieceOnEnemyCamp = state.pieceOnBoard(Square(j,i));
00116       if (pieceOnEnemyCamp.isOnBoardByOwner<Turn>()) {
00117         ++countPiece;
00118         onEnemyCamp += 1 + 4 * isMajor(pieceOnEnemyCamp.ptype());
00119       }
00120     }
00121 
00122   int onStand =
00123     5 * state.countPiecesOnStand<ROOK>(Turn)
00124     + 5 * state.countPiecesOnStand<BISHOP>(Turn)
00125     + state.countPiecesOnStand<GOLD>(Turn)
00126     + state.countPiecesOnStand<SILVER>(Turn)
00127     + state.countPiecesOnStand<KNIGHT>(Turn)
00128     + state.countPiecesOnStand<LANCE>(Turn)
00129     + state.countPiecesOnStand<PAWN>(Turn);
00130 
00131   if ( onEnemyCamp + onStand < 27 + (Turn==BLACK) )
00132     return false;
00133 
00134   if (countPiece < 11) {
00135     drops = 11 - countPiece;
00136     return false;
00137   } else {
00138     drops = 0;
00139   }
00140 
00141   return true;
00142 }
00143 
00144 namespace osl
00145 {
00146   namespace enter_king
00147   {
00148     template bool osl::enter_king::EnterKing::canDeclareWin<BLACK>(const NumEffectState&);
00149     template bool osl::enter_king::EnterKing::canDeclareWin<WHITE>(const NumEffectState&);
00150     template bool osl::enter_king::EnterKing::canDeclareWin<BLACK>(const NumEffectState&, int &drops);
00151     template bool osl::enter_king::EnterKing::canDeclareWin<WHITE>(const NumEffectState&, int &drops);
00152   }
00153 }
00154 
00155 // ;;; Local Variables:
00156 // ;;; mode:c++
00157 // ;;; c-basic-offset:2
00158 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines