Skip to content

Instantly share code, notes, and snippets.

@horstjens
Last active March 19, 2020 10:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save horstjens/658ba6220999e3aa27c0d67f801c2018 to your computer and use it in GitHub Desktop.
Save horstjens/658ba6220999e3aa27c0d67f801c2018 to your computer and use it in GitHub Desktop.
Blog Artikel spielend-programmieren
import random
# TODO: include Sandwich's graphic https://imgur.com/SCrUgqq ?
class Person:
"""a person has a location, can change this location, and can be healthy,
infected or immune. If location is shared with an infected person, all
healthy persons at this location become infected.
After some time of infection, persons become immune and can neither
become infected again nor spread the infection"""
number = 0
def __init__(self, x, y, infected=False, immune=False, stay_home = True):
self.number = Person.number
Person.number += 1
Game.population[self.number] = self
self.x = x
self.y = y
self.infected = infected
self.days_infected = 0
self.immune = immune
self.stay_home = stay_home
print("new person infected:", self.infected)
def turn(self):
"""a day passes, if infected long enough, person becomes immune"""
if self.infected:
self.days_infected += 1
if self.days_infected > Game.infection_time:
self.immune = True
self.infected = False
def move_around(self):
if self.stay_home:
self.x += random.randint(-Game.low_mobile, Game.low_mobile)
self.y += random.randint(-Game.low_mobile, Game.low_mobile)
else:
self.x += random.randint(-Game.high_mobile, Game.high_mobile)
self.y += random.randint(-Game.high_mobile, Game.high_mobile)
self.wrap_around_edges()
def wrap_around_edges(self):
if self.x < 0:
self.x = Game.area[0] + self.x
if self.x > Game.area[0] - 1:
self.x = self.x - Game.area[0]
if self.y < 0:
self.y = Game.area[1] + self.y
if self.y > Game.area[1] - 1:
self.y = self.y - Game.area[1]
class Game:
# this class attributes can be overwritten by __init__ !
low_mobile = 1
high_mobile = 5
infection_time = 20 # turns until an infected person becomes immune
area = (80,30)
percent_low_mobile = 0.8 # 80%
population = {}
history = []
def __init__(self, people=10, x=80, y=30, percent_home=0.1, low_mobile = 1, high_mobile=5, infection_time = 20 ):
Game.area = (x,y)
Game.percent_low_mobile = percent_home
Game.low_mobile = low_mobile
Game.high_mobile = high_mobile
Game.infection_time = infection_time
self.percent_immune = 0.0
self.percent_infected = 0.0
self.percent_healthy = 1.0
Game.history = []
# create one infected person and other non-infected persons
for number in range(people):
# decide if this persons stays at home or no
home = True if random.random() < Game.percent_low_mobile else False
Person(x=random.randint(0,Game.area[0]-1),
y=random.randint(0,Game.area[1]-1),
infected = True if number == 0 else False,
immune=False, stay_home = home)
def turn(self):
"""moves all persons around"""
population = Game.population.values()
for person in population:
person.turn() # chance to become immune
person.move_around()
for spreader in [p for p in population if p.infected and not p.immune]:
for infectable in [p for p in population if not p.infected and not p.immune and p.x == spreader.x and p.y == spreader.y]:
infectable.infected = True # spread the infection
def statistic(self):
immune = 0
infected = 0
for p in Game.population.values():
if p.immune:
immune += 1
if p.infected:
infected += 1
total = len(Game.population)
healthy = total - infected - immune
self.percent_immune = immune / total
self.percent_infected = infected / total
self.percent_healthy = 1- self.percent_infected-self.percent_immune
Game.history.append((healthy, infected, immune))
return "healthy: {}({:.2f}%) sick: {}({:.2f}%) immune:{}({:.2f}%)".format(
healthy, self.percent_healthy, infected, self.percent_infected, immune,
self.percent_immune)
def draw_map():
for y in range(Game.area[1]):
for x in range(Game.area[0]):
# how many people are here
here = []
for p in Game.population.values():
if p.x == x and p.y == y:
here.append(p)
infected_here = len([p2 for p2 in here if p2.infected])
immune_here = len([p2 for p2 in here if p2.immune])
healthy_here = len(here)-infected_here - immune_here
if len(here) == 0: # nobody here
char="."
elif len(here) == 1: # only one person here
char = "h" # healthy
if infected_here == 1:
char = "x" # sick
elif immune_here == 1:
char = "i" # immune
else: # several persons at the same place.
char = "H" # all healthy
if healthy_here > 0 and infected_here > 0:
char = "*" # spreading!
elif healthy_here == 0:
char = "-" # not spreading
elif immune_here == len(here):
char = "I" # all immune
elif infected_here == len(here):
char = "X" # all infected
print(char, end="")
print() # new line
def draw_graph():
print("turn, x=sick, i=immune, h=healthy")
width = Game.area[0]
for number, line in enumerate(Game.history):
healthy, infected, immune = line
total = healthy + infected + immune
healthy_percent = healthy / total
infected_percent = infected / total
immune_percent = immune / total
print("{: >3}:".format(number), end="") # fill with spaces, minimum lenght is 3
print("x"*int(round(infected_percent*width,0))+
"i"*int(round(immune_percent*width,0))+
"h"*int(round(healthy_percent*width,0)))
def main(people,x, y, home, low_mobile, high_mobile, infection_time ):
# this is the viewer
game = Game(people,x, y, home, low_mobile, high_mobile, infection_time)
legend = "h, H ........ one/many healthy persons"
legend += "\ni, I ........ one/many immune persons"
legend += "\nx, X ........ one/many sick persons"
legend += "\n* ........ infection spreading"
legend += "\n- ........ infection not spreading"
print(legend)
show_graph = False
show_legend = False
while True:
if show_graph:
draw_graph()
else:
draw_map()
if show_legend:
print(legend)
print(game.statistic())
command = input("ENTER-> next turn, 'q'-> quit, 'g'-> toggle graph/area 'l'-> toggle legend>>>")
if command == "q":
break
if command == "g":
show_graph = not show_graph
if command == "l":
show_legend = not show_legend
game.turn()
if __name__ == "__main__":
main(people=200, x=80, y=30, home=0.1, low_mobile = 1, high_mobile=5, infection_time = 60 )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment