From d4829778b0f1efb8843c9d171837294c5b530502 Mon Sep 17 00:00:00 2001 From: h zy <2658628026@qq.com> Date: Tue, 8 Oct 2024 23:46:57 +0800 Subject: [PATCH] nninput; count area if draw; fix some bugs --- cpp/game/board.cpp | 26 +++++++++++++++++++++----- cpp/game/board.h | 2 +- cpp/game/gamelogic.cpp | 2 +- cpp/game/rules.cpp | 4 +++- cpp/game/rules.h | 5 +++-- cpp/neuralnet/nninputs.cpp | 18 +++++++++++++++++- 6 files changed, 46 insertions(+), 11 deletions(-) diff --git a/cpp/game/board.cpp b/cpp/game/board.cpp index b23dd79be..f93fd6e1e 100644 --- a/cpp/game/board.cpp +++ b/cpp/game/board.cpp @@ -168,7 +168,7 @@ Color Board::getSubBoardResult(int idx) const{ auto checkLine = [&](Loc loc1, Loc loc2, Loc loc3) { if(colors[loc1] == C_BLACK && colors[loc2] == C_BLACK && colors[loc3] == C_BLACK) return C_BLACK; - if(colors[loc1] == C_BLACK && colors[loc2] == C_BLACK && colors[loc3] == C_BLACK) + if(colors[loc1] == C_WHITE && colors[loc2] == C_WHITE && colors[loc3] == C_WHITE) return C_WHITE; return C_EMPTY; }; @@ -211,7 +211,7 @@ Color Board::updateSubBoardResult(int idx) { return r; } -Color Board::getWinner() const { +Color Board::getWinner(int rule) const { static_assert(CON_LEN == 3, ""); const int lines[8][3] = { {0,1,2}, @@ -232,11 +232,26 @@ Color Board::getWinner() const { } // full? - for(int li = 0; li < 8; li++) { - if(subBoardResult[li] == C_WALL) + for(int i = 0; i < CON_LEN * CON_LEN; i++) { + if(subBoardResult[i] == C_WALL) return C_WALL; } + if(rule == 1) + return C_EMPTY;//SCORING_CON + + int score = 0; + for(int i = 0; i < CON_LEN * CON_LEN; i++) { + if(subBoardResult[i] == C_BLACK) + score += 1; + if(subBoardResult[i] == C_WHITE) + score -= 1; + } + if(score > 0) + return C_BLACK; + if(score < 0) + return C_WHITE; return C_EMPTY; + } void Board::setLastLocIdx(int x) { @@ -348,7 +363,8 @@ bool Board::isLegal(Loc loc, Player pla) const if(pla != P_BLACK && pla != P_WHITE) return false; if(loc == PASS_LOC) - return getWinner() != C_WALL; //pass is not allowed, allow pass after game finished just to avoid some crashes + return getWinner(0) != + C_WALL; // pass is not allowed, allow pass after game finished just to avoid some crashes if(!isOnBoard(loc)) return false; diff --git a/cpp/game/board.h b/cpp/game/board.h index 5b1d1b4ba..4b4a0bf81 100644 --- a/cpp/game/board.h +++ b/cpp/game/board.h @@ -190,7 +190,7 @@ struct Board short adj_offsets[8]; //Indices 0-3: Offsets to add for adjacent points. Indices 4-7: Offsets for diagonal points. 2 and 3 are +x and +y. int inWhichSubBoard(Loc loc) const; - Color getWinner() const; + Color getWinner(int rule) const; private: void init(int xS, int yS); diff --git a/cpp/game/gamelogic.cpp b/cpp/game/gamelogic.cpp index bd843e78b..02f35a742 100644 --- a/cpp/game/gamelogic.cpp +++ b/cpp/game/gamelogic.cpp @@ -28,7 +28,7 @@ Color GameLogic::checkWinnerAfterPlayed( return getOpp(pla); //pass is not allowed //write your own logic here - Color winner = board.getWinner(); + Color winner = board.getWinner(hist.rules.scoringRule); if(winner != C_WALL) return winner; diff --git a/cpp/game/rules.cpp b/cpp/game/rules.cpp index 3bb6b0067..886a31387 100644 --- a/cpp/game/rules.cpp +++ b/cpp/game/rules.cpp @@ -41,16 +41,18 @@ Rules Rules::getTrompTaylorish() { set Rules::scoringRuleStrings() { - return {"AREA"}; + return {"AREA", "CON"}; } int Rules::parseScoringRule(const string& s) { if(s == "AREA") return Rules::SCORING_AREA; + if(s == "CON") return Rules::SCORING_CON; else throw IOError("Rules::parseScoringRule: Invalid scoring rule: " + s); } string Rules::writeScoringRule(int scoringRule) { if(scoringRule == Rules::SCORING_AREA) return string("AREA"); + if(scoringRule == Rules::SCORING_CON) return string("CON"); return string("UNKNOWN"); } diff --git a/cpp/game/rules.h b/cpp/game/rules.h index 7f8fcdb1d..8ebd275dd 100644 --- a/cpp/game/rules.h +++ b/cpp/game/rules.h @@ -8,8 +8,9 @@ struct Rules { - - static const int SCORING_AREA = 0; + + static const int SCORING_AREA = 0; //if no connection, whose area bigger wins + static const int SCORING_CON = 1; //only consider connection int scoringRule; diff --git a/cpp/neuralnet/nninputs.cpp b/cpp/neuralnet/nninputs.cpp index e21a99f8c..c62b9661d 100644 --- a/cpp/neuralnet/nninputs.cpp +++ b/cpp/neuralnet/nninputs.cpp @@ -522,6 +522,20 @@ void NNInputs::fillRowV7( else if(stone == opp) setRowBin(rowBin,pos,2, 1.0f, posStride, featureStride); + int sub = board.inWhichSubBoard(loc); + Color sbr = board.subBoardResult[sub]; + if(sbr == pla) + setRowBin(rowBin, pos, 3, 1.0f, posStride, featureStride); + else if(sbr == opp) + setRowBin(rowBin, pos, 4, 1.0f, posStride, featureStride); + else if(sbr == C_EMPTY) + setRowBin(rowBin, pos, 5, 1.0f, posStride, featureStride); + else + { + if(board.lastLocIdx == sub && board.lastLocIdx == -1) + setRowBin(rowBin, pos, 6, 1.0f, posStride, featureStride); + } + } } @@ -539,7 +553,7 @@ void NNInputs::fillRowV7( setRowBin( rowBin, NNPos::locToPos(resultsBeforeNN.myOnlyLoc, board.x_size, nnXLen, nnYLen), - 3, + 20, 1.0f, posStride, featureStride); @@ -560,6 +574,8 @@ void NNInputs::fillRowV7( // Parameter 0 noResultUtilityForWhite, when draw, white's win rate = 0.5*(noResultUtilityForWhite+1) rowGlobal[0] = pla == C_WHITE ? nnInputParams.noResultUtilityForWhite : -nnInputParams.noResultUtilityForWhite; + rowGlobal[6] = hist.rules.scoringRule == Rules::SCORING_CON; + // Parameter 15 is used because there's actually a discontinuity in how training behavior works when this is // nonzero, no matter how slightly. if(nnInputParams.playoutDoublingAdvantage != 0) {