// human-based random experiment - elout de kok ©2003
//
// javac humanramdom02.java
// compiled with the 'old' jdk 1.1.6 
// so it can run in a browser - without the need to download and install a recent java-browser plugin



import java.applet.*;
import java.awt.*;
import java.applet.Applet;
import java.awt.image.*;
import java.net.*;
import java.io.*;

public class humanrandom02 extends Applet implements Runnable
{	
	Thread animatorThread;
	MemoryImageSource goofImage;
	Dimension offDimension;
	Image offImage;
	Graphics offGraphics;
	Image memimg;

	private int w=620;
	private int h=300;

	public int pix[] = new int[w*h];
	private int ytable[]=new int[h];

	//randomtable  pre-buffer stuff
	int maxrandomnumbers=100;  // make this buffer bigger gives more random variation
	public int radoz[] = new int[maxrandomnumbers];  // random buffer
	int rstep;
	int rpos;
	int rmover;

	//randomstuff from the user interaction
	int mouserchange,oldmouserchange, mouserpos,mousemovedtillnow;

	public void init() 
	{
		goofImage = new MemoryImageSource(w, h, ColorModel.getRGBdefault(), pix, 0, w);
		goofImage.setAnimated(true);
		memimg = createImage(goofImage);

		//set y-table
		for (int y=0;y<h;y++ ){ ytable[y]=y*w;} 

		//precalculate randomtable
		for (int i=0; i<maxrandomnumbers; i++)
		{
			//radoz[i]=Randomize(255); //not used anymore
			radoz[i]=0;	//start with zero/black
		}
		rstep=1;
		rpos=0;
		rmover=0;
		//
		mouserpos=0;
		mousemovedtillnow=51;
	}	

	public void start() 
	{
		if (animatorThread == null)
		{
			animatorThread = new Thread(this);
			animatorThread.start();
		}
	}
	
	public void stop() 
	{
		if (animatorThread != null)
		{
			animatorThread.stop();
			animatorThread = null;
		}		
	}
	public void run()
	{
		Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
		while (Thread.currentThread() == animatorThread)
		{ 
			repaint();
			try { Thread.sleep(10); }
			catch (InterruptedException e) { }
		}
	}
	public void paint(Graphics g)
	{
		update(g);
	}
	public void update(Graphics g)
	{
		Dimension d = size();

		if ( (offGraphics == null) || (d.width != offDimension.width) || (d.height != offDimension.height) )
		{
			offDimension = d;
			offImage = createImage(d.width, d.height);
			offGraphics = offImage.getGraphics();
		}
		
		//fill the screen with the numbers
		for (int col=0, i=0;i<h;i++)
		{
			for (int j=0;j<w;j++)
			{
				col=Randooz();
				drawpoint(pix,j, i, col, col, col);
			}
		}

		goofImage.newPixels(0, 0, w, h);
		offGraphics.drawImage(memimg, 0,0, d.width, d.height, this);
		g.drawImage(offImage, 0, 0, this);
	}


	public synchronized boolean mouseMove(Event evt, int x, int y)
	{
		oldmouserchange=mouserchange;
		mouserchange=(x+y)%255;
		if (mouserchange != oldmouserchange)
		{
			if (mousemovedtillnow != maxrandomnumbers)
			{
				mousemovedtillnow++;
			}
			radoz[mouserpos] = mouserchange;
			mouserpos++;
			if (mouserpos>=maxrandomnumbers)
			{
				mousemovedtillnow=maxrandomnumbers;
				mouserpos=0;
			}
		}
		return true;
	}

	public synchronized  boolean mouseEnter(Event evt, int x, int y) 
	{
		requestFocus();
		showStatus("© Elout de Kok - www.xs4all.nl/~elout/");
		return true;
	}

	//not used anymore
	private final int Randomize(int range)
	{
		double  rawResult;
		rawResult = Math.random();
		return (int) (rawResult * range);
	}

	//------------Randomize from int-buffer (pre-calculated - faster than calculating random all the time)--------
	private int Randooz()
	{	
		rpos=rpos+rstep; 
		if (rpos>=mousemovedtillnow) 
		{
			rmover++;
			if (rmover>=mousemovedtillnow)
			{
				rmover=radoz[0]%6;
			}
			rstep=(radoz[radoz[rmover]%mousemovedtillnow]%6)+1;	//new random step -- Randomize(20)+1;
			rpos=(radoz[radoz[rmover]%mousemovedtillnow]%6);		//new randombuffer position --Randomize(20);
		}
		return (int) (radoz[rpos]);	
	}

	public final void drawpoint(int background[],int xpos, int ypos, int r0, int g0, int b0)
	{
		background[ytable[ypos] + xpos] =  ((0xff<<24) | (r0<<16) | (g0<<8) | b0);
	}

	public final void addrandompixel(int source[],int destination[],int width, int height)
	{
		//		addrandompixel(mypix1,pix,w,h);
		int r0,g0,b0,col,posi;

		for (int i=0;i<height ;i++)
		{
			for (int j=0;j<width ;j++)
			{
				posi= ytable[i] + j;
				col=Randooz();
				r0=(((source[posi] >> 16) & 0xff) + col)/2;
				g0=(((source[posi] >>  8) & 0xff) + col)/2;
				b0=((source[posi] & 0xff) + col)/2;
				if (r0>255){r0=255;}
				if (g0>255){g0=255;}
				if (b0>255){b0=255;}
				destination[posi] =  ((0xff<<24) | (r0<<16) | (g0<<8) | b0);
			}
		}

	}

	//--------------------------copy arrays--------------------------------------------
	public final void copyar(int fpix1[], int fpix2[],int w,int h) // source, destination
	{	
		System.arraycopy(fpix1, 0, fpix2, 0, w*h);
	}

}
