import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.net.*;
import sun.audio.*;

public final class noids extends java.applet.Applet implements Runnable
{
	int i,j,k,l,m,n,o,p,q,di,dj,dk,dl,ai,mi,mj,counter=0,gameState=0,nextState=0,seed=1;
	double sc;
	int score,newScore,scoreCount,totalDroids;
	int mapH,mapW,layer,newLayer,newPos=0;
	int baseX,baseY,screenX,screenY,removeX,removeY;
	int moveDir=0,lastDir,droidNum=0,newEnergy,currSound=0,pressedKey=0;
	int pBullet,pBCost,pArmor,killed;
	int moveKey[]={0,'i','k','j','l'};
	boolean firing=false,influence=false,holdBullet=false,holdBCost=false,
		holdArmor=false,updateFinished=true;
	Color duelCol[]={Color.white,Color.red,Color.black},cols[]={Color.red,Color.yellow,
		Color.green,Color.blue,Color.gray};
	final Color presCol[]={new Color(0,0,0),new Color(48,48,48),new Color(96,96,96),
		new Color(144,144,144)},scoreCol=new Color(153,255,153);
	int presColVal[]={0,80,160,239};
		
	int eImp,pImp,eIY,pIY,eMove,eType,pType,eNum,leading;
	int impLength[]={0,23,9,23,9,23,0,0,0,24,9,23,9,23},
		impX[]={0,9,32,41,64,73,0,0,0,144,168,177,200,209,232};
	int impListL[]=new int[50],impListX[]=new int[50],impListY[]=new int[50],
		impListCol[]=new int[50],impNum1,impNum2;
	int handX[]=new int[50],handY[]=new int[50],endPos[][]=new int[12][3],
		endVal[][]=new int[12][3];
	
	final int cyclic[]={0,1,2,1};
	
	final int parDX[]={0,6,0,-6},parDY[]={6,0,-6,0},parXlim1[]={0,1,0,211},
		parYlim1[]={1,0,211,0},parXlim2[]={0,211,0,1},parYlim2[]={211,0,1,0};
	
	int map[][]=new int[10][],mainMap[],propMap[];
	int background[]=new int[10],layerH[]=new int[10],layerW[]=new int[10],
		layerParent[]=new int[10];
	int exitPos[][]=new int [10][25],exitToPos[][]=new int[10][25],
		entrancePos[][]=new int[10][25],entranceLayer[][]=new int[10][25],
		entranceCount[]=new int[10];
	int droidX[][]=new int [10][40],droidY[][]=new int[10][40],droidTX[][]=new int[10][40],
		droidTY[][]=new int[10][40],droidBX[][]=new int [10][40],droidBY[][]=new int[10][40],
		droidType[][]=new int[10][40];

	int duelMap[][]=new int[12][15];

	int objX[]=new int[41],objY[]=new int[41],objType[]=new int[41],
		objDir[]=new int[41],objLook[]=new int[41],objEnergy[]=new int[41],
		objPar1[]=new int[41],objPar2[]=new int[41],objPar3[]=new int[41],
		objPar4[]=new int[41],origDroid[]=new int[41];

	int drawNum[]=new int[10],drawX[]=new int[10],drawY[]=new int[10],drawCount;

	int bullX[]=new int[10],bullY[]=new int[10],bullDir[]=new int[10],
		bullType[]=new int[10],bullets;
	int bullSpeed[]={0,12,13,13,12,12,12};
	int bullWidth[]={0,3,3,4,10,6,4};
	int bullLength[]={0,10,10,8,10,6,10};
	int bullPower[]={0,3,4,5,6,3,6};
	int bullCost[]={0,6,8,9,7,6,8};
	int blastX[]=new int[10],blastY[]=new int[10],blastType[]=new int[10],blasts=0;

// Various scrolling constants
	final int BmoveX[]={240,312,384,456, 240,312,384,456, 240,240,240,240, 264,264,264,264};
	final int BmoveY[]={0,0,0,0, 24,24,24,24, 0,72,144,216, 0,72,144,216};
	final int BmoveW[]={72,72,72,72, 72,72,72,72, 264,264,264,264, 264,264,264,264};
	final int BmoveH[]={264,264,264,264, 264,264,264,264, 72,72,72,72, 72,72,72,72};
	final int BmovedX[]={0,0,0,0, 0,0,0,0, 24,24,24,24, -24,-24,-24,-24};
	final int BmovedY[]={24,24,24,24, -24,-24,-24,-24, 0,0,0,0, 0,0,0,0};
	final int BcopyX1[]={264,264,264,264, 264,264,264,264, 282,276,270,264, 246,252,258,264};
	final int BcopyY1[]={42,36,30,24, 6,12,18,24, 24,24,24,24, 24,24,24,24};
	final int BcopyW1[]={48,120,192,240, 48,120,192,240, 240,240,240,240, 240,240,240,240};
	final int BcopyH1[]={240,240,240,240, 240,240,240,240, 48,120,192,240, 48,120,192,240};
	final int BcopyX2[]={312,384,456,0, 312,384,456,0, 258,252,246,0, 270,276,282,0};
	final int BcopyY2[]={18,12,6,0, 30,36,42,0, 72,144,216,0, 72,144,216,0};
	final int BcopyW2[]={192,120,48,0, 192,120,48,0, 240,240,240,240, 240,240,240,240};
	final int BcopyH2[]={240,240,240,240, 240,240,240,240, 192,120,48,0, 192,120,48,0};
	final int BcopydX2[]={-264,-264,-264,0, -264,-264,-264,0, -258,-252,-246,0, -270,-276,-282,0};
	final int BcopydY2[]={-18,-12,-6,0, -30,-36,-42,0, -24,-24,-24,-24, -24,-24,-24,-24};
	final int BdataX[]={0,3,6,9, 0,3,6,9, -1,-1,-1,-1, 12,12,12,12};
	final int BdataY[]={-1,-1,-1,-1, 12,12,12,12, 0,3,6,9, 0,3,6,9};
	final int BdataToX[]={0,3,6,9, 0,3,6,9, 0,0,0,0, 11,11,11,11};
	final int BdataToY[]={0,0,0,0, 11,11,11,11, 0,3,6,9, 0,3,6,9};
	final int BdatadX[]={1,1,0,0},BdatadY[]={0,0,1,1},BshiftX[]={0,0,0,-1,1},
		BshiftY[]={0,-1,1,0,0};
	int scrollDir=0,scrollCount=0;
	
	final int prop[]={0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,0,0,4,2,2,2,2,0,0,0,0,1,1,1,1,1,1,1,1,1,1,
		1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
		0,0,0,0,0,0,0,0,0,0,8,0,0,4,1,1,1,1,0,0,0,0,
		0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,
		4,1,1,1,1,1,16,8,1,1,1,1,1,1,1,1,1,1,1,1,1,0};
	final int batteries[]={25,0,79,72,110,109};
	
	final int drNumber[]={0,100,331,319,337,710, 140,521,919, 510,557,165,951};
	final int drLook[]={0,0,4,4,4,12, 0,8,16, 8,8,0,16};
	final int drSpeed[]={0,3,4,3,5,4, 3,4,5, 3,4,5,4};
	final int drOS[]={0,1,3,2,2,5, 2,4,7, 5,3,3,9};
	final int drBullet[]={0,0,2,0,0,2, 0,3,4, 5,0,0,6};
	final int drArmor[]={1,1,3,3,3,3, 2,3,4, 4,4,2,5};
	final int drStrength[]={2,1,2,3,4,3, 2,3,3, 1,6,2,5};
	int serialX[]=new int[20],serialY[]=new int[20];
	
	int highscores[]={0,0,0,0,0,0,0,0};
	String highnames[]={"-","-","-","-","-","-","-","-"},s;
	
	boolean menuOn=true,drawCoords=false;
	Image backIm,mobiles[]=new Image[53],ctrlTop,ctrlBot,smalls[]=new Image[12],
		scoreIm,OK;
	Graphics backG,clipG,scoreG;
	Font bigF,smallF,miniF;
	FontMetrics bigFM,smallFM;
	String ss[]={"GAME OVER","SUCCESS","FAILURE","DEADLOCK","HIGHSCORES","PAUSED",
		"Your name, please", "ALL DONE!","YOU","DROID","BATTERY"};
	String cityName="city.dat";
	InputStream soundStream[]=new AudioDataStream[9];
	int soundLengths[]={8192,8192,8192,4096,8192,8192,4096,4096,8192};
	byte rawAudio[][]=new byte[9][];
	MediaTracker mt;
	long nextTime,waitTime=80;
	Thread game;

	public void init()
	{
		backIm=createImage(528,432);
		backG=backIm.getGraphics();
		clipG=backIm.getGraphics();
		clipG.clipRect(0,0,240,240);
		scoreIm=createImage(74,16);
		scoreG=scoreIm.getGraphics();
		mt=new MediaTracker(this);
		loadGraphics();
		bigF=new Font("Helvetica",Font.BOLD,18);
		bigFM=getFontMetrics(bigF);
		miniF=new Font("Helvetica",Font.PLAIN,10);
		smallF=new Font("Helvetica",Font.BOLD,14);
		smallFM=getFontMetrics(smallF);
		scoreG.setFont(smallF);
		makeSounds();
		
		System.gc();
		for (i=0;i<20;i++)
		{
			serialX[i]=18*((i-1)%13);
			serialY[i]=264+8*((i-1)/13);
		}
		for (i=0;i<50;i++)
		{
			handX[i]=(int)(119.0+14.0*Math.sin(0.12566*i));
			handY[i]=(int)(221.0-14.0*Math.cos(0.12566*i));
		}
		prepareIntro();
	}

