// File: jswaff[P]prophet3/src/search.cpp
// Function: search_helper(position*, move_line*, int, int, int, int, bool, bool, bool, search_stats*, unsigned long long*, undo*)
int32 search_helper(position *pos,move_line *parent_pv,
        int32 alpha,int32 beta,int32 depth,int32 ply,
        bool pv_node,bool incheck,bool null_ok,
        search_stats *stats,move *startp,undo *undo_stack) {

    assert(pos);
    assert(parent_pv);
    assert(ply > 0);
    assert(alpha < beta);
    assert(stats);

    stats->nodes++; // should include leaf nodes
    int32 orig_alpha = alpha;
    parent_pv->n=0;

    // leaf node?
    if (depth < 1 || ply >= MAX_PLY) {
        assert(!incheck);
        return qsearch(pos,alpha,beta,ply,0,incheck,stats,startp,undo_stack);
    }

    // time check
    if (!analysis_mode && nodes_last_time_check >= 50000) {
        if (milli_timer() >= stop_time) {
            abort_search = true;
            printd("# Aborting search depth=%d, ply=%d on time...\n",depth,ply);
            return 0;
        }
        nodes_last_time_check = 0;
    } else {
        nodes_last_time_check++;
    }

    // draw check.  Note: not doing insufficient material (too expensive?)
    if (is_draw_by_rep(pos,undo_stack) || is_draw_by_50(pos)) {
        return DRAWSCORE;
    }

    // check hash table for score and/or move
    uint64 hash_val = get_hash_entry(&htbl,pos->hash_key);
    if (hash_val != 0 && get_hash_entry_depth(hash_val) >= depth) {
        hash_entry_t hash_entry_type = get_hash_entry_type(hash_val);
        if (hash_entry_type==LOWER_BOUND) {
            if (get_hash_entry_score(hash_val) >= beta) {
                stats->fail_highs++;
                return beta;
            }
        } else if (hash_entry_type==UPPER_BOUND) {
            if (get_hash_entry_score(hash_val) <= alpha) {
                stats->fail_lows++;
                return alpha;
            }
        } else if (hash_entry_type==EXACT_SCORE) {
            stats->hash_exact_scores++;
            return get_hash_entry_score(hash_val);
        }
    }

    // Null Move
    // The idea here is that if my position is so good that, if by giving the opponent
    // an extra turn they can't raise their score to alpha, then when I actually do make
    // a move I will almost surely fail high.
    if (!pv_node && !incheck && null_ok && depth >= 3 && beta < INF && !is_zugzwang(pos)) {
        square_t ep_sq = apply_null_move(pos);
        int nullDepth = depth - 4; // R=3
        if (nullDepth < 1) { nullDepth = 1; } // don't drop into q-search
        int32 null_score = -search_helper(pos,parent_pv,-beta,-beta+1,nullDepth,ply,
                false,false,false,stats,startp,undo_stack);
        undo_null_move(pos,ep_sq);
        if (abort_search) {
            return 0;
        }
        if (null_score >= beta) {
            return beta;
        }
    }

    // get ready to search
    move_line pv; pv.n=0;
    uint32 moves_searched=0,moves_pruned=0;
    move best_mv = 0;
    move_order_dto mo_dto = build_move_order_dto(startp,
            (pv_node && stats->last_pv.n > ply ? stats->last_pv.mv[ply] : 0),
            get_hash_entry_move(hash_val),
            killer1[ply],killer2[ply],false);

    move *mp;
    while (next(pos,&mp,&mo_dto)) {
        assert(good_move(pos,*mp));
        apply_move(pos,*mp,undo_stack);
        if (in_check(pos,opposite_player(pos->player))) {
            undo_last_move(pos,undo_stack);
            continue;
        }

        if (pv_node && moves_searched==0) {
            stats->first_line_searched.mv[ply] = *mp;
            stats->first_line_searched.n = ply+1;
        }
        bool gives_check = in_check(pos,pos->player);
        int32 ext = extend(pos,*mp,gives_check);
        assert(ext >= 0 && ext <= 1);

        int32 score;

        // TODO: refactor so that pruning decision is here.  (So it will need to consider moves_searched.)

        // TODO: after that call a 'reduce()' function that returns an integer
        // Initially that would include the LMR tests.
        // Later add in the razoring tests: https://chessprogramming.wikispaces.com/Razoring

        // call to search should be depth-1+ext-red
        // Try PVS again!


        if (moves_searched==0) {
            score = -search_helper(pos,&pv,-beta,-alpha,depth-1+ext,ply+1,
                pv_node,gives_check,!pv_node,stats,mo_dto.endp,undo_stack);
        } else {

            // if this position is looking unpromising, just skip it
            if (prune(pos,*mp,incheck,gives_check,ext,alpha,beta,depth)) {
                undo_last_move(pos,undo_stack);
                stats->prunes++;
                moves_pruned++;
                continue;
            }

            // if we've searched enough moves and haven't gotten a fail high yet, this is likely
            // a fail-low node.  reduce the remaining moves.  if the score comes back above alpha,
            // then our assumption was wrong and we need to research at full depth.
            if (moves_searched >= 4 && depth >= 3
                    && !pv_node && !incheck && !gives_check && ext==0
                    && !is_capture(*mp) && !get_promopiece(*mp)
                    && *mp != mo_dto.killer1 && *mp != mo_dto.killer2)
            {
                score = -search_helper(pos,&pv,-(alpha+1),-alpha,depth-2,ply+1,
                    false,false,true,stats,mo_dto.endp,undo_stack);
            } else {
                score = alpha + 1; // ensure a full depth search
            }

            if (score > alpha) {
                // try a PVS search.  since this is not the PV node, our expectation is that it will not improve
                // alpha.  If it does, then we need to research with a full window to establish the real score.
                //score = -search_helper(pos,&pv,-(alpha+1),-alpha,depth-1+ext,ply+1,
                //  false,gives_check,(ext==0),stats,endp,undo_stack);

                //if (score > alpha && score < beta) {
                    score = -search_helper(pos,&pv,-beta,-alpha,depth-1+ext,ply+1,
                            false,gives_check,(ext==0),stats,mo_dto.endp,undo_stack);
                //}
            }
        }
        moves_searched++;

        // restore the position
        undo_last_move(pos,undo_stack);

        if (abort_search) {
            return 0;
        }

        if (score > alpha) {
            if (score >= beta) {
                store_hash_entry(&htbl,pos->hash_key,build_hash_val(LOWER_BOUND,depth,score,*mp));
                if (!is_capture(*mp) && !get_promopiece(*mp)) {
                    assert(get_move_score(mp)==0);
                    killer2[ply] = killer1[ply];
                    killer1[ply] = *mp;
                }
                return beta;
            }
            alpha = score;
            best_mv = *mp;
            update_parent_pv(parent_pv,&pv,*mp);
        }
    }

    assert(moves_searched+moves_pruned==num_moves(pos,true,true));
    assert(alpha >= orig_alpha);

    alpha = adjust_final_score_for_mates(pos,alpha,moves_searched,ply);

    hash_entry_t het = best_mv==0 ? UPPER_BOUND : EXACT_SCORE;
    store_hash_entry(&htbl,pos->hash_key,build_hash_val(het,depth,alpha,best_mv));


    return alpha;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x458, %rsp            # imm = 0x458
movl %ecx, -0x3f8(%rbp)
movl %edx, -0x3f4(%rbp)
movq %rsi, %r10
movl -0x3f8(%rbp), %esi
movq %rdi, %r11
movl -0x3f4(%rbp), %edi
movq 0x38(%rbp), %rax
movq 0x30(%rbp), %rax
movq 0x28(%rbp), %rax
movb 0x20(%rbp), %al
movb 0x18(%rbp), %cl
movb 0x10(%rbp), %dl
movq %r11, -0x28(%rbp)
movq %r10, -0x30(%rbp)
movl %edi, -0x34(%rbp)
movl %esi, -0x38(%rbp)
movl %r8d, -0x3c(%rbp)
movl %r9d, -0x40(%rbp)
andb $0x1, %dl
movb %dl, -0x41(%rbp)
andb $0x1, %cl
movb %cl, -0x42(%rbp)
andb $0x1, %al
movb %al, -0x43(%rbp)
cmpq $0x0, -0x28(%rbp)
je 0x108a3
jmp 0x108c2
leaq 0x24c9f(%rip), %rdi     # 0x35549
leaq 0x275e8(%rip), %rsi     # 0x37e99
movl $0x8a, %edx
leaq 0x276eb(%rip), %rcx     # 0x37fa8
callq 0x20c0
cmpq $0x0, -0x30(%rbp)
je 0x108cb
jmp 0x108ea
leaq 0x2769c(%rip), %rdi     # 0x37f6e
leaq 0x275c0(%rip), %rsi     # 0x37e99
movl $0x8b, %edx
leaq 0x276c3(%rip), %rcx     # 0x37fa8
callq 0x20c0
cmpl $0x0, -0x40(%rbp)
jle 0x108f2
jmp 0x10911
leaq 0x2772a(%rip), %rdi     # 0x38023
leaq 0x27599(%rip), %rsi     # 0x37e99
movl $0x8c, %edx
leaq 0x2769c(%rip), %rcx     # 0x37fa8
callq 0x20c0
movl -0x34(%rbp), %eax
cmpl -0x38(%rbp), %eax
jge 0x1091b
jmp 0x1093a
leaq 0x27709(%rip), %rdi     # 0x3802b
leaq 0x27570(%rip), %rsi     # 0x37e99
movl $0x8d, %edx
leaq 0x27673(%rip), %rcx     # 0x37fa8
callq 0x20c0
cmpq $0x0, 0x28(%rbp)
je 0x10943
jmp 0x10962
leaq 0x2762e(%rip), %rdi     # 0x37f78
leaq 0x27548(%rip), %rsi     # 0x37e99
movl $0x8e, %edx
leaq 0x2764b(%rip), %rcx     # 0x37fa8
callq 0x20c0
movq 0x28(%rbp), %rax
movq 0x18(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rax)
movl -0x34(%rbp), %eax
movl %eax, -0x48(%rbp)
movq -0x30(%rbp), %rax
movl $0x0, (%rax)
cmpl $0x1, -0x3c(%rbp)
jl 0x1098e
cmpl $0x64, -0x40(%rbp)
jl 0x109fd
movb -0x42(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x10999
jmp 0x1099b
jmp 0x109ba
leaq 0x27696(%rip), %rdi     # 0x38038
leaq 0x274f0(%rip), %rsi     # 0x37e99
movl $0x96, %edx
leaq 0x275f3(%rip), %rcx     # 0x37fa8
callq 0x20c0
movq -0x28(%rbp), %rdi
movl -0x34(%rbp), %esi
movl -0x38(%rbp), %edx
movl -0x40(%rbp), %ecx
movb -0x42(%rbp), %r9b
movq 0x28(%rbp), %r11
movq 0x30(%rbp), %r10
movq 0x38(%rbp), %rax
xorl %r8d, %r8d
andb $0x1, %r9b
movzbl %r9b, %r9d
movq %r11, (%rsp)
movq %r10, 0x8(%rsp)
movq %rax, 0x10(%rsp)
callq 0x114e0
movl %eax, -0x1c(%rbp)
jmp 0x113cf
testb $0x1, 0x8770fc(%rip)    # 0x887b00
jne 0x10a54
cmpq $0xc350, 0x8770e7(%rip) # imm = 0xC350
jb 0x10a54
callq 0x14080
cmpl 0x8770d2(%rip), %eax    # 0x887af0
jl 0x10a47
movb $0x1, 0x8770da(%rip)    # 0x887b01
movl -0x3c(%rbp), %esi
movl -0x40(%rbp), %edx
leaq 0x2760d(%rip), %rdi     # 0x38041
movb $0x0, %al
callq 0x8db0
movl $0x0, -0x1c(%rbp)
jmp 0x113cf
movq $0x0, 0x8770a6(%rip) # 0x887af8
jmp 0x10a66
movq 0x87709d(%rip), %rax    # 0x887af8
addq $0x1, %rax
movq %rax, 0x877092(%rip)    # 0x887af8
movq -0x28(%rbp), %rdi
movq 0x38(%rbp), %rsi
callq 0x62d0
testb $0x1, %al
jne 0x10a86
movq -0x28(%rbp), %rdi
callq 0x6490
testb $0x1, %al
jne 0x10a86
jmp 0x10a92
movl $0x0, -0x1c(%rbp)
jmp 0x113cf
movq -0x28(%rbp), %rax
movq 0x1b8(%rax), %rsi
leaq 0xf260c(%rip), %rdi     # 0x1030b0
callq 0x8980
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
je 0x10b63
movq -0x50(%rbp), %rdi
callq 0x8730
cmpl -0x3c(%rbp), %eax
jl 0x10b63
movq -0x50(%rbp), %rdi
callq 0x8710
movl %eax, -0x54(%rbp)
cmpl $0x1, -0x54(%rbp)
jne 0x10b05
movq -0x50(%rbp), %rdi
callq 0x8750
cmpl -0x38(%rbp), %eax
jl 0x10b03
movq 0x28(%rbp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
movl -0x38(%rbp), %eax
movl %eax, -0x1c(%rbp)
jmp 0x113cf
jmp 0x10b61
cmpl $0x2, -0x54(%rbp)
jne 0x10b36
movq -0x50(%rbp), %rdi
callq 0x8750
cmpl -0x34(%rbp), %eax
jg 0x10b34
movq 0x28(%rbp), %rax
movq 0x8(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x8(%rax)
movl -0x34(%rbp), %eax
movl %eax, -0x1c(%rbp)
jmp 0x113cf
jmp 0x10b5f
cmpl $0x3, -0x54(%rbp)
jne 0x10b5d
movq 0x28(%rbp), %rax
movq 0x10(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x10(%rax)
movq -0x50(%rbp), %rdi
callq 0x8750
movl %eax, -0x1c(%rbp)
jmp 0x113cf
jmp 0x10b5f
jmp 0x10b61
jmp 0x10b63
testb $0x1, -0x41(%rbp)
jne 0x10c60
testb $0x1, -0x42(%rbp)
jne 0x10c60
testb $0x1, -0x43(%rbp)
je 0x10c60
cmpl $0x3, -0x3c(%rbp)
jl 0x10c60
cmpl $0x30d40, -0x38(%rbp)   # imm = 0x30D40
jge 0x10c60
movq -0x28(%rbp), %rdi
callq 0xfff0
testb $0x1, %al
jne 0x10c60
movq -0x28(%rbp), %rdi
callq 0x3ce0
movl %eax, -0x58(%rbp)
movl -0x3c(%rbp), %eax
subl $0x4, %eax
movl %eax, -0x5c(%rbp)
cmpl $0x1, -0x5c(%rbp)
jge 0x10bcb
movl $0x1, -0x5c(%rbp)
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
xorl %edx, %edx
subl -0x38(%rbp), %edx
xorl %ecx, %ecx
subl -0x38(%rbp), %ecx
addl $0x1, %ecx
movl -0x5c(%rbp), %r8d
movl -0x40(%rbp), %r9d
movq 0x28(%rbp), %r11
movq 0x30(%rbp), %r10
movq 0x38(%rbp), %rax
xorl %ebx, %ebx
movl $0x0, (%rsp)
movl $0x0, 0x8(%rsp)
movl $0x0, 0x10(%rsp)
movq %r11, 0x18(%rsp)
movq %r10, 0x20(%rsp)
movq %rax, 0x28(%rsp)
callq 0x10830
movl %eax, %ecx
xorl %eax, %eax
subl %ecx, %eax
movl %eax, -0x60(%rbp)
movq -0x28(%rbp), %rdi
movl -0x58(%rbp), %esi
callq 0x3de0
testb $0x1, 0x876ec4(%rip)    # 0x887b01
je 0x10c4b
movl $0x0, -0x1c(%rbp)
jmp 0x113cf
movl -0x60(%rbp), %eax
cmpl -0x38(%rbp), %eax
jl 0x10c5e
movl -0x38(%rbp), %eax
movl %eax, -0x1c(%rbp)
jmp 0x113cf
jmp 0x10c60
movl $0x0, -0x388(%rbp)
movl $0x0, -0x38c(%rbp)
movl $0x0, -0x390(%rbp)
movq $0x0, -0x398(%rbp)
movq 0x30(%rbp), %rax
movq %rax, -0x400(%rbp)
testb $0x1, -0x41(%rbp)
je 0x10cbc
movq 0x28(%rbp), %rax
movl 0x28(%rax), %eax
cmpl -0x40(%rbp), %eax
jle 0x10cbc
movq 0x28(%rbp), %rax
movslq -0x40(%rbp), %rcx
movq 0x30(%rax,%rcx,8), %rax
movq %rax, -0x408(%rbp)
jmp 0x10cc7
xorl %eax, %eax
movq %rax, -0x408(%rbp)
jmp 0x10cc7
movq -0x408(%rbp), %rax
movq %rax, -0x410(%rbp)
movq -0x50(%rbp), %rdi
callq 0x87d0
movq -0x400(%rbp), %rsi
movq -0x410(%rbp), %rdx
movq %rax, %rcx
movslq -0x40(%rbp), %rdi
leaq 0xf2416(%rip), %rax     # 0x103110
movq (%rax,%rdi,8), %r8
movslq -0x40(%rbp), %rdi
leaq 0xf2727(%rip), %rax     # 0x103430
movq (%rax,%rdi,8), %r9
leaq -0x3d8(%rbp), %rdi
xorl %eax, %eax
movl $0x0, (%rsp)
callq 0x10270
movq -0x28(%rbp), %rdi
leaq -0x3e0(%rbp), %rsi
leaq -0x3d8(%rbp), %rdx
callq 0xc670
testb $0x1, %al
jne 0x10d42
jmp 0x112db
movq -0x28(%rbp), %rdi
movq -0x3e0(%rbp), %rax
movq (%rax), %rsi
callq 0xcef0
testb $0x1, %al
jne 0x10d5b
jmp 0x10d5d
jmp 0x10d7c
leaq 0x27231(%rip), %rdi     # 0x37f95
leaq 0x2712e(%rip), %rsi     # 0x37e99
movl $0xdd, %edx
leaq 0x27231(%rip), %rcx     # 0x37fa8
callq 0x20c0
movq -0x28(%rbp), %rdi
movq -0x3e0(%rbp), %rax
movq (%rax), %rsi
movq 0x38(%rbp), %rdx
callq 0x3620
movq -0x28(%rbp), %rax
movq %rax, -0x418(%rbp)
movq -0x28(%rbp), %rax
movl 0x138(%rax), %edi
callq 0x14130
movq -0x418(%rbp), %rdi
movl %eax, %esi
callq 0xfc10
testb $0x1, %al
jne 0x10dc1
jmp 0x10dd3
movq -0x28(%rbp), %rdi
movq 0x38(%rbp), %rsi
callq 0x39a0
jmp 0x10d22
testb $0x1, -0x41(%rbp)
je 0x10e0c
cmpl $0x0, -0x38c(%rbp)
jne 0x10e0c
movq -0x3e0(%rbp), %rax
movq (%rax), %rdx
movq 0x28(%rbp), %rax
movslq -0x40(%rbp), %rcx
movq %rdx, 0x358(%rax,%rcx,8)
movl -0x40(%rbp), %ecx
addl $0x1, %ecx
movq 0x28(%rbp), %rax
movl %ecx, 0x350(%rax)
movq -0x28(%rbp), %rdi
movq -0x28(%rbp), %rax
movl 0x138(%rax), %esi
callq 0xfc10
andb $0x1, %al
movb %al, -0x3e1(%rbp)
movq -0x28(%rbp), %rdi
movq -0x3e0(%rbp), %rax
movq (%rax), %rsi
movb -0x3e1(%rbp), %al
andb $0x1, %al
movzbl %al, %edx
callq 0x8150
movl %eax, -0x3e8(%rbp)
xorl %eax, %eax
cmpl $0x0, -0x3e8(%rbp)
movb %al, -0x419(%rbp)
jl 0x10e6c
cmpl $0x1, -0x3e8(%rbp)
setle %al
movb %al, -0x419(%rbp)
movb -0x419(%rbp), %al
testb $0x1, %al
jne 0x10e78
jmp 0x10e7a
jmp 0x10e99
leaq 0x271ef(%rip), %rdi     # 0x38070
leaq 0x27011(%rip), %rsi     # 0x37e99
movl $0xea, %edx
leaq 0x27114(%rip), %rcx     # 0x37fa8
callq 0x20c0
cmpl $0x0, -0x38c(%rbp)
jne 0x10f3a
movq -0x28(%rbp), %rdi
xorl %edx, %edx
subl -0x38(%rbp), %edx
xorl %ecx, %ecx
subl -0x34(%rbp), %ecx
movl -0x3c(%rbp), %r8d
subl $0x1, %r8d
addl -0x3e8(%rbp), %r8d
movl -0x40(%rbp), %r9d
addl $0x1, %r9d
movb -0x41(%rbp), %sil
movb -0x3e1(%rbp), %r10b
movb -0x41(%rbp), %r11b
xorb $-0x1, %r11b
movq 0x28(%rbp), %rbx
movq -0x3a8(%rbp), %r14
movq 0x38(%rbp), %r15
movq %rsp, %rax
movq %r15, 0x28(%rax)
movq %r14, 0x20(%rax)
movq %rbx, 0x18(%rax)
movzbl %r11b, %r11d
andl $0x1, %r11d
movl %r11d, 0x10(%rax)
movzbl %r10b, %r10d
andl $0x1, %r10d
movl %r10d, 0x8(%rax)
movzbl %sil, %esi
andl $0x1, %esi
movl %esi, (%rax)
leaq -0x388(%rbp), %rsi
callq 0x10830
movl %eax, %ecx
xorl %eax, %eax
subl %ecx, %eax
movl %eax, -0x3ec(%rbp)
jmp 0x11173
movq -0x28(%rbp), %rdi
movq -0x3e0(%rbp), %rax
movq (%rax), %rsi
movb -0x42(%rbp), %dl
movb -0x3e1(%rbp), %cl
movl -0x3e8(%rbp), %r8d
movl -0x34(%rbp), %r9d
movl -0x38(%rbp), %r10d
movl -0x3c(%rbp), %eax
andb $0x1, %dl
andb $0x1, %cl
movzbl %dl, %edx
movzbl %cl, %ecx
movl %r10d, (%rsp)
movl %eax, 0x8(%rsp)
callq 0x10070
testb $0x1, %al
jne 0x10f82
jmp 0x10fb9
movq -0x28(%rbp), %rdi
movq 0x38(%rbp), %rsi
callq 0x39a0
movq 0x28(%rbp), %rax
movq 0x678(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x678(%rax)
movl -0x390(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x390(%rbp)
jmp 0x10d22
cmpl $0x4, -0x38c(%rbp)
jb 0x110cb
cmpl $0x3, -0x3c(%rbp)
jl 0x110cb
testb $0x1, -0x41(%rbp)
jne 0x110cb
testb $0x1, -0x42(%rbp)
jne 0x110cb
testb $0x1, -0x3e1(%rbp)
jne 0x110cb
cmpl $0x0, -0x3e8(%rbp)
jne 0x110cb
movq -0x3e0(%rbp), %rax
movq (%rax), %rdi
callq 0xab20
testb $0x1, %al
jne 0x110cb
movq -0x3e0(%rbp), %rax
movq (%rax), %rdi
callq 0xaae0
cmpl $0x0, %eax
jne 0x110cb
movq -0x3e0(%rbp), %rax
movq (%rax), %rax
cmpq -0x3c0(%rbp), %rax
je 0x110cb
movq -0x3e0(%rbp), %rax
movq (%rax), %rax
cmpq -0x3b8(%rbp), %rax
je 0x110cb
movq -0x28(%rbp), %rdi
movl -0x34(%rbp), %eax
addl $0x1, %eax
xorl %edx, %edx
subl %eax, %edx
xorl %ecx, %ecx
subl -0x34(%rbp), %ecx
movl -0x3c(%rbp), %r8d
subl $0x2, %r8d
movl -0x40(%rbp), %r9d
addl $0x1, %r9d
movq 0x28(%rbp), %r11
movq -0x3a8(%rbp), %r10
movq 0x38(%rbp), %rax
leaq -0x388(%rbp), %rsi
xorl %ebx, %ebx
movl $0x0, (%rsp)
movl $0x0, 0x8(%rsp)
movl $0x1, 0x10(%rsp)
movq %r11, 0x18(%rsp)
movq %r10, 0x20(%rsp)
movq %rax, 0x28(%rsp)
callq 0x10830
movl %eax, %ecx
xorl %eax, %eax
subl %ecx, %eax
movl %eax, -0x3ec(%rbp)
jmp 0x110d7
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3ec(%rbp)
movl -0x3ec(%rbp), %eax
cmpl -0x34(%rbp), %eax
jle 0x11171
movq -0x28(%rbp), %rdi
xorl %edx, %edx
subl -0x38(%rbp), %edx
xorl %ecx, %ecx
subl -0x34(%rbp), %ecx
movl -0x3c(%rbp), %r8d
subl $0x1, %r8d
addl -0x3e8(%rbp), %r8d
movl -0x40(%rbp), %r9d
addl $0x1, %r9d
movb -0x3e1(%rbp), %sil
cmpl $0x0, -0x3e8(%rbp)
sete %r10b
movq 0x28(%rbp), %r11
movq -0x3a8(%rbp), %rbx
movq 0x38(%rbp), %r14
xorl %eax, %eax
movq %rsp, %rax
movq %r14, 0x28(%rax)
movq %rbx, 0x20(%rax)
movq %r11, 0x18(%rax)
movzbl %r10b, %r10d
andl $0x1, %r10d
movl %r10d, 0x10(%rax)
movzbl %sil, %esi
andl $0x1, %esi
movl %esi, 0x8(%rax)
movl $0x0, (%rax)
leaq -0x388(%rbp), %rsi
callq 0x10830
movl %eax, %ecx
xorl %eax, %eax
subl %ecx, %eax
movl %eax, -0x3ec(%rbp)
jmp 0x11173
movl -0x38c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38c(%rbp)
movq -0x28(%rbp), %rdi
movq 0x38(%rbp), %rsi
callq 0x39a0
testb $0x1, 0x87696b(%rip)    # 0x887b01
je 0x111a4
movl $0x0, -0x1c(%rbp)
jmp 0x113cf
movl -0x3ec(%rbp), %eax
cmpl -0x34(%rbp), %eax
jle 0x112d6
movl -0x3ec(%rbp), %eax
cmpl -0x38(%rbp), %eax
jl 0x112a2
movq -0x28(%rbp), %rax
movq 0x1b8(%rax), %rax
movq %rax, -0x428(%rbp)
movl -0x3c(%rbp), %esi
movl -0x3ec(%rbp), %edx
movq -0x3e0(%rbp), %rax
movq (%rax), %rcx
movl $0x1, %edi
callq 0x8470
movq -0x428(%rbp), %rsi
movq %rax, %rdx
leaq 0xf1eae(%rip), %rdi     # 0x1030b0
callq 0x8a50
movq -0x3e0(%rbp), %rax
movq (%rax), %rdi
callq 0xab20
testb $0x1, %al
jne 0x11297
movq -0x3e0(%rbp), %rax
movq (%rax), %rdi
callq 0xaae0
cmpl $0x0, %eax
jne 0x11297
movq -0x3e0(%rbp), %rdi
callq 0xab90
cmpl $0x0, %eax
jne 0x11241
jmp 0x11260
leaq 0x26e3d(%rip), %rdi     # 0x38085
leaq 0x26c4a(%rip), %rsi     # 0x37e99
movl $0x12c, %edx            # imm = 0x12C
leaq 0x26d4d(%rip), %rcx     # 0x37fa8
callq 0x20c0
movslq -0x40(%rbp), %rcx
leaq 0xf1ea5(%rip), %rax     # 0x103110
movq (%rax,%rcx,8), %rdx
movslq -0x40(%rbp), %rcx
leaq 0xf21b6(%rip), %rax     # 0x103430
movq %rdx, (%rax,%rcx,8)
movq -0x3e0(%rbp), %rax
movq (%rax), %rdx
movslq -0x40(%rbp), %rcx
leaq 0xf1e7d(%rip), %rax     # 0x103110
movq %rdx, (%rax,%rcx,8)
movl -0x38(%rbp), %eax
movl %eax, -0x1c(%rbp)
jmp 0x113cf
movl -0x3ec(%rbp), %eax
movl %eax, -0x34(%rbp)
movq -0x3e0(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x398(%rbp)
movq -0x30(%rbp), %rdi
movq -0x3e0(%rbp), %rax
movq (%rax), %rdx
leaq -0x388(%rbp), %rsi
callq 0x113e0
jmp 0x10d22
movl -0x38c(%rbp), %eax
addl -0x390(%rbp), %eax
movl %eax, -0x42c(%rbp)
movq -0x28(%rbp), %rdi
movl $0x1, %edx
movl %edx, %esi
callq 0x14c80
movl %eax, %ecx
movl -0x42c(%rbp), %eax
cmpl %ecx, %eax
jne 0x1130b
jmp 0x1132a
leaq 0x26d89(%rip), %rdi     # 0x3809b
leaq 0x26b80(%rip), %rsi     # 0x37e99
movl $0x138, %edx            # imm = 0x138
leaq 0x26c83(%rip), %rcx     # 0x37fa8
callq 0x20c0
movl -0x34(%rbp), %eax
cmpl -0x48(%rbp), %eax
jl 0x11334
jmp 0x11353
leaq 0x26d96(%rip), %rdi     # 0x380d1
leaq 0x26b57(%rip), %rsi     # 0x37e99
movl $0x139, %edx            # imm = 0x139
leaq 0x26c5a(%rip), %rcx     # 0x37fa8
callq 0x20c0
movq -0x28(%rbp), %rdi
movl -0x34(%rbp), %esi
movl -0x38c(%rbp), %edx
movl -0x40(%rbp), %ecx
callq 0x11920
movl %eax, -0x34(%rbp)
movq -0x398(%rbp), %rdx
movl $0x3, %eax
movl $0x2, %ecx
cmpq $0x0, %rdx
cmovel %ecx, %eax
movl %eax, -0x3f0(%rbp)
movq -0x28(%rbp), %rax
movq 0x1b8(%rax), %rax
movq %rax, -0x438(%rbp)
movl -0x3f0(%rbp), %edi
movl -0x3c(%rbp), %esi
movl -0x34(%rbp), %edx
movq -0x398(%rbp), %rcx
callq 0x8470
movq -0x438(%rbp), %rsi
movq %rax, %rdx
leaq 0xf1cec(%rip), %rdi     # 0x1030b0
callq 0x8a50
movl -0x34(%rbp), %eax
movl %eax, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
addq $0x458, %rsp            # imm = 0x458
popq %rbx
popq %r14
popq %r15
popq %rbp
retq