// FILE: Animal.java
// This animal-guessing program illustrates the use of the binary tree node class.
//import edu.colorado.nodes.BTNode;
//import edu.colorado.io.EasyReader;
/******************************************************************************
* The Animals Java application illustrates the use of
* the binary tree node class is a small animal-guessing game.
*
* 
Java Source Code for this class:
*   
*   http://www.cs.colorado.edu/~main/applications/Animals.java
*   
*
* @author Michael Main 
*    (main@colorado.edu) 
*
* @version
*   Jun 12, 1998
******************************************************************************/
public class Animal
{
   private static EasyReader stdin = new EasyReader(System.in);
   
   /**
   * The main method prints instructions and repeatedly plays the 
   * animal-guessing game. As the game is played, the taxonomy tree
   * grows by learning new animals. The String argument
   * (args) is not used in this implementation.
   **/
   public static void main(String[ ] args)
   {
      BTNode root;
      instruct( );
      root = beginningTree( );
      do
         play(root);
      while (stdin.query("Shall we play again?"));
      System.out.println("Thanks for teaching me a thing or two.");
   }
   
   
   /**
   * Print instructions for the animal-guessing game.
   **/
   public static void instruct( )
   {
      System.out.println("Please think of an animal.");
      System.out.println("I will ask some yes/no questions to try to figure");
      System.out.println("out what you are.");
   }
   
   /**
   * Play one round of the animal guessing game.
   * @param current
   *   a reference to the root node of a binary taxonomy tree that will be
   *   used to play the game.
   * Postcondition:
   *   The method has played one round of the game, and possibly
   *   added new information about a new animal.
   * @exception java.lang.OutOfMemoryError
   *   Indicates that there is insufficient memory to add new
   *   information to the tree.
   **/
   public static void play(BTNode current)
   {
      while (!current.isLeaf( ))
      {
         if (stdin.query((String) current.getData( )))
            current = current.getLeft( );
         else
            current = current.getRight( );
      }
      System.out.print("My guess is " + current.getData( ) + ". ");
      if (!stdin.query("Am I right?"))
         learn(current);
      else
         System.out.println("I knew it all along!");
   }
   
   /**
   * Construct a small taxonomy tree with four animals.
   * @param - none
   * @return
   *   a reference to the root of a taxonomy tree with the animals:
   *   kangaroo, mouse, trout, robin.
   * @exception OutOfMemoryError
   *   Indicates that there is insufficient memory to create the tree.
   **/
   public static BTNode beginningTree( )   
   {
      BTNode root;
      BTNode child;
      final String ROOT_QUESTION = "Are you a mammal?";
      final String LEFT_QUESTION = "Are you bigger than a cat?";
      final String RIGHT_QUESTION = "Do you live underwater?";
      final String ANIMAL1 = "Kangaroo";
      final String ANIMAL2 = "Mouse";
      final String ANIMAL3 = "Trout";
      final String ANIMAL4 = "Robin";
    
      // Create the root node with the question -Y´Are you a mammal?¡
      root = new BTNode(ROOT_QUESTION, null, null);
      // Create and attach the left subtree.
      child = new BTNode(LEFT_QUESTION, null, null);
      child.setLeft(new BTNode(ANIMAL1, null, null));
      child.setRight(new BTNode(ANIMAL2, null, null));
      root.setLeft(child);
      // Create and attach the right subtree.
      child = new BTNode(RIGHT_QUESTION, null, null);
      child.setLeft(new BTNode(ANIMAL3, null, null));
      child.setRight(new BTNode(ANIMAL4, null, null));
      root.setRight(child);
      return root;
   }
 
 
   /**
   * Elicits information from the user to improve a binary taxonomy tree.
   * @param current
   *   a reference to a leaf node of a binary taxonomy tree
   * Precondition:
   *   current is a reference to a leaf in a binary
   *   taxonomy tree
   * Postcondition:
   *   Information has been elicited from the user, and the tree has
   *   been improved.
   * @exception OutOfMemoryError
   *   Indicates that there is insufficient memory to add new
   *   information to the tree. 
   **/
   public static void learn(BTNode current)
   // Precondition: current is a reference to a leaf in a taxonomy tree. This
   // leaf contains a wrong guess that was just made.
   // Postcondition: Information has been elicited from the user, and the tree
   // has been improved.
   {
      String guessAnimal;   // The animal that was just guessed
      String correctAnimal; // The animal that the user was thinking of
      String newQuestion;   // A question to distinguish the two animals
      
      // Set Strings for the guessed animal, correct animal and a new question.
      guessAnimal = (String) current.getData( );
      correctAnimal = stdin.stringQuery("I give up. What are you? ");
      System.out.println("Please type a yes/no question that will distinguish a");
      System.out.println(correctAnimal + " from a " + guessAnimal + ".");
      newQuestion = stdin.stringQuery("Your question: ");
      
      // Put the new question in the current node, and add two new children.
      current.setData(newQuestion);
      System.out.println("As a " + correctAnimal + ", " + newQuestion);
      if (stdin.query("Please answer"))
      {
         current.setLeft(new BTNode(correctAnimal, null, null));
         current.setRight(new BTNode(guessAnimal, null, null));
      }
      else
      {
         current.setRight(new BTNode(guessAnimal, null, null));
         current.setLeft(new BTNode(correctAnimal, null, null));
      }         
   }
}