Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes sulu #45

Merged
merged 2 commits into from Jul 8, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 8 additions & 9 deletions bots/maptools.py
Expand Up @@ -3,7 +3,7 @@

from spacecraft import map

from shapely.geometry import Polygon
from shapely.geometry import Polygon, LineString
from spacecraft import euclid

class MapLoader(map.MapLoader):
Expand All @@ -18,7 +18,6 @@ def __init__(self, filename):
self.close_methods = {
}


def open_rect(self, node, game, transform):
x = float(node.attrib["x"])
y = float(node.attrib["y"])
Expand All @@ -28,23 +27,23 @@ def open_rect(self, node, game, transform):
height = float(node.attrib["height"])
game.add_wall(x, y, width, height)


class GridMap(object):

xsize = 300
ysize = 300
xbuckets = ybuckets = 50


def __init__(self, filename):
l = MapLoader(filename)
self.walls = []
l.setup_map(self)
self.build_grid()
self.goal = None
self.goal_grid = [ [float("+inf")] * self.ybuckets for i in range(self.xbuckets) ]
self.goal_grid = None

def build_grid(self):
self.grid = [ [0] * self.ybuckets for i in range(self.xbuckets) ]
self.grid = [[0] * self.ybuckets for i in range(self.xbuckets)]
for xb in range(self.xbuckets):
for yb in range(self.ybuckets):
cell = self.build_cell(xb, yb)
Expand Down Expand Up @@ -109,7 +108,7 @@ def dump_search_state(self, open, closed, start, goal):
else:
val = str(self.grid[xp][yp])

parts.append( val )
parts.append(val)
print "".join(parts)

def dump_path(self, start, goal, path, X=[]):
Expand Down Expand Up @@ -223,9 +222,7 @@ def is_wall(self, pos):
return False

def visible(self, start, end):
_start = self.world_to_cell(*start)
_end = self.world_to_cell(*end)
return self._visible(_start, _end)
return not self.intersects(LineString([start, end]))

def waypoint(self, start, goal):
"""In world coordinates!"""
Expand Down Expand Up @@ -281,6 +278,8 @@ def towards_goal_from(self, current):
step = 0
while True:
np = winner(self.neighbor_nodes(goal), self.goalpath)
if np is None:
break
if not self._visible(p, np):
break
goal = np
Expand Down
28 changes: 23 additions & 5 deletions bots/navigator.py
@@ -1,4 +1,5 @@
# -*- coding: utf-8 *-*
import uuid
from twisted.internet.protocol import ClientFactory
from twisted.internet import reactor
import random
Expand All @@ -18,7 +19,7 @@ def closer(target, candidates):

class RandomClient(spacecraft.server.ClientBase):

name = "navigator"
name = "navigator_" + str(uuid.uuid4())[:3]

gridmap = None
way = None
Expand All @@ -44,6 +45,16 @@ def look_to(self, target):
target.x, target.y, self.angle)
self.command('turn', value=turn)

def goto(self, target):
dist = abs(self.pos - target)
target = target - self.vel * dist / 70
self.look_to(target)

def aim(self, target, target_velocity):
dist = abs(self.pos - target)
target = target + target_velocity * dist / 70
self.look_to(target)

def messageReceived(self, message):
if self.gridmap is None:
self.gridmap = maptools.GridMap("maps/cross.svg")
Expand All @@ -55,6 +66,7 @@ def messageReceived(self, message):
return

self.pos = euclid.Point2(*message['gps']['position'])
self.vel = euclid.Point2(*message['gps']['velocity'])
self.angle = message['gps']['angle']

# if number of enemies visible == 1
Expand All @@ -65,13 +77,21 @@ def messageReceived(self, message):
if obj['object_type'] in ['player']:
enemies += 1
ep = p2(*obj['position'])
ev = p2(*obj['velocity'])

if enemies == 1:
if self.gridmap.visible(self.pos, ep):
self.look_to(ep)
self.aim(ep, ev)
self.command("throttle", value=1)
self.command("fire")
return
else:
print "enemy not visible."
elif enemies > 1:
# FLEE
while abs(self.pos - self.camp) < 150:
self.camp, self.camp_look = random.choice(self.camp_options)


# camped!!!
if abs(self.pos - self.camp) < 10:
Expand All @@ -95,10 +115,8 @@ def messageReceived(self, message):


