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

  assert(is_ok());
  assert(move_is_ok(m));

  sideToMove = opposite_color(sideToMove);

  if (move_is_castle(m))
  {
      undo_castle_move(m);
      return;
  }
  
  Color us = side_to_move();
  Color them = opposite_color(us);
  Square from = move_from(m);
  Square to = move_to(m);
  bool ep = move_is_ep(m);
  bool pm = move_is_promotion(m);
  
  STARTNEW
  if (st->capturedType) {
	  // Restore the attacking piece 
	  restore_piece(us, to, st->attackingType);
  }
  ENDNEW
  
  PieceType pt = type_of_piece_on(to);

  assert(square_is_empty(from));
  assert(color_of_piece_on(to) == us);
  //NEW assert(st->capturedType ? color_of_piece_on(to) == COLOR_NONE : color_of_piece_on(to) == us);
  assert(!pm || relative_rank(us, to) == RANK_8);
  assert(!ep || to == st->previous->epSquare);
  assert(!ep || relative_rank(us, to) == RANK_6);
  assert(!ep || piece_on(to) == make_piece(us, PAWN));

  if (pm) // promotion ?
  {
	  NEW assert(!st->capturedType); // a promotion with capture is not possible in atomic 
      PieceType promotion = move_promotion_piece(m);
      pt = PAWN;

      assert(promotion >= KNIGHT && promotion <= QUEEN);
      assert(piece_on(to) == make_piece(us, promotion));

      // Replace promoted piece with a pawn
      clear_bit(&(byTypeBB[promotion]), to);
      set_bit(&(byTypeBB[PAWN]), to);

      // Update piece counts
      pieceCount[us][promotion]--;
      pieceCount[us][PAWN]++;

      // Update piece list replacing promotion piece with a pawn
      Square lastPromotionSquare = pieceList[us][promotion][pieceCount[us][promotion]];
      index[lastPromotionSquare] = index[to];
      pieceList[us][promotion][index[lastPromotionSquare]] = lastPromotionSquare;
      pieceList[us][promotion][pieceCount[us][promotion]] = SQ_NONE;
      index[to] = pieceCount[us][PAWN] - 1;
      pieceList[us][PAWN][index[to]] = to;
  }
	  
  
  // Put the piece back at the source square
  Bitboard move_bb = make_move_bb(to, from);
  do_move_bb(&(byColorBB[us]), move_bb);
  do_move_bb(&(byTypeBB[pt]), move_bb);
  do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares

  board[from] = make_piece(us, pt);
  board[to] = PIECE_NONE;

  // Update piece list
  index[from] = index[to];
  pieceList[us][pt][index[from]] = from;

  if (st->capturedType)
  {
      Square capsq = to;

      if (ep)
          capsq = (us == WHITE)? (to - DELTA_N) : (to - DELTA_S);

      assert(st->capturedType != KING);
      assert(!ep || square_is_empty(capsq));

      // Restore the captured piece
      set_bit(&(byColorBB[them]), capsq);
      set_bit(&(byTypeBB[st->capturedType]), capsq);
      set_bit(&(byTypeBB[0]), capsq);

      board[capsq] = make_piece(them, st->capturedType);

      // Update piece count
      pieceCount[them][st->capturedType]++;

      // Update piece list, add a new captured piece in capsq square
      index[capsq] = pieceCount[them][st->capturedType] - 1;
      pieceList[them][st->capturedType][index[capsq]] = capsq;
      
      STARTNEW
      // the first obligatory piece was restored above, TODO: merge this
      Color color;
      Square square;
      PieceType type;
      
      for (int k = 1; k < st->expl.size; ++k) {
    	  color = color_of_piece(st->expl.piece[k]);
    	  type = type_of_piece(st->expl.piece[k]);
    	  square = st->expl.square[k];
    	  restore_piece(color, square, type);
      }
      ENDNEW
  }

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

  assert(is_ok());
}

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x60(%rsp)
movl %esi, 0x5c(%rsp)
movq 0x60(%rsp), %rax
movq %rax, 0x10(%rsp)
movl 0x1090(%rax), %edi
callq 0x122b0
movl %eax, %ecx
movq 0x10(%rsp), %rax
movl %ecx, 0x1090(%rax)
movl 0x5c(%rsp), %edi
callq 0x12970
cmpl $0x0, %eax
je 0x3c670
movq 0x10(%rsp), %rdi
movl 0x5c(%rsp), %esi
callq 0x3cbd0
jmp 0x3cbc4
movq 0x10(%rsp), %rdi
callq 0xf5d0
movl %eax, 0x58(%rsp)
movl 0x58(%rsp), %edi
callq 0x122b0
movl %eax, 0x54(%rsp)
movl 0x5c(%rsp), %edi
callq 0xf680
movl %eax, 0x50(%rsp)
movl 0x5c(%rsp), %edi
callq 0xf690
movl %eax, 0x4c(%rsp)
movl 0x5c(%rsp), %edi
callq 0x2e360
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, 0x4b(%rsp)
movl 0x5c(%rsp), %edi
callq 0xfb40
movb %al, %cl
movq 0x10(%rsp), %rax
andb $0x1, %cl
movb %cl, 0x4a(%rsp)
movq 0x1938(%rax), %rax
cmpl $0x0, 0x30(%rax)
je 0x3c6fa
movq 0x10(%rsp), %rdi
movl 0x58(%rsp), %esi
movl 0x4c(%rsp), %edx
movq 0x1938(%rdi), %rax
movl 0x34(%rax), %ecx
callq 0x3c510
movq 0x10(%rsp), %rdi
movl 0x4c(%rsp), %esi
callq 0x11f10
movl %eax, 0x44(%rsp)
testb $0x1, 0x4a(%rsp)
je 0x3c8c8
movl 0x5c(%rsp), %edi
callq 0xf830
movq 0x10(%rsp), %rdi
movl %eax, 0x40(%rsp)
movl $0x1, 0x44(%rsp)
addq $0x100, %rdi            # imm = 0x100
movl 0x40(%rsp), %eax
shlq $0x3, %rax
addq %rax, %rdi
movl 0x4c(%rsp), %esi
callq 0x29eb0
movq 0x10(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
addq $0x8, %rdi
movl 0x4c(%rsp), %esi
callq 0xe7c0
movq 0x10(%rsp), %rcx
movq %rcx, %rax
addq $0x150, %rax            # imm = 0x150
movl 0x58(%rsp), %edx
shlq $0x5, %rdx
addq %rdx, %rax
movl 0x40(%rsp), %edx
movl (%rax,%rdx,4), %esi
addl $-0x1, %esi
movl %esi, (%rax,%rdx,4)
movq %rcx, %rax
addq $0x150, %rax            # imm = 0x150
movl 0x58(%rsp), %edx
shlq $0x5, %rdx
addq %rdx, %rax
movl 0x4(%rax), %edx
addl $0x1, %edx
movl %edx, 0x4(%rax)
movq %rcx, %rax
addq $0x190, %rax            # imm = 0x190
movl 0x58(%rsp), %edx
shlq $0x9, %rdx
addq %rdx, %rax
movl 0x40(%rsp), %edx
shlq $0x6, %rdx
addq %rdx, %rax
movq %rcx, %rdx
addq $0x150, %rdx            # imm = 0x150
movl 0x58(%rsp), %esi
shlq $0x5, %rsi
addq %rsi, %rdx
movl 0x40(%rsp), %esi
movslq (%rdx,%rsi,4), %rdx
movl (%rax,%rdx,4), %eax
movl %eax, 0x3c(%rsp)
movslq 0x4c(%rsp), %rax
movl 0x590(%rcx,%rax,4), %edx
movslq 0x3c(%rsp), %rax
movl %edx, 0x590(%rcx,%rax,4)
movl 0x3c(%rsp), %esi
movq %rcx, %rax
addq $0x190, %rax            # imm = 0x190
movl 0x58(%rsp), %edx
shlq $0x9, %rdx
addq %rdx, %rax
movl 0x40(%rsp), %edx
shlq $0x6, %rdx
addq %rdx, %rax
movslq 0x3c(%rsp), %rdx
movslq 0x590(%rcx,%rdx,4), %rdx
movl %esi, (%rax,%rdx,4)
movq %rcx, %rax
addq $0x190, %rax            # imm = 0x190
movl 0x58(%rsp), %edx
shlq $0x9, %rdx
addq %rdx, %rax
movl 0x40(%rsp), %edx
shlq $0x6, %rdx
addq %rdx, %rax
movq %rcx, %rdx
addq $0x150, %rdx            # imm = 0x150
movl 0x58(%rsp), %esi
shlq $0x5, %rsi
addq %rsi, %rdx
movl 0x40(%rsp), %esi
movslq (%rdx,%rsi,4), %rdx
movl $0x40, (%rax,%rdx,4)
movq %rcx, %rax
addq $0x150, %rax            # imm = 0x150
movl 0x58(%rsp), %edx
shlq $0x5, %rdx
addq %rdx, %rax
movl 0x4(%rax), %edx
subl $0x1, %edx
movslq 0x4c(%rsp), %rax
movl %edx, 0x590(%rcx,%rax,4)
movl 0x4c(%rsp), %edx
movq %rcx, %rax
addq $0x190, %rax            # imm = 0x190
movl 0x58(%rsp), %esi
shlq $0x9, %rsi
addq %rsi, %rax
movslq 0x4c(%rsp), %rsi
movslq 0x590(%rcx,%rsi,4), %rcx
movl %edx, 0x40(%rax,%rcx,4)
movl 0x4c(%rsp), %edi
movl 0x50(%rsp), %esi
callq 0x3e630
movq 0x10(%rsp), %rdi
movq %rax, 0x30(%rsp)
addq $0x140, %rdi            # imm = 0x140
movl 0x58(%rsp), %eax
shlq $0x3, %rax
addq %rax, %rdi
movq 0x30(%rsp), %rsi
callq 0x3e610
movq 0x10(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
movl 0x44(%rsp), %eax
shlq $0x3, %rax
addq %rax, %rdi
movq 0x30(%rsp), %rsi
callq 0x3e610
movq 0x10(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
movq 0x30(%rsp), %rsi
callq 0x3e610
movl 0x58(%rsp), %edi
movl 0x44(%rsp), %esi
callq 0x1bce0
movl %eax, %edx
movq 0x10(%rsp), %rax
movslq 0x50(%rsp), %rcx
movl %edx, (%rax,%rcx,4)
movslq 0x4c(%rsp), %rcx
movl $0x10, (%rax,%rcx,4)
movslq 0x4c(%rsp), %rcx
movl 0x590(%rax,%rcx,4), %edx
movslq 0x50(%rsp), %rcx
movl %edx, 0x590(%rax,%rcx,4)
movl 0x50(%rsp), %esi
movq %rax, %rcx
addq $0x190, %rcx            # imm = 0x190
movl 0x58(%rsp), %edx
shlq $0x9, %rdx
addq %rdx, %rcx
movl 0x44(%rsp), %edx
shlq $0x6, %rdx
addq %rdx, %rcx
movslq 0x50(%rsp), %rdx
movslq 0x590(%rax,%rdx,4), %rdx
movl %esi, (%rcx,%rdx,4)
movq 0x1938(%rax), %rax
cmpl $0x0, 0x30(%rax)
je 0x3cbaa
movl 0x4c(%rsp), %eax
movl %eax, 0x2c(%rsp)
testb $0x1, 0x4b(%rsp)
je 0x3c9fb
cmpl $0x0, 0x58(%rsp)
jne 0x3c9e1
movl 0x4c(%rsp), %edi
movl $0x8, %esi
callq 0xe9c0
movl %eax, 0xc(%rsp)
jmp 0x3c9f3
movl 0x4c(%rsp), %edi
movl $0xfffffff8, %esi       # imm = 0xFFFFFFF8
callq 0xe9c0
movl %eax, 0xc(%rsp)
movl 0xc(%rsp), %eax
movl %eax, 0x2c(%rsp)
movq 0x10(%rsp), %rdi
addq $0x140, %rdi            # imm = 0x140
movl 0x54(%rsp), %eax
shlq $0x3, %rax
addq %rax, %rdi
movl 0x2c(%rsp), %esi
callq 0xe7c0
movq 0x10(%rsp), %rax
movq %rax, %rdi
addq $0x100, %rdi            # imm = 0x100
movq 0x1938(%rax), %rax
movl 0x30(%rax), %eax
shlq $0x3, %rax
addq %rax, %rdi
movl 0x2c(%rsp), %esi
callq 0xe7c0
movq 0x10(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
movl 0x2c(%rsp), %esi
callq 0xe7c0
movq 0x10(%rsp), %rax
movl 0x54(%rsp), %edi
movq 0x1938(%rax), %rax
movl 0x30(%rax), %esi
callq 0x1bce0
movq 0x10(%rsp), %rcx
movl %eax, %edx
movslq 0x2c(%rsp), %rax
movl %edx, (%rcx,%rax,4)
movq %rcx, %rax
addq $0x150, %rax            # imm = 0x150
movl 0x54(%rsp), %edx
shlq $0x5, %rdx
addq %rdx, %rax
movq 0x1938(%rcx), %rdx
movl 0x30(%rdx), %edx
movl (%rax,%rdx,4), %esi
addl $0x1, %esi
movl %esi, (%rax,%rdx,4)
movq %rcx, %rax
addq $0x150, %rax            # imm = 0x150
movl 0x54(%rsp), %edx
shlq $0x5, %rdx
addq %rdx, %rax
movq 0x1938(%rcx), %rdx
movl 0x30(%rdx), %edx
movl (%rax,%rdx,4), %edx
subl $0x1, %edx
movslq 0x2c(%rsp), %rax
movl %edx, 0x590(%rcx,%rax,4)
movl 0x2c(%rsp), %edx
movq %rcx, %rax
addq $0x190, %rax            # imm = 0x190
movl 0x54(%rsp), %esi
shlq $0x9, %rsi
addq %rsi, %rax
movq 0x1938(%rcx), %rsi
movl 0x30(%rsi), %esi
shlq $0x6, %rsi
addq %rsi, %rax
movslq 0x2c(%rsp), %rsi
movslq 0x590(%rcx,%rsi,4), %rcx
movl %edx, (%rax,%rcx,4)
movl $0x1, 0x1c(%rsp)
movq 0x10(%rsp), %rcx
movl 0x1c(%rsp), %eax
movq 0x1938(%rcx), %rcx
cmpl 0x90(%rcx), %eax
jge 0x3cba8
movq 0x10(%rsp), %rax
movq 0x1938(%rax), %rax
movslq 0x1c(%rsp), %rcx
movl 0x6c(%rax,%rcx,4), %edi
callq 0x3e730
movl %eax, %ecx
movq 0x10(%rsp), %rax
movl %ecx, 0x28(%rsp)
movq 0x1938(%rax), %rax
movslq 0x1c(%rsp), %rcx
movl 0x6c(%rax,%rcx,4), %edi
callq 0x12990
movq 0x10(%rsp), %rdi
movl %eax, 0x20(%rsp)
movq 0x1938(%rdi), %rax
movslq 0x1c(%rsp), %rcx
movl 0x48(%rax,%rcx,4), %eax
movl %eax, 0x24(%rsp)
movl 0x28(%rsp), %esi
movl 0x24(%rsp), %edx
movl 0x20(%rsp), %ecx
callq 0x3c510
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x3cb18
jmp 0x3cbaa
movq 0x10(%rsp), %rax
movq 0x1938(%rax), %rcx
movq 0x98(%rcx), %rcx
movq %rcx, 0x1938(%rax)
addq $0x68, %rsp
retq
nopl (%rax)