void SpLadderMoveGenerator::GenerateMoves(SgEvaluatedMoves& eval, SgBlackWhite toPlay) { GoModBoard modBoard(m_board); GoBoard& bd = modBoard.Board(); // Don't permit player to kill its own groups. GoRestoreToPlay restoreToPlay(bd); bd.SetToPlay(toPlay); GoRestoreSuicide restoreSuicide(bd, false); for (SgBlackWhite color = SG_BLACK; color <= SG_WHITE; ++color) { for (SgConnCompIterator it(bd.All(color), bd.Size()); it; ++it) { SgPointSet block(*it); SgPoint p = block.PointOf(), toCapture, toEscape; GoLadderStatus st = LadderStatus(bd, p, false, &toCapture, &toEscape); if (st == GO_LADDER_UNSETTLED) { SgPoint move = color == bd.ToPlay() ? toEscape : toCapture; int size = 1000 * block.Size(); eval.AddMove(move, size); if ((color == bd.ToPlay()) && (move == SG_PASS)) { // try liberties for (GoBoard::LibertyIterator it(bd, p); it; ++it) { SgPoint lib = *it; GoMoveExecutor m(bd, lib, color); if (m.IsLegal() && bd.Occupied(p)) { SgPoint toCapture2, toEscape2; GoLadderStatus st2 = LadderStatus(bd, p, false, &toCapture2, &toEscape2); if (st2 == GO_LADDER_ESCAPED) eval.AddMove(lib, size); } } } } } } }
void SpDumbTacticalMoveGenerator::GenerateDefendMoves(SgEvaluatedMoves& eval) { const int stoneweight = 1000; // Do any of own blocks have just one liberty? for (GoBlockIterator anchorit(m_board); anchorit; ++anchorit) { // Ignore opponent blocks if (m_board.IsColor(*anchorit, m_board.Opponent())) continue; // Try to save blocks in atari if (! m_board.InAtari(*anchorit)) continue; // Don't waste saving blocks that will be laddered to death anyway if (m_useLadders) { GoLadderStatus status = LadderStatus(m_board, *anchorit, false); if (status == GO_LADDER_CAPTURED) continue; } int score = stoneweight * m_board.NumStones(*anchorit); // Generate liberty eval.AddMove(m_board.TheLiberty(*anchorit), score); // Generate any captures that will save the group for (GoAdjBlockIterator<GoBoard> adjbit(m_board, *anchorit, 1); adjbit; ++adjbit) { int bonus = stoneweight * m_board.NumStones(*adjbit); if (m_board.InAtari(*adjbit)) // should always be true but just in case { eval.AddMove(m_board.TheLiberty(*adjbit), score + bonus); } } } }
void HyperNEATMoveGenerator::GenerateMoves( SgEvaluatedMoves& eval, SgBlackWhite toPlay ) { GoRestoreToPlay restoreToPlay(m_board); m_board.SetToPlay(toPlay); // Don't permit player to kill its own groups. GoRestoreSuicide restoreSuicide(m_board, false); //Passing is an option eval.AddMove(SG_PASS,0); experiment->generateMoves(eval); // Otherwise make a random legal move that doesn't fill own eye // This will be done automatically by the simple player if no moves // have been generated. //TODO: SINCE WE ADD PASS MOVE, THIS SHOULD NEVER HAPPEN }
void GoExperiment::generateMoves(SgEvaluatedMoves& eval) { if(goBoardSize != self->Board().Size()) { cout << "DIFFERENT SIZE BOARD IS NOT SUPPORTED YET!\n"; throw CREATE_LOCATEDEXCEPTION_INFO("DIFFERENT SIZE BOARD IS NOT SUPPORTED YET!"); } //First, have HyperNEAT generate a move substrates[0].getNetwork()->reinitialize(); for(int r=0;r<goBoardSize;r++) { for(int c=0;c<goBoardSize;c++) { SgBoardColor boardColor = self->Board().GetColor(SgPointUtil::Pt(c+1,r+1)); #if USE_SINGLE_LAYER_FOR_PIECES if(boardColor==SG_BLACK) { substrates[0].setValue( Node(r,c,0) , 1 ); } else if(boardColor==SG_WHITE) { substrates[0].setValue( Node(r,c,0) , -1 ); } else //c==SG_EMPTY { substrates[0].setValue( Node(r,c,0) , 0 ); } #else if(boardColor==SG_BLACK) { substrates[0].setValue( Node(r,c,0) , 1 ); } else { substrates[0].setValue( Node(r,c,0) , -1 ); } if(boardColor==SG_WHITE) { substrates[0].setValue( Node(r,c,1) , 1 ); } else { substrates[0].setValue( Node(r,c,1) , -1 ); } #endif } } substrates[0].getNetwork()->dummyActivation(); substrates[0].getNetwork()->update(); //Get a sorted list of moves to make moves.clear(); for(int r=0;r<goBoardSize;r++) { for(int c=0;c<goBoardSize;c++) { SgPoint p = SgPointUtil::Pt(c+1,r+1); if( self->Board().IsLegal(p) ) { int index = substrates[0].getLayerIndex("Output"); float moveMotivation = substrates[0].getValue(Node(r,c,index)); if(moveMotivation>0) { moves.push_back(MoveRating(moveMotivation,p)); } } } } sort(moves.begin(),moves.end()); int curSize = eval.moveListSize(); for(int a=int(moves.size())-1;a>=0;a--) { //Since the values are floats, don't bother with them and just add the best move eval.AddMove(moves[a].move,1000); if(curSize != eval.moveListSize()) { //Move was accepted, we are done break; } } }
void SpDumbTacticalMoveGenerator::GenerateAttackMoves(SgEvaluatedMoves& eval) { const int capturestoneweight = 100; const int firstlibweight = 100; const int secondlibweight = 20; const int stoneweight = 1; // Do Benson life test SgBWSet safepoints; GoModBoard modBoard(m_board); GoBoard& bd = modBoard.Board(); GoBensonSolver benson(bd); benson.FindSafePoints(&safepoints); // Find opponent blocks without two eyes (using Benson algorithm) for (GoBlockIterator anchorit(bd); anchorit; ++anchorit) { // Ignore own blocks if (bd.IsColor(*anchorit, bd.ToPlay())) continue; // Ignore opponent blocks that are unconditionally alive if (safepoints[bd.Opponent()].Contains(*anchorit)) continue; // Generate all ladder captures if (m_useLadders) { SgPoint tocapture, toescape; GoLadderStatus status = LadderStatus(bd, *anchorit, false, &tocapture, &toescape); if (status == GO_LADDER_CAPTURED) { int score = bd.NumStones(*anchorit) * capturestoneweight; eval.AddMove(tocapture, score); } } // Score according to: // 1. -First liberties // 2. +Second liberties // 3. +Size of group // [4]. Own liberties? int firstlibs = bd.NumLiberties(*anchorit); int size = bd.NumStones(*anchorit); for (GoBoard::LibertyIterator libit(bd, *anchorit); libit; ++libit) { int secondlibs = 0; for (SgNb4Iterator nbit(*libit); nbit; ++nbit) { if (bd.IsValidPoint(*nbit) && bd.IsEmpty(*nbit)) { secondlibs++; } } int score = size * stoneweight + secondlibs * secondlibweight - firstlibs * firstlibweight; eval.AddMove(*libit, score); } } }