Java question - sleep while no command (threads needed)

Hello,

I am making a program to demonstrate artificial intelligence.

-To do this I am modelling a pet that can be fed, exercised etc.
-These variables are updated each time a user enters a feed command or exercsie command etc (also boredom, energy and energy volatility variables) or when the user leaves the pet, the variables go down e.g. if no excercise or other variables after a certain amount of time it dies.

The problem is this: It does not automaticlly decrement the variables when its left alone i.e. no commands issued.

Feel free to download and compile if it helps you help me.

Its getting there - at the moment it takes a command, sleeps until the next command, but then it crashes - null exception.

[code]
import java.util.*;

/**
 * Desktop   set path="C:\Program Files\Java\jdk1.5.0_08\bin"
 * Laptop    set path="E:\Program Files\Java\jdk1.5.0_08\bin"
 *
 *
**/

public class AIPet
{
      public int exercise = 90; // Initialise variable to 90%
      public int food = 90; // Initialise variable to 90%
      public int boredom = 90; // Initialise variable to 90%
      public int energy = 50; // Initialise variable to 50%
      public double randomControl = ((exercise + food + boredom) / 3);
      public int volatility = 0;
      public boolean male = true;
      public long goToSleep = 0;

      public String start()
      {
            System.out.println();
            System.out.println();
            System.out.println("Welcome to my AI Pet Demonstration");
            System.out.println("==================================");
            System.out.println("The aim is to keep the pet satisfied");
            System.out.println("i.e. keep all levels (food, exercise and");
            System.out.println("boredom) above 70% and make sure that");
            System.out.println("energy is never less than 1 (no energy");
            System.out.println("for body to function) or more than 100");
            System.out.println("(over exertion).");
            System.out.println("WIN = GETTING ALL LEVELS TO 100%");
            System.out.println();
            System.out.println("COMMANDS (one or two can be issued at once)");
            System.out.println("===========================================");
            System.out.println("Make the pet to exercise,  command = exercise");
            System.out.println("Feed the pet,              command = feed");
            System.out.println("Make the pet more excited, command = excite");
            System.out.println("Exercise and feed,         command = exercise feed");
            System.out.println("Exercise and excite,       command = exercise excite");
            System.out.println("Feed and excite,           command = feed excite");
            System.out.println("Exit,                      command = exit");
            System.out.println();
            System.out.println("NOTES");
            System.out.println("=====");
            System.out.println("Allowing the pet to exercise will make");
            System.out.println("it more fit but more hungry.");
            System.out.println("----------------------------------");
            System.out.println("Feeding the pet will make it less");
            System.out.println("hungry but will also make it bored");
            System.out.println("as it as more energy.");
            System.out.println("----------------------------------");
            System.out.println("Exciting the pet will make it more hungry");
            System.out.println("and fit as it has used energy.");
            System.out.println();
            System.out.println("----------------------------------");
            System.out.println("WARNING - Double commands may create energy imbalance");
            System.out.println("e.g. feeding the pet while exercising the pet will make");
            System.out.println("energy levels more volatile and increase chance of death.");
            System.out.println();
            System.out.println("----------------------------------");
            System.out.println("Choose if you want your pet animal to be");
            System.out.println("male (less excitement needed) or female");
            System.out.println("(does not need so much food).");
            System.out.println("Type male or female.");
            System.out.println();

            Scanner scan = new Scanner(System.in);
            String sex = scan.nextLine();

            if(sex.equals("male"))
            {
                  System.out.println("You choose male");
                  System.out.println();
                  System.out.println("Exercise at:   90");
                  System.out.println("Food at:       90");
                  System.out.println("Boredom at:    90");
                  System.out.println();
                  System.out.println("Energy at:     50");
                  System.out.println("Volatility at:  0");
                  System.out.println();

                  male("yes");
                  male = true;
            }
            else if(sex.equals("female"))
            {
                  System.out.println("You choose female");
                  System.out.println();
                  System.out.println("Exercise at:   90");
                  System.out.println("Food at:       90");
                  System.out.println("Boredom at:    90");
                  System.out.println();
                  System.out.println("Energy at:     50");
                  System.out.println("Volatility at:  0");
                  System.out.println();

                  female("yes");
                  male = false;
            }
            else
            {
                  System.out.println("Restart the program and then choose if you want the pet animal to be male or female.");
            }

            return null;
      }

