

separate( asudx )

-- returns 1st bad Xcycle
procedure badXcycle(
	xcycle: in out xcycletype;
	ca, cz: out ocoords;
	odig : out i9;
	found: out boolean ) is

-- a bad Xcycle has an odd # cells
-- where the first & last are in same house

-- odd links are weak:		dig@A => not dig@B
-- even links are strong:	not dig@A => dig@B
--
-- ca is ON so look for a weak link to cb
-- using any cell in same house with digit=d;
--
-- then cb is OFF so look for a strong link to cc
-- using 3 predefined arrays: rowPair, colPair, boxPair:
-- rowPair(d,c1)=c2, colPair(d,r1)=r2,
-- and boxPair(d, bn, i1) = i2


	npairs: integer := 0; --track length of xCycle
--------------------------------------------------------------------------


--ftn "match"...
--input: coords of 2 cells
--output: 
--		0=>no visibility
--		1=>visibility (same house)
function match( cell1, cell2: ocoords ) return integer is
	r1,c1, r2,c2,
	br1,bc1,b1, br2,bc2,b2: integer;
	fdiag1, fdiag2, bdiag1, bdiag2 : boolean := false;
begin
	r1:=cell1(1); c1:=cell1(2);
	r2:=cell2(1); c2:=cell2(2);

	fdiag1 := (cell1(1)=cell1(2));
	fdiag2 := (cell2(1)=cell2(2));

	bdiag1 := (cell1(1)=10-cell1(2));
	bdiag2 := (cell2(1)=10-cell2(2));

	br1:= (r1-1)/3;		--0..2	zero-based box row
	bc1:= (c1-1)/3; 		--0..2	zero-based box col
	b1 := br1*3 + bc1;	--0..8	lexicographic box number

	br2:= (r2-1)/3;		--0..2
	bc2:= (c2-1)/3;		--0..2
	b2 := br2*3 + bc2;	--0..8

--  rowmatch  colmatch  boxmatch diagmatch

	if r1=r2 then -- rowmatch
		return 1;
	elsif c1=c2 then -- colmatch
		return 1;
	elsif b1=b2 then -- boxmatch
		return 1;
	elsif fdiag1 and fdiag2 then -- fdiag match
		return 1;
	elsif bdiag1 and bdiag2 then -- bdiag match
		return 1;
	else
		return 0;
	end if;

end match;





-- if any, find cs: 1st house pair of cw (OTHER than ca)
-- Note: this version looks only for inconsistent loops so AVOIDS c0!
procedure strongsearch(
	idg: in i9; 
	c0, ca, cw: in ocoords; 
	cs: out ocoords; 
	ssfound: out boolean) is

	boxnum,
	br,bc,cellw, rx,cx,cellx, cc,cr : integer;
	ok, ok2: boolean;
begin

--need ca to avoid using it again...

	ssfound:=false;


	--search fdiag house
if cw(1)=cw(2) then -- cw is on fdiag so search this house
	for diag in 1..9 loop
	ok := ca(1)/=diag or ca(2)/=diag; --avoid ca
	ok2:= c0(1)/=diag or c0(2)/=diag; --avoid c0
	if not ssfound and ok and ok2
	and diag/=cw(1) --avoid cw
	and fdPair(idg,cw(1))=diag 
	and fdPair(idg,diag)=cw(1)
	then
		ssfound:=true;
		cs(1):=diag;
		cs(2):=diag;
	end if;
	end loop; --diag
end if; --cw on fdiag



	--search bdiag
if cw(1)=10-cw(2) then -- cw on bdiag so search this house
	for diag in 1..9 loop
	ok := ca(1)/=diag or ca(2)/=10-diag; --avoid ca
	ok2:= c0(1)/=diag or c0(2)/=10-diag; --avoid c0
	if not ssfound and ok and ok2
	and diag/=cw(1) --avoid cw
	and bdPair(idg,cw(1))=diag 
	and bdPair(idg,diag)=cw(1)
	then
		ssfound:=true;
		cs(1):=diag;
		cs(2):=10-diag;
	end if;
	end loop; --diag
