Skip to content

Commit

Permalink
Merge github.com:guanyilun/AntWorld
Browse files Browse the repository at this point in the history
  • Loading branch information
Chen Yu authored and Chen Yu committed May 16, 2012
2 parents 8daff73 + 6643814 commit 10587b5
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 70 deletions.
13 changes: 6 additions & 7 deletions antWorld.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def drawLandUpdate(ant):
'''refresh the part of the background that ant went pass'''
for x in range(int(ant.x) - 20, int(ant.x) + 20):
for y in range(int(ant.y) - 20, int(ant.y) + 20):
e = antWorld.land.element[x % antWorld.length][y % antWorld.width]
e = antWorld.land.element[x % antWorld.land.length][y % antWorld.land.width]
SURFACE.set_at((e.x, e.y), getLandColor(e))

def drawAnts(ant):
Expand All @@ -45,29 +45,28 @@ def drawAnts(ant):
iWHITE = (250, 250, 250) # background color

# set up the window
SURFACE = pygame.display.set_mode((antWorld.length, antWorld.width), 0, 32)
SURFACE = pygame.display.set_mode((antWorld.land.length, antWorld.land.width), 0, 32)
pygame.display.set_caption('antWorld')
SURFACE.fill(iWHITE)

# load image resources
foodImg = pygame.image.load('food.png')
SURFACE.blit(foodImg, antWorld.getFoodPosition())
SURFACE.blit(foodImg, antWorld.food.getPosition())


#World Simulation Start
while not antWorld.checkSuccess(): # the main game loop

antWorld.run()
map(drawLandUpdate, antWorld.ants)
SURFACE.blit(foodImg, antWorld.getFoodPosition())
antWorld.run()
SURFACE.blit(foodImg, antWorld.food.getPosition())
map(drawAnts, antWorld.ants)

for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
map(drawLandUpdate, antWorld.ants)
fpsClock.tick(FPS)

pygame.quit()
sys.exit()
120 changes: 76 additions & 44 deletions life.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import random
from math import pi, cos, sin, atan
from math import pi, cos, sin, sqrt

class Life:
def __init__(self, land):
self.x = 0
self.y = 0
def __init__(self, land, x=0, y=0):
self.x = x
self.y = y
self.land = land

def getLandElement(self):
Expand All @@ -14,19 +14,17 @@ class Ant(Life):
def __init__(self, land):
Life.__init__(self, land)
self.facingAngle = 0

self.home = land.element[0][0]
self.searchMode = True #For patrol testing
self.hasFood = False

self.speed = 8
self.viewRange = pi*5/6
self.viewMaxDistance = 50
self.signalSensitivity = 20
# Right direction is 0, anticlockwise positive

def walk(self):
'''random walk with step length 5 and random parameter 0.3'''
if not self.detectSignal():
self.randomWalk()

def randomWalk(self):
'''this is internal walking mechanism of ants which is supposed not exposed to user'''
turning_angle = random.gauss(0, 0.3)
self.move(turning_angle, 5)

