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.2 by jsr166, Mon Sep 20 20:42:37 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 <  
837 >
838  
839      static abstract class Mover {
840 <    
840 >
841          // caller for move callbacks
842          protected Microscope game;
843 <    
843 >
844          protected Mover(Microscope ap) { game = ap; }
845 <    
845 >
846          // start a turn as player on given board
847          public abstract void startTurn(Board b, Player p);
848 <    
848 >
849          // cancel current partial move
850          public abstract void cancel();
851 <    
851 >
852          // return true if move not yet ready
853          public abstract boolean placing();
854 <    
854 >
855      }
856 <  
856 >
857      /**
858       *  User builds moves via instructions/clicks by users
859       **/
# Line 861 | Line 861 | public class Microscope extends JPanel {
861      static class User extends Mover {
862  
863          private Move current;
864 <    
864 >
865          public User(Microscope ap) { super(ap); current = null; }
866 <    
866 >
867          public synchronized void startTurn(Board b, Player p) {
868              current = new Move(p, b);
869          }
870 <    
871 <        public boolean placing() {
872 <            return current != null && current.hasFrom() && !current.hasTo();
870 >
871 >        public boolean placing() {
872 >            return current != null && current.hasFrom() && !current.hasTo();
873          }
874 <    
875 <        public synchronized void cancel() {
874 >
875 >        public synchronized void cancel() {
876              if (current != null) {
877 <                current.reset();
878 <                current = null;
877 >                current.reset();
878 >                current = null;
879              }
880          }
881 <    
881 >
882          public synchronized void choose(int row, int col) {
883              if (current != null) {
884                  if (row == Move.PASS_VALUE) {
# Line 898 | Line 898 | public class Microscope extends JPanel {
898                  }
899              }
900          }
901 <    
901 >
902          public synchronized boolean canMoveTo(int row, int col) {
903              return placing() && current.possibleTo(row, col);
904          }
905 <    
905 >
906          public synchronized boolean hasMovedFrom(int row, int col) {
907              return current != null && current.isFrom(row, col);
908          }
909 <    
909 >
910      }
911  
912  
# Line 922 | Line 922 | public class Microscope extends JPanel {
922          public AutoMover(Microscope ap) {
923              super(ap);
924          }
925 <  
926 <    
927 <        public synchronized boolean placing() {
928 <            return currentFinder != null;
925 >
926 >
927 >        public synchronized boolean placing() {
928 >            return currentFinder != null;
929          }
930  
931 <        synchronized void stopPlacing() {
931 >        synchronized void stopPlacing() {
932              currentFinder = null;
933          }
934 <    
935 <    
934 >
935 >
936          public synchronized void cancel() {
937 <            if (placing())  {
937 >            if (placing())  {
938                  currentFinder.cancel(false);
939                  stopPlacing();
940              }
# Line 942 | Line 942 | public class Microscope extends JPanel {
942  
943          public synchronized void startTurn(Board board, Player player) {
944              if (!placing()) {
945 <                currentFinder = new RootFinder(board, player,
945 >                currentFinder = new RootFinder(board, player,
946                                                 Microscope.lookAheads, this);
947                  group.execute(currentFinder);
948              }
949          }
950 <    
950 >
951          synchronized void relay(Move move) { // relay callback from finder
952              if (placing()) {
953                  stopPlacing();
954                  game.move(move, this);
955              }
956          }
957 <    
957 >
958      }
959 <  
959 >
960  
961      /**
962       * Implements a classic all-possible-move search algorith using
# Line 967 | Line 967 | public class Microscope extends JPanel {
967       * be changed to prune moves, although this is unlikely to work
968       * well without better partial evaluation functions.
969       **/
970 <  
970 >
971      static class Finder extends RecursiveAction {
972  
973          static final int NOMOVE = Integer.MIN_VALUE;
974          static final int LOSE   = NOMOVE+1;
975          static final int WIN    = -LOSE;
976 <    
976 >
977          final long ours;     // bits for our tiles
978          final long theirs;   // bits for opponent tiles
979          final int level;     // current number of lookAheads
# Line 992 | Line 992 | public class Microscope extends JPanel {
992          protected final void compute() {
993  
994              // Handle sure wins and losses here
995 <            if ((ours & ~Board.BLUEBIT) == 0)  
995 >            if ((ours & ~Board.BLUEBIT) == 0)
996                  bestScore = LOSE;
997  
998 <            else if ((theirs & ~Board.BLUEBIT) == 0)
998 >            else if ((theirs & ~Board.BLUEBIT) == 0)
999                  bestScore = WIN;
1000  
1001              else if (((ours | theirs) & Board.FULL) == Board.FULL) {
# Line 1005 | Line 1005 | public class Microscope extends JPanel {
1005                  else bestScore = 0;
1006              }
1007  
1008 <            else
1008 >            else
1009                  search();
1010          }
1011 <    
1011 >
1012  
1013          final void search() {
1014              int best = NOMOVE;    // For direct evaluation when level == 1
1015              Finder forked = null; // list of forked subtasks when level > 1
1016 <      
1016 >
1017              long open = ~(ours | theirs);  // currently empty cells
1018              long here = 1;                 // travserse through bits
1019 <      
1019 >
1020              for (int k = 0; k < Board.CELLS; ++k, here <<= 1) {
1021                  if ((here & ours) != 0) {
1022                      /*
# Line 1027 | Line 1027 | public class Microscope extends JPanel {
1027                      for (int j = 0; j < dests.length; ++j) {
1028                          byte d = dests[j];
1029                          long dest = 1L << d;
1030 <                        
1030 >
1031                          if ( (dest & open) != 0) {
1032                              long adjacent = Board.adjacentMasks[d];
1033                              long nTheirs = theirs & ~adjacent;
1034                              long nOurs = (ours & ~here) | dest | (theirs & adjacent);
1035  
1036 <                            if (level > 1)
1037 <                                (forked =
1036 >                            if (level > 1)
1037 >                                (forked =
1038                                   new Finder(nTheirs, nOurs, level-1, forked)).fork();
1039                              else {
1040                                  int sc = Board.score(nOurs, nTheirs);
# Line 1054 | Line 1054 | public class Microscope extends JPanel {
1054                      if ((ours & adjacent) != 0) {
1055                          long nTheirs = theirs & ~adjacent;
1056                          long nOurs = ours | here | (theirs & adjacent);
1057 <                        if (level > 1)
1057 >                        if (level > 1)
1058                              (forked = new Finder(nTheirs, nOurs, level-1, forked)).fork();
1059                          else {
1060                              int sc = Board.score(nOurs, nTheirs);
# Line 1078 | Line 1078 | public class Microscope extends JPanel {
1078          void collect(Finder forked) {
1079              int best = NOMOVE;
1080              while (forked != null) {
1081 <                while (!forked.isDone()) {
1082 <                    // interleave joins with status checks                    
1081 >                while (!forked.isDone()) {
1082 >                    // interleave joins with status checks
1083                      if (isDone()) {
1084                          cancelAll(forked);
1085                          return;
# Line 1122 | Line 1122 | public class Microscope extends JPanel {
1122       **/
1123  
1124      static class RootFinder extends Finder {
1125 <        final AutoMover automover;
1125 >        final AutoMover automover;
1126          final Player player;
1127          RootFinder(Board board, Player p, int level, AutoMover automover) {
1128              super( (p.isBlue()? (board.getBlue()| Board.BLUEBIT) : board.getGreen()),
1129                     (p.isBlue()? board.getGreen() : (board.getBlue()| Board.BLUEBIT)),
1130                     level,
1131                     null);
1132 <            
1132 >
1133              this.player = p;
1134              this.automover = automover;
1135          }
# Line 1163 | Line 1163 | public class Microscope extends JPanel {
1163                          break;
1164                      }
1165                  }
1166 <        
1166 >
1167                  // Just for fun, introduce a little randomness via hashcodes
1168                  else if (score == best &&
1169                           !Microscope.DETERMINISTIC &&
1170 <                         (System.identityHashCode(forked) >
1170 >                         (System.identityHashCode(forked) >
1171                            System.identityHashCode(bestFinder))) {
1172                      bestFinder = forked;
1173                  }
1174                  forked = forked.next;
1175              }
1176 <      
1176 >
1177              Move move = null;
1178              if (bestFinder != null) {
1179 <                /*
1179 >                /*
1180                     Even though accessed here,
1181                     the ours and theirs vars of Finders do not
1182                     need to be volatile because they are immutably
1183                     established in constructors.
1184                  */
1185 <        
1185 >
1186                  long nextOurs = bestFinder.theirs;
1187                  long nextTheirs = bestFinder.ours;
1188                  long blue = (player.isBlue())? nextOurs : nextTheirs;
# Line 1193 | Line 1193 | public class Microscope extends JPanel {
1193          }
1194      }
1195  
1196 <  
1196 >
1197   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines