1. Lars Yencken
  2. aichallenge-py

Commits

Lars Yencken  committed b699c7d

Move more functionality into torus module.

  • Participants
  • Parent commits 746ea6b
  • Branches scent

Comments (0)

Files changed (5)

File MyBot.py

View file
  • Ignore whitespace
 
     def do_move_direction(self, loc, direction):
         "Move in a given direction, handling conflicting orders."
-        new_loc = self.ants.destination(loc, direction)
+        new_loc = loc.dest(direction)
         if (self.ants.unoccupied(new_loc) and new_loc not in self.plans):
             self.ants.issue_order((loc, direction))
             self.plans.add(new_loc)
         def expand(p):
             l0 = p[-1]
             for direction in ('n', 's', 'e', 'w'):
-                l = self.ants.destination(l0, direction)
+                l = l0.dest(l0, direction)
                 if l not in p and l not in self.plans[len(p)] and passable(l) \
                         and (l not in unseen or l in frontier):
                     yield p + (l,)
         for loc in ants.my_ants():
             options = []
             for d in directions:
-                dest = ants.destination(loc, d)
+                dest = loc.dest(d)
                 smell = value[dest]
                 if dest not in self.plans and self.ants.passable(dest):
                     options.append((smell, d))
     
     def do_setup(self, ants):
         "Initialise state with game variables."
-        self.hills = []
         self.rows = ants.rows
         self.cols = ants.cols
         self.seen = np.zeros((self.rows, self.cols), dtype=np.bool_)
                     plannable[loc] = True
 
     def remember_hills(self, ants):
-        for hill_loc, hill_owner in ants.enemy_hills():
-            if hill_loc not in self.hills:
-                self.hills.append(hill_loc)
-            self.enemy_hills.add(hill_loc)
-
-        self.destroyed_hills.update(self.enemy_hills.intersection(
-            ants.my_ants()))
+        my_ants = set(ants.my_ants())
+        for hill in ants.enemy_hills():
+            if hill.loc in my_ants:
+                self.destroyed_hills.add(hill.loc)
+            elif hill.loc not in self.destroyed_hills:
+                self.enemy_hills.add(hill.loc)
 
     def get_reward_matrix(self, frontier, ants):
         reward = np.ones((ants.rows, ants.cols), dtype=np.float32) * -1
         for food in ants.food():
             reward[food] = 15
 
-        for loc in ants.enemy_ants():
-            reward[loc] = 5
+        for ant in ants.enemy_ants():
+            reward[ant.loc] = 5
 
         for y, x in zip(*np.nonzero(frontier)):
             reward[y, x] += 2

File ants.py

View file
  • Ignore whitespace
 #!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+#  ants.py
+#  aichallenge-py
+#
+#  Created by Lars Yencken on 2011-11-15.
+#  Copyright 2011 Lars Yencken. All rights reserved.
+#
+
+"""
+Helper module providing a higher level game abstraction.
+"""
+
 import sys
 import traceback
 import random
 import time
-from collections import defaultdict
+from collections import defaultdict, namedtuple
 from math import sqrt
 import numpy as np
 
 MAP_OBJECT = '?%*.!'
 MAP_RENDER = PLAYER_ANT + HILL_ANT + PLAYER_HILL + MAP_OBJECT
 
-AIM = {'n': Loc(-1, 0),
-       'e': Loc(0, 1),
-       's': Loc(1, 0),
-       'w': Loc(0, -1)}
-RIGHT = {'n': 'e',
-         'e': 's',
-         's': 'w',
-         'w': 'n'}
-LEFT = {'n': 'w',
-        'e': 'n',
-        's': 'e',
-        'w': 's'}
-BEHIND = {'n': 's',
-          's': 'n',
-          'e': 'w',
-          'w': 'e'}
+Hill = namedtuple('Hill', 'loc owner')
+Ant = namedtuple('Ant', 'loc owner')
 
 class Ants():
     def __init__(self):
         self.cols = None
         self.rows = None
         self.map = None
-        self.hill_list = {}
-        self.ant_list = {}
+        self.hill_list = []
+        self.ant_list = []
         self.dead_list = defaultdict(list)
         self.food_list = []
         self.turntime = 0
         self.vision = None
         
         # clear hill, ant and food data
