BitBoard Tests Magic v Non-Rotated 32 Bits v 64 Bits

Discussion of chess software programming and technical issues.

Moderators: hgm, Harvey Williamson, bob

Forum rules
This textbox is used to restore diagrams posted with the [d] tag before the upgrade.
brianr
Posts: 249
Joined: Thu Mar 09, 2006 2:01 pm

BitBoard Tests Magic v Non-Rotated 32 Bits v 64 Bits

Post by brianr » Fri Aug 24, 2007 7:24 pm

I have been working on Tinker a bit lately and am trying to get back to 64 bit mode after initial experiments a few years ago.
I am currently using an evaluation copy of Windows XP Pro x64 (free for 120 days) with the Visual Studio 2008 Beta2 (free for 200 some odd days).
Hardware is an Opteron 246 (2 GHz, 2 CPUs). Tinker only uses one CPU (no parallel search, yet).

Tinker traditionally uses Crafty-style bitboards, but non-rotated.
Magic bitboards are Pradu's (inlined, not mizimized, not perfect), with a minor adjustment (need to use 63-sq instead of just sq).

The following test results happen to be from the starting position searching to a depth of 15 plys,
but four other positions (including middle game and end game positions) were also run with very similar results.

The results are the results. I have done my best to normalize the various Visual Studio setting relating to optimization, no debug info, etc.

Anyway, I thought others might be interested to see how the compiler change impacts things separately from the 32 to 64 bit change.

Code: Select all

Visual Studio	BitBoard		#	 Time
Version			Method		Bits	secs

VS 2003			Non-rotated	32	47.7
 					Magic			32	44.6

VS 2008			Non-rotated	32	50.2
Beta2			  Magic			32	50.7

VS 2008			Non-rotated	64	46.0
Beta2			  Magic			64	46.0

Harald
Posts: 259
Joined: Thu Mar 09, 2006 12:07 am

Re: BitBoard Tests Magic v Non-Rotated 32 Bits v 64 Bits

Post by Harald » Fri Aug 24, 2007 8:52 pm

Bitboard methods compared

Hi

One year ago I did some tests with different bitboards. The postings are
lost but I will repost my results here, copying much of my old texts.

A lot of new methods for generating attack bitboards were discussed.
It was hard to catch up with all the new ideas. But I was very interested and today
I can proudly announce, that I implemented and tested different bitboard attack
generators.

This is the result:

Code: Select all

+----------------------------+-----------------------+--------------+-----------+
| Name                       | Inventor or Supporter | Table Size   | Test-Time |
+----------------------------+-----------------------+--------------+-----------+
| Rotated Bitboards (naive)  | Robert Hyatt          |   77.2 KByte |  87.78 s  |
| Rotated Bitboards (aligned)| ?                     |   35.0 KByte |  86.65 s  |
| Rotated Bitboards (switch) | (Harald Lüßen?)       |   14.9 KByte |  88.91 s  |
| Rotated Indices            | Alessandro Damiani    |  128.3 KByte |  78.93 s  |
| Exploding Bitboards        | Harald Lüßen          |    3.5 KByte | 101.79 s  |
| Magic Mult. (Kinderg.)     | Gerd Isenberg         |    9.7 KByte |  91.87 s  |
| Magic M. (Kinderg.) 32 bit | Gerd Isenberg         |    9.7 KByte |  81.37 s  |
| Sherwin Index              | Michael Sherwin       | 1402.4 KByte |  90.03 s  |
| Pradu Minimize Magic       | Pradyumna Kannan      |  844.0 KByte |  81.42 s  |
| Pradu Perfect Magic Hash   |  and                  |  627.4 KByte |  82.09 s  |
| Pradu Big                  | Lasse Hansen          | 2306.0 KByte |  82.33 s  |
| Kogge-Stone                | Steffan Westcott      |    0.0 KByte |  99.32 s  |
| Simple Shift               | --                    |    0.0 KByte | 110.25 s  |
| Naive Shift                | --                    |    0.0 KByte | 111.69 s  |
+----------------------------+-----------------------+--------------+-----------+
Shorter test times are better. The test was just my chess engine Elephant 1.07
running under Winboard and analysing 3 positions: opening, middlegame and endgame.
The table above shows the sum of the running time until ply 8 or 9 was reached.

The algorithms are:

Rotated Bitboards (naive):
The normal bitboards with the rotated tables that are updated in make_move().
The mapping of the diagonals to rotated squares is just one after the other.

Rotated Bitboards (aligned):
The bitboards with the rotated tables that are updated in make_move().
The mapping sorts the diagonals with the same files normal and rotated.

Rotated Bitboards (switch):
The same as aligned rotated bitboards with a switch statement instead
of a mask and shift table.

Rotated Indices:
Alessandro Damiani sent me his code with rotated indices that are updated in
make/unmake_move() like the normal rotated bitboard code. See new source.

Exploding Bitboards:
Step for step expanding from a square in all four directions simultaneously.
This is done with magic multiplication, switch and nasty overflow control.
It works!

Magic Multiplication (Kindergarten):
Very elegant and compact magic shifts and multiplications for verticals,
horizontals diagonals and antidiagonals.

Magic Multiplication (Kindergarten) 32 bit:
Very elegant and compact magic shifts and multiplications for verticals,
horizontals diagonals and antidiagonals. The 32 bit variant from Gerd Isenberg.

Sherwin Index:
For each square each row of a bitboard generates a few bits of an index
to an bitboard attack table. It's a challenge to do the initialisation right.

Pradu Minimize Magic and Pradu Perfect Magic Hash:
Another magic multiplication attack generator with magic multiplication
numbers depending on squares. I have not tried to understand it and I may
have the defines wrong and the methods confused.

Pradu Big:
Another magic multiplication attack generator with magic multiplication
numbers depending on squares. Both defines commented out. See the corrected sizes.

Kogge Stone:
Shifting and filling all possible slider moves of one direction in parallel.
Here it is used only used for one starting square without the parallelism.
With a Kogge-Stone method the move generation should be changed from
'for each slider do all directions' to 'for each direction do all sliders'.
I have not done this.

Simple Shift:
The simple method of shifting a bit through the bitboard.
I used the Kogge-Stone infrastructure. No loops, if, while.
Only implemented to get a compare basis.

Naive Shift:
The simple method of shifting a bit through the bitboard.
This method uses a do while loop for generating the results.
Only implemented to get a compare basis.


All methods have the same output. Therefore I believe they searched the same
tree and there is no error in the implementation. The positions and output are:

Code: Select all

Opening position
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

  9	-0.05	4.5M	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 
  8	-0.05	3.5M	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 
  8	-0.07	2.2M	e2-e4 Nb8-c6 Ng1-f3 Ng8-f6 Nb1-c3  e7-e5 Bf1-b5  h7-h6 Bb5xc6  d7xc6 Nf3xe5 
  7	-0.09	268393	e2-e4  e7-e5 Ng1-f3 Nb8-c6 Nb1-c3 Ng8-f6 Bf1-c4 Bf8-b4 Bc4-d3 Bb4xc3  d2xc3 
  6	-0.10	111579	e2-e4  e7-e5 Ng1-f3 Nb8-c6 Bf1-d3 Ng8-e7   O-O  
  6	-0.11	50041	d2-d4  d7-d5 Ng1-f3 Ng8-f6 Nb1-c3 Nb8-c6  e2-e3  e7-e6 
  5	-0.08	10029	d2-d4 Nb8-c6  d4-d5  e7-e5  d5xc6 Bf8-b4 Nb1-c3 
  5	-0.07	5114	d2-d4  d7-d5 Ng1-f3 Nb8-c6 Bc1-d2 
  4	-0.19	2625	d2-d4 Nb8-c6  d4-d5 Nc6-e5 
  3	-0.02	1464	d2-d4  d7-d5 Ng1-f3

rotated naive
  9	-0.05	4.5M	0:26.54	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

rotated aligned
  9	-0.05	4.5M	0:26.46	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

rotated switch
  9	-0.05	4.5M	0:27.31	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

rotated indices
  9	-0.05	4.5M	0:23.51	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

exploding
  9	-0.05	4.5M	0:29.67	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

magic
  9	-0.05	4.5M	0:27.71	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

magic 32 bit
  9	-0.05	4.5M	0:24.53	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

sherwin
  9	-0.05	4.5M	0:26.81	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

pradu minimize magic
  9	-0.05	4.5M	0:24.73	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

pradu perfect magic hash
  9	-0.05	4.5M	0:24.87	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

pradu big
  9	-0.05	4.5M	0:25.15	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

kogge-stone
  9	-0.05	4.5M	0:30.57	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

simple shift
  9	-0.05	4.5M	0:34.37	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

naive shift
  9	-0.05	4.5M	0:35.50	d2-d4  d7-d5 Ng1-f3 Nb8-c6  e2-e3 Ng8-f6  c2-c4 Nc6-b4 Nb1-c3  c7-c6 

Code: Select all

Middle game
1r1q1rk1/2p1bppp/p5b1/3pP3/Bn1Pn3/2N1BN1P/1P2QPP1/R2R2K1 w - - 0 1

  8	+0.15	8.0M	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 
  7	+0.12	2.0M	Ra1-c1  c7-c6 Nc3xe4  d5xe4 Nf3-h2 Qd8-d5 Nh2-g4  h7-h5 Rc1-c5 Be7xc5  d4xc5 
  6	+0.12	650331	Ra1-c1  c7-c6 Nc3xe4 Bg6xe4 Rc1-c3 Rb8-c8 Rd1-c1 
  6	+0.07	226075	Rd1-c1  h7-h5 Ra1-a3  c7-c6 Nc3xe4 Bg6xe4 
  5	+0.17	28303	Rd1-c1  h7-h5 Ra1-a3  c7-c6 Nc3xe4 Bg6xe4 
  4	+0.22	5511	Rd1-c1  h7-h5 Nc3xe4 Bg6xe4 
  2	+0.21	2348	Rd1-c1 Ne4xc3 Rc1xc3 

rotated naive
  8	+0.15	8.0M	0:43.03	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

rotated aligned
  8	+0.15	8.0M	0:41.62	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

rotated switch
  8	+0.15	8.0M	0:43.29	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

rotated indices
  8	+0.15	8.0M	0:38.03	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

exploding
  8	+0.15	8.0M	0:49.75	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

magic
  8	+0.15	8.0M	0:44.73	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

magic 32 bit
  8	+0.15	8.0M	0:39.50	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

sherwin
  8	+0.15	8.0M	0:44.40	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

pradu minimize magic
  8	+0.15	8.0M	0:39.34	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

pradu perfect magic hash
  8	+0.15	8.0M	0:39.93	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

pradu big
  8	+0.15	8.0M	0:39.90	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

kogge-stone
  8	+0.15	8.0M	0:48.64	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

simple shift
  8	+0.15	8.0M	0:53.82	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

naive shift
  8	+0.15	8.0M	0:53.71	Ra1-c1 Rb8-c8 Nf3-d2 Ne4xc3 Rc1xc3 Nb4-a2 Rc3-c6 Na2-b4  g2-g4 Nb4xc6 Ba4xc6 

Code: Select all

Near endgame
r2r4/pp3p2/4bkpp/8/7P/3B1P2/PP4P1/1K1R3R b - -

  9	+0.16	4.1M	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 
  8	+0.26	1.7M	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 
  7	+0.25	703521	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 
  6	+0.25	681594	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 
  5	+0.22	611948	Rd8-d7 Bd3-c2 Rd7-c7 Rd1-d2 Ra8-c8 Rh1-d1 

rotated naive
  9	+0.16	4.1M	0:18.21	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

rotated aligned
  9	+0.16	4.1M	0:18.57	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

rotated switch
  9	+0.16	4.1M	0:18.31	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

rotated indices
  9	+0.16	4.1M	0:17.39	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

exploding
  9	+0.16	4.1M	0:22.37	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

magic
  9	+0.16	4.1M	0:19.43	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

magic 32 bit
  9	+0.16	4.1M	0:17.34	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

sherwin
  9	+0.16	4.1M	0:18.82	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

pradu minimize magic
  9	+0.16	4.1M	0:17.35	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

pradu perfect magic hash
  9	+0.16	4.1M	0:17.29	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

pradu big
  9	+0.16	4.1M	0:17.28	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

kogge-stone
  9	+0.16	4.1M	0:20.11	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

simple shift
  9	+0.16	4.1M	0:22.06	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 

naive shift
  9	+0.16	4.1M	0:22.48	Rd8xd3 Rd1xd3 Be6-f5 Rh1-d1 Ra8-e8 Kb1-c2 Re8-e2 Rd1-d2 Bf5xd3 Kc2xd3 
This test is not perfect. There is a lot that can be discussed.
Here are some facts and thoughts:

Environment:
Windows XP Home, Pentium 4, 2.6 GHz, 1.5 GByte, MSVC++ 7, Winboard,
Elephant 1.07 (20061007) chess program. The algorithms are included
in the source dependig on defines. The rest of the source was the same,
including the pawn, knight and king attacks.

Quality of implementation:
I may have missed some optimisations or done a table access or operation that
could have been avoided.

Fairness of implementation:
The native results of bitboard algorithm are rays, all pieces or horizontals,
verticals and diagonals. My program needs rays and orthogonal/diagonal attacks.
Therefore some methods needed extra code.

Statistics and measurement:
Three examples are not statistically relevant. The deviations in the measured
time are +- 0.5 seconds when I redo the tests. Only a part of the time is
spent in the bitboard attack functions. The measured time was short.
Only to ply 8 or 9.

An additional remark:
My engine has no real undo_move(). But make_moves makes copies of the board.
All rotated bitboards have some extra bytes to copy. 38 bytes for rotated indices.

All implementations are available if you request it.


Harald

Gerd Isenberg
Posts: 2105
Joined: Wed Mar 08, 2006 7:47 pm
Location: Hattingen, Germany

Re: BitBoard Tests Magic v Non-Rotated 32 Bits v 64 Bits

Post by Gerd Isenberg » Fri Aug 24, 2007 8:57 pm

Hi Brian,

how fast is 64-bit with optimization off or a 64-bit debug version?

Strange the the 32-bit magic is that fast with VS2003 despite 64-bit imul calls with up to three 32-bit imuls. I would have expected something like 20-30 seconds for 64-bit mode if you do a lot of 64-bit stuff which is likely with bitboards - considering the doubled register width as well as number of registers. There seems something broken with 2008 beta like all optimization disabled. Would be interesting so see some generated assembly though or to do some profiling.

Also to consider - if you change some code + datastructures to compare, things interact with other stuff due the huge processor heuristics which may behave chaotical.

Can you explain how you do sliding attacks in none-rotated?

Gerd

Btw. sq xor 63 instead of 63-sq may safe a register.

Pradu
Posts: 287
Joined: Sat Mar 11, 2006 2:19 am
Location: Atlanta, GA
Contact:

Re: BitBoard Tests Magic v Non-Rotated 32 Bits v 64 Bits

Post by Pradu » Fri Aug 24, 2007 9:20 pm

Harald wrote: All implementations are available if you request it.
Harald
Can you post the source code for the entire test so that others can verify and test in 64-bits as well?

bob
Posts: 20348
Joined: Mon Feb 27, 2006 6:30 pm
Location: Birmingham, AL

Re: BitBoard Tests Magic v Non-Rotated 32 Bits v 64 Bits

Post by bob » Sat Aug 25, 2007 1:52 am

I had reported this earlier. Magic was no faster than rotated. I switched because of two things...

1. magic is simpler, and simpler is better as I get older. :)

2. Magic gives you the opportunity to update the occupied_squares and then generate moves easily. To do this with rotated bitboards first requires that all rotated bitboards be updated in addition to the normal occupied_squares bitboard. This is faster, if you use the feature (I don't yet, but well might at times).

Harald
Posts: 259
Joined: Thu Mar 09, 2006 12:07 am

Re: BitBoard Tests Magic v Non-Rotated 32 Bits v 64 Bits

Post by Harald » Sat Aug 25, 2007 6:43 am

Pradu wrote:
Harald wrote: All implementations are available if you request it.
Harald
Can you post the source code for the entire test so that others can verify and test in 64-bits as well?
OK. But posting a whole source code is not easy because there is so much of it.
The easiest way would be to have a web page with the whole source and just
give you a pointer to it. I have none, so I will do this:
I start with some of the helping and surrounding sources in this posting and
in following postings I give the different bitboard variants. The rest of the
engine's source code will not be published here.

bb_basics.h:

Code: Select all

/*******************************************************************/
/*
Makros, types and printf formats for unsigned ints and bitboards in chess. 
This should help to keep the program portable.
Some basic non class types of the program.

(c) 2002 Harald Lüßen
*/
/*******************************************************************/

#ifndef BB_BASICS_H_
#define BB_BASICS_H_

/*******************************************************************/


typedef unsigned char    byte;
typedef          __int64 int64;
typedef unsigned __int64 uint64;
typedef          __int32 int32;
typedef unsigned __int32 uint32;
typedef          __int16 int16;
typedef unsigned __int16 uint16;


#define C64(c) c##ui64
#define U64_F "I64u"
#define X64_F "016I64x"
#define X64_S "I64x"


#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
#define MIN&#40;a, b&#41; ( &#40;a&#41; < &#40;b&#41; ? &#40;a&#41; &#58; &#40;b&#41; )


typedef int16 value_type;


/*******************************************************************/

#endif // BB_BASICS_H_

/*******************************************************************/
bb_bitboard.h:

Code: Select all

/*******************************************************************/
/*
A class for bitboards in chess. A bitboard is a 64 bit unsigned int 
which is used to mark the squares of a piece on a chess board. 
This class handles all low level operations.

&#40;c&#41; 2002 Harald Lüßen
*/
/*******************************************************************/

#ifndef BB_BITBOARD_H_
#define BB_BITBOARD_H_

/*******************************************************************/

#include <string>
#include "bb_basics.h"


/*******************************************************************/

typedef uint64 Bits64;


/*******************************************************************/

class Bitboard
&#123;
  private&#58;

    Bits64 bb_;

  public&#58;

    /**
    Construct a bitboard from an unsigned int. 
    Default constructor.
    */
    inline
    Bitboard&#40; const Bits64 &b = 0 ) &#58; bb_( b ) &#123;&#125;

    /**
    Construct a bitboard from another bitboard. 
    Copy constructor.
    */
    inline
    Bitboard&#40; const Bitboard &b ) &#58; bb_( b.bb_ ) &#123;&#125;

    /**
    Construct a bitboard from a 2 byte coordinate string. Only one bit is set.
    Construct a bitboard from a 16 byte hex-string. 
    Construct a bitboard from a 64 byte 01-string. 
    Construct a bitboard from a 8 lines 8 rows 01-string. 
    */
    Bitboard&#40; const std&#58;&#58;string &s );

    /**
    Assign a bitboard from an 64 bit unsigned int. 
    */
    inline
    Bitboard &operator=( const Bits64 &b ) &#123; bb_ = b; return *this; &#125;

    /**
    Assign a bitboard from another bitboard. 
    */
    inline
    Bitboard &operator=( const Bitboard &b ) &#123; bb_ = b.bb_; return *this; &#125;
    // No problem with self assignment.

    /**
    Assign a bitboard from a 2 byte coordinate string. Only one bit is set.
    Assign a bitboard from a 16 byte hex-string. 
    Assign a bitboard from a 64 byte 01-string. 
    Assign a bitboard from a 8 lines 8 rows 01-string. 
    */
    Bitboard &operator=( const std&#58;&#58;string &s );

    /**
    Implicit conversion to an unsigned int.
    */
    inline
    operator Bits64&#40;) const &#123; return bb_; &#125;

    /**
    Get a 16 byte hex-string from a bitboard. 
    */
    std&#58;&#58;string hex&#40;) const;

    /**
    Get a bitboard from a 16 byte hex-string. 
    */
    void hex&#40; const std&#58;&#58;string &txt );

    /**
    Get a 64 byte 01-string from a bitboard. 
    */
    std&#58;&#58;string txt01&#40;) const;

    /**
    Get a bitboard from a 64 byte 01-string. 
    */
    void txt01&#40; const std&#58;&#58;string &txt );

    /**
    Get a 8 lines 8 rows 01-string from a bitboard. 
    */
    std&#58;&#58;string txt8lines&#40;) const;

    /**
    Get a bitboard from a 8 lines 8 rows 01-string. 
    */
    void txt8lines&#40; const std&#58;&#58;string &txt );

    /**
    Get a 2 byte coordinate string from a bitboard with only one bit set. 
    If more or less bits are set the result is "??". 
    The normal results are "a1", ..., "h8".
    */
    std&#58;&#58;string coordinate&#40;) const;

    /**
    Get bitboard from a 2 byte coordinate string. Only one bit is set. 
    If the coordinates are invalid the bitboard is empty &#40;0&#41;. 
    Valid coordinate strings are "a1", ..., "h8".
    */
    void coordinate&#40; const std&#58;&#58;string &s );

    /**
    Test if the bitboard is empty. 
    \return true if the board is empty &#40;0&#41;, else false.
    */
    inline
    bool empty&#40;) const &#123; return bb_ == 0; &#125;

    /**
    Count the bits in the bitboard. 
    That is the size of the set of bits in the bitboard.
    &#40;best version&#41;
    */
    int size&#40;) const;

    /**
    Test if only one bit is set. 
    \return true if only one bit is set, else false.
    */
    inline
    bool only_1_bit&#40;) const &#123; return !empty&#40;) && get_all_but_ls1b&#40;).empty&#40;); &#125;

    /**
    Test if the number of bits is odd. 
    &#40;One loop for every set bit.)
    \return true if the number of bits is odd, else false.
    */
    bool odd_parity&#40;) const;

    /**
    Most significant bit number.
    Get the position of the most significant bit &#40;0-63&#41;. 
    \return 0-63 and 64 for an empty bitboard.
    (== log2&#41;
    &#40;best version&#41;
    */
    inline
    byte msb_nr&#40;) const
    &#123;
        //return msb_nr_shift&#40;);
        //return msb_nr_small_table&#40;);
    //    return msb_nr_big_table&#40;);
        return msb_nr_bsr&#40;);
    &#125;

    /**
    Least significant bit number.
    Get the position of the least significant bit &#40;0-63&#41;. 
    \return 0-63 and 64 for an empty bitboard.
    &#40;best version&#41;
    */
    inline
    byte lsb_nr&#40;) const;

    /**
    Fill an array with the positions of the set bits in a bitboard. 
    \return Number of entries/bits. 
    &#40;best version&#41;
    */
    int get_bit_positions&#40; byte positions&#91;64&#93; ) const;

    /**
    Operators
    */
    inline
    bool operator==( const Bitboard &rhs ) const &#123; return bb_ == rhs.bb_; &#125;
    inline
    bool operator!=( const Bitboard &rhs ) const &#123; return bb_ != rhs.bb_; &#125;
    inline
    Bitboard &operator<<=( int i ) &#123; bb_ <<= i; return *this; &#125;
    inline
    Bitboard &operator>>=( int i ) &#123; bb_ >>= i; return *this; &#125;
    inline
    Bitboard operator|( const Bitboard &rhs ) const &#123; return bb_ | rhs.bb_; &#125;
    inline
    Bitboard &operator|=( const Bitboard &rhs ) &#123; bb_ |= rhs.bb_; return *this; &#125;
    inline
    Bitboard operator&( const Bitboard &rhs ) const &#123; return bb_ & rhs.bb_; &#125;
    inline
    Bitboard &operator&=( const Bitboard &rhs ) &#123; bb_ &= rhs.bb_; return *this; &#125;
    inline
    Bitboard &operator*=( const Bits64 mul ) &#123; bb_ *= mul; return *this; &#125;
    // Idee&#58; Bits64 &#40;bb_) oder Bitboard& (*this&#41; zurückgeben.
    // &=, |= mit oder ohne Rückgabe von Bitboard& &#40;Schachtelung möglich oder nicht&#41;.
    // Logausgaben und Zähler in die Konstruktoren, Zuweisungen und Konvertierungen.

    /**
    Move directions
    +-----+-----+-----+-----+-----+
    |     |<<=17|     |<<=15|     |
    +-----+-----+-----+-----+-----+
    |<<=10|<<= 9|<<= 8|<<= 7|<<= 6|
    +-----+-----+-----+-----+-----+         up
    |     |<<= 1|     |>>= 1|     |   left  *  right
    +-----+-----+-----+-----+-----+        down
    |>>= 6|>>= 7|>>= 8|>>= 9|>>=10|
    +-----+-----+-----+-----+-----+
    |     |>>=15|     |>>=17|     |
    +-----+-----+-----+-----+-----+
    */
    inline
    void shift_uul&#40;)  &#123; bb_ <<= 17; &#125;
    inline
    void shift_uur&#40;)  &#123; bb_ <<= 15; &#125;
    inline
    void shift_ull&#40;)  &#123; bb_ <<= 10; &#125;
    inline
    void shift_ul&#40;)   &#123; bb_ <<=  9; &#125;
    inline
    void shift_u&#40;)    &#123; bb_ <<=  8; &#125;
    inline
    void shift_ur&#40;)   &#123; bb_ <<=  7; &#125;
    inline
    void shift_urr&#40;)  &#123; bb_ <<=  6; &#125;
    inline
    void shift_l&#40;)    &#123; bb_ <<=  1; &#125;
    inline
    void shift_r&#40;)    &#123; bb_ >>=  1; &#125;
    inline
    void shift_dll&#40;)  &#123; bb_ >>=  6; &#125;
    inline
    void shift_dl&#40;)   &#123; bb_ >>=  7; &#125;
    inline
    void shift_d&#40;)    &#123; bb_ >>=  8; &#125;
    inline
    void shift_dr&#40;)   &#123; bb_ >>=  9; &#125;
    inline
    void shift_drr&#40;)  &#123; bb_ >>= 10; &#125;
    inline
    void shift_ddl&#40;)  &#123; bb_ >>= 15; &#125;
    inline
    void shift_ddr&#40;)  &#123; bb_ >>= 17; &#125;

    inline
    Bitboard shifted_uul&#40;) const &#123; return bb_ << 17; &#125;
    inline
    Bitboard shifted_uur&#40;) const &#123; return bb_ << 15; &#125;
    inline
    Bitboard shifted_ull&#40;) const &#123; return bb_ << 10; &#125;
    inline
    Bitboard shifted_ul&#40;)  const &#123; return bb_ <<  9; &#125;
    inline
    Bitboard shifted_u&#40;)   const &#123; return bb_ <<  8; &#125;
    inline
    Bitboard shifted_ur&#40;)  const &#123; return bb_ <<  7; &#125;
    inline
    Bitboard shifted_urr&#40;) const &#123; return bb_ <<  6; &#125;
    inline
    Bitboard shifted_l&#40;)   const &#123; return bb_ <<  1; &#125;
    inline
    Bitboard shifted_r&#40;)   const &#123; return bb_ >>  1; &#125;
    inline
    Bitboard shifted_dll&#40;) const &#123; return bb_ >>  6; &#125;
    inline
    Bitboard shifted_dl&#40;)  const &#123; return bb_ >>  7; &#125;
    inline
    Bitboard shifted_d&#40;)   const &#123; return bb_ >>  8; &#125;
    inline
    Bitboard shifted_dr&#40;)  const &#123; return bb_ >>  9; &#125;
    inline
    Bitboard shifted_drr&#40;) const &#123; return bb_ >> 10; &#125;
    inline
    Bitboard shifted_ddl&#40;) const &#123; return bb_ >> 15; &#125;
    inline
    Bitboard shifted_ddr&#40;) const &#123; return bb_ >> 17; &#125;

    // take a piece
    inline
    void take&#40; const Bitboard &b ) &#123; bb_ &= ~b.bb_; &#125;
    // put a piece
    inline
    void put&#40; const Bitboard &b ) &#123; bb_ |= b.bb_; &#125;

    /**
    Set one bit only.
    */
    inline
    static Bitboard set_one_bit&#40; int nr ) &#123; return C64&#40;0x1&#41; << nr; &#125;

    /**
    Set a bit.
    */
    inline
    Bitboard with_bit&#40; int nr ) const &#123; return bb_ | &#40;C64&#40;0x1&#41; << nr&#41;; &#125;
    inline
    void set_bit&#40; int nr ) &#123; bb_ |= &#40;C64&#40;0x1&#41; << nr&#41;; &#125;

    /**
    Clear a bit.
    */
    inline
    Bitboard without_bit&#40; int nr ) const &#123; return bb_ & ~&#40;C64&#40;0x1&#41; << nr&#41;; &#125;
    inline
    void clear_bit&#40; int nr ) &#123; bb_ &= ~&#40;C64&#40;0x1&#41; << nr&#41;; &#125;

    /**
    Test a bit.
    */
    inline
    bool test_bit&#40; int nr ) const &#123; return &#40;bb_ & &#40;C64&#40;0x1&#41; << nr&#41;) != 0; &#125;


  private&#58;

    /**
    Get the least significant 1-bit.
    Clears all but the least significant 1-bit.
    */
    inline
    Bitboard get_the_ls1b&#40;) const &#123; return bb_ &  ( 0 - bb_ ); &#125;

    /**
    Get all but the least significant 1-bit.
    Clears only the least significant 1-bit.
    */
    inline
    Bitboard get_all_but_ls1b&#40;) const &#123; return bb_ & ( bb_ - 1 ); &#125;

    /**
    Count the bits in the bitboard. 
    &#40;Version with tricky b &= b - 1&#41;
    One loop for every set bit.
    */
    int bitcount_loop&#40;) const;

    /**
    Count the bits in the bitboard. 
    &#40;Version with tricky shifts&#41;
    */
    int bitcount_shift&#40;) const;

    /**
    Count the bits in the bitboard. 
    &#40;Version with small table&#41;
    */
    int bitcount_small_table&#40;) const;

    /**
    Count the bits in the bitboard. 
    &#40;Version with big table&#41;
    */
    int bitcount_big_table&#40;) const;

    /**
    Most significant bit number.
    Get the position of the most significant bit &#40;0-63&#41;. 
    \return 0-63 and 64 for an empty bitboard.
    (== log2&#41;
    &#40;Version with shifts&#41;
    */
    byte msb_nr_shift&#40;) const;

    /**
    Most significant bit number.
    Get the position of the most significant bit &#40;0-63&#41;. 
    \return 0-63 and 64 for an empty bitboard.
    (== log2&#41;
    &#40;Version with small table&#41;
    */
    byte msb_nr_small_table&#40;) const;

    /**
    Most significant bit number.
    Get the position of the most significant bit &#40;0-63&#41;. 
    \return 0-63 and 64 for an empty bitboard.
    (== log2&#41;
    &#40;Version with big table&#41;
    */
    byte msb_nr_big_table&#40;) const;

    /**
    Most significant bit number.
    Get the position of the most significant bit &#40;0-63&#41;. 
    \return 0-63 and 64 for an empty bitboard.
    (== log2&#41;
    &#40;Version with bsr = bit scan reverse )
    */
    byte msb_nr_bsr&#40;) const;

    /**
    Least significant bit number.
    Get the position of the least significant bit &#40;0-63&#41;. 
    \return 0-63 and 64 for an empty bitboard.
    &#40;Version with mod 11 every 8 bit&#41;
    */
    byte lsb_nr_with_mod11&#40;) const;

    /**
    Least significant bit number.
    Get the position of the least significant bit &#40;0-63&#41;. 
    \return 0-63 and 64 for an empty bitboard.
    &#40;Version with mod 19 every 16 bit&#41;
    */
    byte lsb_nr_with_mod19&#40;) const;

    /**
    Least significant bit number.
    Get the position of the least significant bit &#40;0-63&#41;. 
    \return 0-63 and 64 for an empty bitboard.
    &#40;Version with msb_nr&#41;
    */
    byte lsb_nr_with_msb&#40;) const;

    /**
    Least significant bit number.
    Get the position of the least significant bit &#40;0-63&#41;. 
    \return 0-63 and 64 for an empty bitboard.
    &#40;Version with bsf = bit scan forward )
    */
    byte lsb_nr_with_bsf&#40;) const;

    /**
    Fill an array with the positions of the set bits in a bitboard. 
    \return Number of entries/bits. 
    The bits are collected from MSB to LSB.
    */
    int get_bit_positions_from_msb&#40; byte positions&#91;64&#93; ) const;

    /**
    Fill an array with the positions of the set bits in a bitboard. 
    \return Number of entries/bits. 
    The bits are collected from MSB to LSB.
    */
    int get_bit_positions_from_msb_with_shift&#40; byte positions&#91;64&#93; ) const;

    /**
    Fill an array with the positions of the set bits in a bitboard. 
    \return Number of entries/bits. 
    The bits are collected from LSB to MSB.
    */
    int get_bit_positions_from_lsb&#40; byte positions&#91;64&#93; ) const;

    /**
    Fill an array with the positions of the set bits in a bitboard. 
    \return Number of entries/bits. 
    The bits are collected from LSB to MSB.
    */
    int get_bit_positions_from_lsb_with_shift&#40; byte positions&#91;64&#93; ) const;

&#125;;


/*******************************************************************/

void teste_bitboard&#40;);
void teste_time&#40;);


/*******************************************************************/

#endif // BB_BITBOARD_H_

/*******************************************************************/
bb_board.h:

Code: Select all

/*******************************************************************/
/*
The Chess board and its pieces implemented with bitboards

&#40;c&#41; 2002 Harald Lüßen
*/
/*******************************************************************/

#ifndef BB_BOARD_H_
#define BB_BOARD_H_


/*******************************************************************/

#include <string>
#include "bb_ifdef.h"
#include "bb_basics.h"
#include "bb_bitboard.h"
#include "bb_error.h"
#include "bb_piece.h"


/*******************************************************************/

/**
Some basic calculations
*/
#define ROW&#40; sq )           ( &#40;sq&#41; >> 3 )
#define BLACKS_ROW&#40; sq )    ( 7 - (&#40;sq&#41; >> 3&#41; )
#define LINE&#40; sq )          ( &#40;sq&#41; & 7 )
#define SQUARE&#40; row, line ) ( (&#40;row&#41; << 3&#41; | &#40;line&#41; )
#define ABS&#40; a )            ( &#40;a&#41; < 0 ? -&#40;a&#41; &#58; &#40;a&#41; )
#define ROW_DIST&#40; a, b )     ABS&#40; ROW&#40;a&#41; - ROW&#40;b&#41; )
#define LINE_DIST&#40; a, b )    ABS&#40; LINE&#40;a&#41; - LINE&#40;b&#41; )

/**
Swap the rows but not the lines
*/
#define MIRROR_SQUARE&#40; sq )                   SQUARE&#40; 7 - ROW&#40;sq&#41;, LINE&#40;sq&#41; )
#define MIRROR_SQUARE_BLACK_WHITE&#40; who, sq )  ( &#40;who&#41; == White ? &#40;sq&#41; &#58; MIRROR_SQUARE&#40;sq&#41; )


/*******************************************************************/

/*
    directions and shifts
    +-----+-----+-----+
    |<<= 9|<<= 8|<<= 7|
    +-----+-----+-----+
    |<<= 1|     |>>= 1|
    +-----+-----+-----+
    |>>= 7|>>= 8|>>= 9|
    +-----+-----+-----+

    We use this mapping of the normal board squares to bitboard bits
    +-------------------------+
    | 63 62 61 60 59 58 57 56 | 8
    | 55 54 53 52 51 50 49 48 | 7
    | 47 46 45 44 43 42 41 40 | 6
    | 39 38 37 36 35 35 33 32 | 5
    | 31 30 29 28 27 26 25 24 | 4
    | 23 22 21 20 19 18 17 16 | 3
    | 15 14 13 12 11 10  9  8 | 2
    |  7  6  5  4  3  2  1  0 | 1
    +-------------------------+
       a  b  c  d  e  f  g  h
*/

// constant square numbers
extern const byte NoSquareNr;
extern const byte A1Nr;
extern const byte A2Nr;
extern const byte A3Nr;
extern const byte A4Nr;
extern const byte A5Nr;
extern const byte A6Nr;
extern const byte A7Nr;
extern const byte A8Nr;
extern const byte B1Nr;
extern const byte B2Nr;
extern const byte B3Nr;
extern const byte B4Nr;
extern const byte B5Nr;
extern const byte B6Nr;
extern const byte B7Nr;
extern const byte B8Nr;
extern const byte C1Nr;
extern const byte C2Nr;
extern const byte C3Nr;
extern const byte C4Nr;
extern const byte C5Nr;
extern const byte C6Nr;
extern const byte C7Nr;
extern const byte C8Nr;
extern const byte D1Nr;
extern const byte D2Nr;
extern const byte D3Nr;
extern const byte D4Nr;
extern const byte D5Nr;
extern const byte D6Nr;
extern const byte D7Nr;
extern const byte D8Nr;
extern const byte E1Nr;
extern const byte E2Nr;
extern const byte E3Nr;
extern const byte E4Nr;
extern const byte E5Nr;
extern const byte E6Nr;
extern const byte E7Nr;
extern const byte E8Nr;
extern const byte F1Nr;
extern const byte F2Nr;
extern const byte F3Nr;
extern const byte F4Nr;
extern const byte F5Nr;
extern const byte F6Nr;
extern const byte F7Nr;
extern const byte F8Nr;
extern const byte G1Nr;
extern const byte G2Nr;
extern const byte G3Nr;
extern const byte G4Nr;
extern const byte G5Nr;
extern const byte G6Nr;
extern const byte G7Nr;
extern const byte G8Nr;
extern const byte H1Nr;
extern const byte H2Nr;
extern const byte H3Nr;
extern const byte H4Nr;
extern const byte H5Nr;
extern const byte H6Nr;
extern const byte H7Nr;
extern const byte H8Nr;

// constant bitboards

// lines
extern const Bitboard line_a;
extern const Bitboard line_b;
extern const Bitboard line_c;
extern const Bitboard line_d;
extern const Bitboard line_e;
extern const Bitboard line_f;
extern const Bitboard line_g;
extern const Bitboard line_h;
extern const Bitboard line_ab;
extern const Bitboard line_ac;
extern const Bitboard line_ad;
extern const Bitboard line_ae;
extern const Bitboard line_af;
extern const Bitboard line_ag;
extern const Bitboard line_ah;
extern const Bitboard line_bh;
extern const Bitboard line_ch;
extern const Bitboard line_dh;
extern const Bitboard line_eh;
extern const Bitboard line_fh;
extern const Bitboard line_gh;
// rows
extern const Bitboard row_1;
extern const Bitboard row_2;
extern const Bitboard row_3;
extern const Bitboard row_4;
extern const Bitboard row_5;
extern const Bitboard row_6;
extern const Bitboard row_7;
extern const Bitboard row_8;
extern const Bitboard row_18;
extern const Bitboard row_17;
extern const Bitboard row_16;
extern const Bitboard row_15;
extern const Bitboard row_14;
extern const Bitboard row_13;
extern const Bitboard row_12;
extern const Bitboard row_28;
extern const Bitboard row_38;
extern const Bitboard row_48;
extern const Bitboard row_58;
extern const Bitboard row_68;
extern const Bitboard row_78;
// squares
extern const Bitboard NoSquare;
extern const Bitboard A1;
extern const Bitboard A2;
extern const Bitboard A3;
extern const Bitboard A4;
extern const Bitboard A5;
extern const Bitboard A6;
extern const Bitboard A7;
extern const Bitboard A8;
extern const Bitboard B1;
extern const Bitboard B2;
extern const Bitboard B3;
extern const Bitboard B4;
extern const Bitboard B5;
extern const Bitboard B6;
extern const Bitboard B7;
extern const Bitboard B8;
extern const Bitboard C1;
extern const Bitboard C2;
extern const Bitboard C3;
extern const Bitboard C4;
extern const Bitboard C5;
extern const Bitboard C6;
extern const Bitboard C7;
extern const Bitboard C8;
extern const Bitboard D1;
extern const Bitboard D2;
extern const Bitboard D3;
extern const Bitboard D4;
extern const Bitboard D5;
extern const Bitboard D6;
extern const Bitboard D7;
extern const Bitboard D8;
extern const Bitboard E1;
extern const Bitboard E2;
extern const Bitboard E3;
extern const Bitboard E4;
extern const Bitboard E5;
extern const Bitboard E6;
extern const Bitboard E7;
extern const Bitboard E8;
extern const Bitboard F1;
extern const Bitboard F2;
extern const Bitboard F3;
extern const Bitboard F4;
extern const Bitboard F5;
extern const Bitboard F6;
extern const Bitboard F7;
extern const Bitboard F8;
extern const Bitboard G1;
extern const Bitboard G2;
extern const Bitboard G3;
extern const Bitboard G4;
extern const Bitboard G5;
extern const Bitboard G6;
extern const Bitboard G7;
extern const Bitboard G8;
extern const Bitboard H1;
extern const Bitboard H2;
extern const Bitboard H3;
extern const Bitboard H4;
extern const Bitboard H5;
extern const Bitboard H6;
extern const Bitboard H7;
extern const Bitboard H8;
// pieces at begin of game
extern const Bitboard begin_pawns;
extern const Bitboard begin_rooks;
extern const Bitboard begin_knights;
extern const Bitboard begin_bishops;
extern const Bitboard begin_queens;
extern const Bitboard begin_kings;
// interesting for castling
extern const Bitboard castling_squares;
// pieces at begin of game in rotated bitboards
extern const Bitboard begin_all_rl90;
extern const Bitboard begin_all_rl45;
extern const Bitboard begin_all_rr45;
// black and white squares, interesting for bishops?
extern const Bitboard wsquares;
extern const Bitboard bsquares;
// more ideas
extern const Bitboard border;
extern const Bitboard center4;
extern const Bitboard center16;
extern const Bitboard corners;
extern const Bitboard wdevelopment_squares;
extern const Bitboard bdevelopment_squares;
extern const Bitboard wking_after_castling;
extern const Bitboard bking_after_castling;
extern const Bitboard wking_in_opening;
extern const Bitboard bking_in_opening;


#if USE_ROTATED_BITBOARDS&#40;) || USE_ROTATED_BITBOARDS_LINES&#40;) || USE_ROTATED_BITBOARDS_SWITCH&#40;)

// Bit numbers of the normal board in the rotated board
extern const byte normal_to_rl90&#91;64&#93;;

// Bit numbers of the normal board in the rotated board
extern const byte normal_to_rl45&#91;64&#93;;

// Bit numbers of the normal board in the rotated board
extern const byte normal_to_rr45&#91;64&#93;;

#endif // USE_ROTATED_BITBOARDS&#40;) || USE_ROTATED_BITBOARDS_LINES&#40;) || USE_ROTATED_BITBOARDS_SWITCH&#40;)


/*******************************************************************/

/**
Color of a square or piece.
Who has the right to move?
What side does the engine play?
*/
extern const int None;
extern const int White;
extern const int Black;
extern const int Both;

#define OPPONENT&#40;c&#41; &#40;1-&#40;c&#41;)


/*******************************************************************/
/*******************************************************************/

/**
The Chess board and its pieces 
implemented with bitboards
*/
class Board
&#123;
  public&#58;

    // basic bitboards of pieces
    Bitboard  pawns_;
    Bitboard  knights_;
    Bitboard  bishops_;
    Bitboard  rooks_;
    Bitboard  queens_;
    Bitboard  kings_;
    Bitboard  wpieces_;
    Bitboard  bpieces_;

#if USE_ROTATED_BITBOARDS&#40;) || USE_ROTATED_BITBOARDS_LINES&#40;) || USE_ROTATED_BITBOARDS_SWITCH&#40;)
    // rotated bitboards
    Bitboard  all_rl90_;
    Bitboard  all_rl45_;
    Bitboard  all_rr45_;
#endif

#if USE_ROTATED_INDICES&#40;)
    // 7 6 5 4 3 2 1 0
    // 7 6 5 4 3 2 1 0
    // 7 6 5 4 3 2 1 0
    // 7 6 5 4 3 2 1 0
    // 7 6 5 4 3 2 1 0
    // 7 6 5 4 3 2 1 0
    // 7 6 5 4 3 2 1 0
    // 7 6 5 4 3 2 1 0
    byte slideIndexV&#91;8&#93;;     // vertical

    // 14 13 12 11 10  9  8  7
    // 13 12 11 10  9  8  7  6
    // 12 11 10  9  8  7  6  5
    // 11 10  9  8  7  6  5  4
    // 10  9  8  7  6  5  4  3
    //  9  8  7  6  5  4  3  2
    //  8  7  6  5  4  3  2  1
    //  7  6  5  4  3  2  1  0
    byte slideIndexRU&#91;15&#93;;   // right up

    //  7  6  5  4  3  2  1  0
    //  8  7  6  5  4  3  2  1
    //  9  8  7  6  5  4  3  2
    // 10  9  8  7  6  5  4  3
    // 11 10  9  8  7  6  5  4
    // 12 11 10  9  8  7  6  5
    // 13 12 11 10  9  8  7  6
    // 14 13 12 11 10  9  8  7
    byte slideIndexRD&#91;15&#93;;   // right down
#endif

#if USE_PIECES_ON_BOARD_ARRAY&#40;)
    signed char pieces_on_board_&#91;64&#93;;
#endif

    // Where are the kings? Provide easy access to this important information.
    byte wking_sq_;
    byte bking_sq_;

    /**
    Attacked squares of white pawns
    */
    static Bitboard white_pawn_attacks&#91;64&#93;;

    /**
    Attacked squares of black pawns
    */
    static Bitboard black_pawn_attacks&#91;64&#93;;

    /**
    Attacked squares of kings
    */
    static Bitboard king_attacks&#91;64&#93;;

    /**
    Attacked squares of knights
    */
    static Bitboard knight_attacks&#91;64&#93;;

    /**
    Directions &#40;0 or 1-8&#41; from square to square.
    4 3 2
    5 0 1
    6 7 8
    */
    static byte direction&#91;64&#93;&#91;64&#93;;

    /**
    Flag to indicate successful initialization of constant arrays.
    */
    static bool initialised;

  public&#58;

    /**
    Constructor.
    */
    inline
    Board&#40;)
    &#123;
        clear&#40;);
        if ( !initialised )
        &#123;
            // Prepare all arrays, constants and other data
            initialised = true;
            init_board_data&#40;);
        &#125;
    &#125;

    /**
    Clear the board.
    */
    void clear&#40;);

    /**
    Test if the board is empty.
    */
    inline
    bool empty&#40;) const &#123; return wpieces_.empty&#40;) && bpieces_.empty&#40;); &#125;

    /**
    Set the pieces to the opening position.
    */
    void opening_position&#40;);

    /**
    Read a board from a FEN string.
    */
    Error fen&#40; const std&#58;&#58;string &fens );

    /**
    Write a board to a FEN string.
    */
    std&#58;&#58;string fen&#40;) const;

    /**
    Write a board to ASCII graphic.
    */
    std&#58;&#58;string ascii_graphic&#40;) const;

    /**
    Check some basic board features which are important for the program. 
    \return error, OK if the board is ok
    */
    Error check_board&#40;) const;

    /**
    Check some basic chess rules which are important for the program. 
    \return error, OK if the board is ok
    */
    Error check_rules&#40;) const;

    /**
    Which piece is on a square?
    No destinction between white and black pieces.
    */
    inline
    int get_abs_piece_on_square&#40; const byte sq ) const
    &#123;
#if USE_PIECES_ON_BOARD_ARRAY&#40;)
        return ABS&#40;pieces_on_board_&#91;sq&#93;);
#else
        Bitboard bb = C64&#40;0x1&#41; << sq;
        if ( pawns_   & bb )  return PawnNr;
        if ( knights_ & bb )  return KnightNr;
        if ( bishops_ & bb )  return BishopNr;
        if ( rooks_   & bb )  return RookNr;
        if ( queens_  & bb )  return QueenNr;
        if ( kings_   & bb )  return KingNr;
        return NoPieceNr;
#endif
    &#125;

    /**
    Which piece is on a square?
    White pieces are positive, black pieces are negative.
    */
    inline
    int get_piece_on_square&#40; const byte sq ) const
    &#123;
#if USE_PIECES_ON_BOARD_ARRAY&#40;)
        return pieces_on_board_&#91;sq&#93;;
#else
        Bitboard bb = C64&#40;0x1&#41; << sq;
        if ( pawns_   & bb )  return &#40;bb & wpieces_) ? PawnNr   &#58; -PawnNr;
        if ( knights_ & bb )  return &#40;bb & wpieces_) ? KnightNr &#58; -KnightNr;
        if ( bishops_ & bb )  return &#40;bb & wpieces_) ? BishopNr &#58; -BishopNr;
        if ( rooks_   & bb )  return &#40;bb & wpieces_) ? RookNr   &#58; -RookNr;
        if ( queens_  & bb )  return &#40;bb & wpieces_) ? QueenNr  &#58; -QueenNr;
        if ( kings_   & bb )  return &#40;bb & wpieces_) ? KingNr   &#58; -KingNr;
        return NoPieceNr;
#endif
    &#125;

    /**
    Is the square attacked?
    &#40;En passant is not part of this test.)
    */
    bool attacks_square&#40; byte square, int who ) const;

    /**
    Get a bitboard with all positions set to 1 which can be attacked 
    from a bishop or queen on the square.
    */
    Bitboard diagonal_attacks&#40; byte square ) const;

    /**
    Get a bitboard with all positions set to 1 which can be attacked 
    from a rook or queen on the square.
    */
    Bitboard orthogonal_attacks&#40; byte square ) const;

    /**
    Get a bitboard with all positions set to 1 which can be attacked 
    from a bishop, rook or queen on the square moving in the direction.
    */
    Bitboard direction_attacks&#40; byte square, byte dir ) const;

    /**
    Get valuable Pieces with at least a material value of min_value.
    There are no kings in the resulting Bitboard.
    Used to filter opponent pieces to generate captures with a sufficient value.
    */
    Bitboard valuable_pieces&#40; value_type min_value ) const;

    /**
    Do the static exchange evaluation &#40;SEE&#41; and return the value.
    This is the material value that results from captures and recaptures 
    on the to square of a capture move from to by who. 
    Capture moves on other squares, attacked kings and other moves are ignored.
    */
    value_type get_static_exchange_evaluation&#40; byte from, byte to, int who ) const;

  private&#58;

    /**
    Possible Attacks of a sliding piece &#40;8 positions&#41; in a single line of squares 
    filled with other pieces &#40;8 bits, 256 values&#41;.
    Returns a byte with all bits set which can be reached through empty positions 
    and the first blocked position.
    */
    static byte slider_attacks&#91;64&#93;&#91;8&#93;;

  private&#58;

    /**
    Prepare all arrays, constants and other data
    */
    static void init_board_data&#40;);

#if USE_ROTATED_BITBOARDS&#40;) || USE_ROTATED_BITBOARDS_LINES&#40;) || USE_ROTATED_BITBOARDS_SWITCH&#40;) || USE_ROTATED_INDICES&#40;)
    /**
    Set the rotated bitboards of all pieces
    */
    void set_all_rotated_bitboards&#40;);
#endif

#if USE_PIECES_ON_BOARD_ARRAY&#40;)
    /**
    Set the pieces on the additional piece board.
    */
    void set_pieces_on_board&#40;);
#endif

    /**
    Prepare directions &#40;0 or 1-8&#41; from square to square.
    4 3 2
    5 0 1
    6 7 8
    */
    static void init_directions&#40;);

    /**
    Prepare all attacks of pawns, kings and knights.
    */
    static void init_simple_attacks&#40;);

    /**
    Prepare the attacks for sliding pieces.
    */
    static void init_slider_attacks&#40;);

#if USE_ROTATED_BITBOARDS&#40;) || USE_ROTATED_BITBOARDS_LINES&#40;) || USE_ROTATED_BITBOARDS_SWITCH&#40;) || USE_EXPLODING_BITBOARDS&#40;) || USE_MAGIC_BITBOARDS&#40;) || USE_SHERWIN_BITBOARDS&#40;) || USE_PRADU_BITBOARDS&#40;) || USE_ROTATED_INDICES&#40;)
    /**
    Prepare the slider attacks back transformation tabel.
    Put the scattered bits of an sliding attack pattern 
    back to the original bitboard.
    */
    static void init_slider_attacks_index&#40;);
#endif

    /**
    Which pieces of both sides can attack the square?
    &#40;En passant is not part of this test.)
    */
    void all_attackers&#40; byte square, Bitboard &white_attackers, Bitboard &black_attackers ) const;

  public&#58;
  
#if USE_EXPLODING_BITBOARDS&#40;)
    /**
    Change generating of bishop and rook attacks.
    Perhaps this improves the performance. 
    Use this function at begin of search, at least when the remaining depth is big.
    */
    void change_slider_attacks_index&#40;);
#endif

    /**
    Which white pieces can attack the square?
    &#40;En passant is not part of this test.)
    */
    void white_attackers&#40; byte square, Bitboard &white_attackers ) const;

    /**
    Which black pieces can attack the square?
    &#40;En passant is not part of this test.)
    */
    void black_attackers&#40; byte square, Bitboard &black_attackers ) const;

&#125;;


/*******************************************************************/

void teste_board&#40;);


/*******************************************************************/

#endif // BB_BOARD_H_


/*******************************************************************/
bb_attacks_common:

Code: Select all

/*******************************************************************/
/*
The common bitboard attack parts of the board structure.

&#40;c&#41; 2002-2006 Harald Lüßen
*/
/*******************************************************************/

#include "bb_ifdef.h"
#include "bb_basics.h"
#include "bb_bitboard.h"
#include "bb_board.h"


/*******************************************************************/

/*
    directions and shifts
    +-----+-----+-----+
    |<<= 9|<<= 8|<<= 7|
    +-----+-----+-----+
    |<<= 1|     |>>= 1|
    +-----+-----+-----+
    |>>= 7|>>= 8|>>= 9|
    +-----+-----+-----+

    We use this mapping of the normal board squares to bitboard bits
    +-------------------------+
    | 63 62 61 60 59 58 57 56 | 8
    | 55 54 53 52 51 50 49 48 | 7
    | 47 46 45 44 43 42 41 40 | 6
    | 39 38 37 36 35 35 33 32 | 5
    | 31 30 29 28 27 26 25 24 | 4
    | 23 22 21 20 19 18 17 16 | 3
    | 15 14 13 12 11 10  9  8 | 2
    |  7  6  5  4  3  2  1  0 | 1
    +-------------------------+
       a  b  c  d  e  f  g  h
*/


/*******************************************************************/

/**
Attacked squares of white pawns
*/
Bitboard Board&#58;&#58;white_pawn_attacks&#91;64&#93;;

/**
Attacked squares of black pawns
*/
Bitboard Board&#58;&#58;black_pawn_attacks&#91;64&#93;;

/**
Attacked squares of kings
*/
Bitboard Board&#58;&#58;king_attacks&#91;64&#93;;

/**
Attacked squares of knights
*/
Bitboard Board&#58;&#58;knight_attacks&#91;64&#93;;

/**
Directions &#40;0 or 1-8&#41; from square to square.
4 3 2
5 0 1
6 7 8
*/
byte Board&#58;&#58;direction&#91;64&#93;&#91;64&#93;;

/**
Possible Attacks of a sliding piece &#40;8 positions&#41; in a single line of squares 
filled with other pieces &#40;8 bits, 256 values&#41;.
Returns a byte with all bits set which can be reached through empty positions 
and the first blocked position.
*/
byte Board&#58;&#58;slider_attacks&#91;64&#93;&#91;8&#93;;


/*******************************************************************/

/**
Is the square attacked from the color who?
&#40;En passant is not part of this test.)
*/
bool Board&#58;&#58;attacks_square&#40; byte square, int who ) const
&#123;
#if 1
    Bitboard own_pieces;
    Bitboard bb = pawns_;

    // Some moves depend on the color to move.
    if ( who == White )
    &#123;
        own_pieces = wpieces_;
        // Can a black pawn on square capture a white pawn?
        bb &= own_pieces;
        if ( bb )
        &#123;
            bb &= black_pawn_attacks&#91;square&#93;;
            if ( bb )
                return true;
        &#125;
    &#125;
    else // Black
    &#123;
        own_pieces = bpieces_;
        // Can a white pawn on square capture a black pawn?
        bb &= own_pieces;
        if ( bb )
        &#123;
            bb &= white_pawn_attacks&#91;square&#93;;
            if ( bb )
                return true;
        &#125;
    &#125; // endif White or Black Pawns
    // En passant is not part of this test.

    // Knights
    bb  = knights_;
    bb &= own_pieces;
    if ( bb )
    &#123;
        bb &= knight_attacks&#91;square&#93;;
        if ( bb )
            return true;
    &#125;

    // Kings
    bb  = kings_;
    bb &= own_pieces;
    bb &= king_attacks&#91;square&#93;;
    if ( bb )
        return true;

    // Rooks, Queens
    bb  = &#40;rooks_ | queens_);
    bb &= own_pieces;
    if ( bb )
    &#123;
        bb &= orthogonal_attacks&#40; square );
        if ( bb )
            return true;
    &#125;

    // Bishops, Queens
    bb  = &#40;bishops_ | queens_);
    bb &= own_pieces;
    if ( bb )
    &#123;
        bb &= diagonal_attacks&#40; square );
        if ( bb )
            return true;
    &#125;

    return false;
#else
    Bitboard attackers;
    if ( who == White )
    &#123;
        white_attackers&#40; square, attackers );
        if ( attackers )
            return true;
    &#125;
    else // Black
    &#123;
        black_attackers&#40; square, attackers );
        if ( attackers )
            return true;
    &#125;
    return false;
#endif
&#125;


/*******************************************************************/

/**
Which pieces of both sides can attack the square?
&#40;En passant is not part of this test.)
*/
void Board&#58;&#58;all_attackers&#40; byte square, Bitboard &white_attackers, Bitboard &black_attackers ) const
&#123;
    white_attackers = &#40;pawns_ & black_pawn_attacks&#91;square&#93;);
    black_attackers = &#40;pawns_ & white_pawn_attacks&#91;square&#93;);
    Bitboard attackers  = ( knights_            & knight_attacks&#91;square&#93;);
             attackers |= ( kings_              & king_attacks&#91;square&#93;);
             attackers |= (&#40;bishops_ | queens_) & diagonal_attacks&#40; square ));
             attackers |= (&#40;rooks_   | queens_) & orthogonal_attacks&#40; square ));
    white_attackers |= attackers;
    white_attackers &= wpieces_;
    black_attackers |= attackers;
    black_attackers &= bpieces_;
&#125;


/*******************************************************************/

/**
Which white pieces can attack the square?
&#40;En passant is not part of this test.)
*/
void Board&#58;&#58;white_attackers&#40; byte square, Bitboard &white_attackers ) const
&#123;
    white_attackers  = ( pawns_              & black_pawn_attacks&#91;square&#93;);
    white_attackers |= ( knights_            & knight_attacks&#91;square&#93;);
    white_attackers |= ( kings_              & king_attacks&#91;square&#93;);
    white_attackers |= (&#40;bishops_ | queens_) & diagonal_attacks&#40; square ));
    white_attackers |= (&#40;rooks_   | queens_) & orthogonal_attacks&#40; square ));
    white_attackers &= wpieces_;
&#125;


/*******************************************************************/

/**
Which black pieces can attack the square?
&#40;En passant is not part of this test.)
*/
void Board&#58;&#58;black_attackers&#40; byte square, Bitboard &black_attackers ) const
&#123;
    black_attackers  = ( pawns_              & white_pawn_attacks&#91;square&#93;);
    black_attackers |= ( knights_            & knight_attacks&#91;square&#93;);
    black_attackers |= ( kings_              & king_attacks&#91;square&#93;);
    black_attackers |= (&#40;bishops_ | queens_) & diagonal_attacks&#40; square ));
    black_attackers |= (&#40;rooks_   | queens_) & orthogonal_attacks&#40; square ));
    black_attackers &= bpieces_;
&#125;


/*******************************************************************/

/**
Prepare directions &#40;0 or 1-8&#41; from square to square.
4 3 2
5 0 1
6 7 8
*/
void Board&#58;&#58;init_directions&#40;)
&#123;
    int sq;
    int to;

    // 0, no orthogonal or diagonal connection
    for ( sq = H1Nr; sq <= A8Nr; ++sq )
    &#123;
        for ( to = H1Nr; to <= A8Nr; ++to )
        &#123;
            direction&#91;sq&#93;&#91;to&#93; = 0;
        &#125;
    &#125;
    for ( sq = H1Nr; sq <= A8Nr; ++sq )
    &#123;
        // 1 (-1&#41;
        for ( to = sq - 1; to >= H1Nr && to % 8 != 7; --to )
            direction&#91;sq&#93;&#91;to&#93; = 1;
        // 2 (+7&#41;
        for ( to = sq + 7; to <  A8Nr && to % 8 != 7; to += 7 )
            direction&#91;sq&#93;&#91;to&#93; = 2;
        // 3 (+8&#41;
        for ( to = sq + 8; to <= A8Nr;                to += 8 )
            direction&#91;sq&#93;&#91;to&#93; = 3;
        // 4 (+9&#41;
        for ( to = sq + 9; to <= A8Nr && to % 8 != 0; to += 9 )
            direction&#91;sq&#93;&#91;to&#93; = 4;
        // 5 (+1&#41;
        for ( to = sq + 1; to <= A8Nr && to % 8 != 0; ++to )
            direction&#91;sq&#93;&#91;to&#93; = 5;
        // 6 (-7&#41;
        for ( to = sq - 7; to >  H1Nr && to % 8 != 0; to -= 7 )
            direction&#91;sq&#93;&#91;to&#93; = 6;
        // 7 (-8&#41;
        for ( to = sq - 8; to >= H1Nr;                to -= 8 )
            direction&#91;sq&#93;&#91;to&#93; = 7;
        // 8 (-9&#41;
        for ( to = sq - 9; to >= H1Nr && to % 8 != 7; to -= 9 )
            direction&#91;sq&#93;&#91;to&#93; = 8;
    &#125;
&#125;


/*******************************************************************/

/**
Prepare all attacks of pawns, kings and knights.
*/
void Board&#58;&#58;init_simple_attacks&#40;)
&#123;
    byte sq;
    Bitboard bb;

    // Attacked squares of white pawns
    for ( sq = H1Nr; sq <= A8Nr; ++sq )
    &#123;
        white_pawn_attacks&#91;sq&#93; = 0;
        // Fill in even attacks from A1 to H1 because this array ist sometimes 
        // used in a reversed way for black pawns attacking pieces while promoting.
        if ( sq > A7Nr )
            continue;
        bb = bb.set_one_bit&#40; sq );
        if ( !&#40;bb & line_a&#41; )
            white_pawn_attacks&#91;sq&#93; |= bb.shifted_ul&#40;);
        if ( !&#40;bb & line_h&#41; )
            white_pawn_attacks&#91;sq&#93; |= bb.shifted_ur&#40;);
    &#125;

    // Attacked squares of black pawns
    for ( sq = H1Nr; sq <= A8Nr; ++sq )
    &#123;
        black_pawn_attacks&#91;sq&#93; = 0;
        // Fill in even attacks from A8 to H8 because this array ist sometimes 
        // used in a reversed way for white pawns attacking pieces while promoting.
        if ( sq < H2Nr )
            continue;
        bb = bb.set_one_bit&#40; sq );
        if ( !&#40;bb & line_a&#41; )
            black_pawn_attacks&#91;sq&#93; |= bb.shifted_dl&#40;);
        if ( !&#40;bb & line_h&#41; )
            black_pawn_attacks&#91;sq&#93; |= bb.shifted_dr&#40;);
    &#125;

    // Attacked squares of kings
    for ( sq = H1Nr; sq <= A8Nr; ++sq )
    &#123;
        king_attacks&#91;sq&#93; = 0;
        bb = bb.set_one_bit&#40; sq );
        if ( !&#40;bb & line_a&#41; )
        &#123;
            king_attacks&#91;sq&#93; |= bb.shifted_ul&#40;);
            king_attacks&#91;sq&#93; |= bb.shifted_l&#40;);
            king_attacks&#91;sq&#93; |= bb.shifted_dl&#40;);
        &#125;
        if ( !&#40;bb & line_h&#41; )
        &#123;
            king_attacks&#91;sq&#93; |= bb.shifted_ur&#40;);
            king_attacks&#91;sq&#93; |= bb.shifted_r&#40;);
            king_attacks&#91;sq&#93; |= bb.shifted_dr&#40;);
        &#125;
        king_attacks&#91;sq&#93; |= bb.shifted_u&#40;);
        king_attacks&#91;sq&#93; |= bb.shifted_d&#40;);
    &#125;

    // Attacked squares of knights
    for ( sq = H1Nr; sq <= A8Nr; ++sq )
    &#123;
        knight_attacks&#91;sq&#93; = 0;
        bb = bb.set_one_bit&#40; sq );
        if ( !&#40;bb & line_a&#41; )
        &#123;
            knight_attacks&#91;sq&#93; |= bb.shifted_uul&#40;);
            knight_attacks&#91;sq&#93; |= bb.shifted_ddl&#40;);
            if ( !&#40;bb & line_b&#41; )
            &#123;
                knight_attacks&#91;sq&#93; |= bb.shifted_ull&#40;);
                knight_attacks&#91;sq&#93; |= bb.shifted_dll&#40;);
            &#125;
        &#125;
        if ( !&#40;bb & line_h&#41; )
        &#123;
            knight_attacks&#91;sq&#93; |= bb.shifted_uur&#40;);
            knight_attacks&#91;sq&#93; |= bb.shifted_ddr&#40;);
            if ( !&#40;bb & line_g&#41; )
            &#123;
                knight_attacks&#91;sq&#93; |= bb.shifted_urr&#40;);
                knight_attacks&#91;sq&#93; |= bb.shifted_drr&#40;);
            &#125;
        &#125;
    &#125;
&#125;


/*******************************************************************/

/**
Prepare the attacks for sliding pieces.
*/
void Board&#58;&#58;init_slider_attacks&#40;)
&#123;
    // Possible Attacks of a sliding piece &#40;8 positions&#41; in a single line of squares 
    // filled with other pieces &#40;8 bits, 256 values&#41;.
    // From this only the middle 6 bits are needed. 
    // The outside bits have no influence on their accessability. 
    // Therefore slider_attacks uses only &#91;64&#93;&#91;8&#93; as index.
    // slider_attacks returns a byte with all bits set which can be reached through 
    // empty positions and the first blocked position.

    int pattern;
    for ( pattern = 0; pattern < 128; pattern += 2 )
    &#123;
        int pos;
        for ( pos = 0; pos < 8; ++pos )
        &#123;
            byte result = 0;
            int i;
            for ( i = 1; i < 8; ++i )
            &#123;
                int testpos = pos + i;
                if ( testpos >= 8 )
                    break;
                int testbit = 1 << testpos;
                result |= testbit;
                if ( pattern & testbit )
                    break;
            &#125;
            for ( i = 1; i < 8; ++i )
            &#123;
                int testpos = pos - i;
                if ( testpos < 0 )
                    break;
                int testbit = 1 << testpos;
                result |= testbit;
                if ( pattern & testbit )
                    break;
            &#125;
            slider_attacks&#91;&#40;pattern >> 1&#41; & 0x3f&#93;&#91;pos&#93; = result;
        &#125;
    &#125;
&#125;


/*******************************************************************/
Harald

Harald
Posts: 259
Joined: Thu Mar 09, 2006 12:07 am

Re: BitBoard Tests (Gerd's Kindergarten Magic)

Post by Harald » Sat Aug 25, 2007 6:47 am

bb_attacks_magic.cpp:

Code: Select all

/*******************************************************************/
/*
The magic multiplication bitboard attacks 
as part of the board structure. 
The original code comes from Gerd Isenberg. 

&#40;c&#41; 2006 Harald Lüßen
*/
/*******************************************************************/


#include "bb_ifdef.h"
#include "bb_basics.h"
#include "bb_bitboard.h"
#include "bb_board.h"
#include "bb_main.h"


#if USE_MAGIC_BITBOARDS&#40;)

/*******************************************************************/

/*
    directions and shifts
    +-----+-----+-----+
    |<<= 9|<<= 8|<<= 7|
    +-----+-----+-----+
    |<<= 1|     |>>= 1|
    +-----+-----+-----+
    |>>= 7|>>= 8|>>= 9|
    +-----+-----+-----+

    We use this mapping of the normal board squares to bitboard bits
    +-------------------------+
    | 63 62 61 60 59 58 57 56 | 8
    | 55 54 53 52 51 50 49 48 | 7
    | 47 46 45 44 43 42 41 40 | 6
    | 39 38 37 36 35 35 33 32 | 5
    | 31 30 29 28 27 26 25 24 | 4
    | 23 22 21 20 19 18 17 16 | 3
    | 15 14 13 12 11 10  9  8 | 2
    |  7  6  5  4  3  2  1  0 | 1
    +-------------------------+
       a  b  c  d  e  f  g  h
*/

/*******************************************************************/

/**
Possible Attacks of a sliding piece &#40;8 positions&#41; in a single line of squares 
filled with other pieces &#40;8 bits, 256 values&#41;.
Returns a byte with all bits set which can be reached through empty positions 
and the first blocked position.
This is a copy of Board&#58;&#58;slider_attacks&#91;64&#93;&#91;8&#93;; In this quick hack I have access problems.
*/
byte firstRankAttacks&#91;64&#93;&#91;8&#93;;

// Projection of 8 bit first rank pattern &#40;with 6 bit index b1..g1&#41; 
// in north direction through the board, for slider on each file.
// This is used for diagonal attacks.
Bitboard fillUpAttacks&#91;64&#93;&#91;8&#93;;

// Bitboard with 8 bit h-file pattern &#40;with 6 bit index h2..h7&#41; 
// for slider on each rank. This is used for vertical file attacks.
Bitboard hFileAttacks&#91;64&#93;&#91;8&#93;;

// Mask for the diagonal slider rays
Bitboard h1a8DiagonalMask&#91;64&#93;;

// Mask for the diagonal slider rays
Bitboard a1h8DiagonalMask&#91;64&#93;;


/*******************************************************************/

#if 0 // good for 64 bit machines

Bitboard rankAttacks&#40; Bitboard occ, int sq )
&#123;
   int f = sq &  7;
   int r = sq & ~7; // rank * 8
   int o = &#40;int&#41;&#40;occ >> &#40;r+1&#41;) & 0x3f;
   return &#40;Bitboard&#41;firstRankAttacks&#91;o&#93;&#91;f&#93; << r;
&#125;

Bitboard fileAttacks&#40; Bitboard occ, int sq )
&#123;
   int f = sq & 7;
   occ   =   C64&#40;0x0101010101010101&#41; & &#40;occ   >> f&#41;; // h-file
   int o = ( C64&#40;0x0080402010080400&#41; *  occ ) >> 58; // h2..h7 -> bits 63..58 -> bits 5..0
   return  ( hFileAttacks&#91;o&#93;&#91;sq >> 3&#93;       ) << f;   
&#125;

Bitboard diagonalAttacks&#40; Bitboard occ, int sq )
&#123;
   int f = sq & 7;
   occ   = ( h1a8DiagonalMask&#91;sq&#93;    &  occ );
   // 1 step west and stripes northward to bits &#40;64&#41;63..57
   // without unimportant edge bits -> bits 63..58 -> bits 5..0
   int o = ( C64&#40;0x0202020202020202&#41; *  occ ) >> 58;
   return  ( h1a8DiagonalMask&#91;sq&#93;    &  fillUpAttacks&#91;o&#93;&#91;f&#93; );
&#125;

Bitboard antiDiagAttacks&#40; Bitboard occ, int sq )
&#123;
   int f = sq & 7;
   occ   = ( a1h8DiagonalMask&#91;sq&#93;    &  occ );
   // 1 step west and stripes northward to bits &#40;64&#41;63..57
   // without unimportant edge bits -> bits 63..58 -> bits 5..0
   int o = ( C64&#40;0x0202020202020202&#41; *  occ ) >> 58;
   return  ( a1h8DiagonalMask&#91;sq&#93;    &  fillUpAttacks&#91;o&#93;&#91;f&#93; );
&#125; 

#else // good for 32 bit machines

// for all getters
// @param occ - the occupied bitboard
//        sq  - square index 0..63 &#40;a1..h8&#41;
// @return the attack set
Bitboard rankAttacks&#40; Bitboard occupied, int sq )
&#123;
   union &#123; Bits64 b; struct &#123; unsigned int l; unsigned int h; &#125;; &#125; b; // little endian!
   int f = sq & 7;
   int r = sq & 24; // 8 * folded rank
   if ( sq < 32 ) &#123;
      b.l = ((&#40;unsigned int&#41;occupied&#41; >> &#40;r+1&#41;) & 63;
      b.l = firstRankAttacks&#91;b.l&#93;&#91;f&#93; << r;
      b.h = 0;
   &#125; else &#123;
      b.l = 0;
      b.h = ((&#40;unsigned int&#41;&#40;occupied>>32&#41;) >> &#40;r+1&#41;) & 63;
      b.h = firstRankAttacks&#91;b.h&#93;&#91;f&#93; << r;
   &#125;
   return b.b;
&#125;

// file attacks with two reversed rotations
// 1. for the occupied state to map a2..a7 to h8..c8
// 2. for the attacks from a1..h1 to h8..h1
Bitboard fileAttacks&#40; Bitboard occupied, int sq )
&#123;
   union &#123; Bits64 b; struct &#123; unsigned int l; unsigned int h; &#125;; &#125; b; // little endian!
   int f = sq & 7;
   b.b = occupied;
   b.l = &#40;b.l >> f&#41; & 0x01010101;
   b.h = &#40;b.h >> f&#41; & 0x01010101;
   b.l = &#40;b.l << 4&#41; + b.h;
   b.h = &#40;b.l       * 0x10080402&#41; >> 26;
   b.l = 0x08040201 * firstRankAttacks&#91;b.h&#93;&#91;&#40;sq^56&#41;>>3&#93;;
   b.h =(&#40;b.l << 4&#41; & 0x80808080&#41; >> &#40;f^7&#41;;
   b.l = &#40;b.l       & 0x80808080&#41; >> &#40;f^7&#41;;
   return b.b;
&#125;

Bitboard diagonalAttacks&#40; Bitboard occupied, int sq )
&#123;
   union &#123; Bits64 b; struct &#123; unsigned int l; unsigned int h; &#125;; &#125; b; // little endian!
   b.b = occupied & h1a8DiagonalMask&#91;sq&#93;;
   b.h = (&#40;b.l + b.h&#41; * 0x02020202&#41; >> 26;
   b.h = b.l = 0x01010101 * firstRankAttacks&#91;b.h&#93;&#91;sq&7&#93;;
   return b.b & h1a8DiagonalMask&#91;sq&#93;;
&#125;

Bitboard antiDiagAttacks&#40; Bitboard occupied, int sq )
&#123;
   union &#123; Bits64 b; struct &#123; unsigned int l; unsigned int h; &#125;; &#125; b; // little endian!
   b.b = occupied & a1h8DiagonalMask&#91;sq&#93;;
   b.h = (&#40;b.l + b.h&#41; * 0x02020202&#41; >> 26;
   b.h = b.l = 0x01010101 * firstRankAttacks&#91;b.h&#93;&#91;sq&7&#93;;
   return b.b & a1h8DiagonalMask&#91;sq&#93;;
&#125; 

#endif


/*******************************************************************/

const Bitboard dirMaskRight&#91;8&#93; =
&#123;
    // 0, line_h, line_gh, line_fh, line_eh, line_dh, line_ch, line_bh, 
    0, C64&#40;0x0101010101010101&#41;, C64&#40;0x0303030303030303&#41;, C64&#40;0x0707070707070707&#41;, C64&#40;0x0f0f0f0f0f0f0f0f&#41;, 
    C64&#40;0x1f1f1f1f1f1f1f1f&#41;, C64&#40;0x3f3f3f3f3f3f3f3f&#41;, C64&#40;0x7f7f7f7f7f7f7f7f&#41;
&#125;;

const Bitboard dirMaskLeft&#91;8&#93; =
&#123;
    // line_ag, line_af, line_ae, line_ad, line_ac, line_ab, line_a, 0, 
    C64&#40;0xfefefefefefefefe&#41;, C64&#40;0xfcfcfcfcfcfcfcfc&#41;, C64&#40;0xf8f8f8f8f8f8f8f8&#41;, C64&#40;0xf0f0f0f0f0f0f0f0&#41;, 
    C64&#40;0xe0e0e0e0e0e0e0e0&#41;, C64&#40;0xc0c0c0c0c0c0c0c0&#41;, C64&#40;0x8080808080808080&#41;, 0
&#125;;

const Bitboard dirMaskUp&#91;8&#93; =
&#123;
    // row_28, row_38, row_48, row_58, row_68, row_78, row_8, 0, 
    C64&#40;0xffffffffffffff00&#41;, C64&#40;0xffffffffffff0000&#41;, C64&#40;0xffffffffff000000&#41;, C64&#40;0xffffffff00000000&#41;, 
    C64&#40;0xffffff0000000000&#41;, C64&#40;0xffff000000000000&#41;, C64&#40;0xff00000000000000&#41;, 0
&#125;;

const Bitboard dirMaskDown&#91;8&#93; =
&#123;
    // 0, row_1, row_12, row_13, row_14, row_15, row_16, row_17,
    0, C64&#40;0x00000000000000ff&#41;, C64&#40;0x000000000000ffff&#41;, C64&#40;0x0000000000ffffff&#41;, C64&#40;0x00000000ffffffff&#41;, 
    C64&#40;0x000000ffffffffff&#41;, C64&#40;0x0000ffffffffffff&#41;, C64&#40;0x00ffffffffffffff&#41;
&#125;;


/*******************************************************************/

/**
Prepare the slider attacks transformation tables.
Put the scattered bits of an sliding attack pattern 
back to the original bitboard.
*/
void Board&#58;&#58;init_slider_attacks_index&#40;)
&#123;
    for ( int file = 0; file < 8; ++file )
    &#123;
        for ( int occ = 0; occ < 64; ++occ )
        &#123;
            // Possible Attacks of a sliding piece &#40;8 positions&#41; in a single line of squares 
            // filled with other pieces &#40;8 bits, 256 values&#41;.
            // Returns a byte with all bits set which can be reached through empty positions 
            // and the first blocked position.
            // This is a copy of Board&#58;&#58;slider_attacks&#91;64&#93;&#91;8&#93;; In this quick hack I have access problems.
            firstRankAttacks&#91;occ&#93;&#91;file&#93; = slider_attacks&#91;occ&#93;&#91;file&#93;;

            // Projection of 8 bit first rank pattern &#40;with 6 bit index b1..g1&#41; 
            // in north direction through the board, for slider on each file.
            // This is used for diagonal attacks.
            fillUpAttacks&#91;occ&#93;&#91;file&#93;  = C64&#40;0x0101010101010101&#41; * slider_attacks&#91;occ&#93;&#91;file&#93;;

            // Bitboard with 8 bit h-file pattern &#40;with 6 bit index h2..h7&#41; 
            // for slider on each rank. This is used for vertical file attacks.
                                        // Start with 8 bit first rank pattern &#40;with 6 bit index b1..g1&#41;
                                        // and shift it in northwest direction through the board.
            hFileAttacks&#91;occ&#93;&#91;file^7&#93; = ( ( C64&#40;0x8040201008040201&#41; * slider_attacks&#91;occ&#93;&#91;file&#93;) 
                                        // That is vertically ordered on a-file &#40;7..0&#41;
                                         &  C64&#40;0x8080808080808080&#41;
                                        // and shifted to the h-hile
                                        ) >> 7; 
                                        // where it is stored in mirrored order &#40;0..7&#41;, done by file^7.
        &#125;
    &#125;

    // Mask for the diagonal slider rays
    for ( int sq = 0; sq < 64; ++sq )
    &#123;
        int f = sq &  7;
        int r = sq >> 3;
        if ( f >= r )
        &#123;
            h1a8DiagonalMask&#91;sq&#93; = C64&#40;0x8040201008040201&#41; >> (&#40;f - r&#41; * 8&#41;;
        &#125;
        else
        &#123;
            h1a8DiagonalMask&#91;sq&#93; = C64&#40;0x8040201008040201&#41; << (&#40;r - f&#41; * 8&#41;;
        &#125;
        f = 7 - f;
        if ( f >= r )
        &#123;
            a1h8DiagonalMask&#91;sq&#93; = C64&#40;0x0102040810204080&#41; >> (&#40;f - r&#41; * 8&#41;;
        &#125;
        else
        &#123;
            a1h8DiagonalMask&#91;sq&#93; = C64&#40;0x0102040810204080&#41; << (&#40;r - f&#41; * 8&#41;;
        &#125;
    &#125;
&#125;


/*******************************************************************/

/**
Get a bitboard with all positions set to 1 which can be attacked 
from a bishop, rook or queen on the square moving in the direction.
*/
Bitboard Board&#58;&#58;direction_attacks&#40; byte square, byte dir ) const
&#123;
    Bitboard result;
    Bitboard occ = wpieces_ | bpieces_;

    // 4 3 2
    // 5 0 1
    // 6 7 8
    switch ( dir )
    &#123;
      case 1&#58;
        result = rankAttacks&#40; occ, square );
        result &= dirMaskRight&#91;square & 7&#93;;
        break;
      case 5&#58;
        result = rankAttacks&#40; occ, square );
        result &= dirMaskLeft&#91;square & 7&#93;;
        break;
      case 7&#58;
        result = fileAttacks&#40; occ, square );
        result &= dirMaskDown&#91;square >> 3&#93;;
        break;
      case 3&#58;
        result = fileAttacks&#40; occ, square );
        result &= dirMaskUp&#91;square >> 3&#93;;
        break;
      case 8&#58;
        result = diagonalAttacks&#40; occ, square );
        result &= dirMaskRight&#91;square & 7&#93;;
        break;
      case 4&#58;
        result = diagonalAttacks&#40; occ, square );
        result &= dirMaskLeft&#91;square & 7&#93;;
        break;
      case 2&#58;
        result = antiDiagAttacks&#40; occ, square );
        result &= dirMaskRight&#91;square & 7&#93;;
        break;
      case 6&#58;
        result = antiDiagAttacks&#40; occ, square );
        result &= dirMaskLeft&#91;square & 7&#93;;
        break;
      default&#58;
        result = 0;
        break;
    &#125;

    return result;
&#125;


/*******************************************************************/

/**
Get a bitboard with all positions set to 1 which can be attacked 
from a rook or queen on the square.
*/
Bitboard Board&#58;&#58;orthogonal_attacks&#40; byte square ) const
&#123;
    Bitboard occ = wpieces_ | bpieces_;
    return rankAttacks&#40; occ, square ) | fileAttacks&#40; occ, square );
&#125;


/*******************************************************************/

/**
Get a bitboard with all positions set to 1 which can be attacked 
from a bishop or queen on the square.
*/
Bitboard Board&#58;&#58;diagonal_attacks&#40; byte square ) const
&#123;
    Bitboard occ = wpieces_ | bpieces_;
    return diagonalAttacks&#40; occ, square ) | antiDiagAttacks&#40; occ, square );
&#125;


/*******************************************************************/
/*
The original from Gerd Isenberg &#40;with a1=0, b1, h8=63-mapping&#41;&#58;

u64 diagonalMask&#91;64&#93;;
u64 antidiagMask&#91;64&#93;;
u64 fillUpAttacks&#91;64&#93;&#91;8&#93;;
u64 aFileAttacks&#91;64&#93;&#91;8&#93;;
u8  firstRankAttacks&#91;64&#93;&#91;8&#93;;

u64 rankAttacks&#40;u64 occ, u32 sq&#41; &#123;
   u32 f = sq &  7;
   u32 r = sq & ~7; // rank * 8
   u32 o = &#40;u32&#41;&#40;occ >> &#40;r+1&#41;) & 63;
   return &#40;u64&#41; firstRankAttacks&#91;o&#93;&#91;f&#93; << r;
&#125;

u64 fileAttacks&#40;u64 occ, u32 sq&#41; &#123;
   u32 f = sq & 7;
   occ   =   0x0101010101010101 & &#40;occ   >> f&#41;; // a-file
   u32 o = ( 0x0080402010080400 *  occ ) >> 58;
   return  ( aFileAttacks&#91;o&#93;&#91;sq>>3&#93;    ) << f;   
&#125;

u64 diagonalAttacks&#40;u64 occ, u32 sq&#41; &#123;
   u32 f = sq & 7;
   occ   = ( diagonalMask&#91;sq&#93;   &  occ );
   u32 o = ( 0x0202020202020202 *  occ ) >> 58;
   return  ( diagonalMask&#91;sq&#93;   &  fillUpAttacks&#91;o&#93;&#91;f&#93; );
&#125;

u64 antiDiagAttacks&#40;u64 occ, u32 sq&#41; &#123;
   u32 f = sq & 7;
   occ   = ( antidiagMask&#91;sq&#93;   &  occ );
   u32 o = ( 0x0202020202020202 *  occ ) >> 58;
   return  ( antidiagMask&#91;sq&#93;   &  fillUpAttacks&#91;o&#93;&#91;f&#93; );
&#125; 

for &#40;x=0; x<64; x++) &#123;
   fillupAttacks&#91;x&#93;&#91;file&#93; = 0x0101010101010101ULL * firstRankAttacks&#91;x&#93;&#91;file&#93;;
   aFileAttacks&#91;x&#93;&#91;file^7&#93; = (&#40;0x8040201008040201ULL * firstRankAttacks&#91;x&#93;&#91;file&#93;) & 0x8080808080808080ULL&#41; >> 7; 
&#125; 

And another variant&#58;

const u64 diagonalMask&#91;64&#93; = &#123;
   0x8040201008040201,
   0x0080402010080402,
   ....
&#125;;

const u64 antiDiagMask&#91;64&#93; = &#123;
   0x0000000000000001,
   0x0000000000000102,
   ...
&#125;;

// for all getters
// @param occ - the occupied bitboard
//        sq  - square index 0..63 &#40;a1..h8&#41;
// @return the attack set
u64 rankAttacks&#40;u64 occupied, u32 sq&#41; &#123;
   union &#123;u64 b; struct &#123;u32 l; u32 h;&#125;;&#125; b; // little endian!
   u32 f = sq & 7;
   u32 r = sq & 24; // 8 * folded rank
   if ( sq < 32 ) &#123;
      b.l = ((&#40;u32&#41;occupied&#41; >> &#40;r+1&#41;) & 63;
      b.l = firstRankAttacks&#91;b.l&#93;&#91;f&#93; << r;
      b.h = 0;
   &#125; else &#123;
      b.l = 0;
      b.h = ((&#40;u32&#41;&#40;occupied>>32&#41;) >> &#40;r+1&#41;) & 63;
      b.h = firstRankAttacks&#91;b.h&#93;&#91;f&#93; << r;
   &#125;
   return b.b;
&#125;

// file attacks with two reversed rotations
// 1. for the occupied state to map a2..a7 to h8..c8
// 2. for the attacks from a1..h1 to h8..h1
u64 fileAttacks&#40;u64 occupied, u32 sq&#41; &#123;
   union &#123;u64 b; struct &#123;u32 l; u32 h;&#125;;&#125; b; // little endian!
   u32 f = sq & 7;
   b.b = occupied;
   b.l = &#40;b.l >> f&#41; & 0x01010101;
   b.h = &#40;b.h >> f&#41; & 0x01010101;
   b.l = &#40;b.l << 4&#41; + b.h;
   b.h = &#40;b.l       * 0x10080402&#41; >> 26;
   b.l = 0x08040201 * firstRankAttacks&#91;b.h&#93;&#91;&#40;sq^56&#41;>>3&#93;;
   b.h =(&#40;b.l << 4&#41; & 0x80808080&#41; >> &#40;f^7&#41;;
   b.l = &#40;b.l       & 0x80808080&#41; >> &#40;f^7&#41;;
   return b.b;
&#125;

u64 diagonalAttacks&#40;u64 occupied, u32 sq&#41; &#123;
   union &#123;u64 b; struct &#123;u32 l; u32 h;&#125;;&#125; b; // little endian!
   b.b = occupied & diagonalMask&#91;sq&#93;;
   b.h = (&#40;b.l + b.h&#41; * 0x02020202&#41; >> 26;
   b.h = b.l = 0x01010101 * firstRankAttacks&#91;b.h&#93;&#91;sq&7&#93;;
   return b.b & diagonalMask&#91;sq&#93;;
&#125;

u64 antiDiagAttacks&#40;u64 occupied, u32 sq&#41; &#123;
   union &#123;u64 b; struct &#123;u32 l; u32 h;&#125;;&#125; b; // little endian!
   b.b = occupied & antiDiagMask&#91;sq&#93;;
   b.h = (&#40;b.l + b.h&#41; * 0x02020202&#41; >> 26;
   b.h = b.l = 0x01010101 * firstRankAttacks&#91;b.h&#93;&#91;sq&7&#93;;
   return b.b & antiDiagMask&#91;sq&#93;;
&#125; 

*/
/*******************************************************************/

#endif // #if USE_MAGIC_BITBOARDS&#40;)

Harald
Posts: 259
Joined: Thu Mar 09, 2006 12:07 am

Re: BitBoard Tests Magic v Non-Rotated 32 Bits v 64 Bits

Post by Harald » Sat Aug 25, 2007 6:50 am

bb_attacks_pradu.cpp:

Code: Select all

/*******************************************************************/
/*
The bitboard attacks of Pradyumna Kannan
as part of the board structure.

&#40;c&#41; 2006 Harald Lüßen
*/
/*******************************************************************/


#include "bb_ifdef.h"
#include "bb_basics.h"
#include "bb_bitboard.h"
#include "bb_board.h"
#include "bb_main.h"


#if USE_PRADU_BITBOARDS&#40;)

#include "magicmoves.h"
#include "magicmoves.c"

/*******************************************************************/

/*
    directions and shifts
    +-----+-----+-----+
    |<<= 9|<<= 8|<<= 7|
    +-----+-----+-----+
    |<<= 1|     |>>= 1|
    +-----+-----+-----+
    |>>= 7|>>= 8|>>= 9|
    +-----+-----+-----+

    We use this mapping of the normal board squares to bitboard bits
    +-------------------------+
    | 63 62 61 60 59 58 57 56 | 8
    | 55 54 53 52 51 50 49 48 | 7
    | 47 46 45 44 43 42 41 40 | 6
    | 39 38 37 36 35 35 33 32 | 5
    | 31 30 29 28 27 26 25 24 | 4
    | 23 22 21 20 19 18 17 16 | 3
    | 15 14 13 12 11 10  9  8 | 2
    |  7  6  5  4  3  2  1  0 | 1
    +-------------------------+
       a  b  c  d  e  f  g  h
*/

/*******************************************************************/

const Bitboard dirMaskRight&#91;8&#93; =
&#123;
    // 0, line_h, line_gh, line_fh, line_eh, line_dh, line_ch, line_bh, 
    0, C64&#40;0x0101010101010101&#41;, C64&#40;0x0303030303030303&#41;, C64&#40;0x0707070707070707&#41;, C64&#40;0x0f0f0f0f0f0f0f0f&#41;, 
    C64&#40;0x1f1f1f1f1f1f1f1f&#41;, C64&#40;0x3f3f3f3f3f3f3f3f&#41;, C64&#40;0x7f7f7f7f7f7f7f7f&#41;
&#125;;

const Bitboard dirMaskLeft&#91;8&#93; =
&#123;
    // line_ag, line_af, line_ae, line_ad, line_ac, line_ab, line_a, 0, 
    C64&#40;0xfefefefefefefefe&#41;, C64&#40;0xfcfcfcfcfcfcfcfc&#41;, C64&#40;0xf8f8f8f8f8f8f8f8&#41;, C64&#40;0xf0f0f0f0f0f0f0f0&#41;, 
    C64&#40;0xe0e0e0e0e0e0e0e0&#41;, C64&#40;0xc0c0c0c0c0c0c0c0&#41;, C64&#40;0x8080808080808080&#41;, 0
&#125;;

const Bitboard dirMaskUp&#91;8&#93; =
&#123;
    // row_28, row_38, row_48, row_58, row_68, row_78, row_8, 0, 
    C64&#40;0xffffffffffffff00&#41;, C64&#40;0xffffffffffff0000&#41;, C64&#40;0xffffffffff000000&#41;, C64&#40;0xffffffff00000000&#41;, 
    C64&#40;0xffffff0000000000&#41;, C64&#40;0xffff000000000000&#41;, C64&#40;0xff00000000000000&#41;, 0
&#125;;

const Bitboard dirMaskDown&#91;8&#93; =
&#123;
    // 0, row_1, row_12, row_13, row_14, row_15, row_16, row_17,
    0, C64&#40;0x00000000000000ff&#41;, C64&#40;0x000000000000ffff&#41;, C64&#40;0x0000000000ffffff&#41;, C64&#40;0x00000000ffffffff&#41;, 
    C64&#40;0x000000ffffffffff&#41;, C64&#40;0x0000ffffffffffff&#41;, C64&#40;0x00ffffffffffffff&#41;
&#125;;


/*******************************************************************/
/*******************************************************************/

/**
Prepare the slider attacks back transformation table.
Put the scattered bits of an sliding attack pattern 
back to the original bitboard.
*/
void Board&#58;&#58;init_slider_attacks_index&#40;)
&#123;
    initmagicmoves&#40;);
&#125;


/*******************************************************************/

/**
Get a bitboard with all positions set to 1 which can be attacked 
from a bishop, rook or queen on the square moving in the direction.
*/
Bitboard Board&#58;&#58;direction_attacks&#40; byte square, byte dir ) const
&#123;
    Bitboard result;
    Bitboard occ = wpieces_ | bpieces_;

    // 4 3 2
    // 5 0 1
    // 6 7 8
    switch ( dir )
    &#123;
      case 1&#58;
        result = Rmagic&#40;square, occ&#41;;
        result &= dirMaskRight&#91;square & 7&#93;;
        break;
      case 5&#58;
        result = Rmagic&#40;square, occ&#41;;
        result &= dirMaskLeft&#91;square & 7&#93;;
        break;
      case 7&#58;
        result = Rmagic&#40;square, occ&#41;;
        result &= dirMaskDown&#91;square >> 3&#93;;
        break;
      case 3&#58;
        result = Rmagic&#40;square, occ&#41;;
        result &= dirMaskUp&#91;square >> 3&#93;;
        break;
      case 8&#58;
        result = Bmagic&#40;square, occ&#41;;
        result &= dirMaskRight&#91;square & 7&#93;;
        result &= dirMaskDown&#91;square >> 3&#93;;
        break;
      case 4&#58;
        result = Bmagic&#40;square, occ&#41;;
        result &= dirMaskLeft&#91;square & 7&#93;;
        result &= dirMaskUp&#91;square >> 3&#93;;
        break;
      case 2&#58;
        result = Bmagic&#40;square, occ&#41;;
        result &= dirMaskRight&#91;square & 7&#93;;
        result &= dirMaskUp&#91;square >> 3&#93;;
        break;
      case 6&#58;
        result = Bmagic&#40;square, occ&#41;;
        result &= dirMaskLeft&#91;square & 7&#93;;
        result &= dirMaskDown&#91;square >> 3&#93;;
        break;
      default&#58;
        result = 0;
        break;
    &#125;

    return result;
&#125;


/*******************************************************************/

/**
Get a bitboard with all positions set to 1 which can be attacked 
from a rook or queen on the square.
*/
Bitboard Board&#58;&#58;orthogonal_attacks&#40; byte square ) const
&#123;
    Bitboard occ = wpieces_ | bpieces_;
    Bitboard result = Rmagic&#40;square, occ&#41;;
    return result;
&#125;


/*******************************************************************/

/**
Get a bitboard with all positions set to 1 which can be attacked 
from a bishop or queen on the square.
*/
Bitboard Board&#58;&#58;diagonal_attacks&#40; byte square ) const
&#123;
    Bitboard occ = wpieces_ | bpieces_;
    Bitboard result = Bmagic&#40;square, occ&#41;;
    return result;
&#125;


/*******************************************************************/

#endif // USE_PRADU_BITBOARDS&#40;)
magicmoves.h:

Code: Select all

/**
 *magicmoves.h
 *
 *Header file for magic move bitboard generation.  Include this in any files
 *need this functionality.
 *
 *Usage&#58;
 *You must first initialize the generator with a call to initmagicmoves&#40;).
 *Then you can use the following macros for generating move bitboards by
 *giving them a square and an occupancy.  The macro will then "return"
 *the correct move bitboard for that particular square and occupancy. It
 *has been named Rmagic and Bmagic so that it will not conflict with
 *any functions/macros in your chess program called Rmoves/Bmoves. You
 *can macro Bmagic/Rmagic to Bmoves/Rmoves if you wish.  If you want to
 *minimize the size of the bitboards, make MINIMIZE_MAGIC uncommented in this
 *header &#40;more info on this later&#41;.  Where you typedef your unsigned 64-bit
 *integer declare __64_BIT_INTEGER_DEFINED__.  If USE_INLINING is uncommented,
 *the macros will be expressed as inlined functions.  If PERFECT_MAGIC_HASH is
 *uncomment, the move generator will use an additional indrection to make the
 *table sizes smaller &#58; (~50kb+(&#40;original size&#41;/sizeof&#40;PERFECT_MAGIC_HASH&#41;).
 *The size listed from here on out are the sizes without PERFECT_MAGIC_HASH.
 *
 *Bmagic&#40;square, occupancy&#41;
 *Rmagic&#40;square, occupancy&#41;
 *
 *Square is an integer that is greater than or equal to zero and less than 64.
 *Occupancy is any unsigned 64-bit integer that describes which squares on
 *the board are occupied.
 *
 *The following macros are identical to Rmagic and Bmagic except that the 
 *occupancy is assumed to already have been "masked".  Look at the following
 *source or read up on the internet about magic bitboard move generation to
 *understand the usage of these macros and what it means by "an occupancy that
 *has already been masked".  Using the following macros when possible might be
 *a tiny bit faster than using Rmagic and Bmagic because it avoids an array
 *access and a 64-bit & operation.
 *
 *BmagicNOMASK&#40;square, occupancy&#41;
 *RmagicNOMASK&#40;square, occupancy&#41;
 *
 *Unsigned 64 bit integers are referenced by this generator as U64.
 *Edit the beginning lines of this header for the defenition of a 64 bit
 *integer if necessary.
 *
 *If MINIMIZE_MAGIC is defined before including this file&#58;
 *The move bitboard generator will use up 841kb of memory.
 *41kb of memory is used for the bishop database and 800kb is used for the rook
 *database.  If you feel the 800kb rook database is too big, then comment it out
 *and use a more traditional move bitboard generator in conjunction with the
 *magic move bitboard generator for bishops.
 *
 *If MINIMIAZE_MAGIC is not defined before including this file&#58;
 *The move bitboard generator will use up 2304kb of memory but might perform a bit
 *faster.
 *
 *Copyright &#40;C&#41; 2006 Pradyumna Kannan.
 *
 *This code is provided 'as-is', without any express or implied warranty.
 *In no event will the authors be held liable for any damages arising from
 *the use of this code. Permission is granted to anyone to use this
 *code for any purpose, including commercial applications, and to alter
 *it and redistribute it freely, subject to the following restrictions&#58;
 *
 *1. The origin of this code must not be misrepresented; you must not
 *claim that you wrote the original code. If you use this code in a
 *product, an acknowledgment in the product documentation would be
 *appreciated but is not required.
 *
 *2. Altered source versions must be plainly marked as such, and must not be
 *misrepresented as being the original code.
 *
 *3. This notice may not be removed or altered from any source distribution.
 */

#ifndef _magicmovesh
#define _magicmovesh

/*********MODIFY THE FOLLOWING IF NECESSARY********/

//Uncomment only one of the following
#define MINIMIZE_MAGIC
//#define PERFECT_MAGIC_HASH unsigned short

#define USE_INLINING

#ifndef __64_BIT_INTEGER_DEFINED__
#define __64_BIT_INTEGER_DEFINED__
#if 1 // MSVC++ 7.0 + Elephant
	typedef Bits64 U64;
#else
#if defined&#40;_MSC_VER&#41; && _MSC_VER<1300
	typedef unsigned __int64 U64; //For the old microsoft compilers
#else
	typedef unsigned long long  U64; //Supported by MSC 13.00+ and GCC
#endif //defined&#40;_MSC_VER&#41; && _MSC_VER<1300
#endif
#endif //__64_BIT_INTEGER_DEFINED__

/***********MODIFY THE ABOVE IF NECESSARY**********/

#ifdef USE_INLINING
	#ifdef _MSC_VER
		#define MAGICMOVES_INLINE_KEYWORD __forceinline
	#endif
	#ifdef __GNUC__
		#define MAGICMOVES_INLINE_KEYWORD __inline__
	#endif
	#ifndef MAGICMOVES_INLINE_KEYWORD
		#define MAGICMOVES_INLINE_KEYWORD inline
	#endif
#endif

extern const U64 magicmoves_r_magics&#91;64&#93;;
extern const U64 magicmoves_r_mask&#91;64&#93;;
extern const U64 magicmoves_b_magics&#91;64&#93;;
extern const U64 magicmoves_b_mask&#91;64&#93;;

#ifndef MINIMIZE_MAGIC
	#define MINIMAL_B_BITS_SHIFT 55
	#define MINIMAL_R_BITS_SHIFT 52
#endif

#ifndef PERFECT_MAGIC_HASH
	#ifdef MINIMIZE_MAGIC

		#ifndef USE_INLINING
			#define Bmagic&#40;square, occupancy&#41; *&#40;magicmoves_b_indecies&#91;square&#93;+(((&#40;occupancy&#41;&magicmoves_b_mask&#91;square&#93;)*magicmoves_b_magics&#91;square&#93;)>>magicmoves_b_shift&#91;square&#93;))
			#define Rmagic&#40;square, occupancy&#41; *&#40;magicmoves_r_indecies&#91;square&#93;+(((&#40;occupancy&#41;&magicmoves_r_mask&#91;square&#93;)*magicmoves_r_magics&#91;square&#93;)>>magicmoves_r_shift&#91;square&#93;))
			#define BmagicNOMASK&#40;square, occupancy&#41; *&#40;magicmoves_b_indecies&#91;square&#93;+((&#40;occupancy&#41;*magicmoves_b_magics&#91;square&#93;)>>magicmoves_b_shift&#91;square&#93;))
			#define RmagicNOMASK&#40;square, occupancy&#41; *&#40;magicmoves_r_indecies&#91;square&#93;+((&#40;occupancy&#41;*magicmoves_r_magics&#91;square&#93;)>>magicmoves_r_shift&#91;square&#93;))
		#endif //USE_INLINING

		//extern U64 magicmovesbdb&#91;5248&#93;;
		extern const unsigned int magicmoves_b_shift&#91;64&#93;;
		extern const U64* magicmoves_b_indecies&#91;64&#93;;

		//extern U64 magicmovesrdb&#91;102400&#93;;
		extern const unsigned int magicmoves_r_shift&#91;64&#93;;
		extern const U64* magicmoves_r_indecies&#91;64&#93;;

	#else //Don't Minimize database size

		#ifndef USE_INLINING
			#define Bmagic&#40;square, occupancy&#41; magicmovesbdb&#91;square&#93;&#91;((&#40;occupancy&#41;&magicmoves_b_mask&#91;square&#93;)*magicmoves_b_magics&#91;square&#93;)>>MINIMAL_B_BITS_SHIFT&#93;
			#define Rmagic&#40;square, occupancy&#41; magicmovesrdb&#91;square&#93;&#91;((&#40;occupancy&#41;&magicmoves_r_mask&#91;square&#93;)*magicmoves_r_magics&#91;square&#93;)>>MINIMAL_R_BITS_SHIFT&#93;
			#define BmagicNOMASK&#40;square, occupancy&#41; magicmovesbdb&#91;square&#93;&#91;(&#40;occupancy&#41;*magicmoves_b_magics&#91;square&#93;)>>MINIMAL_B_BITS_SHIFT&#93;
			#define RmagicNOMASK&#40;square, occupancy&#41; magicmovesrdb&#91;square&#93;&#91;(&#40;occupancy&#41;*magicmoves_r_magics&#91;square&#93;)>>MINIMAL_R_BITS_SHIFT&#93;
		#endif //USE_INLINING

		extern U64 magicmovesbdb&#91;64&#93;&#91;1<<9&#93;;
		extern U64 magicmovesrdb&#91;64&#93;&#91;1<<12&#93;;

	#endif //MINIMIAZE_MAGICMOVES
#else //PERFCT_MAGIC_HASH defined
	#ifndef MINIMIZE_MAGIC

		#ifndef USE_INLINING
			#define Bmagic&#40;square, occupancy&#41; magicmovesbdb&#91;magicmoves_b_indecies&#91;square&#93;&#91;((&#40;occupancy&#41;&magicmoves_b_mask&#91;square&#93;)*magicmoves_b_magics&#91;square&#93;)>>MINIMAL_B_BITS_SHIFT&#93;&#93;
			#define Rmagic&#40;square, occupancy&#41; magicmovesrdb&#91;magicmoves_r_indecies&#91;square&#93;&#91;((&#40;occupancy&#41;&magicmoves_r_mask&#91;square&#93;)*magicmoves_r_magics&#91;square&#93;)>>MINIMAL_R_BITS_SHIFT&#93;&#93;
			#define BmagicNOMASK&#40;square, occupancy&#41; magicmovesbdb&#91;magicmoves_b_indecies&#91;square&#93;&#91;(&#40;occupancy&#41;*magicmoves_b_magics&#91;square&#93;)>>MINIMAL_B_BITS_SHIFT&#93;&#93;
			#define RmagicNOMASK&#40;square, occupancy&#41; magicmovesrdb&#91;magicmoves_r_indecies&#91;square&#93;&#91;(&#40;occupancy&#41;*magicmoves_r_magics&#91;square&#93;)>>MINIMAL_R_BITS_SHIFT&#93;&#93;
		#endif //USE_INLINING

		extern U64 magicmovesbdb&#91;1428&#93;;
		extern U64 magicmovesrdb&#91;4900&#93;;
		extern PERFECT_MAGIC_HASH magicmoves_b_indecies&#91;64&#93;&#91;1<<9&#93;;
		extern PERFECT_MAGIC_HASH magicmoves_r_indecies&#91;64&#93;&#91;1<<12&#93;;
	#else
		#error magicmoves - MINIMIZED_MAGIC and PERFECT_MAGIC_HASH cannot be used together
	#endif
#endif //PERFCT_MAGIC_HASH

#ifdef USE_INLINING
	MAGICMOVES_INLINE_KEYWORD U64 Bmagic&#40;unsigned int square, U64 occupancy&#41;
	&#123;
		#ifndef PERFECT_MAGIC_HASH
			#ifdef MINIMIZE_MAGIC
				return *&#40;magicmoves_b_indecies&#91;square&#93;+((&#40;occupancy&magicmoves_b_mask&#91;square&#93;)*magicmoves_b_magics&#91;square&#93;)>>magicmoves_b_shift&#91;square&#93;));
			#else
				return magicmovesbdb&#91;square&#93;&#91;((&#40;occupancy&#41;&magicmoves_b_mask&#91;square&#93;)*magicmoves_b_magics&#91;square&#93;)>>MINIMAL_B_BITS_SHIFT&#93;;
			#endif
		#else
			return magicmovesbdb&#91;magicmoves_b_indecies&#91;square&#93;&#91;((&#40;occupancy&#41;&magicmoves_b_mask&#91;square&#93;)*magicmoves_b_magics&#91;square&#93;)>>MINIMAL_B_BITS_SHIFT&#93;&#93;;
		#endif
	&#125;
	MAGICMOVES_INLINE_KEYWORD U64 Rmagic&#40;unsigned int square, U64 occupancy&#41;
	&#123;
		#ifndef PERFECT_MAGIC_HASH
			#ifdef MINIMIZE_MAGIC
				return *&#40;magicmoves_r_indecies&#91;square&#93;+((&#40;occupancy&magicmoves_r_mask&#91;square&#93;)*magicmoves_r_magics&#91;square&#93;)>>magicmoves_r_shift&#91;square&#93;));
			#else
				return magicmovesrdb&#91;square&#93;&#91;((&#40;occupancy&#41;&magicmoves_r_mask&#91;square&#93;)*magicmoves_r_magics&#91;square&#93;)>>MINIMAL_R_BITS_SHIFT&#93;;
			#endif
		#else
			return magicmovesrdb&#91;magicmoves_r_indecies&#91;square&#93;&#91;((&#40;occupancy&#41;&magicmoves_r_mask&#91;square&#93;)*magicmoves_r_magics&#91;square&#93;)>>MINIMAL_R_BITS_SHIFT&#93;&#93;;
		#endif
	&#125;
	MAGICMOVES_INLINE_KEYWORD U64 BmagicNOMASK&#40;unsigned int square, U64 occupancy&#41;
	&#123;
		#ifndef PERFECT_MAGIC_HASH
			#ifdef MINIMIZE_MAGIC
				return *&#40;magicmoves_b_indecies&#91;square&#93;+((&#40;occupancy&#41;*magicmoves_b_magics&#91;square&#93;)>>magicmoves_b_shift&#91;square&#93;));
			#else
				return magicmovesbdb&#91;square&#93;&#91;(&#40;occupancy&#41;*magicmoves_b_magics&#91;square&#93;)>>MINIMAL_B_BITS_SHIFT&#93;;
			#endif
		#else
			return magicmovesbdb&#91;magicmoves_b_indecies&#91;square&#93;&#91;(&#40;occupancy&#41;*magicmoves_b_magics&#91;square&#93;)>>MINIMAL_B_BITS_SHIFT&#93;&#93;;
		#endif
	&#125;
	MAGICMOVES_INLINE_KEYWORD U64 RmagicNOMASK&#40;unsigned int square, U64 occupancy&#41;
	&#123;
		#ifndef PERFECT_MAGIC_HASH
			#ifdef MINIMIZE_MAGIC
				return *&#40;magicmoves_r_indecies&#91;square&#93;+((&#40;occupancy&#41;*magicmoves_r_magics&#91;square&#93;)>>magicmoves_r_shift&#91;square&#93;));
			#else
				return magicmovesrdb&#91;square&#93;&#91;(&#40;occupancy&#41;*magicmoves_r_magics&#91;square&#93;)>>MINIMAL_R_BITS_SHIFT&#93;;
			#endif
		#else
			return magicmovesrdb&#91;magicmoves_r_indecies&#91;square&#93;&#91;(&#40;occupancy&#41;*magicmoves_r_magics&#91;square&#93;)>>MINIMAL_R_BITS_SHIFT&#93;&#93;;
		#endif
	&#125;
#endif //USE_INLINING

void initmagicmoves&#40;void&#41;;

#endif //_magicmovesh
magicmoves.c:

Code: Select all

/**
 *magicmoves.h
 *
 *Source file for magic move bitboard generation.
 *
 *See header file for usage.
 *
 *The magic keys are not optimal for all squares but they are very close
 *to optimal.
 *
 *Copyright &#40;C&#41; 2006 Pradyumna Kannan.
 *
 *This code is provided 'as-is', without any express or implied warranty.
 *In no event will the authors be held liable for any damages arising from
 *the use of this code. Permission is granted to anyone to use this
 *code for any purpose, including commercial applications, and to alter
 *it and redistribute it freely, subject to the following restrictions&#58;
 *
 *1. The origin of this code must not be misrepresented; you must not
 *claim that you wrote the original code. If you use this code in a
 *product, an acknowledgment in the product documentation would be
 *appreciated but is not required.
 *
 *2. Altered source versions must be plainly marked as such, and must not be
 *misrepresented as being the original code.
 *
 *3. This notice may not be removed or altered from any source distribution.
 */

#include "magicmoves.h"

#ifdef MINIMIZE_MAGIC
U64 magicmovesbdb&#91;5248&#93;;
const unsigned int magicmoves_b_shift&#91;64&#93;=
&#123;
	58, 59, 59, 59, 59, 59, 59, 58,
	59, 59, 59, 59, 59, 59, 59, 59,
	59, 59, 57, 57, 57, 57, 59, 59,
	59, 59, 57, 55, 55, 57, 59, 59,
	59, 59, 57, 55, 55, 57, 59, 59,
	59, 59, 57, 57, 57, 57, 59, 59,
	59, 59, 59, 59, 59, 59, 59, 59,
	58, 59, 59, 59, 59, 59, 59, 58
&#125;;
const U64* magicmoves_b_indecies&#91;64&#93;=
&#123;
	magicmovesbdb+4992, magicmovesbdb+2624,  magicmovesbdb+256,  magicmovesbdb+896,
	magicmovesbdb+1280, magicmovesbdb+1664, magicmovesbdb+4800, magicmovesbdb+5120,
	magicmovesbdb+2560, magicmovesbdb+2656,  magicmovesbdb+288,  magicmovesbdb+928,
	magicmovesbdb+1312, magicmovesbdb+1696, magicmovesbdb+4832, magicmovesbdb+4928,
	magicmovesbdb+0,     magicmovesbdb+128,  magicmovesbdb+320,  magicmovesbdb+960,
	magicmovesbdb+1344, magicmovesbdb+1728, magicmovesbdb+2304, magicmovesbdb+2432,
	magicmovesbdb+32,    magicmovesbdb+160,  magicmovesbdb+448, magicmovesbdb+2752,
	magicmovesbdb+3776, magicmovesbdb+1856, magicmovesbdb+2336, magicmovesbdb+2464,
	magicmovesbdb+64,    magicmovesbdb+192,  magicmovesbdb+576, magicmovesbdb+3264,
	magicmovesbdb+4288, magicmovesbdb+1984, magicmovesbdb+2368, magicmovesbdb+2496,
	magicmovesbdb+96,    magicmovesbdb+224,  magicmovesbdb+704, magicmovesbdb+1088,
	magicmovesbdb+1472, magicmovesbdb+2112, magicmovesbdb+2400, magicmovesbdb+2528,
	magicmovesbdb+2592, magicmovesbdb+2688,  magicmovesbdb+832, magicmovesbdb+1216,
	magicmovesbdb+1600, magicmovesbdb+2240, magicmovesbdb+4864, magicmovesbdb+4960,
	magicmovesbdb+5056, magicmovesbdb+2720,  magicmovesbdb+864, magicmovesbdb+1248,
	magicmovesbdb+1632, magicmovesbdb+2272, magicmovesbdb+4896, magicmovesbdb+5184
&#125;;
#else
	#ifndef PERFECT_MAGIC_HASH
		U64 magicmovesbdb&#91;64&#93;&#91;1<<9&#93;;
	#else
		U64 magicmovesbdb&#91;1428&#93;;
		PERFECT_MAGIC_HASH magicmoves_b_indecies&#91;64&#93;&#91;1<<9&#93;;
	#endif
#endif

const U64 magicmoves_b_magics&#91;64&#93;=
&#123;
	0x0002020202020200, 0x0002020202020000, 0x0004010202000000, 0x0004040080000000,
	0x0001104000000000, 0x0000821040000000, 0x0000410410400000, 0x0000104104104000,
	0x0000040404040400, 0x0000020202020200, 0x0000040102020000, 0x0000040400800000,
	0x0000011040000000, 0x0000008210400000, 0x0000004104104000, 0x0000002082082000,
	0x0004000808080800, 0x0002000404040400, 0x0001000202020200, 0x0000800802004000,
	0x0000800400A00000, 0x0000200100884000, 0x0000400082082000, 0x0000200041041000,
	0x0002080010101000, 0x0001040008080800, 0x0000208004010400, 0x0000404004010200,
	0x0000840000802000, 0x0000404002011000, 0x0000808001041000, 0x0000404000820800,
	0x0001041000202000, 0x0000820800101000, 0x0000104400080800, 0x0000020080080080,
	0x0000404040040100, 0x0000808100020100, 0x0001010100020800, 0x0000808080010400,
	0x0000820820004000, 0x0000410410002000, 0x0000082088001000, 0x0000002011000800,
	0x0000080100400400, 0x0001010101000200, 0x0002020202000400, 0x0001010101000200,
	0x0000410410400000, 0x0000208208200000, 0x0000002084100000, 0x0000000020880000,
	0x0000001002020000, 0x0000040408020000, 0x0004040404040000, 0x0002020202020000,
	0x0000104104104000, 0x0000002082082000, 0x0000000020841000, 0x0000000000208800,
	0x0000000010020200, 0x0000000404080200, 0x0000040404040400, 0x0002020202020200
&#125;;
const U64 magicmoves_b_mask&#91;64&#93;=
&#123;
	0x0040201008040200, 0x0000402010080400, 0x0000004020100A00, 0x0000000040221400,
	0x0000000002442800, 0x0000000204085000, 0x0000020408102000, 0x0002040810204000,
	0x0020100804020000, 0x0040201008040000, 0x00004020100A0000, 0x0000004022140000,
	0x0000000244280000, 0x0000020408500000, 0x0002040810200000, 0x0004081020400000,
	0x0010080402000200, 0x0020100804000400, 0x004020100A000A00, 0x0000402214001400,
	0x0000024428002800, 0x0002040850005000, 0x0004081020002000, 0x0008102040004000,
	0x0008040200020400, 0x0010080400040800, 0x0020100A000A1000, 0x0040221400142200,
	0x0002442800284400, 0x0004085000500800, 0x0008102000201000, 0x0010204000402000,
	0x0004020002040800, 0x0008040004081000, 0x00100A000A102000, 0x0022140014224000,
	0x0044280028440200, 0x0008500050080400, 0x0010200020100800, 0x0020400040201000,
	0x0002000204081000, 0x0004000408102000, 0x000A000A10204000, 0x0014001422400000,
	0x0028002844020000, 0x0050005008040200, 0x0020002010080400, 0x0040004020100800,
	0x0000020408102000, 0x0000040810204000, 0x00000A1020400000, 0x0000142240000000,
	0x0000284402000000, 0x0000500804020000, 0x0000201008040200, 0x0000402010080400,
	0x0002040810204000, 0x0004081020400000, 0x000A102040000000, 0x0014224000000000,
	0x0028440200000000, 0x0050080402000000, 0x0020100804020000, 0x0040201008040200
&#125;;

#ifdef MINIMIZE_MAGIC
U64 magicmovesrdb&#91;102400&#93;;
const unsigned int magicmoves_r_shift&#91;64&#93;=
&#123;
	52, 53, 53, 53, 53, 53, 53, 52,
	53, 54, 54, 54, 54, 54, 54, 53,
	53, 54, 54, 54, 54, 54, 54, 53,
	53, 54, 54, 54, 54, 54, 54, 53,
	53, 54, 54, 54, 54, 54, 54, 53,
	53, 54, 54, 54, 54, 54, 54, 53,
	53, 54, 54, 54, 54, 54, 54, 53,
	52, 53, 53, 53, 53, 53, 53, 52
&#125;;
const U64* magicmoves_r_indecies&#91;64&#93;=
&#123;
	magicmovesrdb+86016, magicmovesrdb+73728, magicmovesrdb+36864, magicmovesrdb+43008,
	magicmovesrdb+47104, magicmovesrdb+51200, magicmovesrdb+77824, magicmovesrdb+94208,
	magicmovesrdb+69632, magicmovesrdb+32768, magicmovesrdb+38912, magicmovesrdb+10240,
	magicmovesrdb+14336, magicmovesrdb+53248, magicmovesrdb+57344, magicmovesrdb+81920,
	magicmovesrdb+24576, magicmovesrdb+33792,  magicmovesrdb+6144, magicmovesrdb+11264,
	magicmovesrdb+15360, magicmovesrdb+18432, magicmovesrdb+58368, magicmovesrdb+61440,
	magicmovesrdb+26624,  magicmovesrdb+4096,  magicmovesrdb+7168,     magicmovesrdb+0,
	 magicmovesrdb+2048, magicmovesrdb+19456, magicmovesrdb+22528, magicmovesrdb+63488,
	magicmovesrdb+28672,  magicmovesrdb+5120,  magicmovesrdb+8192,  magicmovesrdb+1024,
	 magicmovesrdb+3072, magicmovesrdb+20480, magicmovesrdb+23552, magicmovesrdb+65536,
	magicmovesrdb+30720, magicmovesrdb+34816,  magicmovesrdb+9216, magicmovesrdb+12288,
	magicmovesrdb+16384, magicmovesrdb+21504, magicmovesrdb+59392, magicmovesrdb+67584,
	magicmovesrdb+71680, magicmovesrdb+35840, magicmovesrdb+39936, magicmovesrdb+13312,
	magicmovesrdb+17408, magicmovesrdb+54272, magicmovesrdb+60416, magicmovesrdb+83968,
	magicmovesrdb+90112, magicmovesrdb+75776, magicmovesrdb+40960, magicmovesrdb+45056,
	magicmovesrdb+49152, magicmovesrdb+55296, magicmovesrdb+79872, magicmovesrdb+98304
&#125;;
#else
	#ifndef PERFECT_MAGIC_HASH
		U64 magicmovesrdb&#91;64&#93;&#91;1<<12&#93;;
	#else
		U64 magicmovesrdb&#91;4900&#93;;
		PERFECT_MAGIC_HASH magicmoves_r_indecies&#91;64&#93;&#91;1<<12&#93;;
	#endif
#endif

const U64 magicmoves_r_magics&#91;64&#93;=
&#123;
	0x0080001020400080, 0x0040001000200040, 0x0080081000200080, 0x0080040800100080,
	0x0080020400080080, 0x0080010200040080, 0x0080008001000200, 0x0080002040800100,
	0x0000800020400080, 0x0000400020005000, 0x0000801000200080, 0x0000800800100080,
	0x0000800400080080, 0x0000800200040080, 0x0000800100020080, 0x0000800040800100,
	0x0000208000400080, 0x0000404000201000, 0x0000808010002000, 0x0000808008001000,
	0x0000808004000800, 0x0000808002000400, 0x0000010100020004, 0x0000020000408104,
	0x0000208080004000, 0x0000200040005000, 0x0000100080200080, 0x0000080080100080,
	0x0000040080080080, 0x0000020080040080, 0x0000010080800200, 0x0000800080004100,
	0x0000204000800080, 0x0000200040401000, 0x0000100080802000, 0x0000080080801000,
	0x0000040080800800, 0x0000020080800400, 0x0000020001010004, 0x0000800040800100,
	0x0000204000808000, 0x0000200040008080, 0x0000100020008080, 0x0000080010008080,
	0x0000040008008080, 0x0000020004008080, 0x0000010002008080, 0x0000004081020004,
	0x0000204000800080, 0x0000200040008080, 0x0000100020008080, 0x0000080010008080,
	0x0000040008008080, 0x0000020004008080, 0x0000800100020080, 0x0000800041000080,
	0x0000102040800101, 0x0000102040008101, 0x0000081020004101, 0x0000040810002101,
	0x0001000204080011, 0x0001000204000801, 0x0001000082000401, 0x0000002040810402
&#125;;
const U64 magicmoves_r_mask&#91;64&#93;=
&#123;	
	0x000101010101017E, 0x000202020202027C, 0x000404040404047A, 0x0008080808080876,
	0x001010101010106E, 0x002020202020205E, 0x004040404040403E, 0x008080808080807E,
	0x0001010101017E00, 0x0002020202027C00, 0x0004040404047A00, 0x0008080808087600,
	0x0010101010106E00, 0x0020202020205E00, 0x0040404040403E00, 0x0080808080807E00,
	0x00010101017E0100, 0x00020202027C0200, 0x00040404047A0400, 0x0008080808760800,
	0x00101010106E1000, 0x00202020205E2000, 0x00404040403E4000, 0x00808080807E8000,
	0x000101017E010100, 0x000202027C020200, 0x000404047A040400, 0x0008080876080800,
	0x001010106E101000, 0x002020205E202000, 0x004040403E404000, 0x008080807E808000,
	0x0001017E01010100, 0x0002027C02020200, 0x0004047A04040400, 0x0008087608080800,
	0x0010106E10101000, 0x0020205E20202000, 0x0040403E40404000, 0x0080807E80808000,
	0x00017E0101010100, 0x00027C0202020200, 0x00047A0404040400, 0x0008760808080800,
	0x00106E1010101000, 0x00205E2020202000, 0x00403E4040404000, 0x00807E8080808000,
	0x007E010101010100, 0x007C020202020200, 0x007A040404040400, 0x0076080808080800,
	0x006E101010101000, 0x005E202020202000, 0x003E404040404000, 0x007E808080808000,
	0x7E01010101010100, 0x7C02020202020200, 0x7A04040404040400, 0x7608080808080800,
	0x6E10101010101000, 0x5E20202020202000, 0x3E40404040404000, 0x7E80808080808000
&#125;;


U64 initmagicmoves_occ&#40;const int* squares, const int numSquares, const U64 linocc&#41;
&#123;
	int i;
	U64 ret=0;
	for&#40;i=0;i<numSquares;i++)
		if&#40;linocc&((&#40;U64&#41;&#40;1&#41;)<<i&#41;) ret|=((&#40;U64&#41;&#40;1&#41;)<<squares&#91;i&#93;);
	return ret;
&#125;

U64 initmagicmoves_Rmoves&#40;const int square, const U64 occ&#41;
&#123;
	U64 ret=0;
	U64 bit;
	U64 rowbits=((&#40;U64&#41;0xFF&#41;<<&#40;8*&#40;square/8&#41;));
	
	bit=((&#40;U64&#41;&#40;1&#41;)<<square&#41;;
	do
	&#123;
		bit<<=8;
		ret|=bit;
	&#125;while&#40;bit && !&#40;bit&occ&#41;);
	bit=((&#40;U64&#41;&#40;1&#41;)<<square&#41;;
	do
	&#123;
		bit>>=8;
		ret|=bit;
	&#125;while&#40;bit && !&#40;bit&occ&#41;);
	bit=((&#40;U64&#41;&#40;1&#41;)<<square&#41;;
	do
	&#123;
		bit<<=1;
		if&#40;bit&rowbits&#41; ret|=bit;
		else break;
	&#125;while&#40;!&#40;bit&occ&#41;);
	bit=((&#40;U64&#41;&#40;1&#41;)<<square&#41;;
	do
	&#123;
		bit>>=1;
		if&#40;bit&rowbits&#41; ret|=bit;
		else break;
	&#125;while&#40;!&#40;bit&occ&#41;);
	return ret;
&#125;

U64 initmagicmoves_Bmoves&#40;const int square, const U64 occ&#41;
&#123;
	U64 ret=0;
	U64 bit;
	U64 bit2;
	U64 rowbits=((&#40;U64&#41;0xFF&#41;<<&#40;8*&#40;square/8&#41;));
	
	bit=((&#40;U64&#41;&#40;1&#41;)<<square&#41;;
	bit2=bit;
	do
	&#123;
		bit<<=8-1;
		bit2>>=1;
		if&#40;bit2&rowbits&#41; ret|=bit;
		else break;
	&#125;while&#40;bit && !&#40;bit&occ&#41;);
	bit=((&#40;U64&#41;&#40;1&#41;)<<square&#41;;
	bit2=bit;
	do
	&#123;
		bit<<=8+1;
		bit2<<=1;
		if&#40;bit2&rowbits&#41; ret|=bit;
		else break;
	&#125;while&#40;bit && !&#40;bit&occ&#41;);
	bit=((&#40;U64&#41;&#40;1&#41;)<<square&#41;;
	bit2=bit;
	do
	&#123;
		bit>>=8-1;
		bit2<<=1;
		if&#40;bit2&rowbits&#41; ret|=bit;
		else break;
	&#125;while&#40;bit && !&#40;bit&occ&#41;);
	bit=((&#40;U64&#41;&#40;1&#41;)<<square&#41;;
	bit2=bit;
	do
	&#123;
		bit>>=8+1;
		bit2>>=1;
		if&#40;bit2&rowbits&#41; ret|=bit;
		else break;
	&#125;while&#40;bit && !&#40;bit&occ&#41;);
	return ret;
&#125;

//used so that the original indecies can be left as const so that the compiler can optimize better

#ifndef PERFECT_MAGIC_HASH
	#ifdef MINIMIZE_MAGIC
		#define BmagicNOMASK2&#40;square, occupancy&#41; *&#40;magicmoves_b_indecies2&#91;square&#93;+((&#40;occupancy&#41;*magicmoves_b_magics&#91;square&#93;)>>magicmoves_b_shift&#91;square&#93;))
		#define RmagicNOMASK2&#40;square, occupancy&#41; *&#40;magicmoves_r_indecies2&#91;square&#93;+((&#40;occupancy&#41;*magicmoves_r_magics&#91;square&#93;)>>magicmoves_r_shift&#91;square&#93;))
	#else
		#define BmagicNOMASK2&#40;square, occupancy&#41; magicmovesbdb&#91;square&#93;&#91;(&#40;occupancy&#41;*magicmoves_b_magics&#91;square&#93;)>>MINIMAL_B_BITS_SHIFT&#93;
		#define RmagicNOMASK2&#40;square, occupancy&#41; magicmovesrdb&#91;square&#93;&#91;(&#40;occupancy&#41;*magicmoves_r_magics&#91;square&#93;)>>MINIMAL_R_BITS_SHIFT&#93;
	#endif
/*#else
	#define BmagicNOMASK2&#40;square, occupancy&#41; magicmovesbdb&#91;magicmoves_b_indecies&#91;square&#93;&#91;(&#40;occupancy&#41;*magicmoves_b_magics&#91;square&#93;)>>MINIMAL_B_BITS_SHIFT&#93;&#93;
	#define RmagicNOMASK2&#40;square, occupancy&#41; magicmovesrdb&#91;magicmoves_r_indecies&#91;square&#93;&#91;(&#40;occupancy&#41;*magicmoves_r_magics&#91;square&#93;)>>MINIMAL_R_BITS_SHIFT&#93;&#93;
*/
#endif

void initmagicmoves&#40;void&#41;
&#123;
	int i;

	//for bitscans &#58;
	//initmagicmoves_bitpos64_database&#91;&#40;x*0x07EDD5E59A4E28C2&#41;>>58&#93;
	int initmagicmoves_bitpos64_database&#91;64&#93;=&#123;
	63,  0, 58,  1, 59, 47, 53,  2,
	60, 39, 48, 27, 54, 33, 42,  3,
	61, 51, 37, 40, 49, 18, 28, 20,
	55, 30, 34, 11, 43, 14, 22,  4,
	62, 57, 46, 52, 38, 26, 32, 41,
	50, 36, 17, 19, 29, 10, 13, 21,
	56, 45, 25, 31, 35, 16,  9, 12,
	44, 24, 15,  8, 23,  7,  6,  5&#125;;

#ifdef MINIMIZE_MAGIC
	//identical to magicmove_x_indecies except without the const modifer
	U64* magicmoves_b_indecies2&#91;64&#93;=
	&#123;
		magicmovesbdb+4992, magicmovesbdb+2624,  magicmovesbdb+256,  magicmovesbdb+896,
		magicmovesbdb+1280, magicmovesbdb+1664, magicmovesbdb+4800, magicmovesbdb+5120,
		magicmovesbdb+2560, magicmovesbdb+2656,  magicmovesbdb+288,  magicmovesbdb+928,
		magicmovesbdb+1312, magicmovesbdb+1696, magicmovesbdb+4832, magicmovesbdb+4928,
		magicmovesbdb+0,     magicmovesbdb+128,  magicmovesbdb+320,  magicmovesbdb+960,
		magicmovesbdb+1344, magicmovesbdb+1728, magicmovesbdb+2304, magicmovesbdb+2432,
		magicmovesbdb+32,    magicmovesbdb+160,  magicmovesbdb+448, magicmovesbdb+2752,
		magicmovesbdb+3776, magicmovesbdb+1856, magicmovesbdb+2336, magicmovesbdb+2464,
		magicmovesbdb+64,    magicmovesbdb+192,  magicmovesbdb+576, magicmovesbdb+3264,
		magicmovesbdb+4288, magicmovesbdb+1984, magicmovesbdb+2368, magicmovesbdb+2496,
		magicmovesbdb+96,    magicmovesbdb+224,  magicmovesbdb+704, magicmovesbdb+1088,
		magicmovesbdb+1472, magicmovesbdb+2112, magicmovesbdb+2400, magicmovesbdb+2528,
		magicmovesbdb+2592, magicmovesbdb+2688,  magicmovesbdb+832, magicmovesbdb+1216,
		magicmovesbdb+1600, magicmovesbdb+2240, magicmovesbdb+4864, magicmovesbdb+4960,
		magicmovesbdb+5056, magicmovesbdb+2720,  magicmovesbdb+864, magicmovesbdb+1248,
		magicmovesbdb+1632, magicmovesbdb+2272, magicmovesbdb+4896, magicmovesbdb+5184
	&#125;;
	U64* magicmoves_r_indecies2&#91;64&#93;=
	&#123;
		magicmovesrdb+86016, magicmovesrdb+73728, magicmovesrdb+36864, magicmovesrdb+43008,
		magicmovesrdb+47104, magicmovesrdb+51200, magicmovesrdb+77824, magicmovesrdb+94208,
		magicmovesrdb+69632, magicmovesrdb+32768, magicmovesrdb+38912, magicmovesrdb+10240,
		magicmovesrdb+14336, magicmovesrdb+53248, magicmovesrdb+57344, magicmovesrdb+81920,
		magicmovesrdb+24576, magicmovesrdb+33792,  magicmovesrdb+6144, magicmovesrdb+11264,
		magicmovesrdb+15360, magicmovesrdb+18432, magicmovesrdb+58368, magicmovesrdb+61440,
		magicmovesrdb+26624,  magicmovesrdb+4096,  magicmovesrdb+7168,     magicmovesrdb+0,
		magicmovesrdb+2048, magicmovesrdb+19456, magicmovesrdb+22528, magicmovesrdb+63488,
		magicmovesrdb+28672,  magicmovesrdb+5120,  magicmovesrdb+8192,  magicmovesrdb+1024,
		magicmovesrdb+3072, magicmovesrdb+20480, magicmovesrdb+23552, magicmovesrdb+65536,
		magicmovesrdb+30720, magicmovesrdb+34816,  magicmovesrdb+9216, magicmovesrdb+12288,
		magicmovesrdb+16384, magicmovesrdb+21504, magicmovesrdb+59392, magicmovesrdb+67584,
		magicmovesrdb+71680, magicmovesrdb+35840, magicmovesrdb+39936, magicmovesrdb+13312,
		magicmovesrdb+17408, magicmovesrdb+54272, magicmovesrdb+60416, magicmovesrdb+83968,
		magicmovesrdb+90112, magicmovesrdb+75776, magicmovesrdb+40960, magicmovesrdb+45056,
		magicmovesrdb+49152, magicmovesrdb+55296, magicmovesrdb+79872, magicmovesrdb+98304
	&#125;;
#endif // MINIMIZE_MAGIC


#ifdef PERFECT_MAGIC_HASH
	for&#40;i=0;i<1428;i++)
		magicmovesbdb&#91;i&#93;=0;
	for&#40;i=0;i<4900;i++)
		magicmovesrdb&#91;i&#93;=0;
#endif

	for&#40;i=0;i<64;i++)
	&#123;
		int squares&#91;64&#93;;
		int numsquares=0;
		U64 temp=magicmoves_b_mask&#91;i&#93;;
		while&#40;temp&#41;
		&#123;
			U64 bit=temp&-temp;
			squares&#91;numsquares++&#93;=initmagicmoves_bitpos64_database&#91;&#40;bit*0x07EDD5E59A4E28C2&#41;>>58&#93;;
			temp^=bit;
		&#125;
		for&#40;temp=0;temp<((&#40;U64&#41;&#40;1&#41;)<<numsquares&#41;;temp++)
		&#123;
			U64 tempocc=initmagicmoves_occ&#40;squares,numsquares,temp&#41;;
			#ifndef PERFECT_MAGIC_HASH
				BmagicNOMASK2&#40;i,tempocc&#41;=initmagicmoves_Bmoves&#40;i,tempocc&#41;;
			#else
				U64 moves=initmagicmoves_Bmoves&#40;i,tempocc&#41;;
				U64 index=((&#40;tempocc&#41;*magicmoves_b_magics&#91;i&#93;)>>MINIMAL_B_BITS_SHIFT&#41;;
				int j;
				for&#40;j=0;j<1428;j++)
				&#123;
					if&#40;!magicmovesbdb&#91;j&#93;)
					&#123;
						magicmovesbdb&#91;j&#93;=moves;
						magicmoves_b_indecies&#91;i&#93;&#91;index&#93;=j;
						break;
					&#125;
					else if&#40;magicmovesbdb&#91;j&#93;==moves&#41;
					&#123;
						magicmoves_b_indecies&#91;i&#93;&#91;index&#93;=j;
						break;
					&#125;
				&#125;
			#endif
		&#125;
	&#125;
	for&#40;i=0;i<64;i++)
	&#123;
		int squares&#91;64&#93;;
		int numsquares=0;
		U64 temp=magicmoves_r_mask&#91;i&#93;;
		while&#40;temp&#41;
		&#123;
			U64 bit=temp&-temp;
			squares&#91;numsquares++&#93;=initmagicmoves_bitpos64_database&#91;&#40;bit*0x07EDD5E59A4E28C2&#41;>>58&#93;;
			temp^=bit;
		&#125;
		for&#40;temp=0;temp<((&#40;U64&#41;&#40;1&#41;)<<numsquares&#41;;temp++)
		&#123;
			U64 tempocc=initmagicmoves_occ&#40;squares,numsquares,temp&#41;;
			#ifndef PERFECT_MAGIC_HASH
				RmagicNOMASK2&#40;i,tempocc&#41;=initmagicmoves_Rmoves&#40;i,tempocc&#41;;
			#else
				U64 moves=initmagicmoves_Rmoves&#40;i,tempocc&#41;;
				U64 index=((&#40;tempocc&#41;*magicmoves_r_magics&#91;i&#93;)>>MINIMAL_R_BITS_SHIFT&#41;;
				int j;
				for&#40;j=0;j<4900;j++)
				&#123;
					if&#40;!magicmovesrdb&#91;j&#93;)
					&#123;
						magicmovesrdb&#91;j&#93;=moves;
						magicmoves_r_indecies&#91;i&#93;&#91;index&#93;=j;
						break;
					&#125;
					else if&#40;magicmovesrdb&#91;j&#93;==moves&#41;
					&#123;
						magicmoves_r_indecies&#91;i&#93;&#91;index&#93;=j;
						break;
					&#125;
				&#125;
			#endif
		&#125;
	&#125;
&#125;

Harald
Posts: 259
Joined: Thu Mar 09, 2006 12:07 am

Re: BitBoard Tests (Exploding Bitboards)

Post by Harald » Sat Aug 25, 2007 6:51 am

bb_attacks_explode.cpp:

Code: Select all

/*******************************************************************/
/*
The exploding bitboard attacks 
as part of the board structure.

&#40;c&#41; 2006 Harald Lüßen
*/
/*******************************************************************/


#include "bb_ifdef.h"
#include "bb_basics.h"
#include "bb_bitboard.h"
#include "bb_board.h"
#include "bb_main.h"


#if USE_EXPLODING_BITBOARDS&#40;)

/*******************************************************************/

/*
    directions and shifts
    +-----+-----+-----+
    |<<= 9|<<= 8|<<= 7|
    +-----+-----+-----+
    |<<= 1|     |>>= 1|
    +-----+-----+-----+
    |>>= 7|>>= 8|>>= 9|
    +-----+-----+-----+

    We use this mapping of the normal board squares to bitboard bits
    +-------------------------+
    | 63 62 61 60 59 58 57 56 | 8
    | 55 54 53 52 51 50 49 48 | 7
    | 47 46 45 44 43 42 41 40 | 6
    | 39 38 37 36 35 35 33 32 | 5
    | 31 30 29 28 27 26 25 24 | 4
    | 23 22 21 20 19 18 17 16 | 3
    | 15 14 13 12 11 10  9  8 | 2
    |  7  6  5  4  3  2  1  0 | 1
    +-------------------------+
       a  b  c  d  e  f  g  h
*/

/*******************************************************************/

// Bishops

/**
First expanding step &#40;explosion&#41; for a bishop
 . . . . . . . .
 . . . . . . . .
 . . . . . . . .
 . . 1 . 1 . . .
 . . .sq . . . .
 . . 1 . 1 . . .
 . . . . . . . .
 . . . . . . . .
*/
Bitboard initB&#91;64&#93;;


/**
Mask for bishop attack rays
 . . . . . . . 1
 1 . . . . . 1 .
 . 1 . . . 1 . .
 . . 1 . 1 . . .
 . . .sq . . . .
 . . 1 . 1 . . .
 . 1 . . . 1 . .
 1 . . . . . 1 .
*/
Bitboard maskB&#91;64&#93;;


/**
Number of expanding steps &#40;explosions&#41; for a bishop
*/
const int initRepsB&#91;64&#93; = 
&#123;
    6, 5, 4, 3, 3, 4, 5, 6,
    5, 5, 4, 3, 3, 4, 5, 5,
    4, 4, 4, 3, 3, 4, 4, 4,
    3, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 3, 3, 3, 3,
    4, 4, 4, 3, 3, 4, 4, 4,
    5, 5, 4, 3, 3, 4, 5, 5,
    6, 5, 4, 3, 3, 4, 5, 6,
&#125;;


/**
Modified number of expanding steps &#40;explosions&#41; for a bishop
*/
int repsB&#91;64&#93; = 
&#123;
//  9, 8, 7,       7, 8, 9  // For some squares there is an
//  8, 8,             8, 8  // alternative with if &#40;bb == 0&#41; breaK;
// ------------------------ // after the first iteration
    6, 5, 4, 3, 3, 4, 5, 6,
    5, 5, 4, 3, 3, 4, 5, 5,
    4, 4, 4, 3, 3, 4, 4, 4,
    3, 3, 3, 3, 3, 3, 3, 3,
    3, 3, 3, 3, 3, 3, 3, 3,
    4, 4, 4, 3, 3, 4, 4, 4,
    5, 5, 4, 3, 3, 4, 5, 5,
    6, 5, 4, 3, 3, 4, 5, 6,
// ------------------------ // For some squares there is an 
//  8, 8,             8, 8  // alternative with if &#40;bb == 0&#41; breaK;
//  9, 8, 7,       7, 8, 9  // after the first iteration
&#125;;


/**
First expanding step &#40;explosion&#41; for a bishop
 . . . . . . . .
 . . . . . . . .
 . . . . . . . .
 . . 1 . 1 . . .
 . . .sq . . . .
 . . 1 . 1 . . .
 . . . . . . . .
 . . . . . . . .
*/
void makeInitB&#40;)
&#123;
    for ( int sq = 0; sq < 64; ++sq )
    &#123;
        Bitboard bb = C64&#40;1&#41; << sq;
        initB&#91;sq&#93;  = &#40;bb >> 9&#41; & C64&#40;0x7f7f7f7f7f7f7f7f&#41;;
        initB&#91;sq&#93; |= &#40;bb >> 7&#41; & C64&#40;0xfefefefefefefefe&#41;;
        initB&#91;sq&#93; |= &#40;bb << 9&#41; & C64&#40;0xfefefefefefefefe&#41;;
        initB&#91;sq&#93; |= &#40;bb << 7&#41; & C64&#40;0x7f7f7f7f7f7f7f7f&#41;;
    &#125;
&#125;


/**
Mask for bishop attack rays
 . . . . . . . 1
 1 . . . . . 1 .
 . 1 . . . 1 . .
 . . 1 . 1 . . .
 . . .sq . . . .
 . . 1 . 1 . . .
 . 1 . . . 1 . .
 1 . . . . . 1 .
*/
void makeMaskB&#40;)
&#123;
    int sq;
    for ( sq = 0; sq < 64; ++sq )
    &#123;
        maskB&#91;sq&#93; = 0;
        int i;
        for ( i = sq - 9; i >= 0 && i % 8 != 7; i -= 9 )
        &#123;
            maskB&#91;sq&#93; |= C64&#40;1&#41; << i;
        &#125;
        for ( i = sq - 7; i >= 0 && i % 8 != 0; i -= 7 )
        &#123;
            maskB&#91;sq&#93; |= C64&#40;1&#41; << i;
        &#125;
        for ( i = sq + 9; i < 64 && i % 8 != 0; i += 9 )
        &#123;
            maskB&#91;sq&#93; |= C64&#40;1&#41; << i;
        &#125;
        for ( i = sq + 7; i < 64 && i % 8 != 7; i += 7 )
        &#123;
            maskB&#91;sq&#93; |= C64&#40;1&#41; << i;
        &#125;
    &#125;
&#125;


/**
Change generating of bishop attacks.
Perhaps this improves the performance. 
Use this function at begin of search, at least when the remaining depth is big.
For some squares there is an alternative with if &#40;bb == 0&#41; breaK;
after the first iteration in bishopAttacks&#40;).
*/
void changeRepsB&#40; const Bitboard &wpawns, const Bitboard &bpawns )
&#123;
    static const int w&#91;10&#93; = &#123; 0,  1,  2,   5,  6,  7, 
                               8,  9,          14, 15, &#125;;
    static const int b&#91;10&#93; = &#123;48, 49,          54, 55,
                              56, 57, 58,  61, 62, 63, &#125;;
    for ( int i = 0; i < 10; ++i )
    &#123;
        int sq = w&#91;i&#93;;
        if ( wpawns & initB&#91;sq&#93; )   repsB&#91;sq&#93; = initRepsB&#91;sq&#93; + 3;
        else                        repsB&#91;sq&#93; = initRepsB&#91;sq&#93;;
        sq = b&#91;i&#93;;
        if ( bpawns & initB&#91;sq&#93; )   repsB&#91;sq&#93; = initRepsB&#91;sq&#93; + 3;
        else                        repsB&#91;sq&#93; = initRepsB&#91;sq&#93;;
    &#125;
&#125;


/*
= init               >>= 9               *= 0x5005          &= mask            at |= bb
 . . . . . . . .     . . . . . . . .     . . . . . . . .    . . . . . . . .    . . . . . . . .    
 . . . . . . . .     . . . . . . . .     . . . . . . . .    . . . . . . . .    . . . . . . . .    
 . . . . . . . .     . . . . . . . .     . 1 1 . . 1 . .    . 1 . . . 1 . .    . 1 . . . 1 . .    
 . . 1 . 1 . . .     . . . . . . . .     . . . . . . . .    . . . . . . . .    . . 1 . 1 . . .    
 . . . s . . . .     . . . 1 . 1 . .     1 1 . . 1 . . .    . . . s . . . .    . . . s . . . .    
 . . 1 . 1 . . .     . . . . . . . .     . . . . . . . .    . . . . . . . .    . . 1 . 1 . . .    
 . . . . . . . .     . . . 1 . 1 . .     . 1 1 . . 1 . .    . 1 . . . 1 . .    . 1 . . . 1 . .    
 . . . . . . . .     . . . . . . . .     . . . . . . . .    . . . . . . . .    . . . . . . . .    
*/
Bitboard bishopAttacks&#40; int sq, const Bitboard &free )
&#123;
    Bitboard msk = maskB&#91;sq&#93;;
    Bitboard bb  = initB&#91;sq&#93;;
    Bitboard at  = bb;
    bb &= free;
    switch ( repsB&#91;sq&#93; )
    &#123;
      case 9&#58;
        bb >>= 9; bb *= 0x00050005; bb &= msk; at |= bb; bb &= free;
        if ( !bb )
            break; // Note bishop trapped in corner.
        goto five_to_do;
      case 8&#58;
        bb >>= 9; bb *= 0x00050005; bb &= msk; at |= bb; bb &= free;
        if ( !bb )
            break; // Note bishop trapped in corner.
        goto four_to_do;
      case 7&#58;
        bb >>= 9; bb *= 0x00050005; bb &= msk; at |= bb; bb &= free;
        if ( !bb )
            break;
        goto three_to_do;
      case 6&#58;
        bb >>= 9; bb *= 0x00050005; bb &= msk; at |= bb; bb &= free;
      case 5&#58;
      five_to_do&#58;
        bb >>= 9; bb *= 0x00050005; bb &= msk; at |= bb; bb &= free;
      case 4&#58;
      four_to_do&#58;
        bb >>= 9; bb *= 0x00050005; bb &= msk; at |= bb; bb &= free;
      case 3&#58;
      three_to_do&#58;
        bb >>= 9; bb *= 0x00050005; bb &= msk; at |= bb; bb &= free;
        bb >>= 9; bb *= 0x00050005; bb &= msk; at |= bb; bb &= free;
        bb >>= 9; bb *= 0x00050005; bb &= msk; at |= bb;
    &#125;
    return at;
&#125;


/*******************************************************************/

// Rooks

/**
First expanding step &#40;explosion&#41; for a rook
 . . . . . . . .
 . . . . . . . .
 . . . . . . . .
 . . . 1 . . . .
 . . 1sq 1 . . .
 . . . 1 . . . .
 . . . . . . . .
 . . . . . . . .
*/
Bitboard initR&#91;64&#93;;


/**
Mask for rook attack rays
 . . . 1 . . . .
 . . . 1 . . . .
 . . . 1 . . . .
 . . . 1 . . . .
 1 1 1sq 1 1 1 1
 . . . 1 . . . .
 . . . 1 . . . .
 . . . 1 . . . .
*/
Bitboard maskR&#91;64&#93;;


/**
Number of expanding steps &#40;explosions&#41; for a rook
*/
const int initRepsR&#91;64&#93; = 
&#123;
    7, 6, 6, 6, 6, 6, 6, 8,
    7, 5, 5, 5, 5, 5, 5, 8,
    7, 5, 4, 4, 4, 4, 5, 8,
    7, 5, 4, 3, 3, 4, 5, 8,
    7, 5, 4, 3, 3, 4, 5, 8,
    7, 5, 4, 4, 4, 4, 5, 8,
    7, 5, 5, 5, 5, 5, 5, 8,
    7, 6, 6, 6, 6, 6, 6, 8,
&#125;;

/**
Modified number of expanding steps &#40;explosions&#41; for a rook
*/
int repsR&#91;64&#93; = 
&#123;
// 10, 9, 9, 9, 9, 9, 9,11, // For sq = 63 62 61 &#40;60 59&#41; 58 57 56 there is an
// ------------------------ // alternative with if &#40;bb == 0&#41; breaK;
    7, 6, 6, 6, 6, 6, 6, 8, // after the first iteration
    7, 5, 5, 5, 5, 5, 5, 8,
    7, 5, 4, 4, 4, 4, 5, 8,
    7, 5, 4, 3, 3, 4, 5, 8,
    7, 5, 4, 3, 3, 4, 5, 8,
    7, 5, 4, 4, 4, 4, 5, 8,
    7, 5, 5, 5, 5, 5, 5, 8,
    7, 6, 6, 6, 6, 6, 6, 8,
// ------------------------ // For sq = 7 6 5 &#40;4 3&#41; 2 1 0 there is an
// 10, 9, 9, 9, 9, 9, 9,11, // alternative with if &#40;bb == 0&#41; breaK;
&#125;;                          // after the first iteration


/*
First expanding step &#40;explosion&#41; for a rook
 . . . . . . . .
 . . . . . . . .
 . . . . . . . .
 . . . 1 . . . .
 . . 1sq 1 . . .
 . . . 1 . . . .
 . . . . . . . .
 . . . . . . . .
*/
void makeInitR&#40;)
&#123;
    for ( int sq = 0; sq < 64; ++sq )
    &#123;
        Bitboard bb = C64&#40;1&#41; << sq;
        initR&#91;sq&#93;  = &#40;bb >> 8&#41;;
        initR&#91;sq&#93; |= &#40;bb >> 1&#41; & C64&#40;0x7f7f7f7f7f7f7f7f&#41;;
        initR&#91;sq&#93; |= &#40;bb << 1&#41; & C64&#40;0xfefefefefefefefe&#41;;
        initR&#91;sq&#93; |= &#40;bb << 8&#41;;
        //logf << "initR&#91;sq&#93; " << sq << endl;
        //logf << initR&#91;sq&#93;.txt8lines&#40;) << endl;
    &#125;
&#125;


/*
Mask for rook attack rays
 . . . 1 . . . .
 . . . 1 . . . .
 . . . 1 . . . .
 . . . 1 . . . .
 1 1 1sq 1 1 1 1
 . . . 1 . . . .
 . . . 1 . . . .
 . . . 1 . . . .
*/
void makeMaskR&#40;)
&#123;
    int sq;
    for ( sq = 0; sq < 64; ++sq )
    &#123;
        maskR&#91;sq&#93; = 0;
        int i;
        for ( i = sq - 8; i >= 0; i -= 8 )
        &#123;
            maskR&#91;sq&#93; |= C64&#40;1&#41; << i;
        &#125;
        for ( i = sq - 1; i >= 0 && &#40;i & 7&#41; != 7; --i )
        &#123;
            maskR&#91;sq&#93; |= C64&#40;1&#41; << i;
        &#125;
        for ( i = sq + 1; i < 64 && &#40;i & 7&#41; != 0; ++i )
        &#123;
            maskR&#91;sq&#93; |= C64&#40;1&#41; << i;
        &#125;
        for ( i = sq + 8; i < 64; i += 8 )
        &#123;
            maskR&#91;sq&#93; |= C64&#40;1&#41; << i;
        &#125;
        //logf << "maskR&#91;sq&#93; " << sq << endl;
        //logf << maskR&#91;sq&#93;.txt8lines&#40;) << endl;
    &#125;
&#125; 


int rankR&#91;8&#93;&#91;128&#93;;  // or byte or Bitboard?

void makeRankR&#40;)
&#123;
    for ( int sq = 0; sq < 8; ++sq )
    &#123;
        for ( int i = 0; i < 128; i += 2 )
        &#123;
            int rr = 0;
            int j;
            for ( j = sq - 1; j >= 0; --j )
            &#123;
                rr |= &#40;1 << j&#41;;
                if ( !&#40;i & &#40;1 << j&#41;) )  // the 1 bits are the free squares
                    break;
            &#125;
            for ( j = sq + 1; j < 8; ++j )
            &#123;
                rr |= &#40;1 << j&#41;;
                if ( !&#40;i & &#40;1 << j&#41;) )  // the 1 bits are the free squares
                    break;
            &#125;
            rankR&#91;sq&#93;&#91;i  &#93; = rr;
            rankR&#91;sq&#93;&#91;i+1&#93; = rr;
            //logf << "rankR&#91;sq&#93;&#91;i&#93; " << sq << " " << i << " " << rankR&#91;sq&#93;&#91;i&#93; << endl;
        &#125;
    &#125;
&#125;


/**
Change generating of rook attacks.
Perhaps this improves the performance. 
Use this function at begin of search, at least when the remaining depth is big.
For sq = 63 62 61 &#40;60 59&#41; 58 57 56 and sq = 7 6 5 &#40;4 3&#41; 2 1 0 
there is an alternative with if &#40;bb == 0&#41; breaK;
after the first iteration in rookAttacks&#40;).
*/
void changeRepsR&#40; const Bitboard &wpawns, const Bitboard &bpawns )
&#123;
    Bitboard bb = C64&#40;0x0000000000010100&#41;;
    for ( int sq = 0; sq < 8; ++sq )
    &#123;
        if ( sq != 3 && sq != 4 )
        &#123;
            if ( bb & wpawns )
                repsR&#91;sq&#93; = initRepsR&#91;sq&#93; + 3;
            else
                repsR&#91;sq&#93; = initRepsR&#91;sq&#93;;
        &#125;
        bb <= 1;
    &#125;
    bb = C64&#40;0x0001010000000000&#41;;
    for ( sq = 56; sq < 64; ++sq )
    &#123;
        if ( sq != 59 && sq != 60 )
        &#123;
            if ( bb & bpawns )
                repsR&#91;sq&#93; = initRepsR&#91;sq&#93; + 3;
            else
                repsR&#91;sq&#93; = initRepsR&#91;sq&#93;;
        &#125;
        bb <= 1;
    &#125;
&#125;


/*
= init               >>= 8               *= 10281           &= mask            at |= bb
 . . . . . . . .     . . . . . . . .     . . . . . . . .    . . . . . . . .    . . . . . . . .   
 . . . . . . . .     . . . . . . . .     . . . . . . . .    . . . . . . . .    . . . . . . . .   
 . . . . . . . .     . . . . . . . .     . . . 1 . . . .    . . . 1 . . . .    . . . 1 . . . .   
 . . . 1 . . . .     . . . . . . . .     . . 1 . 1 . . .    . . . . . . . .    . . . 1 . . . .   
 . . 1 s 1 . . .     . . . 1 . . . .     . 1 . 1 . 1 . .    . 1 . s . 1 . .    . 1 1 s 1 1 . .   
 . . . 1 . . . .     . . 1 . 1 . . .     . . 1 . 1 . . .    . . . . . . . .    . . . 1 . . . .   
 . . . . . . . .     . . . 1 . . . .     . . . 1 . . . .    . . . 1 . . . .    . . . 1 . . . .   
 . . . . . . . .     . . . . . . . .     . . . . . . . .    . . . . . . . .    . . . . . . . .   
                                       and nasty overflows
*/
Bitboard rookAttacks&#40; int sq, const Bitboard &free )
&#123;
    Bitboard msk = maskR&#91;sq&#93;;   // The mask kills scattered bits
    Bitboard bb  = initR&#91;sq&#93;;   // This drives the expansion/explosion. Here is the start.
    Bitboard at  = bb;          // Collecting the resulting attacks
    Bitboard cl  = at;          // Clears some intermediate overflows
    Bitboard ov;                // A nasty overflow bit when 4 directions in first step are possible.
                                // Not nessessary on left side of board for repsR&#91;sq&#93; = 4 or 5.
                                // Invent new numbers? 
    // Perhaps it would be easier and faster to use rankR&#91;&#93;&#91;&#93; on all ranks.
    // But I like the 'explosive' algorithm. And I want to show that it works.
    bb &= free;
    switch ( repsR&#91;sq&#93; )
    &#123;
      case 11&#58;
        bb >>= 8; bb *= 0x00010081; bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
        if ( !bb )
            break;
        goto five_to_do;
      case 10&#58;
        bb >>= 8; bb *= 0x00010201; bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
        if ( !bb )
            break;
        goto five_to_do;
      case 9&#58;
        bb >>= 8; bb *= 0x00010281;
        bb &= ~&#40;C64&#40;1&#41; << &#40;sq - 6&#41;);      // Clears for b-squares a nasty overflow from south-west-first-step to h file
        bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
        if ( !bb )
            break;
        goto five_to_do;
      case 8&#58;
        bb >>= 8; bb *= 0x00010081; bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
        goto five_to_do;
      case 7&#58;
        bb >>= 8; bb *= 0x00010201; bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
        goto five_to_do;
      case 6&#58;
        bb >>= 8; bb *= 0x00010281;
        bb &= ~&#40;C64&#40;1&#41; << &#40;sq - 6&#41;);      // Clears for b-squares a nasty overflow from south-west-first-step to h file
        bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
        goto five_to_do;
      case 5&#58;
        cl = at;
        bb >>= 8; bb *= 0x00010281;
        ov = &#40;C64&#40;1&#41; << &#40;sq + 3&#41;);
        bb |= &#40;bb & ov&#41; >> 1; 
        bb &= ~ov; 
        bb &= ~&#40;C64&#40;1&#41; << &#40;sq - 6&#41;);      // Clears for b-squares a nasty overflow from south-west-first-step to h file
        bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
        goto four_to_do;
      case 4&#58;
        cl = at;
        bb >>= 8; bb *= 0x00010281;
        ov = &#40;C64&#40;1&#41; << &#40;sq + 3&#41;); 
        bb |= &#40;bb & ov&#41; >> 1; 
        bb &= ~ov; 
        bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
        goto three_to_do;
      case 3&#58;
        cl = at;
        bb >>= 8; bb *= 0x00010281;
        ov = &#40;C64&#40;1&#41; << &#40;sq + 3&#41;); 
        bb |= &#40;bb & ov&#41; >> 1; 
        bb &= ~ov; 
        bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
        goto two_to_do;
      default&#58;
      five_to_do&#58;
        cl = at;
        bb >>= 8; bb *= 0x00010281; bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
      four_to_do&#58;
        cl = at;
        bb >>= 8; bb *= 0x00010281; bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
      three_to_do&#58;
        cl = at;
        bb >>= 8; bb *= 0x00010281; bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
      two_to_do&#58;
        cl = at;
        bb >>= 8; bb *= 0x00010281; bb &= msk; at |= bb; bb &= free;
        bb &= ~cl;
        bb >>= 8; bb *= 0x00010281; bb &= msk; at |= bb;
    &#125;
    if ( sq < 8 ) // or do this before the switch
    &#123;
        byte a1a8 = free;
        at |= rankR&#91;sq&#93;&#91;a1a8 & 0x7e&#93;;
    &#125;
    return at;
&#125;


/*******************************************************************/

const Bitboard dirMaskRight&#91;8&#93; =
&#123;
    // 0, line_h, line_gh, line_fh, line_eh, line_dh, line_ch, line_bh, 
    0, C64&#40;0x0101010101010101&#41;, C64&#40;0x0303030303030303&#41;, C64&#40;0x0707070707070707&#41;, C64&#40;0x0f0f0f0f0f0f0f0f&#41;, 
    C64&#40;0x1f1f1f1f1f1f1f1f&#41;, C64&#40;0x3f3f3f3f3f3f3f3f&#41;, C64&#40;0x7f7f7f7f7f7f7f7f&#41;
&#125;;

const Bitboard dirMaskLeft&#91;8&#93; =
&#123;
    // line_ag, line_af, line_ae, line_ad, line_ac, line_ab, line_a, 0, 
    C64&#40;0xfefefefefefefefe&#41;, C64&#40;0xfcfcfcfcfcfcfcfc&#41;, C64&#40;0xf8f8f8f8f8f8f8f8&#41;, C64&#40;0xf0f0f0f0f0f0f0f0&#41;, 
    C64&#40;0xe0e0e0e0e0e0e0e0&#41;, C64&#40;0xc0c0c0c0c0c0c0c0&#41;, C64&#40;0x8080808080808080&#41;, 0
&#125;;

const Bitboard dirMaskUp&#91;8&#93; =
&#123;
    // row_28, row_38, row_48, row_58, row_68, row_78, row_8, 0, 
    C64&#40;0xffffffffffffff00&#41;, C64&#40;0xffffffffffff0000&#41;, C64&#40;0xffffffffff000000&#41;, C64&#40;0xffffffff00000000&#41;, 
    C64&#40;0xffffff0000000000&#41;, C64&#40;0xffff000000000000&#41;, C64&#40;0xff00000000000000&#41;, 0
&#125;;

const Bitboard dirMaskDown&#91;8&#93; =
&#123;
    // 0, row_1, row_12, row_13, row_14, row_15, row_16, row_17,
    0, C64&#40;0x00000000000000ff&#41;, C64&#40;0x000000000000ffff&#41;, C64&#40;0x0000000000ffffff&#41;, C64&#40;0x00000000ffffffff&#41;, 
    C64&#40;0x000000ffffffffff&#41;, C64&#40;0x0000ffffffffffff&#41;, C64&#40;0x00ffffffffffffff&#41;
&#125;;


/*******************************************************************/
/*******************************************************************/

/**
Prepare the slider attacks back transformation table.
Put the scattered bits of an sliding attack pattern 
back to the original bitboard.
*/
void Board&#58;&#58;init_slider_attacks_index&#40;)
&#123;
    makeInitB&#40;);
    makeMaskB&#40;);
    makeInitR&#40;);
    makeMaskR&#40;);
    makeRankR&#40;);
&#125;


/*******************************************************************/

/**
Change generating of bishop and rook attacks.
Perhaps this improves the performance. 
Use this function at begin of search, at least when the remaining depth is big.
*/
void Board&#58;&#58;change_slider_attacks_index&#40;)
&#123;
    changeRepsB&#40; wpieces_ & pawns_, bpieces_ & pawns_ );
    changeRepsR&#40; wpieces_ & pawns_, bpieces_ & pawns_ );
&#125;


/*******************************************************************/

/**
Get a bitboard with all positions set to 1 which can be attacked 
from a bishop, rook or queen on the square moving in the direction.
*/
Bitboard Board&#58;&#58;direction_attacks&#40; byte square, byte dir ) const
&#123;
    Bitboard result;
    Bitboard free = ~&#40;wpieces_ | bpieces_);

    // 4 3 2
    // 5 0 1
    // 6 7 8
    switch ( dir )
    &#123;
      case 1&#58;
        result = rookAttacks&#40; square, free );
        result &= dirMaskRight&#91;square & 7&#93;;
        break;
      case 5&#58;
        result = rookAttacks&#40; square, free );
        result &= dirMaskLeft&#91;square & 7&#93;;
        break;
      case 7&#58;
        result = rookAttacks&#40; square, free );
        result &= dirMaskDown&#91;square >> 3&#93;;
        break;
      case 3&#58;
        result = rookAttacks&#40; square, free );
        result &= dirMaskUp&#91;square >> 3&#93;;
        break;
      case 8&#58;
        result = bishopAttacks&#40; square, free );
        result &= dirMaskRight&#91;square & 7&#93;;
        result &= dirMaskDown&#91;square >> 3&#93;;
        break;
      case 4&#58;
        result = bishopAttacks&#40; square, free );
        result &= dirMaskLeft&#91;square & 7&#93;;
        result &= dirMaskUp&#91;square >> 3&#93;;
        break;
      case 2&#58;
        result = bishopAttacks&#40; square, free );
        result &= dirMaskRight&#91;square & 7&#93;;
        result &= dirMaskUp&#91;square >> 3&#93;;
        break;
      case 6&#58;
        result = bishopAttacks&#40; square, free );
        result &= dirMaskLeft&#91;square & 7&#93;;
        result &= dirMaskDown&#91;square >> 3&#93;;
        break;
      default&#58;
        result = 0;
        break;
    &#125;

    return result;
&#125;


/*******************************************************************/

/**
Get a bitboard with all positions set to 1 which can be attacked 
from a rook or queen on the square.
*/
Bitboard Board&#58;&#58;orthogonal_attacks&#40; byte square ) const
&#123;
    Bitboard free = ~&#40;wpieces_ | bpieces_);
    Bitboard result = rookAttacks&#40; square, free );
    return result;
&#125;


/*******************************************************************/

/**
Get a bitboard with all positions set to 1 which can be attacked 
from a bishop or queen on the square.
*/
Bitboard Board&#58;&#58;diagonal_attacks&#40; byte square ) const
&#123;
    Bitboard free = ~&#40;wpieces_ | bpieces_);
    Bitboard result = bishopAttacks&#40; square, free );
    return result;
&#125;


/*******************************************************************/

#endif // USE_EXPLODING_BITBOARDS&#40;)

Harald
Posts: 259
Joined: Thu Mar 09, 2006 12:07 am

Re: BitBoard Tests (Rotated)

Post by Harald » Sat Aug 25, 2007 6:53 am

bb_attacks_rotated.cpp:

Code: Select all

/*******************************************************************/
/*
The rotated bitboard attacks as part of the board structure.

&#40;c&#41; 2002-2006 Harald Lüßen
*/
/*******************************************************************/


#include "bb_ifdef.h"
#include "bb_basics.h"
#include "bb_bitboard.h"
#include "bb_board.h"


#if USE_ROTATED_BITBOARDS&#40;)

/*******************************************************************/

/*
    directions and shifts
    +-----+-----+-----+
    |<<= 9|<<= 8|<<= 7|
    +-----+-----+-----+
    |<<= 1|     |>>= 1|
    +-----+-----+-----+
    |>>= 7|>>= 8|>>= 9|
    +-----+-----+-----+

    We use this mapping of the normal board squares to bitboard bits
    +-------------------------+
    | 63 62 61 60 59 58 57 56 | 8
    | 55 54 53 52 51 50 49 48 | 7
    | 47 46 45 44 43 42 41 40 | 6
    | 39 38 37 36 35 35 33 32 | 5
    | 31 30 29 28 27 26 25 24 | 4
    | 23 22 21 20 19 18 17 16 | 3
    | 15 14 13 12 11 10  9  8 | 2
    |  7  6  5  4  3  2  1  0 | 1
    +-------------------------+
       a  b  c  d  e  f  g  h

    squares on the board rotated left 90 degrees
    H8 H7 H6 H5 H4 H3 H2 H1   |   |   | 
    G8 G7 G6 G5 G4 G3 G2 G1   3.  2.  1.
    F8 F7 F6 F5 F4 F3 F2 F1   |   |   | 
    E8 E7 E6 E5 E4 E3 E2 E1   v   v   v
    D8 D7 D6 D5 D4 D3 D2 D1
    C8 C7 C6 C5 C4 C3 C2 C1
    B8 B7 B6 B5 B4 B3 B2 B1
    A8 A7 A6 A5 A4 A3 A2 A1

    squares on the board rotated left 45 degrees
    H8 G8 H7 F8 G7 H6 E8 F7   \   \    
    G6 H5 D8 E7 F6 G5 H4 C8     \   1. 
    D7 E6 F5 G4 H3 B8 C7 D6   \  2.  \ 
    E5 F4 G3 H2 A8 B7 C6 D5    3.  \  v
    E4 F3 G2 H1 A7 B6 C5 D4      \   \ 
    E3 F2 G1 A6 B5 C4 D3 E2       v   v
    F1 A5 B4 C3 D2 E1 A4 B3
    C2 D1 A3 B2 C1 A2 B1 A1

    squares on the board rotated right 45 degrees
    A8 A7 B8 A6 B7 C8 A5 B6        >    
    C7 D8 A4 B5 C6 D7 E8 A3      /   >  
    B4 C5 D6 E7 F8 A2 B3 C4    1.  /   >
    D5 E6 F7 G8 A1 B2 C3 D4   /  2.  /  
    E5 F6 G7 H8 B1 C2 D3 E4     /  3.   
    F5 G6 H7 C1 D2 E3 F4 G5   /   /     
    H6 D1 E2 F3 G4 H5 E1 F2
    G3 H4 F1 G2 H3 G1 H2 H1
*/

/*******************************************************************/

// pieces at begin of game in rotated bitboards
const Bitboard begin_all_rl90 = C64&#40;0xc3c3c3c3c3c3c3c3&#41;;
const Bitboard begin_all_rl45 = C64&#40;0xfb31861c38618cdf&#41;;
const Bitboard begin_all_rr45 = C64&#40;0xecc61c3c3c386337&#41;;


/*******************************************************************/

// Bit numbers of the normal board in the rotated board
const byte normal_to_rl90&#91;64&#93; =
&#123;
    H8Nr, H7Nr, H6Nr, H5Nr, H4Nr, H3Nr, H2Nr, H1Nr,
    G8Nr, G7Nr, G6Nr, G5Nr, G4Nr, G3Nr, G2Nr, G1Nr,
    F8Nr, F7Nr, F6Nr, F5Nr, F4Nr, F3Nr, F2Nr, F1Nr,
    E8Nr, E7Nr, E6Nr, E5Nr, E4Nr, E3Nr, E2Nr, E1Nr,
    D8Nr, D7Nr, D6Nr, D5Nr, D4Nr, D3Nr, D2Nr, D1Nr,
    C8Nr, C7Nr, C6Nr, C5Nr, C4Nr, C3Nr, C2Nr, C1Nr,
    B8Nr, B7Nr, B6Nr, B5Nr, B4Nr, B3Nr, B2Nr, B1Nr,
    A8Nr, A7Nr, A6Nr, A5Nr, A4Nr, A3Nr, A2Nr, A1Nr,
&#125;;

// Bit numbers of the normal board in the rotated board
const byte normal_to_rl45&#91;64&#93; =
&#123;
    D4Nr, C3Nr, A2Nr, F2Nr, B1Nr, E1Nr, G1Nr, H1Nr,
    D5Nr, C4Nr, B3Nr, H3Nr, E2Nr, A1Nr, D1Nr, F1Nr,
    E6Nr, C5Nr, B4Nr, A3Nr, G3Nr, D2Nr, H2Nr, C1Nr,
    G7Nr, D6Nr, B5Nr, A4Nr, H4Nr, F3Nr, C2Nr, G2Nr,
    B7Nr, F7Nr, C6Nr, A5Nr, H5Nr, G4Nr, E3Nr, B2Nr,
    F8Nr, A7Nr, E7Nr, B6Nr, H6Nr, G5Nr, F4Nr, D3Nr,
    C8Nr, E8Nr, H8Nr, D7Nr, A6Nr, G6Nr, F5Nr, E4Nr,
    A8Nr, B8Nr, D8Nr, G8Nr, C7Nr, H7Nr, F6Nr, E5Nr,
&#125;;

// Bit numbers of the normal board in the rotated board
const byte normal_to_rr45&#91;64&#93; =
&#123;
    H1Nr, F1Nr, C1Nr, G2Nr, B2Nr, D3Nr, E4Nr, E5Nr,
    G1Nr, D1Nr, H2Nr, C2Nr, E3Nr, F4Nr, F5Nr, F6Nr,
    E1Nr, A1Nr, D2Nr, F3Nr, G4Nr, G5Nr, G6Nr, H7Nr,
    B1Nr, E2Nr, G3Nr, H4Nr, H5Nr, H6Nr, A6Nr, C7Nr,
    F2Nr, H3Nr, A3Nr, A4Nr, A5Nr, B6Nr, D7Nr, G8Nr,
    A2Nr, B3Nr, B4Nr, B5Nr, C6Nr, E7Nr, H8Nr, D8Nr,
    C3Nr, C4Nr, C5Nr, D6Nr, F7Nr, A7Nr, E8Nr, B8Nr,
    D4Nr, D5Nr, E6Nr, G7Nr, B7Nr, F8Nr, C8Nr, A8Nr,
&#125;;

// Shift values of the rotated bitboard for attacks and move generation.
// Shift the rotated bitboard this number of bits to find the row in the low bits.
// The index is the square number on the normal board.
const byte shift_of_rl90&#91;64&#93; =
&#123;
    H8Nr, H7Nr, H6Nr, H5Nr, H4Nr, H3Nr, H2Nr, H1Nr,
    H8Nr, H7Nr, H6Nr, H5Nr, H4Nr, H3Nr, H2Nr, H1Nr,
    H8Nr, H7Nr, H6Nr, H5Nr, H4Nr, H3Nr, H2Nr, H1Nr,
    H8Nr, H7Nr, H6Nr, H5Nr, H4Nr, H3Nr, H2Nr, H1Nr,
    H8Nr, H7Nr, H6Nr, H5Nr, H4Nr, H3Nr, H2Nr, H1Nr,
    H8Nr, H7Nr, H6Nr, H5Nr, H4Nr, H3Nr, H2Nr, H1Nr,
    H8Nr, H7Nr, H6Nr, H5Nr, H4Nr, H3Nr, H2Nr, H1Nr,
    H8Nr, H7Nr, H6Nr, H5Nr, H4Nr, H3Nr, H2Nr, H1Nr,
&#125;;

// Shift values of the rotated bitboard for attacks and move generation.
// Shift the rotated bitboard this number of bits to find the row in the low bits.
// The index is the square number on the normal board.
const byte shift_of_rl45&#91;64&#93; =
&#123;
    D4Nr, C3Nr, A2Nr, F2Nr, B1Nr, E1Nr, G1Nr, H1Nr,
    D5Nr, D4Nr, C3Nr, A2Nr, F2Nr, B1Nr, E1Nr, G1Nr,
    E6Nr, D5Nr, D4Nr, C3Nr, A2Nr, F2Nr, B1Nr, E1Nr,
    G7Nr, E6Nr, D5Nr, D4Nr, C3Nr, A2Nr, F2Nr, B1Nr,
    B7Nr, G7Nr, E6Nr, D5Nr, D4Nr, C3Nr, A2Nr, F2Nr,
    F8Nr, B7Nr, G7Nr, E6Nr, D5Nr, D4Nr, C3Nr, A2Nr,
    C8Nr, F8Nr, B7Nr, G7Nr, E6Nr, D5Nr, D4Nr, C3Nr,
    A8Nr, C8Nr, F8Nr, B7Nr, G7Nr, E6Nr, D5Nr, D4Nr,
&#125;;

// Shift values of the rotated bitboard for attacks and move generation.
// Shift the rotated bitboard this number of bits to find the row in the low bits.
// The index is the square number on the normal board.
const byte shift_of_rr45&#91;64&#93; =
&#123;
    H1Nr, G1Nr, E1Nr, B1Nr, F2Nr, A2Nr, C3Nr, D4Nr,
    G1Nr, E1Nr, B1Nr, F2Nr, A2Nr, C3Nr, D4Nr, D5Nr,
    E1Nr, B1Nr, F2Nr, A2Nr, C3Nr, D4Nr, D5Nr, E6Nr,
    B1Nr, F2Nr, A2Nr, C3Nr, D4Nr, D5Nr, E6Nr, G7Nr,
    F2Nr, A2Nr, C3Nr, D4Nr, D5Nr, E6Nr, G7Nr, B7Nr,
    A2Nr, C3Nr, D4Nr, D5Nr, E6Nr, G7Nr, B7Nr, F8Nr,
    C3Nr, D4Nr, D5Nr, E6Nr, G7Nr, B7Nr, F8Nr, C8Nr,
    D4Nr, D5Nr, E6Nr, G7Nr, B7Nr, F8Nr, C8Nr, A8Nr,
&#125;;

// Mask values of the rotated bitboard for attacks and move generation.
// Mask the low bits of a shifted diagonal/row/line with bits in the correct length.
// The index is the square number on the normal board.
const byte mask_of_rl45&#91;64&#93; =
&#123;
    0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 
    0x7f, 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 
    0x3f, 0x7f, 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 
    0x1f, 0x3f, 0x7f, 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 
    0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x7f, 0x3f, 0x1f, 
    0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x7f, 0x3f, 
    0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x7f, 
    0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 
&#125;;

// Mask values of the rotated bitboard for attacks and move generation.
// Mask the low bits of a shifted diagonal/row/line with bits in the correct length.
// The index is the square number on the normal board.
const byte mask_of_rr45&#91;64&#93; =
&#123;
    0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 
    0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x7f, 
    0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x7f, 0x3f, 
    0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x7f, 0x3f, 0x1f, 
    0x1f, 0x3f, 0x7f, 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 
    0x3f, 0x7f, 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 
    0x7f, 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 
    0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 
&#125;;

// Index values of the rotated bitboard for attacks and move generation.
// This is the number of the slider part of the bitboard for use in slider_rl90_to_bitboard.
// The index is the square number on the normal board.
const byte index_of_rl90&#91;64&#93; =
&#123;
    0, 1, 2, 3, 4, 5, 6, 7,
    0, 1, 2, 3, 4, 5, 6, 7,
    0, 1, 2, 3, 4, 5, 6, 7,
    0, 1, 2, 3, 4, 5, 6, 7,
    0, 1, 2, 3, 4, 5, 6, 7,
    0, 1, 2, 3, 4, 5, 6, 7,
    0, 1, 2, 3, 4, 5, 6, 7,
    0, 1, 2, 3, 4, 5, 6, 7,
&#125;;

// Index values of the rotated bitboard for attacks and move generation.
// This is the number of the slider part of the bitboard for use in slider_rl45_to_bitboard.
// The index is the square number on the normal board.
const byte index_of_rl45&#91;64&#93; =
&#123;
    7,  8,  9, 10, 11, 12, 13, 14,
    6,  7,  8,  9, 10, 11, 12, 13,
    5,  6,  7,  8,  9, 10, 11, 12,
    4,  5,  6,  7,  8,  9, 10, 11,
    3,  4,  5,  6,  7,  8,  9, 10,
    2,  3,  4,  5,  6,  7,  8,  9,
    1,  2,  3,  4,  5,  6,  7,  8,
    0,  1,  2,  3,  4,  5,  6,  7,
&#125;;

// Index values of the rotated bitboard for attacks and move generation.
// This is the number of the slider part of the bitboard for use in slider_rr45_to_bitboard.
// The index is the square number on the normal board.
const byte index_of_rr45&#91;64&#93; =
&#123;
    0,  1,  2,  3,  4,  5,  6,  7,
    1,  2,  3,  4,  5,  6,  7,  8,
    2,  3,  4,  5,  6,  7,  8,  9,
    3,  4,  5,  6,  7,  8,  9, 10,
    4,  5,  6,  7,  8,  9, 10, 11,
    5,  6,  7,  8,  9, 10, 11, 12,
    6,  7,  8,  9, 10, 11, 12, 13,
    7,  8,  9, 10, 11, 12, 13, 14,
&#125;;


/*******************************************************************/

/**
Put the scattered bits of an sliding attack pattern 
back to the original bitboard.
*/
Bitboard slider_rl90_to_bitboard&#91;8&#93;&#91;256&#93;;

/**
Put the scattered bits of an sliding attack pattern 
back to the original bitboard.
*/
Bitboard slider_rl45_to_bitboard&#91;15&#93;&#91;256&#93;;

/**
Put the scattered bits of an sliding attack pattern 
back to the original bitboard.
*/
Bitboard slider_rr45_to_bitboard&#91;15&#93;&#91;256&#93;;


/*******************************************************************/

/**
Set the rotated bitboards of all pieces
*/
void Board&#58;&#58;set_all_rotated_bitboards&#40;)
&#123;
    Bitboard pieces = wpieces_ | bpieces_;

    // Fill the bitboard rotated 90 degrees to the left.
    // b is in the rotated bitboard.
    // aa and a are in the original bitboard.
    all_rl90_ = 0;
    Bitboard aa;
    Bitboard a;
    Bitboard b = A8;
    for ( aa = H8; aa != NoSquare; aa.shift_l&#40;) )
    &#123;
        for ( a = aa; a != NoSquare; a.shift_d&#40;), b.shift_r&#40;) )
        &#123;
            all_rl90_ |= ( a & pieces ? b &#58; NoSquare );
        &#125;
    &#125;
    // Fill the bitboard rotated 45 degrees to the left.
    all_rl45_ = 0;
    b = A8;
    for ( aa = H8; aa != A8; aa <<= 1 )
    &#123;
        for ( a = aa; a != NoSquare && &#40;a & line_a&#41; == NoSquare; a.shift_dr&#40;), b.shift_r&#40;) )
        &#123;
            all_rl45_ |= &#40;a & pieces ? b &#58; 0&#41;;
        &#125;
    &#125;
    for ( a = A8; a != NoSquare; a.shift_dr&#40;), b.shift_r&#40;) )
    &#123;
        all_rl45_ |= &#40;a & pieces ? b &#58; 0&#41;;
    &#125;
    for ( aa = A7; aa != NoSquare; aa.shift_d&#40;) )
    &#123;
        for ( a = aa; a != NoSquare; a.shift_dr&#40;), b.shift_r&#40;) )
        &#123;
            all_rl45_ |= &#40;a & pieces ? b &#58; 0&#41;;
        &#125;
    &#125;
    // Fill the bitboard rotated 45 degrees to the right.
    all_rr45_ = 0;
    b = A8;
    for ( aa = A8; aa != A1; aa.shift_d&#40;) )
    &#123;
        for ( a = aa; a != NoSquare; a.shift_ur&#40;), b.shift_r&#40;) )
        &#123;
            all_rr45_ |= &#40;a & pieces ? b &#58; 0&#41;;
        &#125;
    &#125;
    for ( a = A1; a != A8; a.shift_ur&#40;), b.shift_r&#40;) )
    &#123;
        all_rr45_ |= &#40;a & pieces ? b &#58; 0&#41;;
    &#125;
    for ( aa = B1; aa != NoSquare; aa.shift_r&#40;) )
    &#123;
        for ( a = aa; &#40;a & line_a&#41; == NoSquare; a.shift_ur&#40;), b.shift_r&#40;) )
        &#123;
            all_rr45_ |= &#40;a & pieces ? b &#58; 0&#41;;
        &#125;
    &#125;
&#125;


/*******************************************************************/

/**
Prepare the slider attacks back transformation table.
Put the scattered bits of an sliding attack pattern 
back to the original bitboard.
*/
void Board&#58;&#58;init_slider_attacks_index&#40;)
&#123;
    // clear all
    Bitboard result = 0;
    int slider;
    for ( slider = 0; slider < 256; ++slider )
    &#123;
        int index;
        for ( index = 0; index < 15; ++index )
        &#123;
            if ( index < 8 )
                slider_rl90_to_bitboard&#91;index&#93;&#91;slider&#93; = 0;
            slider_rl45_to_bitboard&#91;index&#93;&#91;slider&#93; = 0;
            slider_rr45_to_bitboard&#91;index&#93;&#91;slider&#93; = 0;
        &#125;
    &#125;

    // Bitboard slider_rl90_to_bitboard&#91;8&#93;&#91;256&#93;;
    byte sq;
    for ( sq = 0; sq < 64; ++sq )
    &#123;
        result = result.set_one_bit&#40;sq&#41;; 
        byte shift = shift_of_rl90&#91;sq&#93;;
        byte pos = normal_to_rl90&#91;sq&#93; - shift;
        byte index = index_of_rl90&#91;sq&#93;;
        for ( slider = 0; slider < 256; ++slider )
        &#123;
            int testbit = 1 << pos;
            if ( slider & testbit )
                slider_rl90_to_bitboard&#91;index&#93;&#91;slider&#93; |= result;
        &#125;
    &#125;
    // Bitboard slider_rl45_to_bitboard&#91;15&#93;&#91;256&#93;;
    for ( sq = 0; sq < 64; ++sq )
    &#123;
        result = result.set_one_bit&#40;sq&#41;; 
        byte shift = shift_of_rl45&#91;sq&#93;;
        byte pos = normal_to_rl45&#91;sq&#93; - shift;
        byte mask = mask_of_rl45&#91;sq&#93;;
        byte index = index_of_rl45&#91;sq&#93;;
        for ( slider = 0; slider < 256; ++slider )
        &#123;
            if ( slider > mask )
                break;
            int testbit = 1 << pos;
            if ( slider & mask & testbit )
                slider_rl45_to_bitboard&#91;index&#93;&#91;slider&#93; |= result;
        &#125;
    &#125;
    // Bitboard slider_rr45_to_bitboard&#91;15&#93;&#91;256&#93;;
    for ( sq = 0; sq < 64; ++sq )
    &#123;
        result = result.set_one_bit&#40;sq&#41;; 
        byte shift = shift_of_rr45&#91;sq&#93;;
        byte pos = normal_to_rr45&#91;sq&#93; - shift;
        byte mask = mask_of_rr45&#91;sq&#93;;
        byte index = index_of_rr45&#91;sq&#93;;
        for ( slider = 0; slider < 256; ++slider )
        &#123;
            if ( slider > mask )
                break;
            int testbit = 1 << pos;
            if ( slider & mask & testbit )
                slider_rr45_to_bitboard&#91;index&#93;&#91;slider&#93; |= result;
        &#125;
    &#125;
&#125;


/*******************************************************************/

/**
Get a bitboard with all positions set to 1 which can be attacked 
from a bishop, rook or queen on the square moving in the direction.
*/
Bitboard Board&#58;&#58;direction_attacks&#40; byte square, byte dir ) const
&#123;
    Bitboard result;
    Bitboard bb;
    byte shift;
    byte pattern;
    byte pos;
    byte slider;
    byte mask;
    byte index;

    // 4 3 2
    // 5 0 1
    // 6 7 8
    switch ( dir )
    &#123;
      case 1&#58;
        // normal bitboard
        bb = wpieces_ | bpieces_;
        shift = square & 0xf8;
        bb >>= &#40;shift + 1&#41;;
        pattern = bb;
        pos = square - shift;
        slider = slider_attacks&#91;pattern & 0x3f&#93;&#91;pos&#93;;
        slider &= &#40;1 << pos&#41; - 1;
        result = slider;
        result <<= shift;
        break;
      case 5&#58;
        // normal bitboard
        bb = wpieces_ | bpieces_;
        shift = square & 0xf8;
        bb >>= &#40;shift + 1&#41;;
        pattern = bb;
        pos = square - shift;
        slider = slider_attacks&#91;pattern & 0x3f&#93;&#91;pos&#93;;
        slider &= ~(&#40;1 << pos&#41; - 1&#41;;
        result = slider;
        result <<= shift;
        break;
      case 7&#58;
        // rotated rl90 bitboard
        bb = all_rl90_;
        shift = shift_of_rl90&#91;square&#93;;
        bb >>= &#40;shift + 1&#41;;
        pattern = bb;
        pos = normal_to_rl90&#91;square&#93; - shift;
        slider = slider_attacks&#91;pattern & 0x3f&#93;&#91;pos&#93;;
        slider &= &#40;1 << pos&#41; - 1;
        index = index_of_rl90&#91;square&#93;;
        bb = slider_rl90_to_bitboard&#91;index&#93;&#91;slider&#93;;
        result = bb;
        break;
      case 3&#58;
        // rotated rl90 bitboard
        bb = all_rl90_;
        shift = shift_of_rl90&#91;square&#93;;
        bb >>= &#40;shift + 1&#41;;
        pattern = bb;
        pos = normal_to_rl90&#91;square&#93; - shift;
        slider = slider_attacks&#91;pattern & 0x3f&#93;&#91;pos&#93;;
        slider &= ~(&#40;1 << pos&#41; - 1&#41;;
        index = index_of_rl90&#91;square&#93;;
        bb = slider_rl90_to_bitboard&#91;index&#93;&#91;slider&#93;;
        result = bb;
        break;
      case 8&#58;
        // rotated rl45 bitboard
        bb = all_rl45_;
        shift = shift_of_rl45&#91;square&#93;;
        bb >>= &#40;shift + 1&#41;;
        pattern = bb;
        pos = normal_to_rl45&#91;square&#93; - shift;
        slider = slider_attacks&#91;pattern & 0x3f&#93;&#91;pos&#93;;
        mask = mask_of_rl45&#91;square&#93;;
        slider &= mask;
        slider &= &#40;1 << pos&#41; - 1;
        index = index_of_rl45&#91;square&#93;;
        bb = slider_rl45_to_bitboard&#91;index&#93;&#91;slider&#93;;
        result = bb;
        break;
      case 4&#58;
        // rotated rl45 bitboard
        bb = all_rl45_;
        shift = shift_of_rl45&#91;square&#93;;
        bb >>= &#40;shift + 1&#41;;
        pattern = bb;
        pos = normal_to_rl45&#91;square&#93; - shift;
        slider = slider_attacks&#91;pattern & 0x3f&#93;&#91;pos&#93;;
        mask = mask_of_rl45&#91;square&#93;;
        slider &= mask;
        slider &= ~(&#40;1 << pos&#41; - 1&#41;;
        index = index_of_rl45&#91;square&#93;;
        bb = slider_rl45_to_bitboard&#91;index&#93;&#91;slider&#93;;
        result = bb;
        break;
      case 2&#58;
        // rotated rr45 bitboard
        bb = all_rr45_;
        shift = shift_of_rr45&#91;square&#93;;
        bb >>= &#40;shift + 1&#41;;
        pattern = bb;
        pos = normal_to_rr45&#91;square&#93; - shift;
        slider = slider_attacks&#91;pattern & 0x3f&#93;&#91;pos&#93;;
        mask = mask_of_rr45&#91;square&#93;;
        slider &= mask;
        slider &= &#40;1 << pos&#41; - 1;
        index = index_of_rr45&#91;square&#93;;
        bb = slider_rr45_to_bitboard&#91;index&#93;&#91;slider&#93;;
        result = bb;
        break;
      case 6&#58;
        // rotated rr45 bitboard
        bb = all_rr45_;
        shift = shift_of_rr45&#91;square&#93;;
        bb >>= &#40;shift + 1&#41;;
        pattern = bb;
        pos = normal_to_rr45&#91;square&#93; - shift;
        slider = slider_attacks&#91;pattern & 0x3f&#93;&#91;pos&#93;;
        mask = mask_of_rr45&#91;square&#93;;
        slider &= mask;
        slider &= ~(&#40;1 << pos&#41; - 1&#41;;
        index = index_of_rr45&#91;square&#93;;
        bb = slider_rr45_to_bitboard&#91;index&#93;&#91;slider&#93;;
        result = bb;
        break;
      default&#58;
        result = 0;
        break;
    &#125;

    return result;
&#125;


/*******************************************************************/

/**
Get a bitboard with all positions set to 1 which can be attacked 
from a rook or queen on the square.
*/
Bitboard Board&#58;&#58;orthogonal_attacks&#40; byte square ) const
&#123;
    Bitboard result;

    // normal bitboard
    Bitboard bb = wpieces_ | bpieces_;
    byte shift = square & 0xf8;
    bb >>= &#40;shift + 1&#41;;
    byte pattern = bb;
    byte pos = square - shift;
    byte slider = slider_attacks&#91;pattern & 0x3f&#93;&#91;pos&#93;;
    result = slider;
    result <<= shift;

    // rotated rl90 bitboard
    bb = all_rl90_;
    shift = shift_of_rl90&#91;square&#93;;
    bb >>= &#40;shift + 1&#41;;
    pattern = bb;
    pos = normal_to_rl90&#91;square&#93; - shift;
    slider = slider_attacks&#91;pattern & 0x3f&#93;&#91;pos&#93;;
    byte index = index_of_rl90&#91;square&#93;;
    bb = slider_rl90_to_bitboard&#91;index&#93;&#91;slider&#93;;
    result |= bb;

    return result;
&#125;


/*******************************************************************/

/**
Get a bitboard with all positions set to 1 which can be attacked 
from a bishop or queen on the square.
*/
Bitboard Board&#58;&#58;diagonal_attacks&#40; byte square ) const
&#123;
    Bitboard result;

    // rotated rl45 bitboard
    Bitboard bb = all_rl45_;
    byte shift = shift_of_rl45&#91;square&#93;;
    bb >>= &#40;shift + 1&#41;;
    byte pattern = bb;
    byte pos = normal_to_rl45&#91;square&#93; - shift;
    byte slider = slider_attacks&#91;pattern & 0x3f&#93;&#91;pos&#93;;
    byte mask = mask_of_rl45&#91;square&#93;;
    slider &= mask;
    byte index = index_of_rl45&#91;square&#93;;
    bb = slider_rl45_to_bitboard&#91;index&#93;&#91;slider&#93;;
    result = bb;

    // rotated rr45 bitboard
    bb = all_rr45_;
    shift = shift_of_rr45&#91;square&#93;;
    bb >>= &#40;shift + 1&#41;;
    pattern = bb;
    pos = normal_to_rr45&#91;square&#93; - shift;
    slider = slider_attacks&#91;pattern & 0x3f&#93;&#91;pos&#93;;
    mask = mask_of_rr45&#91;square&#93;;
    slider &= mask;
    index = index_of_rr45&#91;square&#93;;
    bb = slider_rr45_to_bitboard&#91;index&#93;&#91;slider&#93;;
    result |= bb;

    return result;
&#125;


/*******************************************************************/

#endif // USE_ROTATED_BITBOARDS&#40;)

Post Reply