Adds AI action freq timers
authordsc <david.schoonover@gmail.com>
Tue, 7 Dec 2010 09:51:13 +0000 (01:51 -0800)
committerdsc <david.schoonover@gmail.com>
Tue, 7 Dec 2010 09:51:13 +0000 (01:51 -0800)
16 files changed:
css/lttl.css
index.php
src/Y/class.cjs
src/Y/core.cjs
src/Y/delegate.cjs
src/Y/type.cjs
src/Y/types/array.cjs
src/Y/types/function.cjs
src/Y/types/object.cjs
src/Y/y.cjs
src/evt.cjs [moved from src/evt/class.cjs with 92% similarity]
src/evt/evt.js.php [deleted file]
src/tanks/thing/tank.cjs
src/tanks/thing/thing.cjs
tags.html
tanks.php [deleted file]

index 23b3e57..b3d805f 100644 (file)
@@ -57,7 +57,7 @@ table.grid td { /* outline:1px solid rgba(255,255,255,0.1); */
 #welcome legend { padding:0.5em; text-transform:uppercase; }
 */
 
-#debug { position:relative; top:1em; right:1em; }
+#debug { position:relative; top:1em; right:1em; z-index:500; }
     #debug .inner { position:absolute; top:0; right:0; padding:1em; }
     #debug .inner > * { float:right; margin-right:1em; }
 
index 8d435d9..6fe8590 100644 (file)
--- a/index.php
+++ b/index.php
 
 <div id="scripts">
 <?php
-    /* require "tanks.php"; Tanks::writeTags( Tanks::ALL_SCRIPTS ); */
-    require "tanks.php"; Tanks::writeLoaders();
+    $PYTHONPATH = "PYTHONPATH='/Users/dsc/.python/lib/python:/usr/local/lib/python2.7/site-packages:/usr/local/lib/python2.6/site-packages'";
+    
+    error_reporting(E_ALL);
+    echo "<!--\n";
+    echo shell_exec("$PYTHONPATH commonjs src/Y src/ezl src/tanks 2>&1");
+    echo "\n-->\n";
+    
+    include "tags.html";
 ?>
 </div>
 
index 5e90e10..0aa02c8 100644 (file)
@@ -2,18 +2,18 @@
 
 var type       = require('Y/type')
 ,   core       = require('Y/core')
-,   YFunction  = require('Y/types/function').YFunction
+,   yfn        = require('Y/types/function')
+,   YFunction  = yfn.YFunction
+,   unwrap     = yfn.unwrap
 ,   isFunction = type.isFunction
 ,   slice      = core.slice
 
 ,   globals   = (function(){ return this; })()
 ,   _Object   = globals.Object
 ,   _Function = globals.Function
-,   _Array    = globals.Array
 ,   _String   = globals.String
 ,   _Number   = globals.Number
 
-,   slice    = _Array.prototype.slice
 ,   hasOwn   = _Object.prototype.hasOwnProperty
 ,   getProto = _Object.getPrototypeOf
 
@@ -21,15 +21,17 @@ var type       = require('Y/type')
 ,   classToString = function toString(){ return this.className+"()"; }
 ;
 
-// Private delegating constructor -- must be defined for every
-// new class to prevent shared state. All construction is
-// actually done in the init method.
+/**
+ * @private Delegating constructor -- must be defined for every new class to
+ * prevent shared state. All construction is actually done in the init method.
+ */
 function _Class() {
-    var cls = arguments.callee
-    ,   instance = this;
+    var cls      = arguments.callee
+    ,   instance = this
+    ;
     
-    // Not subclassing
-    if ( cls.caller !== Class.fabricate ) {
+    // Not fabricating/subclassing
+    if ( unwrap(cls.caller) !== fabricate ) {
         if ( instance.init ){
             var result = instance.init.apply(instance, arguments);
             if (result) instance = result;
@@ -148,34 +150,44 @@ Class.className = Class.fn.className = "Class";
  * Create a new instance and run delegate constructor if it exists.
  * Unlike the keyword `new`, instantiate can be applied.
  */
-Class.instantiate = 
-    function instantiate(){
-        var instance = this.fabricate();
-        if ( instance.init ) {
-            var r = instance.init.apply(instance, arguments);
-            return (r !== undefined ? r : instance);
-        } else
-            return instance;
-    };
-    
+function instantiate(cls){
+    var instance = cls.fabricate();
+    if ( instance.init ) {
+        var r = instance.init.apply(instance, slice.call(arguments,1));
+        return (r !== undefined ? r : instance);
+    } else
+        return instance;
+}
+
+
 /**
  * Create new instance, but do not run the delegate constructor.
  */
-Class.fabricate =
-    function fabricate(){
-        return new this();
-    };
+function fabricate(cls){
+    return new cls();
+}
 
 /**
- * Class method of Classes, not to be confused with Y.subclass, which is a static method.
+ * As a class method, subclass simply creates a subclass of that class.
+ * As an instance method, this method creates a subclass using that object as the prototype.
+ * Note that still different is Y.subclass, which simply creates a new Y.Class.
  */
+function subclass(className, members){
+    return new Class(className, this, members);
+}
+
 Class.subclass =
-Class.fn.subclass =
-    function subclass(className, members){
-        return new Class(className, this, members);
-    };
+Class.fn.subclass = YFunction(subclass);
 
 
+[ fabricate, instantiate
+].forEach(function(fn){
+        fn = YFunction(fn);
+        var name = fn.getName();
+        exports[name] = fn;
+        Class[name] = fn.methodize();
+    });
+
 
 /**
  * Root-class for all Y-objects.
@@ -185,10 +197,10 @@ var YBase = new Class("YBase", {
 });
 
 
-
 exports['Class'] =
 exports['subclass']    = Class;
-exports['instantiate'] = Class.instantiate.bind(Class);
-exports['fabricate']   = Class.fabricate.bind(Class);
 exports['YBase']       = YBase;
+// exports['instantiate'] = instantiate;
+// exports['fabricate']   = fabricate;
+
 
index 72fa583..620723c 100644 (file)
@@ -88,10 +88,14 @@ function attr(o, key, value, def){
 }
 
 function extend( A, B ){
-    return slice.call(arguments,1).reduce(extendall, A);
+    var args = slice.call(arguments,1);
+    if ( type.isArray(A) )
+        return A.concat.apply(A, args);
+    else
+        return args.reduce(extendall, A);
 }
 function extendall(A, donor){ return reduce(donor, attrvk, A); }
-function attrvk(o, v, k){ return attr(o, k, v, o[k]); }
+function attrvk(o, v, k){     return attr(o, k, v, o[k]); }
 
 
 exports['reduce']  = reduce;
index 016be83..8bc9e64 100644 (file)
@@ -87,17 +87,26 @@ function attr(o, key, value, def){
     if ( type.isPlainObject(key) )
         return extend(o, key);
     
-    if ( value !== undefined || def !== undefined ){
+    if ( value !== undefined || def !== undefined )
         return set(o, key, value, def);
-    } else
-        return o[key];
+    
+    return o[key];
 }
 
 function extend( A, B ){
-    return slice.call(arguments,1).reduce(extendall, A);
+    var args = slice.call(arguments,1);
+    if ( !A ) return A;
+    
+    if ( notWrapped(A.extend) )
+        return A.extend.apply(A, args);
+    
+    if ( type.isArray(A) )
+        return A.concat.apply(A, args);
+    
+    return args.reduce(extendall, A);
 }
 function extendall(A, donor){ return reduce(donor, attrvk, A); }
-function attrvk(o, v, k){ return attr(o, k, v, o[k]); }
+function attrvk(o, v, k){     return attr(o, k, v, o[k]); }
 
 
 exports['reduce']  = reduce;
index 966aab8..9ff3782 100644 (file)
@@ -36,8 +36,8 @@ function type_of(obj){
         class2name[ toString.call(obj) ] || "object";
 }
 
-// isArray.types = [];
-function isArray(obj)    { return type_of(obj) === "array" /*|| obj instanceof Y.YArray*/ ; }
+var arrayLike = isArray.types = [];
+function isArray(obj)    { return type_of(obj) === "array" || (arrayLike.indexOf(type(obj)) !== -1); }
 function isFunction(obj) { return type_of(obj) === "function"; }
 function isString(obj)   { return type_of(obj) === "string"; }
 function isNumber(obj)   { return type_of(obj) === "number"; }
@@ -93,7 +93,7 @@ function type( o ) {
 
 function is( A, B ){
     if ( isArray(B) )
-        return B.map( is.bind(this,A) ).any(); // XXX: implicitly depends on YFunction, but we'll just quietly not use it
+        return B.some( is.bind(this,A) );
     else {
         var AT = type(A), BT = type(B);
         return (A instanceof BT || B instanceof AT || AT === BT);
index abbab0c..c9f11e8 100644 (file)
@@ -1,58 +1,95 @@
-var YCollection = require('Y/types/collection').YCollection
-,   mixin = require('Y/utils').mixin
-,   slice = require('Y/core').slice
+var Y           = require('Y/y').Y  // I *think* this is safe
+,   del         = require('Y/delegate')
+,   type        = require('Y/type')
+,   mixin       = require('Y/utils').mixin
+,   YCollection = require('Y/types/collection').YCollection
+
+,   _Array        = Array
+,   AP            = _Array.prototype
+,   slice         = AP.slice
+,   arrayToString = AP.toString
 ;
 
 exports['YArray'] =
 YCollection.subclass('YArray', function(YArray){
     
-    mixin(YArray, { donor:Array, chain:true,
+    // Add YArray to the things that count as arrays
+    type.isArray.types.push(YArray);
+    
+    mixin(YArray, { donor:_Array, chain:true,
         names:'push unshift sort splice reverse'.split(' ') });
-    mixin(YArray, { donor:Array, wrap:YArray.instantiate.bind(YArray),
+    mixin(YArray, { donor:_Array, wrap:YArray.instantiate.bind(YArray),
         names:'map forEach filter slice'.split(' ') });
-    mixin(YArray, { donor:Array,
+    mixin(YArray, { donor:_Array,
         names:'reduce some every indexOf lastIndexOf shift pop join'.split(' ') });
     
     
-    this.init = function initYArray(o){
+    this['init'] =
+    function initYArray(o){
         this._o = o || [];
     };
     
-    this.merge  =
-    this.concat =
+    this['clone'] =
+    function clone(){
+        return new YArray(this._o.slice(0));
+    };
+    
+    this['size'] =
+    function size(){
+        return this._o.length;
+    };
+    
+    this['toString'] =
+    function toString(){
+        return "Y[" + arrayToString.call(this._o) + "]";
+    };
+    
+    this['last'] =
+    function last(){
+        var A = this._o, L = A.length;
+        return ( L ? A[L-1] : undefined );
+    };
+    
+    function unwrapY(o){
+        return (o instanceof YArray ? o.end() : o);
+    }
+    
+    this['concat'] =
     function concat( donor ){
-        return new YArray( slice.call(arguments).reduce(function(A, donor ){
-            return A.concat(donor instanceof YArray ? donor.end() : donor);
-        }, this._o) );
+        var A = this._o;
+        return new YArray(A.concat.apply( A, slice.call(arguments,0).map(unwrapY) ));
+        // return new YArray( slice.call(arguments).reduce(function(A, donor ){
+        //     return A.concat(donor instanceof YArray ? donor.end() : donor);
+        // }, this._o) );
+    };
+    
+    this['extend'] =
+    function extend( donor ){
+        var A = this._o;
+        this._o = A.concat.apply( A, slice.call(arguments,0).map(unwrapY) );
+        return this;
     };
     
-    this.remove =
+    this['remove'] =
     function remove(v){
-        if (arguments.length > 1)
-            slice.call(arguments).forEach(this.remove, this);
-        else {
+        var L = arguments.length;
+        if (L == 1) {
             var idx = this.indexOf(v);
             if ( idx != -1 )
                 this.splice(idx, 1);
-        }
+        } else if (L > 1)
+            slice.call(arguments,0).forEach(this.remove, this);
         return this;
     };
     
-    this.last =
-    function last(){
-        var A = this._o;
-        return A[ A.length-1 ];
-    };
-    
-    this.unique =
+    this['unique'] =
     function unique(){
         return this.reduce(
             function(acc, v, i){
                 if (acc.indexOf(v) === -1)
                     acc.push(v);
                 return acc;
-                
-            }, new YArray() );
+            }, new YArray(), this );
         
         // return this.filter(function(v, i){
         //     // Executes in the context of the new array, so
@@ -70,39 +107,30 @@ YCollection.subclass('YArray', function(YArray){
     //     }).invoke('end');
     // };
     
-    // Like map, but produces a dict
-    // Y(["Foo?", "R&D"]).generate(encodeURIComponent)
-    //  -> Y({"Foo?":"Foo%3F", "R&D":"R%26D"})
-    this.generate =
-    function generate(fn, acc){
-        var args = slice.call(arguments),
-            fn = args.shift(),
-            acc = args.shift();
-        return this.reduce(function(acc, v, i){
-            return acc.attr(v, fn.apply( this, [v].concat(args) ));
-        }, Y(acc || {}));
+    /**
+     * Like map, but produces a YObject:
+     *      Y(["Foo?", "R&D"]).generate(encodeURIComponent)
+     *      ->
+     *      Y({
+     *          "Foo?" : "Foo%3F",
+     *          "R&D"  : "R%26D"
+     *      })
+     */
+    this['generate'] =
+    function generate(fn, cxt){
+        // var args = slice.call(arguments,2);
+        return this.reduce(function(dict, v){
+            return dict.attr(v, fn.call(this,v));
+        }, Y({}), cxt||this );
     };
     
     // Y([ ["foo", 1], ["bar", 2] ]).toDict()
     //  -> Y({foo:1, bar:2})
-    this.toDict =
+    this['toDict'] =
     function toDict(){
-        
-    };
-    
-    this.clone =
-    function clone(){
-        return new YArray(this._o.slice(0));
-    };
-    
-    this.size =
-    function size(){
-        return this._o.length;
-    };
-    
-    this.toString =
-    function toString(){
-        return "Y[" + (this._o || "") + "]";
+        return this._o.reduce(function(dict, kv){
+            return dict.attr(kv[0], kv[1]);
+        }, Y({}), this );
     };
     
     return this;
index 05d704d..c16d3a0 100644 (file)
@@ -9,8 +9,9 @@ var undefined
 ,   isFunction    = type.isFunction
 ,   slice         = core.slice
 
-,   _   = YFunction._ = {}
-,   YFP = YFunction.prototype
+,   YF  = YFunction
+,   _   = YF._ = {}
+,   YFP = YF.prototype
 ;
 
 function YFunction(fn){
@@ -30,7 +31,7 @@ function YFunction(fn){
 }
 
 core.extend( YFP, {
-    init   : YFunction,
+    init   : YF,
     attr   : methodize(core.attr),
     reduce : methodize(core.reduce),
     extend : methodize(core.extend),
@@ -40,7 +41,7 @@ core.extend( YFP, {
 
 function wraps(wrapper, fn) {
     wrapper[WRAPS] = fn;
-    return YFunction(wrapper);
+    return YF(wrapper);
 }
 
 function unwrap(fn){
@@ -127,7 +128,7 @@ function chain(f,g){
     return chained;
 }
 
-// YFunction.prototype.lazy = methodize(lazy);
+// YF.prototype.lazy = methodize(lazy);
 // function lazy(fn){
 //     var args = slice.call(arguments, 1)
 //     ,   L = unwrap(fn).length
@@ -207,7 +208,7 @@ function memoize(fn){
 // Memorized to reduce eval costs
 var
 _ofArityWrapper =
-YFunction._ofArityWrapper =
+YF._ofArityWrapper =
     memoize(function(n, limit){
         var i = n, args = [];
         while (i-- > 0) args.unshift('$'+i); // Can't use Y.range due to deps
@@ -248,7 +249,7 @@ function limit(fn, n){
 /**
  * Filter the arguments passed to the wrapper function
  */
-// YFunction.prototype.mask = mask;
+// YF.prototype.mask = mask;
 // function mask(){
 //     
 // }
@@ -269,24 +270,32 @@ function getName( fn ){
 
 
 
-exports['wraps']      = wraps;
-exports['unwrap']     = unwrap;
-exports['curry']      = curry;
-exports['methodize']  = methodize;
-exports['genericize'] = genericize;
-exports['compose']    = compose;
-exports['chain']      = chain;
-exports['bind']       = bind;
-exports['partial']    = partial;
-exports['memoize']    = memoize;
-exports['aritize']    = aritize;
-exports['limit']      = limit;
-exports['getName']    = getName;
-
-// Methodize and then attach to YFunction's prototype
-YFP.extend(core.map(exports, methodize));
+// exports['wraps']      = wraps;
+// exports['unwrap']     = unwrap;
+// exports['curry']      = curry;
+// exports['methodize']  = methodize;
+// exports['genericize'] = genericize;
+// exports['compose']    = compose;
+// exports['chain']      = chain;
+// exports['bind']       = bind;
+// exports['partial']    = partial;
+// exports['memoize']    = memoize;
+// exports['aritize']    = aritize;
+// exports['limit']      = limit;
+// exports['getName']    = getName;
+
+
+[   wraps, unwrap, getName,
+    curry, compose, chain, bind, partial,
+    methodize, genericize, memoize, aritize, limit
+].map(function(fn){
+    var name      = getName(fn);
+    YFP[name]     = methodize(fn);
+    exports[name] = fn;
+    return fn;
+}).forEach(YF); // Have to do this AFTER attaching to the prototype
 
 
 // Export these last to avoid methodizing them
-exports['YFunction']  = YFunction;
+exports['YFunction']  = YF(YF);
 exports._ = _;
index 07db9d7..42a2a60 100644 (file)
 var YCollection = require('Y/types/collection').YCollection
-,   type = require('Y/type')
-,   isArray = type.isArray
+,   YFunction   = require('Y/types/function').YFunction
+,   core        = require('Y/core')
+,   del         = require('Y/delegate')
+,   type        = require('Y/type')
 ;
 
+/** 
+ * Ensures an object has the given property or nested property chain. Each missing
+ *  link in a chain is filled with a new, empty object.
+ * @param {Object} base The object to search.
+ * @param {String} chain Property name or nested property chain starting at `base`.
+ *  Property chains are specified in dotted lookup syntax.
+ * @param {Function} [def] If supplied, this function will be called with no 
+ *  arguments to get an object to insert into a missing link.
+ * @return {Object} base
+ */
+function ensure(base, chain, def){
+    if (base && chain)
+        chain.split('.').reduce(ensurer, { 'obj':base, 'def':def });
+    return base;
+}
+function ensurer(meta, link) {
+    var o    = meta.obj
+    ,   def  = meta.def
+    ,   next = del.attr(o, link);
+    if (next === undefined){
+        next = def ? def() : {};
+        del.attr(o, link, next);
+    }
+    meta.obj = next;
+    return meta;
+}
 
-exports['YObject'] =
-YCollection.subclass('YObject', {
-    
-    'init': function initYObject(o){
-        this._o = o || {};
-    },
+/**
+ * Searches an object for a given subkey specified in dotted-property syntax.
+ * @param {Object} o Object to be searched.
+ * @param {Array|String} chain The property-chain to lookup.
+ * @return {Object|undefined} If chain is found, an object of the form:
+ *         `{ 'key': Qualified key name, 'obj': Parent object of key, 'val': Value at obj[key] }`
+ *     and `undefined` otherwise.
+ */
+function getNestedMeta(o, chain){
+    if ( !type.isArray(chain) )
+        chain = chain.toString().split('.');
+    return chain.reduce(metaGetter, { 'val':o });
+}
+function metaGetter(current, link){
+    var val  = current ? current.val : undefined
+    ,   next = del.attr(val,link) ;
     
-    /** 
-     * Ensures an object has the given property or nested property chain. Each missing link in a chain is filled with a new, empty object.
-     * @param {String} chain Property name or nested property chain starting at `base`. Property chains are specified in dotted lookup syntax.
-     * @return {this}
-     */
-    ensure : function ensure(chain){
-        if (chain) chain
-            .split('.')
-            .reduce(function(o,link) {
-                if( o && link && o[link] === undefined )
-                    o[link] = {};
-                return o[link];
-            }, this._o );
-        return this;
-    },
+    if ( next === undefined )
+        return undefined;
     
-    /**
-     * Searches a heirarchical object for a given subkey specified in dotted-property syntax.
-     * @param {Array|String} chain The property-chain to lookup.
-     * @param {Any} [def] Default value should the key be `undefined`.
-     * @param {Boolean} [meta] If supplied return an object of the form
-      *         `{ key: Qualified key name, obj: Parent object of key, value: Value at obj[key] }` 
-      *     if chain is found (and `undefined` otherwise).
-     * @return {Any} The value at the path, or `def` if `undefined`, otherwise `undefined`.
-     */
-    getNested : function getNested(chain, def, meta){
-        if ( !isArray(chain) )
-            chain = chain.toString().split('.');
-        
-        var lastIdx = chain.length-1
-        ,   ret = chain.reduce(function(current, key){
-            if ( current === undefined || current.value[key] === undefined )
-                return undefined;
-            else
-                return {
-                    key   : key,
-                    value : current.value[key],
-                    obj   : current.value
-                };
-        }, { value:this._o });
-        
-        if (ret !== undefined)
-            return (meta ? ret : ret.value);
-        else
-            return (meta ? { value:def } : def);
-    },
-    
-    /**
-     * Searches a heirarchical object for a given subkey specified in dotted-property
-     *  syntax, setting it wiht the provided value if found.
-     * @param {Array|String} chain The property-chain to lookup.
-     * @param {Any} value The value to set.
-     * @return {this}
-     */
-    setNested : function setNested(chain, value){
-        var prop = this.ensure(chain).getNested(chain);
+    return { 'key':link, 'val':next, 'obj':val };
+}
+
+/**
+ * Searches an object for a given subkey specified in dotted-property syntax.
+ * @param {Object} o Object to be searched.
+ * @param {Array|String} chain The property-chain to lookup.
+ * @param {Any} [def] Default value to return should the key be `undefined`.
+ * @return {Any} The value at the path, or `def` if `undefined`, otherwise `undefined`.
+ */
+function getNested(o, chain, def){
+    var ret = getNestedMeta(o, chain);
+    return (ret ? ret.val : def);
+}
+
+/**
+ * Sets `value` at the nested subkey specified in dotted-property syntax.
+ * Intermediate objects will be created as necessary.
+ * @param {Object} o Object to be searched.
+ * @param {Array|String} chain The property-chain to lookup.
+ * @param {Any} value The value to set.
+ * @return {Object} o
+ */
+function setNested(o, chain, value){
+    if (o && chain){
+        var prop = getNestedMeta(ensure(o,chain), chain);
         prop.obj[prop.key] = value;
-        return this;
     }
+    return o;
+}
+
+var YObject =
+exports['YObject'] =
+YCollection.subclass('YObject', function setupYObject(YObject){
+    
+    this['init'] =
+    function initYObject(o){
+        this._o = o || {};
+    };
     
 });
 
+
+core.forEach({
+    'ensure'     : ensure,
+    'metaGetter' : metaGetter,
+    'getNested'  : getNested,
+    'setNested'  : setNested
+}, function(fn, name){
+        fn = exports[name] = YFunction(fn);
+        YObject.fn[name] = fn.methodize();
+    });
+
index a9018a8..57bb49d 100644 (file)
@@ -17,12 +17,8 @@ var undefined
 ,   toString = OP.toString
 ,   hasOwn   = OP.hasOwnProperty
 
-,   core = require('Y/core')
-,   extend = core.extend
-
+,   del  = require('Y/delegate')
 ,   type = require('Y/type')
-,   type_of = type.type_of, isNumber = type.isNumber
-,   isPlainObject = type.isPlainObject, isArray = type.isArray
 ;
 
 /**
@@ -45,7 +41,7 @@ function Y(o){
     // Y( arguments, start=0, stop=arguments.length )
     // Cast `arguments` object to a real Array, optionally slicing at specified delimiters
     if ( o.prototype === undefined
-             && isNumber(o.length)
+             && type.isNumber(o.length)
              && !_Array.isArray(o)
              && o.constructor === _Object )
     {
@@ -60,12 +56,12 @@ function Y(o){
         // Merge Arrays or Objects
         // Y([0,1], [2,3], [4,5])   -> [0,1,2,3,4,5]
         // Y({foo:1}, {bar:2})      -> { foo:1, bar:2 }
-        if ( args.every(isArray) || args.every(isPlainObject) ) {
-            r = extend.apply(this, args);
+        if ( args.every(type.isArray) || args.every(type.isPlainObject) ) {
+            r = del.extend.apply(this, args);
         
         // Convenience of Y(Y.range())
-        } else if ( args.every(isNumber) ) {
-            r = Y.range.apply(this, A);
+        } else if ( args.every(type.isNumber) ) {
+            r = Y.range.apply(this, args);
         
         // We got random stuff: wrap an Array of it
         } else
@@ -75,7 +71,7 @@ function Y(o){
     }
     
     // Do we have a type-specific wrapper?
-    var name  = type_of(o)
+    var name  = type.type_of(o)
     ,   yname = 'Y' + name.charAt(0).toUpperCase() + name.slice(1)
     ,   YType = Y[yname]
     ;
similarity index 92%
rename from src/evt/class.cjs
rename to src/evt.cjs
index dfc3701..14b0090 100644 (file)
@@ -23,8 +23,9 @@ Class Methods
 Note: Metaprogramming events cannot depend on Class.
 */
 
-var Y = require('Y').Y
+var Y       = require('Y').Y
 ,   Emitter = require('Y/modules/y.event').Emitter
+,   unwrap  = require('Y/types/function').unwrap
 
 ,   isFunction      = Y.isFunction
 ,   KNOWN_CLASSES   = Class.KNOWN_CLASSES = exports['KNOWN_CLASSES'] = {}
@@ -43,7 +44,7 @@ function ConstructorTemplate() {
     ,   instance = this;
     
     // Not subclassing
-    if ( cls.caller !== Class.fabricate ) {
+    if ( unwrap(cls.caller) !== Y.fabricate ) {
         
         cls.fire('create', instance, {
             'instance' : instance,
@@ -214,33 +215,29 @@ Class.className = Class.fn.className = "Class";
  * Create a new instance and run delegate constructor if it exists.
  * Unlike the keyword `new`, instantiate can be applied.
  */
-Class.instantiate =
-    function instantiate(){
-        var instance = this.fabricate();
-        if ( instance.initialise )
-            instance.initialise.apply(instance, arguments);
-        return instance;
-    };
+function instantiate(){
+    var instance = this.fabricate();
+    if ( instance.initialise )
+        instance.initialise.apply(instance, arguments);
+    return instance;
+}
 
-/**
- * Create new instance, but do not run the delegate constructor.
- */
-Class.fabricate =
-    function fabricate(){
-        return new this();
-    };
+Class.instantiate = Y(instantiate).methodize();
+Class.fabricate   = Y.Class.fabricate;
 
 /**
  * Class/Instance method of Classes, not to be confused with Evt.subclass, which is a static method.
  */
 Class.subclass =
 Class.fn.subclass =
-    function subclass(className, members){
+    Y(function subclass(className, members){
         return new Class(className, this, members);
-    };
+    });
 
 
 // Expose
 exports['Class'] =
-exports['subclass'] = Class;
+exports['subclass']    = Class;
+exports['instantiate'] = instantiate;
+exports['fabricate']   = Y.fabricate;
 
diff --git a/src/evt/evt.js.php b/src/evt/evt.js.php
deleted file mode 100644 (file)
index c4ee4a0..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-function dump_file($path, $add_newline=true){
-    $size = filesize($path);
-    if ($size > 0) {
-        $f = fopen($path, "r");
-        echo fread($f, $size);
-        fclose($f);
-    }
-    if ($add_newline) echo "\n";
-}
-
-$js_files = array(
-    'evt.class'
-);
-
-function evt_js_list($path='') {
-    global $js_files;
-    $path = $path ? $path : dirname($_SERVER["REQUEST_URI"]);
-    // echo $path;
-    foreach ($js_files as $f) {
-        echo "<script src='$path/$f.js' type='text/javascript'></script>\n";
-    }
-}
-
-function evt_js_dump($expose=false) {
-    global $js_files;
-    if (!$expose)
-        echo "(function(){";
-    foreach ($js_files as $f)
-        dump_file("./$f.js");
-    if (!$expose)
-        echo "})();";
-}
-
-if ( basename($_SERVER["SCRIPT_FILENAME"]) == basename(__FILE__) ) {
-    if ( $_REQUEST["list"] )
-        evt_js_list();
-    else
-        evt_js_dump();
-}
\ No newline at end of file
index 10e2112..38f2251 100644 (file)
@@ -3,6 +3,7 @@ var Y          = require('Y').Y
 ,   Bullet     = require('tanks/thing/bullet').Bullet
 ,   Trajectory = require('tanks/map/trajectory').Trajectory
 ,   Vec        = require('ezl/math/vec').Vec
+,   Cooldown   = require('ezl/loop').Cooldown
 ,   shape      = require('ezl/shape')
 ,   Rect       = shape.Rect
 ,   Circle     = shape.Circle
@@ -28,7 +29,7 @@ Thing.subclass('Tank', {
     height : REF_SIZE*0.55,
     
     // Attributes
-    stats: {
+    stats : {
         hp        : 1,          // health
         
         move      : 0.75,       // move speed (squares/sec)
@@ -39,6 +40,15 @@ Thing.subclass('Tank', {
         shots     : 4           // max projectiles in the air at once
     },
     
+    // AI "Cooldowns" (max frequency of each action per sec)
+    ai : {
+        path          : 1.0,    // calculate a path to enemy
+        dodge         : 1.0,    // dodge an incoming bullet
+        shootIncoming : 0.5,    // shoot down incoming bullet
+        shootEnemy    : 0.75    // shoot at enemy tank if in range
+    },
+    
+    
     nShots : 0,
     currentMove : null,
     forceCurrentMove : false,
@@ -46,7 +56,7 @@ Thing.subclass('Tank', {
     
     
     
-    init : function init(align){
+    init : function initTank(align){
         Thing.init.call(this, align);
         this.onBulletDeath = this.onBulletDeath.bind(this);
         
@@ -60,8 +70,16 @@ Thing.subclass('Tank', {
     
     
     
+    /*
+    ai : {
+        path          : 1.0,    // calculate a path to enemy
+        dodge         : 1.0,    // dodge an incoming bullet
+        shootIncoming : 0.5,    // shoot down incoming bullet
+        shootEnemy    : 0.75    // shoot at enemy tank if in range
+     */
     
     act : function act(allotment){
+        var ai = this.ai;
         
         // Check to see if we should obey our last decision, and not recalc
         if ( this.forceCurrentMove && this.forceCurrentMove() && this.currentMoveLimit > NOW ) {
@@ -72,10 +90,11 @@ Thing.subclass('Tank', {
         
         
         // Try to shoot down nearby bullets
-        if ( this.ableToShoot() ) {
+        if ( ai.shootIncoming.ready && this.ableToShoot() ) {
             var bs = this.willCollide( this.findNearLike(25, isBullet) );
             // console.log('['+TICKS+':'+this.id, this, '] Shoot down bullets?', bs.size() && bs);
             if ( bs.size() ) {
+                ai.shootIncoming.activate(NOW);
                 var b = this.closestOf(bs);
                 // console.log('  --> Incoming! Shoot it down!', b);
                 this.shoot(b.loc.x, b.loc.y);
@@ -84,19 +103,23 @@ Thing.subclass('Tank', {
         }
         
         // Dodge incoming bullet
-        var bs = this.willCollide(this.findNearLike(71, isBullet), 5);
-        // console.log('['+TICKS+':'+this.id, this, '] Dodge bullets?', bs.size() && bs);
-        if ( bs.size() ) {
-            var bullet = this.closestOf(bs);
-            this.moveAwayFrom(bullet);
-            return this;
+        if (ai.dodge.ready) {
+            var bs = this.willCollide(this.findNearLike(71, isBullet), 5);
+            // console.log('['+TICKS+':'+this.id, this, '] Dodge bullets?', bs.size() && bs);
+            if (bs.size()) {
+                ai.dodge.activate(NOW);
+                var bullet = this.closestOf(bs);
+                this.moveAwayFrom(bullet);
+                return this;
+            }
         }
         
         // Try to blow up nearby tanks
-        if ( this.ableToShoot() ) {
+        if (ai.shootEnemy.ready && (this.stats.shots - this.nShots > 1)) {
             var t = this.findNearEnemies(71, true).shift();
             // console.log('['+TICKS+':'+this.id, this, '] Shoot at enemies?', t);
             if (t) {
+                ai.shootEnemy.activate(NOW);
                 // console.log('  --> I gotcha!', t);
                 this.shoot(t.loc.x, t.loc.y);
                 return this;
@@ -177,7 +200,7 @@ Thing.subclass('Tank', {
     },
     
     willCollide : function willCollide(bullets, wiggle){
-        bullets = ( !(Y.isArray(bullets) || bullets instanceof Y.YArray) ? [bullets] : bullets );
+        bullets = ( Y.isArray(bullets) ? bullets : [bullets] );
         wiggle  = wiggle || 0;
         
         var tank = this, bb = this.boundingBox
index 7d4503b..dc48f56 100644 (file)
@@ -1,7 +1,7 @@
-//#ensure "evt/class"
+//#ensure "evt"
 
 var Y           = require('Y').Y
-,   Class       = require('evt/class').Class
+,   evt         = require('evt')
 
 ,   Loc         = require('ezl/loc/loc').Loc
 ,   BoundingBox = require('ezl/loc/boundingbox').BoundingBox
@@ -11,7 +11,7 @@ var Y           = require('Y').Y
 
 Thing =
 exports['Thing'] =
-new Class('Thing', {
+new evt.Class('Thing', {
     
     init : function init(align){
         this.id    = Thing.THING_ID++;
@@ -21,6 +21,7 @@ new Class('Thing', {
         this.createCooldowns();
     },
     
+    // Attributes
     stats: {
         hp        : 1,          // health
         
@@ -32,7 +33,8 @@ new Class('Thing', {
         shots     : 5           // max projectiles in the air at once
     },
     
-    
+    // AI "Cooldowns" (max frequency of each action per sec)
+    ai : {}, // see Tank
     
     // *** Bookkeeping *** //
     
@@ -111,14 +113,20 @@ new Class('Thing', {
     },
     
     createCooldowns : function createCooldowns(){
-        var cs = this.cooldowns = {
-            attack: new Cooldown(1000 * this.stats.speed)
+        this.cooldowns = {
+            'attack': new Cooldown(1000 * this.stats.speed)
         };
-        this._cooldowns = Y(cs);
+        this.ai = Y(this.ai).map(function(freq, k){
+            return new Cooldown(1000 * freq);
+        });
+        
+        this._cooldowns = Y(this.cooldowns);
+        this._ai = Y(this.ai);
     },
     
     updateCooldowns : function updateCooldowns(){
         this._cooldowns.invoke('update', NOW);
+        this._ai.invoke('update', NOW);
         return this;
     },
     
index 66120b7..6a71653 100644 (file)
--- a/tags.html
+++ b/tags.html
@@ -3,16 +3,16 @@
 <script src="build/functional/to-function.js" type="text/javascript"></script>
 <script src="build/Y/type.js" type="text/javascript"></script>
 <script src="build/Y/core.js" type="text/javascript"></script>
-<script src="build/Y/y.js" type="text/javascript"></script>
 <script src="build/Y/delegate.js" type="text/javascript"></script>
 <script src="build/Y/types/function.js" type="text/javascript"></script>
 <script src="build/Y/op.js" type="text/javascript"></script>
 <script src="build/Y/utils.js" type="text/javascript"></script>
 <script src="build/Y/class.js" type="text/javascript"></script>
+<script src="build/Y/y.js" type="text/javascript"></script>
 <script src="build/Y/types/collection.js" type="text/javascript"></script>
-<script src="build/Y/types/string.js" type="text/javascript"></script>
 <script src="build/Y/types/array.js" type="text/javascript"></script>
 <script src="build/Y/types/object.js" type="text/javascript"></script>
+<script src="build/Y/types/string.js" type="text/javascript"></script>
 <script src="build/Y/types/number.js" type="text/javascript"></script>
 <script src="build/Y.js" type="text/javascript"></script>
 <script src="build/jquery.js" type="text/javascript"></script>
@@ -41,7 +41,7 @@
 <script src="build/ezl.js" type="text/javascript"></script>
 <script src="build/jquery.hotkeys.min.js" type="text/javascript"></script>
 <script src="build/tanks/globals.js" type="text/javascript"></script>
-<script src="build/evt/class.js" type="text/javascript"></script>
+<script src="build/evt.js" type="text/javascript"></script>
 <script src="build/ezl/util/binaryheap.js" type="text/javascript"></script>
 <script src="build/ezl/util/astar.js" type="text/javascript"></script>
 <script src="build/tanks/config.js" type="text/javascript"></script>
diff --git a/tanks.php b/tanks.php
deleted file mode 100644 (file)
index 60ca22d..0000000
--- a/tanks.php
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-
-class Tanks {
-    const MAIN_SCRIPTS = 1;
-    const SRC_SCRIPTS  = 2;
-    const LIB_SCRIPTS  = 4;
-    
-    const ONLY_LIB    = 4; // LIB_SCRIPTS; // wtf i can't use expressions of constants?
-    const SRC_AND_LIB = 6; // LIB_SCRIPTS  | SRC_SCRIPTS;
-    const ALL_SCRIPTS = 7; // MAIN_SCRIPTS | LIB_SCRIPTS | SRC_SCRIPTS;
-    
-    const BUILD_DIR = "build";
-    
-    static $modules = array(
-        // array( "main" => "src/Y/index.cjs", "loader" => "y-loader.js" )
-        array( "main" => "src/tanks/index.cjs", "loader" => "tanks-loader.js" )
-    );
-    
-    
-    
-    static $mainScripts = array(
-        "src/tanks/ui/main.js"
-    );
-    
-    static $srcScripts = array(
-        "src/tanks/tanks.js",
-        "src/tanks/globals.js",
-        "src/tanks/config.js",
-        "src/tanks/calc.js",
-        
-        "src/tanks/util/config.js",
-        
-        "src/tanks/thing/thing.js",
-        "src/tanks/thing/bullet.js",
-        "src/tanks/thing/tank.js",
-        "src/tanks/thing/customtank.js",
-        "src/tanks/thing/player.js",
-        
-        "src/tanks/map/loc.js",
-        "src/tanks/map/trajectory.js",
-        "src/tanks/map/level.js",
-        "src/tanks/map/pathmap.js",
-        
-        "src/tanks/ui/ui.js",
-        "src/tanks/ui/grid.js",
-        "src/tanks/ui/config.js",
-        
-        "src/tanks/game.js"
-    );
-    
-    
-    
-    static $libScripts = array(
-        "lib/jquery-1.4.3.js",
-        "lib/jquery.sparkline.min.js",
-        "lib/jquery.hotkeys.js",
-        
-        // "lib/uki/uki.dev.js",
-        // "lib/uki/uki-theamless.dev.js",
-        // "lib/uki/uki-more.dev.js",
-        // "lib/uki/uki-theme/aristo.js",
-        
-        "src/future.js",
-        "lib/cjs/require.js",
-        
-        "src/Y/y.js.php",
-        "src/Y/modules/y.event.js",
-        "src/Y/modules/y.kv.js",
-        "src/Y/modules/y.cookies.js",
-        
-        "src/evt/evt.class.js",
-        
-        "src/ezl/math/math.js",
-        "src/ezl/math/vec.js",
-        "src/ezl/math/line.js",
-        
-        "src/ezl/layer.js",
-        "src/ezl/shape/shape.js",
-        "src/ezl/shape/circle.js",
-        "src/ezl/shape/rect.js",
-        "src/ezl/shape/line.js",
-        "src/ezl/shape/polygon.js",
-        
-        "src/ezl/util/binaryheap.js",
-        "src/ezl/util/graph.js",
-        "src/ezl/util/astar.js",
-        
-        "src/ezl/util/tree/quadtree.js",
-        
-        "src/ezl/loop/eventloop.js",
-        "src/ezl/loop/fps.js",
-        "src/ezl/loop/cooldown.js",
-    );
-    
-    static function writeTags($scripts=null, $prefix="", $recompile=true) {
-        $scripts = $scripts ? $scripts : Tanks::SRC_AND_LIB;
-        
-        if ($scripts & Tanks::LIB_SCRIPTS)  foreach (self::$libScripts  as $s) js($s, $prefix);
-        if ($scripts & Tanks::SRC_SCRIPTS)  foreach (self::$srcScripts  as $s) js($s, $prefix);
-        if ($scripts & Tanks::MAIN_SCRIPTS) foreach (self::$mainScripts as $s) js($s, $prefix);
-    }
-    
-    static function compile($modules=null) {
-        $modules = ($modules ? $modules : self::$modules);
-        $PYTHONPATH = "PYTHONPATH='/Users/dsc/.python/lib/python:/usr/local/lib/python2.7/site-packages:/usr/local/lib/python2.6/site-packages'";
-        error_reporting(E_ALL);
-        echo "<!--\n";
-        foreach ($modules as $module) {
-            $ret = shell_exec("$PYTHONPATH commonjs src/tanks 2>&1"); //
-            echo "    ".trim(join("\n    ", explode("\n", $ret)));
-        }
-        echo "\n-->\n";
-        include "tags.html";
-    }
-    
-    static function writeLoaders($modules=null, $recompile=true){
-        $modules = ($modules ? $modules : self::$modules);
-        // js('lib/cjs/require.js');
-        if ($recompile) Tanks::compile($modules);
-        // foreach ($modules as $module) js($module['loader'], Tanks::BUILD_DIR."/");
-    }
-    
-}
-
-function js($src, $prefix="") {
-    echo "    <script src=\"$prefix$src\" type=\"text/javascript\"></script>\n";
-}
-
-
-
-?>
-