      public String male(String male)
      {
            Scanner command = new Scanner(System.in);
            String commandIssued = command.nextLine();

            if(male.equals("yes"))
            {
                  goToSleep = System.currentTimeMillis() + 9000;

                  if(commandIssued.equals("exercise"))
                  {
                        exercised("exercise");
                  }
                  else if(commandIssued.equals("feed"))
                  {
                        feeding("fed", "male");
                  }
                  else if(commandIssued.equals("excite"))
                  {
                        excite("excite", "male");
                  }
                  else if(commandIssued.equals("exercise feed"))
                  {
                        volatility++;
                        exercised("exercise");
                        feeding("fed", "male");
                  }
                  else if(commandIssued.equals("exercise excite"))
                  {
                        volatility++;
                        exercised("exercise");
                        excite("excite", "male");
                  }
                  else if(commandIssued.equals("feed excite"))
                  {
                        volatility++;
                        feeding("fed", "male");
                        excite("excite", "male");
                  }
                  else if(commandIssued.equals("exit"))
                  {
                        System.exit(1);
                  }
            }

            return null;
      }

      public String female(String female)
      {
            Scanner command = new Scanner(System.in);
            String commandIssued = command.nextLine();

            if(female.equals("yes"))
            {
                  goToSleep = System.currentTimeMillis() + 9000;

                  if(commandIssued.equals("exercise"))
                  {
                        exercised("exercise");
                  }
                  else if(commandIssued.equals("feed"))
                  {
                        feeding("fed", "female");
                  }
                  else if(commandIssued.equals("excite"))
                  {
                        excite("excite", "female");
                  }
                  else if(commandIssued.equals("exercise feed"))
                  {
                        volatility++;
                        exercised("exercise");
                        feeding("fed", "female");
                  }
                  else if(commandIssued.equals("exercise excite"))
                  {
                        volatility++;
                        exercised("exercise");
                        excite("excite", "female");
                  }
                  else if(commandIssued.equals("feed excite"))
                  {
                        volatility++;
                        feeding("fed", "female");
                        excite("excite", "female");
                  }
                  else if(commandIssued.equals("exit"))
                  {
                        System.exit(1);
                  }
            }

            return null;
      }

      public void exercised(String exercised)
      {
            if(exercised.equals("exercise"))
            {
                  food--;
                  exercise++;

                  energy(exercise, food, boredom, energy, "yes");
                  display(exercise, food, boredom, energy, volatility);
            }
            else
            {
                  exercise--;
            }
      }

      public void feeding(String feed, String sex)
      {
            if(feed.equals("fed"))
            {
                  if(sex.equals("male"))
                  {
                        boredom = boredom + 2;
                  }

                  food++;
                  boredom--;

                  energy(exercise, food, boredom, energy, "yes");
                  display(exercise, food, boredom, energy, volatility);
            }
            else
            {
                  food--;
            }
      }

      public void excite(String excite, String sex)
      {
            if(excite.equals("excite"))
            {
                  exercise++;
                  food--;

                  if(sex.equals("female"))
                  {
                        food = food + 2;
                  }
                  else
                  {
                        boredom++;
                  }

                  energy(exercise, food, boredom, energy, "yes");
                  display(exercise, food, boredom, energy, volatility);
            }
            else
            {
                  boredom--;
            }
      }

