// File: 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
movq %rsp, %rbp
subq $0x70, %rsp
movw %dx, %ax
movw %si, %cx
movq %rdi, -0x18(%rbp)
movw %cx, -0x1a(%rbp)
movw %ax, -0x1c(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x70(%rbp)
movzwl -0x1a(%rbp), %ecx
imull $0x3, %ecx, %ecx
movzwl -0x1a(%rbp), %edx
imull %edx, %ecx
movq %rax, -0x8(%rbp)
movl %ecx, -0xc(%rbp)
movq (%rax), %rax
movslq 0x4(%rax), %rax
imulq $0xc8, %rax, %rax
movq %rax, -0x28(%rbp)
movl $0x9c400, %eax          # imm = 0x9C400
xorl %ecx, %ecx
movl %ecx, %edx
divq -0x28(%rbp)
movw %ax, -0x2a(%rbp)
movw -0x2a(%rbp), %ax
movw %ax, -0x1c(%rbp)
movzwl -0x1a(%rbp), %eax
movzwl -0x1c(%rbp), %ecx
cmpl %ecx, %eax
jge 0x580e3
movzwl -0x1a(%rbp), %eax
movzwl -0x2a(%rbp), %ecx
cmpl %ecx, %eax
jge 0x580e3
movq -0x70(%rbp), %rdi
callq 0x586c0
testb $0x1, %al
jne 0x57d6b
movl $0x0, -0x10(%rbp)
jmp 0x5814c
movl $0x0, -0x30(%rbp)
movq -0x70(%rbp), %rcx
movl -0x30(%rbp), %eax
movq (%rcx), %rcx
cmpl 0x4(%rcx), %eax
jge 0x580e1
movl $0x0, -0x34(%rbp)
movq -0x70(%rbp), %rcx
movl -0x34(%rbp), %eax
movq (%rcx), %rcx
cmpl (%rcx), %eax
jge 0x580d1
movq -0x70(%rbp), %rax
imull $0x64, -0x30(%rbp), %ecx
addl -0x34(%rbp), %ecx
movw %cx, -0x36(%rbp)
movq 0x4e28(%rax), %rax
movzwl -0x36(%rbp), %ecx
movw (%rax,%rcx,2), %ax
movw %ax, -0x38(%rbp)
movzwl -0x38(%rbp), %eax
movzwl -0x38(%rbp), %ecx
sarl $0x4, %ecx
movzwl -0x38(%rbp), %edx
sarl $0x8, %edx
orl %edx, %ecx
andl %ecx, %eax
movw %ax, -0x3a(%rbp)
cmpw $0x0, -0x3a(%rbp)
jne 0x57de6
jmp 0x580c3
movq -0x70(%rbp), %rax
movq (%rax), %rax
addq $0xc, %rax
movslq -0x30(%rbp), %rcx
imulq $0x4b0, %rcx, %rcx      # imm = 0x4B0
addq %rcx, %rax
movslq -0x34(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
jge 0x57e17
jmp 0x580c3
movl $0x0, -0x40(%rbp)
cmpl $0x2, -0x40(%rbp)
jge 0x580c1
movzwl -0x3a(%rbp), %eax
movl -0x40(%rbp), %ecx
movl $0x111, %edx            # imm = 0x111
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x580b1
movl -0x40(%rbp), %edx
movl $0xeeee, %eax           # imm = 0xEEEE
movl $0xdddd, %ecx           # imm = 0xDDDD
cmpl $0x0, %edx
cmovnel %ecx, %eax
movl %eax, -0x44(%rbp)
movl $0x0, -0x48(%rbp)
cmpl $0x2, -0x48(%rbp)
jg 0x580af
movl -0x48(%rbp), %ecx
shll $0x2, %ecx
movl $0x1, %eax
shll %cl, %eax
movl -0x40(%rbp), %ecx
shll %cl, %eax
movl %eax, -0x4c(%rbp)
movzwl -0x38(%rbp), %eax
andl -0x4c(%rbp), %eax
cmpl $0x0, %eax
je 0x5809f
movzwl -0x1a(%rbp), %eax
cmpl $0x0, %eax
jne 0x57ebb
movq -0x70(%rbp), %rax
movq (%rax), %rdi
movzwl -0x36(%rbp), %esi
callq 0x4e8e0
movslq -0x40(%rbp), %rcx
movzbl 0x8(%rax,%rcx), %eax
cmpl -0x48(%rbp), %eax
jne 0x57ebb
jmp 0x580a1
movq -0x70(%rbp), %rsi
movzwl -0x38(%rbp), %eax
movl -0x44(%rbp), %ecx
orl -0x4c(%rbp), %ecx
andl %ecx, %eax
movl %eax, -0x50(%rbp)
movq %rsi, %rdi
addq $0x4e30, %rdi           # imm = 0x4E30
movzwl -0x1a(%rbp), %eax
addl $0x1, %eax
cltq
imulq -0x28(%rbp), %rax
shlq %rax
addq %rax, %rdi
addq $0x4e30, %rsi           # imm = 0x4E30
movzwl -0x1a(%rbp), %eax
imulq -0x28(%rbp), %rax
shlq %rax
addq %rax, %rsi
movq -0x28(%rbp), %rdx
callq 0x4280
movq -0x70(%rbp), %rdi
movq %rdi, %rax
addq $0x4e30, %rax           # imm = 0x4E30
movzwl -0x1a(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
imulq -0x28(%rbp), %rcx
shlq %rcx
addq %rcx, %rax
movq %rax, 0x4e28(%rdi)
movw -0x36(%rbp), %cx
movl -0x50(%rbp), %eax
movzwl %cx, %esi
movzwl %ax, %edx
callq 0x574f0
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x54(%rbp)
cmpl $0x0, -0x54(%rbp)
je 0x57f6e
movq -0x70(%rbp), %rdi
movzwl -0x1a(%rbp), %eax
addl $0x1, %eax
movzwl %ax, %esi
movzwl -0x1c(%rbp), %edx
callq 0x57cd0
movl %eax, -0x54(%rbp)
cmpl $0x1, -0x54(%rbp)
jne 0x57fe0
movq -0x70(%rbp), %rsi
movq %rsi, %rax
addq $0x4e30, %rax           # imm = 0x4E30
movzwl -0x1a(%rbp), %ecx
imulq -0x28(%rbp), %rcx
shlq %rcx
addq %rcx, %rax
movq %rax, 0x4e28(%rsi)
movq %rsi, %rdi
addq $0x4e30, %rdi           # imm = 0x4E30
movzwl -0x1a(%rbp), %eax
imulq -0x28(%rbp), %rax
shlq %rax
addq %rax, %rdi
addq $0x4e30, %rsi           # imm = 0x4E30
movzwl -0x1a(%rbp), %eax
addl $0x1, %eax
cltq
imulq -0x28(%rbp), %rax
shlq %rax
addq %rax, %rsi
movq -0x28(%rbp), %rdx
callq 0x4280
movl $0x1, -0x10(%rbp)
jmp 0x5814c
cmpl $0x0, -0x54(%rbp)
jne 0x5809d
movq -0x70(%rbp), %rdi
movq %rdi, %rax
addq $0x4e30, %rax           # imm = 0x4E30
movzwl -0x1a(%rbp), %ecx
imulq -0x28(%rbp), %rcx
shlq %rcx
addq %rcx, %rax
movq %rax, 0x4e28(%rdi)
movw -0x36(%rbp), %cx
movzwl -0x38(%rbp), %eax
movl -0x4c(%rbp), %edx
xorl $-0x1, %edx
andl %edx, %eax
movzwl %cx, %esi
movzwl %ax, %edx
callq 0x574f0
testb $0x1, %al
jne 0x58038
movl $0x0, -0x10(%rbp)
jmp 0x5814c
movq -0x70(%rbp), %rdi
callq 0x586c0
testb $0x1, %al
jne 0x58051
movl $0x0, -0x10(%rbp)
jmp 0x5814c
movq -0x70(%rbp), %rax
movq 0x4e28(%rax), %rax
movzwl -0x36(%rbp), %ecx
movw (%rax,%rcx,2), %ax
movw %ax, -0x38(%rbp)
movzwl -0x38(%rbp), %eax
movzwl -0x38(%rbp), %ecx
sarl $0x4, %ecx
movzwl -0x38(%rbp), %edx
sarl $0x8, %edx
orl %edx, %ecx
andl %ecx, %eax
movw %ax, -0x3a(%rbp)
movzwl -0x3a(%rbp), %eax
movl -0x40(%rbp), %ecx
movl $0x111, %edx            # imm = 0x111
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
jne 0x5809b
jmp 0x580af
jmp 0x5809d
jmp 0x5809f
jmp 0x580a1
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x57e60
jmp 0x580b1
jmp 0x580b3
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x57e1e
jmp 0x580c3
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x57d8c
jmp 0x580d3
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x57d72
jmp 0x58133
movzwl -0x1a(%rbp), %eax
movzwl -0x2a(%rbp), %ecx
cmpl %ecx, %eax
jge 0x580f8
movl $0xffffffff, -0x10(%rbp) # imm = 0xFFFFFFFF
jmp 0x5814c
leaq 0xed27(%rip), %rdi      # 0x66e26
callq 0x4580
movq -0x70(%rbp), %rax
movq (%rax), %rsi
leaq -0x68(%rbp), %rdi
callq 0x4f7f0
leaq -0x68(%rbp), %rdi
callq 0x5660
movq %rax, %rdi
callq 0x4580
leaq -0x68(%rbp), %rdi
callq 0x5870
callq 0x4180
movzwl -0x1a(%rbp), %eax
cmpl $0x0, %eax
jne 0x58145
movl $0x0, -0x10(%rbp)
jmp 0x5814c
movl $0x1, -0x10(%rbp)
movl -0x10(%rbp), %eax
addq $0x70, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)