00001 #ifndef _NUM_SIMPLE_EFFECT_TCC
00002 #define _NUM_SIMPLE_EFFECT_TCC
00003
00004 #include "osl/effect/numSimpleEffect.h"
00005 #include "osl/apply_move/doUndoMoveLock.h"
00006 #include "osl/pieceTable.h"
00007 #include "osl/record/csa.h"
00008 #include <iostream>
00009
00016 template<class State>
00017 template<osl::effect::NumBitmapEffect::Op OP>
00018 void
00019 #ifdef __GNUC__
00020 __attribute__ ((used))
00021 #endif
00022 osl::effect::
00023 NumSimpleEffectTable<State>::doBlockAt(const State& state,Position pos)
00024 {
00025 mask_t mask1 =((effects[pos.index()].getMask(1))
00026 & NumSimpleEffectUtil::longEffectMask());
00027 while (mask1.any()){
00028 int num=mask1.takeOneBit()+NumSimpleEffectUtil::longToNumOffset;
00029 assert(32<=num && num<=39);
00030 Piece p1=state.getPieceOf(num);
00031
00032 assert(p1.ptype()!=PPAWN);
00033 Position pos1=p1.position();
00034 Offset offset0=Board_Table.getShortOffset(Offset32(pos,pos1));
00035 assert(! offset0.zero());
00036 NumBitmapEffect effect=NumSimpleEffectUtil::makeLongEffect(p1.owner(),num);
00037 Position pos2=pos+offset0;
00038 effects[pos2.index()].template opEqual<OP>(effect);
00039 for(;;){
00040 if (! state.getPieceAt(pos2).isEmpty()) break;
00041 pos2+=offset0;
00042 effects[pos2.index()].template opEqual<OP>(effect);
00043 }
00044 }
00045 }
00046 template<class State>
00047 template<osl::effect::NumBitmapEffect::Op OP>
00048 void osl::effect::
00049 NumSimpleEffectTable<State>::doEffect(const State& state,PtypeO ptypeo,Position pos,int num)
00050 {
00051 switch(ptypeo){
00052 case NEW_PTYPEO(WHITE,PAWN): doEffectBy<WHITE,PAWN,OP>(state,pos,num); break;
00053 case NEW_PTYPEO(WHITE,LANCE): doEffectBy<WHITE,LANCE,OP>(state,pos,num); break;
00054 case NEW_PTYPEO(WHITE,KNIGHT): doEffectBy<WHITE,KNIGHT,OP>(state,pos,num); break;
00055 case NEW_PTYPEO(WHITE,SILVER): doEffectBy<WHITE,SILVER,OP>(state,pos,num); break;
00056 case NEW_PTYPEO(WHITE,PPAWN):
00057 case NEW_PTYPEO(WHITE,PLANCE):
00058 case NEW_PTYPEO(WHITE,PKNIGHT):
00059 case NEW_PTYPEO(WHITE,PSILVER):
00060 case NEW_PTYPEO(WHITE,GOLD): doEffectBy<WHITE,GOLD,OP>(state,pos,num); break;
00061 case NEW_PTYPEO(WHITE,BISHOP): doEffectBy<WHITE,BISHOP,OP>(state,pos,num); break;
00062 case NEW_PTYPEO(WHITE,PBISHOP): doEffectBy<WHITE,PBISHOP,OP>(state,pos,num); break;
00063 case NEW_PTYPEO(WHITE,ROOK): doEffectBy<WHITE,ROOK,OP>(state,pos,num); break;
00064 case NEW_PTYPEO(WHITE,PROOK): doEffectBy<WHITE,PROOK,OP>(state,pos,num); break;
00065 case NEW_PTYPEO(WHITE,KING): doEffectBy<WHITE,KING,OP>(state,pos,num); break;
00066 case NEW_PTYPEO(BLACK,PAWN): doEffectBy<BLACK,PAWN,OP>(state,pos,num); break;
00067 case NEW_PTYPEO(BLACK,LANCE): doEffectBy<BLACK,LANCE,OP>(state,pos,num); break;
00068 case NEW_PTYPEO(BLACK,KNIGHT): doEffectBy<BLACK,KNIGHT,OP>(state,pos,num); break;
00069 case NEW_PTYPEO(BLACK,SILVER): doEffectBy<BLACK,SILVER,OP>(state,pos,num); break;
00070 case NEW_PTYPEO(BLACK,PPAWN):
00071 case NEW_PTYPEO(BLACK,PLANCE):
00072 case NEW_PTYPEO(BLACK,PKNIGHT):
00073 case NEW_PTYPEO(BLACK,PSILVER):
00074 case NEW_PTYPEO(BLACK,GOLD): doEffectBy<BLACK,GOLD,OP>(state,pos,num); break;
00075 case NEW_PTYPEO(BLACK,BISHOP): doEffectBy<BLACK,BISHOP,OP>(state,pos,num); break;
00076 case NEW_PTYPEO(BLACK,PBISHOP): doEffectBy<BLACK,PBISHOP,OP>(state,pos,num); break;
00077 case NEW_PTYPEO(BLACK,ROOK): doEffectBy<BLACK,ROOK,OP>(state,pos,num); break;
00078 case NEW_PTYPEO(BLACK,PROOK): doEffectBy<BLACK,PROOK,OP>(state,pos,num); break;
00079 case NEW_PTYPEO(BLACK,KING): doEffectBy<BLACK,KING,OP>(state,pos,num); break;
00080 default: assert(0);
00081 }
00082 return;
00083 }
00084
00085 template<class State>
00086 template<osl::Player P, osl::Ptype T, osl::effect::NumBitmapEffect::Op OP>
00087 void osl::effect::
00088 NumSimpleEffectTable<State>::doEffectBy(const State& state,Position pos,int num)
00089 {
00090 doEffectShort<P,T,UL,OP>(pos,num);
00091 doEffectShort<P,T,U,OP>(pos,num);
00092 doEffectShort<P,T,UR,OP>(pos,num);
00093 doEffectShort<P,T,L,OP>(pos,num);
00094 doEffectShort<P,T,R,OP>(pos,num);
00095 doEffectShort<P,T,DL,OP>(pos,num);
00096 doEffectShort<P,T,D,OP>(pos,num);
00097 doEffectShort<P,T,DR,OP>(pos,num);
00098 doEffectShort<P,T,UUL,OP>(pos,num);
00099 doEffectShort<P,T,UUR,OP>(pos,num);
00100 doEffectLong<P,T,LONG_UL,OP>(state,pos,num);
00101 doEffectLong<P,T,LONG_U,OP>(state,pos,num);
00102 doEffectLong<P,T,LONG_UR,OP>(state,pos,num);
00103 doEffectLong<P,T,LONG_L,OP>(state,pos,num);
00104 doEffectLong<P,T,LONG_R,OP>(state,pos,num);
00105 doEffectLong<P,T,LONG_DL,OP>(state,pos,num);
00106 doEffectLong<P,T,LONG_D,OP>(state,pos,num);
00107 doEffectLong<P,T,LONG_DR,OP>(state,pos,num);
00108 }
00109
00110 template<class State>
00111 void osl::effect::
00112 NumSimpleEffectTable<State>::init(const State& state)
00113 {
00114 std::fill(effects.begin(), effects.end(),NumBitmapEffect());
00115 for(int num=0;num<40;num++){
00116 if (state.isOnBoard(num)){
00117 Piece p=state.getPieceOf(num);
00118 doEffect<NumBitmapEffect::Add>(state,p);
00119 }
00120 }
00121 }
00122 template<class State>
00123 bool osl::effect::operator==(const NumSimpleEffectTable<State>& et1,const NumSimpleEffectTable<State>& et2)
00124 {
00125 for(int y=1;y<=9;y++)
00126 for(int x=9;x>0;x--){
00127 Position pos(x,y);
00128 if (!(et1.getEffect(pos)==et2.getEffect(pos))) return false;
00129 }
00130 return true;
00131 }
00132
00133 template<class State>
00134 std::ostream& osl::effect::operator<<(std::ostream& os,const NumSimpleEffectTable<State> & effectTable)
00135 {
00136 os << "EffectPass" << std::endl;
00137 for(int y=1;y<=9;y++){
00138 for(int x=9;x>0;x--){
00139 Position pos(x,y);
00140 os << static_cast<unsigned int>(effectTable.getEffectPass(pos)) << " ";
00141 }
00142 os << std::endl;
00143 }
00144 os << "Effect" << std::endl;
00145 for(int y=1;y<=9;y++){
00146 for(int x=9;x>0;x--){
00147 Position pos(x,y);
00148 os << effectTable.getEffect(pos) << " ";
00149 }
00150 os << std::endl;
00151 }
00152 return os;
00153 }
00154
00155 template<class State>
00156 bool osl::effect::operator==(const NumSimpleEffect<State>& st1,
00157 const NumSimpleEffect<State>& st2)
00158 {
00159 assert(st1.isConsistent(false));
00160 assert(st2.isConsistent(false));
00161 if (!(st1.effects == st2.effects))
00162 return false;
00163 if (!(st1.onBoardMask == st2.onBoardMask))
00164 return false;
00165 return (static_cast<const State&>(st1)
00166 == static_cast<const State&>(st2));
00167 }
00168
00169 template<class State>
00170 osl::effect::
00171 NumSimpleEffect<State>::NumSimpleEffect(const SimpleState& st)
00172 : State(st),effects(st)
00173 {
00174 onBoardMask[0].resetAll();
00175 onBoardMask[1].resetAll();
00176 for(int num=0;num<40;num++){
00177 Piece p=State::getPieceOf(num);
00178 if (p.isOnBoard()){
00179 getOnBoardMask(p.owner()).set(num);
00180 }
00181 }
00182 }
00183
00184 template<class State>
00185 osl::effect::
00186 NumSimpleEffect<State>::~NumSimpleEffect()
00187 {
00188 }
00189
00190 template<class State>
00191 void osl::effect::NumSimpleEffect<State>::
00192 doSimpleMove(Position from, Position to, int promoteMask)
00193 {
00194 Piece oldPiece;
00195 int num;
00196 PtypeO oldPtypeO, newPtypeO;
00197 if (State::getTurn()==BLACK){
00198 apply_move::ApplyDoUndoSimpleMove<BLACK,NumSimpleEffect<State> >
00199 ::prologue(*this, from, to, promoteMask,
00200 oldPiece, num, oldPtypeO, newPtypeO);
00201 }
00202 else{
00203 apply_move::ApplyDoUndoSimpleMove<WHITE,NumSimpleEffect<State> >
00204 ::prologue(*this, from, to, promoteMask,
00205 oldPiece, num, oldPtypeO, newPtypeO);
00206 }
00207 if (promoteMask!=0 && num < PtypeTraits<PAWN>::indexLimit)
00208 clearPawn(State::getTurn(),from);
00209 }
00210 template<class State>
00211 void osl::effect::NumSimpleEffect<State>::
00212 doCaptureMove(Position from, Position to, Piece target, int promoteMask)
00213 {
00214 Piece oldPiece;
00215 PtypeO oldPtypeO, capturePtypeO, newPtypeO;
00216 int num0, num1, num1Index;
00217 mask_t num1Mask;
00218 if(State::getTurn()==BLACK){
00219 apply_move::ApplyDoUndoCaptureMove<BLACK,NumSimpleEffect<State> >
00220 ::prologue(*this, from, to, target, promoteMask, oldPiece, oldPtypeO,
00221 capturePtypeO, newPtypeO, num0, num1, num1Index,num1Mask);
00222 }
00223 else{
00224 apply_move::ApplyDoUndoCaptureMove<WHITE,NumSimpleEffect<State> >
00225 ::prologue(*this, from, to, target, promoteMask, oldPiece, oldPtypeO,
00226 capturePtypeO, newPtypeO, num0, num1, num1Index,num1Mask);
00227 }
00228 const Ptype capturePtype=target.ptype();
00229 if (capturePtype==PAWN)
00230 clearPawn(alt(State::getTurn()),to);
00231 if (promoteMask!=0 && num0<PtypeTraits<PAWN>::indexLimit)
00232 clearPawn(State::getTurn(),from);
00233 }
00234 template <class State>
00235 void osl::effect::NumSimpleEffect<State>::
00236 doDropMove(Position to,Ptype ptype)
00237 {
00238 Piece oldPiece;
00239 PtypeO ptypeO;
00240 int num, numIndex;
00241 mask_t numMask;
00242 if(State::getTurn()==BLACK){
00243 apply_move::ApplyDoUndoDropMove<BLACK,NumSimpleEffect<State> >
00244 ::prologue(*this, to, ptype, oldPiece, num, ptypeO, numIndex, numMask);
00245 }
00246 else{
00247 apply_move::ApplyDoUndoDropMove<WHITE,NumSimpleEffect<State> >
00248 ::prologue(*this, to, ptype, oldPiece, num, ptypeO, numIndex, numMask);
00249 }
00250 if (ptype==PAWN)
00251 setPawn(State::getTurn(),to);
00252 }
00253 template<class State>
00254 bool osl::effect::NumSimpleEffect<State>::isConsistent(bool showError) const
00255 {
00256 if (!State::isConsistent(showError))
00257 {
00258 if (showError)
00259 std::cerr << "error before effect\n";
00260 return false;
00261 }
00262 NumSimpleEffectTable<typename State::simple_state_t> effects1(*this);
00263 if (!(effects1==effects))
00264 {
00265 if (showError)
00266 {
00267 std::cerr << "Effect error 1" << std::endl;
00268 std::cerr << *this;
00269 for(int y=1;y<=9;y++)
00270 for(int x=9;x>0;x--)
00271 {
00272 Position pos(x,y);
00273 if (!(effects1.getEffect(pos)==effects.getEffect(pos)))
00274 {
00275 std::cerr << pos << ",real=" << effects.getEffect(pos) << ",ideal=" << effects1.getEffect(pos) << std::endl;
00276 }
00277 }
00278 }
00279 return false;
00280 }
00281 return true;
00282 }
00283
00284 template<class State>
00285 bool osl::effect::NumSimpleEffect<State>::isValidMoveByRule(Move move,bool showError) const
00286 {
00287 return State::isValidMoveByRule(move,showError);
00288 }
00289
00290
00291 template<class State>
00292 template <bool show_error>
00293 bool
00294 #ifdef __GNUC__
00295 __attribute__ ((used))
00296 #endif
00297 osl::effect::NumSimpleEffect<State>::isAlmostValidMove(Move move) const{
00298 assert(move.isValid());
00299 assert(getTurn() == move.player());
00300 assert(isValidMoveByRule(move, true));
00301
00302 const Position from=move.from();
00303 const Position to=move.to();
00304 const Piece toPiece=getPieceAt(to);
00305 const Ptype ptype=move.ptype();
00306 const Player turn = move.player();
00307
00308 if (from.isPieceStand()){
00309
00310 if (! toPiece.isEmpty()) {
00311 if (show_error) std::cerr << "drop on to piece : " << move << std::endl;
00312 return false;
00313 }
00314
00315 if (! hasPieceOnStand(turn,ptype)) {
00316 if (show_error) std::cerr << turn << " don't have : " << ptype << std::endl;
00317 return false;
00318 }
00319
00320 if (ptype==PAWN && State::isPawnMaskSet(turn, to.x())) {
00321 if (show_error) std::cerr << " Double Pawn : " << move << std::endl;
00322 return false;
00323 }
00324 }
00325 else{
00326 const Piece from_piece = getPieceAt(from);
00327
00328 if (from_piece.isEmpty() || (from_piece.owner() != turn)){
00329 if (show_error)
00330 std::cerr << " No such piece0 : " << move << std::endl;
00331 return false;
00332 }
00333
00334 if (move.isPromote()){
00335
00336 if (from_piece.ptype() != unpromote(move.ptype()))
00337 {
00338 if (show_error)
00339 std::cerr << " No such piece1 : " << move << std::endl;
00340 return false;
00341 }
00342 if (from_piece.isPromotedNotKingGold()){
00343 if (show_error)
00344 std::cerr << " can't promote promoted piece : " << move << std::endl;
00345 return false;
00346 }
00347 }
00348 else{
00349
00350 if (from_piece.ptype() != move.ptype()){
00351 if (show_error)
00352 std::cerr << " No such piece2 : " << move << std::endl;
00353 return false;
00354 }
00355 }
00356
00357 if (!toPiece.isEmpty() && toPiece.owner()==turn) {
00358 if (show_error) std::cerr << " No move on : " << move << std::endl;
00359 return false;
00360 }
00361 if(!hasEffectByPiece(from_piece,to)){
00362 if (show_error) {
00363 std::cerr << " No such move2 : " << move << std::endl;
00364 }
00365 return false;
00366 }
00367
00368 if (toPiece.ptype()!=move.capturePtype()) {
00369 if (show_error) std::cerr << " Not such capture : " << move
00370 << std::endl << *this;
00371 return false;
00372 }
00373 }
00374
00375 assert(isValidMoveByRule(move, true));
00376 return true;
00377 }
00378
00379 template<class State>
00380 bool osl::effect::NumSimpleEffect<State>::
00381 isAlmostValidMove(Move move,bool show_error) const{
00382 if(show_error)
00383 return isAlmostValidMove<true>(move);
00384 else
00385 return isAlmostValidMove<false>(move);
00386 }
00387
00388 template<class State>
00389 std::ostream&
00390 osl::effect::operator<<(std::ostream& os,const NumSimpleEffect<State>& state)
00391 {
00392 os<< static_cast<State const&>(state);
00393 for(int y=1;y<=9;y++){
00394 os << 'P' << y;
00395 for(int x=9;x>0;x--){
00396 Position pos(x,y);
00397 os << record::csa::show(state.getPieceAt(pos)) << state.getEffect(pos);
00398 }
00399 os << std::endl;
00400 }
00401
00402 for(int num=0;num<Piece::SIZE;num++){
00403 if (state.standMask(BLACK).test(num)){
00404 os << "P+00" << record::csa::show(Piece_Table.getPtypeOf(num))
00405 << std::endl;
00406 }
00407 else if (state.standMask(WHITE).test(num)){
00408 os << "P-00" << record::csa::show(Piece_Table.getPtypeOf(num))
00409 << std::endl;
00410 }
00411 }
00412 return os;
00413 }
00414
00415 template <class BaseState>
00416 class osl::apply_move::DoUndoMoveLockSimple<osl::effect::NumSimpleEffect<BaseState> >
00417 : public apply_move::DoUndoMoveLockCleanUp
00418 {
00419 typedef NumSimpleEffect<BaseState> state_t;
00420 state_t& state;
00421 Position from, to;
00422 Piece oldPiece;
00423 PtypeO oldPtypeO, newPtypeO;
00424 int num;
00425 bool pawnPromotion;
00426 public:
00427 DoUndoMoveLockSimple(state_t& s,
00428 Position f, Position t, int promoteMask)
00429 : state(s), from(f), to(t)
00430 {
00431 if(state.getTurn()==BLACK){
00432 apply_move::ApplyDoUndoSimpleMove<BLACK,NumSimpleEffect<BaseState> >::
00433 prologue(s, from, to, promoteMask, oldPiece, num, oldPtypeO, newPtypeO);
00434 }
00435 else{
00436 apply_move::ApplyDoUndoSimpleMove<WHITE,NumSimpleEffect<BaseState> >::
00437 prologue(s, from, to, promoteMask, oldPiece, num, oldPtypeO, newPtypeO);
00438 }
00439 pawnPromotion = (promoteMask!=0) && (num < PtypeTraits<PAWN>::indexLimit);
00440 if (pawnPromotion)
00441 s.clearPawn(s.getTurn(),from);
00442 }
00443 ~DoUndoMoveLockSimple()
00444 {
00445 if (pawnPromotion)
00446 state.setPawn(state.getTurn(),from);
00447 if(state.getTurn()==BLACK){
00448 apply_move::ApplyDoUndoSimpleMove<BLACK,NumSimpleEffect<BaseState> >::
00449 epilogue(state, from, to, oldPiece, num, oldPtypeO, newPtypeO);
00450 }
00451 else{
00452 apply_move::ApplyDoUndoSimpleMove<WHITE,NumSimpleEffect<BaseState> >::
00453 epilogue(state, from, to, oldPiece, num, oldPtypeO, newPtypeO);
00454 }
00455 }
00456
00457 };
00458
00459 template <class BaseState>
00460 class osl::apply_move::DoUndoMoveLockDrop<osl::effect::NumSimpleEffect<BaseState> >
00461 : public apply_move::DoUndoMoveLockCleanUp
00462 {
00463 typedef NumSimpleEffect<BaseState> state_t;
00464 state_t& state;
00465 Position to;
00466 Piece oldPiece;
00467 PtypeO ptypeO;
00468 int num, numIndex;
00469 mask_t numMask;
00470 bool pawnDrop;
00471 public:
00472 DoUndoMoveLockDrop(state_t& s, Position t, Ptype ptype)
00473 : state(s), to(t)
00474 {
00475 if(state.getTurn()==BLACK){
00476 apply_move::ApplyDoUndoDropMove<BLACK,NumSimpleEffect<BaseState> >::
00477 prologue(s, to, ptype, oldPiece, num, ptypeO, numIndex, numMask);
00478 }
00479 else{
00480 apply_move::ApplyDoUndoDropMove<WHITE,NumSimpleEffect<BaseState> >::
00481 prologue(s, to, ptype, oldPiece, num, ptypeO, numIndex, numMask);
00482 }
00483 pawnDrop = (ptype==PAWN);
00484 if (pawnDrop)
00485 s.setPawn(s.getTurn(),to);
00486 }
00487 ~DoUndoMoveLockDrop()
00488 {
00489 if (pawnDrop)
00490 state.clearPawn(state.getTurn(),to);
00491 if(state.getTurn()==BLACK){
00492 apply_move::ApplyDoUndoDropMove<BLACK,NumSimpleEffect<BaseState> >::
00493 epilogue(state, to, oldPiece, num, ptypeO, numIndex, numMask);
00494 }
00495 else{
00496 apply_move::ApplyDoUndoDropMove<WHITE,NumSimpleEffect<BaseState> >::
00497 epilogue(state, to, oldPiece, num, ptypeO, numIndex, numMask);
00498 }
00499 }
00500 };
00501
00502 template <class BaseState>
00503 class osl::apply_move::DoUndoMoveLockCapture<osl::effect::NumSimpleEffect<BaseState> >
00504 : public apply_move::DoUndoMoveLockCleanUp
00505 {
00506 typedef NumSimpleEffect<BaseState> state_t;
00507 state_t& state;
00508 Position from, to;
00509 Piece target;
00510 Piece oldPiece;
00511 PtypeO oldPtypeO, capturePtypeO, newPtypeO;
00512 int num0, num1;
00513 int num1Index;
00514 mask_t num1Mask;
00515 Ptype capturePtype;
00516 bool pawnPromotion, pawnCapture;
00517 public:
00518 DoUndoMoveLockCapture(state_t& s, Position f, Position t, Piece tg,
00519 int promoteMask)
00520 : state(s), from(f), to(t), target(tg)
00521 {
00522 if(state.getTurn()==BLACK){
00523 apply_move::ApplyDoUndoCaptureMove<BLACK,NumSimpleEffect<BaseState> >::
00524 prologue(s, from, to, target, promoteMask, oldPiece, oldPtypeO,
00525 capturePtypeO, newPtypeO, num0, num1, num1Index,num1Mask);
00526 }
00527 else{
00528 apply_move::ApplyDoUndoCaptureMove<WHITE,NumSimpleEffect<BaseState> >::
00529 prologue(s, from, to, target, promoteMask, oldPiece, oldPtypeO,
00530 capturePtypeO, newPtypeO, num0, num1, num1Index,num1Mask);
00531 }
00532 capturePtype=target.ptype();
00533 pawnCapture = (capturePtype==PAWN);
00534 if (pawnCapture)
00535 s.clearPawn(alt(s.getTurn()),to);
00536 pawnPromotion = (promoteMask!=0) && (num0<PtypeTraits<PAWN>::indexLimit);
00537 if (pawnPromotion)
00538 s.clearPawn(s.getTurn(),from);
00539 }
00540 ~DoUndoMoveLockCapture()
00541 {
00542 if (pawnPromotion)
00543 state.setPawn(state.getTurn(),from);
00544 if (pawnCapture)
00545 state.setPawn(alt(state.getTurn()),to);
00546 if(state.getTurn()==BLACK){
00547 apply_move::ApplyDoUndoCaptureMove<BLACK,NumSimpleEffect<BaseState> >::
00548 epilogue(state, from, to, target, oldPiece,
00549 oldPtypeO, capturePtypeO, newPtypeO,
00550 num0, num1, num1Index,num1Mask);
00551 }
00552 else{
00553 apply_move::ApplyDoUndoCaptureMove<WHITE,NumSimpleEffect<BaseState> >::
00554 epilogue(state, from, to, target, oldPiece,
00555 oldPtypeO, capturePtypeO, newPtypeO,
00556 num0, num1, num1Index,num1Mask);
00557 }
00558 }
00559 };
00560
00561 #endif
00562
00563
00564
00565