Story-based adventure with functions and relationshipsText-based adventure gameText adventure and global...
Fedora boot screen shows both Fedora logo and Lenovo logo. Why and How?
Do flight schools typically have dress codes or expectations?
Should I include salary information on my CV?
Which verb form to use with "с"
Alphabet completion rate
How can I get more energy without spending coins?
Would a two-seat light aircaft with a landing speed of 20 knots and a top speed of 180 knots be technically possible?
When is the original BFGS algorithm still better than the Limited-Memory version?
In the Marvel universe, can a human have a baby with any non-human?
Could Sauron have read Tom Bombadil's mind if Tom had held the Palantir?
Inverse-quotes-quine
Is adding a new player (or players) a DM decision, or a group decision?
Why is the voltage measurement of this circuit different when the switch is on?
STM Microcontroller burns every time
Policemen catch thieves
What sort of mathematical problems are there in AI that people are working on?
Why do textbooks often include the solutions to odd or even numbered problems but not both?
Why does the numerical solution of an ODE move away from an unstable equilibrium?
Is there any evidence that the small canisters (10 liters) of 95% oxygen actually help with altitude sickness?
Require advice on power conservation for backpacking trip
Does Marvel have an equivalent of the Green Lantern?
Why is the Turkish president's surname spelt in Russian as Эрдоган, with г?
Why is C++ initial allocation so much larger than C's?
Why is Madam Hooch not a professor?
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;
}
$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} {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
New contributor
$endgroup$
add a comment |
$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} {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
New contributor
$endgroup$
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
6 hours ago
add a comment |
$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} {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
New contributor
$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
python beginner game functional-programming adventure-game
New contributor
New contributor
edited 5 hours ago
Vogel612♦
22k5 gold badges48 silver badges131 bronze badges
22k5 gold badges48 silver badges131 bronze badges
New contributor
asked 9 hours ago
Mikey AkamiheMikey Akamihe
263 bronze badges
263 bronze badges
New contributor
New contributor
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
6 hours ago
add a comment |
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
6 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
6 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
6 hours ago
add a comment |
2 Answers
2
active
oldest
votes
$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}.')
$endgroup$
add a comment |
$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 return
ed. 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!
$endgroup$
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
$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}.')
$endgroup$
add a comment |
$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}.')
$endgroup$
add a comment |
$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}.')
$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}.')
answered 2 hours ago
AlexVAlexV
2,7659 silver badges31 bronze badges
2,7659 silver badges31 bronze badges
add a comment |
add a comment |
$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 return
ed. 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!
$endgroup$
add a comment |
$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 return
ed. 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!
$endgroup$
add a comment |
$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 return
ed. 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!
$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 return
ed. 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!
edited 1 hour ago
answered 2 hours ago
CarcigenicateCarcigenicate
5,3861 gold badge18 silver badges37 bronze badges
5,3861 gold badge18 silver badges37 bronze badges
add a comment |
add a comment |
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.
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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
6 hours ago