00001
00002
00003 #include "osl/state/numEffectState.h"
00004 #include "osl/state/numEffectState.tcc"
00005 #include "osl/effect/numSimpleEffect.tcc"
00006
00007 #include <iostream>
00008
00009 bool osl::state::operator==(const NumEffectState& st1,
00010 const NumEffectState& st2)
00011 {
00012 assert(st1.isConsistent(true));
00013 assert(st2.isConsistent(true));
00014 if (!(st1.effects == st2.effects))
00015 return false;
00016 if (!(st1.onBoardMask == st2.onBoardMask))
00017 return false;
00018 if (!(st1.promoted == st2.promoted))
00019 return false;
00020 if (!(st1.pin_or_open == st2.pin_or_open))
00021 return false;
00022 if (!(st1.king_mobility == st2.king_mobility))
00023 return false;
00024 return (static_cast<const SimpleState&>(st1)
00025 == static_cast<const SimpleState&>(st2));
00026 }
00027
00028 const osl::checkmate::King8Info osl::state::
00029 NumEffectState::king8Info(Player king) const
00030 {
00031 return King8Info(Iking8Info(king));
00032 }
00033
00034 template<osl::Player P>
00035 void osl::state::NumEffectState::makeKing8Info()
00036 {
00037 const Player altP=PlayerTraits<P>::opponent;
00038 #ifdef ALLOW_KING_ABSENCE
00039 if (getKingPosition<P>().isPieceStand())
00040 return;
00041 #endif
00042 king8infos[P]=King8Info::make<altP>(*this,getKingPosition<P>()).value;
00043 }
00044
00045 osl::state::
00046 NumEffectState::NumEffectState(const SimpleState& st)
00047 : SimpleState(st),effects(st)
00048 {
00049 onBoardMask[0].resetAll();
00050 onBoardMask[1].resetAll();
00051 promoted.resetAll();
00052 effects.effected_mask[0].resetAll();
00053 effects.effected_mask[1].resetAll();
00054 effects.effected_changed_mask[0].resetAll();
00055 effects.effected_changed_mask[1].resetAll();
00056 for(int num=0;num<40;num++){
00057 Piece p=getPieceOf(num);
00058 if (p.isOnBoard()){
00059 mutableOnBoardMask(p.owner()).set(num);
00060 if (p.isPromoted())
00061 promoted.set(num);
00062 for(int i=0;i<2;i++){
00063 Player pl=indexToPlayer(i);
00064 if(hasEffectBy(pl,p.position()))
00065 {
00066 effects.effected_mask[i].set(num);
00067 effects.effected_changed_mask[i].set(num);
00068 }
00069 }
00070 }
00071 }
00072 makePinOpen(BLACK);
00073 makePinOpen(WHITE);
00074 if(getKingPosition<BLACK>().isOnBoard())
00075 makeKing8Info<BLACK>();
00076 if(getKingPosition<WHITE>().isOnBoard())
00077 makeKing8Info<WHITE>();
00078 }
00079 osl::state::
00080 NumEffectState::~NumEffectState()
00081 {
00082 }
00083
00084 const osl::Piece osl::state::
00085 NumEffectState::selectCheapPiece(PieceMask effect) const
00086 {
00087 if (! effect.any())
00088 return Piece::EMPTY();
00089 mask_t pieces = effect.selectBit<PAWN>(), ppieces;
00090 if (pieces.any())
00091 {
00092 ppieces = pieces & promoted.getMask<PAWN>();
00093 pieces &= ~ppieces;
00094 if (pieces.any())
00095 return getPieceOf(pieces.bsf()+PtypeFuns<PAWN>::indexNum*32);
00096 return getPieceOf(ppieces.bsf()+PtypeFuns<PAWN>::indexNum*32);
00097 }
00098 pieces = effect.selectBit<LANCE>();
00099 if (pieces.any())
00100 {
00101 ppieces = pieces & promoted.getMask<LANCE>();
00102 pieces &= ~ppieces;
00103 if (pieces.any())
00104 return getPieceOf(pieces.bsf()+PtypeFuns<LANCE>::indexNum*32);
00105 return getPieceOf(ppieces.bsf()+PtypeFuns<LANCE>::indexNum*32);
00106 }
00107 mask_t king = effect.selectBit<KING>();
00108 effect.clearBit<KING>();
00109 if (effect.none())
00110 return getPieceOf(king.bsf()+PtypeFuns<KING>::indexNum*32);
00111
00112 #if OSL_WORDSIZE == 64
00113 const int index = 0;
00114 #else
00115 const int index = effect.getMask(0).any() ? 0 : 1;
00116 #endif
00117 ppieces = effect.getMask(index) & promoted.getMask(index);
00118 pieces = effect.getMask(index) & ~ppieces;
00119 const int num = pieces.any()
00120 ? (ppieces.any() ? std::min(pieces.bsf(),ppieces.bsf()) : pieces.bsf())
00121 : ppieces.bsf();
00122 return getPieceOf(num + index*32);
00123 }
00124
00125 const osl::Piece osl::state::
00126 NumEffectState::findThreatenedPiece(Player P) const
00127 {
00128 assert(! inCheck(P));
00129 PieceMask pieces = getOnBoardMask(P) & effectedMask(alt(P));
00130 PieceMask nolance = pieces; nolance.clearBit<LANCE>();
00131 int pp=-1, npp=-1, ret=-1;
00132 const int lance_index = PtypeFuns<LANCE>::indexNum;
00133 for (int i=lance_index; i>=0; --i) {
00134 mask_t all = nolance.getMask(i);
00135 mask_t promoted = all & promotedPieces().getMask(i);
00136 mask_t notpromoted = all & ~promoted;
00137 if (promoted.any()) {
00138 pp = promoted.bsr() + i*32;
00139 notpromoted &= ~Ptype_Table.getMaskLow(Piece_Table.getPtypeOf(pp));
00140 }
00141 if (notpromoted.any())
00142 npp = notpromoted.bsr() + i*32;
00143 ret = std::max(pp, npp);
00144 if (ret >= PtypeTraits<KNIGHT>::indexMin)
00145 return getPieceOf(ret);
00146 }
00147 mask_t lance = pieces.selectBit<LANCE>();
00148 if (lance.any()) {
00149 mask_t plance = lance & promotedPieces().getMask(lance_index);
00150 if (plance.any())
00151 return getPieceOf(plance.bsr()+lance_index*32);
00152 return getPieceOf(lance.bsr()+lance_index*32);
00153 }
00154 if (ret >= 0) {
00155 assert(Piece_Table.getPtypeOf(ret) == PAWN);
00156 return getPieceOf(ret);
00157 }
00158 return Piece::EMPTY();
00159 }
00160
00161 void osl::state::NumEffectState::
00162 doSimpleMove(Position from, Position to, int promoteMask)
00163 {
00164 Piece oldPiece;
00165 int num;
00166 PtypeO oldPtypeO, newPtypeO;
00167 CArray<PieceMask,2> pin_or_open_backup;
00168 KingMobility king_mobility_backup;
00169 PieceMask promoted_backup;
00170 CArray<PieceMask,2> effected_mask_backup;
00171 CArray<PieceMask,2> effected_changed_mask_backup;
00172 CArray<uint64_t,2> king8infos_backup;
00173 mobility::MobilityTable mobilityTable;
00174 if (getTurn()==BLACK){
00175 apply_move::ApplyDoUndoSimpleMove<BLACK,NumEffectState >
00176 ::prologue(*this, from, to, promoteMask,
00177 oldPiece, num, oldPtypeO, newPtypeO,
00178 pin_or_open_backup, king_mobility_backup,
00179 promoted_backup, effected_mask_backup, effected_changed_mask_backup,king8infos_backup,mobilityTable);
00180 }
00181 else{
00182 apply_move::ApplyDoUndoSimpleMove<WHITE,NumEffectState >
00183 ::prologue(*this, from, to, promoteMask,
00184 oldPiece, num, oldPtypeO, newPtypeO,
00185 pin_or_open_backup, king_mobility_backup,
00186 promoted_backup, effected_mask_backup, effected_changed_mask_backup,king8infos_backup,mobilityTable);
00187 }
00188 if (promoteMask!=0 && num < PtypeTraits<PAWN>::indexLimit)
00189 clearPawn(getTurn(),from);
00190 }
00191 void osl::state::NumEffectState::
00192 doCaptureMove(Position from, Position to, Piece target, int promoteMask)
00193 {
00194 Piece oldPiece;
00195 PtypeO oldPtypeO, capturePtypeO, newPtypeO;
00196 int num0, num1, num1Index;
00197 mask_t num1Mask;
00198 CArray<PieceMask,2> pin_or_open_backup;
00199 KingMobility king_mobility_backup;
00200 PieceMask promoted_backup;
00201 CArray<PieceMask,2> effected_mask_backup;
00202 CArray<PieceMask,2> effected_changed_mask_backup;
00203 CArray<uint64_t,2> king8infos_backup;
00204 mobility::MobilityTable mobilityTable;
00205 if(getTurn()==BLACK){
00206 apply_move::ApplyDoUndoCaptureMove<BLACK,NumEffectState >
00207 ::prologue(*this, from, to, target, promoteMask, oldPiece, oldPtypeO,
00208 capturePtypeO, newPtypeO, num0, num1, num1Index,num1Mask,
00209 pin_or_open_backup, king_mobility_backup,
00210 promoted_backup, effected_mask_backup, effected_changed_mask_backup,king8infos_backup,mobilityTable);
00211 }
00212 else{
00213 apply_move::ApplyDoUndoCaptureMove<WHITE,NumEffectState >
00214 ::prologue(*this, from, to, target, promoteMask, oldPiece, oldPtypeO,
00215 capturePtypeO, newPtypeO, num0, num1, num1Index,num1Mask,
00216 pin_or_open_backup, king_mobility_backup,
00217 promoted_backup, effected_mask_backup, effected_changed_mask_backup,king8infos_backup,mobilityTable);
00218 }
00219 const Ptype capturePtype=target.ptype();
00220 if (capturePtype==PAWN)
00221 clearPawn(alt(getTurn()),to);
00222 if (promoteMask!=0 && num0<PtypeTraits<PAWN>::indexLimit)
00223 clearPawn(getTurn(),from);
00224 }
00225
00226 void osl::state::NumEffectState::
00227 doDropMove(Position to,Ptype ptype)
00228 {
00229 Piece oldPiece;
00230 PtypeO ptypeO;
00231 int num, numIndex;
00232 mask_t numMask;
00233 CArray<PieceMask,2> pin_or_open_backup;
00234 KingMobility king_mobility_backup;
00235 CArray<PieceMask,2> effected_mask_backup;
00236 CArray<PieceMask,2> effected_changed_mask_backup;
00237 CArray<uint64_t,2> king8infos_backup;
00238 mobility::MobilityTable mobilityTable;
00239 if(getTurn()==BLACK){
00240 apply_move::ApplyDoUndoDropMove<BLACK,NumEffectState >
00241 ::prologue(*this, to, ptype, oldPiece, num, ptypeO, numIndex, numMask,
00242 pin_or_open_backup, king_mobility_backup,
00243 effected_mask_backup, effected_changed_mask_backup,king8infos_backup,mobilityTable);
00244 }
00245 else{
00246 apply_move::ApplyDoUndoDropMove<WHITE,NumEffectState >
00247 ::prologue(*this, to, ptype, oldPiece, num, ptypeO, numIndex, numMask,
00248 pin_or_open_backup, king_mobility_backup,
00249 effected_mask_backup, effected_changed_mask_backup,king8infos_backup,mobilityTable);
00250 }
00251 if (ptype==PAWN)
00252 setPawn(getTurn(),to);
00253 }
00254
00255 #ifndef MINIMAL
00256 bool osl::state::NumEffectState::isConsistent(bool showError) const
00257 {
00258 if (!SimpleState::isConsistent(showError))
00259 {
00260 if (showError)
00261 std::cerr << "error before effect\n";
00262 return false;
00263 }
00264 effect::NumSimpleEffectTable effects1(*this);
00265 if (!(effects1==effects))
00266 {
00267 if (showError)
00268 {
00269 std::cerr << "Effect error 1" << std::endl;
00270 std::cerr << *this;
00271 for(int y=1;y<=9;y++)
00272 for(int x=9;x>0;x--)
00273 {
00274 Position pos(x,y);
00275 if (!(effects1.getEffect(pos)==effects.getEffect(pos)))
00276 {
00277 std::cerr << pos << ",real=" << effects.getEffect(pos) << ",ideal=" << effects1.getEffect(pos) << std::endl;
00278 }
00279 }
00280 for(int num=0;num<=39;num++){
00281 for(int i=0;i<8;i++){
00282 Direction d=static_cast<Direction>(i);
00283 if(effects.effectedNumTable[num][d]!=effects1.effectedNumTable[num][d]){
00284 std::cerr << "piece=" << getPieceOf(num) << ",num=" << num << ",d=" << d << ",v1=" << effects.effectedNumTable[num][d] << ",v2=" << effects1.effectedNumTable[num][d] << std::endl;
00285 }
00286 }
00287 }
00288 std::cerr << effects.effectedNumTable << std::endl;
00289 }
00290 return false;
00291 }
00292 for (int z=0; z<2; ++z) {
00293 const Player p = indexToPlayer(z);
00294 #ifdef ALLOW_KING_ABSENCE
00295 if (getKingPosition(p).isPieceStand())
00296 continue;
00297 #endif
00298 const PieceMask pin2 = effect_util::Pin::make(*this, p);
00299 if (pin(p) != pin2) {
00300 if (showError)
00301 std::cerr << "pin for " << p << " differs " << pin(p) << " " << pin2 << "\n";
00302 return false;
00303 }
00304 King8Info king8info2 = King8Info::make(alt(p), *this);
00305 if (King8Info(Iking8Info(p)).value != king8info2.value) {
00306 if (showError)
00307 std::cerr << "king8info for " << p << " differs \n" << King8Info(Iking8Info(p)) << "\n" << king8info2 << "\n";
00308 return false;
00309 }
00310 }
00311 for (int i=0; i<Piece::SIZE; ++i) {
00312 const Piece p = getPieceOf(i);
00313 if (p.isOnBoard()) {
00314 if (promoted.test(i) != p.isPromoted()) {
00315 if (showError)
00316 std::cerr << "promoted differs " << p << " " << promoted << " " << promoted.test(i) << "\n";
00317 return false;
00318 }
00319 }
00320 }
00321 return true;
00322 }
00323 #endif
00324
00325 bool osl::state::NumEffectState::isConsistent(const NumEffectState& prev, Move moved, bool show_error) const
00326 {
00327 #ifdef MINIMAL
00328 show_error=false;
00329 #endif
00330
00331 const CArray<BoardMask,2> changed_squares
00332 = {{ changedEffects(BLACK), changedEffects(WHITE) }};
00333 const BoardMask changed_all = changed_squares[BLACK] | changed_squares[WHITE];
00334 CArray<BoardMask, Piece::SIZE> each_effect, prev_effect;
00335 for (int i=0; i<Piece::SIZE; ++i) {
00336 each_effect[i].clear();
00337 prev_effect[i].clear();
00338 }
00339 for (int x=1; x<=9; ++x) {
00340 for (int y=1; y<=9; ++y) {
00341 const Position sq(x, y);
00342 for (int i=0; i<Piece::SIZE; ++i) {
00343 if (getEffect(sq).test(i))
00344 each_effect[i].set(sq);
00345 if (prev.getEffect(sq).test(i))
00346 prev_effect[i].set(sq);
00347 }
00348 if (! changed_all.test(sq))
00349 {
00350 if (getEffect(sq) != prev.getEffect(sq)) {
00351 #ifndef MINIMAL
00352 if (show_error)
00353 std::cerr << "changedEffects unset\n" << *this << moved << sq << "\n";
00354 #endif
00355 return false;
00356 }
00357 }
00358 for (int i=0; i<2; ++i)
00359 {
00360 const Player pl = indexToPlayer(i);
00361 if (! changed_squares[pl].test(sq))
00362 {
00363 if ((getEffect(sq) & getOnBoardMask(pl))
00364 != (prev.getEffect(sq) & prev.getOnBoardMask(pl))) {
00365 #ifndef MINIMAL
00366 if (show_error)
00367 std::cerr << "changedEffects unset for " << pl << "\n" << *this << moved << sq << "\n";
00368 #endif
00369 return false;
00370 }
00371 }
00372 }
00373 }
00374 }
00375
00376 const NumBitmapEffect changed_effect_pieces = changedPieces();
00377 for (int i=0; i<Piece::SIZE; ++i) {
00378 if (each_effect[i] == prev_effect[i])
00379 continue;
00380 if (! changed_effect_pieces.test(i)) {
00381 #ifndef MINIMAL
00382 if (show_error)
00383 std::cerr << "changedPieces() unset\n" << *this << moved << i
00384 << " " << each_effect[i] << " != " << prev_effect[i] << "\n";
00385 #endif
00386 return false;
00387 }
00388 }
00389
00390 for (int i=0; i<Piece::SIZE; ++i)
00391 {
00392 for (int j=0; j<2; ++j)
00393 {
00394 const Player pl = indexToPlayer(j);
00395 if (prev.getPieceOf(i).position() == moved.to())
00396 continue;
00397 if (prev.effectedMask(pl).test(i) != effectedMask(pl).test(i)) {
00398 if (! effectedChanged(pl).test(i)) {
00399 #ifndef MINIMAL
00400 if (show_error)
00401 std::cerr << "effectedChanged(" << pl << ") unset\n" << *this << moved << i
00402 << " " << prev.effectedChanged(pl) << " != " << prev.effectedChanged(WHITE) << "\n";
00403 #endif
00404 return false;
00405 }
00406 }
00407 }
00408 }
00409 return true;
00410 }
00411
00412 template <bool show_error>
00413 bool
00414 #if (defined __GNUC__) && (! defined GPSONE) && (! defined GPSUSIONE)
00415 __attribute__ ((used))
00416 #endif
00417 osl::state::NumEffectState::isAlmostValidMove(Move move) const{
00418 assert(move.isValid());
00419 assert(move.isNormal());
00420 assert(this->getTurn() == move.player());
00421 assert(isValidMoveByRule(move, true));
00422
00423 const Position from=move.from();
00424 const Position to=move.to();
00425 const Piece toPiece=this->getPieceAt(to);
00426 const Ptype ptype=move.ptype();
00427 const Player turn = move.player();
00428
00429 if (from.isPieceStand()){
00430
00431 if (! toPiece.isEmpty()) {
00432 if (show_error) std::cerr << "drop on to piece : " << move << std::endl;
00433 return false;
00434 }
00435
00436 if (! this->hasPieceOnStand(turn,ptype)) {
00437 if (show_error) std::cerr << turn << " don't have : " << ptype << std::endl;
00438 return false;
00439 }
00440
00441 if (ptype==PAWN && isPawnMaskSet(turn, to.x())) {
00442 if (show_error) std::cerr << " Double Pawn : " << move << std::endl;
00443 return false;
00444 }
00445 }
00446 else{
00447 const Piece from_piece = this->getPieceAt(from);
00448
00449 if (from_piece.isEmpty() || (from_piece.owner() != turn)){
00450 if (show_error)
00451 std::cerr << " No such piece0 : " << move << std::endl;
00452 return false;
00453 }
00454
00455 if (move.isPromote()){
00456
00457 if (from_piece.ptype() != unpromote(move.ptype()))
00458 {
00459 if (show_error)
00460 std::cerr << " No such piece1 : " << move << std::endl;
00461 return false;
00462 }
00463 if (from_piece.isPromotedNotKingGold()){
00464 if (show_error)
00465 std::cerr << " can't promote promoted piece : " << move << std::endl;
00466 return false;
00467 }
00468 }
00469 else{
00470
00471 if (from_piece.ptype() != move.ptype()){
00472 if (show_error)
00473 std::cerr << " No such piece2 : " << move << std::endl;
00474 return false;
00475 }
00476 }
00477
00478 if (!toPiece.isEmpty() && toPiece.owner()==turn) {
00479 if (show_error) std::cerr << " No move on : " << move << std::endl;
00480 return false;
00481 }
00482 if(!hasEffectByPiece(from_piece,to)){
00483 if (show_error) {
00484 std::cerr << " No such move2 : " << move << std::endl;
00485 }
00486 return false;
00487 }
00488
00489 if (toPiece.ptype()!=move.capturePtype()) {
00490 if (show_error) std::cerr << " Not such capture : " << move
00491 << std::endl << *this;
00492 return false;
00493 }
00494 }
00495
00496 assert(isValidMoveByRule(move, true));
00497 return true;
00498 }
00499
00500 bool osl::state::NumEffectState::
00501 isAlmostValidMove(Move move,bool show_error) const{
00502 #ifdef MINIMAL
00503 show_error=false;
00504 #endif
00505 if(show_error)
00506 return isAlmostValidMove<true>(move);
00507 else
00508 return isAlmostValidMove<false>(move);
00509 }
00510
00511 #ifndef MINIMAL
00512 void osl::state::NumEffectState::showEffect(std::ostream& os) const
00513 {
00514 os<< static_cast<SimpleState const&>(*this);
00515 for(int y=1;y<=9;y++){
00516 os << 'P' << y;
00517 for(int x=9;x>0;x--){
00518 Position pos(x,y);
00519 os << record::csa::show(getPieceAt(pos)) << getEffect(pos);
00520 }
00521 os << std::endl;
00522 }
00523
00524 for(int num=0;num<Piece::SIZE;num++){
00525 if (standMask(BLACK).test(num)){
00526 os << "P+00" << record::csa::show(Piece_Table.getPtypeOf(num))
00527 << std::endl;
00528 }
00529 else if (standMask(WHITE).test(num)){
00530 os << "P-00" << record::csa::show(Piece_Table.getPtypeOf(num))
00531 << std::endl;
00532 }
00533 }
00534 }
00535 #endif
00536
00537 osl::container::PieceMask osl::state::NumEffectState::
00538 makePinOpen(osl::Position target,osl::Player defense)
00539 {
00540 PieceMask pins;
00541 if(target.isPieceStand()) return pins;
00542 PieceMask mask=getOnBoardMask(alt(defense));
00543 makePinOpenDir<UL>(target,pins,mask,defense);
00544 makePinOpenDir<U>(target,pins,mask,defense);
00545 makePinOpenDir<UR>(target,pins,mask,defense);
00546 makePinOpenDir<L>(target,pins,mask,defense);
00547 makePinOpenDir<R>(target,pins,mask,defense);
00548 makePinOpenDir<DL>(target,pins,mask,defense);
00549 makePinOpenDir<D>(target,pins,mask,defense);
00550 makePinOpenDir<DR>(target,pins,mask,defense);
00551 return pins;
00552 }
00553
00554 void osl::state::NumEffectState::
00555 makePinOpen(osl::Player defense)
00556 {
00557 pin_or_open[defense]=makePinOpen(getKingPosition(defense),defense);
00558 }
00559
00560 const osl::mask_t osl::state::NumEffectState::
00561 effectBit(Player attack, Ptype ptype, Position target) const
00562 {
00563 switch (ptype) {
00564 case PAWN: case PPAWN:
00565 return effectBit<PAWN>(attack, target);
00566 case LANCE: case PLANCE:
00567 return effectBit<LANCE>(attack, target);
00568 case KNIGHT: case PKNIGHT:
00569 return effectBit<KNIGHT>(attack, target);
00570 case SILVER: case PSILVER:
00571 return effectBit<SILVER>(attack, target);
00572 case GOLD:
00573 return effectBit<GOLD>(attack, target);
00574 case BISHOP: case PBISHOP:
00575 return effectBit<BISHOP>(attack, target);
00576 case ROOK: case PROOK:
00577 return effectBit<ROOK>(attack, target);
00578 case KING:
00579 return effectBit<KING>(attack, target);
00580 default:
00581 assert(0);
00582 }
00583 return mask_t();
00584 }
00585
00586 namespace osl
00587 {
00588
00589
00590 template bool NumEffectState::
00591 hasEffectByWithRemove<BLACK>(Position, Position) const;
00592 template bool NumEffectState::
00593 hasEffectByWithRemove<WHITE>(Position, Position) const;
00594 template void NumEffectState::makeKing8Info<BLACK>();
00595 template void NumEffectState::makeKing8Info<WHITE>();
00596 }
00597
00598
00599
00600
00601
00602