 
          
        
        Move with arrows. Smoother remake of my 2013 entry, but the weather is not as nice this year.
for(_='){Z-1Y20XMath.WWcos(V*VUataTv[S++R256Q-X0*s+q*30*d-PQP384Ox=NNb/XLonkeyK(d-k)J))H);G)GF2*E+=%t=$0,#;b="/80 Wsqrt(=-4;Rt&3]55D[aR]==0;&511)for(Rf;--f&2;rgb2;;;}}512;a-=X64ZWmin(1,Wmax(#$(e-35)/tImageDT(Wsin(*eUC)+e*C)*t+(1-t)*	*=y	x*y;=2*%[#1,#Y][Vh)+X0*=$>St.keyCode&3]=.5*d 0;y=-d 0/2;p[*(y+m+(x+l]I=c.ge##i=,GD=I.dT;v=p=[];s=q=$Ny>y;y%!(Nx+1)p.push(52-Ux -y H)YGbRbYe6;$9*t+2+9Ut)&YZx;y3-;Sll-5;C=h=11)mm-5;)%.01}m=72;setInterval($>{s=s*.97+ES2]-ES0];Nyl%sUC=WTn2(C),VCH+qGm%s*CGq=q/2+S1]-S3];i=.9*i+5+5*Gd=k=43EC-67Eh%1/QGu=O*;d=-Q;Q>d;d%4Zf=,a=4*(*f-Q+d),eRe-300;ZNb=Gw=O*Eb/e+15*i/eGif(f>wZRy;y=.4+(b-H*h)Fg=rG$e/X#L;rNx/2+.75;gL||1"Gb>w}r=;g=118+11E"4*Fe=J*J+(f-u)*(f-uFY0FxGy=x	(FN(99+1*H)	x;QFr=r	2;g=g	x"b	y;e=40*/(QPfGN9*h+$-2-,-t*(Pf)/QFr.5+EH	r;gVh-.2H	g"(3Uh+.5HH	b;c.puI,#0)},40GKdown.01;Kup0';G=/[^!&-DIM[-}]/.exec(_);)with(_.split(G))_=join(shift());eval(_)Zm9yKF89Jyl7Wi0xWTIwWE1hdGguV1djb3MoVipWVWF0YVR2W1MrK1IyNTZRLVgwKnMrcSozMCpkLVBRUDM4NE94PU5OYi9YTG9ua2V5SyhkLWspSikpSCk7RylHRjIqRSs9JXQ9JDAsIztiPSIvODAgV3NxcnQoHz0tNDtSHnQmM10dNTUcRFthUl09Gz0wOxomNTExKRlmb3IoGBhSZjstLWYXJjIcOxsWG3IWZxZiFjIcFRU7FTsVOxV9fRQ1MTITO2EtPVg2NFoSV21pbigxLBFXbWF4KCMQJBARKGUtMzUpLw90SW1hZ2VEVCgOV3NpbigMKmVVQykrZSoMQykLKnQrKDEtdCkqCSo9eQl4Knk7CD0yHCoQByVbIzEsI1ldWwZWaCkFHCtYMCoQBD0kPlN0LmtleUNvZGUmM109Ay41CypkIDA7eT0tZCAwCy8yOwJwWxMqKHkrbRkrKHgrbBldAUk9Yy5nZQ4jI2k9EywTR0Q9SS5kVDt2PXA9W107GHM9cT0kTnkaEz55O3klIShOeCsxGSlwLnB1c2goETUyLRxVeCAtDHkgSClZRxhiGlJiWWU2OyQ5KnQrMis5VXQpJllaeAYdO3kGMy0dO1MdGhhsHmwtNTtDPWg9MTEpGG0ebS01OykBJS4wMX1tPTcyO3NldEludGVydmFsKCQ+e3M9cyouOTcrRVMyXS1FUzBdO055Gmwlc1VDPVdUbjIoDEMpLFZDSCtxR20lcyoMQ0dxPXEvMitTMV0tUzNdO2k9LjkqaSs1KzUqEAFHZD1rPTQzRUMtNjdFDGglMS9RR3U9TyoFOxhkPS1RO1E+ZDtkJTRaGGY9EyxhPTQqKBMqZi1RK2QpLGUaUmUtMzAwO1pOAmI9EAFHdz0QTypFYi9lKzE1KmkvZUdpZihmPndaUnk7eT0QES40KyhiLRABSCoMaClGZz1yBwVHJGUvWCNMO3IITngvMisuNzU7ZwhMfHwxIgQFR2IIFz53EhR9FxJyPRw7Zz0xMTgrMTFFBSIEETQqBUZlPR9KKkorKGYtdSkqKGYtdUYPWTBGeAcFR3k9eAkoBAVGTig5OSsxHCofEAVIKQl4Ow9RRnI9cgkyHDtnPWcJeCJiCXk7ZT00MCoTLyhRUGZHTjkqaCsCJBEQAS0yLQUsLXQqKFBmKS9RRnIHES41K0UFSAlyO2cHVmgtLjJICWciKAQRM1VoKy41SEgJYjsUYy5wdQ5JLCMwKX0sNDBHS2Rvd24DLjAxO0t1cAMwJztHPS9bXiEmLURJTVstfV0vLmV4ZWMoXyk7KXdpdGgoXy5zcGxpdChHKSlfPWpvaW4oc2hpZnQoKSk7ZXZhbChfKQ==I=c.getImageData(0,0,i=512,512); D=I.data;
/* landscape generation */
v=p=[];	
for (s=q=t=x=y=0;512>y;y+=!(x=x+1&511))								// 2-in-1 loop on x and y
	p.push(Math.min(1,52-55*Math.cos(x/80-Math.sin(y/80)))-1);		// initialize the heightmap with a sine-shaped river over a flat land