waypoint = p2(*self.gridmap.towards_goal_from(self.pos))
print "going to", waypoint, "from", self.pos
print "w1", self.gridmap.is_wall(waypoint)

self.look_to(waypoint)
self.goto(waypoint)
self.command("throttle", value=1)


Expand Down
96 changes: 64 additions & 32 deletions bots/sulu.py
Expand Up @@ -9,6 +9,9 @@
TILE_SIZE = 10
TWO_PI = 2 * pi

def dist(x1, y1, x2, y2):
return sqrt((x1 - x2)**2 + (y1 - y2)**2)

class Wall(object):
def __init__(self, x, y, w, h):
self.x, self.y, self.w, self.h = x, y, w, h
Expand Down Expand Up @@ -65,8 +68,8 @@ def __init__(self, x, y, speedx, speedy):
self.certainty = 50

def step(self):
self.x += self.speedx
self.y += self.speedy
self.x += self.speedx / 10
self.y += self.speedy / 10
self.certainty -= 1

class NavigatorClient(spacecraft.server.ClientBase):
Expand All @@ -87,46 +90,73 @@ def messageReceived(self, message):
if parser:
parser(message)

def filter_visible(self, objs, x, y, obj_type):
result = [o for o in objs if o['object_type'] == obj_type and
self.has_line_of_fire(x, y, o['position'][0], o['position'][1])]
result.sort(key=lambda o:(o['position'][0] - x)**2 + (o['position'][1] - y)**2)
return result

def is_incoming(self, x, y, bullet):
bulletx, bullety = bullet['position']
speedx, speedy = bullet['velocity']
nextdist = dist(x, y, bulletx + speedx, bullety + speedy)
return nextdist < dist(x, y, bulletx, bullety) * 0.9

def parse_sensor(self, message):
if 'gps' not in message:
return
x, y = message['gps']['position']
angle = message['gps']['angle']
speedx, speedy = message['gps']['velocity']
tracking = False
# Increase visited tile count
self.visit(x, y)

