// File: ATOMIC-LICHESS[P]ATOMKRAFT/movegen.cpp
// Function: MoveStack* (anonymous namespace)::generate_castle_moves<((anonymous namespace)::CastlingSide)1>(Position const&, MoveStack*, Color)
MoveStack* generate_castle_moves(const Position& pos, MoveStack* mlist, Color us) {
	NEW assert(pos.piece_count(WHITE, KING) && pos.piece_count(BLACK, KING));
	  	
    Color them = opposite_color(us);
    NEW assert(pos.piece_count(us, KING));
    Square ksq = pos.king_square(us);

    assert(pos.piece_on(ksq) == make_piece(us, KING));

    Square rsq = (Side == KING_SIDE ? pos.initial_kr_square(us) : pos.initial_qr_square(us));
    Square s1 = relative_square(us, Side == KING_SIDE ? SQ_G1 : SQ_C1);
    Square s2 = relative_square(us, Side == KING_SIDE ? SQ_F1 : SQ_D1);
    Square s;
    bool illegal = false;
    

    // assert(pos.piece_on(rsq) == make_piece(us, ROOK)); //can fail in atomic?
    if (pos.piece_on(rsq) != make_piece(us, ROOK)) return mlist;
    
    STARTNEW
#ifndef NDEBUG
    if (pos.piece_on(rsq) != make_piece(us, ROOK)) {
    	cout << "miau" << endl;
    	print_debuginfo(pos);
    }
#endif
    ENDNEW
    	
    STARTOLD
    // It is a bit complicated to correctly handle Chess960
    for (s = Min(ksq, s1); s <= Max(ksq, s1); s++)
        if (  (s != ksq && s != rsq && pos.square_is_occupied(s))
            ||(pos.attackers_to(s) & pos.pieces_of_color(them)))
            illegal = true;
    ENDOLD
    
    STARTNEW
    // It is a bit complicated to correctly handle Chess960
    // castling is allowed even if the opponent king gives "check" on castling squares
    Bitboard att_to;

    for (s = Min(ksq, s1); s <= Max(ksq, s1); s++) {
    	att_to =  (pos.attacks_from<PAWN>(s, BLACK) & pos.pieces(PAWN, WHITE))
				| (pos.attacks_from<PAWN>(s, WHITE) & pos.pieces(PAWN, BLACK))
				| (pos.attacks_from<KNIGHT>(s)      & pos.pieces(KNIGHT))
				| (pos.attacks_from<ROOK>(s)        & pos.pieces(ROOK, QUEEN))
				| (pos.attacks_from<BISHOP>(s)      & pos.pieces(BISHOP, QUEEN));
    	
        if (  (s != ksq && s != rsq && pos.square_is_occupied(s))
            ||(att_to & pos.pieces_of_color(them))) // att_to is the only modification
            illegal = true;
    }
    ENDNEW

    for (s = Min(rsq, s2); s <= Max(rsq, s2); s++)
        if (s != ksq && s != rsq && pos.square_is_occupied(s))
            illegal = true;

    if (   Side == QUEEN_SIDE
        && square_file(rsq) == FILE_B
        && (   pos.piece_on(relative_square(us, SQ_A1)) == make_piece(them, ROOK)
            || pos.piece_on(relative_square(us, SQ_A1)) == make_piece(them, QUEEN)))
        illegal = true;

    if (!illegal)
        (*mlist++).move = make_castle_move(ksq, rsq);

    return mlist;
  }

