├── requirements.txt ├── README.md ├── items.json ├── Game_State.txt ├── rooms.json ├── .gitignore ├── Logs.txt ├── Item.py ├── general_funcs.py ├── Room.py ├── Human.py └── Fallout_Shelter.py /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dis446/Shelter-Survival-Text-Based/HEAD/requirements.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shelter-Survival-Text-Based 2 | An open source, text based version of the popular Bethesda Fallout Shelter game, with a few modifications, written in Python 3. 3 | Shelter Survival should has inventory, crafting, room-building, room-rushing, and scrapping systems. The player shall be an overseer who is an actual character in the game, with their own stats. Uses Fallout's S.P.E.C.I.A.L system. 4 | 5 | 6 | Depedencies: 7 | 8 | -json 9 | -python 3.x 10 | -pickle 11 | -appdirs 12 | -readline or pyreadline (optional) 13 | 14 | 15 | 16 | Notes: By T.G. 17 | I had this idea to help me get started with developing more advanced games. I am an aspiring software engineer and wanted to get serious about software and convinced myself to get an account on Github. I will now start developing projects in Python and (hopefully) other languages. 18 | 19 | 20 | -------------------------------------------------------------------------------- /items.json: -------------------------------------------------------------------------------- 1 | { 2 | "wood": { 3 | "value": 10, 4 | "weight": 5, 5 | "components": [], 6 | "rarity": 1 7 | }, 8 | "steel": { 9 | "value": 50, 10 | "weight": 20, 11 | "components": [], 12 | "rarity": 4 13 | }, 14 | "food": { 15 | "value": 20, 16 | "weight": 1, 17 | "components": [], 18 | "rarity": 2 19 | }, 20 | "water": { 21 | "value": 30, 22 | "weight": 2, 23 | "components": [], 24 | "rarity": 3 25 | }, 26 | "silicon": { 27 | "value": 50, 28 | "weight": 1, 29 | "components": [], 30 | "rarity": 6 31 | }, 32 | "copper": { 33 | "value": 20, 34 | "weight": 1, 35 | "components": [], 36 | "rarity": 3 37 | }, 38 | "watt": { 39 | "value": 40, 40 | "weight": 0, 41 | "components": [], 42 | "rarity": 4 43 | }, 44 | "turret": { 45 | "value": 20, 46 | "weight": 20, 47 | "components": ["steel", "steel", "steel", "chip", "steel", "steel"], 48 | "rarity": 8 49 | }, 50 | "chip": { 51 | "value": 100, 52 | "weight": 1, 53 | "components": ["wire", "wire", "wire", "silicon"], 54 | "rarity": 8 55 | }, 56 | "wire": { 57 | "value": 40, 58 | "weight": 3, 59 | "components": ["copper", "copper", "copper"], 60 | "rarity": 4 61 | }, 62 | "gun": { 63 | "value": 100, 64 | "weight": 5, 65 | "components": ["steel", "copper"], 66 | "rarity": 6 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Game_State.txt: -------------------------------------------------------------------------------- 1 | This is a in-progress summary of the game. 2 | 3 | The game is divided into several .py source files and a few .json files. 4 | The main (and longest) source file is Fallout_Shelter.py 5 | It stores the main Game class, which initilizes it's values and is only called when a new game is made. 6 | It initilizes the: 7 | -Player character, which is a class onto itself 8 | -Inventory, which is a sorted dictionary in the form of 9 | --inventory = {"item_name": count_of_instances} 10 | ---The items are stored only with the name and how many of them there are. If an item's attribute has to be used, the item has be created, on the fly, via the name 11 | -Rooms, which is a dictionary in the form of 12 | --rooms = {"room_name": room_object} 13 | ---Stored in their object form, alongside their names 14 | -Inhabitants, in the form 15 | --people = {"person_name": person_object} 16 | ---Stored in the exact same way rooms are 17 | -Other variables like day count and the number of caps the player has 18 | 19 | 20 | Player actions are done via dispatching. 21 | There's a Game.actions ordered dictionary that stores all possible player commands in the form 22 | -game.actions = {action_name:function_it_calls} 23 | 24 | The Human class and functions/methods to do with humans are stored in the Human.py file. 25 | 26 | The Items class and functions/methods to do with items are stored in the Item.py file. 27 | All possible items are stored in the items.json file, with all the specific attributes and stuff 28 | 29 | The Room class and functions/methods to do with rooms are stored in the Room.py file. 30 | All possible rooms are stored in the rooms.json file, with all the specific attributes. 31 | 32 | There's a general functions file that stores functions that are used heavily everywhere else. 33 | -Most notable of which is the print_line() function which is used instead of the standard print() function to space out prints and give the user time to read output. 34 | 35 | There's an incomplete save/load feature that needs work. 36 | 37 | 38 | -------------------------------------------------------------------------------- /rooms.json: -------------------------------------------------------------------------------- 1 | { 2 | "living": { 3 | "risk": 0, 4 | "can_produce": false, 5 | "attribute" : "", 6 | "perk" : "", 7 | "produce" : "", 8 | "assigned_limit": 0, 9 | "components": ["wood", "wood", "wood", "wood"], 10 | "power_usage": 5 11 | }, 12 | "generator": { 13 | "risk": 2, 14 | "can_produce": true, 15 | "attribute" : "strength", 16 | "perk" : "electrician", 17 | "produce" : "watt", 18 | "assigned_limit": 3, 19 | "components": ["steel", "steel", "steel", "steel"], 20 | "power_usage": 0 21 | }, 22 | "storage": { 23 | "risk": 0, 24 | "can_produce": false, 25 | "attribute" : "", 26 | "perk" : "", 27 | "produce" : "", 28 | "assigned_limit": 0, 29 | "components": ["steel", "steel"], 30 | "power_usage": 1 31 | }, 32 | "kitchen": { 33 | "risk": 1, 34 | "can_produce": true, 35 | "attribute" : "agility", 36 | "perk" : "cooking", 37 | "produce" : "food", 38 | "assigned_limit": 3, 39 | "components": ["wood", "wood", "wood"], 40 | "power_usage": 10 41 | }, 42 | "trader": { 43 | "risk": 0, 44 | "can_produce": false, 45 | "attribute" : "", 46 | "perk" : "", 47 | "produce" : "", 48 | "assigned_limit": 1, 49 | "components": ["wood", "wood", "wood", "steel", "steel"], 50 | "power_usage": 2 51 | }, 52 | "water": { 53 | "risk": 2, 54 | "can_produce": true, 55 | "attribute" : "perception", 56 | "perk" : "", 57 | "produce" : "water", 58 | "assigned_limit": 3, 59 | "components": ["wood", "wood", "steel"], 60 | "power_usage": 10 61 | }, 62 | "radio": { 63 | "risk": 0, 64 | "can_produce": false, 65 | "attribute" : "", 66 | "perk" : "inspiration", 67 | "produce" : "", 68 | "assigned_limit": 2, 69 | "components": ["wood", "wood", "wood", "steel", "steel"], 70 | "power_usage": 15 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/python,eclipse,cloud9,vim 2 | 3 | ### Python ### 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | env/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *,cover 49 | .hypothesis/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | 58 | # Sphinx documentation 59 | docs/_build/ 60 | 61 | # PyBuilder 62 | target/ 63 | 64 | #Ipython Notebook 65 | .ipynb_checkpoints 66 | 67 | 68 | ### Eclipse ### 69 | 70 | .metadata 71 | bin/ 72 | tmp/ 73 | *.tmp 74 | *.bak 75 | *.swp 76 | *~.nib 77 | local.properties 78 | .settings/ 79 | .loadpath 80 | 81 | # Eclipse Core 82 | .project 83 | 84 | # External tool builders 85 | .externalToolBuilders/ 86 | 87 | # Locally stored "Eclipse launch configurations" 88 | *.launch 89 | 90 | # PyDev specific (Python IDE for Eclipse) 91 | *.pydevproject 92 | 93 | # CDT-specific (C/C++ Development Tooling) 94 | .cproject 95 | 96 | # JDT-specific (Eclipse Java Development Tools) 97 | .classpath 98 | 99 | # Java annotation processor (APT) 100 | .factorypath 101 | 102 | # PDT-specific (PHP Development Tools) 103 | .buildpath 104 | 105 | # sbteclipse plugin 106 | .target 107 | 108 | # TeXlipse plugin 109 | .texlipse 110 | 111 | # STS (Spring Tool Suite) 112 | .springBeans 113 | 114 | 115 | ### Cloud9 ### 116 | # Cloud9 IDE - http://c9.io 117 | .c9revisions 118 | .c9 119 | 120 | 121 | ### Vim ### 122 | [._]*.s[a-w][a-z] 123 | [._]s[a-w][a-z] 124 | *.un~ 125 | Session.vim 126 | .netrwhist 127 | *~ 128 | 129 | ### Custom ### 130 | #used for testing small snippets 131 | test.py 132 | #keeping track of local goals 133 | fix.txt 134 | fstb.p 135 | *.fuse_hidden* 136 | *.iml 137 | -------------------------------------------------------------------------------- /Logs.txt: -------------------------------------------------------------------------------- 1 | Logs: 2 | 3 | 4 | 8.12.15: T.G. 5 | Have uploaded a v0.1 of the game and secured one collaborator. 6 | After a few mods, decided to put v0.1 in stasis and any new changes should be commited as further versions. 7 | Any minor mods should be commited as seperate files. After a while, minor mods shall be collated into one new version of the game. 8 | 9 | 10 | 11 | 9.12.15: T.G. 12 | Uploaded possible solution to adding items to the inventory in the easiest way. Need to modify the "item" class. 13 | 14 | 15 | 16 | 10.12.15: T.G. 17 | Discovered Cloud 9 workstation system thanks to The-9880. Will use it to develop code and use github to store our work. 18 | Pushed massive update to all systems. Version 0.2 commited to github. 19 | Changelog: 20 | Developed choice system. 21 | The main game loop seems almost done. 22 | Improved inventory system. 23 | Improved birthing system for new inhabitants. 24 | Initial implementation of hunger and happiness systems. 25 | Initial attempt at Action Points system. 26 | Alpha version of trading system pushed. Pre-alpha. Like it barely even exists. 3 lines of code or something. 27 | Initial Food system. 28 | Player can now create a character. Kind of important to games so glad this is up. 29 | General bug fixes (Syntax errors only) 30 | 31 | All code needs massive debugging :( Will develop "broken" versions of all systems and patch them later. 32 | Isn't that how software development works? 33 | 34 | 35 | 14.12.15: T.G. 36 | Pushed v.03 to github. Massive overhaul of some systems and development of many new systems. Code line count doubled! This project is getting complicated fast... 37 | Changelog: 38 | Complete re-working of item system. Now class(item) just needs a name to create itself. 39 | Comparmentalized all the code into seperate "systems" to make development and debugging simpler. 40 | Added create_player function. 41 | Scrapped crafting and room-building systems. Also need to rework room system. 42 | New systems: raiding, scavenging, random item finding/losing, thirst system, hunger system, Action point usage. Informaion systems. 43 | Trading system massively improved. 44 | Imporoved daily loop system. 45 | Improved game loop system. 46 | Minor bug fixes. Emphasis on minor. 47 | Might be some stuff I've forgotten, but it doesn't really matter. 48 | 49 | Still no debugging has happened :( 50 | With the inclusion of all these new systems it's even less likely that this code will run. I don't know what I'm doing. 51 | 52 | 18.12.15: T.G. 53 | Pushed v.04 to github. Too many changes to list. Basically improved every system. Most notably, completely reworked room system. 54 | Passed 1000 source code line count! The-9880 has done the crafting and scavenging systems. 55 | #NoDebug #ftw #CodeWontRun 56 | 57 | 29.12.15: T.G. 58 | Been a while since log update. Doesn't mean work wasn't being done. Pushed v0.5 and the game works... Sort of. 59 | All Syntax errors resolved. Now debugging. 60 | Information, human management and trading systems fully functional. 61 | Other systems quasi-functional. Need more work. Especially room assignment system. 62 | 63 | In other news, started using git on local workstations and github to auto-sync code between local stations and cloud spaces (C9!!!) 64 | Passed 1400 code line mark. Project is coming together. 65 | 66 | 08/02/16: T.G. 67 | Been a while since any log updates. But a lot of work has been done. Most of the systems work. Have switched to PEP-8 style format and moved all the classes to seperate .py files. Mikevb1 has been a huge help. 68 | -------------------------------------------------------------------------------- /Item.py: -------------------------------------------------------------------------------- 1 | """Module containing all Item classes.""" 2 | 3 | from general_funcs import print_line, FAST, SLOW, NORMAL 4 | import json 5 | import sys 6 | import os 7 | 8 | 9 | def all_items(): 10 | """Get a list of all items available in game. 11 | 12 | Returns: 13 | items -- list of all items 14 | """ 15 | fn = "items.json" 16 | path = os.path.join(os.path.dirname(sys.argv[0]), fn) 17 | with open(path) as i: 18 | items = [item for item in json.loads(i.read())] 19 | return items 20 | 21 | 22 | class Item(object): 23 | """Item class. Only used for on-the-fly cases, not storage.""" 24 | 25 | def __init__(self, name): 26 | """Item constructor. 27 | 28 | Arguments: 29 | name -- name of item 30 | """ 31 | # Just needs to get the name, all other attributes are automatically 32 | # assigned by the following lines, from parsing an item.json file. 33 | self.name = name 34 | with open('items.json') as f: 35 | parsed = json.loads(f.read()) 36 | try: 37 | item = parsed[self.name] 38 | self.value = item['value'] 39 | self.weight = item['weight'] 40 | self.components = item['components'] 41 | self.rarity = item['rarity'] 42 | except KeyError: 43 | print("Unknown item. This is a bug. Please contact the dev.") 44 | # Keeps track of whether item has been scrapped by player. 45 | self.scrapped = False 46 | 47 | def print_(self, count): 48 | """Print item name and attributes. 49 | 50 | Arguments: 51 | count -- amount of item held 52 | """ 53 | att = " | {}: {}" 54 | print_line( 55 | "{} * {}".format(self.name, count), 56 | att.format("Weight", self.weight), 57 | att.format("Value", self.value), 58 | att.format("Rarity", self.rarity), 59 | att.format("Components", self.components), 60 | end="", 61 | speed=FAST) 62 | print() 63 | 64 | def count_component(self, component): 65 | """Count number of components in Item. 66 | 67 | Arguments: 68 | component -- component to count 69 | """ 70 | return self.components.count(str(component)) 71 | 72 | def scrap(self): 73 | """Destroy Item and add its components to inventory.""" 74 | print_line(self.name, " has been scrapped and these") 75 | for item in self.components: 76 | inventory[item] += 1 77 | print_line(item) 78 | print_line("have been added to your inventory") 79 | 80 | chance = randint(0, 101) 81 | if (player.scrapper) * 3 > chance: 82 | print_line( 83 | "Your scrapper skill has allowed you to gain more components!") 84 | # Randomly adds extra component of the scrapped item the inventory. 85 | inventory[self.components[randint(len(self.components))]] += 1 86 | self.destroy("player") 87 | 88 | 89 | class Inventory(dict): 90 | """Inventory class, inherits dict attributes.""" 91 | 92 | def __init__(self, items=[]): 93 | """Inventory class constructor, sets values to 0.""" 94 | for item in items: 95 | self[item] = 0 96 | 97 | def print_(self): 98 | """Print all items in inventory.""" 99 | for item in self: 100 | if self[item] > 0: 101 | Item(item).print_(self[item]) 102 | -------------------------------------------------------------------------------- /general_funcs.py: -------------------------------------------------------------------------------- 1 | """General functions used by most modules in this project.""" 2 | 3 | from string import ascii_uppercase 4 | from time import sleep 5 | from sys import stdout 6 | 7 | load = False # Enables/disables loading screens. 8 | if load: 9 | from tqdm import tqdm 10 | 11 | 12 | def input_int(message): 13 | """Allow user to input integers while catching errors. 14 | 15 | Arguments: 16 | message -- string to print as a prompt 17 | 18 | Returns: 19 | inp -- integer inputted by user 20 | """ 21 | while True: 22 | inp = input(str(message)) 23 | try: 24 | return int(inp) 25 | except: 26 | print_line("Invalid. Only integer numbers are accepted!") 27 | 28 | 29 | def default_input(text): 30 | """Ask for input and accept a default answer. 31 | 32 | Example `text`: "Answer? (Y/n) " where `Y` is default answer. 33 | 34 | Arguments: 35 | text -- text as prompt 36 | 37 | Returns: 38 | char/None -- answer 39 | """ 40 | answers = [] 41 | default = "" 42 | in_ans = False 43 | for c in text[len(text):0:-1]: 44 | if in_ans: 45 | if c == "(": 46 | in_ans = False 47 | break 48 | answers += c.lower() 49 | if c in ascii_uppercase: 50 | default = answers[-1] 51 | if c == ")": 52 | in_ans = True 53 | answer = input(text).lower() 54 | if len(answer) == 0: 55 | return default 56 | elif answer in answers: 57 | return answer 58 | return None 59 | 60 | 61 | def validate_input(text): 62 | """Check if input is valid ( i.e has enougth length). 63 | 64 | Arguments: 65 | text -- string to be checked 66 | 67 | Returns: 68 | bool -- Whether input is acceptable 69 | """ 70 | if len(text) > 0: 71 | return True 72 | return False 73 | 74 | 75 | def validate_name(name): 76 | """Check if name is valid ( Has to be one word only). 77 | 78 | Arguments: 79 | name -- name to be checked 80 | 81 | Returns: 82 | bool -- Whether name is acceptable or not 83 | """ 84 | if validate_input(name) and len(name.split()) == 1: 85 | return True 86 | return False 87 | 88 | 89 | def text_align(starts): 90 | """Align starts and ends so the beginning of end strings line up. 91 | 92 | Arguments: 93 | starts -- list of strings to begin 94 | 95 | Returns: 96 | align -- list of differences of max string length and each string length 97 | """ 98 | lens = [len(s) for s in starts] 99 | align = [max(lens) - l for l in lens] 100 | return align 101 | 102 | 103 | def sentence_split(text): 104 | """Split text by sentences and return first sentence. 105 | 106 | Arguments: 107 | text -- text to split 108 | 109 | Returns: 110 | sen -- first sentence 111 | """ 112 | sens = text.split(".") 113 | sen = sens[0] + "." 114 | return sen 115 | 116 | SLOW = 0.5 117 | FAST = 0.01 118 | NORMAL = 0.2 119 | 120 | def print_line(*messages, end = "\n", speed = FAST): 121 | """Print message with artificial spacing by sleeping. 122 | 123 | Arguments: 124 | *messages -- tuple of strings to print 125 | end -- end of string 126 | fast -- if true, shortens time between prints 127 | slow -- if true, extends time between prints 128 | """ 129 | if len(messages) == 2: 130 | output = ' '.join([str(messages[0]), str(messages[1])]) 131 | messages = (output,) 132 | for message in messages: 133 | message = str(message) 134 | for line in message.splitlines(): 135 | sleep(speed) 136 | if end != "\n": 137 | stdout.write(line) 138 | stdout.flush() 139 | else: 140 | print(line) 141 | 142 | 143 | def load_time(x, *messages): 144 | """Loading bars. 145 | 146 | Arguments: 147 | x -- length of loading bar in seconds 148 | messages -- tuple of message to print before loading bar 149 | """ 150 | print_line(*messages) 151 | if load: 152 | for x in tqdm(range(0, x)): 153 | sleep(0.01) 154 | else: 155 | sleep(x / 10000) 156 | 157 | -------------------------------------------------------------------------------- /Room.py: -------------------------------------------------------------------------------- 1 | """Module containing Room class.""" 2 | 3 | from general_funcs import print_line 4 | from Item import Item 5 | import json 6 | import os 7 | import sys 8 | 9 | def all_rooms(): 10 | """Get a list of all rooms in game. 11 | 12 | Returns: 13 | rooms -- list of all rooms 14 | """ 15 | fn = "rooms.json" 16 | path = os.path.join(os.path.dirname(sys.argv[0]), fn) 17 | with open(path) as r: 18 | rooms = [room for room in json.loads(r.read())] 19 | return rooms 20 | 21 | 22 | class Room(object): # Basic class for the rooms in the game. 23 | """Room class.""" 24 | 25 | def __init__(self, name): 26 | """Room class constructor. 27 | 28 | Arguments: 29 | name -- name of room 30 | """ 31 | self.name = name 32 | with open('rooms.json') as f: 33 | parsed = json.loads(f.read()) 34 | try: 35 | room = parsed[self.name] 36 | self.risk = room['risk'] 37 | self.can_produce = room['can_produce'] 38 | self.assigned_limit = room['assigned_limit'] 39 | self.attribute = room['attribute'] 40 | self.produce = room['produce'] 41 | self.perk = room['perk'] 42 | self.components = room['components'] 43 | self.power_usage = room['power_usage'] 44 | self.wattage = room['power_usage'] 45 | except KeyError: 46 | print("Unknown room {}. Please contact dev.".format(name)) 47 | self.level = 1 48 | self.power_available = True 49 | self.assigned = [] #list of names of people assigned 50 | self.broken = False 51 | 52 | if self.can_produce: 53 | self.production = 0 54 | self.can_rush = True 55 | else: 56 | self.can_rush = False 57 | self.rushed = False 58 | 59 | def __str__(self): 60 | """String representation of object. 61 | 62 | Returns: 63 | self.name -- eg. "Living Room" 64 | """ 65 | return "{} Room".format(self.name.title()) 66 | 67 | def print_(self): 68 | """Print room name and its attributes. 69 | 70 | Arguments: 71 | game -- Main game object. 72 | """ 73 | print_line(self) 74 | if self.power_available: 75 | power_availablility = "Working" 76 | else: 77 | power_availablility = "No power available" 78 | if self.broken: 79 | status = "Broken" 80 | status = "Functional" 81 | else: 82 | status = "Functional" 83 | print_line(" Risk: {}%".format(self.risk), 84 | " Level: {}".format(self.level), 85 | " Attribute: {}".format(self.attribute.title()), 86 | " Power: {}".format(power_availablility), 87 | " Status: {}".format(status)) 88 | if self.can_produce: 89 | print_line(" Production: {}".format(self.production)) 90 | if self.can_produce or self.name == "trader": 91 | print_line(" Assigned: ") 92 | self.see_assigned() 93 | print() 94 | 95 | def rush(self): 96 | """Rush building of Room.""" 97 | self.rushed = True # Lets game know this room has been rushed. 98 | self.risk += 20 99 | print_line("{} room has been rushed!".format(self.name)) 100 | 101 | def fix(self): 102 | """Repair room if damaged.""" 103 | self.broken = False 104 | 105 | def count_assigned(self): 106 | """Count inhabitants assigned to Room.""" 107 | return len(self.assigned) 108 | 109 | def see_assigned(self): 110 | """Print names of inhabitants assigned to Room.""" 111 | if self.assigned: 112 | for person_name in self.assigned: 113 | print_line(" " + person_name) 114 | else: 115 | print_line(" None") 116 | 117 | def count_component(self, component): 118 | """Count components required to build Room. 119 | 120 | Arguments: 121 | component -- component to count 122 | 123 | Returns: 124 | int -- amount of component required to build Room 125 | """ 126 | return self.components.count(str(component)) 127 | 128 | 129 | def use_power(self): 130 | """Consume player's power.""" 131 | for x in range(0, self.power_usage): 132 | Item('watt').destroy("player") 133 | -------------------------------------------------------------------------------- /Human.py: -------------------------------------------------------------------------------- 1 | """Module containing all Human classes.""" 2 | 3 | from general_funcs import print_line, SLOW, FAST, NORMAL 4 | from Item import Inventory, all_items 5 | 6 | class Human(object): 7 | """Basic class for all humans in game.""" 8 | 9 | def __init__( 10 | self, first_name=None, day_of_birth=0, 11 | parent_1=None, parent_2=None, age=0, gender='M', surname=None): 12 | """Constructor for Human class. 13 | 14 | Arguments: 15 | first_name -- first name of Human 16 | day_of_birth -- day Human was born 17 | parent_1 -- name of Human's father 18 | parent_2 -- name of Human's mother 19 | age -- age of Human 20 | gender -- gender of Human 21 | """ 22 | self.alive = True 23 | self.name = first_name # First name 24 | self.day_of_birth = day_of_birth 25 | self.parent_1 = parent_1 #Object 26 | self.parent_2 = parent_2 #Object 27 | self.age = age 28 | self.gender = gender.upper() 29 | self.hunger = 0 30 | self.thirst = 0 31 | self.job = "" #eg trader, mechanic, hunter, farmer etc. 32 | self.inventory = Inventory(all_items()) 33 | try: 34 | self.surname = self.parent_1.surname 35 | except: 36 | self.surname = surname 37 | self.partner = "" 38 | 39 | # The stats of the person. Affects the production of 40 | # room the person has been assigned to. 41 | self.stats = {"strength": 1, 42 | "perception": 1, 43 | "endurance": 1, 44 | "charisma": 1, 45 | "intelligence": 1, 46 | "luck": 1 47 | } 48 | 49 | self.assigned_room = "" # Keeps track of where person is working. 50 | self.children = [] # List of all children's names. 51 | self.partner = "" #Significant other's name. 52 | self.level = 1 # Determines production efficiency. 53 | self.XP = 0 54 | 55 | def __str__(self): 56 | """String representation of object, first name and last name. 57 | 58 | Returns: 59 | str -- "Firstname Lastname" 60 | """ 61 | return "{} {}".format(self.name.title(), self.surname.title()) 62 | 63 | def print_(self): 64 | """Print name and attributes.""" 65 | print_line("\n") 66 | print_line( 67 | self, 68 | "\n Age: {}".format(self.age) + 69 | " Gender: {}".format(self.gender) + 70 | " Hunger: {}".format(self.hunger) + 71 | " Thirst: {}".format(self.thirst) + 72 | " Room: {}".format(self.assigned_room), 73 | speed = FAST) 74 | for stat in self.stats.keys(): 75 | print_line(" " + stat + " : " + str(self.stats[stat])) 76 | print_line("\n") 77 | 78 | def see_stats(self): 79 | """Check stats of inhabitant.""" 80 | for stat in self.stats: 81 | print_line("{}: {}".format(stat, self.stats[stat])) 82 | 83 | def feed(self, amount): 84 | """Reduce hunger level of inhabitant. 85 | 86 | Arguments: 87 | amount -- how much to feed inhabitant 88 | """ 89 | self.hunger -= amount 90 | if self.hunger < 0: 91 | self.hunger = 0 92 | 93 | def drink(self, amount): 94 | """Reduce thirst level of inhabitant. 95 | 96 | Arguments: 97 | amount -- how much to feed inhabitant 98 | """ 99 | self.thirst -= amount 100 | if self.thirst < 0: 101 | self.thirst = 0 102 | 103 | def level_up(self): 104 | """Level up Human and ask player for input on what stat to level up.""" 105 | print_line("{} has gained enough experience to level up!!!".format(self)) 106 | self.see_stats() 107 | self.level += 1 108 | choice_dict = { 109 | 'strength':self.stats["strength"], 110 | 'perception':self.stats["perception"], 111 | 'endurance':self.stats["endurance"], 112 | 'charisma':self.stats["charisma"], 113 | 'intelligence':self.stats["intelligence"], 114 | 'luck':self.stats["luck"] 115 | } 116 | #This method is overridden and super() is called by both subclasses of the Human class. 117 | 118 | def check_xp(self): 119 | """Check experience of inhabitant is enough to level up. 120 | 121 | Returns: 122 | bool -- whether or not Human can level up""" 123 | # Xp needed to level up increases exponentially 124 | xp_needed = 10 + (2**self.level) 125 | if self.XP >= xp_needed: 126 | return True 127 | else: 128 | return False 129 | 130 | def gain_xp(self, amount): 131 | """Increase experience of person. If they have enough to level 132 | up, they do. 133 | 134 | Arguments: 135 | amount -- amount to level up by 136 | """ 137 | self.XP += amount 138 | while self.check_xp(): 139 | self.level_up() 140 | 141 | def max_HP(self): 142 | """Determines the maximum amount of natural health the person 143 | can have, depending on level and gear equppied. 144 | 145 | Returns: 146 | max_HP -- The maximum amount of health. Base is 100. 147 | """ 148 | 149 | max_HP = 100 + (10*self.level) 150 | max_HP += 5*(self.stats["strength"]) 151 | """ #Leave this until armour is implemeted in Item.py 152 | for item_name in self.inventory.keys(): 153 | try: 154 | if self.inventory[item_name].is_armour: 155 | max_HP += self.inventory[item_name].level 156 | """ 157 | return max_HP 158 | 159 | def heal(self, amount): 160 | """Heal Human. 161 | 162 | Arguments: 163 | amount -- amount of health to give 164 | """ 165 | max_health = self.max_HP() 166 | self.HP += amount 167 | if self.HP > max_health: # Truncates health 168 | self.HP = max_health 169 | print_line("{} has healed and now has {} health \ 170 | points".format(str(self), self.HP)) 171 | 172 | def rebirth(self): 173 | """Don't know if I'll ever use this.""" 174 | self.age = 0 175 | if self.gender == "m": 176 | print_line( 177 | self.name + 178 | " has been reborn and his stats have been reset") 179 | else: 180 | print_line( 181 | self.name + 182 | " has been reborn and her stats have been reset") 183 | self.stats["strength"] = self.perception = self.endurance = 1 184 | self.stats["charisma"] = self.luck = self.intelligence = 1 185 | 186 | def mature(self, person): 187 | """Increment Human's age. 188 | 189 | Arguments: 190 | person -- Human who's aging 191 | """ 192 | person.age += 1 193 | print_line("{} has matured and is now {} years old!" \ 194 | .format(self, self.age)) 195 | 196 | def take_damage(self, amount): 197 | """Take health from Human. 198 | 199 | Arguments: 200 | amount -- amount of health to take 201 | """ 202 | self.defense = self.stats["strength"] * 10 203 | damage_taken = amount - self.defense 204 | if damage_taken < 1: 205 | damage_taken = 0 206 | else: 207 | self.HP -= damage_taken 208 | if self.HP < 1: 209 | self.die() 210 | 211 | def increase_hunger(self, amount): 212 | """Increase hunger level of Human by certain amount 213 | 214 | Arguments: 215 | amount -- amount of hunger to increase by 216 | """ 217 | self.hunger += amount 218 | 219 | def increase_thirst(self, amount): 220 | """Increase thirst level of Human by certain amount 221 | 222 | Arguments: 223 | amount -- amount of thirst to increase by 224 | """ 225 | self.thirst += amount 226 | 227 | def scavenge(self, days=10): 228 | """Send inhabitant on scavenging mission. 229 | 230 | Arguments: 231 | days -- ask user for number of days if this is 'days'. 232 | """ 233 | self.current_activity = "scavenging" 234 | if not (isinstance(days, int)) or days <= 0: 235 | person.days_to_scavenge_for = 10 236 | else: 237 | person.days_to_scavenge_for = days 238 | 239 | def can_mate(self): 240 | """Check if Human meets requirements to have children. 241 | 242 | Returns: 243 | bool -- whether or not human can mate 244 | """ 245 | if self.age < 18: 246 | return False 247 | if len(self.children) > 5: # Upper limit of children is 5 248 | return False 249 | # Have to wait for a year before parent can have child again. 250 | for child in self.children: 251 | if people(child).age < 1: 252 | return False 253 | return True 254 | 255 | def die(self, cause = ""): 256 | """Kill self, and unassign from a assigned room. 257 | #Should make this a method of the main game. 258 | Arguments: 259 | game -- main game object 260 | cause -- cause of death 261 | """ 262 | print_line("{} has died of {}!".format(self, cause)) 263 | if not isinstance(self, Player): 264 | pass 265 | else: 266 | self.alive = False 267 | 268 | 269 | class NPC(Human): 270 | """NPC class, inherits Human attributes.""" 271 | 272 | def __init__( 273 | self, first_name, day_of_birth, 274 | parent_1, parent_2, age, gender, surname=None): 275 | """NPC class constructor. 276 | 277 | Arguments: 278 | first_name -- first name of NPC 279 | day_of_birth -- day NPC was born on 280 | parent_1 -- father 281 | parent_2 -- mother 282 | age -- age of NPC 283 | gender -- gender of NPC 284 | """ 285 | Human.__init__( 286 | self, first_name, day_of_birth, 287 | parent_1, parent_2, age, gender, surname) 288 | self.current_activity = "" 289 | self.days_active = 0 290 | self.activity_limit = 0 291 | self.scavenging = False 292 | self.days_scavenging = 0 293 | self.days_to_scavenge_for = 0 294 | 295 | def level_up(self): 296 | super().level_up() 297 | for stat in choice_dict.keys(): 298 | print_line(" {}".format(stat), end = " ") 299 | choice = input("Please choose an attribute to level up: ") 300 | choice.lower() 301 | if choice in choice_dict: 302 | choice_dict[choice] += 1 303 | else: 304 | print_line("\nInvalid choice.\n") 305 | self.level -= 1 306 | self.level_up() 307 | 308 | class Player(Human): 309 | """Player class, inherits Human attributes.""" 310 | 311 | def __init__( 312 | self, first_name=None, day_of_birth=0, 313 | parent_1=None, parent_2=None, age=21, gender='M'): 314 | """Player class constructor. 315 | 316 | Arguments: 317 | first_name -- first name of Player 318 | day_of_birth -- day Player was born 319 | parent_1 -- father 320 | parent_2 -- mother 321 | age -- age of player 322 | gender -- gender of player 323 | """ 324 | Human.__init__( 325 | self, first_name, day_of_birth, 326 | parent_1, parent_2, age, gender) 327 | player_stats = ["medic", "crafting", "tactician", "cooking", 328 | "barter", "inspiration", "scrapper", 329 | "electrician"] 330 | for stat in player_stats: #Adds player specific stats to stat 331 | # dict 332 | self.stats[str(stat)] = 0 333 | """ 334 | self.medic = 0 # Improves healing capabilities of stimpacks 335 | self.crafting = 0 # Chance to not use components when crafting. 336 | self.tactician = 0 # Boosts defense. 337 | self.cooking = 0 # Boosts production level of kitchen. 338 | self.barter = 0 # Increases selling prices, decreases buying prices. 339 | self.inspiration = 0 # Boosts production and defense. 340 | self.scrapper = 0 # Boosts chance of bonus components when scrapping. 341 | self.electrician = 0 # Boosts power production 342 | """ 343 | 344 | def level_up(self): 345 | super().level_up() 346 | print_line("\n") 347 | print_line("You can level up any of these attributes: ") 348 | for stat in choice_dict.keys(): 349 | print_line(" {}".format(stat), end = " ") 350 | choice = input("Please choose an attribute to level up: ") 351 | choice.lower() 352 | perks = ["medic", "crafting", "tactitian", "cooking", 353 | "inspiration", "scrapper", "barter", "electrician"] 354 | #Perks specific to the player are added to the dictionary of 355 | #available choices 356 | for perk in perks: 357 | choice_dict[perk] = self.stats[perk] 358 | """ #Old choice_dict dictionary 359 | choice_dict = { 360 | 'strength':self.stats["strength"], 'perception':self.stats["perception"], 361 | 'endurance':self.stats["endurance"], 'charisma':self.stats["charisma"], 362 | 'intelligence':self.stats["intelligence"], 'luck':self.stats["luck"], 363 | 'medic':self.stats["medic"], 'crafting':self.stats["crafting"], 364 | 'tactician':self.stats["tactician"], 'cooking':self.stats["cooking"], 365 | 'inspiration':self.stats["inspiration"], 'scrapper':self.stats["scrapper"], 366 | 'barter':self.stats["barter"], 'electrician':self.stats["electician"] 367 | } 368 | """ 369 | if choice in choice_dict.keys(): 370 | choice_dict[choice] += 1 371 | else: 372 | print_line("Invalid choice") 373 | self.level -= 1 374 | self.level_up() 375 | -------------------------------------------------------------------------------- /Fallout_Shelter.py: -------------------------------------------------------------------------------- 1 | """Text-based Fallout Shelter game developed by T.G.""" 2 | 3 | """ 4 | MIT License 5 | 6 | Copyright (c) [year] [fullname] 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | """ 26 | 27 | 28 | from collections import OrderedDict 29 | from random import randint, randrange 30 | #from appdirs import user_data_dir 31 | import pickle 32 | import sys 33 | import os 34 | 35 | from Human import Human, Player, NPC 36 | from Room import Room, all_rooms 37 | from Item import Item, Inventory, all_items 38 | 39 | from general_funcs import * 40 | 41 | try: 42 | try: 43 | import readline 44 | except ImportError: 45 | import pyreadline as readline 46 | 47 | #if can't get any readline library, default to standard IO 48 | except ImportError: 49 | pass 50 | """ 51 | def save_file(): 52 | #Generate save file location/name based on system. 53 | 54 | #Returns: 55 | #str -- path to save file 56 | 57 | sfn = "fstb.p" 58 | if "-l" in sys.argv: 59 | sfp = os.path.split(os.path.abspath(sys.argv[0]))[0] 60 | else: 61 | appname = "Fallout-Shelter-Text-Based" 62 | sfp = user_data_dir(appname=appname, appauthor=False, roaming=True) 63 | return os.path.join(sfp, sfn) 64 | 65 | 66 | 67 | def load_game(_=None, save=_save_file): 68 | Load game from file, `load filename` to load from specific file. 69 | 70 | Arguments: 71 | save -- file to load from 72 | 73 | Returns: 74 | game -- Game object 75 | 76 | with open(save, "rb") as s: 77 | try: 78 | game = pickle.load(s) 79 | except pickle.UnpicklingError: 80 | print_line("Unable to load game.") 81 | return None 82 | print_line("Game loaded from {}.".format(save)) 83 | return game 84 | 85 | 86 | _save_file = save_file() 87 | """ 88 | 89 | class Game(object): 90 | """Main game class.""" 91 | 92 | def __init__(self): 93 | """Initilize main game system.""" 94 | self.setup_player() 95 | self.all_items = all_items() # Fetches all items from items.json 96 | self.all_rooms = all_rooms() # Fetches all items from rooms.json 97 | #player.inventory = Inventory(self.all_items) 98 | self.player.inventory['turret'] += 1 99 | self.player.inventory["steel"] += 5 100 | self.player.inventory["chip"] += 1 101 | #self.trader_inventory = Inventory(self.all_items) 102 | self.rooms = { 103 | 'living' : Room('living'), 104 | 'generator' : Room('generator'), 105 | 'water' : Room('water'), 106 | #'trader' : Room('trader'), 107 | 'kitchen' : Room('kitchen') 108 | } 109 | self.people = {} 110 | self.caps = 100 111 | self.trader_caps = 500 112 | self.happiness = 100 113 | self.action_points = 50 114 | self.defense = 0 115 | self.security = "secure" 116 | self.days = 1 117 | self.overuse = False # If player uses too many action points in one day. 118 | self.actions = OrderedDict() # [('action': function)] 119 | self.first_few() 120 | action_see_people(self) 121 | if check_built_room(self, "trader"): 122 | self = find_rand_items(self, 'trader', 10) 123 | 124 | self.actions["quit"] = action_quit 125 | self.actions["skip"] = None 126 | #self.actions["save"] = action_save 127 | #self.actions["load"] = load_game 128 | self.actions["help"] = action_help 129 | self.actions["see day"] = action_see_day 130 | self.actions["see people"] = action_see_people 131 | self.actions["see inventory"] = action_see_inventory 132 | self.actions["see items"] = action_see_inventory 133 | self.actions["see trader"] = action_see_inventory 134 | self.actions["see rooms"] = action_see_rooms 135 | self.actions["see resources"] = action_see_resources 136 | self.actions["auto assign all"] = action_auto_assign 137 | self.actions["trade"] = action_trade 138 | self.actions["craft"] = action_craft 139 | self.actions["rush"] = action_rush_room 140 | self.actions["assign"] = action_assign_to_room 141 | self.actions["unassign"] = action_unassign 142 | self.actions["auto feed all"] = action_auto_feed_all 143 | self.actions["coitus"] = action_coitus 144 | self.actions["build"] = action_build_room 145 | self.actions["fix"] = action_fix_room 146 | self.actions["heal"] = action_heal 147 | 148 | def add_action(self, name, action): 149 | """Add entries to the actions dictionary. 150 | 151 | Arguments: 152 | name -- name of action 153 | action -- function to execute 154 | """ 155 | self.actions[name] = action 156 | 157 | def setup_player(self): 158 | """Create player object.""" 159 | invalid_name = "Invalid name. Only one word is acceptable." 160 | while True: 161 | name = input("Choose a first name for yourself: ") 162 | if validate_name(name): 163 | first_name = name 164 | break 165 | print_line(invalid_name) 166 | while True: 167 | name = input("What is the surname of your father? ") 168 | if validate_name(name): 169 | father = Human(surname=name) 170 | break 171 | print_line(invalid_name) 172 | while True: 173 | name = input("What is the surname of your mother? ") 174 | if validate_name(name): 175 | mother = Human(surname=name) 176 | break 177 | print_line(invalid_name) 178 | while True: 179 | gender = input("Please enter your gender (M/F): ") 180 | if len(gender) >= 1 and gender[0].upper() in ("M", "F"): 181 | gender = gender[0].upper() 182 | break 183 | print_line("Invalid gender choice.") 184 | self.player = Player(first_name, 0, father, mother, 21, gender) 185 | 186 | def first_few(self): 187 | """Create first few inhabitants with random names.""" 188 | used_names = [] 189 | names = [ 190 | "Thompson", 191 | "Elenor", 192 | "Codsworth", 193 | "Sharmak", 194 | "Luthor", 195 | "Marshall", 196 | "Cole", 197 | "Diven", 198 | "Davenport", 199 | "John", 200 | "Max", 201 | "Lex", 202 | "Leth", 203 | "Exavor"] 204 | for person_name in self.people.keys(): 205 | used_names.append(person_name.split(" ")[0]) 206 | used_names.append(person_name.split(" ")[1]) 207 | load_time(100, "Populating vault with random inhabitants.") 208 | while len(self.people) < 5: 209 | num_1 = randint(0, len(names) - 1) 210 | num_2 = randint(0, len(names) - 1) 211 | if num_1 == num_2: 212 | continue 213 | if names[num_1] in used_names or names[num_2] in used_names: 214 | continue 215 | self.people["{} {}".format(names[num_1], names[num_2])] = NPC( 216 | names[num_1], 217 | self.days, 218 | None, 219 | "Alena", 220 | 21, 221 | get_gender(), 222 | names[num_2]) 223 | used_names.append(names[num_1]) 224 | used_names.append(names[num_2]) 225 | 226 | def storage_capacity(self): 227 | """Calculate max inventory capacity of player. 228 | 229 | Returns: 230 | capacity -- max inventory capacity of player 231 | """ 232 | capacity = self.rooms["storage"].production 233 | return capacity 234 | 235 | def use_points(self, number): 236 | """Remove action points from total. 237 | 238 | Arguments: 239 | number -- how many points to remove 240 | """ 241 | if self.action_points - number < 0: # If overuse occurs, i.e. if overuse is negative 242 | self.overuse = True 243 | self.overuse_amount = 0 - (self.action_points - number) 244 | self.action_points -= number 245 | 246 | def run(self, debug=False): 247 | """Main game. Once all values are initilized or loaded from a save file, this is run.""" 248 | action_help(self) # Initially prints the available commands. 249 | while True and self.player.alive: # Day loop 250 | self.action_points = 50 251 | if self.overuse: 252 | self.action_points -= self.overuse_amount 253 | 254 | load_time(100, " A new day dawns. It is now day {} in the vault".format( 255 | self.days)) 256 | print_line("\n") 257 | 258 | 259 | self = update_all_room_production(self) 260 | #Room loop 261 | for room in self.rooms.values(): 262 | if self.player.inventory['watt'] >= room.wattage: 263 | self.player.inventory['watt'] -= room.wattage #Use power 264 | if room.produce: 265 | self.player.inventory[room.produce] += room.production 266 | else: 267 | print_line("Not enough power to operate room: {}".format( 268 | room.name)) 269 | if room.rushed: 270 | room.rushed = False 271 | 272 | self = action_auto_feed_all(game) 273 | for person in self.people.values(): #People loop 274 | if person.check_xp(): 275 | person.level_up() 276 | person.increase_hunger(10) 277 | if person.hunger > 99: 278 | 279 | if self.assigned_room: 280 | self = unassign(self, str(person)) 281 | person.die(self, "hunger") 282 | 283 | elif person.hunger > 80: 284 | print_line( 285 | "Warning! {} is starving and may die soon".format( 286 | person)) 287 | elif person.hunger > 50: 288 | print_line("{} is hungry".format(person)) 289 | person.increase_thirst(20) 290 | 291 | if person.thirst > 99: 292 | if person.assigned_room: 293 | self = unassign(self, str(person)) 294 | person.die(self, "thirst") 295 | 296 | elif person.thirst > 80: 297 | print_line("Warning! {} is extremely thristy " + 298 | "and may die soon.".format(str(person))) 299 | elif person.thirst > 50: 300 | print_line("{} is thirsty".format(person)) 301 | if person.current_activity != "": 302 | if person.current_activity == "scavenging": 303 | person.take_damage(person, randint(0, 30)) 304 | if person.health < 20: 305 | pass # Need to end scavenging. 306 | elif person.current_activity == "guarding": 307 | pass 308 | if person.days_active == person.activity_limit: 309 | if person.current_activity == "scavenging": 310 | print_line("{} has come back from".format(person) + 311 | " scavenging and has found these items:") 312 | # Need to print items found. 313 | person.current_activity = "" 314 | person.active_days = 0 315 | person.activity_limit = 0 316 | else: 317 | person.days_active += 1 318 | 319 | if check_built_room(self, 'trader'): #Trader randomly loses and gains items daily 320 | if game.rooms['trader'].assigned: 321 | self = lose_items(self, 'trader', 10) 322 | self = find_rand_items(self, 'trader', 10) 323 | 324 | while self.action_points > 0: # Choice loop 325 | print_line("Action Points Remaining: {}".format(self.action_points)) 326 | a = input("Choose an action: ") 327 | if len(a) > 0: 328 | action, *args = a.split() 329 | if action.lower() == "skip": 330 | break 331 | elif action in ("trade", "assign", "unassign", \ 332 | "auto feed all", "auto assign all", "build", "craft",\ 333 | "fix", 'rush', 'coitus', 'heal'): 334 | try: 335 | self = self.actions[action](self, *args) 336 | except TypeError: 337 | print_line("Incorrect number of arguments") 338 | elif a in self.actions.keys(): 339 | try: 340 | self.actions[a](self, *args) 341 | except Exception as e: 342 | print_line("Error: {}".format(e)) 343 | elif action in ("save", "load"): 344 | self.actions[action](self, args[0]) 345 | 346 | else: 347 | print_line("Invalid action selected. Try again.") 348 | else: 349 | print_line("You have to choose a valid action.") 350 | self.days += 1 351 | 352 | 353 | def action_quit(*_): 354 | """Quit current game. 355 | 356 | Arguments: 357 | game -- main game object 358 | """ 359 | save = default_input("Quit without saving? (y/N) ") 360 | if save == "n": 361 | return 362 | else: 363 | sys.exit(0) 364 | 365 | """ 366 | def action_save(game, save=_save_file): 367 | Save current game state, `save filename` to save to specific file. 368 | 369 | Arguments: 370 | game -- game object to save 371 | save -- file to save to 372 | if os.path.exists(save): 373 | ow = default_input("{} already exists, overwrite? (Y/n) ".format(save)) 374 | if ow != 'y': 375 | return 376 | with open(save, "wb") as s: 377 | try: 378 | pickle.dump(game, s) 379 | except pickle.PicklingError: 380 | print_line("Unable to save game.") 381 | return 382 | print_line("Game has been saved to {}.".format(save)) 383 | """ 384 | 385 | def action_help(game): 386 | """See help for all actions available. 387 | 388 | Arguments: 389 | game -- main game object 390 | """ 391 | print_line('Actions:') 392 | lens = text_align(game.actions) 393 | for i, action in enumerate(game.actions.keys()): 394 | if action == "skip": 395 | desc = "Skip current day." 396 | else: 397 | desc = sentence_split(game.actions[action].__doc__) 398 | print_line('{}{}: {}'.format( 399 | action, 400 | ' ' * (2 + lens[i]), 401 | desc), 402 | speed=FAST) 403 | print_line("\n") 404 | 405 | 406 | def action_see_day(game, *args): 407 | """See current day number. 408 | 409 | Arguments: 410 | game -- main game object 411 | """ 412 | print_line("It is currently day number {} in the vault.".format(game.days)) 413 | 414 | 415 | def action_see_people(game, *args): 416 | """Display info of all inhabitants. 417 | 418 | Arguments: 419 | game -- Main game object 420 | """ 421 | game.player.print_() 422 | for person in game.people.values(): 423 | person.print_() 424 | 425 | 426 | def action_see_inventory(game, inventory): 427 | """See given inventory's contents. 428 | 429 | Arguments: 430 | game -- main game object 431 | inventory -- inventory to print 432 | """ 433 | inv = inventory.lower() 434 | if inv == "inventory": 435 | game.player.inventory.print_() 436 | elif inv == "trader": 437 | game.trader_inventory.print_() 438 | else: 439 | print("No inventory named '{}' exists.".format(inventory)) 440 | 441 | 442 | def action_see_rooms(game, *args): 443 | """Print each room with details. 444 | 445 | Arguments: 446 | game -- main game object 447 | """ 448 | game = update_all_room_production(game) 449 | for room in game.rooms.values(): 450 | room.print_() 451 | 452 | 453 | def action_see_resources(game, *args): 454 | """See available resources (food, water, and power). 455 | 456 | Arguments: 457 | game -- Main game object 458 | """ 459 | print_line("Food * ", game.player.inventory["food"]) 460 | print_line("Water * ", game.player.inventory["water"]) 461 | print_line("Power * ", game.player.inventory["watt"]) 462 | 463 | 464 | def living_capacity(game): 465 | """Get maximum inhabitant capacity of shelter. 466 | 467 | Arguments: 468 | game -- main game object 469 | 470 | Returns: 471 | int -- maximum capacity of shelter 472 | """ 473 | room = game.rooms["living"] 474 | print_line("Maximum number of inhabitants", 5 * room.level) 475 | return (5 * room.level) 476 | 477 | 478 | 479 | # Construction system: 480 | 481 | def action_build_room(game, room_name): 482 | #Need to check if player has the materials to build room 483 | """Build room specified. 484 | 485 | Arguments: 486 | game -- Main game object 487 | room_name -- name of room to build 488 | 489 | Returns: 490 | game -- Main game object 491 | """ 492 | if check_room(game, room_name): 493 | if not check_built_room(game, room_name): 494 | room = Room(str(room_name)) # creates a room. 495 | game.rooms[str(room_name)] = room # Stores the room in memory. 496 | load_time(50, "Building " + room_name) 497 | for y in room.components: # Does this for each component 498 | game.player.inventory[y] -= 1 499 | #game.player.gain_xp(100) #Commented out for now since levelling up 500 | # system doesn't work 501 | game.use_points(50) 502 | else: 503 | print_line("You've already built the {} room.".format(room_name.title())) 504 | else: 505 | print_line("{} isn't a valid room name.".format(room_name.title())) 506 | return game 507 | 508 | 509 | def action_craft(game, item_name): 510 | """Craft specified item. 511 | 512 | Arguments: 513 | game -- Main game object 514 | item_name -- name of item to craft 515 | 516 | Returns: 517 | game -- Main game object 518 | """ 519 | if can_craft_item(game, item_name): 520 | load_time(5, ("Crafting ", item_name)) 521 | game.player.inventory[item_name] += 1 522 | # Perk bonuses 523 | item = Item(item_name) 524 | chance = game.player.stats["crafting"] 525 | for component in item.components: 526 | if randint(1,101) > chance: 527 | #The higher the player's crafting level, the less 528 | #likely they are to lose their items. 529 | game.player.inventory[component] -= 1 530 | #game.player.gain_xp(item.rarity * 10) 531 | #game.use_points(5) 532 | return game 533 | 534 | def action_scrap(game, item): 535 | """Deletes an item from the inventory and adds it's components to the inventory 536 | 537 | Arguments: 538 | game -- Main game object 539 | item -- name of item being scrapped 540 | 541 | Returns: 542 | game -- Main game object 543 | """ 544 | it = Item(item) 545 | for component in it.components: 546 | game.player.inventory[component] += 1 547 | game.player.inventory[item] -= 1 548 | return game 549 | 550 | 551 | 552 | 553 | # Human management system: 554 | 555 | def get_gender(): 556 | """Randomly generate gender for NPC. 557 | 558 | Returns: 559 | char -- 'm' or 'f' 560 | """ 561 | if randint(0, 1) == 0: 562 | return "m" 563 | else: 564 | return "f" 565 | 566 | def check_person(game, name): 567 | """Check if inhabitant exists in list of all inhabitants. 568 | 569 | Arguments: 570 | game -- Main game object 571 | name -- full name of person 572 | 573 | Returns: 574 | bool -- whether inhabitant exists or not 575 | """ 576 | #print("Checking to see if {} exists".format(name.title())) 577 | if name.title() in game.people.keys(): 578 | return True 579 | else: 580 | print_line("{} {} does not exist").format(name.split()[0], name.split()[1]) 581 | return False 582 | 583 | 584 | def action_assign_to_room(game, *args): 585 | """ Assign a person to a room. 586 | In the form "assign first_name surname to room" 587 | 588 | Arguments: 589 | game -- main game object 590 | first_name -- first_name of person 591 | surname -- surname of person 592 | room -- room to assign to 593 | 594 | Returns: 595 | game -- Main game object 596 | """ 597 | 598 | if (len(args) == 4) and (args[2] == "to"): 599 | if check_person(game, str(args[0]) + " " + str(args[1])): 600 | if check_built_room(game, args[3]): 601 | game = assign_to_room(game, 602 | args[0].title() + " " + args[1].title(), 603 | args[3]) 604 | else: 605 | if not check_room(game, args[3]): 606 | print_line("This room doesn't exist") 607 | else: 608 | print_line("You need to build the {} room".format(args[4])) 609 | else: 610 | print_line("Invalid syntax. Must be in form of (assign cole leth to living)") 611 | return game 612 | 613 | def assign_to_room(game, person_name, room_name): 614 | """Assign Human to room, assuming all inputted arguments are valid. 615 | 616 | Arguments: 617 | game -- Main game object 618 | person_name -- full name of person being assigned (with first letter's capitalized) 619 | room_name -- name of room to assign to 620 | 621 | """ 622 | room = game.rooms[room_name] 623 | person = game.people[person_name] 624 | if room.count_assigned() < room.assigned_limit: 625 | if person.assigned_room: #If person is already assigned to a room, unassigns them. 626 | game = unassign(game, person_name) 627 | room.assigned.append(person_name) 628 | person.assigned_room = room_name 629 | game.use_points(1) 630 | print_line("{} has been assigned to the {}".format(person_name, str(room))) 631 | else: 632 | print("The {} has {} people assigned and can hold no more".format(str(room), room.count_assigned())) 633 | return game 634 | 635 | def action_unassign(game, *args): 636 | """ Unassigns person from their room. 637 | Checks to see if all arguments are valid, then passes them to 638 | unassing() function. Only called by the player. 639 | 640 | Arguments: 641 | game -- main game object 642 | name -- name of person to unassign 643 | 644 | Returns: 645 | game -- Main game object 646 | 647 | """ 648 | name = str(args[0] + " " + args[1]).title() 649 | print("Input name is", name) 650 | if len(name.split()) == 2: 651 | if check_person(game, name): 652 | game = unassign(game, name) 653 | print_line("{} has been unassigned from their room.".format(name)) 654 | else: 655 | print_line("The name must be of type: 2 words") 656 | return game 657 | 658 | def unassign(game, name): 659 | """ Unassigns person from their room. 660 | 661 | Arguments: 662 | game -- main game object 663 | name -- name of person to unnassign 664 | 665 | Returns: 666 | game -- Main game object 667 | 668 | """ 669 | name.title() 670 | person = game.people[name] 671 | room = game.rooms[person.assigned_room] 672 | person.assigned_room = "" 673 | room.assigned.remove(name) 674 | return game 675 | 676 | def action_coitus(game, *args): 677 | """Have two adults try for a child. 678 | 679 | Arguments: 680 | game -- main game object 681 | parent_1 -- name of first parent 682 | parent_2 -- name of second parent 683 | 684 | Returns: 685 | game -- main game object 686 | """ 687 | if len(args) > 1: 688 | print(args) 689 | print(args[0]) 690 | 691 | # if args[-1] == args[3]: 692 | parent_1_name = (args[0] + " " + args[1]).title() 693 | print("parent name:", parent_1_name) 694 | if check_person(game, parent_1_name): 695 | parent_1 = game.people[parent_1_name] 696 | parent_2_name = (args[2] + " " + args[3]).title() 697 | if check_person(game, parent_2_name): 698 | parent_2 = game.people[parent_2_name] 699 | person = create_npc(parent_1, parent_2,game.days) 700 | game.people[str(person)] = person 701 | parent_1.children.append(person.name + " " + parent_1.surname) 702 | parent_2.children.append(person.name + " " + parent_1.surname) 703 | parent_1.partner = parent_2.name + " " + parent_2.surname 704 | parent_2.partner = parent_1.name + " " + parent_1.surname 705 | if game.days > 2: # First few births cost no points 706 | use_points(50) 707 | # else: 708 | # print_line("Invalid input. You have to input two names") 709 | return game 710 | 711 | def create_npc( 712 | parent_1, 713 | parent_2, 714 | day_count): 715 | """Create new child inhabitant. 716 | 717 | Arguments: 718 | parent_1 -- parent of new child 719 | parent_2 -- parent of new child 720 | 721 | Returns: 722 | person -- New NPC 723 | """ 724 | while True: 725 | name = input("Choose a first name for the new child: ") 726 | if len(name.split()) == 1: # Player can only input one word 727 | name = name.title() # Capitalizes first letter 728 | if parent_2.gender == "m": 729 | parent_1, parent_2 = parent_2, parent_1 #Ensure father 730 | #is parent_1, for surname purposes. 731 | person = NPC( 732 | name, 733 | day_count, 734 | parent_1, 735 | parent_2, 736 | 0, 737 | get_gender()) 738 | load_time(50, (name.title() + " is being born!")) 739 | return person 740 | else: 741 | print_line("You have to input a single word!") 742 | 743 | def create_player(): 744 | """Create player inhabitant. 745 | 746 | Returns: 747 | Player -- player object 748 | """ 749 | while True: 750 | name = input("Choose a first name for yourself: ") 751 | if len(name) <= 0: 752 | print_line("You need a name!") 753 | elif len(name.split()) != 1: 754 | print_line("Only single word inputs are accepted.") 755 | else: 756 | name = name.title() 757 | break 758 | while True: 759 | parent_1 = input("What is the surname of your father? ") 760 | if len(parent_1) <= 0: 761 | print_line("Your father needs a surname!") 762 | elif len(parent_1.split()) != 1: 763 | print_line("Only single word inputs are accepted.") 764 | else: 765 | parent_1 = parent_1.title() 766 | break 767 | while True: 768 | parent_2 = input("What is the surname of your mother? ") 769 | if len(parent_2) <= 0: 770 | print_line("Your mother needs a surname!") 771 | elif len(parent_2.split()) != 1: 772 | print_line("Only single word inputs are accepted.") 773 | else: 774 | parent_2 = parent_2.title() 775 | break 776 | while True: 777 | gender = input("What is your gender?(m/f) ") 778 | if len(gender) == 0: 779 | print_line("You need a gender.") 780 | elif gender[0].lower() not in ("m", "f"): 781 | print_line("Invalid input. Only accepts 'm' or 'f'.") 782 | else: 783 | gender = gender[0].lower() 784 | break 785 | 786 | return Player( 787 | name, 788 | 0, 789 | parent_1, 790 | parent_2, 791 | 21, 792 | gender) 793 | 794 | def action_auto_assign(game, *args): 795 | """Automatically assign inhabitants to rooms. 796 | 797 | Arguments: 798 | game -- Main game object 799 | """ 800 | while True: 801 | for room in game.rooms.values(): 802 | if room.count_assigned() < room.assigned_limit: 803 | for person in game.people.values(): 804 | if not person.assigned_room: 805 | break 806 | game = assign_to_room(game, str(person), room.name) 807 | unemployed_count = 0 808 | for person in game.people.values(): 809 | if not person.assigned_room: 810 | unemployed_count +=1 811 | if unemployed_count == 0: 812 | break 813 | return game 814 | 815 | def action_heal(game, *args): 816 | """ Heal an inhabitant. 817 | Player chooses to heal an inhabitant, possibly themselves. 818 | In the form (heal Thomas Paine by 10) 819 | 820 | Arguments: 821 | game -- Main game object 822 | first_name -- first_name of person 823 | surname -- surname of person 824 | amount -- base amount they want to heal by 825 | 826 | Returns: 827 | game -- Main game object 828 | """ 829 | player = game.player() 830 | if len(args) > 0 and len(args.split()) == 4: 831 | name = args[0] + " " + args[1] 832 | if check_person(game, name): 833 | person = game.people[name] 834 | try: 835 | amount = int(args[-1]) 836 | if player.medic > 0: # Medic Boost. 837 | amount = amount * (1 + (0.05 * player.medic)) 838 | if person.HP == person.max_HP(): 839 | print_line("{} is already at max health.".format(person)) 840 | else: 841 | person.heal(amount) 842 | except: 843 | print_line("You can only heal by an integer amount") 844 | else: 845 | print_line("Heal command must be in form: heal Thomas Paine by \ 846 | 10 ") 847 | return game 848 | 849 | 850 | 851 | # Room Management system: 852 | 853 | def action_rush_room(game, room): 854 | """Rush a room in the game. 855 | 856 | Arguments: 857 | game -- Main game object 858 | room -- name of room to rush 859 | 860 | Returns: 861 | game -- main game object 862 | """ 863 | try: 864 | room = game.rooms[room] 865 | except KeyError: 866 | print_line("No such room!") 867 | return game 868 | 869 | if not room.can_rush: 870 | print_line("Cannot rush {}".format(room)) 871 | return game 872 | 873 | room.rush() 874 | 875 | random = randint(0,101) 876 | if random < room.risk: 877 | print_line(" The {} room has been broken.".format(room.name)) 878 | room.broken = True 879 | else: 880 | room.rushed = True 881 | return game 882 | 883 | def check_room(game, room): 884 | """Check if room exists. 885 | 886 | Arguments: 887 | game -- main game object 888 | room -- room to check for 889 | 890 | Returns: 891 | bool -- whether room exists or not 892 | """ 893 | if room in game.all_rooms: 894 | return True 895 | return False 896 | 897 | 898 | def check_built_room(game, room): 899 | """Check if room has been built yet. 900 | 901 | Arguments: 902 | game -- main game object 903 | room -- room to check for 904 | 905 | Returns: 906 | bool -- whether room has been built or not 907 | """ 908 | if room in game.rooms: 909 | return True 910 | print("{} has not been built yet".format(room)) 911 | return False 912 | 913 | 914 | def can_use_power(game, room): 915 | """ 916 | Determine whether the room may use power or not. 917 | 918 | Arguments: 919 | game -- main game object 920 | room - room which uses power 921 | 922 | Returns: 923 | bool -- whether room may use power 924 | """ 925 | if game.player.inventory["watt"] > room.power_usage: 926 | return True 927 | else: 928 | return False 929 | 930 | 931 | def power_usage(game): 932 | """Check total power needed. 933 | 934 | Arguments: 935 | game -- main game object 936 | 937 | Returns: 938 | total -- total power needed by all rooms 939 | """ 940 | total = 0 941 | for room in game.rooms: 942 | total += room.power_usage 943 | return total 944 | 945 | 946 | def power_production(game): 947 | """Check total power being produced. 948 | 949 | Arguments: 950 | game -- main game object 951 | 952 | Returns: 953 | production -- total amount of power being produced 954 | """ 955 | generator = game.rooms['generator'] 956 | return generator.production 957 | 958 | def action_fix_room(game, room_name): 959 | """Tries to fix room. 960 | Arguments: 961 | game -- Main game object 962 | room_name -- Name of room to try to fix 963 | 964 | Returns: 965 | game -- Main game object 966 | """ 967 | if check_room(game, room_name): 968 | if check_built_room(game, room_name): 969 | room = game.rooms[room_name] 970 | if room.broken: 971 | can_fix = True 972 | items_needed = Inventory(game.all_items) 973 | for component in room.components: 974 | if randrange(0,1) == 0: 975 | items_needed[component] += 1 976 | for item_needed in items_needed.keys(): 977 | if game.player.inventory[item_needed] \ 978 | < items_needed[item_needed]: 979 | can_fix = False 980 | print_line("You don't have enough {} to fix\ 981 | {} room".format(item_needed, room_name)) 982 | if can_fix: 983 | room.fix() 984 | else: 985 | print_line("{} room doesn't need to be fixed".format(room_name)) 986 | else: 987 | print_line("You haven't built the {} room yet".format(room_name)) 988 | else: 989 | print_line("Invalid room name: {}".format(room_name)) 990 | return game 991 | 992 | def update_all_room_production(game): 993 | for room in game.rooms.values(): 994 | production = 0 995 | if room.broken: 996 | print_line(room.name, "is broken and needs to be fixed.") 997 | else: 998 | player = game.player 999 | if room.attribute: 1000 | attribute = room.attribute 1001 | for person_name in room.assigned: 1002 | person = game.people[person_name] 1003 | for stat in person.stats: 1004 | if stat == attribute: 1005 | level = person.stats[stat] 1006 | production += level 1007 | production += 1 1008 | 1009 | if room.perk: #Some player perks improve production. 1010 | value = game.player.stats[room.perk] 1011 | production = production * (1 + (value * 0.05)) 1012 | 1013 | if player.stats["inspiration"] > 0: 1014 | production = production * \ 1015 | (1 + (player.inspiration * 0.03)) 1016 | if room.can_rush: 1017 | if room.rushed: 1018 | production = production * 2 1019 | 1020 | room.production = production * 10 1021 | return game 1022 | 1023 | 1024 | # Inventory managment system: 1025 | 1026 | 1027 | def count_weight(game): 1028 | """Calculate weight of all items in inventory. 1029 | 1030 | Arguments: 1031 | game -- main game object 1032 | 1033 | Returns: 1034 | weight -- weight of all items in inventory 1035 | """ 1036 | weight = 0 1037 | for x in game.player.inventory: 1038 | weight += Item(x).weight 1039 | return weight 1040 | 1041 | 1042 | def find_rand_items(game, inven, num): 1043 | """Find random items and add them to inventory. 1044 | 1045 | Arguments: 1046 | game -- main game object 1047 | inven -- inventory to add items to 1048 | items -- how many items to add 1049 | 1050 | Returns: 1051 | game -- with all items added. 1052 | """ 1053 | for x in range(num): 1054 | # Following lines randomly choose an item, based on rarity 1055 | rand_num = randint(1, 1024) 1056 | lst = [2**a for a in range(0, 11)] 1057 | rarity = 1 1058 | for chance in lst: 1059 | if rand_num < chance: 1060 | break 1061 | rarity += 1 1062 | # Determines the rarity of an item. 50% chance it's a level 1, 1063 | # 25% chance it's a level 2, 12.5% chance it's a level 3 and so on. 1064 | 1065 | # Stores each item if the rarity level matches what was randomly picked 1066 | possible_items = [] 1067 | for it in game.all_items: 1068 | if Item(it).rarity == rarity: 1069 | possible_items.append(it) 1070 | if len(possible_items) > 0: 1071 | actual_item = possible_items[randint(0, len(possible_items) - 1)] 1072 | # Following lines actually store the item in memory 1073 | if inven == "player": 1074 | game.player.inventory[actual_item] += 1 1075 | elif inven == "trader": 1076 | game.trader_inventory[actual_item] += 1 1077 | return game 1078 | 1079 | 1080 | def add_to_inven(game, item, number, inven): #Shouldn't need this anymore 1081 | """Add given item to inventory. 1082 | 1083 | Arguments: 1084 | x -- item to add to inventory 1085 | number -- amount of item to add to inventory 1086 | inven -- inventory to add item to 1087 | """ 1088 | item = str(item) 1089 | inven = str(inven) 1090 | if inven == "player": 1091 | for y in range(number): 1092 | pass 1093 | elif inven == "trader": 1094 | for y in range(number): 1095 | pass 1096 | return game 1097 | 1098 | 1099 | def list_of_items(game, inven): 1100 | """Returns a flat list of every item present in the chosen inventory 1101 | 1102 | Arguments: 1103 | game -- Main game object 1104 | inven -- chosen inventory to search 1105 | 1106 | Returns: 1107 | list -- all the items found in the inventory. 1108 | """ 1109 | found_items = [] 1110 | if inven == "player": 1111 | for item, num in game.player.inventory.items(): 1112 | if num > 0: 1113 | found_items.append(item) 1114 | elif inven == "trader": 1115 | for item, num in game.trader_inventory.items(): 1116 | if num > 0: 1117 | found_items.append(item) 1118 | return found_items 1119 | 1120 | 1121 | def can_craft_item(game, item_name): 1122 | """Checks to see if an item can be built 1123 | 1124 | Arguments: 1125 | game -- main game object 1126 | item -- name of item to check 1127 | 1128 | Returns: 1129 | bool -- Whether or not item can be crafted 1130 | """ 1131 | item = Item(str(item_name)) 1132 | can_craft = True 1133 | checked_components = [] 1134 | 1135 | #handle case where item is not in items.json 1136 | if not hasattr(item, 'components'): 1137 | return False 1138 | for component in item.components: 1139 | if component not in checked_components: 1140 | number_needed = item.components.count(component) 1141 | number_available = game.player.inventory[component] 1142 | if number_needed > number_available: 1143 | can_craft = False 1144 | print_line("You need {} more {} to craft this item"\ 1145 | .format(number_needed - number_available, component)) 1146 | checked_components.append(component) 1147 | checked_components.append(component) 1148 | return can_craft 1149 | 1150 | def lose_items(game, inven, number): 1151 | """Randomly delete multiple items from inventory. 1152 | 1153 | Arguments: 1154 | game -- main game object 1155 | inven -- inventory to delete items from 1156 | number -- amount of items to delete 1157 | 1158 | Returns: 1159 | game -- with less items in selected inventory 1160 | """ 1161 | if inven == "trader": 1162 | for x in range(number): 1163 | items_available = list_of_items(game, "trader") 1164 | item = items_available[randint(0, len(items_available) - 1)] 1165 | game.player.inventory[item] -= 1 1166 | elif inven == "player": 1167 | for x in range(number): 1168 | items_available = list_of_items(game, "player") 1169 | item = items_available[randint(0, len(items_available) - 1)] 1170 | game.trader_inventory[item] -= 1 1171 | else: 1172 | print_line("Major bug in item losing system. Please contact dev!") 1173 | return game 1174 | 1175 | 1176 | def action_scrap(game, item): 1177 | """Scrap item and recieve its components. 1178 | 1179 | Arguments: 1180 | game -- main game object 1181 | item -- item to scrap 1182 | 1183 | Returns: 1184 | game -- with the item removed and it's components added to the 1185 | """ 1186 | if item not in game.all_items: 1187 | print_line( 1188 | "Bug with item scrapping system.", 1189 | "Invalid argument passes to function. Please contact dev.") 1190 | else: 1191 | game.player.inventory[item] -= 1 1192 | item = Item(item) 1193 | for component in item.components: 1194 | game.player.inventory[component] += 1 1195 | use_points(2) 1196 | return game 1197 | 1198 | # Raiding system: 1199 | 1200 | 1201 | def raid(game): 1202 | """Force raid on shelter. 1203 | 1204 | Arguments: 1205 | game -- main game object 1206 | """ 1207 | game = update_defense(game) 1208 | raiders = ["Super Mutant", "Raider", "Synth", "Feral Ghoul"] 1209 | raider_index = randint(0, len(raiders)) 1210 | raider = raiders[raider_index] # Randomly chooses a raider party. 1211 | max_attack = days // 5 1212 | attack_power = randint(1, max_attack) 1213 | load_time(10, ("There was a " + raider + " raid on your shelter!")) 1214 | print_line("The total enemy power was ", attack_power) 1215 | print_line("Your total defenses are ", defense) 1216 | if defense > attack_power: 1217 | print_line("Your defenses were strong enough to send them packing!") 1218 | else: 1219 | loss = attack_power - defense 1220 | lose_items("player", loss) 1221 | if loss > 10: 1222 | death_chance = loss // 10 1223 | dice = randint(2, 25) 1224 | if death_chance < dice: 1225 | # Death 1226 | # The player can't die in a raid! 1227 | possible_deaths = people[1, len(game.people) - 1] 1228 | death_number = randint(len(possible_deaths)) 1229 | print_line( 1230 | possible_deaths[death_number] + 1231 | " has been killed in a raid") 1232 | # dead_person = game.people[death_number] 1233 | game = death(game, dead.person.name) 1234 | for person in game.people: # Survivors gain xp 1235 | person.gain_xp(attack_power * 10) 1236 | use_points(30) 1237 | return game 1238 | 1239 | 1240 | def update_defense(game): 1241 | """Update defense of shelter based on guns and turrets in inventory.""" 1242 | player = game.player 1243 | game.defense = 0 1244 | turret_count = game.player.inventory["turret"] 1245 | game.defense += 10 * turret_count 1246 | gun_count = game.player.inventory["gun"] 1247 | game.defense += gun_count 1248 | # Add cases for more items that increase defense 1249 | strength_sum = 0 1250 | for person in game.people.values(): 1251 | strength_sum += person.stats["strength"] 1252 | game.defense += strength_sum 1253 | if game.player.tactician > 0: 1254 | game.defense = defense * (1 + (player.tactician * 0.05)) 1255 | if game.player.inspiration > 0: 1256 | game.defense = defense * (1 + (player.inspiration * 0.03)) 1257 | return game 1258 | 1259 | # Happiness System: 1260 | 1261 | def avg_hunger(game): 1262 | """Calculate average hunger level of all inhabitants. 1263 | 1264 | Returns: 1265 | avg -- average hunger level 1266 | """ 1267 | total = 0 1268 | for person in game.people.values(): 1269 | total += person.hunger 1270 | avg = total // len(game.people) 1271 | return avg 1272 | 1273 | 1274 | def avg_thirst(game): 1275 | """Calculate average thirst level of all inhabitants. 1276 | 1277 | Returns: 1278 | avg -- average thirst level 1279 | """ 1280 | total = 0 1281 | for person in game.people.values(): 1282 | total += person.thirst 1283 | avg = total // len(game.people) 1284 | return avg 1285 | 1286 | 1287 | 1288 | def action_auto_feed_all(game, *args): 1289 | """Automatically feed all inhabitants.""" 1290 | food_count = game.player.inventory["food"] 1291 | water_count = game.player.inventory["water"] 1292 | load_time(200, "Feeding all inhabitants.") 1293 | while game.player.inventory["food"] > 0 and avg_hunger(game) > 1: 1294 | for person in game.people.values(): 1295 | person.feed(1) 1296 | game.player.inventory["food"] -= 1 1297 | while game.player.inventory["water"] > 0 and avg_thirst(game) > 1: 1298 | for person in game.people.values(): 1299 | person.drink(1) 1300 | game.player.inventory["water"] -= 1 1301 | return game 1302 | 1303 | 1304 | def happiness_loss(): 1305 | """Decrease overall happiness level based on overall hunger and thirst.""" 1306 | global happiness 1307 | loss = 0 1308 | for y in range(30, 101, 10): 1309 | if avg_hunger() < y: 1310 | loss += y - 30 1311 | break 1312 | for y in range(30, 101, 10): 1313 | if avg_thirst() < y: 1314 | loss += y - 30 1315 | break 1316 | if loss > 0: 1317 | happiness -= loss 1318 | print_line( 1319 | "Due to your inhabitants being hungry and/or thirsty the " + 1320 | "shelter's overall happiness has dropped to ", 1321 | happiness) 1322 | 1323 | # Trading system: 1324 | 1325 | 1326 | def action_trade(game): 1327 | """Trading system.""" 1328 | can_trade = True 1329 | if not check_built_room(game, 'trader'): 1330 | print_line("You need to build a trader room") 1331 | return game 1332 | 1333 | trader_room = game.rooms['trader'] 1334 | if not trader_room.assigned: #If trader_room.assigned is empty. 1335 | print_line("There's no one assigned to the trader room!") 1336 | return game 1337 | 1338 | load_time(100, "Initializing trading system.") 1339 | while True: 1340 | print_line("") 1341 | print_line("Here are the traders' items: ") 1342 | action_see_inventory(game, "trader") 1343 | print_line("\nThe trader has " + str(game.trader_caps) + " caps.") 1344 | 1345 | print_line("\nHere are your items: ") 1346 | action_see_inventory(game, "inventory") 1347 | print_line("\nYou have " + str(game.caps) + " caps.") 1348 | 1349 | print_line( 1350 | "\nFor instance, input (buy 5 food) if you want to buy 5 " + 1351 | "units of food. Or input (end) to stop trading.") 1352 | a = input("What trade would you like to make? ") 1353 | if len(a) < 1: 1354 | print_line("You have to input something") 1355 | continue 1356 | 1357 | cmd, *args = a.split() 1358 | cmd = cmd.lower() 1359 | if cmd not in ('buy', 'sell', 'end', 'stop'): 1360 | print_line("Invalid Input, you can (buy), (sell) or (end) the trade") 1361 | continue 1362 | 1363 | if cmd in ('end', 'stop'): 1364 | break 1365 | 1366 | #if a number of items is not given, default to 1 1367 | if len(args) == 1: 1368 | args = [1] + args 1369 | 1370 | if len(args) != 2: 1371 | print_line("Invalid number of arguments") 1372 | continue 1373 | 1374 | num, item = args 1375 | 1376 | if item not in game.all_items: 1377 | print_line("This item doesn't exis") 1378 | continue 1379 | try: 1380 | num = int(num) 1381 | except ValueError: 1382 | print_line("You have to input a number as the second word") 1383 | continue 1384 | 1385 | cost = Item(item).value 1386 | total_cost = cost * num 1387 | print_line("Cost of all items: ", total_cost) 1388 | if cmd == "buy": 1389 | # Adjusts the prices, depending on player's bartering level. 1390 | total_cost = int(total_cost * (1.2 - (game.player.stats['barter'] * 0.05))) 1391 | if total_cost > game.caps: 1392 | print_line("You can't afford that!") 1393 | continue 1394 | 1395 | count = game.trader_inventory[item] 1396 | 1397 | if num > count: # If trader doesn't have enough. 1398 | if count < 1: 1399 | print_line( "The trader doesn't have any {}".format(item)) 1400 | else: 1401 | print_line( "The trader doesn't have {} of {}".format(num, item)) 1402 | continue 1403 | 1404 | for x in range(num): 1405 | game.trader_inventory[item] -= 1 1406 | game.player.inventory[item] += 1 1407 | 1408 | game.caps -= total_cost 1409 | game.trader_caps += total_cost 1410 | 1411 | elif cmd == "sell": 1412 | # Adjusts the prices, depending on bartering level. 1413 | total_cost = int(total_cost * (0.8 + (game.player.stats['barter'] * 0.05))) 1414 | print("Total cost is " + str(total_cost)) 1415 | if total_cost > game.trader_caps: 1416 | print_line("The trader can't afford that!") 1417 | continue 1418 | 1419 | count = game.player.inventory[item] 1420 | if num > count: # If player doesn't have enough of the item to sell. 1421 | if count < 1: 1422 | print_line( "You don't have any {}".format(item)) 1423 | else: 1424 | print_line( "You don't have {} of {}".format(num, item)) 1425 | continue 1426 | 1427 | for x in range(num): 1428 | game.player.inventory[item] -= 1 1429 | game.trader_inventory[item] += 1 1430 | 1431 | game.caps += total_cost 1432 | game.trader_caps -= total_cost 1433 | print_line("Ending trade") 1434 | return game 1435 | 1436 | """ 1437 | def choice(): # Need to move these commands into Game() class 1438 | a = input("Choose what to do: ") 1439 | # From here on out, a.split()[0] is used to cut out the first word of the 1440 | # input and compare it individually. 1441 | if len(a) > 0: 1442 | # Allows player to build new rooms. Checks if player has components to 1443 | # build room. 1444 | if a.split()[0] == "build": 1445 | potential_room = '' 1446 | for x in a.split()[1:]: 1447 | if len(potential_room) == 0: 1448 | potential_room = x 1449 | else: 1450 | potential_room = potential_room + " " + x 1451 | # print_line("The potential room is",potential_room) 1452 | if len(a.split()) < 2: 1453 | print_line( 1454 | "You have to input 2 or more " + 1455 | "words to build a room.") 1456 | elif not check_room(potential_room): 1457 | print_line("Checking for room:", potential_room) 1458 | print_line("This room doesn't exist.") 1459 | elif check_built_room(potential_room): 1460 | print_line("You've already built this room.") 1461 | else: 1462 | room = Room(potential_room, player) 1463 | checked = [] 1464 | can_craft = True 1465 | for component in room.components: 1466 | if component not in checked: 1467 | if room.count_component(component) > \ 1468 | count_item(game, component, "player"): 1469 | print_line( 1470 | "You don't have enough", 1471 | component, 1472 | "to build", 1473 | potential_room) 1474 | can_craft = False 1475 | # break #I don't break so the users will see 1476 | # everything they don't have. 1477 | checked.append(component) 1478 | if can_craft: 1479 | print_line("You have built a", a.split()[1]) 1480 | player = player 1481 | build(potential_room, player) 1482 | 1483 | elif a.split()[0] == "craft": 1484 | # Checks to see if crafting possible. 1485 | if a.split()[1] not in all_items: 1486 | print_line("Invalid item. Try again.") 1487 | else: 1488 | can_craft = True 1489 | # Creates an instance of the item, so it's attributes can be 1490 | # fetched. 1491 | actual_item = Item(a.split()[1]) 1492 | if len(actual_item.components) == 0: 1493 | print_line( 1494 | "This is a basic item and " + 1495 | "so cannot be crafted.") 1496 | else: 1497 | checked = [] 1498 | for component in actual_item.components: 1499 | if component not in checked: 1500 | number_available = count_item(game, component, "player") 1501 | number_needed = actual_item.count_component( 1502 | component) 1503 | if number_needed > number_available: 1504 | print_line( 1505 | "You don't have enough", 1506 | component, 1507 | "to craft", 1508 | a.split()[1]) 1509 | can_craft = False 1510 | checked.append(component) 1511 | if can_craft: 1512 | print_line("You have crafted a", a.split()[1]) 1513 | craft(a.split()[1]) 1514 | 1515 | elif a.split()[0] == "scrap": 1516 | if len(a.split()) == 2: # Only scrap item once. 1517 | if a.split()[1] not in all_items: 1518 | print_line("Invalid item. Please try again.") 1519 | else: 1520 | count = count_item(game, str(a.split()[1]), "player") 1521 | if count > 0: 1522 | scrap(a.split()[1]) 1523 | else: 1524 | print_line("You don't have that item.") 1525 | elif len(a.split()) == 3: # Scrap multiple times 1526 | if a.split()[1] in range(1, 100): 1527 | if a.split()[2] in all_items: 1528 | count = count_item(game, str(a.split()[1]), "player") 1529 | if count >= a.split()[1]: 1530 | for x in range(a.split()[1]): 1531 | scrap(a.split()[2]) 1532 | else: 1533 | print_line( 1534 | "You don't have enough of these items " + 1535 | "to scrap that many times.") 1536 | else: 1537 | print_line("This item doesn't exist.") 1538 | else: 1539 | print_line( 1540 | "Invalid input.", 1541 | "You can scrap an item up to 99 times " + 1542 | "(If you have that many).") 1543 | else: 1544 | print_line( 1545 | "Invalid Input.", 1546 | "Either enter (scrap wood) " + 1547 | "or (scrap 5 wood)") 1548 | 1549 | elif a.split()[0] == "rush": # Speeds up room tempoarily. 1550 | potential_room = '' 1551 | for x in a.split()[1:]: 1552 | if len(potential_room) == 0: 1553 | potential_room = x 1554 | else: 1555 | potential_room = potential_room + " " + x 1556 | if not check_room(potential_room): 1557 | print_line("This room doesn't exist.") 1558 | elif not check_built_room(potential_room): 1559 | print_line("You haven't built this room yet.") 1560 | elif Room(potential_room).can_rush: 1561 | print_line("This room cannot be rushed") 1562 | elif Room(potential_room).rushed: 1563 | print_line("This room has already been rushed.") 1564 | else: 1565 | room = rooms[get_room_index(potential_room)] 1566 | # Chance that the rush fails and the room tempoarily breaks. 1567 | chance = randint(0, 9) 1568 | if room.risk > chance: 1569 | print_line(room.name, " has failed to rush and is broken!") 1570 | room.broken = True 1571 | else: 1572 | check = input( 1573 | "Are you sure?", 1574 | room.name, 1575 | "has a", 1576 | room.risk * 10, 1577 | "% chance of breaking.") 1578 | if len(check) > 0: 1579 | if check[0].lower() == "y": 1580 | room.rush() 1581 | else: 1582 | print_line("Rush failed.") 1583 | else: 1584 | print_line("Rush failed.") 1585 | elif a.split()[0] == "fix": 1586 | potential_room = '' 1587 | for x in a.split()[1:]: 1588 | if len(potential_room) == 0: 1589 | potential_room = x 1590 | else: 1591 | potential_room = potential_room + " " + x 1592 | if not check_room(potential_room): 1593 | print_line("This room doesn't exist.") 1594 | elif not check_built_room(potential_room): 1595 | print_line("You haven't built this room yet.") 1596 | elif not rooms[get_room_index(potential_room)].broken: 1597 | print_line( 1598 | "This room isn't even broken. " + 1599 | "There's no need to fix it!") 1600 | else: 1601 | room = rooms[get_room_index(potential_room)] 1602 | can_fix = True 1603 | items_needed = [] 1604 | for it in room.components: 1605 | chance = randint(0, 1) 1606 | if chance: 1607 | items_needed.append(it) 1608 | checked_items = [] 1609 | for it in items_needed: 1610 | if it not in checked_items: 1611 | available = count_item(game, it, 'player') 1612 | needed = room.count_component(it) 1613 | if needed > available: 1614 | print_line( 1615 | "You need", needed - available, 1616 | "more", it, "to fix this room.") 1617 | can_fix = False 1618 | checked_items.append(it) 1619 | if can_fix: 1620 | room.broken = False 1621 | for it in items_needed: 1622 | Item(it).destroy("player") 1623 | print_line( 1624 | room.name, 1625 | "has been fixed and is now in full working order.") 1626 | 1627 | elif a.split()[0] == "see": 1628 | if a.split()[1] == "people": 1629 | see_people() 1630 | elif (a.split()[1]) == "items": 1631 | see_inventory("player") 1632 | elif a.split()[1] == "rooms": 1633 | see_rooms() 1634 | elif a.split()[1] == "day": 1635 | print_line("Today is day", days) 1636 | elif a.split()[1] == "resources": 1637 | see_resources() 1638 | else: 1639 | print_line( 1640 | "Incorrect input.", 1641 | "You can (see people), (see inventory), " + 1642 | "(see rooms) or (see resources)") 1643 | 1644 | elif a.split()[0] == "coitus": 1645 | if len(a.split()) != 5: 1646 | print_line( 1647 | "You need to input 2 mature people of opposite genders " + 1648 | "in the form (coitus Alex Marshall Mallus Cumberland)") 1649 | elif not check_person(a.split()[1], a.split()[2]): 1650 | print_line("No such", a.split()[1], a.split()[2], " exists!") 1651 | elif not check_person(a.split()[3], a.split()[4]): 1652 | print_line("No such", a.split()[2], a.split()[4], " exists!") 1653 | elif len(people) == living_capacity(): 1654 | print_line( 1655 | "You've reached the vault's maximum capacity.", 1656 | "Upgrade your living room to hold more people") 1657 | else: 1658 | person_1 = people[get_person_index(a.split()[1], a.split()[2])] 1659 | person_2 = people[get_person_index(a.split()[3], a.split()[4])] 1660 | if (person_1.partner == "" and person_2.partner == "") or \ 1661 | person_1.partner == person_2.name + " " + \ 1662 | person_2.surname: 1663 | if person_1.age < 18: 1664 | print_line( 1665 | a.split()[1] + 1666 | " isn't old enough to copulate.") 1667 | elif person_2.age < 18: 1668 | print_line( 1669 | a.split()[2] + 1670 | " isn't old enough to copulate.") 1671 | elif person_1.surname == person_2.surname: 1672 | print_line( 1673 | "Incest isn't allowed. " + 1674 | "At least be ethical!") 1675 | elif person_1.gender == person_2.gender: 1676 | print_line( 1677 | "The people need to be different genders! " + 1678 | "COME ON MAN CAN U EVEN BIOLOGY!?") 1679 | else: 1680 | # Pass these love birds to the birthing system 1681 | person = create_npc( 1682 | person_1, 1683 | person_2) 1684 | people.append(person) 1685 | else: 1686 | print_line("Infedility shall not be allowed!!!") 1687 | if person_1.partner != "": 1688 | print_line( 1689 | person_1.name, 1690 | person_1.surname, 1691 | " is married to ", 1692 | person_1.partner) 1693 | else: 1694 | print_line( 1695 | person_1.name, 1696 | person_1.surname, 1697 | " isn't married.") 1698 | if person_2.partner != "": 1699 | print_line( 1700 | person_2.name, 1701 | person_2.surname, 1702 | " is married to ", 1703 | person_2.partner) 1704 | else: 1705 | print_line( 1706 | person_2.name, 1707 | person_2.surname, 1708 | " isn't married.") 1709 | 1710 | # Checks if player has enough food to feed person and then calls 1711 | # feed(person) function. 1712 | elif a.split()[0] == "feed": 1713 | if len(choice) > 0: 1714 | # Counts how much food is available for feeding 1715 | # food_count = count_item("food") 1716 | if avg_hunger() < 2: 1717 | print_line("Your people are working on full bellies boss!") 1718 | elif len(a.split()) == 2: 1719 | if a.split()[1] not in people: 1720 | print_line("This person doesn't exist.") 1721 | else: 1722 | # Fetches hunger level of selected Human 1723 | hunger = people(a.split()[1].hunger) 1724 | amount = input( 1725 | "Feed ", a.split()[1], " by how much? ") 1726 | if amount < hunger: 1727 | print_line( 1728 | "You don't have enough food to feed ", 1729 | a.split()[1]) 1730 | else: 1731 | feed(a.split()[1], amount) 1732 | else: 1733 | print_line( 1734 | "Invalid input! Can only feed one person like this. ", 1735 | "Use the auto_feed system to feed everyone.") 1736 | else: 1737 | print_line("Invalid input. Who do you want to feed?") 1738 | elif a.split()[0] == "trade": 1739 | if not check_built_room('trader'): 1740 | print_line("You haven't built a trader room yet!") 1741 | elif '1' not in str(rooms[get_room_index('trader')].assigned): 1742 | print_line( 1743 | "No one has been assigned to this room!", 1744 | "You can't trade until then.") 1745 | else: 1746 | trade() 1747 | 1748 | elif a.split()[0] == "assign": 1749 | potential_room = '' 1750 | for x in a.split()[4:]: 1751 | if len(potential_room) == 0: 1752 | potential_room = x 1753 | else: 1754 | potential_room = potential_room + " " + x 1755 | 1756 | if len(a.split()) < 5: 1757 | print_line( 1758 | "You have to input 4 or more words.", 1759 | "E.g. assign Thomas Marc to living") 1760 | # Capitalizes first character of first and last name so player 1761 | # doesn't have to. 1762 | elif not check_person(a.split()[1], a.split()[2]): 1763 | print_line("This ", a.split()[1], " doesn't exist.") 1764 | elif not check_room(potential_room): 1765 | print_line("This room doesn't exist.") 1766 | elif not check_built_room(potential_room): 1767 | print_line("You haven't built this room yet") 1768 | elif rooms[get_room_index(potential_room)].assigned_limit == \ 1769 | rooms[get_room_index(potential_room)].count_assigned(): 1770 | print_line("This room is full.") 1771 | print_line( 1772 | "You can assign someone in the room to " + 1773 | "another room to create space.") 1774 | else: 1775 | person_index = get_person_index( 1776 | a.split()[1].title(), 1777 | a.split()[2].title()) 1778 | people[person_index].assign_to_room(potential_room) 1779 | 1780 | elif a.split()[0] == "auto": # All automatic functions 1781 | if a.split()[1] == "assign": 1782 | auto_assign() # Auto-assigns every free person to a room 1783 | 1784 | elif a.split()[0] == "upgrade": 1785 | if not check_room( 1786 | a.split()[1]) or not check_built_room( 1787 | a.split()[1]): 1788 | print_line("This room doesn't exist. Try again.") 1789 | elif a.split()[1] == "trader": 1790 | print_line("This room cannot be upgraded") 1791 | else: 1792 | # Tempoarily fetches room so it's attributes can be used 1793 | r = rooms[get_room_index(a.split()[1])] 1794 | items_needed = r.components 1795 | for x in range(r.level - 1): 1796 | for component in items_needed: 1797 | items_needed.append(component) 1798 | can_up = True 1799 | for ite in all_items: 1800 | needed = 0 1801 | for comp in items_needed: 1802 | if ite == comp: 1803 | needed += 1 1804 | # Counts number of component available to the player 1805 | available = count_item(game, ite, "player") 1806 | if available < needed: # Not enough 1807 | can_up = False 1808 | print_line( 1809 | "You don't have enough", 1810 | ite, 1811 | "to upgrade your ", 1812 | r.name) 1813 | break 1814 | if can_up: 1815 | for component in items_needed: 1816 | inventory.remove(component) 1817 | r.upgrade() 1818 | print_line( 1819 | r.name, 1820 | "has been upgraded and is now level", 1821 | r.level) 1822 | 1823 | elif a.split()[0] == "disable": 1824 | if a.split()[1] == "auto_feed": 1825 | # auto_feed = False 1826 | print_line( 1827 | "Warning. You have disabled the auto_feed feature. " + 1828 | "Be careful, your people may starve!") 1829 | else: 1830 | print_line( 1831 | "Invalid input.", 1832 | "You can disable the 'auto_feed' system.") 1833 | 1834 | elif a.split()[0] == "enable": 1835 | if a.split()[1] == "auto_feed": 1836 | # auto_feed = True 1837 | print_line("Auto-feed system is working optimally.") 1838 | else: 1839 | print_line( 1840 | "Invalid Input.", 1841 | "You can enable the 'auto_feed' system.") 1842 | 1843 | elif a.split()[0] == "scavenge": 1844 | if a.split()[1] not in people: 1845 | print_line("This person doesn't exist.") 1846 | elif people(a.split()[1]).scavenging: 1847 | print_line("This person is already out scavenging.") 1848 | else: 1849 | cho = input( 1850 | "Would you like to scavenge for a certain number of " + 1851 | "days or until their health gets low?(1-100/H) ") 1852 | try: 1853 | cho = int(cho) 1854 | except: 1855 | pass 1856 | scavenge(a.split()[1], cho) 1857 | 1858 | elif a.split()[0] == "heal": 1859 | if a.split()[1] == "all": 1860 | heal_all() 1861 | else: 1862 | if a.split()[1] not in people: 1863 | print_line("That person doesn't exist.") 1864 | else: 1865 | stim_count = count_item("stimpack", "player") 1866 | if stim_count > 0: 1867 | people(a.split()[1]).heal(heal_amount) 1868 | elif a.split()[0] == "skip": 1869 | global skip 1870 | skip = True 1871 | elif a.split()[0] == "end": 1872 | global player_quit 1873 | confirm = input("Are you sure? All unsaved data will be lost! ") 1874 | confirm = confirm[0].lower() 1875 | if confirm == "y": 1876 | player_quit = True 1877 | elif a.split()[0] == "help": 1878 | print_help() 1879 | else: 1880 | print_line("Invalid Input. Try again.") 1881 | else: 1882 | print_line("You have to choose something!") 1883 | """ 1884 | 1885 | if __name__ == '__main__': 1886 | game = None 1887 | #if os.path.exists(_save_file): 1888 | # load = default_input("Load game from {}? (Y/n) ".format(_save_file)) 1889 | # if load == "y": 1890 | # game = load_game() 1891 | #if game is None: 1892 | game = Game() 1893 | game.run() 1894 | --------------------------------------------------------------------------------