位棋盘表示法中车和炮的着法生成

这里没有采用Magic Bitboard技术,采用了4个方向扫描最高1位或最低1位的办法,效率虽然比magic bitboard低一点,但代码还是比较容易理解的。

 

 

occupied

attacks = PRESET_RAY_NORTH[fromPos];

blockers = attacks & occupied;

9

8

7

6

5

4

3

2

1

0

000000000

001000000

001100100

000000000

001001000

000000000

000000000

010010110

000000000

001000000

ABCDEFGHI

001000000

001000000

001000000

001000000

001000000

001000000

001000000

000000000

000000000

000000000

ABCDEFGHI

000000000

001000000

001000000

000000000

001000000

000000000

000000000

000000000

000000000

000000000

ABCDEFGHI

 

一个位棋盘,1表示有棋子占据,0表示无棋子。这里的fromPos是C2位置。

C2格子的正北面的格子都可以攻击到

blockingPos = blockers.GetLowestBit( );

此例中表示C5格阻碍了车的前进

 

 

 

PRESET_RAY_NORTH[blockingPos]

attacks ^= PRESET_RAY_NORTH[blockingPos];

 

9

8

7

6

5

4

3

2

1

0

001000000

001000000

001000000

001000000

000000000

000000000

000000000

000000000

000000000

000000000

ABCDEFGHI

000000000

000000000

000000000

000000000

001000000

001000000

001000000

000000000

000000000

000000000

ABCDEFGHI

上面一系列的位运算处理了正北方可以攻击到的位置,同理再处理东面、南面和西面的情况,就可以得到所有可以攻击到的格子的位棋盘

 

C5格正北方的格子

异或后,正好就是位于C2格子的车向北方前进时可以攻击到的所有位置的位棋盘

 

 

 1 /*! 车的着法生成 
 2 * \param fromPos 出发位置 
 3 * \param occupied 棋子占据情况的位棋盘 
 4 * \return 可到达位置组成一个位棋盘 
 5 */ 
 6 BitBoard MoveGenerator::RookAttacks( int fromPos, BitBoard occupied ) 
 7 { 
 8     int        blockingPos; 
 9     BitBoard   attacks, partAttacks, blockers; 
10 
11     
12     // 向北扫描
13     attacks = PRESET_RAY_NORTH[fromPos]; 
14     blockers = attacks & occupied; 
15     if ( blockers.H | blockers.L) 
16     { 
17         blockingPos = blockers.GetLowestBit( ); 
18         attacks ^= PRESET_RAY_NORTH[blockingPos]; // mask off beyond blocking square 
19     } 
20 
21  
22     // 向东扫描 
23     partAttacks = PRESET_RAY_EAST[fromPos]; 
24     blockers = partAttacks & occupied; 
25     if ( blockers.H | blockers.L) 
26     { 
27         blockingPos = blockers.GetLowestBit( ); 
28         partAttacks ^= PRESET_RAY_EAST[blockingPos]; 
29     } 
30     attacks |= partAttacks;  
31     
32     // 向南扫描
33     partAttacks = PRESET_RAY_SOUTH[fromPos]; 
34     blockers = partAttacks & occupied; 
35     if ( blockers.H | blockers.L) 
36     { 
37         blockingPos = blockers.GetHighestBit(  ); 
38         partAttacks ^= PRESET_RAY_SOUTH[blockingPos]; 
39     } 
40     attacks |= partAttacks; 
41 
42     // 向西扫描
43     partAttacks = PRESET_RAY_WEST[fromPos]; 
44     blockers = partAttacks & occupied; 
45     if ( blockers.H | blockers.L)  
46     { 
47         blockingPos = blockers.GetHighestBit(  ); 
48         partAttacks ^= PRESET_RAY_WEST[blockingPos]; 
49     } 
50 
51     return attacks | partAttacks; 
52 } 

 

 

炮的着法生成可以类似的处理,但要处理吃子的情况。

 

 

occupied

attacks = PRESET_RAY_NORTH[fromPos];

blockers = attacks & occupied;

9

8

7

6

5

4

3

2

1

0

000000000

001000000

001100100

000000000

001001000

000000000

000000000

010010110

000000000

001000000

ABCDEFGHI

001000000

001000000

001000000

001000000

001000000

001000000

001000000

000000000

000000000

000000000

ABCDEFGHI

000000000

001000000

001000000

000000000

000000000

000000000

000000000

000000000

000000000

000000000

ABCDEFGHI

 

一个位棋盘,1表示有棋子占据,0表示无棋子。这里的fromPos是C2位置。

C2格子的正北面的格子都可以走到

blockingPos = blockers.GetLowestBitWithReset( );

此例中表示C5格阻碍了炮的前进,同时要把此位置0

 

 

 

PRESET_RAY_NORTH_SELF[blockingPos]

attacks ^= PRESET_RAY_NORTH

_SELF[blockingPos];

如果有吃子的话
eatPos = blockers.GetLowestBit( );
此例中为C7。

attacks.SetBit(eatPos);
 

9

8

7

6

5

4

3

2

1

0

001000000

001000000

001000000

001000000

001000000

000000000

000000000

000000000

000000000

000000000

ABCDEFGHI

000000000

000000000

000000000

000000000

000000000

001000000

001000000

000000000

000000000

000000000

ABCDEFGHI

000000000

000000000

001000000

000000000

000000000

001000000

001000000

000000000

000000000

000000000

ABCDEFGHI

上面一系列的位运算处理了正北方可以移动到或攻击到的位置,同理再处理东面、南面和西面的情况,就可以得到所有可以生成所有着法。

 

C5正北方的格子,包括C5位置

异或后,正好就是位于C2格子的炮向北方前进时可以移动到的所有位置的位棋盘

   

 

 1 attacks = PRESET_RAY_NORTH[fromPos]; 
 2 blockers = attacks & occupied; 
 3 if ( blockers.H | blockers.L) 
 4 { 
 5     blockingPos = blockers.GetLowestBitWithReset(  ); 
 6     attacks ^= PRESET_RAY_NORTH_SELF[blockingPos]; // mask off beyond blocking square 
 7     if ( blockers.H | blockers.L) { 
 8         eatPos = blockers.GetLowestBit(  ); 
 9         attacks.SetBit(eatPos); 
10     } 
11 } 
12 
13 partAttacks = PRESET_RAY_EAST[fromPos]; 
14 blockers = partAttacks & occupied; 
15 if ( blockers.H | blockers.L) 
16 { 
17     blockingPos = blockers.GetLowestBitWithReset(  ); 
18     partAttacks ^= PRESET_RAY_EAST_SELF[blockingPos]; 
19     if ( blockers.H | blockers.L) { 
20         eatPos = blockers.GetLowestBit( ); 
21         partAttacks.SetBit(eatPos); 
22     } 
23 } 
24 attacks |= partAttacks; 
25 
26 partAttacks = PRESET_RAY_SOUTH[fromPos]; 
27 blockers = partAttacks & occupied; 
28 if ( blockers.H | blockers.L) 
29 { 
30     blockingPos = blockers.GetHighestBitWithReset(  ); 
31     partAttacks ^= PRESET_RAY_SOUTH_SELF[blockingPos]; 
32     if ( blockers.H | blockers.L) { 
33         eatPos = blockers.GetHighestBit(  ); 
34         partAttacks.SetBit(eatPos); 
35     } 
36 } 
37 attacks |= partAttacks; 
38 
39 
40 partAttacks = PRESET_RAY_WEST[fromPos]; 
41 blockers = partAttacks & occupied; 
42 if ( blockers.H | blockers.L)  
43 { 
44     blockingPos = blockers.GetHighestBitWithReset(  ); 
45     partAttacks ^= PRESET_RAY_WEST_SELF[blockingPos]; 
46     if ( blockers.H | blockers.L) { 
47         eatPos = blockers.GetHighestBit( ); 
48         partAttacks.SetBit(eatPos); 
49     } 
50 } 
51 
52 return attacks | partAttacks; 

 

 

posted @ 2012-09-14 17:19  申龙斌的程序人生  阅读(1302)  评论(0编辑  收藏  举报