00001 #ifndef OSL_NUM_SIMPLE_EFFECT_H
00002 #define OSL_NUM_SIMPLE_EFFECT_H
00003
00004 #include "osl/effect/numBitmapEffect.h"
00005 #include "osl/misc/carray.h"
00006 #include "osl/container/boardMask.h"
00007 #include "osl/container/bitXmask.h"
00008 #include "osl/piece.h"
00009 #include "osl/state/simpleState.h"
00010 #include "osl/mobility/mobilityTable.h"
00011 #include "osl/effect/effectedNumTable.h"
00012
00013 #include <boost/static_assert.hpp>
00014
00015 namespace osl
00016 {
00017 namespace checkmate
00018 {
00019 class King8Info;
00020 }
00021 namespace effect
00022 {
00023 class NumSimpleEffectTable;
00024 bool operator==(const NumSimpleEffectTable&,const NumSimpleEffectTable&);
00025 std::ostream& operator<<(std::ostream&, const NumSimpleEffectTable&);
00026
00030 class NumSimpleEffectTable
00031 {
00032 protected:
00033 CArray<NumBitmapEffect, Square::SIZE> effects
00034 #ifdef __GNUC__
00035 __attribute__((aligned(16)))
00036 #endif
00037 ;
00038 CArray<BoardMask,2> changed_effects;
00040 NumBitmapEffect changed_effect_pieces;
00041 public:
00042 CArray<PieceMask,2> effected_mask;
00043 CArray<PieceMask,2> effected_changed_mask;
00045 mobility::MobilityTable mobilityTable;
00047 EffectedNumTable effectedNumTable;
00057 template<Player P,Ptype T,Direction Dir,NumBitmapEffect::Op OP,bool UC>
00058 void doEffectShort(const SimpleState& state,Square pos,int num)
00059 {
00060 if ((PtypeTraits<T>::moveMask & DirectionTraits<Dir>::mask)!=0)
00061 {
00062 const Square target = pos+DirectionPlayerTraits<Dir,P>::offset();
00063 effects[target.index()].template opEqual<OP>(NumBitmapEffect::makeEffect<P>(num));
00064 if(UC){
00065 int posIndex=BoardMask::index(pos);
00066 changed_effects[P].set(posIndex+BoardMask::getIndexOffset<Dir,P>());
00067 int num1;
00068 if(Piece::isPieceNum(num1=state.pieceAt(target).number())){
00069 if(OP==NumBitmapEffect::Add){
00070 effected_mask[P].set(num1);
00071 }
00072 else{
00073 if((effects[target.index()].getMask(1)&NumBitmapEffect::playerEffectMask(P)).none()){
00074 effected_mask[P].reset(num1);
00075 }
00076 }
00077 effected_changed_mask[P].set(num1);
00078 }
00079 }
00080 }
00081 }
00092 template<Player P,Ptype T,Direction Dir,NumBitmapEffect::Op OP,bool UC>
00093 void doEffectLong(const SimpleState& state,Square pos,int num)
00094 {
00095 if ((PtypeTraits<T>::moveMask & DirectionTraits<DirectionPlayerTraits<Dir,P>::directionByBlack>::mask)!=0)
00096 {
00097 int posIndex;
00098 if(UC){
00099 posIndex=BoardMask::index(pos);
00100 }
00101 const Offset offset=DirectionPlayerTraits<Dir,BLACK>::offset();
00102 assert(!offset.zero());
00103 NumBitmapEffect effect=NumBitmapEffect::makeLongEffect<P>(num);
00104
00105 const Direction SD=longToShort(Dir);
00106 if(OP==NumBitmapEffect::Sub){
00107 Square ePos=mobilityTable.get(longToShort(Dir),num);
00108 int count=((SD==D || SD==DL || SD==DR) ? ePos.y()-pos.y() :
00109 ( (SD==U || SD==UL || SD==UR) ? pos.y()-ePos.y() :
00110 ( SD==L ? ePos.x()-pos.x() : pos.x()-ePos.x())));
00111 assert(0<=count && count<=9);
00112 if(UC){
00113 for(int i=1;i<count;i++){
00114 pos+=offset;
00115 posIndex+=BoardMask::getIndexOffset<Dir,BLACK>();
00116 effects[pos.index()].template opEqual<OP>(effect);
00117 changed_effects[P].set(posIndex);
00118 }
00119 Piece p;
00120 mobilityTable.set(longToShort(Dir),num,Square::STAND());
00121 int num1=state.pieceAt(ePos).number();
00122 if (!Piece::isEdgeNum(num1)){
00123 effectedNumTable[num1][SD]=EMPTY_NUM;
00124 effects[ePos.index()].template opEqual<OP>(effect);
00125 effected_changed_mask[P].set(num1);
00126 posIndex+=BoardMask::getIndexOffset<Dir,BLACK>();
00127 changed_effects[P].set(posIndex);
00128 if((effects[ePos.index()].getMask(1)&NumBitmapEffect::playerEffectMask(P)).none()){
00129 effected_mask[P].reset(num1);
00130 }
00131 }
00132 }
00133 else{
00134 for(int i=0;i<count;i++){
00135 pos+=offset;
00136 effects[pos.index()].template opEqual<OP>(effect);
00137 }
00138 int num1=state.pieceAt(ePos).number();
00139 if (!Piece::isEdgeNum(num1))
00140 effectedNumTable[num1][SD]=EMPTY_NUM;
00141 }
00142 }
00143 else{
00144 for (;;)
00145 {
00146 pos=pos+offset;
00147 if(UC){
00148 posIndex+=BoardMask::getIndexOffset<Dir,BLACK>();
00149 changed_effects[P].set(posIndex);
00150 }
00151 effects[pos.index()].template opEqual<OP>(effect);
00152
00153 int num1=state.pieceAt(pos).number();
00154 if (!Piece::isEmptyNum(num1)){
00155 if(UC){
00156 mobilityTable.set(longToShort(Dir),num,pos);
00157 if(!Piece::isEdgeNum(num1)){
00158 effectedNumTable[num1][SD]=num;
00159 changed_effects[P].set(posIndex);
00160 effected_mask[P].set(num1);
00161 effected_changed_mask[P].set(num1);
00162 }
00163 }
00164 else if(!Piece::isEdgeNum(num1)){
00165 effectedNumTable[num1][SD]=num;
00166 }
00167 break;
00168 }
00169 }
00170 }
00171 }
00172 }
00182 template<Player P,Ptype T,NumBitmapEffect::Op OP,bool UC>
00183 void doEffectBy(const SimpleState& state,Square pos,int num);
00192 template<NumBitmapEffect::Op OP,bool UC>
00193 void doEffect(const SimpleState& state,PtypeO ptypeo,Square pos,int num);
00194
00201 template<NumBitmapEffect::Op OP,bool UC>
00202 void doEffect(const SimpleState& state,Piece p)
00203 {
00204 doEffect<OP,UC>(state,p.ptypeO(),p.square(),p.number());
00205 }
00210 void init(const SimpleState& state);
00214 NumSimpleEffectTable(const SimpleState& state)
00215 {
00216 assert(reinterpret_cast<size_t>(this) % 16 == 0);
00217 init(state);
00218 }
00223 const NumBitmapEffect effectSetAt(Square pos) const
00224 {
00225 return effects[pos.index()];
00226 }
00233 template<NumBitmapEffect::Op OP,bool UC>
00234 void doBlockAt(const SimpleState& state,Square pos,int piece_num);
00235 friend bool operator==(const NumSimpleEffectTable& et1,const NumSimpleEffectTable& et2);
00236
00237
00238
00239 const BoardMask changedEffects(Player pl) const{
00240 return changed_effects[pl];
00241 }
00242 const NumBitmapEffect changedPieces() const {
00243 return changed_effect_pieces;
00244 }
00245 const PieceMask effectedMask(Player pl) const {
00246 return effected_mask[playerToIndex(pl)];
00247 }
00248 const PieceMask effectedChanged(Player pl) const {
00249 return effected_changed_mask[playerToIndex(pl)];
00250 }
00251 void setChangedPieces(NumBitmapEffect const& effect) {
00252 changed_effect_pieces |= effect;
00253 }
00254 void clearChangedEffects(){
00255 changed_effects[0].clear();
00256 changed_effects[1].clear();
00257 changed_effect_pieces.resetAll();
00258 }
00259 void invalidateChangedEffects(){
00260 changed_effects[0].invalidate();
00261 changed_effects[1].invalidate();
00262 changed_effect_pieces.setAll();
00263 }
00264 void clearEffectedChanged(){
00265 effected_changed_mask[0].resetAll();
00266 effected_changed_mask[1].resetAll();
00267 }
00269 void copyFrom(const NumSimpleEffectTable& src);
00270 };
00271
00272 inline bool operator!=(const NumSimpleEffectTable& et1,const NumSimpleEffectTable& et2)
00273 {
00274 return !(et1==et2);
00275 }
00276
00277 }
00278 using effect::NumBitmapEffect;
00279
00280 }
00281
00288 template<osl::effect::NumBitmapEffect::Op OP,bool UC>
00289 void osl::effect::
00290 NumSimpleEffectTable::doBlockAt(const SimpleState& state,Square pos,int piece_num)
00291 {
00292 if(UC){
00293 setChangedPieces(effects[pos.index()]);
00294 }
00295 mask_t mask1 =((effects[pos.index()].getMask(1))
00296 & NumBitmapEffect::longEffectMask());
00297 while (mask1.any()){
00298 int num=mask1.takeOneBit()+NumBitmapEffect::longToNumOffset;
00299 assert(32<=num && num<=39);
00300 Piece p1=state.pieceOf(num);
00301 Player pl1=p1.owner();
00302 assert(p1.ptype()!=PPAWN);
00303 Square pos1=p1.square();
00304 Offset offset0;
00305 Direction d=Board_Table.getShort8<BLACK>(pos1,pos,offset0);
00306 if(OP==NumBitmapEffect::Sub){
00307 Square endSquare=mobilityTable.get(d,num);
00308 NumBitmapEffect effect=NumBitmapEffect::makeLongEffect(pl1,num);
00309 Piece p;
00310 Square pos2=pos+offset0;
00311 int pos2Index, offset81;
00312 if(UC){
00313 int posIndex=BoardMask::index(pos);
00314 pos2Index=BoardMask::index(pos2);
00315 offset81=pos2Index-posIndex;
00316 }
00317 for(;pos2!=endSquare;pos2+=offset0){
00318 if(UC){
00319 changed_effects[pl1].set(pos2Index);
00320 pos2Index+=offset81;
00321 }
00322 effects[pos2.index()].template opEqual<OP>(effect);
00323 }
00324 effects[pos2.index()].template opEqual<OP>(effect);
00325 int num1=state.pieceAt(endSquare).number();
00326 if (!Piece::isEdgeNum(num1)){
00327 effectedNumTable[num1][d]=EMPTY_NUM;
00328 if(UC){
00329 changed_effects[pl1].set(pos2Index);
00330 if((effects[endSquare.index()].getMask(1)&NumBitmapEffect::playerEffectMask(pl1)).none()){
00331 effected_mask[pl1].reset(num1);
00332 }
00333 effected_changed_mask[pl1].set(num1);
00334 mobilityTable.set(d,num,pos);
00335 }
00336 }
00337 else
00338 mobilityTable.set(d,num,pos);
00339 effectedNumTable[piece_num][d]=num;
00340 }
00341 else{
00342 NumBitmapEffect effect=NumBitmapEffect::makeLongEffect(pl1,num);
00343 Square pos2=pos+offset0;
00344 int pos2Index, offset81;
00345 if(UC){
00346 int posIndex=BoardMask::index(pos);
00347 pos2Index=BoardMask::index(pos2);
00348 offset81=pos2Index-posIndex;
00349 }
00350 for(;;){
00351 int num1=state.pieceAt(pos2).number();
00352 if(!Piece::isEmptyNum(num1)){
00353 if(UC){
00354 mobilityTable.set(d,num,pos2);
00355 if(!Piece::isEdgeNum(num1)){
00356 effectedNumTable[num1][d]=num;
00357 effects[pos2.index()].template opEqual<OP>(effect);
00358 changed_effects[pl1].set(pos2Index);
00359 effected_mask[pl1].set(num1);
00360 effected_changed_mask[pl1].set(num1);
00361 }
00362 }
00363 else if(!Piece::isEdgeNum(num1)){
00364 effectedNumTable[num1][d]=num;
00365 effects[pos2.index()].template opEqual<OP>(effect);
00366 }
00367 break;
00368 }
00369 if(UC){
00370 changed_effects[pl1].set(pos2Index);
00371 pos2Index+=offset81;
00372 }
00373 effects[pos2.index()].template opEqual<OP>(effect);
00374 pos2+=offset0;
00375 }
00376 }
00377 }
00378 }
00379
00380 #endif // OSL_NUM_SIMPLE_EFFECT_H
00381
00382
00383
00384