Instructions for narrativeConsequences

(produced at 17:04 UTC on 2021-09-30)

This task is part of ps04 which is due at 23:59 EDT on 2021-10-05.

You have the option to work with a partner on this task if you wish. Working with a partner requires more work to coordinate schedules, but if you work together and make sure that you are both understanding the code you write, you will make progress faster and learn more.

You can submit this task using this link.

Put all of your work for this task into the file choiceStory.py
(you will create this file from scratch)

This task will give you practice reasoning about booleans and possibilities, and it will also give you a chance to write a story.

One interesting application area for programming is entertainment, and within that space, computers give rise to new forms of entertainment known as computational media, including video games and other interactive forms. Now that you've learned about Booleans and conditionals, you're equipped to make your own interactive programs, and for this task, you will write an interactive story. Note that we won't grade you on the quality of your story: just on whether or not it responds properly to user inputs according to the pattern that we have specified. You're free to write a very simple or very complicated story, although you'll have to think at least a little bit about how to weave choices and consequences together in a way that makes sense.

Note: if you don't want to spend time writing a story for this task, you don't have to. You're free to copy the story text shown in the examples, or just make up meaningless text to use, as long as your functions have the required patterns of variation in their output depending on their inputs.

The story you will write will have 6 parts:

  1. A prologue: some text that's always the same.
  2. An initial choice, with two options, which influences...
  3. ...the first scene, which has two different versions based on which option the player chose at the initial choice.
  4. A second choice, also with two options, which along with the first choice influences...
  5. ...the second scene, which has four possibilities, depending on the selections made at the first two choices.
  6. An epilogue, which has three possibilities: one version if the first option was selected at both choices, another version if the second option was selected at both choices, and a third version if the selections were eiter option1-option2 or option2-option1.

To implement this, you will write a function for each part, along with a tellStory function that puts them all together, and a letUserPick function for use in constructing choices. These functions have the following requirements:

  • The letUserPick function must print out a message explaining the choice facing the user (based on the two arguments it receives indicating what the options are), and then must use input to let the user choose between the two options by answering '1' or '2'. If anything other than one of those digits is given as input, letUserPick must return the integer 0 indicating an ambiguous answer, but if either exactly '1' or '2' is the input, it must return the corresponding integer. So it will always return an integer, which will be 0, 1, or 2. These examples show how it should work. You will need to use both an if/else statement and a return statement.
  • The prologue function should not have any parameters, and must print out some text, which will be the same every time. It will not use return.
  • The choice1 function will not have any parameters, and will call letUserPick to give the player a choice between two options. Depending on their selection, it will print one of three messages (one for a selection of 1, another for 2, and a third for 0, based on the result of letUserPick). It will use an if/else to accomplish that, and will also return either True or False. It must return True if the user's selction is 1 and False if it's 2, but you're free to decide whether it will return True or False if the user gives an ambiguous input causing letUserPick to return 0.
  • The choice2 function works exactly the same way as choice1 in all respects. The specific text of the choice may be different, however, and the decision of whether to return True or False for an ambiguous input could be different.
  • The scene1 function accepts one parameter, which tellStory will ensure comes from the result of choice1. It will print out some text which is up to you to write, but that text must be different (in at least some part) depending on whether it gets True or False as its argument. You will need to use an if/else to accomplish this. scene1 will not use return, and its behavior is determined by its argument, rather than by user input, so it will not call letUserPick, nor will it call choice1. Instead tellStory will call choice1 and will pass the result of that call into scene1.
  • The scene2 function accepts two parameters, which tellStory will ensure come from the results of choice1 and choice2. Both will be Booleans, so there will be 4 possibilities: True-True, True-False, False-True, and False-False. In each of these four cases, the text that it prints must be different. Other than having four different cases instead of two, it has the same restrictions as scene1, although it must use at least two if/else clauses to create the necessary distinctions. As with scene1, some or even most of the text may be the same when called with differnet parameters, as long as there is also some difference.
  • The epilogue function accepts two parameters, which again will come from choice1 and choice2 (and tellStory is responsible for ensuring that). It will print out different text depending on the arguments it receives, but unlike scene2, although there are four possible combinations of argument values, it will only have three possible texts that it prints: one for the True-True case, another for the False-False case, and a third for both the True-False and False-True cases. You will need to plan your story so that this makes sense: so that two different choice combinations (which lead to differences in scene2) lead to the same conclusion.
  • The tellStory function combines all of the other functions together to tell the whole story, offering choices along the way. It must call prologue, choice1, scene1, choice2, scene2, and epilogue in that order, and it must store the results of choice1 and choice2 along the way so that it can pass them into scene1, scene2, and epilogue as appropriate. It must not call letUserPick directly because the choice1 and choice2 functions will handle that, and it must also not use input, so that in the end, it uses exactly two inputs overall. Depending on those two inputs, it must print out four different possible stories, which should happen automatically if it calls even just scene2 with the correct arguments (i.e., with the results from choice1 and choice2).