end if; --cw on bdiag




	--search row of cw [cw(1)]
	for c in 1..9 loop
	ok := ca(1)/=cw(1) or ca(2)/=c; --avoid ca
	ok2:= c0(1)/=cw(1) or c0(2)/=c; --avoid c0
	if not ssfound and ok and ok2 and c/=cw(2) --avoid cw
	and rowPair(idg,cw(1),cw(2))=c 
	and rowPair(idg,cw(1),c)=cw(2)
	then
		ssfound:=true;
		cs(1):=cw(1);
		cs(2):=c;
	end if;
	end loop; --c



	--search col of cw [cw(2)]
	for r in 1..9 loop
	ok := ca(1)/=r or ca(2)/=cw(2); --avoid ca 21
	ok2:= c0(1)/=r or c0(2)/=cw(2); --avoid c0
	if not ssfound and ok and ok2 and r/=cw(1) --avoid cw 26
	and colPair(idg,cw(2),cw(1))=r 
	and colPair(idg,cw(2),r)=cw(1)
	then --56=bad (r=5)
		ssfound:=true;
		cs(1):=r;
		cs(2):=cw(2);
	end if;
	end loop; --r



	--search box of cw
	br:= ( cw(1) - 1 ) / 3; -- 0..2 = box-row of cw 1
	bc:= ( cw(2) - 1 ) / 3; -- 0..2 = box-col of cw 1
	boxnum:=br*3+bc+1; -- 1..9: lexicographic box#  6

	cr:=(cw(1)-1)-br*3;--0..2: zero-based row within box of cw
	cc:=(cw(2)-1)-bc*3;--0..2: 0-based col w/in box of cw
	cellw:=cr*3+cc+1; --1..9: lexicographic pos of cw within box

	for r in 0..2 loop
	for c in 0..2 loop
	rx:=br*3+r+1; -- 1..9: row of cx
	cx:=bc*3+c+1; -- 1..9: col of cx
	cellx:=r*3+c+1; -- 1..9 = pos within box of cx
	ok := ca(1)/=rx or ca(2)/=cx; --avoid ca
	ok2:= c0(1)/=rx or c0(2)/=cx; --avoid c0
	if not ssfound and ok and ok2
	and (rx/=cw(1) or cx/=cw(2)) --avoid cw
	and boxPair(idg,boxnum,cellw)=cellx 
	and boxPair(idg,boxnum,cellx)=cellw 
	then
		ssfound:=true;
		cs(1):=rx;
		cs(2):=cx;
	end if;
	end loop; --c
	end loop; --r



end strongsearch;



procedure addlinks(ca, cw, cs: ocoords) is
begin
	
	npairs:=npairs+1;

	xcycle( ca(1), ca(2) ) := cw;
	xcycle( cw(1), cw(2) ) := cs;

	--xoncycle( ca(1), ca(2) ) := true;
	--xoncycle( cw(1), cw(2) ) := false;

end addlinks;


--recursive proc
procedure nextChainPair( 
	idig: in i9;
	c0,					--root cell ON
	ca: in ocoords; 	--this cell ON
	cz: out ocoords; 	--final cell ON and same house as c0 =><=
	victor: out boolean) is

	cw, cs: ocoords; -- Weak, Strong

	notseen, ok2,
	sfound: boolean:=false;
	boxnum: i9;

	br0,bc0,cellrow,cellcol,
	rx,cx,cellx,
	bra,bca,cella: integer;
begin
	victor:=false;

	--We assume ca has idig:ON

	--Note that xcycle(r,c)(1)=0 is a test to avoid revisiting same cell


	--weakFdiagSearch
if ca(1)=ca(2) then		--ca on Fdiag
	for d in 1..9 loop	--try dd
	notseen := xcycle(d,d)(1)=0;
	if not victor and d/=ca(1) and notseen then
		ok2 := fdPair(idig,ca(1))/=d; --(d,d)=cw is NOT a FDpair with ca
		if ok2 and candidate(d,d)(idig) then
			cw(1):=d;
			cw(2):=d; --idig: OFF
			strongsearch(idig,c0,ca,cw,cs,sfound); --find any house pair of cw
			if sfound then
				addlinks(ca,cw,cs); --cs idig: ON
				if match(c0,cs)=1 then --done
					victor:=true;
					cz:=cs;
					odig:=idig;
				else --recurse
					nextChainPair(idig,c0,cs,cz,victor);
				end if; --done
			end if; --sfound
		end if; --candid
	end if; --not found
	end loop; --d
end if; --ca on fdiag


------------------------------------------------------------

	--weakBdiagSearch
if ca(1)=10-ca(2) then	--ca on Bdiag
	for d in 1..9 loop	--try (d,10-d)
	notseen := xcycle(d,10-d)(1)=0;
	if not victor and d/=ca(1) and notseen then
		ok2 := bdPair(idig,ca(1))/=d;	--(d,10-d)=cw is NOT a BDpair with ca
		if ok2 and candidate(d,10-d)(idig) then
			cw(1):=d;
			cw(2):=10-d; --idig OFF @ cw
			strongsearch(idig,c0,ca,cw,cs,sfound); --find any house pair of cw
			if sfound then
				addlinks(ca,cw,cs); --cs idig ON
				if match(c0,cs)=1 then --done
					victor:=true;
					cz:=cs;
					odig:=idig;
				else --recurse
					nextChainPair(idig,c0,cs,cz,victor);
				end if; --done
			end if; --sfound
		end if; --candid
	end if; --not found
	end loop; --d
end if; --ca on Bdiag


------------------------------------------------------------

	--weakrowsearch...simply find one:
	for c in 1..9 loop --try each col in same row as ca
	notseen := xcycle( ca(1), c )(1)=0;
	if not victor and c/=ca(2) and notseen then
		ok2 := rowPair(idig,ca(1),ca(2)) /= c; --ca is NOT a rowpair with cw
		if ok2 and candidate( ca(1), c )(idig) then
			cw(1):=ca(1);
			cw(2):=c; --idig OFF...weaklink found in same row
			strongsearch(idig,c0,ca,cw,cs,sfound); --find any house pair of cw
			if sfound then
				addlinks(ca,cw,cs); --cs ON
				if match(c0, cs)=1 then --done
					victor:=true;
					cz:=cs;
					odig:=idig;
				else --recurse
					nextChainPair(idig,c0,cs,cz,victor);
				end if; --done
			end if; --sfound
		end if;
	end if;
	end loop; --c


