New concepts to be applied for this assignment
File input and output
Generating random numbers
(Note: style requirements from previous assignments e.g., functional decomposition must also be applied).
Write a fitness simulation whereby a single runner is traveling a fixed distance. The runner only has a finite amount of energy. Movement can occur at different speeds (walk, jog, run and fast-run/sprint). Faster speeds allow more distance to be covered but will expend more energy. If the runner has exhausted all of his/her energy before reaching the end then only a walk is possible. Barring energy limitations the user can select any running speed. Based on the speed the distance traveled and energy expended will be determined and the simulation will be updated and displayed. The simulation ends when the runner reaches the end or the user quits the program. Time passes in discrete time units (turns). Much like an actual race there is strategy involved: The goal is to balance speed vs. energy consumption in order to complete the course in the shortest possible time. The simulation can be saved/loaded from file during any turn.
The simulated running world (Figure 1) consists of a one-dimensional list of twenty elements. Each element will be either empty (represented by a space) or contain the runner (represented by the ‘r’ character). To make it easier to interpret: each list element will be bound above, left, right and below by a line, and columns will be numbered. At the start of the simulation the runner starts on the far left and the end is on the far right. Time starts at zero units and will be incremented by one for each ‘turn’ that passes. Also the current energy level should also be displayed.
No energy expended
1 – 4 units
1 – 2 units
3 – 8 units
3 – 5 units
When the energy level reaches zero or less, the runner can only travel at a ‘walk’. The main menu will only display a particular speed if the runner’s current energy level is at or greater than the minimum energy units needed to travel at that speed. For example, if the energy level is at one unit then the option to ‘run fast’ won’t be displayed. If the energy level is zero or less then the options to ‘jog’ or ‘run’ won’t be displayed either. The energy level starts at 10 units and will be decreased as the runner moves (if speed is faster than a walk). When the simulation ends (far right reached) the program should display the time, energy and track one last time as well as an appropriate status message (e.g., "Race finished")
Load/Save features: allow the current state of the simulation (time, energy, location of the runner, and whether the program is operating is random or deterministic fashion – see the ‘operating mode’ section) to be saved to a text file. The save file should either: 1) be named “save.dat” and be located in the same location as the simulation program (current directory) OR 2) allow the user to specify the save information. An IOError type of exception should be used to deal with file input or output problems.
Selecting the quit feature will display the current state of the simulation once more and end the program.
Whenever prompting for user input (at the main menu and menu to determine the operating mode), the program should be able to determine if a valid option has been selected and to take appropriate action otherwise. (Refer to the 'heuristics for good design' in the section of notes which covers loops).
Finally the program should include a debug mode (activated by selecting the hidden: Option ‘d’ or ‘D’ at the main menu). When activated the program will display messages that describe the current state of the program and (as the name implies) information to assist the programmer in finding and fixing errors. The exact content of these messages is left to your discretion. Some examples include: showing the current column location of the runner, showing the movement option selected, the randomly generated distance to be traveled and showing the destination. A Boolean debugging ‘flag’ will be used to determine whether or not the program is in debugging mode. This flag will take the form of a global variable and is the sole exception to the prohibition on this type of variable.
Under normal operation the program should make use of the functions in the ‘random’ module to generate different values for the distance traveled and energy expended. This allows for some variation or random chance to come into play when running the program. Running the program multiple times and selecting a particular speed will not guarantee that same amount of distance/energy expenditure will occur each time. This models the effects of things like having a ‘good’ or ‘bad’ workout day.
However to make it easier to mark your work your program (and to help you determine if features have been correctly implemented) it should also be able to operate in a deterministic mode so that the same series of random numbers will be generated. To help you understand how to write a deterministic program, the example “notSoRandom.py” will simulate the rolling of a six-sided die ten times. Under normal conditions it’s highly improbably that multiple runs of the program should produce an identical sequence of ten numbers. That’s because a mathematical function is used to generate the random number and normally a different value is used to start or ‘seed’ the function. If however the starting value is set to the same constant each time that program is run, the same sequence of numbers will be generated. This is exactly what is done in the ‘setStartingValue’ function of the sample program.
As Figure 2 illustrates when the program is first started it should give the user the ability to determine whether it will operate in a deterministic mode (by setting the seed either to the constant value of one (or by allowing the user to enter an alternate value for the seed), or if it will operate in a random mode (the seed is not set to a starting value and will instead be based on a random value). After setting the operating mode the program should initialize the simulation to the proper starting values and operate in the fashion described above.
Figure 2: The menu to determine operating mode appears once when the program is first started.
Using pre-written Python code
You will need to use the built in random number generator in the ‘random’ module/library. At a minimum you should make use of the ‘seed’ and ‘randrange’ functions. Beyond that (and common sense operators and functions such as input/output function, mathematical operators), unless you told otherwise, you will need to write your own code and cannot use other pre-written Python modules or operators.
import random # by default seeds with the system time random.seed() # random.randrange([start], stop[, step]) mylist =  for k in range(10): # produce integers between 0 and 99 n = random.randrange(0, 100) mylist.append(n) print(mylist) print("sum = %d" % sum(mylist)) print("avg = %f" % (sum(mylist)/len(mylist))) '''possible result >>> [32, 23, 61, 6, 37, 70, 81, 52, 83, 79] sum = 524 avg = 52.400000 '''