Story-based adventure with functions and relationshipsText-based adventure gameText adventure and global variablesCactus (Prototype) - A game engine for text-based adventure gamesFirst text-based adventure gameText based adventure game navigationText-based Adventure-Game EngineJava text-based adventure gameShort text-based adventure gameText-based adventure and combat gameAdventure Game (text based) in C++

Is my Rep in Stack-Exchange Form?

How to split an equation over two lines?

Could Sauron have read Tom Bombadil's mind if Tom had held the Palantir?

Why does the numerical solution of an ODE move away from an unstable equilibrium?

Do flight schools typically have dress codes or expectations?

Is it damaging to turn off a small fridge for two days every week?

Going to get married soon, should I do it on Dec 31 or Jan 1?

Animation advice please

What reason would an alien civilization have for building a Dyson Sphere (or Swarm) if cheap Nuclear fusion is available?

How can I get more energy without spending coins?

Inverse-quotes-quine

Smooth Julia set for quadratic polynomials

How to perform Login Authentication at the client-side?

Impossible darts scores

Plotting with different color for a single curve

Can White Castle? #2

MH370 blackbox - is it still possible to retrieve data from it?

Why is the Turkish president's surname spelt in Russian as Эрдоган, with г?

Why would people reject a god's purely beneficial blessing?

Cascading Repair Costs following Blown Head Gasket on a 2004 Subaru Outback

What do you call a weak person's act of taking on bigger opponents?

Links to webpages in books

Peace Arch without exiting USA

What happens when I sacrifice a creature when my Teysa Karlov is on the battlefield?



Story-based adventure with functions and relationships


Text-based adventure gameText adventure and global variablesCactus (Prototype) - A game engine for text-based adventure gamesFirst text-based adventure gameText based adventure game navigationText-based Adventure-Game EngineJava text-based adventure gameShort text-based adventure gameText-based adventure and combat gameAdventure Game (text based) in C++






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








4












$begingroup$


This is a story-based adventure program I coded by myself (forgive the length). It took a long time but it was fun. It includes loading times, changes in relationships, relationship levels, storyline and possible outcomes, user input with xbox-style options, function calling and more. Your choices determine the outcomes and scenarios you land yourself in. Relationships go up or down(+x, -x) depending on your choices. In the end, the code prints all the choices you made and the impact on your community.



import time

def long_sleep():
for num in range(5):
time.sleep(1)
print('Loading...')
def short_sleep():
for num in range(3):
time.sleep(1)
print('Loading...')
#loading times
choices = []
synopsis = '''13 December 2027. A year into the zombie apocolypse, you are the young leader of a small, demoralized group in the middle of nowhere, fighting for a chance to see
light at the end of the tunnel. By September of next year, your group has grown greatly but that does not mean that your community on the brink of collapse. You must the make
tough political decisions to determine how your community fares.'''

vengeful = 'VENGEFUL.'
hateful = 'HATEFUL.'
disappointed = 'DISAPPOINTED.'
conflicted = 'CONFLICTED/NUETRAL.'
satisfied = 'SATISFIED.'
happy = 'HAPPY.'
prosperous = 'PROPEROUS'
#relationship levels
army_government = 'ARMY & GOVERNMENT'
civilian = 'CIVILIANS'
everybody = 'EVERYBODY'
civil_great_increase = ' This greatly improves your relationship with ' + civilian + '.'
civil_increase = ' This improves your relationship with ' + civilian + '.'
civil_slight_increase = ' This slightly improves your relationship with ' + civilian + '.'
civil_slight_decrease = ' This slightly decreases your relationship with ' + civilian + '.'
civil_decrease = ' This worsens your relationship with ' + civilian + '.'
civil_great_decrease = ' This greatly worsens your relationship with ' + civilian + '.'
army_great_decrease = ' This greatly worsens your relationship with ' + army_government + '.'
army_decrease = ' This worsens your relationship with ' + army_government + '.'
army_slight_decrease = ' This slightly decreases your relationship with ' + army_government + '.'
army_slight_increase = ' This slightly improves your relationship with ' + army_government + '.'
army_increase = ' This improves your relationship with ' + army_government + '.'
army_great_increase = ' This greatly improves your relationship with ' + army_government + '.'
everybody_great_increase = ' This greatly improves your relationship with ' + everybody + '.'
everybody_increase = ' This improves your relationship with ' + everybody + '.'
everybody_slight_increase = ' This slightly improves your relationship with ' + everybody + '.'
everybody_slight_decrease = ' This sligtly decreases your relationship with ' + everybody + '.'
everybody_decrease = ' This worsens your relationship with ' + everybody + '.'
everybody_great_decrease = ' This greatly worsens your relationship with ' + everybody + '.'
traitor = ' ' + everybody + ' wants you dead.'
hero = ' ' + everybody + ' looks to you as a hero. '

winter = 'n' + '''29 January 2029. It is five weeks into winter and the season shows no mercy. A drought happened for a majority of the last fall and it devastated
the food supply. As your community dives deeper into the winter, you realize that your supply will run out if consumption is not altered. You could do one of two options: reduce
consumption among civilians, or ignore the risk and take a chance([ALTER SUPPLY]X} B[IGNORE RISK]).''' + 'n> '
alter_supply = 'n' + '''Your government is now seen as selfish. You took the risk to protect the important people and "do your best with the rest". You have suffered heavy
civilian losses but your army and government losses have been few. As a result, there is division and danger in the streets. Riots breaking out, murders, arson, all happening in
your community.''' + civil_great_decrease
ignore_risk = 'n' + '''Your community did better than expected during the period. That is until you ran out of food in early March. Now you rely solely on scavenging,
risking getting devoured by zombies in order to go another day. Half your community is either dead or lost with great amount of casualties from civilians and
non-civilians.''' + army_great_decrease

spring = 'n' + '''27 March 2029. One way or another, you have made through the harsh winter and now must face a totally obstacle that could jeopardize your
survival. A group of violent, hostiles target your community and threaten to overtake it if not their demands are met([DEFEND]X [MERGE]B} [NEGOTIATE]A})''' + 'n> '
defend_alter_supply = 'n' + '''It was a tough battle but it was victory in the end. You sucessfully fended off the hostiles. Your army took a heavy blow but it is still intact.
Tensions are even worse though as hostile sympathizers were suppresed all around the community.''' + civil_decrease
merge_alter_supply = 'n' + '''You have sucessfully merged with hostiles giving most of what is owned to them. Civilians have actually commended this call in hopes of being
treated better. Nobody was harmed.''' + civil_increase + army_slight_decrease
negotiate_alter_supply = 'n' + '''You have sucessfully made a deal with the hostiles giving a large amount of resources in order to keep some peace. Your strugling-to-survive
civilians are irate with having to deal with even worse conditions. The government and army is also starting to starve. There are few to work with and things are not
looking up soon.''' + everybody_great_decrease
defend_ignore_risk = 'n' + '''Your whole community got destroyed. Everyone is dead, nice one chief.'''
merge_ignore_risk = 'n' + '''You have sucessfully merged with hostiles giving most of what is owned to them. Everybody sees this as the best possible option to end the
famine.''' + everybody_increase
negotiate_ignore_risk = 'n' + '''The last portions of supplies have been all been swallowed by the hostiles. You are left with nothing, nice one chief.'''

outbreak = 'n' + '''22 May 2029. There was no problem in sight until one happened on this date. Civil-government relations even improved. West Nile virus has shaken your
community to the core. All healthy folks are in quarantine including you do treat the sick, which could heavily strain resources, or exile them, which could skyrocket tensions
between civilians and the government([TREAT]X} B[EXILE])''' + 'n> '
outbreak_treat = 'n' + '''You have treated everyone with the sickness at a cost for low meds. Another epedemic happened a few weeks later, and you lost a lot of
people.''' + army_decrease + civil_increase
outbreak_exile = 'n' + '''You exiled the least useful to keep the most useful surviving. Though, resouces and supplies are stable and death is
rare.''' + civil_great_decrease + army_slight_increase
population = 'n' + '''2 June 2029. Everyone is starving in a famine worse than what you imagined. Once again people are dying of starvaton and once again it is your job
to decide what happens ([POPULATION REDUCTION]X B[DESPERATION])''' + 'n> '
population_reduce = 'n' + '''Remaining civilians resent this decision grealty calling it worse than cruel. However, resource control is the best way to avoid dying
out.''' + civil_great_decrease
population_desperation = 'n' + '''Your community's desperate attempts at sustaining itself failed horribly. Scavenging outside the safe zone, hunting, mining, even crimes
like robbery and cannibalism, all failed. Eventually you all died out. Nice one chief.'''
independence = 'n' + '''12 July 2029. Either everyone or the civilians came to a new home to hopefully recover from their famine. However how you all were treated is a
different story. You all were treated with inferiority, and rebuttal. You all were embarassed, mistreated and underfed. Now, you all are fed up and now want to devise a plan.
Folks however, are divided on whether an ([ESCAPE]X [CRUSADE]B} [TALK]Y}) should happen.''' + 'n> '
independence_escape = 'n' + '''It took a few weeks to thoroughly plan out the escape. You gathered as much people as you could to take part. The execution was
mostly sucessful, stripping as much supplies from the hostiles as you could. There were few deaths. The enraged, devastated hostiles kill all of your remaining folk, whether
they were in for the plan or out. You return to home and have some heavy clean up to do''' + civil_great_increase + army_slight_increase
independence_crusade = 'n' + '''A lot of intelligence and thought was put into infiltrating and arming your people in a fight for their freedom. In the end the
mission was accomplished. If you altered the food supply, you did not lose much. If you took the risk, you lost a great deal of people. You take over their place and make it your
own after finding out it has closer proximity to vital resources.''' + army_great_increase + civil_slight_increase
new_independence = 'n' + '''You gather up your most persuasive minds to convince the hostiles away from their inhumane ways. This surprisingly, goes better
than expected and with some initiative taken, your people and theirs now work together in unity.''' + everybody_increase

election = 'n' + '''25 October 2029. For the rest of the summer and the early autumn, you bounced back and for once resources are not a priority if you have made it this far.
But, the problems never stop. A new polotician named Mr. Powell looks to takeover and "lead this community in the right direction" but you know, deep down, he is tyrannical. He
picking up steam rapidly. A lot of people want him as the leader. The election is next week and you must decide whether to sabatoge the eleciton for the safety of your
impressionable community or think of every possible compelling argument to sway your people into safety. ([SABOTAGE]X} B[PERSUADE])''' + 'n> '
election_sabatoge = 'n' + '''You have sucessfully sabatoged and won the election and there is already suspicion in the results as most people picked the new person. Everyone is
irate with arson and riots breaking out all across the town. Everyone claims that the election was sabatoged but you hide the evidence that proves them
right.''' + civil_great_decrease
election_persuade = 'n' + '''You try your best to convince the crowd but fail as the crowd hangs on every word Mr. Powell says. He has taken over the town. In weeks his tyrannical
overtakes the town. Cruel actions like murdering innocent outsiders, killing the children and elderly, and decapitating those who sympathize, all take effect. Your community has
become the opposite of what you envisioned.''' + army_slight_decrease
upgrade = 'n' + '''14 November 2029. New Independence is now your new home, where the community thrives together on working to make the town a better place to live in. Different
types of people are divided on what should be big priority. ([ARMY]X [RESILIENCY]B} [RESOURCES]Y} [SERVICES]A})''' + 'n> '
army = 'n' + '''An EF-5 tornado directly hit your way and killed everything in its path. Nice one chief.'''
resources = 'n' + '''An EF-5 tornado directly hit your way and killed everything in its path. Nice one chief.'''
services = 'n' + '''An EF-5 tornado directly hit your way and killed everything in its path. Nice one chief.'''
resiliency = 'n' + '''You have focused you attention at making your community hard to destroy. Additions like much tougher boundaries and an underground helped prepare your
community to sucessfully survive an EF-5 tornado directly hitting the town. But now you lost everything and will have to rebuild.''' + everybody_increase