Once you've defined these eight functions, you're done! If you want to keep things simple, your 'story' could just be a few sentences, but you're welcome to think about interesting ways to create consequences for different player choices. In the examples provided (including examples for choice1 and choice2, for scene1 and scene2, for epilogue, and for tellStory) the story is about taking a hike, with a choice about preparation and then about which path to take. The epilogue provides the same text if the user chose a difficult path with little preparation, or if they chose an easy path with a lot of preparation, although the second scene does show different consequences for these two cases.

Notes

  • As usual, you must document every function you write.
  • Also as usual, you must not waste fruit and you must not waste boxes.
  • You will create a new file from scratch for this task; there is no provided starter code.
  • You are not required to do any testing for this task, but it isn't a bad idea to write some tests for your letUserPick, choice1, and choice2 functions. We've provided a copy of optimism.py in the starter code in case you want to do this. Testing scene1, scene2, epilogue, and tellStory is also possible, using expectOutputContains, although testing that the output from two different test cases is the same (as is required for epilogue) is very tricky.

Examples

letUserPick Examples

These examples show how letUserPick works. Note that it always returns an integer, and any input other than exactly '1' or '2' will give a result of 0.

In []:
letUserPick('Option 1', 'Option 2')
Prints
What do you want to do? 1. Option 1 2. Option 2 Enter your choice (1 or 2): 1
Out[]:
1
In []:
letUserPick('Persuade', 'Intimidate')
Prints
What do you want to do? 1. Persuade 2. Intimidate Enter your choice (1 or 2): 2
Out[]:
2
In []:
letUserPick('Follow them', 'Wait for Ian')
Prints
What do you want to do? 1. Follow them 2. Wait for Ian Enter your choice (1 or 2): follow
Out[]:
0

choice1 and choice2 Examples

These are some examples of how choice1 and choice2 might work, but of course your text will be completely different. The important points are that they call letUserPick with some specific prompts, they print a different message based on the user's selection (including a special message for an ambiguous selection where letUserPick returns 0), and they always return a boolean, choosing some default in cases where the user's selection was not '1' or '2'. Note that choice2 works exactly the same as choice1, except that it uses a different prompt and has different responses to each selection.

In []:
choice1()
Prints
What do you want to do? 1. Grab your hiking poles for a strenuous climb. 2. Just pack some light snacks for a relaxing hike. Enter your choice (1 or 2): 1 You grab some energy bars and pack plenty of water, getting ready for a long hike.
Out[]:
True
In []:
choice1()
Prints
What do you want to do? 1. Grab your hiking poles for a strenuous climb. 2. Just pack some light snacks for a relaxing hike. Enter your choice (1 or 2): 2 You grab a water bottle and some crackers, ready to spend some relaxing time on the trail.
Out[]:
False
In []:
choice1()
Prints
What do you want to do? 1. Grab your hiking poles for a strenuous climb. 2. Just pack some light snacks for a relaxing hike. Enter your choice (1 or 2): blah You're not quite sure what you want to do, so you pack some energy bars and plenty of water just in case.
Out[]:
True
In []:
choice2()
Prints
What do you want to do? 1. Head upwards along the top of the ridge. 2. Head down into cool shade of the valley. Enter your choice (1 or 2): one You're indecisive, but eventually head down toward the valley floor.
Out[]:
False

