// File: Alcaro[P]bridges/solver.cpp
// Function: (anonymous namespace)::solver<((anonymous namespace)::op_t)3>::do_isolation_rule()
bool do_isolation_rule()
	{
		//use the isolation rule
	link_again_top: ;
		link.init(map, possibilities);
//puts("BEGIN");
		for (int y=0;y<map.height;y++)
		for (int x=0;x<map.width;x++)
		{
			uint16_t index = y*100+x;
			gamemap::island& here = map.map[y][x];
			
			uint16_t flags = possibilities[index];
			if (here.population>0 && !(flags & 0x0001) && link.can_join(index, 0))
			{
				if (!link.join(index, index+here.bridgelen[0])) return false;
			}
			if (here.population>0 && !(flags & 0x0008) && link.can_join(index, 3))
			{
				if (!link.join(index, index+here.bridgelen[3]*100)) return false;
			}
//if(x==0&&y!=0)puts("");printf("%.4X ",flags);
		}
//puts("");
		
		bool link_did_any = false;
		
		if (map.has_castles)
		{
			//if map has castles, enforce that they don't touch each other
			for (int y=0;y<map.height;y++)
			for (int x=0;x<map.width;x++)
			{
				uint16_t index = y*100+x;
				gamemap::island& here = map.map[y][x];
				if (here.population < 0) continue;
				
				uint16_t flags = possibilities[index];
				uint16_t newflags = flags;
				//test all four links, to ensure the offending bridge is always caught
				for (int dir=0;dir<4;dir++)
				{
					if (!(flags & (0x0110<<dir))) continue;
					
					static const int16_t offsets[4] = { 1, -100, -1, 100 };
					uint16_t other = index + offsets[dir]*here.bridgelen[dir];
					
					uint16_t mycolor = link.color(index);
					uint16_t othercolor = link.color(other);
					
					if (mycolor != othercolor && mycolor >= 80 && othercolor >= 80)
					{
						newflags &= ~(0x0110<<dir);
					}
				}
				if (newflags != flags)
				{
					if (!set_state(index, newflags)) return false;
					link_did_any = true;
				}
//if(x==0&&y!=0)puts("");printf("%.4X ",flags);
			}
			if (link_did_any) goto link_again_top; // to ensure it doesn't try to create the bridges we just removed
			
			//then create fake links between the castles, so the solver won't say
			// 'okay, only one path, it must exist' when reaching another castle
			
			uint16_t prevcastle = -1;
			for (int castletype=1;castletype<=4;castletype++)
			{
				if (map.an_island[castletype] == -1) continue;
				
				uint16_t newcastle = map.an_island[castletype];
				if (prevcastle != (uint16_t)-1)
					link.join(prevcastle, newcastle);
				prevcastle = newcastle;
			}
		}
		
		
//puts("HELLO");
		if (link.count() != 0)
		{
	link_again: ;
			uint16_t index1 = link.any();
			uint16_t index2 = index1;
			uint16_t index1p = -1;
			uint16_t index2p = -1;
			
			//TODO: this can go 1,2,3,4,5,3,2 and consider 2 part of the loop,
			// rather than enforcing the existence of that bridge
			
			do
			{
				uint16_t next;
				
//printf("1:%.3i(...),%.3i(...),...\n",index1,index1p);
//printf("1:%.3i(%.3i),%.3i(%.3i),...\n",
//index1,link.root(index1),
//index1p,(index1p==65535)?-1:link.root(index1p));
				next = link.query(index1, index1p);
//printf("1:%.3i(%.3i),%.3i(%.3i),%.3i(%.3i)\n",
//index1,link.root(index1),
//index1p,(index1p==65535)?-1:link.root(index1p),
//next,(next==65535)?-1:link.root(next));
				index1p = index1;
				index1 = next;
				if (next == (uint16_t)-1) goto link_done; // only a single island left? then we're done here, try the other castles
				
				next = link.query(index2, index2p);
//printf("2:%.3i(%.3i),%.3i(%.3i),%.3i(%.3i)\n",
//index2,link.root(index2),
//index2p,(index2p==65535)?-1:link.root(index2p),
//next,(next==65535)?-1:link.root(next));
				if (next != (uint16_t)-1)
				{
					index2p = index2;
					index2 = next;
					
					next = link.query(index2, index2p);
//printf("3:%.3i(%.3i),%.3i(%.3i),%.3i(%.3i)\n",
//index2,link.root(index2),
//index2p,(index2p==65535)?-1:link.root(index2p),
//next,(next==65535)?-1:link.root(next));
				}
				if (next != (uint16_t)-1)
				{
					index2p = index2;
					index2 = next;
				}
				
				if (next == (uint16_t)-1)
				{
					//if (map.get(index2).population < 80 && map.get(index2p).population < 80)
					{
						uint16_t topleft;
						bool down;
						link.lookback(map, index2, index2p, topleft, down);
//printf("FORCEJOIN=%.3i(%.3i) - join %.3i dir %i\n", index2, index2p, topleft, down*3);
						if (possibilities[topleft] & (down ? 0x0008 : 0x0001))
						{
							add_difficulty(10);
//puts("A");
							if (!set_state(topleft, possibilities[topleft] & ~(down ? 0x0008 : 0x0001))) return false;
//puts("A+");
							link_did_any = true;
						}
					}
//else printf("FORCEJOINCASTLE=%.3i,%.3i\n",index2,index2p);
					link.join(index2, index2p);
					goto link_again;
				}
			} while (index1 != index2);
			
//printf("LOOP=%.3i\n",index1);
			int numvisited = 0;
			do {
				map.towalk[numvisited++] = index1;
				
				uint16_t next = link.query(index1, index1p);
//printf("LOOPWALK:%.3i(%.3i),%.3i(%.3i),%.3i(%.3i)\n",
//index1,link.root(index1),
//index1p,(index1p==65535)?-1:link.root(index1p),
//next,(next==65535)?-1:link.root(next));
				index1p = index1;
				index1 = next;
			} while (index1 != index2);
			
			for (int i=1;i<numvisited;i++)
			{
//printf("JOINLOOP:%.3i,%.3i\n",index1,map.towalk[i]);
				link.join(index1, map.towalk[i]);
			}
			goto link_again;
		}
		link_done:
		// if a set_state from a forced join helped, perhaps that set_state blocked some other bridges,
		// so let's check if we can prove anything new
		if (link_did_any) goto link_again_top;
		
		
		if (link.count() != 0)
		{
			//iterate everything joined with a_linkable_island; if not equal to n_linkable_islands, it's disjoint, so return false
			uint16_t n_linked_islands = 0;
			
			uint16_t index = link.any();
			uint16_t indexstart = index;
			do {
//printf("LINK::%.3i\n",index);
				n_linked_islands++;
				index = link.iter(index);
			} while (index != indexstart);
			
//printf("LINKS=%i,%i\n",n_linked_islands,link.count());
			if (n_linked_islands != link.count()) return false;
		}
		
		return true;
	}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
