
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);
}
