const std = @import("std"); const constants = @import("constants.zig"); const WHITE_TO_PLAY = true; const BLACK_TO_PLAY = false; //inline BitscanForward(const tempBitboard); const MAGIC:u64 = 0x03f79d71b4cb0a89; const DEBRUIJN64:[64]usize = [64]usize { 0, 47, 1, 56, 48, 27, 2, 60, 57, 49, 41, 37, 28, 16, 3, 61, 54, 58, 35, 52, 50, 42, 21, 44, 38, 32, 29, 23, 17, 11, 4, 62, 46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43, 31, 22, 10, 45, 25, 39, 14, 33, 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63 }; fn BitscanForward(tempBitboard:u64) usize { return @truncate(DEBRUIJN64[MAGIC *% (tempBitboard ^ (tempBitboard - 1)) >> 58]); } //fens const FEN_STARTING_POSITION = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; const PINNED_SQUARE_INDEX = 0; const PINNING_PIECE_INDEX = 1; //LSB //equation: startingSquare = (DEBRUIJN64[MAGIC * (tempBitboard ^ (tempBitboard - 1)) >> 58]); const MAX_ULONG = 18446744073709551615; const MOVE_STARTING = 0; const MOVE_TARGET = 1; const MOVE_PIECE = 2; const MOVE_TAG = 3; const SQ_CHAR_Y = [_]u8 { '8','8','8','8','8','8','8','8', '7','7','7','7','7','7','7','7', '6','6','6','6','6','6','6','6', '5','5','5','5','5','5','5','5', '4','4','4','4','4','4','4','4', '3','3','3','3','3','3','3','3', '2','2','2','2','2','2','2','2', '1','1','1','1','1','1','1','1','A' }; const SQ_CHAR_X = [_]u8 { 'a','b','c','d','e','f','g','h', 'a','b','c','d','e','f','g','h', 'a','b','c','d','e','f','g','h', 'a','b','c','d','e','f','g','h', 'a','b','c','d','e','f','g','h', 'a','b','c','d','e','f','g','h', 'a','b','c','d','e','f','g','h', 'a','b','c','d','e','f','g','h','N' }; const BLACK_PAWN_CHAR = 'p'; const BLACK_KNIGHT_CHAR = 'n'; const BLACK_BISHOP_CHAR = 'b'; const BLACK_ROOK_CHAR = 'r'; const BLACK_QUEEN_CHAR = 'q'; const BLACK_KING_CHAR = 'k'; const WHITE_PAWN_CHAR = 'P'; const WHITE_KNIGHT_CHAR = 'N'; const WHITE_BISHOP_CHAR = 'B'; const WHITE_ROOK_CHAR = 'R'; const WHITE_QUEEN_CHAR = 'Q'; const WHITE_KING_CHAR = 'K'; const DUCK_CHAR = 'D'; const BRACKET_CHAR = '/'; const SPACE_CHAR = ' '; const DASH_CHAR = '-'; const W_SIDE_CHAR = 'w'; const B_SIDE_CHAR = 'b'; const CAPITAL_K_CHAR = 'K'; const CAPITAL_Q_CHAR = 'Q'; const SMALL_K_CHAR = 'k'; const SMALL_Q_CHAR = 'q'; const BITBOARD_COUNT = 12; const WKS_CASTLE_RIGHTS = 0; const WQS_CASTLE_RIGHTS = 1; const BKS_CASTLE_RIGHTS = 2; const BQS_CASTLE_RIGHTS = 3; const WP = 0; const WN = 1; const WB = 2; const WR = 3; const WQ = 4; const WK = 5; const BP = 6; const BN = 7; const BB = 8; const BR = 9; const BQ = 10; const BK = 11; const WHITE_PAWN_ATTACKS = [_]u64 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 10, 20, 40, 80, 160,64, 512, 1280, 2560, 5120, 10240, 20480, 40960, 16384, 131072, 327680, 655360, 1310720,2621440,5242880,10485760,4194304, 33554432,83886080,167772160,335544320,671088640,1342177280,2684354560,1073741824, 8589934592,21474836480,42949672960,85899345920,171798691840,343597383680,687194767360,274877906944, 2199023255552,5497558138880,10995116277760,21990232555520,43980465111040,87960930222080,175921860444160,70368744177664, 562949953421312,1407374883553280,2814749767106560,5629499534213120,11258999068426240,22517998136852480,45035996273704960,18014398509481984, }; const BLACK_PAWN_ATTACKS = [_]u64 { 512,1280,2560,5120,10240,20480,40960,16384, 131072,327680,655360,1310720,2621440,5242880,10485760,4194304, 33554432,83886080,167772160,335544320,671088640,1342177280,2684354560,1073741824, 8589934592,21474836480,42949672960,85899345920,171798691840,343597383680,687194767360,274877906944, 2199023255552,5497558138880,10995116277760,21990232555520,43980465111040,87960930222080,175921860444160,70368744177664, 562949953421312,1407374883553280,2814749767106560,5629499534213120,11258999068426240,22517998136852480,45035996273704960,18014398509481984, 144115188075855872,360287970189639680,720575940379279360,1441151880758558720,2882303761517117440,5764607523034234880,11529215046068469760,4611686018427387904, 0,0,0,0,0,0,0,0, }; const KNIGHT_ATTACKS = [_]u64 { 132096, 329728, 659712, 1319424, 2638848, 5277696, 10489856, 4202496, 33816580, 84410376, 168886289, 337772578, 675545156, 1351090312, 2685403152, 1075839008, 8657044482, 21609056261, 43234889994, 86469779988, 172939559976, 345879119952, 687463207072, 275414786112, 2216203387392, 5531918402816, 11068131838464, 22136263676928, 44272527353856, 88545054707712, 175990581010432, 70506185244672, 567348067172352, 1416171111120896, 2833441750646784, 5666883501293568, 11333767002587136, 22667534005174272, 45053588738670592, 18049583422636032, 145241105196122112, 362539804446949376, 725361088165576704, 1450722176331153408, 2901444352662306816, 5802888705324613632, 11533718717099671552, 4620693356194824192, 288234782788157440, 576469569871282176, 1224997833292120064, 2449995666584240128, 4899991333168480256, 9799982666336960512, 1152939783987658752, 2305878468463689728, 1128098930098176, 2257297371824128, 4796069720358912, 9592139440717824, 19184278881435648, 38368557762871296, 4679521487814656, 9077567998918656, }; const BISHOP_MASKS = [_]u64 { 18049651735527936, 70506452091904, 275415828992, 1075975168, 38021120, 8657588224, 2216338399232, 567382630219776, 9024825867763712, 18049651735527424, 70506452221952, 275449643008, 9733406720, 2216342585344, 567382630203392, 1134765260406784, 4512412933816832, 9024825867633664, 18049651768822272, 70515108615168, 2491752130560, 567383701868544, 1134765256220672, 2269530512441344, 2256206450263040, 4512412900526080, 9024834391117824, 18051867805491712, 637888545440768, 1135039602493440, 2269529440784384, 4539058881568768, 1128098963916800, 2256197927833600, 4514594912477184, 9592139778506752, 19184279556981248, 2339762086609920, 4538784537380864, 9077569074761728, 562958610993152, 1125917221986304, 2814792987328512, 5629586008178688, 11259172008099840, 22518341868716544, 9007336962655232, 18014673925310464, 2216338399232, 4432676798464, 11064376819712, 22137335185408, 44272556441600, 87995357200384, 35253226045952, 70506452091904, 567382630219776, 1134765260406784, 2832480465846272, 5667157807464448, 11333774449049600, 22526811443298304, 9024825867763712, 18049651735527936 }; const ROOK_MASKS = [_]u64 { 282578800148862, 565157600297596, 1130315200595066, 2260630401190006, 4521260802379886, 9042521604759646, 18085043209519166, 36170086419038334, 282578800180736, 565157600328704, 1130315200625152, 2260630401218048, 4521260802403840, 9042521604775424, 18085043209518592, 36170086419037696, 282578808340736, 565157608292864, 1130315208328192, 2260630408398848, 4521260808540160, 9042521608822784, 18085043209388032, 36170086418907136, 282580897300736, 565159647117824, 1130317180306432, 2260632246683648, 4521262379438080, 9042522644946944, 18085043175964672, 36170086385483776, 283115671060736, 565681586307584, 1130822006735872, 2261102847592448, 4521664529305600, 9042787892731904, 18085034619584512, 36170077829103616, 420017753620736, 699298018886144, 1260057572672512, 2381576680245248, 4624614895390720, 9110691325681664, 18082844186263552, 36167887395782656, 35466950888980736, 34905104758997504, 34344362452452352, 33222877839362048, 30979908613181440, 26493970160820224, 17522093256097792, 35607136465616896, 9079539427579068672, 8935706818303361536, 8792156787827803136, 8505056726876686336, 7930856604974452736, 6782456361169985536, 4485655873561051136, 9115426935197958144 }; const ROOK_MAGIC_NUMBERS = [_]u64 { 0x8a80104000800020, 0x140002000100040, 0x2801880a0017001, 0x100081001000420, 0x200020010080420, 0x3001c0002010008, 0x8480008002000100, 0x2080088004402900, 0x800098204000, 0x2024401000200040, 0x100802000801000, 0x120800800801000, 0x208808088000400, 0x2802200800400, 0x2200800100020080, 0x801000060821100, 0x80044006422000, 0x100808020004000, 0x12108a0010204200, 0x140848010000802, 0x481828014002800, 0x8094004002004100, 0x4010040010010802, 0x20008806104, 0x100400080208000, 0x2040002120081000, 0x21200680100081, 0x20100080080080, 0x2000a00200410, 0x20080800400, 0x80088400100102, 0x80004600042881, 0x4040008040800020, 0x440003000200801, 0x4200011004500, 0x188020010100100, 0x14800401802800, 0x2080040080800200, 0x124080204001001, 0x200046502000484, 0x480400080088020, 0x1000422010034000, 0x30200100110040, 0x100021010009, 0x2002080100110004, 0x202008004008002, 0x20020004010100, 0x2048440040820001, 0x101002200408200, 0x40802000401080, 0x4008142004410100, 0x2060820c0120200, 0x1001004080100, 0x20c020080040080, 0x2935610830022400, 0x44440041009200, 0x280001040802101, 0x2100190040002085, 0x80c0084100102001, 0x4024081001000421, 0x20030a0244872, 0x12001008414402, 0x2006104900a0804, 0x1004081002402 }; const BISHOP_MAGIC_NUMBERS = [_]u64 { 0x40040844404084, 0x2004208a004208, 0x10190041080202, 0x108060845042010, 0x581104180800210, 0x2112080446200010, 0x1080820820060210, 0x3c0808410220200, 0x4050404440404, 0x21001420088, 0x24d0080801082102, 0x1020a0a020400, 0x40308200402, 0x4011002100800, 0x401484104104005, 0x801010402020200, 0x400210c3880100, 0x404022024108200, 0x810018200204102, 0x4002801a02003, 0x85040820080400, 0x810102c808880400, 0xe900410884800, 0x8002020480840102, 0x220200865090201, 0x2010100a02021202, 0x152048408022401, 0x20080002081110, 0x4001001021004000, 0x800040400a011002, 0xe4004081011002, 0x1c004001012080, 0x8004200962a00220, 0x8422100208500202, 0x2000402200300c08, 0x8646020080080080, 0x80020a0200100808, 0x2010004880111000, 0x623000a080011400, 0x42008c0340209202, 0x209188240001000, 0x400408a884001800, 0x110400a6080400, 0x1840060a44020800, 0x90080104000041, 0x201011000808101, 0x1a2208080504f080, 0x8012020600211212, 0x500861011240000, 0x180806108200800, 0x4000020e01040044, 0x300000261044000a, 0x802241102020002, 0x20906061210001, 0x5a84841004010310, 0x4010801011c04, 0xa010109502200, 0x4a02012000, 0x500201010098b028, 0x8040002811040900, 0x28000010020204, 0x6000020202d0240, 0x8918844842082200, 0x4010011029020020 }; const BISHOP_REL_BITS =[_]usize { 6 ,5 ,5 ,5 ,5 ,5 ,5 ,6 , 5 ,5 ,5 ,5 ,5 ,5 ,5 ,5 , 5 ,5 ,7 ,7 ,7 ,7 ,5 ,5 , 5 ,5 ,7 ,9 ,9 ,7 ,5 ,5 , 5 ,5 ,7 ,9 ,9 ,7 ,5 ,5 , 5 ,5 ,7 ,7 ,7 ,7 ,5 ,5 , 5 ,5 ,5 ,5 ,5 ,5 ,5 ,5 , 6 ,5 ,5 ,5 ,5 ,5 ,5 ,6 , }; const ROOK_REL_BITS = [_]usize { 12 ,11 ,11 ,11 ,11 ,11 ,11 ,12 , 11 ,10 ,10 ,10 ,10 ,10 ,10 ,11 , 11 ,10 ,10 ,10 ,10 ,10 ,10 ,11 , 11 ,10 ,10 ,10 ,10 ,10 ,10 ,11 , 11 ,10 ,10 ,10 ,10 ,10 ,10 ,11 , 11 ,10 ,10 ,10 ,10 ,10 ,10 ,11 , 11 ,10 ,10 ,10 ,10 ,10 ,10 ,11 , 12 ,11 ,11 ,11 ,11 ,11 ,11 ,12 , }; const KING_ATTACKS = [_]u64 { 770, 1797, 3594, 7188, 14376, 28752, 57504, 49216, 197123, 460039, 920078, 1840156, 3680312, 7360624, 14721248, 12599488, 50463488, 117769984, 235539968, 471079936, 942159872, 1884319744, 3768639488, 3225468928, 12918652928, 30149115904, 60298231808, 120596463616, 241192927232, 482385854464, 964771708928, 825720045568, 3307175149568, 7718173671424, 15436347342848, 30872694685696, 61745389371392, 123490778742784, 246981557485568, 211384331665408, 846636838289408, 1975852459884544, 3951704919769088, 7903409839538176, 15806819679076352, 31613639358152704, 63227278716305408, 54114388906344448, 216739030602088448, 505818229730443264, 1011636459460886528, 2023272918921773056, 4046545837843546112, 8093091675687092224, 16186183351374184448, 13853283560024178688, 144959613005987840, 362258295026614272, 724516590053228544, 1449033180106457088, 2898066360212914176, 5796132720425828352, 11592265440851656704, 4665729213955833856, }; const SQUARE_BBS = [_]u64 { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648, 4294967296, 8589934592, 17179869184, 34359738368, 68719476736, 137438953472, 274877906944, 549755813888, 1099511627776, 2199023255552, 4398046511104, 8796093022208, 17592186044416, 35184372088832, 70368744177664, 140737488355328, 281474976710656, 562949953421312, 1125899906842624, 2251799813685248, 4503599627370496, 9007199254740992, 18014398509481984, 36028797018963968, 72057594037927936, 144115188075855872, 288230376151711744, 576460752303423488, 1152921504606846976, 2305843009213693952, 4611686018427387904, 9223372036854775808, }; const RANK_1_BITBOARD = 18374686479671623680; const RANK_2_BITBOARD = 71776119061217280; const RANK_3_BITBOARD = 280375465082880; const RANK_4_BITBOARD = 1095216660480; const RANK_5_BITBOARD = 4278190080; const RANK_6_BITBOARD = 16711680; const RANK_7_BITBOARD = 65280; const RANK_8_BITBOARD = 255; const FILE_A_BITBOARD = 72340172838076673; const FILE_B_BITBOARD = 144680345676153346; const FILE_C_BITBOARD = 289360691352306692; const FILE_D_BITBOARD = 578721382704613384; const FILE_E_BITBOARD = 1157442765409226768; const FILE_F_BITBOARD = 2314885530818453536; const FILE_G_BITBOARD = 4629771061636907072; const FILE_H_BITBOARD = 9259542123273814144; const FILE_TO_SQUARE_BBS = [_]u64 { 72340172838076673, 144680345676153346, 289360691352306692, 578721382704613384, 1157442765409226768, 2314885530818453536, 4629771061636907072, 9259542123273814144, 72340172838076673, 144680345676153346, 289360691352306692, 578721382704613384, 1157442765409226768, 2314885530818453536, 4629771061636907072, 9259542123273814144, 72340172838076673, 144680345676153346, 289360691352306692, 578721382704613384, 1157442765409226768, 2314885530818453536, 4629771061636907072, 9259542123273814144, 72340172838076673, 144680345676153346, 289360691352306692, 578721382704613384, 1157442765409226768, 2314885530818453536, 4629771061636907072, 9259542123273814144, 72340172838076673, 144680345676153346, 289360691352306692, 578721382704613384, 1157442765409226768, 2314885530818453536, 4629771061636907072, 9259542123273814144, 72340172838076673, 144680345676153346, 289360691352306692, 578721382704613384, 1157442765409226768, 2314885530818453536, 4629771061636907072, 9259542123273814144, 72340172838076673, 144680345676153346, 289360691352306692, 578721382704613384, 1157442765409226768, 2314885530818453536, 4629771061636907072, 9259542123273814144, 72340172838076673, 144680345676153346, 289360691352306692, 578721382704613384, 1157442765409226768, 2314885530818453536, 4629771061636907072, 9259542123273814144, }; pub inline fn GetBishopAttacksFast(startingSquare: usize, occupancy: u64) u64 { var mutableOccupancy: u64 = occupancy; const shiftAmount: u64 = 64 - BISHOP_REL_BITS[startingSquare]; mutableOccupancy &= BISHOP_MASKS[startingSquare]; mutableOccupancy *%= BISHOP_MAGIC_NUMBERS[startingSquare]; mutableOccupancy >>= @truncate(shiftAmount); return constants.BISHOP_ATTACKS[startingSquare][@truncate(mutableOccupancy)]; } pub inline fn GetRookAttacksFast(startingSquare: usize, occupancy: u64) u64 { var mutableOccupancy: u64 = occupancy; const shiftAmount: u64 = 64 - ROOK_REL_BITS[startingSquare]; mutableOccupancy &= ROOK_MASKS[startingSquare]; mutableOccupancy *%= ROOK_MAGIC_NUMBERS[startingSquare]; mutableOccupancy >>= @truncate(shiftAmount); return constants.ROOK_ATTACKS[startingSquare][@truncate(mutableOccupancy)]; } const WHITE_START_INDEX = WP; const WHITE_END_INDEX = WK; const BLACK_START_INDEX = BP; const BLACK_END_INDEX = BK; const TAG_NONE = 0; const TAG_CAPTURE = 1; const TAG_WHITEEP = 2; const TAG_BLACKEP = 3; const TAG_WCASTLEKS = 4; const TAG_WCASTLEQS = 5; const TAG_BCASTLEKS = 6; const TAG_BCASTLEQS = 7; const TAG_BKnightPromotion = 8; const TAG_BBishopPromotion = 9; const TAG_BQueenPromotion = 10; const TAG_BRookPromotion = 11; const TAG_WKnightPromotion = 12; const TAG_WBishopPromotion = 13; const TAG_WQueenPromotion = 14; const TAG_WRookPromotion = 15; const TAG_BCaptureKnightPromotion = 16; const TAG_BCaptureBishopPromotion = 17; const TAG_BCaptureQueenPromotion = 18; const TAG_BCaptureRookPromotion = 19; const TAG_WCaptureKnightPromotion = 20; const TAG_WCaptureBishopPromotion = 21; const TAG_WCaptureQueenPromotion = 22; const TAG_WCaptureRookPromotion = 23; const TAG_DoublePawnWhite = 24; const TAG_DoublePawnBlack = 25; const TAG_CHECK = 26; const TAG_CHECK_CAPTURE = 27; const PROMOTION_START = TAG_BKnightPromotion; const PROMOTION_END_INCLUSIVE = TAG_WCaptureRookPromotion; const A8 = 0; const B8 = 1; const C8 = 2; const D8 = 3; const E8 = 4; const F8 = 5; const G8 = 6; const H8 = 7; const A7 = 8; const B7 = 9; const C7 = 10; const D7 = 11; const E7 = 12; const F7 = 13; const G7 = 14; const H7 = 15; const A6 = 16; const B6 = 17; const C6 = 18; const D6 = 19; const E6 = 20; const F6 = 21; const G6 = 22; const H6 = 23; const A5 = 24; const B5 = 25; const C5 = 26; const D5 = 27; const E5 = 28; const F5 = 29; const G5 = 30; const H5 = 31; const A4 = 32; const B4 = 33; const C4 = 34; const D4 = 35; const E4 = 36; const F4 = 37; const G4 = 38; const H4 = 39; const A2 = 48; const B2 = 49; const C2 = 50; const D2 = 51; const E2 = 52; const F2 = 53; const G2 = 54; const H2 = 55; const A1 = 56; const B1 = 57; const C1 = 58; const D1 = 59; const E1 = 60; const F1 = 61; const G1 = 62; const H1 = 63; const NO_SQUARE = 64; const WKS_EMPTY_BITBOARD = 6917529027641081856; const WQS_EMPTY_BITBOARD = 1008806316530991104; const BKS_EMPTY_BITBOARD = 96; const BQS_EMPTY_BITBOARD = 14; const COMBINED_OCCUPANCIES = 0; const WHITE_OCCUPANCIES = 1; const BLACK_OCCUPANCIES = 2; var bitboard_array_global: [12]u64 = undefined; var occupancies_global: [3]u64 = undefined; var ep_global: usize = undefined; var castle_rights_global: [4]bool = undefined; var is_white_global: bool = true; //struct Board { // pieceArray[12]; // occupancies[3]; // isWhite; // ep; // castleRights[4]; //}; const PIECE_PHASE = 0; const SIDE_PHASE = 1; const CASTLE_PHASE = 2; const EP_PHASE = 3; const FIFTY_MOVE_PHASE = 4; const MOVE_COUNT_PHASE = 5; const PIECE_COLOURS = [_]u8 { 'W','W','W','W','W','W','b','b','b','b','b','b' }; const PIECE_CHARS = [_]u8 { 'P','N','B','R','Q','K','p','n','b','r','q','k' }; fn ResetBoardGlobal() void { castle_rights_global[0] = false; castle_rights_global[1] = false; castle_rights_global[2] = false; castle_rights_global[3] = false; for (0..BITBOARD_COUNT) |i| { bitboard_array_global[i] = 0; } is_white_global = true; ep_global = NO_SQUARE; } fn ParseFenGlobal(input:[]const u8, starting_index:usize) void { ResetBoardGlobal(); const inputLength = input.len; if (starting_index >= inputLength) { return; } if (starting_index < 0) { return; } var currentPhase:usize = PIECE_PHASE; var bracketCount:usize = 0; var squareCount:usize = 0; var epX:usize = NO_SQUARE; var epY:usize = NO_SQUARE; for (0..inputLength) |characterIndex| { const characterInFen = input[characterIndex]; switch (currentPhase) { 0=> { if (bracketCount == 7 and characterInFen == ' ') { //prf(" next phase brackcount = 7, is empty\n"); currentPhase+=1; } else { if (bracketCount > 7) { bracketCount = 0; } if (squareCount > 7) { squareCount = 0; } const square:usize = (bracketCount * 8) + squareCount; switch (characterInFen) { 'B' => { //prf(" W bishop found %d\n", square); bitboard_array_global[WB] |= SQUARE_BBS[square]; squareCount+=1; }, 'R' => { //prf(" WR found\n"); bitboard_array_global[WR] |= SQUARE_BBS[square]; squareCount+=1; }, 'P' => { //prf(" add white pawn %d\n", square); bitboard_array_global[WP] |= SQUARE_BBS[square]; squareCount+=1; }, 'Q'=>{ //prf(" WQ found\n"); bitboard_array_global[WQ] |= SQUARE_BBS[square]; squareCount+=1; }, 'K'=>{ //prf(" WK\n"); bitboard_array_global[WK] |= SQUARE_BBS[square]; squareCount+=1; }, 'N'=>{ //prf(" WN found\n"); bitboard_array_global[WN] |= SQUARE_BBS[square]; squareCount+=1; }, 'b'=>{ //prf(" BB found\n"); bitboard_array_global[BB] |= SQUARE_BBS[square]; squareCount+=1; }, 'p'=>{ //prf(" BP sq: %d\n", square); bitboard_array_global[BP] |= SQUARE_BBS[square]; squareCount+=1; }, 'q'=>{ //prf(" BQ sq: %d\n", square); bitboard_array_global[BQ] |= SQUARE_BBS[square]; squareCount+=1; }, 'r'=>{ //prf(" BR sq: %d\n", square); bitboard_array_global[BR] |= SQUARE_BBS[square]; squareCount+=1; }, 'n'=>{ //prf(" BN sq: %d\n", square); bitboard_array_global[BN] |= SQUARE_BBS[square]; squareCount+=1; }, 'k'=>{ //prf(" BK sq: %d\n", square); bitboard_array_global[BK] |= SQUARE_BBS[square]; squareCount+=1; }, '/'=>{ //prf(" forward bracket slash\n", square); squareCount = 0; bracketCount+=1; }, '1'=>{ //prf(" 1 found\n"); squareCount += 1; }, '2'=>{ //prf(" 2 found\n"); squareCount += 2; }, '3'=>{ //prf(" 3 found\n"); squareCount += 3; }, '4'=>{ //prf(" 4 found\n"); squareCount += 4; }, '5'=>{ //prf(" 5 found\n"); squareCount += 5; }, '6'=>{ //prf(" 6 found\n"); squareCount += 6; }, '7'=>{ //prf(" 7 found\n"); squareCount += 7; }, '8'=>{ //prf(" 8 found\n"); squareCount += 8; }, else => { unreachable; } } } }, 1 => { if (characterInFen == 'w') { is_white_global = true; } else if (characterInFen == 'b') { is_white_global = false; } else if (characterInFen == ' ') { currentPhase+=1; } break; }, 2 => { switch (characterInFen) { 'K'=>{ castle_rights_global[0] = true; }, 'Q'=>{ castle_rights_global[1] = true; }, 'k'=>{ castle_rights_global[2] = true; }, 'q'=>{ castle_rights_global[3] = true; }, '-'=>{ }, ' '=>{ currentPhase+=1; }, else => { } } }, 3 => { if (characterInFen == ' ') { if (epX != -1) { if (epY != -1) { ep_global = (epY * 8) + epX; } } currentPhase+=1; } else { switch (characterInFen) { 'a' => { epX = 0; }, 'b' =>{ epX = 1; }, 'c'=>{ epX = 2; }, 'd'=>{ epX = 3; }, 'e'=>{ epX = 4; }, 'f'=>{ epX = 5; }, 'g'=>{ epX = 6; }, 'h'=>{ epX = 7; }, '1'=>{ epY = 7; }, '2'=>{ epY = 6; }, '3'=>{ epY = 5; }, '4'=>{ epY = 4; }, '5'=>{ epY = 3; }, '6'=>{ epY = 2; }, '7'=>{ epY = 1; }, '8'=>{ epY = 0; }, else => { unreachable; } } } }, 4 =>{ }, 5 => { }, else => { unreachable; }, } } } fn Is_Square_Attacked_By_Black_Global(square:usize, occupancy: u64) bool { if ((bitboard_array_global[BP] & WHITE_PAWN_ATTACKS[square]) != 0) { return true; } if ((bitboard_array_global[BN] & KNIGHT_ATTACKS[square]) != 0) { return true; } if ((bitboard_array_global[BK] & KING_ATTACKS[square]) != 0) { return true; } const bishopAttacks = GetBishopAttacksFast(square, occupancy); if ((bitboard_array_global[BB] & bishopAttacks) != 0) { return true; } if ((bitboard_array_global[BQ] & bishopAttacks) != 0) { return true; } const rookAttacks = GetRookAttacksFast(square, occupancy); if ((bitboard_array_global[BR] & rookAttacks) != 0) { return true; } if ((bitboard_array_global[BQ] & rookAttacks) != 0) { return true; } return false; } fn Is_Square_Attacked_By_White_Global(square:usize, occupancy:u64) bool { if ((bitboard_array_global[WP] & BLACK_PAWN_ATTACKS[square]) != 0) { return true; } if ((bitboard_array_global[WN] & KNIGHT_ATTACKS[square]) != 0) { return true; } if ((bitboard_array_global[WK] & KING_ATTACKS[square]) != 0) { return true; } const bishopAttacks = GetBishopAttacksFast(square, occupancy); if ((bitboard_array_global[WB] & bishopAttacks) != 0) { return true; } if ((bitboard_array_global[WQ] & bishopAttacks) != 0) { return true; } const rookAttacks = GetRookAttacksFast(square, occupancy); if ((bitboard_array_global[WR] & rookAttacks) != 0) { return true; } if ((bitboard_array_global[WQ] & rookAttacks) != 0) { return true; } return false; } fn OutOfBounds(move:usize) bool { if (move > 63) { return true; } return false; } fn PrMoveNoNL(starting_square:usize, target_square:usize) void { //starting if (OutOfBounds(starting_square) == true) { std.debug.print("{}", .{starting_square}); } else { std.debug.print("{c}{c}", .{SQ_CHAR_X[starting_square], SQ_CHAR_Y[starting_square]}); } if (OutOfBounds(target_square) == true) { std.debug.print("{}", .{target_square}); } else { std.debug.print("{c}{c}", .{SQ_CHAR_X[target_square], SQ_CHAR_Y[target_square]}); } } fn PerftInlineGlobalOcc(depth:i8, ply:u8) usize { //if (depth == 0) //{ // return 1; //} var move_list:[250][4]usize = undefined; var move_count:usize = 0; //Move generating variables const WHITE_OCCUPANCIES_LOCAL:u64 = bitboard_array_global[0] | bitboard_array_global[1] | bitboard_array_global[2] | bitboard_array_global[3] | bitboard_array_global[4] | bitboard_array_global[5]; const BLACK_OCCUPANCIES_LOCAL:u64 = bitboard_array_global[6] | bitboard_array_global[7] | bitboard_array_global[8] | bitboard_array_global[9] | bitboard_array_global[10] | bitboard_array_global[11]; const COMBINED_OCCUPANCIES_LOCAL:u64 = WHITE_OCCUPANCIES_LOCAL | BLACK_OCCUPANCIES_LOCAL; const EMPTY_OCCUPANCIES:u64 = ~COMBINED_OCCUPANCIES_LOCAL; var temp_bitboard:u64 = undefined; var check_bitboard:u64 = 0; var temp_pin_bitboard:u64 = undefined; var temp_attack:u64 = undefined; var temp_empty:u64 = undefined; var temp_captures:u64 = undefined; var starting_square:usize = NO_SQUARE; var target_square:usize = NO_SQUARE; var pinArray:[8][2]usize = [8][2]usize { [_]usize{ NO_SQUARE, NO_SQUARE }, [_]usize{ NO_SQUARE, NO_SQUARE }, [_]usize{ NO_SQUARE, NO_SQUARE }, [_]usize{ NO_SQUARE, NO_SQUARE }, [_]usize{ NO_SQUARE, NO_SQUARE }, [_]usize{ NO_SQUARE, NO_SQUARE }, [_]usize{ NO_SQUARE, NO_SQUARE }, [_]usize{ NO_SQUARE, NO_SQUARE}, }; var pinNumber:usize = 0; if (is_white_global == true) { var whiteKingCheckCount:usize = 0; const whiteKingPosition:usize = (DEBRUIJN64[MAGIC *% (bitboard_array_global[WK] ^ (bitboard_array_global[WK] - 1)) >> 58]); //pawns temp_bitboard = bitboard_array_global[BP] & WHITE_PAWN_ATTACKS[whiteKingPosition]; if (temp_bitboard != 0) { const pawn_square:usize = @intCast(DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); if (check_bitboard == 0) { check_bitboard = SQUARE_BBS[pawn_square]; } whiteKingCheckCount+=1; } //knights temp_bitboard = bitboard_array_global[BN] & KNIGHT_ATTACKS[whiteKingPosition]; if (temp_bitboard != 0) { const knight_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); if (knight_square != -1) { if (check_bitboard == 0) { check_bitboard = SQUARE_BBS[knight_square]; } } whiteKingCheckCount+=1; } //bishops const bishopAttacksChecks = GetBishopAttacksFast(whiteKingPosition, BLACK_OCCUPANCIES_LOCAL); temp_bitboard = bitboard_array_global[BB] & bishopAttacksChecks; while (temp_bitboard != 0) { const piece_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES_LOCAL; if (temp_pin_bitboard == 0) { if (check_bitboard == 0) { check_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square]; } whiteKingCheckCount+=1; } else { const pinned_square = (DEBRUIJN64[MAGIC *% (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); temp_pin_bitboard &= temp_pin_bitboard - 1; if (temp_pin_bitboard == 0) { pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; pinNumber+=1; } } temp_bitboard &= temp_bitboard - 1; } //queen temp_bitboard = bitboard_array_global[BQ] & bishopAttacksChecks; while (temp_bitboard != 0) { const piece_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES_LOCAL; if (temp_pin_bitboard == 0) { if (check_bitboard == 0) { check_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square]; } whiteKingCheckCount+=1; } else { const pinned_square = (DEBRUIJN64[MAGIC *% (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); temp_pin_bitboard &= temp_pin_bitboard - 1; if (temp_pin_bitboard == 0) { pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; pinNumber+=1; } } temp_bitboard &= temp_bitboard - 1; } //rook const rook_attacks = GetRookAttacksFast(whiteKingPosition, BLACK_OCCUPANCIES_LOCAL); temp_bitboard = bitboard_array_global[BR] & rook_attacks; while (temp_bitboard != 0) { const piece_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES_LOCAL; if (temp_pin_bitboard == 0) { if (check_bitboard == 0) { check_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square]; } whiteKingCheckCount+=1; } else { const pinned_square = (DEBRUIJN64[MAGIC *% (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); temp_pin_bitboard &= temp_pin_bitboard - 1; if (temp_pin_bitboard == 0) { pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; pinNumber+=1; } } temp_bitboard &= temp_bitboard - 1; } //queen temp_bitboard = bitboard_array_global[BQ] & rook_attacks; while (temp_bitboard != 0) { const piece_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); if (piece_square == -1) { break; } temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES_LOCAL; if (temp_pin_bitboard == 0) { if (check_bitboard == 0) { check_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square]; } whiteKingCheckCount+=1; } else { const pinned_square = (DEBRUIJN64[MAGIC *% (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); temp_pin_bitboard &= temp_pin_bitboard - 1; if (temp_pin_bitboard == 0) { pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; pinNumber+=1; } } temp_bitboard &= temp_bitboard - 1; } if (whiteKingCheckCount > 1) { const occupanciesWithoutWhiteKing = COMBINED_OCCUPANCIES_LOCAL & (~bitboard_array_global[WK]); temp_attack = KING_ATTACKS[whiteKingPosition]; temp_empty = temp_attack & EMPTY_OCCUPANCIES; while (temp_empty != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_empty ^ (temp_empty - 1)) >> 58]); temp_empty &= temp_empty - 1; if ((bitboard_array_global[BP] & WHITE_PAWN_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[BN] & KNIGHT_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[BK] & KING_ATTACKS[target_square]) != 0) { continue; } const bishopAttacks = GetBishopAttacksFast(target_square, occupanciesWithoutWhiteKing); if ((bitboard_array_global[BB] & bishopAttacks) != 0) { continue; } if ((bitboard_array_global[BQ] & bishopAttacks) != 0) { continue; } const rookAttacks = GetRookAttacksFast(target_square, occupanciesWithoutWhiteKing); if ((bitboard_array_global[BR] & rookAttacks) != 0) { continue; } if ((bitboard_array_global[BQ] & rookAttacks) != 0) { continue; } move_list[move_count][MOVE_STARTING] = whiteKingPosition; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = WK; move_count+=1; } //captures temp_captures = temp_attack & BLACK_OCCUPANCIES_LOCAL; while (temp_captures != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_captures ^ (temp_captures - 1)) >> 58]); temp_captures &= temp_captures - 1; if ((bitboard_array_global[BP] & WHITE_PAWN_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[BN] & KNIGHT_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[BK] & KING_ATTACKS[target_square]) != 0) { continue; } const bishopAttacks = GetBishopAttacksFast(target_square, occupanciesWithoutWhiteKing); if ((bitboard_array_global[BB] & bishopAttacks) != 0) { continue; } if ((bitboard_array_global[BQ] & bishopAttacks) != 0) { continue; } const rookAttacks = GetRookAttacksFast(target_square, occupanciesWithoutWhiteKing); if ((bitboard_array_global[BR] & rookAttacks) != 0) { continue; } if ((bitboard_array_global[BQ] & rookAttacks) != 0) { continue; } move_list[move_count][MOVE_STARTING] = whiteKingPosition; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = WK; move_count+=1; } } else { if (whiteKingCheckCount == 0) { check_bitboard = MAX_ULONG; } const occupanciesWithoutWhiteKing = COMBINED_OCCUPANCIES_LOCAL & (~bitboard_array_global[WK]); temp_attack = KING_ATTACKS[whiteKingPosition]; temp_empty = temp_attack & EMPTY_OCCUPANCIES; while (temp_empty != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_empty ^ (temp_empty - 1)) >> 58]); temp_empty &= temp_empty - 1; if ((bitboard_array_global[BP] & WHITE_PAWN_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[BN] & KNIGHT_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[BK] & KING_ATTACKS[target_square]) != 0) { continue; } const bishopAttacks = GetBishopAttacksFast(target_square, occupanciesWithoutWhiteKing); if ((bitboard_array_global[BB] & bishopAttacks) != 0) { continue; } if ((bitboard_array_global[BQ] & bishopAttacks) != 0) { continue; } const rookAttacks = GetRookAttacksFast(target_square, occupanciesWithoutWhiteKing); if ((bitboard_array_global[BR] & rookAttacks) != 0) { continue; } if ((bitboard_array_global[BQ] & rookAttacks) != 0) { continue; } move_list[move_count][MOVE_STARTING] = whiteKingPosition; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = WK; move_count+=1; } //captures temp_captures = temp_attack & BLACK_OCCUPANCIES_LOCAL; while (temp_captures != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_captures ^ (temp_captures - 1)) >> 58]); temp_captures &= temp_captures - 1; if ((bitboard_array_global[BP] & WHITE_PAWN_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[BN] & KNIGHT_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[BK] & KING_ATTACKS[target_square]) != 0) { continue; } const bishopAttacks = GetBishopAttacksFast(target_square, occupanciesWithoutWhiteKing); if ((bitboard_array_global[BB] & bishopAttacks) != 0) { continue; } if ((bitboard_array_global[BQ] & bishopAttacks) != 0) { continue; } const rookAttacks = GetRookAttacksFast(target_square, occupanciesWithoutWhiteKing); if ((bitboard_array_global[BR] & rookAttacks) != 0) { continue; } if ((bitboard_array_global[BQ] & rookAttacks) != 0) { continue; } move_list[move_count][MOVE_STARTING] = whiteKingPosition; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = WK; move_count+=1; } if (whiteKingCheckCount == 0) { if (castle_rights_global[WKS_CASTLE_RIGHTS] == true) { if (whiteKingPosition == E1) //king on e1 { if ((WKS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES_LOCAL) == 0) //f1 and g1 empty { if ((bitboard_array_global[WR] & SQUARE_BBS[H1]) != 0) //rook on h1 { if (Is_Square_Attacked_By_Black_Global(F1, COMBINED_OCCUPANCIES_LOCAL) == false) { if (Is_Square_Attacked_By_Black_Global(G1, COMBINED_OCCUPANCIES_LOCAL) == false) { move_list[move_count][MOVE_STARTING] = E1; move_list[move_count][MOVE_TARGET] = G1; move_list[move_count][MOVE_TAG] = TAG_WCASTLEKS; move_list[move_count][MOVE_PIECE] = WK; move_count+=1; } } } } } } if (castle_rights_global[WQS_CASTLE_RIGHTS] == true) { if (whiteKingPosition == E1) //king on e1 { if ((WQS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES_LOCAL) == 0) //f1 and g1 empty { if ((bitboard_array_global[WR] & SQUARE_BBS[A1]) != 0) //rook on h1 { if (Is_Square_Attacked_By_Black_Global(C1, COMBINED_OCCUPANCIES_LOCAL) == false) { if (Is_Square_Attacked_By_Black_Global(D1, COMBINED_OCCUPANCIES_LOCAL) == false) { move_list[move_count][MOVE_STARTING] = E1; move_list[move_count][MOVE_TARGET] = C1; move_list[move_count][MOVE_TAG] = TAG_WCASTLEQS; move_list[move_count][MOVE_PIECE] = WK; move_count+=1; } } } } } } } temp_bitboard = bitboard_array_global[WN]; while (temp_bitboard != 0) { starting_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_bitboard &= temp_bitboard - 1; //removes the knight from that square to not infinitely loop temp_pin_bitboard = MAX_ULONG; if (pinNumber != 0) { for (0..pinNumber) |i| { if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square) { temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; } } } temp_attack = ((KNIGHT_ATTACKS[starting_square] & BLACK_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; //gets knight captures while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = WN; move_count+=1; } temp_attack = ((KNIGHT_ATTACKS[starting_square] & EMPTY_OCCUPANCIES) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = WN; move_count+=1; } } temp_bitboard = bitboard_array_global[WP]; while (temp_bitboard != 0) { starting_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_bitboard &= temp_bitboard - 1; temp_pin_bitboard = MAX_ULONG; if (pinNumber != 0) { for (0..pinNumber) |i| { if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square) { temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; } } } if ((SQUARE_BBS[starting_square - 8] & COMBINED_OCCUPANCIES_LOCAL) == 0) { //if up one square is empty if (((SQUARE_BBS[starting_square - 8] & check_bitboard) & temp_pin_bitboard) != 0) { if ((SQUARE_BBS[starting_square] & RANK_7_BITBOARD) != 0) { //if promotion move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = starting_square - 8; move_list[move_count][MOVE_TAG] = TAG_WQueenPromotion; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = starting_square - 8; move_list[move_count][MOVE_TAG] = TAG_WRookPromotion; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = starting_square - 8; move_list[move_count][MOVE_TAG] = TAG_WBishopPromotion; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = starting_square - 8; move_list[move_count][MOVE_TAG] = TAG_WKnightPromotion; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; } else { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = starting_square - 8; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; } } if ((SQUARE_BBS[starting_square] & RANK_2_BITBOARD) != 0) { //if on rank 2 if (((SQUARE_BBS[starting_square - 16] & check_bitboard) & temp_pin_bitboard) != 0) { //if not pinned or if (((SQUARE_BBS[starting_square - 16]) & COMBINED_OCCUPANCIES_LOCAL) == 0) { //if up two squares and one square are empty move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = starting_square - 16; move_list[move_count][MOVE_TAG] = TAG_DoublePawnWhite; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; } } } } temp_attack = ((WHITE_PAWN_ATTACKS[starting_square] & BLACK_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; //if black piece diagonal to pawn while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; if ((SQUARE_BBS[starting_square] & RANK_7_BITBOARD) != 0) //if promotion { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_WCaptureQueenPromotion; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_WCaptureRookPromotion; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_WCaptureBishopPromotion; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_WCaptureKnightPromotion; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; } else { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; } } if ((SQUARE_BBS[starting_square] & RANK_5_BITBOARD) != 0) //check rank for ep { if (ep_global != NO_SQUARE) { if ((((WHITE_PAWN_ATTACKS[starting_square] & SQUARE_BBS[ep_global]) & check_bitboard) & temp_pin_bitboard) != 0) { if ((bitboard_array_global[WK] & RANK_5_BITBOARD) == 0) //if no king on rank 5 { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = ep_global; move_list[move_count][MOVE_TAG] = TAG_WHITEEP; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; } else if ((bitboard_array_global[BR] & RANK_5_BITBOARD) == 0 and (bitboard_array_global[BQ] & RANK_5_BITBOARD) == 0) // if no b rook or queen on rank 5 { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = ep_global; move_list[move_count][MOVE_TAG] = TAG_WHITEEP; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; } else //wk and br or bq on rank 5 { var occupancyWithoutEPPawns:u64 = COMBINED_OCCUPANCIES_LOCAL & ~SQUARE_BBS[starting_square]; occupancyWithoutEPPawns &= ~SQUARE_BBS[ep_global + 8]; const rookAttacksFromKing = GetRookAttacksFast(whiteKingPosition, occupancyWithoutEPPawns); if ((rookAttacksFromKing & bitboard_array_global[BR]) == 0) { if ((rookAttacksFromKing & bitboard_array_global[BQ]) == 0) { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = ep_global; move_list[move_count][MOVE_TAG] = TAG_WHITEEP; move_list[move_count][MOVE_PIECE] = WP; move_count+=1; } } } } } } } temp_bitboard = bitboard_array_global[WR]; while (temp_bitboard != 0) { starting_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_bitboard &= temp_bitboard - 1; temp_pin_bitboard = MAX_ULONG; if (pinNumber != 0) { for (0..pinNumber) |i| { if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square) { temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; } } } const rookAttacks = GetRookAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); temp_attack = ((rookAttacks & BLACK_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = WR; move_count+=1; } temp_attack = ((rookAttacks & EMPTY_OCCUPANCIES) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = WR; move_count+=1; } } temp_bitboard = bitboard_array_global[WB]; while (temp_bitboard != 0) { starting_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_bitboard &= temp_bitboard - 1; temp_pin_bitboard = MAX_ULONG; if (pinNumber != 0) { for (0..pinNumber) |i| { if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square) { temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; } } } const bishopAttacks = GetBishopAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); temp_attack = ((bishopAttacks & BLACK_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = WB; move_count+=1; } temp_attack = ((bishopAttacks & EMPTY_OCCUPANCIES) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = WB; move_count+=1; } } temp_bitboard = bitboard_array_global[WQ]; while (temp_bitboard != 0) { starting_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_bitboard &= temp_bitboard - 1; temp_pin_bitboard = MAX_ULONG; if (pinNumber != 0) { for (0..pinNumber) |i| { if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square) { temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; } } } var queenAttacks:u64 = GetRookAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); queenAttacks |= GetBishopAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); temp_attack = ((queenAttacks & BLACK_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = WQ; move_count+=1; } temp_attack = ((queenAttacks & EMPTY_OCCUPANCIES) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = WQ; move_count+=1; } } } } else { //black move var blackKingCheckCount:usize = 0; const blackKingPosition:usize = (DEBRUIJN64[MAGIC *% (bitboard_array_global[BK] ^ (bitboard_array_global[BK] - 1)) >> 58]); //pawns temp_bitboard = bitboard_array_global[WP] & BLACK_PAWN_ATTACKS[blackKingPosition]; if (temp_bitboard != 0) { const pawn_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); if (check_bitboard == 0) { check_bitboard = SQUARE_BBS[pawn_square]; } blackKingCheckCount+=1; } //knights temp_bitboard = bitboard_array_global[WN] & KNIGHT_ATTACKS[blackKingPosition]; if (temp_bitboard != 0) { const knight_square:usize = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); if (check_bitboard == 0) { check_bitboard = SQUARE_BBS[knight_square]; } blackKingCheckCount+=1; } //bishops const bishopAttacksChecks = GetBishopAttacksFast(blackKingPosition, WHITE_OCCUPANCIES_LOCAL); temp_bitboard = bitboard_array_global[WB] & bishopAttacksChecks; while (temp_bitboard != 0) { const piece_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][piece_square] & BLACK_OCCUPANCIES_LOCAL; if (temp_pin_bitboard == 0) { if (check_bitboard == 0) { check_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][piece_square]; } blackKingCheckCount+=1; } else { const pinned_square = (DEBRUIJN64[MAGIC *% (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); temp_pin_bitboard &= temp_pin_bitboard - 1; if (temp_pin_bitboard == 0) { pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; pinNumber+=1; } } temp_bitboard &= temp_bitboard - 1; } //queen temp_bitboard = bitboard_array_global[WQ] & bishopAttacksChecks; while (temp_bitboard != 0) { const piece_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][piece_square] & BLACK_OCCUPANCIES_LOCAL; if (temp_pin_bitboard == 0) { if (check_bitboard == 0) { check_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][piece_square]; } blackKingCheckCount+=1; } else { const pinned_square = (DEBRUIJN64[MAGIC *% (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); temp_pin_bitboard &= temp_pin_bitboard - 1; if (temp_pin_bitboard == 0) { pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; pinNumber+=1; } } temp_bitboard &= temp_bitboard - 1; } //rook const rook_attacks = GetRookAttacksFast(blackKingPosition, WHITE_OCCUPANCIES_LOCAL); temp_bitboard = bitboard_array_global[WR] & rook_attacks; while (temp_bitboard != 0) { const piece_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); if (piece_square == -1) { break; } temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][piece_square] & BLACK_OCCUPANCIES_LOCAL; if (temp_pin_bitboard == 0) { if (check_bitboard == 0) { check_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][piece_square]; } blackKingCheckCount+=1; } else { const pinned_square = (DEBRUIJN64[MAGIC *% (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); temp_pin_bitboard &= temp_pin_bitboard - 1; if (temp_pin_bitboard == 0) { pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; pinNumber+=1; } } temp_bitboard &= temp_bitboard - 1; } //queen temp_bitboard = bitboard_array_global[WQ] & rook_attacks; while (temp_bitboard != 0) { const piece_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); if (piece_square == -1) { break; } temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][piece_square] & BLACK_OCCUPANCIES_LOCAL; if (temp_pin_bitboard == 0) { if (check_bitboard == 0) { check_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][piece_square]; } blackKingCheckCount+=1; } else { const pinned_square = (DEBRUIJN64[MAGIC *% (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); temp_pin_bitboard &= temp_pin_bitboard - 1; if (temp_pin_bitboard == 0) { pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; pinNumber+=1; } } temp_bitboard &= temp_bitboard - 1; } if (blackKingCheckCount > 1) { const occupancyWithoutBlackKing = COMBINED_OCCUPANCIES_LOCAL & (~bitboard_array_global[BK]); if (blackKingPosition == -1) { return 0; } temp_attack = KING_ATTACKS[blackKingPosition] & WHITE_OCCUPANCIES_LOCAL; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; if ((bitboard_array_global[WP] & BLACK_PAWN_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[WN] & KNIGHT_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[WK] & KING_ATTACKS[target_square]) != 0) { continue; } const bishopAttacks = GetBishopAttacksFast(target_square, occupancyWithoutBlackKing); if ((bitboard_array_global[WB] & bishopAttacks) != 0) { continue; } if ((bitboard_array_global[WQ] & bishopAttacks) != 0) { continue; } const rookAttacks = GetRookAttacksFast(target_square, occupancyWithoutBlackKing); if ((bitboard_array_global[WR] & rookAttacks) != 0) { continue; } if ((bitboard_array_global[WQ] & rookAttacks) != 0) { continue; } move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = BK; move_count+=1; } temp_attack = KING_ATTACKS[blackKingPosition] & ~COMBINED_OCCUPANCIES_LOCAL; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; if ((bitboard_array_global[WP] & WHITE_PAWN_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[WN] & KNIGHT_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[WK] & KING_ATTACKS[target_square]) != 0) { continue; } const bishopAttacks = GetBishopAttacksFast(target_square, occupancyWithoutBlackKing); if ((bitboard_array_global[WB] & bishopAttacks) != 0) { continue; } if ((bitboard_array_global[WQ] & bishopAttacks) != 0) { continue; } const rookAttacks = GetRookAttacksFast(target_square, occupancyWithoutBlackKing); if ((bitboard_array_global[WR] & rookAttacks) != 0) { continue; } if ((bitboard_array_global[WQ] & rookAttacks) != 0) { continue; } move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = BK; move_count+=1; } } else { if (blackKingCheckCount == 0) { check_bitboard = MAX_ULONG; } temp_bitboard = bitboard_array_global[BP]; while (temp_bitboard != 0) { starting_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_bitboard &= temp_bitboard - 1; temp_pin_bitboard = MAX_ULONG; if (pinNumber != 0) { for (0..pinNumber) |i| { if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square) { temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; } } } if ((SQUARE_BBS[starting_square + 8] & COMBINED_OCCUPANCIES_LOCAL) == 0) //if up one square is empty { if (((SQUARE_BBS[starting_square + 8] & check_bitboard) & temp_pin_bitboard) != 0) { if ((SQUARE_BBS[starting_square] & RANK_2_BITBOARD) != 0) //if promotion { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = starting_square + 8; move_list[move_count][MOVE_TAG] = TAG_BBishopPromotion; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = starting_square + 8; move_list[move_count][MOVE_TAG] = TAG_BKnightPromotion; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = starting_square + 8; move_list[move_count][MOVE_TAG] = TAG_BRookPromotion; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = starting_square + 8; move_list[move_count][MOVE_TAG] = TAG_BQueenPromotion; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; } else { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = starting_square + 8; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; } } if ((SQUARE_BBS[starting_square] & RANK_7_BITBOARD) != 0) //if on rank 2 { if (((SQUARE_BBS[starting_square + 16] & check_bitboard) & temp_pin_bitboard) != 0) { if (((SQUARE_BBS[starting_square + 16]) & COMBINED_OCCUPANCIES_LOCAL) == 0) //if up two squares and one square are empty { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = starting_square + 16; move_list[move_count][MOVE_TAG] = TAG_DoublePawnBlack; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; } } } } temp_attack = ((BLACK_PAWN_ATTACKS[starting_square] & WHITE_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; //if black piece diagonal to pawn while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); //find the bit temp_attack &= temp_attack - 1; if ((SQUARE_BBS[starting_square] & RANK_2_BITBOARD) != 0) //if promotion { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_BCaptureQueenPromotion; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_BCaptureRookPromotion; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_BCaptureKnightPromotion; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_BCaptureBishopPromotion; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; } else { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; } } if ((SQUARE_BBS[starting_square] & RANK_4_BITBOARD) != 0) //check rank for ep { if (ep_global != NO_SQUARE) { if ((((BLACK_PAWN_ATTACKS[starting_square] & SQUARE_BBS[ep_global]) & check_bitboard) & temp_pin_bitboard) != 0) { if ((bitboard_array_global[BK] & RANK_4_BITBOARD) == 0) //if no king on rank 5 { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = ep_global; move_list[move_count][MOVE_TAG] = TAG_BLACKEP; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; } else if ((bitboard_array_global[WR] & RANK_4_BITBOARD) == 0 and (bitboard_array_global[WQ] & RANK_4_BITBOARD) == 0) // if no b rook or queen on rank 5 { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = ep_global; move_list[move_count][MOVE_TAG] = TAG_BLACKEP; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; } else //wk and br or bq on rank 5 { var occupancyWithoutEPPawns = COMBINED_OCCUPANCIES_LOCAL & ~SQUARE_BBS[starting_square]; occupancyWithoutEPPawns &= ~SQUARE_BBS[ep_global - 8]; const rookAttacksFromKing = GetRookAttacksFast(blackKingPosition, occupancyWithoutEPPawns); if ((rookAttacksFromKing & bitboard_array_global[WR]) == 0) { if ((rookAttacksFromKing & bitboard_array_global[WQ]) == 0) { move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = ep_global; move_list[move_count][MOVE_TAG] = TAG_BLACKEP; move_list[move_count][MOVE_PIECE] = BP; move_count+=1; } } } } } } } temp_bitboard = bitboard_array_global[BN]; while (temp_bitboard != 0) { starting_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); //looks for the startingSquare temp_bitboard &= temp_bitboard - 1; //removes the knight from that square to not infinitely loop temp_pin_bitboard = MAX_ULONG; if (pinNumber != 0) { for (0..pinNumber) |i| { if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square) { temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; } } } temp_attack = ((KNIGHT_ATTACKS[starting_square] & WHITE_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; //gets knight captures while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = BN; move_count+=1; } temp_attack = ((KNIGHT_ATTACKS[starting_square] & (~COMBINED_OCCUPANCIES_LOCAL)) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = BN; move_count+=1; } } temp_bitboard = bitboard_array_global[BB]; while (temp_bitboard != 0) { starting_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_bitboard &= temp_bitboard - 1; temp_pin_bitboard = MAX_ULONG; if (pinNumber != 0) { for (0..pinNumber) |i| { if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square) { temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; } } } const bishopAttacks = GetBishopAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); temp_attack = ((bishopAttacks & WHITE_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = BB; move_count+=1; } temp_attack = ((bishopAttacks & (~COMBINED_OCCUPANCIES_LOCAL)) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = BB; move_count+=1; } } temp_bitboard = bitboard_array_global[BR]; while (temp_bitboard != 0) { starting_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_bitboard &= temp_bitboard - 1; temp_pin_bitboard = MAX_ULONG; if (pinNumber != 0) { for (0..pinNumber) |i| { if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square) { temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; } } } const rookAttacks = GetRookAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); temp_attack = ((rookAttacks & WHITE_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = BR; move_count+=1; } temp_attack = ((rookAttacks & (~COMBINED_OCCUPANCIES_LOCAL)) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = BR; move_count+=1; } } temp_bitboard = bitboard_array_global[BQ]; while (temp_bitboard != 0) { starting_square = (DEBRUIJN64[MAGIC *% (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); temp_bitboard &= temp_bitboard - 1; temp_pin_bitboard = MAX_ULONG; if (pinNumber != 0) { for (0..pinNumber) |i| { if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square) { temp_pin_bitboard = constants.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; } } } var queenAttacks:u64 = GetRookAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); queenAttacks |= GetBishopAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); temp_attack = ((queenAttacks & WHITE_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = BQ; move_count+=1; } temp_attack = ((queenAttacks & (~COMBINED_OCCUPANCIES_LOCAL)) & check_bitboard) & temp_pin_bitboard; while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; move_list[move_count][MOVE_STARTING] = starting_square; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = BQ; move_count+=1; } } temp_attack = KING_ATTACKS[blackKingPosition] & WHITE_OCCUPANCIES_LOCAL; //gets knight captures while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; if ((bitboard_array_global[WP] & BLACK_PAWN_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[WN] & KNIGHT_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[WK] & KING_ATTACKS[target_square]) != 0) { continue; } const occupancyWithoutBlackKing = COMBINED_OCCUPANCIES_LOCAL & (~bitboard_array_global[BK]); const bishopAttacks = GetBishopAttacksFast(target_square, occupancyWithoutBlackKing); if ((bitboard_array_global[WB] & bishopAttacks) != 0) { continue; } if ((bitboard_array_global[WQ] & bishopAttacks) != 0) { continue; } const rookAttacks = GetRookAttacksFast(target_square, occupancyWithoutBlackKing); if ((bitboard_array_global[WR] & rookAttacks) != 0) { continue; } if ((bitboard_array_global[WQ] & rookAttacks) != 0) { continue; } move_list[move_count][MOVE_STARTING] = blackKingPosition; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_CAPTURE; move_list[move_count][MOVE_PIECE] = BK; move_count+=1; } temp_attack = KING_ATTACKS[blackKingPosition] & (~COMBINED_OCCUPANCIES_LOCAL); //get knight moves to emtpy squares while (temp_attack != 0) { target_square = (DEBRUIJN64[MAGIC *% (temp_attack ^ (temp_attack - 1)) >> 58]); temp_attack &= temp_attack - 1; if ((bitboard_array_global[WP] & BLACK_PAWN_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[WN] & KNIGHT_ATTACKS[target_square]) != 0) { continue; } if ((bitboard_array_global[WK] & KING_ATTACKS[target_square]) != 0) { continue; } const occupancyWithoutBlackKing = COMBINED_OCCUPANCIES_LOCAL & (~bitboard_array_global[BK]); const bishopAttacks = GetBishopAttacksFast(target_square, occupancyWithoutBlackKing); if ((bitboard_array_global[WB] & bishopAttacks) != 0) { continue; } if ((bitboard_array_global[WQ] & bishopAttacks) != 0) { continue; } const rookAttacks = GetRookAttacksFast(target_square, occupancyWithoutBlackKing); if ((bitboard_array_global[WR] & rookAttacks) != 0) { continue; } if ((bitboard_array_global[WQ] & rookAttacks) != 0) { continue; } move_list[move_count][MOVE_STARTING] = blackKingPosition; move_list[move_count][MOVE_TARGET] = target_square; move_list[move_count][MOVE_TAG] = TAG_NONE; move_list[move_count][MOVE_PIECE] = BK; move_count+=1; } } if (blackKingCheckCount == 0) { if (castle_rights_global[BKS_CASTLE_RIGHTS] == true) { if (blackKingPosition == E8) //king on e1 { if ((BKS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES_LOCAL) == 0) //f1 and g1 empty { if ((bitboard_array_global[BR] & SQUARE_BBS[H8]) != 0) //rook on h1 { if (Is_Square_Attacked_By_White_Global(F8, COMBINED_OCCUPANCIES_LOCAL) == false) { if (Is_Square_Attacked_By_White_Global(G8, COMBINED_OCCUPANCIES_LOCAL) == false) { move_list[move_count][MOVE_STARTING] = E8; move_list[move_count][MOVE_TARGET] = G8; move_list[move_count][MOVE_TAG] = TAG_BCASTLEKS; move_list[move_count][MOVE_PIECE] = BK; move_count+=1; } } } } } } if (castle_rights_global[BQS_CASTLE_RIGHTS] == true) { if (blackKingPosition == E8) //king on e1 { if ((BQS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES_LOCAL) == 0) //f1 and g1 empty { if ((bitboard_array_global[BR] & SQUARE_BBS[A8]) != 0) //rook on h1 { if (Is_Square_Attacked_By_White_Global(C8, COMBINED_OCCUPANCIES_LOCAL) == false) { if (Is_Square_Attacked_By_White_Global(D8, COMBINED_OCCUPANCIES_LOCAL) == false) { move_list[move_count][MOVE_STARTING] = E8; move_list[move_count][MOVE_TARGET] = C8; move_list[move_count][MOVE_TAG] = TAG_BCASTLEQS; move_list[move_count][MOVE_PIECE] = BK; move_count+=1; } } } } } } } } if (depth == 1) { return move_count; } var nodes:usize = 0; var priorNodes:usize = undefined; const copyEp = ep_global; const copy_castle :[4]bool = [4]bool { castle_rights_global[0], castle_rights_global[1], castle_rights_global[2], castle_rights_global[3], }; for (0..move_count) |move_index| { const startingSquare = move_list[move_index][MOVE_STARTING]; const targetSquare = move_list[move_index][MOVE_TARGET]; const piece = move_list[move_index][MOVE_PIECE]; const tag = move_list[move_index][MOVE_TAG]; var captureIndex:usize = NO_SQUARE; if (is_white_global == true) { is_white_global = false; } else { is_white_global = true; } switch (tag) { 0, 26 => { //none bitboard_array_global[piece] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; }, 1, 27 => { //check cap bitboard_array_global[piece] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; if (piece >= WP and piece <= WK) { for (6..12) |i| { if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) { captureIndex = i; break; } } bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; } else //is black { for (WHITE_START_INDEX..BP) |i| { if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) { captureIndex = i; break; } } bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; } ep_global = NO_SQUARE; }, 2 => { //white ep //move piece bitboard_array_global[WP] |= SQUARE_BBS[targetSquare]; bitboard_array_global[WP] &= ~SQUARE_BBS[startingSquare]; //remove bitboard_array_global[BP] &= ~SQUARE_BBS[targetSquare + 8]; ep_global = NO_SQUARE; }, 3 => { //black ep //move piece bitboard_array_global[BP] |= SQUARE_BBS[targetSquare]; bitboard_array_global[BP] &= ~SQUARE_BBS[startingSquare]; //remove white pawn square up bitboard_array_global[WP] &= ~SQUARE_BBS[targetSquare - 8]; ep_global = NO_SQUARE; }, 4 => { //WKS //white king bitboard_array_global[WK] |= SQUARE_BBS[G1]; bitboard_array_global[WK] &= ~SQUARE_BBS[E1]; //white rook bitboard_array_global[WR] |= SQUARE_BBS[F1]; bitboard_array_global[WR] &= ~SQUARE_BBS[H1]; castle_rights_global[WKS_CASTLE_RIGHTS] = false; castle_rights_global[WQS_CASTLE_RIGHTS] = false; ep_global = NO_SQUARE; }, 5 => { //WQS //white king bitboard_array_global[WK] |= SQUARE_BBS[C1]; bitboard_array_global[WK] &= ~SQUARE_BBS[E1]; //white rook bitboard_array_global[WR] |= SQUARE_BBS[D1]; bitboard_array_global[WR] &= ~SQUARE_BBS[A1]; castle_rights_global[WKS_CASTLE_RIGHTS] = false; castle_rights_global[WQS_CASTLE_RIGHTS] = false; ep_global = NO_SQUARE; }, 6 => { //BKS //white king bitboard_array_global[BK] |= SQUARE_BBS[G8]; bitboard_array_global[BK] &= ~SQUARE_BBS[E8]; //white rook bitboard_array_global[BR] |= SQUARE_BBS[F8]; bitboard_array_global[BR] &= ~SQUARE_BBS[H8]; castle_rights_global[BKS_CASTLE_RIGHTS] = false; castle_rights_global[BQS_CASTLE_RIGHTS] = false; ep_global = NO_SQUARE; }, 7 => { //BQS //white king bitboard_array_global[BK] |= SQUARE_BBS[C8]; bitboard_array_global[BK] &= ~SQUARE_BBS[E8]; //white rook bitboard_array_global[BR] |= SQUARE_BBS[D8]; bitboard_array_global[BR] &= ~SQUARE_BBS[A8]; castle_rights_global[BKS_CASTLE_RIGHTS] = false; castle_rights_global[BQS_CASTLE_RIGHTS] = false; ep_global = NO_SQUARE; }, 8 => { //BNPr bitboard_array_global[BN] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; }, 9 => { //BBPr bitboard_array_global[BB] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; }, 10 => { //BQPr bitboard_array_global[BQ] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; }, 11 => { //BRPr bitboard_array_global[BR] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; }, 12 => { //WNPr bitboard_array_global[WN] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; }, 13 => { //WBPr bitboard_array_global[WB] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; }, 14 => { //WQPr bitboard_array_global[WQ] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; }, 15 => { //WRPr bitboard_array_global[WR] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; }, 16 => { //BNPrCAP bitboard_array_global[BN] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; for (WHITE_START_INDEX..BP) |i| { if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) { captureIndex = i; break; } } bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; }, 17 => { //BBPrCAP bitboard_array_global[BB] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; for (WHITE_START_INDEX..BP) |i| { if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) { captureIndex = i; break; } } bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; }, 18 => { //BQPrCAP bitboard_array_global[BQ] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; for (WHITE_START_INDEX..BP) |i| { if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) { captureIndex = i; break; } } bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; }, 19 => { //BRPrCAP bitboard_array_global[BR] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; for (WHITE_START_INDEX..BP) |i| { if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) { captureIndex = i; break; } } bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; }, 20 => { //WNPrCAP bitboard_array_global[WN] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; for (BP..12) |i| { if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) { captureIndex = i; break; } } bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; }, 21 => { //WBPrCAP bitboard_array_global[WB] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; for (BP..12) |i| { if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) { captureIndex = i; break; } } bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; }, 22 => { //WQPrCAP bitboard_array_global[WQ] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; for (BLACK_START_INDEX..12) |i| { if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) { captureIndex = i; break; } } bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; }, 23 => { //WRPrCAP bitboard_array_global[WR] |= SQUARE_BBS[targetSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; ep_global = NO_SQUARE; for (BP..12) |i| { if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) { captureIndex = i; break; } } bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; }, 24 => { //WDouble bitboard_array_global[WP] |= SQUARE_BBS[targetSquare]; bitboard_array_global[WP] &= ~SQUARE_BBS[startingSquare]; ep_global = targetSquare + 8; }, 25 => { //BDouble bitboard_array_global[BP] |= SQUARE_BBS[targetSquare]; bitboard_array_global[BP] &= ~SQUARE_BBS[startingSquare]; ep_global = targetSquare - 8; }, else => { unreachable; } } if (piece == WK) { castle_rights_global[WKS_CASTLE_RIGHTS] = false; castle_rights_global[WQS_CASTLE_RIGHTS] = false; } else if (piece == BK) { castle_rights_global[BKS_CASTLE_RIGHTS] = false; castle_rights_global[BQS_CASTLE_RIGHTS] = false; } else if (piece == WR) { if (castle_rights_global[WKS_CASTLE_RIGHTS] == true) { if ((bitboard_array_global[WR] & SQUARE_BBS[H1]) == 0) { castle_rights_global[WKS_CASTLE_RIGHTS] = false; } } if (castle_rights_global[WQS_CASTLE_RIGHTS] == true) { if ((bitboard_array_global[WR] & SQUARE_BBS[A1]) == 0) { castle_rights_global[WQS_CASTLE_RIGHTS] = false; } } } else if (piece == BR) { if (castle_rights_global[BKS_CASTLE_RIGHTS] == true) { if ((bitboard_array_global[BR] & SQUARE_BBS[H8]) == 0) { castle_rights_global[BKS_CASTLE_RIGHTS] = false; } } if (castle_rights_global[BQS_CASTLE_RIGHTS] == true) { if ((bitboard_array_global[BR] & SQUARE_BBS[A8]) == 0) { castle_rights_global[BQS_CASTLE_RIGHTS] = false; } } } priorNodes = nodes; nodes += PerftInlineGlobalOcc(depth - 1, ply + 1); is_white_global = !is_white_global; switch (tag) { 0, 26 => { //check bitboard_array_global[piece] |= SQUARE_BBS[startingSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[targetSquare]; }, 1, 27 => { //check cap bitboard_array_global[piece] |= SQUARE_BBS[startingSquare]; bitboard_array_global[piece] &= ~SQUARE_BBS[targetSquare]; if (piece >= WP and piece <= WK) { bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; } else //is black { bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; } }, 2 => { //white ep bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[WP] &= ~SQUARE_BBS[targetSquare]; bitboard_array_global[BP] |= SQUARE_BBS[targetSquare + 8]; }, 3 => { //black ep bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[BP] &= ~SQUARE_BBS[targetSquare]; bitboard_array_global[WP] |= SQUARE_BBS[targetSquare - 8]; }, 4 => { //WKS //white king bitboard_array_global[WK] |= SQUARE_BBS[E1]; bitboard_array_global[WK] &= ~SQUARE_BBS[G1]; //white rook bitboard_array_global[WR] |= SQUARE_BBS[H1]; bitboard_array_global[WR] &= ~SQUARE_BBS[F1]; }, 5 => { //WQS //white king bitboard_array_global[WK] |= SQUARE_BBS[E1]; bitboard_array_global[WK] &= ~SQUARE_BBS[C1]; //white rook bitboard_array_global[WR] |= SQUARE_BBS[A1]; bitboard_array_global[WR] &= ~SQUARE_BBS[D1]; }, 6 => { //BKS //white king bitboard_array_global[BK] |= SQUARE_BBS[E8]; bitboard_array_global[BK] &= ~SQUARE_BBS[G8]; //white rook bitboard_array_global[BR] |= SQUARE_BBS[H8]; bitboard_array_global[BR] &= ~SQUARE_BBS[F8]; }, 7 => { //BQS //white king bitboard_array_global[BK] |= SQUARE_BBS[E8]; bitboard_array_global[BK] &= ~SQUARE_BBS[C8]; //white rook bitboard_array_global[BR] |= SQUARE_BBS[A8]; bitboard_array_global[BR] &= ~SQUARE_BBS[D8]; }, 8 => { //BNPr bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[BN] &= ~SQUARE_BBS[targetSquare]; }, 9 => { //BBPr bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[BB] &= ~SQUARE_BBS[targetSquare]; }, 10 => { //BQPr bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[BQ] &= ~SQUARE_BBS[targetSquare]; }, 11 => { //BRPr bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[BR] &= ~SQUARE_BBS[targetSquare]; }, 12 => { //WNPr bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[WN] &= ~SQUARE_BBS[targetSquare]; }, 13 => { //WBPr bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[WB] &= ~SQUARE_BBS[targetSquare]; }, 14 => { //WQPr bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[WQ] &= ~SQUARE_BBS[targetSquare]; }, 15 => { //WRPr bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[WR] &= ~SQUARE_BBS[targetSquare]; }, 16 => { //BNPrCAP bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[BN] &= ~SQUARE_BBS[targetSquare]; bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; }, 17 => { //BBPrCAP bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[BB] &= ~SQUARE_BBS[targetSquare]; bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; }, 18 => { //BQPrCAP bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[BQ] &= ~SQUARE_BBS[targetSquare]; bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; }, 19 => { //BRPrCAP bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[BR] &= ~SQUARE_BBS[targetSquare]; bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; }, 20 => { //WNPrCAP bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[WN] &= ~SQUARE_BBS[targetSquare]; bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; }, 21 => { //WBPrCAP bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[WB] &= ~SQUARE_BBS[targetSquare]; bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; }, 22 => { //WQPrCAP bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[WQ] &= ~SQUARE_BBS[targetSquare]; bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; }, 23 => { //WRPrCAP bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[WR] &= ~SQUARE_BBS[targetSquare]; bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; }, 24 => { //WDouble bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[WP] &= ~SQUARE_BBS[targetSquare]; }, 25 => { //BDouble bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; bitboard_array_global[BP] &= ~SQUARE_BBS[targetSquare]; }, else => { unreachable; } } castle_rights_global[0] = copy_castle[0]; castle_rights_global[1] = copy_castle[1]; castle_rights_global[2] = copy_castle[2]; castle_rights_global[3] = copy_castle[3]; ep_global = copyEp; //if (epGlobal != NO_SQUARE) //{ // std::cout << " ep: " << SQ_CHAR_X[epGlobal] << SQ_CHAR_Y[epGlobal] << '\n'; //} //if (ply == 0) //{ //PrMoveNoNL(startingSquare, targetSquare); //std.debug.print(": {}\n", .{nodes - priorNodes}); //} } return nodes; } fn RunPerftInlineGlobalOcc(depth:i8) void { const start_time: i64 = std.time.milliTimestamp(); const nodes = PerftInlineGlobalOcc(depth, 0); const stop_time: i64 = std.time.milliTimestamp(); const elapsed_milliseconds = stop_time - start_time; std.debug.print("Nodes: {}\n", .{nodes}); std.debug.print("Elapsed time: {}\n", .{elapsed_milliseconds}); } pub fn main() void { ParseFenGlobal(FEN_STARTING_POSITION, 0); RunPerftInlineGlobalOcc(6); }