00001
00002
00003 #ifndef EVAL_MINORPIECEBONUS_H
00004 #define EVAL_MINORPIECEBONUS_H
00005
00006 #include "osl/eval/pieceEval.h"
00007 #include "osl/progress/progress16.h"
00008 #include "osl/state/simpleState.h"
00009 #include <boost/static_assert.hpp>
00010
00011 namespace osl
00012 {
00013 namespace eval
00014 {
00015 struct MinorPieceDebugInfo
00016 {
00017 int pawn_bonus, lance_bonus, knight_bonus, gold_bonus;
00018 };
00022 class MinorPieceBonus
00023 {
00024 CArray<int,2> pawn_on_stand;
00025 CArray<int,2> lance_on_stand;
00026 CArray<int,2> knight_on_stand;
00027 CArray<int,2> pawns;
00028 CArray<int,2> golds;
00029 private:
00030 int pawnBonus(Progress16 progress16) const
00031 {
00032 const int black_pawn = pawn_on_stand[playerToIndex(BLACK)];
00033 const int white_pawn = pawn_on_stand[playerToIndex(WHITE)];
00034 const int black_pawn_total = pawns[playerToIndex(BLACK)];
00035 const int white_pawn_total = pawns[playerToIndex(WHITE)];
00036 int result = 0;
00037 if (black_pawn > 1)
00038 {
00039 result -= (black_pawn - 1) * progress16.value() *
00040 PtypeEvalTraits<PAWN>::val / 32;
00041 }
00042 else if (black_pawn == 0 && black_pawn_total < white_pawn_total)
00043 {
00044 result -= PtypeEvalTraits<PAWN>::val / 2;
00045 }
00046 if (black_pawn >= 9)
00047 {
00048 result -= (black_pawn - 8) * progress16.value() *
00049 PtypeEvalTraits<PAWN>::val / 8;
00050 }
00051 if (white_pawn > 1)
00052 {
00053 result += (white_pawn - 1) * progress16.value() *
00054 PtypeEvalTraits<PAWN>::val / 32;
00055 }
00056 else if (white_pawn == 0 && white_pawn_total < black_pawn_total)
00057 {
00058 result += PtypeEvalTraits<PAWN>::val / 2;
00059 }
00060 if (white_pawn >= 9)
00061 {
00062 result += (white_pawn - 8) * progress16.value() *
00063 PtypeEvalTraits<PAWN>::val / 8;
00064 }
00065 return result;
00066 }
00067 int lanceBonus(Progress16 progress16) const
00068 {
00069 const int black_lance = lance_on_stand[playerToIndex(BLACK)];
00070 const int white_lance = lance_on_stand[playerToIndex(WHITE)];
00071 int result = 0;
00072 if (black_lance > 1)
00073 {
00074 result -= (black_lance - 1) * progress16.value() * PtypeEvalTraits<LANCE>::val / 32;
00075 }
00076 if (black_lance > 2)
00077 {
00078 result -= (black_lance - 2) * progress16.value() * PtypeEvalTraits<PAWN>::val / 24;
00079 }
00080 if (white_lance > 1)
00081 {
00082 result += (white_lance - 1) * progress16.value() * PtypeEvalTraits<LANCE>::val / 32;
00083 }
00084 if (white_lance > 2)
00085 {
00086 result += (white_lance - 2) * progress16.value() * PtypeEvalTraits<PAWN>::val / 24;
00087 }
00088 return result;
00089 }
00090 int knightBonus(Progress16 progress16) const
00091 {
00092 const int black_knight = knight_on_stand[playerToIndex(BLACK)];
00093 const int white_knight = knight_on_stand[playerToIndex(WHITE)];
00094 int result = 0;
00095 if (black_knight > 1)
00096 {
00097 result -= (black_knight - 1) * progress16.value() * PtypeEvalTraits<KNIGHT>::val / 32;
00098 }
00099 if (black_knight > 2)
00100 {
00101 result -= (black_knight - 2) * progress16.value() * PtypeEvalTraits<PAWN>::val / 8;
00102 }
00103 if (white_knight > 1)
00104 {
00105 result += (white_knight - 1) * progress16.value() * PtypeEvalTraits<KNIGHT>::val / 32;
00106 }
00107 if (white_knight > 2)
00108 {
00109 result += (white_knight - 2) * progress16.value() * PtypeEvalTraits<PAWN>::val / 8;
00110 }
00111 return result;
00112 }
00113 int goldBonus(Progress16 black, Progress16 white) const
00114 {
00115 const int black_gold = golds[playerToIndex(BLACK)];
00116 const int white_gold = golds[playerToIndex(WHITE)];
00117 if (black_gold >= 3)
00118 {
00119 return white.value() * PtypeEvalTraits<GOLD>::val
00120 * (black_gold - 2);
00121 }
00122 else if (white_gold >= 3)
00123 {
00124 return -black.value() * PtypeEvalTraits<GOLD>::val
00125 * (white_gold - 2);
00126 }
00127
00128 return 0;
00129 }
00130
00131 public:
00132 MinorPieceBonus(const SimpleState& state)
00133 {
00134 pawn_on_stand[playerToIndex(BLACK)] = state.countPiecesOnStand(BLACK, PAWN);
00135 pawn_on_stand[playerToIndex(WHITE)] = state.countPiecesOnStand(WHITE, PAWN);
00136 lance_on_stand[playerToIndex(BLACK)] = state.countPiecesOnStand(BLACK, LANCE);
00137 lance_on_stand[playerToIndex(WHITE)] = state.countPiecesOnStand(WHITE, LANCE);
00138 knight_on_stand[playerToIndex(BLACK)] = state.countPiecesOnStand(BLACK, KNIGHT);
00139 knight_on_stand[playerToIndex(WHITE)] = state.countPiecesOnStand(WHITE, KNIGHT);
00140 pawns[playerToIndex(BLACK)] = 0;
00141 pawns[playerToIndex(WHITE)] = 0;
00142 golds[playerToIndex(BLACK)] = 0;
00143 golds[playerToIndex(WHITE)] = 0;
00144 for (int i = PtypeTraits<PAWN>::indexMin;
00145 i < PtypeTraits<PAWN>::indexLimit; i++)
00146 {
00147 const Piece pawn = state.getPieceOf(i);
00148 if (pawn.owner() == BLACK)
00149 pawns[playerToIndex(BLACK)]++;
00150 else
00151 pawns[playerToIndex(WHITE)]++;
00152 }
00153
00154 for (int i = PtypeTraits<GOLD>::indexMin;
00155 i < PtypeTraits<GOLD>::indexLimit; i++)
00156 {
00157 const Piece gold = state.getPieceOf(i);
00158 golds[playerToIndex(gold.owner())]++;
00159 }
00160 }
00161
00162 int value(Progress16 progress16,
00163 Progress16 black,
00164 Progress16 white) const
00165 {
00166 return pawnBonus(progress16) + lanceBonus(progress16) +
00167 knightBonus(progress16) + goldBonus(black, white);
00168 }
00169
00170 void update(const SimpleState& , Move last_move)
00171 {
00172 const Player player = last_move.player();
00173 const Ptype ptype = last_move.ptype();
00174 if (last_move.isDrop()) {
00175 if (ptype == PAWN) {
00176 pawn_on_stand[playerToIndex(player)]--;
00177 assert(pawn_on_stand[playerToIndex(BLACK)] >= 0);
00178 assert(pawn_on_stand[playerToIndex(WHITE)] >= 0);
00179 }
00180 if (ptype == LANCE) {
00181 lance_on_stand[playerToIndex(player)]--;
00182 }
00183 if (ptype == KNIGHT) {
00184 knight_on_stand[playerToIndex(player)]--;
00185 }
00186 return;
00187 }
00188 const Ptype captured = last_move.capturePtype();
00189 if (captured != PTYPE_EMPTY) {
00190 switch (unpromote(captured)) {
00191 case PAWN:
00192 pawn_on_stand[playerToIndex(player)]++;
00193 pawns[playerToIndex(player)]++;
00194 pawns[playerToIndex(alt(player))]--;
00195 assert(pawns[playerToIndex(BLACK)] + pawns[playerToIndex(WHITE)] == 18);
00196 assert(pawn_on_stand[playerToIndex(BLACK)] >= 0);
00197 assert(pawn_on_stand[playerToIndex(WHITE)] >= 0);
00198 break;
00199 case LANCE:
00200 lance_on_stand[playerToIndex(player)]++;
00201 break;
00202 case KNIGHT:
00203 knight_on_stand[playerToIndex(player)]++;
00204 break;
00205 case GOLD:
00206 golds[playerToIndex(player)]++;
00207 golds[playerToIndex(alt(player))]--;
00208 assert(golds[playerToIndex(BLACK)] + golds[playerToIndex(WHITE)] == 4);
00209 break;
00210 default:
00211 ;
00212 }
00213 }
00214 }
00215
00216 int expect(const SimpleState& state, Move move, Progress16 progress16,
00217 Progress16 black,
00218 Progress16 white) const
00219 {
00220 MinorPieceBonus new_eval = *this;
00221 if (move.isDrop()){
00222 const Ptype ptype = move.ptype();
00223 if (ptype == PAWN) {
00224 new_eval.pawn_on_stand[playerToIndex(state.getTurn())]--;
00225 assert(new_eval.pawn_on_stand[playerToIndex(BLACK)] >= 0);
00226 assert(new_eval.pawn_on_stand[playerToIndex(WHITE)] >= 0);
00227 }
00228 else if (ptype == LANCE) {
00229 new_eval.lance_on_stand[playerToIndex(state.getTurn())]--;
00230 }
00231 else if (ptype == KNIGHT) {
00232 new_eval.knight_on_stand[playerToIndex(state.getTurn())]--;
00233 }
00234 return new_eval.value(progress16, black, white);
00235 }
00236 Ptype ptype = move.capturePtype();
00237 if (ptype != PTYPE_EMPTY) {
00238 if (unpromote(ptype) == PAWN) {
00239 new_eval.pawn_on_stand[playerToIndex(state.getTurn())]++;
00240 new_eval.pawns[playerToIndex(state.getTurn())]++;
00241 new_eval.pawns[playerToIndex(alt(state.getTurn()))]--;
00242 assert(new_eval.pawns[playerToIndex(BLACK)] + new_eval.pawns[playerToIndex(WHITE)] == 18);
00243 assert(new_eval.pawn_on_stand[playerToIndex(BLACK)] >= 0);
00244 assert(new_eval.pawn_on_stand[playerToIndex(WHITE)] >= 0);
00245 }
00246 else if (unpromote(ptype) == LANCE) {
00247 new_eval.lance_on_stand[playerToIndex(state.getTurn())]++;
00248 }
00249 else if (unpromote(ptype) == KNIGHT) {
00250 new_eval.knight_on_stand[playerToIndex(state.getTurn())]++;
00251 }
00252 else if (unpromote(ptype) == GOLD) {
00253 new_eval.golds[playerToIndex(state.getTurn())]++;
00254 new_eval.golds[playerToIndex(alt(state.getTurn()))]--;
00255 assert(new_eval.golds[playerToIndex(BLACK)] + new_eval.golds[playerToIndex(WHITE)] == 4);
00256 }
00257 }
00258 return new_eval.value(progress16, black, white);
00259 }
00260
00261 MinorPieceDebugInfo debugInfo(Progress16 progress16,
00262 Progress16 black, Progress16 white) const
00263 {
00264 MinorPieceDebugInfo debug_info;
00265 debug_info.pawn_bonus = pawnBonus(progress16);
00266 debug_info.lance_bonus = lanceBonus(progress16);
00267 debug_info.knight_bonus = knightBonus(progress16);
00268 debug_info.gold_bonus = goldBonus(black, white);
00269
00270 return debug_info;
00271 }
00272 };
00273 }
00274 }
00275
00276 #endif
00277
00278
00279
00280