// File: /workspace/github_cpp_makefile_star2_O2/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movl %esi, %r15d
movq %rdi, %rbx
movl 0x1090(%rdi), %r12d
movq %r12, %r14
xorq $0x1, %r14
movl %r14d, 0x1090(%rdi)
movl $0xc000, %eax           # imm = 0xC000
movl %esi, %r13d
andl %eax, %r13d
cmpl %eax, %r13d
jne 0x1a0a5
movq %rbx, %rdi
movl %r15d, %esi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1a32e
movl %r15d, %ebp
shrl $0x6, %ebp
movl %r15d, %edx
andl $0x3f, %edx
movq 0x1938(%rbx), %rax
cmpl $0x0, 0x30(%rax)
je 0x1a0e0
movl 0x34(%rax), %ecx
movq %rbx, %rdi
movl %r14d, %esi
movl %ebp, 0x4(%rsp)
movq %r12, %rbp
movl %edx, %r12d
callq 0x19fe0
movl %r12d, %edx
movq %rbp, %r12
movl 0x4(%rsp), %ebp
andl $0x3f, %ebp
movl %edx, %eax
cmpl $0x4000, %r13d          # imm = 0x4000
jne 0x1a1bf
shrl $0xc, %r15d
andl $0x3, %r15d
addl $0x2, %r15d
leal (,%rax,8), %ecx
leaq 0xf72a4(%rip), %rsi     # 0x1113b0
movq (%rsi,%rcx), %rsi
andq %rsi, 0x100(%rbx,%r15,8)
leaq 0xf7081(%rip), %rsi     # 0x1111a0
movq (%rsi,%rcx), %rcx
orq %rcx, 0x108(%rbx)
movl %r14d, %ecx
movq %rcx, %r11
shlq $0x5, %r11
leaq (%rbx,%r11), %rsi
movslq 0x150(%rsi,%r15,4), %rdi
leaq -0x1(%rdi), %r8
movl %r8d, 0x150(%rsi,%r15,4)
incl 0x154(%rbx,%r11)
movq %rcx, %r9
shlq $0x9, %r9
addq %rbx, %r9
movl %r15d, %r8d
shll $0x6, %r8d
addq %r9, %r8
addq $0x190, %r8             # imm = 0x190
movslq -0x4(%r8,%rdi,4), %rdi
movslq 0x590(%rbx,%rax,4), %r10
movl %r10d, 0x590(%rbx,%rdi,4)
movl %edi, (%r8,%r10,4)
movslq 0x150(%rsi,%r15,4), %rsi
movl $0x40, (%r8,%rsi,4)
movslq 0x154(%rbx,%r11), %rsi
leaq -0x1(%rsi), %r8
movl %r8d, 0x590(%rbx,%rax,4)
movl %edx, %r15d
movl %edx, 0x1cc(%r9,%rsi,4)
pushq $0x1
popq %rdi
movl %r8d, %r9d
jmp 0x1a1d6
movl %edx, %r15d
movl (%rbx,%rax,4), %edi
andl $0x7, %edi
movl 0x590(%rbx,%rax,4), %r9d
movslq %r9d, %r8
movq %r14, %rcx
leaq 0xf6fc3(%rip), %rdx     # 0x1111a0
movl %ebp, %r10d
movq (%rdx,%r10,8), %rsi
orq (%rdx,%rax,8), %rsi
xorq %rsi, 0x140(%rbx,%rcx,8)
movl %edi, %r11d
xorq %rsi, 0x100(%rbx,%r11,8)
xorq 0x100(%rbx), %rsi
movq %rsi, 0x100(%rbx)
leal (%rdi,%r14,8), %r11d
movl %r11d, (%rbx,%r10,4)
movl $0x10, (%rbx,%rax,4)
movl %r9d, 0x590(%rbx,%r10,4)
shlq $0x9, %rcx
leaq (%rbx,%rcx), %rax
addq $0x190, %rax            # imm = 0x190
shll $0x6, %edi
addq %rax, %rdi
movl %ebp, (%rdi,%r8,4)
movq 0x1938(%rbx), %rax
movl 0x30(%rax), %ecx
testq %rcx, %rcx
je 0x1a310
leaq 0x190(%rbx), %rdi
cmpl $0x8000, %r13d          # imm = 0x8000
jne 0x1a26b
cmpl $0x1, %r12d
jne 0x1a267
addl $-0x8, %r15d
jmp 0x1a26b
addl $0x8, %r15d
movslq %r15d, %r8
movq (%rdx,%r8,8), %r9
orq %r9, 0x140(%rbx,%r12,8)
movq (%rdx,%r8,8), %r9
orq %r9, 0x100(%rbx,%rcx,8)
orq (%rdx,%r8,8), %rsi
movq %rsi, 0x100(%rbx)
leal (,%r12,8), %edx
orl %ecx, %edx
movl %edx, (%rbx,%r8,4)
movq %r12, %rdx
shlq $0x5, %rdx
addq %rbx, %rdx
movslq 0x150(%rdx,%rcx,4), %rsi
leal 0x1(%rsi), %r9d
movl %r9d, 0x150(%rdx,%rcx,4)
movl %esi, 0x590(%rbx,%r8,4)
shlq $0x9, %r12
addq %r12, %rdi
shlq $0x6, %rcx
addq %rdi, %rcx
movl %r8d, (%rcx,%rsi,4)
pushq $0x13
popq %r14
leaq -0x12(%r14), %rcx
movslq 0x90(%rax), %rdx
cmpq %rdx, %rcx
jge 0x1a310
movl (%rax,%r14,4), %edx
movl 0x24(%rax,%r14,4), %ecx
movl %ecx, %esi
sarl $0x3, %esi
andl $0x7, %ecx
movq %rbx, %rdi
callq 0x19fe0
movq 0x1938(%rbx), %rax
incq %r14
jmp 0x1a2db
movq 0x98(%rax), %rax
movq %rax, 0x1938(%rbx)
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop