# sim8: doctest
from visual import *
import time, doctest
bigG = 0.1

class Body(sphere):
    def __init__(self, vel = vector(0,0,0),
                 mass=1.0, *args, **kwargs):
        sphere.__init__(self, *args, **kwargs)
        self.vel = vector(vel)
        self.mass = mass
    def __cmp__(self, other):
        return cmp(self.mass, other.mass)
    def is_colliding(self, other):
        return (self.pos - other.pos).mag < \
               (self.radius + other.radius) \
               and self.visible and other.visible
    def momentum(self):
        return self.mass * self.vel
    def absorb(self, other):
        '''Transfers other's mass and momentum to self.
	
        >>> b1 = Body(mass=1.0, vel=(10,0,0))
        >>> b2 = Body(mass=2.0, vel=(-10,0,0))
        >>> b1.absorb(b2)
        >>> b1.mass
        3.0
        >>> b1.momentum()
        vector(-10, 0, 0)
        '''
        self.mass += other.mass
        self.vel = (self.momentum() + other.momentum()) / \
                   self.mass
	# There's a logic flaw here!  I shouldn't use
	# self.momentum() this way after I've already
	# added other.mass to self.mass, because
	# self.momentum() is a function of self.mass.
	# It will be caught by the unit test when I run
	# python body.py
	# The following would be the correct logic:
        #self.vel = (self.momentum() + other.momentum()) / \
        #           (self.mass + other.mass)
        #self.mass += other.mass  
        other.visible = False
    def explode(self):
        self.color = color.orange
        for i in range(20):
            self.radius += 0.2
            time.sleep(0.03)
    def applyForce(self, force):
        self.vel += (force / self.mass)
        self.pos += self.vel
    def gravity(self, otherBody):
        force = (otherBody.pos - self.pos)
        force.mag = self.mass * otherBody.mass * bigG \
                    / force.mag ** 2
        return force

doctest.testmod()

