ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/loops/Microscope.java
(Generate patch)

Comparing jsr166/src/test/loops/Microscope.java (file contents):
Revision 1.1 by dl, Sun Sep 19 12:55:37 2010 UTC vs.
Revision 1.3 by jsr166, Mon Sep 27 19:15:15 2010 UTC

# Line 18 | Line 18 | import java.util.concurrent.*;
18   * See <a href="http://gee.cs.oswego.edu/dl/applets/micro.html">
19   * Microscope</a> version for instructions.
20   * <p>
21 < * The code has been mangled beyond recognition
21 > * The code has been mangled beyond recognition
22   * as a test of ForkJoin
23   **/
24  
# Line 72 | Line 72 | public class Microscope extends JPanel {
72          System.exit(0);
73      }
74  
75 <    static void onExit() {
75 >    static void onExit() {
76          long now = System.currentTimeMillis();
77          System.out.println("time: " + (now - startTime) + "ms");
78          System.out.println(group.toString());
79          System.exit(0);
80 <    }        
81 <    
80 >    }
81 >
82      static void oneRun() {
83          if (java.awt.GraphicsEnvironment.isHeadless()) {
84              headless = true;
# Line 89 | Line 89 | public class Microscope extends JPanel {
89              JFrame frame = new JFrame();
90              frame.addWindowListener(new WindowAdapter() {
91                      public void windowClosing(WindowEvent e) {onExit();}});
92 <            
92 >
93              Microscope t = new Microscope();
94              frame.setSize(new Dimension(400, 400));
95              frame.getContentPane().add(t);
# Line 104 | Line 104 | public class Microscope extends JPanel {
104      Board board = new Board();        // The current board representation
105  
106      synchronized Board getBoard() { return board; }
107 <    synchronized void  setBoard(Board b) {
108 <        board = b;
107 >    synchronized void  setBoard(Board b) {
108 >        board = b;
109          System.out.print(b.score(player) + " ");
110          if (boardPanel != null)
111 <            boardPanel.repaint();
111 >            boardPanel.repaint();
112      }
113  
114      Player player = Player.Blue;      // current player (BLUE, GREEN)
# Line 140 | Line 140 | public class Microscope extends JPanel {
140      JButton modeButton;
141      JSlider levelSlider;
142  
143 <    public Microscope() {  
143 >    public Microscope() {
144          if (headless) {
145              boardPanel = null;
146              auto = new AutoMover(this);
# Line 166 | Line 166 | public class Microscope extends JPanel {
166                      }
167                      else {
168                          stopMover();
169 <                        if (getDemoMode())
169 >                        if (getDemoMode())
170                              autoButton.setText(" Start ");
171                          else
172                              autoButton.setText(" Find ");
# Line 184 | Line 184 | public class Microscope extends JPanel {
184                  public void actionPerformed(ActionEvent e) {
185                      undo();
186                  }});
187 <
187 >
188          levelSlider.addChangeListener(new ChangeListener() {
189                  public void stateChanged(ChangeEvent e) {
190                      setLevel(((JSlider)(e.getSource())).getValue());
# Line 194 | Line 194 | public class Microscope extends JPanel {
194          //        Dimension labDim = new Dimension(72, 24);
195          //        scoreLabel.setMinimumSize(labDim);
196          //        scoreLabel.setPreferredSize(labDim);
197 <    
197 >
198  
199          topPanel.add(autoButton);
200          topPanel.add(modeButton);
201          topPanel.add(undoButton);
202          topPanel.add(scoreLabel);
203          add(topPanel);
204 <    
204 >
205  
206          levelSlider.setLabelTable(levelSlider.createStandardLabels(1));
207          levelSlider.setPaintLabels(true);
# Line 215 | Line 215 | public class Microscope extends JPanel {
215          sliderPanel.add(new JLabel("Level"));
216  
217          botPanel.add(sliderPanel);
218 <    
218 >
219          add(botPanel);
220      }
221  
# Line 242 | Line 242 | public class Microscope extends JPanel {
242          lookAheads = l;
243          if (lookAheads <= 1) lookAheads = 2;
244      }
245 <    
245 >
246      public int level () { return Microscope.lookAheads; }
247 <    
247 >
248  
249      // process a move (called only from mover)
250  
251      public void move(Move m, Mover mvr) {
252 <        if (mvr != mover ||
252 >        if (mvr != mover ||
253              m == null ||
254              (mvr == user && !m.isLegal())) {
255              setMover(null);
# Line 265 | Line 265 | public class Microscope extends JPanel {
265  
266              history.addElement(m);
267  
268 <            if (mvr == auto &&
269 <                getDemoMode() &&
268 >            if (mvr == auto &&
269 >                getDemoMode() &&
270                  !m.isPass()) {
271                  if (getBoard().gameOver()) {
272                      if (autostart) {
# Line 303 | Line 303 | public class Microscope extends JPanel {
303              mvr.cancel();
304          }
305      }
306 <
306 >
307  
308      // handle Undo button
309      synchronized void undo() {
# Line 326 | Line 326 | public class Microscope extends JPanel {
326          startMover(user);
327          user.choose(row, col);
328      }
329 <  
329 >
330      void updateStatus() { // normally called from board update
331          Player p = getPlayer();
332          int s = getBoard().score(p);
# Line 334 | Line 334 | public class Microscope extends JPanel {
334              System.out.print(s + " ");
335              return;
336          }
337 <        
337 >
338          scoreLabel.setForeground(displayColor(p));
339          scoreLabel.setText("Score: " +  s);
340  
341 <        if (getDemoMode())
341 >        if (getDemoMode())
342              modeButton.setText("Demo  mode");
343          else {
344              if (getPlayer().isBlue())
# Line 350 | Line 350 | public class Microscope extends JPanel {
350      }
351  
352  
353 <    static final int CELL_SIZE = 40; // size of a tile/cell
354 <  
353 >    static final int CELL_SIZE = 40; // size of a tile/cell
354 >
355      static final Color paleGreen = new Color(152, 251, 152);
356      static final Color darkGreen = new Color(60, 179, 113);
357 <    
357 >
358      static final Color possibleMoveColor = Color.yellow;
359 <    
359 >
360  
361      public static Color displayColor(Player pl) {
362          if (pl.isBlue()) return Color.blue;
# Line 372 | Line 372 | public class Microscope extends JPanel {
372  
373  
374      class BoardPanel extends Canvas implements MouseListener {
375 <    
376 <        BoardPanel() {
377 <            setSize(new Dimension(Board.RANKS * CELL_SIZE + 5,
375 >
376 >        BoardPanel() {
377 >            setSize(new Dimension(Board.RANKS * CELL_SIZE + 5,
378                                    Board.RANKS * CELL_SIZE + 5));
379              addMouseListener(BoardPanel.this);
380          }
381 <    
381 >
382          public void paint(Graphics g) {
383 <      
383 >
384              Board b = getBoard();
385              Player p = getPlayer();
386 <      
386 >
387              // the cells
388              for (int row = 0; row < Board.RANKS; row++) {
389                  for (int col = 0; col < Board.RANKS; col++) {
390 <          
390 >
391                      // Highlight selected tile and legal destinations
392                      if (user.placing()) {
393 <                        if (user.hasMovedFrom(row, col))
393 >                        if (user.hasMovedFrom(row, col))
394                              g.setColor(lightDisplayColor(p));
395                          else if (user.canMoveTo(row, col))
396                              g.setColor(possibleMoveColor);
397                          else
398                              g.setColor(displayColor(b.occupant(row, col)));
399                      }
400 <          
400 >
401                      else
402                          g.setColor(displayColor(b.occupant(row, col)));
403 <          
403 >
404                      // tiles are just filled rectangles
405                      g.fillRect(row * CELL_SIZE, col * CELL_SIZE, CELL_SIZE, CELL_SIZE);
406                  }
407              }
408 <      
408 >
409              // the grid over the cells
410              g.setColor(Color.black);
411              for ( int i = 0; i <= Board.RANKS; i++) {
412                  g.drawLine(0, i * CELL_SIZE, Board.RANKS * CELL_SIZE, i * CELL_SIZE);
413                  g.drawLine(i * CELL_SIZE, 0, i * CELL_SIZE, Board.RANKS * CELL_SIZE);
414              }
415 <      
415 >
416              updateStatus();
417          }
418 <    
418 >
419          public void mouseReleased(MouseEvent evt) {
420 <      
420 >
421              int x = evt.getX();
422              int y = evt.getY();
423 <      
423 >
424              int row = x / CELL_SIZE;
425              int col = y / CELL_SIZE;
426 <      
426 >
427              if (Board.inBounds(row, col)) { // cell selection
428                  userMove(row, col);
429                  repaint();
430              }
431          }
432 <    
432 >
433          public void mouseClicked(MouseEvent e) {}
434          public void mousePressed(MouseEvent e) {}
435          public void mouseEntered(MouseEvent e) {}
# Line 446 | Line 446 | public class Microscope extends JPanel {
446          public static final int BLUE = 1;
447          public static final int GREEN = 2;
448          public static final int ILLEGAL_PLAYER_VALUE = 3;
449 <    
449 >
450          public static final Player Empty   = new Player(EMPTY);
451          public static final Player Blue    = new Player(BLUE);
452          public static final Player Green   = new Player(GREEN);
453          public static final Player Illegal = new Player(ILLEGAL_PLAYER_VALUE);
454 <    
454 >
455          /* private */ int code_;
456 <    
456 >
457          public Player(int code)       { code_ = code; }
458          public Player(Player p)       { code_ = p.code_; }
459 <    
459 >
460          public boolean same(Player p) { return code_ == p.code_; }
461 <    
461 >
462          public boolean isEmpty()      { return code_ == EMPTY; }
463          public boolean isBlue()       { return code_ == BLUE; }
464          public boolean isGreen()      { return code_ == GREEN; }
465          public boolean isLegal()      { return code_ <= GREEN; }
466 <    
467 <        public Player opponent() {
466 >
467 >        public Player opponent() {
468              if (code_ == GREEN) return Blue;
469              else if (code_ == BLUE) return Green;
470              else return Illegal;
471          }
472 <    
472 >
473      }
474 <  
474 >
475      /**
476       *   Board configurations are represented by bit vectors.
477       *   Since there are only 49 cells, the bits can be held in `longs',
# Line 481 | Line 481 | public class Microscope extends JPanel {
481       * threads (instead new ones are constructed), so don't
482       * need any synch.
483       **/
484 <  
484 >
485      static final class Board   {
486  
487 <        /*
487 >        /*
488             First, some Constants and utilities that might as well be here
489          */
490 <    
490 >
491          public static final int RANKS = 7;
492          public static final int CELLS = RANKS * RANKS;
493 <    
493 >
494          static final long FULL = (1L << CELLS) - 1;
495 <    
495 >
496          // The finder uses a spare bit to remember whose move it is.
497          static final long BLUEBIT = (1L << CELLS);
498 <    
498 >
499          // Bits representing the adjacent cells for every position
500          static final long[] adjacentMasks = new long[CELLS];
501 <    
501 >
502          // bit pattern associated with each tile
503          static final long[] cellBits = new long[CELLS];
504  
# Line 537 | Line 537 | public class Microscope extends JPanel {
537              }
538  
539          }
540 <    
541 <    
540 >
541 >
542          public static boolean inBounds(int row, int col) {
543              return (0 <= row)  && (row < RANKS) && (0 <= col) && (col < RANKS);
544          }
545 <    
545 >
546          // The representation
547 <    
547 >
548          long blue_;      // bit vector; true if occupied by blue
549          long green_;     // same for green;
550 <    
550 >
551          // constructors and intializers:
552 <    
552 >
553          public Board()               { blue_ = 0L; green_ = 0L; }
554          public Board(Board b)        { blue_ = b.blue_; green_ = b.green_; }
555          public Board(long b, long g) { blue_ = b; green_ = g; }
556 <    
556 >
557          public void copyState(Board b) {
558 <            blue_ = b.blue_;
559 <            green_ = b.green_;
558 >            blue_ = b.blue_;
559 >            green_ = b.green_;
560          }
561  
562 <        void reset() {
563 <            blue_ = 0L; green_ = 0L;
562 >        void reset() {
563 >            blue_ = 0L; green_ = 0L;
564          }
565 <    
565 >
566          long getBlue() { return blue_; }
567          long getGreen() { return green_; }
568  
# Line 577 | Line 577 | public class Microscope extends JPanel {
577              else
578                  return Player.Illegal;
579          }
580 <    
581 <    
580 >
581 >
582          // place a tile without taking opponent tiles
583 <    
583 >
584          public void occupy(Player player, int row, int col) {
585              long m = 1L << (row + col * RANKS);
586              long nm = ~m;
587 <            if (player.code_ == Player.BLUE)  {
587 >            if (player.code_ == Player.BLUE)  {
588                  blue_ |= m;
589                  green_ &= nm;
590              }
591 <            else if (player.code_ == Player.GREEN) {
591 >            else if (player.code_ == Player.GREEN) {
592                  blue_ &=  nm;
593                  green_ |= m;
594              }
595 <            else {
595 >            else {
596                  blue_ &= nm;
597                  green_ &= nm;
598              }
599          }
600 <    
600 >
601          public void unoccupy(int row, int col) {
602              long nm = ~(1L << (row + col * RANKS));
603              blue_ &=  nm;
604              green_ &= nm;
605          }
606 <    
607 <    
608 <    
606 >
607 >
608 >
609          // place a tile, taking all adjacent tiles of opponent
610 <    
610 >
611          public void take(Player player, int row, int col) {
612              int k =  (row + col * RANKS);
613              long dest = 1L << k;
# Line 623 | Line 623 | public class Microscope extends JPanel {
623                  green_ =  sourceGreen | dest | (sourceBlue & nbrMask);
624              }
625          }
626 <    
626 >
627          public boolean gameOver() {
628 <            return
628 >            return
629                  (((blue_ | green_) & FULL) == FULL) ||
630                  ((blue_ & ~BLUEBIT) == 0) ||
631                  ((green_ & ~BLUEBIT) == 0);
632          }
633 <    
634 <    
633 >
634 >
635          public int score(Player player) {
636              if (player.isBlue()) {
637                  return score(blue_, green_);
# Line 640 | Line 640 | public class Microscope extends JPanel {
640                  return score(green_, blue_);
641              }
642          }
643 <    
643 >
644          static int score(long b, long g) {
645 <      
645 >
646              // much faster by splitting into ints
647              // and using clever shift-based bit counter
648 <      
648 >
649              int lb = (int)(b & ((1L << 32) - 1));
650              int hb = ((int)(b >>> 32)) & ((1 << (CELLS - 32)) - 1);
651  
# Line 680 | Line 680 | public class Microscope extends JPanel {
680  
681              return hb - ((lg + hg) & 0xff);
682          }
683 <    
684 <    
685 <    
683 >
684 >
685 >
686          static int slowscore(long b, long g) {
687              int score = 0;
688              for (int l = 0; l < CELLS; ++l) {
# Line 693 | Line 693 | public class Microscope extends JPanel {
693              }
694              return score;
695          }
696 <  
697 <    
696 >
697 >
698      }
699 <  
699 >
700      /**
701       * Moves represent transitions across Board states
702       **/
# Line 706 | Line 706 | public class Microscope extends JPanel {
706  
707          static final int NO_VALUE = -1;     // row/col value if not yet set
708          static final int PASS_VALUE = -2;   // special value for pass moves
709 <    
709 >
710          // utilities for classifying moves
711 <    
712 <        public static boolean twoFrom(int a, int b) {
713 <            return (a - b == 2) || (b - a == 2);
711 >
712 >        public static boolean twoFrom(int a, int b) {
713 >            return (a - b == 2) || (b - a == 2);
714          }
715 <    
716 <        public static boolean withinTwo(int a, int b) {
715 >
716 >        public static boolean withinTwo(int a, int b) {
717              int diff = a - b; return -2 <= diff && diff <= 2;
718          }
719 <    
719 >
720          // representations
721 <    
721 >
722          int fromRow;
723          int fromCol;
724 <    
724 >
725          int toRow;
726          int toCol;
727 <    
727 >
728          Player player_;
729          Board board_;
730 <    
730 >
731          boolean committed = false; // true if board reflects move
732 <    
732 >
733          // constructors and intializers
734 <    
735 <        public Move(Player turn, Board board) {
734 >
735 >        public Move(Player turn, Board board) {
736              fromRow = NO_VALUE; fromCol = NO_VALUE;
737              toRow = NO_VALUE;   toCol = NO_VALUE;
738              player_ = turn;
739              board_ = board;
740          }
741 <    
742 <        public Move(Player turn, Board board, boolean isCommitted) {
741 >
742 >        public Move(Player turn, Board board, boolean isCommitted) {
743              fromRow = NO_VALUE; fromCol = NO_VALUE;
744              toRow = NO_VALUE;   toCol = NO_VALUE;
745              player_ = turn;
746              board_ = board;
747              committed = isCommitted;
748          }
749 <    
749 >
750          synchronized void reset() {
751              fromRow = NO_VALUE;
752              fromCol = NO_VALUE;
753              toRow = NO_VALUE;
754              toCol = NO_VALUE;
755          }
756 <    
756 >
757          // setters:
758 <    
758 >
759          synchronized void player(Player p)       { player_ = p;  }
760          synchronized void board(Board b)         { board_ = b;  }
761          synchronized void from(int sr, int sc)   { fromRow = sr; fromCol = sc;  }
762          synchronized void to(int dr, int dc)     { toRow = dr;   toCol = dc; }
763 <  
763 >
764          //  accessors:
765 <    
766 <        synchronized boolean isFrom(int r, int c) {
767 <            return fromRow== r && fromCol == c;
765 >
766 >        synchronized boolean isFrom(int r, int c) {
767 >            return fromRow== r && fromCol == c;
768          }
769 <        synchronized boolean isTo(int r, int c)   {
770 <            return toRow == r && toCol == c;
769 >        synchronized boolean isTo(int r, int c)   {
770 >            return toRow == r && toCol == c;
771          }
772 <        synchronized Board board() {
773 <            return board_;
772 >        synchronized Board board() {
773 >            return board_;
774          }
775 <        synchronized Player player() {
776 <            return player_;
775 >        synchronized Player player() {
776 >            return player_;
777          }
778 <    
778 >
779  
780          // status checks:
781 <    
781 >
782          synchronized boolean isPass() { // is this a `pass' move?
783              return (toRow == PASS_VALUE || fromRow == PASS_VALUE);
784          }
785 <    
785 >
786          synchronized boolean isJump() {
787 <            return
787 >            return
788                  (fromRow - toRow == 2) || (toRow - fromRow == 2) ||
789                  (fromCol - toCol == 2) || (toCol - fromCol == 2);
790          }
791 <    
791 >
792          synchronized boolean hasFrom() { // is from set?
793              return fromRow != NO_VALUE && fromCol != NO_VALUE;
794          }
795 <    
795 >
796          synchronized boolean hasTo() { // is to set?
797              return toRow != NO_VALUE && toCol != NO_VALUE;
798          }
799 <    
800 <    
799 >
800 >
801          synchronized boolean possibleTo(int r, int c) { // is (r, c) a legal `to'?
802              return hasFrom() &&
803                  withinTwo(fromRow, r) &&
804                  withinTwo(fromCol, c) &&
805                  board_.occupant(r, c).isEmpty();
806          }
807 <    
807 >
808          synchronized boolean isLegal() {
809 <            if (isPass())
809 >            if (isPass())
810                  return true;
811 <            else if (!board_.occupant(toRow, toCol).isEmpty())
811 >            else if (!board_.occupant(toRow, toCol).isEmpty())
812                  return false;
813 <            else if (!board_.occupant(fromRow, fromCol).same(player_))
813 >            else if (!board_.occupant(fromRow, fromCol).same(player_))
814                  return false;
815 <            else if (!(withinTwo(fromRow, toRow) && withinTwo(fromCol, toCol)))
815 >            else if (!(withinTwo(fromRow, toRow) && withinTwo(fromCol, toCol)))
816                  return false;
817              else
818                  return true;
819          }
820 <    
820 >
821          synchronized void commit() { // update board to reflect move
822              if (!committed) {
823                  committed = true;
# Line 827 | Line 827 | public class Microscope extends JPanel {
827                  }
828              }
829          }
830 <    
830 >
831      }
832 <  
832 >
833      /**
834       *  Mover is an abstract class to simplify code dealing with
835       *  either user moves or auto moves.
836 <     **/
837 <  
836 >     */
837 >    abstract static class Mover {
838  
839    static abstract class Mover {
840    
839          // caller for move callbacks
840          protected Microscope game;
841 <    
841 >
842          protected Mover(Microscope ap) { game = ap; }
843 <    
843 >
844          // start a turn as player on given board
845          public abstract void startTurn(Board b, Player p);
846 <    
846 >
847          // cancel current partial move
848          public abstract void cancel();
849 <    
849 >
850          // return true if move not yet ready
851          public abstract boolean placing();
852 <    
852 >
853      }
854 <  
854 >
855      /**
856       *  User builds moves via instructions/clicks by users
857       **/
# Line 861 | Line 859 | public class Microscope extends JPanel {
859      static class User extends Mover {
860  
861          private Move current;
862 <    
862 >
863          public User(Microscope ap) { super(ap); current = null; }
864 <    
864 >
865          public synchronized void startTurn(Board b, Player p) {
866              current = new Move(p, b);
867          }
868 <    
869 <        public boolean placing() {
870 <            return current != null && current.hasFrom() && !current.hasTo();
868 >
869 >        public boolean placing() {
870 >            return current != null && current.hasFrom() && !current.hasTo();
871          }
872 <    
873 <        public synchronized void cancel() {
872 >
873 >        public synchronized void cancel() {
874              if (current != null) {
875 <                current.reset();
876 <                current = null;
875 >                current.reset();
876 >                current = null;
877              }
878          }
879 <    
879 >
880          public synchronized void choose(int row, int col) {
881              if (current != null) {
882                  if (row == Move.PASS_VALUE) {
# Line 898 | Line 896 | public class Microscope extends JPanel {
896                  }
897              }
898          }
899 <    
899 >
900          public synchronized boolean canMoveTo(int row, int col) {
901              return placing() && current.possibleTo(row, col);
902          }
903 <    
903 >
904          public synchronized boolean hasMovedFrom(int row, int col) {
905              return current != null && current.isFrom(row, col);
906          }
907 <    
907 >
908      }
909  
910  
# Line 922 | Line 920 | public class Microscope extends JPanel {
920          public AutoMover(Microscope ap) {
921              super(ap);
922          }
923 <  
924 <    
925 <        public synchronized boolean placing() {
926 <            return currentFinder != null;
923 >
924 >
925 >        public synchronized boolean placing() {
926 >            return currentFinder != null;
927          }
928  
929 <        synchronized void stopPlacing() {
929 >        synchronized void stopPlacing() {
930              currentFinder = null;
931          }
932 <    
933 <    
932 >
933 >
934          public synchronized void cancel() {
935 <            if (placing())  {
935 >            if (placing())  {
936                  currentFinder.cancel(false);
937                  stopPlacing();
938              }
# Line 942 | Line 940 | public class Microscope extends JPanel {
940  
941          public synchronized void startTurn(Board board, Player player) {
942              if (!placing()) {
943 <                currentFinder = new RootFinder(board, player,
943 >                currentFinder = new RootFinder(board, player,
944                                                 Microscope.lookAheads, this);
945                  group.execute(currentFinder);
946              }
947          }
948 <    
948 >
949          synchronized void relay(Move move) { // relay callback from finder
950              if (placing()) {
951                  stopPlacing();
952                  game.move(move, this);
953              }
954          }
955 <    
955 >
956      }
957 <  
957 >
958  
959      /**
960       * Implements a classic all-possible-move search algorith using
# Line 967 | Line 965 | public class Microscope extends JPanel {
965       * be changed to prune moves, although this is unlikely to work
966       * well without better partial evaluation functions.
967       **/
968 <  
968 >
969      static class Finder extends RecursiveAction {
970  
971          static final int NOMOVE = Integer.MIN_VALUE;
972          static final int LOSE   = NOMOVE+1;
973          static final int WIN    = -LOSE;
974 <    
974 >
975          final long ours;     // bits for our tiles
976          final long theirs;   // bits for opponent tiles
977          final int level;     // current number of lookAheads
# Line 992 | Line 990 | public class Microscope extends JPanel {
990          protected final void compute() {
991  
992              // Handle sure wins and losses here
993 <            if ((ours & ~Board.BLUEBIT) == 0)  
993 >            if ((ours & ~Board.BLUEBIT) == 0)
994                  bestScore = LOSE;
995  
996 <            else if ((theirs & ~Board.BLUEBIT) == 0)
996 >            else if ((theirs & ~Board.BLUEBIT) == 0)
997                  bestScore = WIN;
998  
999              else if (((ours | theirs) & Board.FULL) == Board.FULL) {
# Line 1005 | Line 1003 | public class Microscope extends JPanel {
1003                  else bestScore = 0;
1004              }
1005  
1006 <            else
1006 >            else
1007                  search();
1008          }
1009 <    
1009 >
1010  
1011          final void search() {
1012              int best = NOMOVE;    // For direct evaluation when level == 1
1013              Finder forked = null; // list of forked subtasks when level > 1
1014 <      
1014 >
1015              long open = ~(ours | theirs);  // currently empty cells
1016              long here = 1;                 // travserse through bits
1017 <      
1017 >
1018              for (int k = 0; k < Board.CELLS; ++k, here <<= 1) {
1019                  if ((here & ours) != 0) {
1020                      /*
# Line 1027 | Line 1025 | public class Microscope extends JPanel {
1025                      for (int j = 0; j < dests.length; ++j) {
1026                          byte d = dests[j];
1027                          long dest = 1L << d;
1028 <                        
1028 >
1029                          if ( (dest & open) != 0) {
1030                              long adjacent = Board.adjacentMasks[d];
1031                              long nTheirs = theirs & ~adjacent;
1032                              long nOurs = (ours & ~here) | dest | (theirs & adjacent);
1033  
1034 <                            if (level > 1)
1035 <                                (forked =
1034 >                            if (level > 1)
1035 >                                (forked =
1036                                   new Finder(nTheirs, nOurs, level-1, forked)).fork();
1037                              else {
1038                                  int sc = Board.score(nOurs, nTheirs);
# Line 1054 | Line 1052 | public class Microscope extends JPanel {
1052                      if ((ours & adjacent) != 0) {
1053                          long nTheirs = theirs & ~adjacent;
1054                          long nOurs = ours | here | (theirs & adjacent);
1055 <                        if (level > 1)
1055 >                        if (level > 1)
1056                              (forked = new Finder(nTheirs, nOurs, level-1, forked)).fork();
1057                          else {
1058                              int sc = Board.score(nOurs, nTheirs);
# Line 1078 | Line 1076 | public class Microscope extends JPanel {
1076          void collect(Finder forked) {
1077              int best = NOMOVE;
1078              while (forked != null) {
1079 <                while (!forked.isDone()) {
1080 <                    // interleave joins with status checks                    
1079 >                while (!forked.isDone()) {
1080 >                    // interleave joins with status checks
1081                      if (isDone()) {
1082                          cancelAll(forked);
1083                          return;
# Line 1122 | Line 1120 | public class Microscope extends JPanel {
1120       **/
1121  
1122      static class RootFinder extends Finder {
1123 <        final AutoMover automover;
1123 >        final AutoMover automover;
1124          final Player player;
1125          RootFinder(Board board, Player p, int level, AutoMover automover) {
1126              super( (p.isBlue()? (board.getBlue()| Board.BLUEBIT) : board.getGreen()),
1127                     (p.isBlue()? board.getGreen() : (board.getBlue()| Board.BLUEBIT)),
1128                     level,
1129                     null);
1130 <            
1130 >
1131              this.player = p;
1132              this.automover = automover;
1133          }
# Line 1163 | Line 1161 | public class Microscope extends JPanel {
1161                          break;
1162                      }
1163                  }
1164 <        
1164 >
1165                  // Just for fun, introduce a little randomness via hashcodes
1166                  else if (score == best &&
1167                           !Microscope.DETERMINISTIC &&
1168 <                         (System.identityHashCode(forked) >
1168 >                         (System.identityHashCode(forked) >
1169                            System.identityHashCode(bestFinder))) {
1170                      bestFinder = forked;
1171                  }
1172                  forked = forked.next;
1173              }
1174 <      
1174 >
1175              Move move = null;
1176              if (bestFinder != null) {
1177 <                /*
1177 >                /*
1178                     Even though accessed here,
1179                     the ours and theirs vars of Finders do not
1180                     need to be volatile because they are immutably
1181                     established in constructors.
1182                  */
1183 <        
1183 >
1184                  long nextOurs = bestFinder.theirs;
1185                  long nextTheirs = bestFinder.ours;
1186                  long blue = (player.isBlue())? nextOurs : nextTheirs;
# Line 1193 | Line 1191 | public class Microscope extends JPanel {
1191          }
1192      }
1193  
1194 <  
1194 >
1195   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines