Program: 181078
Project: 181078
Buggy source:
@Override public void play(){
  String[] commands={"String_Node_Str","String_Node_Str","String_Node_Str","String_Node_Str"};
  short[] tokens={TOKEN_SAVE,TOKEN_UNDO,TOKEN_REDO,TOKEN_QUIT};
  short[] argCount={0,0,0,0};
  short invalid=-1;
  inputParser=new ParserImpl(commands,tokens,argCount,invalid);
  MoveParser parser=new MoveParserImpl();
  Scanner s=new Scanner(System.in);
  short token;
  GenericMove nextMove;
  printBoard();
  while (!isOver()) {
    if (current.equals(players._1())) {
      System.out.println("String_Node_Str" + current.getName() + "String_Node_Str");
    }
 else {
      System.out.println("String_Node_Str" + current.getName() + "String_Node_Str");
    }
    String command;
    if (current.isHuman()) {
      command=s.next();
    }
 else {
      State thinker=new StateImpl(gameBoard,current);
      command=thinker.nextBestMove().toString();
      System.out.println(command);
    }
    token=inputParser.ensureString(command);
    if (token == TOKEN_SAVE) {
      try {
        Manager.saveGame();
      }
 catch (      IOException e) {
        e.printStackTrace();
      }
    }
 else     if (token == TOKEN_UNDO) {
      undoMove();
      printBoard();
      current=current.getOpponent();
    }
 else     if (token == TOKEN_REDO) {
      redoMove();
      printBoard();
      current=current.getOpponent();
    }
 else {
      nextMove=parser.loadMove(current,gameBoard,command);
      if (nextMove == null) {
        System.out.println("String_Node_Str");
      }
 else {
        if (nextMove.isValid()) {
          nextMove.makeMove();
          printBoard();
          undoMoves.add(nextMove);
          redoMoves=new LinkedList<GenericMove>();
          current=current.getOpponent();
        }
 else {
          System.out.println("String_Node_Str");
        }
      }
    }
  }
  System.out.println("String_Node_Str" + current.getOpponent().getName() + "String_Node_Str");
  System.out.println("String_Node_Str");
}

Fixed version (ground truth):
@Override public void play(){
  String[] commands={"String_Node_Str","String_Node_Str","String_Node_Str","String_Node_Str"};
  short[] tokens={TOKEN_SAVE,TOKEN_UNDO,TOKEN_REDO,TOKEN_QUIT};
  short[] argCount={0,0,0,0};
  short invalid=-1;
  inputParser=new ParserImpl(commands,tokens,argCount,invalid);
  MoveParser parser=new MoveParserImpl();
  Scanner s=new Scanner(System.in);
  short token;
  GenericMove nextMove;
  printBoard();
  while (!isOver()) {
    if (current.equals(players._1())) {
      System.out.println("String_Node_Str" + current.getName() + "String_Node_Str");
    }
 else {
      System.out.println("String_Node_Str" + current.getName() + "String_Node_Str");
    }
    String command;
    if (current.isHuman()) {
      command=s.next();
    }
 else {
      State thinker=new StateImpl(gameBoard,current);
      command=thinker.nextBestMove().toString();
      System.out.println(command);
    }
    token=inputParser.ensureString(command);
    if (token == TOKEN_SAVE) {
      try {
        Manager.saveGame();
      }
 catch (      IOException e) {
        e.printStackTrace();
      }
    }
 else     if (token == TOKEN_UNDO) {
      if (undoMove() == true) {
        printBoard();
        current=current.getOpponent();
      }
    }
 else     if (token == TOKEN_REDO) {
      if (redoMove()) {
        printBoard();
        current=current.getOpponent();
      }
    }
 else {
      nextMove=parser.loadMove(current,gameBoard,command);
      if (nextMove == null) {
        System.out.println("String_Node_Str");
      }
 else {
        if (nextMove.isValid()) {
          nextMove.makeMove();
          printBoard();
          undoMoves.add(nextMove);
          redoMoves=new LinkedList<GenericMove>();
          current=current.getOpponent();
        }
 else {
          System.out.println("String_Node_Str");
        }
      }
    }
  }
  System.out.println("String_Node_Str" + current.getOpponent().getName() + "String_Node_Str");
  System.out.println("String_Node_Str");
}