moth/tanks/Program.py

101 lines
2.5 KiB
Python
Executable File

#! /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.
"""
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()