// File: jswaff[P]prophet3/src/magic.cpp
// Function: init_magic_numbers(bool)
void init_magic_numbers(bool is_rook) {
    for (uint32 sq=0;sq<64;sq++) {
        uint64 mask = is_rook ? bb_rook_masks[sq] : bb_bishop_masks[sq];
        uint32 num_mask_bits = get_num_bits(mask);
        uint32 num_variations = 1 << num_mask_bits;

        uint64 magic;
        uint32 magic_shift = 64 - num_mask_bits;

        bool fail;
        bool is_used[4096];
        uint64 used_by[4096];

        do {
            magic = random64() & random64() & random64(); // not many bits set

            for (uint32 i=0;i<num_variations;i++) {
                is_used[i] = false;
            }

            fail = false;
            for (uint32 i=0;i<num_variations;i++) {
                uint64 occupied = is_rook ? bb_rook_occ_var[sq][i] : bb_bishop_occ_var[sq][i];
                int index = (int)((occupied * magic) >> magic_shift);
                assert(index <= (1 << num_mask_bits) && index <= (is_rook ?4096:1024));

                // fail if this index is used by an attack set that is incorrect
                // for this occupancy variation
                uint64 attack_set = is_rook ? bb_rook_attack_set[sq][i] : bb_bishop_attack_set[sq][i];
                fail = is_used[index] && (used_by[index] != attack_set);
                if (fail) {
                    break;
                }
                is_used[index] = true;
                used_by[index] = attack_set;
            }
        } while (fail);

        if (is_rook) {
            magic_numbers_rooks[sq] = magic;
            magic_numbers_shift_rooks[sq] = magic_shift;
        } else {
            magic_numbers_bishops[sq] = magic;
            magic_numbers_shift_bishops[sq] = magic_shift;
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x9090, %rsp           # imm = 0x9090
movb %dil, %al
andb $0x1, %al
movb %al, -0x1(%rbp)
movl $0x0, -0x8(%rbp)
cmpl $0x40, -0x8(%rbp)
jae 0x9fd8
testb $0x1, -0x1(%rbp)
je 0x9cc3
movl -0x8(%rbp), %eax
movl %eax, %ecx
leaq 0xfd40a(%rip), %rax     # 0x1070c0
movq (%rax,%rcx,8), %rax
movq %rax, -0x9058(%rbp)
jmp 0x9cda
movl -0x8(%rbp), %eax
movl %eax, %ecx
leaq 0x6fd8f1(%rip), %rax    # 0x7075c0
movq (%rax,%rcx,8), %rax
movq %rax, -0x9058(%rbp)
movq -0x9058(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rdi
callq 0x47b0
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, -0x18(%rbp)
movl $0x40, %eax
subl -0x14(%rbp), %eax
movl %eax, -0x24(%rbp)
callq 0x14ff0
movq %rax, -0x9068(%rbp)
callq 0x14ff0
movq %rax, %rcx
movq -0x9068(%rbp), %rax
andq %rcx, %rax
movq %rax, -0x9060(%rbp)
callq 0x14ff0
movq %rax, %rcx
movq -0x9060(%rbp), %rax
andq %rcx, %rax
movq %rax, -0x20(%rbp)
movl $0x0, -0x9034(%rbp)
movl -0x9034(%rbp), %eax
cmpl -0x18(%rbp), %eax
jae 0x9d78
movl -0x9034(%rbp), %eax
movb $0x0, -0x1030(%rbp,%rax)
movl -0x9034(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x9034(%rbp)
jmp 0x9d4e
movb $0x0, -0x25(%rbp)
movl $0x0, -0x9038(%rbp)
movl -0x9038(%rbp), %eax
cmpl -0x18(%rbp), %eax
jae 0x9f68
testb $0x1, -0x1(%rbp)
je 0x9dc1
movl -0x8(%rbp), %eax
movl %eax, %ecx
leaq 0x2fd519(%rip), %rax    # 0x3072c0
shlq $0xf, %rcx
addq %rcx, %rax
movl -0x9038(%rbp), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, -0x9070(%rbp)
jmp 0x9de5
movl -0x8(%rbp), %eax
movl %eax, %ecx
leaq 0x77d9f3(%rip), %rax    # 0x7877c0
shlq $0xd, %rcx
addq %rcx, %rax
movl -0x9038(%rbp), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, -0x9070(%rbp)
movq -0x9070(%rbp), %rax
movq %rax, -0x9040(%rbp)
movq -0x9040(%rbp), %rax
imulq -0x20(%rbp), %rax
movl -0x24(%rbp), %ecx
shrq %cl, %rax
movl %eax, -0x9044(%rbp)
movl -0x9044(%rbp), %eax
movl %eax, -0x9078(%rbp)
movl -0x14(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl -0x9078(%rbp), %ecx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x9071(%rbp)
jg 0x9e59
movl -0x9044(%rbp), %eax
movb -0x1(%rbp), %sil
movl $0x400, %ecx            # imm = 0x400
movl $0x1000, %edx           # imm = 0x1000
testb $0x1, %sil
cmovnel %edx, %ecx
cmpl %ecx, %eax
setle %al
movb %al, -0x9071(%rbp)
movb -0x9071(%rbp), %al
testb $0x1, %al
jne 0x9e65
jmp 0x9e67
jmp 0x9e86
leaq 0x2c955(%rip), %rdi     # 0x367c3
leaq 0x2c763(%rip), %rsi     # 0x365d8
movl $0x101, %edx            # imm = 0x101
leaq 0x2c981(%rip), %rcx     # 0x36802
callq 0x20c0
testb $0x1, -0x1(%rbp)
je 0x9eb2
movl -0x8(%rbp), %eax
movl %eax, %ecx
leaq 0x4fd428(%rip), %rax    # 0x5072c0
shlq $0xf, %rcx
addq %rcx, %rax
movl -0x9038(%rbp), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, -0x9080(%rbp)
jmp 0x9ed6
movl -0x8(%rbp), %eax
movl %eax, %ecx
leaq 0x7fd902(%rip), %rax    # 0x8077c0
shlq $0xd, %rcx
addq %rcx, %rax
movl -0x9038(%rbp), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, -0x9080(%rbp)
movq -0x9080(%rbp), %rax
movq %rax, -0x9050(%rbp)
movslq -0x9044(%rbp), %rcx
xorl %eax, %eax
testb $0x1, -0x1030(%rbp,%rcx)
movb %al, -0x9081(%rbp)
je 0x9f1c
movslq -0x9044(%rbp), %rax
movq -0x9030(%rbp,%rax,8), %rax
cmpq -0x9050(%rbp), %rax
setne %al
movb %al, -0x9081(%rbp)
movb -0x9081(%rbp), %al
andb $0x1, %al
movb %al, -0x25(%rbp)
testb $0x1, -0x25(%rbp)
je 0x9f2f
jmp 0x9f68
movslq -0x9044(%rbp), %rax
movb $0x1, -0x1030(%rbp,%rax)
movq -0x9050(%rbp), %rcx
movslq -0x9044(%rbp), %rax
movq %rcx, -0x9030(%rbp,%rax,8)
movl -0x9038(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x9038(%rbp)
jmp 0x9d86
jmp 0x9f6a
testb $0x1, -0x25(%rbp)
jne 0x9d09
testb $0x1, -0x1(%rbp)
je 0x9fa2
movq -0x20(%rbp), %rdx
movl -0x8(%rbp), %eax
movl %eax, %ecx
leaq 0x6fd336(%rip), %rax    # 0x7072c0
movq %rdx, (%rax,%rcx,8)
movl -0x24(%rbp), %edx
movl -0x8(%rbp), %eax
movl %eax, %ecx
leaq 0x6fd523(%rip), %rax    # 0x7074c0
movl %edx, (%rax,%rcx,4)
jmp 0x9fc8
movq -0x20(%rbp), %rdx
movl -0x8(%rbp), %eax
movl %eax, %ecx
leaq 0x87d80e(%rip), %rax    # 0x8877c0
movq %rdx, (%rax,%rcx,8)
movl -0x24(%rbp), %edx
movl -0x8(%rbp), %eax
movl %eax, %ecx
leaq 0x87d9fb(%rip), %rax    # 0x8879c0
movl %edx, (%rax,%rcx,4)
jmp 0x9fca
movl -0x8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8(%rbp)
jmp 0x9c9a
addq $0x9090, %rsp           # imm = 0x9090
popq %rbp
retq
nopw %cs:(%rax,%rax)