// File: vygr[P]C-Chess/chess.cpp
// Function: best_move(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, int, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>> const&)
auto best_move(const board &brd, int colour, const boards &history)
{
	//first ply of boards
	auto next_boards = all_moves(brd, colour);
	for (auto &sbrd : next_boards)
	{
		auto rep = std::count(begin(history), end(history), sbrd.brd);
		sbrd.bias = static_cast<int>(-(rep * queen_value));
	}
	if (next_boards.size() == 0) return std::string("");
	if (next_boards.size() == 1) return next_boards[0].brd;
	std::sort(begin(next_boards), end(next_boards), [&] (const auto &brd1, const auto &brd2)
	{
		return brd1.score > brd2.score;
	});

	//start move timer
	start_time = std::chrono::high_resolution_clock::now();
	for (auto ply = 1; ply <= max_ply; ++ply)
 	{
		//iterative deepening of ply so we allways have a best move to go with if the timer expires
		std::cout << "\nPly = " << ply << " " << std::flush;
		auto best_index = 0;
		auto alpha = -mate_value*10;
		auto beta = mate_value*10;
		for (auto index = 0; index < static_cast<int>(next_boards.size()); ++index)
		{
			auto score_board = &next_boards[index];
			score_board->score = -score(*score_board, -colour, -beta, -alpha, ply);
			if (score_board->score == timeout_value || score_board->score == -timeout_value)
			{
				//move timer expired
				return next_boards[0].brd;
			}
			score_board->score += score_board->bias;
			if (score_board->score > alpha)
			{
				//got a better board than last best
				alpha = score_board->score;
				best_index = index;
				std::cout << "*" << std::flush;
			}
			else
			{
				//just tick off another board
				std::cout << "." << std::flush;
			}
		}
		if (best_index != 0)
		{
			//promote board to PV
			auto score_board = next_boards[best_index];
			next_boards.erase(begin(next_boards) + best_index);
			next_boards.insert(begin(next_boards), score_board);
		}
		if (alpha >= mate_value || alpha <= -mate_value)
		{
			//don't look further ahead if we allready can force mate
			break;
		}
	}
	return next_boards[0].brd;
}

