def process_turret(field, robot, dt):
    """Get new turret position and rotation attributes for a time-delta."""
    new_robot = lib.clone_struct(robot)
    move_to_angle = lib.first([robot.fire_angle, robot.turret_final_angle], 
        pred=lambda x: x is not None)
    new_bullets = []    
    new_turret_angle = robot.turret_angle + dt * robot.turret_rotation
    if move_to_angle is not None:
        old_direction = geometry.get_direction_for_rotation(
            robot.angle + robot.turret_angle, move_to_angle)
        new_direction = geometry.get_direction_for_rotation(
            robot.angle + new_turret_angle, move_to_angle)
        if old_direction * new_direction < 0:
            new_robot.turret_rotation = 0.0
            if robot.fire_angle:
                new_bullet = fire_bullet(robot, field)
                new_bullets.append(new_bullet)
            new_turret_angle = move_to_angle - robot.angle
            new_robot.fire_angle = None
            new_robot.turret_final_angle = None
        else:
            max_speed = field.config["robot"]["turret_rotation_max_speed"]
            new_robot.turret_rotation = max_speed * new_direction
    else: 
        new_bullets = []
    new_robot.turret_angle = geometry.normalize_angle(new_turret_angle)

    # Update time to fire
    if robot.time_to_fire: 
        new_robot.time_to_fire -= dt
        if new_robot.time_to_fire < 0:
            new_robot.time_to_fire = 0.0                
    
    return StateChange(update_robots=[new_robot], new_bullets=new_bullets)
def process_bullet(bullet, dt, screen_size):
    """Update bullet position for a delta_t."""
    new_bullet = lib.clone_struct(bullet)
    screen_width, screen_height = screen_size
    k = dt * bullet.speed
    new_bullet.x = bullet.x + k * math.cos(geometry.torad(bullet.angle))
    new_bullet.y = bullet.y - k * math.sin(geometry.torad(bullet.angle))
    if (new_bullet.x >= 0 and new_bullet.x < screen_width and
            new_bullet.y >= 0 and new_bullet.y < screen_height):
        return new_bullet
def process_robot(robot, dt, screen_size):
    """Get new robot position and rotation attributes for a time-delta."""
    new_robot = lib.clone_struct(robot)
    screen_width, screen_height = screen_size            
    body_width, body_height = robot.width, robot.height
    new_robot.x = robot.x + dt * robot.speed * math.cos(geometry.torad(robot.angle))
    if new_robot.x - body_width/2.0 < 0:
        new_robot.x = body_width/2.0
    elif new_robot.x + body_width/2.0 >= screen_width:
        new_robot.x = screen_width - body_width/2.0
    new_robot.y = robot.y - dt * robot.speed * math.sin(geometry.torad(robot.angle))
    if new_robot.y < body_height/2.0:
        new_robot.y = body_height/2.0
    elif new_robot.y + body_height/2.0 >= screen_height:
        new_robot.y = screen_height - body_height/2.0                
    new_robot.angle = geometry.normalize_angle(robot.angle + dt * robot.rotation)    
    return new_robot