# Check if we should track
for obj in message.get('proximity', []):
# FIXME: If there's a player, forget the powerup!
if obj['object_type'] in ['powerup', 'player']:
trackx, tracky = obj['position']
trackspeedx, trackspeedy = obj['velocity']
if self.has_line_of_fire(x, y, trackx, tracky):
tracking = True
d = sqrt((x - trackx)**2 + (y - tracky)**2)
if obj['object_type'] == 'player':
turn = relative_angle(x, y, trackx, tracky, angle)
self.command('turn', value=turn)
self.guesstimate = Guesstimate(trackx, tracky, trackspeedx, trackspeedy)
self.command("fire")
else:
# (x + speedx, y + speedy) here, to compensate the "orbit" effect
turn = relative_angle(
x + speedx * d / 70, y + speedy * d / 70,
trackx, tracky, angle)
self.command('turn', value=turn)
self.command("throttle", value=1)
objs = message.get('proximity', [])
bullets = self.filter_visible(objs, x, y, 'bullet')
bullets = [b for b in bullets if self.is_incoming(x, y, b)]
players = self.filter_visible(objs, x, y, 'player')
powerups = self.filter_visible(objs, x, y, 'powerup')
if players:
#~ print "Firing at player"
obj = players[0]
trackx, tracky = obj['position']
trackspeedx, trackspeedy = obj['velocity']
d = dist(x, y, trackx, tracky)
turn = relative_angle(x, y, trackx, tracky, angle)
self.command('turn', value=turn)
self.guesstimate = Guesstimate(trackx, tracky, trackspeedx, trackspeedy)
self.command("fire")
elif bullets:
#~ print "Firing at bullet"
obj = bullets[0]
trackx, tracky = obj['position']
trackspeedx, trackspeedy = obj['velocity']
d = sqrt((x - trackx)**2 + (y - tracky)**2)
turn = relative_angle(x, y, trackx, tracky, angle)
self.command('turn', value=turn)
self.command("fire")
elif powerups:
#~ print "Grabbing powerup"
obj = powerups[0]
trackx, tracky = obj['position']
trackspeedx, trackspeedy = obj['velocity']
d = sqrt((x - trackx)**2 + (y - tracky)**2)
# (x + speedx, y + speedy) here, to compensate the "orbit" effect
turn = relative_angle(
x + speedx * d / 70, y + speedy * d / 70,
trackx, tracky, angle)
self.command('turn', value=turn)
self.command("throttle", value=1)
#~ else:
#~ print obj
if not tracking:
if self.guesstimate and self.guesstimate.certainty > 0:
turn = relative_angle(x, y, self.guesstimate.x, self.guesstimate.y, angle)
self.command('turn', value=turn)
self.command("fire")
self.guesstimate.step()
return
elif self.guesstimate and self.guesstimate.certainty > 0:
#~ print "Firing at a guesstimate", self.guesstimate.certainty
turn = relative_angle(x, y, self.guesstimate.x, self.guesstimate.y, angle)
self.command('turn', value=turn)
self.command("fire")
self.guesstimate.step()
else:
#~ print "No guesstimate"
# Pick a good next exploration tile
if self.going is None or not self.has_line_of_fire(x, y, self.going.x, self.going.y):
options = [t for t in self.tiles
Expand All @@ -147,6 +177,7 @@ def parse_sensor(self, message):
divergence = (targetangle - speedangle) % TWO_PI
divergence = min(divergence, TWO_PI - divergence)
if speed > 500 and divergence < 0.1:
#~ print "Firing at random"
fireangle = self.pick_fireangle(x, y, speedx, speedy, angle)
if fireangle is not None:
self.command("turn", value=fireangle)
Expand All @@ -159,6 +190,7 @@ def parse_sensor(self, message):
#~ print "Not bang because divergence = %.3f" % divergence
#~ else:
#~ print "EH!? OGG WANT BANG!!1! Y U NO BANG!??!?1!?"
#~ print "Going to", self.going
turn = relative_angle(x, y, self.going.x + speedx, self.going.y + speedy, angle)
self.command("throttle", value=1)
self.command("turn", value=turn)
Expand Down Expand Up @@ -216,7 +248,7 @@ def pick_fireangle(self, x, y, speedx, speedy, angle):
iright = w.intersect(right)
if iright:
dright = min(dright, iright.distance(origin))
if max(dleft, dright) < 25:
if max(dleft, dright) < 35:
return
COMPENSATE = pi / 8
if dleft > dright:
Expand Down
24 changes: 17 additions & 7 deletions spacecraft/monitor.py
Expand Up @@ -136,6 +136,16 @@ def process_events(self):
self.track_next()
elif event.key == pygame.K_RIGHT:
self.track_previous()
elif event.key == pygame.K_UP:
self.zoom_in()
elif event.key == pygame.K_DOWN:
self.zoom_out()

def zoom_in(self):
self.scene.scale(1.1)

def zoom_out(self):
self.scene.scale(0.9)

def process_message(self, message):
pass
Expand Down Expand Up @@ -167,8 +177,9 @@ def draw_avatar(self, position, angle, velocity, throttle=None,

def draw_proximity_area(self, position):
color = (36, 46, 56)
pygame.draw.circle(self.screen, color, position,
UNIVERSE_SCALING_FACTOR * world.ProximitySensor.radius, 1)
radius, _ = self.scene.to_screen(
world.ProximitySensor.radius, world.ProximitySensor.radius)
pygame.draw.circle(self.screen, color, position, radius, 1)

def draw_name(self, position, name):
font_size = 16
Expand Down Expand Up @@ -202,10 +213,9 @@ def render_screen(self, messages):
self.offset = self.next_offset
for wall in self.terrain:
x, y = self.to_screen((wall['x'], wall['y']))
w = int(wall['width'] * 7) # Because 7 works
h = int(wall['height'] * 7)
y = y - h
rect = pygame.Rect(x, y, w, h)
w, h = self.to_screen((wall['width'] + wall['x'],
wall['height'] + wall['y']))
rect = pygame.Rect(x, y, w - x, h - y)
pygame.draw.rect(self.screen, (100, 100, 100), rect, 0)
for msg in messages:
kind = msg.get("type", None)
Expand Down Expand Up @@ -267,7 +277,7 @@ def render_screen(self, messages):
def set_next_offset(self, msg):
if self.world_size==[0,0]:
# the world size has not arrived yet
return
return
x, y = self.scene.to_screen(*msg['position'])
speedx, speedy = msg['velocity']
w, h = self.scene.size
Expand Down
1 change: 1 addition & 0 deletions spacecraft/world.py
Expand Up @@ -177,6 +177,7 @@ def get_result_table(self):


class ObjectBase(object):
name = "unknown"

def __init__(self, map, x=None, y=None):
self.map = map
Expand Down