// File: codeandkey[P]neocortex/src/position.cpp
// Function: neocortex::Position::unmake_move(neocortex::Move)
void Position::unmake_move(Move move) {
	assert(ply.size() > 1);
	assert(ply.back().last_move == move);

	State last_state = ply.back();
	ply.pop_back();

	/* Flip CTM early for readability */
	color_to_move = !color_to_move;

	/* If unmaking null move, good to go */
	if (move == Move::null) {
		return;
	}

	/* Unpromote */
	if (piece::is_type(move.ptype())) {
		board.replace(move.dst(), piece::make_piece(color_to_move, piece::PAWN));
	}

	/* Move piece back to source */
	int dst_piece = board.remove(move.dst());
	board.place(move.src(), dst_piece);

	/* Unmove rook in castling */
	if (piece::type(dst_piece) == piece::KING && abs(square::file(move.src()) - square::file(move.dst())) > 1) {
		int is_ks = move.dst() > move.src();
		int castle_rank = (color_to_move == piece::WHITE) ? 0 : 7;
		int rook_file = is_ks ? 5 : 3;
		int rook_dstfile = is_ks ? 7 : 0;

		int rook_src = square::at(castle_rank, rook_file);
		int rook_dst = square::at(castle_rank, rook_dstfile);

		board.place(rook_dst, board.remove(rook_src));
	}

	/* Replace captured pieces */
	if (piece::is_valid(last_state.captured_piece)) {
		board.place(last_state.captured_square, last_state.captured_piece);
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rsi, -0x1c(%rbp)
movl %edx, -0x14(%rbp)
movq -0x1c(%rbp), %rax
movq %rax, -0xc(%rbp)
movl -0x14(%rbp), %eax
movl %eax, -0x4(%rbp)
movq %rdi, -0x28(%rbp)
movq -0x28(%rbp), %rdi
movq %rdi, -0x88(%rbp)
addq $0x158, %rdi            # imm = 0x158
callq 0x14c10
cmpq $0x1, %rax
jbe 0xdd63
jmp 0xdd82
leaq 0x19b91(%rip), %rdi     # 0x278fb
leaq 0x19a54(%rip), %rsi     # 0x277c5
movl $0x126, %edx            # imm = 0x126
leaq 0x19b8d(%rip), %rcx     # 0x2790a
callq 0x5290
movq -0x88(%rbp), %rdi
addq $0x158, %rdi            # imm = 0x158
callq 0xbce0
movq %rax, %rdi
leaq -0xc(%rbp), %rsi
callq 0xadc0
testb $0x1, %al
jne 0xdda7
jmp 0xdda9
jmp 0xddc8
leaq 0x19b86(%rip), %rdi     # 0x27936
leaq 0x19a0e(%rip), %rsi     # 0x277c5
movl $0x127, %edx            # imm = 0x127
leaq 0x19b47(%rip), %rcx     # 0x2790a
callq 0x5290
movq -0x88(%rbp), %rdi
addq $0x158, %rdi            # imm = 0x158
callq 0xbce0
movq %rax, %rsi
leaq -0x60(%rbp), %rdi
movl $0x38, %edx
callq 0x5360
movq -0x88(%rbp), %rdi
addq $0x158, %rdi            # imm = 0x158
callq 0x14e00
movq -0x88(%rbp), %rax
cmpl $0x0, 0x170(%rax)
setne %cl
xorb $-0x1, %cl
andb $0x1, %cl
movzbl %cl, %ecx
movl %ecx, 0x170(%rax)
leaq -0xc(%rbp), %rdi
leaq 0x2ee5e(%rip), %rsi     # 0x3cc88
callq 0xadc0
testb $0x1, %al
jne 0xde35
jmp 0xde3a
jmp 0xdfea
leaq -0xc(%rbp), %rdi
callq 0xbdd0
movl %eax, %edi
callq 0xb080
testb $0x1, %al
jne 0xde50
jmp 0xde89
leaq -0xc(%rbp), %rdi
callq 0x14dd0
movl %eax, %ecx
movq -0x88(%rbp), %rax
movl %ecx, -0x8c(%rbp)
movl 0x170(%rax), %edi
xorl %esi, %esi
callq 0xc370
movq -0x88(%rbp), %rdi
movl -0x8c(%rbp), %esi
movl %eax, %edx
callq 0x7f10
leaq -0xc(%rbp), %rdi
callq 0x14dd0
movq -0x88(%rbp), %rdi
movl %eax, %esi
callq 0x7da0
movl %eax, -0x64(%rbp)
leaq -0xc(%rbp), %rdi
callq 0x14df0
movq -0x88(%rbp), %rdi
movl %eax, %esi
movl -0x64(%rbp), %edx
callq 0x7b80
movl -0x64(%rbp), %edi
callq 0x8d20
cmpl $0x5, %eax
jne 0xdfca
leaq -0xc(%rbp), %rdi
callq 0x14df0
movl %eax, %edi
callq 0x6b80
movl %eax, -0x90(%rbp)
leaq -0xc(%rbp), %rdi
callq 0x14dd0
movl %eax, %edi
callq 0x6b80
movl %eax, %ecx
movl -0x90(%rbp), %eax
subl %ecx, %eax
movl %eax, %ecx
negl %ecx
cmovnsl %ecx, %eax
cmpl $0x1, %eax
jle 0xdfca
leaq -0xc(%rbp), %rdi
callq 0x14dd0
movl %eax, -0x98(%rbp)
leaq -0xc(%rbp), %rdi
callq 0x14df0
movl -0x98(%rbp), %ecx
movl %eax, %edx
movq -0x88(%rbp), %rax
cmpl %edx, %ecx
setg %cl
andb $0x1, %cl
movzbl %cl, %ecx
movl %ecx, -0x68(%rbp)
movl 0x170(%rax), %edx
movl $0x7, %eax
xorl %ecx, %ecx
cmpl $0x0, %edx
cmovel %ecx, %eax
movl %eax, -0x6c(%rbp)
movl -0x68(%rbp), %edx
movl $0x3, %eax
movl $0x5, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
movl %eax, -0x70(%rbp)
movl -0x68(%rbp), %edx
xorl %eax, %eax
movl $0x7, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
movl %eax, -0x74(%rbp)
movl -0x6c(%rbp), %edi
movl -0x70(%rbp), %esi
callq 0x6c20
movl %eax, -0x78(%rbp)
movl -0x6c(%rbp), %edi
movl -0x74(%rbp), %esi
callq 0x6c20
movq -0x88(%rbp), %rdi
movl %eax, -0x7c(%rbp)
movl -0x7c(%rbp), %eax
movl %eax, -0x94(%rbp)
movl -0x78(%rbp), %esi
callq 0x7da0
movq -0x88(%rbp), %rdi
movl -0x94(%rbp), %esi
movl %eax, %edx
callq 0x7b80
movl -0x4c(%rbp), %edi
callq 0x8cf0
testb $0x1, %al
jne 0xdfd8
jmp 0xdfea
movq -0x88(%rbp), %rdi
movl -0x48(%rbp), %esi
movl -0x4c(%rbp), %edx
callq 0x7b80
addq $0xa0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)