
separate (adagate)

-- island prologue
--
-- involves a large cubemapped ocean-setting skybox
-- with round body of water and a annular island of sand at center
-- Walking about is done by keeping the eye @ (0,0,0) and moving
-- the sandy island in the opposite direction.  This is done
-- to preserve the proper skybox perspective.  Thus, within
-- this skybox, we maintain 2 distinct view matrices:
-- mviewMatrix [& mmvp] with eyepos @ (0,0,0)
-- iviewMatrix [& imvp] with eyepos @ island-virtual-position
--
function drawisland( 
	dbkgd: integer:= 0; 
	skipFly: boolean := true  -- skipFlyover only false 1st time
	) return integer is

	bkg : integer := 0;
	foglev : glint := 0;
	fogclr : glint := 1;

	use gl;
	use matutils;
	use type interfaces.c.c_float;

	use interfaces.c;
	use interfaces.c.strings;
	use glext;
	use glext.pointers;
	use glext.binding;
	use gl.binding;
	use gl.pointers;





-- to draw sandweeds in order from far to near
procedure ssort( 
	f2n: in out ssortarray; 
	nx,px,nz,pz : slimarray;  
	eyex,eyez : float;  
	avgdist: out float ) is

	n, isave : integer;
	fn, ni,pi,di, nj,pj,dj : float;
begin
	n:=nsrng'last; --nptex
	fn := float(n);

	for i in nsrng loop
		f2n(i):=i; -- initialize permutation
	end loop;
	avgdist:=0.0;

	for i in reverse nsrng loop
		ni := sqr( nx( f2n(i) ) - eyex ) + sqr( nz( f2n(i) ) - eyez );
		pi := sqr( px( f2n(i) ) - eyex ) + sqr( pz( f2n(i) ) - eyez );
		di := min( ni, pi );
		avgdist := avgdist + fmath.sqrt(di)/fn;

		for j in 1..i loop

			ni := sqr( nx( f2n(i) ) - eyex ) + sqr( nz( f2n(i) ) - eyez );
			pi := sqr( px( f2n(i) ) - eyex ) + sqr( pz( f2n(i) ) - eyez );
			di := min( ni, pi );

			nj := sqr( nx( f2n(j) ) - eyex ) + sqr( nz( f2n(j) ) - eyez );
			pj := sqr( px( f2n(j) ) - eyex ) + sqr( pz( f2n(j) ) - eyez );
			dj := min( nj, pj );

			if( di > dj ) then -- swap i,j
				isave:=f2n(i);
				f2n(i):=f2n(j);
				f2n(j):=isave;
			end if;

		end loop; -- for j

	end loop; -- for i

end ssort;











-- to draw seaweed in order from far to near
procedure wsort( 
	f2n: in out wsortarray; 
	nx,px,nz,pz : wlimarray;  
	eyex,eyez : float;  
	avgdist: out float ) is

	n, isave : integer;
	fn, ni,pi,di, nj,pj,dj : float;
begin
	n:=nwrng'last; --nptex
	fn := float(n);

	for i in nwrng loop
		f2n(i):=i; -- initialize permutation
	end loop;
	avgdist:=0.0;

	for i in reverse nwrng loop
		ni := sqr( nx( f2n(i) ) - eyex ) + sqr( nz( f2n(i) ) - eyez );
		pi := sqr( px( f2n(i) ) - eyex ) + sqr( pz( f2n(i) ) - eyez );
		di := min( ni, pi );
		avgdist := avgdist + fmath.sqrt(di)/fn;

		for j in 1..i loop

			ni := sqr( nx( f2n(i) ) - eyex ) + sqr( nz( f2n(i) ) - eyez );
			pi := sqr( px( f2n(i) ) - eyex ) + sqr( pz( f2n(i) ) - eyez );
			di := min( ni, pi );

			nj := sqr( nx( f2n(j) ) - eyex ) + sqr( nz( f2n(j) ) - eyez );
			pj := sqr( px( f2n(j) ) - eyex ) + sqr( pz( f2n(j) ) - eyez );
			dj := min( nj, pj );

			if( di > dj ) then -- swap i,j
				isave:=f2n(i);
				f2n(i):=f2n(j);
				f2n(j):=isave;
			end if;

		end loop; -- for j

	end loop; -- for i

end wsort;









-- We need to draw trees/bamboo in order from far to near
procedure sort( 
	f2n: in out psortarray; 
	nx,px,nz,pz : plimarray;  
	eyex,eyez : float;  
	avgdist: out float ) is

	n, isave : integer;
	fn, ni,pi,di, nj,pj,dj : float;
begin
	n:=nprng'last; --nptex
	fn := float(n);

	for i in nprng loop
		f2n(i):=i; -- initialize permutation
	end loop;
	avgdist:=0.0;

	for i in reverse nprng loop
		ni := sqr( nx( f2n(i) ) - eyex ) + sqr( nz( f2n(i) ) - eyez );
		pi := sqr( px( f2n(i) ) - eyex ) + sqr( pz( f2n(i) ) - eyez );
		di := min( ni, pi );
		avgdist := avgdist + fmath.sqrt(di)/fn;

		for j in 1..i loop

			ni := sqr( nx( f2n(i) ) - eyex ) + sqr( nz( f2n(i) ) - eyez );
			pi := sqr( px( f2n(i) ) - eyex ) + sqr( pz( f2n(i) ) - eyez );
			di := min( ni, pi );

			nj := sqr( nx( f2n(j) ) - eyex ) + sqr( nz( f2n(j) ) - eyez );
			pj := sqr( px( f2n(j) ) - eyex ) + sqr( pz( f2n(j) ) - eyez );
			dj := min( nj, pj );

			if( di > dj ) then -- swap i,j
				isave:=f2n(i);
				f2n(i):=f2n(j);
				f2n(j):=isave;
			end if;

		end loop; -- for j

	end loop; -- for i

end sort;