------------------------------------------------------------

	--weakcolsearch...simply find one
	for r in 1..9 loop --try each row in same col as ca
	notseen := xcycle(r,ca(2))(1)=0; --cw not yet visited in this chain
	if not victor and r/=ca(1) and notseen then
		ok2 := colPair(idig,ca(2),ca(1)) /= r; --ca is NOT a colpair of cw
		if ok2 and candidate( r, ca(2))(idig) then
			cw(1):=r;
			cw(2):=ca(2); --idig OFF weaklink found in same col
			strongsearch(idig,c0,ca,cw,cs,sfound); --find cs: a house pair of cw
			if sfound then
				addlinks(ca,cw,cs); --cs ON
				if match(c0, cs)=1 then --done
					victor:=true;
					cz:=cs;
					odig:=idig;
				else --recurse
					nextChainPair(idig,c0,cs,cz,victor);
				end if; --done
			end if; --sfound
		end if; --candidate
	end if;
	end loop; --c


------------------------------------------------------------


	--weakboxsearch...simply find one
	bra:= ( ca(1) - 1 ) / 3; --0..2
	bca:= ( ca(2) - 1 ) / 3; --0..2
	boxnum := bra*3+bca+1; --1..9	

	br0:=bra*3+1; --1..7: row of box UL cell
	bc0:=bca*3+1; --1..7: col of box UL cell
	cellrow:=ca(1)-br0; --0..2: row of ca within its box
	cellcol:=ca(2)-bc0; --0..2: col of ca within its box
	cella := cellrow*3+cellcol+1; --1..9: lexicographic cell# of ca within its box

	for r in 0..2 loop
	for c in 0..2 loop
	rx:=bra*3+r+1; --1..9 true row# of cw
	cx:=bca*3+c+1; --1..9 true col# of cw
	cellx:=r*3+c+1; --1..9 lexi cell# of cw withiin box of ca
	notseen:=xcycle(rx,cx)(1)=0; --cw not yet visited in this chain
	if not victor and cellx/=cella and notseen then
		ok2 := boxPair(idig, boxnum, cellx) /= cella; --cw is NOT a boxpair of ca
		if ok2 and candidate(rx,cx)(idig) then
			cw(1):=rx;
			cw(2):=cx; --idig OFF weaklink found in same box
			strongsearch(idig,c0,ca,cw,cs,sfound); --find cs: a house pair of cw
			if sfound then
				addlinks(ca,cw,cs); -- cs ON
				if match(c0, cs)=1 then --done
					victor:=true;
					cz:=cs;
					odig:=idig;
				else --recurse
					nextChainPair(idig,c0,cs,cz,victor);
				end if; --done
			end if; --found
		end if; --candidate
	end if;
	end loop; --c
	end loop; --r


end nextChainPair;
--------------------------------------------------------------------------

	victory : boolean := false;
	xxon, xxoff : ocoords;

begin --findXcycle: 1st only

	found:=false;

	for r in 1..9 loop
	for c in 1..9 loop	--for each cell
	for d in 1..9 loop	--for each digit

	if not victory and candidate(r,c)(d) then
		xcycle:=(others=>(others=>(others=>0)));
		ca(1):=r; ca(2):=c;
		npairs:=0;

		--we assume ca is ON


		-- recursive proc:
		nextChainPair( d, ca, ca, cz, victory );

------------------------------------begin insert-----------------------------
		if victory then

	new_line;
	put(" dig="&i2st(d)); 
	new_line;

			--now runthru finalized linkages 
			--to set xoncycle, xoffcycle arrays properly
			xoncycle:=(others=>(others=>false));
			xoffcycle:=(others=>(others=>false));
			xxon:=ca;
			xxoff:=xcycle(xxon(1),xxon(2));
		npairs:=0;
			loop

				xoncycle(xxon(1),xxon(2)):=true;
				xoffcycle(xxoff(1),xxoff(2)):=true;
				npairs:=npairs+1;

	--Always show this:
	put(" On:"&i2st( xxon(1) )&i2st( xxon(2) ));
	put(",");
	put(" Off:"&i2st( xxoff(1) )&i2st( xxoff(2) ));
	new_line;

				--update xxon
				xxon:=xcycle(xxoff(1),xxoff(2));
				exit when xxon=cz; --signals EndOfChain
				xxoff:=xcycle(xxon(1),xxon(2));

			end loop;

		end if; --victory
------------------------------------end insert-----------------------------



		if npairs>0 and  victory then
			put(" On:"&i2st(cz(1))&i2st(cz(2)));
			new_line;
		end if;

	end if; --candidate(r,c)(d)
	end loop; --d
	end loop; --c
	end loop; --r

	found:=victory;


end badXcycle;