	public void loadGraphics()
	{
		Image collection,big;
		ImageProducer improd;
		collection = getImage(getCodeBase(),"noids.gif");
		mt.addImage(collection,0);
		big = getImage(getCodeBase(),"pieces.gif");
		mt.addImage(big,0);
		try
		{
			mt.waitForID(0);
		}
			catch(InterruptedException e) {}
		improd=collection.getSource();
			
		for (i=0;i<44;i++)
		{
			mobiles[i]=createImage(new FilteredImageSource(improd,
				new CropImageFilter(28*(i%12),28*(i/12),28,28)));
			mt.addImage(mobiles[i],1);
		}
		for (i=0;i<3;i++)
		{
			mobiles[44+i]=createImage(new FilteredImageSource(improd,
				new CropImageFilter(240+32*i,84,32,32)));
			mt.addImage(mobiles[44+i],1);
		}
		j=151;
		for (i=0;i<3;i++)
		{
			mobiles[47+i]=createImage(new FilteredImageSource(improd,
				new CropImageFilter(j,112,20+4*i,20+4*i)));
			mt.addImage(mobiles[47+i],1);
			mobiles[50+i]=createImage(new FilteredImageSource(improd,
				new CropImageFilter(j+72,116,20+4*i,20+4*i)));
			mt.addImage(mobiles[50+i],1);
			j+=(20+4*i);
		}
		ctrlTop=createImage(new FilteredImageSource(improd,
			new CropImageFilter(93,112,58,27)));
		mt.addImage(ctrlTop,1);
		ctrlBot=createImage(new FilteredImageSource(improd,
			new CropImageFilter(0,112,57,44)));
		mt.addImage(ctrlBot,1);
		OK=createImage(new FilteredImageSource(improd,
			new CropImageFilter(93,139,32,17)));
		mt.addImage(OK,1);
		for (i=0;i<12;i++)
		{
			smalls[i]=createImage(new FilteredImageSource(improd,
				new CropImageFilter(57+9*(i%4),112+12*(i/4),9,12)));
			mt.addImage(smalls[i],1);
		}
		try
		{
			mt.waitForID(1);
		}
			catch(InterruptedException e) {}
		backG.drawImage(big,0,264,this);
		backG.copyArea(288,264,240,23,-288,-24);
		backG.copyArea(378,277,150,5,-288,5); // Energy meter
	}
	
	public void makeSounds() // Create AudioDataStream sounds
	{
		byte audioTable[]=new byte[8192];
		
		for (i=0;i<9;i++)
			rawAudio[i]=new byte[soundLengths[i]];

		i=32; // Fix 8-bit audio conversion table
		m=32;
		j=1;
		l=1;
		n=255;
		o=0;
		for (k=0;k<7;k++)
		{
			while (l<m)
			{
				audioTable[4096+l]=(byte)(n-((l-o) >>> j));
				audioTable[l]=(byte)(audioTable[4096+l]&0x7f);
				l++;
			}
			j++;
			n-=16;
			i*=2;
			o=m;
			m+=i;
		}
		audioTable[0]=(byte)255;
		audioTable[4096]=(byte)255;

		j=16384; // Player bullet sound
		k=0;
		l=4095;
		for (i=0;i<8192;i++)
		{
			k+=j--;
			l=(l*4093)>>12;
			rawAudio[0][i]=audioTable[l+((k&32768)>>3)];
		}
		j=16384; // Explosion
		k=1;
		l=4095;
		for (i=0;i<8192;i++)
		{
			k=(k*171)&32767;
			l=(l*4094)>>12;
			rawAudio[1][i]=audioTable[((k&16384)+(k&3)*l)>>2];
		}
		j=8191; // Weird
		k=0;
		l=3500;
		for (i=0;i<8192;i++)
		{
			k+=j;
			j=(j+8186)&8191;
			l=(l*4095)>>12;
			rawAudio[2][i]=audioTable[l+((k&32768)>>3)];
		}
		k=0; // "Plink"
		j=2;
		l=3000;
		for (i=0;i<4096;i++)
		{
			j=(j*171)&32767;
			k+=9000+(j&511);
			l=(l*4092)>>12;
			rawAudio[3][i]=audioTable[l+((k&32768)>>3)];
		}
		j=8191; // Enemy bullet
		k=0;
		l=4095;
		for (i=0;i<8192;i++)
		{
			k+=j;
			j=(j+8188)&8191;
			l=(l*4094)>>12;
			rawAudio[4][i]=audioTable[l+((k&32768)>>3)];
		}
		j=5; // Battery
		k=0;
		l=4095;
		for (i=0;i<8192;i++)
		{
			k+=j;
			j=(j+7)&8191;
			l=(l*4095)>>12;
			rawAudio[5][i]=audioTable[l+((k&32768)>>3)];
		}
		k=1; // Small puff
		l=3000;
		for (i=0;i<4096;i++)
		{
			k=(k*171)&32767;
			l=(l*4092)>>12;
			rawAudio[6][i]=audioTable[l+(k&4096)];
		}
		j=14000; // Impulse sound
		k=0;
		l=3400;
		for (i=0;i<4096;i++)
		{
			k+=j;
			j-=2;
			l=(l*4092)>>12;
			rawAudio[7][i]=audioTable[l+((k&32768)>>3)];
		}
		j=5; // Failure
		k=0;
		l=4095;
		for (i=0;i<8192;i++)
		{
			k+=j;
			j=(j+4089)&4095;
			l=(l*4095)>>12;
			rawAudio[8][i]=audioTable[l+((k&32768)>>3)];
		}
		for (i=0;i<9;i++)
		{
			soundStream[i]=new AudioDataStream(new AudioData(rawAudio[i]));
			soundStream[i].mark(10000);
		}
	}

	public void prepareIntro()
	{
		k=0;
		for (i=0;i<240;i++)
		{
			j=239-i+k;
			m=200;
			n=0;
			for (l=0;l<4;l++)
			{
				if (Math.abs(presColVal[l]-j)<m)
				{
					m=Math.abs(presColVal[l]-j);
					n=l;
				}
			}
			k=j-presColVal[n];
			backG.setColor(presCol[n]);
			backG.drawLine(264,24+i,504,24+i);
		}
		backG.setFont(smallF);
		for (i=0;i<4;i++)
			objY[i]=-50;
		gameState=1;
		firing=false;
		influence=false;
		counter=0;
	}

	public void run()
	{
		while (game!=null)
		{
			try
			{
				game.sleep(Math.max(25,nextTime-System.currentTimeMillis()));
			} catch (InterruptedException e) {}
			nextTime=System.currentTimeMillis()+waitTime;
			counter++;
			switch(gameState)
			{
				case 0:
					backG.copyArea(264,24,240,240,-264,-24);
					break;
				case 1: // Highscore intro
					if (counter<=180)
					{
						if ((counter%20)==1)
							backG.copyArea(306,54+counter,198,14,0,215-counter);
						else if ((counter%20)==2)
						{
							backG.setColor(Color.white);
							if (counter==2)
								backG.drawString(ss[4],384-smallFM.stringWidth(ss[4])/2,282);
							else
							{
								j=counter/20-1;
								backG.drawString((j+1)+".  "+highnames[j],306,281);
								s=""+highscores[j];
								backG.drawString(s,462-smallFM.stringWidth(s),281);
							}
						}
						else
						{
							j=(counter-2)/20;
							k=(counter-2)%20;
							backG.copyArea(306,269,k*11,14,198-11*k,-214+20*j);
						}
					}
					backG.copyArea(264,24,240,240,-264,-24);
					for (i=0;i<4;i++)
					{
						if ((objY[i]<-30)||(objY[i]>242)||(objX[i]<-30)||(objX[i]>242))
						{
							j=(randi()>>2)&3;
							switch(j)
							{
								case 0:
									objY[i]=-29;
									objX[i]=13+6*((randi()>>2)&31);
									break;
								case 1:
									objX[i]=-29;
									objY[i]=13+6*((randi()>>2)&31);
									break;
								case 2:
									objY[i]=241;
									objX[i]=13+6*((randi()>>2)&31);
									break;
								default:
									objX[i]=241;
									objY[i]=13+6*((randi()>>2)&31);
									break;
							}
							objType[i]=1+(randi()%24)/2;
							objDir[i]=j;
							objPar1[i]=0;
							k=0;
							for (j=0;j<4;j++)
								if ((i!=j)&&((objX[i]-objX[j])*(objX[i]-objX[j])+
									(objY[i]-objY[j])*(objY[i]-objY[j])<6400))
									k++;
							if (k>0)
								objY[i]=-50;
						}
						else
						{
							k=objDir[i];
							objX[i]+=parDX[k];
							objY[i]+=parDY[k];
							if (objX[i]==parXlim1[k] || objY[i]==parYlim1[k])
							{
								objDir[i]=(k+3)&3;
								objPar1[i]=1;
							}
							else if (objX[i]==parXlim2[k] || objY[i]==parYlim2[k])
								objDir[i]=(k+1)&3;
							j=objType[i];
							k=objX[i];
							l=objY[i];
							clipG.drawImage(mobiles[drLook[j]+(counter&3)],k,l,this);
							backG.copyArea(serialX[j],serialY[j],Math.max(0,Math.min(18,235-k)),
								Math.max(0,Math.min(8,230-l)),k-serialX[j]+5,l-serialY[j]+10);
							if ((((randi()>>2)&127)==0)&&(objPar1[i]==1))
							{
								objDir[i]=(objDir[i]+3)&3;
								objPar1[i]=2;
							}
						}
					}
/*					if (firing)
						prepareGame();*/
					break;
				case 8: // Paused
					if (counter==1)
					{
						backG.setFont(smallF);
						backG.setColor(Color.black);
						j=smallFM.stringWidth(ss[5]);
						backG.fillRoundRect(2,2,j+12,21,12,12);
						backG.setColor(Color.white);
						backG.drawString(ss[5],8,18);
					}
					break;
				case 9: // Transitional state
					if (counter>=1)
					{
						clipG.setColor(Color.black);
						clipG.fillRect(0,120-6*counter,240,6);
						clipG.fillRect(0,114+6*counter,240,6);
					}
					if (counter>20)
					{
						counter=0;
						gameState=nextState;
						switch(gameState)
						{
							case 1:
								try{
									getAppletContext().showDocument(new
										URL(getCodeBase(),"tpantext.html"),"info");
								}
								catch(MalformedURLException ex){System.out.println("Darn!");}
								prepareIntro();
								break;
							case 10:
								prepareGame();
							default:
								break;
						}
					}
					break;
				case 10:
					if (objType[0]<50) // Normal mode
					{
					k=(objX[0]+2)/24+mapW*((objY[0]+2)/24);
					l=0;
					switch (moveDir)
					{
						case 1:
							if (objY[0]%24==22)
							{
								j=objX[0]%24;
								if (j==22)
								{
									if ((propMap[k-mapW]&3)==0)
										l=1;
								}
								else if (j==4)
								{
									if ((propMap[k-mapW]&3)==0)
										if ((propMap[k-mapW+1]&3)==0)
											l=1;
										else
											objDir[0]=3;
								}
								else if (j==10)
								{
									if (((propMap[k-mapW]&3)==0)&&
										((propMap[k-mapW+1]&3)==0))
										l=1;
								}
								else
								{
									if ((propMap[k-mapW+1]&3)==0)
										if ((propMap[k-mapW]&3)==0)
											l=1;
										else
											objDir[0]=4;
								}
								if (l>0)
								{
									if (objY[0]-screenY>70)
										objDir[0]=1;
									else
										if (scrollDir==0)
										{
											objDir[0]=1;
											scrollDir=1;
											scrollCount=0;
										}
								}
							}
							else
								objDir[0]=1;
							break;
						case 2:
							if (objY[0]%24==22)
							{
								j=objX[0]%24;
								if (j==22)
								{
									if ((propMap[k+mapW]&3)==0)
										l=1;
								}
								else if (j==4)
								{
									if ((propMap[k+mapW]&3)==0)
										if ((propMap[k+mapW+1]&3)==0)
											l=1;
										else
											objDir[0]=3;
								}
								else if (j==10)
								{
									if (((propMap[k+mapW]&3)==0)&&
										((propMap[k+mapW+1]&3)==0))
										l=1;
								}
								else
								{
									if ((propMap[k+mapW+1]&3)==0)
										if ((propMap[k+mapW]&3)==0)
											l=1;
										else
											objDir[0]=4;
								}
								if (l>0)
								{
									if (objY[0]-screenY<142)
										objDir[0]=2;
									else
										if (scrollDir==0)
										{
											objDir[0]=2;
											scrollDir=2;
											scrollCount=0;
										}
								}
							}
							else
								objDir[0]=2;
							break;
						case 3:
							if (objX[0]%24==22)
							{
								j=objY[0]%24;
								if (j==22)
								{
									if ((propMap[k-1]&3)==0)
										l=1;
								}
								else if (j==4)
								{
									if ((propMap[k-1]&3)==0)
										if ((propMap[k-1+mapW]&3)==0)
											l=1;
										else
											objDir[0]=1;
								}
								else if (j==10)
								{
									if (((propMap[k-1]&3)==0)&&
										((propMap[k-1+mapW]&3)==0))
										l=1;
								}
								else
								{
									if ((propMap[k-1+mapW]&3)==0)
										if ((propMap[k-1]&3)==0)
											l=1;
										else
											objDir[0]=2;
								}
								if (l>0)
								{
									if (objX[0]-screenX>70)
										objDir[0]=3;
									else
										if (scrollDir==0)
										{
											objDir[0]=3;
											scrollDir=3;
											scrollCount=0;
										}
								}
							}
							else
								objDir[0]=3;
							break;
						case 4:
							if (objX[0]%24==22)
							{
								j=objY[0]%24;
								if (j==22)
								{
									if ((propMap[k+1]&3)==0)
										l=1;
								}
								else if (j==4)
								{
									if ((propMap[k+1]&3)==0)
										if ((propMap[k+mapW+1]&3)==0)
											l=1;
										else
											objDir[0]=1;
								}
								else if (j==10)
								{
									if (((propMap[k+1]&3)==0)&&
										((propMap[k+mapW+1]&3)==0))
										l=1;
								}
								else
								{
									if ((propMap[k+mapW+1]&3)==0)
										if ((propMap[k+1]&3)==0)
											l=1;
										else
											objDir[0]=2;
								}
								if (l>0)
								{
									if (objX[0]-screenX<142)
										objDir[0]=4;
									else
										if (scrollDir==0)
										{
											objDir[0]=4;
											scrollDir=4;
											scrollCount=0;
										}
								}
							}
							else
								objDir[0]=4;
							break;
						case 5:
							k=(objX[0]+14)/24+mapW*((objY[0]+14)/24);
							if ((propMap[k]&8)>0)
							{
								l=0;
								while (entrancePos[layer][l]!=k)
									l++;
								newLayer=entranceLayer[layer][l];
								l=0;
								while (exitToPos[newLayer][l]!=k)
									l++;
								newPos=exitPos[newLayer][l];
								counter=0;
								gameState=11;
							}
							break;
						case 6:
							k=(objX[0]+14)/24+mapW*((objY[0]+14)/24);
							if ((propMap[k]&16)>0)
							{
								l=0;
								while (exitPos[layer][l]!=k)
									l++;
								newLayer=layerParent[layer];
								newPos=exitToPos[layer][l];
								counter=0;
								gameState=11;
							}
							break;
						default:
							break;
					}
					if (objDir[0]>0)
					{
						propMap[k]=(propMap[k]&31)+(objDir[0]<<5)+(counter<<8);
						lastDir=objDir[0];
						objX[0]+=6*BshiftX[objDir[0]];
						objY[0]+=6*BshiftY[objDir[0]];
						objLook[0]=21+3*objDir[0]+cyclic[counter&3];
						objDir[0]=0;
						
						j=(objX[0]+14)/24;
						k=(objY[0]+14)/24;
						l=j+mapW*k;
						if ((propMap[l]&4)>0) // Battery found
						{
							m=0;
							while (batteries[m]!=mainMap[l])
								m+=2;
							mainMap[l]=batteries[m+1];
							propMap[l]=0;
							map[layer][j-4+(mapW-8)*(k-4)]=mainMap[l];
							
							j-=baseX;
							k-=baseY;
							if ((scrollCount==3)||((k<6)&&(scrollCount==2)))
									j-=BshiftX[scrollDir];
							if ((scrollCount==3)||((j<6)&&(scrollCount==2)))
									k-=BshiftY[scrollDir];
							drawBlock(mainMap[l],j,k);
							newEnergy+=100;
							newScore+=25;
							playSound(5);
						}
					}
					
					if ((firing)&&(bullType[0]==0))
					{
						bullX[0]=objX[0]+14;
						bullY[0]=objY[0]+14;
						bullDir[0]=lastDir;
						if (drBullet[objType[0]]==0)
							bullType[0]=1;
						else
							bullType[0]=drBullet[objType[0]];
						newEnergy-=pBCost;
						playSound(0);
					}
					}
					else // Player exploding
					{
						objPar1[0]++;
						if (objPar1[0]>43)
							objX[0]=-50;
						else
							objLook[0]=objPar1[0];
						if ((scrollDir==0)&&(objPar2[0]>0))
						{
							backG.drawImage(mobiles[36],objX[0]-screenX+264,objY[0]-screenY+24,this);
							objPar2[0]=0;
						}
						if (objPar1[0]>65)
						{
							gameState=12;
							counter=0;
						}
					}
					
					if ((counter&63)==0 && newEnergy>0 && objType[0]<50)
						newEnergy--;		
					if (newEnergy!=objEnergy[0]) // Energy check
					{
						if (newEnergy<objEnergy[0])
						{
							if (newEnergy<=0) // All empty? Explode
							{
								playSound(1);
								if (objType[0]==0)
								{
									newEnergy=0;
									objPar1[0]=36;
									objType[0]=50;
									objPar2[0]=1;
								}
								else
								{
									newEnergy=10;
									objType[0]=0;
									setSomeProperties(1,3,6);
									addBlast(objX[0]+14,objY[0]+14,4);
								}
							}
							backG.setColor(Color.black);
							backG.fillRect(90+newEnergy,253,objEnergy[0]-newEnergy,5);
						}
						else
						{
							if (newEnergy>150)
								newEnergy=150;
							backG.copyArea(90,282,newEnergy,5,0,-29);
						}
						objEnergy[0]=newEnergy;
					}
					
					if (scrollDir>0) // Scroll screen
					{
						screenX+=6*BshiftX[scrollDir];
						screenY+=6*BshiftY[scrollDir];
						i=scrollDir*4+scrollCount-4;
						backG.copyArea(BmoveX[i],BmoveY[i],BmoveW[i],BmoveH[i],
							BmovedX[i],BmovedY[i]);
						backG.copyArea(BcopyX1[i],BcopyY1[i],BcopyW1[i],BcopyH1[i],
							-BcopyX1[i],-BcopyY1[i]);
						if (scrollCount<3)
							backG.copyArea(BcopyX2[i],BcopyY2[i],BcopyW2[i],BcopyH2[i],
							BcopydX2[i],BcopydY2[i]);
						scrollCount++;
						k=baseX+BdataX[i]+mapW*(baseY+BdataY[i]);
						l=BdataToX[i];
						m=BdataToY[i];
						for (j=0;j<3;j++)
						{
							drawBlock(mainMap[k],l,m);
							k+=BdatadX[scrollDir-1]+mapW*BdatadY[scrollDir-1];
							l+=BdatadX[scrollDir-1];
							m+=BdatadY[scrollDir-1];
						}
						if (scrollCount==4)
						{
							baseX+=BshiftX[scrollDir];
							baseY+=BshiftY[scrollDir];
							scrollDir=0;
						}
					}
					else
						backG.copyArea(264,24,240,240,-264,-24);

					// Droids
					drawCount=0;
					for (i=1;i<droidNum;i++)
					{
						j=objType[i];
						if (j>0)
						{
							if (j<50)
							{
							objLook[i]=drLook[j]+(counter&3);
							if (objDir[i]>0)
							{
								objX[i]+=drSpeed[j]*BshiftX[objDir[i]];
								objY[i]+=drSpeed[j]*BshiftY[objDir[i]];
							}
							l=objDir[i];
							switch(l)
							{
								case 1:
									k=(7198-objY[i])%24;
									break;
								case 2:
									k=(objY[i]+2)%24;
									break;
								case 3:
									k=(7198-objX[i])%24;
									break;
								case 4:
									k=(objX[i]+2)%24;
									break;
								default:
									k=0;
									break;
							}
							if (k<drSpeed[j])
							{
								if (l>0)
								{
									if (randi()<4000)
										if (l<3)
											l=((randi()&2)>>1)+3;
										else
											l=((randi()&2)>>1)+1;
								}
								else
									l=((randi()&6)>>1)+1;
								
								m=(objX[i]+14)/24+mapW*((objY[i]+14)/24);
								if ((counter-propMap[m]>>8)<80 &&
									(randi()<drOS[objType[i]]*300))
									l=(propMap[m]&224)>>5;
								if ((l>0)&&((propMap[m+BshiftX[l]+
									mapW*BshiftY[l]]&7)>0))
									l=0;
								if (((l==1)&&(objY[i]<=objPar2[i]))||
									((l==2)&&(objY[i]>=objPar4[i]))||
									((l==3)&&(objX[i]<=objPar1[i]))||
									((l==4)&&(objX[i]>=objPar3[i])))
									l=0;
								
								if (l!=objDir[i])
								{
									objX[i]+=k*(BshiftX[l]-BshiftX[objDir[i]]);
									objY[i]+=k*(BshiftY[l]-BshiftY[objDir[i]]);
									objDir[i]=l;
								}
								if (objEnergy[i]<1)
								{
									newScore+=drNumber[objType[i]];
									objType[i]=50;
									objLook[i]=37;
									killed++;
									playSound(1);
								}
							}
							}
							else
							{
								objLook[i]++;
								if (objLook[i]>43)
								{
									objType[i]=0;
									objX[i]=-50;
									if (killed==totalDroids) // All done
									{
										gameState=17;
										counter=0;
									}
								}
							}
							k=objX[i]-screenX;
							l=objY[i]-screenY;
							if ((k>-28)&&(k<240)&&(l>-28)&&(l<240))
							{
								drawNum[drawCount]=i;
								drawX[drawCount]=k;
								drawY[drawCount++]=l;
								
								if (objType[i]<50 && objType[0]<50)
								{
									if ((objX[i]-objX[0])*(objX[i]-objX[0])+
										(objY[i]-objY[0])*(objY[i]-objY[0])<780) // Touch player
									{
										if (influence)
										{
											gameState=13;
											counter=0;
											eType=objType[i];
											eNum=i;
										}
										else
										{
											if ((randi()&24)==0)
												playSound(6);
											if (drStrength[objType[i]]>pArmor)
												newEnergy-=(drStrength[objType[i]]-pArmor);
											if (drStrength[objType[0]]>drArmor[objType[i]])
												objEnergy[i]-=2*(drStrength[objType[0]]-drArmor[objType[i]]);
										}
									}
									else if (drBullet[objType[i]]>0 && bullets<4 &&
										(randi()&63)<=drOS[objType[i]])
									{
										if ((objX[i]-objX[0])*(objX[i]-objX[0])<400)
										{
											if (objY[i]>objY[0])
												fireBullet(objX[i]+14,objY[i]+14,1,
													drBullet[objType[i]]);
											else
												fireBullet(objX[i]+14,objY[i]+14,2,
													drBullet[objType[i]]);
										}
										else if ((objY[i]-objY[0])*(objY[i]-objY[0])<400)
										{
											if (objX[i]>objX[0])
												fireBullet(objX[i]+14,objY[i]+14,3,
													drBullet[objType[i]]);
											else
												fireBullet(objX[i]+14,objY[i]+14,4,
													drBullet[objType[i]]);
										}
									}
								}
							}
						}
					}

					// Bullets
					for (i=1;i<bullets;i++)
						if (bullType[i]==0)
						{
							for (j=i;j<bullets-1;j++)
							{
								bullX[j]=bullX[j+1];
								bullY[j]=bullY[j+1];
								bullType[j]=bullType[j+1];
								bullDir[j]=bullDir[j+1];
							}
							bullets--;
						}
					
					clipG.setColor(Color.white);
					for (i=0;i<bullets;i++)
					{
						j=bullType[i];
						if (j>0)
						{
							bullX[i]+=bullSpeed[j]*BshiftX[bullDir[i]];
							bullY[i]+=bullSpeed[j]*BshiftY[bullDir[i]];
							k=bullX[i]-screenX;
							l=bullY[i]-screenY;
							if ((k>245)||(k<-5)||(l>245)||(l<-5))
								bullType[i]=0;
							else
							{
								if (bullDir[i]<3)
								{
									m=(bullX[i]-bullWidth[j]/2)/24+mapW*(bullY[i]/24);
									n=(bullX[i]+bullWidth[j]/2)/24+mapW*(bullY[i]/24);
								}
								else
								{
									m=bullX[i]/24+mapW*((bullY[i]-bullWidth[j]/2)/24);
									n=bullX[i]/24+mapW*((bullY[i]+bullWidth[j]/2)/24);
								}
								if ((propMap[m]&5)+(propMap[n]&5)>0)
								{
									bullType[i]=0;
									addBlast(bullX[i],bullY[i],4);
									playSound(6);
								}
								else
								{
									// Check for robot collisions
										if (bullDir[i]<3)
										{
											m=bullWidth[j]>>1;
											n=bullLength[j]>>1;
										}
										else
										{
											n=bullWidth[j]>>1;
											m=bullLength[j]>>1;
										}
										for (j=0;j<drawCount;j++)
										{
											if (i==0) // Player bullet
												o=drawNum[j];
											else
											{
												o=0;
												j=drawCount;
											}
											p=Math.abs(14+objX[o]-bullX[i])-m;
											q=Math.abs(14+objY[o]-bullY[i])-n;
											if ((p*p+q*q<200)&&(objType[o]<50))
											{
												if (i==0)
												{
													q=pBullet;
													p=drArmor[objType[o]];
												}
												else
												{
													q=bullPower[bullType[i]];
													p=pArmor;
												}
												if (p<q)
												{
													if (i==0)
													{
														objEnergy[o]-=30*(q-p);
														objLook[o]=(objLook[o]&3)+20;
														if (objEnergy[o]<1)
														{
															newScore+=drNumber[objType[o]];
															objType[o]=50;
															objLook[o]=37;
															killed++;
															playSound(1);
														}
														else
														{
															addBlast(bullX[i],bullY[i],8);
															playSound(1);
														}
													}
													else
													{
														newEnergy-=15*(q-p);
														addBlast(bullX[i],bullY[i],8);
														playSound(1);
													}
												}
												else
												{
													addBlast(bullX[i],bullY[i],4);
													playSound(3);
												}
												bullType[i]=0;
											}
										}
								}
							}
							j=bullType[i];
							switch(j)
							{
								case 1:
								case 2:
									if (bullDir[i]<3)
										clipG.fillRect(k-2,l-5,3,10);
									else
										clipG.fillRect(k-5,l-2,10,3);
									break;
								case 3:
									if (bullDir[i]<3)
										clipG.fillRect(k-2,l-4,4,8);
									else
										clipG.fillRect(k-4,l-2,8,4);
									break;
								case 4:
									if (bullDir[i]<3)
									{
										clipG.fillRect(k-5,l-5,3,10);
										clipG.fillRect(k+2,l-5,3,10);
									}
									else
									{
										clipG.fillRect(k-5,l-5,10,3);
										clipG.fillRect(k-5,l+2,10,3);
									}
									break;
								case 5:
									clipG.fillRect(k-3,l-3,6,6);
									break;
								case 6:
									if (bullDir[i]<3)
										clipG.fillRect(k-2,l-5,4,10);
									else
										clipG.fillRect(k-5,l-2,10,4);
									break;
								default:
									break;
							}
						}
					}
					
					// Draw droids
					for (m=0;m<drawCount;m++)
					{
						k=drawX[m];
						l=drawY[m];
						i=drawNum[m];
						j=objType[i];
						clipG.drawImage(mobiles[objLook[i]],k,l,this);
						if (j<50)
							backG.copyArea(serialX[j],serialY[j],Math.max(0,Math.min(18,235-k)),
							Math.max(0,Math.min(8,230-l)),k-serialX[j]+5,l-serialY[j]+10);
					}
					
					// Draw player
					j=objType[0];
					if (j>0 && j<50)
					{
						clipG.drawImage(mobiles[20+(counter&3)],objX[0]-screenX,objY[0]-screenY,this);
						backG.copyArea(serialX[j],serialY[j],18,8,
							objX[0]-screenX-serialX[j]+5,objY[0]-screenY-serialY[j]+10);
					}
					else
						clipG.drawImage(mobiles[objLook[0]],objX[0]-screenX,objY[0]-screenY,this);
					if (influence)
					{
						clipG.drawImage(mobiles[44+(counter%3)],objX[0]-screenX-2,objY[0]-screenY-2,this);
						if ((counter&3)==0)
							newEnergy--;
					}
					for (i=0;i<blasts;i++)
						if (blastType[i]>0)
						{
							blastType[i]++;
							if (blastType[i]==8 || blastType[i]==12)
								removeBlast(i);
							else
								clipG.drawImage(mobiles[42+blastType[i]-blastType[i]/8],blastX[i]-screenX-2*blastType[i],
									blastY[i]-screenY-2*blastType[i],this);
						}
					if (newScore>score && scoreCount==0)
						scoreCount=3;
					if (scoreCount>0)
					{
						if (scoreCount==3)
						{
							scoreG.setColor(scoreCol);
							scoreG.fillRect(0,0,74,16);
						}
						else if (scoreCount==2)
						{
							score=newScore;
							scoreG.setColor(Color.black);
							scoreG.drawString(""+score,1,14);
						}
						else
							backG.drawImage(scoreIm,0,247,this);
						scoreCount--;
					}
					break;
				case 11:
					if (counter<17)
					{
						clipG.setColor(Color.black);
						for (i=0;i<15;i++)
							clipG.drawLine(0,i*16+counter-1,240,i*16+counter-1);
					}
					else // Enter new layer
					{
						copyFromMain();
						layer=newLayer;
						copyToMain(layer);
						objX[0]=24*(newPos%mapW)-2;
						objY[0]=24*(newPos/mapW)-2;
						objDir[0]=0;
						moveDir=0;
						scrollDir=0;
						screenX=objX[0]-94;
						screenY=objY[0]-94;
						baseX=screenX/24-1;
						baseY=screenY/24-1;
						fixBackground();
						gameState=10;
					}
					break;
				case 12: // Game over
					if (counter==1)
					{
						clipG.setFont(bigF);
						clipG.setColor(Color.black);
						j=bigFM.stringWidth(ss[0]);
						clipG.fillRoundRect(113-j/2,106,j+14,26,12,12);
						clipG.setColor(Color.white);
						clipG.drawString(ss[0],120-j/2,125);
					}
					else if (counter>50)
					{
						holdBullet=false;holdBCost=false;holdArmor=false; // Cheat off
						if (score>highscores[7])
							prepareInput();
						else
						{
							gameState=9;
							nextState=1;
							counter=0;
						}
					}

					if (newScore>score && scoreCount==0)  // Make sure score is OK
						scoreCount=3;
					if (scoreCount>0)
					{
						if (scoreCount==3)
						{
							scoreG.setColor(scoreCol);
							scoreG.fillRect(0,0,74,16);
						}
						else if (scoreCount==2)
						{
							score=newScore;
							scoreG.setColor(Color.black);
							scoreG.drawString(""+score,1,14);
						}
						else
							backG.drawImage(scoreIm,0,247,this);
						scoreCount--;
					}
					break;
				case 13: // Duel area
					if (counter<17)
					{
						clipG.setColor(Color.black);
						for (i=0;i<15;i++)
							clipG.drawLine(i*16+counter-1,0,i*16+counter-1,240);
					}
					else // Prepare duel area
					{
						waitTime=90;
						influence=false;
						scrollDir=0;
						screenX=(baseX+1)*24;
						screenY=(baseY+1)*24;
						objX[0]=Math.min(Math.max(objX[0],screenX+70),screenX+142);
						objY[0]=Math.min(Math.max(objY[0],screenY+70),screenY+142);
						pType=objType[0];
						drawDuelArea();
						gameState=14;
						counter=0;
						eIY=-1;pIY=-1;
					}
					break;
				case 14:
					if (pIY<0 && (firing || moveDir==2) && pImp>0) // Release new impulse
					{
						pIY=0;
						while (pIY<12 && (duelMap[pIY][0]!=1))
							pIY++;
						if (pIY<12)
						{
							pImp--;
							backG.setColor(Color.darkGray);
							backG.fillRect(266+10*(pImp&7),25+12*(pImp/8),9,12);
						}
						firing=false;
					}
					else if (pIY>=0) // Move impulse
					{
						if (moveDir==1)
						{
							pIY=(11+pIY)%12;
							while (duelMap[pIY][0]!=1)
								pIY=(11+pIY)%12;
						}
						else if (moveDir==2)
						{
							pIY=(1+pIY)%12;
							while (duelMap[pIY][0]!=1)
								pIY=(1+pIY)%12;
						}
						else if (firing)
						{
							duelMap[pIY][0]=80;
							backG.drawImage(smalls[10],264,50+pIY*14,this);
							pIY=-1;
							firing=false;
							playSound(7);
						}
					}
					if (eIY<0 && eImp>0) // Release new impulse
					{
						eIY=0;
						while (eIY<12 && (duelMap[eIY][14]!=1))
							eIY++;
						if (eIY<12)
						{
							eImp--;
							backG.setColor(Color.darkGray);
							backG.fillRect(493-10*(eImp&7),25+12*(eImp/8),9,12);
						}
					}
					else if (eIY>=0 && (counter&1)==0)
					{
						if (eMove<0)
						{
							eMove++;
							eIY=(eIY+11)%12;
							while (duelMap[eIY][14]!=1)
								eIY=(eIY+11)%12;
						}
						else if (eMove>0)
						{
							eMove--;
							eIY=(eIY+1)%12;
							while (duelMap[eIY][14]!=1)
								eIY=(eIY+1)%12;
						}
						else
							eMove=((randi()>>2)%7)-3;
						if (((randi()>>3)&15)<=
							(1-duelMap[endPos[eIY][0]][7])*endVal[eIY][0]+
							(1-duelMap[endPos[eIY][1]][7])*endVal[eIY][1]+
							(1-duelMap[endPos[eIY][2]][7])*endVal[eIY][2])
						{
							duelMap[eIY][14]=80;
							backG.drawImage(smalls[1+drLook[eType]/2],495,50+eIY*14,this);
							eIY=-1;
							playSound(7);
						}
					}
					backG.copyArea(264,24,240,240,-264,-24);
					for (i=0;i<12;i++)
					{
						if (duelMap[i][0]>1)
						{
							duelMap[i][0]--;
							if (duelMap[i][0]<9)
							{
								duelMap[i][0]=1;
								backG.setColor(Color.darkGray);
								backG.fillRect(264,50+i*14,9,12);
								backG.setColor(Color.black);
								backG.fillRect(264,54+i*14,9,4);
							}
						}
						if (duelMap[i][14]>1)
						{
							duelMap[i][14]--;
							if (duelMap[i][14]<9)
							{
								duelMap[i][14]=1;
								backG.setColor(Color.darkGray);
								backG.fillRect(495,50+i*14,9,12);
								backG.setColor(Color.black);
								backG.fillRect(495,54+i*14,9,4);
							}
						}
					}
					for (j=1;j<6;j++)
						for (i=0;i<12;i++)
							if (duelMap[i][j]==1)
							{
								switch (duelMap[i][j-1])
								{
									case 9:
										duelMap[i][j]=9;
										break;
									case 2:
										if (duelMap[i+1][j-2]==9)
											duelMap[i][j]=9;
										break;
									case 4:
										if (duelMap[i-1][j-2]==9)
											duelMap[i][j]=9;
										break;
									case 3:
										if (duelMap[i+1][j-2]==9 && duelMap[i-1][j-2]==9)
											duelMap[i][j]=9;
										break;
									case 7:
										if (duelMap[i][j-2]==9)
											duelMap[i][j]=9;
										break;
									case 0:
									case 1:
									case 5:
									case 6:
										break;
									default:
										duelMap[i][j]=9;
										break;
								}
							}
					for (j=13;j>8;j--)
						for (i=0;i<12;i++)
							if (duelMap[i][j]==1)
							{
								switch (duelMap[i][j+1])
								{
									case 9:
										duelMap[i][j]=9;
										break;
									case 2:
										if (duelMap[i+1][j+2]==9)
											duelMap[i][j]=9;
										break;
									case 4:
										if (duelMap[i-1][j+2]==9)
											duelMap[i][j]=9;
										break;
									case 3:
										if (duelMap[i+1][j+2]==9 && duelMap[i-1][j+2]==9)
											duelMap[i][j]=9;
										break;
									case 7:
										if (duelMap[i][j+2]==9)
											duelMap[i][j]=9;
										break;
									case 0:
									case 1:
									case 5:
									case 6:
										break;
									default:
										duelMap[i][j]=9;
										break;
								}
							}
					impNum1=0;
					for (i=0;i<12;i++)
						for (j=1;j<6;j++)
							if (duelMap[i][j]==9)
							{
								duelMap[i][j]=1;
								if (duelMap[i][j-1]==7)
									impListCol[impNum1]=2;
								else
									impListCol[impNum1]=0;
								impListX[impNum1]=impX[j];
								impListY[impNum1]=31+i*14;
								impListL[impNum1]=impLength[j];
								j++;
								while (duelMap[i][j]==9)
								{
									duelMap[i][j]=1;
									impListL[impNum1]+=impLength[j++];
								}
								k=impListCol[impNum1]/2;
								if (j==6 && (counter&1)==0)
									if (duelMap[i][7]!=k)
									{
										duelMap[i][7]=k;
										backG.setColor(duelCol[k]);
										backG.fill3DRect(374,51+i*14,20,10,true);
									}
								impNum1++;
							}
					impNum2=impNum1;
					for (i=0;i<12;i++)
						for (j=13;j>8;j--)
							if (duelMap[i][j]==9)
							{
								duelMap[i][j]=1;
								if (duelMap[i][j+1]==7)
									impListCol[impNum2]=0;
								else
									impListCol[impNum2]=2;
								impListY[impNum2]=31+i*14;
								impListL[impNum2]=impLength[j];
								impListX[impNum2]=impX[j];
								j--;
								while (duelMap[i][j]==9)
								{
									impListX[impNum2]=impX[j];
									duelMap[i][j]=1;
									impListL[impNum2]+=impLength[j--];
								}
								k=impListCol[impNum2]/2;
								if (j==8 && (counter&1)==1)
									if (duelMap[i][7]!=k)
									{
										duelMap[i][7]=k;
										backG.setColor(duelCol[k]);
										backG.fill3DRect(374,51+i*14,20,10,true);
									}
								impNum2++;
							}
					j=285-(counter&7)*3;
					for (i=0;i<impNum1;i++)
						backG.copyArea(j,impListCol[i],impListL[i],2,impListX[i]-j,
							impListY[i]-impListCol[i]);
					j=264+(counter&7)*3;
					for (i=impNum1;i<impNum2;i++)
						backG.copyArea(j,impListCol[i],impListL[i],2,impListX[i]-j,
							impListY[i]-impListCol[i]);
					if (pIY>=0)
						backG.drawImage(smalls[10],0,26+pIY*14,this);
					if (eIY>=0)
						backG.drawImage(smalls[1+drLook[eType]/2],231,26+eIY*14,this);
					backG.setColor(Color.black);
					backG.drawLine(119,221,handX[(counter>>2)],handY[(counter>>2)]);
					j=0;
					for (i=0;i<12;i++)
					{
						j+=duelMap[i][7];
					}
					if (j<6)
						leading=0;
					else if (j>6)
						leading=1;
					else
						leading=2;
					backG.setColor(duelCol[leading]);
					backG.fill3DRect(366,29,36,12,true);
					if (counter>198)
					{
						gameState=15;
						counter=0;
					}
					break;
				case 15: // Right after mind game
					if (counter==1)
					{
						waitTime=80;
						backG.setFont(bigF);
						backG.setColor(Color.black);
						j=bigFM.stringWidth(ss[1+leading]);
						backG.fillRoundRect(377-j/2,125,j+14,26,12,12);
						backG.setColor(Color.white);
						backG.drawString(ss[1+leading],384-j/2,145);
						playSound(3*((leading+1)%3)+2);			
					}
					else if (counter==2)
							backG.copyArea(264,24,240,240,-264,-24);
					else if (counter>39)
					{
						if (counter<56)
						{
							clipG.setColor(Color.black);
							for (i=0;i<15;i++)
								clipG.drawLine(i*16+counter-40,0,i*16+counter-40,240);
						}
						else
						{
							switch (leading)
							{
								case 0: // Player wins
									objType[0]=eType;
									objType[eNum]=0;
									if (drBullet[eType]==0)
										j=1;
									else
										j=drBullet[eType];
									setSomeProperties(drArmor[eType],bullPower[j],
										bullCost[j]);
									counter=0;
									newScore+=2*drNumber[eType];
									fixBackground();
									gameState=10;
									killed++;
									if (killed==totalDroids)
										gameState=17;
									break;
								case 1: // Enemy wins
									if (objType[0]>0)
									{
										objType[eNum]=50;
										objLook[eNum]=36;
										objType[0]=0;
										newEnergy=Math.min(10,objEnergy[0]);
										playSound(1);
										killed++;
									}
									else
									{
										objType[eNum]=0;
										newEnergy=0;
									}
									counter=0;
									fixBackground();
									gameState=10;
									break;
								default: // Deadlock
									counter=16;
									gameState=13;
									break;
							}
						}
					}
					break;
				case 16: // Entering name
					if (pressedKey>0)
					{
						if ((pressedKey>31)&&(pressedKey<126))
							s=s+(char)pressedKey;
						l=s.length();
						if ((smallFM.stringWidth(s)>o-4)||((pressedKey=='\b')&&(l>0)))
							s=s.substring(0,l-1);
						clipG.setColor(Color.black);
						clipG.fillRect(120-o/2,173,o,19);
						clipG.setColor(Color.white);
						clipG.drawString(s,121-o/2,188);
						j=smallFM.stringWidth(s);
						clipG.drawLine(122-o/2+j,175,122-o/2+j,189);
						if (pressedKey=='\n')
						{
							j=7;
							while (j>0 && highscores[j-1]<score)
							{
								highscores[j]=highscores[j-1];
								highnames[j]=highnames[j-1];
								j--;
							}
							highnames[j]=new String(s);
							highscores[j]=score;
							gameState=9;
							nextState=1;
							counter=0;
						}
						pressedKey=0;
					}
					break;
				case 17: // All done
					if (counter==1)
					{
						clipG.setFont(bigF);
						clipG.setColor(Color.black);
						j=bigFM.stringWidth(ss[7]);
						clipG.fillRoundRect(113-j/2,106,j+14,26,12,12);
						clipG.setColor(Color.white);
						clipG.drawString(ss[7],120-j/2,125);
					}
					else
						gameState=12;
					break;
				case 18: // Showing map
					if (counter==1)
					{
						clipG.setColor(Color.black);
						clipG.fillRect(0,0,240,240);
						sc=Math.min(230.5/mapW,200.5/mapH);
						k=(int)(mapW*sc);
						l=(int)(mapH*sc);
						i=120-k/2;
						j=110-l/2;
						clipG.setColor(Color.blue);
						clipG.fillRect(i,j,k,l);
						clipG.setColor(Color.cyan);
						clipG.drawRect(i-2,j-2,k+3,l+3);
						clipG.drawRect(i-1,j-1,k+1,l+1);
						for (m=i+20;m<i+k;m+=20)
							clipG.drawLine(m,j,m,j+l);
						for (m=j+20;m<j+l;m+=20)
							clipG.drawLine(i,m,i+k,m);
						o=0;
						clipG.setColor(Color.red);
						for (m=0;m<mapH;m++)
							for (n=0;n<mapW;n++)
								if (propMap[o++]==4)
									clipG.drawRect((int)(i+n*sc),
									(int)(j+m*sc),4,4);
						clipG.drawRect(110,227,4,4);
						clipG.setColor(Color.green);
						clipG.fillOval(55,226,7,7);
						for (m=1;m<droidNum;m++)
							if (objType[m]>0 && objType[m]<50)
								clipG.fillOval((int)(i+objX[m]*sc/24),
									(int)(j+objY[m]*sc/24),7,7);
						clipG.setColor(Color.white);
						clipG.fillRect((int)(i+objX[0]*sc/24),
							(int)(j+objY[0]*sc/24),7,7);
						clipG.fillRect(10,226,7,7);
						clipG.setFont(miniF);
						clipG.drawString(ss[8],20,233);
						clipG.drawString(ss[9],65,233);
						clipG.drawString(ss[10],120,233);
						clipG.drawImage(OK,200,221,this);
					}
					break;
				default:
					break;
			}
			waitForRepaint();
			repaint();
		}
	}

	public void addBlast(int x, int y, int bType)
	{
		ai=0;
		while (blastType[ai]!=0)
			ai++;
		blastX[ai]=x;
		blastY[ai]=y;
		blastType[ai]=bType;
		if (ai==blasts)
			blasts=ai+1;
	}

	public void removeBlast(int num)
	{
		blastType[num]=0;
		while ((blasts>0)&&(blastType[blasts-1]==0))
			blasts--;
	}
	
	public void prepareInput()
	{
		clipG.setFont(smallF);
		clipG.setColor(Color.black);
		j=smallFM.stringWidth(ss[6]);
		clipG.fillRoundRect(113-j/2,150,j+14,52,16,16);
		clipG.setColor(Color.white);
		o=j-46;
		clipG.drawString(ss[6],120-j/2,166);
		clipG.drawRect(119-o/2,172,o+1,20);
		clipG.drawLine(122-o/2,175,122-o/2,189);
		pressedKey=0;
		s="";
		gameState=16;
	}

	public void fireBullet(int x, int y, int d, int t)
	{
		bullX[bullets]=x;
		bullY[bullets]=y;
		bullDir[bullets]=d;
		bullType[bullets++]=t;
		playSound(4);
	}

	public void prepareGame()
	{
		backG.copyArea(90,282,150,5,0,-29);
		objEnergy[0]=150;
		newEnergy=150;
		loadFile();
		copyToMain(0);
		fixBackground();
		backG.setColor(scoreCol);
		backG.fillRect(0,247,74,16);
		screenX=24*(baseX+1);
		screenY=24*(baseY+1);
		objX[0]=screenX+94;
		objY[0]=screenY+94;
		objType[0]=0;
		objLook[0]=24;
		lastDir=1;
		gameState=10;
		score=0;
		newScore=0;
		scoreCount=0;
		killed=0;
		layer=0;
		setSomeProperties(1,3,6);
	}

	public void copyToMain(int layer)
	{
		i=layerW[layer];
		mapW=i+8;
		j=layerH[layer];
		mapH=j+12;
		mainMap=new int[mapW*mapH];
		propMap=new int[mapW*mapH];
		m=0;
		l=mapW*4;
		for (k=0;k<l;k++)
			mainMap[k]=background[layer];
		for (l=0;l<j;l++)
		{
			for (n=0;n<4;n++)
				mainMap[k++]=background[layer];
			for (n=0;n<i;n++)
			{
				mainMap[k]=map[layer][m++];
				propMap[k]=prop[mainMap[k++]];
			}
			for (n=0;n<4;n++)
				mainMap[k++]=background[layer];
		}
		l=mapW*8;
		for (n=0;n<l;n++)
			mainMap[k++]=background[layer];
		m=1;
		for (n=0;n<40;n++)
		{
			k=droidType[layer][n];
			if (k>0)
			{
				objType[m]=k;
				objX[m]=droidX[layer][n];
				objY[m]=droidY[layer][n];
				objPar1[m]=droidTX[layer][n];
				objPar2[m]=droidTY[layer][n];
				objPar3[m]=droidBX[layer][n];
				objPar4[m]=droidBY[layer][n];
				objType[m]=droidType[layer][n];
				objDir[m]=0;
				objEnergy[m]=100;
				origDroid[m]=n;
				objLook[m++]=drLook[k];
			}
		}
		droidNum=m;
		for (i=0;i<10;i++)
			bullType[i]=0;
		bullets=1;
	}

