Lab 3: Virtual Pet — Changing State

Pam Cutter and Kelly Schultz 2003, Nathan Sprague 2009, Alyce Brady 2017, 2021, Kalamazoo College
Based on work done at Drexel University by JL Popyack & Paul Zoski

Introduction

This is the fourth assignment in the Virtual Pet series (of 5). In previous assignments you designed and created a virtual pet with 5 possible states, and with behaviors or state indicators associated with each state. You also created a state diagram that showed how the pet might change from one state to another.

In this lab you will add functionality that represents the random state changes that your pet might undergo as time passes, based on your state diagram. You will also add two buttons that represent actions by the pet owner (such as patting or feeding the pet), and implement functions that change the pet's state based on those actions.


Representing the Passage of Time:

In this exercise, you will add a Counter text field to the page to show time passing — specifically, the number of seconds since the simulation began.

Exercise 1:
  1. Add a new Counter or Elapsed Time text field to the <body> section of your page where you will display the number of seconds your pet "simulation" has run so far. Be sure to give your new text field a unique, one-word id attribute.
  2. In your initialization function, add a statement that initializes the Counter text field value to 0 before or after you initialize the State text field. Be sure to set it to 0, not "0", since the counter should be a numeric value, not a string.
  3. Define a new function in the <head> section that will increment the counter to show the passage of time. (Later you will add code that will check whether to change the pet's state also.)
    • Give this new function a name that indicates its purpose, such as advanceTime, onClockTick, advanceSimulation, simulateTime, etc. This function does not need any parameters although, like all functions, it does need parentheses after its name.
    • For now, you only need 1 statement in this function, to add 1 to the counter. Increment the counter value using the ++ operator, e.g., counter.value++   (if the id is "counter"; if the id is something else, you would use that instead).
    Warning: if you increment the counter with counter.value = counter.value + 1 instead, it may treat the counter value as a string rather than as a number and do string concatenation instead of addition.
  4. Back in your initialization function, add a new statement to start the simulated action of the page by setting up a timer that will call your new function every 1000 milliseconds; for example,
        setInterval("functionName()",1000)
    
    where functionName is the name you gave your new "advance time" function.
  5. Test your new function by previewing your page. You should see your Counter field start at 0 and increment by 1 every second. If you want to slow it down, increase the number of milliseconds between calls to your "advance time" function; for example, 2000 milliseconds is 2 seconds.
  6. Recommendation: Upload your modified page at the end of each exercise, or at other clean breaking points, as a backup.

Implementing Random State Changes:

Now we get to the heart of the simulation, implementing the probability-driven state transitions from one state to another in your state diagram.

Exercise 2:
  1. In the new "advance time" function you wrote in Exercise 1, generate a random number in the interval [0,1) using the following command:
            var randomVal = Math.random();
    
    This number will be used to represent different probabilities. For example, there is a 10% probability that randomVal < 0.1 and a 30% probability that randomVal < 0.3
  2. For each probability-driven transition in your state diagram that goes from one state to another, you will need to write an "if" statement to check if the pet is currently in the first state and whether the pet should change or not. For example, if a pet in the "content" state changes to the "angry" state 40% of the time and stays in the "content" state the rest of the time, then the if statement would look like this:

        if ( state.value == "content" && randomVal < 0.4 )
             state.value = "angry";
    
    where state is whatever id you gave to your State text field element. You will need to continue this "if" statement with "else-if" clauses until you have handled all of the probabilistic state transitions in your state diagram.

    If you have a state with more than one probability-driven transitions from it to other states, you will need to be careful about the probabilities. For example, if the "content" pet above has a 10% chance of changing to "angry" and a 10% chance of changing to "sleeping", you could implement that like this:

        if ( state.value == "content" )
        {
             if ( randomVal < 0.1 )
                 state.value = "angry";
             else if ( randomVal < 0.2 )
                 state.value = "sleeping";
        }
    

    because there is a 10% chance that randomVal is less than 0.1 and a 10% chance that it is between 0.1 and 0.2.

  3. As you modify this new function (and all other functions), use comments to clarify the purpose and steps in your code, and use white space and indentation to make it easier to read.
  4. Since you have (potentially) changed the pet's state, you should add a call to the updateIndicators() as the last action in the "advance time" function to bring the state indicator text fields up to date with the pet's new state.
  5. Preview your page. Your pet should now change state at random intervals corresponding to your state diagram. You can continue to use the temporary state-changing buttons at the bottom of the page to force the pet into specific states for testing purposes.
  6. Recommendation: Upload your modified page as a backup.

Adding Interaction:

Next, you will add buttons corresponding to pet owner actions that cause changes in the pet's state.

Exercise 3:
  1. Create two new functions, one corresponding to each owner action you identified in the State Transition Design Assignment such as petting, feeding, or ignoring the pet. Give each function a name that indicates its purpose. Neither of these functions take any parameters although, like all functions, they will need parentheses after their names.
    • In each function, implement the appropriate transitions using if statements to check the pet's current state and switch to the corresponding new state. For example, if the pet is "hungry" and is fed, then the pet could become "content". That would be accomplished with an "if" statement like this:
          if ( state.value == "hungry" )
              state.value = "content";
      
      You will need to continue this "if" statement with "else-if" clauses until you have told the pet what to do in each possible state (or at least in each state where the pet doesn't just ignore the action).
    • You may want to call the updateIndicators function at the end of these functions, as you did in your "advance time" function, although it isn't as important here since that function is already being called every second.
  2. Add two new buttons to your page to represent these owner actions. Be sure to give each button a unique, one-word id attribute. When the user clicks on each button, your page should call the appropriate owner action function. This action is similar to the onclick action in the temporary buttons at the bottom of your page, except that your new owner action functions do not take a parameter.
  3. Preview your page. Your pet should now change states in a way that is consistent with your state diagram. The pet's actions, implemented in the previous lab, should also change as the pet's state changes, corresponding to the table you created in your initial design.

    You can continue to use the temporary state-changing buttons at the bottom of the page to force the pet into specific states for testing purposes.


Finishing Up:

Exercise 4: