// File: jswaff[P]prophet3/test/hash__test.cpp
// Function: test_hash_keys2()
void test_hash_keys2() {
    position pos;
    reset_pos(&pos);

    position pos2;
    reset_pos(&pos2);

    uint64 keys[20]; int nkeys=0;
    uint64 keys2[20]; int nkeys2=0;

    assert(build_hash_key(&pos)==build_hash_key(&pos2));

    // step through French Defense with pos1
    apply_move(&pos,to_move(PAWN,E2,E4),gundos);
    keys[nkeys++] = build_hash_key(&pos);
    apply_move(&pos,to_move(PAWN,E7,E6),gundos);
    keys[nkeys++] = build_hash_key(&pos);
    apply_move(&pos,to_move(PAWN,D2,D4),gundos);
    keys[nkeys++] = build_hash_key(&pos);
    apply_move(&pos,to_move(PAWN,D7,D5),gundos);
    keys[nkeys++] = build_hash_key(&pos);
    apply_move(&pos,to_capture(PAWN,E4,D5,PAWN),gundos);
    keys[nkeys++] = build_hash_key(&pos);
    apply_move(&pos,to_capture(PAWN,E6,D5,PAWN),gundos);
    keys[nkeys++] = build_hash_key(&pos);
    apply_move(&pos,to_move(KNIGHT,G1,F3),gundos);
    keys[nkeys++] = build_hash_key(&pos);
    apply_move(&pos,to_move(KNIGHT,G8,F6),gundos);
    keys[nkeys++] = build_hash_key(&pos);

    // step through the Petrov Defense with pos2
    apply_move(&pos2,to_move(PAWN,E2,E4),gundos);
    keys2[nkeys2++] = build_hash_key(&pos2);
    apply_move(&pos2,to_move(PAWN,E7,E5),gundos);
    keys2[nkeys2++] = build_hash_key(&pos2);
    apply_move(&pos2,to_move(KNIGHT,G1,F3),gundos);
    keys2[nkeys2++] = build_hash_key(&pos2);
    apply_move(&pos2,to_move(KNIGHT,G8,F6),gundos);
    keys2[nkeys2++] = build_hash_key(&pos2);
    apply_move(&pos2,to_capture(KNIGHT,F3,E5,PAWN),gundos);
    keys2[nkeys2++] = build_hash_key(&pos2);
    apply_move(&pos2,to_move(PAWN,D7,D6),gundos);
    keys2[nkeys2++] = build_hash_key(&pos2);
    apply_move(&pos2,to_move(KNIGHT,E5,F3),gundos);
    keys2[nkeys2++] = build_hash_key(&pos2);
    apply_move(&pos2,to_capture(KNIGHT,F6,E4,PAWN),gundos);
    keys2[nkeys2++] = build_hash_key(&pos2);
    apply_move(&pos2,to_move(PAWN,D2,D3),gundos);
    keys2[nkeys2++] = build_hash_key(&pos2);
    apply_move(&pos2,to_move(KNIGHT,E4,F6),gundos);
    keys2[nkeys2++] = build_hash_key(&pos2);
    apply_move(&pos2,to_move(PAWN,D3,D4),gundos);
    keys2[nkeys2++] = build_hash_key(&pos2);
    apply_move(&pos2,to_move(PAWN,D6,D5),gundos);
    keys2[nkeys2++] = build_hash_key(&pos2);

    // Positions would be equal at this point, except for move history and fifty counter
    assert(!equal_pos(&pos,&pos2,true));
    assert(build_hash_key(&pos)==build_hash_key(&pos2));

    // by adding a pawn move we should be equal except move history and number of moves
    apply_move(&pos,to_move(PAWN,G2,G3),gundos);
    apply_move(&pos2,to_move(PAWN,G2,G3),gundos);

    assert(!equal_pos(&pos,&pos2,true));
    assert(build_hash_key(&pos)==build_hash_key(&pos2));

    // hash codes should be equal at beginning, move 1, move 7 and end only.
    for (int i=0;i<nkeys;i++) {
        if (i==0) {
            assert(keys2[i]==keys[i]);
            assert(!contains_key(keys[i],keys2,nkeys2,1));
        } else if (i==7) {
            assert(keys2[11]==keys[i]);
            assert(!contains_key(keys[i],keys2,nkeys2-1,0));
        } else {
            assert(!contains_key(keys[i],keys2,nkeys2));
        }
    }

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x500, %rsp            # imm = 0x500
leaq -0x1c8(%rbp), %rdi
callq 0xf390
leaq -0x390(%rbp), %rdi
callq 0xf390
movl $0x0, -0x434(%rbp)
movl $0x0, -0x4e4(%rbp)
leaq -0x1c8(%rbp), %rdi
callq 0x81f0
movq %rax, -0x4f0(%rbp)
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movq -0x4f0(%rbp), %rax
cmpq %rcx, %rax
jne 0x1e9e7
jmp 0x1ea06
leaq 0x1f956(%rip), %rdi     # 0x3e344
leaq 0x1f906(%rip), %rsi     # 0x3e2fb
movl $0xa3, %edx
leaq 0x1f96f(%rip), %rcx     # 0x3e370
callq 0x20c0
movl $0x1, %edi
movl $0x34, %esi
movl $0x24, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x1c8(%rbp), %rdi
leaq 0xb5285(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x1c8(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x434(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x434(%rbp)
cltq
movq %rcx, -0x430(%rbp,%rax,8)
movl $0x1, %edi
movl $0xc, %esi
movl $0x14, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x1c8(%rbp), %rdi
leaq 0xb5231(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x1c8(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x434(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x434(%rbp)
cltq
movq %rcx, -0x430(%rbp,%rax,8)
movl $0x1, %edi
movl $0x33, %esi
movl $0x23, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x1c8(%rbp), %rdi
leaq 0xb51dd(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x1c8(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x434(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x434(%rbp)
cltq
movq %rcx, -0x430(%rbp,%rax,8)
movl $0x1, %edi
movl $0xb, %esi
movl $0x1b, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x1c8(%rbp), %rdi
leaq 0xb5189(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x1c8(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x434(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x434(%rbp)
cltq
movq %rcx, -0x430(%rbp,%rax,8)
movl $0x1, %ecx
movl $0x24, %esi
movl $0x1b, %edx
movl %ecx, %edi
callq 0xa890
movq %rax, %rsi
leaq -0x1c8(%rbp), %rdi
leaq 0xb5133(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x1c8(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x434(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x434(%rbp)
cltq
movq %rcx, -0x430(%rbp,%rax,8)
movl $0x1, %ecx
movl $0x14, %esi
movl $0x1b, %edx
movl %ecx, %edi
callq 0xa890
movq %rax, %rsi
leaq -0x1c8(%rbp), %rdi
leaq 0xb50dd(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x1c8(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x434(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x434(%rbp)
cltq
movq %rcx, -0x430(%rbp,%rax,8)
movl $0x2, %edi
movl $0x3e, %esi
movl $0x2d, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x1c8(%rbp), %rdi
leaq 0xb5089(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x1c8(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x434(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x434(%rbp)
cltq
movq %rcx, -0x430(%rbp,%rax,8)
movl $0x2, %edi
movl $0x6, %esi
movl $0x15, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x1c8(%rbp), %rdi
leaq 0xb5035(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x1c8(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x434(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x434(%rbp)
cltq
movq %rcx, -0x430(%rbp,%rax,8)
movl $0x1, %edi
movl $0x34, %esi
movl $0x24, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4fe1(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x4e4(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x4e4(%rbp)
cltq
movq %rcx, -0x4e0(%rbp,%rax,8)
movl $0x1, %edi
movl $0xc, %esi
movl $0x1c, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4f8d(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x4e4(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x4e4(%rbp)
cltq
movq %rcx, -0x4e0(%rbp,%rax,8)
movl $0x2, %edi
movl $0x3e, %esi
movl $0x2d, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4f39(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x4e4(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x4e4(%rbp)
cltq
movq %rcx, -0x4e0(%rbp,%rax,8)
movl $0x2, %edi
movl $0x6, %esi
movl $0x15, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4ee5(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x4e4(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x4e4(%rbp)
cltq
movq %rcx, -0x4e0(%rbp,%rax,8)
movl $0x2, %edi
movl $0x2d, %esi
movl $0x1c, %edx
movl $0x1, %ecx
callq 0xa890
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4e8c(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x4e4(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x4e4(%rbp)
cltq
movq %rcx, -0x4e0(%rbp,%rax,8)
movl $0x1, %edi
movl $0xb, %esi
movl $0x13, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4e38(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x4e4(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x4e4(%rbp)
cltq
movq %rcx, -0x4e0(%rbp,%rax,8)
movl $0x2, %edi
movl $0x1c, %esi
movl $0x2d, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4de4(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x4e4(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x4e4(%rbp)
cltq
movq %rcx, -0x4e0(%rbp,%rax,8)
movl $0x2, %edi
movl $0x15, %esi
movl $0x24, %edx
movl $0x1, %ecx
callq 0xa890
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4d8b(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x4e4(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x4e4(%rbp)
cltq
movq %rcx, -0x4e0(%rbp,%rax,8)
movl $0x1, %edi
movl $0x33, %esi
movl $0x2b, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4d37(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x4e4(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x4e4(%rbp)
cltq
movq %rcx, -0x4e0(%rbp,%rax,8)
movl $0x2, %edi
movl $0x24, %esi
movl $0x15, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4ce3(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x4e4(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x4e4(%rbp)
cltq
movq %rcx, -0x4e0(%rbp,%rax,8)
movl $0x1, %edi
movl $0x2b, %esi
movl $0x23, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4c8f(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x4e4(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x4e4(%rbp)
cltq
movq %rcx, -0x4e0(%rbp,%rax,8)
movl $0x1, %edi
movl $0x13, %esi
movl $0x1b, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4c3b(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movl -0x4e4(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x4e4(%rbp)
cltq
movq %rcx, -0x4e0(%rbp,%rax,8)
leaq -0x1c8(%rbp), %rdi
leaq -0x390(%rbp), %rsi
movl $0x1, %edx
callq 0xe490
xorb $-0x1, %al
testb $0x1, %al
jne 0x1f0c4
jmp 0x1f0c6
jmp 0x1f0e5
leaq 0x1f2ba(%rip), %rdi     # 0x3e387
leaq 0x1f227(%rip), %rsi     # 0x3e2fb
movl $0xd2, %edx
leaq 0x1f290(%rip), %rcx     # 0x3e370
callq 0x20c0
leaq -0x1c8(%rbp), %rdi
callq 0x81f0
movq %rax, -0x4f8(%rbp)
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movq -0x4f8(%rbp), %rax
cmpq %rcx, %rax
jne 0x1f115
jmp 0x1f134
leaq 0x1f228(%rip), %rdi     # 0x3e344
leaq 0x1f1d8(%rip), %rsi     # 0x3e2fb
movl $0xd3, %edx
leaq 0x1f241(%rip), %rcx     # 0x3e370
callq 0x20c0
movl $0x1, %edi
movl $0x36, %esi
movl $0x2e, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x1c8(%rbp), %rdi
leaq 0xb4b57(%rip), %rdx     # 0xd3cb0
callq 0x3620
movl $0x1, %edi
movl $0x36, %esi
movl $0x2e, %edx
callq 0xa830
movq %rax, %rsi
leaq -0x390(%rbp), %rdi
leaq 0xb4b2d(%rip), %rdx     # 0xd3cb0
callq 0x3620
leaq -0x1c8(%rbp), %rdi
leaq -0x390(%rbp), %rsi
movl $0x1, %edx
callq 0xe490
xorb $-0x1, %al
testb $0x1, %al
jne 0x1f1a8
jmp 0x1f1aa
jmp 0x1f1c9
leaq 0x1f1d6(%rip), %rdi     # 0x3e387
leaq 0x1f143(%rip), %rsi     # 0x3e2fb
movl $0xd9, %edx
leaq 0x1f1ac(%rip), %rcx     # 0x3e370
callq 0x20c0
leaq -0x1c8(%rbp), %rdi
callq 0x81f0
movq %rax, -0x500(%rbp)
leaq -0x390(%rbp), %rdi
callq 0x81f0
movq %rax, %rcx
movq -0x500(%rbp), %rax
cmpq %rcx, %rax
jne 0x1f1f9
jmp 0x1f218
leaq 0x1f144(%rip), %rdi     # 0x3e344
leaq 0x1f0f4(%rip), %rsi     # 0x3e2fb
movl $0xda, %edx
leaq 0x1f15d(%rip), %rcx     # 0x3e370
callq 0x20c0
movl $0x0, -0x4e8(%rbp)
movl -0x4e8(%rbp), %eax
cmpl -0x434(%rbp), %eax
jge 0x1f3d1
cmpl $0x0, -0x4e8(%rbp)
jne 0x1f2d6
movslq -0x4e8(%rbp), %rax
movq -0x4e0(%rbp,%rax,8), %rax
movslq -0x4e8(%rbp), %rcx
cmpq -0x430(%rbp,%rcx,8), %rax
jne 0x1f263
jmp 0x1f282
leaq 0x1f139(%rip), %rdi     # 0x3e3a3
leaq 0x1f08a(%rip), %rsi     # 0x3e2fb
movl $0xdf, %edx
leaq 0x1f0f3(%rip), %rcx     # 0x3e370
callq 0x20c0
movslq -0x4e8(%rbp), %rax
movq -0x430(%rbp,%rax,8), %rdi
leaq -0x4e0(%rbp), %rsi
movl -0x4e4(%rbp), %edx
movl $0x1, %ecx
callq 0x1d900
xorb $-0x1, %al
testb $0x1, %al
jne 0x1f2b0
jmp 0x1f2b2
jmp 0x1f2d1
leaq 0x1f0fc(%rip), %rdi     # 0x3e3b5
leaq 0x1f03b(%rip), %rsi     # 0x3e2fb
movl $0xe0, %edx
leaq 0x1f0a4(%rip), %rcx     # 0x3e370
callq 0x20c0
jmp 0x1f3bb
cmpl $0x7, -0x4e8(%rbp)
jne 0x1f36d
movq -0x488(%rbp), %rax
movslq -0x4e8(%rbp), %rcx
cmpq -0x430(%rbp,%rcx,8), %rax
jne 0x1f2fd
jmp 0x1f31c
leaq 0x1f0d7(%rip), %rdi     # 0x3e3db
leaq 0x1eff0(%rip), %rsi     # 0x3e2fb
movl $0xe2, %edx
leaq 0x1f059(%rip), %rcx     # 0x3e370
callq 0x20c0
movslq -0x4e8(%rbp), %rax
movq -0x430(%rbp,%rax,8), %rdi
leaq -0x4e0(%rbp), %rsi
movl -0x4e4(%rbp), %edx
subl $0x1, %edx
xorl %ecx, %ecx
callq 0x1d900
xorb $-0x1, %al
testb $0x1, %al
jne 0x1f34a
jmp 0x1f34c
jmp 0x1f36b
leaq 0x1f09b(%rip), %rdi     # 0x3e3ee
leaq 0x1efa1(%rip), %rsi     # 0x3e2fb
movl $0xe3, %edx
leaq 0x1f00a(%rip), %rcx     # 0x3e370
callq 0x20c0
jmp 0x1f3b9
movslq -0x4e8(%rbp), %rax
movq -0x430(%rbp,%rax,8), %rdi
leaq -0x4e0(%rbp), %rsi
movl -0x4e4(%rbp), %edx
callq 0x1d950
xorb $-0x1, %al
testb $0x1, %al
jne 0x1f396
jmp 0x1f398
jmp 0x1f3b7
leaq 0x1f077(%rip), %rdi     # 0x3e416
leaq 0x1ef55(%rip), %rsi     # 0x3e2fb
movl $0xe5, %edx
leaq 0x1efbe(%rip), %rcx     # 0x3e370
callq 0x20c0
jmp 0x1f3b9
jmp 0x1f3bb
jmp 0x1f3bd
movl -0x4e8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4e8(%rbp)
jmp 0x1f222
addq $0x500, %rsp            # imm = 0x500
popq %rbp
retq
nopw (%rax,%rax)