// File: czinn[P]homeworlds/game.cc
// Function: Game::perform_action(Action&)
bool Game::perform_action(Action& action) {
  if (action.player != cur_player_) {
    return false;
  }

  if (sacrifice_actions_ > 0) {
    sacrifice_actions_--;
  }

  switch(action.type) {
    case PASS:
      advance_cur_player();
      break;

    case ATTACK: {
        // Need to find player of attacked ship
        const System& system = get_system(action.system);
        const auto& ship = find_if(system.ships.begin(), system.ships.end(),
            [&action](const Ship& ship) {
              return ship.pyramid == action.ship && ship.player != action.player;
            });
        if (ship == system.ships.end()) {
          return false;
        }
        remove_ship(action.system, *ship);
        add_ship(action.system, Ship{action.player, ship->pyramid});
        done_main_action_ = true;
      }
      break;

    case DISCOVER: {
        int system_id = create_system({action.target});
        action.system_target = system_id;
        add_ship(system_id,
            remove_ship(action.system, Ship{action.player, action.ship}));
        if (get_system(action.system).ships.size() == 0) {
          destroy_system(action.system);
        }
        done_main_action_ = true;
      }
      break;

    case TRAVEL:
      add_ship(action.system_target,
          remove_ship(action.system, Ship{action.player, action.ship}));
      if (get_system(action.system).ships.size() == 0) {
        destroy_system(action.system);
      }
      done_main_action_ = true;
      break;

    case BUILD:
      add_ship(action.system, Ship{action.player, action.ship});
      done_main_action_ = true;
      break;

    case TRADE:
      remove_ship(action.system, Ship{action.player, action.ship});
      add_ship(action.system, Ship{action.player, action.target});
      done_main_action_ = true;
      break;

    case SACRIFICE:
      remove_ship(action.system, Ship{action.player, action.ship});
      if (get_system(action.system).ships.size() == 0) {
        destroy_system(action.system);
      }
      sacrifice_colour_ = action.ship.colour;
      sacrifice_actions_ = action.ship.size;
      done_main_action_ = true;
      break;

    case CATASTROPHE:
      apply_catastrophe(action.system, action.ship.colour);
      break;

  }

  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1c0, %rsp            # imm = 0x1C0
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rcx
movq %rcx, -0x190(%rbp)
movq -0x18(%rbp), %rax
movl (%rax), %eax
cmpl 0x4(%rcx), %eax
je 0x5932
movb $0x0, -0x1(%rbp)
jmp 0x5ed5
movq -0x190(%rbp), %rax
cmpl $0x0, 0x14(%rax)
jle 0x594f
movq -0x190(%rbp), %rax
movl 0x14(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x14(%rax)
movq -0x18(%rbp), %rax
movl 0x4(%rax), %eax
movq %rax, -0x198(%rbp)
subq $0x7, %rax
ja 0x5ed1
movq -0x198(%rbp), %rax
leaq 0x1e6bb(%rip), %rcx     # 0x24030
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x190(%rbp), %rdi
callq 0x5ef0
jmp 0x5ed1
movq -0x190(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0x8(%rax), %esi
callq 0x3e20
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rdi
addq $0x20, %rdi
callq 0x8be0
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rdi
addq $0x20, %rdi
callq 0x8c10
movq %rax, -0x40(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x38(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x48(%rbp), %rdx
callq 0x5f30
movq %rax, -0x30(%rbp)
leaq -0x30(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x1a0(%rbp)
movq -0x20(%rbp), %rdi
addq $0x20, %rdi
callq 0x8c10
movq -0x1a0(%rbp), %rdi
movq %rax, -0x50(%rbp)
leaq -0x50(%rbp), %rsi
callq 0x9360
testb $0x1, %al
jne 0x5a1f
jmp 0x5a28
movb $0x0, -0x1(%rbp)
jmp 0x5ed5
movq -0x18(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x1a8(%rbp)
movq -0x28(%rbp), %rdi
callq 0x8fb0
movl -0x1a8(%rbp), %esi
movq -0x190(%rbp), %rdi
movq %rax, %rdx
callq 0x5f90
movl %edx, -0x68(%rbp)
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
movq %rax, -0x5c(%rbp)
movl -0x68(%rbp), %eax
movl %eax, -0x54(%rbp)
movq -0x18(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x1a4(%rbp)
movq -0x18(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x7c(%rbp)
movq -0x28(%rbp), %rdi
callq 0x93a0
movl -0x1a4(%rbp), %esi
movq -0x190(%rbp), %rdi
movq 0x4(%rax), %rax
movq %rax, -0x78(%rbp)
leaq -0x7c(%rbp), %rdx
callq 0x6110
movq -0x190(%rbp), %rax
movb $0x1, 0x8(%rax)
jmp 0x5ed1
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0xb0(%rbp)
leaq -0xb0(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq $0x1, -0xa0(%rbp)
leaq -0xb1(%rbp), %rdi
movq %rdi, -0x1b0(%rbp)
callq 0x93c0
movq -0x1b0(%rbp), %rcx
movq -0xa8(%rbp), %rsi
movq -0xa0(%rbp), %rdx
leaq -0x98(%rbp), %rdi
callq 0x93e0
jmp 0x5b13
movq -0x190(%rbp), %rdi
leaq -0x98(%rbp), %rsi
xorl %edx, %edx
callq 0x61a0
movl %eax, -0x1b4(%rbp)
jmp 0x5b30
leaq -0x98(%rbp), %rdi
callq 0x9460
leaq -0xb1(%rbp), %rdi
callq 0x94c0
movl -0x1b4(%rbp), %eax
movq -0x190(%rbp), %rdi
movl %eax, -0x80(%rbp)
movl -0x80(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x14(%rax)
movl -0x80(%rbp), %eax
movl %eax, -0x1b8(%rbp)
movq -0x18(%rbp), %rcx
movl (%rcx), %eax
movl 0x8(%rcx), %esi
movl %eax, -0xdc(%rbp)
movq -0x18(%rbp), %rax
movq 0xc(%rax), %rax
movq %rax, -0xd8(%rbp)
leaq -0xdc(%rbp), %rdx
callq 0x5f90
movl -0x1b8(%rbp), %esi
movq -0x190(%rbp), %rdi
movl %edx, -0xe8(%rbp)
movq %rax, -0xf0(%rbp)
movq -0xf0(%rbp), %rax
movq %rax, -0xd0(%rbp)
movl -0xe8(%rbp), %eax
movl %eax, -0xc8(%rbp)
leaq -0xd0(%rbp), %rdx
callq 0x6110
movq -0x190(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0x8(%rax), %esi
callq 0x3e20
movq %rax, %rdi
addq $0x20, %rdi
callq 0x94e0
cmpq $0x0, %rax
jne 0x5c52
movq -0x190(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0x8(%rax), %esi
callq 0x62c0
jmp 0x5c52
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
jmp 0x5c41
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xc0(%rbp)
movl %eax, -0xc4(%rbp)
leaq -0x98(%rbp), %rdi
callq 0x9460
leaq -0xb1(%rbp), %rdi
callq 0x94c0
jmp 0x5ee3
movq -0x190(%rbp), %rax
movb $0x1, 0x8(%rax)
jmp 0x5ed1
movq -0x190(%rbp), %rdi
movq -0x18(%rbp), %rcx
movl 0x14(%rcx), %eax
movl %eax, -0x1bc(%rbp)
movl (%rcx), %eax
movl 0x8(%rcx), %esi
movl %eax, -0x108(%rbp)
movq -0x18(%rbp), %rax
movq 0xc(%rax), %rax
movq %rax, -0x104(%rbp)
leaq -0x108(%rbp), %rdx
callq 0x5f90
movl -0x1bc(%rbp), %esi
movq -0x190(%rbp), %rdi
movl %edx, -0x110(%rbp)
movq %rax, -0x118(%rbp)
movq -0x118(%rbp), %rax
movq %rax, -0xfc(%rbp)
movl -0x110(%rbp), %eax
movl %eax, -0xf4(%rbp)
leaq -0xfc(%rbp), %rdx
callq 0x6110
movq -0x190(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0x8(%rax), %esi
callq 0x3e20
movq %rax, %rdi
addq $0x20, %rdi
callq 0x94e0
cmpq $0x0, %rax
jne 0x5d14
movq -0x190(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0x8(%rax), %esi
callq 0x62c0
movq -0x190(%rbp), %rax
movb $0x1, 0x8(%rax)
jmp 0x5ed1
movq -0x190(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x18(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x124(%rbp)
movq -0x18(%rbp), %rax
movq 0xc(%rax), %rax
movq %rax, -0x120(%rbp)
leaq -0x124(%rbp), %rdx
callq 0x6110
movq -0x190(%rbp), %rax
movb $0x1, 0x8(%rax)
jmp 0x5ed1
movq -0x190(%rbp), %rdi
movq -0x18(%rbp), %rcx
movl (%rcx), %eax
movl 0x8(%rcx), %esi
movl %eax, -0x130(%rbp)
movq -0x18(%rbp), %rax
movq 0xc(%rax), %rax
movq %rax, -0x12c(%rbp)
leaq -0x130(%rbp), %rdx
callq 0x5f90
movq -0x190(%rbp), %rdi
movl %edx, -0x148(%rbp)
movq %rax, -0x150(%rbp)
movq -0x150(%rbp), %rax
movq %rax, -0x13c(%rbp)
movl -0x148(%rbp), %eax
movl %eax, -0x134(%rbp)
movq -0x18(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x18(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x15c(%rbp)
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x158(%rbp)
leaq -0x15c(%rbp), %rdx
callq 0x6110
movq -0x190(%rbp), %rax
movb $0x1, 0x8(%rax)
jmp 0x5ed1
movq -0x190(%rbp), %rdi
movq -0x18(%rbp), %rcx
movl (%rcx), %eax
movl 0x8(%rcx), %esi
movl %eax, -0x168(%rbp)
movq -0x18(%rbp), %rax
movq 0xc(%rax), %rax
movq %rax, -0x164(%rbp)
leaq -0x168(%rbp), %rdx
callq 0x5f90
movq -0x190(%rbp), %rdi
movl %edx, -0x180(%rbp)
movq %rax, -0x188(%rbp)
movq -0x188(%rbp), %rax
movq %rax, -0x174(%rbp)
movl -0x180(%rbp), %eax
movl %eax, -0x16c(%rbp)
movq -0x18(%rbp), %rax
movl 0x8(%rax), %esi
callq 0x3e20
movq %rax, %rdi
addq $0x20, %rdi
callq 0x94e0
cmpq $0x0, %rax
jne 0x5e96
movq -0x190(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0x8(%rax), %esi
callq 0x62c0
movq -0x190(%rbp), %rax
movq -0x18(%rbp), %rcx
movl 0x10(%rcx), %ecx
movl %ecx, 0x18(%rax)
movq -0x18(%rbp), %rcx
movl 0xc(%rcx), %ecx
movl %ecx, 0x14(%rax)
movb $0x1, 0x8(%rax)
jmp 0x5ed1
movq -0x190(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x18(%rbp), %rax
movl 0x10(%rax), %edx
callq 0x6450
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x1c0, %rsp            # imm = 0x1C0
popq %rbp
retq
movq -0xc0(%rbp), %rdi
callq 0x33c0
nop