-- keeping it simple...cannot back into stargate...
-- limited only by how far we allow going into ocean:
procedure myst_movebackward( currenttime: float ) is
	dt : float := currenttime-boldtime;
	lagfac : constant float := 1.0;
	nuy, oy, dx,dy,dz, dist2 : float;
	--kxl,kxh,kzl,kzh,okxl,okxh,okzl,okzh : float;
	kxc,kzc, kxr,kzr, kr2,kt2, fac : float;
	gaterad: float;
	mxrad: constant float := fmath.sqrt(radialMax2);
begin

if thirdperson then gaterad:=gaterad3;
else gaterad:=gaterad1; end if;


if not mrolling then

	-- avoid large jumps due to inactivity
	if (dt>2.0) then dt:=0.0; end if;

	forwardok := true;

	dx:=dt*0.25*speed*xlook;
	dz:=dt*0.25*speed*zlook;
	direction:=-1;

	boldtime := currenttime;
	oxme:=xme;
	oyme:=yme;
	ozme:=zme;

	xme := xme - dx;
	zme := zme - dz;



	-- limit incursion into ocean...
	-- by tangential deflection:
	rad := fmath.sqrt(xme*xme+zme*zme);
	if( rad >= mxrad ) then
		xme := xme*mxrad/rad;
		zme := zme*mxrad/rad;
	end if;




	-- test for passing thru active stargate:
	dist2 := sqr( xme-gatex ) + sqr( zme-gatez );
	if mseated and (dhdstate>0) and (dist2 < gaterad*gaterad) then
		mystexit := true;
	end if;

	-- further, limit pos to avoid ko zones:
	for i in 1..nko loop

		kxc:=0.5*(koxhi(i)+koxlo(i));
		kzc:=0.5*(kozhi(i)+kozlo(i));

		kxr:=0.5*(koxhi(i)-koxlo(i));
		kzr:=0.5*(kozhi(i)-kozlo(i));
		kr2:=kxr*kxr+kzr*kzr; --square of circular radius

		dx:=xme-kxc;
		dz:=zme-kzc;
		kt2:=dx*dx+dz*dz;

		if kt2<kr2 then --intrusion into KO
			fac:=fmath.sqrt(kr2/kt2);
			xme:=kxc+fac*dx;
			zme:=kzc+fac*dz; --move radially away from KO center
		end if;

	end loop; --for i


	moving:=true;
	nuy :=  sandht(xme,zme,hmax,mwaterlevel,r1,r2);
	inwater := (nuy<mwaterlevel-aheight/7.0);
	oy :=  sandht(oxme,ozme,hmax,mwaterlevel,r1,r2);
	dy := nuy-oy;
	yme := yme + dy;

	if yme>eyeht+nuy then yme:=eyeht+nuy; end if; --find bottom after floating
	if yme<minyme then yme:=minyme; end if; --float if in water too deep


end if;

end myst_movebackward;





-- limited by how far we allow going into ocean,
-- and by rock obstacles, and big palm trees...
procedure myst_moveforward( currenttime: float ) is
	dt : float := currenttime-foldtime;
	lagfac : constant float := 1.0;
	nuy, oy, dx,dy,dz, dist2, rad : float;
	--kxl,kxh,kzl,kzh,okxl,okxh,okzl,okzh : float;
	kxc,kzc, kxr,kzr, kr2,kt2, fac : float;
	gaterad: float;
	mxrad: constant float := fmath.sqrt(radialMax2);
begin

if thirdperson then gaterad:=gaterad3;
else gaterad:=gaterad1; end if;

if not mrolling and forwardOk then

	-- avoid large jumps due to inactivity
	if (dt>2.0) then dt:=0.0; end if;

	dx:=dt*0.25*speed*xlook;
	dz:=dt*0.25*speed*zlook;
	direction:=+1;


	foldtime := currenttime;
	oxme:=xme;
	oyme:=yme;
	ozme:=zme;

	xme := xme + dx;
	zme := zme + dz;

	-- limit incursion into ocean...
	-- by tangential deflection:
	rad := fmath.sqrt(xme*xme+zme*zme);
	if( rad >= mxrad ) then
		xme := xme*mxrad/rad;
		zme := zme*mxrad/rad;
	end if;


	-- test for passing thru active stargate:
	dist2 := sqr( xme-gatex ) + sqr( zme-gatez );
	if mseated and (dhdstate>0) and (dist2 < gaterad*gaterad) then
		mystexit := true;
	end if;


	-- further, limit pos to avoid ko zones:
	for i in 1..nko loop

		kxc:=0.5*(koxhi(i)+koxlo(i));
		kzc:=0.5*(kozhi(i)+kozlo(i));

		kxr:=0.5*(koxhi(i)-koxlo(i));
		kzr:=0.5*(kozhi(i)-kozlo(i));
		kr2:=kxr*kxr+kzr*kzr; --square of circular radius

		dx:=xme-kxc;
		dz:=zme-kzc;
		kt2:=dx*dx+dz*dz;

		if kt2<kr2 then --intrusion into KO
			fac:=fmath.sqrt(kr2/kt2);
			xme:=kxc+fac*dx;
			zme:=kzc+fac*dz; --move radially away from KO center
		end if;

	end loop; --for i


	moving:=true;
	nuy :=  sandht(xme,zme,hmax,mwaterlevel,r1,r2);
	inwater := (nuy<mwaterlevel-aheight/7.0);

	oy :=  sandht(oxme,ozme,hmax,mwaterlevel,r1,r2);
	dy := nuy-oy;
	yme := yme + dy;

	if yme>eyeht+nuy then yme:=eyeht+nuy; end if; --find bottom after floating
	if yme<minyme then yme:=minyme; end if; --float if in water too deep


end if;

end myst_moveforward;









procedure myst_handle_gc_look( gcx,gcy:sint16 ) is
-- to update look direction using left game controller stick
	ux : float := float(gcx)/float(32768);
	uy : float := float(gcy)/float(32768);
begin


	if abs(ux)<0.15 then 
		ux:=0.0;
	else
		ux:=ux-0.15*signum(ux);
	end if;

	if abs(uy)<0.15 then 
		uy:=0.0; 
	else
		uy:=uy-0.15*signum(uy);
	end if;


	horiAng := horiAng - 0.04 * ux * Lsens;
	vertAng := vertAng + 0.02 * uy * Lsens;



	if thirdperson then -- vertang represents camera
		xlook := fmath.cos(0.0)*fmath.sin(horiAng);
		zlook := fmath.cos(0.0)*fmath.cos(horiAng);
	else
		xlook := fmath.cos(vertAng)*fmath.sin(horiAng);
		zlook := fmath.cos(vertAng)*fmath.cos(horiAng);
	end if;
	cylook := fmath.sin(vertAng);



	--slewToAvLook; --gradually slew choriang (camera) toward horiang=avatar-look-dir

	--better:
	slewToAv; -- 26jan18: gradually slew choriang (camera) toward avatar


	if
	( 
	not forwardOk 
	and (abs(badHoriAng-horiAng)>fourthpi) 
	and not pauseAtLevelChange 
	)  then
		forwardOk:=true;
		badHoriAng:=-10.0*twopi;
	end if;

end myst_handle_gc_look;

procedure myst_handle_gc_move( nowtime: float;  gcx,gcy:sint16 ) is
-- to update move direction using right game controller stick
	ux : float := Rsens*float(gcx)/float(32768);
	uy : float := Rsens*float(gcy)/float(32768);
begin

	if    uy < -0.05 then
		myst_moveforward(nowTime);

	elsif uy > +0.05 then
		myst_movebackward(nowTime);

	end if;

	myst_handle_gc_look(gcx,0); -- turns left/right

end myst_handle_gc_move;






















-- until flyover is false, (oxme,oyme,ozme) holds original position

procedure fly(
currenttime, xme,yme,zme, xlook,cylook,zlook : in out float;
flyover : in out boolean ) is
	tt : constant float := (currenttime - flystart)/flyduration;
	ang0 : constant float := fmath.arctan(ozme,oxme);
	rxz : float;
begin

if tt>1.0 then
	flyover:=false;
else

	yme:=(1.0-tt)*yfly + tt*oyme;
	horiang := tt*onepi*3.0 + ang0;


	-- nice...looking in direction of flight
	--xme := oxme*cos(-horiang+onepi) - ozme*sin(-horiang+onepi);
	--zme := oxme*sin(-horiang+onepi) + ozme*cos(-horiang+onepi);

	-- best...looking between island center and direction of flight
	xme := oxme*fmath.cos(-horiang+1.2*onepi) - ozme*fmath.sin(-horiang+1.2*onepi);
	zme := oxme*fmath.sin(-horiang+1.2*onepi) + ozme*fmath.cos(-horiang+1.2*onepi);

	rxz := fmath.sqrt( xme*xme+zme*zme );
	vertang := -onepi/12.0 - fmath.arctan(yme,rxz);

	xlook := fmath.cos(vertang)*fmath.sin(horiang);
	cylook := fmath.sin(vertang);
	zlook := fmath.cos(vertang)*fmath.cos(horiang);

	slewToAvLook;
	updateCamera;

end if;

end fly;








-- Simplified version of update used for prolog (on beach) 
-- where jumping is disallowed...
-- this must also initiate beach-ZPM rolls
procedure mupdatezpm( currenttime : float ) is

	barrelwasmoved, barrelhitko : boolean := false;
	dist, nbx,nby,nbz : float;
	--k: integer := 0;
begin

	nbx:=0.0; nby:=0.0; nbz:=0.0;

	---------- begin barrel logic -------------------------------

	-- initiate roll when appropriate:
	if not mrolling then

		barrl := mposbar;
		-- xme,zme are used in this next ftn:
		mtestbarrel( nbx,nby,nbz, barrelwasmoved, barrelhitko);

		if barrelhitko then
			forwardok := false;
			badhoriang := horiang;
		end if;


		if forwardok and barrelwasmoved  then

			nubarrl(1):=nbx;
			nubarrl(2):=nby;
			nubarrl(3):=nbz;
			mrolling:=true;
			mseated:=false;
			if dhdstate/=5 then
				dhdstate:=0;
			end if;
			timeofroll:=currenttime;
			olbarrl:=barrl;
			incbarrl:=olbarrl;

			-- barrel can only roll in 2 directions
			if (nubarrl(3)=olbarrl(3)) then
				rolldir := 3 * integer( signum(nubarrl(1)-olbarrl(1)) );
			elsif (nubarrl(1)=olbarrl(1)) then
				rolldir := 1 * integer( signum(nubarrl(3)-olbarrl(3)) );
			end if;
			--snd4ada_hpp.playSnd(kick);
			snd4ada_hpp.playSnd(beachkick); --4dec18

		end if;

	end if;



	-- check whether barrel is on receptacle:
	if  not mrolling  and not mseated then

		dist := fmath.sqrt( 
			sqr(mposbar(1)-barx) +
			sqr(mposbar(3)-barz) );
		if (dist<0.1) then 
			mseated:=true; -- barrel is on receptacle
		end if;

		if mseated then
			snd4ada_hpp.playSnd(qport); --sbQport signals empowerment 11nov14

			if dhdstate=5 then
				dhdtime:=currenttime;
				snd4ada_hpp.playSnd(kwush);
				snd4ada_hpp.playLoop(kbub);
			end if;

		end if;

	end if;

	if not mseated then --4dec18
		snd4ada_hpp.stopLoop(kbub);
	end if;

	---------- end barrel logic -------------------------------

	lasttime := currenttime;

end mupdatezpm;








-- this assumes mm=ID, (xme,yme,zme)=virtual pos on island
-- [ actual pos is always (0,0,0) ]
procedure myst_update3MVPs( bkgdNum: integer; currentTime, wid,hit : float) is
	pmx,pmy,pmz,madeg,
	mang,
	xlk,ylk,zlk,
	xrt,yrt,zrt,
	xpos,ypos,zpos,
	xup,yup,zup : float;
	degtilt: constant float := -60.0; -- -45.0;