      public void energy(int exercise, int food, int boredom, int energy, String energyChange)
      {
            int randomControl2 = (int)randomControl;

            if(energyChange.equals("yes"))
            {
                  if(volatility > 0)
                  {
                        Random random = new Random();//Second double command + 2 * 2 = 4 therefore higher random
                        energy = random.nextInt(randomControl2 + ((volatility * volatility)) + volatility);

                        display(exercise, food, boredom, energy, volatility);
                  }
                  else
                  {
                        Random random = new Random();
                        energy = random.nextInt(randomControl2) + volatility;

                        display(exercise, food, boredom, energy, volatility);
                  }
            }
      }

      public void display(int exercise, int food, int boredom, int energy, int volatility)
      {
            if(exercise >= 100)
            {
                  exercise = 100;
            }

            if(food >= 100)
            {
                  food = 100;
            }

            if(boredom >= 100)
            {
                  boredom = 100;
            }

            if(exercise < 70)
            {
                  System.out.println("Your pet died through lack of exercise.");
                  System.exit(1);
            }

            if(food < 70)
            {
                  System.out.println("Your pet died through lack of food.");
                  System.exit(1);
            }

            if(boredom < 70)
            {
                  System.out.println("Your pet died through lack of excitement.");
                  System.exit(1);
            }

            if(energy > 100)
            {
                  System.out.println("Your pet died from over excertion.");
                  System.exit(1);
            }

            if(energy < 0)
            {
                  System.out.println("Your pet died from lack of energy.");
                  System.exit(1);
            }

            System.out.println();
            System.out.println("Exercise at:    " + exercise);
            System.out.println("Food at:        " + food);
            System.out.println("Boredom at:     " + boredom);
            System.out.println("-----------------");
            System.out.println("Energy at:      " + energy);
            System.out.println("Volatility at:  " + volatility);
            System.out.println();
            System.out.println();

            System.out.print("Sleeping");

            for(int i = 0; i < 6; i++)
            {
                  System.out.print(".");

                  try
                  {
                        Thread.sleep(200);
                  }
                  catch(Exception e)
                  {
                        System.err.println("Caught Exception: " + e.getMessage());
                  }
            }

            System.out.println();
            System.out.println();

            backgroundThread.start(); //start after first input e.g. feed

            if(male == true)
            {
                  male("yes");
            }

            if(male == false)
            {
                  female("yes");
            }
      }

      private void sleep()
      {
            while(true)
            {
                  long timeLeft = goToSleep - System.currentTimeMillis(); // time left before next action

                  if(timeLeft <= 0)
                  {
                        break; // surely this needs to be a method call i.e. if no action in given time go back to display

                        //display(exercise, food, boredom, energy, volatility);
                  }

                  try
                  {
                        Thread.sleep(timeLeft);

                        System.out.println(timeLeft);

                        display(exercise, food, boredom, energy, volatility);
                  }
                  catch(Exception e)
                  {
                        System.err.println("Caught Exception: " + e.getMessage());
                  }

                  // OK, timer expired at this point so go to sleep.
            }
      }

      Thread backgroundThread = new Thread(new Runnable()
      {
            public void run()
            {
               sleep();
            }
      });

      public static void main(String[] args)
      {
            AIPet pet = new AIPet();
            pet.start();
      }
}
[/code]

If you can help I would be very happy

Thank you

John
john8932Asked:
Who is Participating?
 
valipotorConnect With a Mentor Commented:
Post the current code, so I can take a look.
0
 
valipotorCommented:
What is the purpose of:

 for(int i = 0; i < 6; i++)
          {
               System.out.print(".");

               try
               {
                    Thread.sleep(200);
               }
               catch(Exception e)
               {
                    System.err.println("Caught Exception: " + e.getMessage());
               }
          }

an then

backgroundThread.start(); //start after first input e.g. feed

So sleep and then sleep again?
0
 
john8932Author Commented:
This is just a fancy way of displaying its sleeping i.e. sleeping. then next iteration sleeping.. then sleeping... and so on.

This is repeated every 9 seconds if no input, or should be anyway.

Cheers
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
valipotorCommented:
In my opinion you should:

- start a thread that
 - sleeps for a second
 - prints Sleeping ....
 - checks if the vars were modified (if (modified==true) )
       - if yes, go back to sleep, set modified=false;
       - if no, decrement the variables by the required values