// Assembly:
subq $0x1b8, %rsp            # imm = 0x1B8
movq %rdi, 0x80(%rsp)
movq %rdi, %rax
movq %rax, 0x88(%rsp)
movq %rdi, 0x1b0(%rsp)
movq %rsi, 0x1a8(%rsp)
movl %edx, 0x1a4(%rsp)
movq %rcx, 0x198(%rsp)
movq 0x1a8(%rsp), %rsi
movl 0x1a4(%rsp), %edx
leaq 0x180(%rsp), %rdi
callq 0x5230
leaq 0x180(%rsp), %rax
movq %rax, 0x178(%rsp)
movq 0x178(%rsp), %rdi
callq 0xad00
movq %rax, 0x170(%rsp)
movq 0x178(%rsp), %rdi
callq 0xad30
movq %rax, 0x168(%rsp)
leaq 0x170(%rsp), %rdi
leaq 0x168(%rsp), %rsi
callq 0xad60
testb $0x1, %al
jne 0x5ded
jmp 0x5ec2
leaq 0x170(%rsp), %rdi
callq 0xada0
movq %rax, 0x160(%rsp)
movq 0x198(%rsp), %rdi
callq 0xaec0
movq %rax, 0x78(%rsp)
jmp 0x5e16
movq 0x78(%rsp), %rax
movq %rax, 0x150(%rsp)
movq 0x198(%rsp), %rdi
callq 0xaef0
movq %rax, 0x70(%rsp)
jmp 0x5e37
movq 0x70(%rsp), %rax
movq %rax, 0x138(%rsp)
movq 0x160(%rsp), %rdx
addq $0x8, %rdx
movq 0x150(%rsp), %rdi
movq 0x138(%rsp), %rsi
callq 0xae70
movq %rax, 0x68(%rsp)
jmp 0x5e6c
movq 0x68(%rsp), %rax
movq %rax, 0x158(%rsp)
imulq $0x384, 0x158(%rsp), %rcx # imm = 0x384
xorl %eax, %eax
subq %rcx, %rax
movl %eax, %ecx
movq 0x160(%rsp), %rax
movl %ecx, 0x4(%rax)
leaq 0x170(%rsp), %rdi
callq 0xae50
jmp 0x5dcf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x148(%rsp)
movl %eax, 0x144(%rsp)
jmp 0x6416
leaq 0x180(%rsp), %rdi
callq 0xac80
cmpq $0x0, %rax
jne 0x5f45
leaq 0x137(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0x2390
movq 0x80(%rsp), %rdi
movq 0x60(%rsp), %rdx
leaq 0x14dfb(%rip), %rsi     # 0x1acf6
callq 0x22e0
jmp 0x5f02
leaq 0x137(%rsp), %rdi
callq 0x2260
movl $0x1, 0x130(%rsp)
jmp 0x63f9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x148(%rsp)
movl %eax, 0x144(%rsp)
leaq 0x137(%rsp), %rdi
callq 0x2260
jmp 0x6416
leaq 0x180(%rsp), %rdi
callq 0xac80
cmpq $0x1, %rax
jne 0x5f8f
xorl %eax, %eax
movl %eax, %esi
leaq 0x180(%rsp), %rdi
callq 0xaf20
movq 0x80(%rsp), %rdi
movq %rax, %rsi
addq $0x8, %rsi
callq 0x20e0
jmp 0x5f7f
movl $0x1, 0x130(%rsp)
jmp 0x63f9
leaq 0x180(%rsp), %rdi
callq 0xaca0
movq %rax, 0x58(%rsp)
jmp 0x5fa3
movq 0x58(%rsp), %rax
movq %rax, 0x128(%rsp)
leaq 0x180(%rsp), %rdi
callq 0xacd0
movq %rax, 0x50(%rsp)
jmp 0x5fc4
movq 0x50(%rsp), %rax
movq %rax, 0x120(%rsp)
movq 0x128(%rsp), %rdi
movq 0x120(%rsp), %rsi
callq 0x6430
jmp 0x5fe8
callq 0x2050
movq %rax, 0x110(%rsp)
movq 0x110(%rsp), %rax
movq %rax, 0x2047c(%rip)     # 0x26480
movl $0x1, 0x10c(%rsp)
cmpl $0x14, 0x10c(%rsp)
jg 0x63c7
movq 0x1ffac(%rip), %rdi     # 0x25fd0
leaq 0x14c2b(%rip), %rsi     # 0x1ac56
callq 0x2210
movq %rax, 0x48(%rsp)
jmp 0x6037
movq 0x48(%rsp), %rdi
movl 0x10c(%rsp), %esi
callq 0x2370
movq %rax, 0x40(%rsp)
jmp 0x604f
movq 0x40(%rsp), %rdi
leaq 0x14c56(%rip), %rsi     # 0x1acb1
callq 0x2210
movq %rax, 0x38(%rsp)
jmp 0x6067
movq 0x38(%rsp), %rdi
movq 0x1ff65(%rip), %rsi     # 0x25fd8
callq 0x2250
jmp 0x607a
movl $0x0, 0x108(%rsp)
movl $0xffe17b80, 0x104(%rsp) # imm = 0xFFE17B80
movl $0x1e8480, 0x100(%rsp) # imm = 0x1E8480
movl $0x0, 0xfc(%rsp)
movl 0xfc(%rsp), %eax
movl %eax, 0x34(%rsp)
leaq 0x180(%rsp), %rdi
callq 0xac80
movq %rax, %rcx
movl 0x34(%rsp), %eax
cmpl %ecx, %eax
jge 0x6248
movslq 0xfc(%rsp), %rsi
leaq 0x180(%rsp), %rdi
callq 0xaf20
movq %rax, 0xf0(%rsp)
movq 0xf0(%rsp), %rdi
movl 0x1a4(%rsp), %esi
negl %esi
movl 0x100(%rsp), %edx
negl %edx
movl 0x104(%rsp), %ecx
negl %ecx
movl 0x10c(%rsp), %r8d
callq 0x53e0
movl %eax, 0x30(%rsp)
jmp 0x6120
movl 0x30(%rsp), %eax
xorl %ecx, %ecx
subl %eax, %ecx
movq 0xf0(%rsp), %rax
movl %ecx, (%rax)
movq 0xf0(%rsp), %rax
cmpl $0x61a80, (%rax)        # imm = 0x61A80
je 0x6152
movq 0xf0(%rsp), %rax
cmpl $0xfff9e580, (%rax)     # imm = 0xFFF9E580
jne 0x6189
xorl %eax, %eax
movl %eax, %esi
leaq 0x180(%rsp), %rdi
callq 0xaf20
movq 0x80(%rsp), %rdi
movq %rax, %rsi
addq $0x8, %rsi
callq 0x20e0
jmp 0x6179
movl $0x1, 0x130(%rsp)
jmp 0x63f9
movq 0xf0(%rsp), %rax
movl 0x4(%rax), %ecx
movq 0xf0(%rsp), %rax
addl (%rax), %ecx
movl %ecx, (%rax)
movq 0xf0(%rsp), %rax
movl (%rax), %eax
cmpl 0x104(%rsp), %eax
jle 0x6201
movq 0xf0(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x104(%rsp)
movl 0xfc(%rsp), %eax
movl %eax, 0x108(%rsp)
movq 0x1fdf7(%rip), %rdi     # 0x25fd0
leaq 0x14a7e(%rip), %rsi     # 0x1ac5e
callq 0x2210
movq %rax, 0x28(%rsp)
jmp 0x61ec
movq 0x28(%rsp), %rdi
movq 0x1fde0(%rip), %rsi     # 0x25fd8
callq 0x2250
jmp 0x61ff
jmp 0x6230
movq 0x1fdc8(%rip), %rdi     # 0x25fd0
leaq 0x14a51(%rip), %rsi     # 0x1ac60
callq 0x2210
movq %rax, 0x20(%rsp)
jmp 0x621b
movq 0x20(%rsp), %rdi
movq 0x1fdb1(%rip), %rsi     # 0x25fd8
callq 0x2250
jmp 0x622e
jmp 0x6230
jmp 0x6232
movl 0xfc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xfc(%rsp)
jmp 0x60a6
cmpl $0x0, 0x108(%rsp)
je 0x6393
movslq 0x108(%rsp), %rsi
leaq 0x180(%rsp), %rdi
callq 0xaf20
movq %rax, %rsi
leaq 0xc8(%rsp), %rdi
callq 0xaf40
jmp 0x627d
leaq 0x180(%rsp), %rdi
callq 0xaca0
movq %rax, 0x18(%rsp)
jmp 0x6291
movq 0x18(%rsp), %rax
movq %rax, 0xb0(%rsp)
movslq 0x108(%rsp), %rsi
leaq 0xb0(%rsp), %rdi
callq 0xaff0
movq %rax, 0xb8(%rsp)
leaq 0xc0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0xb030
movq 0xc0(%rsp), %rsi
leaq 0x180(%rsp), %rdi
callq 0xaf80
movq %rax, 0x10(%rsp)
jmp 0x62ec
movq 0x10(%rsp), %rax
movq %rax, 0xa8(%rsp)
leaq 0x180(%rsp), %rdi
callq 0xaca0
movq %rax, 0x8(%rsp)
jmp 0x630d
movq 0x8(%rsp), %rax
movq %rax, 0x98(%rsp)
leaq 0xa0(%rsp), %rdi
leaq 0x98(%rsp), %rsi
callq 0xb030
movq 0xa0(%rsp), %rsi
leaq 0x180(%rsp), %rdi
leaq 0xc8(%rsp), %rdx
callq 0xb070
movq %rax, (%rsp)
jmp 0x6352
movq (%rsp), %rax
movq %rax, 0x90(%rsp)
leaq 0xc8(%rsp), %rdi
callq 0xa660
jmp 0x6393
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x148(%rsp)
movl %eax, 0x144(%rsp)
leaq 0xc8(%rsp), %rdi
callq 0xa660
jmp 0x6416
cmpl $0x30d40, 0x104(%rsp) # imm = 0x30D40
jge 0x63ad
cmpl $0xfffcf2c0, 0x104(%rsp) # imm = 0xFFFCF2C0
jg 0x63af
jmp 0x63c7
jmp 0x63b1
movl 0x10c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x10c(%rsp)
jmp 0x600f
xorl %eax, %eax
movl %eax, %esi
leaq 0x180(%rsp), %rdi
callq 0xaf20
movq 0x80(%rsp), %rdi
movq %rax, %rsi
addq $0x8, %rsi
callq 0x20e0
jmp 0x63ee
movl $0x1, 0x130(%rsp)
leaq 0x180(%rsp), %rdi
callq 0xa8d0
movq 0x88(%rsp), %rax
addq $0x1b8, %rsp            # imm = 0x1B8
retq
leaq 0x180(%rsp), %rdi
callq 0xa8d0
movq 0x148(%rsp), %rdi
callq 0x2380