def draw_units(self, surf):
    """Draw the units and buildings."""
    unit_dict = None  # Cache the units {tag: unit_proto} for orders.
    tau = 2 * math.pi
    for u, p in self._visible_units():
      if self._camera.intersects_circle(p, u.radius):
        fraction_damage = clamp((u.health_max - u.health) / (u.health_max or 1),
                                0, 1)
        if u.display_type == sc_raw.Placeholder:
          surf.draw_circle(colors.PLAYER_ABSOLUTE_PALETTE[u.owner] // 3, p,
                           u.radius)
        else:
          surf.draw_circle(colors.PLAYER_ABSOLUTE_PALETTE[u.owner], p, u.radius)

          if fraction_damage > 0:
            surf.draw_circle(colors.PLAYER_ABSOLUTE_PALETTE[u.owner] // 2,
                             p, u.radius * fraction_damage)
        surf.draw_circle(colors.black, p, u.radius, thickness=1)

        if self._static_data.unit_stats[u.unit_type].movement_speed > 0:
          surf.draw_arc(colors.white, p, u.radius, u.facing - 0.1,
                        u.facing + 0.1, thickness=1)

        def draw_arc_ratio(color, world_loc, radius, start, end, thickness=1):
          surf.draw_arc(color, world_loc, radius, start * tau, end * tau,
                        thickness)

        if u.shield and u.shield_max:
          draw_arc_ratio(colors.blue, p, u.radius - 0.05, 0,
                         u.shield / u.shield_max)
        if u.energy and u.energy_max:
          draw_arc_ratio(colors.purple * 0.9, p, u.radius - 0.1, 0,
                         u.energy / u.energy_max)
        if 0 < u.build_progress < 1:
          draw_arc_ratio(colors.cyan, p, u.radius - 0.15, 0, u.build_progress)
        elif u.orders and 0 < u.orders[0].progress < 1:
          draw_arc_ratio(colors.cyan, p, u.radius - 0.15, 0,
                         u.orders[0].progress)

        if u.buff_duration_remain and u.buff_duration_max:
          draw_arc_ratio(colors.white, p, u.radius - 0.2, 0,
                         u.buff_duration_remain / u.buff_duration_max)

        if u.attack_upgrade_level:
          draw_arc_ratio(self.upgrade_colors[u.attack_upgrade_level], p,
                         u.radius - 0.25, 0.18, 0.22, thickness=3)

        if u.armor_upgrade_level:
          draw_arc_ratio(self.upgrade_colors[u.armor_upgrade_level], p,
                         u.radius - 0.25, 0.23, 0.27, thickness=3)

        if u.shield_upgrade_level:
          draw_arc_ratio(self.upgrade_colors[u.shield_upgrade_level], p,
                         u.radius - 0.25, 0.28, 0.32, thickness=3)

        def write_small(loc, s):
          surf.write_world(self._font_small, colors.white, loc, str(s))

        name = self.get_unit_name(
            surf, self._static_data.units.get(u.unit_type, "<none>"), u.radius)
        if name:
          write_small(p, name)
        if u.ideal_harvesters > 0:
          write_small(p + point.Point(0, 0.5),
                      "%s / %s" % (u.assigned_harvesters, u.ideal_harvesters))
        if u.mineral_contents > 0:
          write_small(p - point.Point(0, 0.5), u.mineral_contents)
        elif u.vespene_contents > 0:
          write_small(p - point.Point(0, 0.5), u.vespene_contents)
        elif u.display_type == sc_raw.Snapshot:
          write_small(p - point.Point(0, 0.5), "snapshot")
        elif u.display_type == sc_raw.Placeholder:
          write_small(p - point.Point(0, 0.5), "placeholder")
        elif u.is_hallucination:
          write_small(p - point.Point(0, 0.5), "hallucination")
        elif u.is_burrowed:
          write_small(p - point.Point(0, 0.5), "burrowed")
        elif u.cloak != sc_raw.NotCloaked:
          write_small(p - point.Point(0, 0.5), "cloaked")

        if u.is_selected:
          surf.draw_circle(colors.green, p, u.radius + 0.1, 1)

          # Draw the orders of selected units.
          start_point = p
          for o in u.orders:
            target_point = None
            if o.HasField("target_world_space_pos"):
              target_point = point.Point.build(o.target_world_space_pos)
            elif o.HasField("target_unit_tag"):
              if unit_dict is None:
                unit_dict = {t.tag: t
                             for t in self._obs.observation.raw_data.units}
              target_unit = unit_dict.get(o.target_unit_tag)
              if target_unit:
                target_point = point.Point.build(target_unit.pos)
            if target_point:
              surf.draw_line(colors.cyan * 0.75, start_point, target_point)
              start_point = target_point
            else:
              break
          for rally in u.rally_targets:
            surf.draw_line(colors.cyan * 0.75, p,
                           point.Point.build(rally.point))