// File: cpirc[P]Monochrome/src/position.cpp
// Function: parse_fen_to_position(char const*, Position&)
void parse_fen_to_position(const char *fen_str, Position &pos) {
    std::size_t i = 0, square_idx = 0;
    char c;

    std::memset((void *)&pos.pieces, 0, sizeof(pos.pieces));
    std::memset((void *)&pos.colours, 0, sizeof(pos.colours));

    while (square_idx < ARR_LEN(fen_board)) {
        c = fen_str[i++];

        switch (c) {
            case 'p':
                put_piece(pos, (const Square)fen_board[square_idx], PAWN, THEM);
                square_idx++;
                break;
            case 'r':
                put_piece(pos, (const Square)fen_board[square_idx], ROOK, THEM);
                square_idx++;
                break;
            case 'n':
                put_piece(pos, (const Square)fen_board[square_idx], KNIGHT,
                          THEM);
                square_idx++;
                break;
            case 'b':
                put_piece(pos, (const Square)fen_board[square_idx], BISHOP,
                          THEM);
                square_idx++;
                break;
            case 'q':
                put_piece(pos, (const Square)fen_board[square_idx], QUEEN,
                          THEM);
                square_idx++;
                break;
            case 'k':
                put_piece(pos, (const Square)fen_board[square_idx], KING, THEM);
                square_idx++;
                break;
            case 'P':
                put_piece(pos, (const Square)fen_board[square_idx], PAWN, US);
                square_idx++;
                break;
            case 'R':
                put_piece(pos, (const Square)fen_board[square_idx], ROOK, US);
                square_idx++;
                break;
            case 'N':
                put_piece(pos, (const Square)fen_board[square_idx], KNIGHT, US);
                square_idx++;
                break;
            case 'B':
                put_piece(pos, (const Square)fen_board[square_idx], BISHOP, US);
                square_idx++;
                break;
            case 'Q':
                put_piece(pos, (const Square)fen_board[square_idx], QUEEN, US);
                square_idx++;
                break;
            case 'K':
                put_piece(pos, (const Square)fen_board[square_idx], KING, US);
                square_idx++;
                break;
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
                square_idx += (c - '0');
                break;
        }
    }

    c = fen_str[++i];
    bool flipped = c == 'b';

    i += 2;
    pos.castle = 0;
    do {
        c = fen_str[i++];

        switch (c) {
            case 'K':
                pos.castle |= US_OO;
                break;
            case 'Q':
                pos.castle |= US_OOO;
                break;
            case 'k':
                pos.castle |= THEM_OO;
                break;
            case 'q':
                pos.castle |= THEM_OOO;
                break;
            case '-':
                c = fen_str[i++];
                break;
        }

    } while (c != ' ');

    switch (fen_str[i]) {
        case '-':
            pos.epsq = INVALID_SQUARE;
            i += 2;
            break;
        default:
            pos.epsq =
                (Square)((fen_str[i] - 'a') + ((fen_str[i + 1] - '1') * 8));
            i += 3;
            break;
    }

    if (fen_str[i + 1] != ' ') {
        pos.halfmoves = (fen_str[i] - '0') * 10 + (fen_str[i + 1] - '0');
    } else {
        pos.halfmoves = fen_str[i] - '0';
    }

    pos.flipped = false;
    if (flipped) flip_position(pos);

    calculate_key(pos);

    pos.history.reserve(256);
    pos.history.clear();
    pos.history.push_back(pos.hash_key);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movq -0x10(%rbp), %rdi
xorl %esi, %esi
movl $0x30, %edx
callq 0x30f0
movq -0x10(%rbp), %rdi
addq $0x30, %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x30f0
cmpq $0x40, -0x20(%rbp)
jae 0x9e67
movq -0x8(%rbp), %rax
movq -0x18(%rbp), %rcx
movq %rcx, %rdx
incq %rdx
movq %rdx, -0x18(%rbp)
movb (%rax,%rcx), %al
movb %al, -0x21(%rbp)
movsbl -0x21(%rbp), %eax
addl $-0x31, %eax
movl %eax, %ecx
movq %rcx, -0x30(%rbp)
subl $0x41, %eax
ja 0x9e62
movq -0x30(%rbp), %rax
leaq 0xa078(%rip), %rcx      # 0x13c80
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
xorl %edx, %edx
movl $0x1, %ecx
leaq 0xa169(%rip), %rax      # 0x13d90
movzbl (%rax,%rsi), %esi
callq 0x6890
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x9e62
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x3, %edx
movl $0x1, %ecx
leaq 0xa136(%rip), %rax      # 0x13d90
movzbl (%rax,%rsi), %esi
callq 0x6890
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x9e62
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rdx
movl $0x1, %ecx
leaq 0xa108(%rip), %rax      # 0x13d90
movzbl (%rax,%rdx), %esi
movl %ecx, %edx
callq 0x6890
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x9e62
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x2, %edx
movl $0x1, %ecx
leaq 0xa0d3(%rip), %rax      # 0x13d90
movzbl (%rax,%rsi), %esi
callq 0x6890
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x9e62
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x4, %edx
movl $0x1, %ecx
leaq 0xa0a0(%rip), %rax      # 0x13d90
movzbl (%rax,%rsi), %esi
callq 0x6890
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x9e62
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x5, %edx
movl $0x1, %ecx
leaq 0xa06d(%rip), %rax      # 0x13d90
movzbl (%rax,%rsi), %esi
callq 0x6890
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x9e62
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rdx
xorl %ecx, %ecx
leaq 0xa042(%rip), %rax      # 0x13d90
movzbl (%rax,%rdx), %esi
movl %ecx, %edx
callq 0x6890
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x9e62
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x3, %edx
xorl %ecx, %ecx
leaq 0xa010(%rip), %rax      # 0x13d90
movzbl (%rax,%rsi), %esi
callq 0x6890
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x9e62
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x1, %edx
xorl %ecx, %ecx
leaq 0x9fe0(%rip), %rax      # 0x13d90
movzbl (%rax,%rsi), %esi
callq 0x6890
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x9e62
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x2, %edx
xorl %ecx, %ecx
leaq 0x9fb0(%rip), %rax      # 0x13d90
movzbl (%rax,%rsi), %esi
callq 0x6890
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x9e62
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x4, %edx
xorl %ecx, %ecx
leaq 0x9f83(%rip), %rax      # 0x13d90
movzbl (%rax,%rsi), %esi
callq 0x6890
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x9e62
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x5, %edx
xorl %ecx, %ecx
leaq 0x9f56(%rip), %rax      # 0x13d90
movzbl (%rax,%rsi), %esi
callq 0x6890
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x9e62
movsbl -0x21(%rbp), %eax
subl $0x30, %eax
cltq
addq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x9bc4
movq -0x8(%rbp), %rax
movq -0x18(%rbp), %rcx
movq %rcx, %rdx
addq $0x1, %rdx
movq %rdx, -0x18(%rbp)
movb 0x1(%rax,%rcx), %al
movb %al, -0x21(%rbp)
movsbl -0x21(%rbp), %eax
cmpl $0x62, %eax
sete %al
andb $0x1, %al
movb %al, -0x22(%rbp)
movq -0x18(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movb $0x0, 0x40(%rax)
movq -0x8(%rbp), %rax
movq -0x18(%rbp), %rcx
movq %rcx, %rdx
incq %rdx
movq %rdx, -0x18(%rbp)
movb (%rax,%rcx), %al
movb %al, -0x21(%rbp)
movsbl -0x21(%rbp), %eax
movl %eax, -0x34(%rbp)
subl $0x2d, %eax
je 0x9f32
jmp 0x9eca
movl -0x34(%rbp), %eax
subl $0x4b, %eax
je 0x9ef2
jmp 0x9ed4
movl -0x34(%rbp), %eax
subl $0x51, %eax
je 0x9f02
jmp 0x9ede
movl -0x34(%rbp), %eax
subl $0x6b, %eax
je 0x9f12
jmp 0x9ee8
movl -0x34(%rbp), %eax
subl $0x71, %eax
je 0x9f22
jmp 0x9f4b
movq -0x10(%rbp), %rax
movzbl 0x40(%rax), %ecx
orl $0x1, %ecx
movb %cl, 0x40(%rax)
jmp 0x9f4b
movq -0x10(%rbp), %rax
movzbl 0x40(%rax), %ecx
orl $0x2, %ecx
movb %cl, 0x40(%rax)
jmp 0x9f4b
movq -0x10(%rbp), %rax
movzbl 0x40(%rax), %ecx
orl $0x4, %ecx
movb %cl, 0x40(%rax)
jmp 0x9f4b
movq -0x10(%rbp), %rax
movzbl 0x40(%rax), %ecx
orl $0x8, %ecx
movb %cl, 0x40(%rax)
jmp 0x9f4b
movq -0x8(%rbp), %rax
movq -0x18(%rbp), %rcx
movq %rcx, %rdx
addq $0x1, %rdx
movq %rdx, -0x18(%rbp)
movb (%rax,%rcx), %al
movb %al, -0x21(%rbp)
jmp 0x9f4d
movsbl -0x21(%rbp), %eax
cmpl $0x20, %eax
jne 0x9ea4
movq -0x8(%rbp), %rax
movq -0x18(%rbp), %rcx
movb (%rax,%rcx), %al
subb $0x2d, %al
jne 0x9f81
jmp 0x9f6b
movq -0x10(%rbp), %rax
movb $0x40, 0x42(%rax)
movq -0x18(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x18(%rbp)
jmp 0x9fba
movq -0x8(%rbp), %rax
movq -0x18(%rbp), %rcx
movsbl (%rax,%rcx), %eax
subl $0x61, %eax
movq -0x8(%rbp), %rcx
movq -0x18(%rbp), %rdx
movsbl 0x1(%rcx,%rdx), %ecx
subl $0x31, %ecx
shll $0x3, %ecx
addl %ecx, %eax
movb %al, %cl
movq -0x10(%rbp), %rax
movb %cl, 0x42(%rax)
movq -0x18(%rbp), %rax
addq $0x3, %rax
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq -0x18(%rbp), %rcx
movsbl 0x1(%rax,%rcx), %eax
cmpl $0x20, %eax
je 0x9ffb
movq -0x8(%rbp), %rax
movq -0x18(%rbp), %rcx
movsbl (%rax,%rcx), %eax
subl $0x30, %eax
imull $0xa, %eax, %eax
movq -0x8(%rbp), %rcx
movq -0x18(%rbp), %rdx
movsbl 0x1(%rcx,%rdx), %ecx
subl $0x30, %ecx
addl %ecx, %eax
movb %al, %cl
movq -0x10(%rbp), %rax
movb %cl, 0x43(%rax)
jmp 0xa013
movq -0x8(%rbp), %rax
movq -0x18(%rbp), %rcx
movsbl (%rax,%rcx), %eax
subl $0x30, %eax
movb %al, %cl
movq -0x10(%rbp), %rax
movb %cl, 0x43(%rax)
movq -0x10(%rbp), %rax
movb $0x0, 0x41(%rax)
testb $0x1, -0x22(%rbp)
je 0xa02a
movq -0x10(%rbp), %rdi
callq 0x42a0
movq -0x10(%rbp), %rdi
callq 0x9a00
movq -0x10(%rbp), %rdi
addq $0x50, %rdi
movl $0x100, %esi            # imm = 0x100
callq 0xa7f0
movq -0x10(%rbp), %rdi
addq $0x50, %rdi
callq 0x6910
movq -0x10(%rbp), %rdi
addq $0x50, %rdi
movq -0x10(%rbp), %rsi
addq $0x48, %rsi
callq 0x6930
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax)