void BStar::VerifyInitNode(int ColorRoot,TreeNode *parent) { TreeNode *aux; if(!(parent->MoveCount)) return; int ParamJob = DepthEval; for(aux = parent->MoveTo(FIRSTCHILD); aux; aux = aux->MoveTo(NEXTSIBBLING)) { if(!FixedDepth) if((TimeElapsed()-ini) >= TimeLimit ) break; if(aux->OptVal == UNDEFINED) { SmpWorkers.DoWork(aux,true,ParamJob); } } // wait for all workers end his job while(!SmpWorkers.AllIdle())SmpWorkers.Sleep(); for(aux = parent->MoveTo(FIRSTCHILD); aux; aux = aux->MoveTo(NEXTSIBBLING)) { TotalNodes += aux->HNCount; CalcVerifPrb(aux); VerifyInitNode(ColorRoot,aux); } }
void BStar::RecalcSubtreeOptPrbVerify(TreeNode *parent) { TreeNode *aux; aux = parent->MoveTo(FIRSTCHILD); if(!aux) { // if leaf recalc OptPrb RecalProb(parent); } else { // if not leaf recalc each child for(;aux;aux = aux->MoveTo(NEXTSIBBLING)) { RecalcSubtreeOptPrb(aux); } // backup value if(parent->Color != ColorRoot ) { parent->OptPrb = GetBestChildOptPrb(parent); } else parent->OptPrb = Product(parent,0); } }
// Best OptVal but not BestAtRoot int BStar::OptValAnyOtherMoveAtRoot() { TreeNode *FromNode = TreeNode::GetRootNode(); TreeNode *aux; int MaxValue = -UNDEFINED; for(aux = FromNode->MoveTo(FIRSTCHILD); aux; aux = aux->MoveTo(NEXTSIBBLING)) { if(aux == BestMoveAtRoot) continue; if(aux->OptVal > MaxValue ) { MaxValue = aux->OptVal; } } OptVal2ndBest = MaxValue; return OptVal2ndBest; }
void BStar::CalcVerifPrbP(TreeNode *parent) { int NumMoves,StartPos,pos,i; TreeNode *aux; aux = parent->MoveTo(FIRSTCHILD); for(;aux; aux = aux->MoveTo(NEXTSIBBLING)) { CalcVerifPrb(aux); } }
void BStar::PropagateDown(TreeNode *parent) { TreeNode *aux; for(aux = parent->MoveTo(FIRSTCHILD); aux; aux = aux->MoveTo(NEXTSIBBLING)) { aux->PessVal = -parent->OptVal; } }
void BStar::Backup(int mode,TreeNode *node) { TreeNode *aux = 0; TreeNode *aux1 = node; for(aux = node->MoveTo(PARENT); aux; aux = aux->MoveTo(PARENT)) { Propagate1(aux1,aux,mode); aux1 = aux; } }
void BStar::BackupPrb(TreeNode *node) { TreeNode *aux = 0; TreeNode *aux1 = node; for(aux = node->MoveTo(PARENT); aux; aux = aux->MoveTo(PARENT)) { PropagatePrb1(aux1,aux); aux1 = aux; } }
double BStar::Product(TreeNode *parent,int modo) { double producto = 1.0; TreeNode *aux; aux = parent->MoveTo(FIRSTCHILD); for(;aux; aux = aux->MoveTo(NEXTSIBBLING)) { assert(aux->RealVal < (UNDEFINED-50)); producto *= aux->OptPrb; if(producto == 0.0)break; } return producto; }
TreeNode *BStar::GetBestOptPrb(TreeNode *parent) { double MaxValue = 0.0; double PrbD = 0.0; TreeNode *aux = 0; TreeNode *Sel = 0; int DPV = 0; // depth PV int DOpt = 0; for(aux = parent->SelectBestReal();aux; aux = aux->SelectBestReal()) { DPV++; } double np = parent->SubtreeSize; const double Cucb = 2.0; //0.0000001; //2000.0; for(aux = parent->MoveTo(FIRSTCHILD); aux; aux = aux->MoveTo(NEXTSIBBLING)) { PrbD = aux->OptPrb ; if( PrbD > MaxValue ) { MaxValue = PrbD; Sel = aux ; } } // PV can not be shorter than opt path if(Sel == NULL) Sel = parent->SelectBestReal(); aux = Sel->TraceDown(1); for(;aux && aux != TreeNode::GetRootNode(); aux = aux->MoveTo(PARENT)) DOpt++; if(DOpt > DPV) return parent->SelectBestReal(); return Sel; }
int BStar::EsRepeticion(TreeNode *nodo) { TreeNode *aux; for(aux = nodo->MoveTo(PARENT);aux;aux = aux->MoveTo(PARENT)) { if(strcmp(nodo->fen,aux->fen)==0) { return 1; } } if(ThreeFold.IsRep(nodo->fen)) return 1; return 0; }
double BStar::GetBestChildOptPrb(TreeNode *parent) { double MaxValue = -1.0; TreeNode *aux; for(aux = parent->MoveTo(FIRSTCHILD); aux; aux = aux->MoveTo(NEXTSIBBLING)) { if(aux->OptPrb > MaxValue) { MaxValue = aux->OptPrb; } } return MaxValue; }
int BStar::RealVal2ndBstMoveAtRoot() { TreeNode *aux = 0; int MaxValue; MaxValue = -UNDEFINED; for(aux = TreeNode::GetRootNode()->MoveTo(FIRSTCHILD); aux; aux = aux->MoveTo(NEXTSIBBLING)) { if(aux->RealVal > MaxValue && aux != BestMoveAtRoot) { MaxValue = aux->RealVal; } } return MaxValue ; }
double BStar::SecondRootOptPrb() { double MaxValue = 0.0; TreeNode *aux = 0; for(aux = TreeNode::GetRootNode()->MoveTo(FIRSTCHILD); aux; aux = aux->MoveTo(NEXTSIBBLING)) { RecalProb(aux); if(aux->OptPrb >= MaxValue && aux != BestMoveAtRoot ) { MaxValue = aux->OptPrb; } } return MaxValue ; }
void BStar::Run(char *fen) { int TiempoLimiteOld; DumpTree *dt; ini = TimeElapsed(); Running = 1; PrintPVV = true; if(DumpData) { dt = new DumpTree(); } if(FixedDepth) { TiempoLimiteOld = TimeLimit = 0; } else { TiempoLimiteOld = TimeLimit; } ExpandCount = 0; SelectNodes = 72; //72; VerifyNodes = 40; //40; TotalExpand = 0; TotalProbes = 0; TotalNodes = 0; TimeExpand = 0; TimeProbe = 0; TargetVal = -UNDEFINED; BestMoveAtRoot = NULL; RealValBest = 0; OptVal2ndBest = 0; ColorRoot = White; ExpandCount = 0; TotalExpand = 0; if(TiempoLimiteOld == 0) TiempoLimiteOld = 60000; TimeLimit = TiempoLimiteOld-15; if(TimeLimit <= 0) { TimeLimit = TiempoLimiteOld; //60000-15; } // antes primero a ver si ya tenemos en memoria el nodo a expandir TreeNode *raiz = GetNodeOfFEN(TreeNode::GetRootNode(),fen); if(raiz && raiz->SubtreeSize && raiz->MoveTo(FIRSTCHILD)) { if(DumpData) Print("info string position in Cache saving %d nodes\n",raiz->SubtreeSize); TreeNode *OldRoot = TreeNode::GetRootNode(); TreeNode::SetRootNode(raiz); if(OldRoot && OldRoot != raiz) OldRoot->Delete(); } else { if(DumpData) Print("info string Position %s not found\n",fen); // limpiar el arbol raiz = TreeNode::GetRootNode(); if(raiz) raiz->Delete(); // establecer el nodo raiz raiz = TreeNode::GetFree(); TreeNode::SetRootNode(raiz); strcpy(raiz->fen,fen); // expand del nodo raiz if(Cancel) {Running = 0;return;} Expand(raiz,PLAYER); } if(Cancel) {Running = 0;return;} // if(TimeElapsed()-ini < TimeLimit) Search(); if(DumpData) Print("info string TransPos %d\n",TransPos); if(DumpData) { dt->Print("Probe depth %d, Select Nodes Limit %d, Verify Nodes limit %d\n", DepthEval, SelectNodes, VerifyNodes ); dt->Print("Time used %d Nodes Expanded %d\n",TimeElapsed()-ini,TotalExpand); int TargetVal = ((BestMoveAtRoot->RealVal) + OptVal2Best())/2; dt->Print("Target %d\n",TargetVal); dt->DumpRoot(); dt->Write(); } // Print the best move... int BestMove; _Board.LoadFen(TreeNode::GetRootNode()->fen); // para movetoAlgebra BestMove = TreeNode::GetRootNode()->SelectBestReal()->Move; int ColorMove = _Board.MoveToAlgebra(BestMove,BestMoveStr); Print("bestmove %s\n",BestMoveStr); Running = 0; if(DumpData) { delete dt; } }
// Get RealVal for each Child Node of this leaf; // If it is a Player-to-Move node get OptVals for each Child; void BStar::Expand(TreeNode *SelectedNode,int modo) { int EsRaiz; EsRaiz = SelectedNode == TreeNode::GetRootNode(); //PLY ply(0); //CJugada J; int NMoves = 0; bool EvalOpt; // int StatusEnroque; // int alpaso; int TotalNodesPVS = 0; int fase = 0; TreeNode *aux; // it that position a transposition ? //aux= GetNodeOfFEN(TreeNode::GetRootNode(),SelectedNode->fen); //if(aux && aux != SelectedNode) //{ // TransPos++; // TransPos += aux->SubtreeSize; //} ExpandCount++; TotalExpand++; if(!EsRaiz && EsRepeticion(SelectedNode)) { SelectedNode->RealVal = 0; SelectedNode->OptVal = 0; SelectedNode->OptPrb = 0; SelectedNode->PessVal = 0; SelectedNode->MoveCount = -1; SelectedNode->SubtreeSize++; SelectedNode->Stopper = 1; RecalProb(SelectedNode); BackupSubtreeSize(SelectedNode); return; } if(SelectedNode->MoveCount != 0) return; // already expanded ? _Board.LoadFen(SelectedNode->fen); if(EsRaiz) { SelectedNode->Color = _Board.wtm; SelectedNode->OptVal = UNDEFINED; SelectedNode->PessVal = -UNDEFINED; } SelectedNode->Color = _Board.wtm; SelectedNode->SubtreeSize = 1; DepthNode = GetDepth(SelectedNode); // determinar si necesitamos optvalues EvalOpt = (SelectedNode->Color == TreeNode::GetRootNode()->Color); UndoData undo; MoveList List; int Move; int i; _Board.GenPseudoMoves(List); for(i = 0; i < List.Length();i++) { Move = List.Move(i); _Board.DoMove(Move,undo); // Test legality if(_Board.IsLegal()) { // agregamos un nodo. aux = TreeNode::GetFree(); aux->Color = _Board.wtm; aux->Stopper = 0; aux->Move = Move; _Board.MoveToAlgebra(Move,aux->MoveStr); aux->Flags = Normal; if(undo.capture || undo.IsPromote) aux->Flags = Capture; else if(_Board.IsCheck()) aux->Flags = InCheck; assert(aux->OptVal <= UNDEFINED); assert(aux->PessVal <= UNDEFINED); char dest[100]; _Board.SaveFEN(&dest[0]); strcpy(aux->fen,dest); SelectedNode->Add(aux); NMoves++; } _Board.UndoMove(Move,undo); } SelectedNode->MoveCount = NMoves; if(NMoves) { int ParamJob = DepthEval; // segunda fase calculamos el valor real // Calculamos el valor real y el optimista. // Get Real and optimistic value. for(aux = SelectedNode->MoveTo(FIRSTCHILD);aux; aux = aux->MoveTo(NEXTSIBBLING)) { // verify repets if(EsRepeticion(aux)) { aux->RealVal = 0; aux->OptVal = 0; aux->OptPrb = 0; aux->PessVal = 0; aux->MoveCount = -1; aux->Stopper = 1; } else { aux->OptVal = -SelectedNode->PessVal; aux->PessVal = -SelectedNode->OptVal; aux->StaticVal = UNDEFINED; aux->RealVal = -MATE; SmpWorkers.DoWork(aux,EvalOpt,ParamJob); } } } // wait for all workers end his job while(!SmpWorkers.AllIdle())SmpWorkers.Sleep(); for(aux = SelectedNode->MoveTo(FIRSTCHILD);aux; aux = aux->MoveTo(NEXTSIBBLING)) { TotalNodes += aux->HNCount; } if(SelectedNode->MoveCount == 0) { if(_Board.IsCheck()) { // mate SelectedNode->RealVal = -MATE; SelectedNode->OptVal = -MATE; SelectedNode->PessVal = -MATE; SelectedNode->Stopper = 1; } else { // stalemate SelectedNode->RealVal = 0; SelectedNode->OptVal = 0; SelectedNode->PessVal = 0; SelectedNode->Stopper = 1; } } else { aux = SelectedNode->SelectBestReal(); SelectedNode->RealVal = -aux->RealVal; } BackupSubtreeSize(SelectedNode); }
void BStar::Search() { int Cancelar = 0; int i,NExpandFD = 0; int LastIteration = -1; Cancelar = 0; DumpTree *dt; TreeNode *CurNode = NULL; // last move expanded TreeNode *CurBestNode = NULL; // last best if(DumpData) { dt = new DumpTree(); } TreeNode *a = NULL; TreeNode *SelectedNode = NULL; ColorRoot = TreeNode::GetRootNode()->Color; NExpandFD = 18; for(i=1;i < FixedDepth;i++) { NExpandFD *= 3; // Branch factor 3 } if(FixedDepth) { SelectNodes = (NExpandFD * 6)/10; VerifyNodes = NExpandFD - SelectNodes; } for(;;) { if(LastIteration == TotalExpand) break; // avoid cicle without expands. LastIteration = TotalExpand; if(Cancel||Cancelar) break; // printf("SELECT Step %d\n",TotalExpand); while (GetRealValBestAtRoot() <= OptValAnyOtherMoveAtRoot()) { if(BestMoveAtRoot != CurBestNode) { if(CurBestNode != NULL) PrintPV(); CurBestNode = BestMoveAtRoot; LastChange = TotalExpand; PrintPV(); } if(TreeNode::GetRootNode()->RealVal > (MATE-50) || TreeNode::GetRootNode()->RealVal < (50-MATE) ) { Cancelar= 1; // switch to verify break; } TargetVal = ((BestMoveAtRoot->RealVal) + OptVal2ndBest)/2; // it is unlikely that any other move can achieve as good a RealVal ? if( SecondRootOptPrb() < MinAct) { if(GetRealValBestAtRoot() >= (RealVal2ndBstMoveAtRoot() + 1)) // goto salida; break; } if(DumpData ) { dt->Print("SELECT STEP Color %d Best %d Target Value %d\n",ColorRoot,BestMoveAtRoot->RealVal,TargetVal); dt->Write(); } // Select Root Node with greatest OptPrb; a = GetBestOptPrb(TreeNode::GetRootNode()); if(!a) break; if(a != CurNode) { CurNode = a; } // Trace down the child subtree selecting // For Player-to-Move nodes, child with largest OptPrb // For Opponent-to-Move nodes, child with best RealVal // Until arriving at a leaf node; SelectedNode = a->TraceDownNotStopper(true); if(DumpData) { dt->Print("Selected node:"); dt->DumpPath(SelectedNode,TreeNode::GetRootNode()); dt->Print("Color root %d\n",TreeNode::GetRootNode()->Color); dt->DumpRoot(); } if(SelectedNode->MoveCount != 0) // already expanded, mate pos? { break; } // Get RealVal for each Child Node of this leaf; // If it is a Player-to-Move node get OptVals for each Child; if(Cancelar||Cancel) break; Expand(SelectedNode,PLAYER); // search path down to new expanded SelectedNode = a->TraceDown(true); a = SelectedNode; if(DumpData) { dt->Print("Backup Node :"); dt->DumpPath(a,TreeNode::GetRootNode()); } // Back up Values; if( SelectedNode->RealVal == 0 && SelectedNode->OptVal == 0 && SelectedNode->MoveCount == -1 ) Backup(PLAYER,a->MoveTo(PARENT)); else Backup(PLAYER,a); // best move at root can change after a Backup GetRealValBestAtRoot(); TargetVal = ((BestMoveAtRoot->RealVal) + OptVal2Best())/2; BackupPrb(a); if(TotalExpand > MaxExpand) { Cancelar = 1; break; } if(FixedDepth) { if(TotalExpand > NExpandFD ) //18*(3^FixedDepth)) { Cancelar = 1; break; // EffortLimitsExceeded } } else if((TimeElapsed()-ini) >= TimeLimit ) { Cancelar = 1; break; // EffortLimitsExceeded } if ((ExpandCount > SelectNodes)) { ExpandCount = 0; break; // EffortLimitsExceeded } } if(Cancel||Cancelar) break; TargetVal = RealVal2ndBstMoveAtRoot() + 1; if(TargetVal == (-UNDEFINED+1)) goto salida; // printf("VERIFY Step %d\n",TotalExpand); if(DumpData) { dt->Print("VERIFY Step\n"); dt->Print("Target Value %d\n",TargetVal); } if(!FixedDepth && (TimeElapsed()-ini) >= TimeLimit ) { break; } if(FixedDepth) { if(TotalExpand > NExpandFD) //18*(3^FixedDepth)) { break; // EffortLimitsExceeded } } VerifyInit(); if(!FixedDepth && (TimeElapsed()-ini) >= TimeLimit ) break; GetRealValBestAtRoot() ; if(BestMoveAtRoot->RealVal < TargetVal && GetRealValBestAtRoot() > OptValAnyOtherMoveAtRoot()) break; if(BestMoveAtRoot->RealVal >= MATE-50 || BestMoveAtRoot->RealVal <= 50-MATE) break; ExpandCount = 0; while(BestMoveAtRoot->RealVal >= TargetVal) { if(BestMoveAtRoot != CurBestNode) { CurBestNode = BestMoveAtRoot; LastChange = TotalExpand; // print info PrintPV(); } if(DumpData) { dt->Print("Verify 1:"); } // Select reply Node with Greatest RealVal a = BestMoveAtRoot; if(DumpData) dt->Print("BestMove Real %d Opt %d Pess %d\n",a->RealVal,a->OptVal,a->PessVal); // Trace down the child subtree selecting // For Opponent-to-Move nodes, child with largest OptPrb // For Player-to-Move nodes, child with best RealVal // Until arriving at a leaf node; SelectedNode = TraceDownVerify(a); if(DumpData) { dt->Print("Verify Selected node:"); dt->DumpPath(SelectedNode,TreeNode::GetRootNode()); } if(DumpData) { dt->Print("Verify 2:"); } // TODO // if(IsOver(a)) // return; // Solved if(SelectedNode->RealVal == MATE || SelectedNode->RealVal == -MATE) break; // goto salida; // Get RealVal for each Child Node of this leaf; // If it is an Opponent-to-Move node get OptVals for each Child; Expand(SelectedNode,OPPONENT); if(SelectedNode->MoveCount > 0) { SelectedNode = TraceDownVerify(SelectedNode); // Search leaf node Backup(OPPONENT,SelectedNode); // and Back up Values; if(DumpData) { dt->Print("Verify Selected node:"); dt->DumpPath(SelectedNode,TreeNode::GetRootNode()); dt->DumpRoot(); } } else { if( SelectedNode->RealVal == 0 && SelectedNode->OptVal == 0 && SelectedNode->MoveCount == -1 ) break; } if(DumpData) { dt->Print("Verify 3:"); } if(TotalExpand > MaxExpand) { Cancelar = 1; break; } if(FixedDepth) { if(TotalExpand > NExpandFD) // 18*(3^FixedDepth)) { goto salida; break; // EffortLimitsExceeded } } else if (((TimeElapsed()-ini) >= TimeLimit && ExpandCount > 3 )|| (ExpandCount > VerifyNodes)) { ExpandCount = 0; if((TimeElapsed()-ini) >= TimeLimit ) { goto salida; } break; } } if(DumpData) { int TargetVal = ((BestMoveAtRoot->RealVal) + OptVal2Best())/2; dt->Print("Target %d\n",TargetVal); dt->Write(); } } salida: PrintPV(); if(DumpData) { delete dt; } }