// File: /workspace/github_cpp_makefile_star2_O2/Alcaro[P]bridges/solver.cpp
// Function: gamemap::solve()
bool solve()
	{
//puts("SOLVEBEGIN");
		possibilities = possibilities_buf;
		
		int num_roots = 0;
		
		//make sure that existing bridges are labeled as such on all tiles they're on
		//'map' is known correct, but anything other than that should use set_state
		
		for (int y=0;y<map.height;y++)
		for (int x=0;x<map.width;x++)
		{
			nextjoined[y*100+x] = y*100+x;
		}
		
		for (int y=0;y<map.height;y++)
		for (int x=0;x<map.width;x++)
		{
			gamemap::island& here = map.map[y][x];
			int index = y*100+x;
			
			if (here.rootnode != index)
			{
				int tmp = nextjoined[here.rootnode];
				nextjoined[here.rootnode] = nextjoined[index];
				nextjoined[index] = tmp;
			}
			
			if (here.rootnode == index && here.population > 0) num_roots++;
			
			uint16_t flags = 0x000F;
			for (int dir=0;dir<4;dir++)
			{
				if (here.bridgelen[dir] != -1) flags |= 0x0110<<dir;
				if (op!=op_another && op!=op_difficulty && here.bridges[dir] == 1) flags &= ~(0x0001<<dir);
				if (op!=op_another && op!=op_difficulty && here.bridges[dir] == 2) flags &= ~(0x0011<<dir);
				if (here.bridges[dir] == 3) { flags &= ~(0x0111<<dir); flags |= 0x1000<<dir; }
			}
			possibilities[index] = flags;
		}
		
		if (map.numislands == 0) return (op!=op_another);
		if (op==op_hint || op==op_difficulty) accumulator=0;
		
		//block 1s and 2s from using both of their bindings towards each other
		if (num_roots > 2) // except if that's the only two islands
		{
			for (int y=0;y<map.height;y++)
			for (int x=0;x<map.width;x++)
			{
				gamemap::island& here = map.map[y][x];
				uint16_t flags = possibilities[y*100+x];
				uint16_t newflags = flags;
				
				//keep the pointless flags&0x1234 checks, here.bridgelen[0] is undefined if the relevant flag isn't set
				//this isn't a pure performance optimization - the isolation rule processor ignores pop-1 islands,
				//  so without this, it could claim the map '1111' is solvable
				if (here.population == 2 && (flags&0x0100) && map.map[y][x+here.bridgelen[0]].population == 2)
					newflags &= ~0x0100;
				if (here.population == 1 && (flags&0x0010) && map.map[y][x+here.bridgelen[0]].population == 1)
					newflags &= ~0x0010;
				
				if (here.population == 2 && (flags&0x0800) && map.map[y+here.bridgelen[3]][x].population == 2)
					newflags &= ~0x0800;
				if (here.population == 1 && (flags&0x0080) && map.map[y+here.bridgelen[3]][x].population == 1)
					newflags &= ~0x0080;
				
				if (flags != newflags)
				{
//printf("%.3i(%.3i) %.4X->%.4X\n",y*100+x,here.population,flags,newflags);
					if (!set_state(y*100+x, newflags)) return false;
				}
			}
		}
		
		for (int y=0;y<map.height;y++)
		for (int x=0;x<map.width;x++)
		{
			if (map.map[y][x].rootnode != y*100+x) continue; // only poke the roots, no point doing duplicate checks
			if (!fill_simple(y*100+x)) return false;
		}
		
		if (op==op_hint && accumulator) return false;
		
		if (op == op_hint || op == op_difficulty)
		{
			int maxdepth = 1;
		again: ;
			int ret = solve_rec(0, maxdepth);
			if (ret == 0) return false;
			if (ret == -1) { maxdepth++; goto again; }
			maxdepth--; // needs at least depth 1, or it won't notice that it's finished. this should not contribute to difficulty
			add_difficulty(100*maxdepth*maxdepth);
#ifndef STDOUT_ERROR
if(maxdepth>=2)puts("#######"),puts(map.serialize()),puts("#######");
#endif
		}
		else
		{
			if (solve_rec(0, 0) <= 0) return false;
		}
		
		if (op==op_hint || op==op_difficulty) return false; // return value for these operations is irrelevant
		
		assign();
		return true;
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8378, %rsp          # imm = 0xC8378
leaq 0x4e70(%rsp), %rax
movq %rdi, -0x4e30(%rax)
movq %rax, -0x8(%rax)
movl (%rdi), %edx
movl 0x4(%rdi), %ecx
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %r9d
movl %ecx, 0x14(%rsp)
cmovgl %ecx, %r9d
testl %edx, %edx
cmovlel %eax, %edx
xorl %ecx, %ecx
movq %rdx, %rsi
movq %rax, %r8
cmpq %r9, %rcx
je 0x1fcd3
subq $0x1, %rsi
jb 0x1fcca
movw %r8w, 0x48(%rsp,%r8,2)
incq %r8
jmp 0x1fcb9
incq %rcx
addq $0x64, %rax
jmp 0x1fcae
leaq 0xc(%rdi), %rax
movq %rax, 0x20(%rsp)
movq %rdi, 0x18(%rsp)
leaq 0x14(%rdi), %rcx
xorl %r10d, %r10d
pushq $-0x2
popq %rax
movl $0xffff, %ebx           # imm = 0xFFFF
pushq $0x11
popq %r14
xorl %esi, %esi
xorl %ebp, %ebp
movq %r9, 0x28(%rsp)
cmpq %r9, %rsi
je 0x1fe09
imulq $0x64, %rsi, %r12
movq %rsi, 0x8(%rsp)
imulq $0x4b0, %rsi, %r13      # imm = 0x4B0
addq 0x20(%rsp), %r13
movq %rcx, (%rsp)
movq %rcx, %r9
xorl %r8d, %r8d
cmpq %rdx, %r8
je 0x1fdec
imulq $0xc, %r8, %rcx
leaq (%r8,%r12), %rdi
movswq 0x2(%rcx,%r13), %rsi
movl %esi, %r11d
cmpq %r11, %rdi
jne 0x1fd54
addq %r13, %rcx
xorl %esi, %esi
cmpb $0x0, (%rcx)
setg %sil
addl %esi, %ebp
jmp 0x1fd6a
movzwl 0x48(%rsp,%rsi,2), %ecx
movzwl 0x48(%rsp,%rdi,2), %r11d
movw %r11w, 0x48(%rsp,%rsi,2)
movw %cx, 0x48(%rsp,%rdi,2)
movw $0xf, %si
xorl %ecx, %ecx
cmpq $0x4, %rcx
je 0x1fdd8
movl $0x110, %r11d           # imm = 0x110
shll %cl, %r11d
cmpb $-0x1, -0x4(%r9,%rcx)
cmovel %r10d, %r11d
orl %r11d, %esi
movl %eax, %r11d
roll %cl, %r11d
movb (%r9,%rcx), %r15b
cmpb $0x1, %r15b
cmovnel %ebx, %r11d
andl %esi, %r11d
movl %r14d, %esi
shll %cl, %esi
cmpb $0x2, %r15b
notl %esi
cmovnel %ebx, %esi
cmpb $0x3, %r15b
jne 0x1fdcd
movl $0x111, %esi            # imm = 0x111
shll %cl, %esi
notl %esi
andl %esi, %r11d
movl $0x1000, %esi           # imm = 0x1000
shll %cl, %esi
orl %r11d, %esi
jmp 0x1fdd3
andl %esi, %r11d
movl %r11d, %esi
incq %rcx
jmp 0x1fd70
movw %si, 0x4e70(%rsp,%rdi,2)
incq %r8
addq $0xc, %r9
jmp 0x1fd25
movq 0x8(%rsp), %rsi
incq %rsi
movq (%rsp), %rcx
addq $0x4b0, %rcx            # imm = 0x4B0
movq 0x28(%rsp), %r9
jmp 0x1fcfd
movb $0x1, %al
movq 0x18(%rsp), %r10
cmpl $0x0, 0x8(%r10)
je 0x2011e
cmpl $0x3, %ebp
jl 0x1ffb3
xorl %r15d, %r15d
xorl %r13d, %r13d
xorl %ebp, %ebp
movq %r10, %rcx
xorl %r12d, %r12d
movl 0x14(%rsp), %eax
cltq
cmpq %rax, %r12
jge 0x1ffb0
pushq $0xc
popq %rbx
xorl %r14d, %r14d
movslq (%rcx), %rax
cmpq %rax, %r14
jge 0x1ff93
leaq 0xc(%rcx), %r8
leaq (%rcx,%r15), %rsi
movq 0x4e68(%rsp), %rax
addq %r13, %rax
movzwl (%rax,%r14,2), %eax
movb (%rbx,%rsi), %dil
movl %eax, %edx
cmpb $0x2, %dil
jne 0x1feb1
movl %eax, %r9d
movl %eax, %edx
andl $0x100, %r9d            # imm = 0x100
je 0x1feb1
movsbl 0x4(%rbx,%rsi), %edx
addl %r14d, %edx
movslq %edx, %rdx
imulq $0x4b0, %r12, %r9       # imm = 0x4B0
addq %r8, %r9
imulq $0xc, %rdx, %rdx
cmpb $0x2, (%rdx,%r9)
je 0x1fea9
movl %eax, %edx
jmp 0x1feb1
movl %eax, %edx
andl $0xfffffeff, %edx       # imm = 0xFFFFFEFF
cmpb $0x1, %dil
jne 0x1ff26
movl %eax, %r9d
andl $0x10, %r9d
je 0x1ff26
movsbl 0x4(%rbx,%rsi), %r9d
addl %r14d, %r9d
movslq %r9d, %r9
movq %r10, %r11
imulq $0x4b0, %r12, %r10      # imm = 0x4B0
addq %r10, %r8
imulq $0xc, %r9, %r9
movl %edx, %r10d
andl $-0x11, %r10d
cmpb $0x1, (%r9,%r8)
cmovnel %edx, %r10d
movl %r10d, %edx
movq %r11, %r10
cmpb $0x1, %dil
jne 0x1ff5e
movl %eax, %edi
andl $0x80, %edi
je 0x1ff5e
movsbl 0x7(%rbx,%rsi), %esi
addl %r12d, %esi
movslq %esi, %rsi
imulq $0x4b0, %rsi, %rsi      # imm = 0x4B0
addq %rsi, %rcx
movl %edx, %esi
andl $0xffffff7f, %esi       # imm = 0xFFFFFF7F
cmpb $0x1, (%rbx,%rcx)
jmp 0x1ff59
cmpb $0x2, %dil
jne 0x1fef3
movl %eax, %r8d
andl $0x800, %r8d            # imm = 0x800
je 0x1fef3
movsbl 0x7(%rbx,%rsi), %esi
addl %r12d, %esi
movslq %esi, %rsi
imulq $0x4b0, %rsi, %rsi      # imm = 0x4B0
addq %rsi, %rcx
movl %edx, %esi
andl $0xfffff7ff, %esi       # imm = 0xFFFFF7FF
cmpb $0x2, (%rbx,%rcx)
cmovnel %edx, %esi
movl %esi, %edx
cmpw %dx, %ax
je 0x1ff84
leal (%r14,%rbp), %eax
movzwl %ax, %esi
movzwl %dx, %edx
leaq 0x40(%rsp), %rdi
callq 0x20bf2
testb %al, %al
je 0x2011c
movq 0x40(%rsp), %r10
incq %r14
addq $0xc, %rbx
movq %r10, %rcx
jmp 0x1fe47
incq %r12
movl 0x4(%rcx), %eax
addq $0x64, %rbp
addq $0xc8, %r13
addq $0x4b0, %r15            # imm = 0x4B0
jmp 0x1fe36
movq %rcx, %r10
pushq $0xe
popq %r13
xorl %r15d, %r15d
leaq 0x40(%rsp), %r14
xorl %r12d, %r12d
movslq 0x4(%r10), %rax
cmpq %rax, %r12
jge 0x20020
movq %r13, (%rsp)
movq %r15, %rbp
xorl %ebx, %ebx
movslq (%r10), %rax
cmpq %rax, %rbx
jge 0x2000c
movswq (%r10,%r13), %rax
movl %eax, %eax
cmpq %rax, %rbp
jne 0x20000
movzwl %bp, %esi
movq %r14, %rdi
callq 0x20dce
testb %al, %al
je 0x2011c
movq 0x40(%rsp), %r10
incq %rbx
incq %rbp
addq $0xc, %r13
jmp 0x1ffd4
incq %r12
addq $0x64, %r15
movq (%rsp), %r13
addq $0x4b0, %r13            # imm = 0x4B0
jmp 0x1ffc2
leaq 0x40(%rsp), %rdi
xorl %esi, %esi
callq 0x21192
testl %eax, %eax
jle 0x2011c
movq 0x40(%rsp), %rdi
xorl %r14d, %r14d
pushq $0x3
popq %rbp
movslq 0x4(%rdi), %rax
cmpq %rax, %r14
jge 0x20130
imulq $0xc8, %r14, %rax
movq %rax, 0x8(%rsp)
imulq $0x4b0, %r14, %r12      # imm = 0x4B0
xorl %r15d, %r15d
movslq (%rdi), %rax
cmpq %rax, %r15
jge 0x20114
leaq (%r15,%r15), %rax
addq 0x4e68(%rsp), %rax
movq 0x8(%rsp), %rcx
movzwl (%rcx,%rax), %ecx
movl %ecx, %eax
notl %eax
andl $0x1, %eax
xorl %ebx, %ebx
testb $0x11, %cl
sete %bl
movl %ecx, (%rsp)
andl $0x111, %ecx            # imm = 0x111
cmpl $0x1, %ecx
adcw %ax, %bx
imulq $0xc, %r15, %r13
leaq (%rdi,%r12), %rax
movzbl 0x14(%r13,%rax), %eax
cmpw %ax, %bx
je 0x200c8
movl %r15d, %esi
movl %r14d, %edx
xorl %ecx, %ecx
callq 0x1d49c
movq 0x40(%rsp), %rdi
jmp 0x200a5
xorl %eax, %eax
movl (%rsp), %edx
testb $-0x78, %dl
sete %al
movl %edx, %ecx
andl $0x888, %ecx            # imm = 0x888
xorl %ebx, %ebx
testb $0x8, %dl
sete %bl
cmpl $0x1, %ecx
adcw %ax, %bx
leaq (%rdi,%r12), %rax
movzbl 0x17(%r13,%rax), %eax
cmpw %ax, %bx
je 0x2010c
movl %r15d, %esi
movl %r14d, %edx
movl %ebp, %ecx
callq 0x1d49c
movq 0x40(%rsp), %rdi
jmp 0x200e9
incq %r15
jmp 0x20062
incq %r14
jmp 0x2003f
xorl %eax, %eax
addq $0xc8378, %rsp          # imm = 0xC8378
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x1d664
testb %al, %al
movb $0x1, %al
jne 0x2011e
leaq 0xbc9a(%rip), %rdi      # 0x2bddc
callq 0x3590
movq 0x40(%rsp), %rsi
leaq 0x30(%rsp), %rbx
movq %rbx, %rdi
callq 0x1d85a
cmpb $0x0, 0xf(%rbx)
movq %rbx, %rdi
jns 0x20167
movq 0x30(%rsp), %rdi
callq 0x3590
movq %rbx, %rdi
callq 0x23ab8
callq 0x3180
nop