Plague Inc. in Python - Extremely Early Stage I've been working to create a game in Python similar to Plague Inc. and instead of just writing one big clump of code and then getting it reviewed, I wanted to do it stage-by-stage and make it a little easier. Also, reviews might possibly help me later on in the development process.

import datetime
import random 

countries = [
   dict(Name = "China", Population = "1,363,560,000"),
   dict(Name = "India", Population = "1,242,070,000"),
   dict(Name = "United States", Population = "317,768,000"),
   dict(Name = "Indonesia", Population = "249,866,000"),
   dict(Name = "Brazil", Population = "201,032,714"),
   dict(Name = "Pakistan", Population = "186,015,000"),
   dict(Name = "Nigeria", Population = "173,615,000"),
   dict(Name = "Bangladesh", Population = "152,518,015"),
   dict(Name = "Russia", Population = "143,700,000"),
   dict(Name = "Japan", Population = "127,120,000"),
   dict(Name = "Mexico", Population = "119,713,203"),
   dict(Name = "Philippines", Population = "99,329,000"),
   dict(Name = "Vietnam", Population = "89,708,900"),
   dict(Name = "Egypt", Population = "86,188,600"),
   dict(Name = "Germany", Population = "80,716,000"),
   dict(Name = "Iran", Population = "77,315,000"),
   dict(Name = "Turkey", Population = "76,667,864"),
   dict(Name = "Thailand", Population = "65,926,261"),
   dict(Name = "France", Population = "65,844,000"),
   dict(Name = "United Kingdom", Population = "63,705,000"),
   dict(Name = "Italy", Population = "59,996,777"),
   dict(Name = "South Africa", Population = "52,981,991"),
   dict(Name = "South Korea", Population = "50,219,669"),
   dict(Name = "Colombia", Population = "47,522,000"),
   dict(Name = "Spain", Population = "46,609,700"),
   dict(Name = "Ukraine", Population = "45,410,071"),
   dict(Name = "Kenya", Population = "44,354,000"),
   dict(Name = "Argentina", Population = "40,117,096"),
   dict(Name = "Poland", Population = "38,502,396"),
   dict(Name = "Sudan", Population = "37,964,000"),
   dict(Name = "Uganda", Population = "35,357,000"),
   dict(Name = "Canada", Population = "35,344,962"),
   dict(Name = "Iraq", Population = "34,035,000"),
   ]

current_date = datetime.datetime.strftime(datetime.date.today(), "%m-%d-%Y")   

print "Welcome to a Python version of Plague Inc."
user = raw_input('\nWhat is your name? ').title() # for later on in the game
print '\nCountries to choose from are\n'
print "Country".ljust(15),"Population\n"
for country in countries:
    print country["Name"].ljust(15), country["Population"]
startcountry = raw_input('\nWhat country would you like to start in? ').title() 

if startcountry == 'Random': # random.sample can be used for more than one country later on
    startcountry = random.choice(countries)

diseasename = raw_input('\nWhat would you like to name your disease? ').title()

print '\nNews Bulletin'.ljust(45), current_date
print '-' * 55
print 'An unknown disease named', diseasename, 'has struck', startcountry, 'by storm.'
print 'Doctors and scientists will need to collaborate to find out more information about this disease.'
Some thoughts:


As the game goes on, you’ll need to record more information about the countries. Whether they’re doing medical research, border closures, infection/mortality rates, etc. Rather than storing all this information in a list of dictionaries, I’d suggest creating objects for each country. Here’s a simple example:



class Country(object):
    def __init__(self, name, population):
        self.name = name
        self.population = population

china = Country("China", 1363560000)


Also follow martijnn2008’s advice, and load the countries from an external file (probably a CSV). Keeping the data separate from the code is generally good practice. You’d probably be better off having a small dataset in the program to start with, as you build the basic logic, then start using the full data set later.

As unholysampler suggests, use an int for the population; this will make your life much easier later when chunks of the population start dying. You can always define a function that does nice comma-printing on your population data later.
Have different functions for parts of the game. For example, a start_game() function which just includes the code for setting up a new game, then another function news_bulletin() which prints a random news bulletin.

This will make it easier to reuse this code later – for example, if the user gets to the end of the game and you want to ask "Play again?", you can just redirect them to start_game() rather than jumping through hoops.
Rather than expecting the user to enter a name that’s formatted exactly as it’s stored in your data, you could:


Do something to clean up messy input. For example, right now, "china" is an invalid input, but any reasonable person can see what they meant. Perhaps do something like

if start_country.lower() in list_of_countries:
     # more code here


And weirdness happens if I choose a country name which isn't on your list. You could perhaps just ask again and again until you get an answer, or just pick one at random for me. I just want to get on with the game!
Just offer them a choice from a numbered list. Here’s a very crude mockup of how that might work:

Which country would you like to choose?
1 China
2 India
3 United States
Type the corresponding number: # wait for input
3
You have chosen "United States"


Magic numbers as arguments to ljust() throughout your code. Icky and fragile. Pull them out and make them variables, or better try to compute the necessary values on the fly.

ETA: The problem arises because you’re assuming that the window is 55 characters wide (for example, the print '-' * 55 line). You should pull this out into a window_width variable, so you don't have problems later on (and if necessary, can adapt it for wider or narrower windows).

What if, later, you want to add the Independent Former Republic of New South Nebelsbad? Stuff like that might cause you problems if you’re rigid about the width.
In your import statements, I would write



from datetime import datetime


Cuts out datetime.datetime statements, which just look weird. Also note that your MM-DD-YY may confuse players for whom that isn’t their default date system. How about



&gt;&gt;&gt; current_date = datetime.datetime.strftime(datetime.date.today(), "%d %B, %Y")
&gt;&gt;&gt; print current_date
29 April, 2014


That looks much more natural, and is unambiguous.