movq %rax, %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
movq (%rax), %rsi
movq 0x4e28(%rax), %rdx
callq 0x56c00
movl $0x0, -0x1c(%rbp)
movq -0x88(%rbp), %rcx
movl -0x1c(%rbp), %eax
movq (%rcx), %rcx
cmpl 0x4(%rcx), %eax
jge 0x5a054
movl $0x0, -0x20(%rbp)
movq -0x88(%rbp), %rcx
movl -0x20(%rbp), %eax
movq (%rcx), %rcx
cmpl (%rcx), %eax
jge 0x5a044
movq -0x88(%rbp), %rax
imull $0x64, -0x1c(%rbp), %ecx
addl -0x20(%rbp), %ecx
movw %cx, -0x22(%rbp)
movq (%rax), %rcx
addq $0xc, %rcx
movslq -0x1c(%rbp), %rdx
imulq $0x4b0, %rdx, %rdx      # imm = 0x4B0
addq %rdx, %rcx
movslq -0x20(%rbp), %rdx
imulq $0xc, %rdx, %rdx
addq %rdx, %rcx
movq %rcx, -0x30(%rbp)
movq 0x4e28(%rax), %rax
movzwl -0x22(%rbp), %ecx
movw (%rax,%rcx,2), %ax
movw %ax, -0x32(%rbp)
movq -0x30(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
jle 0x59fbd
movzwl -0x32(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x59fbd
movq -0x88(%rbp), %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
xorl %edx, %edx
movzwl -0x22(%rbp), %esi
callq 0x56f30
testb $0x1, %al
jne 0x59f83
jmp 0x59fbd
movq -0x88(%rbp), %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
movw -0x22(%rbp), %cx
movzwl -0x22(%rbp), %eax
movq -0x30(%rbp), %rdx
movsbl 0x4(%rdx), %edx
addl %edx, %eax
movzwl %cx, %esi
movzwl %ax, %edx
callq 0x56f70
testb $0x1, %al
jne 0x59fbb
movb $0x0, -0xd(%rbp)
jmp 0x5a64d
jmp 0x59fbd
movq -0x30(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
jle 0x5a034
movzwl -0x32(%rbp), %eax
andl $0x8, %eax
cmpl $0x0, %eax
jne 0x5a034
movq -0x88(%rbp), %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
movl $0x3, %edx
movzwl -0x22(%rbp), %esi
callq 0x56f30
testb $0x1, %al
jne 0x59ff7
jmp 0x5a034
movq -0x88(%rbp), %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
movw -0x22(%rbp), %cx
movzwl -0x22(%rbp), %eax
movq -0x30(%rbp), %rdx
movsbl 0x7(%rdx), %edx
imull $0x64, %edx, %edx
addl %edx, %eax
movzwl %cx, %esi
movzwl %ax, %edx
callq 0x56f70
testb $0x1, %al
jne 0x5a032
movb $0x0, -0xd(%rbp)
jmp 0x5a64d
jmp 0x5a034
jmp 0x5a036
movl -0x20(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x59eee
jmp 0x5a046
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x59ed1
movq -0x88(%rbp), %rax
movb $0x0, -0x33(%rbp)
movq (%rax), %rax
testb $0x1, 0x1d4cc(%rax)
je 0x5a2cb
movl $0x0, -0x38(%rbp)
movq -0x88(%rbp), %rcx
movl -0x38(%rbp), %eax
movq (%rcx), %rcx
cmpl 0x4(%rcx), %eax
jge 0x5a238
movl $0x0, -0x3c(%rbp)
movq -0x88(%rbp), %rcx
movl -0x3c(%rbp), %eax
movq (%rcx), %rcx
cmpl (%rcx), %eax
jge 0x5a228
movq -0x88(%rbp), %rax
imull $0x64, -0x38(%rbp), %ecx
addl -0x3c(%rbp), %ecx
movw %cx, -0x3e(%rbp)
movq (%rax), %rax
addq $0xc, %rax
movslq -0x38(%rbp), %rcx
imulq $0x4b0, %rcx, %rcx      # imm = 0x4B0
addq %rcx, %rax
movslq -0x3c(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
jge 0x5a0ef
jmp 0x5a21a
movq -0x88(%rbp), %rax
movq 0x4e28(%rax), %rax
movzwl -0x3e(%rbp), %ecx
movw (%rax,%rcx,2), %ax
movw %ax, -0x4a(%rbp)
movw -0x4a(%rbp), %ax
movw %ax, -0x4c(%rbp)
movl $0x0, -0x50(%rbp)
cmpl $0x4, -0x50(%rbp)
jge 0x5a1e4
movzwl -0x4a(%rbp), %eax
movl -0x50(%rbp), %ecx
movl $0x110, %edx            # imm = 0x110
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
jne 0x5a13e
jmp 0x5a1d6
movq -0x88(%rbp), %rdi
movzwl -0x3e(%rbp), %eax
movslq -0x50(%rbp), %rdx
leaq 0xcd2c(%rip), %rcx      # 0x66e80
movswl (%rcx,%rdx,2), %ecx
movq -0x48(%rbp), %rdx
movslq -0x50(%rbp), %rsi
movsbl 0x4(%rdx,%rsi), %edx
imull %edx, %ecx
addl %ecx, %eax
movw %ax, -0x52(%rbp)
addq $0xa1230, %rdi          # imm = 0xA1230
movzwl -0x3e(%rbp), %esi
callq 0x570d0
movq -0x88(%rbp), %rdi
movw %ax, -0x54(%rbp)
addq $0xa1230, %rdi          # imm = 0xA1230
movzwl -0x52(%rbp), %esi
callq 0x570d0
movw %ax, -0x56(%rbp)
movzwl -0x54(%rbp), %eax
movzwl -0x56(%rbp), %ecx
cmpl %ecx, %eax
je 0x5a1d4
movzwl -0x54(%rbp), %eax
cmpl $0x50, %eax
jl 0x5a1d4
movzwl -0x56(%rbp), %eax
cmpl $0x50, %eax
jl 0x5a1d4
movl -0x50(%rbp), %ecx
movl $0x110, %eax            # imm = 0x110
shll %cl, %eax
movl %eax, %ecx
xorl $-0x1, %ecx
movzwl -0x4c(%rbp), %eax
andl %ecx, %eax
movw %ax, -0x4c(%rbp)
jmp 0x5a1d6
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x5a118
movzwl -0x4c(%rbp), %eax
movzwl -0x4a(%rbp), %ecx
cmpl %ecx, %eax
je 0x5a218
movq -0x88(%rbp), %rdi
movw -0x3e(%rbp), %ax
movzwl %ax, %esi
movzwl -0x4c(%rbp), %edx
callq 0x58e80
testb $0x1, %al
jne 0x5a214
movb $0x0, -0xd(%rbp)
jmp 0x5a64d
movb $0x1, -0x33(%rbp)
jmp 0x5a21a
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x5a093
jmp 0x5a22a
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x5a076
testb $0x1, -0x33(%rbp)
je 0x5a243
jmp 0x59eaa
movw $0xffff, -0x58(%rbp)    # imm = 0xFFFF
movl $0x1, -0x5c(%rbp)
cmpl $0x4, -0x5c(%rbp)
jg 0x5a2c9
movq -0x88(%rbp), %rax
movq (%rax), %rax
movslq -0x5c(%rbp), %rcx
movswl 0x1d4ce(%rax,%rcx,2), %eax
cmpl $-0x1, %eax
jne 0x5a273
jmp 0x5a2be
movq -0x88(%rbp), %rax
movq (%rax), %rax
movslq -0x5c(%rbp), %rcx
movw 0x1d4ce(%rax,%rcx,2), %ax
movw %ax, -0x5e(%rbp)
movzwl -0x58(%rbp), %eax
cmpl $0xffff, %eax           # imm = 0xFFFF
je 0x5a2b6
movq -0x88(%rbp), %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
movw -0x58(%rbp), %ax
movzwl %ax, %esi
movzwl -0x5e(%rbp), %edx
callq 0x56f70
movw -0x5e(%rbp), %ax
movw %ax, -0x58(%rbp)
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x5a250
jmp 0x5a2cb
movq -0x88(%rbp), %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
callq 0x57110
movzwl %ax, %eax
cmpl $0x0, %eax
je 0x5a590
jmp 0x5a2ec
movq -0x88(%rbp), %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
callq 0x57130
movw %ax, -0x60(%rbp)
movw -0x60(%rbp), %ax
movw %ax, -0x62(%rbp)
movw $0xffff, -0x64(%rbp)    # imm = 0xFFFF
movw $0xffff, -0x66(%rbp)    # imm = 0xFFFF
movq -0x88(%rbp), %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
movw -0x60(%rbp), %ax
movzwl %ax, %esi
movzwl -0x64(%rbp), %edx
callq 0x57150
movw %ax, -0x68(%rbp)
movw -0x60(%rbp), %ax
movw %ax, -0x64(%rbp)
movw -0x68(%rbp), %ax
movw %ax, -0x60(%rbp)
movzwl -0x68(%rbp), %eax
cmpl $0xffff, %eax           # imm = 0xFFFF
jne 0x5a359
jmp 0x5a592
movq -0x88(%rbp), %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
movw -0x62(%rbp), %ax
movzwl %ax, %esi
movzwl -0x66(%rbp), %edx
callq 0x57150
movw %ax, -0x68(%rbp)
movzwl -0x68(%rbp), %eax
cmpl $0xffff, %eax           # imm = 0xFFFF
je 0x5a3b8
movq -0x88(%rbp), %rdi
movw -0x62(%rbp), %ax
movw %ax, -0x66(%rbp)
movw -0x68(%rbp), %ax
movw %ax, -0x62(%rbp)
addq $0xa1230, %rdi          # imm = 0xA1230
movw -0x62(%rbp), %ax
movzwl %ax, %esi
movzwl -0x66(%rbp), %edx
callq 0x57150
movw %ax, -0x68(%rbp)
movzwl -0x68(%rbp), %eax
cmpl $0xffff, %eax           # imm = 0xFFFF
je 0x5a3d3
movw -0x62(%rbp), %ax
movw %ax, -0x66(%rbp)
movw -0x68(%rbp), %ax
movw %ax, -0x62(%rbp)
movzwl -0x68(%rbp), %eax
cmpl $0xffff, %eax           # imm = 0xFFFF
jne 0x5a4d1
movq -0x88(%rbp), %rax
movq %rax, %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
movq (%rax), %rsi
movw -0x62(%rbp), %ax
leaq -0x6a(%rbp), %r8
leaq -0x6b(%rbp), %r9
movzwl %ax, %edx
movzwl -0x66(%rbp), %ecx
callq 0x57280
movq -0x88(%rbp), %rax
movq 0x4e28(%rax), %rax
movzwl -0x6a(%rbp), %ecx
movzwl (%rax,%rcx,2), %eax
movb -0x6b(%rbp), %sil
movl $0x1, %ecx
movl $0x8, %edx
testb $0x1, %sil
cmovnel %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x5a4ae
movq -0x88(%rbp), %rdi
movq %rdi, -0x8(%rbp)
movl $0xa, -0xc(%rbp)
movq -0x8(%rbp), %rax
movl -0xc(%rbp), %ecx
addl 0xc8334(%rax), %ecx
movl %ecx, 0xc8334(%rax)
movw -0x6a(%rbp), %cx
movq 0x4e28(%rdi), %rax
movzwl -0x6a(%rbp), %edx
movzwl (%rax,%rdx,2), %eax
movb -0x6b(%rbp), %r8b
movl $0x1, %edx
movl $0x8, %esi
testb $0x1, %r8b
cmovnel %esi, %edx
xorl $-0x1, %edx
andl %edx, %eax
movzwl %cx, %esi
movzwl %ax, %edx
callq 0x58e80
testb $0x1, %al
jne 0x5a4aa
movb $0x0, -0xd(%rbp)
jmp 0x5a64d
movb $0x1, -0x33(%rbp)
movq -0x88(%rbp), %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
movw -0x62(%rbp), %ax
movzwl %ax, %esi
movzwl -0x66(%rbp), %edx
callq 0x56f70
jmp 0x5a2ec
jmp 0x5a4d3
movzwl -0x60(%rbp), %eax
movzwl -0x62(%rbp), %ecx
cmpl %ecx, %eax
jne 0x5a317
movl $0x0, -0x70(%rbp)
movq -0x88(%rbp), %rdi
movw -0x60(%rbp), %dx
movq (%rdi), %rax
movl -0x70(%rbp), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, -0x70(%rbp)
movslq %ecx, %rcx
movw %dx, 0x1fbe8(%rax,%rcx,2)
addq $0xa1230, %rdi          # imm = 0xA1230
movw -0x60(%rbp), %ax
movzwl %ax, %esi
movzwl -0x64(%rbp), %edx
callq 0x57150
movw %ax, -0x72(%rbp)
movw -0x60(%rbp), %ax
movw %ax, -0x64(%rbp)
movw -0x72(%rbp), %ax
movw %ax, -0x60(%rbp)
movzwl -0x60(%rbp), %eax
movzwl -0x62(%rbp), %ecx
cmpl %ecx, %eax
jne 0x5a4ea
movl $0x1, -0x78(%rbp)
movl -0x78(%rbp), %eax
cmpl -0x70(%rbp), %eax
jge 0x5a58b
movq -0x88(%rbp), %rax
movq %rax, %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
movw -0x60(%rbp), %dx
movq (%rax), %rax
movslq -0x78(%rbp), %rcx
movzwl %dx, %esi
movzwl 0x1fbe8(%rax,%rcx,2), %edx
callq 0x56f70
movl -0x78(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x78(%rbp)
jmp 0x5a54c
jmp 0x5a2ec
jmp 0x5a592
testb $0x1, -0x33(%rbp)
je 0x5a59d
jmp 0x59eaa
movq -0x88(%rbp), %rdi
addq $0xa1230, %rdi          # imm = 0xA1230
callq 0x57110
movzwl %ax, %eax
cmpl $0x0, %eax
je 0x5a649
movq -0x88(%rbp), %rdi
movw $0x0, -0x7a(%rbp)
addq $0xa1230, %rdi          # imm = 0xA1230
callq 0x57130
movw %ax, -0x7c(%rbp)
movw -0x7c(%rbp), %ax
movw %ax, -0x7e(%rbp)
movq -0x88(%rbp), %rdi
movw -0x7a(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x7a(%rbp)
addq $0xa1230, %rdi          # imm = 0xA1230
movzwl -0x7c(%rbp), %esi
callq 0x57410
movw %ax, -0x7c(%rbp)
movzwl -0x7c(%rbp), %eax
movzwl -0x7e(%rbp), %ecx
cmpl %ecx, %eax
jne 0x5a5e1
movq -0x88(%rbp), %rdi
movzwl -0x7a(%rbp), %eax
movl %eax, -0x8c(%rbp)
addq $0xa1230, %rdi          # imm = 0xA1230
callq 0x57110
movw %ax, %cx
movl -0x8c(%rbp), %eax
movzwl %cx, %ecx
cmpl %ecx, %eax
je 0x5a647
movb $0x0, -0xd(%rbp)
jmp 0x5a64d
jmp 0x5a649
movb $0x1, -0xd(%rbp)
movb -0xd(%rbp), %al
andb $0x1, %al
addq $0x90, %rsp
popq %rbp
retq
nopl (%rax,%rax)