再寫圍棋的MC類比

來源:互聯網
上載者:User

  有了棋串的資料結構後,落子就變得很高效了,接下來要產生隨機棋步。

  以9x9棋盤為例,直接產生0~80的隨機數進行類比會很低效,因為它們並不都是合法落子點——有3類落子點是非法的:1. 非空點 2. 劫爭點 3. 自殺點。

  自然想在類比過程中增量維護這3類點集,前兩類很容易維護,痛點在於自殺點的增量維護。

  著手寫自殺點的維護後,才發現問題出乎意料的複雜。我先寫了個IsSuiside函數,通過試下作為最終的裁決,而這又涉及到對象的拷貝,太過昂貴。於是想盡量少用,通過位元運算來判定多數情況。然後隨著測試的進行,陸續發現多處的位元運算判定不可靠,不得不用IsSuiside函數替代……

  最後的效率可想而知,9 x 9棋盤類比1w局,用時約40秒——這是不可授受的。

  回過頭來思考,越發覺得這件事並不必要做。多數情況下,自殺點本身並無價值(除了打劫時也許可作劫材),即使允許自殺,在UCT搜尋過程中,自殺點自然會冷下來——用過多的資源判定自殺點划不來。

  於是修改程式,讓規則允許自殺,不過為了儘早結束棋局,不允許自填眼位,也不允許填對方眼位而不提子。增量維護眼位集合要簡單得多。

  測試下來要快很多,9 x 9棋盤,2.3秒類比1萬局,CPU是2.4G core 2,編譯器是clang,開O3最佳化級。

  Simulate函數:

template <BoardLen BOARD_LEN>PointIndexMCSimulator<BOARD_LEN>::Simulate(const BoardInGm<BOARD_LEN> &input_board) const{    BoardInGm<BOARD_LEN> bingm;    bingm.Copy(input_board);    do {        PlayerColor last_player = bingm.LastPlayer();        PlayerColor cur_player = OppstColor(last_player);        const auto &playable = bingm.PlayableIndexes(cur_player);        std::bitset<BLSq<BOARD_LEN>()> noko_plbl(playable);        PointIndex ko = bingm.KoIndex();        if (ko != BoardInGm<BOARD_LEN>::NONE) {            std::bitset<BLSq<BOARD_LEN>()> kobits;            kobits.set();            kobits.reset(ko);            noko_plbl &= kobits;        }        PointIndex play_c = noko_plbl.count();        if (play_c > 0) {            PointIndex rand = this->Rand(play_c - 1);            PointIndex cur_indx =                GetXst1<BLSq<BOARD_LEN>()>(noko_plbl, rand);            bingm.PlayMove(Move(cur_player, cur_indx));        } else {            bingm.Pass(cur_player);        }    } while(bingm.PlayableIndexes(BLACK_PLAYER).count() > 0 ||            bingm.PlayableIndexes(WHITE_PLAYER).count() > 0);    return bingm.BlackRegion();}

  忽然想試試19路標準棋盤下,雙方隨機落子黑棋能贏多少,測試函數:

template <BoardLen BOARD_LEN>void MCSimulator<BOARD_LEN>::TEST(){    int begin = clock();    int sum = 0;    const int a = 10000;    for (int i=0; i<a; ++i) {        BoardInGm<TEST_LEN> b;        b.Init();        auto &mcs = MCSimulator<TEST_LEN>::Ins();        int r = mcs.Simulate(b);        sum += r;    }    int end = clock();    printf("time = %f\n", (float)(end - begin) / 1000000);    printf("simulate complte.\n");    printf("average black = %f\n", (float)sum / a);}

  19路的類比速度有點慢,28秒1w局。看來隨機落子的先行優勢並不明顯……

  代碼:https://github.com/chncwang/FooGo

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.