scene1 and scene2 Examples

These examples show how scene1 and scene2 might work, but of course your text will be completely different. The important points are that they print different text based on the Boolean value(s) they get (two options for scene1, and 4 options for scene2, since it has two Boolean parameters). Note that some or even most of the text may be the same, as long as there are some differences. Also note that input, the choice functions, and letUserPick are not involved.

In []:
scene1(True)
Prints
The trail that you've chosen climbs upwards, winding in and out of aromatic pines as it climbs along the side of a ridge, just below the treeline. Along the way you spot plenty of birds and wildflowers, as well as a deer that quickly bounds out of view among the trees. The cool mountain air feels wonderful, and the morning sun isn't strong enough to overheat you yet. You make good time along the trail, eager to see how far you can go today. The path branches before you, with one side heading up towards the top of the ridge, and the other heading down into the valley.
In []:
scene1(False)
Prints
The trail that you've chosen climbs upwards, winding in and out of aromatic pines as it climbs along the side of a ridge, just below the treeline. Along the way you spot plenty of birds and wildflowers, as well as a deer that quickly bounds out of view among the trees. The cool mountain air feels wonderful, and the morning sun isn't strong enough to overheat you yet. You take your time, relishing the wildlife and the beauty around you. You're rewarded with a glimpse of a few shy pika that hide among the scree above the treeline as you walk nearby. The path branches before you, with one side heading up towards the top of the ridge, and the other heading down into the valley.
In []:
scene2(True, True)
Prints
The path climbs upwards, leaving the treeline behind and winding along the top of the ridge towards the mountain's summit. You stop to put on some extra sunscreen and catch your breath in the thin alpine air. Although the climb to the ridge is steep, you are afforded a panoramic view of the valley below, including the waterfall at the head of the valley that feeds into a small lake and then a river running down the valley floor. With plenty of energy, you stride forward, appreciating the view and making steady progress. The trail is long, but eventually you reach a rocky outcropping at the shoulder of the mountain, and you relish a spectacular view of the valley you just climbed along as well as the next valley over. Tired but satisfied, you finish the last of your provisions and start the long walk back.
In []:
scene2(True, False)
Prints
The path snakes down between the trees, with stands of aspen interspersed among the pines, and as you approach the valley floor, the path joins a small river, meandering through the shade of ash and maple trees. You hurry along the river, excited to see where this path leads. Before long, you find yourself at a lake, fed by a waterfall from an impressive cliff above it, but the path doesn't continue further. A bit nonplussed, you cool your feet off in the lake, and then head back, wondering whether the other path would have given you more of a challenge, but by the time you make it back to the branching point, it's too late to explore the other option.
In []:
scene2(False, True)
Prints
The path climbs upwards, leaving the treeline behind and winding along the top of the ridge towards the mountain's summit. You stop to put on some extra sunscreen and catch your breath in the thin alpine air. Although the climb to the ridge is steep, you are afforded a panoramic view of the valley below, including the waterfall at the head of the valley that feeds into a small lake and then a river running down the valley floor. On the steep path, you take your time, and stop often to appreciate the view. You make it up to the ridge top and a little ways along, before deciding that you've had enough and it's time to turn back. There might have been an even more spectacular view at the end of the ridge trail, but you weren't looking for a strenuous hike today.
In []:
scene2(False, False)
Prints
The path snakes down between the trees, with stands of aspen interspersed among the pines, and as you approach the valley floor, the path joins a small river, meandering through the shade of ash and maple trees. You stroll along the trail, luxuriating in the rich green colors of ferns and moss, and happy to see chickadees, nuthatches, and even a woodpecker among the tall riverside trees. Columbines and trillium are flowering in the shade, and occasional meadows open up full of tall grasses that sway beautifully in the mountain breeze. Eventually you reach a lake at the head of the valley, fed by a beautiful waterfall streaming down from the cliffs above. You linger at the lake, eating your snacks and dipping your toes in the water as you appreciate the rainbows that form in the waterfall's misty spray. You even catch a glimpse of a muskrat or maybe a beaver swimming among the reeds. Eventually, satisfied with a such a beautiful hike, you leave the lake and head back towards the trailhead.

