// Divide spawns a new organism in the neighboring cell in the direction the // organism is pointing. Energy from the parent, multiplied by energyFrac, will // be transferred to the child to give it something to start off with. The // returns organism will be associated with a grid2d.Locator and given driver, // but still requires the caller spawn a goroutine to drive it. Returns nil and // an error if there was insufficient energy to divide, or if the cell the child // would be spawned within is already occupied by anything other than Food. func (o *Organism) Divide(driver interface{}, energyFrac float64) (*Organism, error) { Logger.Printf("%v.Divide(%v, %v)\n", o, driver, energyFrac) if err := o.Discharge(BodyEnergy); err != nil { return nil, err } n := Random() n.Driver = driver dx, dy := o.delta(1) if _, loc := o.loc.Put(dx, dy, n, PutWhenFood); loc != nil { energy.Transfer(n, o, int(float64(o.Energy())*energyFrac)) Logger.Printf("- parent: %v\n", o) Logger.Printf("- child: %v\n", n) runtime.Gosched() return n, nil } return nil, ErrNotEmpty }
// Eat attempts to transfer energy from the occupant in the neighboring cell in the // direction the organism points. Returns the amount transferred successfully or // an error if there was insufficient energy to complete the action. func (o *Organism) Eat(amt int) (int, error) { Logger.Printf("%v.Eat(%v)\n", o, amt) if err := o.Discharge(int(math.Ceil(float64(amt) / 100.0))); err != nil { return 0, err } if n := o.loc.Get(o.delta(1)); n != nil { Logger.Printf("- got %v\n", n.Value()) if n, ok := n.Value().(energy.Energetic); ok { amt, _, _ = energy.Transfer(o, n, amt) Logger.Printf("- transferred %v\n", amt) Logger.Printf(" - %v\n", o) Logger.Printf(" - %v\n", n) runtime.Gosched() return -amt, nil } else { Logger.Printf("- not energetic\n") } } return 0, nil }