2010-03-07 23:57:15 -07:00
|
|
|
#! /usr/bin/python
|
|
|
|
|
|
|
|
import forf
|
|
|
|
import random
|
|
|
|
import rfc822
|
|
|
|
from cStringIO import StringIO
|
|
|
|
from math import pi
|
|
|
|
|
|
|
|
def deg2rad(deg):
|
|
|
|
return float(deg) * pi / 180
|
|
|
|
|
|
|
|
def rad2deg(rad):
|
|
|
|
return int(rad * 180 / pi)
|
|
|
|
|
|
|
|
class Environment(forf.Environment):
|
|
|
|
def __init__(self, tank, stdout):
|
|
|
|
forf.Environment.__init__(self)
|
|
|
|
self.tank = tank
|
|
|
|
self.stdout = stdout
|
|
|
|
|
|
|
|
def err(self, msg):
|
|
|
|
self.stdout.write('Error: %s\n' % msg)
|
|
|
|
|
|
|
|
def msg(self, msg):
|
|
|
|
self.stdout.write('%s\n' % msg)
|
|
|
|
|
|
|
|
def cmd_random(self, data):
|
|
|
|
high = data.pop()
|
|
|
|
ret = random.randrange(high)
|
|
|
|
data.push(ret)
|
|
|
|
|
|
|
|
def cmd_fireready(self, data):
|
|
|
|
ret = self.tank.fireReady()
|
|
|
|
data.push(ret)
|
|
|
|
|
|
|
|
def cmd_sensoractive(self, data):
|
|
|
|
sensor = data.pop()
|
|
|
|
try:
|
|
|
|
ret = int(self.tank.getSensorState(sensor))
|
|
|
|
except KeyError:
|
|
|
|
ret = 0
|
|
|
|
data.push(ret)
|
|
|
|
|
|
|
|
def cmd_getturret(self, data):
|
|
|
|
rad = self.tank.getTurretAngle()
|
|
|
|
deg = rad2deg(rad)
|
|
|
|
data.push(deg)
|
|
|
|
|
|
|
|
def cmd_setled(self, data):
|
|
|
|
self.tank.setLED()
|
|
|
|
|
|
|
|
def cmd_fire(self, data):
|
|
|
|
self.tank.setFire()
|
|
|
|
|
|
|
|
def cmd_move(self, data):
|
|
|
|
right = data.pop()
|
|
|
|
left = data.pop()
|
|
|
|
self.tank.setMove(left, right)
|
|
|
|
|
|
|
|
def cmd_setturret(self, data):
|
|
|
|
deg = data.pop()
|
|
|
|
rad = deg2rad(deg)
|
|
|
|
self.tank.setTurretAngle(rad)
|
|
|
|
|
|
|
|
|
|
|
|
class Program:
|
|
|
|
def __init__(self, tank, source):
|
|
|
|
self.tank = tank
|
|
|
|
self.stdout = StringIO()
|
|
|
|
self.env = Environment(self.tank, self.stdout)
|
|
|
|
|
|
|
|
code_str = self.read_source(StringIO(source))
|
|
|
|
self.env.parse_str(code_str)
|
|
|
|
|
|
|
|
def get_output(self):
|
|
|
|
return self.stdout.getvalue()
|
|
|
|
|
|
|
|
def read_source(self, f):
|
|
|
|
"""Read in a tank program, establish sensors, and return code.
|
|
|
|
|
|
|
|
Tank programs are stored as rfc822 messages. The header
|
|
|
|
block includes fields for sensors (Sensor:)
|
|
|
|
and other crap which may be used later.
|
2010-03-02 20:45:21 -07:00
|
|
|
"""
|
|
|
|
|
2010-03-07 23:57:15 -07:00
|
|
|
message = rfc822.Message(f)
|
|
|
|
print 'reading tank %s' % message['Name']
|
|
|
|
sensors = message.getallmatchingheaders('Sensor')
|
|
|
|
for s in sensors:
|
|
|
|
k, v = s.strip().split(':')
|
|
|
|
r, angle, width, turret = [int(p) for p in v.split()]
|
|
|
|
r = float(r) / 100
|
|
|
|
angle = deg2rad(angle)
|
|
|
|
width = deg2rad(width)
|
|
|
|
self.tank.addSensor(r, angle, width, turret)
|
|
|
|
return message.fp.read()
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
self.env.eval()
|
|
|
|
|