// File: /workspace/github_cpp_makefile_star2_O2/niekh1234[P]nnchesslib/board.cpp
// Function: nnchesslib::ChessBoard::isValidFen(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
bool ChessBoard::isValidFen(std::string fen)
{
    // Setup variables
    std::istringstream iss(fen);
    std::string board, sideToMove, castleRights, enpassant, movecount, plycount;

    // check if fen is provided
    if(!iss) return false;

    iss >> board;

    if(!iss) return false;

    iss >> sideToMove;

    if (!iss) 
    {
        castleRights = "-";
        enpassant = "-";
    } 
    else 
    {
        iss >> castleRights;
        if (iss)
            iss >> enpassant;
        else
            enpassant = "-";
    }
    
    iss >> movecount;

    iss >> plycount;

    boardinfo.plyCount = stoi(plycount);
    boardinfo.fiftyMoveRule = stoi(movecount);

    // Let's check that all components of the supposed FEN are OK.
    // Check side to move
    if (sideToMove != "w" && sideToMove != "b") return false;
    
    // Check castling rights
    if (castleRights != "-" && castleRights != "K" && castleRights != "Kk"
        && castleRights != "Kkq" && castleRights != "Kq" && castleRights !="KQ"
        && castleRights != "KQk" && castleRights != "KQq" && castleRights != "KQkq"
        && castleRights != "k" && castleRights != "q" && castleRights != "kq"
        && castleRights != "Q" && castleRights != "Qk" && castleRights != "Qq"
        && castleRights != "Qkq")
        return false;

    // Check valid en passant
    if (enpassant != "-") {
        if (enpassant.length() != 2) return false;
        if (!(enpassant[0] >= 'a' && enpassant[0] <= 'h')) return false;
        if (!((sideToMove == "w" && enpassant[1] == '6') || (sideToMove == "b" && enpassant[1] == '3')))
            return false;
    }

    // Check valid board
    // Seven board dividers
    if (std::count(board.begin(), board.end(), '/') != 7) return false;

    // Board contains only legal characters
    for (int i = 0; i < board.length(); i++)
        if (!(board[i] == '/' || (board[i] >= '1' && board[i] <= '8')
                || board[i] == 'p' || board[i] == 'P' || board[i] == 'r' || board[i] == 'R' || 
                board[i] == 'k' || board[i] == 'K' || board[i] == 'n' || board[i] == 'N' || board[i] == 'b' || board[i] == 'B'
                || board[i] == 'q' || board[i] == 'Q'))
            return false;
    
    // Check king amount
    if (std::count(board.begin(), board.end(), 'K') != 1) return false;
    if (std::count(board.begin(), board.end(), 'k') != 1) return false;

    // Count other piece amounts
    size_t wp = std::count(board.begin(), board.end(), 'P'),
        bp = std::count(board.begin(), board.end(), 'p'),
        wn = std::count(board.begin(), board.end(), 'N'),
        bn = std::count(board.begin(), board.end(), 'n'),
        wb = std::count(board.begin(), board.end(), 'B'),
        bb = std::count(board.begin(), board.end(), 'b'),
        wr = std::count(board.begin(), board.end(), 'R'),
        br = std::count(board.begin(), board.end(), 'r'),
        wq = std::count(board.begin(), board.end(), 'Q'),
        bq = std::count(board.begin(), board.end(), 'q');

    // Check if piece count is valid
    if (wp > 8 || bp > 8 || wn > 10 || bn > 10 || wb > 10 || bb > 10
        || wr > 10 || br > 10 || wq > 9 || bq > 9
        || wp + wn + wb + wr + wq > 15 || bp + bn + bb + br + bq > 15)
        return false;

    // setting some variables now that all the checks have been passed:
    // put this in dedicated function in the future.

    // changing who's turn it is.
    if(sideToMove == "w") boardinfo.whiteToMove = true;
    else boardinfo.whiteToMove = false;

    // setting the castling rights bools
    for (auto c : castleRights)
    {
        switch(c)
        {
            case 'K':
                boardinfo.whiteCastleShort = true;
                break;
            case 'Q':
                boardinfo.whiteCastleLong = true;
                break;
            case 'k':
                boardinfo.blackCastleShort = true;
                break;
            case 'q':
                boardinfo.blackCastleLong = true;
                break;
        }
    }

    // setting en passant bitboard.
    if(enpassant != "-")
    {
        if(boardinfo.whiteToMove)  boardinfo.whiteEnPassantTarget.set(getSquareInt(enpassant), true);
        if(!boardinfo.whiteToMove) boardinfo.blackEnPassantTarget.set(getSquareInt(enpassant), true);
    }
    // All checks passed
    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2b8, %rsp            # imm = 0x2B8
movq %rdi, %rbx
leaq -0x2d8(%rbp), %r15
pushq $0x8
popq %rdx
movq %r15, %rdi
callq 0x2260
leaq -0x40(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
xorl %r14d, %r14d
movb %r14b, (%rax)
leaq -0xa0(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
leaq -0x60(%rbp), %rcx
movq %rcx, -0x10(%rcx)
andq $0x0, -0x8(%rcx)
movb %r14b, (%rax)
movb %r14b, (%rcx)
leaq -0x80(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
leaq -0x108(%rbp), %rcx
movq %rcx, -0x10(%rcx)
andq $0x0, -0x8(%rcx)
movb %r14b, (%rax)
movb %r14b, (%rcx)
leaq -0xe8(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb %r14b, (%rax)
movq (%r15), %rax
movq -0x18(%rax), %rax
testb $0x5, -0x2b8(%rbp,%rax)
jne 0x3892
leaq -0x2d8(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x21e0
movq -0x2d8(%rbp), %rax
movq -0x18(%rax), %rax
testb $0x5, -0x2b8(%rbp,%rax)
je 0x38f5
xorl %r14d, %r14d
leaq -0xf8(%rbp), %rdi
callq 0x2308
leaq -0x118(%rbp), %rdi
callq 0x2308
leaq -0x90(%rbp), %rdi
callq 0x2308
leaq -0x70(%rbp), %rdi
callq 0x2308
leaq -0xb0(%rbp), %rdi
callq 0x2308
leaq -0x50(%rbp), %rdi
callq 0x2308
leaq -0x2d8(%rbp), %rdi
callq 0x20b0
movl %r14d, %eax
addq $0x2b8, %rsp            # imm = 0x2B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq -0x2d8(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0x21e0
movq -0x2d8(%rbp), %rax
movq -0x18(%rax), %rax
testb $0x5, -0x2b8(%rbp,%rax)
je 0x392f
leaq 0x4d02(%rip), %rsi      # 0x8626
leaq -0x70(%rbp), %rdi
callq 0x22c0
jmp 0x3958
leaq -0x2d8(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x21e0
movq -0x2d8(%rbp), %rax
movq -0x18(%rax), %rax
testb $0x5, -0x2b8(%rbp,%rax)
je 0x3c4c
leaq 0x4cc7(%rip), %rsi      # 0x8626
leaq -0x90(%rbp), %rdi
callq 0x22c0
leaq -0x2d8(%rbp), %rdi
leaq -0x118(%rbp), %rsi
callq 0x21e0
leaq -0x2d8(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x21e0
leaq -0xf8(%rbp), %rdi
pushq $0xa
popq %rdx
xorl %esi, %esi
callq 0x56ff
movl %eax, 0x4c(%rbx)
leaq -0x118(%rbp), %rdi
pushq $0xa
popq %rdx
xorl %esi, %esi
callq 0x56ff
movl %eax, 0x48(%rbx)
leaq 0x4d18(%rip), %rsi      # 0x86d8
leaq -0xb0(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x39eb
leaq 0x4d03(%rip), %rsi      # 0x86da
leaq -0xb0(%rbp), %rdi
callq 0x5720
testb %al, %al
jne 0x388f
leaq 0x4c34(%rip), %rsi      # 0x8626
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4dbe(%rip), %rsi      # 0x87c8
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4cba(%rip), %rsi      # 0x86dc
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4ca5(%rip), %rsi      # 0x86df
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4c91(%rip), %rsi      # 0x86e3
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4c7c(%rip), %rsi      # 0x86e6
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4c67(%rip), %rsi      # 0x86e9
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4c53(%rip), %rsi      # 0x86ed
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4c3f(%rip), %rsi      # 0x86f1
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4c13(%rip), %rsi      # 0x86dd
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4c06(%rip), %rsi      # 0x86e4
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4bee(%rip), %rsi      # 0x86e0
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4be1(%rip), %rsi      # 0x86e7
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4bd0(%rip), %rsi      # 0x86ea
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4bc0(%rip), %rsi      # 0x86ee
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3b53
leaq 0x4bb0(%rip), %rsi      # 0x86f2
leaq -0x70(%rbp), %rdi
callq 0x5720
testb %al, %al
jne 0x388f
leaq 0x4acc(%rip), %rsi      # 0x8626
leaq -0x90(%rbp), %rdi
callq 0x5720
testb %al, %al
je 0x3bdb
cmpq $0x2, -0x88(%rbp)
jne 0x388f
movq -0x90(%rbp), %rax
movb (%rax), %al
addb $-0x61, %al
cmpb $0x7, %al
ja 0x388f
leaq 0x4b46(%rip), %rsi      # 0x86d8
leaq -0xb0(%rbp), %rdi
callq 0x572d
testb %al, %al
je 0x3baf
movq -0x90(%rbp), %rax
cmpb $0x36, 0x1(%rax)
je 0x3bdb
leaq 0x4b24(%rip), %rsi      # 0x86da
leaq -0xb0(%rbp), %rdi
callq 0x572d
testb %al, %al
je 0x388f
movq -0x90(%rbp), %rax
cmpb $0x33, 0x1(%rax)
jne 0x388f
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x2f, (%rdx)
callq 0x59c7
cmpq $0x7, %rax
jne 0x388f
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
xorl %eax, %eax
movabsq $0x1d2010001d201, %rcx  # imm = 0x1D2010001D201
xorl %r14d, %r14d
cmpq %rax, %rsi
je 0x3c64
movb (%rdi,%rax), %dl
cmpb $0x2f, %dl
je 0x3c47
cmpb $0x31, %dl
jl 0x388f
cmpb $0x39, %dl
jb 0x3c47
movzbl %dl, %edx
addl $-0x42, %edx
cmpl $0x30, %edx
ja 0x3892
btq %rdx, %rcx
jae 0x3892
incq %rax
jmp 0x3c13
leaq -0x2d8(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x21e0
jmp 0x396b
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x4b, (%rdx)
callq 0x59c7
cmpq $0x1, %rax
jne 0x388f
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x6b, (%rdx)
callq 0x59c7
cmpq $0x1, %rax
jne 0x388f
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x50, (%rdx)
callq 0x59c7
movq %rax, -0xd8(%rbp)
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x70, (%rdx)
callq 0x59c7
movq %rax, -0xd0(%rbp)
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x4e, (%rdx)
callq 0x59c7
movq %rax, -0xc8(%rbp)
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x6e, (%rdx)
callq 0x59c7
movq %rax, -0xc0(%rbp)
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x42, (%rdx)
callq 0x59c7
movq %rax, %r15
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x62, (%rdx)
callq 0x59c7
movq %rax, %r14
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x52, (%rdx)
callq 0x59c7
movq %rax, -0xb8(%rbp)
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x72, (%rdx)
callq 0x59c7
movq %rax, %r13
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x51, (%rdx)
callq 0x59c7
movq %rax, %r12
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq %rdi, %rsi
leaq -0x29(%rbp), %rdx
movb $0x71, (%rdx)
callq 0x59c7
movq -0xd8(%rbp), %rdi
cmpq $0x9, %rdi
setae %cl
movq -0xd0(%rbp), %r8
cmpq $0x9, %r8
setae %dl
orb %cl, %dl
movq -0xc8(%rbp), %r9
cmpq $0xb, %r9
setae %cl
movq -0xc0(%rbp), %r10
cmpq $0xb, %r10
setae %sil
orb %cl, %sil
orb %dl, %sil
cmpq $0xb, %r15
setae %cl
cmpq $0xb, %r14
setae %dl
orb %cl, %dl
movq -0xb8(%rbp), %r11
cmpq $0xb, %r11
setae %cl
orb %dl, %cl
orb %sil, %cl
cmpq $0xb, %r13
setae %dl
cmpq $0xa, %r12
setae %sil
orb %dl, %sil
cmpq $0xa, %rax
setae %dl
orb %sil, %dl
orb %cl, %dl
testb $0x1, %dl
jne 0x388f
addq %rdi, %r9
addq %r11, %r15
addq %r9, %r15
addq %r12, %r15
cmpq $0xf, %r15
ja 0x388f
addq %r8, %r10
addq %r13, %r14
addq %r10, %r14
addq %rax, %r14
cmpq $0xf, %r14
ja 0x388f
leaq 0x4867(%rip), %rsi      # 0x86d8
leaq -0xb0(%rbp), %rdi
callq 0x572d
movb %al, 0x40(%rbx)
movq -0x70(%rbp), %rax
movq -0x68(%rbp), %rcx
xorl %edx, %edx
cmpq %rdx, %rcx
je 0x3ec2
movzbl (%rax,%rdx), %esi
cmpl $0x71, %esi
je 0x3eb9
cmpl $0x51, %esi
je 0x3ead
cmpl $0x6b, %esi
je 0x3eb3
cmpl $0x4b, %esi
jne 0x3ebd
movb $0x1, 0x41(%rbx)
jmp 0x3ebd
movb $0x1, 0x42(%rbx)
jmp 0x3ebd
movb $0x1, 0x43(%rbx)
jmp 0x3ebd
movb $0x1, 0x44(%rbx)
incq %rdx
jmp 0x3e8a
leaq 0x475d(%rip), %rsi      # 0x8626
leaq -0x90(%rbp), %rdi
callq 0x5720
movb $0x1, %r14b
testb %al, %al
je 0x3892
movb 0x40(%rbx), %al
cmpb $0x1, %al
jne 0x3f23
leaq -0x158(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x2200
leaq -0x158(%rbp), %rdi
callq 0x757a
leaq 0x58(%rbx), %rdi
pushq $0x1
popq %rdx
movl %eax, %esi
callq 0x3062
leaq -0x158(%rbp), %rdi
callq 0x2308
movb 0x40(%rbx), %al
testb $0x1, %al
jne 0x3892
leaq -0x138(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x2200
leaq -0x138(%rbp), %rdi
callq 0x757a
addq $0x60, %rbx
pushq $0x1
popq %rdx
movq %rbx, %rdi
movl %eax, %esi
callq 0x3062
leaq -0x138(%rbp), %rdi
callq 0x2308
jmp 0x3892
movq %rax, %rbx
leaq -0x138(%rbp), %rdi
jmp 0x3f82
movq %rax, %rbx
leaq -0x158(%rbp), %rdi
callq 0x2308
jmp 0x3fa8
jmp 0x3fa5
jmp 0x3fa5
jmp 0x3fa5
jmp 0x3fa5
jmp 0x3fa5
jmp 0x3fa5
jmp 0x3fa5
jmp 0x3fa5
jmp 0x3fa5
jmp 0x3fa5
jmp 0x3fa5
jmp 0x3fa5
jmp 0x3fa5
jmp 0x3fa5
movq %rax, %rbx
leaq -0xf8(%rbp), %rdi
callq 0x2308
leaq -0x118(%rbp), %rdi
callq 0x2308
leaq -0x90(%rbp), %rdi
callq 0x2308
leaq -0x70(%rbp), %rdi
callq 0x2308
leaq -0xb0(%rbp), %rdi
callq 0x2308
leaq -0x50(%rbp), %rdi
callq 0x2308
leaq -0x2d8(%rbp), %rdi
callq 0x20b0
movq %rbx, %rdi
callq 0x2290