diff --git a/src/bitboard.hpp b/src/bitboard.hpp index 69774b7a..18cc005b 100644 --- a/src/bitboard.hpp +++ b/src/bitboard.hpp @@ -78,6 +78,10 @@ struct Bitboard { return Square{static_cast(std::countr_zero(m_raw))}; } + [[nodiscard]] bool any() const { + return static_cast(m_raw); + } + // Rank closest to player [[nodiscard]] u8 front_rank(Color color) const { i32 color_shift = color == Color::White ? 0 : 56; @@ -107,6 +111,15 @@ struct Bitboard { } } + [[nodiscard]] Square frontmost_square(Color color) const { + return color == Color::White ? msb() : lsb(); + } + + [[nodiscard]] static Bitboard forward_ranks(Color c, Square sq) { + return c == Color::White ? ~rank_mask(0) << (8 * sq.relative_rank(c)) + : ~rank_mask(7) >> (8 * sq.relative_rank(c)); + } + [[nodiscard]] Bitboard shift_relative(Color perspective, Direction dir) const { if (perspective == Color::Black) { dir = static_cast((static_cast(dir) + 4) % 8); @@ -215,6 +228,24 @@ struct Bitboard { friend constexpr Bitboard& operator^=(Bitboard& a, Bitboard b) { return a = a ^ b; } + friend constexpr Bitboard& operator>>=(Bitboard& a, i32 shift) { + return a = a >> shift; + } + friend constexpr Bitboard& operator<<=(Bitboard& a, i32 shift) { + return a = a << shift; + } + + // ostream support for debugging + friend std::ostream& operator<<(std::ostream& os, const Bitboard& bb) { + for (i32 rank = 7; rank >= 0; rank--) { + for (i32 file = 0; file < 8; file++) { + Square sq = Square::from_file_and_rank(file, rank); + os << (bb.is_set(sq) ? '1' : '.') << ' '; + } + os << std::endl; + } + return os; + } private: u64 m_raw = 0; diff --git a/src/eval_constants.hpp b/src/eval_constants.hpp index f6177930..81bc1f48 100644 --- a/src/eval_constants.hpp +++ b/src/eval_constants.hpp @@ -5,163 +5,178 @@ namespace Clockwork { // clang-format off -inline const PParam PAWN_MAT = S(171, 156); -inline const PParam KNIGHT_MAT = S(517, 316); -inline const PParam BISHOP_MAT = S(473, 272); -inline const PParam ROOK_MAT = S(546, 411); -inline const PParam QUEEN_MAT = S(1082, 561); -inline const PParam TEMPO_VAL = S(63, 14); +inline const PParam PAWN_MAT = S(162, 160); +inline const PParam KNIGHT_MAT = S(514, 311); +inline const PParam BISHOP_MAT = S(450, 266); +inline const PParam ROOK_MAT = S(547, 407); +inline const PParam QUEEN_MAT = S(1076, 555); +inline const PParam TEMPO_VAL = S(64, 13); inline const PParam BISHOP_PAIR_VAL = S(77, 163); inline const PParam ROOK_OPEN_VAL = S(114, -26); -inline const PParam ROOK_SEMIOPEN_VAL = S(44, 17); +inline const PParam ROOK_SEMIOPEN_VAL = S(42, 18); -inline const PParam DOUBLED_PAWN_VAL = S(-32, -75); +inline const PParam DOUBLED_PAWN_VAL = S(-19, -85); -inline const PParam POTENTIAL_CHECKER_VAL = S(-69, -10); -inline const PParam OUTPOST_KNIGHT_VAL = S(51, 40); -inline const PParam OUTPOST_BISHOP_VAL = S(61, 26); +inline const PParam POTENTIAL_CHECKER_VAL = S(-66, -11); +inline const PParam OUTPOST_KNIGHT_VAL = S(50, 40); +inline const PParam OUTPOST_BISHOP_VAL = S(60, 26); -inline const PParam PAWN_PUSH_THREAT_KNIGHT = S(49, 4); -inline const PParam PAWN_PUSH_THREAT_BISHOP = S(58, -25); -inline const PParam PAWN_PUSH_THREAT_ROOK = S(38, 34); -inline const PParam PAWN_PUSH_THREAT_QUEEN = S(70, -53); +inline const PParam PAWN_PUSH_THREAT_KNIGHT = S(48, 4); +inline const PParam PAWN_PUSH_THREAT_BISHOP = S(56, -24); +inline const PParam PAWN_PUSH_THREAT_ROOK = S(37, 35); +inline const PParam PAWN_PUSH_THREAT_QUEEN = S(68, -49); inline const std::array PAWN_PHALANX = { - S(22, 12), S(57, 33), S(73, 70), S(181, 153), S(481, 225), S(668, 679), + S(20, 11), S(55, 35), S(71, 69), S(170, 158), S(478, 229), S(654, 680), }; inline const std::array DEFENDED_PAWN = { - S(70, 38), S(60, 33), S(73, 65), S(175, 117), S(593, -10), + S(65, 41), S(58, 34), S(74, 64), S(177, 115), S(590, -11), }; inline const std::array PASSED_PAWN = { - S(-80, -96), S(-80, -74), S(-54, 7), S(28, 76), S(102, 197), S(302, 277), + S(-80, -98), S(-79, -78), S(-55, 2), S(23, 74), S(112, 207), S(303, 278), }; inline const std::array DEFENDED_PASSED_PUSH = { - S(43, -38), S(38, -6), S(29, 20), S(26, 66), S(97, 129), S(211, 209), + S(40, -35), S(35, -6), S(29, 18), S(28, 63), S(94, 131), S(202, 217), }; inline const std::array BLOCKED_PASSED_PAWN = { - S(10, -33), S(-1, 11), S(-4, -19), S(-7, -40), S(-14, -89), S(-268, -106), + S(11, -34), S(1, 6), S(-1, -22), S(-4, -42), S(-14, -90), S(-270, -106), }; inline const std::array FRIENDLY_KING_PASSED_PAWN_DISTANCE = { - S(0, 0), S(-3, 114), S(-16, 90), S(-9, 33), S(-1, 5), S(11, 6), S(57, 2), S(19, -6), + S(0, 0), S(16, 110), S(-9, 89), S(-8, 35), S(-5, 8), S(4, 7), S(48, 2), S(8, -5), }; inline const std::array ENEMY_KING_PASSED_PAWN_DISTANCE = { - S(0, 0), S(-300, -9), S(-35, 23), S(-13, 50), S(34, 60), S(39, 80), S(48, 87), S(19, 84), + S(0, 0), S(-292, -11), S(-26, 21), S(-7, 49), S(35, 62), S(37, 81), S(45, 86), S(20, 80), }; inline const std::array KNIGHT_MOBILITY = { - S(15, -60), S(114, 94), S(171, 164), S(209, 193), S(255, 203), S(284, 235), S(320, 228), S(358, 229), S(404, 169), + S(15, -67), S(113, 87), S(168, 158), S(203, 189), S(252, 198), S(280, 230), S(317, 222), S(354, 223), S(401, 162), }; inline const std::array BISHOP_MOBILITY = { - S(-18, -122), S(53, 37), S(115, 79), S(143, 127), S(172, 156), S(190, 176), S(199, 192), S(217, 197), S(229, 208), S(249, 197), S(272, 187), S(331, 143), S(336, 142), S(407, 96), + S(-10, -123), S(57, 39), S(119, 80), S(147, 128), S(177, 157), S(195, 176), S(204, 192), S(223, 197), S(234, 208), S(254, 197), S(277, 186), S(336, 143), S(342, 140), S(409, 98), }; inline const std::array ROOK_MOBILITY = { - S(275, 98), S(198, 259), S(226, 279), S(243, 282), S(256, 292), S(262, 304), S(270, 312), S(281, 311), S(288, 316), S(299, 318), S(311, 317), S(321, 316), S(327, 315), S(347, 295), S(455, 200), + S(279, 96), S(198, 260), S(227, 277), S(247, 281), S(261, 290), S(266, 302), S(274, 310), S(285, 309), S(292, 314), S(303, 316), S(316, 315), S(327, 313), S(334, 313), S(353, 292), S(461, 197), }; inline const std::array QUEEN_MOBILITY = { - S(457, 121), S(522, 233), S(570, 270), S(598, 364), S(609, 423), S(626, 454), S(630, 496), S(639, 501), S(642, 525), S(648, 534), S(651, 548), S(656, 551), S(668, 539), S(673, 542), S(677, 538), S(680, 534), S(686, 526), S(685, 526), S(697, 505), S(716, 487), S(731, 466), S(747, 433), S(775, 413), S(895, 301), S(946, 248), S(940, 241), S(861, 287), S(958, 217), + S(463, 104), S(526, 231), S(577, 264), S(605, 360), S(616, 419), S(633, 451), S(636, 494), S(645, 500), S(648, 523), S(654, 533), S(658, 547), S(663, 550), S(675, 538), S(681, 540), S(684, 537), S(689, 532), S(694, 525), S(694, 524), S(706, 503), S(726, 485), S(741, 465), S(758, 431), S(786, 411), S(906, 298), S(956, 246), S(950, 238), S(873, 283), S(975, 211), }; inline const std::array KING_MOBILITY = { - S(657, -331), S(243, -187), S(120, -84), S(81, -36), S(29, -21), S(-27, 4), S(-74, 40), S(-127, 68), S(-165, 56), + S(548, -257), S(147, -120), S(58, -45), S(39, -10), S(14, -9), S(-17, 6), S(-40, 29), S(-67, 43), S(-83, 20), }; inline const std::array KNIGHT_KING_RING = { - S(225, 227), S(344, 180), S(447, 118), + S(238, 231), S(355, 186), S(453, 126), }; inline const std::array BISHOP_KING_RING = { - S(457, 372), S(281, 235), S(163, 70), + S(483, 375), S(297, 236), S(163, 70), }; inline const std::array ROOK_KING_RING = { - S(319, 321), S(446, 313), S(488, 321), S(589, 372), S(746, 331), + S(317, 319), S(439, 316), S(482, 323), S(596, 367), S(761, 324), }; inline const std::array QUEEN_KING_RING = { - S(874, 747), S(589, 609), S(332, 459), S(142, 254), S(81, -12), S(15, -297), + S(883, 742), S(596, 607), S(335, 461), S(142, 257), S(84, -9), S(23, -299), }; inline const std::array PT_INNER_RING_ATTACKS = { - S(-119, 61), S(27, -18), S(-216, -128), S(56, 38), S(-242, -154), + S(-85, 41), S(27, -18), S(-227, -130), S(66, 34), S(-243, -154), }; inline const std::array PT_OUTER_RING_ATTACKS = { - S(-28, 22), S(-21, 20), S(-20, 15), S(-15, 9), S(-21, -12), + S(-26, 19), S(-20, 19), S(-19, 15), S(-16, 9), S(-21, -13), }; -inline const PParam PAWN_THREAT_KNIGHT = S(245, 60); -inline const PParam PAWN_THREAT_BISHOP = S(217, 116); -inline const PParam PAWN_THREAT_ROOK = S(203, 100); -inline const PParam PAWN_THREAT_QUEEN = S(186, -45); +inline const PParam PAWN_THREAT_KNIGHT = S(244, 61); +inline const PParam PAWN_THREAT_BISHOP = S(218, 116); +inline const PParam PAWN_THREAT_ROOK = S(204, 99); +inline const PParam PAWN_THREAT_QUEEN = S(186, -43); inline const PParam KNIGHT_THREAT_BISHOP = S(118, 73); inline const PParam KNIGHT_THREAT_ROOK = S(256, 15); -inline const PParam KNIGHT_THREAT_QUEEN = S(155, -18); +inline const PParam KNIGHT_THREAT_QUEEN = S(156, -20); -inline const PParam BISHOP_THREAT_KNIGHT = S(115, 38); +inline const PParam BISHOP_THREAT_KNIGHT = S(116, 38); inline const PParam BISHOP_THREAT_ROOK = S(238, 72); -inline const PParam BISHOP_THREAT_QUEEN = S(199, 52); +inline const PParam BISHOP_THREAT_QUEEN = S(200, 51); inline const std::array BISHOP_PAWNS = { - S(3, -20), S(-3, -8), S(-4, -18), S(-9, -25), S(-15, -32), S(-21, -35), S(-24, -46), S(-29, -47), S(-37, -52), + S(3, -20), S(-3, -8), S(-4, -18), S(-10, -24), S(-16, -31), S(-22, -34), S(-25, -45), S(-30, -46), S(-38, -50), }; inline const std::array PAWN_PSQT = { - S(294, 277), S(196, 348), S(309, 313), S(292, 250), S(343, 180), S(249, 255), S(203, 279), S(309, 230), // - S(158, 173), S(209, 218), S(199, 165), S(163, 130), S(146, 100), S(116, 140), S(95, 179), S(60, 185), // - S(100, 138), S(99, 157), S(112, 116), S(98, 108), S(83, 96), S(53, 110), S(24, 143), S(9, 161), // - S(87, 93), S(100, 123), S(105, 96), S(87, 99), S(58, 93), S(40, 100), S(-9, 142), S(-23, 128), // - S(85, 68), S(145, 73), S(91, 119), S(75, 119), S(43, 113), S(12, 112), S(-12, 127), S(-28, 113), // - S(83, 75), S(209, 84), S(150, 129), S(104, 146), S(73, 131), S(49, 117), S(29, 136), S(-9, 129), // + S(290, 301), S(160, 371), S(267, 324), S(302, 224), S(355, 161), S(268, 239), S(214, 270), S(329, 220), // + S(113, 187), S(160, 237), S(174, 183), S(161, 102), S(148, 77), S(124, 116), S(107, 158), S(73, 172), // + S(85, 157), S(90, 172), S(97, 141), S(100, 93), S(92, 80), S(62, 107), S(47, 138), S(28, 159), // + S(64, 114), S(82, 144), S(79, 127), S(81, 86), S(61, 79), S(50, 101), S(13, 141), S(-2, 127), // + S(54, 90), S(105, 103), S(83, 153), S(81, 108), S(57, 102), S(28, 106), S(15, 117), S(-5, 109), // + S(89, 88), S(179, 91), S(101, 130), S(110, 127), S(84, 115), S(69, 100), S(50, 125), S(13, 124), // }; inline const std::array KNIGHT_PSQT = { - S(-288, -49), S(-224, 184), S(-461, 436), S(89, 146), S(17, 153), S(-113, 131), S(-375, 194), S(-343, 30), // - S(107, 119), S(159, 120), S(239, 81), S(214, 116), S(211, 128), S(145, 121), S(127, 129), S(101, 103), // - S(176, 90), S(189, 137), S(246, 151), S(207, 169), S(181, 174), S(124, 184), S(135, 123), S(105, 118), // - S(235, 131), S(219, 149), S(222, 175), S(197, 208), S(215, 196), S(188, 181), S(189, 137), S(186, 112), // - S(228, 116), S(263, 106), S(239, 150), S(225, 173), S(211, 171), S(213, 160), S(214, 109), S(176, 110), // - S(173, 90), S(203, 87), S(185, 124), S(206, 148), S(208, 144), S(157, 132), S(157, 96), S(123, 79), // - S(184, 84), S(199, 70), S(180, 85), S(178, 106), S(165, 112), S(145, 67), S(150, 79), S(110, 15), // - S(127, 62), S(161, 120), S(186, 73), S(203, 61), S(188, 80), S(138, 61), S(128, 96), S(78, 34), // + S(-292, -44), S(-218, 182), S(-455, 433), S(92, 145), S(18, 152), S(-114, 132), S(-377, 194), S(-352, 39), // + S(112, 118), S(161, 119), S(245, 78), S(223, 112), S(215, 125), S(145, 121), S(124, 130), S(96, 104), // + S(184, 86), S(201, 130), S(254, 147), S(214, 164), S(186, 174), S(126, 183), S(132, 125), S(109, 117), // + S(238, 131), S(223, 149), S(230, 172), S(200, 205), S(219, 195), S(187, 181), S(188, 138), S(183, 114), // + S(228, 118), S(267, 107), S(240, 151), S(226, 173), S(211, 171), S(212, 160), S(211, 111), S(174, 111), // + S(171, 92), S(204, 89), S(185, 124), S(205, 150), S(207, 144), S(154, 133), S(155, 99), S(121, 81), // + S(184, 82), S(207, 66), S(178, 87), S(176, 109), S(165, 113), S(143, 70), S(148, 81), S(106, 20), // + S(123, 63), S(161, 121), S(185, 73), S(206, 59), S(186, 81), S(137, 63), S(130, 95), S(74, 39), // }; inline const std::array BISHOP_PSQT = { - S(-34, 184), S(-69, 168), S(-360, 241), S(-223, 208), S(-190, 217), S(-291, 252), S(-105, 219), S(-30, 194), // - S(76, 114), S(24, 174), S(58, 132), S(-6, 180), S(-21, 186), S(38, 161), S(67, 144), S(50, 134), // - S(143, 126), S(170, 124), S(166, 156), S(128, 149), S(99, 146), S(97, 155), S(143, 132), S(117, 113), // - S(122, 107), S(142, 125), S(162, 138), S(142, 176), S(171, 163), S(111, 147), S(118, 121), S(89, 112), // - S(139, 81), S(149, 109), S(159, 128), S(166, 150), S(155, 158), S(120, 148), S(84, 129), S(90, 96), // - S(157, 86), S(192, 92), S(210, 107), S(158, 144), S(150, 130), S(156, 126), S(165, 102), S(104, 108), // - S(141, 38), S(225, 56), S(188, 69), S(155, 96), S(137, 106), S(145, 79), S(146, 85), S(135, 45), // - S(147, 48), S(133, 97), S(138, 120), S(157, 76), S(165, 64), S(156, 123), S(151, 79), S(130, 71), // + S(-35, 182), S(-67, 164), S(-366, 241), S(-228, 208), S(-194, 217), S(-291, 248), S(-108, 217), S(-28, 192), // + S(85, 107), S(27, 170), S(60, 128), S(-10, 180), S(-21, 182), S(34, 160), S(63, 142), S(44, 131), // + S(137, 126), S(175, 119), S(165, 153), S(129, 144), S(95, 145), S(95, 153), S(135, 132), S(114, 111), // + S(125, 104), S(143, 124), S(166, 133), S(142, 173), S(172, 160), S(104, 146), S(116, 119), S(81, 113), // + S(142, 79), S(152, 106), S(158, 127), S(167, 147), S(153, 155), S(119, 145), S(79, 128), S(87, 94), // + S(160, 81), S(196, 87), S(211, 104), S(157, 143), S(150, 126), S(153, 124), S(163, 100), S(101, 106), // + S(144, 31), S(228, 52), S(186, 67), S(155, 94), S(136, 105), S(144, 76), S(144, 84), S(134, 44), // + S(146, 43), S(129, 93), S(141, 116), S(159, 74), S(164, 61), S(156, 121), S(151, 76), S(127, 70), // }; inline const std::array ROOK_PSQT = { - S(399, 246), S(435, 254), S(396, 278), S(406, 261), S(402, 260), S(351, 271), S(365, 273), S(362, 276), // - S(293, 302), S(356, 292), S(447, 266), S(382, 289), S(385, 290), S(345, 295), S(264, 324), S(262, 324), // - S(280, 288), S(407, 255), S(439, 247), S(423, 245), S(383, 254), S(335, 279), S(336, 280), S(256, 313), // - S(258, 275), S(334, 275), S(374, 259), S(354, 256), S(349, 264), S(307, 284), S(288, 285), S(228, 298), // - S(216, 230), S(287, 240), S(267, 258), S(265, 245), S(255, 255), S(241, 282), S(210, 273), S(185, 270), // - S(184, 204), S(248, 201), S(252, 224), S(238, 216), S(243, 210), S(214, 247), S(205, 225), S(164, 239), // - S(96, 220), S(213, 163), S(235, 184), S(243, 187), S(235, 188), S(222, 202), S(200, 185), S(172, 201), // - S(146, 208), S(163, 229), S(236, 189), S(263, 173), S(243, 191), S(231, 206), S(216, 198), S(197, 222), // + S(420, 240), S(457, 247), S(411, 274), S(420, 256), S(414, 257), S(357, 271), S(375, 272), S(370, 275), // + S(316, 294), S(380, 284), S(467, 259), S(399, 284), S(398, 287), S(353, 295), S(271, 324), S(269, 324), // + S(291, 285), S(424, 250), S(453, 243), S(428, 244), S(386, 257), S(338, 279), S(332, 284), S(254, 317), // + S(265, 275), S(343, 275), S(386, 256), S(355, 257), S(351, 266), S(307, 286), S(284, 288), S(222, 303), // + S(225, 230), S(297, 240), S(280, 255), S(266, 248), S(257, 255), S(242, 283), S(209, 274), S(183, 273), // + S(194, 201), S(258, 199), S(260, 222), S(241, 217), S(246, 211), S(216, 248), S(204, 228), S(162, 243), // + S(109, 216), S(227, 158), S(241, 184), S(246, 188), S(236, 191), S(222, 205), S(199, 189), S(170, 205), // + S(156, 206), S(167, 229), S(238, 191), S(262, 175), S(243, 194), S(230, 210), S(214, 203), S(194, 226), // }; inline const std::array QUEEN_PSQT = { - S(462, 412), S(540, 347), S(530, 380), S(448, 484), S(462, 447), S(451, 442), S(488, 372), S(389, 447), // - S(484, 441), S(427, 545), S(432, 557), S(289, 620), S(295, 613), S(364, 567), S(393, 484), S(414, 461), // - S(422, 497), S(514, 485), S(440, 557), S(407, 576), S(360, 579), S(377, 532), S(452, 435), S(428, 406), // - S(498, 395), S(494, 464), S(454, 508), S(430, 559), S(419, 562), S(421, 496), S(475, 402), S(473, 369), // - S(481, 398), S(491, 417), S(466, 467), S(438, 511), S(441, 507), S(438, 469), S(458, 398), S(469, 349), // - S(469, 318), S(503, 350), S(504, 420), S(469, 401), S(465, 393), S(472, 415), S(477, 358), S(463, 332), // - S(450, 199), S(493, 152), S(496, 242), S(508, 290), S(490, 318), S(490, 286), S(460, 336), S(461, 322), // - S(408, 240), S(458, 41), S(459, 67), S(487, 158), S(495, 233), S(496, 185), S(485, 217), S(437, 266), // + S(470, 403), S(552, 336), S(534, 372), S(449, 479), S(461, 442), S(452, 436), S(489, 368), S(389, 445), // + S(493, 434), S(438, 535), S(437, 549), S(293, 613), S(298, 606), S(362, 565), S(390, 483), S(411, 459), // + S(422, 496), S(519, 482), S(442, 552), S(412, 567), S(360, 575), S(376, 528), S(444, 436), S(424, 405), // + S(498, 398), S(493, 466), S(458, 504), S(428, 558), S(419, 559), S(416, 494), S(468, 401), S(463, 370), // + S(481, 399), S(491, 418), S(466, 467), S(436, 512), S(437, 506), S(433, 468), S(450, 397), S(463, 345), // + S(469, 319), S(503, 351), S(502, 420), S(465, 401), S(461, 394), S(468, 414), S(472, 356), S(457, 329), // + S(451, 193), S(495, 156), S(494, 243), S(502, 292), S(483, 321), S(485, 286), S(453, 337), S(454, 322), // + S(406, 232), S(453, 40), S(456, 68), S(483, 158), S(488, 235), S(491, 184), S(481, 215), S(431, 265), // }; inline const std::array KING_PSQT = { - S(-603, -152), S(-132, 154), S(58, 72), S(-134, 40), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // - S(23, -42), S(174, 59), S(173, 68), S(141, -12), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // - S(-42, 87), S(210, 62), S(228, 54), S(123, 19), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // - S(-293, 102), S(132, 36), S(63, 46), S(56, 34), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // - S(-298, 68), S(74, 2), S(94, 5), S(10, 39), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // - S(-153, 36), S(160, -34), S(119, -7), S(90, 12), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // - S(-4, -25), S(180, -56), S(134, -28), S(62, 7), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // - S(-189, -17), S(-18, -21), S(-107, 11), S(-110, -4), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // -}; - -// Epoch duration: 4.78127s + S(-422, -244), S(12, 87), S(161, 8), S(-89, -4), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // + S(163, -108), S(228, 38), S(187, 48), S(111, -17), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // + S(77, 36), S(249, 54), S(229, 43), S(89, 16), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // + S(-189, 58), S(153, 35), S(58, 38), S(16, 33), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // + S(-214, 32), S(81, 9), S(83, -1), S(-38, 41), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // + S(-97, 17), S(154, -17), S(104, -7), S(44, 13), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // + S(8, -20), S(131, -18), S(80, -17), S(1, 7), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // + S(-126, -35), S(-11, -9), S(-89, -12), S(-95, -48), S(0, 0), S(0, 0), S(0, 0), S(0, 0), // +}; + +inline const std::array, 4> KING_SHELTER = {{ + {{ S(-57, 29), S(4, -32), S(55, -45), S(30, -26), S(34, -26), S(53, -45), S(9, -41), }}, + {{ S(-60, 31), S(54, -20), S(68, -44), S(14, 3), S(17, -10), S(71, -54), S(52, -30), }}, + {{ S(-54, 25), S(49, -15), S(-12, -28), S(-10, -4), S(-9, -12), S(-16, -36), S(48, -19), }}, + {{ S(-46, 11), S(21, 29), S(11, 5), S(8, 9), S(15, 3), S(20, -2), S(21, 4), }}, +}}; +inline const std::array BLOCKED_SHELTER_STORM = { + S(0, 0), S(0, 0), S(-11, -85), S(40, -23), S(18, -13), S(-9, -8), S(16, 19), +}; +inline const std::array, 4> SHELTER_STORM = {{ + {{ S(-26, -5), S(7, -8), S(15, -12), S(5, 1), S(13, 9), S(6, -6), S(6, -8), }}, + {{ S(-35, 6), S(-14, -9), S(10, -7), S(-6, 27), S(4, 19), S(11, -10), S(-13, -14), }}, + {{ S(3, -9), S(29, -37), S(15, -11), S(2, 5), S(8, 9), S(17, -11), S(24, -37), }}, + {{ S(-5, 17), S(14, 12), S(35, 3), S(8, -5), S(6, -4), S(34, 7), S(27, 6), }}, +}}; +// Epoch duration: 5.04286s // clang-format on } // namespace Clockwork diff --git a/src/evaltune_main.cpp b/src/evaltune_main.cpp index d4d3a660..7390f93d 100644 --- a/src/evaltune_main.cpp +++ b/src/evaltune_main.cpp @@ -385,6 +385,24 @@ int main() { printPsqtArray("QUEEN_PSQT", QUEEN_PSQT); printPsqtArray("KING_PSQT", KING_PSQT); std::cout << std::endl; + + auto print_2d_array = [](const std::string& name, const auto& arr) { + std::cout << "inline const std::array, " + << arr.size() << "> " << name << " = {{" << std::endl; + for (const auto& subarr : arr) { + std::cout << " {{"; + for (const auto& val : subarr) { + std::cout << " " << val << ","; + } + std::cout << " }}," << std::endl; + } + std::cout << "}};" << std::endl; + }; + + print_2d_array("KING_SHELTER", KING_SHELTER); + print_table("BLOCKED_SHELTER_STORM", BLOCKED_SHELTER_STORM); + print_2d_array("SHELTER_STORM", SHELTER_STORM); + #endif const auto end = time::Clock::now(); std::cout << "// Epoch duration: " << time::cast(end - start).count() diff --git a/src/evaluation.cpp b/src/evaluation.cpp index 296f2866..b8f0acbf 100644 --- a/src/evaluation.cpp +++ b/src/evaluation.cpp @@ -104,6 +104,46 @@ std::array, 2> passed_pawn_spans = []() { return passed_pawn_masks; }(); +template +PScore king_shelter(const Position& pos) { + constexpr Color opp = ~color; + + Square king_square = pos.king_sq(color); + + Bitboard b = ~Bitboard::forward_ranks(opp, king_square); // Squares ahead or on king's rank + Bitboard our_pawns = + pos.bitboard_for(color, PieceType::Pawn) & b & ~pos.attacked_by(opp, PieceType::Pawn); + Bitboard their_pawns = pos.bitboard_for(opp, PieceType::Pawn) & b; + + PScore score = PSCORE_ZERO; + + i32 shelter_center = std::clamp(king_square.file(), 1, 6); + + for (i32 offset = -1; offset <= 1; offset++) { + i32 file = shelter_center + offset; + Bitboard file_bb = Bitboard::file_mask(file); + + // Our pawns + b = our_pawns & file_bb; + i32 our_rank = b.any() ? b.frontmost_square(opp).relative_rank(color) : 0; + + // Opponent pawns + b = their_pawns & file_bb; + i32 their_rank = b.any() ? b.frontmost_square(opp).relative_rank(color) : 0; + + i32 edge_idx = std::min(file, 7 - file); + + score += KING_SHELTER[static_cast(edge_idx)][static_cast(our_rank)]; + if (our_rank && (our_rank == their_rank - 1)) { + score += BLOCKED_SHELTER_STORM[static_cast(their_rank)]; + } else { + score += SHELTER_STORM[static_cast(edge_idx)][static_cast(their_rank)]; + } + } + + return score; +} + template PScore evaluate_pawns(const Position& pos) { constexpr i32 RANK_2 = 1; @@ -303,6 +343,9 @@ PScore evaluate_king_safety(const Position& pos) { eval += PT_OUTER_RING_ATTACKS[static_cast(pt) - static_cast(PieceType::Pawn)] * outer.ipopcount(); } + + eval += king_shelter(pos); + return eval; } diff --git a/src/square.hpp b/src/square.hpp index ea59f5c7..8bbfd2ac 100644 --- a/src/square.hpp +++ b/src/square.hpp @@ -54,6 +54,10 @@ struct Square { return c == Color::White ? *this : flip_vertical(); } + [[nodiscard]] constexpr i32 relative_rank(Color c) const { + return c == Color::White ? rank() : 7 - rank(); + } + [[nodiscard]] constexpr std::tuple to_file_and_rank() const { return {file(), rank()}; }