-        self.hill_list = {}
-        for l in self.ant_list.keys():
-            self.map[l] = LAND
-        self.ant_list = {}
+        self.hill_list = []
+        for a in self.ant_list:
+            self.map[a.loc] = LAND
+        self.ant_list = []
         for l in self.dead_list.keys():
             self.map[l] = LAND
         self.dead_list = defaultdict(list)
                         owner = int(tokens[3])
                         if tokens[0] == 'a':
                             self.map[l] = owner
-                            self.ant_list[l] = owner
+                            self.ant_list.append(Ant(l, owner))
                         elif tokens[0] == 'd':
                             # food could spawn on a spot where an ant just died
                             # don't overwrite the space unless it is land
                             self.dead_list[l].append(owner)
                         elif tokens[0] == 'h':
                             owner = int(tokens[3])
-                            self.hill_list[l] = owner
+                            self.hill_list.append(Hill(l, owner))
                         
     def time_remaining(self):
         return self.turntime - int(1000 * (time.clock() - self.turn_start_time))
         sys.stdout.flush()
     
     def my_hills(self):
-        return [loc for loc, owner in self.hill_list.items()
-                    if owner == MY_ANT]
+        return [h.loc for h in self.hill_list if h.owner == MY_ANT]
 
     def enemy_hills(self):
-        return [(loc, owner) for loc, owner in self.hill_list.items()
-                    if owner != MY_ANT]
+        return [h for h in self.hill_list if h.owner != MY_ANT]
         
     def my_ants(self):
         'return a list of all my ants'
-        return [loc for loc, owner in self.ant_list.items() if owner == MY_ANT]
+        return [ant.loc for ant in self.ant_list if ant.owner == MY_ANT]
 
     def enemy_ants(self):
         'return a list of all visible enemy ants'
-        return [(loc, owner) for loc, owner in self.ant_list.items()
-                    if owner != MY_ANT]
+        return [ant for ant in self.ant_list if ant.owner != MY_ANT]
 
     def food(self):
         'return a list of all food locations'
         'true if no ants are at the location'
         return self.map[loc] in (LAND, DEAD)
 
-    def destination(self, loc, direction):
-        'calculate a new location given the direction and wrap correctly'
-        return loc + AIM[direction]
-
     def direction(self, loc1, loc2):
         'determine the 1 or 2 fastest (closest) directions to reach a location'
         row1, col1 = loc1

File test_mdp.py

View file
  • Ignore whitespace
         value = mdp.value_iteration(reward, torus=True, gamma=0.5, eps=1e-5)
         assert abs(value - expected).mean() < 1e-5, str(value)
 
+def suite():
+    return unittest.TestSuite([
+            unittest.makeSuite(MDPPlaneTest),
+            unittest.makeSuite(MDPTorusTest),
+        ])
+
+if __name__ == '__main__':
+    unittest.TextTestRunner(verbosity=1).run(suite())
+

File test_torus.py

View file
  • Ignore whitespace
         self.assertEqual(l1.dist(l3), 10)
         self.assertEqual(l3.dist(l1), 10)
 
+    def test_dest(self):
+        l = torus.Loc(0, 0)
+        self.assertEqual(l.dest('n'), torus.Loc(14, 0))
+        self.assertEqual(l.dest('s'), torus.Loc(1, 0))
+        self.assertEqual(l.dest('e'), torus.Loc(0, 1))
+        self.assertEqual(l.dest('w'), torus.Loc(0, 19))
+
+if __name__ == '__main__':
+    unittest.TextTestRunner(verbosity=1).run(unittest.makeSuite(TorusTest))
+

File torus.py

View file
  • Ignore whitespace
 
 Loc = namedtuple('Loc', 'y x')
 
+AIM = {'n': Loc(-1, 0),
+       'e': Loc(0, 1),
+       's': Loc(1, 0),
+       'w': Loc(0, -1)}
+
 def init(rows, cols):
     global ROWS, COLS
     ROWS = rows
         return min(x_diff, COLS - x_diff) + min(y_diff, ROWS - y_diff)
     Loc.dist = _loc_dist
 
+    def _loc_dest(l, aim):
+        return l + AIM[aim]
+    Loc.dest = _loc_dest
+