def do_step(): # Buffer all the move_by calls and do at once. # Note that this does not buffer other state changes made in objects, # such as a teleport - we really should have that facility for a proper # simulation of a time step # we should also enforce the restriction on the move limit for each # type of object. At the moment, you can get around this limit by calling # move_by in the compute_next_move method! moves = [ ] # give the defenders a chance to tell the normals what to do # and try to teleport any zombies for p in Defender.get_all_present_instances(): moves.append( (p,) + p.compute_next_move() ) # then give the normals a chance for p in Normal.get_all_present_instances(): moves.append( (p,) + p.compute_next_move() ) # and finally the zombies, which may have been teleported to new positions for p in Zombie.get_all_present_instances(): moves.append( (p,) + p.compute_next_move() ) # then execute the moves, even though other state may have been changed # earlier for (p, delta_x, delta_y) in moves: p.move_by(delta_x, delta_y) # then convert normals into zombies if the zombies are close enough # Warning: z - number of zombies, n - number of normals, then the # time complexity of this is O( z n ) for z in Zombie.get_all_present_instances(): for n in Normal.get_all_present_instances(): d_e_e = z.distances_to(n)[3] d_touch = z.get_touching_threshold() # print(z.get_name(), n.get_name(), d_e_e, d_touch) if d_e_e <= d_touch: x = n.get_xpos() y = n.get_ypos() new_z = Zombie(size=n.get_size(), haircolor='green', xpos = x, ypos = y, move_limit=person_move_limit) new_z.arrive() n.leave() Person.del_instance(n)