// Don's Dugout // By Karl Hörnell, Aug 18 1996 // Last modified Aug 26 import java.awt.*; import java.awt.image.*; import java.applet.AudioClip; import java.net.*; import java.awt.Font; public final class dugout extends java.applet.Applet implements Runnable { int i,j,k,l,n,runMode,counter,seed,loc,presMode,red=12,yellow=60; int lives,level,currentKey,activeObjects,death; int objX[],objY[],objType[],objMode[],objLook[],objPar[]; int bx,by,pos,posVal,scoreCount=0,groundLocs[],rockPos,enemyPos[],enemyType[]; int field[],flameX,flameY,flameLook,hoseX,hoseY,currentSnd; int temp1,temp2,tipX[],tipY[],levEnC; double levFlC,levGhC; final int opaque=(255 << 24),weedNum=9,actorNum=81,normalActorNum=54; final int maxObj=8,cyclic[]={0,1,2,1}; final int weedX[]={0,24,48,112,48,80,240,240,144}; final int weedY[]={58,58,85,85,58,58,0,30,58}; final int weedW[]={24,24,64,64,32,32,16,16,32}; final int weedH[]={35,35,8,8,27,27,30,28,27}; final int holeX[]={176,192,208,112,112,112,112,112}; final int holeY[]={63,63,63,58,64,64,70,76}; final int holeW[]={16,16,16,32,32,32,32,32}; final int holeH[]={30,30,30,12,12,6,12,6}; final int actX[]={0,192,0,48,32,192,96,144,64,64,96,96,128,128, 224,160,184,120,160,96,0,160,0,160,0,160, 232}; final int actY[]={379,303,333,333,379,341,333,333,379,399,379,399,379,399, 273,303,273,303,273,303,303,379,303,379,303,379, 303}; final int actW[]={32,40,48,48,32,40,48,48,32,32,32,32,32,32, 32,32,72,72,96,96,32,32,72,72,96,96, 16}; final int actH[]={30,38,46,46,30,38,46,46,20,10,20,10,20,10, 29,29,29,29,29,29,29,29,29,29,29,29, 12}; final int weedOrder[]={0,1,4,7,5,8,6},weedsToPlace=7; final int weedMax[]={4,4,2,3,2,3,2}; final int weedMin[]={2,2,0,0,0,1,1}; final double baseCol[]={82,82,82, 82,50,10, 61,82,10}; final int offsetX[]={0,0,0,0,0,4,0,0,0,0,4,0,0,0,0}; final int offsetY[]={0,0,0,0,0,4,0,0,0,0,3,0,0,0,0}; final int inflateLook[]={0,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2}; final int levEnemies[]={2,3,3,3,4,4,4}; final double levFlameOdds[]={0.1,0.15,0.2,0.25,0.3,0.3,0.35}; final double levGhostOdds[]={0.02,0.025,0.03,0.035,0.04,0.05,0.06}; boolean strata[],flameOn,hoseOn; Image clouds,offImage,farImage,scoreHolder,scoreCover,lifeCover; Image weeds[],logo,holes[],actors[],hose,groundKeep[]; AudioClip sound[]; Font presFont,gameFont; Graphics offGraphics,farGraphics,scoreGraphics,scoreCG,lifeCG,groundG[]; long startTime,score,newScore,highScores[]={0,0,0,0,0,0,0,0},snooze=20,pause=100; Thread game; public void init() { weeds=new Image[weedNum]; holes=new Image[12]; actors=new Image[actorNum]; loadGraphics(); System.gc(); sound=new AudioClip[3]; sound[0] = getAudioClip(getCodeBase(),"dugout0.au"); sound[1] = getAudioClip(getCodeBase(),"dugout1.au"); sound[2] = getAudioClip(getCodeBase(),"dugout2.au"); fixClouds(); System.gc(); strata=new boolean[512*30]; fixStrata(); System.gc(); objX=new int[maxObj]; objY=new int[maxObj]; objType=new int[maxObj]; objMode=new int[maxObj]; objLook=new int[maxObj]; objPar=new int[maxObj]; field=new int[15*13]; groundLocs=new int[5]; enemyPos=new int[4]; enemyType=new int[4]; tipX=new int[3]; // Used for speech balloon tipY=new int[3]; offImage=createImage(390,350); offGraphics=offImage.getGraphics(); farImage=createImage(390,338); farGraphics=farImage.getGraphics(); scoreHolder=createImage(390,12); scoreGraphics=scoreHolder.getGraphics(); scoreCover=createImage(80,12); scoreCG=scoreCover.getGraphics(); lifeCover=createImage(48,12); lifeCG=lifeCover.getGraphics(); presFont=new Font("Helvetica",Font.PLAIN,12); gameFont=new Font("Courier",Font.PLAIN,14); scoreGraphics.setFont(gameFont); scoreGraphics.setColor(Color.black); groundKeep=new Image[5]; groundG=new Graphics[5]; for (i=0;i<5;i++) { groundKeep[i]=createImage(30,30); groundG[i]=groundKeep[i].getGraphics(); } preparePresentation(); resize(392,352); } public void loadGraphics() { Image collection; ImageProducer prod; MediaTracker tracker; tracker=new MediaTracker(this); collection = getImage(getCodeBase(),"dugout.gif"); tracker.addImage(collection,0); try { tracker.waitForID(0); } catch(InterruptedException e) {} prod=collection.getSource(); logo=createImage(new FilteredImageSource( prod,new CropImageFilter(0,0,240,58))); tracker.addImage(logo,1); for (i=0;iw) { row=s.substring(lastStop,lastSpace); lastStop=lastSpace+1; if (center) g.drawString(row,x-getFontMetrics(presFont).stringWidth(row)/2,yPos); else g.drawString(row,x,yPos); yPos+=14; } lastSpace=i; } else if (s.charAt(i)=='#') // Force new line { row=s.substring(lastStop,i); lastStop=i+1; if (center) g.drawString(row,x-getFontMetrics(presFont).stringWidth(row)/2,yPos); else g.drawString(row,x,yPos); yPos+=14; lastSpace=i; } i++; } row=s.substring(lastStop,l); if (getFontMetrics(presFont).stringWidth(row)>w) { row=s.substring(lastStop,lastSpace); if (center) g.drawString(row,x-getFontMetrics(presFont).stringWidth(row)/2,yPos); else g.drawString(row,x,yPos); yPos+=14; row=s.substring(lastSpace+1,l); } if (center) g.drawString(row,x-getFontMetrics(presFont).stringWidth(row)/2,yPos); else g.drawString(row,x,yPos); } public void playSound(int sndNum) { if (currentSnd>=0) sound[currentSnd].stop(); if (sndNum>=0) sound[sndNum].play(); currentSnd=sndNum; } public void run() { int i; while (game !=null) { try { game.sleep(Math.max(startTime-System.currentTimeMillis(),snooze)); } catch (InterruptedException e) {} startTime=System.currentTimeMillis()+pause; counter++; switch (runMode) { case 1: // Presentation loop if (counter>120) { counter=0; presMode=(presMode+1)%3; fixLayout(presMode); } offGraphics.drawImage(farImage,0,90,this); animatePresentation(presMode); offGraphics.setColor(Color.red); offGraphics.fillRect(22,324,red,4); offGraphics.setColor(Color.yellow); offGraphics.fillRect(22+red,324,yellow-red,4); switch (currentKey) { case 32: runMode=2; break; case 97: if (red>3) red-=3; break; case 115: if (redred)&&(yellow>30)) yellow-=3; break; case 120: if (yellow<75) yellow+=3; break; default: break; } snooze=(5*red)/3; pause=(5*yellow)/3; break; case 2: // Prepare for game resetVariables(); offGraphics.setColor(Color.black); offGraphics.fillRect(0,0,390,350); runMode=3; break; case 3: // Prepare for new level drawGround(); fixLevelSpecifics(); putInPlace(); offGraphics.drawImage(scoreHolder,0,0,this); runMode=4; break; case 4: // Game loop handleObjects(); offGraphics.drawImage(farImage,0,12,this); checkDeath(); trackScore(); drawObjects(); checkRock(); break; case 5: // Just after dying j=0; for (i=0;i=0) { putInPlace(); offGraphics.drawImage(scoreHolder,0,0,this); runMode=4; } else { offGraphics.setColor(Color.white); placeText(195,120,200,"GAME OVER",true,offGraphics); counter=0; runMode=6; } break; case 6: // After death if (counter>18) { score=newScore; if (score<=highScores[7]) preparePresentation(); else // New highscore { farGraphics.setColor(Color.black); farGraphics.fillRect(0,0,390,350); farGraphics.setColor(Color.white); highScores[7]=score; j=7; for (i=6;i>=0;i--) if (score>highScores[i]) { highScores[i+1]=highScores[i]; highScores[i]=score; j=i; } placeText(195,70,200,"CURRENT HIGHSCORES",true,farGraphics); for (i=0;i<8;i++) { if (i==j) farGraphics.setColor(Color.green); else farGraphics.setColor(Color.white); placeText(150,100+i*24,200,""+(i+1)+".",true,farGraphics); placeText(230,100+i*24,200,""+highScores[i],true,farGraphics); } counter=0; runMode=9; } } break; case 7: // Level completed if (objX[0]>180) { j=objX[0]-45; tipX[0]=j+36; tipX[1]=j+45; tipX[2]=j+41; } else { j=objX[0]+25; tipX[0]=j+11; tipX[1]=j+3; tipX[2]=j+16; } offGraphics.setColor(Color.white); offGraphics.fillOval(j,objY[0]-5,60,25); offGraphics.setColor(Color.black); offGraphics.drawOval(j-1,objY[0]-6,61,26); tipY[0]=objY[0]+18; tipY[1]=objY[0]+26; tipY[2]=objY[0]+18; offGraphics.setColor(Color.white); offGraphics.fillPolygon(tipX,tipY,3); offGraphics.setColor(Color.black); offGraphics.drawPolygon(tipX,tipY,3); if (Math.random()<0.333) placeText(j+30,objY[0]+13,100,"YES!!",true,offGraphics); else if (Math.random()<0.5) placeText(j+30,objY[0]+13,100,"Whew!",true,offGraphics); else placeText(j+30,objY[0]+13,100,"Awrite!!",true,offGraphics); counter=0; runMode=8; break; case 8: // Wait, then jump to next level if (counter>25) { level++; score=newScore+250; newScore=score; offGraphics.fillRect(0,0,390,350); runMode=3; } break; case 9: // Wait while displaying highscores and animating critters offGraphics.drawImage(farImage,0,0,this); offGraphics.drawImage(actors[37+cyclic[counter&3]],counter*5,20,this); offGraphics.drawImage(actors[46+cyclic[counter&3]],360-counter*5,280,this); if (counter>80) preparePresentation(); break; default: break; } repaint(); } } public void start() { if (game==null) { game=new Thread(this); game.start(); startTime=System.currentTimeMillis(); } } public void stop() { if ((game!=null)&&(game.isAlive())) { game.stop(); } game=null; } public void resetVariables() // Called before starting game { lives=3; level=0; score=0; newScore=0; seed=1; } public void fixLevelSpecifics() { for (i=0;i<(15*13);i++) // Fix field map field[i]=32767; // Blocked, outer limits for (j=1;j<14;j++) field[15+j]=0; // Open air for (i=2;i<12;i++) for (j=1;j<14;j++) field[i*15+j]=4095; // Plain ground j=Math.min(6,level); // Set level constants levEnC=levEnemies[j]; levFlC=levFlameOdds[j]; levGhC=levGhostOdds[j]; for (i=0;i<3;i++) // Make dugouts { j=0;k=0;l=1; while ((field[k*15+j]!=4095)&&(field[k*15+j+l-1]!=4095)) { j=(int)(1+8*rand()); k=(int)(3+8*rand()); l=(int)(4+2*rand()); } field[k*15+j]=2081; for (n=1;n<(l-1);n++) field[k*15+j+n]=33; field[k*15+j+l-1]=97; j=(j-1)*30; k=k*30-22; farGraphics.drawImage(holes[0],j,k,this); for (n=1;n<((l*5+1)/2-1);n++) farGraphics.drawImage(holes[1],j+12*n,k,this); farGraphics.drawImage(holes[2],j+30*l-12,k,this); } for (i=0;i0) activateObject(((enemyPos[i]%15)-1)*30,((enemyPos[i]/15)-1)*30, enemyType[i],0,12*enemyType[i]-34,0); scoreCount=0; death=0; rockPos=0; currentSnd=-1; flameOn=false; hoseOn=false; scoreGraphics.drawImage(lifeCover,316,0,this); for (i=0;i0) { objType[0]=3; objPar[0]=50; hoseOn=false; if (death==1) { objLook[0]=0; activateObject(objX[0],objY[0],4,0,16,0); } else if (death==2) { activateObject(objX[0],objY[0]-24,4,0,16,0); } death=0; } } public void drawObjects() { if (hoseOn) offGraphics.drawImage(hose,hoseX,hoseY,this); for (i=0;i0)&&(objMode[i]<5)) objMode[i]=0; switch(currentKey) // Which direction? { case 105: // Up newStep(loc-15,i,1); break; case 107: // Down newStep(loc+15,i,2); break; case 106: // Left newStep(loc-1,i,3); break; case 108: // Right newStep(loc+1,i,4); break; default: break; } } if ((currentKey==74)&&((objY[i]%30)!=6)) // Pump left { k=0; l=87; for (j=1;j=objY[i])&& (objY[j]-objY[i]<20)&&(objX[i]-objX[j]>40)) if (objX[i]-objX[j]0)&&((field[j]&3968)==0)) { n=k; l=l-(objX[i]%30)-30; j--; while (l>=30) { if ((field[j]&4032)>0) n=0; l-=30; j--; } if ((field[j]&1984)>0) n=0; if (n>0) { hoseOn=true; hoseX=(objX[i]+objX[n])/2-17; hoseY=objY[i]+44; objLook[i]=13; objPar[i]=objMode[i]; objMode[i]=5; if (objType[n]<10) objType[n]+=4; if (objMode[n]==5) { objMode[n]=objPar[n]>>8; flameOn=false; objPar[n]=0; } if (objPar[n]!=0) objPar[n]=objPar[n]&255; playSound(0); } } } else if ((currentKey==76)&&((objY[i]%30)!=6)) // Pump right { k=0; l=87; for (j=1;j=objY[i])&& (objY[j]-objY[i]<20)&&(objX[j]-objX[i]>40)) if (objX[j]-objX[i]0)&&((field[j]&1984)==0)) { n=k; l=l-((30-objX[i])%30)-30; j++; while (l>=30) { if ((field[j]&4032)>0) n=0; l-=30; j++; } if ((field[j]&3968)>0) n=0; if (n>0) { hoseOn=true; hoseX=(objX[i]+objX[n])/2-17; hoseY=objY[i]+44; objLook[i]=13; objPar[i]=objMode[i]; objMode[i]=5; if (objType[n]<10) objType[n]+=4; if (objMode[n]==5) { objMode[n]=objPar[n]>>8; flameOn=false; objPar[n]=0; } if (objPar[n]!=0) objPar[n]=objPar[n]&255; playSound(0); } } } if (objMode[i]>0) digGround(objX[i],objY[i],objMode[i]); } else { if (((currentKey==74)||(currentKey==76))&&hoseOn) { objLook[i]++; if (objLook[i]==16) { objLook[i]=13; playSound(0); } } else { objMode[i]=objPar[i]; hoseOn=false; } } fixLook(i,objMode[i],1,6); fixWalk(i,objMode[i],6); break; case 2: // Rock if (objMode[i]==0) // Wiggling { objLook[i]=22+(objPar[i] & 1); objPar[i]--; if (objPar[i]<0) { field[objX[i]/30+1+(objY[i]/30+1)*15]-=28672; objMode[i]=1; objPar[i]=0; // 0 for nothing below, 10 for crushed actor } } else if (objMode[i]==1) // Falling { objY[i]+=10; loc=16+(objX[i]/30)+15*((objY[i]+objPar[i])/30); if (((objY[i]+objPar[i])%30)==0) { if ((field[loc] & 3)>0) { objMode[i]=2; objPar[i]=0; stopRockVictims(i); if ((field[loc] & 2)>3) objY[i]-=6; } } else if (((objY[i]+objPar[i])%30)==20) { if ((field[loc+15] & 12)>0) { objMode[i]=2; objPar[i]=0; objY[i]-=2; stopRockVictims(i); if ((field[loc] & 8)>0) objY[i]-=6; } } else { if ((field[loc+15] & 16)>0) { objMode[i]=2; objPar[i]=0; objY[i]-=4; stopRockVictims(i); } } for (j=0;j13)&& (objY[j]-objY[i]<30)) { if (objType[j]==1) objLook[j]=62; else if (objType[j]==6) { objLook[j]=64; newScore+=50; } else { objLook[j]=66; newScore+=150; } objPar[i]=10; // Register hit objY[j]=objY[i]+30; objMode[j]=objType[j]; objType[j]=5; objPar[j]=i; } } else // Cracking up { objPar[i]++; objLook[i]=objPar[i]+23; if (objPar[i]>4) objType[i]=0; } break; case 3: // Just wait, then go away objPar[i]--; if (objPar[i]<0) { objType[i]=0; if (i==0) // It's Don runMode=5; } break; case 4: // Angel objY[i]-=7; if (objY[i]<-50) // Vanished off screen { objType[i]=0; if (objPar[0]>15) // Don't let the corpse lie too long objPar[0]=15; } break; case 5: // Squashed objY[i]+=10; if ((objLook[i]&1)==0) objLook[i]++; break; case 6: // Pig loc=16+(objX[i]/30)+15*(objY[i]/30); if (((objX[i] % 30)==0)&&((objY[i] % 30)==0)) { stopIfBlocked(i,loc); if (objMode[i]==0) // Blocked. Find new direction. { while (objMode[i]==0) { objMode[i]=(int)(1+4*Math.random()); stopIfBlocked(i,loc); } } else if (Math.random()<0.5) // Find new direction anyway findNewDirection(i,loc); if (((field[16+(objX[0]/30)+15*(objY[0]/30)] & 1950)==0)&& (Math.random()objX[0])&&(objY[i]-objY[0]<30)&& (objY[0]-objY[i]<30)) // Fire left? { if (((objX[i]%30)==25)&&((field[loc]&2048)>0)) // Small { flameOn=true; flameX=objX[i]-23; flameLook=68; } else if (((objX[i]%30)==5)&&((field[loc]&2048)==0)&& ((field[loc-1]&4032)==0)&& ((field[loc-2]&4032)==2048)) // Medium { flameOn=true; flameX=objX[i]-63; flameLook=70; } else if (((field[loc]&3968)==0)&&((field[loc-1]&4032)==0)&& ((field[loc-2]&4032)==0)&&((field[loc-3]&1984)==0)&& (Math.random()0)) // Small { flameOn=true; flameX=objX[i]+21; flameLook=74; } else if (((objX[i]%30)==25)&&((field[loc+1]&64)==0)&& ((field[loc+2]&4032)==0)&& ((field[loc+3]&4032)==64)) // Medium { flameOn=true; flameX=objX[i]+21; flameLook=76; } else if (((field[loc+1]&1984)==0)&&(Math.random()>8; flameOn=false; objPar[i]=0; } } if (((objX[i] % 30)==0)&&((objY[i] % 30)==0)&&(objMode[i]!=5)) { stopIfBlocked(i,loc); if (objMode[i]==0) // Blocked. Find new direction. { while (objMode[i]==0) { objMode[i]=(int)(1+4*Math.random()); stopIfBlocked(i,loc); } } else if (Math.random()<0.5) // Find new direction anyway findNewDirection(i,loc); if (((field[16+(objX[0]/30)+15*(objY[0]/30)] & 1950)==0)&& (Math.random()>8); if (objPar[i]>2048) // Done { objPar[i]=objPar[i]&255; objType[i]=9; } break; case 9: // Eyes if (objX[i]<(objPar[i]%15-1)*30) objX[i]+=3; else if (objX[i]>(objPar[i]%15-1)*30) objX[i]-=3; if (objY[i]<(objPar[i]/15-1)*30) objY[i]+=3; else if (objY[i]>(objPar[i]/15-1)*30) objY[i]-=3; else { if (objX[i]==(objPar[i]%15-1)*30) // Arrived at destination { objType[i]=objMode[i]; objLook[i]=52; objMode[i]=0; objPar[i]=0; } } loc=16+(objX[i]/30)+15*(objY[i]/30); if ((Math.random()<0.1)&&((objX[i]%30)==0)&&((objY[i]%30)==0)&& ((field[loc]&1950)==0)&&(objType[i]==9)) { objType[i]=objMode[i]; // Sometimes return to normal earlier objLook[i]=52; objMode[i]=0; objPar[i]=0; } break; case 10: // Inflated pig if (!hoseOn) objPar[i]=objPar[i] | 256; if (objPar[i]>255) // Shrink { objPar[i]--; j=objPar[i] & 255; if (j!=255) { objX[i]+=offsetX[j]; objY[i]+=offsetY[j]; objLook[i]=inflateLook[j]+54; } else // Return to normal { objType[i]=6; objPar[i]=0; } } else // Grow { j=objPar[i]; if (j<15) { objX[i]-=offsetX[j]; objY[i]-=offsetY[j]; objLook[i]=inflateLook[j+1]+54; objPar[i]++; } else // Explode { newScore+=15; objLook[i]=57; objType[i]=3; objPar[i]=3; hoseOn=false; playSound(1); } } break; case 11: // Inflated dragon if (!hoseOn) objPar[i]=objPar[i] | 256; if (objPar[i]>255) // Shrink { objPar[i]--; j=objPar[i] & 255; if (j!=255) { objX[i]+=offsetX[j]; objY[i]+=offsetY[j]; objLook[i]=inflateLook[j]+58; } else // Return to normal { objType[i]=7; objPar[i]=0; } } else // Grow { j=objPar[i]; if (j<15) { objX[i]-=offsetX[j]; objY[i]-=offsetY[j]; objLook[i]=inflateLook[j+1]+58; objPar[i]++; } else // Explode { newScore+=25; objLook[i]=61; objType[i]=3; objPar[i]=3; hoseOn=false; playSound(1); } } break; default: break; } } k=activeObjects; for (i=0;i0)||((field[where]&32)>0))) objMode[who]=0; if ((objMode[who]==2)&&(((field[where+15]&62)>0)||((field[where]&1)>0))) objMode[who]=0; if ((objMode[who]==3)&&(((field[where-1]&1984)>0)||((field[where]&2048)>0))) objMode[who]=0; if ((objMode[who]==4)&&(((field[where+1]&3968)>0)||((field[where]&64)>0))) objMode[who]=0; } public void try2beGhost(int who,int where) // There must be a wall in the way { if (((objX[0]0))|| ((objX[0]>objX[who])&&((field[where]&64)>0))|| ((objY[0]0))|| ((objY[0]>objY[who])&&((field[where]&1)>0))) { objMode[who]=objType[who]; objType[who]=8; objLook[who]=52; objPar[who]=16+(objX[0]/30)+15*(objY[0]/30); } } public void findNewDirection(int who,int where) // Change direction of enemy? { temp1=0;temp2=0; if (objMode[who]<3) // Change to horizontal { if (((field[where-1]&1984)==0)&&((field[where]&2048)==0)) temp1=objX[who]-objX[0]; if (((field[where+1]&3968)==0)&&((field[where]&64)==0)) temp2=objX[0]-objX[who]; if ((temp1!=0)&&(temp2!=0)) { if (temp1>temp2) objMode[who]=3; else objMode[who]=4; } else { if (temp1!=0) objMode[who]=3; if (temp2!=0) objMode[who]=4; } } else // Change to vertical { if (((field[where-15]&31)==0)&&((field[where]&32)==0)) temp1=objY[who]-objY[0]; if (((field[where+15]&62)==0)&&((field[where]&1)==0)) temp2=objY[0]-objY[who]; if ((temp1!=0)&&(temp2!=0)) { if (temp1>temp2) objMode[who]=1; else objMode[who]=2; } else { if (temp1!=0) objMode[who]=1; if (temp2!=0) objMode[who]=2; } } } public void newStep(int where,int who,int dir) { if ((field[where] & 28672)<12288) { objMode[who]=dir; if ((field[where] & 28672)==8192) death=1; else if ((field[where] & 28672)==4096) { j=0; while (where!=groundLocs[j]) j++; farGraphics.drawImage(groundKeep[j],(where%15-1)*30, (where/15)*30-22,this); field[where]-=4096; newScore+=100; } } } public void stopRockVictims(int who) { for (j=0;j0) { if ((field[pos-15] & 1)==0) // Out of ground farGraphics.drawImage(holes[5],x,y+8,this); else if ((field[pos-15] & 2)>0) // Normal farGraphics.drawImage(holes[3],x,y+2,this); else // Breakthrough farGraphics.drawImage(holes[4],x,y+2,this); field[pos]=posVal-32; field[pos-15]=field[pos-15] & 32766; } } else { if ((posVal & (1 << by)) > 0) { if ((posVal & (1 << (by+1))) > 0) // Normal farGraphics.drawImage(holes[3],x,y+2,this); else // Breakthrough { farGraphics.drawImage(holes[4],x,y+2,this); posVal=posVal & 30847; // Clear horizontal } if (by==4) posVal=posVal & 30847; // Clear horizontal field[pos]=posVal & (32767-(1 << by)); } } break; case 2: // Down by=4-((y+24)%30)/6; if (by==0) // Edge { pos=16+(x/30)+15*(y/30); posVal=field[pos]; if ((posVal & 1)>0) { if ((field[pos+15] & 16)>0) // Normal farGraphics.drawImage(holes[6],x,y+32,this); else // Breakthrough farGraphics.drawImage(holes[4],x,y+32,this); field[pos]=posVal-1; field[pos+15]=field[pos+15] & 32735; } else if ((field[pos+15] & 32)>0) // Into ground { farGraphics.drawImage(holes[7],x,y+38,this); field[pos+15]=field[pos+15] & 32735; } } else { pos=31+(x/30)+15*(y/30); posVal=field[pos]; if ((posVal & (1 << by)) > 0) { if ((posVal & (1 << (by-1))) > 0) // Normal farGraphics.drawImage(holes[6],x,y+32,this); else // Breakthrough { farGraphics.drawImage(holes[4],x,y+32,this); posVal=posVal & 30847; // Clear horizontal } if (by==1) posVal=posVal & 30847; // Clear horizontal field[pos]=posVal &(32767-(1 << by)); } } break; case 3: // Left pos=16+(x/30)+15*(y/30); posVal=field[pos]; bx=5-(x%30)/6; if (bx==5) // Edge { if ((posVal & 2048)>0) { if ((field[pos-1] & 128)>0) // Normal farGraphics.drawImage(holes[0],x-6,y+8,this); else // Breakthrough farGraphics.drawImage(holes[1],x-6,y+8,this); field[pos]=posVal-2048; field[pos-1]=field[pos-1]-64; } } else { if ((posVal & (64 << bx)) > 0) { if ((posVal & (64 << (bx+1))) > 0) // Normal farGraphics.drawImage(holes[0],x-6,y+8,this); else // Breakthrough { farGraphics.drawImage(holes[1],x-6,y+8,this); posVal=posVal & 32737; // Clear vertical } if (bx==4) posVal=posVal & 32737; // Clear vertical field[pos]=posVal-(64 << bx); } } break; case 4: // Right bx=4-((x+24)%30)/6; if (bx==0) // Edge { pos=16+(x/30)+15*(y/30); posVal=field[pos]; if ((posVal & 64)>0) { if ((field[pos+1] & 1024)>0) // Normal farGraphics.drawImage(holes[2],x+24,y+8,this); else // Breakthrough farGraphics.drawImage(holes[1],x+24,y+8,this); field[pos]=posVal-64; field[pos+1]=field[pos+1]-2048; } } else { pos=17+(x/30)+15*(y/30); posVal=field[pos]; if ((posVal & (64 << bx)) > 0) { if ((posVal & (64 << (bx-1))) > 0) // Normal farGraphics.drawImage(holes[2],x+24,y+8,this); else // Breakthrough { farGraphics.drawImage(holes[1],x+24,y+8,this); posVal=posVal & 32737; // Clear vertical } if (bx==1) posVal=posVal & 32737; // Clear vertical field[pos]=posVal-(64 << bx); } } break; default: break; } } public void checkRock() // If a rock is loose, activate it { if (rockPos>0) { int rx=(rockPos%15-1)*30; int ry=(rockPos/15)*30-22; j=0; while (rockPos!=groundLocs[j]) j++; farGraphics.drawImage(groundKeep[j],rx,ry,this); field[rockPos]+=16384; rockPos=0; activateObject(rx,ry-8,2,0,23,5); } } public void fixClouds() { double d,scale=0.5; int holder[]=new int[448*64]; // Image source double fuzzy[]=new double[481*97]; // Raw fractal data for (i=0;i<2;i++) for (j=0;j<8;j++) fuzzy[i*30784+j*64]=(float)Math.random(); l=32; for (k=0;k<6;k++) { for (i=l*481;i<30784;i+=962*l) // Midpoints for (j=l;j<448;j+=2*l) fuzzy[i+j]=0.25*(fuzzy[i-l*482+j]+ fuzzy[i+l*480+j]+fuzzy[i-l*480+j]+ fuzzy[i+l*482+j])+scale*(Math.random()-0.5); for (i=0;i<30784;i+=962*l) // Other points for (j=0;j<448;j+=2*l) { fuzzy[i+l*483+j]=0.25*(fuzzy[i+l*2+j]+ fuzzy[i+l*964+j]+fuzzy[i+l*482+j]+ fuzzy[i+l*484+j])+scale*(Math.random()-0.5); fuzzy[i+l*963+j]=0.25*(fuzzy[i+l*962+j]+ fuzzy[i+l*964+j]+fuzzy[i+l*482+j]+ fuzzy[i+l*1444+j])+scale*(Math.random()-0.5); } for (i=0;i<=30784;i+=30784) for (j=l;j<448;j+=2*l) fuzzy[i+j]=0.5*(fuzzy[i+j-l]+fuzzy[i+j+l])+ scale*(Math.random()-0.5); for (i=l*481;i<30784;i+=962*l) for (j=0;j<=448;j+=448) fuzzy[i+j]=0.5*(fuzzy[i+j-l*481]+fuzzy[i+j+l*481])+ scale*(Math.random()-0.5); l=l/2; scale*=0.5; } for (i=0;i<64;i++) for (j=0;j<448;j++) { d=Math.min(fuzzy[i*481+j],1.0); if (d>0.5) holder[i*448+j]=opaque | (65792*(int)(255*d)) | 255; else holder[i*448+j]=opaque | 8355839; } clouds=createImage(new MemoryImageSource(448, 64, ColorModel.getRGBdefault(), holder, 0, 448)); } public void fixStrata() { double d,scale=0.6; double fuzzy[]=new double[513*33]; // Raw fractal data l=16; for (k=0;k<5;k++) { for (j=0;j<=512;j+=l) { fuzzy[j]=1; fuzzy[513*32+j]=0; } for (i=l;i<32;i+=2*l) for (j=l;j<512;j+=2*l) fuzzy[i*513+j]=0.25*(fuzzy[(i-l)*513+j-l]+ fuzzy[(i+l)*513+j-l]+fuzzy[(i-l)*513+j+l]+ fuzzy[(i+l)*513+j+l])+scale*(Math.random()-0.5); for (i=l;i<32;i+=2*l) for (j=0;j<=512;j+=2*l) if (j==0) fuzzy[i*513+j]=0.3333*(fuzzy[i*513+j+l]+ fuzzy[(i+l)*513+j]+fuzzy[(i-l)*513+j])+ scale*(Math.random()-0.5); else if (j==512) fuzzy[i*513+j]=0.3333*(fuzzy[i*513+j-l]+ fuzzy[(i+l)*513+j]+fuzzy[(i-l)*513+j])+ scale*(Math.random()-0.5); else fuzzy[i*513+j]=0.25*(fuzzy[i*513+j-l]+ fuzzy[(i+l)*513+j]+fuzzy[(i-l)*513+j]+ fuzzy[(i)*513+j+l])+scale*(Math.random()-0.5); for (i=0;i<=32;i+=2*l) for (j=l;j<512;j+=2*l) if (i==0) fuzzy[i*513+j]=0.3333*(fuzzy[i*513+j+l]+ fuzzy[(i+l)*513+j]+fuzzy[i*513+j-l])+ scale*(Math.random()-0.5); else if (i==32) fuzzy[i*513+j]=0.3333*(fuzzy[i*513+j-l]+ fuzzy[(i-l)*513+j]+fuzzy[i*513+j+l])+ scale*(Math.random()-0.5); else fuzzy[i*513+j]=0.25*(fuzzy[i*513+j-l]+ fuzzy[(i+l)*513+j]+fuzzy[(i-l)*513+j]+ fuzzy[i*513+j+l])+scale*(Math.random()-0.5); for (i=1;i<32;i++) fuzzy[512+513*i]=fuzzy[513*i]; l=l/2; scale*=0.7; } for (i=0;i<30;i++) for (j=0;j<512;j++) { strata[i*512+j]=(fuzzy[(i+1)*513+j]>0.5); } } public void drawGround() { Image pixel,separation; int oldCol,newCol,colHolder[],strataHolder[]; double a,b,c,oldLight,newLight; MediaTracker tracker; colHolder=new int[8]; strataHolder=new int[392*30]; tracker=new MediaTracker(this); i=-(int)(14*rand()); // Place sky j=-(int)(56*rand()); farGraphics.drawImage(clouds,j,i-12,this); scoreGraphics.drawImage(clouds,j,i,this); scoreCG.drawImage(scoreHolder,-176,0,this); lifeCG.drawImage(scoreHolder,-316,0,this); drawWeeds(); i=-(int)(20*rand()); // Grass farGraphics.drawImage(weeds[2],i,30,this); while (i<326) { i+=(40+(int)(24*rand())); farGraphics.drawImage(weeds[2],i,30+(int)(3*rand()),this); } n=0; a=rand();b=rand();c=rand(); oldLight=a*246+b*157+c*173; oldCol=opaque | 65536*(int)(a*baseCol[0]+b*baseCol[3]+c*baseCol[6]) | 256*(int)(a*baseCol[1]+b*baseCol[4]+c*baseCol[7]) | (int)(a*baseCol[2]+b*baseCol[5]+c*baseCol[8]); i=39; while (i<338) { for (l=0;l<8;l++) colHolder[l]=oldCol; pixel=createImage(new MemoryImageSource(8, 1, ColorModel.getRGBdefault(), colHolder, 0, 8)); tracker.addImage(pixel,n); n++; try { tracker.waitForID(0); } catch(InterruptedException e) {} j=(int)(2+30*rand()); farGraphics.drawImage(pixel,0,i,390,j,this); do { a=rand();b=rand();c=rand(); newLight=a*240+b*160+c*170; newCol=opaque | 65536*(int)(a*baseCol[0]+b*baseCol[3]+c*baseCol[6]) | 256*(int)(a*baseCol[1]+b*baseCol[4]+c*baseCol[7]) | (int)(a*baseCol[2]+b*baseCol[5]+c*baseCol[8]); } while ((newLight-oldLight<100)&&(oldLight-newLight<100)); i+=j; j=(int)(500*rand()); for (k=0;k<30;k++) for (l=0;l<392;l++) if (strata[512*k+((l+j)&511)]) strataHolder[392*k+l]=oldCol; else strataHolder[392*k+l]=newCol; separation=createImage(new MemoryImageSource(392, 30, ColorModel.getRGBdefault(), strataHolder, 0, 392)); tracker.addImage(separation,n); n++; try { tracker.waitForID(0); } catch(InterruptedException e) {} farGraphics.drawImage(separation,0,i,this); i+=30; oldCol=newCol; oldLight=newLight; } i=-(int)(30*rand()); // Roots farGraphics.drawImage(weeds[3],i,38,this); while (i<326) { i+=64; farGraphics.drawImage(weeds[3],i,38,this); } } public void drawWeeds() // Used by drawGround { for (i=0;i