begin

	if thirdPerson and not worming then

		xpos:=xcam; ypos:=ycam; zpos:=zcam;
		-- camera look + choriang are already defined

	else -- firstPerson

		xpos:=xme; ypos:=yme; zpos:=zme;

		choriang:=horiang;
		cxlook := fmath.cos(vertang)*fmath.sin(choriang);
		cylook := fmath.sin(vertang);
		czlook := fmath.cos(vertang)*fmath.cos(choriang);

	end if;


	-- Look Vector
	xlk:=xpos+cxlook;
	ylk:=ypos+cylook;
	zlk:=zpos+czlook;

	-- Right unit-Direction
	xrt:= fmath.sin(choriang-halfpi);
	yrt:= 0.0;
	zrt:= fmath.cos(choriang-halfpi);

	-- calculate UP unit-Direction
	cross( xrt,yrt,zrt, cxlook,cylook,czlook, xup,yup,zup );

	perspective(projMatrix, 45.0, wid/hit,  0.1, 100.0);

	lookat(mviewMatrix, 0.0,0.0,0.0, cxlook,cylook,czlook, xup,yup,zup );
	lookat(iviewMatrix, xpos,ypos,zpos, xlk,ylk,zlk, xup,yup,zup );

	mmvp:=mviewMatrix; --use only for skybox
	imvp:=iviewMatrix;
	imv:=iviewMatrix;

	matXmat(mmvp,projMatrix); -- for skybox only
	matXmat(imvp,projMatrix); -- for all else



---------------------------------------------
	-- orbit pos (myrad,mrad=20)
	if bkgdNum=4 then --night stars
		mang:=currentTime*twopi*0.002; --0.002
		pmx:=8.0*fmath.sin(mang);
		pmz:=8.0*fmath.cos(mang);
		pmy:=15.0;
	elsif bkgdNum=3 then --evening
		mang:=currentTime*twopi*0.005; --0.005
		pmx:=2.0*fmath.sin(mang);
		pmz:=2.0*fmath.cos(mang);
		pmy:=15.0;
	elsif bkgdNum=2 then -- icy, foggy
		pmx:=-0.5; pmz:=-0.5; pmy:=15.0;
	elsif bkgdNum=1 then -- clouds, fog
		pmx:=1.0; pmz:=-4.0; pmy:=15.0;
	elsif bkgdNum=0 then -- sunny, clouds
		mang:=currentTime*twopi*0.01; --0.01
		pmx:=5.0*fmath.sin(mang);
		pmz:=5.0*fmath.cos(mang);
		pmy:=15.0;
	else
		raise program_error;
	end if;


	-- spinAngle
	madeg := -currentTime*twopi*rad2deg*0.1; -- 10sec/rev

	mars.setpos( pmx, pmy, pmz );
	ellobj.setpos(jupit,pmx,pmy,pmz);

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


	satmm:=identity;
	translate(satmm, -pmx,-pmy,-pmz); --first, move to origin

-- begin rotations

	--spin on polar axis:
	degRotate(satmm, madeg, 0.0,1.0,0.0); -- Y=polar-axis (best 4 mars)

	--axis-tilt:
	degRotate(satmm, degtilt, 1.0, 0.0, 0.0);

-- end rotations

	translate(satmm, pmx,pmy,pmz); --now, move back

	satmv:=satmm;
	matXmat(satmv,mviewMatrix);
	satmvp:=satmv;
	matXmat(satmvp,projMatrix);
---------------------------------------------



end myst_update3MVPs;




procedure aimu(x,y,z: out float) is
	x0,y0,z0, x1,y1,z1, tt : float := 0.0;
	yplane : constant float := dhdy+dhdh; -- Y-coord of DHD Face
begin

	x0:=xme;
	y0:=yme;
	z0:=zme;
	x1:=x0;
	y1:=y0;
	z1:=z0;

	while (y1>yplane) loop
		tt:=tt+1.0;
		x1 := x0 + tt*xlook;
		y1 := y0 + tt*cylook;
		z1 := z0 + tt*zlook;
	end loop;
	tt := (yplane-y0)/(y1-y0);
	x := x0 + tt*(x1-x0);
	z := z0 + tt*(z1-z0);
	y := yplane;

end aimu;



-- on beach, decide which button on DHD the user selects:
procedure pickleft is
	x0,y0,z0, x1,y1,z1, tt : float := 0.0;
	dx,dz,xtgt,ztgt : float;
	yplane : constant float := dhdy+dhdh; -- Y-coord of DHD Face
begin

	x0:=xme;
	y0:=yme;
	z0:=zme;
	x1:=x0;
	y1:=y0;
	z1:=z0;

	while (y1>yplane) loop
		tt:=tt+1.0;
		x1 := x0 + tt*xlook;
		y1 := y0 + tt*cylook;
		z1 := z0 + tt*zlook;
	end loop;
	tt := (yplane-y0)/(y1-y0);
	xtgt := x0 + tt*(x1-x0);
	ztgt := z0 + tt*(z1-z0);

	dx := xtgt-dhdx;
	dz := ztgt-dhdz;

	if( (abs(dx)<dhdr) and (abs(dz)<dhdr) and (dhdstate<5) ) then


		if( (dx<0.0) and (dz<0.0) ) then -- SE

			if not solved(3) then 
				dhdstate:=3; --4;
				dhdtime:=currenttime;
				snd4ada_hpp.playSnd(kwush);
						snd4ada_hpp.playLoop(kbub);
			end if;

		elsif( (dx>0.0) and (dz<0.0) ) then -- SW

			if not solved(4) then
				dhdstate:=4; --1;
				dhdtime:=currenttime;
				snd4ada_hpp.playSnd(kwush);
						snd4ada_hpp.playLoop(kbub);
			end if;

		elsif( (dx>0.0) and (dz>0.0) ) then -- NW

			if not solved(1) then
				dhdstate:=1; --2;
				dhdtime:=currenttime;
				snd4ada_hpp.playSnd(kwush);
						snd4ada_hpp.playLoop(kbub);
			end if;

		elsif( (dx<0.0) and (dz>0.0) ) then -- NE

			if not solved(2) then
				dhdstate:=2; --3;
				dhdtime:=currenttime;
				snd4ada_hpp.playSnd(kwush);
						snd4ada_hpp.playLoop(kbub);
			end if;

		end if;


	end if;
	-- else look too far away



