// File: ATOMIC-LICHESS[P]ATOMKRAFT/position.cpp
// Function: Position::undo_castle_move(Move)
void Position::undo_castle_move(Move m) {

  assert(move_is_ok(m));
  assert(move_is_castle(m));

  // When we have arrived here, some work has already been done by
  // Position::undo_move.  In particular, the side to move has been switched,
  // so the code below is correct.
  Color us = side_to_move();

  // Find source squares for king and rook
  Square kfrom = move_from(m);
  Square rfrom = move_to(m);  // HACK: See comment at beginning of function
  Square kto, rto;

  // Find destination squares for king and rook
  if (rfrom > kfrom) // O-O
  {
      kto = relative_square(us, SQ_G1);
      rto = relative_square(us, SQ_F1);
  } else { // O-O-O
      kto = relative_square(us, SQ_C1);
      rto = relative_square(us, SQ_D1);
  }

  assert(piece_on(kto) == make_piece(us, KING));
  assert(piece_on(rto) == make_piece(us, ROOK));

  // Remove pieces from destination squares:
  clear_bit(&(byColorBB[us]), kto);
  clear_bit(&(byTypeBB[KING]), kto);
  clear_bit(&(byTypeBB[0]), kto); // HACK: byTypeBB[0] == occupied squares
  clear_bit(&(byColorBB[us]), rto);
  clear_bit(&(byTypeBB[ROOK]), rto);
  clear_bit(&(byTypeBB[0]), rto); // HACK: byTypeBB[0] == occupied squares

  // Put pieces on source squares:
  set_bit(&(byColorBB[us]), kfrom);
  set_bit(&(byTypeBB[KING]), kfrom);
  set_bit(&(byTypeBB[0]), kfrom); // HACK: byTypeBB[0] == occupied squares
  set_bit(&(byColorBB[us]), rfrom);
  set_bit(&(byTypeBB[ROOK]), rfrom);
  set_bit(&(byTypeBB[0]), rfrom); // HACK: byTypeBB[0] == occupied squares

  // Update board
  board[rto] = board[kto] = PIECE_NONE;
  board[rfrom] = make_piece(us, ROOK);
  board[kfrom] = make_piece(us, KING);

  // Update piece lists
  pieceList[us][KING][index[kto]] = kfrom;
  pieceList[us][ROOK][index[rto]] = rfrom;
  int tmp = index[rto];  // In Chess960 could be rto == kfrom
  index[kfrom] = index[kto];
  index[rfrom] = tmp;

  // Finally point our state pointer back to the previous state
  st = st->previous;

  assert(is_ok());
}