epilogue Examples

These examples show how epilogue might work, but of course your text will be completely different. The important points are that it prints different text based on the Boolean value(s) it gets, but that there are only 3 distinct possibilities: one for the both-True case, one for the both-False case, and a third for both the True-False and False-True cases. You will have to structure your story so that this makes sense. As with the scenes, any tiny difference output counts, and as a corollary, the output must be exactly the same for the two mixed cases.

In []:
epilogue(True, True)
Prints
As you reach the trailhead once more and conclude your hike, you glance back over your shoulder at the path you just traveled. You're worn out after the intense climb, but the views were worth it, and you feel totally satisfied with your choices.
In []:
epilogue(True, False)
Prints
As you reach the trailhead once more and conclude your hike, you glance back over your shoulder at the path you just traveled. You're not sure that you picked a trail that matched your energy level, but you had fun just the same.
In []:
epilogue(False, True)
Prints
As you reach the trailhead once more and conclude your hike, you glance back over your shoulder at the path you just traveled. You're not sure that you picked a trail that matched your energy level, but you had fun just the same.
In []:
epilogue(False, False)
Prints
As you reach the trailhead once more and conclude your hike, you glance back over your shoulder at the path you just traveled. You had a nice relaxing hike along the valley floor, and the animals and plants you spotted were inspiring. You feel great about your decisions.

tellStory Example

This example shows how tellStory puts together the other functions defined so far to tell an interactive story. Your text won't be the same, but the way that your whole story responds to different input combinations is important. Since there are two choices, each with two options, there are four possible selections the user might make, and so your function should be able to print out four different stories (different in at least some way, although much of the text can be the same) depending on which of the four possible input scenarios happens.

In []:
tellStory()
Prints
Read the story, and make choices along the way... --- You are preparing to set off on a hike in an alpine valley. You haven't decided yet whether you want to tackle a serious climb or have a more relaxed hike, but you've found a trailhead that will give you both options. --- What do you want to do? 1. Grab your hiking poles for a strenuous climb. 2. Just pack some light snacks for a relaxing hike. Enter your choice (1 or 2): 1 You grab some energy bars and pack plenty of water, getting ready for a long hike. --- The trail that you've chosen climbs upwards, winding in and out of aromatic pines as it climbs along the side of a ridge, just below the treeline. Along the way you spot plenty of birds and wildflowers, as well as a deer that quickly bounds out of view among the trees. The cool mountain air feels wonderful, and the morning sun isn't strong enough to overheat you yet. You make good time along the trail, eager to see how far you can go today. The path branches before you, with one side heading up towards the top of the ridge, and the other heading down into the valley. --- What do you want to do? 1. Head upwards along the top of the ridge. 2. Head down into cool shade of the valley. Enter your choice (1 or 2): 2 You take the downwards path towards the valley floor. --- The path snakes down between the trees, with stands of aspen interspersed among the pines, and as you approach the valley floor, the path joins a small river, meandering through the shade of ash and maple trees. You hurry along the river, excited to see where this path leads. Before long, you find yourself at a lake, fed by a waterfall from an impressive cliff above it, but the path doesn't continue further. A bit nonplussed, you cool your feet off in the lake, and then head back, wondering whether the other path would have given you more of a challenge, but by the time you make it back to the branching point, it's too late to explore the other option. --- As you reach the trailhead once more and conclude your hike, you glance back over your shoulder at the path you just traveled. You're not sure that you picked a trail that matched your energy level, but you had fun just the same.

Rubric

 
unknown Style Requirements
How your code is written.
 
unknown Core goals
Complete all core goals for core credit. Get partial credit for completing at least half, and more partial credit for completing at least 90%.
 
unknown All functions are documented
Each function you define must include a non-empty documentation string as the very first thing in the function.
 
unknown Procedure Requirements
What code you use to solve the problem.
 
unknown Core goals
Complete all core goals for core credit. Get partial credit for completing at least half, and more partial credit for completing at least 90%.
 
