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

这里没有采用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; 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值