	public void copyFromMain()
	{
		for (i=1;i<droidNum;i++)
		{
			if (objType[i]<50)
				droidType[layer][origDroid[i]]=objType[i];
			else
				droidType[layer][origDroid[i]]=0;
		}
	}

	public void drawDuelArea()
	{
		duelCol[1]=cols[drLook[eType]/4];
		
		backG.setColor(Color.darkGray);
		backG.fillRect(264,24,240,240);
		backG.drawImage(ctrlTop,355,24,this);
		backG.drawImage(ctrlBot,357,220,this);
		backG.setColor(Color.black);
		backG.drawRect(369,46,29,173);
		backG.setColor(Color.lightGray);
		backG.fillRect(370,47,28,172);
		backG.setColor(Color.white);
		backG.drawLine(370,47,396,47);
		backG.drawLine(370,47,370,217);
		backG.setColor(Color.darkGray);
		backG.drawLine(397,48,397,218);
		backG.drawLine(371,218,397,218);
		
		for (i=0;i<12;i++)
		{
			backG.setColor(Color.darkGray);
			backG.fillRect(374,51+i*14,22,12);
			backG.setColor(Color.black);
			backG.fillRect(373,50+i*14,22,12);
			backG.setColor(duelCol[i&1]);
			backG.fill3DRect(374,51+i*14,20,10,true);
		}
		for (i=0;i<12;i++)
			for (j=0;j<15;j++)
				duelMap[i][j]=1;
		for (p=0;p<=8;p+=8)
		{
		j=1+((randi()>>2)%4); // Insert forks
		for (i=0;i<j;i++)
		{
			k=2+p+((randi()>>3)&2);
			l=1+((randi()>>3)%10);
			if ((duelMap[l][k]==1)&&(duelMap[l-1][k]==1)&&(duelMap[l+1][k]==1))
			{
				m=randi()&8;
				if (m>0) // -=
				{
					if ((duelMap[l][k-1]==1)&&(duelMap[l-1][k+1]==1)&&
						(duelMap[l+1][k+1]==1))
					{
						duelMap[l-1][k]=2;
						duelMap[l][k]=3;
						duelMap[l+1][k]=4;
						duelMap[l-1][k-1]=0;
						duelMap[l][k+1]=0;
						duelMap[l+1][k-1]=0;
					}
				}
				else // =-
				{
					if ((duelMap[l][k+1]==1)&&(duelMap[l-1][k-1]==1)&&
						(duelMap[l+1][k-1]==1))
					{
						duelMap[l-1][k]=2;
						duelMap[l][k]=3;
						duelMap[l+1][k]=4;
						duelMap[l-1][k+1]=0;
						duelMap[l][k-1]=0;
						duelMap[l+1][k+1]=0;
					}
				}
			}
		}
		j=1+((randi()>>2)%4); // Insert holes
		for (i=0;i<j;i++)
		{
			k=1+p+2*((randi()>>3)%3);
			l=(randi()>>3)%12;
			if ((duelMap[l][k]==1)&&(duelMap[l][k-1]==1)&&(duelMap[l][k+1]==1))
			{
				duelMap[l][k]=0;
			}
		}
		for (i=0;i<12;i++) // Fill holes
		{
			if (duelMap[i][1+p]==0)
				duelMap[i][p]=0;
			if (duelMap[i][5+p]==0)
				duelMap[i][6+p]=0;
			for (j=2+p;j<6+p;j+=2)
				if (duelMap[i][j]==1)
				{
					if ((duelMap[i][j-1]==0)&&(duelMap[i][j+1]==1))
						duelMap[i][j]=5;
					else if ((duelMap[i][j-1]==1)&&(duelMap[i][j+1]==0))
						duelMap[i][j]=6;
					else if ((duelMap[i][j-1]==0)&&(duelMap[i][j+1]==0))
						duelMap[i][j]=0;
				}
		}
		j=(randi()>>2)%4; // Insert color changer
		for (i=0;i<j;i++)
		{
			k=2+p+((randi()>>3)&2);
			l=(randi()>>3)%12;
			if ((duelMap[l][k]==1)&&(duelMap[l][k-1]==1)&&(duelMap[l][k+1]==1))
			{
				duelMap[l][k]=7;
			}
		}
		for (i=0;i<12;i++)
		{
			if (p==0)
				q=10;
			else
				q=drLook[eType]/2;
			backG.setColor(Color.black);
			if (duelMap[i][p]==1)
			{
				if (p==0)
					backG.fillRect(264,54+i*14,32,4);
				else
				{
					backG.fillRect(408,54+i*14,24,4);
					backG.drawImage(smalls[q],399,50+i*14,this);
				}
			}
			if (duelMap[i][6+p]==1)
			{
				if (p==0)
				{
					backG.fillRect(337,54+i*14,23,4);
					backG.drawImage(smalls[11],360,50+i*14,this);
				}
				else
					backG.fillRect(472,54+i*14,32,4);
			}
			if (duelMap[i][3+p]==1)
				backG.fillRect(305+17*p,54+i*14,23,4);
			for (j=0;j<2;j++)
				switch(duelMap[i][2+2*j+p])
				{
					case 1:
						backG.fillRect(296+j*32+17*p,54+i*14,9,4);
						break;
					case 3:
						backG.fillRect(296+j*32+17*p,36+i*14,9,40);
						backG.setColor(duelCol[p/8]);
						backG.fill3DRect(297+j*32+17*p,37+i*14,7,38,true);
						backG.setColor(Color.white);
						backG.drawLine(297+j*32+17*p,37+i*14,302+j*32+17*p,37+i*14);
						backG.drawLine(297+j*32+17*p,37+i*14,297+j*32+17*p,73+i*14);
						backG.setColor(Color.black);
						break;
					case 7:
						backG.fillRect(296+j*32+17*p,50+i*14,9,12);
						backG.setColor(duelCol[1-p/8]);
						backG.fill3DRect(297+j*32+17*p,51+i*14,7,10,true);
						backG.setColor(Color.white);
						backG.drawLine(297+j*32+17*p,51+i*14,302+j*32+17*p,51+i*14);
						backG.drawLine(297+j*32+17*p,51+i*14,297+j*32+17*p,59+i*14);
						backG.setColor(Color.black);
						break;
					case 5:
						backG.drawImage(smalls[q],296+j*32+17*p,50+i*14,this);
						break;
					case 6:
						backG.drawImage(smalls[q+1],296+j*32+17*p,50+i*14,this);
						break;
					default:
						break;
				}
		}
		}
		// Draw contestants
		if (pType==0)
			backG.drawImage(mobiles[28],274,226,this);
		else
		{
			backG.drawImage(mobiles[20],274,226,this);
			backG.copyArea(serialX[pType],serialY[pType],18,8,279-serialX[pType],
				236-serialY[pType]);
		}
		backG.drawImage(mobiles[drLook[eType]],466,226,this);
		backG.copyArea(serialX[eType],serialY[eType],18,8,471-serialX[eType],
			236-serialY[eType]);

		pImp=3+drOS[pType];
		eImp=3+drOS[eType];
		for (i=0;i<pImp;i++)
			backG.drawImage(smalls[10],266+10*(i&7),25+12*(i/8),this);
		for (i=0;i<eImp;i++)
			backG.drawImage(smalls[1+drLook[eType]/2],493-10*(i&7),25+12*(i/8),this);
		backG.fillRect(264,0,120,4);
		for (i=0;i<2;i++)
		{
			backG.setColor(duelCol[i]);
			for (j=0;j<5;j++)
				backG.fillRect(264+j*24,i*2,12,2);
		}
		for (i=0;i<12;i++) // Right colors
			duelMap[i][7]=i&1;
		for (i=0;i<12;i++) // Get statistics for enemy AI
		{
			endVal[i][0]=0;endVal[i][1]=0;endVal[i][2]=0;
			findEnd(i,13,i,0);
		}
	}

