package main

import "core:fmt"
import "core:time"

PerftInline :: proc(depth: int, ply: int) -> u64 {

	//if depth == 0 {
	//	return 1
	//}

	moveList: [250][4]int;
	moveCount: u64 = 0;

	WHITE_OCCUPANCIES: u64 = PieceArray[0] |
		PieceArray[1] |
		PieceArray[2] |
		PieceArray[3] |
		PieceArray[4] |
		PieceArray[5];

	BLACK_OCCUPANCIES: u64 = PieceArray[6] |
		PieceArray[7] |
		PieceArray[8] |
		PieceArray[9] |
		PieceArray[10] |
		PieceArray[11];

	COMBINED_OCCUPANCIES: u64 = WHITE_OCCUPANCIES | BLACK_OCCUPANCIES;
	EMPTY_OCCUPANCIES: u64 = ~COMBINED_OCCUPANCIES;
	tempBitboard: u64;
	checkBitboard: u64 = EMPTY_BITBOARD;
	tempPinBitboard: u64;
	tempAttack: u64;
	tempEmpty: u64;
	tempCaptures: u64;
	startingSquare:int = NO_SQUARE;
	targetSquare:int = NO_SQUARE;

	pinArray := [8][2]int{
		{-1, -1},
		{-1, -1},
		{-1, -1},
		{-1, -1},
		{-1, -1},
		{-1, -1},
		{-1, -1},
		{-1, -1},
	}
	pinNumber := 0;

	//Generate Moves
	if whiteToPlay {

		whiteKingCheckCount: int = 0
		whiteKingPosition: int = BitscanForward(PieceArray[WK])

		//pawns
		tempBitboard = PieceArray[BP] & WHITE_PAWN_ATTACKS[whiteKingPosition]
		if tempBitboard != 0 {

			pawn_square: int = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58]);
			if pawn_square != -1 {

				if checkBitboard == 0 {

					checkBitboard = SQUARE_BBS[pawn_square];
				}
			}
			whiteKingCheckCount+=1;
		}

		//knights
		tempBitboard = PieceArray[BN] & KNIGHT_ATTACKS[whiteKingPosition]
		if tempBitboard != 0 {

			knight_square: int = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58]);
			if checkBitboard == 0 {
				checkBitboard = SQUARE_BBS[knight_square];
			}
			
			whiteKingCheckCount+=1;
		}

		//bishops
		bishopAttacksChecks: u64 = GetBishopAttacksFast(whiteKingPosition, BLACK_OCCUPANCIES);
		tempBitboard = PieceArray[BB] & bishopAttacksChecks;
		for tempBitboard != 0 {

			piece_square: int = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58]);
			tempPinBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES;

			if tempPinBitboard == 0 {

				if checkBitboard == 0 {
					checkBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
				}
				whiteKingCheckCount+=1;
			} else {

				pinned_square: int = (DEBRUIJN64[MAGIC*(tempPinBitboard~(tempPinBitboard-1))>>58]);
				tempPinBitboard &= tempPinBitboard - 1;

				if tempPinBitboard == 0 {

					pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
					pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
					pinNumber+=1;
				}
			}
			tempBitboard &= tempBitboard - 1;
		}

		//queen
		tempBitboard = PieceArray[BQ] & bishopAttacksChecks;
		for tempBitboard != 0 {

			piece_square: int = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58]);
			tempPinBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES;

			if tempPinBitboard == 0 {
				if checkBitboard == 0 {
					checkBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
				}
				whiteKingCheckCount+=1;
			} else {
				pinned_square: int = (DEBRUIJN64[MAGIC*(tempPinBitboard~(tempPinBitboard-1))>>58]);
				tempPinBitboard &= tempPinBitboard - 1;

				if tempPinBitboard == 0 {

					pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
					pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
					pinNumber+=1;
				}
			}
			tempBitboard &= tempBitboard - 1;
		}

		//rook
		rook_attacks: u64 = GetRookAttacksFast(whiteKingPosition, BLACK_OCCUPANCIES);
		tempBitboard = PieceArray[BR] & rook_attacks;
		for tempBitboard != 0 {

			piece_square: int = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
			tempPinBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES

			if tempPinBitboard == 0 {
				if checkBitboard == 0 {
					checkBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
				}
				whiteKingCheckCount+=1;
			} else {
				pinned_square: int = (DEBRUIJN64[MAGIC*(tempPinBitboard~(tempPinBitboard-1))>>58]);
				tempPinBitboard &= tempPinBitboard - 1;

				if tempPinBitboard == 0 {
					pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
					pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
					pinNumber+=1;
				}
			}
			tempBitboard &= tempBitboard - 1;
		}

		//queen
		tempBitboard = PieceArray[BQ] & rook_attacks;
		for tempBitboard != 0 {

			piece_square: int = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58]);
			tempPinBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES;

			if tempPinBitboard == 0 {
				if checkBitboard == 0 {
					checkBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
				}
				whiteKingCheckCount+=1;
			} else {
				pinned_square: int = (DEBRUIJN64[MAGIC*(tempPinBitboard~(tempPinBitboard-1))>>58]);
				tempPinBitboard &= tempPinBitboard - 1;

				if tempPinBitboard == 0 {
					pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
					pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
					pinNumber+=1;
				}
			}
			tempBitboard &= tempBitboard - 1;
		}

		//If double check
		if whiteKingCheckCount > 1 {

			occupanciesWithoutWhiteKing: u64 = COMBINED_OCCUPANCIES & (~PieceArray[WK]);
			tempAttack = KING_ATTACKS[whiteKingPosition];
			tempEmpty = tempAttack & EMPTY_OCCUPANCIES;
			for tempEmpty != 0 {
				targetSquare = BitscanForward(tempEmpty);
				tempEmpty &= tempEmpty - 1;

				if (PieceArray[BP] & WHITE_PAWN_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[BN] & KNIGHT_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[BK] & KING_ATTACKS[targetSquare]) != 0 {
					continue
				}
				bishopAttacks: u64 = GetBishopAttacksFast(targetSquare, occupanciesWithoutWhiteKing);
				if (PieceArray[BB] & bishopAttacks) != 0 {
					continue
				}
				if (PieceArray[BQ] & bishopAttacks) != 0 {
					continue
				}
				rookAttacks: u64 = GetRookAttacksFast(targetSquare, occupanciesWithoutWhiteKing)
				if (PieceArray[BR] & rookAttacks) != 0 {
					continue
				}
				if (PieceArray[BQ] & rookAttacks) != 0 {
					continue
				}

				moveList[moveCount][MOVE_STARTING] = whiteKingPosition;
				moveList[moveCount][MOVE_TARGET] = targetSquare;
				moveList[moveCount][MOVE_TAG] = TAG_NONE;
				moveList[moveCount][MOVE_PIECE] = WK;
				moveCount+=1;
			}

			//captures
			tempCaptures = tempAttack & BLACK_OCCUPANCIES
			for tempCaptures != 0 {
				targetSquare = BitscanForward(tempCaptures)
				tempCaptures &= tempCaptures - 1

				if (PieceArray[BP] & WHITE_PAWN_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[BN] & KNIGHT_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[BK] & KING_ATTACKS[targetSquare]) != 0 {
					continue
				}
				bishopAttacks: u64 = GetBishopAttacksFast(targetSquare, occupanciesWithoutWhiteKing);
				if (PieceArray[BB] & bishopAttacks) != 0 {
					continue
				}
				if (PieceArray[BQ] & bishopAttacks) != 0 {
					continue
				}
				rookAttacks: u64 = GetRookAttacksFast(targetSquare, occupanciesWithoutWhiteKing);
				if (PieceArray[BR] & rookAttacks) != 0 {
					continue
				}
				if (PieceArray[BQ] & rookAttacks) != 0 {
					continue
				}

				moveList[moveCount][MOVE_STARTING] = whiteKingPosition;
				moveList[moveCount][MOVE_TARGET] = targetSquare;
				moveList[moveCount][MOVE_TAG] = TAG_CAPTURE;
				moveList[moveCount][MOVE_PIECE] = WK;
				moveCount+=1;
			}

		} else {

			if whiteKingCheckCount == 0 {
				checkBitboard = MAX_ULONG;
			}

			occupanciesWithoutWhiteKing: u64 = COMBINED_OCCUPANCIES & (~PieceArray[WK]);
			tempAttack = KING_ATTACKS[whiteKingPosition]
			tempEmpty = tempAttack & EMPTY_OCCUPANCIES
			for tempEmpty != 0 {
				targetSquare = BitscanForward(tempEmpty)
				tempEmpty &= tempEmpty - 1

				if (PieceArray[BP] & WHITE_PAWN_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[BN] & KNIGHT_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[BK] & KING_ATTACKS[targetSquare]) != 0 {
					continue
				}
				bishopAttacks: u64 = GetBishopAttacksFast(targetSquare, occupanciesWithoutWhiteKing);
				if (PieceArray[BB] & bishopAttacks) != 0 {
					continue
				}
				if (PieceArray[BQ] & bishopAttacks) != 0 {
					continue
				}
				rookAttacks: u64 = GetRookAttacksFast(targetSquare, occupanciesWithoutWhiteKing);
				if (PieceArray[BR] & rookAttacks) != 0 {
					continue
				}
				if (PieceArray[BQ] & rookAttacks) != 0 {
					continue
				}

				moveList[moveCount][MOVE_STARTING] = whiteKingPosition;
				moveList[moveCount][MOVE_TARGET] = targetSquare;
				moveList[moveCount][MOVE_TAG] = TAG_NONE;
				moveList[moveCount][MOVE_PIECE] = WK;
				moveCount+=1;
			}

			//captures
			tempCaptures = tempAttack & BLACK_OCCUPANCIES
			for tempCaptures != 0 {

				targetSquare = BitscanForward(tempCaptures)
				tempCaptures &= tempCaptures - 1

				if (PieceArray[BP] & WHITE_PAWN_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[BN] & KNIGHT_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[BK] & KING_ATTACKS[targetSquare]) != 0 {
					continue
				}
				bishopAttacks: u64 = GetBishopAttacksFast(targetSquare, occupanciesWithoutWhiteKing)
				if (PieceArray[BB] & bishopAttacks) != 0 {
					continue
				}
				if (PieceArray[BQ] & bishopAttacks) != 0 {
					continue
				}
				rookAttacks: u64 = GetRookAttacksFast(targetSquare, occupanciesWithoutWhiteKing);
				if (PieceArray[BR] & rookAttacks) != 0 {
					continue
				}
				if (PieceArray[BQ] & rookAttacks) != 0 {
					continue
				}

				moveList[moveCount][MOVE_STARTING] = whiteKingPosition;
				moveList[moveCount][MOVE_TARGET] = targetSquare;
				moveList[moveCount][MOVE_TAG] = TAG_CAPTURE;
				moveList[moveCount][MOVE_PIECE] = WK;
				moveCount+=1;
			}

			if whiteKingCheckCount == 0 {

				if CastleRights[WKS_CASTLE_RIGHTS] == true {

					if whiteKingPosition == E1 { //king on e1

						if (WKS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES) == 0 { //f1 and g1 empty

							if (PieceArray[WR] & SQUARE_BBS[H1]) != 0 { //rook on h1

								if Is_Square_Attacked_By_Black(F1, COMBINED_OCCUPANCIES) == false {

									if Is_Square_Attacked_By_Black(G1, COMBINED_OCCUPANCIES) == false {

										moveList[moveCount][MOVE_STARTING] = E1;
										moveList[moveCount][MOVE_TARGET] = G1;
										moveList[moveCount][MOVE_TAG] = TAG_WCASTLEKS;
										moveList[moveCount][MOVE_PIECE] = WK;
										moveCount+=1;
									}
								}
							}
						}
					}
				}
				if CastleRights[WQS_CASTLE_RIGHTS] == true {

					if whiteKingPosition == E1 { //king on e1

						if (WQS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES) == 0 { //f1 and g1 empty

							if (PieceArray[WR] & SQUARE_BBS[A1]) != 0 { //rook on h1

								if Is_Square_Attacked_By_Black(C1, COMBINED_OCCUPANCIES) == false {

									if Is_Square_Attacked_By_Black(D1, COMBINED_OCCUPANCIES) == false {

										moveList[moveCount][MOVE_STARTING] = E1;
										moveList[moveCount][MOVE_TARGET] = C1;
										moveList[moveCount][MOVE_TAG] = TAG_WCASTLEQS;
										moveList[moveCount][MOVE_PIECE] = WK;
										moveCount+=1;
									}
								}
							}
						}
					}
				}
			}

			tempBitboard = PieceArray[WN]

			for tempBitboard != 0 {

				startingSquare = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
				tempBitboard &= tempBitboard - 1 //removes the knight from that square to not infinitely loop

				tempPinBitboard = MAX_ULONG
				if pinNumber != 0 {

					for i := 0; i < pinNumber; i+=1 {

						if pinArray[i][PINNED_SQUARE_INDEX] == startingSquare {

							tempPinBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
						}
					}
				}

				tempAttack = ((KNIGHT_ATTACKS[startingSquare] & BLACK_OCCUPANCIES) & checkBitboard) & tempPinBitboard //gets knight captures
				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58]);
					tempAttack &= tempAttack - 1;

					moveList[moveCount][MOVE_STARTING] = startingSquare;
					moveList[moveCount][MOVE_TARGET] = targetSquare;
					moveList[moveCount][MOVE_TAG] = TAG_CAPTURE;
					moveList[moveCount][MOVE_PIECE] = WN;
					moveCount+=1;
				}

				tempAttack = ((KNIGHT_ATTACKS[startingSquare] & EMPTY_OCCUPANCIES) & checkBitboard) & tempPinBitboard;

				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58]);
					tempAttack &= tempAttack - 1;

					moveList[moveCount][MOVE_STARTING] = startingSquare;
					moveList[moveCount][MOVE_TARGET] = targetSquare;
					moveList[moveCount][MOVE_TAG] = TAG_NONE;
					moveList[moveCount][MOVE_PIECE] = WN;
					moveCount+=1;
				}
			}

			tempBitboard = PieceArray[WP]

			for tempBitboard != 0 {

				startingSquare = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
				tempBitboard &= tempBitboard - 1

				tempPinBitboard = MAX_ULONG
				if pinNumber != 0 {
					for i := 0; i < pinNumber; i+=1 {
						if pinArray[i][PINNED_SQUARE_INDEX] == startingSquare {

							tempPinBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]
						}
					}
				}

				if (SQUARE_BBS[startingSquare-8] & COMBINED_OCCUPANCIES) == 0 { //if up one square is empty

					if ((SQUARE_BBS[startingSquare-8] & checkBitboard) & tempPinBitboard) != 0 {

						if (SQUARE_BBS[startingSquare] & RANK_7_BITBOARD) != 0 { //if promotion

							moveList[moveCount][MOVE_STARTING] = startingSquare
							moveList[moveCount][MOVE_TARGET] = startingSquare - 8
							moveList[moveCount][MOVE_TAG] = TAG_WQueenPromotion
							moveList[moveCount][MOVE_PIECE] = WP
							moveCount+=1

							moveList[moveCount][MOVE_STARTING] = startingSquare
							moveList[moveCount][MOVE_TARGET] = startingSquare - 8
							moveList[moveCount][MOVE_TAG] = TAG_WRookPromotion
							moveList[moveCount][MOVE_PIECE] = WP
							moveCount+=1

							moveList[moveCount][MOVE_STARTING] = startingSquare
							moveList[moveCount][MOVE_TARGET] = startingSquare - 8
							moveList[moveCount][MOVE_TAG] = TAG_WBishopPromotion
							moveList[moveCount][MOVE_PIECE] = WP
							moveCount+=1

							moveList[moveCount][MOVE_STARTING] = startingSquare
							moveList[moveCount][MOVE_TARGET] = startingSquare - 8
							moveList[moveCount][MOVE_TAG] = TAG_WKnightPromotion
							moveList[moveCount][MOVE_PIECE] = WP
							moveCount+=1

						} else {

							moveList[moveCount][MOVE_STARTING] = startingSquare
							moveList[moveCount][MOVE_TARGET] = startingSquare - 8
							moveList[moveCount][MOVE_TAG] = TAG_NONE
							moveList[moveCount][MOVE_PIECE] = WP
							moveCount+=1
						}
					}

					if (SQUARE_BBS[startingSquare] & RANK_2_BITBOARD) != 0 { //if on rank 2

						if ((SQUARE_BBS[startingSquare-16] & checkBitboard) & tempPinBitboard) != 0 { //if not pinned or

							if ((SQUARE_BBS[startingSquare-16]) & COMBINED_OCCUPANCIES) == 0 { //if up two squares and one square are empty

								moveList[moveCount][MOVE_STARTING] = startingSquare
								moveList[moveCount][MOVE_TARGET] = startingSquare - 16
								moveList[moveCount][MOVE_TAG] = TAG_DoublePawnWhite
								moveList[moveCount][MOVE_PIECE] = WP
								moveCount+=1
							}
						}
					}
				}

				tempAttack = ((WHITE_PAWN_ATTACKS[startingSquare] & BLACK_OCCUPANCIES) & checkBitboard) & tempPinBitboard //if black piece diagonal to pawn

				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					if (SQUARE_BBS[startingSquare] & RANK_7_BITBOARD) != 0 { //if promotion

						moveList[moveCount][MOVE_STARTING] = startingSquare
						moveList[moveCount][MOVE_TARGET] = targetSquare
						moveList[moveCount][MOVE_TAG] = TAG_WCaptureQueenPromotion
						moveList[moveCount][MOVE_PIECE] = WP
						moveCount+=1

						moveList[moveCount][MOVE_STARTING] = startingSquare
						moveList[moveCount][MOVE_TARGET] = targetSquare
						moveList[moveCount][MOVE_TAG] = TAG_WCaptureRookPromotion
						moveList[moveCount][MOVE_PIECE] = WP
						moveCount+=1

						moveList[moveCount][MOVE_STARTING] = startingSquare
						moveList[moveCount][MOVE_TARGET] = targetSquare
						moveList[moveCount][MOVE_TAG] = TAG_WCaptureBishopPromotion
						moveList[moveCount][MOVE_PIECE] = WP
						moveCount+=1

						moveList[moveCount][MOVE_STARTING] = startingSquare
						moveList[moveCount][MOVE_TARGET] = targetSquare
						moveList[moveCount][MOVE_TAG] = TAG_WCaptureKnightPromotion
						moveList[moveCount][MOVE_PIECE] = WP
						moveCount+=1
					} else {

						moveList[moveCount][MOVE_STARTING] = startingSquare
						moveList[moveCount][MOVE_TARGET] = targetSquare
						moveList[moveCount][MOVE_TAG] = TAG_CAPTURE
						moveList[moveCount][MOVE_PIECE] = WP
						moveCount+=1
					}
				}

				if (SQUARE_BBS[startingSquare] & RANK_5_BITBOARD) != 0 { //check rank for ep

					if ep != NO_SQUARE {

						if (((WHITE_PAWN_ATTACKS[startingSquare] & SQUARE_BBS[ep]) & checkBitboard) & tempPinBitboard) != 0 {

							if (PieceArray[WK] & RANK_5_BITBOARD) == 0 { //if no king on rank 5

								moveList[moveCount][MOVE_STARTING] = startingSquare
								moveList[moveCount][MOVE_TARGET] = int(ep)
								moveList[moveCount][MOVE_TAG] = TAG_WHITEEP
								moveList[moveCount][MOVE_PIECE] = WP
								moveCount+=1
							} else if (PieceArray[BR]&RANK_5_BITBOARD) == 0 && (PieceArray[BQ]&RANK_5_BITBOARD) == 0 { // if no b rook or queen on rank 5

								moveList[moveCount][MOVE_STARTING] = startingSquare
								moveList[moveCount][MOVE_TARGET] = int(ep)
								moveList[moveCount][MOVE_TAG] = TAG_WHITEEP
								moveList[moveCount][MOVE_PIECE] = WP
								moveCount+=1
							} else { //wk and br or bq on rank 5

								occupancyWithoutEPPawns: u64 = COMBINED_OCCUPANCIES & ~SQUARE_BBS[startingSquare]
								occupancyWithoutEPPawns &= ~SQUARE_BBS[ep+8]

								rookAttacksFromKing: u64 = GetRookAttacksFast(whiteKingPosition, occupancyWithoutEPPawns)

								if (rookAttacksFromKing & PieceArray[BR]) == 0 {

									if (rookAttacksFromKing & PieceArray[BQ]) == 0 {

										moveList[moveCount][MOVE_STARTING] = startingSquare
										moveList[moveCount][MOVE_TARGET] = int(ep)
										moveList[moveCount][MOVE_TAG] = TAG_WHITEEP
										moveList[moveCount][MOVE_PIECE] = WP
										moveCount+=1
									}
								}
							}
						}
					}
				}
			}

			tempBitboard = PieceArray[WR]
			for tempBitboard != 0 {

				startingSquare = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
				tempBitboard &= tempBitboard - 1

				tempPinBitboard = MAX_ULONG
				if pinNumber != 0 {

					for i := 0; i < pinNumber; i+=1 {

						if pinArray[i][PINNED_SQUARE_INDEX] == startingSquare {

							tempPinBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]
						}
					}
				}

				rookAttacks :u64= GetRookAttacksFast(startingSquare, COMBINED_OCCUPANCIES)

				tempAttack = ((rookAttacks & BLACK_OCCUPANCIES) & checkBitboard) & tempPinBitboard
				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_CAPTURE
					moveList[moveCount][MOVE_PIECE] = WR
					moveCount+=1
				}

				tempAttack = ((rookAttacks & EMPTY_OCCUPANCIES) & checkBitboard) & tempPinBitboard
				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_NONE
					moveList[moveCount][MOVE_PIECE] = WR
					moveCount+=1
				}
			}

			tempBitboard = PieceArray[WB]
			for tempBitboard != 0 {

				startingSquare = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
				tempBitboard &= tempBitboard - 1

				tempPinBitboard = MAX_ULONG
				if pinNumber != 0 {

					for i := 0; i < pinNumber; i+=1 {

						if pinArray[i][PINNED_SQUARE_INDEX] == startingSquare {

							tempPinBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]
						}
					}
				}

				bishopAttacks :u64= GetBishopAttacksFast(startingSquare, COMBINED_OCCUPANCIES)

				tempAttack = ((bishopAttacks & BLACK_OCCUPANCIES) & checkBitboard) & tempPinBitboard
				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_CAPTURE
					moveList[moveCount][MOVE_PIECE] = WB
					moveCount+=1
				}

				tempAttack = ((bishopAttacks & EMPTY_OCCUPANCIES) & checkBitboard) & tempPinBitboard
				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_NONE
					moveList[moveCount][MOVE_PIECE] = WB
					moveCount+=1
				}
			}

			tempBitboard = PieceArray[WQ]
			for tempBitboard != 0 {

				startingSquare = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
				tempBitboard &= tempBitboard - 1

				tempPinBitboard = MAX_ULONG
				if pinNumber != 0 {

					for i := 0; i < pinNumber; i+=1 {

						if pinArray[i][PINNED_SQUARE_INDEX] == startingSquare {

							tempPinBitboard = INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]
						}
					}
				}

				queenAttacks :u64= GetRookAttacksFast(startingSquare, COMBINED_OCCUPANCIES)
				queenAttacks |= GetBishopAttacksFast(startingSquare, COMBINED_OCCUPANCIES)

				tempAttack = ((queenAttacks & BLACK_OCCUPANCIES) & checkBitboard) & tempPinBitboard

				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_CAPTURE
					moveList[moveCount][MOVE_PIECE] = WQ
					moveCount+=1
				}

				tempAttack = ((queenAttacks & EMPTY_OCCUPANCIES) & checkBitboard) & tempPinBitboard
				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_NONE
					moveList[moveCount][MOVE_PIECE] = WQ
					moveCount+=1
				}
			}

		}
	} else { //black move

		blackKingCheckCount: int = 0
		blackKingPosition: int = (DEBRUIJN64[MAGIC*(PieceArray[BK]~(PieceArray[BK]-1))>>58])

		//pawns
		tempBitboard = PieceArray[WP] & BLACK_PAWN_ATTACKS[blackKingPosition]
		if tempBitboard != 0 {

			pawn_square:int = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
			if pawn_square != -1 {

				if checkBitboard == 0 {

					checkBitboard = SQUARE_BBS[pawn_square]
				}
			}
			blackKingCheckCount+=1;
		}

		//knights
		tempBitboard = PieceArray[WN] & KNIGHT_ATTACKS[blackKingPosition]
		if tempBitboard != 0 {

			knight_square: int = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
			if knight_square != -1 {

				if checkBitboard == 0 {

					checkBitboard = SQUARE_BBS[knight_square]
				}
			}
			blackKingCheckCount+=1;
		}

		//bishops
		bishopAttacksChecks :u64= GetBishopAttacksFast(blackKingPosition, WHITE_OCCUPANCIES)
		tempBitboard = PieceArray[WB] & bishopAttacksChecks
		for tempBitboard != 0 {

			piece_square: int = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
			tempPinBitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square] & BLACK_OCCUPANCIES

			if tempPinBitboard == 0 {

				if checkBitboard == 0 {

					checkBitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square]
				}
				blackKingCheckCount+=1
			} else {

				pinned_square: int = (DEBRUIJN64[MAGIC*(tempPinBitboard~(tempPinBitboard-1))>>58])
				tempPinBitboard &= tempPinBitboard - 1

				if tempPinBitboard == 0 {

					pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square
					pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square
					pinNumber+=1
				}
			}
			tempBitboard &= tempBitboard - 1
		}

		//queen
		tempBitboard = PieceArray[WQ] & bishopAttacksChecks
		for tempBitboard != 0 {

			piece_square := (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
			tempPinBitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square] & BLACK_OCCUPANCIES

			if tempPinBitboard == 0 {

				if checkBitboard == 0 {

					checkBitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square]
				}
				blackKingCheckCount+=1
			} else {

				pinned_square:int = (DEBRUIJN64[MAGIC*(tempPinBitboard~(tempPinBitboard-1))>>58])
				tempPinBitboard &= tempPinBitboard - 1

				if tempPinBitboard == 0 {

					pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square
					pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square
					pinNumber+=1
				}
			}
			tempBitboard &= tempBitboard - 1
		}

		//rook
		rook_attacks :u64= GetRookAttacksFast(blackKingPosition, WHITE_OCCUPANCIES)
		tempBitboard = PieceArray[WR] & rook_attacks
		for tempBitboard != 0 {

			piece_square := (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
			tempPinBitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square] & BLACK_OCCUPANCIES

			if tempPinBitboard == 0 {
				if checkBitboard == 0 {

					checkBitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square]
				}
				blackKingCheckCount+=1
			} else {

				pinned_square := (DEBRUIJN64[MAGIC*(tempPinBitboard~(tempPinBitboard-1))>>58])
				tempPinBitboard &= tempPinBitboard - 1

				if tempPinBitboard == 0 {

					pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square
					pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square
					pinNumber+=1
				}
			}
			tempBitboard &= tempBitboard - 1
		}

		//queen
		tempBitboard = PieceArray[WQ] & rook_attacks
		for tempBitboard != 0 {

			piece_square :int= (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
			if piece_square == -1 {
				break
			}
			tempPinBitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square] & BLACK_OCCUPANCIES

			if tempPinBitboard == 0 {

				if checkBitboard == 0 {

					checkBitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square]
				}
				blackKingCheckCount+=1
			} else {

				pinned_square := (DEBRUIJN64[MAGIC*(tempPinBitboard~(tempPinBitboard-1))>>58])
				tempPinBitboard &= tempPinBitboard - 1

				if tempPinBitboard == 0 {

					pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square
					pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square
					pinNumber+=1
				}
			}
			tempBitboard &= tempBitboard - 1
		}

		if blackKingCheckCount > 1 {

			occupancyWithoutBlackKing := COMBINED_OCCUPANCIES & (~PieceArray[BK])
			if blackKingPosition == -1 {
				return 0
			}
			tempAttack = KING_ATTACKS[blackKingPosition] & WHITE_OCCUPANCIES

			for tempAttack != 0 {

				targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
				tempAttack &= tempAttack - 1

				if (PieceArray[WP] & BLACK_PAWN_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[WN] & KNIGHT_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[WK] & KING_ATTACKS[targetSquare]) != 0 {
					continue
				}
				bishopAttacks := GetBishopAttacksFast(targetSquare, occupancyWithoutBlackKing)
				if (PieceArray[WB] & bishopAttacks) != 0 {
					continue
				}
				if (PieceArray[WQ] & bishopAttacks) != 0 {
					continue
				}
				rookAttacks := GetRookAttacksFast(targetSquare, occupancyWithoutBlackKing)
				if (PieceArray[WR] & rookAttacks) != 0 {
					continue
				}
				if (PieceArray[WQ] & rookAttacks) != 0 {
					continue
				}

				moveList[moveCount][MOVE_STARTING] = startingSquare
				moveList[moveCount][MOVE_TARGET] = targetSquare
				moveList[moveCount][MOVE_TAG] = TAG_CAPTURE
				moveList[moveCount][MOVE_PIECE] = BK
				moveCount+=1
			}

			tempAttack = KING_ATTACKS[blackKingPosition] & ~COMBINED_OCCUPANCIES

			for tempAttack != 0 {
				targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
				tempAttack &= tempAttack - 1

				if (PieceArray[WP] & WHITE_PAWN_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[WN] & KNIGHT_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[WK] & KING_ATTACKS[targetSquare]) != 0 {
					continue
				}
				bishopAttacks := GetBishopAttacksFast(targetSquare, occupancyWithoutBlackKing)
				if (PieceArray[WB] & bishopAttacks) != 0 {
					continue
				}
				if (PieceArray[WQ] & bishopAttacks) != 0 {
					continue
				}
				rookAttacks := GetRookAttacksFast(targetSquare, occupancyWithoutBlackKing)
				if (PieceArray[WR] & rookAttacks) != 0 {
					continue
				}
				if (PieceArray[WQ] & rookAttacks) != 0 {
					continue
				}

				moveList[moveCount][MOVE_STARTING] = startingSquare
				moveList[moveCount][MOVE_TARGET] = targetSquare
				moveList[moveCount][MOVE_TAG] = TAG_NONE
				moveList[moveCount][MOVE_PIECE] = BK
				moveCount+=1
			}
		} else {
			if blackKingCheckCount == 0 {
				checkBitboard = MAX_ULONG
			}

			tempBitboard = PieceArray[BP]

			for tempBitboard != 0 {
				startingSquare = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
				tempBitboard &= tempBitboard - 1

				tempPinBitboard = MAX_ULONG
				if pinNumber != 0 {
					for i := 0; i < pinNumber; i+=1 {

						if pinArray[i][PINNED_SQUARE_INDEX] == startingSquare {
							tempPinBitboard = INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]
						}
					}
				}

				if (SQUARE_BBS[startingSquare+8] & COMBINED_OCCUPANCIES) == 0 { //if up one square is empty

					if ((SQUARE_BBS[startingSquare+8] & checkBitboard) & tempPinBitboard) != 0 {

						if (SQUARE_BBS[startingSquare] & RANK_2_BITBOARD) != 0 { //if promotion

							moveList[moveCount][MOVE_STARTING] = startingSquare
							moveList[moveCount][MOVE_TARGET] = startingSquare + 8
							moveList[moveCount][MOVE_TAG] = TAG_BBishopPromotion
							moveList[moveCount][MOVE_PIECE] = BP
							moveCount+=1

							moveList[moveCount][MOVE_STARTING] = startingSquare
							moveList[moveCount][MOVE_TARGET] = startingSquare + 8
							moveList[moveCount][MOVE_TAG] = TAG_BKnightPromotion
							moveList[moveCount][MOVE_PIECE] = BP
							moveCount+=1

							moveList[moveCount][MOVE_STARTING] = startingSquare
							moveList[moveCount][MOVE_TARGET] = startingSquare + 8
							moveList[moveCount][MOVE_TAG] = TAG_BRookPromotion
							moveList[moveCount][MOVE_PIECE] = BP
							moveCount+=1

							moveList[moveCount][MOVE_STARTING] = startingSquare
							moveList[moveCount][MOVE_TARGET] = startingSquare + 8
							moveList[moveCount][MOVE_TAG] = TAG_BQueenPromotion
							moveList[moveCount][MOVE_PIECE] = BP
							moveCount+=1
						} else {

							moveList[moveCount][MOVE_STARTING] = startingSquare
							moveList[moveCount][MOVE_TARGET] = startingSquare + 8
							moveList[moveCount][MOVE_TAG] = TAG_NONE
							moveList[moveCount][MOVE_PIECE] = BP
							moveCount+=1
						}
					}

					if (SQUARE_BBS[startingSquare] & RANK_7_BITBOARD) != 0 { //if on rank 2

						if ((SQUARE_BBS[startingSquare+16] & checkBitboard) & tempPinBitboard) != 0 {

							if ((SQUARE_BBS[startingSquare+16]) & COMBINED_OCCUPANCIES) == 0 { //if up two squares and one square are empty

								moveList[moveCount][MOVE_STARTING] = startingSquare
								moveList[moveCount][MOVE_TARGET] = startingSquare + 16
								moveList[moveCount][MOVE_TAG] = TAG_DoublePawnBlack
								moveList[moveCount][MOVE_PIECE] = BP
								moveCount+=1
							}
						}
					}
				}

				tempAttack = ((BLACK_PAWN_ATTACKS[startingSquare] & WHITE_OCCUPANCIES) & checkBitboard) & tempPinBitboard //if black piece diagonal to pawn

				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58]) //find the bit
					tempAttack &= tempAttack - 1

					if (SQUARE_BBS[startingSquare] & RANK_2_BITBOARD) != 0 { //if promotion

						moveList[moveCount][MOVE_STARTING] = startingSquare
						moveList[moveCount][MOVE_TARGET] = targetSquare
						moveList[moveCount][MOVE_TAG] = TAG_BCaptureQueenPromotion
						moveList[moveCount][MOVE_PIECE] = BP
						moveCount+=1

						moveList[moveCount][MOVE_STARTING] = startingSquare
						moveList[moveCount][MOVE_TARGET] = targetSquare
						moveList[moveCount][MOVE_TAG] = TAG_BCaptureRookPromotion
						moveList[moveCount][MOVE_PIECE] = BP
						moveCount+=1

						moveList[moveCount][MOVE_STARTING] = startingSquare
						moveList[moveCount][MOVE_TARGET] = targetSquare
						moveList[moveCount][MOVE_TAG] = TAG_BCaptureKnightPromotion
						moveList[moveCount][MOVE_PIECE] = BP
						moveCount+=1

						moveList[moveCount][MOVE_STARTING] = startingSquare
						moveList[moveCount][MOVE_TARGET] = targetSquare
						moveList[moveCount][MOVE_TAG] = TAG_BCaptureBishopPromotion
						moveList[moveCount][MOVE_PIECE] = BP
						moveCount+=1
					} else {

						moveList[moveCount][MOVE_STARTING] = startingSquare
						moveList[moveCount][MOVE_TARGET] = targetSquare
						moveList[moveCount][MOVE_TAG] = TAG_CAPTURE
						moveList[moveCount][MOVE_PIECE] = BP
						moveCount+=1
					}
				}

				if (SQUARE_BBS[startingSquare] & RANK_4_BITBOARD) != 0 { //check rank for ep

					if ep != NO_SQUARE {

						if (((BLACK_PAWN_ATTACKS[startingSquare] & SQUARE_BBS[ep]) & checkBitboard) & tempPinBitboard) != 0 {

							if (PieceArray[BK] & RANK_4_BITBOARD) == 0 { //if no king on rank 5

								moveList[moveCount][MOVE_STARTING] = startingSquare
								moveList[moveCount][MOVE_TARGET] = int(ep)
								moveList[moveCount][MOVE_TAG] = TAG_BLACKEP
								moveList[moveCount][MOVE_PIECE] = BP
								moveCount+=1
							} else if (PieceArray[WR]&RANK_4_BITBOARD) == 0 && (PieceArray[WQ]&RANK_4_BITBOARD) == 0 { // if no b rook or queen on rank 5

								moveList[moveCount][MOVE_STARTING] = startingSquare
								moveList[moveCount][MOVE_TARGET] = int(ep)
								moveList[moveCount][MOVE_TAG] = TAG_BLACKEP
								moveList[moveCount][MOVE_PIECE] = BP
								moveCount+=1
							} else { //wk and br or bq on rank 5

								occupancyWithoutEPPawns :u64= COMBINED_OCCUPANCIES & ~SQUARE_BBS[startingSquare]
								occupancyWithoutEPPawns &= ~SQUARE_BBS[ep-8]

								rookAttacksFromKing :u64= GetRookAttacksFast(blackKingPosition, occupancyWithoutEPPawns);

								if (rookAttacksFromKing & PieceArray[WR]) == 0 {

									if (rookAttacksFromKing & PieceArray[WQ]) == 0 {
										moveList[moveCount][MOVE_STARTING] = startingSquare
										moveList[moveCount][MOVE_TARGET] = int(ep)
										moveList[moveCount][MOVE_TAG] = TAG_BLACKEP
										moveList[moveCount][MOVE_PIECE] = BP
										moveCount+=1
									}
								}
							}
						}
					}
				}
			}

			tempBitboard = PieceArray[BN]

			for tempBitboard != 0 {

				startingSquare = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58]) //looks for the startingSquare
				tempBitboard &= tempBitboard - 1                                         //removes the knight from that square to not infinitely loop

				tempPinBitboard = MAX_ULONG
				if pinNumber != 0 {

					for i := 0; i < pinNumber; i+=1 {

						if pinArray[i][PINNED_SQUARE_INDEX] == startingSquare {

							tempPinBitboard = INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]
						}
					}
				}

				tempAttack = ((KNIGHT_ATTACKS[startingSquare] & WHITE_OCCUPANCIES) & checkBitboard) & tempPinBitboard //gets knight captures
				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_CAPTURE
					moveList[moveCount][MOVE_PIECE] = BN
					moveCount+=1
				}

				tempAttack = ((KNIGHT_ATTACKS[startingSquare] & (~COMBINED_OCCUPANCIES)) & checkBitboard) & tempPinBitboard

				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_NONE
					moveList[moveCount][MOVE_PIECE] = BN
					moveCount+=1
				}
			}

			tempBitboard = PieceArray[BB]
			for tempBitboard != 0 {

				startingSquare = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
				tempBitboard &= tempBitboard - 1

				tempPinBitboard = MAX_ULONG
				if pinNumber != 0 {
					for i := 0; i < pinNumber; i+=1 {

						if pinArray[i][PINNED_SQUARE_INDEX] == startingSquare {

							tempPinBitboard = INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]
						}
					}
				}

				bishopAttacks :u64= GetBishopAttacksFast(startingSquare, COMBINED_OCCUPANCIES)

				tempAttack = ((bishopAttacks & WHITE_OCCUPANCIES) & checkBitboard) & tempPinBitboard
				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_CAPTURE
					moveList[moveCount][MOVE_PIECE] = BB
					moveCount+=1
				}

				tempAttack = ((bishopAttacks & (~COMBINED_OCCUPANCIES)) & checkBitboard) & tempPinBitboard
				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_NONE
					moveList[moveCount][MOVE_PIECE] = BB
					moveCount+=1
				}
			}

			tempBitboard = PieceArray[BR]
			for tempBitboard != 0 {

				startingSquare = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
				tempBitboard &= tempBitboard - 1

				tempPinBitboard = MAX_ULONG
				if pinNumber != 0 {

					for i := 0; i < pinNumber; i+=1 {

						if pinArray[i][PINNED_SQUARE_INDEX] == startingSquare {

							tempPinBitboard = INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]
						}
					}
				}

				rookAttacks :u64= GetRookAttacksFast(startingSquare, COMBINED_OCCUPANCIES)

				tempAttack = ((rookAttacks & WHITE_OCCUPANCIES) & checkBitboard) & tempPinBitboard
				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_CAPTURE
					moveList[moveCount][MOVE_PIECE] = BR
					moveCount+=1
				}

				tempAttack = ((rookAttacks & (~COMBINED_OCCUPANCIES)) & checkBitboard) & tempPinBitboard
				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_NONE
					moveList[moveCount][MOVE_PIECE] = BR
					moveCount+=1
				}
			}

			tempBitboard = PieceArray[BQ]
			for tempBitboard != 0 {

				startingSquare = (DEBRUIJN64[MAGIC*(tempBitboard~(tempBitboard-1))>>58])
				tempBitboard &= tempBitboard - 1

				tempPinBitboard = MAX_ULONG
				if pinNumber != 0 {

					for i := 0; i < pinNumber; i+=1 {

						if pinArray[i][PINNED_SQUARE_INDEX] == startingSquare {

							tempPinBitboard = INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]
						}
					}
				}

				queenAttacks :u64= GetRookAttacksFast(startingSquare, COMBINED_OCCUPANCIES)
				queenAttacks |= GetBishopAttacksFast(startingSquare, COMBINED_OCCUPANCIES)

				tempAttack = ((queenAttacks & WHITE_OCCUPANCIES) & checkBitboard) & tempPinBitboard

				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_CAPTURE
					moveList[moveCount][MOVE_PIECE] = BQ
					moveCount+=1
				}

				tempAttack = ((queenAttacks & (~COMBINED_OCCUPANCIES)) & checkBitboard) & tempPinBitboard

				for tempAttack != 0 {

					targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
					tempAttack &= tempAttack - 1

					moveList[moveCount][MOVE_STARTING] = startingSquare
					moveList[moveCount][MOVE_TARGET] = targetSquare
					moveList[moveCount][MOVE_TAG] = TAG_NONE
					moveList[moveCount][MOVE_PIECE] = BQ
					moveCount+=1
				}
			}

			tempAttack = KING_ATTACKS[blackKingPosition] & WHITE_OCCUPANCIES //gets knight captures
			for tempAttack != 0 {

				targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
				tempAttack &= tempAttack - 1

				if (PieceArray[WP] & BLACK_PAWN_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[WN] & KNIGHT_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[WK] & KING_ATTACKS[targetSquare]) != 0 {
					continue
				}
				occupancyWithoutBlackKing := COMBINED_OCCUPANCIES & (~PieceArray[BK])
				bishopAttacks := GetBishopAttacksFast(targetSquare, occupancyWithoutBlackKing)
				if (PieceArray[WB] & bishopAttacks) != 0 {
					continue
				}
				if (PieceArray[WQ] & bishopAttacks) != 0 {
					continue
				}
				rookAttacks := GetRookAttacksFast(targetSquare, occupancyWithoutBlackKing)
				if (PieceArray[WR] & rookAttacks) != 0 {
					continue
				}
				if (PieceArray[WQ] & rookAttacks) != 0 {
					continue
				}

				moveList[moveCount][MOVE_STARTING] = blackKingPosition
				moveList[moveCount][MOVE_TARGET] = targetSquare
				moveList[moveCount][MOVE_TAG] = TAG_CAPTURE
				moveList[moveCount][MOVE_PIECE] = BK
				moveCount+=1
			}

			tempAttack = KING_ATTACKS[blackKingPosition] & (~COMBINED_OCCUPANCIES) //get knight moves to emtpy squares

			for tempAttack != 0 {

				targetSquare = (DEBRUIJN64[MAGIC*(tempAttack~(tempAttack-1))>>58])
				tempAttack &= tempAttack - 1

				if (PieceArray[WP] & BLACK_PAWN_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[WN] & KNIGHT_ATTACKS[targetSquare]) != 0 {
					continue
				}
				if (PieceArray[WK] & KING_ATTACKS[targetSquare]) != 0 {
					continue
				}
				occupancyWithoutBlackKing := COMBINED_OCCUPANCIES & (~PieceArray[BK])
				bishopAttacks := GetBishopAttacksFast(targetSquare, occupancyWithoutBlackKing)
				if (PieceArray[WB] & bishopAttacks) != 0 {
					continue
				}
				if (PieceArray[WQ] & bishopAttacks) != 0 {
					continue
				}
				rookAttacks:u64 = GetRookAttacksFast(targetSquare, occupancyWithoutBlackKing)
				if (PieceArray[WR] & rookAttacks) != 0 {
					continue
				}
				if (PieceArray[WQ] & rookAttacks) != 0 {
					continue
				}

				moveList[moveCount][MOVE_STARTING] = blackKingPosition
				moveList[moveCount][MOVE_TARGET] = targetSquare
				moveList[moveCount][MOVE_TAG] = TAG_NONE
				moveList[moveCount][MOVE_PIECE] = BK
				moveCount+=1
			}
		}
		if blackKingCheckCount == 0 {

			if CastleRights[BKS_CASTLE_RIGHTS] == true {

				if blackKingPosition == E8 { //king on e1

					if (BKS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES) == 0 { //f1 and g1 empty

						if (PieceArray[BR] & SQUARE_BBS[H8]) != 0 { //rook on h1

							if Is_Square_Attacked_By_White(F8, COMBINED_OCCUPANCIES) == false {

								if Is_Square_Attacked_By_White(G8, COMBINED_OCCUPANCIES) == false {

									moveList[moveCount][MOVE_STARTING] = E8
									moveList[moveCount][MOVE_TARGET] = G8
									moveList[moveCount][MOVE_TAG] = TAG_BCASTLEKS
									moveList[moveCount][MOVE_PIECE] = BK
									moveCount+=1
								}
							}
						}
					}
				}
			}
			if CastleRights[BQS_CASTLE_RIGHTS] == true {

				if blackKingPosition == E8 { //king on e1

					if (BQS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES) == 0 { //f1 and g1 empty

						if (PieceArray[BR] & SQUARE_BBS[A8]) != 0 { //rook on h1

							if Is_Square_Attacked_By_White(C8, COMBINED_OCCUPANCIES) == false {

								if Is_Square_Attacked_By_White(D8, COMBINED_OCCUPANCIES) == false {

									moveList[moveCount][MOVE_STARTING] = E8
									moveList[moveCount][MOVE_TARGET] = C8
									moveList[moveCount][MOVE_TAG] = TAG_BCASTLEQS
									moveList[moveCount][MOVE_PIECE] = BK
									moveCount+=1
								}
							}
						}
					}
				}
			}
		}
	}

	if depth == 1 {
		return moveCount;
	}

	nodes: u64 = 0
	priorNodes: u64
	copyEp: int = ep
	copyCastle: [4]bool;
	copyCastle[0] = CastleRights[0]
	copyCastle[1] = CastleRights[1]
	copyCastle[2] = CastleRights[2]
	copyCastle[3] = CastleRights[3]

	for moveIndex := 0; moveIndex < int(moveCount); moveIndex+=1 {

		startingSquare := moveList[moveIndex][MOVE_STARTING]
		targetSquare := moveList[moveIndex][MOVE_TARGET]
		piece := moveList[moveIndex][MOVE_PIECE]
		tag := moveList[moveIndex][MOVE_TAG]

		captureIndex: int = -1

		whiteToPlay = !whiteToPlay

		switch tag {
		case TAG_NONE: //none
			PieceArray[piece] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE
		case TAG_CHECK: //check
			PieceArray[piece] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE
		case TAG_CAPTURE: //capture
			PieceArray[piece] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			if PieceIsWhite(piece) {

				for i := BLACK_START_INDEX; i <= BLACK_END_INDEX; i+=1 {

					if (PieceArray[i] & SQUARE_BBS[targetSquare]) != 0 {

						captureIndex = i
						break
					}
				}
				PieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare]

			} else { //is black

				for i := WHITE_START_INDEX; i <= WHITE_END_INDEX; i+=1 {

					if (PieceArray[i] & SQUARE_BBS[targetSquare]) != 0 {

						captureIndex = i
						break
					}
				}
				PieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare]

			}
			ep = NO_SQUARE
		case TAG_CHECK_CAPTURE: //check cap
			PieceArray[piece] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			if PieceIsWhite(piece) {

				for i := BLACK_START_INDEX; i <= BLACK_END_INDEX; i+=1 {

					if (PieceArray[i] & SQUARE_BBS[targetSquare]) != 0 {

						captureIndex = i
						break
					}
				}
				PieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare]

			} else { //is black

				for i := WHITE_START_INDEX; i <= WHITE_END_INDEX; i+=1 {

					if (PieceArray[i] & SQUARE_BBS[targetSquare]) != 0 {

						captureIndex = i
						break
					}
				}
				PieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare]

			}
			ep = NO_SQUARE
		case TAG_WHITEEP: //white ep
			//move piece
			PieceArray[WP] |= SQUARE_BBS[targetSquare]
			PieceArray[WP] &= ~SQUARE_BBS[startingSquare]
			//remove
			PieceArray[BP] &= ~SQUARE_BBS[targetSquare+8]
			ep = NO_SQUARE
		case TAG_BLACKEP: //black ep
			//move piece
			PieceArray[BP] |= SQUARE_BBS[targetSquare]
			PieceArray[BP] &= ~SQUARE_BBS[startingSquare]
			//remove white pawn square up
			PieceArray[WP] &= ~SQUARE_BBS[targetSquare-8]
			ep = NO_SQUARE

		case TAG_WCASTLEKS: //WKS
			//white king
			PieceArray[WK] |= SQUARE_BBS[G1]
			PieceArray[WK] &= ~SQUARE_BBS[E1]
			//white rook
			PieceArray[WR] |= SQUARE_BBS[F1]
			PieceArray[WR] &= ~SQUARE_BBS[H1]
			//occupancies
			CastleRights[WKS_CASTLE_RIGHTS] = false
			CastleRights[WQS_CASTLE_RIGHTS] = false
			ep = NO_SQUARE

		case TAG_WCASTLEQS: //WQS
			//white king
			PieceArray[WK] |= SQUARE_BBS[C1]
			PieceArray[WK] &= ~SQUARE_BBS[E1]
			//white rook
			PieceArray[WR] |= SQUARE_BBS[D1]
			PieceArray[WR] &= ~SQUARE_BBS[A1]

			CastleRights[WKS_CASTLE_RIGHTS] = false
			CastleRights[WQS_CASTLE_RIGHTS] = false
			ep = NO_SQUARE

		case TAG_BCASTLEKS: //BKS
			//white king
			PieceArray[BK] |= SQUARE_BBS[G8]
			PieceArray[BK] &= ~SQUARE_BBS[E8]
			//white rook
			PieceArray[BR] |= SQUARE_BBS[F8]
			PieceArray[BR] &= ~SQUARE_BBS[H8]
			CastleRights[BKS_CASTLE_RIGHTS] = false
			CastleRights[BQS_CASTLE_RIGHTS] = false
			ep = NO_SQUARE

		case TAG_BCASTLEQS: //BQS
			//white king
			PieceArray[BK] |= SQUARE_BBS[C8]
			PieceArray[BK] &= ~SQUARE_BBS[E8]
			//white rook
			PieceArray[BR] |= SQUARE_BBS[D8]
			PieceArray[BR] &= ~SQUARE_BBS[A8]
			CastleRights[BKS_CASTLE_RIGHTS] = false
			CastleRights[BQS_CASTLE_RIGHTS] = false
			ep = NO_SQUARE

		case TAG_BKnightPromotion: //BNPr
			PieceArray[BN] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE

		case TAG_BBishopPromotion: //BBPr
			PieceArray[BB] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE

		case TAG_BQueenPromotion: //BQPr
			PieceArray[BQ] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE

		case TAG_BRookPromotion: //BRPr
			PieceArray[BR] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE

		case 12: //WNPr
			PieceArray[WN] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE

		case 13: //WBPr
			PieceArray[WB] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE

		case 14: //WQPr
			PieceArray[WQ] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE

		case 15: //WRPr
			PieceArray[WR] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE

		case 16: //BNPrCAP
			PieceArray[BN] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE
			for i := WHITE_START_INDEX; i <= WHITE_END_INDEX; i+=1 {

				if (PieceArray[i] & SQUARE_BBS[targetSquare]) != 0 {

					captureIndex = i
					break
				}
			}
			PieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare]

		case 17: //BBPrCAP
			PieceArray[BB] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]

			ep = NO_SQUARE
			for i := WHITE_START_INDEX; i <= WHITE_END_INDEX; i+=1 {

				if (PieceArray[i] & SQUARE_BBS[targetSquare]) != 0 {

					captureIndex = i
					break
				}
			}
			PieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare]

		case 18: //BQPrCAP
			PieceArray[BQ] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE
			for i := WHITE_START_INDEX; i <= WHITE_END_INDEX; i+=1 {

				if (PieceArray[i] & SQUARE_BBS[targetSquare]) != 0 {

					captureIndex = i
					break
				}
			}
			PieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare]

		case 19: //BRPrCAP
			PieceArray[BR] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE
			for i := WHITE_START_INDEX; i <= WHITE_END_INDEX; i+=1 {

				if (PieceArray[i] & SQUARE_BBS[targetSquare]) != 0 {

					captureIndex = i
					break
				}
			}
			PieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare]

		case 20: //WNPrCAP
			PieceArray[WN] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE
			for i := BLACK_START_INDEX; i <= BLACK_END_INDEX; i+=1 {

				if (PieceArray[i] & SQUARE_BBS[targetSquare]) != 0 {

					captureIndex = i
					break
				}
			}
			PieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare]

		case 21: //WBPrCAP
			PieceArray[WB] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE
			for i := BLACK_START_INDEX; i <= BLACK_END_INDEX; i+=1 {

				if (PieceArray[i] & SQUARE_BBS[targetSquare]) != 0 {

					captureIndex = i
					break
				}
			}
			PieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare]

		case 22: //WQPrCAP
			PieceArray[WQ] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE
			for i := BLACK_START_INDEX; i <= BLACK_END_INDEX; i+=1 {

				if (PieceArray[i] & SQUARE_BBS[targetSquare]) != 0 {

					captureIndex = i
					break
				}
			}
			PieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare]

		case 23: //WRPrCAP
			PieceArray[WR] |= SQUARE_BBS[targetSquare]
			PieceArray[piece] &= ~SQUARE_BBS[startingSquare]
			ep = NO_SQUARE
			for i := BLACK_START_INDEX; i <= BLACK_END_INDEX; i+=1 {

				if (PieceArray[i] & SQUARE_BBS[targetSquare]) != 0 {

					captureIndex = i
					break
				}
			}
			PieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare]

		case 24: //WDouble
			PieceArray[WP] |= SQUARE_BBS[targetSquare]
			PieceArray[WP] &= ~SQUARE_BBS[startingSquare]
			ep = targetSquare + 8

		case 25: //BDouble
			PieceArray[BP] |= SQUARE_BBS[targetSquare]
			PieceArray[BP] &= ~SQUARE_BBS[startingSquare]
			ep = targetSquare - 8
		}

		if piece == WK {

			CastleRights[WKS_CASTLE_RIGHTS] = false
			CastleRights[WQS_CASTLE_RIGHTS] = false
		} else if piece == BK {

			CastleRights[BKS_CASTLE_RIGHTS] = false
			CastleRights[BQS_CASTLE_RIGHTS] = false
		} else if piece == WR {

			if CastleRights[WKS_CASTLE_RIGHTS] == true {

				if (PieceArray[WR] & SQUARE_BBS[H1]) == 0 {

					CastleRights[WKS_CASTLE_RIGHTS] = false
				}
			}
			if CastleRights[WQS_CASTLE_RIGHTS] == true {

				if (PieceArray[WR] & SQUARE_BBS[A1]) == 0 {

					CastleRights[WQS_CASTLE_RIGHTS] = false
				}
			}
		} else if piece == BR {

			if CastleRights[BKS_CASTLE_RIGHTS] == true {

				if (PieceArray[BR] & SQUARE_BBS[H8]) == 0 {

					CastleRights[BKS_CASTLE_RIGHTS] = false
				}
			}
			if CastleRights[BQS_CASTLE_RIGHTS] == true {

				if (PieceArray[BR] & SQUARE_BBS[A8]) == 0 {

					CastleRights[BQS_CASTLE_RIGHTS] = false
				}
			}
		}

		priorNodes = nodes
		nodes += PerftInline(depth-1, ply+1)

		whiteToPlay = !whiteToPlay
		switch tag {
		case TAG_NONE: //none
			PieceArray[piece] |= SQUARE_BBS[startingSquare]
			PieceArray[piece] &= ~SQUARE_BBS[targetSquare]
		case TAG_CHECK: //check
			PieceArray[piece] |= SQUARE_BBS[startingSquare]
			PieceArray[piece] &= ~SQUARE_BBS[targetSquare]

		case TAG_CAPTURE: //capture
			PieceArray[piece] |= SQUARE_BBS[startingSquare]
			PieceArray[piece] &= ~SQUARE_BBS[targetSquare]
			if PieceIsWhite(piece) == true {

				PieceArray[captureIndex] |= SQUARE_BBS[targetSquare]
			} else { //is black

				PieceArray[captureIndex] |= SQUARE_BBS[targetSquare]
			}
		case TAG_CHECK_CAPTURE: //check cap
			PieceArray[piece] |= SQUARE_BBS[startingSquare]
			PieceArray[piece] &= ~SQUARE_BBS[targetSquare]
			if PieceIsWhite(piece) == true {

				PieceArray[captureIndex] |= SQUARE_BBS[targetSquare]
			} else { //is black

				PieceArray[captureIndex] |= SQUARE_BBS[targetSquare]
			}

		case TAG_WHITEEP: //white ep
			PieceArray[WP] |= SQUARE_BBS[startingSquare]
			PieceArray[WP] &= ~SQUARE_BBS[targetSquare]
			PieceArray[BP] |= SQUARE_BBS[targetSquare+8]

		case TAG_BLACKEP: //black ep
			PieceArray[BP] |= SQUARE_BBS[startingSquare]
			PieceArray[BP] &= ~SQUARE_BBS[targetSquare]
			PieceArray[WP] |= SQUARE_BBS[targetSquare-8]

		case TAG_WCASTLEKS: //WKS
			//white king
			PieceArray[WK] |= SQUARE_BBS[E1]
			PieceArray[WK] &= ~SQUARE_BBS[G1]
			//white rook
			PieceArray[WR] |= SQUARE_BBS[H1]
			PieceArray[WR] &= ~SQUARE_BBS[F1]

		case TAG_WCASTLEQS: //WQS
			//white king
			PieceArray[WK] |= SQUARE_BBS[E1]
			PieceArray[WK] &= ~SQUARE_BBS[C1]
			//white rook
			PieceArray[WR] |= SQUARE_BBS[A1]
			PieceArray[WR] &= ~SQUARE_BBS[D1]

		case TAG_BCASTLEKS: //BKS
			//white king
			PieceArray[BK] |= SQUARE_BBS[E8]
			PieceArray[BK] &= ~SQUARE_BBS[G8]
			//white rook
			PieceArray[BR] |= SQUARE_BBS[H8]
			PieceArray[BR] &= ~SQUARE_BBS[F8]

		case TAG_BCASTLEQS: //BQS
			//white king
			PieceArray[BK] |= SQUARE_BBS[E8]
			PieceArray[BK] &= ~SQUARE_BBS[C8]
			//white rook
			PieceArray[BR] |= SQUARE_BBS[A8]
			PieceArray[BR] &= ~SQUARE_BBS[D8]

		case TAG_BKnightPromotion: //BNPr
			PieceArray[BP] |= SQUARE_BBS[startingSquare]
			PieceArray[BN] &= ~SQUARE_BBS[targetSquare]

		case TAG_BBishopPromotion: //BBPr
			PieceArray[BP] |= SQUARE_BBS[startingSquare]
			PieceArray[BB] &= ~SQUARE_BBS[targetSquare]

		case TAG_BQueenPromotion: //BQPr
			PieceArray[BP] |= SQUARE_BBS[startingSquare]
			PieceArray[BQ] &= ~SQUARE_BBS[targetSquare]

		case TAG_BRookPromotion: //BRPr
			PieceArray[BP] |= SQUARE_BBS[startingSquare]
			PieceArray[BR] &= ~SQUARE_BBS[targetSquare]

		case TAG_WKnightPromotion: //WNPr
			PieceArray[WP] |= SQUARE_BBS[startingSquare]
			PieceArray[WN] &= ~SQUARE_BBS[targetSquare]

		case TAG_WBishopPromotion: //WBPr
			PieceArray[WP] |= SQUARE_BBS[startingSquare]
			PieceArray[WB] &= ~SQUARE_BBS[targetSquare]

		case TAG_WQueenPromotion: //WQPr
			PieceArray[WP] |= SQUARE_BBS[startingSquare]
			PieceArray[WQ] &= ~SQUARE_BBS[targetSquare]

		case TAG_WRookPromotion: //WRPr
			PieceArray[WP] |= SQUARE_BBS[startingSquare]
			PieceArray[WR] &= ~SQUARE_BBS[targetSquare]

		case TAG_BCaptureKnightPromotion: //BNPrCAP
			PieceArray[BP] |= SQUARE_BBS[startingSquare]
			PieceArray[BN] &= ~SQUARE_BBS[targetSquare]
			PieceArray[captureIndex] |= SQUARE_BBS[targetSquare]

		case TAG_BCaptureBishopPromotion: //BBPrCAP
			PieceArray[BP] |= SQUARE_BBS[startingSquare]
			PieceArray[BB] &= ~SQUARE_BBS[targetSquare]
			PieceArray[captureIndex] |= SQUARE_BBS[targetSquare]

		case TAG_BCaptureQueenPromotion: //BQPrCAP
			PieceArray[BP] |= SQUARE_BBS[startingSquare]
			PieceArray[BQ] &= ~SQUARE_BBS[targetSquare]
			PieceArray[captureIndex] |= SQUARE_BBS[targetSquare]

		case TAG_BCaptureRookPromotion: //BRPrCAP
			PieceArray[BP] |= SQUARE_BBS[startingSquare]
			PieceArray[BR] &= ~SQUARE_BBS[targetSquare]
			PieceArray[captureIndex] |= SQUARE_BBS[targetSquare]

		case TAG_WCaptureKnightPromotion: //WNPrCAP
			PieceArray[WP] |= SQUARE_BBS[startingSquare]
			PieceArray[WN] &= ~SQUARE_BBS[targetSquare]
			PieceArray[captureIndex] |= SQUARE_BBS[targetSquare]

		case TAG_WCaptureBishopPromotion: //WBPrCAP
			PieceArray[WP] |= SQUARE_BBS[startingSquare]
			PieceArray[WB] &= ~SQUARE_BBS[targetSquare]
			PieceArray[captureIndex] |= SQUARE_BBS[targetSquare]

		case TAG_WCaptureQueenPromotion: //WQPrCAP
			PieceArray[WP] |= SQUARE_BBS[startingSquare]
			PieceArray[WQ] &= ~SQUARE_BBS[targetSquare]
			PieceArray[captureIndex] |= SQUARE_BBS[targetSquare]

		case TAG_WCaptureRookPromotion: //WRPrCAP
			PieceArray[WP] |= SQUARE_BBS[startingSquare]
			PieceArray[WR] &= ~SQUARE_BBS[targetSquare]
			PieceArray[captureIndex] |= SQUARE_BBS[targetSquare]

		case TAG_DoublePawnWhite: //WDouble
			PieceArray[WP] |= SQUARE_BBS[startingSquare]
			PieceArray[WP] &= ~SQUARE_BBS[targetSquare]

		case TAG_DoublePawnBlack: //BDouble
			PieceArray[BP] |= SQUARE_BBS[startingSquare]
			PieceArray[BP] &= ~SQUARE_BBS[targetSquare]

		}

		CastleRights[0] = copyCastle[0]
		CastleRights[1] = copyCastle[1]
		CastleRights[2] = copyCastle[2]
		CastleRights[3] = copyCastle[3]
		ep = copyEp

		if ply == 0 {
			PrintMoveNoNL(moveList[moveIndex][MOVE_STARTING], moveList[moveIndex][MOVE_TARGET], moveList[moveIndex][MOVE_TAG])
			fmt.printf(": %d\n", nodes-priorNodes)
		}
	}

	return nodes
}

RunPerftInline :: proc(depth: int) {


	start_time: = time.now();

	nodes := PerftInline(depth, 0)

	end_time: = time.now();
	elapsed_time:= end_time._nsec - start_time._nsec; 


	fmt.printf("Nodes: %d\n", nodes)
	fmt.printf("Raw elapsed duration: %d ms\n", elapsed_time);
}