unknown Define letUserPick with 2 arguments
Use def to define letUserPick with 2 arguments
 
unknown Call print
Within the definition of letUserPick with 2 arguments, call print in at least once place.
 
unknown Call input
Within the definition of letUserPick with 2 arguments, call input in at least once place.
 
unknown Use a conditional
Within the definition of letUserPick with 2 arguments, use an if statement (possibly accompanied by an elif or else block) in at least once place.
 
unknown Use a return statement
Within the definition of letUserPick with 2 arguments, use return _ in at least once place.
 
unknown Define choice1 with 0 arguments
Use def to define choice1 with 0 arguments
 
unknown Call letUserPick
Within the definition of choice1 with 0 arguments, call letUserPick in at least once place.
 
unknown Call print
Within the definition of choice1 with 0 arguments, call print in at least once place.
 
unknown Use a conditional
Within the definition of choice1 with 0 arguments, use an if statement (possibly accompanied by an elif or else block) in at least once place.
 
unknown Use a return statement
Within the definition of choice1 with 0 arguments, use return _ in at least once place.
 
unknown Define choice2 with 0 arguments
Use def to define choice2 with 0 arguments
 
unknown Call letUserPick
Within the definition of choice2 with 0 arguments, call letUserPick in at least once place.
 
unknown Call print
Within the definition of choice2 with 0 arguments, call print in at least once place.
 
unknown Use a conditional
Within the definition of choice2 with 0 arguments, use an if statement (possibly accompanied by an elif or else block) in at least once place.
 
unknown Use a return statement
Within the definition of choice2 with 0 arguments, use return _ in at least once place.
 
unknown Define prologue with 0 arguments
Use def to define prologue with 0 arguments
 
unknown Call print
Within the definition of prologue with 0 arguments, call print in at least once place.
 
unknown Do not use a return statement
Within the definition of prologue with 0 arguments, do not use return _.
 
unknown Define scene1 with 1 argument
Use def to define scene1 with 1 argument
 
unknown Call print
Within the definition of scene1 with 1 argument, call print in at least once place.
 
unknown Do not call letUserPick
Within the definition of scene1 with 1 argument, do not call letUserPick.
 
unknown Do not call choice1
Within the definition of scene1 with 1 argument, do not call choice1.
 
unknown Use a conditional
Within the definition of scene1 with 1 argument, use an if statement (possibly accompanied by an elif or else block) in at least once place.
 
unknown Do not use a return statement
Within the definition of scene1 with 1 argument, do not use return _.
 
unknown Define scene2 with 2 arguments
Use def to define scene2 with 2 arguments
 
unknown Call print
Within the definition of scene2 with 2 arguments, call print in at least once place.
 
unknown Do not call letUserPick
Within the definition of scene2 with 2 arguments, do not call letUserPick.
 
unknown Do not call choice1
Within the definition of scene2 with 2 arguments, do not call choice1.
 
unknown Do not call choice2
Within the definition of scene2 with 2 arguments, do not call choice2.
 
unknown Use a conditional
Within the definition of scene2 with 2 arguments, use an if statement (possibly accompanied by an elif or else block) in at least 2 places.
 
unknown Do not use a return statement
Within the definition of scene2 with 2 arguments, do not use return _.
 
unknown Define epilogue with 2 arguments
Use def to define epilogue with 2 arguments
 
unknown Call print
Within the definition of epilogue with 2 arguments, call print in at least once place.
 
unknown Do not call letUserPick
Within the definition of epilogue with 2 arguments, do not call letUserPick.
 
unknown Do not call choice1
Within the definition of epilogue with 2 arguments, do not call choice1.
 
unknown Do not call choice2
Within the definition of epilogue with 2 arguments, do not call choice2.
 
unknown Use a conditional
Within the definition of epilogue with 2 arguments, use an if statement (possibly accompanied by an elif or else block) in at least once place.
 
unknown Do not use a return statement
Within the definition of epilogue with 2 arguments, do not use return _.
 
unknown Define tellStory with 0 arguments
Use def to define tellStory with 0 arguments
 