// Assembly:
subq $0x38, %rsp
movq %rdi, 0x30(%rsp)
movl %esi, 0x2c(%rsp)
movq 0x30(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0xf5d0
movl %eax, 0x28(%rsp)
movl 0x2c(%rsp), %edi
callq 0xf680
movl %eax, 0x24(%rsp)
movl 0x2c(%rsp), %edi
callq 0xf690
movl %eax, 0x20(%rsp)
movl 0x20(%rsp), %eax
cmpl 0x24(%rsp), %eax
jle 0x3cc3a
movl 0x28(%rsp), %edi
movl $0x6, %esi
callq 0x1b380
movl %eax, 0x1c(%rsp)
movl 0x28(%rsp), %edi
movl $0x5, %esi
callq 0x1b380
movl %eax, 0x18(%rsp)
jmp 0x3cc5e
movl 0x28(%rsp), %edi
movl $0x2, %esi
callq 0x1b380
movl %eax, 0x1c(%rsp)
movl 0x28(%rsp), %edi
movl $0x3, %esi
callq 0x1b380
movl %eax, 0x18(%rsp)
movq 0x8(%rsp), %rdi
addq $0x140, %rdi            # imm = 0x140
movl 0x28(%rsp), %eax
shlq $0x3, %rax
addq %rax, %rdi
movl 0x1c(%rsp), %esi
callq 0x29eb0
movq 0x8(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
addq $0x30, %rdi
movl 0x1c(%rsp), %esi
callq 0x29eb0
movq 0x8(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
movl 0x1c(%rsp), %esi
callq 0x29eb0
movq 0x8(%rsp), %rdi
addq $0x140, %rdi            # imm = 0x140
movl 0x28(%rsp), %eax
shlq $0x3, %rax
addq %rax, %rdi
movl 0x18(%rsp), %esi
callq 0x29eb0
movq 0x8(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
addq $0x20, %rdi
movl 0x18(%rsp), %esi
callq 0x29eb0
movq 0x8(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
movl 0x18(%rsp), %esi
callq 0x29eb0
movq 0x8(%rsp), %rdi
addq $0x140, %rdi            # imm = 0x140
movl 0x28(%rsp), %eax
shlq $0x3, %rax
addq %rax, %rdi
movl 0x24(%rsp), %esi
callq 0xe7c0
movq 0x8(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
addq $0x30, %rdi
movl 0x24(%rsp), %esi
callq 0xe7c0
movq 0x8(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
movl 0x24(%rsp), %esi
callq 0xe7c0
movq 0x8(%rsp), %rdi
addq $0x140, %rdi            # imm = 0x140
movl 0x28(%rsp), %eax
shlq $0x3, %rax
addq %rax, %rdi
movl 0x20(%rsp), %esi
callq 0xe7c0
movq 0x8(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
addq $0x20, %rdi
movl 0x20(%rsp), %esi
callq 0xe7c0
movq 0x8(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
movl 0x20(%rsp), %esi
callq 0xe7c0
movq 0x8(%rsp), %rax
movslq 0x1c(%rsp), %rcx
movl $0x10, (%rax,%rcx,4)
movslq 0x18(%rsp), %rcx
movl $0x10, (%rax,%rcx,4)
movl 0x28(%rsp), %edi
movl $0x4, %esi
callq 0x1bce0
movl %eax, %edx
movq 0x8(%rsp), %rax
movslq 0x20(%rsp), %rcx
movl %edx, (%rax,%rcx,4)
movl 0x28(%rsp), %edi
movl $0x6, %esi
callq 0x1bce0
movl %eax, %edx
movq 0x8(%rsp), %rax
movslq 0x24(%rsp), %rcx
movl %edx, (%rax,%rcx,4)
movl 0x24(%rsp), %esi
movq %rax, %rcx
addq $0x190, %rcx            # imm = 0x190
movl 0x28(%rsp), %edx
shlq $0x9, %rdx
addq %rdx, %rcx
movslq 0x1c(%rsp), %rdx
movslq 0x590(%rax,%rdx,4), %rdx
movl %esi, 0x180(%rcx,%rdx,4)
movl 0x20(%rsp), %esi
movq %rax, %rcx
addq $0x190, %rcx            # imm = 0x190
movl 0x28(%rsp), %edx
shlq $0x9, %rdx
addq %rdx, %rcx
movslq 0x18(%rsp), %rdx
movslq 0x590(%rax,%rdx,4), %rdx
movl %esi, 0x100(%rcx,%rdx,4)
movslq 0x18(%rsp), %rcx
movl 0x590(%rax,%rcx,4), %ecx
movl %ecx, 0x14(%rsp)
movslq 0x1c(%rsp), %rcx
movl 0x590(%rax,%rcx,4), %edx
movslq 0x24(%rsp), %rcx
movl %edx, 0x590(%rax,%rcx,4)
movl 0x14(%rsp), %edx
movslq 0x20(%rsp), %rcx
movl %edx, 0x590(%rax,%rcx,4)
movq 0x1938(%rax), %rcx
movq 0x98(%rcx), %rcx
movq %rcx, 0x1938(%rax)
addq $0x38, %rsp
retq
nopl (%rax)