end pickleft;



	darkness : interfaces.c.int := 0; -- 0..4

	dt, rr : float;

	detales: boolean := false;

	vmt,vcc: vec4;
	ang2dhd, adiff, dist,xap,yap,zap: float;

	beach_error : exception;

	extension, et: float;
	
	kz: glfloat;

	bubbling: boolean := false;

	xeye,yeye,zeye: float;



procedure drawMisc is separate;

procedure drawStargate is separate;

procedure drawPalms is separate;

procedure drawRocks is separate;

procedure drawOcean(ibkg: integer) is separate;

procedure drawSeaweed is separate;
procedure drawWeeds is separate;

procedure drawsand is separate;

procedure drawZPM is separate;
procedure rustyZPM is separate;

procedure drawDHD is separate;

procedure drawfish is separate;

procedure drawSkybox is separate;

procedure redefineKOs is separate;



	dbx, dbz : float;


begin ------------- begin main drawisland ###############



	bubbling:=false;

	mars.setpos( 0.0, 0.0, 0.0 );
	jupit.setpos( 0.0, 0.0, 0.0 );

		currentTime:=float(sdl_getticks)/1000.0;

	myassert( npt = nprng'last, 113 );

	--3apr18 begin
	if 
		skipFly
	then

		-- in this case, we are exitting the stargate:
		xme := gatex+0.0; -- -4.0;
		zme := gatez+0.5; -- -3.5;
		yme := eyeht + sandht(xme,zme,hmax,mwaterlevel,r1,r2);

		vertang:=0.0;
		horiang:=0.0;

		if dbug then

			mposbar(1):=barx;
			mposbar(3):=barz;
			bary := -0.02 + barad +  --25may18
				sandht( mposbar(1), mposbar(3), hmax,mwaterlevel,r1,r2);
			mposbar(2):= bary;
			cyl2obj.setcyl2( mbarrel, mposbar(1),mposbar(2),mposbar(3), barad );
			cyl2lit.setcyl2( rbarrel, mposbar(1),mposbar(2),mposbar(3), barad );
			mseated:=true;

		else

			dbx:=-1.0*mrolldist;  dbz:=+1.0*mrolldist;
			if solved(1) then
				dbx := dbx - mrolldist;
			elsif solved(2) then
				dbz := dbz + mrolldist;
			elsif solved(3) then
				null;
			elsif solved(4) then
				dbz := dbz - mrolldist;
			end if;

			--move ZPM so player must reset:
			mposbar(1):=barx+dbx;
			mposbar(3):=barz+dbz;
			bary := -0.02 + barad +  --25may18
				sandht( mposbar(1), mposbar(3), hmax,mwaterlevel,r1,r2);
			mposbar(2):= bary;
			cyl2obj.setcyl2( mbarrel, mposbar(1),mposbar(2),mposbar(3), barad );
			cyl2lit.setcyl2( rbarrel, mposbar(1),mposbar(2),mposbar(3), barad );
			mseated:=false;

		end if;


	else --first arrival @ island

		xme := 4.0;
		zme := 1.0;
		yme := eyeht + sandht(xme,zme,hmax,mwaterlevel,r1,r2);

		vertang:=0.0;
		horiang:=-onepi;

	end if;
	--3apr18 end


	xlook := fmath.cos(vertang)*fmath.sin(horiang);
	cylook := fmath.sin(vertang);
	zlook := fmath.cos(vertang)*fmath.cos(horiang);

	slewToAvLook;
	updateCamera(true);


	if not flyover then
		toIsland:=true;
		-- note:  as written, tunnel requires horiang be a multiple of halfpi
		prepwormhole( currenttime, 
			xme-40.0*xlook, yme, zme-40.0*zlook, xme,yme,zme, xme,yme,zme);
	end if;

	--hold pos until after flyover
	oxme:=xme; oyme:=yme; ozme:=zme;
	flystart:=float(sdl_getticks)/1000.0;

	if skipFly then
		flyover:=false; -- debug only
	end if;


	jupit.yseteli(0.5,0.5,0.5); -- +Y=Npole
	mars.yseteli(0.4,0.4,0.4); -- +Y=Npole



	redefineKOs;
	-- these keepout zones must be
	-- reinitialized here at each return to the island since the
	-- same ko arrays are also used in the dungeon rooms:



	bkg:=0;
	if solved(1) then bkg:=bkg+1; end if;
	if solved(2) then bkg:=bkg+1; end if;
	if solved(3) then bkg:=bkg+1; end if;
	if solved(4) then bkg:=bkg+1; end if;


	if bkg=0 then
		mcubemap_texid := tropical_cubemap_texid; -- sunny day
		foglev:=0;
	elsif bkg=1 then
		mcubemap_texid := blue_cubemap_texid;     -- cloudy day
		foglev:=2;
	elsif bkg=2 then
		mcubemap_texid := sargas_cubemap_texid;   -- icy, colorful
		foglev:=1;
	elsif bkg=3 then
		mcubemap_texid := sunset_cubemap_texid;   -- evening
		foglev:=0;
	elsif bkg=4 then
		mcubemap_texid := moon_cubemap_texid;     -- night
		foglev:=0; -- 13dec17

		nko:=nko-1; --16jan18: remove DHD as KO zone

	end if;
	darkness:=interfaces.c.int(bkg);

	mystexit:=false;
	mrolling:=false;


	updateCamera(true);
	myst_update3MVPs(bkg, currentTime, float(winwidth), float(winheight) );

	snd4ada_hpp.playLoop(beach); -- tradewinds & surf



	dhdstate:=0;
	if( solved(1) and solved(2) and solved(3) and solved(4) ) then
		dhdstate:=5; -- allow going directly to epilogue
	end if;


	xmonk:=-4.5;
	zmonk:=+3.5;
	ymonk:=sandht(xmonk,zmonk,hmax,mwaterlevel,r1,r2);
	mang:=0.0;
	mdir:=1;



	----------------------- main event loop begin -----------------------
   while not mystexit loop

		direction:=0; --stop avatar's legs, unless moving

		currentTime:=float(sdl_getticks)/1000.0;
		SDL_PumpEvents;



------- begin response to user inputs /////////////////////////////////////////

		currentTime := float(sdl_getticks)/1000.0;

		SDL_PumpEvents;

		-- these are only 2 keyboard responses needed in level=5 (epilogue)
		if( key_map( SDL_SCANCODE_ESCAPE ) /= 0 ) then 
			userexit:=true; 
			mystexit:=true;
		end if;

		if( key_map( SDL_SCANCODE_Q ) /= 0 ) then 
			userexit:=true; 
			mystexit:=true;
		end if;


	if not flyover and not worming then

		moving:=false;
		if
			( key_map( SDL_SCANCODE_UP ) /= 0 )
			or ( key_map( SDL_SCANCODE_W ) /= 0 )
		then 
			myst_moveForward(currentTime);

		elsif
			( key_map( SDL_SCANCODE_DOWN ) /= 0 ) 
			or ( key_map( SDL_SCANCODE_S ) /= 0 )
		then 
			myst_moveBackward(currentTime);

		end if;


		-- now using h-key for help...
		-- debug utility...helps see new viewpoints
		--if dbug then
		--	if( key_map( SDL_SCANCODE_H ) /= 0 ) then --move Higher
		--		yme := yme + 0.01;
		--		yme := min(yme, maxyme);
		--	elsif( key_map( SDL_SCANCODE_L ) /= 0 ) then --move Lower
		--		yme := max(yme-0.01,eyeht+sandht(xme,zme,hmax,mwaterlevel,r1,r2));
		--		yme := max(yme, minyme);
		--	end if;
		--end if;
		-- Test Result:  eventually, island disappears below bottom of skybox



		if
			(
				( key_map( SDL_SCANCODE_M )  /= 0 )
				or
				( key_map( SDL_SCANCODE_F1 ) /= 0 )
			)
		then
			dt := currentTime - dBtnTime;
			if( dt > 0.8 ) then
				thirdPerson := not thirdPerson;
				dBtnTime:=currentTime;
			end if;
		end if;



		if( key_map( SDL_SCANCODE_H )  /= 0 ) then --8dec18
			dt := currentTime - dBtnTime;
			if( dt > 0.8 ) then
				help:=not help;
				dBtnTime:=currentTime;
			end if;
		end if;




		if( key_map( SDL_SCANCODE_X )  /= 0 ) then 
			dt := currentTime - dBtnTime;
			if( dt > 0.8 ) then
				detales:=not detales;
				dBtnTime:=currentTime;
			end if;
		end if;


		deltaT := currentTime - oldTimeKb;


		if
			( key_map( SDL_SCANCODE_LEFT ) /= 0 ) 
			or ( key_map( SDL_SCANCODE_A ) /= 0 )
		then

			if thirdperson then
				roty := angrate3*deltaT;
			else
				roty := angrate1*deltaT;
			end if;

			horiang := horiang + roty;
			--slewToAvLook;
			slewToAv; --26jan18 (better)
			roty:=0.0;


			if thirdperson then -- vertang represents camera
				xlook := fmath.cos(0.0)*fmath.sin(horiAng);
				zlook := fmath.cos(0.0)*fmath.cos(horiAng);
			else
				xlook := fmath.cos(vertAng)*fmath.sin(horiAng);
				zlook := fmath.cos(vertAng)*fmath.cos(horiAng);
			end if;
			cylook := fmath.sin(vertAng);




		elsif
			( key_map( SDL_SCANCODE_RIGHT ) /= 0 ) 
			or ( key_map( SDL_SCANCODE_D ) /= 0 )
		then

			if thirdperson then
				roty := -angrate3*deltaT;
			else
				roty := -angrate1*deltaT;
			end if;

			horiang := horiang + roty;
			--slewToAvLook;
			slewToAv; --26jan18 (better)
			roty:=0.0;


			if thirdperson then -- vertang represents camera
				xlook := fmath.cos(0.0)*fmath.sin(horiAng);
				zlook := fmath.cos(0.0)*fmath.cos(horiAng);
			else
				xlook := fmath.cos(vertAng)*fmath.sin(horiAng);
				zlook := fmath.cos(vertAng)*fmath.cos(horiAng);
			end if;
			cylook := fmath.sin(vertAng);




		end if;


--------------------------------------------------------- addendum 8dec18


		if( key_map( SDL_SCANCODE_z )  /= 0 ) then --default-view-restore
				--camdist:=1.0; --default
				if camdist>1.01 then
					camdist := 0.99*camdist;
				elsif camdist<0.99 then
					camdist := 1.01*camdist;
				end if;

		elsif( key_map( SDL_SCANCODE_N )  /= 0 ) then --nearer
				camdist := 0.99*camdist;
				if camdist<0.1 then camdist:=0.1; end if;

		elsif( key_map( SDL_SCANCODE_F )  /= 0 ) then --further
				camdist := 1.01*camdist;
				if camdist>10.0 then camdist:=10.0; end if;

		end if;


--------------------------------------------------------- addendum 19jan18
		if SDL_PollEvent(test_event'access)>0 
		and then test_event.wheel.c_type = SDL_MouseWheel then

			--if not onMac then --use this if necessary

				if test_event.wheel.y<0 then --move eye closer by 1%
					camdist := 0.99*camdist;
					if camdist<0.1 then camdist:=0.1; end if;

				--move eye away by 1%
				elsif test_event.wheel.y>0 then
					camdist := 1.01*camdist;
					if camdist>10.0 then camdist:=10.0; end if;

				end if;

			--end if;

		end if;
--------------------------------------------------------- addendum 19jan18



------ begin mouse button -----------------------------------------

-- Here, I am assuming dhdy < yme ...
-- so if we are close enough to the DHD
-- and if we are looking down then we test:


		dist:=fmath.sqrt( sqr(xme-dhdx) + sqr(zme-dhdz) );



----------- force 1st person insert 25jan18 -----------------------
		if dist<dhdnear1 and thirdperson then

			restoreThird:=true;
			thirdperson:=false;

		elsif dist>dhdnear1 and restoreThird then

			thirdperson:=true;
			restoreThird:=false;

		end if;
----------- force 1st person insert 25jan18 -----------------------


		if dist>0.001 then

			--difference between DHD and look direction...since we are using sine
			--we must test halfangle so that test fails @ delta=onepi
			--adiff := abs(fmath.sin( 0.5*fmath.arctan(dhdx-xme,dhdz-zme) - 0.5*horiang ));
			ang2dhd:=branchnear(horiang,fmath.arctan(dhdx-xme,dhdz-zme));
			adiff := abs(fmath.sin( 0.5*(ang2dhd-horiang) ));

			if thirdPerson then
				--neardhd:=((dist<dhdnear1)and(cylook<-0.1)and(adiff<fmath.sin(eighthpi)));
				neardhd := ( (dist<dhdnear1) and (adiff<fmath.sin(eighthpi)) );
			else
				-- must be looking down at 30 degrees or more below horizontal
				neardhd:=((dist<dhdnear1) and (cylook<-0.5) and (adiff<fmath.sin(eighthpi)));
			end if;

		else
			neardhd:=false; --too close for calculations
		end if;

		if dhdstate=5 then neardhd:=false; end if; --14jan18 fix


		if mseated and neardhd and (dhdstate<5) then
			MouseState:=SDL_GetMouseState(mousex'access,mousey'access);
			state := integer( MouseState );
			ileft := integer( SDL_BUTTON_left );
			if    bitmatch(state, ileft)   then 
				pickLeft;
			end if;
		end if;

		handle_mouse_move(currentTime); -- change look direction here


----------- begin game controller handler ---------------------------------
		if joystik or gamepad then

			-- axis_* values in [-32768...+32767]

			-- JS: 2nd Axis parm:  0..2
			-- GC: 2nd Axis parm:  0..3

			currentTime := float(sdl_getticks)/1000.0;

			if joystik then
				axis_lx := SDL_JoystickGetAxis(jsa, 0);
				axis_ly := SDL_JoystickGetAxis(jsa, 1);
				myst_handle_gc_look(axis_lx,axis_ly);

			elsif gamepad then

				--this grabs right stick
				axis_lx := SDL_JoystickGetAxis(jsa, 2);
				axis_ly := SDL_JoystickGetAxis(jsa, 3);
				myst_handle_gc_look(axis_lx,axis_ly); --adjust look dir

				-- If the gamepad analog btn is down
				-- then this grabs the left HAT btn;
				-- otherwise this grabs the left stick:
				axis_rx := SDL_JoystickGetAxis(jsa, 0);
				axis_ry := SDL_JoystickGetAxis(jsa, 1);
				myst_handle_gc_move(currentTime,axis_rx,axis_ry); --move

				--these fail?
				--axis_lx := SDL_GameControllerGetAxis(jsa, 2);
				--axis_ly := SDL_GameControllerGetAxis(jsa, 3);
				--myst_handle_gc_look(axis_lx,axis_ly); --adjust look dir

				--axis_rx := SDL_GameControllerGetAxis(jsa, 0);
				--axis_ry := SDL_GameControllerGetAxis(jsa, 1);
				--myst_handle_gc_move(currentTime,axis_rx,axis_ry); --move


			end if;

-- now handle the buttons:

			-- 1 => pressed,  0 => not pressed
			-- JS: 2nd Btn parm:  0..7
			-- GC: 2nd Btn parm:  0..11

			zeroBtns; -- sets btns 0..8 to zero
			if gamepad then
				btn_pic1 := SDL_JoystickGetButton(jsa,gshtl); -- pick
				btn_pic2 := SDL_JoystickGetButton(jsa,gshtr); -- pick
			elsif joystik then
				btn_bak := SDL_JoystickGetButton(jsa,jbak); -- back
				btn_for := SDL_JoystickGetButton(jsa,jfor); -- forw
				btn_pic1 := SDL_JoystickGetButton(jsa,jshtl); -- pick
				btn_pic2 := SDL_JoystickGetButton(jsa,jshtr); -- pick
			end if;


			--if btn_4>0 or btn_5>0 or btn_2>0 or btn_3>0 then
			if btn_pic1>0 or btn_pic2>0 then
				if mseated and neardhd and (dhdstate<5) then
					pickLeft;
				end if;
			end if;

			if joystik then
				if btn_bak>0 then -- JS.trigger
					myst_moveBackward(currentTime);
				elsif btn_for>0 then -- JS.thumb
					myst_moveForward(currentTime);
				end if;
			end if;

		end if; --joystik or gamepad


		if not moving and splashing then
			snd4ada_hpp.stopLoop(splash); --Splash;
			splashing:=false;
		elsif not inwater and splashing then
			snd4ada_hpp.stopLoop(splash);
			splashing:=false;
		elsif moving and inwater and not splashing then
			snd4ada_hpp.playLoop(splash);
			splashing:=true;
		end if;



----------- end game controller ---------------------------------




----///////////////////// end response to user inputs /////////////////////////


	else -- flyover or worming is taking place
		if flyover then
			fly(currenttime, xme,yme,zme, xlook,cylook,zlook,flyover);
		elsif worming then
			vertang:=0.0;
			worm(currenttime, xme,yme,zme, worming);
		end if;
	end if; -- not flyover




		updateCamera; -- main call within myst event loop

		myst_update3MVPs(bkg,currentTime, float(winwidth), float(winheight) );


		mupdatezpm(currenttime); -- 6nov15 addition ???
		-- much simpler version of updategamestate for beach


		foldtime:=currenttime;
		boldtime:=currenttime;
		oldTimeKb := currenttime;

		glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);


		if thirdperson then
			xeye:=xcam; yeye:=ycam; zeye:=zcam;
		else
			xeye:=xme; yeye:=yme; zeye:=zme;
		end if;


--/////// begin draw textured objects ////////////////////////////////


		drawsand; --and planet

		drawSkyBox;

		drawSeaweed;

		drawMisc;
		-- crab, bones, jar, woodsign,
		-- SoS, ZPMreceptacle, airplane-nose

		drawFish;

		updateMonkey(currenttime,xme,zme, xmonk,ymonk,zmonk,mang,mdir);
		drawMonkey(currenttime,xmonk,ymonk,zmonk,mang,mdir);

		if thirdPerson then

			if neardhd and mseated  then --translucent
				fadeAvatar:=true;
			else
				fadeAvatar:=false;
			end if;

			drawAvatar(currenttime, xme,yme,zme,horiang); --draw after DHD
		end if;


		drawOcean(bkg); --AFTER all undersea objects are drawn

		drawRocks; -- coconuts + rocks
		drawDHD;

		--drawZPM;
		rustyZPM;


		drawStargate;

		sort(far2near,nx,px,nz,pz, xeye,zeye, avgdist); --palmtrees
		drawPalms;

		drawWeeds;





		if neardhd and mseated  then -- show hand-cursor

			-- "`" => rightPalm in my alphabet
			aimu(xap,yap,zap);
			vmt:=(xap,yap,zap,1.0);
			matXvec(imvp,vmt,vcc);
			utex.print3d("`",vcc(1),vcc(2),vcc(3),vcc(4), 40, 1.0);

		end if;




		if worming then -- draw passage thru wormhole
				drawWormHole( currentTime, imvp );


		elsif help then
			utex.print2d(" Help Screen Tips:",0.02, 0.70,15);
			utex.print2d(" m-key => toggle Avatar",0.02, 0.60,15);
			utex.print2d(" ...and if avatar is showing...",0.02, 0.55,15);
			utex.print2d(" n-key => zoom_Nearer;  f-key => zoom_Further;  z-key => default_zoom", 0.02, 0.5, 15);

			utex.print2d(" <esc> => quit", 0.02, 0.40, 25);


		elsif detales then -- debug info (x-key)

			utex.print2d(" ME: "&float'image(xme)&","&float'image(zme),0.02,0.9,25 );

			utex.print2d(" bkg="& integer'image(bkg), 0.02, 0.8, 25);
			utex.print2d(" hdpi: " &
				interfaces.c.int'image(Fwid)&" X "
				& interfaces.c.int'image(Fhit), 0.02, 0.7, 25 );

--------- begin OGL queries -----------------------------------------

			glGetIntegerv(GL_CONTEXT_PROFILE_MASK, profile'address);
			if( profile = GL_CONTEXT_CORE_PROFILE_BIT ) then
				utex.print2d("ogl-query:  Core Profile", 0.02, 0.6, 20);
			end if;

			-- Note that OSX currently requires the forward_compatible flag!
			glGetIntegerv(GL_CONTEXT_FLAGS, flags'address);
			if( flags = GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT ) then
				utex.print2d("ogl-query:  Forward-Compatible bit is set", 0.02, 0.55, 10);
			end if;

			glgetintegerv(gl_major_version, major'address);
			glgetintegerv(gl_minor_version, minor'address);
			utex.print2d( "ogl-query: OGL-major: "&glint'image(major), 0.02, 0.5, 10);
			utex.print2d( "ogl-query: OGL-minor: "&glint'image(minor), 0.02, 0.45, 10);

			glgetintegerv(gl_max_texture_units, mtu'address);
			utex.print2d( "ogl-query: maxTexUnits: "&glint'image(mtu), 0.02, 0.4, 10);

			glgetintegerv(gl_max_texture_image_units, mtu'address);
			utex.print2d( "ogl-query: maxTexImgUnits: "&glint'image(mtu), 0.02, 0.35, 10);

			glgetintegerv(gl_max_combined_texture_image_units, mtu'address);
			utex.print2d( "ogl-query: maxCombTexImgUnits: "&glint'image(mtu), 0.02, 0.3, 10);

			glgetintegerv(gl_max_uniform_buffer_bindings, mul'address);
			utex.print2d("ogl-query: maxUnifBufferBindings: "&glint'image(mul),0.02,0.25,10);

			glgetintegerv(gl_max_uniform_locations, mul'address);
			utex.print2d("ogl-query: maxUniformLocations: "&glint'image(mul), 0.02,0.20,10);


--------- end OGL queries -----------------------------------------





		end if; -- worming/detales





		--minimal gl error check if dbug
		if dbug then
			if dumpGLerrorQueue("gameutils.island_ftn loop end")>0 then
				--raise beach_error;
				null;
			end if;
		end if;




		sdl_gl_swapwindow( mainWindow );

   end loop; 
	----------------------- main event loop end -----------------------

	if not userexit then
		snd4ada_hpp.stopLoops;
	end if; --otherwise stopSnd is called at end of main


	myassert( (dhdstate>0) or userexit , 114 );
	myassert( dhdstate <= 5, 115 );

	return dhdstate;


exception -- added 8jan18

	when ada.numerics.argument_error =>

		new_line;
		put("iFtn:  xme="&float'image(xme));
		put("iFtn:  zme="&float'image(zme));
		new_line;

		put("iFtn:  xcam="&float'image(xcam));
		put("iFtn:  zcam="&float'image(zcam));
		new_line;

		put("iFtn:  xme-xcam="&float'image(xme-xcam));
		put("iFtn:  zme-zcam="&float'image(zme-zcam));
		new_line;

		raise;



end drawisland;


