#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; }
<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>
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
, 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;
* 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.
});
-
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;
+
}
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;
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;
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"; }
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);
-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
// }).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;
, isFunction = type.isFunction
, slice = core.slice
-, _ = YFunction._ = {}
-, YFP = YFunction.prototype
+, YF = YFunction
+, _ = YF._ = {}
+, YFP = YF.prototype
;
function YFunction(fn){
}
core.extend( YFP, {
- init : YFunction,
+ init : YF,
attr : methodize(core.attr),
reduce : methodize(core.reduce),
extend : methodize(core.extend),
function wraps(wrapper, fn) {
wrapper[WRAPS] = fn;
- return YFunction(wrapper);
+ return YF(wrapper);
}
function unwrap(fn){
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
// 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
/**
* Filter the arguments passed to the wrapper function
*/
-// YFunction.prototype.mask = mask;
+// YF.prototype.mask = mask;
// function mask(){
//
// }
-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._ = _;
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();
+ });
+
, 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
;
/**
// 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 )
{
// 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
}
// 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]
;
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'] = {}
, instance = this;
// Not subclassing
- if ( cls.caller !== Class.fabricate ) {
+ if ( unwrap(cls.caller) !== Y.fabricate ) {
cls.fire('create', instance, {
'instance' : instance,
* 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;
+++ /dev/null
-<?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
, 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
height : REF_SIZE*0.55,
// Attributes
- stats: {
+ stats : {
hp : 1, // health
move : 0.75, // move speed (squares/sec)
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,
- init : function init(align){
+ init : function initTank(align){
Thing.init.call(this, align);
this.onBulletDeath = this.onBulletDeath.bind(this);
+ /*
+ 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 ) {
// 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);
}
// 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;
},
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
-//#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
Thing =
exports['Thing'] =
-new Class('Thing', {
+new evt.Class('Thing', {
init : function init(align){
this.id = Thing.THING_ID++;
this.createCooldowns();
},
+ // Attributes
stats: {
hp : 1, // health
shots : 5 // max projectiles in the air at once
},
-
+ // AI "Cooldowns" (max frequency of each action per sec)
+ ai : {}, // see Tank
// *** Bookkeeping *** //
},
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;
},
<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>
<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>
+++ /dev/null
-<?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";
-}
-
-
-
-?>
-