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