With the data structure of the chess string, it becomes very efficient. Next we need to generate random chess steps.
Take the 9x9 Board as an example to directly generate 0 ~ Simulation of random numbers of 80 is very inefficient, because they are not all legal sub-points-three types of sub-points are illegal: 1. Non-empty points 2. Hijacking points 3. Suicide points.
Naturally, if you want to incrementally maintain these three types of points during the simulation process, the first two types of points are easy to maintain. The difficulty lies in the Incremental Maintenance of the suicide points.
After the maintenance of handwritten suicide points, unexpected and complex problems were discovered. I first wrote an issuiside function and tried it as the final ruling. This involves copying objects, which is too expensive. So I want to use it as little as possible and use bitwise operations to determine the majority of cases. Then, as the test was conducted, multiple bit operations were found to be unreliable, and they had to be replaced by the issuiside function ......
The final efficiency can be imagined. The 9x9 Board simulates a 1 W board and takes about 40 seconds-this is unacceptable.
Looking back, I feel that this is not necessary. In most cases, the suicide site itself has no value (except that it may be useful for robbery). Even if it permits suicide, during uct search, suicide points will naturally cool down-too many resources are used to determine whether a suicide point can be crossed.
ModifyProgramAllow the rule to allow suicide. However, in order to finish the game as soon as possible, you are not allowed to fill in your own bits or your opponent's bits without mentioning them. Incremental Maintenance eye position set is much simpler.
The test is much faster. The 9x9 Board is used to simulate 2.3 game boards in 10 thousand seconds. The CPU is 2.4g Core 2, the compiler is Clang, And the O3 optimization level is enabled.
Simulate function:
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 ();}
Suddenly I want to try the 19 standard checkerboards, how much the two sides can win at random. Test function:
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 );}
The simulation speed of the 19th Route is a little slow, with 28 seconds and 1 W. It seems that the First Advantage of random sub-accounts is not obvious ......
Code: Https://github.com/chncwang/FooGo