def move(self, turn, forward):
'''
Function: used to turn ant and move the ant forward
Expand All @@ -46,52 +44,83 @@ def move(self, turn, forward):
self.x = x
self.y = y
self.facingAngle = facingAngle

print "angle", self.facingAngle/pi*180

def randomWalk(self):
'''this is internal walking mechanism of ants which is supposed not exposed to user'''
turning_angle = random.gauss(0, 0.2)
self.move(turning_angle, self.speed)

def detectSignal(self):
'''return true if signal detected in adjacent elements and move towards the signal'''
sight = self.getSight()
for element in sight:
if element.antSignal > self.signalSensitivity:
x, y = element.x, element.y
if x-self.x == 0 and y-self.y < 0:
self.facingAngle = 3*pi/2
elif x-self.x == 0 and y-self.y > 0:
self.facingAngle = pi/2
elif x-self.x < 0:
self.facingAngle = atan((y-self.y) / (x-self.x)) + pi
else:
self.facingAngle = atan((y-self.y) / (x-self.x))
self.move(0, 1)
print "Detect!"
return True
return False
'''return the angle of the signal of the strongest direction'''
sideAngle = int((0.5 * self.viewRange) * self.viewMaxDistance)# viewResolution = 1 / self.viewMaxDistance theta is about actan(theta) when theta is small
maxAngle = self.facingAngle
maxSignal = 0
for a in range(-sideAngle, sideAngle):
for distance in range(0, self.viewMaxDistance):
x = sin(a) * distance
y = cos(a) * distance
s = self.land.getElement(x, y).antSignal
if s > maxSignal:
maxSignal = s
maxAngle = a
if maxSignal <= 10:
return None
else:
print "signal",maxSignal
return maxAngle

def followSignal(self):
'''follow the signal...'''
if self.detectSignal() != None:
turning_angle = self.detectSignal() - self.facingAngle
self.move(turning_angle, self.speed)
print "following!"
else:
print "still no signal..."
self.randomWalk()

def patrol(self):
if (not self.hasFood) and self.land.getDistanceAB(self, self.land.food) < 100:#Turn back
self.facingAngle = (pi + self.facingAngle) % (2*pi)
self.searchMode = False
self.hasFood = True
self.followSignal()
print "Found! Turing back"
elif self.hasFood and self.land.getDistanceAB(self, self.home) < 100: #Go to food again
self.facingAngle = (pi + self.facingAngle) % (2*pi)
self.hasFood = False
self.followSignal()
else:
if self.searchMode: #Find food
self.randomWalk()
else:
self.followSignal()



def leaveSignal(self):
'''leave traces after walking'''
element = self.getLandElement()
element.gainSignal(100)
element.diffuseSignal()

def getSight(self):
'''get landElements in the sight'''
s = 2
x = self.x + s*cos(self.facingAngle)
y = self.y + s*sin(self.facingAngle)
return self.land.getAdjacentElements(x, y)

class Food(Life):
def __init__(self, land):
Life.__init__(self, land)
self.x, self.y = 400, 400
def getPosition(self):
return (self.x, self.y)

class LandElement:
'''all kinds of infomation in land'''
'''all kinds of information in land'''
def __init__(self, land, x, y):
self.land = land
self.x = x
self.y = y
self.antSignal = 0 # the tracing signal of ants



def getAdjacentElements(self):
return self.land.getAdjacentElements(self.x, self.y)

Expand All @@ -104,14 +133,14 @@ def diffuseSignal(self):
amount = self.antSignal * diffuseRatio / len(adjacent)
if amount >= diffuseThreshold:
element.gainSignal(amount)
self.gainSignal(-amount)
self.gainSignal(-amount-10)
element.diffuseSignal()

def gainSignal(self, amount = 100):
self.antSignal += amount

class Land:
def __init__(self, length, width):
def __init__(self, width,length):
self.length = length
self.width = width
self.element = []
Expand All @@ -121,9 +150,12 @@ def __init__(self, length, width):
column.append(LandElement(self, x, y))
self.element.append(column)

def getDistanceAB(self, A, B):
return sqrt((A.x - B.x) ** 2 + (A.y - B.y) ** 2)

def getElement(self, x, y):
'''getLandElement at x, y, (x, y need not to be integer)'''
return self.element[int(x) % self.width][int(y) % self.length]
return self.element[int(x)][int(y)]

def getAdjacentElements(self, x, y):
s = 2 # size of adjacent
Expand Down
35 changes: 16 additions & 19 deletions worldModel.py
Original file line number Diff line number Diff line change
@@ -1,54 +1,51 @@
from life import Ant, Food, Land
from math import sqrt, pi
from math import pi
class AntWorld:
'''
It contains the World Model
'''
def __init__(self, numOfAnts=1, width=800, length=800):
self.numOfAnts = numOfAnts
self.width = width
self.length = length
self.land = Land(width, length)
self.ants = [Ant(self.land) for i in range(numOfAnts)]
self.food = Food(self.land)
self.land.ants = [Ant(self.land) for i in range(numOfAnts)]
self.land.food = Food(self.land)
self.ants = self.land.ants
self.food = self.land.food

def run(self):
for ant in self.ants:
ant.walk()
self.checkBoundary(ant)
ant.patrol()
self.checkBoundary(ant, True)
ant.leaveSignal()

def checkSuccess(self):
for ant in self.ants:
if self.getDistance(ant, self.food) < 15:
return True
# for ant in self.ants:
# if self.land.getDistanceAB(ant, self.food) < 15:
# return True
return False

def getFoodPosition(self):
return (self.food.x, self.food.y)

def getDistance(self, lifea, lifeb):
return sqrt((lifea.x - lifeb.x) ** 2 + (lifea.y - lifeb.y) ** 2)

def checkBoundary(self, ant, bounce=False):
if (bounce == True):
#Rule 1 Touch wall = bounce back like light
if (int(ant.x) >= self.width - 1):
if (int(ant.x) >= self.land.width - 1):
ant.facingAngle = -ant.facingAngle - pi
ant.x = self.width - 1
ant.x = self.land.width - 1
elif (int(ant.x) <= 0):
ant.facingAngle = -ant.facingAngle - pi
ant.x = 0

elif (int(ant.y) >= self.length - 1):
elif (int(ant.y) >= self.land.length - 1):
ant.facingAngle = -ant.facingAngle
ant.y = self.length - 1
ant.y = self.land.length - 1

elif (int(ant.y) <= 0):
ant.facingAngle = -ant.facingAngle
ant.y = 0
ant.facingAngle %= 2 * pi
else:
#Rule 2 Touch wall = cross
ant.x %= self.width
ant.x %= self.land.width
ant.y %= self.length

0 comments on commit 10587b5

Please sign in to comment.