Checkpoint in pathing refactor.
authordsc <david.schoonover@gmail.com>
Tue, 11 Jan 2011 03:25:26 +0000 (19:25 -0800)
committerdsc <david.schoonover@gmail.com>
Tue, 11 Jan 2011 03:25:26 +0000 (19:25 -0800)
20 files changed:
data/config.yaml
data/types/levels.yaml
pavement.py
src/ezl/layer/layer.cjs
src/tanks/game.cjs
src/tanks/globals.js
src/tanks/map/index.cjs
src/tanks/map/level.cjs
src/tanks/map/pathing/index.cjs
src/tanks/map/pathing/map-blockers.cjs [moved from src/tanks/map/map.cjs with 79% similarity]
src/tanks/map/pathing/map-pathing.cjs [moved from src/tanks/map/pathing/pathmap.cjs with 87% similarity]
src/tanks/map/pathing/map-searching.cjs [new file with mode: 0644]
src/tanks/map/pathing/map.cjs [new file with mode: 0644]
src/tanks/map/pathing/trajectory.cjs
src/tanks/map/pathing/traversal.cjs
src/tanks/thing/tank.cjs
src/tanks/thing/thing.cjs
src/tanks/ui/pathmapui.cjs
src/tanks/util/utils.cjs
www/data [new symlink]

index a52c410..9c01445 100644 (file)
@@ -1,20 +1,21 @@
 game:
-    timeDilation       : 1.0
-    gameoverDelay      : 1000
+    timeDilation        : 1.0
+    # zoom                : 1.0
+    gameoverDelay       : 1000
 debug:
-    showFpsGraph       : false
+    showFpsGraph        : false
     # createGridTable    : false
     # showGridCoords     : false
 map:
-    refSize            : &ref_size 50
-    minSplitSize       : 12.5
+    refSize             : &ref_size 50
+    minSplitSize        : 12.5
 pathing:
-    pathSquare         : *ref_size
-    overlayAiPaths     : false
-    overlayPathmap     : false
-    traceTrajectories  : false
+    pathSquare          : *ref_size
+    overlayAiPaths      : false
+    overlayPathmap      : false
+    traceTrajectories   : false
 ui:
-    createGridCanvas   : true
-    overlayOnPause     : true
-    showAttackCooldown : false
-    showCountdown      : true
+    createGridCanvas    : true
+    overlayOnPause      : true
+    showAttackCooldown  : false
+    showCountdown       : true
index 3a6b7da..35f3bc3 100644 (file)
@@ -57,6 +57,12 @@ types:
           - type: player
             align: 1
             loc: [325,475]
+          - type: green
+            align: 2
+            loc: [75,25]
+          - type: blue
+            align: 1
+            loc: [75,475]
           - type: blue
             align: 1
             loc: [175,475]
@@ -65,9 +71,6 @@ types:
             loc: [25,375]
           - type: green
             align: 2
-            loc: [75,25]
-          - type: green
-            align: 2
             loc: [425,75]
         items:
           - type: nitro
index d0ec9ed..d767048 100755 (executable)
@@ -95,7 +95,7 @@ def build_data():
 def build_scripts():
     "Builds js modules."
     info('Building scripts...')
-    sh('rm build/tanks/config.js')
+    sh('rm -f build/tanks/config.js')
     tags = sourceTags( commonjs(script_tags=True, capture=True) )
     with path('build/deps.html').open('w') as f:
         f.write(tags)