unknown Call prologue
Within the definition of tellStory with 0 arguments, call prologue in at least once place.
 
unknown Call choice1
Within the definition of tellStory with 0 arguments, call choice1 in at least once place.
 
unknown Call choice2
Within the definition of tellStory with 0 arguments, call choice2 in at least once place.
 
unknown Call scene1
Within the definition of tellStory with 0 arguments, call scene1 in at least once place.
 
unknown Call scene2
Within the definition of tellStory with 0 arguments, call scene2 in at least once place.
 
unknown Call epilogue
Within the definition of tellStory with 0 arguments, call epilogue in at least once place.
 
unknown Do not call letUserPick
Within the definition of tellStory with 0 arguments, do not call letUserPick.
 
unknown Do not call input
Within the definition of tellStory with 0 arguments, do not call input.
 
unknown Extra goals
Complete all extra goals in addition to the core goals for a perfect score.
 
unknown Do not ignore the results of any fruitful function calls
According to the "Don't waste fruit" principle, every place you call a fruitful function (built-in or custom) you must store the result in a variable, or that function call must be part of a larger expression that uses its return value.
 
unknown Do not create any variables that you never make use of
According to the "Don't waste boxes" principle, every time you create a variable (using = or by defining a parameter for a function) you must also later use that variable as part of another expression. If you need to create a variable that you won't use, it must have the name _, but you should only do this if absolutely necessary.
 
unknown Process Requirements
How your code achieves its results.
 
unknown Extra goals
Complete all extra goals in addition to the core goals for a perfect score.
 
unknown tellStory does not crash
Your tellStory function must run without crashing.
 
unknown Product Requirements
Your code's result values.
 
unknown Core goals
Complete all core goals for core credit. Get partial credit for completing at least half, and more partial credit for completing at least 90%.
 
unknown letUserPick returns the correct result
The result returned when your letUserPick function is run must match the solution result.
 
unknown choice1 returns the correct result
The result returned when your choice1 function is run must match the solution result.
 
unknown choice2 returns the correct result
The result returned when your choice2 function is run must match the solution result.
 
unknown Extra goals
Complete all extra goals in addition to the core goals for a perfect score.
 
unknown letUserPick returns the correct result
The result returned when your letUserPick function is run must match the solution result.
 
unknown choice1 must be a predicate
The return value of choice1 must be a Boolean, no matter what input is provided.
 
unknown choice2 must be a predicate
The return value of choice2 must be a Boolean, no matter what input is provided.
 
unknown Behavior Requirements
What your code does from the user's perspective.
 
unknown Core goals
Complete all core goals for core credit. Get partial credit for completing at least half, and more partial credit for completing at least 90%.
 
unknown tellStory must respond to choices
When different inputs are provided (4 combinations of '1' and '2'), tellStory must print stories that have at least some differences: if the user makes different choices, the story must change somehow (there can be as much overlap as you like, as long as there is some part that changes.
 
unknown choice1 must respond to inputs
When different inputs are provided ('1' or '2') choice1 must print different responses.
 
unknown choice2 must respond to inputs
When different inputs are provided ('1' or '2') choice2 must print different responses.
 
unknown scene1 must respond to its argument
When different arguments are provided (True or False) scene1 must print different output.
 
unknown scene2 must respond to its arguments
When different arguments are provided (True or False for both the first and second arguments) scene2 must print different output. It's output must be distinct in all four possible contexts.
 
unknown Extra goals
Complete all extra goals in addition to the core goals for a perfect score.
 
unknown choice1 must respond to ambiguous inputs
When different inputs are provided ('1', '2', or other values) choice1 must print different responses (one response for '1', one for '2', and a third for anything else).
 
unknown choice2 must respond to ambiguous inputs
When different inputs are provided ('1', '2', or other values) choice2 must print different responses (one response for '1', one for '2', and a third for anything else).
 
unknown epilogue must respond correctly to its arguments
When different arguments are provided (True or False for both the first and second arguments) epilogue must print different output. It must have exactly three possible outputs: one that gets printed when the arguments are both True, one when they're both False, and a third when they're mixed (in either order).