// File: /workspace/github_cpp_makefile_star2_O3/Alcaro[P]bridges/solver.cpp
// Function: (anonymous namespace)::solver<((anonymous namespace)::op_t)1>::solve_rec(unsigned short, unsigned short)
int solve_rec(uint16_t layer, uint16_t maxlayer)
	{
//static int n=0;if(layer>n){n=layer;printf("MAXDEPTH=%i\n",n);}
//printf("LAYER=%i\n",layer);
		add_difficulty(3*layer*layer);
		
		size_t layerbufsize = sizeof(uint16_t)*100*map.height;
		
		uint16_t maxlayer2 = sizeof(possibilities_buf)/layerbufsize;
		if (op != op_hint && op != op_difficulty) maxlayer = maxlayer2; // discard the argument and hope inliner deletes it
		if (layer < maxlayer && layer < maxlayer2)
		{
			if (!do_isolation_rule()) return false;
			
			//if still unsure, guess
			for (int y=0;y<map.height;y++)
			for (int x=0;x<map.width;x++)
			{
				uint16_t index = y*100+x;
//printf("EEE=%.3i\n",index);
				//gamemap::island& here = map.map[y][x];
				uint16_t flags = possibilities[index];
				uint16_t multidir_flags = (flags & (flags>>4 | flags>>8));
				if (!multidir_flags) continue; // no guess possible? skip this tile
				if (map.map[y][x].population < 0) continue; // don't guess on ocean tiles
				
				//right and up (ignore left/down, they'd only find duplicates)
				for (int dir=0;dir<2;dir++)
				{
//printf("%.4X:%.4X\n",flags,multidir_flags & (0x0111<<dir));
					//if multiple bridge numbers are allowed in this direction...
					if (multidir_flags & (0x0111<<dir))
					{
						int set_mask = (dir ? 0xDDDD : 0xEEEE);
						for (int n=0;n<=2;n++)
						{
							int dirbit = (0x0001<<(n*4)<<dir);
							if (flags & dirbit)
							{
//printf("GUESS:BEGIN(%.3i:%.4X->%.4X)\n",index,flags,(flags & (set_mask | dirbit)));
								//if looking for another solution, only make contrary assumptions
								// (but only for first layer, deeper ones can do whatever)
								if (op==op_another && layer==0 && map.get(index).bridges[dir] == n)
								{
//puts("GUESS:NOTSAME");
									continue;
								}
								
								int newflags = (flags & (set_mask | dirbit));
								memcpy(possibilities_buf + (layer+1)*layerbufsize, possibilities_buf + layer*layerbufsize, layerbufsize);
								possibilities = possibilities_buf + (layer+1)*layerbufsize;
								
								int ret = set_state(index, newflags);
								if (ret) ret = solve_rec(layer+1, maxlayer);
								if (ret == 1)
								{
//puts("GUESS:GOOD");
									//if that's a valid solution, return it
									//otherwise, mark the map unsolvable
									possibilities = possibilities_buf + layer*layerbufsize;
									memcpy(possibilities_buf + layer*layerbufsize, possibilities_buf + (layer+1)*layerbufsize, layerbufsize);
									return true;
								}
								if (ret == 0)
								{
//puts("GUESS:BAD");
									//if that can't be a valid solution, mark it as such
									possibilities = possibilities_buf + layer*layerbufsize;
									
									//it's possible that both yes and no are impossible
									if (!set_state(index, flags & ~dirbit)) return false;
									
									if (!do_isolation_rule()) return false;
									flags = possibilities[index];
									multidir_flags = (flags & (flags>>4 | flags>>8));
									if (!(multidir_flags & (0x0111<<dir))) break;
								}
							}
						}
					}
				}
			}
		}
		else if (layer < maxlayer2)
		{
			return -1;
		}
		else
		{
#ifndef STDOUT_ERROR
			puts("Out of memory");
			puts(map.serialize());
#endif
			abort();
			return -1;
		}
		
		if (op==op_another && layer==0) return false;
		return true;
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rdi, %rbx
movq (%rdi), %rax
movslq 0x4(%rax), %rax
imulq $0xc8, %rax, %rcx
xorl %r12d, %r12d
movl $0x9c400, %eax          # imm = 0x9C400
xorl %edx, %edx
movq %rcx, 0x10(%rsp)
divq %rcx
movzwl %ax, %eax
movl %esi, 0x4(%rsp)
cmpl %esi, %eax
jbe 0x293ab
movq %rbx, %rdi
callq 0x293e8
testb %al, %al
je 0x29373
movq (%rbx), %rax
cmpl $0x0, 0x4(%rax)
jle 0x29366
movl 0x4(%rsp), %esi
movl %esi, %edx
incl %edx
movq 0x10(%rsp), %rdi
movq %rdi, %rcx
imulq %rdx, %rcx
leaq (%rbx,%rcx,2), %rcx
addq $0x4e30, %rcx           # imm = 0x4E30
movq %rcx, 0x30(%rsp)
movzwl %si, %ecx
imulq %rdi, %rcx
leaq (%rbx,%rcx,2), %rcx
addq $0x4e30, %rcx           # imm = 0x4E30
movq %rcx, 0x18(%rsp)
movl (%rax), %ecx
xorl %edi, %edi
movzwl %dx, %edx
movl %edx, 0x24(%rsp)
testl %ecx, %ecx
jle 0x29356
imulq $0x64, %rdi, %r8
imulq $0x4b0, %rdi, %r9       # imm = 0x4B0
xorl %r10d, %r10d
movq %rdi, 0x50(%rsp)
movq %r8, 0x48(%rsp)
movq %r9, 0x40(%rsp)
leaq (%r10,%r8), %rdx
movq 0x4e28(%rbx), %rsi
movzwl %dx, %r15d
movl %r15d, %edx
movzwl (%rsi,%rdx,2), %ebp
movl %ebp, %edx
shrl $0x4, %edx
movl %ebp, %r12d
shrl $0x8, %r12d
orl %edx, %r12d
andw %bp, %r12w
je 0x29347
leaq (%rax,%r9), %rdx
leaq (%r10,%r10,2), %rsi
cmpb $0x0, 0xc(%rdx,%rsi,4)
js 0x29347
movq %r10, 0x58(%rsp)
movl %r15d, %eax
shrl $0x2, %eax
imull $0x147b, %eax, %eax     # imm = 0x147B
shrl $0x11, %eax
imull $0x64, %eax, %ecx
movl %r15d, %edx
subl %ecx, %edx
movzwl %dx, %ecx
movq %rcx, 0x68(%rsp)
movb $0x1, %cl
movl $0xeeee, 0x8(%rsp)      # imm = 0xEEEE
imulq $0x4b0, %rax, %rax      # imm = 0x4B0
movq %rax, 0x60(%rsp)
xorl %edx, %edx
movq %r15, 0x70(%rsp)
movl %ecx, 0x20(%rsp)
movzwl %r12w, %eax
movl $0x111, %esi            # imm = 0x111
movl %edx, %ecx
shll %cl, %esi
movl %esi, 0x28(%rsp)
testl %eax, %esi
je 0x29311
xorl %esi, %esi
xorl %r13d, %r13d
movq %rdx, 0x38(%rsp)
movl $0x1, %r14d
movl %esi, %ecx
shll %cl, %r14d
movl %edx, %ecx
shll %cl, %r14d
movzwl %bp, %eax
testl %eax, %r14d
je 0x29301
cmpw $0x0, 0x4(%rsp)
jne 0x2921e
movq (%rbx), %rax
addq 0x60(%rsp), %rax
movq 0x68(%rsp), %rcx
leaq (%rcx,%rcx,2), %rcx
leaq (%rax,%rcx,4), %rax
movzbl 0x14(%rdx,%rax), %eax
cmpl %eax, %r13d
je 0x29301
movl %esi, 0xc(%rsp)
movq %rbx, %r15
movl %r14d, %ebx
orl 0x8(%rsp), %ebx
movl %ebp, 0x2c(%rsp)
movq 0x30(%rsp), %rbp
movq %rbp, %rdi
movq 0x18(%rsp), %rsi
movq 0x10(%rsp), %rdx
callq 0x3280
movq %rbp, 0x4e28(%r15)
movl 0x2c(%rsp), %ebp
andl %ebp, %ebx
movzwl %bx, %edx
movq %r15, %rbx
movq 0x70(%rsp), %r15
movq %rbx, %rdi
movl %r15d, %esi
callq 0x28a50
testb %al, %al
je 0x29291
movq %rbx, %rdi
movl 0x24(%rsp), %esi
callq 0x29062
testl %eax, %eax
je 0x29291
cmpl $0x1, %eax
movq 0x38(%rsp), %rdx
movl 0xc(%rsp), %esi
jne 0x29301
jmp 0x29388
movq 0x18(%rsp), %rax
movq %rax, 0x4e28(%rbx)
notl %r14d
andl %r14d, %ebp
movzwl %bp, %edx
movq %rbx, %rdi
movl %r15d, %esi
callq 0x28a50
xorl %r12d, %r12d
testb %al, %al
je 0x29373
movq %rbx, %rdi
callq 0x293e8
testb %al, %al
je 0x29373
movq 0x4e28(%rbx), %rax
movzwl (%rax,%r15,2), %ebp
movl %ebp, %eax
shrl $0x4, %eax
movl %ebp, %r12d
shrl $0x8, %r12d
orl %eax, %r12d
andl %ebp, %r12d
movl %r12d, %eax
andl 0x28(%rsp), %eax
testl $0xffff, %eax           # imm = 0xFFFF
movq 0x38(%rsp), %rdx
movl 0xc(%rsp), %esi
je 0x29311
incl %r13d
addl $0x4, %esi
cmpl $0x3, %r13d
jne 0x291d7
movl $0x1, %edx
movl $0xdddd, 0x8(%rsp)      # imm = 0xDDDD
testb $0x1, 0x20(%rsp)
movl $0x0, %ecx
jne 0x291b0
movq (%rbx), %rax
movl (%rax), %ecx
movq 0x50(%rsp), %rdi
movq 0x48(%rsp), %r8
movq 0x40(%rsp), %r9
movq 0x58(%rsp), %r10
incq %r10
movslq %ecx, %rdx
cmpq %rdx, %r10
jl 0x2912d
incq %rdi
movslq 0x4(%rax), %rdx
cmpq %rdx, %rdi
jl 0x29108
xorl %r12d, %r12d
cmpw $0x0, 0x4(%rsp)
setne %r12b
movl %r12d, %eax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x18(%rsp), %rdi
movq %rdi, 0x4e28(%rbx)
movq 0x30(%rsp), %rsi
movq 0x10(%rsp), %rdx
callq 0x3280
movl $0x1, %r12d
jmp 0x29373
leaq 0x9acc(%rip), %rdi      # 0x32e7e
callq 0x3590
movq (%rbx), %rsi
leaq 0x78(%rsp), %rbx
movq %rbx, %rdi
callq 0x2335a
cmpb $0x0, 0xf(%rbx)
movq %rbx, %rdi
jns 0x293d5
movq 0x78(%rsp), %rdi
callq 0x3590
movq %rbx, %rdi
callq 0x2a87c
callq 0x3180
nop