// Assembly:
subq $0xc8, %rsp
movq %rdi, 0xb8(%rsp)
movq %rsi, 0xb0(%rsp)
movl %edx, 0xac(%rsp)
movl 0xac(%rsp), %edi
callq 0x122b0
movl %eax, 0xa8(%rsp)
movq 0xb8(%rsp), %rdi
movl 0xac(%rsp), %esi
callq 0x1b250
movl %eax, 0xa4(%rsp)
movq 0xb8(%rsp), %rdi
movl 0xac(%rsp), %esi
callq 0x33b10
movl %eax, 0xa0(%rsp)
movl 0xac(%rsp), %edi
movl $0x2, %esi
callq 0x1b380
movl %eax, 0x9c(%rsp)
movl 0xac(%rsp), %edi
movl $0x3, %esi
callq 0x1b380
movl %eax, 0x98(%rsp)
movb $0x0, 0x93(%rsp)
movq 0xb8(%rsp), %rdi
movl 0xa0(%rsp), %esi
callq 0xf530
movl %eax, 0x84(%rsp)
movl 0xac(%rsp), %edi
movl $0x4, %esi
callq 0x1bce0
movl %eax, %ecx
movl 0x84(%rsp), %eax
cmpl %ecx, %eax
je 0x2ec0d
movq 0xb0(%rsp), %rax
movq %rax, 0xc0(%rsp)
jmp 0x2f02c
movl 0xa4(%rsp), %eax
cmpl 0x9c(%rsp), %eax
jge 0x2ec2d
movl 0xa4(%rsp), %eax
movl %eax, 0x80(%rsp)
jmp 0x2ec3b
movl 0x9c(%rsp), %eax
movl %eax, 0x80(%rsp)
movl 0x80(%rsp), %eax
movl %eax, 0x94(%rsp)
movl 0x94(%rsp), %eax
movl %eax, 0x7c(%rsp)
movl 0xa4(%rsp), %eax
cmpl 0x9c(%rsp), %eax
jge 0x2ec71
movl 0x9c(%rsp), %eax
movl %eax, 0x78(%rsp)
jmp 0x2ec7c
movl 0xa4(%rsp), %eax
movl %eax, 0x78(%rsp)
movl 0x7c(%rsp), %eax
movl 0x78(%rsp), %ecx
cmpl %ecx, %eax
jg 0x2ee73
movq 0xb8(%rsp), %rdi
movl 0x94(%rsp), %esi
movl $0x1, %edx
callq 0x1b460
movq %rax, 0x30(%rsp)
movq 0xb8(%rsp), %rdi
movl $0x1, %esi
xorl %edx, %edx
callq 0x16530
movq %rax, %rcx
movq 0x30(%rsp), %rax
andq %rcx, %rax
movq %rax, 0x40(%rsp)
movq 0xb8(%rsp), %rdi
movl 0x94(%rsp), %esi
xorl %edx, %edx
callq 0x1b460
movq %rax, 0x38(%rsp)
movq 0xb8(%rsp), %rdi
movl $0x1, %edx
movl %edx, %esi
callq 0x16530
movq 0x38(%rsp), %rcx
movq %rax, %rdx
movq 0x40(%rsp), %rax
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, 0x50(%rsp)
movq 0xb8(%rsp), %rdi
movl 0x94(%rsp), %esi
callq 0x29aa0
movq %rax, 0x48(%rsp)
movq 0xb8(%rsp), %rdi
movl $0x2, %esi
callq 0x33a70
movq 0x48(%rsp), %rcx
movq %rax, %rdx
movq 0x50(%rsp), %rax
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, 0x60(%rsp)
movq 0xb8(%rsp), %rdi
movl 0x94(%rsp), %esi
callq 0x29d40
movq %rax, 0x58(%rsp)
movq 0xb8(%rsp), %rdi
movl $0x4, %esi
movl $0x5, %edx
callq 0x33a90
movq 0x58(%rsp), %rcx
movq %rax, %rdx
movq 0x60(%rsp), %rax
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, 0x70(%rsp)
movq 0xb8(%rsp), %rdi
movl 0x94(%rsp), %esi
callq 0x1b550
movq %rax, 0x68(%rsp)
movq 0xb8(%rsp), %rdi
movl $0x3, %esi
movl $0x5, %edx
callq 0x33a90
movq 0x68(%rsp), %rcx
movq %rax, %rdx
movq 0x70(%rsp), %rax
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, 0x88(%rsp)
movl 0x94(%rsp), %eax
cmpl 0xa4(%rsp), %eax
je 0x2ee23
movl 0x94(%rsp), %eax
cmpl 0xa0(%rsp), %eax
je 0x2ee23
movq 0xb8(%rsp), %rdi
movl 0x94(%rsp), %esi
callq 0x33ac0
testb $0x1, %al
jne 0x2ee55
movq 0x88(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0xb8(%rsp), %rdi
movl 0xa8(%rsp), %esi
callq 0x298c0
movq %rax, %rcx
movq 0x28(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
je 0x2ee5d
movb $0x1, 0x93(%rsp)
jmp 0x2ee5f
leaq 0x94(%rsp), %rdi
xorl %esi, %esi
callq 0xe5c0
jmp 0x2ec49
movl 0xa0(%rsp), %eax
cmpl 0x98(%rsp), %eax
jge 0x2ee90
movl 0xa0(%rsp), %eax
movl %eax, 0x24(%rsp)
jmp 0x2ee9b
movl 0x98(%rsp), %eax
movl %eax, 0x24(%rsp)
movl 0x24(%rsp), %eax
movl %eax, 0x94(%rsp)
movl 0x94(%rsp), %eax
movl %eax, 0x20(%rsp)
movl 0xa0(%rsp), %eax
cmpl 0x98(%rsp), %eax
jge 0x2eece
movl 0x98(%rsp), %eax
movl %eax, 0x1c(%rsp)
jmp 0x2eed9
movl 0xa0(%rsp), %eax
movl %eax, 0x1c(%rsp)
movl 0x20(%rsp), %eax
movl 0x1c(%rsp), %ecx
cmpl %ecx, %eax
jg 0x2ef3d
movl 0x94(%rsp), %eax
cmpl 0xa4(%rsp), %eax
je 0x2ef27
movl 0x94(%rsp), %eax
cmpl 0xa0(%rsp), %eax
je 0x2ef27
movq 0xb8(%rsp), %rdi
movl 0x94(%rsp), %esi
callq 0x33ac0
testb $0x1, %al
jne 0x2ef1f
jmp 0x2ef27
movb $0x1, 0x93(%rsp)
jmp 0x2ef29
leaq 0x94(%rsp), %rdi
xorl %esi, %esi
callq 0xe5c0
jmp 0x2eea6
movl 0xa0(%rsp), %edi
callq 0xce10
cmpl $0x1, %eax
jne 0x2efe4
movq 0xb8(%rsp), %rax
movq %rax, 0x10(%rsp)
movl 0xac(%rsp), %edi
xorl %esi, %esi
callq 0x1b380
movq 0x10(%rsp), %rdi
movl %eax, %esi
callq 0xf530
movl %eax, 0x18(%rsp)
movl 0xa8(%rsp), %edi
movl $0x4, %esi
callq 0x1bce0
movl %eax, %ecx
movl 0x18(%rsp), %eax
cmpl %ecx, %eax
je 0x2efdc
movq 0xb8(%rsp), %rax
movq %rax, (%rsp)
movl 0xac(%rsp), %edi
xorl %esi, %esi
callq 0x1b380
movq (%rsp), %rdi
movl %eax, %esi
callq 0xf530
movl %eax, 0xc(%rsp)
movl 0xa8(%rsp), %edi
movl $0x5, %esi
callq 0x1bce0
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jne 0x2efe4
movb $0x1, 0x93(%rsp)
testb $0x1, 0x93(%rsp)
jne 0x2f01c
movl 0xa4(%rsp), %edi
movl 0xa0(%rsp), %esi
callq 0x33af0
movl %eax, %ecx
movq 0xb0(%rsp), %rax
movq %rax, %rdx
addq $0x8, %rdx
movq %rdx, 0xb0(%rsp)
movl %ecx, (%rax)
movq 0xb0(%rsp), %rax
movq %rax, 0xc0(%rsp)
movq 0xc0(%rsp), %rax
addq $0xc8, %rsp
retq
nopl (%rax)