00001
00002
00003 #include "osl/progress/effect5x3.h"
00004 #include "osl/progress/effect5x3Table.h"
00005
00006 osl::progress::
00007 Effect5x3::Effect5x3(const NumEffectState& state)
00008 {
00009 area_progresses[BLACK]=makeProgressArea(WHITE, state, state.kingSquare(BLACK));
00010 area_progresses[WHITE]=makeProgressArea(BLACK, state, state.kingSquare(WHITE));
00011 stand_progresses[WHITE]=makeProgressStand(BLACK, state);
00012 stand_progresses[BLACK]=makeProgressStand(WHITE, state);
00013 progresses[BLACK]=area_progresses[BLACK]+stand_progresses[BLACK];
00014 progresses[WHITE]=area_progresses[WHITE]+stand_progresses[WHITE];
00015 }
00016
00017 int osl::progress::
00018 Effect5x3::makeProgressAll(Player defense, const NumEffectState& state,
00019 Square king)
00020 {
00021 return makeProgressArea(alt(defense), state, king)
00022 + makeProgressStand(alt(defense), state);
00023 }
00024
00025 int osl::progress::
00026 Effect5x3::makeProgressArea(Player attack, const NumEffectState& state,
00027 Square king)
00028 {
00029 const Square center = Centering5x3::adjustCenter(king);
00030
00031 const int min_x = center.x() - 2;
00032 const int min_y = center.y() - 1;
00033
00034
00035 int sum_effect = 0;
00036
00037 for (int dx=0; dx<5; ++dx)
00038 {
00039 for (int dy=0; dy<3; ++dy)
00040 {
00041 const Square target(min_x+dx,min_y+dy);
00042 sum_effect += state.countEffect(attack, target) *
00043 Effect5x3_Table.getAttackEffect(attack,king,dx,dy);
00044 }
00045 }
00046 return sum_effect / 2;
00047 }
00048
00049 int osl::progress::
00050 Effect5x3::makeProgressStand(Player attack, const NumEffectState& state)
00051 {
00052
00053 int sum_pieces = 0;
00054 sum_pieces += state.countPiecesOnStand<PAWN>(attack)*Effect5x3Table::StandPAWN;
00055 sum_pieces += state.countPiecesOnStand<LANCE>(attack)*Effect5x3Table::StandLANCE;
00056 sum_pieces += state.countPiecesOnStand<KNIGHT>(attack)*Effect5x3Table::StandKNIGHT;
00057 sum_pieces += state.countPiecesOnStand<SILVER>(attack)*Effect5x3Table::StandSILVER;
00058 sum_pieces += state.countPiecesOnStand<GOLD>(attack)*Effect5x3Table::StandGOLD;
00059 sum_pieces += state.countPiecesOnStand<BISHOP>(attack)*Effect5x3Table::StandBISHOP;
00060 sum_pieces += state.countPiecesOnStand<ROOK>(attack)*Effect5x3Table::StandROOK;
00061 return sum_pieces;
00062 }
00063
00064 void osl::progress::
00065 Effect5x3::updateStand(int& old_stand, Move last_move)
00066 {
00067 if (last_move.isDrop()) {
00068 const Ptype ptype = last_move.ptype();
00069 old_stand -= Effect5x3_Table.piecesOnStand(ptype);
00070 return;
00071 }
00072 const Ptype ptype = last_move.capturePtype();
00073 if (ptype == PTYPE_EMPTY) {
00074 return;
00075 }
00076 old_stand += Effect5x3_Table.piecesOnStand(unpromote(ptype));
00077 }
00078
00079 void osl::progress::
00080 Effect5x3::update(const NumEffectState& new_state, Move last_move)
00081 {
00082 const Player pl = last_move.player();
00083 updateStand(stand_progresses[alt(pl)], last_move);
00084
00085 const Square kb = new_state.kingSquare<BLACK>(), kw = new_state.kingSquare<WHITE>();
00086 BoardMask mb = new_state.changedEffects(BLACK), mw = new_state.changedEffects(WHITE);
00087 bool king_move = last_move.ptype() == KING;
00088 if ((king_move && new_state.turn() == BLACK) || mb.anyInRange(Board_Mask_Table5x3_Center.mask(kw)))
00089 area_progresses[WHITE]=makeProgressArea(BLACK,new_state, kw);
00090 if ((king_move && new_state.turn() == WHITE) || mw.anyInRange(Board_Mask_Table5x3_Center.mask(kb)))
00091 area_progresses[BLACK]=makeProgressArea(WHITE,new_state, kb);
00092
00093 progresses[BLACK]=area_progresses[BLACK]+stand_progresses[BLACK];
00094 progresses[WHITE]=area_progresses[WHITE]+stand_progresses[WHITE];
00095 }
00096
00097 osl::progress::Effect5x3 osl::progress::
00098 Effect5x3::expect(const NumEffectState&, Move move) const
00099 {
00100 Effect5x3 new_progress = *this;
00101 if (move.capturePtype() != PTYPE_EMPTY) {
00102 const Player alt_pl = alt(move.player());
00103 int old = stand_progresses[alt_pl];
00104 updateStand(new_progress.stand_progresses[alt_pl], move);
00105 new_progress.progresses[alt_pl] += new_progress.stand_progresses[alt_pl] - old;
00106 }
00107 return new_progress;
00108 }
00109
00110
00111
00112 osl::progress::
00113 Effect5x3WithBonus::Effect5x3WithBonus(const NumEffectState& state) : Effect5x3(state)
00114 {
00115 progress_bonuses[BLACK]=makeProgressAreaBonus<WHITE>(state, state.kingSquare<BLACK>());
00116 progress_bonuses[WHITE]=makeProgressAreaBonus<BLACK>(state, state.kingSquare<WHITE>());
00117 effect_mask[BLACK] = makeEffectMask<BLACK>(state);
00118 effect_mask[WHITE] = makeEffectMask<WHITE>(state);
00119 updateProgressBonuses(state);
00120 }
00121
00122 template <osl::Player Defense>
00123 osl::PieceMask osl::progress::
00124 Effect5x3WithBonus::makeEffectMask(const NumEffectState &state)
00125 {
00126 const Square king =
00127 state.kingSquare<Defense>();
00128 const Square center =
00129 Centering5x3::adjustCenter(king);
00130
00131 const int min_x = center.x() - 2;
00132 const int min_y = center.y() - 1;
00133
00134 PieceMask mask;
00135 for (int dx = 0; dx < 5; ++dx)
00136 {
00137 for (int dy = 0; dy < 3; ++dy)
00138 {
00139 const Square target(min_x+dx, min_y+dy);
00140 mask = mask | state.effectSetAt(target);
00141 }
00142 }
00143 return mask;
00144 }
00145
00146 inline
00147 int osl::progress::
00148 Effect5x3WithBonus::attackEffect3(const NumEffectState& state, Player attack, Square target)
00149 {
00150 const int a = state.countEffect(attack, target);
00151 if (a <= 1)
00152 return a;
00153 if (state.countEffect(alt(attack), target) > 0
00154 || state.pieceAt(target).isOnBoardByOwner(attack))
00155 return 1;
00156 return 2;
00157 }
00158
00159 namespace osl
00160 {
00161 namespace
00162 {
00163 template <Player P>
00164 int countPawnLanceKnight(const NumEffectState& state, Square target)
00165 {
00166
00167
00168 const Square d = target+DirectionPlayerTraits<D,P>::offset();
00169 const Piece pd = state.pieceAt(d);
00170
00171
00172 int count = 0;
00173 if (pd.ptypeO() == newPtypeO(P,PAWN))
00174 ++count;
00175 else if (pd.ptypeO() == newPtypeO(P,LANCE))
00176 ++count;
00177 else if (pd.isEmpty())
00178 {
00179 if (state.hasLongEffectAt<LANCE>(P, target))
00180 ++count;
00181 }
00182 else if (pd.isEdge())
00183 return 0;
00184
00185
00186 const Piece pdl = state.pieceAt(d+DirectionPlayerTraits<DL,P>::offset());
00187 if (pdl.ptypeO() == newPtypeO(P,KNIGHT))
00188 return count+1;
00189 const Piece pdr = state.pieceAt(d+DirectionPlayerTraits<DR,P>::offset());
00190 if (pdr.ptypeO() == newPtypeO(P,KNIGHT))
00191 return count+1;
00192 return count;
00193 }
00194 }
00195 }
00196
00197 template <osl::Player Attack, bool AlwaysPromotable, bool AlwaysNotPromotable>
00198 int osl::progress::
00199 Effect5x3WithBonus::makeProgressAreaBonus(const NumEffectState& state, Square king,
00200 Square center)
00201 {
00202 const int min_x = center.x() - 2;
00203 const int min_y = center.y() - 1;
00204
00205
00206 int sum_effect = 0;
00207
00208 for (int dy = 0; dy < 3; ++dy)
00209 {
00210 const Square target(king.x(), min_y + dy);
00211 int effect = attackEffect3(state, Attack, target) * 2;
00212 if (effect > 0)
00213 {
00214 if (! AlwaysPromotable
00215 && (AlwaysNotPromotable || !target.canPromote<Attack>()) )
00216 {
00217 effect -= countPawnLanceKnight<Attack>(state, target);
00218 assert(effect >= 0);
00219 }
00220 sum_effect += effect *
00221 Effect5x3_Table.getAttackEffect(Attack, king, target.x() - min_x, dy) / 2;
00222
00223 }
00224 }
00225 for (int x = king.x() - 1; x >= min_x; --x)
00226 {
00227 int y_count = 0;
00228 int sum = 0;
00229 for (int dy = 0; dy < 3; ++dy)
00230 {
00231 const Square target(x, min_y + dy);
00232 int effect = attackEffect3(state, Attack, target) * 2;
00233 if (effect > 0)
00234 {
00235 if (! AlwaysPromotable
00236 && (AlwaysNotPromotable || !target.canPromote<Attack>()) )
00237 {
00238 if (king.x() - x > 1)
00239 effect = 0;
00240 else
00241 effect -= countPawnLanceKnight<Attack>(state, target);
00242 assert(effect >= 0);
00243 }
00244 sum += effect *
00245 Effect5x3_Table.getAttackEffect(Attack, king, x - min_x, dy) / 2;
00246 y_count++;
00247 }
00248 }
00249 sum_effect += sum;
00250 if (y_count == 3)
00251 {
00252 sum_effect += sum;
00253 break;
00254 }
00255 }
00256 for (int x = king.x() + 1; x < min_x + 5; ++x)
00257 {
00258 int y_count = 0;
00259 int sum = 0;
00260 for (int dy = 0; dy < 3; ++dy)
00261 {
00262 const Square target(x, min_y + dy);
00263 int effect = attackEffect3(state, Attack, target) * 2;
00264 if (effect > 0)
00265 {
00266 if (! AlwaysPromotable
00267 && (AlwaysNotPromotable || !target.canPromote<Attack>()) )
00268 {
00269 if (x - king.x() > 1)
00270 effect = 0;
00271 else
00272 effect -= countPawnLanceKnight<Attack>(state, target);
00273 assert(effect >= 0);
00274 }
00275 sum += effect *
00276 Effect5x3_Table.getAttackEffect(Attack, king, x - min_x, dy) / 2;
00277 y_count++;
00278 }
00279 }
00280 sum_effect += sum;
00281 if (y_count == 3)
00282 {
00283 sum_effect += sum;
00284 break;
00285 }
00286 }
00287 return sum_effect / 2;
00288 }
00289
00290 template <osl::Player Attack>
00291 int osl::progress::
00292 Effect5x3WithBonus::makeProgressAreaBonus(const NumEffectState& state,
00293 Square king)
00294 {
00295 const Square center = Centering5x3::adjustCenter(king);
00296
00297 const bool always_promotable = center.squareForBlack<Attack>().y() <= 2;
00298 if (always_promotable)
00299 return makeProgressAreaBonus<Attack,true,false>(state, king, center);
00300 const bool always_notpromotable = center.squareForBlack<Attack>().y() >= 5;
00301 if (always_notpromotable)
00302 return makeProgressAreaBonus<Attack,false,true>(state, king, center);
00303 return makeProgressAreaBonus<Attack,false,false>(state, king, center);
00304 }
00305
00306 void osl::progress::
00307 Effect5x3WithBonus::update(const NumEffectState& new_state, Move last_move)
00308 {
00309 Effect5x3::update(new_state, last_move);
00310
00311 const Square kb = new_state.kingSquare<BLACK>(), kw = new_state.kingSquare<WHITE>();
00312 BoardMask mask = new_state.changedEffects();
00313 mask.set(last_move.to()); mask.set(last_move.from());
00314
00315 const bool update_black = mask.anyInRange(Board_Mask_Table5x3_Center.mask(kb));
00316 const bool update_white = mask.anyInRange(Board_Mask_Table5x3_Center.mask(kw));
00317
00318 if (update_black)
00319 {
00320 progress_bonuses[BLACK]=makeProgressAreaBonus<WHITE>(new_state,kb);
00321 effect_mask[BLACK] = makeEffectMask<BLACK>(new_state);
00322 }
00323 if (update_white)
00324 {
00325 progress_bonuses[WHITE]=makeProgressAreaBonus<BLACK>(new_state,kw);
00326 effect_mask[WHITE] = makeEffectMask<WHITE>(new_state);
00327 }
00328 updateProgressBonuses(new_state, update_black, update_white);
00329 }
00330
00331 osl::progress::Effect5x3WithBonus osl::progress::
00332 Effect5x3WithBonus::expect(const NumEffectState&, Move move) const
00333 {
00334 Effect5x3WithBonus new_progress = *this;
00335 if (move.capturePtype() != PTYPE_EMPTY) {
00336 const Player alt_pl = alt(move.player());
00337 int old = stand_progresses[playerToIndex(alt_pl)];
00338 new_progress.updateStand(alt_pl, move);
00339 new_progress.progresses[playerToIndex(alt_pl)] += new_progress.stand_progresses[playerToIndex(alt_pl)] - old;
00340 }
00341 return new_progress;
00342 }
00343
00344 void osl::progress::
00345 Effect5x3WithBonus::updateProgressBonuses(const NumEffectState& state, bool update_black, bool update_white)
00346 {
00347 if (update_black && progress_bonuses[BLACK] != 0)
00348 {
00349 const int pieces = countEffectPieces(state, WHITE);
00350 progress_bonuses[BLACK] =
00351 std::min(pieces * pieces * 4,
00352 progress_bonuses[BLACK]);
00353 }
00354 if (update_white && progress_bonuses[WHITE] != 0)
00355 {
00356 const int pieces = countEffectPieces(state, BLACK);
00357 progress_bonuses[WHITE] =
00358 std::min(pieces * pieces * 4,
00359 progress_bonuses[WHITE]);
00360 }
00361 }
00362
00363 int osl::progress::
00364 Effect5x3WithBonus::countEffectPieces(const NumEffectState &state, Player attack) const
00365 {
00366 PieceMask mask = effect5x3Mask(alt(attack));
00367 mask = mask & state.piecesOnBoard(attack);
00368 return mask.countBit();
00369 }
00370
00371
00372
00373
00374
00375