and the main thread should
- wait for input
- process any command
- update a flag, saying that the vars were modified
        modified=true;

Hope this helps,

valipotor
0
 
john8932Author Commented:
Ok cool but why for one second?

So I move the sleeping... into the thread then.

And the boolean variable is a good idea.

Ill try and code this - if it does not work ill post it up again, but a shortened version.

Thanks
0
 
john8932Author Commented:
I am having trouble implementing your idea.

Was this what you were suggesting:

          backgroundThread.start(); //start after first input e.g. feed

          if(male == true)
              {
                     male("yes");
              }

              if(male == false)
              {
                     female("yes");
          }
    }

     private void sleep()
     {
          if(modified == true)
          {
                        try
                        {
                               Thread.sleep(1000);

                               System.out.print("Sleeping");

                               for(int i = 0; i < 6; i++)
                               {
                                     System.out.print(".");
                               }
                               try
                               {
                                     Thread.sleep(200);
                               }
                               catch(Exception e)
                               {
                                     System.err.println("Caught Exception: " + e.getMessage());
                               }

                               modified = false;
                     }
                     catch(Exception e)
                     {
                                 System.err.println("Caught Exception: " + e.getMessage());
                     }
          }
          else
          {
                    exercise--;
                    food--;
                    boredom--;
              }
     }

     Thread backgroundThread = new Thread(new Runnable()
     {
          public void run()
          {
             sleep();
          }
     });

     public static void main(String[] args)
     {
          AIPet pet = new AIPet();
          pet.start();
     }
}

Please change this if it is not right.
0
 
valipotorCommented:
  private void sleep()
     {
                    try
                    {
                          Thread.sleep(1000);

                          System.out.print("Sleeping");
          if(modified == false)
          {
                 exercise--;
                 food--;
                 boredom--;
         }

                          modified = false;
                  }
                  catch(Exception e)
                  {
                            System.err.println("Caught Exception: " + e.getMessage());
                  }
          }
0
 
john8932Author Commented:
Its not working at the moment but I think I know why.

Where do you think I should use this code?

modified = true;

In the variable methods e.g. excite or exercised or in the female and male methods?

Also I think at the moment I am starting this thread twice with:

backgroundThread.start();

Therefore where should this go?

Thanks for the help so far
0
 
valipotorCommented:
In the variable methods e.g. excite or exercised ...
0
 
john8932Author Commented:
Were you repeating this because you did not understand - it means do I put the modified = true in the exercised or excite type methods i.e. the methods that change variables once a command is input.

or did you mean this is the correct way?
0
 
valipotorCommented:
Yes, you need to put the modified=true wherw you change the variables, in the exercise, feed ... methods.
0
 
john8932Author Commented:
Okay thats been done.

I think the background method is starting more than once at a time therefore an illegalthreadstate esception occurs at runtime.

Maybe I should put the thread method call in the start method so that it only gets run once i.e. when the program starts.

Then I could make the thread loop and run all the time, checking for input, if not sleep.

Does this sound feasable?

0
 
valipotorCommented:
This is the way to implement the background thread:

Thread backgroundThread = new Thread(new Runnable()
     {
          public void run()
          {
             while (true)
             {
               sleep();
             }
          }
     });
0
 
valipotorCommented:
The background task should be started only once, in the main() method.

After the male(), female() initialisation.

Once the start method is invokes, the thread will execute the run() method in a spearate thread of execution.

That's why the loop in the run() method. The run() method must not finish.
0
 
john8932Author Commented:
public boolean male = true;
      public long goToSleep;

      public String start()
      {
            backgroundThread.start();
            
            System.out.println();
            System.out.println();
            System.out.println("Welcome to my AI Pet Demonstration");

This is the new location for starting the method.

Do you think this is suitable?

It was going to be in main allow that produced an error.

Any more advice would be appreciated as it is still not working.

Cheers
0
All Courses

From novice to tech pro — start learning today.