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