ending_opportunity = 'n' + '''1 December 2029. After a few weeks of trying to rebuild you realize that reconstruction. You can't go back your old community beacuse there is
nothing there. So now your stuck. You went scavenging earlier before the tornado and found a living space that could keep a person going for months. However, it keeps ONE person
going for months. You are left to decide if survival is really that important. ([ABANDON]X} B[PERSERVERE])''' + 'n> '
ending_abandon = 'n' + '''You left your community, with no leader, to die in exchange for your comfort. The community is irate and you will be killed on first sight if found.
Luckily, just before your food and supplies ran out, you found another community and you had few problems. You lived there for the rest of your life.''' + traitor
ending_perservere = 'n' + '''One by one, everyone fell out. With no necessities, your community died out. You where seen as loyal for sticking with your community until the end.
Nice one chief.'''
ending_terrorism = 'n' + '''6 February 2029. Mr. Powell is back and he is out for revenge from losing the election. He and his militia are destroying everything and everyone in
sight until he gets what wants. With only a few minutes before he arrives at your city hall, you and your army must decide to ([ATTACK]X B[RETREAT])''' + 'n> '
ending_attack = 'n' + '''You and your remaining army fought ferociousy against the bigger opposition. In the end, you won, but at a cost, destroyed the whole city. Few survived
being admist the exchange of explosives and gunfire. Your city is decimated but you stopped a major threat from taking over. It took two years before conditions returned to
normal'''
ending_retreat = 'n' + '''You most peaceful decision and left with your most trusted peers. You wandered off into unknown and eventually fit in with another community. A few
months later, you gathered up enough men to take back your old city. When you arrived, you discovered the city collapsed with decayed skeletons everywhere walked. It was a ghost
city.'''
ending_execution = 'n' + '''11 April 2030. You are about to be hanged for sympathizing against their standards. Everyone watches outside cheering and patiently awaiting your
death. When you asked for last words, you tried to ([CONVINCE THE CROWD]X  













4












$begingroup$


This is a story-based adventure program I coded by myself (forgive the length). It took a long time but it was fun. It includes loading times, changes in relationships, relationship levels, storyline and possible outcomes, user input with xbox-style options, function calling and more. Your choices determine the outcomes and scenarios you land yourself in. Relationships go up or down(+x, -x) depending on your choices. In the end, the code prints all the choices you made and the impact on your community.



import time

def long_sleep():
for num in range(5):
time.sleep(1)
print('Loading...')
def short_sleep():
for num in range(3):
time.sleep(1)
print('Loading...')
#loading times
choices = []
synopsis = '''13 December 2027. A year into the zombie apocolypse, you are the young leader of a small, demoralized group in the middle of nowhere, fighting for a chance to see
light at the end of the tunnel. By September of next year, your group has grown greatly but that does not mean that your community on the brink of collapse. You must the make
tough political decisions to determine how your community fares.'''

vengeful = 'VENGEFUL.'
hateful = 'HATEFUL.'
disappointed = 'DISAPPOINTED.'
conflicted = 'CONFLICTED/NUETRAL.'
satisfied = 'SATISFIED.'
happy = 'HAPPY.'
prosperous = 'PROPEROUS'
#relationship levels
army_government = 'ARMY & GOVERNMENT'
civilian = 'CIVILIANS'
everybody = 'EVERYBODY'
civil_great_increase = ' This greatly improves your relationship with ' + civilian + '.'
civil_increase = ' This improves your relationship with ' + civilian + '.'
civil_slight_increase = ' This slightly improves your relationship with ' + civilian + '.'
civil_slight_decrease = ' This slightly decreases your relationship with ' + civilian + '.'
civil_decrease = ' This worsens your relationship with ' + civilian + '.'
civil_great_decrease = ' This greatly worsens your relationship with ' + civilian + '.'
army_great_decrease = ' This greatly worsens your relationship with ' + army_government + '.'
army_decrease = ' This worsens your relationship with ' + army_government + '.'
army_slight_decrease = ' This slightly decreases your relationship with ' + army_government + '.'
army_slight_increase = ' This slightly improves your relationship with ' + army_government + '.'
army_increase = ' This improves your relationship with ' + army_government + '.'
army_great_increase = ' This greatly improves your relationship with ' + army_government + '.'
everybody_great_increase = ' This greatly improves your relationship with ' + everybody + '.'
everybody_increase = ' This improves your relationship with ' + everybody + '.'
everybody_slight_increase = ' This slightly improves your relationship with ' + everybody + '.'
everybody_slight_decrease = ' This sligtly decreases your relationship with ' + everybody + '.'
everybody_decrease = ' This worsens your relationship with ' + everybody + '.'
everybody_great_decrease = ' This greatly worsens your relationship with ' + everybody + '.'
traitor = ' ' + everybody + ' wants you dead.'
hero = ' ' + everybody + ' looks to you as a hero. '

winter = 'n' + '''29 January 2029. It is five weeks into winter and the season shows no mercy. A drought happened for a majority of the last fall and it devastated
the food supply. As your community dives deeper into the winter, you realize that your supply will run out if consumption is not altered. You could do one of two options: reduce
consumption among civilians, or ignore the risk and take a chance([ALTER SUPPLY]X B[IGNORE RISK]).''' + 'n> '
alter_supply = 'n' + '''Your government is now seen as selfish. You took the risk to protect the important people and "do your best with the rest". You have suffered heavy
civilian losses but your army and government losses have been few. As a result, there is division and danger in the streets. Riots breaking out, murders, arson, all happening in
your community.''' + civil_great_decrease
ignore_risk = 'n' + '''Your community did better than expected during the period. That is until you ran out of food in early March. Now you rely solely on scavenging,
risking getting devoured by zombies in order to go another day. Half your community is either dead or lost with great amount of casualties from civilians and
non-civilians.''' + army_great_decrease

spring = 'n' + '''27 March 2029. One way or another, you have made through the harsh winter and now must face a totally obstacle that could jeopardize your
survival. A group of violent, hostiles target your community and threaten to overtake it if not their demands are met([DEFEND]X [MERGE]B} [NEGOTIATE]A})''' + 'n> '
defend_alter_supply = 'n' + '''It was a tough battle but it was victory in the end. You sucessfully fended off the hostiles. Your army took a heavy blow but it is still intact.
Tensions are even worse though as hostile sympathizers were suppresed all around the community.''' + civil_decrease
merge_alter_supply = 'n' + '''You have sucessfully merged with hostiles giving most of what is owned to them. Civilians have actually commended this call in hopes of being
treated better. Nobody was harmed.''' + civil_increase + army_slight_decrease
negotiate_alter_supply = 'n' + '''You have sucessfully made a deal with the hostiles giving a large amount of resources in order to keep some peace. Your strugling-to-survive
civilians are irate with having to deal with even worse conditions. The government and army is also starting to starve. There are few to work with and things are not
looking up soon.''' + everybody_great_decrease
defend_ignore_risk = 'n' + '''Your whole community got destroyed. Everyone is dead, nice one chief.'''
merge_ignore_risk = 'n' + '''You have sucessfully merged with hostiles giving most of what is owned to them. Everybody sees this as the best possible option to end the
famine.''' + everybody_increase
negotiate_ignore_risk = 'n' + '''The last portions of supplies have been all been swallowed by the hostiles. You are left with nothing, nice one chief.'''

outbreak = 'n' + '''22 May 2029. There was no problem in sight until one happened on this date. Civil-government relations even improved. West Nile virus has shaken your
community to the core. All healthy folks are in quarantine including you do treat the sick, which could heavily strain resources, or exile them, which could skyrocket tensions
between civilians and the government([TREAT]X} B[EXILE])''' + 'n> '
outbreak_treat = 'n' + '''You have treated everyone with the sickness at a cost for low meds. Another epedemic happened a few weeks later, and you lost a lot of
people.''' + army_decrease + civil_increase
outbreak_exile = 'n' + '''You exiled the least useful to keep the most useful surviving. Though, resouces and supplies are stable and death is
rare.''' + civil_great_decrease + army_slight_increase
population = 'n' + '''2 June 2029. Everyone is starving in a famine worse than what you imagined. Once again people are dying of starvaton and once again it is your job
to decide what happens ([POPULATION REDUCTION]X B[DESPERATION])''' + 'n> '
population_reduce = 'n' + '''Remaining civilians resent this decision grealty calling it worse than cruel. However, resource control is the best way to avoid dying
out.''' + civil_great_decrease
population_desperation = 'n' + '''Your community's desperate attempts at sustaining itself failed horribly. Scavenging outside the safe zone, hunting, mining, even crimes
like robbery and cannibalism, all failed. Eventually you all died out. Nice one chief.'''
independence = 'n' + '''12 July 2029. Either everyone or the civilians came to a new home to hopefully recover from their famine. However how you all were treated is a
different story. You all were treated with inferiority, and rebuttal. You all were embarassed, mistreated and underfed. Now, you all are fed up and now want to devise a plan.
Folks however, are divided on whether an ([ESCAPE]X [CRUSADE]B} [TALK]Y}) should happen.''' + 'n> '
independence_escape = 'n' + '''It took a few weeks to thoroughly plan out the escape. You gathered as much people as you could to take part. The execution was
mostly sucessful, stripping as much supplies from the hostiles as you could. There were few deaths. The enraged, devastated hostiles kill all of your remaining folk, whether
they were in for the plan or out. You return to home and have some heavy clean up to do''' + civil_great_increase + army_slight_increase
independence_crusade = 'n' + '''A lot of intelligence and thought was put into infiltrating and arming your people in a fight for their freedom. In the end the
mission was accomplished. If you altered the food supply, you did not lose much. If you took the risk, you lost a great deal of people. You take over their place and make it your
own after finding out it has closer proximity to vital resources.''' + army_great_increase + civil_slight_increase
new_independence = 'n' + '''You gather up your most persuasive minds to convince the hostiles away from their inhumane ways. This surprisingly, goes better
than expected and with some initiative taken, your people and theirs now work together in unity.''' + everybody_increase

election = 'n' + '''25 October 2029. For the rest of the summer and the early autumn, you bounced back and for once resources are not a priority if you have made it this far.
But, the problems never stop. A new polotician named Mr. Powell looks to takeover and "lead this community in the right direction" but you know, deep down, he is tyrannical. He
picking up steam rapidly. A lot of people want him as the leader. The election is next week and you must decide whether to sabatoge the eleciton for the safety of your
impressionable community or think of every possible compelling argument to sway your people into safety. ([SABOTAGE]X} B[PERSUADE])''' + 'n> '
election_sabatoge = 'n' + '''You have sucessfully sabatoged and won the election and there is already suspicion in the results as most people picked the new person. Everyone is
irate with arson and riots breaking out all across the town. Everyone claims that the election was sabatoged but you hide the evidence that proves them
right.''' + civil_great_decrease
election_persuade = 'n' + '''You try your best to convince the crowd but fail as the crowd hangs on every word Mr. Powell says. He has taken over the town. In weeks his tyrannical
overtakes the town. Cruel actions like murdering innocent outsiders, killing the children and elderly, and decapitating those who sympathize, all take effect. Your community has
become the opposite of what you envisioned.''' + army_slight_decrease
upgrade = 'n' + '''14 November 2029. New Independence is now your new home, where the community thrives together on working to make the town a better place to live in. Different
types of people are divided on what should be big priority. ([ARMY]X [RESILIENCY]B} [RESOURCES]Y} [SERVICES]A})''' + 'n> '
army = 'n' + '''An EF-5 tornado directly hit your way and killed everything in its path. Nice one chief.'''
resources = 'n' + '''An EF-5 tornado directly hit your way and killed everything in its path. Nice one chief.'''
services = 'n' + '''An EF-5 tornado directly hit your way and killed everything in its path. Nice one chief.'''
resiliency = 'n' + '''You have focused you attention at making your community hard to destroy. Additions like much tougher boundaries and an underground helped prepare your
community to sucessfully survive an EF-5 tornado directly hitting the town. But now you lost everything and will have to rebuild.''' + everybody_increase

ending_opportunity = 'n' + '''1 December 2029. After a few weeks of trying to rebuild you realize that reconstruction. You can't go back your old community beacuse there is
nothing there. So now your stuck. You went scavenging earlier before the tornado and found a living space that could keep a person going for months. However, it keeps ONE person
going for months. You are left to decide if survival is really that important. ([ABANDON]X} B[PERSERVERE])''' + 'n> '
ending_abandon = 'n' + '''You left your community, with no leader, to die in exchange for your comfort. The community is irate and you will be killed on first sight if found.
Luckily, just before your food and supplies ran out, you found another community and you had few problems. You lived there for the rest of your life.''' + traitor
ending_perservere = 'n' + '''One by one, everyone fell out. With no necessities, your community died out. You where seen as loyal for sticking with your community until the end.
Nice one chief.'''
ending_terrorism = 'n' + '''6 February 2029. Mr. Powell is back and he is out for revenge from losing the election. He and his militia are destroying everything and everyone in
sight until he gets what wants. With only a few minutes before he arrives at your city hall, you and your army must decide to ([ATTACK]X B[RETREAT])''' + 'n> '
ending_attack = 'n' + '''You and your remaining army fought ferociousy against the bigger opposition. In the end, you won, but at a cost, destroyed the whole city. Few survived
being admist the exchange of explosives and gunfire. Your city is decimated but you stopped a major threat from taking over. It took two years before conditions returned to
normal'''
ending_retreat = 'n' + '''You most peaceful decision and left with your most trusted peers. You wandered off into unknown and eventually fit in with another community. A few
months later, you gathered up enough men to take back your old city. When you arrived, you discovered the city collapsed with decayed skeletons everywhere walked. It was a ghost
city.'''
ending_execution = 'n' + '''11 April 2030. You are about to be hanged for sympathizing against their standards. Everyone watches outside cheering and patiently awaiting your
death. When you asked for last words, you tried to ([CONVINCE THE CROWD]X  









4












4








4





$begingroup$


This is a story-based adventure program I coded by myself (forgive the length). It took a long time but it was fun. It includes loading times, changes in relationships, relationship levels, storyline and possible outcomes, user input with xbox-style options, function calling and more. Your choices determine the outcomes and scenarios you land yourself in. Relationships go up or down(+x, -x) depending on your choices. In the end, the code prints all the choices you made and the impact on your community.



import time

def long_sleep():
for num in range(5):
time.sleep(1)
print('Loading...')
def short_sleep():
for num in range(3):
time.sleep(1)
print('Loading...')
#loading times
choices = []
synopsis = '''13 December 2027. A year into the zombie apocolypse, you are the young leader of a small, demoralized group in the middle of nowhere, fighting for a chance to see
light at the end of the tunnel. By September of next year, your group has grown greatly but that does not mean that your community on the brink of collapse. You must the make
tough political decisions to determine how your community fares.'''

vengeful = 'VENGEFUL.'
hateful = 'HATEFUL.'
disappointed = 'DISAPPOINTED.'
conflicted = 'CONFLICTED/NUETRAL.'
satisfied = 'SATISFIED.'
happy = 'HAPPY.'
prosperous = 'PROPEROUS'
#relationship levels
army_government = 'ARMY & GOVERNMENT'
civilian = 'CIVILIANS'
everybody = 'EVERYBODY'
civil_great_increase = ' This greatly improves your relationship with ' + civilian + '.'
civil_increase = ' This improves your relationship with ' + civilian + '.'
civil_slight_increase = ' This slightly improves your relationship with ' + civilian + '.'
civil_slight_decrease = ' This slightly decreases your relationship with ' + civilian + '.'
civil_decrease = ' This worsens your relationship with ' + civilian + '.'
civil_great_decrease = ' This greatly worsens your relationship with ' + civilian + '.'
army_great_decrease = ' This greatly worsens your relationship with ' + army_government + '.'
army_decrease = ' This worsens your relationship with ' + army_government + '.'
army_slight_decrease = ' This slightly decreases your relationship with ' + army_government + '.'
army_slight_increase = ' This slightly improves your relationship with ' + army_government + '.'
army_increase = ' This improves your relationship with ' + army_government + '.'
army_great_increase = ' This greatly improves your relationship with ' + army_government + '.'
everybody_great_increase = ' This greatly improves your relationship with ' + everybody + '.'
everybody_increase = ' This improves your relationship with ' + everybody + '.'
everybody_slight_increase = ' This slightly improves your relationship with ' + everybody + '.'
everybody_slight_decrease = ' This sligtly decreases your relationship with ' + everybody + '.'
everybody_decrease = ' This worsens your relationship with ' + everybody + '.'
everybody_great_decrease = ' This greatly worsens your relationship with ' + everybody + '.'
traitor = ' ' + everybody + ' wants you dead.'
hero = ' ' + everybody + ' looks to you as a hero. '

winter = 'n' + '''29 January 2029. It is five weeks into winter and the season shows no mercy. A drought happened for a majority of the last fall and it devastated
the food supply. As your community dives deeper into the winter, you realize that your supply will run out if consumption is not altered. You could do one of two options: reduce
consumption among civilians, or ignore the risk and take a chance([ALTER SUPPLY]X B[IGNORE RISK]).''' + 'n> '
alter_supply = 'n' + '''Your government is now seen as selfish. You took the risk to protect the important people and "do your best with the rest". You have suffered heavy
civilian losses but your army and government losses have been few. As a result, there is division and danger in the streets. Riots breaking out, murders, arson, all happening in
your community.''' + civil_great_decrease
ignore_risk = 'n' + '''Your community did better than expected during the period. That is until you ran out of food in early March. Now you rely solely on scavenging,
risking getting devoured by zombies in order to go another day. Half your community is either dead or lost with great amount of casualties from civilians and
non-civilians.''' + army_great_decrease

spring = 'n' + '''27 March 2029. One way or another, you have made through the harsh winter and now must face a totally obstacle that could jeopardize your
survival. A group of violent, hostiles target your community and threaten to overtake it if not their demands are met([DEFEND]X [MERGE]B} [NEGOTIATE]A})''' + 'n> '
defend_alter_supply = 'n' + '''It was a tough battle but it was victory in the end. You sucessfully fended off the hostiles. Your army took a heavy blow but it is still intact.
Tensions are even worse though as hostile sympathizers were suppresed all around the community.''' + civil_decrease
merge_alter_supply = 'n' + '''You have sucessfully merged with hostiles giving most of what is owned to them. Civilians have actually commended this call in hopes of being
treated better. Nobody was harmed.''' + civil_increase + army_slight_decrease
negotiate_alter_supply = 'n' + '''You have sucessfully made a deal with the hostiles giving a large amount of resources in order to keep some peace. Your strugling-to-survive
civilians are irate with having to deal with even worse conditions. The government and army is also starting to starve. There are few to work with and things are not
looking up soon.''' + everybody_great_decrease
defend_ignore_risk = 'n' + '''Your whole community got destroyed. Everyone is dead, nice one chief.'''
merge_ignore_risk = 'n' + '''You have sucessfully merged with hostiles giving most of what is owned to them. Everybody sees this as the best possible option to end the
famine.''' + everybody_increase
negotiate_ignore_risk = 'n' + '''The last portions of supplies have been all been swallowed by the hostiles. You are left with nothing, nice one chief.'''

outbreak = 'n' + '''22 May 2029. There was no problem in sight until one happened on this date. Civil-government relations even improved. West Nile virus has shaken your
community to the core. All healthy folks are in quarantine including you do treat the sick, which could heavily strain resources, or exile them, which could skyrocket tensions
between civilians and the government([TREAT]X} B[EXILE])''' + 'n> '
outbreak_treat = 'n' + '''You have treated everyone with the sickness at a cost for low meds. Another epedemic happened a few weeks later, and you lost a lot of
people.''' + army_decrease + civil_increase
outbreak_exile = 'n' + '''You exiled the least useful to keep the most useful surviving. Though, resouces and supplies are stable and death is
rare.''' + civil_great_decrease + army_slight_increase
population = 'n' + '''2 June 2029. Everyone is starving in a famine worse than what you imagined. Once again people are dying of starvaton and once again it is your job
to decide what happens ([POPULATION REDUCTION]X B[DESPERATION])''' + 'n> '
population_reduce = 'n' + '''Remaining civilians resent this decision grealty calling it worse than cruel. However, resource control is the best way to avoid dying
out.''' + civil_great_decrease
population_desperation = 'n' + '''Your community's desperate attempts at sustaining itself failed horribly. Scavenging outside the safe zone, hunting, mining, even crimes
like robbery and cannibalism, all failed. Eventually you all died out. Nice one chief.'''
independence = 'n' + '''12 July 2029. Either everyone or the civilians came to a new home to hopefully recover from their famine. However how you all were treated is a
different story. You all were treated with inferiority, and rebuttal. You all were embarassed, mistreated and underfed. Now, you all are fed up and now want to devise a plan.
Folks however, are divided on whether an ([ESCAPE]X [CRUSADE]B} [TALK]Y}) should happen.''' + 'n> '
independence_escape = 'n' + '''It took a few weeks to thoroughly plan out the escape. You gathered as much people as you could to take part. The execution was
mostly sucessful, stripping as much supplies from the hostiles as you could. There were few deaths. The enraged, devastated hostiles kill all of your remaining folk, whether
they were in for the plan or out. You return to home and have some heavy clean up to do''' + civil_great_increase + army_slight_increase
independence_crusade = 'n' + '''A lot of intelligence and thought was put into infiltrating and arming your people in a fight for their freedom. In the end the
mission was accomplished. If you altered the food supply, you did not lose much. If you took the risk, you lost a great deal of people. You take over their place and make it your
own after finding out it has closer proximity to vital resources.''' + army_great_increase + civil_slight_increase
new_independence = 'n' + '''You gather up your most persuasive minds to convince the hostiles away from their inhumane ways. This surprisingly, goes better
than expected and with some initiative taken, your people and theirs now work together in unity.''' + everybody_increase

election = 'n' + '''25 October 2029. For the rest of the summer and the early autumn, you bounced back and for once resources are not a priority if you have made it this far.
But, the problems never stop. A new polotician named Mr. Powell looks to takeover and "lead this community in the right direction" but you know, deep down, he is tyrannical. He
picking up steam rapidly. A lot of people want him as the leader. The election is next week and you must decide whether to sabatoge the eleciton for the safety of your
impressionable community or think of every possible compelling argument to sway your people into safety. ([SABOTAGE]X} B[PERSUADE])''' + 'n> '
election_sabatoge = 'n' + '''You have sucessfully sabatoged and won the election and there is already suspicion in the results as most people picked the new person. Everyone is
irate with arson and riots breaking out all across the town. Everyone claims that the election was sabatoged but you hide the evidence that proves them
right.''' + civil_great_decrease
election_persuade = 'n' + '''You try your best to convince the crowd but fail as the crowd hangs on every word Mr. Powell says. He has taken over the town. In weeks his tyrannical
overtakes the town. Cruel actions like murdering innocent outsiders, killing the children and elderly, and decapitating those who sympathize, all take effect. Your community has
become the opposite of what you envisioned.''' + army_slight_decrease
upgrade = 'n' + '''14 November 2029. New Independence is now your new home, where the community thrives together on working to make the town a better place to live in. Different
types of people are divided on what should be big priority. ([ARMY]X [RESILIENCY]B} [RESOURCES]Y} [SERVICES]A})''' + 'n> '
army = 'n' + '''An EF-5 tornado directly hit your way and killed everything in its path. Nice one chief.'''
resources = 'n' + '''An EF-5 tornado directly hit your way and killed everything in its path. Nice one chief.'''
services = 'n' + '''An EF-5 tornado directly hit your way and killed everything in its path. Nice one chief.'''
resiliency = 'n' + '''You have focused you attention at making your community hard to destroy. Additions like much tougher boundaries and an underground helped prepare your
community to sucessfully survive an EF-5 tornado directly hitting the town. But now you lost everything and will have to rebuild.''' + everybody_increase

ending_opportunity = 'n' + '''1 December 2029. After a few weeks of trying to rebuild you realize that reconstruction. You can't go back your old community beacuse there is
nothing there. So now your stuck. You went scavenging earlier before the tornado and found a living space that could keep a person going for months. However, it keeps ONE person
going for months. You are left to decide if survival is really that important. ([ABANDON]X} B[PERSERVERE])''' + 'n> '
ending_abandon = 'n' + '''You left your community, with no leader, to die in exchange for your comfort. The community is irate and you will be killed on first sight if found.
Luckily, just before your food and supplies ran out, you found another community and you had few problems. You lived there for the rest of your life.''' + traitor
ending_perservere = 'n' + '''One by one, everyone fell out. With no necessities, your community died out. You where seen as loyal for sticking with your community until the end.
Nice one chief.'''
ending_terrorism = 'n' + '''6 February 2029. Mr. Powell is back and he is out for revenge from losing the election. He and his militia are destroying everything and everyone in
sight until he gets what wants. With only a few minutes before he arrives at your city hall, you and your army must decide to ([ATTACK]X B[RETREAT])''' + 'n> '
ending_attack = 'n' + '''You and your remaining army fought ferociousy against the bigger opposition. In the end, you won, but at a cost, destroyed the whole city. Few survived
being admist the exchange of explosives and gunfire. Your city is decimated but you stopped a major threat from taking over. It took two years before conditions returned to
normal'''
ending_retreat = 'n' + '''You most peaceful decision and left with your most trusted peers. You wandered off into unknown and eventually fit in with another community. A few
months later, you gathered up enough men to take back your old city. When you arrived, you discovered the city collapsed with decayed skeletons everywhere walked. It was a ghost
city.'''
ending_execution = 'n' + '''11 April 2030. You are about to be hanged for sympathizing against their standards. Everyone watches outside cheering and patiently awaiting your
death. When you asked for last words, you tried to ([CONVINCE THE CROWD]X improve this question









New contributor



Mikey Akamihe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$




This is a story-based adventure program I coded by myself (forgive the length). It took a long time but it was fun. It includes loading times, changes in relationships, relationship levels, storyline and possible outcomes, user input with xbox-style options, function calling and more. Your choices determine the outcomes and scenarios you land yourself in. Relationships go up or down(+x, -x) depending on your choices. In the end, the code prints all the choices you made and the impact on your community.



import time

def long_sleep():
for num in range(5):
time.sleep(1)
print('Loading...')
def short_sleep():
for num in range(3):
time.sleep(1)
print('Loading...')
#loading times
choices = []
synopsis = '''13 December 2027. A year into the zombie apocolypse, you are the young leader of a small, demoralized group in the middle of nowhere, fighting for a chance to see
light at the end of the tunnel. By September of next year, your group has grown greatly but that does not mean that your community on the brink of collapse. You must the make
tough political decisions to determine how your community fares.'''

vengeful = 'VENGEFUL.'
hateful = 'HATEFUL.'
disappointed = 'DISAPPOINTED.'
conflicted = 'CONFLICTED/NUETRAL.'
satisfied = 'SATISFIED.'
happy = 'HAPPY.'
prosperous = 'PROPEROUS'
#relationship levels
army_government = 'ARMY & GOVERNMENT'
civilian = 'CIVILIANS'
everybody = 'EVERYBODY'
civil_great_increase = ' This greatly improves your relationship with ' + civilian + '.'
civil_increase = ' This improves your relationship with ' + civilian + '.'
civil_slight_increase = ' This slightly improves your relationship with ' + civilian + '.'
civil_slight_decrease = ' This slightly decreases your relationship with ' + civilian + '.'
civil_decrease = ' This worsens your relationship with ' + civilian + '.'
civil_great_decrease = ' This greatly worsens your relationship with ' + civilian + '.'
army_great_decrease = ' This greatly worsens your relationship with ' + army_government + '.'
army_decrease = ' This worsens your relationship with ' + army_government + '.'
army_slight_decrease = ' This slightly decreases your relationship with ' + army_government + '.'
army_slight_increase = ' This slightly improves your relationship with ' + army_government + '.'
army_increase = ' This improves your relationship with ' + army_government + '.'
army_great_increase = ' This greatly improves your relationship with ' + army_government + '.'
everybody_great_increase = ' This greatly improves your relationship with ' + everybody + '.'
everybody_increase = ' This improves your relationship with ' + everybody + '.'
everybody_slight_increase = ' This slightly improves your relationship with ' + everybody + '.'
everybody_slight_decrease = ' This sligtly decreases your relationship with ' + everybody + '.'
everybody_decrease = ' This worsens your relationship with ' + everybody + '.'
everybody_great_decrease = ' This greatly worsens your relationship with ' + everybody + '.'
traitor = ' ' + everybody + ' wants you dead.'
hero = ' ' + everybody + ' looks to you as a hero. '

winter = 'n' + '''29 January 2029. It is five weeks into winter and the season shows no mercy. A drought happened for a majority of the last fall and it devastated
the food supply. As your community dives deeper into the winter, you realize that your supply will run out if consumption is not altered. You could do one of two options: reduce
consumption among civilians, or ignore the risk and take a chance([ALTER SUPPLY]X B[IGNORE RISK]).''' + 'n> '
alter_supply = 'n' + '''Your government is now seen as selfish. You took the risk to protect the important people and "do your best with the rest". You have suffered heavy
civilian losses but your army and government losses have been few. As a result, there is division and danger in the streets. Riots breaking out, murders, arson, all happening in
your community.''' + civil_great_decrease
ignore_risk = 'n' + '''Your community did better than expected during the period. That is until you ran out of food in early March. Now you rely solely on scavenging,
risking getting devoured by zombies in order to go another day. Half your community is either dead or lost with great amount of casualties from civilians and
non-civilians.''' + army_great_decrease

spring = 'n' + '''27 March 2029. One way or another, you have made through the harsh winter and now must face a totally obstacle that could jeopardize your
survival. A group of violent, hostiles target your community and threaten to overtake it if not their demands are met([DEFEND]X [MERGE]B} [NEGOTIATE]A})''' + 'n> '
defend_alter_supply = 'n' + '''It was a tough battle but it was victory in the end. You sucessfully fended off the hostiles. Your army took a heavy blow but it is still intact.
Tensions are even worse though as hostile sympathizers were suppresed all around the community.''' + civil_decrease
merge_alter_supply = 'n' + '''You have sucessfully merged with hostiles giving most of what is owned to them. Civilians have actually commended this call in hopes of being
treated better. Nobody was harmed.''' + civil_increase + army_slight_decrease
negotiate_alter_supply = 'n' + '''You have sucessfully made a deal with the hostiles giving a large amount of resources in order to keep some peace. Your strugling-to-survive
civilians are irate with having to deal with even worse conditions. The government and army is also starting to starve. There are few to work with and things are not
looking up soon.''' + everybody_great_decrease
defend_ignore_risk = 'n' + '''Your whole community got destroyed. Everyone is dead, nice one chief.'''
merge_ignore_risk = 'n' + '''You have sucessfully merged with hostiles giving most of what is owned to them. Everybody sees this as the best possible option to end the
famine.''' + everybody_increase
negotiate_ignore_risk = 'n' + '''The last portions of supplies have been all been swallowed by the hostiles. You are left with nothing, nice one chief.'''

outbreak = 'n' + '''22 May 2029. There was no problem in sight until one happened on this date. Civil-government relations even improved. West Nile virus has shaken your
community to the core. All healthy folks are in quarantine including you do treat the sick, which could heavily strain resources, or exile them, which could skyrocket tensions
between civilians and the government([TREAT]X} B[EXILE])''' + 'n> '
outbreak_treat = 'n' + '''You have treated everyone with the sickness at a cost for low meds. Another epedemic happened a few weeks later, and you lost a lot of
people.''' + army_decrease + civil_increase
outbreak_exile = 'n' + '''You exiled the least useful to keep the most useful surviving. Though, resouces and supplies are stable and death is
rare.''' + civil_great_decrease + army_slight_increase
population = 'n' + '''2 June 2029. Everyone is starving in a famine worse than what you imagined. Once again people are dying of starvaton and once again it is your job
to decide what happens ([POPULATION REDUCTION]X B[DESPERATION])''' + 'n> '
population_reduce = 'n' + '''Remaining civilians resent this decision grealty calling it worse than cruel. However, resource control is the best way to avoid dying
out.''' + civil_great_decrease
population_desperation = 'n' + '''Your community's desperate attempts at sustaining itself failed horribly. Scavenging outside the safe zone, hunting, mining, even crimes
like robbery and cannibalism, all failed. Eventually you all died out. Nice one chief.'''
independence = 'n' + '''12 July 2029. Either everyone or the civilians came to a new home to hopefully recover from their famine. However how you all were treated is a
different story. You all were treated with inferiority, and rebuttal. You all were embarassed, mistreated and underfed. Now, you all are fed up and now want to devise a plan.
Folks however, are divided on whether an ([ESCAPE]X [CRUSADE]B} [TALK]Y}) should happen.''' + 'n> '
independence_escape = 'n' + '''It took a few weeks to thoroughly plan out the escape. You gathered as much people as you could to take part. The execution was
mostly sucessful, stripping as much supplies from the hostiles as you could. There were few deaths. The enraged, devastated hostiles kill all of your remaining folk, whether
they were in for the plan or out. You return to home and have some heavy clean up to do''' + civil_great_increase + army_slight_increase
independence_crusade = 'n' + '''A lot of intelligence and thought was put into infiltrating and arming your people in a fight for their freedom. In the end the
mission was accomplished. If you altered the food supply, you did not lose much. If you took the risk, you lost a great deal of people. You take over their place and make it your
own after finding out it has closer proximity to vital resources.''' + army_great_increase + civil_slight_increase
new_independence = 'n' + '''You gather up your most persuasive minds to convince the hostiles away from their inhumane ways. This surprisingly, goes better
than expected and with some initiative taken, your people and theirs now work together in unity.''' + everybody_increase

election = 'n' + '''25 October 2029. For the rest of the summer and the early autumn, you bounced back and for once resources are not a priority if you have made it this far.
But, the problems never stop. A new polotician named Mr. Powell looks to takeover and "lead this community in the right direction" but you know, deep down, he is tyrannical. He
picking up steam rapidly. A lot of people want him as the leader. The election is next week and you must decide whether to sabatoge the eleciton for the safety of your
impressionable community or think of every possible compelling argument to sway your people into safety. ([SABOTAGE]X} B[PERSUADE])''' + 'n> '
election_sabatoge = 'n' + '''You have sucessfully sabatoged and won the election and there is already suspicion in the results as most people picked the new person. Everyone is
irate with arson and riots breaking out all across the town. Everyone claims that the election was sabatoged but you hide the evidence that proves them
right.''' + civil_great_decrease
election_persuade = 'n' + '''You try your best to convince the crowd but fail as the crowd hangs on every word Mr. Powell says. He has taken over the town. In weeks his tyrannical
overtakes the town. Cruel actions like murdering innocent outsiders, killing the children and elderly, and decapitating those who sympathize, all take effect. Your community has
become the opposite of what you envisioned.''' + army_slight_decrease
upgrade = 'n' + '''14 November 2029. New Independence is now your new home, where the community thrives together on working to make the town a better place to live in. Different
types of people are divided on what should be big priority. ([ARMY]X [RESILIENCY]B} [RESOURCES]Y} [SERVICES]A})''' + 'n> '
army = 'n' + '''An EF-5 tornado directly hit your way and killed everything in its path. Nice one chief.'''
resources = 'n' + '''An EF-5 tornado directly hit your way and killed everything in its path. Nice one chief.'''
services = 'n' + '''An EF-5 tornado directly hit your way and killed everything in its path. Nice one chief.'''
resiliency = 'n' + '''You have focused you attention at making your community hard to destroy. Additions like much tougher boundaries and an underground helped prepare your
community to sucessfully survive an EF-5 tornado directly hitting the town. But now you lost everything and will have to rebuild.''' + everybody_increase

ending_opportunity = 'n' + '''1 December 2029. After a few weeks of trying to rebuild you realize that reconstruction. You can't go back your old community beacuse there is
nothing there. So now your stuck. You went scavenging earlier before the tornado and found a living space that could keep a person going for months. However, it keeps ONE person
going for months. You are left to decide if survival is really that important. ([ABANDON]X} B[PERSERVERE])''' + 'n> '
ending_abandon = 'n' + '''You left your community, with no leader, to die in exchange for your comfort. The community is irate and you will be killed on first sight if found.
Luckily, just before your food and supplies ran out, you found another community and you had few problems. You lived there for the rest of your life.''' + traitor
ending_perservere = 'n' + '''One by one, everyone fell out. With no necessities, your community died out. You where seen as loyal for sticking with your community until the end.
Nice one chief.'''
ending_terrorism = 'n' + '''6 February 2029. Mr. Powell is back and he is out for revenge from losing the election. He and his militia are destroying everything and everyone in
sight until he gets what wants. With only a few minutes before he arrives at your city hall, you and your army must decide to ([ATTACK]X B[RETREAT])''' + 'n> '
ending_attack = 'n' + '''You and your remaining army fought ferociousy against the bigger opposition. In the end, you won, but at a cost, destroyed the whole city. Few survived
being admist the exchange of explosives and gunfire. Your city is decimated but you stopped a major threat from taking over. It took two years before conditions returned to
normal'''
ending_retreat = 'n' + '''You most peaceful decision and left with your most trusted peers. You wandered off into unknown and eventually fit in with another community. A few
months later, you gathered up enough men to take back your old city. When you arrived, you discovered the city collapsed with decayed skeletons everywhere walked. It was a ghost
city.'''
ending_execution = 'n' + '''11 April 2030. You are about to be hanged for sympathizing against their standards. Everyone watches outside cheering and patiently awaiting your
death. When you asked for last words, you tried to ([CONVINCE THE CROWD]X {B[KILL MR. POWELL]).''' 'n> '
ending_death = 'n' + '''You have died. The people heard your short speech and were compelled and related to it deeply. They were so emotional that no little time wasted to
overthrow Mr. Powell's government after you were executed. Soon a new leader was chosen to lead the community and ever since, they have advanced to be one of the most expansive
good guys in the apocolypse. They even found a cure.''' + hero
ending_kill = 'n' + '''Just before somebody could do something, you grabbed a soldier's AK-47 and AKed both him and Mr.Powell. You barely managed to escape the scene. You gathered
any remaining supporters to basically go on a warpath and kill as much army members as you could until they surrendered. You somehow succeedeed in this and basically took over by
force. This makes the people very unhappy but over time they realize how much you care.'''

the_end = 'n' + 'THE END'

army_relationship = 0
civil_relationship = 0
hero_traitor = 15
major_change = 2
change = 1
slight = 0.5
relationships = [army_relationship, civil_relationship, hero_traitor, major_change, change, slight]
army = relationships[0]
civil = relationships[1]
hero_betray = relationships[2]
major = relationships[3]
up = relationships[4]
down = relationships[4]
slightly = relationships[5]

def roadblock():
roadblock = 'Please enter a valid input'
print(roadblock)
def story():
situation_winter = str(input(winter))
if situation_winter == 'X':
short_sleep()
print(alter_supply)
relationships[1] -= major
spring_alter_supply()
choices.append('chose safety over risk')
elif situation_winter == 'B':
short_sleep()
print(ignore_risk)
relationships[0] -= major
spring_ignore_risk()
choices.append('chose risk over safety')
else:
roadblock()
def spring_alter_supply():
situation_spring = str(input(spring))
if situation_spring == 'X':
short_sleep()
print(defend_alter_supply)
relationships[1] -= down
sit_outbreak()
choices.append('chose defence over all')
elif situation_spring == 'B':
short_sleep()
print(merge_alter_supply)
relationships[1] += up
relationships[0] -= slightly
independence_missouri()
choices.append('chose merging over all')
elif situation_spring == 'A':
short_sleep()
print(negotiate_alter_supply)
relationships[0] -= major
relationships[1] -= major
populated()
choices.append('chose negotiation over all')
else:
roadblock()
def spring_ignore_risk():
situation_spring = str(input(spring))
if situation_spring == 'X':
short_sleep()
print(defend_ignore_risk)
choices.append('chose to defend and died')
elif situation_spring == 'B':
short_sleep()
print(merge_ignore_risk)
relationships[1] += up
relationships[0] += up
independence_missouri()
choices.append('chose merging over all')
elif situation_spring == 'A':
short_sleep()
print(negotiate_ignore_risk)
('chose to negotiate and starved')
else:
roadblock()
def sit_outbreak():
situation_outbreak = str(input(outbreak))
if situation_outbreak == 'X':
short_sleep()
print(outbreak_treat)
relationships[0] -= down
relationships[1] += up
elect()
choices.append('chose aid over resources')
elif(situation_outbreak) == 'B':
short_sleep()
print(outbreak_exile)
relationships[1] -= major
relationships[0] += slightly
elect()
choices.append('chose resources over aid')
else:
roadblock()
def independence_missouri():
situation_independence = str(input(independence))
time.sleep(4)
if situation_independence == 'X':
short_sleep()
print(independence_escape)
relationships[0] += slightly
relationships[1] += major
elect()
choices.append('chose to escape')
elif situation_independence == 'B':
short_sleep()
print(independence_crusade)
relationships[0] += major
relationships[1] += slightly
buff()
choices.append('resorted to violence')
elif situation_independence == 'Y':
short_sleep()
print(new_independence)
relationships[0] += up
relationships[1] += up
buff()
choices.append('chose to talk')
else:
roadblock()
def populated():
situation_population = str(input(population))
if situation_population == 'X':
short_sleep()
print(population_reduce)
relationships[1] -= major
elect()
choices.append('chose survival over morals')
elif situation_population == 'B':
short_sleep()
print(population_desperation)
choices.append('tried to perservere but died')
else:
roadblock()
def elect():
situation_election = str(input(election))
if situation_election == 'X':
short_sleep()
print(election_sabatoge)
relationships[1] -= major
terrorism()
choices.append('chose dirty play over clean')
elif situation_election == 'B':
short_sleep()
print(election_persuade)
relationships[0] -= slightly
execute()
choices.append('chose clean play over dirty')
else:
roadblock()
def buff():
situation_upgrade = str(input(upgrade))
if situation_upgrade == 'X':
short_sleep()
print(army)
choices.append('chose army over all and died')
elif situation_upgrade == 'B':
short_sleep()
print(resiliency)
relationships[0] += up
relationships[1] += up
opportunity()
choices.append('chose resiliency and survived')
elif situation_upgrade == 'Y':
short_sleep()
print(resources)
choices.append('chose resources over all and died')
elif situation_upgrade == 'A':
short_sleep()
print(services)
choices.append('chose services over all and died')
else:
roadblock()
def opportunity():
situation_end_opportunity = str(input(ending_opportunity))
if situation_end_opportunity == 'X':
short_sleep()
print(ending_abandon)
relationships[0] -= hero_traitor
relationships[1] -= hero_traitor
print(the_end)
choices.append('chose your self over all')
print('n')
civil_left()
army_left()
elif situation_end_opportunity == 'B':
short_sleep()
print(ending_perservere)
print(the_end)
choices.append('chose everyone over selfishness')
print('n')
civil_left()
army_left()
else:
roadblock()
def terrorism():
situation_end_terrorism = str(input(ending_terrorism))
if situation_end_terrorism == 'X':
short_sleep()
print(ending_attack)
print(the_end)
choices.append('chose war over retreat')
print('n')
civil_left()
army_left()
elif situation_end_terrorism == 'B':
short_sleep()
print(ending_retreat)
print(the_end)
choices.append('chose retreat over war')
print('n')
civil_left()
army_left()
else:
roadblock
def execute():
situation_end_execute = str(input(ending_execution))
if situation_end_execute== 'X':
short_sleep()
print(ending_death)
relationships[0] += hero_traitor
relationships[1] += hero_traitor
print(the_end)
choices.append('chose words over guns')
print('n')
civil_left()
army_left()
elif situation_end_execute== 'B':
short_sleep()
print(ending_kill)
print(the_end)
choices.append('chose guns over words')
print('n')
civil_left()
army_left()
else:
roadblock()
def civil_left():
if relationships[1] <= -8:
print('You left the ' + civilian + ' feeling ' + vengeful)
if relationships[1] > -8 and relationships[1] < -4:
print('You left the ' + civilian + ' feeling ' + hateful)
if relationships[1] >= -4 and relationships[1] < -1:
print('You left the ' + civilian + ' feeling ' + disappointed)
if relationships[1] >= -1 and relationships[1] < 2:
print('You left the ' + civilian + ' feeling ' + conflicted)
if relationships[1] >= 2 and relationships[1] < 5:
print('You left the ' + civilian + ' feeling ' + satisfied)
if relationships[1] >= 5 and relationships[1] < 8:
print('You left the ' + civilian + ' feeling ' + happy)
if relationships[1] >= 8:
print('You left the ' + civilian + ' feeling ' + prosperous)
def army_left():
if relationships[0] <= -7:
print('You left the ' + army_government + ' feeling ' + vengeful)
if relationships[0] > -7 and relationships[0] < -4:
print('You left the ' + army_government + ' feeling ' + hateful)
if relationships[0] >= -4 and relationships[0] < -2:
print('You left the ' + army_government + ' feeling ' + disappointed)
if relationships[0] >= -2 and relationships[0] < 2:
print('You left the ' + army_government + ' feeling ' + conflicted)
if relationships[0] >= 2 and relationships[0] < 5:
print('You left the ' + army_government + ' feeling ' + satisfied)
if relationships[0] >= 5 and relationships[0] < 7:
print('You left the ' + army_government + ' feeling ' + happy)
if relationships[0] >= 7:
print('You left the ' + army_government + ' feeling ' + prosperous)
print(synopsis)
time.sleep(3)
long_sleep()
story()
def choice():
print('n' + 'You: ')
for decision in choices:
print(' - ' + decision + 'n')
choice()






python beginner game functional-programming adventure-game






share|improve this question









New contributor



Mikey Akamihe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.










share|improve this question









New contributor



Mikey Akamihe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








share|improve this question




share|improve this question








edited 4 hours ago









Vogel612

22k5 gold badges48 silver badges131 bronze badges




22k5 gold badges48 silver badges131 bronze badges






New contributor



Mikey Akamihe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








asked 8 hours ago









Mikey AkamiheMikey Akamihe

263 bronze badges




263 bronze badges




New contributor



Mikey Akamihe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




New contributor




Mikey Akamihe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









  • 2




    $begingroup$
    your question probably will get closed soon because you need to explain a little bit more what's happening in your code. Explain what your game is, what's expected and well... what's your game. Without this information, your title indeed seem a little off, but I'm sure your question is salvageable and you'll get good reviews if you take the time to provide more context.
    $endgroup$
    – IEatBagels
    4 hours ago












  • 2




    $begingroup$
    your question probably will get closed soon because you need to explain a little bit more what's happening in your code. Explain what your game is, what's expected and well... what's your game. Without this information, your title indeed seem a little off, but I'm sure your question is salvageable and you'll get good reviews if you take the time to provide more context.
    $endgroup$
    – IEatBagels
    4 hours ago







2




2




$begingroup$
your question probably will get closed soon because you need to explain a little bit more what's happening in your code. Explain what your game is, what's expected and well... what's your game. Without this information, your title indeed seem a little off, but I'm sure your question is salvageable and you'll get good reviews if you take the time to provide more context.
$endgroup$
– IEatBagels
4 hours ago




$begingroup$
your question probably will get closed soon because you need to explain a little bit more what's happening in your code. Explain what your game is, what's expected and well... what's your game. Without this information, your title indeed seem a little off, but I'm sure your question is salvageable and you'll get good reviews if you take the time to provide more context.
$endgroup$
– IEatBagels
4 hours ago










2 Answers
2






active

oldest

votes


















3












$begingroup$

Style



Before diving in the actual code, some general style considerations first. Python comes with an official Style Guide. The most relevant parts for your code would be the sections on how to structure code using blank lines where appropriate (two blank lines between separate functions and classes, only single blank line within functions and classes) and the recommendations on how to document your functions using documentation strings """enclosed in triple quotes""". The code examples in the following answer will demonstrate both of these style elements.




Note: For convenience, some of the code below uses f-strings, which is a new Python feature introduced with Python 3.6. If you're not yet there, it should be obvious how to transform those pieces to use .format(...) instead.




Don't repeat yourself



Your game has a lot of duplicate text, e.g. where you start to describe the possible changes in the relationship with the other factions. I would propose to collect those templates in a "dumb" class, or maybe a dictionary if you don't like classes, and then put in the factions as you need them. This could be done like so:



class Factions:
"""Class to represent the factions found in the game"""

ARMY = "ARMY & GOVERNMENT"
CIVILIANS = "CIVILIANS"
EVERYBODY = "EVERYBODY"


class RelationshipChanges:
"""Holds templates to decribe changes in relationships"""

HEROISM = ' looks at you as a hero.'
GREAT_INCREASE = 'This greatly improves your relationship with .'
INCREASE = 'This improves your relationship with .'
SLIGHT_INCREASE = 'This slightly improves your relationship with .'

SLIGHT_DECREASE = 'This slightly decreases your relationship with .'
DECREASE = 'This worsens your relationship with .'
GREAT_DECREASE = 'This greatly worsens your relationship with .'
TREASON = ' wants you dead.'


and then do RelationshipChanges.GREAT_INCREASE.format(Factions.CIVILIANS) instead of defining civil_great_increase and all of its companions. The code would generate



This greatly improves your relationship with CIVILIANS.


It might be also a good idea to define a function as a shorthand for this, since it's not quite a pleasure to type.



def change_relation(faction, type_of_change):
"""Create a message to describe the change in the relationship

faction and type_of_change are case insensitive and have to correspond to
class variables of Factions nd RelationshipChanges.
"""
message_template = getattr(RelationshipChanges, type_of_change.upper())
return message_template.format(getattr(Factions, faction.upper()))


With this, change_relation("civilians", "great_increase") would generate the same output as previously seen. The function uses Python's built-in getattr(...) function to programmatically access members of the class by their name. As an example, getattr(Factions, "ARMY") would be the same as Factions.ARMY. Neat, isn't it? If you were even more keen on saving some typing, this function would easily allow to add a "translation" dictionaries as an intermediate. These dict could then map '+++' to RelationshipChanges.GREAT_INCREASE or 'civ' to Factions.CIVILIANS and shorten the previous function call to change_relation('civ', '+++'). I will leave that as an exercise to you.



The relationship levels themselves could be handled similarly.



class RelationshipLevels:
"""Class to represent the player's relationship to other factions"""

VENGEFUL = "VENGEFUL"
HATEFUL = "HATEFUL"
DISAPPOINTED = "DISAPPOINTED"
CONFLICTED = "CONFLICTED/NEUTRAL"
SATISFIED = "SATISFIED"
HAPPY = "HAPPY"
PROPEROUS = "PROPEROUS"

ALL = [VENGEFUL, HATEFUL, DISAPPOINTED, CONFLICTED, SATISFIED, HAPPY, PROSPEROUS]
#^--- this will become handy in a moment


army_left and civil_left are another instance where you tend to repeat the same pieces of code/text over and over again. If you think about those two for a moment, the common pattern will become clear: For a given faction and its relationship score, you want to determine the relationship level. Therefor, you essentially check if the score is below a certain treshold, format the message and print it. A way to generalize that idea would be as follows:



def get_final_standing(relation_score, thresholds):
"""Determine how the faction thinks about the player at the end"""
for threshold, feeling in zip(thresholds, RelationshipLevels.ALL):
if relation_score <= threshold:
return feeling

return RelationshipLevels.ALL[-1]


The function uses zip(...) two iterate over two sequences in parallel, and stops the loop (break) if it has found the appropriate relationship level. It becomes a little bit tricky if you don't want to put an upper limit to the threshold so I decided to implement this in a way that whenever the score is greater than the last threshold you gave, the most positive (i.e. rightmost) level will be returned.
To realize the same funcationality as army_left formerly implemented you would then do



final_standing = get_final_standing(relationships[Factions.CIVILIANS], (-7, -4, -2, 2, 5, 7))
print(f'You left the Factions.ARMY feeling final_standing.')


I leave civil_left as an exercise to you.



All the score increments/decrements should also be bundled somehow. At the moment you have slight, slightly, and relationships[5] to express a slight change in the score in either direction. The same pattern is more or less to be found for normal and major changes, as well as for hero/traitor. That's madness!



One way would be to put them into a class such as we did before with the other constant values. A dict might also be a viable solution. But wait! We have already started somethind related to those changes, haven't we? Well observed. Time to have another look at RelationshipChanges. At the moment this class simply holds the template message for each of the changes. With just one more level of "nesting", we can add the score modifiers as well. As we wrote a function to help us handle those relationship changes, everything will stay smooth.



ULTIMATE_SCORE_CHANGE = 15
MAJOR_SCORE_CHANGE = 2
NORMAL_SCORE_CHANGE = 1
SLIGHT_SCORE_CHANGE = 0.5

class RelationshipChanges:
"""Holds templates and modifiers to decribe changes in the relationships"""

HEORISM =
'message': ' looks at you as a hero.',
'modifier': ULTIMATE_SCORE_CHANGE

GREAT_INCREASE =
'message': 'This greatly improves your relationship with .',
'modifier': MAJOR_SCORE_CHANGE

INCREASE =
'message': 'This improves your relationship with .',
'modifier': NORMAL_SCORE_CHANGE

SLIGHT_INCREASE =
'message': 'This slightly improves your relationship with .',
'modifier': SLIGHT_SCORE_CHANGE


SLIGHT_DECREASE =
'message': 'This slightly decreases your relationship with .',
'modifier': -SLIGHT_SCORE_CHANGE

DECREASE =
'message': 'This worsens your relationship with .',
'modifier': -NORMAL_SCORE_CHANGE

GREAT_DECREASE =
'message': 'This greatly worsens your relationship with .',
'modifier': -MAJOR_SCORE_CHANGE

TREASON =
'message': ' wants you dead.',
'modifier': -ULTIMATE_SCORE_CHANGE



def change_relation(faction, type_of_change):
"""Create a message to describe the change in the relationship

faction and type_of_change are case insensitive and have to correspond to
class variables of Factions nd RelationshipChanges.
"""
change_descr = getattr(RelationshipChanges, type_of_change.upper())
faction_name = getattr(Factions, faction.upper())
return change_descr['modifier'], change_descr['message'].format(faction_name)


Now that those messages and the actual changes to the score are linked more closely, it would be a great moment to remove those change messages from the static game text. A benefit of this would be that if you ever decided to change the effects of an action, you would only have to do this in on place, namely on of the event functions, and not there and somewhere else hidden in all the storyline text. Since those message are IIRC merely appended to the storyline text, the output should not change significantly.



Make it harder to be wrong



Ah, that damn army ... where was their score in relationships again? Was it the first or the second position? Maybe the third?



To avoid situations like this, I would recommend to use a dictionary. This leaves you with something like relationships = "army": 0, "civil": 0 or even relationships = Factions.ARMY: 0, Factions.CIVILIANS: 0. Using relationships[Factions.ARMY] leaves absolutely no doubt what you're trying to do. It will also make it waaaay easier to spot copy and paste errors.



Avoid globals



Global variables are best avoided, since it's harder to see which parts of the code modify them, which leads to all kind of problems. The core object of your game would be relationships and it would be easy to transform all your game functions to accept it as an argument instead of relying on it to be present on a global scope.
The most common approach would be to somehow define a main function which does all the needed initialization stuff, like displaying the synopsis or initializing relationships. relationships is then passed to story which again passes it onwards depending on how the player chooses his actions.



All the game text should wrightfully stay in global variables. For them I would recommend to CAPITALIZE_THEIR_NAMES to make it clear that they are supposed to be used/seen as constant values.



User input handling



At the moment the user input handling is not very robust. Once you enter an invalid command, e.g. by smashing the enter key to long, the program bails out and you have to start all over. This can be very annoying. A better approach would be to ask for invalid input several times and only bail out if a termination character like q is entered or the user did not provide a valid input six times in a row.



Mini demo



With those changes above you are now at a stage wher you can write code like:



modifier, message = change_relation("civilians", "great_increase")
relationships[Factions.CIVILIANS] += modifier
final_standing = get_final_standing(relationships[Factions.CIVILIANS], (-7, -4, -2, 2, 5, 7))
print(message)
print(f'You left the Factions.CIVILIANS feeling final_standing.')





share|improve this answer









$endgroup$




















    2












    $begingroup$

    I'm on my phone, so it's hard to really see this code as a whole and really take the full context of everything. I'm just going to flip through and mention things as I notice them.




    At the top, you have



    vengeful = 'VENGEFUL.'


    And other such lines. This strikes me as odd. The only small benefit I can see is this would help the IDE auto-complete the word. Looking at how you're using it, you're forcing a ton of repetitious code in functions like civil_left. Look at that function, and look at the function below it and think about how much of those functions are the same. Not only are each of lines in the functions nearly identical, both of those functions are basically the same! Whenever you have code that's nearly identical in multiple spots, make the identical code the body of a function, and make the parts that differ parameters to the function.



    How would that look? The only real part that differs is the end of that sentence where you decide what status to display. First, factor out the part that decides the the word to use:



    def describe_status(relation):
    if relation <= -8:
    return "vengeful"

    elif -8 < relation <= -4: # Note, you can chain comparison operators
    return "hateful"

    elif -4 < relation <= -1:
    return "disappointed"

    elif -1 < relation <= 2:
    return "conflicted"

    #... The rest of the statuses


    Then, use that function:



    def civil_left():
    status = describe_status(relationship[1])

    print('You left the', civilian, 'feeling', status)

    def army_left():
    status = describe_status(relationship[0])

    print('You left the', army_government, 'feeling', status)


    Now, the major problem here is that you set the relationship thresholds at different levels for each. You could add a second parameter to describe_status that adds an offset to each condition to remedy that though. Note how much duplication that removed though!




    I'll note that you tagged this as functional-programming, but this is far from what would be considered functional. I'm not going to go into great detail about what all FP means, but basically, if you're following FP principals, you're passing data around instead of mutating objects and carrying out side effects. All of your functions print directly, and none seem to accept any parameters. This is not good, regardless of the paradigm that you're following. You're relying entirely on global state (like relationships), and on operating through side effects (like altering relationships and using print everywhere). If you continue to code like this, you will have a very difficult time creating anything other than small projects, and debugging will increasingly become a nightmare.



    Look at how describe_status operates. Every piece of data that it requires is a parameter (relation), and everything the function does is done via the data that's returned. When functions are just taking and returning data, it becomes much easier to reason about how the code works; and that's an extremely important goal. Code that's hard to understand the operation of is code that's hard to maintain and build on.




    You have a lot of story Strings embedded in the code. I would save these in a file and read them from file as needed. That will make the code less bulky, and will make it so you don't need to alter the code if you want to alter the story.




    I'm going to submit this before it gets closed. Good luck!






    share|improve this answer











    $endgroup$















      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "196"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );






      Mikey Akamihe is a new contributor. Be nice, and check out our Code of Conduct.









      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f222720%2fstory-based-adventure-with-functions-and-relationships%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      3












      $begingroup$

      Style



      Before diving in the actual code, some general style considerations first. Python comes with an official Style Guide. The most relevant parts for your code would be the sections on how to structure code using blank lines where appropriate (two blank lines between separate functions and classes, only single blank line within functions and classes) and the recommendations on how to document your functions using documentation strings """enclosed in triple quotes""". The code examples in the following answer will demonstrate both of these style elements.




      Note: For convenience, some of the code below uses f-strings, which is a new Python feature introduced with Python 3.6. If you're not yet there, it should be obvious how to transform those pieces to use .format(...) instead.




      Don't repeat yourself



      Your game has a lot of duplicate text, e.g. where you start to describe the possible changes in the relationship with the other factions. I would propose to collect those templates in a "dumb" class, or maybe a dictionary if you don't like classes, and then put in the factions as you need them. This could be done like so:



      class Factions:
      """Class to represent the factions found in the game"""

      ARMY = "ARMY & GOVERNMENT"
      CIVILIANS = "CIVILIANS"
      EVERYBODY = "EVERYBODY"


      class RelationshipChanges:
      """Holds templates to decribe changes in relationships"""

      HEROISM = ' looks at you as a hero.'
      GREAT_INCREASE = 'This greatly improves your relationship with .'
      INCREASE = 'This improves your relationship with .'
      SLIGHT_INCREASE = 'This slightly improves your relationship with .'

      SLIGHT_DECREASE = 'This slightly decreases your relationship with .'
      DECREASE = 'This worsens your relationship with .'
      GREAT_DECREASE = 'This greatly worsens your relationship with .'
      TREASON = ' wants you dead.'


      and then do RelationshipChanges.GREAT_INCREASE.format(Factions.CIVILIANS) instead of defining civil_great_increase and all of its companions. The code would generate



      This greatly improves your relationship with CIVILIANS.


      It might be also a good idea to define a function as a shorthand for this, since it's not quite a pleasure to type.



      def change_relation(faction, type_of_change):
      """Create a message to describe the change in the relationship

      faction and type_of_change are case insensitive and have to correspond to
      class variables of Factions nd RelationshipChanges.
      """
      message_template = getattr(RelationshipChanges, type_of_change.upper())
      return message_template.format(getattr(Factions, faction.upper()))


      With this, change_relation("civilians", "great_increase") would generate the same output as previously seen. The function uses Python's built-in getattr(...) function to programmatically access members of the class by their name. As an example, getattr(Factions, "ARMY") would be the same as Factions.ARMY. Neat, isn't it? If you were even more keen on saving some typing, this function would easily allow to add a "translation" dictionaries as an intermediate. These dict could then map '+++' to RelationshipChanges.GREAT_INCREASE or 'civ' to Factions.CIVILIANS and shorten the previous function call to change_relation('civ', '+++'). I will leave that as an exercise to you.



      The relationship levels themselves could be handled similarly.



      class RelationshipLevels:
      """Class to represent the player's relationship to other factions"""

      VENGEFUL = "VENGEFUL"
      HATEFUL = "HATEFUL"
      DISAPPOINTED = "DISAPPOINTED"
      CONFLICTED = "CONFLICTED/NEUTRAL"
      SATISFIED = "SATISFIED"
      HAPPY = "HAPPY"
      PROPEROUS = "PROPEROUS"

      ALL = [VENGEFUL, HATEFUL, DISAPPOINTED, CONFLICTED, SATISFIED, HAPPY, PROSPEROUS]
      #^--- this will become handy in a moment


      army_left and civil_left are another instance where you tend to repeat the same pieces of code/text over and over again. If you think about those two for a moment, the common pattern will become clear: For a given faction and its relationship score, you want to determine the relationship level. Therefor, you essentially check if the score is below a certain treshold, format the message and print it. A way to generalize that idea would be as follows:



      def get_final_standing(relation_score, thresholds):
      """Determine how the faction thinks about the player at the end"""
      for threshold, feeling in zip(thresholds, RelationshipLevels.ALL):
      if relation_score <= threshold:
      return feeling

      return RelationshipLevels.ALL[-1]


      The function uses zip(...) two iterate over two sequences in parallel, and stops the loop (break) if it has found the appropriate relationship level. It becomes a little bit tricky if you don't want to put an upper limit to the threshold so I decided to implement this in a way that whenever the score is greater than the last threshold you gave, the most positive (i.e. rightmost) level will be returned.
      To realize the same funcationality as army_left formerly implemented you would then do



      final_standing = get_final_standing(relationships[Factions.CIVILIANS], (-7, -4, -2, 2, 5, 7))
      print(f'You left the Factions.ARMY feeling final_standing.')


      I leave civil_left as an exercise to you.



      All the score increments/decrements should also be bundled somehow. At the moment you have slight, slightly, and relationships[5] to express a slight change in the score in either direction. The same pattern is more or less to be found for normal and major changes, as well as for hero/traitor. That's madness!



      One way would be to put them into a class such as we did before with the other constant values. A dict might also be a viable solution. But wait! We have already started somethind related to those changes, haven't we? Well observed. Time to have another look at RelationshipChanges. At the moment this class simply holds the template message for each of the changes. With just one more level of "nesting", we can add the score modifiers as well. As we wrote a function to help us handle those relationship changes, everything will stay smooth.



      ULTIMATE_SCORE_CHANGE = 15
      MAJOR_SCORE_CHANGE = 2
      NORMAL_SCORE_CHANGE = 1
      SLIGHT_SCORE_CHANGE = 0.5

      class RelationshipChanges:
      """Holds templates and modifiers to decribe changes in the relationships"""

      HEORISM =
      'message': ' looks at you as a hero.',
      'modifier': ULTIMATE_SCORE_CHANGE

      GREAT_INCREASE =
      'message': 'This greatly improves your relationship with .',
      'modifier': MAJOR_SCORE_CHANGE

      INCREASE =
      'message': 'This improves your relationship with .',
      'modifier': NORMAL_SCORE_CHANGE

      SLIGHT_INCREASE =
      'message': 'This slightly improves your relationship with .',
      'modifier': SLIGHT_SCORE_CHANGE


      SLIGHT_DECREASE =
      'message': 'This slightly decreases your relationship with .',
      'modifier': -SLIGHT_SCORE_CHANGE

      DECREASE =
      'message': 'This worsens your relationship with .',
      'modifier': -NORMAL_SCORE_CHANGE

      GREAT_DECREASE =
      'message': 'This greatly worsens your relationship with .',
      'modifier': -MAJOR_SCORE_CHANGE

      TREASON =
      'message': ' wants you dead.',
      'modifier': -ULTIMATE_SCORE_CHANGE



      def change_relation(faction, type_of_change):
      """Create a message to describe the change in the relationship

      faction and type_of_change are case insensitive and have to correspond to
      class variables of Factions nd RelationshipChanges.
      """
      change_descr = getattr(RelationshipChanges, type_of_change.upper())
      faction_name = getattr(Factions, faction.upper())
      return change_descr['modifier'], change_descr['message'].format(faction_name)


      Now that those messages and the actual changes to the score are linked more closely, it would be a great moment to remove those change messages from the static game text. A benefit of this would be that if you ever decided to change the effects of an action, you would only have to do this in on place, namely on of the event functions, and not there and somewhere else hidden in all the storyline text. Since those message are IIRC merely appended to the storyline text, the output should not change significantly.



      Make it harder to be wrong



      Ah, that damn army ... where was their score in relationships again? Was it the first or the second position? Maybe the third?



      To avoid situations like this, I would recommend to use a dictionary. This leaves you with something like relationships = "army": 0, "civil": 0 or even relationships = Factions.ARMY: 0, Factions.CIVILIANS: 0. Using relationships[Factions.ARMY] leaves absolutely no doubt what you're trying to do. It will also make it waaaay easier to spot copy and paste errors.



      Avoid globals



      Global variables are best avoided, since it's harder to see which parts of the code modify them, which leads to all kind of problems. The core object of your game would be relationships and it would be easy to transform all your game functions to accept it as an argument instead of relying on it to be present on a global scope.
      The most common approach would be to somehow define a main function which does all the needed initialization stuff, like displaying the synopsis or initializing relationships. relationships is then passed to story which again passes it onwards depending on how the player chooses his actions.



      All the game text should wrightfully stay in global variables. For them I would recommend to CAPITALIZE_THEIR_NAMES to make it clear that they are supposed to be used/seen as constant values.



      User input handling



      At the moment the user input handling is not very robust. Once you enter an invalid command, e.g. by smashing the enter key to long, the program bails out and you have to start all over. This can be very annoying. A better approach would be to ask for invalid input several times and only bail out if a termination character like q is entered or the user did not provide a valid input six times in a row.



      Mini demo



      With those changes above you are now at a stage wher you can write code like:



      modifier, message = change_relation("civilians", "great_increase")
      relationships[Factions.CIVILIANS] += modifier
      final_standing = get_final_standing(relationships[Factions.CIVILIANS], (-7, -4, -2, 2, 5, 7))
      print(message)
      print(f'You left the Factions.CIVILIANS feeling final_standing.')





      share|improve this answer









      $endgroup$

















        3












        $begingroup$

        Style



        Before diving in the actual code, some general style considerations first. Python comes with an official Style Guide. The most relevant parts for your code would be the sections on how to structure code using blank lines where appropriate (two blank lines between separate functions and classes, only single blank line within functions and classes) and the recommendations on how to document your functions using documentation strings """enclosed in triple quotes""". The code examples in the following answer will demonstrate both of these style elements.




        Note: For convenience, some of the code below uses f-strings, which is a new Python feature introduced with Python 3.6. If you're not yet there, it should be obvious how to transform those pieces to use .format(...) instead.




        Don't repeat yourself



        Your game has a lot of duplicate text, e.g. where you start to describe the possible changes in the relationship with the other factions. I would propose to collect those templates in a "dumb" class, or maybe a dictionary if you don't like classes, and then put in the factions as you need them. This could be done like so:



        class Factions:
        """Class to represent the factions found in the game"""

        ARMY = "ARMY & GOVERNMENT"
        CIVILIANS = "CIVILIANS"
        EVERYBODY = "EVERYBODY"


        class RelationshipChanges:
        """Holds templates to decribe changes in relationships"""

        HEROISM = ' looks at you as a hero.'
        GREAT_INCREASE = 'This greatly improves your relationship with .'
        INCREASE = 'This improves your relationship with .'
        SLIGHT_INCREASE = 'This slightly improves your relationship with .'

        SLIGHT_DECREASE = 'This slightly decreases your relationship with .'
        DECREASE = 'This worsens your relationship with .'
        GREAT_DECREASE = 'This greatly worsens your relationship with .'
        TREASON = ' wants you dead.'


        and then do RelationshipChanges.GREAT_INCREASE.format(Factions.CIVILIANS) instead of defining civil_great_increase and all of its companions. The code would generate



        This greatly improves your relationship with CIVILIANS.


        It might be also a good idea to define a function as a shorthand for this, since it's not quite a pleasure to type.



        def change_relation(faction, type_of_change):
        """Create a message to describe the change in the relationship

        faction and type_of_change are case insensitive and have to correspond to
        class variables of Factions nd RelationshipChanges.
        """
        message_template = getattr(RelationshipChanges, type_of_change.upper())
        return message_template.format(getattr(Factions, faction.upper()))


        With this, change_relation("civilians", "great_increase") would generate the same output as previously seen. The function uses Python's built-in getattr(...) function to programmatically access members of the class by their name. As an example, getattr(Factions, "ARMY") would be the same as Factions.ARMY. Neat, isn't it? If you were even more keen on saving some typing, this function would easily allow to add a "translation" dictionaries as an intermediate. These dict could then map '+++' to RelationshipChanges.GREAT_INCREASE or 'civ' to Factions.CIVILIANS and shorten the previous function call to change_relation('civ', '+++'). I will leave that as an exercise to you.



        The relationship levels themselves could be handled similarly.



        class RelationshipLevels:
        """Class to represent the player's relationship to other factions"""

        VENGEFUL = "VENGEFUL"
        HATEFUL = "HATEFUL"
        DISAPPOINTED = "DISAPPOINTED"
        CONFLICTED = "CONFLICTED/NEUTRAL"
        SATISFIED = "SATISFIED"
        HAPPY = "HAPPY"
        PROPEROUS = "PROPEROUS"

        ALL = [VENGEFUL, HATEFUL, DISAPPOINTED, CONFLICTED, SATISFIED, HAPPY, PROSPEROUS]
        #^--- this will become handy in a moment


        army_left and civil_left are another instance where you tend to repeat the same pieces of code/text over and over again. If you think about those two for a moment, the common pattern will become clear: For a given faction and its relationship score, you want to determine the relationship level. Therefor, you essentially check if the score is below a certain treshold, format the message and print it. A way to generalize that idea would be as follows:



        def get_final_standing(relation_score, thresholds):
        """Determine how the faction thinks about the player at the end"""
        for threshold, feeling in zip(thresholds, RelationshipLevels.ALL):
        if relation_score <= threshold:
        return feeling

        return RelationshipLevels.ALL[-1]


        The function uses zip(...) two iterate over two sequences in parallel, and stops the loop (break) if it has found the appropriate relationship level. It becomes a little bit tricky if you don't want to put an upper limit to the threshold so I decided to implement this in a way that whenever the score is greater than the last threshold you gave, the most positive (i.e. rightmost) level will be returned.
        To realize the same funcationality as army_left formerly implemented you would then do



        final_standing = get_final_standing(relationships[Factions.CIVILIANS], (-7, -4, -2, 2, 5, 7))
        print(f'You left the Factions.ARMY feeling final_standing.')


        I leave civil_left as an exercise to you.



        All the score increments/decrements should also be bundled somehow. At the moment you have slight, slightly, and relationships[5] to express a slight change in the score in either direction. The same pattern is more or less to be found for normal and major changes, as well as for hero/traitor. That's madness!



        One way would be to put them into a class such as we did before with the other constant values. A dict might also be a viable solution. But wait! We have already started somethind related to those changes, haven't we? Well observed. Time to have another look at RelationshipChanges. At the moment this class simply holds the template message for each of the changes. With just one more level of "nesting", we can add the score modifiers as well. As we wrote a function to help us handle those relationship changes, everything will stay smooth.



        ULTIMATE_SCORE_CHANGE = 15
        MAJOR_SCORE_CHANGE = 2
        NORMAL_SCORE_CHANGE = 1
        SLIGHT_SCORE_CHANGE = 0.5

        class RelationshipChanges:
        """Holds templates and modifiers to decribe changes in the relationships"""

        HEORISM =
        'message': ' looks at you as a hero.',
        'modifier': ULTIMATE_SCORE_CHANGE

        GREAT_INCREASE =
        'message': 'This greatly improves your relationship with .',
        'modifier': MAJOR_SCORE_CHANGE

        INCREASE =
        'message': 'This improves your relationship with .',
        'modifier': NORMAL_SCORE_CHANGE

        SLIGHT_INCREASE =
        'message': 'This slightly improves your relationship with .',
        'modifier': SLIGHT_SCORE_CHANGE


        SLIGHT_DECREASE =
        'message': 'This slightly decreases your relationship with .',
        'modifier': -SLIGHT_SCORE_CHANGE

        DECREASE =
        'message': 'This worsens your relationship with .',
        'modifier': -NORMAL_SCORE_CHANGE

        GREAT_DECREASE =
        'message': 'This greatly worsens your relationship with .',
        'modifier': -MAJOR_SCORE_CHANGE

        TREASON =
        'message': ' wants you dead.',
        'modifier': -ULTIMATE_SCORE_CHANGE



        def change_relation(faction, type_of_change):
        """Create a message to describe the change in the relationship

        faction and type_of_change are case insensitive and have to correspond to
        class variables of Factions nd RelationshipChanges.
        """
        change_descr = getattr(RelationshipChanges, type_of_change.upper())
        faction_name = getattr(Factions, faction.upper())
        return change_descr['modifier'], change_descr['message'].format(faction_name)


        Now that those messages and the actual changes to the score are linked more closely, it would be a great moment to remove those change messages from the static game text. A benefit of this would be that if you ever decided to change the effects of an action, you would only have to do this in on place, namely on of the event functions, and not there and somewhere else hidden in all the storyline text. Since those message are IIRC merely appended to the storyline text, the output should not change significantly.



        Make it harder to be wrong



        Ah, that damn army ... where was their score in relationships again? Was it the first or the second position? Maybe the third?



        To avoid situations like this, I would recommend to use a dictionary. This leaves you with something like relationships = "army": 0, "civil": 0 or even relationships = Factions.ARMY: 0, Factions.CIVILIANS: 0. Using relationships[Factions.ARMY] leaves absolutely no doubt what you're trying to do. It will also make it waaaay easier to spot copy and paste errors.



        Avoid globals



        Global variables are best avoided, since it's harder to see which parts of the code modify them, which leads to all kind of problems. The core object of your game would be relationships and it would be easy to transform all your game functions to accept it as an argument instead of relying on it to be present on a global scope.
        The most common approach would be to somehow define a main function which does all the needed initialization stuff, like displaying the synopsis or initializing relationships. relationships is then passed to story which again passes it onwards depending on how the player chooses his actions.



        All the game text should wrightfully stay in global variables. For them I would recommend to CAPITALIZE_THEIR_NAMES to make it clear that they are supposed to be used/seen as constant values.



        User input handling



        At the moment the user input handling is not very robust. Once you enter an invalid command, e.g. by smashing the enter key to long, the program bails out and you have to start all over. This can be very annoying. A better approach would be to ask for invalid input several times and only bail out if a termination character like q is entered or the user did not provide a valid input six times in a row.



        Mini demo



        With those changes above you are now at a stage wher you can write code like:



        modifier, message = change_relation("civilians", "great_increase")
        relationships[Factions.CIVILIANS] += modifier
        final_standing = get_final_standing(relationships[Factions.CIVILIANS], (-7, -4, -2, 2, 5, 7))
        print(message)
        print(f'You left the Factions.CIVILIANS feeling final_standing.')





        share|improve this answer









        $endgroup$















          3












          3








          3





          $begingroup$

          Style



          Before diving in the actual code, some general style considerations first. Python comes with an official Style Guide. The most relevant parts for your code would be the sections on how to structure code using blank lines where appropriate (two blank lines between separate functions and classes, only single blank line within functions and classes) and the recommendations on how to document your functions using documentation strings """enclosed in triple quotes""". The code examples in the following answer will demonstrate both of these style elements.




          Note: For convenience, some of the code below uses f-strings, which is a new Python feature introduced with Python 3.6. If you're not yet there, it should be obvious how to transform those pieces to use .format(...) instead.




          Don't repeat yourself



          Your game has a lot of duplicate text, e.g. where you start to describe the possible changes in the relationship with the other factions. I would propose to collect those templates in a "dumb" class, or maybe a dictionary if you don't like classes, and then put in the factions as you need them. This could be done like so:



          class Factions:
          """Class to represent the factions found in the game"""

          ARMY = "ARMY & GOVERNMENT"
          CIVILIANS = "CIVILIANS"
          EVERYBODY = "EVERYBODY"


          class RelationshipChanges:
          """Holds templates to decribe changes in relationships"""

          HEROISM = ' looks at you as a hero.'
          GREAT_INCREASE = 'This greatly improves your relationship with .'
          INCREASE = 'This improves your relationship with .'
          SLIGHT_INCREASE = 'This slightly improves your relationship with .'

          SLIGHT_DECREASE = 'This slightly decreases your relationship with .'
          DECREASE = 'This worsens your relationship with .'
          GREAT_DECREASE = 'This greatly worsens your relationship with .'
          TREASON = ' wants you dead.'


          and then do RelationshipChanges.GREAT_INCREASE.format(Factions.CIVILIANS) instead of defining civil_great_increase and all of its companions. The code would generate



          This greatly improves your relationship with CIVILIANS.


          It might be also a good idea to define a function as a shorthand for this, since it's not quite a pleasure to type.



          def change_relation(faction, type_of_change):
          """Create a message to describe the change in the relationship

          faction and type_of_change are case insensitive and have to correspond to
          class variables of Factions nd RelationshipChanges.
          """
          message_template = getattr(RelationshipChanges, type_of_change.upper())
          return message_template.format(getattr(Factions, faction.upper()))


          With this, change_relation("civilians", "great_increase") would generate the same output as previously seen. The function uses Python's built-in getattr(...) function to programmatically access members of the class by their name. As an example, getattr(Factions, "ARMY") would be the same as Factions.ARMY. Neat, isn't it? If you were even more keen on saving some typing, this function would easily allow to add a "translation" dictionaries as an intermediate. These dict could then map '+++' to RelationshipChanges.GREAT_INCREASE or 'civ' to Factions.CIVILIANS and shorten the previous function call to change_relation('civ', '+++'). I will leave that as an exercise to you.



          The relationship levels themselves could be handled similarly.



          class RelationshipLevels:
          """Class to represent the player's relationship to other factions"""

          VENGEFUL = "VENGEFUL"
          HATEFUL = "HATEFUL"
          DISAPPOINTED = "DISAPPOINTED"
          CONFLICTED = "CONFLICTED/NEUTRAL"
          SATISFIED = "SATISFIED"
          HAPPY = "HAPPY"
          PROPEROUS = "PROPEROUS"

          ALL = [VENGEFUL, HATEFUL, DISAPPOINTED, CONFLICTED, SATISFIED, HAPPY, PROSPEROUS]
          #^--- this will become handy in a moment


          army_left and civil_left are another instance where you tend to repeat the same pieces of code/text over and over again. If you think about those two for a moment, the common pattern will become clear: For a given faction and its relationship score, you want to determine the relationship level. Therefor, you essentially check if the score is below a certain treshold, format the message and print it. A way to generalize that idea would be as follows:



          def get_final_standing(relation_score, thresholds):
          """Determine how the faction thinks about the player at the end"""
          for threshold, feeling in zip(thresholds, RelationshipLevels.ALL):
          if relation_score <= threshold:
          return feeling

          return RelationshipLevels.ALL[-1]


          The function uses zip(...) two iterate over two sequences in parallel, and stops the loop (break) if it has found the appropriate relationship level. It becomes a little bit tricky if you don't want to put an upper limit to the threshold so I decided to implement this in a way that whenever the score is greater than the last threshold you gave, the most positive (i.e. rightmost) level will be returned.
          To realize the same funcationality as army_left formerly implemented you would then do



          final_standing = get_final_standing(relationships[Factions.CIVILIANS], (-7, -4, -2, 2, 5, 7))
          print(f'You left the Factions.ARMY feeling final_standing.')


          I leave civil_left as an exercise to you.



          All the score increments/decrements should also be bundled somehow. At the moment you have slight, slightly, and relationships[5] to express a slight change in the score in either direction. The same pattern is more or less to be found for normal and major changes, as well as for hero/traitor. That's madness!



          One way would be to put them into a class such as we did before with the other constant values. A dict might also be a viable solution. But wait! We have already started somethind related to those changes, haven't we? Well observed. Time to have another look at RelationshipChanges. At the moment this class simply holds the template message for each of the changes. With just one more level of "nesting", we can add the score modifiers as well. As we wrote a function to help us handle those relationship changes, everything will stay smooth.



          ULTIMATE_SCORE_CHANGE = 15
          MAJOR_SCORE_CHANGE = 2
          NORMAL_SCORE_CHANGE = 1
          SLIGHT_SCORE_CHANGE = 0.5

          class RelationshipChanges:
          """Holds templates and modifiers to decribe changes in the relationships"""

          HEORISM =
          'message': ' looks at you as a hero.',
          'modifier': ULTIMATE_SCORE_CHANGE

          GREAT_INCREASE =
          'message': 'This greatly improves your relationship with .',
          'modifier': MAJOR_SCORE_CHANGE

          INCREASE =
          'message': 'This improves your relationship with .',
          'modifier': NORMAL_SCORE_CHANGE

          SLIGHT_INCREASE =
          'message': 'This slightly improves your relationship with .',
          'modifier': SLIGHT_SCORE_CHANGE


          SLIGHT_DECREASE =
          'message': 'This slightly decreases your relationship with .',
          'modifier': -SLIGHT_SCORE_CHANGE

          DECREASE =
          'message': 'This worsens your relationship with .',
          'modifier': -NORMAL_SCORE_CHANGE

          GREAT_DECREASE =
          'message': 'This greatly worsens your relationship with .',
          'modifier': -MAJOR_SCORE_CHANGE

          TREASON =
          'message': ' wants you dead.',
          'modifier': -ULTIMATE_SCORE_CHANGE



          def change_relation(faction, type_of_change):
          """Create a message to describe the change in the relationship

          faction and type_of_change are case insensitive and have to correspond to
          class variables of Factions nd RelationshipChanges.
          """
          change_descr = getattr(RelationshipChanges, type_of_change.upper())
          faction_name = getattr(Factions, faction.upper())
          return change_descr['modifier'], change_descr['message'].format(faction_name)


          Now that those messages and the actual changes to the score are linked more closely, it would be a great moment to remove those change messages from the static game text. A benefit of this would be that if you ever decided to change the effects of an action, you would only have to do this in on place, namely on of the event functions, and not there and somewhere else hidden in all the storyline text. Since those message are IIRC merely appended to the storyline text, the output should not change significantly.



          Make it harder to be wrong



          Ah, that damn army ... where was their score in relationships again? Was it the first or the second position? Maybe the third?



          To avoid situations like this, I would recommend to use a dictionary. This leaves you with something like relationships = "army": 0, "civil": 0 or even relationships = Factions.ARMY: 0, Factions.CIVILIANS: 0. Using relationships[Factions.ARMY] leaves absolutely no doubt what you're trying to do. It will also make it waaaay easier to spot copy and paste errors.



          Avoid globals



          Global variables are best avoided, since it's harder to see which parts of the code modify them, which leads to all kind of problems. The core object of your game would be relationships and it would be easy to transform all your game functions to accept it as an argument instead of relying on it to be present on a global scope.
          The most common approach would be to somehow define a main function which does all the needed initialization stuff, like displaying the synopsis or initializing relationships. relationships is then passed to story which again passes it onwards depending on how the player chooses his actions.



          All the game text should wrightfully stay in global variables. For them I would recommend to CAPITALIZE_THEIR_NAMES to make it clear that they are supposed to be used/seen as constant values.



          User input handling



          At the moment the user input handling is not very robust. Once you enter an invalid command, e.g. by smashing the enter key to long, the program bails out and you have to start all over. This can be very annoying. A better approach would be to ask for invalid input several times and only bail out if a termination character like q is entered or the user did not provide a valid input six times in a row.



          Mini demo



          With those changes above you are now at a stage wher you can write code like:



          modifier, message = change_relation("civilians", "great_increase")
          relationships[Factions.CIVILIANS] += modifier
          final_standing = get_final_standing(relationships[Factions.CIVILIANS], (-7, -4, -2, 2, 5, 7))
          print(message)
          print(f'You left the Factions.CIVILIANS feeling final_standing.')





          share|improve this answer









          $endgroup$



          Style



          Before diving in the actual code, some general style considerations first. Python comes with an official Style Guide. The most relevant parts for your code would be the sections on how to structure code using blank lines where appropriate (two blank lines between separate functions and classes, only single blank line within functions and classes) and the recommendations on how to document your functions using documentation strings """enclosed in triple quotes""". The code examples in the following answer will demonstrate both of these style elements.




          Note: For convenience, some of the code below uses f-strings, which is a new Python feature introduced with Python 3.6. If you're not yet there, it should be obvious how to transform those pieces to use .format(...) instead.




          Don't repeat yourself



          Your game has a lot of duplicate text, e.g. where you start to describe the possible changes in the relationship with the other factions. I would propose to collect those templates in a "dumb" class, or maybe a dictionary if you don't like classes, and then put in the factions as you need them. This could be done like so:



          class Factions:
          """Class to represent the factions found in the game"""

          ARMY = "ARMY & GOVERNMENT"
          CIVILIANS = "CIVILIANS"
          EVERYBODY = "EVERYBODY"


          class RelationshipChanges:
          """Holds templates to decribe changes in relationships"""

          HEROISM = ' looks at you as a hero.'
          GREAT_INCREASE = 'This greatly improves your relationship with .'
          INCREASE = 'This improves your relationship with .'
          SLIGHT_INCREASE = 'This slightly improves your relationship with .'

          SLIGHT_DECREASE = 'This slightly decreases your relationship with .'
          DECREASE = 'This worsens your relationship with .'
          GREAT_DECREASE = 'This greatly worsens your relationship with .'
          TREASON = ' wants you dead.'


          and then do RelationshipChanges.GREAT_INCREASE.format(Factions.CIVILIANS) instead of defining civil_great_increase and all of its companions. The code would generate



          This greatly improves your relationship with CIVILIANS.


          It might be also a good idea to define a function as a shorthand for this, since it's not quite a pleasure to type.



          def change_relation(faction, type_of_change):
          """Create a message to describe the change in the relationship

          faction and type_of_change are case insensitive and have to correspond to
          class variables of Factions nd RelationshipChanges.
          """
          message_template = getattr(RelationshipChanges, type_of_change.upper())
          return message_template.format(getattr(Factions, faction.upper()))


          With this, change_relation("civilians", "great_increase") would generate the same output as previously seen. The function uses Python's built-in getattr(...) function to programmatically access members of the class by their name. As an example, getattr(Factions, "ARMY") would be the same as Factions.ARMY. Neat, isn't it? If you were even more keen on saving some typing, this function would easily allow to add a "translation" dictionaries as an intermediate. These dict could then map '+++' to RelationshipChanges.GREAT_INCREASE or 'civ' to Factions.CIVILIANS and shorten the previous function call to change_relation('civ', '+++'). I will leave that as an exercise to you.



          The relationship levels themselves could be handled similarly.



          class RelationshipLevels:
          """Class to represent the player's relationship to other factions"""

          VENGEFUL = "VENGEFUL"
          HATEFUL = "HATEFUL"
          DISAPPOINTED = "DISAPPOINTED"
          CONFLICTED = "CONFLICTED/NEUTRAL"
          SATISFIED = "SATISFIED"
          HAPPY = "HAPPY"
          PROPEROUS = "PROPEROUS"

          ALL = [VENGEFUL, HATEFUL, DISAPPOINTED, CONFLICTED, SATISFIED, HAPPY, PROSPEROUS]
          #^--- this will become handy in a moment


          army_left and civil_left are another instance where you tend to repeat the same pieces of code/text over and over again. If you think about those two for a moment, the common pattern will become clear: For a given faction and its relationship score, you want to determine the relationship level. Therefor, you essentially check if the score is below a certain treshold, format the message and print it. A way to generalize that idea would be as follows:



          def get_final_standing(relation_score, thresholds):
          """Determine how the faction thinks about the player at the end"""
          for threshold, feeling in zip(thresholds, RelationshipLevels.ALL):
          if relation_score <= threshold:
          return feeling

          return RelationshipLevels.ALL[-1]


          The function uses zip(...) two iterate over two sequences in parallel, and stops the loop (break) if it has found the appropriate relationship level. It becomes a little bit tricky if you don't want to put an upper limit to the threshold so I decided to implement this in a way that whenever the score is greater than the last threshold you gave, the most positive (i.e. rightmost) level will be returned.
          To realize the same funcationality as army_left formerly implemented you would then do



          final_standing = get_final_standing(relationships[Factions.CIVILIANS], (-7, -4, -2, 2, 5, 7))
          print(f'You left the Factions.ARMY feeling final_standing.')


          I leave civil_left as an exercise to you.



          All the score increments/decrements should also be bundled somehow. At the moment you have slight, slightly, and relationships[5] to express a slight change in the score in either direction. The same pattern is more or less to be found for normal and major changes, as well as for hero/traitor. That's madness!



          One way would be to put them into a class such as we did before with the other constant values. A dict might also be a viable solution. But wait! We have already started somethind related to those changes, haven't we? Well observed. Time to have another look at RelationshipChanges. At the moment this class simply holds the template message for each of the changes. With just one more level of "nesting", we can add the score modifiers as well. As we wrote a function to help us handle those relationship changes, everything will stay smooth.



          ULTIMATE_SCORE_CHANGE = 15
          MAJOR_SCORE_CHANGE = 2
          NORMAL_SCORE_CHANGE = 1
          SLIGHT_SCORE_CHANGE = 0.5

          class RelationshipChanges:
          """Holds templates and modifiers to decribe changes in the relationships"""

          HEORISM =
          'message': ' looks at you as a hero.',
          'modifier': ULTIMATE_SCORE_CHANGE

          GREAT_INCREASE =
          'message': 'This greatly improves your relationship with .',
          'modifier': MAJOR_SCORE_CHANGE

          INCREASE =
          'message': 'This improves your relationship with .',
          'modifier': NORMAL_SCORE_CHANGE

          SLIGHT_INCREASE =
          'message': 'This slightly improves your relationship with .',
          'modifier': SLIGHT_SCORE_CHANGE


          SLIGHT_DECREASE =
          'message': 'This slightly decreases your relationship with .',
          'modifier': -SLIGHT_SCORE_CHANGE

          DECREASE =
          'message': 'This worsens your relationship with .',
          'modifier': -NORMAL_SCORE_CHANGE

          GREAT_DECREASE =
          'message': 'This greatly worsens your relationship with .',
          'modifier': -MAJOR_SCORE_CHANGE

          TREASON =
          'message': ' wants you dead.',
          'modifier': -ULTIMATE_SCORE_CHANGE



          def change_relation(faction, type_of_change):
          """Create a message to describe the change in the relationship

          faction and type_of_change are case insensitive and have to correspond to
          class variables of Factions nd RelationshipChanges.
          """
          change_descr = getattr(RelationshipChanges, type_of_change.upper())
          faction_name = getattr(Factions, faction.upper())
          return change_descr['modifier'], change_descr['message'].format(faction_name)


          Now that those messages and the actual changes to the score are linked more closely, it would be a great moment to remove those change messages from the static game text. A benefit of this would be that if you ever decided to change the effects of an action, you would only have to do this in on place, namely on of the event functions, and not there and somewhere else hidden in all the storyline text. Since those message are IIRC merely appended to the storyline text, the output should not change significantly.



          Make it harder to be wrong



          Ah, that damn army ... where was their score in relationships again? Was it the first or the second position? Maybe the third?



          To avoid situations like this, I would recommend to use a dictionary. This leaves you with something like relationships = "army": 0, "civil": 0 or even relationships = Factions.ARMY: 0, Factions.CIVILIANS: 0. Using relationships[Factions.ARMY] leaves absolutely no doubt what you're trying to do. It will also make it waaaay easier to spot copy and paste errors.



          Avoid globals



          Global variables are best avoided, since it's harder to see which parts of the code modify them, which leads to all kind of problems. The core object of your game would be relationships and it would be easy to transform all your game functions to accept it as an argument instead of relying on it to be present on a global scope.
          The most common approach would be to somehow define a main function which does all the needed initialization stuff, like displaying the synopsis or initializing relationships. relationships is then passed to story which again passes it onwards depending on how the player chooses his actions.



          All the game text should wrightfully stay in global variables. For them I would recommend to CAPITALIZE_THEIR_NAMES to make it clear that they are supposed to be used/seen as constant values.



          User input handling



          At the moment the user input handling is not very robust. Once you enter an invalid command, e.g. by smashing the enter key to long, the program bails out and you have to start all over. This can be very annoying. A better approach would be to ask for invalid input several times and only bail out if a termination character like q is entered or the user did not provide a valid input six times in a row.



          Mini demo



          With those changes above you are now at a stage wher you can write code like:



          modifier, message = change_relation("civilians", "great_increase")
          relationships[Factions.CIVILIANS] += modifier
          final_standing = get_final_standing(relationships[Factions.CIVILIANS], (-7, -4, -2, 2, 5, 7))
          print(message)
          print(f'You left the Factions.CIVILIANS feeling final_standing.')






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 1 hour ago









          AlexVAlexV

          2,7659 silver badges31 bronze badges




          2,7659 silver badges31 bronze badges























              2












              $begingroup$

              I'm on my phone, so it's hard to really see this code as a whole and really take the full context of everything. I'm just going to flip through and mention things as I notice them.




              At the top, you have



              vengeful = 'VENGEFUL.'


              And other such lines. This strikes me as odd. The only small benefit I can see is this would help the IDE auto-complete the word. Looking at how you're using it, you're forcing a ton of repetitious code in functions like civil_left. Look at that function, and look at the function below it and think about how much of those functions are the same. Not only are each of lines in the functions nearly identical, both of those functions are basically the same! Whenever you have code that's nearly identical in multiple spots, make the identical code the body of a function, and make the parts that differ parameters to the function.



              How would that look? The only real part that differs is the end of that sentence where you decide what status to display. First, factor out the part that decides the the word to use:



              def describe_status(relation):
              if relation <= -8:
              return "vengeful"

              elif -8 < relation <= -4: # Note, you can chain comparison operators
              return "hateful"

              elif -4 < relation <= -1:
              return "disappointed"

              elif -1 < relation <= 2:
              return "conflicted"

              #... The rest of the statuses


              Then, use that function:



              def civil_left():
              status = describe_status(relationship[1])

              print('You left the', civilian, 'feeling', status)

              def army_left():
              status = describe_status(relationship[0])

              print('You left the', army_government, 'feeling', status)


              Now, the major problem here is that you set the relationship thresholds at different levels for each. You could add a second parameter to describe_status that adds an offset to each condition to remedy that though. Note how much duplication that removed though!




              I'll note that you tagged this as functional-programming, but this is far from what would be considered functional. I'm not going to go into great detail about what all FP means, but basically, if you're following FP principals, you're passing data around instead of mutating objects and carrying out side effects. All of your functions print directly, and none seem to accept any parameters. This is not good, regardless of the paradigm that you're following. You're relying entirely on global state (like relationships), and on operating through side effects (like altering relationships and using print everywhere). If you continue to code like this, you will have a very difficult time creating anything other than small projects, and debugging will increasingly become a nightmare.



              Look at how describe_status operates. Every piece of data that it requires is a parameter (relation), and everything the function does is done via the data that's returned. When functions are just taking and returning data, it becomes much easier to reason about how the code works; and that's an extremely important goal. Code that's hard to understand the operation of is code that's hard to maintain and build on.




              You have a lot of story Strings embedded in the code. I would save these in a file and read them from file as needed. That will make the code less bulky, and will make it so you don't need to alter the code if you want to alter the story.




              I'm going to submit this before it gets closed. Good luck!






              share|improve this answer











              $endgroup$

















                2












                $begingroup$

                I'm on my phone, so it's hard to really see this code as a whole and really take the full context of everything. I'm just going to flip through and mention things as I notice them.




                At the top, you have



                vengeful = 'VENGEFUL.'


                And other such lines. This strikes me as odd. The only small benefit I can see is this would help the IDE auto-complete the word. Looking at how you're using it, you're forcing a ton of repetitious code in functions like civil_left. Look at that function, and look at the function below it and think about how much of those functions are the same. Not only are each of lines in the functions nearly identical, both of those functions are basically the same! Whenever you have code that's nearly identical in multiple spots, make the identical code the body of a function, and make the parts that differ parameters to the function.



                How would that look? The only real part that differs is the end of that sentence where you decide what status to display. First, factor out the part that decides the the word to use:



                def describe_status(relation):
                if relation <= -8:
                return "vengeful"

                elif -8 < relation <= -4: # Note, you can chain comparison operators
                return "hateful"

                elif -4 < relation <= -1:
                return "disappointed"

                elif -1 < relation <= 2:
                return "conflicted"

                #... The rest of the statuses


                Then, use that function:



                def civil_left():
                status = describe_status(relationship[1])

                print('You left the', civilian, 'feeling', status)

                def army_left():
                status = describe_status(relationship[0])

                print('You left the', army_government, 'feeling', status)


                Now, the major problem here is that you set the relationship thresholds at different levels for each. You could add a second parameter to describe_status that adds an offset to each condition to remedy that though. Note how much duplication that removed though!




                I'll note that you tagged this as functional-programming, but this is far from what would be considered functional. I'm not going to go into great detail about what all FP means, but basically, if you're following FP principals, you're passing data around instead of mutating objects and carrying out side effects. All of your functions print directly, and none seem to accept any parameters. This is not good, regardless of the paradigm that you're following. You're relying entirely on global state (like relationships), and on operating through side effects (like altering relationships and using print everywhere). If you continue to code like this, you will have a very difficult time creating anything other than small projects, and debugging will increasingly become a nightmare.



                Look at how describe_status operates. Every piece of data that it requires is a parameter (relation), and everything the function does is done via the data that's returned. When functions are just taking and returning data, it becomes much easier to reason about how the code works; and that's an extremely important goal. Code that's hard to understand the operation of is code that's hard to maintain and build on.




                You have a lot of story Strings embedded in the code. I would save these in a file and read them from file as needed. That will make the code less bulky, and will make it so you don't need to alter the code if you want to alter the story.




                I'm going to submit this before it gets closed. Good luck!






                share|improve this answer











                $endgroup$















                  2












                  2








                  2





                  $begingroup$

                  I'm on my phone, so it's hard to really see this code as a whole and really take the full context of everything. I'm just going to flip through and mention things as I notice them.




                  At the top, you have



                  vengeful = 'VENGEFUL.'


                  And other such lines. This strikes me as odd. The only small benefit I can see is this would help the IDE auto-complete the word. Looking at how you're using it, you're forcing a ton of repetitious code in functions like civil_left. Look at that function, and look at the function below it and think about how much of those functions are the same. Not only are each of lines in the functions nearly identical, both of those functions are basically the same! Whenever you have code that's nearly identical in multiple spots, make the identical code the body of a function, and make the parts that differ parameters to the function.



                  How would that look? The only real part that differs is the end of that sentence where you decide what status to display. First, factor out the part that decides the the word to use:



                  def describe_status(relation):
                  if relation <= -8:
                  return "vengeful"

                  elif -8 < relation <= -4: # Note, you can chain comparison operators
                  return "hateful"

                  elif -4 < relation <= -1:
                  return "disappointed"

                  elif -1 < relation <= 2:
                  return "conflicted"

                  #... The rest of the statuses


                  Then, use that function:



                  def civil_left():
                  status = describe_status(relationship[1])

                  print('You left the', civilian, 'feeling', status)

                  def army_left():
                  status = describe_status(relationship[0])

                  print('You left the', army_government, 'feeling', status)


                  Now, the major problem here is that you set the relationship thresholds at different levels for each. You could add a second parameter to describe_status that adds an offset to each condition to remedy that though. Note how much duplication that removed though!




                  I'll note that you tagged this as functional-programming, but this is far from what would be considered functional. I'm not going to go into great detail about what all FP means, but basically, if you're following FP principals, you're passing data around instead of mutating objects and carrying out side effects. All of your functions print directly, and none seem to accept any parameters. This is not good, regardless of the paradigm that you're following. You're relying entirely on global state (like relationships), and on operating through side effects (like altering relationships and using print everywhere). If you continue to code like this, you will have a very difficult time creating anything other than small projects, and debugging will increasingly become a nightmare.



                  Look at how describe_status operates. Every piece of data that it requires is a parameter (relation), and everything the function does is done via the data that's returned. When functions are just taking and returning data, it becomes much easier to reason about how the code works; and that's an extremely important goal. Code that's hard to understand the operation of is code that's hard to maintain and build on.




                  You have a lot of story Strings embedded in the code. I would save these in a file and read them from file as needed. That will make the code less bulky, and will make it so you don't need to alter the code if you want to alter the story.




                  I'm going to submit this before it gets closed. Good luck!






                  share|improve this answer











                  $endgroup$



                  I'm on my phone, so it's hard to really see this code as a whole and really take the full context of everything. I'm just going to flip through and mention things as I notice them.




                  At the top, you have



                  vengeful = 'VENGEFUL.'


                  And other such lines. This strikes me as odd. The only small benefit I can see is this would help the IDE auto-complete the word. Looking at how you're using it, you're forcing a ton of repetitious code in functions like civil_left. Look at that function, and look at the function below it and think about how much of those functions are the same. Not only are each of lines in the functions nearly identical, both of those functions are basically the same! Whenever you have code that's nearly identical in multiple spots, make the identical code the body of a function, and make the parts that differ parameters to the function.



                  How would that look? The only real part that differs is the end of that sentence where you decide what status to display. First, factor out the part that decides the the word to use:



                  def describe_status(relation):
                  if relation <= -8:
                  return "vengeful"

                  elif -8 < relation <= -4: # Note, you can chain comparison operators
                  return "hateful"

                  elif -4 < relation <= -1:
                  return "disappointed"

                  elif -1 < relation <= 2:
                  return "conflicted"

                  #... The rest of the statuses


                  Then, use that function:



                  def civil_left():
                  status = describe_status(relationship[1])

                  print('You left the', civilian, 'feeling', status)

                  def army_left():
                  status = describe_status(relationship[0])

                  print('You left the', army_government, 'feeling', status)


                  Now, the major problem here is that you set the relationship thresholds at different levels for each. You could add a second parameter to describe_status that adds an offset to each condition to remedy that though. Note how much duplication that removed though!




                  I'll note that you tagged this as functional-programming, but this is far from what would be considered functional. I'm not going to go into great detail about what all FP means, but basically, if you're following FP principals, you're passing data around instead of mutating objects and carrying out side effects. All of your functions print directly, and none seem to accept any parameters. This is not good, regardless of the paradigm that you're following. You're relying entirely on global state (like relationships), and on operating through side effects (like altering relationships and using print everywhere). If you continue to code like this, you will have a very difficult time creating anything other than small projects, and debugging will increasingly become a nightmare.



                  Look at how describe_status operates. Every piece of data that it requires is a parameter (relation), and everything the function does is done via the data that's returned. When functions are just taking and returning data, it becomes much easier to reason about how the code works; and that's an extremely important goal. Code that's hard to understand the operation of is code that's hard to maintain and build on.




                  You have a lot of story Strings embedded in the code. I would save these in a file and read them from file as needed. That will make the code less bulky, and will make it so you don't need to alter the code if you want to alter the story.




                  I'm going to submit this before it gets closed. Good luck!







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 20 mins ago

























                  answered 58 mins ago









                  CarcigenicateCarcigenicate

                  5,3861 gold badge18 silver badges37 bronze badges




                  5,3861 gold badge18 silver badges37 bronze badges




















                      Mikey Akamihe is a new contributor. Be nice, and check out our Code of Conduct.









                      draft saved

                      draft discarded


















                      Mikey Akamihe is a new contributor. Be nice, and check out our Code of Conduct.












                      Mikey Akamihe is a new contributor. Be nice, and check out our Code of Conduct.











                      Mikey Akamihe is a new contributor. Be nice, and check out our Code of Conduct.














                      Thanks for contributing an answer to Code Review Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      Use MathJax to format equations. MathJax reference.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f222720%2fstory-based-adventure-with-functions-and-relationships%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

                      Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

                      Ласкавець круглолистий Зміст Опис | Поширення | Галерея | Примітки | Посилання | Навігаційне меню58171138361-22960890446Bupleurum rotundifoliumEuro+Med PlantbasePlants of the World Online — Kew ScienceGermplasm Resources Information Network (GRIN)Ласкавецькн. VI : Літери Ком — Левиправивши або дописавши її