index 3cae1c7..55dca75 100644 (file)
@@ -29,8 +29,8 @@ Y.subclass('Layer', {
     animQueue  : null,
     _erased    : null,
     
-    layerWidth  : 0,  canvasWidth : 0,
-    layerHeight : 0,  canvasHeight : 0,
+    layerWidth  : 0,  canvasWidth  : 0, realWidth  : 0,
+    layerHeight : 0,  canvasHeight : 0, realHeight : 0,
     
     x: 0, y: 0, loc : null, // Position relative to parent
     
@@ -175,16 +175,19 @@ Y.subclass('Layer', {
         if (w === undefined && h === undefined)
             return new Vec(this.layerWidth,this.layerHeight);
         
-        if (w === null) w = this.layerWidth;
-        if (h === null) h = this.layerHeight;
+        if (w === null) w = this.realWidth;
+        if (h === null) h = this.realHeight;
         
-        this.layerWidth  = w;
-        this.layerHeight = h;
+        this.realWidth  = w;
+        this.realHeight = h;
+        
+        // HTMLElement.{width,height} is a long
+        this.layerWidth  = Math.round(w);
+        this.layerHeight = Math.round(h);
         
         var bb = this.bbox.resize(w,h)
         ,   nb = this.negBleed, pb = this.posBleed
         
-        // HTMLCanvas.{width,height} is a long
         ,   cw = this.canvasWidth  = Math.ceil(w + nb.x + pb.x)
         ,   ch = this.canvasHeight = Math.ceil(h + nb.y + pb.y)
         ;
index 8dfac07..3a50a85 100644 (file)
@@ -7,12 +7,11 @@ var Y         = require('Y').Y
 ,   Circle    = require('ezl/shape').Circle
 
 ,   config    = require('tanks/config').config
-,   map       = require('tanks/map')
 ,   thing     = require('tanks/thing')
+,   Level     = require('tanks/map/level').Level
 ,   Grid      = require('tanks/ui/grid').Grid
 ,   PathMapUI = require('tanks/ui/pathmapui').PathMapUI
 
-,   Level  = map.Level
 ,   Thing  = thing.Thing
 ,   Tank   = thing.Tank
 ,   Bullet = thing.Bullet
@@ -51,9 +50,9 @@ Y.subclass('Game', {
             Level.create('test', this, CAPACITY, REF_SIZE)
                 .appendTo(this.root);
         
-        this.pathmap = this.level.pathmap;
-        this.pathmap.ui = new PathMapUI(this, this.pathmap);
-        this.root.append(this.pathmap.ui);
+        this.map = this.level.map;
+        this.map.ui = new PathMapUI(this, this.map);
+        this.root.append(this.map.ui);
         
         // automatically keep track of units
         Thing.addEventListener('created', this.addThing);
@@ -184,7 +183,7 @@ Y.subclass('Game', {
             unit.render( this.level );
         }
         
-        this.pathmap.addBlocker(unit);
+        this.map.addBlocker(unit);
         
         return unit;
     },
@@ -195,7 +194,7 @@ Y.subclass('Game', {
         
         delete this.byId[unit.__id__];
         this.active.remove(unit);
-        this.pathmap.removeBlocker(unit);
+        this.map.removeBlocker(unit);
         
         if (unit instanceof Bullet)
             this.bullets.remove(unit);
@@ -206,10 +205,10 @@ Y.subclass('Game', {
     },
     
     moveThingTo : function moveThingTo(agent, x,y){
-        this.pathmap.removeBlocker(agent);
+        this.map.removeBlocker(agent);
         if (agent.dead) return agent;
         agent.position(x,y);
-        this.pathmap.addBlocker(agent);
+        this.map.addBlocker(agent);
         return agent;
     },
     
index b03d4be..24b2520 100644 (file)
@@ -19,20 +19,6 @@ var undefined
 ,   ELAPSED       = MS_PER_FRAME         // Time (ms) since previous tick
 ,   TICKS         = 0                    // Ticks since start of game
 
-/// Pathing Constants (from tanks/map/map) ///
-
-/** Does not obstruct other objects. */
-,   PASSABLE = 0
-
-/** Does not obstruct other objects, but still collides with them. */
-,   ZONE = 1
-
-/** Obstructs other blockers with its BoundingBox. */
-,   BLOCKING = 2
-
-/** Potentially obstructs other objects, but requires a special test once a BoundingBox collision has been detected. */
-,   IRREGULAR = 3
-
 
 /// Common Components of Computation ///
 
index f357fa0..ba5cba8 100644 (file)
@@ -2,7 +2,7 @@ require('Y').Y
 .extend(exports, {
     'pathing' : require('tanks/map/pathing'),
     
-    'Map'     : require('tanks/map/map').Map,
+    'Map'     : require('tanks/map/pathing').Map,
     'Level'   : require('tanks/map/level').Level,
     'Wall'    : require('tanks/map/wall').Wall,
     'Drywall' : require('tanks/map/drywall').Drywall,
index c31d975..393b6eb 100644 (file)
@@ -5,7 +5,7 @@ var Y          = require('Y').Y
 ,   Rect       = require('ezl/shape').Rect
 
 ,   Buff       = require('tanks/effects/buff').Buff
-,   PathMap    = require('tanks/map/pathing/pathmap').PathMap
+,   Map    = require('tanks/map/pathing/map').Map
 ,   Thing      = require('tanks/thing/thing').Thing
 ,   Tank       = require('tanks/thing/tank').Tank
 ,   Item       = require('tanks/thing/item').Item
@@ -36,7 +36,7 @@ new evt.Class('Level', {
     
     init : function init(game, capacity, buffer_size){
         this.game    = game;
-        this.pathmap = new PathMap(0,0, this.width, this.height, capacity, buffer_size);
+        this.map = new Map(0,0, this.width, this.height, capacity, buffer_size);
         
         var shape = this.shape = new Rect(this.width,this.height).fill('transparent');
         shape.layer.attr('class', this._cssClasses);
index 633d120..c9b122e 100644 (file)
@@ -1,6 +1,13 @@
+// Load in order to ensure class is assembled the right way
+require('tanks/map/pathing/map');
+require('tanks/map/pathing/map-blockers');
+require('tanks/map/pathing/map-pathing');
+require('tanks/map/pathing/map-searching');
+//
+
 require('Y').Y
 .extend(exports, {
-    'PathMap'    : require('tanks/map/pathing/pathmap').PathMap,
+    'Map'        : require('tanks/map/pathing/map').Map,
     'Traversal'  : require('tanks/map/pathing/traversal').Traversal,
     'Trajectory' : require('tanks/map/pathing/trajectory').Trajectory
 });
similarity index 79%
rename from src/tanks/map/map.cjs
rename to src/tanks/map/pathing/map-blockers.cjs
index 92461b4..82bede1 100644 (file)
@@ -1,27 +1,13 @@
 //  -*- mode: JavaScript; tab-width: 4; indent-tabs-mode: nil; -*-
-var Y        = require('Y').Y
-,   QuadTree    = require('ezl/util/tree/quadtree').QuadTree
-
+var Y = require('Y').Y
 ,   constants   = require('tanks/constants')
 ,   BoundsType  = constants.BoundsType
 ,   DensityType = constants.DensityType
-,
+,   Map = require('tanks/map/pathing/map').Map
+;
 
 
-Map =
-exports['Map'] =
-QuadTree.subclass('Map', {
-    allWalls   : null, // All walls in this map
-    innerWalls : null, // Non-boundary walls
-    denseWalls : null, // Non-boundary non-Fences
-    
-    
-    init : function initMap(x1,y1, x2,y2, capacity){
-        this.allWalls   = Y([]);
-        this.innerWalls = Y([]);
-        this.denseWalls = Y([]);
-        QuadTree.init.call(this, x1,y1, x2,y2, capacity);
-    },
+Y.core.extend(Map.fn, {
     
     addBlocker : function addBlocker(obj){
         this.removeBlocker(obj);
similarity index 87%
rename from src/tanks/map/pathing/pathmap.cjs
rename to src/tanks/map/pathing/map-pathing.cjs
index c81b110..36cdc97 100644 (file)
@@ -1,5 +1,6 @@
 //  -*- mode: JavaScript; tab-width: 4; indent-tabs-mode: nil; -*-
 var Y = require('Y').Y
+,   op = require('Y/op')
 
 ,   vec        = require('ezl/math/vec')
 ,   Vec        = vec.Vec
@@ -11,11 +12,19 @@ var Y = require('Y').Y
 ,   constants   = require('tanks/constants')
 ,   BoundsType  = constants.BoundsType
 ,   DensityType = constants.DensityType
-,   Map         = require('tanks/map/map').Map
-
+,   Map         = require('tanks/map/pathing/map').Map
+,   Trajectory  = require('tanks/map/pathing/trajectory').Trajectory
+,   Traversal   = require('tanks/map/pathing/traversal').Traversal
+,   Thing       = require('tanks/thing/thing').Thing
+,   Bullet      = require('tanks/thing/bullet').Bullet
 
+,   _X = 0, _Y = 1
+,   BULLET_MOVE_PER_FRAME = MS_PER_FRAME * Bullet.fn.stats.move*REF_SIZE/1000
 ,   SQRT_TWO = Math.sqrt(2)
-,
+
+,   kTrue = op.K(true)
+,   isBullet = Y.is(Bullet)
+;
 
 /**
  * A QuadTree which aids in pathing for AI.
@@ -24,47 +33,7 @@ var Y = require('Y').Y
  *  - Pathing methods will account for the unit's size when calculating paths,
  *    intersections, blocking, and similar tasks.
  */
-PathMap =
-exports['PathMap'] =
-Map.subclass('PathMap', {
-    // Config
-    pathSquare    : null,
-    pathSquareMid : null,
-    
-    // State
-    _squares : null,    // Cache of Square objects
-    _pathId : -1,       // Instance of A* being run, to track when to reset Square instances
-    
-    
-    
-    init : function init(x1,y1, x2,y2, capacity, buffer_size) {
-        this.buffer_size = buffer_size;
-        x1 -= buffer_size; y1 -= buffer_size;
-        x2 += buffer_size; y2 += buffer_size;
-        Map.init.call(this, x1,y1, x2,y2, capacity);
-        this._squares = {};
-    },
-    
-    /**
-     * Takes normal (not pathSquare-relative) coordinates.
-     */
-    _getSquare : function getSquare(x,y){
-        if (x instanceof Array) { y=x[1]; x=x[0]; }
-        var cache = this._squares
-        ,   SIZE = this.pathSquare ;
-        
-        x = Math.floor(x / SIZE) * SIZE;
-        y = Math.floor(y / SIZE) * SIZE;
-        var key = x+'_'+y
-        ,   sq  = cache[key] ;
-        
-        if (sq)
-            sq.reset();
-        else
-            sq = cache[key] = new Square(this, x,y);
-        
-        return sq;
-    },
+Y.core.extend(Map.fn, {
     
     /**
      * Finds the shortest path to a destination for the given agent.
@@ -168,6 +137,28 @@ Map.subclass('PathMap', {
         return Y([]);
     },
     
+    /**
+     * @private
+     * Takes normal (not pathSquare-relative) coordinates.
+     */
+    _getSquare : function getSquare(x,y){
+        if (x instanceof Array) { y=x[1]; x=x[0]; }
+        var cache = this._squares
+        ,   SIZE = this.pathSquare ;
+        
+        x = Math.floor(x / SIZE) * SIZE;
+        y = Math.floor(y / SIZE) * SIZE;
+        var key = x+'_'+y
+        ,   sq  = cache[key] ;
+        
+        if (sq)
+            sq.reset();
+        else
+            sq = cache[key] = new Square(this, x,y);
+        
+        return sq;
+    },
+    
     vec2Square : function vec2Square(x,y){
         if (x instanceof Array){ y = x.y; x = x.x; }
         var floor = Math.floor, SIZE = this.pathSquare;
@@ -203,19 +194,19 @@ Y.subclass('Square', new Vec(0,0), {
      * @param x Left coord of square.
      * @param y Top coord of square.
      */
-    init : function initSquare(pathmap, x,y){
+    init : function initSquare(map, x,y){
         Vec.init.call(this, x,y);
-        this.pathmap = pathmap;
+        this.map = map;
         this.reset();
     },
     
     reset : function reset(){
-        var pathId = this.pathmap._pathId;
+        var pathId = this.map._pathId;
         if (this.pathId === pathId)
             return this;
         
         this.pathId  = pathId;
-        this.agent   = this.pathmap._agent;
+        this.agent   = this.map._agent;
         this.blocked = this._blocked();
         
         this.dist      = 0;
@@ -232,7 +223,7 @@ Y.subclass('Square', new Vec(0,0), {
      * @private Calculates this.blocked value. Should only be called by reset() to cache the result.
      */
     _blocked : function blocked(){
-        var pm    = this.pathmap
+        var pm    = this.map
         // ,   bb    = this.agent.bbox
         
         // ,   origin = bb.relOrigin
@@ -266,7 +257,7 @@ Y.subclass('Square', new Vec(0,0), {
     getNeighbors : function getNeighbors(){
         var neighbors = []
         ,   abs   = Math.abs
-        ,   pm    = this.pathmap
+        ,   pm    = this.map
         ,   agent = pm._agent
         ,   SIZE  = pm.pathSquare
         
@@ -320,24 +311,8 @@ Y.subclass('Square', new Vec(0,0), {
 ;
 
 
-
-// Wrap QuadTree Methods to accept Rect-like objects
-'overlaps get set removeAll leaves collect'
-    .split(' ')
-    .forEach(function(name){
-        var method = PathMap.fn[name] || QuadTree.fn[name];
-        PathMap.fn[name] = function pmHandleRect(o){
-            var args = arguments, xy;
-            if (o.x1 !== undefined){
-                xy = [o.x1,o.y1, o.x2,o.y2];
-                args = (args.length === 1) ? xy : xy.concat(Y(args,1));
-            }
-            return method.apply(this, args);
-        };
-    });
-
 // Stay sync'd with config
 config.updateOnChange(
     ['pathing.pathSquare', 'pathing.pathSquareMid'],
-    PathMap.fn);
+    Map.fn);
 
diff --git a/src/tanks/map/pathing/map-searching.cjs b/src/tanks/map/pathing/map-searching.cjs
new file mode 100644 (file)
index 0000000..35d54ac
--- /dev/null
@@ -0,0 +1,109 @@
+//  -*- mode: JavaScript; tab-width: 4; indent-tabs-mode: nil; -*-
+var Y = require('Y').Y
+,   op = require('Y/op')
+
+,   vec        = require('ezl/math/vec')
+,   Vec        = vec.Vec
+,   Line       = require('ezl/math/line').Line
+,   QuadTree   = require('ezl/util/tree/quadtree').QuadTree
+,   BinaryHeap = require('ezl/util/tree/binaryheap').BinaryHeap
+
+,   config      = require('tanks/config').config
+,   constants   = require('tanks/constants')
+,   BoundsType  = constants.BoundsType
+,   DensityType = constants.DensityType
+,   Map         = require('tanks/map/pathing/map').Map
+,   Trajectory  = require('tanks/map/pathing/trajectory').Trajectory
+,   Traversal   = require('tanks/map/pathing/traversal').Traversal
+,   Thing       = require('tanks/thing/thing').Thing
+,   Bullet      = require('tanks/thing/bullet').Bullet
+
+,   _X = 0, _Y = 1
+,   BULLET_MOVE_PER_FRAME = MS_PER_FRAME * Bullet.fn.stats.move*REF_SIZE/1000
+,   SQRT_TWO = Math.sqrt(2)
+;
+
+
+Y.core.extend(Map.fn, {
+    
+    // moveAwayFrom : function moveAwayFrom(agent){
+    //     var mid = this.midpoint
+    //     ,   trj = agent.trajectory.tangent(mid)
+    //     
+    //     ,   wall = this.closestOf(this.game.map.allWalls)
+    //     ,   wmid = wall.midpoint
+    //     
+    //     ,   lvl = this.game.level.bbox, w = lvl.width, h = lvl.height
+    //     ,   x   = ((mid.x - wmid.x) > 0 ? w : 0)
+    //     ,   y   = ((mid.y - wmid.y) > 0 ? h : 0)
+    //     ,   to  = this.currentMove = trj.near(x,y);
+    //     
+    //     this.forceCurrentMove = this.willCollide.bind(this, [agent], 5);
+    //     this.currentMoveLimit = this.now + 1000;
+    //     
+    //     this.move(to.x, to.y);
+    //     
+    //     // console.log('  --> Dodge', agent, 'away from', wall, 'to', to);
+    //     return to;
+    // },
+    
+    findNearLike : function findNearLike(me, ticks, fn){
+        if (fn) fn = fn.toFunction();
+        
+        var within = BULLET_MOVE_PER_FRAME*ticks
+        ,   bb = me.bbox
+        ,   x1 = bb.x1 - within, y1 = bb.y1 - within
+        ,   x2 = bb.x2 + within, y2 = bb.y2 + within
+        ,   dudes = this.get(x1,y1, x2,y2)
+        ;
+        if (fn && dudes.length)
+            return dudes.filter(fn, me);
+        else
+            return dudes;
+    },
+    
+    findNearEnemies : function findNearEnemies(me, ticks){
+        return this.findNearLike(me, ticks, this._nearEnemyFilter);
+    },
+    
+    _nearEnemyFilter : function nearEnemyFilter(agent){
+        var me = this; // Runs in the context of the 'me' unit; @see this.findNearLike()
+        return agent.isCombatant && agent.align !== me.align;
+    },
+    
+    findNearEnemiesInSight : function findNearEnemiesInSight(me, ticks){
+        return this.findNearLike(me, ticks, this._nearEnemyInSightFilter);
+    },
+    
+    _nearEnemyInSightFilter : function nearEnemyInSightFilter(agent){
+        var me = this; // Runs in the context of the 'me' unit; @see this.findNearLike()
+        return ( agent.align !== me.align && agent.isCombatant && 
+                 new Trajectory(me, me.loc, agent.loc).pathBlocked(agent) );
+    },
+    
+    closestOf : function closestOf(me, agents){
+        if ( !(agents && agents.length) )
+            return null;
+        
+        return agents.sort(function(a,b){
+            return op.cmp(
+                manhattan(a.midpoint, me.loc),
+                manhattan(b.midpoint, me.loc) );
+        })[0];
+    },
+    
+    willCollide : function willCollide(me, bullets, wiggle){
+        bullets = ( Y.isArray(bullets) ? bullets : [bullets] );
+        wiggle  = wiggle || 0;
+        
+        var bb = me.bbox
+        ,   w  = bb.width+wiggle, h = bb.height+wiggle ;
+        return bullets.filter(function(agent){
+            var trj = agent.trajectory;
+            return ( !agent.dead
+                &&  trj.comesWithin(me, w,h)
+                && !trj.pathBlocked(me) );
+        });
+    }
+    
+});
diff --git a/src/tanks/map/pathing/map.cjs b/src/tanks/map/pathing/map.cjs
new file mode 100644 (file)
index 0000000..3d7ce32
--- /dev/null
@@ -0,0 +1,57 @@
+//  -*- mode: JavaScript; tab-width: 4; indent-tabs-mode: nil; -*-
+var Y = require('Y').Y
+,   QuadTree    = require('ezl/util/tree/quadtree').QuadTree
+
+,   constants   = require('tanks/constants')
+,   BoundsType  = constants.BoundsType
+,   DensityType = constants.DensityType
+,
+
+
+Map =
+exports['Map'] =
+QuadTree.subclass('Map', {
+    // Config
+    pathSquare    : null,
+    pathSquareMid : null,
+    
+    // State
+    _squares : null,    // Cache of Square objects
+    _pathId : -1,       // Instance of A* being run, to track when to reset Square instances
+    
+    allWalls   : null, // All walls in this map
+    innerWalls : null, // Non-boundary walls
+    denseWalls : null, // Non-boundary non-Fences
+    
+    
+    
+    init : function initMap(x1,y1, x2,y2, capacity, buffer_size) {
+        this._squares = {};
+        this.allWalls   = Y([]);
+        this.innerWalls = Y([]);
+        this.denseWalls = Y([]);
+        
+        this.buffer_size = buffer_size;
+        x1 -= buffer_size; y1 -= buffer_size;
+        x2 += buffer_size; y2 += buffer_size;
+        
+        QuadTree.init.call(this, x1,y1, x2,y2, capacity);
+    }
+
+
+});
+
+// Wrap QuadTree Methods to accept Rect-like objects
+'overlaps get set removeAll leaves collect'
+    .split(' ')
+    .forEach(function(name){
+        var method = Map.fn[name] || QuadTree.fn[name];
+        Map.fn[name] = function mapHandleRect(o){
+            var args = arguments, xy;
+            if (o.x1 !== undefined){
+                xy = [o.x1,o.y1, o.x2,o.y2];
+                args = (args.length === 1) ? xy : xy.concat(Y(args,1));
+            }
+            return method.apply(this, args);
+        };
+    });
index 6bd8add..5cc3892 100644 (file)
@@ -22,7 +22,7 @@ Line.subclass('Trajectory', {
         
         this.owner   = owner;
         this.game    = owner.game;
-        this.pathmap = this.game.pathmap;
+        this.map = this.game.map;
         
         this.reset(x1,y1, x2,y2, tdist, tCurrent);
     },
@@ -38,7 +38,7 @@ Line.subclass('Trajectory', {
         Line.init.call(this, x1,y1, x2,y2, tdist || this.tdist);
         
         // Find appropriate edge in direction of line
-        var pm = this.pathmap
+        var pm = this.map
         ,   ex = (x1 > x2 ? -REF_SIZE : REF_SIZE+pm.width )
         ,   ey = (y1 > y2 ? -REF_SIZE : REF_SIZE+pm.height)
         ,   edge = this.near(ex,ey)
@@ -155,9 +155,9 @@ Line.subclass('Trajectory', {
     pathBlocked : function pathBlocked(obj, ignore){
         var walls, blockers;
         if (this.owner.isProjectile)
-            walls = this.pathmap.denseWalls;
+            walls = this.map.denseWalls;
         else
-            walls = this.pathmap.innerWalls; // FIXME: won't filter out concave intersections with the bounds
+            walls = this.map.innerWalls; // FIXME: won't filter out concave intersections with the bounds
         
         blockers = walls
                     .concat( this.game.units )
index 6f6beda..bc0ca25 100644 (file)
@@ -22,7 +22,7 @@ Y.subclass('Traversal', {
         
         this.thing   = thing;
         this.game    = thing.game;
-        this.pathmap = thing.game.pathmap;
+        this.map = thing.game.map;
         this.bbox    = thing.bbox.clone();
         
         this.trajectory = trajectory || thing.trajectory;
@@ -61,7 +61,7 @@ Y.subclass('Traversal', {
         this.bbox.relocate(to); // BoundingBox.relocate() is in-place
         
         this.blockers =
-            this.pathmap.get(this.bbox)
+            this.map.get(this.bbox)
                 .remove(this.thing)
                 .sort(tr.compare);
         
index 4c318d5..2caad1c 100644 (file)
@@ -29,6 +29,8 @@ exports['Tank'] =
 Thing.subclass('Tank', function(Tank){
     
     Y.core.descriptors(this, {
+        isCombatant : true,
+        
         colors : {
             body   : '#83BB32',
             turret : '#1C625B',
@@ -92,9 +94,6 @@ Thing.subclass('Tank', function(Tank){
         this.elapsed = elapsed;
         this.now = now;
         
-        // this.continueMove();
-        // return;
-        
         // Check to see if we should obey our last decision, and not recalc
         if (this.forceCurrentMove && this.forceCurrentMove() && this.currentMoveLimit > now) {
             // console.log('forced!', this.currentMove);
@@ -174,7 +173,7 @@ Thing.subclass('Tank', function(Tank){
         
         ,   x1 = tx - pw2 - WIGGLE, y1 = ty - ph2 - WIGGLE
         ,   x2 = tx + pw2 + WIGGLE, y2 = ty + ph2 + WIGGLE
-        ,   blockers = this.game.pathmap.get(x1,y1, x2,y2).filter(filterShoot, this)
+        ,   blockers = this.game.map.get(x1,y1, x2,y2).filter(filterShoot, this)
         ;
         
         if ( blockers.size() )
@@ -254,7 +253,7 @@ Thing.subclass('Tank', function(Tank){
         this.forceCurrentMove = false;
         this.currentMoveLimit = -1;
         
-        var pm    = this.game.pathmap
+        var pm    = this.game.map
         ,   start = this.loc
         
         ,   path  = this.currentPath = pm.path(this, end)
@@ -264,97 +263,6 @@ Thing.subclass('Tank', function(Tank){
     };
     
     
-    /**
-     * TODO: Get this.currentMove etc out of the calc methods.
-     */
-    this['moveAwayFrom'] =
-    function moveAwayFrom(agent){
-        var mid = this.midpoint
-        ,   trj = agent.trajectory.tangent(mid)
-        
-        ,   wall = this.closestOf(this.game.pathmap.allWalls)
-        ,   wmid = wall.midpoint
-        
-        ,   lvl = this.game.level.bbox, w = lvl.width, h = lvl.height
-        ,   x   = ((mid.x - wmid.x) > 0 ? w : 0)
-        ,   y   = ((mid.y - wmid.y) > 0 ? h : 0)
-        ,   to  = this.currentMove = trj.near(x,y);
-        
-        this.forceCurrentMove = this.willCollide.bind(this, [agent], 5);
-        this.currentMoveLimit = this.now + 1000;
-        
-        this.move(to.x, to.y);
-        
-        // console.log('  --> Dodge', agent, 'away from', wall, 'to', to);
-        return to;
-    };
-    
-    this['find'] =
-    function find(x1,y1, x2,y2){
-        return this.pathmap.get(x1,y1, x2,y2);
-    };
-    
-    
-    var kTrue = op.K(true);
-    
-    this['findNearLike'] =
-    function findNearLike(ticks, fn){
-        fn = (fn || kTrue).toFunction();
-        
-        var within = BULLET_MOVE_PER_FRAME*ticks
-        ,   bb = this.bbox
-        ,   x1 = bb.x1 - within, y1 = bb.y1 - within
-        ,   x2 = bb.x2 + within, y2 = bb.y2 + within
-        ;
-        
-        return this.game.pathmap.get(x1,y1, x2,y2).filter(fn, this);
-    };
-    
-    this['findNearEnemies'] =
-    function findNearEnemies(ticks, needLineOfSight){ // TODO: Split off LOS version
-        return this.findNearLike(ticks, function nearEnemyFilter(agent){
-            var aLoc = agent.loc;
-            return ( agent.align !== this.align
-                  && (agent instanceof Tank)
-                  && !(needLineOfSight 
-                        && new Trajectory(this,this.loc,aLoc).pathBlocked(agent))
-                );
-        });
-    };
-    
-    this['closestOf'] =
-    function closestOf(agents){
-        if ( !(agents && agents.size()) )
-            return null;
-        
-        var cmp = op.cmp
-        ,   loc = this.loc ;
-        
-        agents.sort(function(a,b){
-            return cmp(
-                manhattan(a.midpoint,loc),
-                manhattan(b.midpoint,loc) );
-        });
-        
-        return agents.attr(0);
-    };
-    
-    this['willCollide'] =
-    function willCollide(bullets, wiggle){
-        bullets = ( Y.isArray(bullets) ? bullets : [bullets] );
-        wiggle  = wiggle || 0;
-        
-        var tank = this, bb = this.bbox
-        ,   w = bb.width+wiggle, h = bb.height+wiggle ;
-        
-        return bullets.filter(function(b){
-            var trj = b.trajectory;
-            return ( !b.dead
-                &&  trj.comesWithin(tank, w,h)
-                && !trj.pathBlocked(tank) );
-        });
-    };
-    
     this['getTurretLoc'] =
     function getTurretLoc(){
         var WIGGLE = 2
index 5487ab5..e184dc3 100644 (file)
@@ -53,9 +53,11 @@ new evt.Class('Thing', {
     dead    : false,
     dirty   : true,
     
-    // Properties
+    // Unit Flags
     blocking     : BoundsType.BLOCKING,
     density      : DensityType.DENSE,
+    isWall       : false,
+    isCombatant  : false,
     isProjectile : false,
     isRenderable : false,       // Agent will present itself for rendering when ready // FIXME: stupid hack
     active       : true,        // Agent takes actions?
index cf27951..aca2005 100644 (file)
@@ -6,7 +6,7 @@ var Y         = require('Y').Y
 
 ,   config    = require('tanks/config').config
 ,   BoundsType = require('tanks/constants').BoundsType
-,   PathMap   = require('tanks/map/pathing/pathmap').PathMap
+,   Map   = require('tanks/map/pathing/map').Map
 
 ,
 
@@ -20,7 +20,7 @@ Rect.subclass('PathMapUI', {
     overlayAiPaths : null,
     
     // Shape Config
-    _cssClasses : 'pathmap rect shape layer ezl',
+    _cssClasses : 'map rect shape layer ezl',
     
     
     // Blocking objects
@@ -36,11 +36,11 @@ Rect.subclass('PathMapUI', {
     
     
     
-    init : function initPathMapUI(game, pathmap){
+    init : function initPathMapUI(game, map){
         Y.bindAll(this, 'pathWithUI', 'cleanUpAgent', 'drawPathStep', 'overlayRegion');
         
         var level = game.level
-        ,   b = this.buffer = pathmap.buffer_size;
+        ,   b = this.buffer = map.buffer_size;
         Rect.init.call(this, level.width, level.height);
         // this.posBleed.x = this.posBleed.y = 
         // this.negBleed.x = this.negBleed.y = b;
@@ -48,18 +48,18 @@ Rect.subclass('PathMapUI', {
         this.size(null,null);
         
         this.game = game;
-        this.pathmap = pathmap;
+        this.map = map;
         this.highlights = Y([]);
         
         // Store ref to original path function
-        this._path = pathmap.path;
-        pathmap.path = this.pathWithUI;
+        this._path = map.path;
+        map.path = this.pathWithUI;
     },
     
     render : function render(ctx){
         // nb. AI paths are automatically drawn (and cleaned up) as they are created (and destroyed).
         
-        // Redraw pathmap
+        // Redraw map
         if (this.overlayPathmap)
             this.overlay(ctx);
         
@@ -69,7 +69,7 @@ Rect.subclass('PathMapUI', {
     
     overlay : function overlay(ctx){
         // console.group('overlay');
-        this.pathmap.reduce(this.overlayRegion, { 'ctx':ctx });
+        this.map.reduce(this.overlayRegion, { 'ctx':ctx });
         // console.groupEnd();
     },
     
@@ -104,10 +104,10 @@ Rect.subclass('PathMapUI', {
     },
     
     /**
-     * Wraps PathMap.path() to draw AI pathes.
+     * Wraps Map.path() to draw AI pathes.
      */
     pathWithUI : function pathWithUI(agent, x,y){
-        var pm    = this.pathmap
+        var pm    = this.map
         ,   path  = this._path.call(pm, agent, x,y)
         ,   start = vec.sum(pm._getSquare(agent.loc), pm.pathSquareMid)
         ;
index 86f52a1..6016604 100644 (file)
@@ -6,7 +6,7 @@ Object.dump = function(o){
 };
 
 function dumpPathmap(){
-    var pm = tanks.game.pathmap;
+    var pm = tanks.game.map;
     console.warn(new Date(), pm);
     pm.collect(pm.x1,pm.y1, pm.x2,pm.y2, function(acc, v, r){
         console.log(r+'');
diff --git a/www/data b/www/data
new file mode 120000 (symlink)
index 0000000..4909e06
--- /dev/null
+++ b/www/data
@@ -0,0 +1 @@
+../data
\ No newline at end of file