func (s *Sim) potential(unit *unit, x, y float64) float64 {
	// Distance to end
	//max := 300.0
	//dist := (&geo.Vec{x,y}).Distance(&unit.end)

	//potEnd := dist/max
	potEnd := 1.0
	pos := &geo.Vec{x, y}

	if unit.path != nil {
		for e := unit.path.Front(); e.Next() != nil; e = e.Next() {
			pt0 := e.Value.(*geo.Vec)
			pt1 := e.Next().Value.(*geo.Vec)

			av := geo.OrthogonalVector(pt0, pt1.Sub(pt0), &geo.Vec{x, y})
			if av != nil {
				potEnd = math.Min(av.Len()/10.0, 1)
			} else {
				if l := pt0.Sub(pos).Len(); l <= 10 {
					potEnd = math.Min(l/10.0, potEnd)
				} else if l := pt1.Sub(pos).Len(); l <= 10 {
					potEnd = math.Min(l/10.0, potEnd)
				}
			}

		}
	}

	// other units
	MIN := 5.0
	MAX := 10.0
	potDist := 0.0
	for _, oUnit := range s.units {
		if oUnit.id != unit.id {
			dist := oUnit.pos.Distance(&geo.Vec{x, y})
			potDist += 1 - math2.MinMax(1, (dist-MIN)/(MAX-MIN), 0)
		}
	}

	potDist = math2.MinMax(1, potDist, 0)

	// trail
	potTrail := 0.0
	elms := unit.trail.Elements()
	for _, elm := range elms {
		if elm != nil {
			trailPos := elm.(geo.Vec)
			dist := trailPos.Distance(&geo.Vec{x, y})
			potTrail += 1.0 - math2.MinMax(1, dist/float64(1), 0)
		}
	}

	potTrail = math2.MinMax(1, potTrail, 0)

	if unit.id == 0 && potDist > 0 {
		//fmt.Println(potDist)
	}

	pot := 0.5*potEnd + 0*potDist + 0.25*potTrail

	xd := int(x)
	yd := int(y)
	if xd >= 0 && xd < 300 && yd >= 0 && yd < 300 {
		if s.static[xd][yd] == 1 {
			pot = 1
		}
	}

	return pot
}
func (s *Sim) Update() {
	speed := 20.0 / float64(time.Second) // -> 10 units per second

	lastUpdate := time.Now()
	time.Sleep(1 * time.Nanosecond)

	for {

		dTime := time.Since(lastUpdate)
		start := time.Now()

		// Update the units
		for _, unit := range s.units {
			if unit.pos == unit.end {
				// TODO when to finish?
				continue
			}

			min, radMin := 1.0, 0.0
			for i := 0; i < 16; i++ {
				// TODO We can cache all these static directions
				rad := math.Pi * 2 * float64(i) / 16.0
				dy := math.Sin(rad)
				dx := math.Cos(rad)

				pot := s.potential(unit, unit.pos.X+dx, unit.pos.Y+dy)

				if pot < min {
					min = pot
					radMin = rad
				}
			}

			d := speed * float64(dTime)
			unit.pos.X += math.Cos(radMin) * d
			unit.pos.Y += math.Sin(radMin) * d

			// Add position to trail if more than 0.25 units away
			if last := unit.trail.Front(); last != nil {
				lastPos := last.(geo.Vec)
				if lastPos.Distance(&unit.pos) >= 0.25 {
					unit.trail.AddToFront(unit.pos)
				}
			} else {
				unit.trail.AddToFront(unit.pos)
			}

			// if the unit already walks at the next path piece, forget the current front one
			if unit.path.Len() > 2 {
				pt1 := unit.path.Front().Next().Value.(*geo.Vec)
				pt2 := unit.path.Front().Next().Next().Value.(*geo.Vec)
				if geo.OrthogonalVector(pt1, pt2.Sub(pt1), &unit.pos) != nil {
					unit.path.Remove(unit.path.Front())
				}
			}
		}

		// Important: update BEFORE the render
		lastUpdate = time.Now()

		fps := 1 / (float64(time.Since(start)) / float64(time.Second))
		_ = fps
		//fmt.Printf("%.f \t\n", fps)
		//fmt.Println(fps, s.units[0].pos)
		//s.ui.fpsLabel.SetLabel(fmt.Sprintf("%f", fps))

		time.Sleep(1 * time.Millisecond)
	}
}