shakmaty/
zobrist.rs

1//! Zobrist hashing for positions.
2//!
3//! # Stability
4//!
5//! The Zobrist hash for each position is guaranteed to be stable. Changing
6//! hash values is considered a semver breaking change and will be noted in the
7//! changelog.
8//!
9//! # Warning: Forged collisions
10//!
11//! Zobrist hashes have excellent collision resistance, but can be
12//! forged efficiently.
13//!
14//! # Examples
15//!
16//! ```
17//! use shakmaty::{Chess, EnPassantMode, Position, zobrist::Zobrist64};
18//!
19//! let pos = Chess::default();
20//! assert_eq!(pos.zobrist_hash::<Zobrist64>(EnPassantMode::Legal), Zobrist64(0x463b96181691fc9c));
21//! ```
22
23use core::{
24    fmt,
25    hash::{Hash, Hasher},
26    ops::{BitXor, BitXorAssign},
27};
28
29use crate::{
30    Board, ByCastlingSide, ByColor, ByRole, CastlingSide, Color, File, Piece, RemainingChecks,
31    Role, Square,
32};
33
34/// Integer type that can be returned as a Zobrist hash.
35pub trait ZobristValue: BitXorAssign + Default + Copy {
36    fn zobrist_for_piece(square: Square, piece: Piece) -> Self;
37    fn zobrist_for_white_turn() -> Self;
38    fn zobrist_for_castling_right(color: Color, side: CastlingSide) -> Self;
39    fn zobrist_for_en_passant_file(file: File) -> Self;
40    fn zobrist_for_remaining_checks(color: Color, remaining: RemainingChecks) -> Self;
41    fn zobrist_for_promoted(square: Square) -> Self;
42    fn zobrist_for_pocket(color: Color, role: Role, pieces: u8) -> Self;
43}
44
45macro_rules! zobrist_value_impl {
46    ($t:ident, $proxy:ty, $bits:literal) => {
47        #[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
48        #[doc = "A [`ZobristValue`] with "]
49        #[doc = stringify!($bits)]
50        #[doc = " bits."]
51        #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
52        pub struct $t(pub $proxy);
53
54        impl From<$proxy> for $t {
55            #[inline]
56            fn from(value: $proxy) -> $t {
57                $t(value)
58            }
59        }
60        impl From<$t> for $proxy {
61            #[inline]
62            fn from(value: $t) -> $proxy {
63                value.0
64            }
65        }
66
67        impl BitXor for $t {
68            type Output = $t;
69            #[inline]
70            fn bitxor(self, other: $t) -> $t {
71                $t(self.0 ^ other.0)
72            }
73        }
74        impl BitXor<&$t> for $t {
75            type Output = $t;
76            #[inline]
77            fn bitxor(self, other: &$t) -> $t {
78                $t(self.0 ^ other.0)
79            }
80        }
81        impl BitXor<&$t> for &$t {
82            type Output = $t;
83            #[inline]
84            fn bitxor(self, other: &$t) -> $t {
85                $t(self.0 ^ other.0)
86            }
87        }
88        impl BitXor<$t> for &$t {
89            type Output = $t;
90            #[inline]
91            fn bitxor(self, other: $t) -> $t {
92                $t(self.0 ^ other.0)
93            }
94        }
95        impl BitXorAssign for $t {
96            #[inline]
97            fn bitxor_assign(&mut self, rhs: $t) {
98                self.0 ^= rhs.0;
99            }
100        }
101        impl BitXorAssign<&$t> for $t {
102            #[inline]
103            fn bitxor_assign(&mut self, rhs: &$t) {
104                self.0 ^= rhs.0;
105            }
106        }
107
108        impl fmt::Debug for $t {
109            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110                write!(f, concat!(stringify!($t), "({:#x})"), self.0)
111            }
112        }
113        impl fmt::UpperHex for $t {
114            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115                fmt::UpperHex::fmt(&self.0, f)
116            }
117        }
118        impl fmt::LowerHex for $t {
119            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120                fmt::LowerHex::fmt(&self.0, f)
121            }
122        }
123        impl fmt::Octal for $t {
124            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125                fmt::Octal::fmt(&self.0, f)
126            }
127        }
128        impl fmt::Binary for $t {
129            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130                fmt::Binary::fmt(&self.0, f)
131            }
132        }
133
134        impl ZobristValue for $t {
135            #[inline]
136            fn zobrist_for_piece(square: Square, piece: Piece) -> $t {
137                #[allow(overflowing_literals)]
138                static PIECE_MASKS: ByColor<ByRole<[$proxy; 64]>> = ByColor {
139                    black: ByRole {
140                        pawn: [
141                            0x52b3_75aa_7c0d_7bac_9d39_247e_3377_6d41,
142                            0x208d_169a_534f_2cf5_2af7_3980_05aa_a5c7,
143                            0x8981_5137_22b4_7f24_44db_0150_2462_3547,
144                            0x09b8_f20f_910a_8ff7_9c15_f73e_62a7_6ae2,
145                            0x0b8e_a702_5520_9cc0_7583_4465_489c_0c89,
146                            0xa688_a979_1f02_7500_3290_ac3a_2030_01bf,
147                            0x19b8_8b8f_faed_8f55_0fbb_ad1f_6104_2279,
148                            0x88bf_7822_d00d_5526_e83a_908f_f2fb_60ca,
149                            0xdb7b_f62a_b390_b71b_0d7e_765d_5875_5c10,
150                            0x33a6_ac1d_85c9_f22f_1a08_3822_ceaf_e02d,
151                            0x55ab_2a27_271d_42ac_9605_d5f0_e25e_c3b0,
152                            0x40a2_1ff9_c803_fca4_d021_ff5c_d13a_2ed5,
153                            0x3c16_9aeb_80a1_d5d2_40bd_f15d_4a67_2e32,
154                            0x8768_4e27_293e_cf96_0113_5514_6fd5_6395,
155                            0xf8b9_1b39_d4c6_997c_5db4_8320_46f3_d9e5,
156                            0x1d5f_744f_312f_d467_239f_8b2d_7ff7_19cc,
157                            0xeda1_8c45_2d5d_e5b4_05d1_a1ae_85b4_9aa1,
158                            0x7497_db88_8ecc_da0f_679f_848f_6e8f_c971,
159                            0x94c1_bb70_1674_9887_7449_bbff_801f_ed0b,
160                            0x35b2_3d66_3606_fde2_7d11_cdb1_c3b7_adf0,
161                            0x17b4_ae80_b818_4845_82c7_709e_781e_b7cc,
162                            0x8bd9_8922_a308_9d8e_f321_8f1c_9510_786c,
163                            0xfec7_7fb0_7cea_5e84_3314_78f3_af51_bbe6,
164                            0xe153_a54d_23c9_3a8a_4bb3_8de5_e721_9443,
165                            0xa196_fa76_c244_05eb_aa64_9c6e_bcfd_50fc,
166                            0x6f33_3e11_d079_240a_8dbd_98a3_52af_d40b,
167                            0x23b8_d480_df5b_b521_87d2_074b_81d7_9217,
168                            0x634a_daec_002b_3000_19f3_c751_d3e9_2ae1,
169                            0x3d0e_41d6_5872_d549_b4ab_30f0_62b1_9abf,
170                            0x5aba_8390_8462_b892_7b05_00ac_4204_7ac4,
171                            0x2645_7864_aff2_88af_c945_2ca8_1a09_d85d,
172                            0x43f1_0561_015d_a64e_24aa_6c51_4da2_7500,
173                            0x545c_c628_5df4_2807_4c9f_3442_7501_b447,
174                            0xa714_0dc7_b82e_96ef_14a6_8fd7_3c91_0841,
175                            0xb1dc_adc8_fe30_a8d4_a71b_9b83_461c_bd93,
176                            0x72eb_d048_ba37_3ac4_0348_8b95_b0f1_850f,
177                            0x2eb0_ddf1_351a_1adb_637b_2b34_ff93_c040,
178                            0x9cdc_8c44_a201_836d_09d1_bc9a_3dd9_0a94,
179                            0x0afc_1fb4_5a72_8973_3575_6683_34a1_dd3b,
180                            0x58c8_fa41_5b96_ec95_735e_2b97_a4c4_5a23,
181                            0x497a_9b9a_7f9f_8872_1872_7070_f1bd_400b,
182                            0xbff8_4079_9ee0_5fdf_1fcb_acd2_59bf_02e7,
183                            0xe4ec_1554_316c_2704_d310_a7c2_ce9b_6555,
184                            0x3c9f_0c8b_89f3_1f3e_bf98_3fe0_fe5d_8244,
185                            0x4a60_1b99_475b_af4e_9f74_d14f_7454_a824,
186                            0x6c65_e138_6536_c3a9_51eb_dc4a_b9ba_3035,
187                            0xb60a_571d_59e8_a485_5c82_c505_db9a_b0fa,
188                            0xe23c_5d70_4569_6d85_fcf7_fe8a_3430_b241,
189                            0xc9d4_d61b_569e_c607_3253_a729_b9ba_3dde,
190                            0xce9e_d71a_6d18_deb2_8c74_c368_081b_3075,
191                            0x2dbc_1655_9bdb_a870_b9bc_6c87_167c_33e7,
192                            0x50cd_a533_9d83_6c83_7ef4_8f2b_8302_4e20,
193                            0x9809_1ef4_f2ab_1ed3_11d5_05d4_c351_bd7f,
194                            0xf580_3ac1_7fc4_5ecf_6568_fca9_2c76_a243,
195                            0x0973_0ef1_5a78_c687_4de0_b0f4_0f32_a7b8,
196                            0xf8bb_209d_715a_b566_96d6_9346_0cc3_7e5d,
197                            0x0c5b_201d_6cb8_9a50_42e2_40cb_6368_9f2f,
198                            0x5257_1fbf_abb4_a367_6d2b_dcda_e291_9661,
199                            0x1b1d_b822_6989_0861_4288_0b02_36e4_d951,
200                            0x9423_f70e_d512_f1ea_5f0f_4a58_9817_1bb6,
201                            0x79e4_48c7_2183_e2a5_39f8_90f5_79f9_2f88,
202                            0x3c88_a0cf_5b85_2900_93c5_b5f4_7356_388b,
203                            0x9e12_f819_acaa_6653_63dc_359d_8d23_1b78,
204                            0xc6f0_9266_299a_5902_ec16_ca8a_ea98_ad76,
205                        ],
206                        knight: [
207                            0x6a07_7209_3f97_e152_5643_6c9f_e1a1_aa8d,
208                            0xfa76_d367_19e7_e5e3_efac_4b70_633b_8f81,
209                            0x2e79_9233_a544_062a_bb21_5798_d45d_f7af,
210                            0xe003_4511_44a0_3be8_45f2_0042_f24f_1768,
211                            0x974d_8f4e_e692_ed35_930f_80f4_e8eb_7462,
212                            0xd30a_fadf_c4dc_52f5_ff67_12ff_cfd7_5ea1,
213                            0x278d_de02_bf30_c1da_ae62_3fd6_7468_aa70,
214                            0x8b7e_3a2b_f5a0_61a3_dd2c_5bc8_4bc8_d8fc,
215                            0xd144_3752_e511_a579_7eed_120d_54cf_2dd9,
216                            0xd1b0_2672_a0ec_44cf_22fe_5454_0116_5f1c,
217                            0xba30_05c8_5125_14f1_c918_00e9_8fb9_9929,
218                            0x2e3b_8621_1f6b_4295_808b_d68e_6ac1_0365,
219                            0x0574_31bf_eaa9_d6f5_dec4_6814_5b76_05f6,
220                            0xa348_ddd6_6378_afaf_1bed_e3a3_aef5_3302,
221                            0x4a18_1777_5b08_6ce1_4353_9603_d6c5_5602,
222                            0x184b_1c98_3a6a_1a77_aa96_9b5c_691c_cb7a,
223                            0xcb70_392e_7b7d_b185_a878_32d3_92ef_ee56,
224                            0x3b1b_1166_a648_330e_6594_2c7b_3c7e_11ae,
225                            0xe520_1b15_5f51_cc30_ded2_d633_cad0_04f6,
226                            0x4d05_3ee8_65f2_1b96_21f0_8570_f420_e565,
227                            0xd8d8_062e_343d_9c66_b415_938d_7da9_4e3c,
228                            0x1350_7b31_a966_da7d_91b8_59e5_9ecb_6350,
229                            0xd637_536d_2e7a_58b0_10cf_f333_e0ed_804a,
230                            0xcbca_e035_eab8_24a0_28ae_d140_be0b_b7dd,
231                            0x8c77_fe1e_1b06_691b_c5cc_1d89_724f_a456,
232                            0xfd78_41ed_1ab4_b961_5648_f680_f11a_2741,
233                            0xcaa8_8da0_1766_9d53_2d25_5069_f0b7_dab3,
234                            0xabda_5baf_650b_3675_9bc5_a38e_f729_abd4,
235                            0xfe14_d0c6_b8f1_1e97_ef2f_0543_08f6_a2bc,
236                            0xc134_23f8_1c4b_9adf_af20_42f5_cc5c_2858,
237                            0x3450_7a35_0393_5243_4804_12ba_b7f5_be2a,
238                            0xec50_4bd0_c7ae_79a1_aef3_af4a_563d_fe43,
239                            0x0bc7_61ea_4004_d2ae_19af_e59a_e451_497f,
240                            0x3a07_4807_8a78_fd4d_5259_3803_dff1_e840,
241                            0xc5f3_6bde_8caa_93fe_f4f0_76e6_5f2c_e6f0,
242                            0x5b22_99dc_4408_0278_1137_9625_747d_5af3,
243                            0x3f99_cbeb_6ec6_53fa_bce5_d224_8682_c115,
244                            0x48eb_cfc0_04b5_24ca_9da4_243d_e836_994f,
245                            0xd227_8829_cd34_4d05_066f_70b3_3fe0_9017,
246                            0x5fe6_37e5_8fc1_c0f3_4dc4_de18_9b67_1a1c,
247                            0x0a4b_136f_25a6_5a32_5103_9ab7_7124_57c3,
248                            0x4119_314b_520d_04d9_c07a_3f80_c31f_b4b4,
249                            0x5354_a8b0_8947_cc8e_b46e_e9c5_e64a_6e7c,
250                            0x6001_d6a9_4517_300b_b381_9a42_abe6_1c87,
251                            0x1459_7a07_4f13_3855_21a0_0793_3a52_2a20,
252                            0xdc9a_6baf_92ff_de03_2df1_6f76_1598_aa4f,
253                            0xc5cb_c527_0de9_86b0_763c_4a13_71b3_68fd,
254                            0x95c7_2d49_bd75_60be_f793_c467_02e0_86a0,
255                            0x12b4_37e4_c286_737a_d728_8e01_2aeb_8d31,
256                            0xaa7c_6f89_f144_2c5d_de33_6a2a_4bc1_c44b,
257                            0x1a3e_bbf3_17bf_c4d8_0bf6_92b3_8d07_9f23,
258                            0x4ad3_c9fa_863a_5aa3_2c60_4a7a_1773_26b3,
259                            0xc7c9_4147_de66_3b5b_4850_e73e_03eb_6064,
260                            0x840e_7fe4_b35d_4a4b_cfc4_47f1_e53c_8e1b,
261                            0x8921_1091_26e2_3341_b05c_a3f5_6426_8d99,
262                            0xa18a_4f12_c127_de17_9ae1_82c8_bc94_74e8,
263                            0x4719_73e4_dc6e_fb4b_a4fc_4bd4_fc55_58ca,
264                            0xc723_867b_98d0_7330_e755_178d_58fc_4e76,
265                            0xf5fc_c6de_3509_50d1_69b9_7db1_a4c0_3dfe,
266                            0xb909_13e0_2bde_576a_f9b5_b7c4_acc6_7c96,
267                            0x5554_c92f_272b_73c5_fc6a_82d6_4b86_55fb,
268                            0x3738_a3f0_fdf5_d9c6_9c68_4cb6_c4d2_4417,
269                            0x3771_f25e_5e27_8ee3_8ec9_7d29_1745_6ed0,
270                            0xa9d5_8a81_2b10_906e_6703_df9d_2924_e97e,
271                        ],
272                        bishop: [
273                            0x1497_56bc_2136_8632_7f9b_6af1_ebf7_8baf,
274                            0x25c8_0f32_3a51_6eaa_5862_7e1a_149b_ba21,
275                            0x3ea0_39f7_ff28_ae8e_2cd1_6e2a_bd79_1e33,
276                            0x0caf_481f_4006_3dd8_d363_eff5_f097_7996,
277                            0xbce2_3e10_6b1e_efd7_0ce2_a38c_344a_6eed,
278                            0x1085_3ea8_2a5c_cb34_1a80_4aad_b9cf_a741,
279                            0xe7c7_6ac3_dbbf_8c8c_907f_3042_1d78_c5de,
280                            0x1624_c0ce_1532_313d_501f_65ed_b303_4d07,
281                            0x5f38_95b2_5d7b_4744_3762_4ae5_a48f_a6e9,
282                            0xfbe3_63cb_b55a_913e_957b_af61_700c_ff4e,
283                            0x3585_0e8f_6340_0ddd_3a6c_2793_4e31_188a,
284                            0x3d30_0047_b5dd_de66_d495_0353_6abc_a345,
285                            0x1c1c_7ca8_b338_6353_088e_0495_89c4_32e0,
286                            0x986e_c52a_c2c8_8cec_f943_aee7_febf_21b8,
287                            0xc93b_616a_554d_23c8_6c3b_8e3e_3361_39d3,
288                            0x211d_7b57_59da_7504_364f_6ffa_464e_e52e,
289                            0xf266_3fc5_9b54_1585_d60f_6dce_dc31_4222,
290                            0xf57f_efea_db21_b029_5696_3b0d_ca41_8fc0,
291                            0x30fd_60d9_ee26_0966_16f5_0edf_91e5_13af,
292                            0x3c29_da00_0d5b_9a08_ef19_5591_4b60_9f93,
293                            0xd0d6_203f_a69d_a0ba_5656_01c0_364e_3228,
294                            0x8167_e4bd_87c6_f05e_ecb5_3939_887e_8175,
295                            0x5c06_3405_c62f_8154_bac7_a9a1_8531_294b,
296                            0xb86f_e57d_5308_1fe6_b344_c470_397b_ba52,
297                            0xeb60_ad08_0cd5_73fe_65d3_4954_daf3_cebd,
298                            0xbfbb_b416_0263_5b78_b4b8_1b3f_a975_11e2,
299                            0x4e39_d536_b723_213c_b422_0611_93d6_f6a7,
300                            0x56d7_e046_8df1_5a47_0715_8240_1c38_434d,
301                            0x9e60_1537_348e_d732_7a13_f18b_bedc_4ff5,
302                            0xee2e_827d_9faa_74c1_bc40_97b1_16c5_24d2,
303                            0xe433_02e0_d517_a316_59b9_7885_e2f2_ea28,
304                            0xf662_e9ba_781a_1fae_9917_0a5d_c311_5544,
305                            0xe83d_a2ef_ce44_2856_6f42_3357_e7c6_a9f9,
306                            0x143a_e097_749a_513a_3259_28ee_6e6f_8794,
307                            0xa203_386e_6a86_f7c7_d0e4_3662_28b0_3343,
308                            0x7390_5f8c_5056_ecee_565c_31f7_de89_ea27,
309                            0x0da0_7ce4_4c01_42e4_30f5_6114_8411_9414,
310                            0x8b9e_9700_3ef0_1d2e_d873_db39_1292_ed4f,
311                            0xd8c6_66a6_6584_0842_7bd9_4e1d_8e17_debc,
312                            0x8bb1_069b_ba16_9263_c7d9_f168_64a7_6e94,
313                            0x6bdc_866d_7daa_19dc_947a_e053_ee56_e63c,
314                            0xe111_5bb3_f8ad_0cfe_c8c9_3882_f947_5f5f,
315                            0x0859_ae34_a51e_d77c_3a9b_f55b_a91f_81ca,
316                            0xf1d7_3663_c53a_0156_d9a1_1fbb_3d98_08e4,
317                            0x6692_83df_212c_93db_0fd2_2063_edc2_9fca,
318                            0x7489_abc0_8bd4_db15_b3f2_56d8_aca0_b0b9,
319                            0xf9d2_b26d_0375_aab0_b030_31a8_b451_6e84,
320                            0xde48_56e7_777e_27d1_35dd_37d5_8714_48af,
321                            0x2cae_af61_386f_a1f2_e9f6_082b_0554_2e4e,
322                            0x7c6d_4b00_383f_052a_ebfa_fa33_d725_4b59,
323                            0xb194_3df6_ea36_87ff_9255_abb5_0d53_2280,
324                            0x7e4d_1bac_a94d_a20d_b9ab_4ce5_7f2d_34f3,
325                            0x38d1_a6b6_448f_dc40_6935_01d6_2829_7551,
326                            0x8aed_5305_1756_d212_c62c_58f9_7dd9_49bf,
327                            0x1805_fa74_82c6_0f4e_cd45_4f8f_19c5_126a,
328                            0x24c9_891c_2f4d_b0b1_bbe8_3f4e_cc2b_decb,
329                            0xbb70_3190_b30e_b664_dc84_2b7e_2819_e230,
330                            0xb52f_857f_41e6_8fce_ba89_142e_0075_03b8,
331                            0xeb5a_7a71_4d4e_c1a1_a3bc_941d_0a50_61cb,
332                            0xc413_34a3_6d42_11ea_e9f6_760e_32cd_8021,
333                            0xe601_88ec_b537_010d_09c7_e552_bc76_492f,
334                            0xff67_dd93_2e57_55cc_852f_5493_4da5_5cc9,
335                            0x14c9_2be5_5246_7cfb_8107_fccf_064f_cf56,
336                            0xc94f_b8ea_e42b_3453_0989_54d5_1fff_6580,
337                        ],
338                        rook: [
339                            0x2bb2_c23c_899c_bc9e_da3a_361b_1c51_57b1,
340                            0xbfb0_766d_2652_6dbf_dcdd_7d20_903d_0c25,
341                            0x166d_bdc3_8309_e26b_3683_3336_d068_f707,
342                            0x6796_f7e1_1a4c_3cba_ce68_341f_7989_3389,
343                            0x562c_093e_14a8_7ff2_ab90_9016_8dd0_5f34,
344                            0x3627_e637_e241_3092_4395_4b32_52dc_25e5,
345                            0x2404_1470_2e63_067a_b438_c2b6_7f98_e5e9,
346                            0xa6f6_3494_f774_323c_10dc_d78e_3851_a492,
347                            0xc19e_a801_fb34_4afb_dbc2_7ab5_4478_22bf,
348                            0x9d18_e8c2_1a6c_8c61_9b3c_db65_f82c_a382,
349                            0x87f9_503f_9fde_d941_b67b_7896_167b_4c84,
350                            0x3e50_98f6_27c4_ed6c_bfce_d1b0_048e_ac50,
351                            0x6eb0_6344_3f58_c2ae_a911_9b60_369f_febd,
352                            0x3427_2006_16f6_5462_1fff_7ac8_0904_bf45,
353                            0xe3b7_4fe5_5c76_691f_ac12_fb17_1817_eee7,
354                            0xd631_6d50_08f9_32ec_af08_da91_77dd_a93d,
355                            0x35a0_d4ca_7416_842f_1b0c_ab93_6e65_c744,
356                            0xde46_8328_6c56_072d_b559_eb1d_04e5_e932,
357                            0x1587_5465_7dc0_f21d_c37b_45b3_f8d6_f2ba,
358                            0x6d80_8b47_2208_eab2_c3a9_dc22_8caa_c9e9,
359                            0xcb20_8f7c_937f_44e6_f3b8_b667_5a65_07ff,
360                            0xdff1_dc38_532c_3a2e_9fc4_77de_4ed6_81da,
361                            0x64ee_6958_558a_5d83_6737_8d8e_ccef_96cb,
362                            0xf103_b408_d124_5a6d_6dd8_56d9_4d25_9236,
363                            0xa1f1_9c51_8c3e_0b41_a319_ce15_b0b4_db31,
364                            0x48f0_c2ff_4281_9bfd_0739_7375_1f12_dd5e,
365                            0x1472_ba92_5a4c_6123_8a8e_849e_b327_81a5,
366                            0xe3b7_5066_0989_609a_e192_5c71_2852_79f5,
367                            0x6dd7_60ab_49ed_7373_74c0_4bf1_790c_0efe,
368                            0x6792_6c59_3a78_bcaa_4dda_4815_3c94_938a,
369                            0x5978_ff00_9a18_007c_9d26_6d6a_1cc0_542c,
370                            0x5568_e6bf_328b_448e_7440_fb81_6508_c4fe,
371                            0x7cc9_0fbe_d116_5f2b_1332_8503_df48_229f,
372                            0x156f_28d7_28f9_7cba_d6bf_7bae_e43c_ac40,
373                            0x2edf_603e_c74b_4900_4838_d65f_6ef6_748f,
374                            0xd48f_2990_33fa_9c9a_1e15_2328_f331_8dea,
375                            0x5437_5176_6a18_d326_8f84_19a3_48f2_96bf,
376                            0x04f2_5bdd_180f_31cb_72c8_834a_5957_b511,
377                            0xc66a_3569_f903_b0dc_d7a0_23a7_3260_b45c,
378                            0xce61_b42c_7eea_d35c_94eb_c8ab_cfb5_6dae,
379                            0xa705_d681_44ca_af00_9fc1_0d0f_9899_93e0,
380                            0x3371_ede2_9684_98fb_de68_a235_5b93_cae6,
381                            0x1c0c_9a22_0f8f_bf8a_a44c_fe79_ae53_8bbe,
382                            0x6631_fc26_158f_aebd_9d1d_84fc_ce37_1425,
383                            0xef0e_c337_ff2a_ef59_51d2_b1ab_2ddf_b636,
384                            0xc979_ef82_43e7_1d7a_2fd7_e4b9_e72c_d38c,
385                            0xd6c1_a706_01c9_1112_65ca_5b96_b755_2210,
386                            0xf3a1_da18_6614_1057_dd69_a0d8_ab3b_546d,
387                            0xd3e2_b4c6_98f2_a99e_604d_51b2_5fbf_70e2,
388                            0x1b4f_5d57_60ac_5121_73aa_8a56_4fb7_ac9e,
389                            0x27d0_b28f_28e7_d0ef_1a8c_1e99_2b94_1148,
390                            0xf3a2_d309_d1e7_2bc0_aac4_0a27_03d9_bea0,
391                            0x1294_c73b_3f91_4dda_764d_beae_7fa4_f3a6,
392                            0x56da_b15d_c8b3_fc48_1e99_b96e_70a9_be8b,
393                            0x5b77_d320_2095_d45c_2c5e_9deb_57ef_4743,
394                            0xe0d3_17e2_6a17_ae47_3a93_8fee_32d2_9981,
395                            0x5b1d_671e_1706_9897_26e6_db8f_fdf5_adfe,
396                            0x937d_c438_ef99_030b_4693_56c5_04ec_9f9d,
397                            0xce09_ea57_087e_bea9_c876_3c5b_08d1_908c,
398                            0xd0d8_fac3_d4cf_a048_3f6c_6af8_59d8_0055,
399                            0x27a5_8868_62d5_6b94_7f7c_c394_20a3_a545,
400                            0x5916_7366_1c00_d80b_9bfb_227e_bdf4_c5ce,
401                            0xd1cc_44ae_71a9_791d_8903_9d79_d6fc_5c5c,
402                            0xdf5a_715a_da20_9d36_8fe8_8b57_305e_2ab6,
403                        ],
404                        queen: [
405                            0xddf7_d6c0_8847_b906_001f_837c_c735_0524,
406                            0x76a4_f4c4_bd5b_4dc4_1877_b51e_57a7_64d5,
407                            0xde91_6ef3_cda0_4b7a_a285_3b80_f17f_58ee,
408                            0xf79a_5f06_f054_8dcf_993e_1de7_2d36_d310,
409                            0x7980_b63a_9726_39bc_b359_8080_ce64_a656,
410                            0xc327_c42e_fcd3_dcb0_252f_59cf_0d9f_04bb,
411                            0x8ae9_9f5a_1377_1265_d23c_8e17_6d11_3600,
412                            0xaeb9_6c60_887b_f568_1bda_0492_e7e4_586e,
413                            0x0262_cf9c_fb1b_e6f7_21e0_bd50_26c6_19bf,
414                            0x96f2_8db3_af9f_8eaf_3b09_7ada_f088_f94e,
415                            0xbd74_fc2e_2cd1_30ed_8d14_dedb_30be_846e,
416                            0xbfb4_0b3b_f213_0455_f95c_ffa2_3af5_f6f4,
417                            0x0d27_3904_28f9_09cc_3871_7007_61b3_f743,
418                            0xe641_18d4_1047_bff4_ca67_2b91_e9e4_fa16,
419                            0x9f17_5874_ee74_dfc0_64c8_e531_bff5_3b55,
420                            0x3c41_2787_59da_9b49_2412_60ed_4ad1_e87d,
421                            0xce24_3a58_7f0b_6bbd_106c_09b9_72d2_e822,
422                            0x1979_0b6c_ab0e_f9bc_7fba_1954_10e5_ca30,
423                            0x1b7b_b956_b20e_0ff1_7884_d9bc_6cb5_69d8,
424                            0xfcd5_5d2a_3d92_556c_0647_dfed_cd89_4a29,
425                            0x4f6a_4915_71d2_a627_6357_3ff0_3e22_4774,
426                            0x2a4b_d439_b908_5684_4fc8_e956_0f91_b123,
427                            0xb8eb_5b22_d497_aa9d_1db9_56e4_5027_5779,
428                            0xf6cb_137e_8867_9a76_b8d9_1274_b9e9_d4fb,
429                            0x22bc_9905_78e7_dd2c_a2eb_ee47_e2fb_fce1,
430                            0x01fc_46a5_af41_ba72_d9f1_f30c_cd97_fb09,
431                            0x9ee5_40b9_ce7e_922a_efed_53d7_5fd6_4e6b,
432                            0x5a82_3d7d_a29d_e33e_2e6d_02c3_6017_f67f,
433                            0xdcb5_4247_ed75_0238_a9aa_4d20_db08_4e9b,
434                            0xbbe3_4604_4327_e21a_b64b_e8d8_b253_96c1,
435                            0x3905_a0da_abfe_04e3_70cb_6af7_c2d5_bcf0,
436                            0x1670_290a_b911_8147_98f0_76a4_f7a2_322e,
437                            0x6816_3cb7_77ea_b10d_bf84_4708_05e6_9b5f,
438                            0xed24_0589_e171_a9a1_94c3_251f_06f9_0cf3,
439                            0x2281_ad67_174b_b66b_3e00_3e61_6a65_91e9,
440                            0x579e_d522_cb20_efa0_b925_a6cd_0421_aff3,
441                            0x9c31_9f6b_6fd2_554a_61bd_d130_7c66_e300,
442                            0x0dd4_faaa_fa80_e520_bf8d_5108_e27e_0d48,
443                            0x74bb_ae7f_87e8_60f9_240a_b57a_8b88_8b20,
444                            0xdff3_18b4_d732_a759_fc87_614b_af28_7e07,
445                            0xc371_ee9d_7d2a_f132_ef02_cdd0_6ffd_b432,
446                            0x76cc_4be2_658d_da80_a108_2c04_66df_6c0a,
447                            0xfd9e_506d_75af_7df5_8215_e577_0013_32c8,
448                            0xc5a0_d6e0_2e70_3f74_d39b_b9c3_a48d_b6cf,
449                            0x6317_01e4_2e35_f5cf_2738_2596_3430_5c14,
450                            0x3055_4020_95f7_43c0_61cf_4f94_c97d_f93d,
451                            0x37e8_9e5d_eff3_4268_1b6b_aca2_ae4e_125b,
452                            0xcc01_cd9d_386a_49cb_758f_450c_8857_2e0b,
453                            0x04a3_2825_1bd5_828f_959f_587d_507a_8359,
454                            0xc8dc_0ff4_362a_8c8f_b063_e962_e045_f54d,
455                            0xee81_4f9b_3bce_7af1_60e8_ed72_c0df_f5d1,
456                            0x57ae_92f6_b7f0_94ef_7b64_9785_5532_6f9f,
457                            0x0dbc_0ba7_bb1c_2445_fd08_0d23_6da8_14ba,
458                            0xec57_a417_b3ae_8ad1_8c90_fd9b_083f_4558,
459                            0x08d8_ec9d_3a3a_3a85_106f_72fe_81e2_c590,
460                            0x18a2_e3da_a4c6_bbe3_7976_033a_39f7_d952,
461                            0x68f8_161c_3538_8cf9_a4ec_0132_764c_a04b,
462                            0xe6e7_cc97_33d7_aa2f_733e_a705_fae4_fa77,
463                            0x206c_16a4_93a1_94f6_b4d8_f77b_c3e5_6167,
464                            0x2211_53de_c7e3_7554_9e21_f4f9_03b3_3fd9,
465                            0xd110_651a_a3d8_3db7_9d76_5e41_9fb6_9f6d,
466                            0x841c_2076_74a2_a59d_d30c_088b_a61e_a5ef,
467                            0xc09b_4da2_5303_cd0e_5d94_337f_bfaf_7f5b,
468                            0xe48f_ec76_c3d4_85e3_1a4e_4822_eb4d_7a59,
469                        ],
470                        king: [
471                            0x66fe_aacd_911b_81a2_230e_343d_fba0_8d33,
472                            0x94c1_e650_8f5f_1f47_43ed_7f5a_0fae_657d,
473                            0x4206_c6c8_0ef8_fd9f_3a88_a0fb_bcb0_5c63,
474                            0x3c1d_ea6d_0afc_ae52_2187_4b8b_4d2d_bc4f,
475                            0xe79c_f804_4680_e415_1bde_a12e_35f6_a8c9,
476                            0x4867_6fcc_8584_4eb5_53c0_65c6_c8e6_3528,
477                            0x62f2_0ecb_3011_44ad_e34a_1d25_0e7a_8d6b,
478                            0x2778_709c_b5ff_3fc7_d6b0_4d3b_7651_dd7e,
479                            0xd87c_6801_0650_c250_5e90_277e_7cb3_9e2d,
480                            0xbe61_c9fc_8adc_7260_2c04_6f22_062d_c67d,
481                            0xeaec_3f66_9523_6d35_b10b_b459_132d_0a26,
482                            0xd47e_9167_9b5b_befc_3fa9_ddfb_67e2_f199,
483                            0x1956_9361_7db7_534c_0e09_b88e_1914_f7af,
484                            0x2725_134b_52fd_2c81_10e8_b35a_f3ee_ab37,
485                            0x2277_0ffa_079a_1704_9eed_eca8_e272_b933,
486                            0x012c_2a69_dda5_ad22_d4c7_18bc_4ae8_ae5f,
487                            0x0933_8c04_f427_a66f_8153_6d60_1170_fc20,
488                            0x0d85_fd75_19aa_9dec_91b5_34f8_8581_8a06,
489                            0x0246_a0f9_fd64_2861_ec81_77f8_3f90_0978,
490                            0xac61_5f38_f5a4_51ea_190e_714f_ada5_156e,
491                            0x07a4_4f64_3033_6f1c_b592_bf39_b036_4963,
492                            0x2184_3034_22b5_3201_89c3_50c8_93ae_7dc1,
493                            0x6e47_c775_85ab_8164_ac04_2e70_f8b3_83f2,
494                            0x55d7_5131_c650_586c_b49b_52e5_87a1_ee60,
495                            0x4205_14ac_9286_37fa_fb15_2fe3_ff26_da89,
496                            0xbb00_290a_9289_ce13_3e66_6e6f_69ae_2c15,
497                            0x321f_8022_ccc2_553a_3b54_4ebe_544c_19f9,
498                            0x7eff_cb24_d14c_9d18_e805_a1e2_90cf_2456,
499                            0xdc41_8c09_511a_5174_24b3_3c9d_7ed2_5117,
500                            0x1130_c8b2_334d_05c7_e747_3342_7b72_f0c1,
501                            0x57f1_0554_d8e9_323b_0a80_4d18_b709_7475,
502                            0x90a5_ce5a_89ea_0b56_57e3_306d_881e_db4f,
503                            0xc273_27f9_36e6_8d1b_4ae7_d6a3_6eb5_dbcb,
504                            0x417b_730c_b2a9_66b0_2d8d_5432_1570_64c8,
505                            0x1d30_1ea1_5b8e_a672_d1e6_49de_1e7f_268b,
506                            0xf14d_ee33_99dd_f91c_8a32_8a1c_edfe_552c,
507                            0xbd98_9097_807f_7fbf_07a3_aec7_9624_c7da,
508                            0xc3a0_533a_6d96_954b_8454_7ddc_3e20_3c94,
509                            0x1992_5751_60c4_3696_990a_98fd_5071_d263,
510                            0xd494_93b5_23ad_7777_1a4f_f126_16ee_fc89,
511                            0xb77c_0f9c_f9e4_36f2_f6f7_fd14_3171_4200,
512                            0xe627_02fe_f789_82ef_30c0_5b1b_a332_f41c,
513                            0x236a_476e_d946_6eb7_8d26_36b8_1555_a786,
514                            0xe304_cfd6_1b4f_416c_46c9_feb5_5d12_0902,
515                            0x2cb2_ea09_2e5f_1215_ccec_0a73_b49c_9921,
516                            0xe200_4d8b_7660_e169_4e9d_2827_355f_c492,
517                            0x7fca_be79_c444_2ade_19eb_b029_435d_cb0f,
518                            0x3ec3_d068_6df2_4ad5_4659_d2b7_4384_8a2c,
519                            0x8f3d_9e86_c7b3_1fff_963e_f2c9_6b33_be31,
520                            0x6ba1_30e1_edb0_873d_74f8_5198_b05a_2e7d,
521                            0x40fe_52ea_aac0_4a87_5a0f_544d_d2b1_fb18,
522                            0x789e_b8c7_4c29_b5bd_0372_7073_c2e1_34b1,
523                            0x4630_d701_99d8_fe85_c7f6_aa2d_e59a_ea61,
524                            0xc4f6_e06e_6ead_b36d_3527_87ba_a0d7_c22f,
525                            0x2d9c_d053_6bdd_c355_9853_eab6_3b5e_0b35,
526                            0x9522_ac8d_318d_e072_abbd_cdd7_ed5c_0860,
527                            0xdac1_5872_053f_b2a8_cf05_daf5_ac8d_77b0,
528                            0x4b63_b051_2042_2ba5_49ca_d48c_ebf4_a71e,
529                            0xc4f7_97ac_06e0_c775_7a4c_10ec_2158_c4a6,
530                            0x4b9e_fbbe_d8c2_bd98_d9e9_2aa2_46bf_719e,
531                            0x67b2_d764_0bd6_d12a_13ae_978d_09fe_5557,
532                            0x6921_6ca2_1f6e_1bf4_7304_99af_9215_49ff,
533                            0x49ab_0589_118f_e345_4e4b_705b_9290_3ba4,
534                            0x90b6_72aa_f076_4986_ff57_7222_c14f_0a3a,
535                        ],
536                    },
537                    white: ByRole {
538                        pawn: [
539                            0x3e8c_ad22_10fc_e3f3_5355_f900_c2a8_2dc7,
540                            0xa386_8eff_5334_6da1_07fb_9f85_5a99_7142,
541                            0x61de_5496_186b_0d70_5093_417a_a8a7_ed5e,
542                            0xe17a_09f0_e53b_c940_7bcb_c38d_a25a_7f3c,
543                            0xe0ff_e83a_fe44_ec11_19fc_8a76_8cf4_b6d4,
544                            0xf35a_5e31_84c1_c980_637a_7780_decf_c0d9,
545                            0x8339_0d9b_2e75_63a6_8249_a47a_ee0e_41f7,
546                            0x950f_1473_7ed6_be5b_79ad_6955_01e7_d1e8,
547                            0x6df4_2fcf_a743_809d_14ac_baf4_777d_5776,
548                            0x0f2b_1872_ba3f_ef30_f145_b6be_ccde_a195,
549                            0x0417_1b94_f58c_5d2e_dabf_2ac8_2017_52fc,
550                            0x78b0_5fea_0dc7_7c38_24c3_c94d_f9c8_d3f6,
551                            0xa76d_df41_aa67_5504_bb6e_2924_f039_12ea,
552                            0xe634_bc8f_87d0_fe75_0ce2_6c0b_95c9_80d9,
553                            0x2dbf_77a8_8512_37de_a49c_d132_bfbf_7cc4,
554                            0x10f9_b7d9_9683_6741_e99d_662a_f424_3939,
555                            0x26f6_547b_b047_1fb0_27e6_ad78_9116_5c3f,
556                            0xf727_c06d_b8bb_34e0_8535_f040_b974_4ff1,
557                            0x2898_4171_f866_b615_54b3_f4fa_5f40_d873,
558                            0x349d_2450_78c3_12ef_72b1_2c32_127f_ed2b,
559                            0x99f8_f1ab_94a1_3206_ee95_4d3c_7b41_1f47,
560                            0x967d_7e5e_9956_6e67_9a85_ac90_9a24_eaa1,
561                            0x470f_da10_3f94_76cc_70ac_4cd9_f04f_21f5,
562                            0x37da_d4fc_dedc_6db8_f9b8_9d3e_99a0_75c2,
563                            0x99f9_1b1c_d65c_50f0_87b3_e2b2_b5c9_07b1,
564                            0x6d89_c29c_b703_4aef_a366_e5b8_c54f_48b8,
565                            0x824c_9daa_114a_11c7_ae4a_9346_cc3f_7cf2,
566                            0xf3b1_ee14_5059_39c6_1920_c04d_4726_7bbd,
567                            0x2fa0_d39c_bee0_5ced_87bf_02c6_b49e_2ae9,
568                            0xc0c4_3ea8_a642_a49c_0922_37ac_237f_3859,
569                            0x4824_a871_bca3_4e17_ff07_f64e_f8ed_14d0,
570                            0x394b_500f_07f9_6989_8de8_dca9_f03c_c54e,
571                            0x7c6e_fb4d_c9be_a9d9_9c16_3326_4db4_9c89,
572                            0xca09_213b_feb3_6c6a_b3f2_2c3d_0b0b_38ed,
573                            0x0069_832f_9f2b_d0b5_390e_5fb4_4d01_144b,
574                            0xf092_a01d_0d44_20da_5bfe_a5b4_7127_68e9,
575                            0x6952_e201_5db3_9c5a_1e10_3291_1fa7_8984,
576                            0xf399_3e2a_4cdf_615e_9a74_acb9_64e7_8cb3,
577                            0x7d3d_dc6b_ef2e_d6f2_4f80_f7a0_35da_fb04,
578                            0xa704_0db3_8e23_3bac_6304_d09a_0b37_38c4,
579                            0xa8b5_9fe4_836f_fc08_2171_e646_8302_3a08,
580                            0xc55d_bb54_3604_14a9_5b9b_63eb_9cef_f80c,
581                            0x3e24_4653_59dc_03c0_506a_acf4_8988_9342,
582                            0xd27a_416e_d84c_c3b7_1881_afc9_a3a7_01d6,
583                            0x7a77_677e_0de6_20c4_6503_0804_4075_0644,
584                            0x30ca_cd32_e031_3d3b_dfd3_9533_9cdb_f4a7,
585                            0xdc69_52fd_3e61_c11a_ef92_7dbc_f00c_20f2,
586                            0x08ab_1642_b512_9e01_7b32_f7d1_e036_80ec,
587                            0xaa8e_0962_b8ee_bcdc_b9fd_7620_e731_6243,
588                            0x6dda_36ba_cc3b_2e2c_05a7_e8a5_7db9_1b77,
589                            0xba82_f4e2_cb60_b43e_b588_9c6e_1563_0a75,
590                            0x509d_a4ba_5295_c4a5_4a75_0a09_ce95_73f7,
591                            0x36a1_8fa3_8c3d_74c6_cf46_4cec_899a_2f8a,
592                            0xb9e5_6524_81a6_df69_f538_639c_e705_b824,
593                            0x5f49_46b7_dd41_d1c7_3c79_a0ff_5580_ef7f,
594                            0xfd7a_4fb7_bfe1_d23d_ede6_c87f_8477_609d,
595                            0x32e0_b2b6_8ea8_3031_799e_81f0_5bc9_3f31,
596                            0xf25f_cb24_f0c1_9623_8653_6b8c_f342_8a8c,
597                            0xa317_676d_c1eb_8797_97d7_374c_6008_7b73,
598                            0xf754_b557_c09a_e146_a246_637c_ff32_8532,
599                            0x5bbd_920f_ffe5_fa7a_043f_cae6_0cc0_eba0,
600                            0x5b3c_978e_296d_2280_920e_4495_35dd_359e,
601                            0xca9c_1ea3_4fc1_484f_70eb_093b_15b2_90cc,
602                            0x470c_408e_3b3d_2dc5_73a1_9219_1659_1cbd,
603                        ],
604                        knight: [
605                            0x2814_f2a1_9d86_70eb_c547_f57e_42a7_444e,
606                            0x5ced_6d61_7e9d_6b4d_78e3_7644_e7ca_d29e,
607                            0x69be_27bd_c682_e06a_fe9a_44e9_362f_05fa,
608                            0x945e_3cd5_4c7a_41f4_08bd_35cc_3833_6615,
609                            0xfac8_25c2_9c4e_52fc_9315_e5eb_3a12_9ace,
610                            0x95c3_8063_3671_f3c0_9406_1b87_1e04_df75,
611                            0xb1f0_f11b_309f_849f_df1d_9f9d_784b_a010,
612                            0x36b7_ac17_862b_c4ac_3bba_57b6_8871_b59d,
613                            0x8b89_835b_5e73_1ac5_d2b7_adee_ded1_f73f,
614                            0x1221_38b6_76fc_6561_f7a2_55d8_3bc3_73f8,
615                            0xce31_07b8_58b3_68ea_d7f4_f244_8c0c_eb81,
616                            0xaa14_dd37_33de_4203_d95b_e88c_d210_ffa7,
617                            0xec4e_a680_5a8d_ad1e_336f_52f8_ff47_28e7,
618                            0xce5c_d593_8049_dcf0_a740_49da_c312_ac71,
619                            0x2115_6227_c06a_4b0b_a2f6_1bb6_e437_fdb5,
620                            0xda13_d541_802c_4d5e_4f2a_5cb0_7f6a_35b3,
621                            0xfbf0_3d5c_9f78_3bb2_87d3_80bd_a5bf_7859,
622                            0xe512_fa9f_d5c6_8b8a_16b9_f7e0_6c45_3a21,
623                            0x30bd_781b_2227_7dcd_7ba2_484c_8a0f_d54e,
624                            0x5662_5e22_aef3_16ec_f3a6_78ca_d9a2_e38c,
625                            0xed75_251a_7102_4db6_39b0_bf7d_de43_7ba2,
626                            0xb468_dc45_b39c_de2f_fcaf_55c1_bf8a_4424,
627                            0x68b3_3836_bea9_a0a0_18fc_f680_573f_a594,
628                            0x3187_565f_03cc_0d85_4c05_63b8_9f49_5ac3,
629                            0x9bbc_591d_dc43_447f_40e0_8793_1a00_930d,
630                            0xc53a_2945_8191_d2db_8cff_a941_2eb6_42c1,
631                            0x6bc2_6380_3d69_1ec8_68ca_3905_3261_169f,
632                            0x04cc_a686_2885_8bac_7a1e_e967_d275_79e2,
633                            0xa20a_13cf_fa46_79d1_9d1d_60e5_076f_5b6f,
634                            0x8572_5a1e_096e_1abf_3810_e399_b6f6_5ba2,
635                            0xbc98_6393_043f_78d5_3209_5b6d_4ab5_f9b1,
636                            0x0fa4_7125_507c_cb12_35ca_b621_09dd_038a,
637                            0xc2c2_7b60_c8b2_ce36_a90b_2449_9fcf_afb1,
638                            0x2175_20a8_09c9_7da6_77a2_25a0_7cc2_c6bd,
639                            0x552a_d48c_9661_7c16_513e_5e63_4c70_e331,
640                            0x758c_0637_4011_44ae_4361_c0ca_3f69_2f12,
641                            0xf1ae_50d5_91ae_b10f_d941_aca4_4b20_a45b,
642                            0x0c12_7280_b892_40a3_528f_7c86_02c5_807b,
643                            0xa9a8_cd5d_dd77_37b0_52ab_92be_b961_3989,
644                            0x8506_683f_3e28_c050_9d1d_fa2e_fc55_7f73,
645                            0x8105_b057_3483_941f_722f_f175_f572_c348,
646                            0xd00b_cf69_74e8_788c_1d12_60a5_1107_fe97,
647                            0x3311_a2a4_e61f_c638_7a24_9a57_ec0c_9ba2,
648                            0x5b31_cba0_35ff_4f50_0420_8fe9_e8f7_f2d6,
649                            0x9ef0_4914_1a01_e743_5a11_0c60_58b9_20a0,
650                            0x3355_b7a6_3e03_cf20_0cd9_a497_658a_5698,
651                            0x78bf_716c_2f94_ffcf_56fd_23c8_f971_5a4c,
652                            0x2323_04d6_a359_676e_284c_847b_9d88_7aae,
653                            0xffee_bdd0_4f15_816e_04fe_abfb_bdb6_19cb,
654                            0x594f_dc90_c434_a4fd_742e_1e65_1c60_ba83,
655                            0xba5c_c088_b72c_0942_9a96_32e6_5904_ad3c,
656                            0x036e_fdc3_0e38_9de2_881b_82a1_3b51_b9e2,
657                            0x5038_b23c_9af1_74d2_506e_6744_cd97_4924,
658                            0x9b5e_64f3_0447_4d48_b018_3db5_6ffc_6a79,
659                            0x280a_4b8c_73c2_e8d8_0ed9_b915_c66e_d37e,
660                            0xfda0_76be_88bc_c507_5e11_e86d_5873_d484,
661                            0xafc8_96ae_852c_60c2_f678_647e_3519_ac6e,
662                            0xbe90_3340_939e_63fd_1b85_d488_d0f2_0cc5,
663                            0x7a97_bd60_aba4_c349_dab9_fe65_25d8_9021,
664                            0xf62e_51f1_7859_7cf9_0d15_1d86_adb7_3615,
665                            0x8f9a_b427_11b6_63dc_a865_a54e_dcc0_f019,
666                            0xc8d0_03d1_19dc_ac63_93c4_2566_aef9_8ffb,
667                            0xef21_01c3_2ada_ed38_99e7_afea_be00_0731,
668                            0xdde8_1906_502a_d1b0_48cb_ff08_6ddf_285a,
669                        ],
670                        bishop: [
671                            0x0bd0_0704_2735_acc6_23b7_0edb_1955_c4bf,
672                            0xb9dd_82de_bb9a_bd3d_c330_de42_6430_f69d,
673                            0x3312_b675_a5bc_5dfb_4715_ed43_e8a4_5c0a,
674                            0xd2e9_447e_6c6d_3509_a8d7_e4da_b780_a08d,
675                            0xd4d7_71a8_9c91_beb6_0572_b974_f03c_e0bb,
676                            0x31d0_7241_8324_8884_b57d_2e98_5e14_19c7,
677                            0xe722_9acd_b568_bc00_e8d9_ecbe_2cf3_d73f,
678                            0xb4ef_94e8_251e_cb66_2fe4_b171_70e5_9750,
679                            0xac81_7cad_3cfb_00ed_1131_7ba8_7905_e790,
680                            0x3fe8_6989_0b69_552c_7fbf_21ec_8a1f_45ec,
681                            0x91ae_c362_daa3_7fcd_1725_cabf_cb04_5b00,
682                            0xfb25_f88c_a887_ca77_964e_915c_d5e2_b207,
683                            0x053b_ff88_6db0_847c_3e2b_8bcb_f016_d66d,
684                            0x991f_d564_1b66_6e80_be74_44e3_9328_a0ac,
685                            0x24fc_37ad_820e_d73a_f85b_2b4f_bcde_44b7,
686                            0x2b2b_cac1_fa28_086e_4935_3fea_39ba_63b1,
687                            0x4c1a_3a21_90e0_8f26_1dd0_1aaf_cd53_486a,
688                            0x8e71_8591_cf07_851e_1fca_8a92_fd71_9f85,
689                            0xb14f_adbd_3baa_703f_fc7c_95d8_2735_7afa,
690                            0x8f1e_b8cc_7eed_d98e_18a6_a990_c8b3_5ebd,
691                            0x89ed_662f_01bc_b2fd_cccb_7005_c6b9_c28d,
692                            0xa263_fa3b_9a32_5a8f_3bdb_b92c_43b1_7f26,
693                            0xbae9_f4e1_4d09_637c_aa70_b5b4_f896_95a2,
694                            0x6be0_76b5_2945_a007_e94c_39a5_4a98_307f,
695                            0xd264_830e_7dc7_f906_b7a0_b174_cff6_f36e,
696                            0xc260_59b7_8ed6_854f_d4db_a847_29af_48ad,
697                            0x148d_ca9a_9b0c_8474_2e18_bc1a_d970_4a68,
698                            0x9749_c690_73ba_feb8_2de0_966d_af2f_8b1c,
699                            0xbba6_f466_2b0c_fd3c_b9c1_1d5b_1e43_a07e,
700                            0x6201_03f0_1e5b_63f8_6497_2d68_dee3_3360,
701                            0x4c78_20f9_50a4_c583_9462_8d38_d0c2_0584,
702                            0xe126_2fa8_ff1d_3269_dbc0_d2b6_ab90_a559,
703                            0x8f51_21c2_8730_29ef_d273_3c43_35c6_a72f,
704                            0x4fb3_edb5_4d50_7b36_7e75_d99d_94a7_0f4d,
705                            0xf859_4c47_0632_ebb6_6ced_1983_376f_a72b,
706                            0xb6e8_76e7_8ecf_5164_97fc_aacb_f030_bc24,
707                            0xafeb_0a5d_8071_50f5_7b77_497b_3250_3b12,
708                            0xf651_bea4_c88f_caae_8547_eddf_b81c_cb94,
709                            0xbfbc_e123_f031_77da_7999_9cdf_f709_02cb,
710                            0xb6aa_0fd2_2855_e81c_cffe_1939_438e_9b24,
711                            0xa240_adf5_4d70_b24e_8296_26e3_892d_95d7,
712                            0x732e_a6db_834b_f5a4_92fa_e242_91f2_b3f1,
713                            0xb472_31e0_7ae8_b35f_63e2_2c14_7b9c_3403,
714                            0x8055_4c03_9ab7_af15_c678_b6d8_6028_4a1c,
715                            0xdb2e_8329_7a30_b541_5873_8888_5065_9ae7,
716                            0xd58b_2a39_6b5a_1669_0981_dcd2_96a8_736d,
717                            0x2151_156a_affd_f4b7_9f65_789a_6509_a440,
718                            0x6547_9a62_9704_845e_9ff3_8fed_72e9_052f,
719                            0xa9be_d810_39cf_1c6d_e479_ee5b_9930_578c,
720                            0xd1a3_f98b_97ee_a710_e7f2_8ecd_2d49_eecd,
721                            0xff78_a5d7_2aa1_8fe3_56c0_74a5_81ea_17fe,
722                            0x96d1_a983_0ba7_ffd3_5544_f7d7_74b1_4aef,
723                            0xe19f_501d_cdf1_16db_7b3f_0195_fc6f_290f,
724                            0x8e68_f253_a278_535d_1215_3635_b2c0_cf57,
725                            0xdc75_c481_b2cd_c0fa_7f51_26db_ba5e_0ca7,
726                            0x7162_fa40_8d90_42fd_7a76_956c_3eaf_b413,
727                            0x9fad_ef0b_ce1a_7da1_3d57_74a1_1d31_ab39,
728                            0x5421_bbff_426d_4e84_8a1b_0838_21f4_0cb4,
729                            0xe794_4bee_b699_c0e7_7b4a_38e3_2537_df62,
730                            0x2ed8_b2db_0379_9071_9501_1364_6d1d_6e03,
731                            0xfc4e_188d_f10d_5454_4da8_979a_0041_e8a9,
732                            0x9de7_df26_c145_7c8f_3bc3_6e07_8f75_15d7,
733                            0x8fd7_3517_b47f_22c8_5d0a_12f2_7ad3_10d1,
734                            0xa300_5e22_b1bd_3e53_7f9d_1a2e_1ebe_1327,
735                        ],
736                        rook: [
737                            0x4911_7194_4e67_7dae_a09e_8c8c_35ab_96de,
738                            0xd0cf_9236_7e04_163c_fa7e_3939_8332_5753,
739                            0x67b6_a5b0_51ce_8d5c_d6b6_d0ec_c617_c699,
740                            0x88d4_1953_044d_621e_dfea_21ea_9e75_57e3,
741                            0xb93b_cd9d_d369_fe49_b67c_1fa4_8168_0af8,
742                            0x7999_9db5_7b23_5430_ca1e_3785_a9e7_24e5,
743                            0x20ba_d52d_d13a_90d4_1cfc_8bed_0d68_1639,
744                            0x4ccc_c5ae_16a2_9dd2_d18d_8549_d140_caea,
745                            0xa061_5c69_803b_77c7_4ed0_fe7e_9dc9_1335,
746                            0x2e2c_b093_8ba8_01a0_e4db_f063_4473_f5d2,
747                            0x7ba9_1914_cab5_0528_1761_f93a_44d5_aefe,
748                            0x2738_8731_08dc_ba8a_5389_8e4c_3910_da55,
749                            0x4502_a978_9913_1230_734d_e818_1f6e_c39a,
750                            0x3810_8697_800e_8bb5_2680_b122_baa2_8d97,
751                            0xa46e_de14_5d66_a90b_298a_f231_c85b_afab,
752                            0xe99d_73fe_edfd_98b3_7983_eed3_7408_47d5,
753                            0x3267_a96b_ed60_4a38_66c1_a2a1_a60c_d889,
754                            0xad66_f2c8_1cc3_fc42_9e17_e496_42a3_e4c1,
755                            0xfa2d_e5ba_2d8c_3693_edb4_54e7_badc_0805,
756                            0xd4ca_1c86_d116_bcbd_50b7_04ca_b602_c329,
757                            0x525f_7774_ee1d_de6b_4cc3_17fb_9cdd_d023,
758                            0xa8e3_4668_2e28_83b9_66b4_835d_9eaf_ea22,
759                            0xae03_d84b_90df_4cb2_219b_97e2_6ffc_81bd,
760                            0xd127_35c3_d08e_24d9_261e_4e4c_0a33_3a9d,
761                            0xb737_b467_cee7_1d3a_1fe2_cca7_6517_db90,
762                            0x3697_0fe3_34b2_a37e_d750_4dfa_8816_edbb,
763                            0xd5c7_3db7_872b_e26f_b957_1fa0_4dc0_89c8,
764                            0x8aeb_0ed5_6a41_77fa_1ddc_0325_259b_27de,
765                            0x0199_f29d_bf7a_1802_cf3f_4688_801e_b9aa,
766                            0x1cab_a957_a1ff_78f0_f4f5_d05c_10ca_b243,
767                            0x2abf_d2ec_bf62_492e_38b6_525c_21a4_2b0e,
768                            0xadd3_70c3_cd31_6a3e_36f6_0e2b_a4fa_6800,
769                            0x08a3_07d2_18ff_bcbf_eb35_9380_3173_e0ce,
770                            0x7bf0_2813_994b_261f_9c4c_d625_7c5a_3603,
771                            0x8942_9036_6274_ef43_af0c_317d_32ad_aa8a,
772                            0xc082_1c96_5822_94b4_258e_5a80_c720_4c4b,
773                            0xbd2c_e07a_63da_7db1_8b88_9d62_4d44_885d,
774                            0x03ba_38df_61db_a3a6_f4d1_4597_e660_f855,
775                            0x4bc8_ce1e_706b_b08d_d434_7f66_ec89_41c3,
776                            0x7dca_263e_a902_4a3c_e699_ed85_b0df_b40d,
777                            0x4e87_6b14_0c9c_da33_2472_f620_7c2d_0484,
778                            0x5bda_bc35_a2fa_1b4e_c2a1_e7b5_b459_aeb5,
779                            0x383a_46ec_e18c_27c4_ab4f_6451_cc1d_45ec,
780                            0x532e_e826_c31a_9b81_6376_7572_ae3d_6174,
781                            0x84f3_d8fa_ecfd_7924_a59e_0bd1_0173_1a28,
782                            0xba90_5cc3_71f0_66d9_116d_0016_cb94_8f09,
783                            0x3da8_8231_8279_b416_2cf9_c8ca_052f_6e9f,
784                            0xb356_6f6d_ccae_32ed_0b09_0a75_60a9_68e3,
785                            0x6eb1_3ec5_ca4c_b179_abee_ddb2_dde0_6ff1,
786                            0xab38_2663_03f6_72c0_58ef_c10b_06a2_068d,
787                            0xc5e2_3f86_9808_4689_c6e5_7a78_fbd9_86e0,
788                            0x502f_e8a1_ce0a_1bc6_2eab_8ca6_3ce8_02d7,
789                            0x4664_fe51_5409_3ec2_14a1_9564_0116_f336,
790                            0x3e39_d0fe_fb4f_faf8_7c08_28dd_624e_c390,
791                            0x4162_ffb2_b58a_ed88_d74b_be77_e611_6ac7,
792                            0x5e1e_505c_7c91_6883_8044_56af_10f5_fb53,
793                            0x2185_b1f3_4d27_5173_ebe9_ea2a_df43_21c7,
794                            0xdb89_8d04_8727_1365_0321_9a39_ee58_7a30,
795                            0xddb7_e20f_4f0b_0a5f_4978_7fef_17af_9924,
796                            0xe39e_cdbb_8083_0b57_a1e9_300c_d852_0548,
797                            0xd1e1_2d09_eb3d_6c76_5b45_e522_e4b1_b4ef,
798                            0xf33d_e059_1295_1acf_b49c_3b39_9509_1a36,
799                            0x7ddc_a4e7_cf6a_2022_d449_0ad5_26f1_4431,
800                            0x37da_e739_34d2_b45c_12a8_f216_af94_18c2,
801                        ],
802                        queen: [
803                            0x4c37_f288_95f6_b9e0_6ffe_73e8_1b63_7fb3,
804                            0x97fe_8d6e_8425_ea84_ddf9_57bc_36d8_b9ca,
805                            0xe131_7625_1539_f9db_64d0_e29e_ea88_38b3,
806                            0x4e88_7953_d437_13f5_08dd_9bdf_d96b_9f63,
807                            0x32dc_49e0_f8b9_6e5c_087e_79e5_a57d_1d13,
808                            0x1240_f031_5707_df84_e328_e230_e3e2_b3fb,
809                            0xe22f_60c8_78f0_3163_1c25_59e3_0f09_46be,
810                            0x733e_de41_31a1_662d_720b_f5f2_6f4d_2eaa,
811                            0x5c82_e1f5_8657_d112_b077_4d26_1cc6_09db,
812                            0x6b39_b173_0052_9a95_443f_64ec_5a37_1195,
813                            0x9a36_6e73_434c_37a3_4112_cf68_649a_260e,
814                            0x3af0_4822_ac63_ca77_d813_f2fa_b7f5_c5ca,
815                            0x6c20_030d_cbb3_e153_660d_3257_3808_41ee,
816                            0x812b_c00a_41d9_de43_59ac_2c78_73f9_10a3,
817                            0x9d69_8757_f729_c30b_e846_9638_7767_1a17,
818                            0x7644_07e6_839c_724e_93b6_33ab_fa34_69f8,
819                            0x347b_8bcf_7aa8_a816_c0c0_f5a6_0ef4_cdcf,
820                            0xa15c_bc1e_7357_7012_caf2_1ecd_4377_b28c,
821                            0x8387_a4b0_8cc2_8a2e_5727_7707_199b_8175,
822                            0xce82_7a97_fe83_0269_506c_11b9_d90e_8b1d,
823                            0xfc36_77ad_2158_9c7a_d83c_c268_7a19_255f,
824                            0xc902_d33e_0a46_4ec1_4a29_c646_5a31_4cd1,
825                            0xfb39_2946_99a1_e2aa_ed2d_f212_1623_5097,
826                            0xd7bf_168e_258f_8f01_b563_5c95_ff72_96e2,
827                            0x2e60_2229_d2b3_7a22_22af_003a_b672_e811,
828                            0x821b_c37e_2c1f_8912_52e7_6259_6bf6_8235,
829                            0xc57a_1ba0_f260_acc5_9aeb_a33a_c6ec_c6b0,
830                            0xce78_cb66_7346_e38c_944f_6de0_9134_dfb6,
831                            0xbb39_eae7_a290_fcb0_6c47_bec8_83a7_de39,
832                            0x1bbc_42a4_5ca2_0618_6ad0_47c4_30a1_2104,
833                            0xef37_e286_f590_dcfb_a5b1_cfdb_a0ab_4067,
834                            0xd970_8ed7_ec64_1deb_7c45_d833_aff0_7862,
835                            0x12c5_e2f4_8472_4605_5092_ef95_0a16_da0b,
836                            0xf3e8_5d7b_8a77_b033_9338_e69c_052b_8e7b,
837                            0x8ee1_7c00_2143_8904_455a_4b4c_fe30_e3f5,
838                            0x462f_7fba_7c28_68f2_6b02_e631_95ad_0cf8,
839                            0xfb7a_14d6_137f_a5b1_6b17_b224_bad6_bf27,
840                            0x99ce_ec99_465f_e08c_d1e0_ccd2_5bb9_c169,
841                            0xa4be_0f00_1787_9351_de0c_89a5_56b9_ae70,
842                            0x48c9_c74e_faef_f5a7_5006_5e53_5a21_3cf6,
843                            0x682f_784b_a23d_c02e_9c11_69fa_2777_b874,
844                            0x226e_96a5_4011_3353_78ed_efd6_94af_1eed,
845                            0xaa04_b725_850e_2e32_6dc9_3d95_26a5_0e68,
846                            0xbc33_38f5_3303_ff19_ee97_f453_f067_91ed,
847                            0x94d8_0fc8_e255_9d54_32ab_0edb_6967_03d3,
848                            0xb470_b50e_6769_b2e4_3a68_53c7_e707_57a7,
849                            0x9d5c_af79_d12f_737c_3186_5ced_6120_f37d,
850                            0x0335_ce67_90cc_e15a_67fe_f95d_9260_7890,
851                            0xa9d8_8c05_289c_bd6d_1f2b_1d1f_15f6_dc9c,
852                            0xf3d1_d29b_153d_bd5e_b69e_38a8_965c_6b65,
853                            0x4104_7645_1284_9057_aa91_19ff_184c_ccf4,
854                            0x1d6d_02af_2005_1f53_f43c_7328_73f2_4c13,
855                            0xc8e4_8715_2b25_6129_fb4a_3d79_4a9a_80d2,
856                            0xaf60_d64f_bda8_f2ce_3550_c232_1fd6_109c,
857                            0xbf6d_091a_0541_7402_371f_77e7_6bb8_417e,
858                            0xda18_4d8f_f54f_3fc1_6bfa_9aae_5ec0_5779,
859                            0xb836_57ca_6633_e2ac_cd04_f3ff_001a_4778,
860                            0x75d3_e0b8_feed_bdb7_e327_3522_0644_80ca,
861                            0x26a5_8648_fd56_deab_9f91_508b_ffcf_c14a,
862                            0x5da2_dbf1_0323_e25c_049a_7f41_061a_9e60,
863                            0x1e3e_d1a3_9072_4f66_fcb6_be43_a9f2_fe9b,
864                            0xc761_5961_9f3a_f003_08de_8a1c_7797_da9b,
865                            0xb4af_22b5_f5b2_6389_8f98_87e6_0787_35a1,
866                            0x4667_92d7_a2e6_c6fa_b5b4_071d_bfc7_3a66,
867                        ],
868                        king: [
869                            0xc24a_a6db_9b0e_9300_55b6_344c_f97a_afae,
870                            0x8478_cc06_efce_550e_b862_225b_055b_6960,
871                            0x82e3_ec2c_cd28_350f_cac0_9afb_ddd2_cdb4,
872                            0xbc05_9bb7_4b99_3690_daf8_e982_9fe9_6b5f,
873                            0xe311_11d1_4445_238b_b5fd_fc5d_3132_c498,
874                            0xa7ed_1df7_7e79_a736_310c_b380_db6f_7503,
875                            0xa137_dc05_8288_8c63_e87f_bb46_217a_360e,
876                            0x7630_e700_4028_1934_2102_ae46_6ebb_1148,
877                            0x2c17_c3b7_4634_a6d6_f854_9e1a_3aa5_e00d,
878                            0x05ef_f03a_838a_4fb4_07a6_9afd_cc42_261a,
879                            0x3c28_d21d_40d4_f80e_c4c1_18bf_e78f_eaae,
880                            0xbeb9_cec1_8b16_3f7c_f9f4_892e_d96b_d438,
881                            0xdc75_1952_9748_4115_1af3_dbe2_5d8f_45da,
882                            0x5489_55be_3bde_572b_f5b4_b0b0_d2de_eeb4,
883                            0xc828_1bde_4d28_0b81_962a_ceef_a82e_1c84,
884                            0x914d_a129_a132_922b_046e_3eca_af45_3ce9,
885                            0xff11_d08f_1cee_77a4_f05d_1296_8194_9a4c,
886                            0x8070_295b_d01f_6bfd_9647_81ce_734b_3c84,
887                            0x006a_9346_f317_a9c9_9c2e_d440_81ce_5fbd,
888                            0x37e6_2ccd_f973_9fc3_522e_23f3_925e_319e,
889                            0x5cbf_8b75_3a7e_703c_177e_00f9_fc32_f791,
890                            0xfe0f_162f_cebe_01c8_2bc6_0a63_a6f3_b3f2,
891                            0x094f_481a_19d4_64ff_222b_bfae_6172_5606,
892                            0x9737_e370_b3c6_79cf_4862_89dd_cc3d_6780,
893                            0x60d6_7575_f3b9_b1c2_7dc7_785b_8efd_fc80,
894                            0x3948_fbaf_4119_6093_8af3_8731_c02b_a980,
895                            0x0c20_4d1c_fdbf_6e2a_1fab_64ea_29a2_ddf7,
896                            0xb7d2_d42a_9be2_9c2a_e4d9_4293_22cd_065a,
897                            0x49fa_e729_fc29_74b3_9da0_58c6_7844_f20c,
898                            0x6fb2_6356_dad9_8ed6_24c0_e332_b700_19b0,
899                            0x4847_b6cc_14ee_ffd4_2330_03b5_a6cf_e6ad,
900                            0x3b52_85a9_f015_2c99_d586_bd01_c5c2_17f6,
901                            0xff1f_e7f4_b91c_ff4c_5e56_3788_5f29_bc2b,
902                            0x16e2_0774_363e_99d0_7eba_726d_8c94_094b,
903                            0x437d_1aa9_cb41_59e0_0a56_a5f0_bfe3_9272,
904                            0x7bdc_c9d5_c1c4_da0b_d794_76a8_4ee2_0d06,
905                            0x8fd0_8773_3782_eecd_9e4c_1269_baa4_bf37,
906                            0xbf94_dee3_ad47_8cda_17ef_ee45_b0de_e640,
907                            0x83c9_4bbe_4c62_3bf5_1d95_b0a5_fcf9_0bc6,
908                            0x08fd_a03a_a45e_e9ba_93cb_e0b6_99c2_585d,
909                            0xc188_f92d_4d40_3856_65fa_4f22_7a2b_6d79,
910                            0xfd66_11df_b123_45fc_d5f9_e858_2925_04d5,
911                            0xef00_3ffd_18ae_cc12_c2b5_a03f_7147_1a6f,
912                            0xb7b4_74cb_f293_4019_5930_0222_b456_1e00,
913                            0xbc2a_55e5_8b30_deee_ce2f_8642_ca07_12dc,
914                            0x3e77_de18_337c_da42_7ca9_723f_bb2e_8988,
915                            0x2f81_e058_ffb7_5885_2785_3383_47f2_ba08,
916                            0x8f0c_300c_f585_707e_c61b_b3a1_41e5_0e8c,
917                            0xcf4f_4c53_6e0e_2af2_150f_361d_ab9d_ec26,
918                            0x24c8_1ee5_fd39_a8e4_9f6a_419d_3825_95f4,
919                            0x2841_577e_66ad_726e_64a5_3dc9_24fe_7ac9,
920                            0x6809_0c81_a135_7214_142d_e49f_ff7a_7c3d,
921                            0xa6aa_70d4_4a61_3a24_0c33_5248_857f_a9e7,
922                            0xdb80_5d26_087f_4db9_0a9c_32d5_eae4_5305,
923                            0x6dd9_54b4_5a12_2182_e6c4_2178_c4bb_b92e,
924                            0xc347_29fd_9f19_48a3_71f1_ce24_90d2_0b07,
925                            0xf068_2ca0_764c_c153_f1bc_c3d2_75af_e51a,
926                            0xbf29_8242_79ca_73e1_e728_e8c8_3c33_4074,
927                            0xf0c7_0fb4_e725_caff_96fb_f83a_1288_4624,
928                            0x1e18_cad8_09e9_eedc_81a1_549f_d657_3da5,
929                            0xa893_a8fa_258f_383e_5fa7_867c_af35_e149,
930                            0xe78c_30cc_1179_b849_5698_6e2e_f3ed_091b,
931                            0x2e44_32e6_ce49_96d9_917f_1dd5_f888_6c61,
932                            0x576e_c7a8_4e0b_932d_d20d_8c88_c8ff_e65f,
933                        ],
934                    },
935                };
936
937                $t(PIECE_MASKS.piece(piece)[usize::from(square)])
938            }
939
940            #[inline]
941            fn zobrist_for_white_turn() -> $t {
942                #[allow(overflowing_literals)]
943                $t(0x3815_e537_b622_2c85_f8d6_26aa_af27_8509)
944            }
945
946            #[inline]
947            fn zobrist_for_castling_right(color: Color, side: CastlingSide) -> $t {
948                #[allow(overflowing_literals)]
949                static CASTLING_RIGHT_MASKS: ByColor<ByCastlingSide<$proxy>> = ByColor {
950                    black: ByCastlingSide {
951                        king_side: 0x7756_8e6e_6151_6b92_a57e_6339_dd2c_f3a0,
952                        queen_side: 0xd153_e6cf_8d19_84ea_1ef6_e6db_b196_1ec9,
953                    },
954                    white: ByCastlingSide {
955                        king_side: 0xca3c_7f8d_050c_44ba_31d7_1dce_64b2_c310,
956                        queen_side: 0x8f50_a115_834e_5414_f165_b587_df89_8190,
957                    },
958                };
959
960                $t(CASTLING_RIGHT_MASKS.get(color)[side])
961            }
962
963            #[inline]
964            fn zobrist_for_en_passant_file(file: File) -> $t {
965                #[allow(overflowing_literals)]
966                static EN_PASSANT_FILE_MASKS: [$proxy; 8] = [
967                    0x1309_9942_ab63_3504_70cc_73d9_0bc2_6e24,
968                    0x946c_7352_9a2f_3850_e21a_6b35_df0c_3ad7,
969                    0x3d1a_dc27_d706_b921_003a_93d8_b280_6962,
970                    0x994b_8bd2_60c3_fad2_1c99_ded3_3cb8_90a1,
971                    0xf4cf_0c83_cace_7fe4_cf31_45de_0add_4289,
972                    0x5480_7a18_b695_2e27_d0e4_427a_5514_fb72,
973                    0xe2a1_aff4_0d08_315c_77c6_21cc_9fb3_a483,
974                    0x47ec_43ff_bc09_2584_67a3_4dac_4356_550b,
975                ];
976
977                $t(EN_PASSANT_FILE_MASKS[usize::from(file)])
978            }
979
980            #[inline]
981            fn zobrist_for_remaining_checks(color: Color, remaining: RemainingChecks) -> $t {
982                #[allow(overflowing_literals)]
983                static REMAINING_CHECKS_MASKS: ByColor<[$proxy; 2]> = ByColor {
984                    black: [
985                        0x6a2a_d922_a69a_13e9_1d6d_c0ee_61ce_803e,
986                        0x49b5_72c7_9420_27d5_c628_4b65_3d38_e96a,
987                    ],
988                    white: [
989                        0x08c2_e927_1dc9_1e69_803f_5fb0_d2f9_7fae,
990                        0x088d_fad9_83bb_7913_b183_ccc9_e73d_f9ed,
991                    ],
992                };
993
994                let masks = REMAINING_CHECKS_MASKS.get(color);
995                let n = !<$proxy>::from(remaining);
996
997                $t(((n & 1) * masks[0]) ^ (((n >> 1) & 1) * masks[1]))
998            }
999
1000            #[inline]
1001            fn zobrist_for_promoted(square: Square) -> $t {
1002                #[allow(overflowing_literals)]
1003                static PROMOTED_MASKS: [$proxy; 64] = [
1004                    0x2b91_78eb_57f3_db25_2f99_00cc_2b7a_19ca,
1005                    0x17d1_6678_351d_3778_f752_35be_b018_86d3,
1006                    0x88b1_7afb_dae8_36b1_8ae7_e298_89ac_9964,
1007                    0xa898_5bb0_47c3_88b1_ad30_091c_e7cb_4204,
1008                    0x2577_b875_de12_0fd2_aae1_1877_3ddd_4e4d,
1009                    0xbdf2_fdea_13ee_21fd_8ec5_14ce_4736_aa07,
1010                    0x3bcf_1cf1_605d_a5e7_26a4_12bd_8cef_4f15,
1011                    0x6ea6_f4fb_2ca4_d856_1bdc_e26b_d9af_059f,
1012                    0xb119_8a96_21b2_37f4_ea5f_4ade_5acc_0516,
1013                    0x6c87_686b_2878_2362_69ab_7ebc_0765_0565,
1014                    0x5158_703d_9536_de86_3e65_5f89_5a18_8a1c,
1015                    0xb312_6faf_bea7_5501_f394_f688_2a11_4d65,
1016                    0x80d3_3358_5254_7580_3173_cfa2_be5b_d4d3,
1017                    0xc5af_c4f4_4d5a_b019_434d_20d2_ca00_ae71,
1018                    0x7aff_7035_ddcd_e586_3ba2_97f7_3d33_8c93,
1019                    0xc338_837c_9531_20b2_099b_a1b0_205a_5ea5,
1020                    0x7f8b_4b71_5fc6_eee8_c49f_050b_5e1c_5653,
1021                    0x76d1_cd96_2b7c_0005_e14e_ec50_a9c6_90e8,
1022                    0xad3d_b13d_420b_8915_2571_cc79_f4ce_0169,
1023                    0xe5a6_0762_8406_1351_de0f_98d6_002f_4323,
1024                    0x7f61_ddc8_b19d_e688_0682_220b_02e5_c3e8,
1025                    0x8648_ca9b_e569_6f33_cb90_0d3a_6b38_c39d,
1026                    0x469d_c25e_1b32_d323_2462_0fbf_09d5_0d66,
1027                    0x4f52_9fa2_8957_8425_0f40_a9b2_781a_119d,
1028                    0x82d5_50f6_a40a_3d66_83c6_980d_f0d0_4932,
1029                    0x8e79_1844_cfb8_7476_ab6f_9af7_20cb_5df4,
1030                    0xb229_ab8b_b605_4dad_1c90_6974_166e_e8d4,
1031                    0x50a0_b7e3_c796_ad7e_9c1b_a3db_0784_ebda,
1032                    0x186c_0c4a_7a5d_68d1_81a1_9098_d16a_a929,
1033                    0x7483_01e9_e571_a670_fce5_6173_c63c_cefd,
1034                    0x2119_955c_d577_ee40_43cb_7aa2_0c62_09c2,
1035                    0x6c57_c138_0ffb_21fb_7e96_e2ae_8692_4bab,
1036                    0xadd6_07ff_5aaa_f995_0186_0725_034b_0fef,
1037                    0xd41e_c439_c73a_3e0f_f74d_3690_66ec_4e96,
1038                    0x3ee3_43c1_d983_7a9e_1ae9_962c_6e0d_1232,
1039                    0x9770_7414_bf74_3321_5d66_fa46_5ccf_c560,
1040                    0xe6a8_ec45_3ed6_7917_e9c1_3ae1_fc36_afaa,
1041                    0x0384_5f08_49e1_83df_caec_4035_fb84_0be4,
1042                    0xccd5_f9e7_ce7e_601f_839d_28ad_afad_0f8f,
1043                    0xe2c0_4ba3_4842_32d8_e470_3b6e_3042_2003,
1044                    0x5d9b_925a_3e6a_f022_1e2f_d5b2_827d_5e43,
1045                    0xa852_b770_63b9_e148_96f1_e8d8_b94b_d960,
1046                    0x279d_2c0c_53ec_aac6_90f2_075c_3f43_960c,
1047                    0x39f0_827a_4f81_1c72_c48e_0774_c4f9_134f,
1048                    0x3b06_4b86_1451_7b48_f17e_5f6a_2cb0_00c7,
1049                    0xdb19_bcf0_00dd_394a_6248_409b_f55a_4925,
1050                    0xa63d_ddb6_17c5_9634_967b_d94e_b305_05cc,
1051                    0xece8_3ffa_46fd_173a_e91e_8985_3f9e_844f,
1052                    0x01c4_d4d3_9c11_557f_b841_038e_2419_3f08,
1053                    0xa618_dd21_a5f6_b67f_46f3_b25c_ae82_a6cc,
1054                    0x8356_bdf4_4056_3fb0_3e97_e042_449e_3ed5,
1055                    0xf35a_d55d_7273_51a1_868a_166a_f46d_cbd2,
1056                    0xa3a0_c83e_c173_d41c_f71b_e788_b3fd_1a7a,
1057                    0xa8b2_fe93_fc5d_dd19_cb6d_6541_0533_cc37,
1058                    0x984f_d612_fa39_36bd_7e30_d705_59ef_aedc,
1059                    0x71c7_e142_bb02_9d2a_32db_0f5c_a181_59ce,
1060                    0x759f_8a94_60c6_34a6_97a9_116e_8742_28c5,
1061                    0x6fa2_ca2c_a3bd_eb90_85ee_68ee_3a17_5297,
1062                    0xea5f_0228_fc31_4b97_076a_1417_0b40_9e2a,
1063                    0xc40c_265d_97e7_63c0_bad4_9d47_dc95_855b,
1064                    0x201d_68d0_d89f_0e31_6361_87d9_4ded_991e,
1065                    0x1b76_9456_c778_79cf_962e_5097_1f09_cfab,
1066                    0xa8ba_af8b_31da_09a5_8f16_c910_d677_6589,
1067                    0x06a7_9ac4_14c9_632e_7e3d_e4bf_bef5_566f,
1068                ];
1069
1070                $t(PROMOTED_MASKS[usize::from(square)])
1071            }
1072
1073            #[inline]
1074            fn zobrist_for_pocket(color: Color, role: Role, pieces: u8) -> $t {
1075                #[allow(overflowing_literals)]
1076                static POCKET_MASKS: ByColor<ByRole<[$proxy; 7]>> = ByColor {
1077                    black: ByRole {
1078                        pawn: [
1079                            0x6e21_a47d_5b56_1a1d_b262_e9f9_d612_3320,
1080                            0x4263_a757_e414_fe44_9153_3947_cdaa_8bec,
1081                            0x93c4_3f67_cf55_b53f_a13b_56b4_5723_a3d4,
1082                            0xa897_32f3_39d3_5eec_9a35_cce2_9ca3_ac75,
1083                            0x5df4_ac25_c29f_bebf_2716_940e_1d4f_28d7,
1084                            0x6205_9230_cedc_d78f_7447_209c_fb79_3066,
1085                            0x9b0f_7261_932d_2c8e_5cf9_1d8a_e640_2e1a,
1086                        ],
1087                        knight: [
1088                            0xfc0f_99f0_0e0c_c0e7_4625_588d_3848_7ac5,
1089                            0xcba8_a5a0_2c35_1aa5_e42e_c619_1353_e3bd,
1090                            0x77a6_c01b_d017_4d69_478e_6cc8_f6b2_dada,
1091                            0xc200_e526_4100_e463_1726_fc94_8b99_4b87,
1092                            0x3f34_0a89_f525_effe_fb9d_2e5a_66b4_6741,
1093                            0xf748_b2be_597b_2f7a_7f66_8e40_1ffe_9e6f,
1094                            0xf7b2_eddf_7b88_38c2_ee4d_6fe1_1c46_a236,
1095                        ],
1096                        bishop: [
1097                            0xbdec_7e9f_4317_a678_006c_b700_6425_9959,
1098                            0x5e02_2239_fdf2_0b36_3353_5a7c_4def_1b24,
1099                            0xfdd9_2fa0_5b03_b629_479e_792f_8171_fc29,
1100                            0x80cd_ab95_a899_27dc_656a_6e71_de97_0975,
1101                            0x92cb_516b_8eba_4a30_cada_3e48_618a_1c2b,
1102                            0xac95_0f8b_ce3a_f2d9_b37a_d726_2db9_c99e,
1103                            0x9a43_060d_3aaa_e01a_85ae_2540_2a31_1d5d,
1104                        ],
1105                        rook: [
1106                            0xf12b_2f60_12f9_333c_3de4_e82d_52db_b44c,
1107                            0x8ae9_143e_ce61_584a_b1c8_4996_7446_4c21,
1108                            0x676f_7093_0e72_993c_f1c1_853c_c682_7b84,
1109                            0x25e0_f5f0_1447_6a1f_51f9_7ed3_ba00_4fb0,
1110                            0x1e33_827f_042d_e978_00da_9ede_878e_3e98,
1111                            0xdd15_8e4a_7838_524d_3cd0_fd65_8e1c_db12,
1112                            0x2b75_316d_fa1b_15e2_ac29_40b6_88a1_d0f9,
1113                        ],
1114                        queen: [
1115                            0x0283_b57f_325e_a495_e51a_cb5b_336d_b0df,
1116                            0x146e_60f5_6ab9_1765_cf75_17fb_dcb1_6174,
1117                            0xf50d_2497_f8b1_2819_dfe9_01ab_a4a2_ced3,
1118                            0x7600_c53f_3c60_308b_24bf_d4b7_2c88_52eb,
1119                            0xb752_08a6_056d_c7e9_f085_bcd9_7118_83d4,
1120                            0xe5f0_eb83_c20e_921b_41b7_1908_a3d8_6274,
1121                            0x7529_d0a0_c95f_08ed_6d60_4cc0_a2df_1a69,
1122                        ],
1123                        king: [
1124                            0x33c7_b70e_e04a_511c_aedf_8291_e004_8c39,
1125                            0x727a_256d_ad06_cc11_09d3_c83f_5954_7935,
1126                            0x1b26_058e_1ba7_3008_257d_5c7e_bc71_8242,
1127                            0x09c4_8fc7_e167_f3b0_56ac_1c99_8f5c_2ede,
1128                            0x954f_57cd_f607_6cd4_a25c_0b06_7993_7316,
1129                            0x32fa_cc37_b50d_925e_a9a2_a7e2_00fa_a936,
1130                            0x2596_9816_8b89_f941_b8e7_ca47_16cf_9d49,
1131                        ],
1132                    },
1133                    white: ByRole {
1134                        pawn: [
1135                            0xb447_9bfb_3575_d3fc_9b25_3f89_247c_4c1d,
1136                            0xe69d_2038_0ad4_5ef5_1e70_1e2a_73f9_dc4b,
1137                            0x0ea7_2e45_5dfb_08e6_cdf3_51b2_89aa_5a84,
1138                            0x7f83_4fab_7161_3f89_2e4e_118f_c45f_dc0d,
1139                            0x0bef_7b04_290f_a4d3_8024_7d70_885a_d5ce,
1140                            0x425d_9a92_61ab_b5b9_0a99_dccf_ce31_6ca0,
1141                            0x231b_fd9d_fb70_f61e_b555_3435_dae7_6840,
1142                        ],
1143                        knight: [
1144                            0xf2ce_79a6_9837_967f_ee56_2004_d5d1_4158,
1145                            0xf901_2eb6_947f_5b8c_551b_5fa3_ec71_66a2,
1146                            0xe867_f9c7_0350_3bf1_2dbb_493c_6e9f_ec06,
1147                            0xee98_c901_0d1d_3cbc_f06b_4c65_f4bb_14a1,
1148                            0x95fc_0aa1_2223_89e8_5f0b_44d9_8013_acb9,
1149                            0xbf75_33eb_b6c9_9102_ce7d_bafa_734b_ba8a,
1150                            0xbc41_5372_0b7d_8489_e009_c0e3_55a7_7913,
1151                        ],
1152                        bishop: [
1153                            0xe892_965f_4753_afa0_2191_8f47_3cb6_decf,
1154                            0xeaec_3e07_7478_1d2e_dcf1_1e80_dc14_763f,
1155                            0x00b6_98a9_c339_0404_7ac2_1357_500f_b0c6,
1156                            0x84c9_4d9a_3d13_f9b5_28ab_e0a3_761e_326c,
1157                            0xe4a9_10d5_16e8_0a37_30b8_e3da_17d3_4c6e,
1158                            0x30a9_9425_bba7_3df4_d999_d38f_fa5d_771e,
1159                            0x1fe9_2363_cf09_9b7e_8a7e_0d13_67d7_0b28,
1160                        ],
1161                        rook: [
1162                            0x3fce_173a_5e42_7cb2_9157_bfe7_ac07_1796,
1163                            0x3cf0_44d0_bd7b_fb26_adda_94b2_1edd_779a,
1164                            0x14dd_9fdf_d382_638a_6f55_5cf7_856f_0d63,
1165                            0xa4ec_5d64_1160_68be_5b2a_5b27_88ad_c947,
1166                            0x970d_0225_c315_5df4_500c_782c_8c56_2a42,
1167                            0x96bb_58fa_f0fd_1692_20f8_b3f7_059d_8884,
1168                            0x183f_9136_b816_0b83_79c8_90ed_3e95_f3f4,
1169                        ],
1170                        queen: [
1171                            0x85c1_79d2_2cce_92b9_e64d_bd47_4ddc_f8ca,
1172                            0xd355_d775_2b44_05ff_a949_66fb_f7f2_70d5,
1173                            0xda7b_7aa3_7223_0d64_2473_b4e6_ad9f_aa9a,
1174                            0x8218_ddc4_550f_6260_98ab_df9f_a4b4_87e6,
1175                            0x090f_2692_c727_e1a1_75fa_1ecb_0717_029a,
1176                            0xce74_c18e_0f75_f7f8_f605_3757_646a_08ba,
1177                            0x0750_81d9_944c_f832_060e_2788_d998_13aa,
1178                        ],
1179                        king: [
1180                            0x90fb_3433_62ef_172d_5fa6_1c63_681e_bbc8,
1181                            0xac07_cd32_cdd4_a6c5_90bb_f42d_b708_006a,
1182                            0x3684_e6c1_eaf9_e5f5_b525_460e_c1c1_5916,
1183                            0x0f51_5afc_1356_a5ca_2696_070a_4502_024d,
1184                            0x282b_bc7b_2209_e436_1580_8744_2731_df68,
1185                            0xc017_2402_afbb_cbc5_6501_0c3e_a0ac_fdcf,
1186                            0x34e3_45bf_a3c4_7ceb_b28e_cdf3_05a7_a831,
1187                        ],
1188                    },
1189                };
1190
1191                let masks = POCKET_MASKS.get(color).get(role);
1192                let n = <$proxy>::from(pieces);
1193
1194                $t(((n & 1) * masks[0])
1195                    ^ (((n >> 1) & 1) * masks[1])
1196                    ^ (((n >> 2) & 1) * masks[2])
1197                    ^ (((n >> 3) & 1) * masks[3])
1198                    ^ (((n >> 4) & 1) * masks[4])
1199                    ^ (((n >> 5) & 1) * masks[5])
1200                    ^ (((n >> 6) & 1) * masks[6]))
1201            }
1202        }
1203
1204        #[cfg(feature = "nohash-hasher")]
1205        impl nohash_hasher::IsEnabled for $t {}
1206    };
1207}
1208
1209zobrist_value_impl! { Zobrist8, u8, 8 }
1210zobrist_value_impl! { Zobrist16, u16, 16 }
1211zobrist_value_impl! { Zobrist32, u32, 32 }
1212zobrist_value_impl! { Zobrist64, u64, 64 }
1213zobrist_value_impl! { Zobrist128, u128, 128 }
1214
1215impl Hash for Zobrist128 {
1216    fn hash<H>(&self, state: &mut H)
1217    where
1218        H: Hasher,
1219    {
1220        state.write_u64(self.0 as u64); // Truncating!
1221    }
1222}
1223impl Hash for Zobrist64 {
1224    fn hash<H>(&self, state: &mut H)
1225    where
1226        H: Hasher,
1227    {
1228        state.write_u64(self.0);
1229    }
1230}
1231impl Hash for Zobrist32 {
1232    fn hash<H>(&self, state: &mut H)
1233    where
1234        H: Hasher,
1235    {
1236        state.write_u32(self.0);
1237    }
1238}
1239impl Hash for Zobrist16 {
1240    fn hash<H>(&self, state: &mut H)
1241    where
1242        H: Hasher,
1243    {
1244        state.write_u16(self.0);
1245    }
1246}
1247impl Hash for Zobrist8 {
1248    fn hash<H>(&self, state: &mut H)
1249    where
1250        H: Hasher,
1251    {
1252        state.write_u8(self.0);
1253    }
1254}
1255
1256impl From<Zobrist128> for Zobrist64 {
1257    fn from(value: Zobrist128) -> Zobrist64 {
1258        Zobrist64(value.0 as u64)
1259    }
1260}
1261impl From<Zobrist128> for Zobrist32 {
1262    fn from(value: Zobrist128) -> Zobrist32 {
1263        Zobrist32(value.0 as u32)
1264    }
1265}
1266impl From<Zobrist128> for Zobrist16 {
1267    fn from(value: Zobrist128) -> Zobrist16 {
1268        Zobrist16(value.0 as u16)
1269    }
1270}
1271impl From<Zobrist128> for Zobrist8 {
1272    fn from(value: Zobrist128) -> Zobrist8 {
1273        Zobrist8(value.0 as u8)
1274    }
1275}
1276
1277impl From<Zobrist64> for Zobrist32 {
1278    fn from(value: Zobrist64) -> Zobrist32 {
1279        Zobrist32(value.0 as u32)
1280    }
1281}
1282impl From<Zobrist64> for Zobrist16 {
1283    fn from(value: Zobrist64) -> Zobrist16 {
1284        Zobrist16(value.0 as u16)
1285    }
1286}
1287impl From<Zobrist64> for Zobrist8 {
1288    fn from(value: Zobrist64) -> Zobrist8 {
1289        Zobrist8(value.0 as u8)
1290    }
1291}
1292
1293impl From<Zobrist32> for Zobrist16 {
1294    fn from(value: Zobrist32) -> Zobrist16 {
1295        Zobrist16(value.0 as u16)
1296    }
1297}
1298impl From<Zobrist32> for Zobrist8 {
1299    fn from(value: Zobrist32) -> Zobrist8 {
1300        Zobrist8(value.0 as u8)
1301    }
1302}
1303
1304impl From<Zobrist16> for Zobrist8 {
1305    fn from(value: Zobrist16) -> Zobrist8 {
1306        Zobrist8(value.0 as u8)
1307    }
1308}
1309
1310impl Board {
1311    pub(crate) fn board_zobrist_hash<V: ZobristValue>(&self) -> V {
1312        // Order optimized for cache efficiency.
1313        let mut zobrist = V::default();
1314        for role in Role::ALL {
1315            for color in [Color::Black, Color::White] {
1316                let piece = role.of(color);
1317                for sq in self.by_piece(piece) {
1318                    zobrist ^= V::zobrist_for_piece(sq, piece);
1319                }
1320            }
1321        }
1322        zobrist
1323    }
1324}
1325
1326#[cfg(test)]
1327mod tests {
1328    use super::*;
1329    use crate::{CastlingMode, Chess, EnPassantMode, Position, fen::Fen};
1330
1331    #[test]
1332    fn test_polyglot() {
1333        let reference_values = [
1334            (
1335                "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
1336                Zobrist64(0x463b_9618_1691_fc9c),
1337            ),
1338            (
1339                "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1",
1340                Zobrist64(0x823c_9b50_fd11_4196),
1341            ),
1342            (
1343                "rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2",
1344                Zobrist64(0x0756_b944_61c5_0fb0),
1345            ),
1346            (
1347                "rnbqkbnr/ppp1pppp/8/3pP3/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2",
1348                Zobrist64(0x662f_afb9_65db_29d4),
1349            ),
1350            (
1351                "rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPP1PPP/RNBQKBNR w KQkq f6 0 3",
1352                Zobrist64(0x22a4_8b5a_8e47_ff78),
1353            ),
1354            (
1355                "rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPPKPPP/RNBQ1BNR b kq - 1 3",
1356                Zobrist64(0x652a_607c_a3f2_42c1),
1357            ),
1358            (
1359                "rnbq1bnr/ppp1pkpp/8/3pPp2/8/8/PPPPKPPP/RNBQ1BNR w - - 2 4",
1360                Zobrist64(0x00fd_d303_c946_bdd9),
1361            ),
1362            (
1363                "rnbqkbnr/p1pppppp/8/8/PpP4P/8/1P1PPPP1/RNBQKBNR b KQkq c3 0 3",
1364                Zobrist64(0x3c81_23ea_7b06_7637),
1365            ),
1366            (
1367                "rnbqkbnr/p1pppppp/8/8/P6P/R1p5/1P1PPPP1/1NBQKBNR b Kkq - 1 4",
1368                Zobrist64(0x5c3f_9b82_9b27_9560),
1369            ),
1370        ];
1371
1372        for (fen, expected) in reference_values {
1373            let pos: Chess = fen
1374                .parse::<Fen>()
1375                .expect("valid fen")
1376                .into_position(CastlingMode::Standard)
1377                .expect("legal position");
1378
1379            assert_eq!(
1380                pos.zobrist_hash::<Zobrist64>(EnPassantMode::Legal),
1381                expected,
1382                "{fen}",
1383            );
1384        }
1385    }
1386
1387    #[cfg(feature = "variant")]
1388    #[test]
1389    fn test_variants_not_distinguished() {
1390        // Useful when indexing a table of opening names by Zorbist hash.
1391        let chess: Zobrist128 = Chess::default().zobrist_hash(EnPassantMode::Legal);
1392        let crazyhouse = crate::variant::Crazyhouse::default().zobrist_hash(EnPassantMode::Legal);
1393        let three_check = crate::variant::ThreeCheck::default().zobrist_hash(EnPassantMode::Legal);
1394        let king_of_the_hill =
1395            crate::variant::KingOfTheHill::default().zobrist_hash(EnPassantMode::Legal);
1396        assert_eq!(chess, crazyhouse);
1397        assert_eq!(chess, three_check);
1398        assert_eq!(chess, king_of_the_hill);
1399    }
1400
1401    #[test]
1402    fn test_full_pockets() {
1403        // 8/8/8/7k/8/8/3K4/8[ppppppppppppppppnnnnbbbbrrrrqq] w - - 0 54
1404        for color in Color::ALL {
1405            assert_ne!(
1406                Zobrist64::zobrist_for_pocket(color, Role::Pawn, 16),
1407                Zobrist64::zobrist_for_pocket(color, Role::Pawn, 15)
1408            );
1409            assert_ne!(
1410                Zobrist64::zobrist_for_pocket(color, Role::Queen, 2),
1411                Zobrist64::zobrist_for_pocket(color, Role::Queen, 1)
1412            );
1413        }
1414    }
1415
1416    #[cfg(feature = "nohash-hasher")]
1417    #[test]
1418    fn test_nohash_hasher() {
1419        let mut hasher = nohash_hasher::NoHashHasher::<Zobrist128>::default();
1420        Zobrist128(128).hash(&mut hasher);
1421        assert_eq!(hasher.finish(), 128);
1422
1423        let mut hasher = nohash_hasher::NoHashHasher::<Zobrist64>::default();
1424        Zobrist64(64).hash(&mut hasher);
1425        assert_eq!(hasher.finish(), 64);
1426
1427        let mut hasher = nohash_hasher::NoHashHasher::<Zobrist32>::default();
1428        Zobrist32(32).hash(&mut hasher);
1429        assert_eq!(hasher.finish(), 32);
1430
1431        let mut hasher = nohash_hasher::NoHashHasher::<Zobrist16>::default();
1432        Zobrist16(16).hash(&mut hasher);
1433        assert_eq!(hasher.finish(), 16);
1434
1435        let mut hasher = nohash_hasher::NoHashHasher::<Zobrist8>::default();
1436        Zobrist8(8).hash(&mut hasher);
1437        assert_eq!(hasher.finish(), 8);
1438    }
1439}