	public void findEnd(int y, int h, int v, int pos)
	{
		int num=2;
		while (h>7)
		{
			switch (duelMap[v][h])
			{
				case 1:
					break;
				case 2:
					v++;
					num=num/2;
					break;
				case 4:
					num=num/2;
					v--;
					break;
				case 3:
					findEnd(y,h-1,v+1,pos+1);
					v--;
					break;
				case 7:
					num=-num;
					break;
				default:
					num=0;
					break;
			}
			h--;
		}
		endPos[y][pos]=v;
		endVal[y][pos]=num;
	}

	public void fixBackground()
	{
		k=baseY*mapW+baseX;
		for (i=0;i<12;i++)
		{
			for (j=0;j<12;j++)
				drawBlock(mainMap[k++],j,i);
			k+=mapW-12;
		}
	}

	public void drawBlock(int num, int x, int y)
	{
		di=(num%22)*24;
		dj=288+(num/22)*24;
		dk=240+x*24;
		dl=y*24;
		backG.copyArea(di,dj,24,24,dk-di,dl-dj);
	}

	public void loadFile()
	{
		InputStream infile;
		int layers;
		byte tempback[];
		totalDroids=0;
		for (i=0;i<10;i++)
		{
			background[i]=-1;
			entranceCount[i]=0;
		}
		try
		{
			URL tempURL=new URL(getCodeBase(),cityName);
			URLConnection tempConn=tempURL.openConnection();
			tempConn.connect();
			infile=tempConn.getInputStream();
			layers=infile.read();
			for (i=0;i<layers;i++)
			{
				layerParent[i]=infile.read();
				layerW[i]=infile.read();
				layerH[i]=infile.read();
				background[i]=infile.read();
				
				k=infile.read(); // Number of robots
				totalDroids+=k;
				for (j=0;j<k;j++)
				{
					droidType[i][j]=infile.read();
					droidX[i][j]=24*infile.read()+94;
					droidY[i][j]=24*infile.read()+94;
					droidTX[i][j]=24*infile.read()+94;
					droidTY[i][j]=24*infile.read()+94;
					droidBX[i][j]=24*infile.read()+94;
					droidBY[i][j]=24*infile.read()+94;
				}
				while (j<40)
					droidType[i][j++]=0;
				
				k=infile.read(); // Number of exits
				for (j=0;j<k;j++)
				{
					exitPos[i][j]=infile.read()+4+(layerW[i]+8)*(infile.read()+4);
					exitToPos[i][j]=infile.read()+4+(layerW[layerParent[i]]+8)*(infile.read()+4);
					entranceLayer[layerParent[i]][entranceCount[layerParent[i]]]=i;
					entrancePos[layerParent[i]][entranceCount[layerParent[i]]++]=exitToPos[i][j];
				}
				
				if (i==0)
					j=(layerW[i]*layerH[i]*7)/8+1;
				else
					j=(layerW[i]*layerH[i]*5)/8+1;
				tempback=new byte[j+1];
				map[i]=new int[layerW[i]*layerH[i]];
				k=0;
				while (k<j)
				{
					l=infile.read(tempback,k,j-k);
					if (l>=0)
						k+=l;
				}
				j=0;
				o=0;
				p=0;
				m=0;
				if (i==0)
				{
						for (k=0;k<layerH[i];k++)
							for (l=0;l<layerW[i];l++)
							{
								n=((256+tempback[o])&255)+256*((256+tempback[o+1])&255);
								n=(n>>p)&127;
								map[i][j++]=n;
								if (p>0)
									o++;
								p=(p+7)&7;
							}
				}
				else
				{
						for (k=0;k<layerH[i];k++)
							for (l=0;l<layerW[i];l++)
							{
								n=((256+tempback[o])&255)+256*((256+tempback[o+1])&255);
								n=100+((n>>p)&31);
								map[i][j++]=n;
								if (p>2)
									o++;
								p=(p+5)&7;
							}
				}
			}
			baseX=infile.read()-1;
			baseY=infile.read()-1;
			infile.close();
		}
		catch(FileNotFoundException ex){}
		catch(MalformedURLException ex){}
		catch(IOException ex){}
	}

	public void setSomeProperties(int a, int b, int bc)
	{
		if (!holdArmor)
			pArmor=a;
		if (!holdBullet)
			pBullet=b;
		if (!holdBCost)
			pBCost=bc;
	}

	public void playSound(int sd)
	{
		AudioPlayer.player.stop(soundStream[currSound]);
		try{
			soundStream[sd].reset();
		}
		catch(IOException ioe){}
		AudioPlayer.player.start(soundStream[sd]);
		currSound=sd;
	}
	
	public boolean mouseDown(java.awt.Event e, int x, int y)
	{
		requestFocus();
		if (gameState==8)
		{
			mj=-1;
			for (mi=0;mi<droidNum;mi++)
				if ((objX[mi]-screenX-x+14)*(objX[mi]-screenX-x+14)+
					(objY[mi]-screenY-y+14)*(objY[mi]-screenY-y+14)<200)
					mj=mi;
			if (mj>=0)
			{
				s=""+(1000+drNumber[objType[mj]]);
				try{
					getAppletContext().showDocument(new
						URL(getCodeBase(),"info/m"+s.substring(1)+".html"),"info");
				}
				catch(MalformedURLException ex){System.out.println("Darn!");}
			}
		}
		else if (gameState==18)
		{
			if (x>200 && x<232 && y>221 && y<238)
				gameState=10;
		}
		return true;
	}

	public boolean keyDown(java.awt.Event e, int key)
	{
		pressedKey=key;
		switch(key)
		{
			case 'i':
				moveDir=1;
				break;
			case 'k':
				moveDir=2;
				break;
			case 'j':
				moveDir=3;
				break;
			case 'l':
				moveDir=4;
				break;
			case 'd':
				moveDir=5;
				break;
			case 'e':
				moveDir=6;
				break;
			case ' ':
				if (!influence)
					firing=true;
				break;
			case 't':
				if (!influence)
					playSound(2);
				influence=true;
				break;
			case 's': // Stop
				if (gameState==10)
				{
					counter=0;
					gameState=8;
				}
				break;
			case 'g': // Resume
				if (gameState==8)
					gameState=10;
				break;
			default:
				break;
		}
		return true;
	}

	public boolean keyUp(java.awt.Event e, int key)
	{
	  if (moveDir>0 && moveDir<5 && moveKey[moveDir]==key)
	    moveDir=0;
//		if ((key=='i')||(key=='j')||(key=='k')||(key=='l'))
//			moveDir=0;
		firing=false;
		if (key=='t')
			influence=false;
		return true;
	}
	
	public void start()
	{
		if (game==null)
		{
			game=new Thread(this);
			game.start();
			nextTime=System.currentTimeMillis()+80;
		}
	}
 
	public void stop()
	{
		if ((game!=null)&&(game.isAlive()))
		{
			game.stop();
		}
		game=null;
	}
	
	public int randi() // Pseudo-random number generator, integer
	{
		seed=(seed*171)%30269;
		return seed;
	}

	public void chosenCity(String s)
	{
		if (gameState==0)
		{
			cityName=s;
			gameState=9;
			nextState=10;
			counter=0;
		}
	}

	public void chosenCheat(String s) // Selected type of cheating
	{
		switch(s.charAt(0))
		{
			case '1': // Free bullets
				pBCost=0;
				holdBCost=true;
				break;
			case '2': // Invulnerability
				pArmor=100;
				holdArmor=true;
				break;
			default: // Infinite firepower
				pBullet=100;
				holdBullet=true;
				break;
		}
		if (gameState==0)
		{
			try{
				getAppletContext().showDocument(new URL(getCodeBase(),"choice.html"),"info");
			}
			catch(MalformedURLException ex){}
		}
	}
	
	public void clickMap() // Used by the image map
	{
		if (gameState==10)
		{
			gameState=18;
			counter=0;
		}
	}
	
	public void clickCheat() // Used by the image map
	{
		if (gameState==1)
		{
			gameState=0;
			try{
				getAppletContext().showDocument(new URL(getCodeBase(),"cheat.html"),"info");
			}
			catch(MalformedURLException ex){}
		}
	}

	public void clickStart() // Used by the image map
	{
		if (gameState==1)
		{
			gameState=0;
			try{
				getAppletContext().showDocument(new URL(getCodeBase(),"choice.html"),"info");
			}
			catch(MalformedURLException ex){}
		}
	}
	
	public synchronized void waitForRepaint()
	{
		while (!updateFinished)
		{
			try{wait(1000);}
			catch(InterruptedException exci){}
			break;
		}
		updateFinished=false;
	}

	public void paint(Graphics g)
	{
		if (backIm!=null)
			g.drawImage(backIm,0,0,this);
	}

	public synchronized void update(Graphics g)
	{
		g.drawImage(backIm,0,0,this);
		updateFinished=true;
		notify();
	}

}