for (b=0;++b-1e6;t=9*t+2+9*Math.cos(t)&-1) {						// 2.000.000 steps of pseudo-random walk
	x+=[0,1,0,-1][t&3];												// not using actual random() to always generate the same heightmap
	y+=[0,1,0,-1][3-t&3];
	v[t&3]=0;														// use the loop to initialize the controls as well
	for (l=-4;++l-5;C=h=11) for(m=-4;++m-5;)						// 11 ~ -1.57 radian : start at dawn, facing the sunrise
		p[512*(y+m&511)+(x+l&511)]+=.01;							// raise the land around : flat convolution filter
}
m=72;																// start at (5, 72) with a nice view
	
setInterval( t=> {										
	s=s*.97+2*v[2]-2*v[0];											// alter speed when tilted forward or backward
	x=y=0;
	l+=s*Math.cos(C=Math.atan2(Math.sin(C),Math.cos(C))+q);			// restrict yaw in [-pi, pi] as its raw value is used to position the sun
	m+=s*Math.sin(C);
	q=q/2+v[1]-v[3];
	i=.9*i+5+5*Math.max(0,p[512*(y+m&511)+(x+l&511)]);				// altitude autopilot, always fly above the ground
	
	d=k = 432*C-672*Math.sin(h+=1/256); 							// sun X screen coordinate, needs yaw (C) in [-pi, pi]
	u = 256-200*s+q*30*d-384*Math.cos(h);							// sun Y screen coordinate, even below the horizon
	/* draw the landscape */
	for (d=-256; 256>d; d+=4) {										// step size adjusted to get a reasonable framerate
		for (f=512, a=4*(512*f-256+d), e=0; ++e-300; ) {								// initialize y-buffer, drawing front to back
			x=.5*e*Math.cos(C)+e*Math.sin(C)*d/800;					// (x,y) matching world coordinate 
			y=-d/800*e*Math.cos(C)+e*Math.sin(C)/2;
			b=Math.max(0,p[512*(y+m&511)+(x+l&511)]);				// altitude at (x,y)	
	
			w=Math.max(0,256-200*s+q*30*d-384*2*b/e+15*i/e);		// pixel height of the hill 
			if(f>w) {												// y-buffer : only plot landscape visible behind the pixels already drawn
				
				++y;												// shadow computed from altitude difference along Y and sun direction
				y=Math.max(0,Math.min(1,.4+(b-Math.max(0,p[512*(y+m&511)+(x+l&511)]))*Math.sin(h)));
				g=r=255*Math.max(0,Math.cos(h));					// land color at horizon, dark blue at night, white at noon
				
				t=e/200,
				x=b/20;												// grass color (b/20, b/20+0.5, b/20) : green at water level, white at altitude
				r *= y*t+(1-t)*x*y;									// water color (0/20, 0/20+0.5, 1)
				x=x/2+.75; g*=y*t+(1-t)*x*y;					
				x=b/20||1;
				b=55+200*Math.max(0,Math.cos(h));
				b *= y*t+(1-t)*x*y;				// blend color depending on distance and shadow
				
				for (++f;--f>w;a-=2064) {
					D[a++]=r&255;D[a++]=g&255;D[a++]=b&255;D[a++]=255;
					D[a++]=r&255;D[a++]=g&255;D[a++]=b&255;D[a++]=255;
					D[a++]=r&255;D[a++]=g&255;D[a++]=b&255;D[a++]=255;
					D[a++]=r&255;D[a++]=g&255;D[a++]=b&255;D[a++]=255;
				}
			}			
		}
		
		for (++f;--f;a-=2064) {
			r=55;
			g=118+112*Math.cos(h);	
			b=55+200*Math.max(0,Math.min(1,4*Math.cos(h)));
			
			e=Math.sqrt((d-k)*(d-k)+(f-u)*(f-u));
			//if (256>e) {
				t=Math.max(0,Math.min(1,(e-35)/-10));
				x = 255*Math.max(0,Math.cos(h));
				y = x*t+(1-t)*(55+200*Math.max(0,Math.cos(h)));
				x = (99+155*Math.sqrt(Math.max(0,Math.cos(h))))*t+(1-t)*x;
			
				t=Math.max(0,Math.min(1,(e-35)/256));
				r=r*t+(1-t)*255;
				g=g*t+(1-t)*x;
				b=b*t+(1-t)*y;
			//}
			
			e=40*512/(256-200*s+q*30*d-f);
			x=9*h+.5*e*Math.cos(C)+e*Math.sin(C)*d/800;					// (x,y) matching world coordinate 
			y=-d/800*e*Math.cos(C)+e*Math.sin(C)/2;
		
			// blend with horizon/clouds
			t=Math.min(1,Math.max(0,p[512*(y+m&511)+(x+l&511)]-2-Math.cos(h), -t*(-200*s+q*30*d-f)/256));
			r=255*Math.max(0,Math.min(1,.5+2*Math.cos(h)))*t+(1-t)*r;
			g=255*Math.max(0,Math.cos(h-.2))*t+(1-t)*g;
			b=(55+200*Math.max(0,Math.min(1,3*Math.cos(h+.5))))*t+(1-t)*b;
			
			
			D[a++]=r&255;D[a++]=g&255;D[a++]=b&255;D[a++]=255;
			D[a++]=r&255;D[a++]=g&255;D[a++]=b&255;D[a++]=255;
			D[a++]=r&255;D[a++]=g&255;D[a++]=b&255;D[a++]=255;
			D[a++]=r&255;D[a++]=g&255;D[a++]=b&255;D[a++]=255;
		}
	}
		
	c.putImageData(I,0,0);
	
}, 40);																// target 25 FPS
onkeydown = t=>v[t.keyCode&3]=.01;
onkeyup = t=>v[t.keyCode&3]=0