import java.awt.*; import java.awt.image.*; import java.applet.*; import java.awt.event.*; import java.io.*; import java.net.*; // This applet implements the skill control buttons and also does all the computational // work of determining the computer's move (standard MINMAX algorithm with pruning) public class right extends Applet implements Runnable, MouseListener { int i,j,k,l,m,n,o,p,x,y,dbi,mpi,mpj; int counter,leaves; int numchecks,seed; long playerMasks[],computerMasks[],tl,lbase=3; final long pmask=0x555555555555555L,cmask=0xaaaaaaaaaaaaaaaL; long posMasks[]=new long[27]; long currentBoard,li,lj; int xdirs[]=new int[27],ydirs[]=new int[27],zdirs[]=new int[27]; int skill=2; boolean computerToMove; Image background,collection,but1,but2; Graphics bg; long nextTime; MediaTracker mt; Thread runner; ImageProducer improd; cluster clusterApplet; public void init() { mt=new MediaTracker(this); InputStream imgstrm; imgstrm = getClass().getResourceAsStream("row2c.gif"); try { byte imageBytes[] = new byte[imgstrm.available()]; imgstrm.read(imageBytes); collection = Toolkit.getDefaultToolkit().createImage(imageBytes); } catch (IOException ioe) {} mt.addImage(collection,0); try { mt.waitForID(0); } catch(InterruptedException e) {} background=createImage(51,126); bg=background.getGraphics(); improd=collection.getSource(); but1=createImage(new FilteredImageSource(improd, new CropImageFilter(0,126,30,19))); mt.addImage(but1,1); but2=createImage(new FilteredImageSource(improd, new CropImageFilter(0,145,30,19))); mt.addImage(but2,1); try { mt.waitForID(1); } catch(InterruptedException e) {} bg.drawImage(collection,0,0,this); drawButtons(); // Slight randomness in choice of moves, in case of several equivalent // alternatives seed=1+(int)(System.currentTimeMillis()&16383); // Figure out some values that will make the MINMAX algorithm a little more // efficient. A "long" value represents the state of the board, where // each bit pair is either 00 (empty pos.), 01 (blue marble) or 10 (red marble) l=0; for (i=-1;i<2;i++) for (j=-1;j<2;j++) for (k=-1;k<2;k++) { xdirs[l]=i; ydirs[l]=j; zdirs[l++]=k; } long holders[]=new long[70]; numchecks=0; for (i=0;i<3;i++) for (j=0;j<3;j++) for (k=0;k<3;k++) for (l=0;l<27;l++) { if (i+2*xdirs[l]>=0 && i+2*xdirs[l]<3 && j+2*ydirs[l]>=0 && j+2*ydirs[l]<3 && k+2*zdirs[l]>=0 && k+2*zdirs[l]<3 && l!=13) for (m=l+1;m<27;m++) { if (i+2*xdirs[m]>=0 && i+2*xdirs[m]<3 && j+2*ydirs[m]>=0 && j+2*ydirs[m]<3 && k+2*zdirs[m]>=0 && k+2*zdirs[m]<3 && xdirs[l]*xdirs[m]+ydirs[l]*ydirs[m]+zdirs[l]*zdirs[m]==0 && m!=13) { tl=lbase<<2*(i+3*j+9*k); tl|=lbase<<2*(i+xdirs[l]+3*(j+ydirs[l])+9*(k+zdirs[l])); tl|=lbase<<2*(i+2*xdirs[l]+3*(j+2*ydirs[l])+9*(k+2*zdirs[l])); tl|=lbase<<2*(i+xdirs[m]+3*(j+ydirs[m])+9*(k+zdirs[m])); tl|=lbase<<2*(i+2*xdirs[m]+3*(j+2*ydirs[m])+9*(k+2*zdirs[m])); holders[numchecks++]=tl; } } } playerMasks=new long[numchecks]; computerMasks=new long[numchecks]; for (i=0;i=0) // Player wins clusterApplet.playerWins(playerMasks[j]); else computerToMove=true; // Let the main loop know it's time to call the AI } public void clearBoard() // Called during reset { currentBoard=0; computerToMove=false; } public void makeComputerMove() { // MINMAX implementation, outer routine int i,j,k,bestscore=-2000,bestmove=0; leaves=0; i=randi()%27; // Start evaluating at a random position for (k=0;k<27;k++) { if ((currentBoard & posMasks[i])==0) { j=evaluateMove(currentBoard | (posMasks[i]&cmask),1,bestscore); if (j>bestscore) { bestscore=j; bestmove=i; } } i=(i+1)%27; } currentBoard|=posMasks[bestmove] & cmask; j=-1; for (i=0;i=0) // Computer wins clusterApplet.computerWins(computerMasks[j]); else clusterApplet.placeComputerBall(bestmove); } public int evaluateMove(long currB, int lev, int best) { // MINMAX recursive part int i,j,k; if (lev>=skill) // Bottom level { leaves++; j=0; for (i=0;ik) { k=j; if (j>=best) i=27; } } return k; } } public void mouseEntered(MouseEvent me){} public void mouseExited(MouseEvent me){} public void mouseReleased(MouseEvent me){} public void mouseClicked(MouseEvent me){} public void mousePressed(MouseEvent me) { x=me.getX(); y=me.getY(); mpj=-1; for (mpi=0;mpi<4;mpi++) { if (y>109-27*mpi && y<122-27*mpi && x>25 && x<45) mpj=mpi; } if (mpj>=0) // Changed skill level? { skill=mpj+1; drawButtons(); repaint(); } } public int randi() // Pseudo-random number generator, integer { seed=(seed*171)%30269; return seed; } public void update(Graphics g) { g.drawImage(background,0,0,this); } public void paint(Graphics g) { g.drawImage(background,0,0,this); } }