@Override
 public void advance() {
   if (end) return;
   super.advance();
   switch (animDirection) {
     case ShowHint:
       if (hintAnimCount < HINT_ANIM_MAX) ++hintAnimCount;
       break;
     case HideHint:
       if (hintAnimCount > 0) --hintAnimCount;
       else {
         resetMask.setVisible(false);
         resetMask.setEnabled(false);
         animDirection = Stay;
       }
       break;
   }
   int[] currentColorIndexes = Ball.ballsToInts(balls);
   boolean finished = true;
   for (int i = 0; i < currentColorIndexes.length; ++i) {
     if (currentColorIndexes[i] != record.targetColorIndexes[i]) {
       finished = false;
       break;
     }
   }
   if (finished) {
     end = true;
     PuzzleInfo.testMinSteps(
         record.type, record.stage, record.advanced, currentMoveItem.getNumber());
     PuzzleNextStageWidget widget =
         new PuzzleNextStageWidget(record.type, record.stage, record.advanced);
     mainWidget.changeControl(widget, true);
   }
 }
 @Override
 public void buttonClicked(int indexOfTheButton) {
   super.buttonClicked(indexOfTheButton);
   switch (indexOfTheButton) {
     case ResetMaskButton:
       if (animDirection == Stay || animDirection == ShowHint) animDirection = HideHint;
       break;
     case PuzzleHintButton:
       animDirection = ShowHint;
       resetMask.setVisible(true);
       resetMask.setEnabled(true);
       break;
   }
 }
 @Override
 public void paint(MyGraphics g) {
   BasicPainter.paintBackGround(BasicPainter.Game61, g, width(), height(), 0);
   super.paint(g);
   BasicPainter.paintPuzzleGameBallHint(gameBoard, record.targetColorIndexes, g, HideHint, rate());
 }
 @Override
 public void goodMove() {
   super.goodMove();
   currentMoveItem.setNumber(currentMoveItem.getNumber() + 1);
 }