From 5f6eeeb1b85a4e693150639b77b8ac74218815b3 Mon Sep 17 00:00:00 2001 From: Curt Hash Date: Tue, 19 Jan 2010 15:31:15 -0700 Subject: [PATCH] more merged changes from server --- ctf/histogram.py | 8 ++++++-- ctf/points.py | 2 ++ ctf/scoreboard.py | 12 +++++++++--- tanks/lib/Pflanzarr.py | 25 ++++++++++++++++--------- tanks/lib/Program.py | 28 ++++++++++++++++++++++------ tanks/lib/actions.py | 3 ++- tanks/lib/conditions.py | 2 +- tanks/lib/setup.py | 4 ++-- 8 files changed, 60 insertions(+), 24 deletions(-) diff --git a/ctf/histogram.py b/ctf/histogram.py index 8afe39a..b7341d2 100755 --- a/ctf/histogram.py +++ b/ctf/histogram.py @@ -21,7 +21,9 @@ def main(s=None): catscores = {} for cat in s.categories(): - catscores[cat] = s.cat_points(cat) + score = s.cat_points(cat) + if score: + catscores[cat] = score scoresfile = tempfile.NamedTemporaryFile('w') fn = scoresfile.name @@ -38,6 +40,8 @@ def main(s=None): scoresfile.write('\n') for when, cat, team, score in s.log: + if not cat in catscores: + continue if when > now: if now: write_scores(now) @@ -59,7 +63,7 @@ set border 3 set xtics nomirror set ytics nomirror set nokey -set terminal png transparent size 640,200 x000000 xffffff +set terminal png transparent size 1200,400 x000000 xffffff set output "%(pngout)s,tmp" plot %(plot)s\n''' % {'plot': ','.join(plotparts), 'pngout': pngout}) diff --git a/ctf/points.py b/ctf/points.py index 5099550..ea0249c 100755 --- a/ctf/points.py +++ b/ctf/points.py @@ -167,6 +167,8 @@ class Storage: def team_points(self, team): points = 0 for cat, tot in self.points_by_cat.items(): + if not tot: + continue team_points = self.team_points_in_cat(cat, team) points += team_points / float(tot) return points diff --git a/ctf/scoreboard.py b/ctf/scoreboard.py index 4d25594..1c009ec 100755 --- a/ctf/scoreboard.py +++ b/ctf/scoreboard.py @@ -3,6 +3,7 @@ import cgitb; cgitb.enable() import os import sys +from cgi import escape as quote from . import config from . import teams from . import points @@ -14,6 +15,7 @@ def main(): s = points.Storage() categories = [(cat, s.cat_points(cat)) for cat in s.categories()] + categories = [(c, p) for (c, p) in categories if p > 0] print('Refresh: 10') print(config.start_html('Scoreboard', cls='wide')) @@ -28,7 +30,7 @@ def main(): team = open(fn).read() or house_team print('
') print(' %s' - % (cat, teams.color(team), team)) + % (cat, teams.color(team), quote(team[:15]))) except IOError: pass print('') @@ -41,16 +43,20 @@ def main(): total = s.team_points(team) totals.append((total, team)) for total, team in sorted(totals, reverse=True): + if total < 0.1: + break print('
  • %s (%0.3f)
  • ' - % (teams.color(team), team, total)) + % (teams.color(team), quote(team[:15]), total)) print('') for cat, total in categories: print('') scores = sorted([(s.team_points_in_cat(cat, team), team) for team in s.teams]) for score, team in scores: + if not score: + continue color = teams.color(team) print('
    ' % (float(score * 100)/total, color)) - print(' %s: %d' % (cat, team, score)) + print(' %s: %d' % (cat, quote(team[:15]), score)) print('
    ') print('') print('') diff --git a/tanks/lib/Pflanzarr.py b/tanks/lib/Pflanzarr.py index 5291faa..017fcf1 100644 --- a/tanks/lib/Pflanzarr.py +++ b/tanks/lib/Pflanzarr.py @@ -40,20 +40,23 @@ class Pflanzarr: tmpPlayers = os.listdir(self._playerDir) players = [] for p in tmpPlayers: - p = unquote(p, safe='') + p = unquote(p) if not (p.startswith('.') or p.endswith('#') or p.endswith('~'))\ and p in colors: players.append(p) AIs = {} for player in players: - AIs[player] = open(os.path.join(self._playerDir, player)).read() + qPlayer = quote(player) + AIs[player] = open(os.path.join(self._playerDir, qPlayer)).read() defaultAIs = self._getDefaultAIs(dir, difficulty) - assert len(players) >= 1, "There must be at least one player." + if not players: + self._tanks = [] + return # The one is added to ensure that there is at least one #default bot. - cols = math.sqrt(len(players) + 1) + cols = math.sqrt(len(players) + 3) if int(cols) != cols: cols = cols + 1 @@ -61,7 +64,7 @@ class Pflanzarr: if cols < 2: cols = 2 - rows = len(players)/cols + rows = (len(players) + 3)/cols if len(players) % cols != 0: rows = rows + 1 @@ -97,7 +100,11 @@ class Pflanzarr: def run(self, maxTurns=None): - print "Starting new game with %d players." % len(self._tanks) + + if self._tanks: + print "Starting new game with %d players." % len(self._tanks) + else: + return kills = {} for tank in self._tanks: @@ -229,7 +236,7 @@ class Pflanzarr: # Write a blank file if the winner is a default tank.. if winner.name != None: - winnerFile.write(tanks[0].name) + winnerFile.write(winner.name) winnerFile.close() resultsFile.write('\n'.join(html)) @@ -396,12 +403,12 @@ class Pflanzarr: try: file = open(self.TEAMS_FILE) except: - return {}.fromkeys(players, errorColor) + return {} colors = {} for line in file: try: - team, passwd, color = map(unquote, line.split('\t'),['']*3) + team, passwd, color = map(unquote, line.split('\t')) colors[team] = '#%s' % color except: colors[team] = errorColor diff --git a/tanks/lib/Program.py b/tanks/lib/Program.py index 2063d1f..4d287b2 100644 --- a/tanks/lib/Program.py +++ b/tanks/lib/Program.py @@ -29,21 +29,37 @@ functions. If all the conditions are satisfactory (true), all of the actions are given as orders. Conditions are separated by ampersands, actions separated by periods. Here are some examples of AI commands:
    -sensor(1) & sensor(2) & fireready() : fire();
    -sensor(0,0)&sin(5): move(40, 30) . turretcw(50);
    -sensor(4) & random(4,5) : led(1).settoggle(0,1);
    +sense(1) & sense(2) & fireready() : fire(); +sense(0,0)&sin(5): move(40, 30) . turretcw(50); +sense(4) & random(4,5) : led(1).settoggle(0,1); -Your tank will check its program each turn, and attempt to the best of its +Your tank will execute its program each turn(frame), and attempt to +the best of its abilities to carry out its orders (or die trying). Like any military mind, your tank may receive a plethora of often conflicting orders and information. This a SMART TANK, however. It knows that the proper thing to do with each subsystem is to have that subsystem follow only the last order given each turn. + +
    +#Setup commands define your tank when your program compiles
    +>addsensor(50, 0, 5, 1); # 0-Fire Sensor
    +>addsensor(30, 0, 180); # 1-Anti-collision sensor
    +
    +# These commands execute each frame.  
    +# Blank condition sections are true.
    +         : move(90, 100).
    +           turretset(0);
    +sense(0) : fire();
    +sense(1) : move(-100, 100)
    +
    """ import conditions import actions import setup +import traceback + class Statement(object): """Represents a single program statement. If all the condition Functions evaluate to True, the actions are all executed in order.""" @@ -82,8 +98,8 @@ class Program(object): try: action(tank) except Exception, msg: - self.errors.append("Bad setup action, line %d, msg: %s" % \ - (action.lineNum, msg)) + self.errors.append("Bad setup action, line %d, msg: %s, %s" % \ + (action.lineNum, msg, traceback.format_exc())) def __call__(self, tank): """Execute this program on the given tank.""" diff --git a/tanks/lib/actions.py b/tanks/lib/actions.py index 790afab..2dc12c6 100644 --- a/tanks/lib/actions.py +++ b/tanks/lib/actions.py @@ -57,7 +57,8 @@ class TurretSet(Function.Function): class Fire(Function.Function): """fire() - Attempt to fire the tanks laser cannon.""" + Attempt to fire the tanks laser cannon. + It's range is 50% of your sensor range.""" def __call__(self, tank): tank.setFire() diff --git a/tanks/lib/conditions.py b/tanks/lib/conditions.py index 3a6c0ac..5346a38 100644 --- a/tanks/lib/conditions.py +++ b/tanks/lib/conditions.py @@ -31,7 +31,7 @@ Returns True if the given toggle is set, False otherwise. """ def __init__(self, toggle): self._toggle = toggle def __call__(self, tank): - return tank.toggles[toggle] + return tank.toggles[self._toggle] class TimerCheck(Function.Function): """timer(#, [invert]) diff --git a/tanks/lib/setup.py b/tanks/lib/setup.py index 29bc861..267198b 100644 --- a/tanks/lib/setup.py +++ b/tanks/lib/setup.py @@ -14,7 +14,7 @@ Sensors are numbered, starting at 0, in the order they are added.

    range - The range of the sensor, as a percent of the tanks max range. angle - The angle of the center of the sensor, in degrees. -width - The width of the sensor, in percent (100 is a full circle). +width - The width of the sensor, in degrees. turretAttached - Normally, the angle is relative to the front of the tank. When this is set, the angle is relative to the current turret direction. @@ -53,7 +53,7 @@ starting at 0. if len(tank.toggles) >= tank.SENSOR_LIMIT: raise ValueError('You can not have more than 10 toggles.') - tank.toggles.append[self._state] + tank.toggles.append(self._state) class AddTimer(Function.Function): """addtimer(timeout)