From eb80e34a654e2e06c8d1da5be5620d54f16565c8 Mon Sep 17 00:00:00 2001 From: Micael Robles Date: Tue, 11 Jul 2017 17:43:32 -0300 Subject: [PATCH 01/10] added auto-shifting --- dist/README.md | 2 +- dist/blockrain.jquery.min.js | 2 +- dist/blockrain.zip | Bin 55927 -> 55806 bytes package-lock.json | 1854 ++++++++++++++++++++++++++++++++++ src/blockrain.jquery.src.js | 22 +- 5 files changed, 1877 insertions(+), 3 deletions(-) create mode 100644 package-lock.json diff --git a/dist/README.md b/dist/README.md index 4745dc4..20a6c84 100644 --- a/dist/README.md +++ b/dist/README.md @@ -21,7 +21,7 @@ Then you just include **jquery** and **blockrain** and setup the game with **$(' ```html - + diff --git a/dist/blockrain.jquery.min.js b/dist/blockrain.jquery.min.js index dfd9e9d..bf50ddc 100644 --- a/dist/blockrain.jquery.min.js +++ b/dist/blockrain.jquery.min.js @@ -8,5 +8,5 @@ * Released under the MIT license * http://aerolab.github.io/blockrain.js/LICENSE.txt */ - !function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)}(function(t){var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var o,n,s;for(s=0;null!=(n=i[s]);s++)try{o=t._data(n,"events"),o&&o.remove&&t(n).triggerHandler("remove")}catch(r){}e(i)}}(t.cleanData),t.widget=function(e,i,o){var n,s,r,a,h={},l=e.split(".")[0];return e=e.split(".")[1],n=l+"-"+e,o||(o=i,i=t.Widget),t.expr[":"][n.toLowerCase()]=function(e){return!!t.data(e,n)},t[l]=t[l]||{},s=t[l][e],r=t[l][e]=function(t,e){return this._createWidget?void(arguments.length&&this._createWidget(t,e)):new r(t,e)},t.extend(r,s,{version:o.version,_proto:t.extend({},o),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(o,function(e,o){return t.isFunction(o)?void(h[e]=function(){var t=function(){return i.prototype[e].apply(this,arguments)},n=function(t){return i.prototype[e].apply(this,t)};return function(){var e,i=this._super,s=this._superApply;return this._super=t,this._superApply=n,e=o.apply(this,arguments),this._super=i,this._superApply=s,e}}()):void(h[e]=o)}),r.prototype=t.widget.extend(a,{widgetEventPrefix:s?a.widgetEventPrefix||e:e},h,{constructor:r,namespace:l,widgetName:e,widgetFullName:n}),s?(t.each(s._childConstructors,function(e,i){var o=i.prototype;t.widget(o.namespace+"."+o.widgetName,r,i._proto)}),delete s._childConstructors):i._childConstructors.push(r),t.widget.bridge(e,r),r},t.widget.extend=function(e){for(var o,n,s=i.call(arguments,1),r=0,a=s.length;a>r;r++)for(o in s[r])n=s[r][o],s[r].hasOwnProperty(o)&&void 0!==n&&(e[o]=t.isPlainObject(n)?t.isPlainObject(e[o])?t.widget.extend({},e[o],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,o){var n=o.prototype.widgetFullName||e;t.fn[e]=function(s){var r="string"==typeof s,a=i.call(arguments,1),h=this;return s=!r&&a.length?t.widget.extend.apply(null,[s].concat(a)):s,this.each(r?function(){var i,o=t.data(this,n);return"instance"===s?(h=o,!1):o?t.isFunction(o[s])&&"_"!==s.charAt(0)?(i=o[s].apply(o,a),i!==o&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+s+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; attempted to call method '"+s+"'")}:function(){var e=t.data(this,n);e?(e.option(s||{}),e._init&&e._init()):t.data(this,n,new o(s,this))}),h}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{disabled:!1,create:null},_createWidget:function(i,o){o=t(o||this.defaultElement||this)[0],this.element=t(o),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),o!==this&&(t.data(o,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===o&&this.destroy()}}),this.document=t(o.style?o.ownerDocument:o.document||o),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:t.noop,_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(t.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var o,n,s,r=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(r={},o=e.split("."),e=o.shift(),o.length){for(n=r[e]=t.widget.extend({},this.options[e]),s=0;o.length-1>s;s++)n[o[s]]=n[o[s]]||{},n=n[o[s]];if(e=o.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];r[e]=i}return this._setOptions(r),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!e),e&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(e,i,o){var n,s=this;"boolean"!=typeof e&&(o=i,i=e,e=!1),o?(i=n=t(i),this.bindings=this.bindings.add(i)):(o=i,i=this.element,n=this.widget()),t.each(o,function(o,r){function a(){return e||s.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof r?s[r]:r).apply(s,arguments):void 0}"string"!=typeof r&&(a.guid=r.guid=r.guid||a.guid||t.guid++);var h=o.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+s.eventNamespace,c=h[2];c?n.delegate(c,l,a):i.bind(l,a)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(i).undelegate(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?o[t]:t).apply(o,arguments)}var o=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){t(e.currentTarget).addClass("ui-state-hover")},mouseleave:function(e){t(e.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){t(e.currentTarget).addClass("ui-state-focus")},focusout:function(e){t(e.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(e,i,o){var n,s,r=this.options[e];if(o=o||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],s=i.originalEvent)for(n in s)n in i||(i[n]=s[n]);return this.element.trigger(i,o),!(t.isFunction(r)&&r.apply(this.element[0],[i].concat(o))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(o,n,s){"string"==typeof n&&(n={effect:n});var r,a=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),r=!t.isEmptyObject(n),n.complete=s,n.delay&&o.delay(n.delay),r&&t.effects&&t.effects.effect[a]?o[e](n):a!==e&&o[a]?o[a](n.duration,n.easing,s):o.queue(function(i){t(this)[e](),s&&s.call(o[0]),i()})}}),t.widget}),function(t){"use strict";t.widget("aerolab.blockrain",{options:{autoplay:!1,autoplayRestart:!0,showFieldOnStart:!0,theme:null,blockWidth:10,autoBlockWidth:!1,autoBlockSize:24,difficulty:"normal",speed:20,asdwKeys:!0,playText:"Let's play some Tetris",playButtonText:"Play",gameOverText:"Game Over",restartButtonText:"Play Again",scoreText:"Score",onStart:function(){},onRestart:function(){},onGameOver:function(t){},onPlaced:function(){},onLine:function(t,e,i){}},start:function(){this._doStart(),this.options.onStart.call(this.element)},restart:function(){this._doStart(),this.options.onRestart.call(this.element)},gameover:function(){this.showGameOverMessage(),this._board.gameover=!0,this.options.onGameOver.call(this.element,this._filled.score)},_doStart:function(){this._filled.clearAll(),this._filled._resetScore(),this._board.cur=this._board.nextShape(),this._board.started=!0,this._board.gameover=!1,this._board.dropDelay=5,this._board.render(!0),this._board.animate(),this._$start.fadeOut(150),this._$gameover.fadeOut(150),this._$score.fadeIn(150)},pause:function(){this._board.paused=!0},resume:function(){this._board.paused=!1},autoplay:function(t){"boolean"!=typeof t&&(t=!0),this.options.autoplay=t,t&&!this._board.started&&this._doStart(),this._setupControls(!t),this._setupTouchControls(!t)},controls:function(t){"boolean"!=typeof t&&(t=!0),this._setupControls(t)},touchControls:function(t){"boolean"!=typeof t&&(t=!0),this._setupTouchControls(t)},score:function(t){return"undefined"!=typeof t&&parseInt(t)>=0&&(this._filled.score=parseInt(t),this._$scoreText.text(this._filled_score)),this._filled.score},freesquares:function(){return this._filled.getFreeSpaces()},showStartMessage:function(){this._$start.show()},showGameOverMessage:function(){this._$gameover.show()},updateSizes:function(){this._PIXEL_WIDTH=this.element.innerWidth(),this._PIXEL_HEIGHT=this.element.innerHeight(),this._BLOCK_WIDTH=this.options.blockWidth,this._BLOCK_HEIGHT=Math.floor(this.element.innerHeight()/this.element.innerWidth()*this._BLOCK_WIDTH),this._block_size=Math.floor(this._PIXEL_WIDTH/this._BLOCK_WIDTH),this._border_width=2,this._PIXEL_WIDTH=this._block_size*this._BLOCK_WIDTH,this._PIXEL_HEIGHT=this._block_size*this._BLOCK_HEIGHT,this._$canvas.attr("width",this._PIXEL_WIDTH).attr("height",this._PIXEL_HEIGHT)},theme:function(e){return"undefined"==typeof e?this.options.theme||this._theme:("string"==typeof e?(this.options.theme=e,this._theme=t.extend(!0,{},BlockrainThemes[e])):(this.options.theme=null,this._theme=e),("undefined"==typeof this._theme||null===this._theme)&&(this._theme=t.extend(!0,{},BlockrainThemes.retro),this.options.theme="retro"),(isNaN(parseInt(this._theme.strokeWidth))||"number"!=typeof parseInt(this._theme.strokeWidth))&&(this._theme.strokeWidth=2),this._preloadThemeAssets(),void(null!==this._board&&("string"==typeof this._theme.background&&this._$canvas.css("background-color",this._theme.background),this._board.render())))},_theme:{},_$game:null,_$canvas:null,_$gameholder:null,_$start:null,_$gameover:null,_$score:null,_$scoreText:null,_canvas:null,_ctx:null,_create:function(){var e=this;this.theme(this.options.theme),this._createHolder(),this._createUI(),this._refreshBlockSizes(),this.updateSizes(),t(window).resize(function(){}),this._SetupShapeFactory(),this._SetupFilled(),this._SetupInfo(),this._SetupBoard(),this._info.init(),this._board.init();var i=function(){requestAnimationFrame(i),e._board.render()};i(),this.options.autoplay?(this.autoplay(!0),this._setupTouchControls(!1)):(this._setupControls(!0),this._setupTouchControls(!1))},_checkCollisions:function(t,e,i,o){for(var n,s,r=0,a=i.length;a>r;r+=2){if(n=t+i[r],s=e+i[r+1],s>=this._BLOCK_HEIGHT||this._filled.check(n,s))return!0;if(!o&&0>n||n>=this._BLOCK_WIDTH)return!0}return!1},_board:null,_info:null,_filled:null,_drawBackground:function(){if("string"==typeof this._theme.background){if(this._theme.backgroundGrid instanceof Image){if(0===this._theme.backgroundGrid.width||0===this._theme.backgroundGrid.height)return;this._ctx.globalAlpha=1;for(var t=0;to;o+=2)i[o]r&&(r=i[o]),i[o+1]h&&(h=i[o+1]);return{left:s,right:r,top:a,bottom:h,width:r-s,height:h-a}}}),this.init()}var i=this;null===this._shapeFactory&&(this._shapeFactory={line:function(){return new e(i,i._shapes.line,!1,"line")},square:function(){return new e(i,i._shapes.square,!1,"square")},arrow:function(){return new e(i,i._shapes.arrow,!1,"arrow")},leftHook:function(){return new e(i,i._shapes.leftHook,!1,"leftHook")},rightHook:function(){return new e(i,i._shapes.rightHook,!1,"rightHook")},leftZag:function(){return new e(i,i._shapes.leftZag,!1,"leftZag")},rightZag:function(){return new e(i,i._shapes.rightZag,!1,"rightZag")}})},_SetupFilled:function(){var t=this;null===this._filled&&(this._filled={data:new Array(t._BLOCK_WIDTH*t._BLOCK_HEIGHT),score:0,toClear:{},check:function(t,e){return this.data[this.asIndex(t,e)]},add:function(e,i,o,n,s,r){e>=0&&e=0&&i=0;i--)this.data[i]=i>=t._BLOCK_WIDTH?this.data[i-t._BLOCK_WIDTH]:void 0},checkForClears:function(){var e,i,o,n,s=t._board.lines,r=[];for(e=0,i=this.data.length;i>e;e++)n=this.asX(e),0==n&&(o=0),this.data[e]&&"undefined"!=typeof this.data[e]&&"string"==typeof this.data[e].blockType&&(o+=1),n==t._BLOCK_WIDTH-1&&o==t._BLOCK_WIDTH&&r.push(this.asY(e));for(e=0,i=r.length;i>e;e++)this._popRow(r[e]),t._board.lines++,t._board.lines%10==0&&t._board.dropDelay>1&&(t._board.dropDelay*=.9);var a=t._board.lines-s;this._updateScore(a)},_updateScore:function(e){if(!(0>=e)){var i=[0,400,1e3,3e3,12e3];e>=i.length&&(e=i.length-1),this.score+=i[e],t._$scoreText.text(this.score),t.options.onLine.call(t.element,e,i[e],this.score)}},_resetScore:function(){this.score=0,t._$scoreText.text(this.score)},draw:function(){for(var e,i=0,o=this.data.length;o>i;i++)if(void 0!==this.data[i]){e=this.asY(i);var n=this.data[i];t._board.drawBlock(this.asX(i),e,n.blockType,n.blockVariation,n.blockIndex,n.blockOrientation)}}})},_SetupInfo:function(){var t=this;this._info={mode:t.options.difficulty,modes:["normal","nice","evil"],modesY:170,autopilotY:null,init:function(){this.mode=t.options.difficulty},setMode:function(e){this.mode=e,t._board.nextShape(!0)}}},_SetupBoard:function(){var e=this,i=this._info;this._board={animateDelay:1e3/e.options.speed,animateTimeoutId:null,cur:null,lines:0,dropCount:0,dropDelay:5,holding:{left:null,right:null,drop:null},holdingThreshold:200,started:!1,gameover:!1,renderChanged:!0,init:function(){this.cur=this.nextShape(),e.options.showFieldOnStart&&(e._drawBackground(),e._board.createRandomBoard(),e._board.render()),this.showStartMessage()},showStartMessage:function(){e._$start.show()},showGameOverMessage:function(){e._$gameover.show()},nextShape:function(o){var n,s,r,a=this.next;if(n="nice"==i.mode||"evil"==i.mode?e._niceShapes:e._randomShapes(),e.options.no_preview){if(this.next=null,o)return null;if(s=n(e._filled,e._checkCollisions,e._BLOCK_WIDTH,e._BLOCK_HEIGHT,i.mode),!s)throw new Error("No shape returned from shape function!",n);s.init(),r=s}else{if(s=n(e._filled,e._checkCollisions,e._BLOCK_WIDTH,e._BLOCK_HEIGHT,i.mode),!s)throw new Error("No shape returned from shape function!",n);if(s.init(),this.next=s,o)return null;r=a||this.nextShape()}return e.options.autoplay&&(e._niceShapes(e._filled,e._checkCollisions,e._BLOCK_WIDTH,e._BLOCK_HEIGHT,"normal",r),r.orientation=r.best_orientation,r.x=r.best_x),"undefined"!=typeof e._theme.complexBlocks?r.blockVariation=t.isArray(e._theme.complexBlocks[r.blockType])?e._randInt(0,e._theme.complexBlocks[r.blockType].length-1):null:"undefined"!=typeof e._theme.blocks&&(r.blockVariation=t.isArray(e._theme.blocks[r.blockType])?e._randInt(0,e._theme.blocks[r.blockType].length-1):null),r},animate:function(){var t=!1,i=!1,o=!1,n=Date.now();if(this.animateTimeoutId&&clearTimeout(this.animateTimeoutId),!this.paused&&!this.gameover&&(this.dropCount++,(this.dropCount>=this.dropDelay||e.options.autoplay||this.holding.drop&&n-this.holding.drop>=this.holdingThreshold)&&(t=!0,i=!0,this.dropCount=0),this.holding.left&&n-this.holding.left>=this.holdingThreshold&&(i=!0,this.cur.moveLeft()),this.holding.right&&n-this.holding.right>=this.holdingThreshold&&(i=!0,this.cur.moveRight()),t)){var s=this.cur,r=s.x,a=s.y,h=s.getBlocks();if(e._checkCollisions(r,a+1,h,!0)){t=!1;for(var l=0,c=0;ct;t++)for(o=0,n=e._randChoice([e._randInt(0,8),e._randInt(5,9)]);n>o;o++)s&&e._randInt(0,3)||(s=e._randChoice(r)),e._filled.add(t,e._BLOCK_HEIGHT-o,s,e._randInt(0,3),null,e._randInt(0,3));e._board.render(!0)},render:function(t){(this.renderChanged||t)&&(this.renderChanged=!1,e._ctx.clearRect(0,0,e._PIXEL_WIDTH,e._PIXEL_HEIGHT),e._drawBackground(),e._filled.draw(),this.cur.draw())},drawBlock:function(t,i,o,n,s,r,a){t*=e._block_size,i*=e._block_size,a="boolean"==typeof a?a:!1;var h=e._theme.strokeWidth,l=Math.round(.23*e._block_size),c=Math.round(.3*e._block_size),d=this.getBlockColor(o,n,s,a);if(e._ctx.globalAlpha=1,d instanceof Image){if(e._ctx.globalAlpha=1,0===d.width||0===d.height)return;if("undefined"!=typeof e._theme.blocks&&null!==e._theme.blocks)e._ctx.drawImage(d,0,0,d.width,d.height,t,i,e._block_size,e._block_size);else if("undefined"!=typeof e._theme.complexBlocks&&null!==e._theme.complexBlocks){("undefined"==typeof s||null===s)&&(s=0);var u=function(t,i,o){var n=e._shapes[i][0],s=Math.min(n[0],n[2],n[4],n[6]),r=Math.max(n[0],n[2],n[4],n[6]),a=Math.min(n[1],n[3],n[5],n[7]),h=Math.max(n[1],n[3],n[5],n[7]),l=r-s+1,c=h-a+1,d=t.width/l,u=t.height/c;return{x:d*(n[2*o]-s),y:u*Math.abs(a-n[2*o+1]),w:d,h:u}},g=u(d,o,s);e._ctx.save(),e._ctx.translate(t,i),e._ctx.translate(e._block_size/2,e._block_size/2),e._ctx.rotate(-Math.PI/2*r),e._ctx.drawImage(d,g.x,g.y,g.w,g.h,-e._block_size/2,-e._block_size/2,e._block_size,e._block_size),e._ctx.restore()}else e._ctx.fillStyle="#ff0000",e._ctx.fillRect(t,i,e._block_size,e._block_size)}else"string"==typeof d&&(e._ctx.fillStyle=d,e._ctx.fillRect(t,i,e._block_size,e._block_size),"string"==typeof e._theme.innerShadow&&(e._ctx.globalAlpha=1,e._ctx.strokeStyle=e._theme.innerShadow,e._ctx.lineWidth=1,e._ctx.strokeRect(t+1,i+1,e._block_size-2,e._block_size-2)),"string"==typeof e._theme.stroke&&(e._ctx.globalAlpha=1,e._ctx.fillStyle=e._theme.stroke,e._ctx.strokeStyle=e._theme.stroke,e._ctx.lineWidth=h,e._ctx.strokeRect(t,i,e._block_size,e._block_size)),"string"==typeof e._theme.innerStroke&&(e._ctx.fillStyle=e._theme.innerStroke,e._ctx.fillRect(t+l,i+l,e._block_size-2*l,h),e._ctx.fillRect(t+l,i+l+h,h,e._block_size-2*l-h)),"string"==typeof e._theme.innerSquare&&(e._ctx.fillStyle=e._theme.innerSquare,e._ctx.globalAlpha=.2,e._ctx.fillRect(t+c,i+c,e._block_size-2*c,e._block_size-2*c)));e._ctx.globalAlpha=1},getBlockColor:function(i,o,n,s){var r=function(e,i){return t.isArray(e)?null!==i&&"undefined"!=typeof e[i]?e[i]:e.length>0?e[0]:null:e};return"boolean"!=typeof s&&(s=!0),s?"string"==typeof e._theme.primary&&""!==e._theme.primary?e._theme.primary:"undefined"!=typeof e._theme.blocks&&null!==e._theme.blocks?r(e._theme.blocks[i],o):r(e._theme.complexBlocks[i],o):"string"==typeof e._theme.secondary&&""!==e._theme.secondary?e._theme.secondary:"undefined"!=typeof e._theme.blocks&&null!==e._theme.blocks?r(e._theme.blocks[i],o):r(e._theme.complexBlocks[i],o)}},e._niceShapes=e._getNiceShapes()},_randInt:function(t,e){return t+Math.floor(Math.random()*(1+e-t))},_randSign:function(){return 2*this._randInt(0,1)-1},_randChoice:function(t){return t[this._randInt(0,t.length-1)]},_preloadThemeAssets:function(){var e=this,i=new RegExp("^#[A-F0-9+]{3,6}","i"),o=(new RegExp("^data:image/(png|gif|jpg);base64,","i"),function(){e._board&&e._board.render(!0)}),n=function(t){var e=t;return i.test(e)?t=e:(t=new Image,t.src=e,t.onload=o),t},s=function(e){if(t.isArray(e)&&e.length>0)for(var i=0;i
'),this._$gameholder.css("position","relative").css("width","100%").css("height","100%"),this.element.html("").append(this._$gameholder),this._$canvas=t(''),"string"==typeof this._theme.background&&this._$canvas.css("background-color",this._theme.background),this._$gameholder.append(this._$canvas),this._canvas=this._$canvas.get(0),this._ctx=this._canvas.getContext("2d")},_createUI:function(){var e=this;e._$score=t('
'+this.options.scoreText+'
0
').hide(),e._$scoreText=e._$score.find(".blockrain-score-num"),e._$gameholder.append(e._$score),e._$start=t('
'+this.options.playText+'
'+this.options.playButtonText+"
").hide(),e._$gameholder.append(e._$start),e._$start.find(".blockrain-start-btn").click(function(t){t.preventDefault(),e.start()}),e._$gameover=t('
'+this.options.gameOverText+'
'+this.options.restartButtonText+"
").hide(),e._$gameover.find(".blockrain-game-over-btn").click(function(t){t.preventDefault(),e.restart()}),e._$gameholder.append(e._$gameover),this._createControls()},_createControls:function(){var e=this;e._$touchLeft=t('').appendTo(e._$gameholder),e._$touchRight=t('').appendTo(e._$gameholder),e._$touchRotateRight=t('').appendTo(e._$gameholder),e._$touchRotateLeft=t('').appendTo(e._$gameholder),e._$touchDrop=t('').appendTo(e._$gameholder)},_refreshBlockSizes:function(){this.options.autoBlockWidth&&(this.options.blockWidth=Math.ceil(this.element.width()/this.options.autoBlockSize))},_getNiceShapes:function(){function t(t,e,i,n,s,r,a){var h,l,c,d,u=e.length,g=0,A={};for(h=0;u>h;h+=2)g+=t[o._filled.asIndex(i+e[h],n+e[h+1])]||0;for(h=0;u>h;h+=2)l=e[h],c=e[h+1],(void 0===A[l]||A[l]n+c;c++,h++)if(!o._filled.check(i+l,n+c)){d+=0==h?2:1;break}return g-=d}function e(){for(var t in n)n[t].x=0,n[t].y=-1}var i,o=this,n={};for(var i in this._shapeFactory)n[i]=this._shapeFactory[i]();var s=function(i,s,r,a,h,l){l||e();var c,d,u,g,A,f,p,b,m,k,_,I,v,y,C,w=new Array(r*a),B="evil"==h,G=999*(B?1:-1);for(c=0;r>c;c++)for(d=0;a>=d;d++)if(d==a||i.check(c,d)){for(u=d-4;d>u;u++)w[i.asIndex(c,u)]=u;break}var D=void 0===l?n:{cur:l};for(g in D){for(A=D[g],v=-999,f=0;f<(A.symmetrical?2:4);f++)for(p=A.getBlocks(f),b=A.getBounds(p),c=-b.left;cv&&(v=m,y=f,C=c);break}(B&&G>v||!B&&v>G)&&(k=A,G=v,_=y,I=C)}return k.best_orientation=_,k.best_x=I,k};return s.no_preview=!0,s},_randomShapes:function(){var e=[];return t.each(this._shapeFactory,function(t,i){e.push(i)}),this._randChoice(e)},_setupControls:function(e){function i(t){var e={stopKeys:{37:1,38:1,39:1,40:1}},i=e.stopKeys[t.keyCode]||e.moreStopKeys&&e.moreStopKeys[t.keyCode];return i&&t.preventDefault(),i}function o(t){return"safekeypress."+t.keyCode}function n(e){var i=o(e);return t.data(this,i,(t.data(this,i)||0)-1),c.call(this,e)}function s(e){return t.data(this,o(e),0),d.call(this,e),i(e)}var r=this,a=function(t){return t?void(r._board.holding.left||(r._board.cur.moveLeft(),r._board.holding.left=Date.now(),r._board.holding.right=null)):void(r._board.holding.left=null)},h=function(t){return t?void(r._board.holding.right||(r._board.cur.moveRight(),r._board.holding.right=Date.now(),r._board.holding.left=null)):void(r._board.holding.right=null)},l=function(t){return t?void(r._board.holding.drop||(r._board.cur.drop(),r._board.holding.drop=Date.now())):void(r._board.holding.drop=null)},c=function(t){if(!r._board.cur)return!0;var e=!1;if(e=!0,r.options.asdwKeys)switch(t.keyCode){case 65:a(!0);break;case 68:h(!0);break;case 83:l(!0);break;case 87:r._board.cur.rotate("right")}switch(t.keyCode){case 37:a(!0);break;case 39:h(!0);break;case 40:l(!0);break;case 38:r._board.cur.rotate("right");break;case 88:r._board.cur.rotate("right");break;case 90:r._board.cur.rotate("left");break;default:e=!1}return e&&t.preventDefault(),!e},d=function(t){if(!r._board.cur)return!0;var e=!1;if(e=!0,r.options.asdwKeys)switch(t.keyCode){case 65:a(!1);break;case 68:h(!1);break;case 83:l(!1)}switch(t.keyCode){case 37:a(!1);break;case 39:h(!1);break;case 40:l(!1);break;default:e=!1}return e&&t.preventDefault(),!e};t(document).unbind("keydown.blockrain").unbind("keyup.blockrain"),r.options.autoplay||e&&t(document).bind("keydown.blockrain",n).bind("keyup.blockrain",s)},_setupTouchControls:function(t){var e=this,i=function(t){t.preventDefault(),e._board.cur.moveLeft(),e._board.holding.left=Date.now(),e._board.holding.right=null,e._board.holding.drop=null},o=function(t){t.preventDefault(),e._board.cur.moveRight(),e._board.holding.right=Date.now(),e._board.holding.left=null,e._board.holding.drop=null},n=function(t){t.preventDefault(),e._board.cur.drop(),e._board.holding.drop=Date.now()},s=function(t){t.preventDefault(),e._board.holding.left=null},r=function(t){t.preventDefault(),e._board.holding.right=null},a=function(t){t.preventDefault(),e._board.holding.drop=null},h=function(t){t.preventDefault(),e._board.cur.rotate("left")},l=function(t){t.preventDefault(),e._board.cur.rotate("right")};e._$touchLeft.unbind("touchstart touchend click"),e._$touchRight.unbind("touchstart touchend click"),e._$touchRotateLeft.unbind("touchstart touchend click"),e._$touchRotateRight.unbind("touchstart touchend click"),e._$touchDrop.unbind("touchstart touchend click"),!e.options.autoplay&&t?(e._$touchLeft.show().bind("touchstart click",i).bind("touchend",s),e._$touchRight.show().bind("touchstart click",o).bind("touchend",r),e._$touchDrop.show().bind("touchstart click",n).bind("touchend",a),e._$touchRotateLeft.show().bind("touchstart click",h),e._$touchRotateRight.show().bind("touchstart click",l)):(e._$touchLeft.hide(),e._$touchRight.hide(),e._$touchRotateLeft.hide(),e._$touchRotateRight.hide(),e._$touchDrop.hide())}})}(jQuery),window.BlockrainThemes={custom:{background:"#040304",backgroundGrid:"data:image/png;base64,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", + !function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)}(function(t){var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var o,n,s;for(s=0;null!=(n=i[s]);s++)try{o=t._data(n,"events"),o&&o.remove&&t(n).triggerHandler("remove")}catch(r){}e(i)}}(t.cleanData),t.widget=function(e,i,o){var n,s,r,a,h={},l=e.split(".")[0];return e=e.split(".")[1],n=l+"-"+e,o||(o=i,i=t.Widget),t.expr[":"][n.toLowerCase()]=function(e){return!!t.data(e,n)},t[l]=t[l]||{},s=t[l][e],r=t[l][e]=function(t,e){return this._createWidget?void(arguments.length&&this._createWidget(t,e)):new r(t,e)},t.extend(r,s,{version:o.version,_proto:t.extend({},o),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(o,function(e,o){return t.isFunction(o)?void(h[e]=function(){var t=function(){return i.prototype[e].apply(this,arguments)},n=function(t){return i.prototype[e].apply(this,t)};return function(){var e,i=this._super,s=this._superApply;return this._super=t,this._superApply=n,e=o.apply(this,arguments),this._super=i,this._superApply=s,e}}()):void(h[e]=o)}),r.prototype=t.widget.extend(a,{widgetEventPrefix:s?a.widgetEventPrefix||e:e},h,{constructor:r,namespace:l,widgetName:e,widgetFullName:n}),s?(t.each(s._childConstructors,function(e,i){var o=i.prototype;t.widget(o.namespace+"."+o.widgetName,r,i._proto)}),delete s._childConstructors):i._childConstructors.push(r),t.widget.bridge(e,r),r},t.widget.extend=function(e){for(var o,n,s=i.call(arguments,1),r=0,a=s.length;a>r;r++)for(o in s[r])n=s[r][o],s[r].hasOwnProperty(o)&&void 0!==n&&(e[o]=t.isPlainObject(n)?t.isPlainObject(e[o])?t.widget.extend({},e[o],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,o){var n=o.prototype.widgetFullName||e;t.fn[e]=function(s){var r="string"==typeof s,a=i.call(arguments,1),h=this;return s=!r&&a.length?t.widget.extend.apply(null,[s].concat(a)):s,r?this.each(function(){var i,o=t.data(this,n);return"instance"===s?(h=o,!1):o?t.isFunction(o[s])&&"_"!==s.charAt(0)?(i=o[s].apply(o,a),i!==o&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+s+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; attempted to call method '"+s+"'")}):this.each(function(){var e=t.data(this,n);e?(e.option(s||{}),e._init&&e._init()):t.data(this,n,new o(s,this))}),h}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{disabled:!1,create:null},_createWidget:function(i,o){o=t(o||this.defaultElement||this)[0],this.element=t(o),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),o!==this&&(t.data(o,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===o&&this.destroy()}}),this.document=t(o.style?o.ownerDocument:o.document||o),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:t.noop,_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(t.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var o,n,s,r=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(r={},o=e.split("."),e=o.shift(),o.length){for(n=r[e]=t.widget.extend({},this.options[e]),s=0;o.length-1>s;s++)n[o[s]]=n[o[s]]||{},n=n[o[s]];if(e=o.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];r[e]=i}return this._setOptions(r),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!e),e&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(e,i,o){var n,s=this;"boolean"!=typeof e&&(o=i,i=e,e=!1),o?(i=n=t(i),this.bindings=this.bindings.add(i)):(o=i,i=this.element,n=this.widget()),t.each(o,function(o,r){function a(){return e||s.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof r?s[r]:r).apply(s,arguments):void 0}"string"!=typeof r&&(a.guid=r.guid=r.guid||a.guid||t.guid++);var h=o.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+s.eventNamespace,c=h[2];c?n.delegate(c,l,a):i.bind(l,a)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(i).undelegate(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?o[t]:t).apply(o,arguments)}var o=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){t(e.currentTarget).addClass("ui-state-hover")},mouseleave:function(e){t(e.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){t(e.currentTarget).addClass("ui-state-focus")},focusout:function(e){t(e.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(e,i,o){var n,s,r=this.options[e];if(o=o||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],s=i.originalEvent)for(n in s)n in i||(i[n]=s[n]);return this.element.trigger(i,o),!(t.isFunction(r)&&r.apply(this.element[0],[i].concat(o))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(o,n,s){"string"==typeof n&&(n={effect:n});var r,a=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),r=!t.isEmptyObject(n),n.complete=s,n.delay&&o.delay(n.delay),r&&t.effects&&t.effects.effect[a]?o[e](n):a!==e&&o[a]?o[a](n.duration,n.easing,s):o.queue(function(i){t(this)[e](),s&&s.call(o[0]),i()})}}),t.widget}),function(t){"use strict";t.widget("aerolab.blockrain",{options:{autoplay:!1,autoplayRestart:!0,showFieldOnStart:!0,theme:null,blockWidth:10,autoBlockWidth:!1,autoBlockSize:24,difficulty:"normal",speed:20,asdwKeys:!0,playText:"Let's play some Tetris",playButtonText:"Play",gameOverText:"Game Over",restartButtonText:"Play Again",scoreText:"Score",onStart:function(){},onRestart:function(){},onGameOver:function(t){},onPlaced:function(){},onLine:function(t,e,i){}},start:function(){this._doStart(),this.options.onStart.call(this.element)},restart:function(){this._doStart(),this.options.onRestart.call(this.element)},gameover:function(){this.showGameOverMessage(),this._board.gameover=!0,this.options.onGameOver.call(this.element,this._filled.score)},_doStart:function(){this._filled.clearAll(),this._filled._resetScore(),this._board.cur=this._board.nextShape(),this._board.started=!0,this._board.gameover=!1,this._board.dropDelay=5,this._board.render(!0),this._board.animate(),this._$start.fadeOut(150),this._$gameover.fadeOut(150),this._$score.fadeIn(150)},pause:function(){this._board.paused=!0},resume:function(){this._board.paused=!1},autoplay:function(t){"boolean"!=typeof t&&(t=!0),this.options.autoplay=t,t&&!this._board.started&&this._doStart(),this._setupControls(!t),this._setupTouchControls(!t)},controls:function(t){"boolean"!=typeof t&&(t=!0),this._setupControls(t)},touchControls:function(t){"boolean"!=typeof t&&(t=!0),this._setupTouchControls(t)},score:function(t){return"undefined"!=typeof t&&parseInt(t)>=0&&(this._filled.score=parseInt(t),this._$scoreText.text(this._filled_score)),this._filled.score},freesquares:function(){return this._filled.getFreeSpaces()},showStartMessage:function(){this._$start.show()},showGameOverMessage:function(){this._$gameover.show()},updateSizes:function(){this._PIXEL_WIDTH=this.element.innerWidth(),this._PIXEL_HEIGHT=this.element.innerHeight(),this._BLOCK_WIDTH=this.options.blockWidth,this._BLOCK_HEIGHT=Math.floor(this.element.innerHeight()/this.element.innerWidth()*this._BLOCK_WIDTH),this._block_size=Math.floor(this._PIXEL_WIDTH/this._BLOCK_WIDTH),this._border_width=2,this._PIXEL_WIDTH=this._block_size*this._BLOCK_WIDTH,this._PIXEL_HEIGHT=this._block_size*this._BLOCK_HEIGHT,this._$canvas.attr("width",this._PIXEL_WIDTH).attr("height",this._PIXEL_HEIGHT)},theme:function(e){return"undefined"==typeof e?this.options.theme||this._theme:("string"==typeof e?(this.options.theme=e,this._theme=t.extend(!0,{},BlockrainThemes[e])):(this.options.theme=null,this._theme=e),"undefined"!=typeof this._theme&&null!==this._theme||(this._theme=t.extend(!0,{},BlockrainThemes.retro),this.options.theme="retro"),(isNaN(parseInt(this._theme.strokeWidth))||"number"!=typeof parseInt(this._theme.strokeWidth))&&(this._theme.strokeWidth=2),this._preloadThemeAssets(),void(null!==this._board&&("string"==typeof this._theme.background&&this._$canvas.css("background-color",this._theme.background),this._board.render())))},_theme:{},_$game:null,_$canvas:null,_$gameholder:null,_$start:null,_$gameover:null,_$score:null,_$scoreText:null,_canvas:null,_ctx:null,_create:function(){var e=this;this.theme(this.options.theme),this._createHolder(),this._createUI(),this._refreshBlockSizes(),this.updateSizes(),t(window).resize(function(){}),this._SetupShapeFactory(),this._SetupFilled(),this._SetupInfo(),this._SetupBoard(),this._info.init(),this._board.init();var i=function(){requestAnimationFrame(i),e._board.render()};i(),this.options.autoplay?(this.autoplay(!0),this._setupTouchControls(!1)):(this._setupControls(!0),this._setupTouchControls(!1))},_checkCollisions:function(t,e,i,o){for(var n,s,r=0,a=i.length;r=this._BLOCK_HEIGHT||this._filled.check(n,s))return!0;if(!o&&n<0||n>=this._BLOCK_WIDTH)return!0}return!1},_board:null,_info:null,_filled:null,_drawBackground:function(){if("string"==typeof this._theme.background){if(this._theme.backgroundGrid instanceof Image){if(0===this._theme.backgroundGrid.width||0===this._theme.backgroundGrid.height)return;this._ctx.globalAlpha=1;for(var t=0;tr&&(r=i[o]),i[o+1]h&&(h=i[o+1]);return{left:s,right:r,top:a,bottom:h,width:r-s,height:h-a}}}),this.init()}var i=this;null===this._shapeFactory&&(this._shapeFactory={line:function(){return new e(i,i._shapes.line,(!1),"line")},square:function(){return new e(i,i._shapes.square,(!1),"square")},arrow:function(){return new e(i,i._shapes.arrow,(!1),"arrow")},leftHook:function(){return new e(i,i._shapes.leftHook,(!1),"leftHook")},rightHook:function(){return new e(i,i._shapes.rightHook,(!1),"rightHook")},leftZag:function(){return new e(i,i._shapes.leftZag,(!1),"leftZag")},rightZag:function(){return new e(i,i._shapes.rightZag,(!1),"rightZag")}})},_SetupFilled:function(){var t=this;null===this._filled&&(this._filled={data:new Array(t._BLOCK_WIDTH*t._BLOCK_HEIGHT),score:0,toClear:{},check:function(t,e){return this.data[this.asIndex(t,e)]},add:function(e,i,o,n,s,r){e>=0&&e=0&&i=0;i--)this.data[i]=i>=t._BLOCK_WIDTH?this.data[i-t._BLOCK_WIDTH]:void 0},checkForClears:function(){var e,i,o,n,s=t._board.lines,r=[];for(e=0,i=this.data.length;e1&&(t._board.dropDelay*=.9);var a=t._board.lines-s;this._updateScore(a)},_updateScore:function(e){if(!(e<=0)){var i=[0,400,1e3,3e3,12e3];e>=i.length&&(e=i.length-1),this.score+=i[e],t._$scoreText.text(this.score),t.options.onLine.call(t.element,e,i[e],this.score)}},_resetScore:function(){this.score=0,t._$scoreText.text(this.score)},draw:function(){for(var e,i=0,o=this.data.length;i=this.dropDelay||e.options.autoplay||this.holding.drop&&n-this.holding.drop>=this.holdingThreshold)&&(t=!0,i=!0,this.dropCount=0),this.holding.left&&n-this.holding.left>=this.holdingThreshold&&(i=!0,this.cur.moveLeft()),this.holding.right&&n-this.holding.right>=this.holdingThreshold&&(i=!0,this.cur.moveRight()),t)){var s=this.cur,r=s.x,a=s.y,h=s.getBlocks();if(e._checkCollisions(r,a+1,h,!0)){t=!1;for(var l=0,c=0;c0?e[0]:null:e};return"boolean"!=typeof s&&(s=!0),s?"string"==typeof e._theme.primary&&""!==e._theme.primary?e._theme.primary:"undefined"!=typeof e._theme.blocks&&null!==e._theme.blocks?r(e._theme.blocks[i],o):r(e._theme.complexBlocks[i],o):"string"==typeof e._theme.secondary&&""!==e._theme.secondary?e._theme.secondary:"undefined"!=typeof e._theme.blocks&&null!==e._theme.blocks?r(e._theme.blocks[i],o):r(e._theme.complexBlocks[i],o)}},e._niceShapes=e._getNiceShapes()},_randInt:function(t,e){return t+Math.floor(Math.random()*(1+e-t))},_randSign:function(){return 2*this._randInt(0,1)-1},_randChoice:function(t){return t[this._randInt(0,t.length-1)]},_preloadThemeAssets:function(){var e=this,i=new RegExp("^#[A-F0-9+]{3,6}","i"),o=(new RegExp("^data:image/(png|gif|jpg);base64,","i"),function(){e._board&&e._board.render(!0)}),n=function(t){var e=t;return i.test(e)?t=e:(t=new Image,t.src=e,t.onload=o),t},s=function(e){if(t.isArray(e)&&e.length>0)for(var i=0;i
'),this._$gameholder.css("position","relative").css("width","100%").css("height","100%"),this.element.html("").append(this._$gameholder),this._$canvas=t(''),"string"==typeof this._theme.background&&this._$canvas.css("background-color",this._theme.background),this._$gameholder.append(this._$canvas),this._canvas=this._$canvas.get(0),this._ctx=this._canvas.getContext("2d")},_createUI:function(){var e=this;e._$score=t('
'+this.options.scoreText+'
0
').hide(),e._$scoreText=e._$score.find(".blockrain-score-num"),e._$gameholder.append(e._$score),e._$start=t('
").hide(),e._$gameholder.append(e._$start),e._$start.find(".blockrain-start-btn").click(function(t){t.preventDefault(),e.start()}),e._$gameover=t('
'+this.options.gameOverText+'
'+this.options.restartButtonText+"
").hide(),e._$gameover.find(".blockrain-game-over-btn").click(function(t){t.preventDefault(),e.restart()}),e._$gameholder.append(e._$gameover),this._createControls()},_createControls:function(){var e=this;e._$touchLeft=t('').appendTo(e._$gameholder),e._$touchRight=t('').appendTo(e._$gameholder),e._$touchRotateRight=t('').appendTo(e._$gameholder),e._$touchRotateLeft=t('').appendTo(e._$gameholder),e._$touchDrop=t('').appendTo(e._$gameholder)},_refreshBlockSizes:function(){this.options.autoBlockWidth&&(this.options.blockWidth=Math.ceil(this.element.width()/this.options.autoBlockSize))},_getNiceShapes:function(){function t(t,e,i,n,s,r,a){var h,l,c,d,u=e.length,g=0,A={};for(h=0;hv&&(v=m,y=f,C=c);break}(B&&vG)&&(k=A,G=v,_=y,I=C)}return k.best_orientation=_,k.best_x=I,k};return s.no_preview=!0,s},_randomShapes:function(){var e=[];return t.each(this._shapeFactory,function(t,i){e.push(i)}),this._randChoice(e)},_setupControls:function(e){function i(t){var e={stopKeys:{37:1,38:1,39:1,40:1}},i=e.stopKeys[t.keyCode]||e.moreStopKeys&&e.moreStopKeys[t.keyCode];return i&&t.preventDefault(),i}function o(t){return"safekeypress."+t.keyCode}function n(e){var i=o(e);return t.data(this,i,(t.data(this,i)||0)-1),c.call(this,e)}function s(e){return t.data(this,o(e),0),d.call(this,e),i(e)}var r=this,a=function(t){return t?void(r._board.holding.left||(r._board.cur.moveLeft(),r._board.holding.left=Date.now(),r._board.holding.right=null)):void(r._board.holding.left=null)},h=function(t){return t?void(r._board.holding.right||(r._board.cur.moveRight(),r._board.holding.right=Date.now(),r._board.holding.left=null)):void(r._board.holding.right=null)},l=function(t){return t?void(r._board.holding.drop||(r._board.cur.drop(),r._board.holding.drop=Date.now())):void(r._board.holding.drop=null)},c=function(t){if(!r._board.cur)return!0;var e=!1;if(e=!0,r.options.asdwKeys)switch(t.keyCode){case 65:a(!0);break;case 68:h(!0);break;case 83:l(!0);break;case 87:r._board.cur.rotate("right")}switch(t.keyCode){case 37:a(!0);break;case 39:h(!0);break;case 40:l(!0);break;case 38:r._board.cur.rotate("right");break;case 88:r._board.cur.rotate("right");break;case 90:r._board.cur.rotate("left");break;default:e=!1}return e&&t.preventDefault(),!e},d=function(t){if(!r._board.cur)return!0;var e=!1;if(e=!0,r.options.asdwKeys)switch(t.keyCode){case 65:a(!1);break;case 68:h(!1);break;case 83:l(!1)}switch(t.keyCode){case 37:a(!1);break;case 39:h(!1);break;case 40:l(!1);break;default:e=!1}return e&&t.preventDefault(),!e};t(document).unbind("keydown.blockrain").unbind("keyup.blockrain"),r.options.autoplay||e&&t(document).bind("keydown.blockrain",n).bind("keyup.blockrain",s)},_setupTouchControls:function(t){var e=this,i=function(t){t.preventDefault(),e._board.cur.moveLeft(),e._board.holding.left=Date.now(),e._board.holding.right=null,e._board.holding.drop=null},o=function(t){t.preventDefault(),e._board.cur.moveRight(),e._board.holding.right=Date.now(),e._board.holding.left=null,e._board.holding.drop=null},n=function(t){t.preventDefault(),e._board.cur.drop(),e._board.holding.drop=Date.now()},s=function(t){t.preventDefault(),e._board.holding.left=null},r=function(t){t.preventDefault(),e._board.holding.right=null},a=function(t){t.preventDefault(),e._board.holding.drop=null},h=function(t){t.preventDefault(),e._board.cur.rotate("left")},l=function(t){t.preventDefault(),e._board.cur.rotate("right")};e._$touchLeft.unbind("touchstart touchend click"),e._$touchRight.unbind("touchstart touchend click"),e._$touchRotateLeft.unbind("touchstart touchend click"),e._$touchRotateRight.unbind("touchstart touchend click"),e._$touchDrop.unbind("touchstart touchend click"),!e.options.autoplay&&t?(e._$touchLeft.show().bind("touchstart click",i).bind("touchend",s),e._$touchRight.show().bind("touchstart click",o).bind("touchend",r),e._$touchDrop.show().bind("touchstart click",n).bind("touchend",a),e._$touchRotateLeft.show().bind("touchstart click",h),e._$touchRotateRight.show().bind("touchstart click",l)):(e._$touchLeft.hide(),e._$touchRight.hide(),e._$touchRotateLeft.hide(),e._$touchRotateRight.hide(),e._$touchDrop.hide())}})}(jQuery),window.BlockrainThemes={custom:{background:"#040304",backgroundGrid:"data:image/png;base64,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", complexBlocks:{line:["assets/blocks/custom/line.png","assets/blocks/custom/line.png"],square:["assets/blocks/custom/square.png"],arrow:"assets/blocks/custom/arrow.png",rightHook:["assets/blocks/custom/rightHook.png"],leftHook:"assets/blocks/custom/leftHook.png",rightZag:["assets/blocks/custom/rightZag.png"],leftZag:"assets/blocks/custom/leftZag.png"}},candy:{background:"#040304",backgroundGrid:"data:image/png;base64,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",blocks:{line:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACuklEQVR4Xi2MzW4cRRSFz/2p6p4eT2zjjE2MHBQWvAALNjwDS8SOFc/FIyCxQgh2LFHkBQgJyQo/wXKCEZ7x9E9VV93LBPNJ516dxXfo/U8+HTZ9uzrZympTjLo4DbtDiBpXSBGMocI5lkaMhKv0fz+LVX9P6ZuvvxqBby+3L3eJu6Zt27DL4qgIWW0KsxPC3Kjxz5fPT3z48csvtHSHd0C/1374RddPX/9xK6JdcjEutNfqFJMBsQat3By+i/7VxqJ6c/zd5avvn1+N7dl2V9Ad92M2ViI2ksyWSJ2QXQXc5/H25jYcHHKl1YYebcJqw/rW03OOzfr89NHbR8vH3Wq9Olofrddni+XhycXJhBSkKFLxWeHBZFFDVyD343Rzc/0XeYSXeXZIJaam2V9pLsBOtRIKYAorXqvAg8giaKsCKw1zJAGFbKhwtxrdG9E3BQxAIW1xyYUKUIwNxMAwDEwuSgA5iAw2l5ITOeE/GLRMihIOsnQZnKqOlWXRUWidyYkFpCxtCF1s8D+seBggYVYRhChkqqjmld3NKhhu1XKuKUf4g6egEitkvqc5ewo+3ZOVZJO4Q4OSEDGRRyAQkYH8QfMUCR07KS8DIsO8xhjcnUXnSv4GMRYShSUG2MFCeby/awOJFyvF3TU22ckk3E3FQjci+mJVggwz12rKVEvWOk3dwWpIr7ezrU4XZ+9ciBAxWCVlhDb2o5cZTgBR17R3w45hgg8/fu+Dj643adZVXzCmebsbp5T6fhr2L9W8z5xLNsyDpl2btrsXPynS9NvVVc28xzMLPDCUYbVUMy+TMgdinupCEapdvPv0lqGwjW9fHsXjF39eIzRpnFbLdiy918qCWmclnq3mcWhVnzw5v+83XYz0+LPP/8lL704NB3BBdbCDKlChAq8QgRvmGSFouyo3vz7Lr/8FMHqie3VCpNQAAAAASUVORK5CYII=",square:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACfUlEQVR4Xh3LvY5cRRBA4VNV3ffe+fEaZARgWfBExEhEZEg8A69AgkC8AzEiICMgJCdAxggsGRuW3Z3dmenbXVWskT6d7MiXnz3qclu87esm1qW3NteRuqaCIAmQABwPvPU2NyeaUa6P159/9QV3l/HqlWqN41El0PaadEJAoZBKqS9+eybL/tvvvi8PrHA4ku33pz9v5rafKmc0I7QhbiGaJSikyeCh1T7OG6fMluOvP/5+8csb+/RxhUtlEXA5KUMpiEpWwZKU3D799Zl1CtpEjsoh++HRxUMBVhgry4yUXLvstnE8qWi/HZndTEwpppj5XLIg7fZ4+fJlb91jzSlGhjc2O7RMj995nApRIRW0BHRl9UXLona6PYiGGKpaa50qPtQ96/5BCgkpBKghpI7VJZK5bmYju5IxQkZONqtbu+txd5ZEQFI0KaRRJxEZY0wjh/dqKqbZ/z9tqmJIqpQSnaD8T9sYkGqWmuTIZHgoWYupKh4SqSQimqrJfeV1gTECF4NKmUHwDFRqNSuJjMTxFQANNKGUyTBxYqSX6J6USdc1BquYFhEMFEQCUvSeC5rheL/Y74kAvX/OPXRZojIkqHkaLpMwWdYJm1fHlZIJotdXN7tFtczvvfuB5MIyRZwQ11pora2BTKOvva3zPKtStpsKLNNmmcr53xtFMtLaGLSR61IKKaPHenO1L2+qThqrn5FvPuGjjz8s4x+NI6Ptdvtxckywo0cjstZZZfZhNhSWNuoPP/5Udhebc8+tbp4//zPd6dcaGtJtWtUiVkhTWSJkTn3y5P15M19ervL1p9UZFzX9zHYmO1Ph3KFQK+rkIBMScbY7DicOzn+QRoW5iamqhgAAAABJRU5ErkJggg==",arrow:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACsklEQVR4XhWPu25bVxREZz/OuQ9RVKhXjBSu8gX5h+QD0udD8ilByjRpUqZxa6RxY8DuYlhwHhAc2qRIieK9vOfsvUMNBoPVrGLoh6+++7y7mbFfTNIVdShCxCGuAgE8tSilhOVWU6lrtPjPK33ffvvb6xd4KG9/+f1kenIYoAgOIc+AF9u5Rdteuvubty9LU168fqW9z7AFanr36uPZSOIgWHB1IJABKE0keSr3QdLolXitjw1n717++sfPP/7Ula6pfbYmeU7eaBybnzg6ewwpT8DW/vth2acFkzf9Pi0OOU1+/eVlM2/m14vZ+Rfz88t+Np+fnZ8tns1OL66vLss0FIughgppDumLzIpmYBrHz+uVsZVSsraorJoMQU5dOs3K3jaiSXGciNYoG3cQcbJjwiKC3Ny9ljhEEUlGBnh4IJwR+qQ6q7FbuMPBLEQCVjaYA0mYwcyIY6p5qYFQQqOexRMhHOqg6sV8mtiqQki51gSHV6YAMYMMxgIC2IOcBcIsQipBBCIjNqEQBWARjjAOHAtSh1eqk9bqLpBKQUSZE4ccIqpJFnWQiRSKypjUA1DgEDw5janNkgA4zKmGQtpgsNqhMoRCmRni4AgKJh6DB842TffENWWqU+m448eYje186GZT31nXo5EqPhUGIqoGwd1gtWFtRBeLxcXF1TydYh+td1E5lMdpOOxGr9bPOzdrtFGWk2lAg84e9/fYbGmsync0xD7mfkITgUMbJaKc26GOVn2sB61Gf958OE992wsoQjSSjBHUwEmlISTsxjEsOIsxP3v+/M3tey3wrRVh29wuA2Vo3Xoe3KP6Endhzh3v92NjKefcXZzETKxR+Sa+vt2s3/3z127YrYfN+mGz2m4+rT+tNuu77d3yfvn3+vbh8eH4bb3dLrer97c3q7L6H15gvODKB5u4AAAAAElFTkSuQmCC",rightHook:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACqElEQVR4Xh3PO2tlZRSH8f9a73XvPTkTExl1dLAIKFpNY2Fl4UcT7G3FwmIaO3sbEfQjWAxDAkIORDHJyXFf3stayzC/9qke+ubrF0u7zqwfsJNFXEKtCAJriBGBoB0gNAZ5WIekcC0f+br8++3Pr1AP5Y/f6Xgfx4RqoB2kI27QgkYQw5BA2L95M+vTn379y0c2HI+Y5Ob6z3B/M/ZmlTieV7ISj9rXZ2n338NciEMedGshJacbZ9X16vK3H76vh/1paCOWiWvos5M1U9llLIebKeqz0zG4PmZ/dfl6XWc/9p4Ox/fMwnIcXrwL6ohPg54OZhYTUUc+w1YQ83z3kMadEKdp8EmE54cnKifTBLOr17cqtwIf4gAuKhUd8Lh4+TKPowjyOK1l8cxAm9nK2nWnsQeAyNtgldnClCLntkrRrTBcFyPjYRg8AEAY4JDhkhp7uOBIRbyqrmK+KcBm1qU30UbSxHcGnIGpKYk63dQxnC2sPcWo2slZUCCGYXPkkBnUqjcCSAGFsaOUQk5koqUqPFV5G2sDai+tG3vv6ZF3BojBzFrvpeij4KtDZTjPXTWGBA91uWJTo1WkqTAZoAbpT3ejd0YOBW1zoAHE/tG8FThm52KOLnDv1dA8DACTwbRU6TxSaX1WZII/1qBgwLvWtgN6ieQc2hC9hwLGTFS35eTJ7uOL5xxTkZI44l7BDGpwBke8FFCA9Pj2EAipHbd8Qre3fxOMDWykGryyM2Vv67JwmCJ7cQRRM6JXX+CrLz97/uHJ4bgHFUdKBi8B5gECLLAys4grAkr5Vt758ZdLTwhuPNvfHP7ZPzjrBAHYLBlChwPQ+jrtpq2UJv3i0/clni/Y03efYzxPvZdBkAzeAKATukENAoTA86ynZ3GrVQl3Eu/yJ/8D33mmeKR3Cz8AAAAASUVORK5CYII=",leftHook:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACq0lEQVR4Xg3HO24mVRBH8X/Vrfv4ut02BjS8GSBAQuyCmE0gwSLICFgCBLASAhLiiQjQICFBMAMSFn63v+77qCp89EsO5U+/rus/0zQPPW8thXRQABLAjtHAAZ2gzGk2HRCG1YMPwgdf/fnXj1fX+O7732s/A0kzbwEUCW5Fgh8HGVdFTOn5H79NiZ/98rPATBVS8OzX5xTehYsxd3KFwXcGEljVOGVJ8a7W4Q4YT8sb33z70xdf/oB8HufzhjI0m2a3JLykuAyV4RGxrLVN5+f/3dxSKXJc59qfUk77djhdXhGx0/mMAg/rpm30bXq97Fp3su1mrMe19e46BLLw9Nb1w0WaZoO+fPmCNbTW3D1Fcjci77Cnn3wMhCBpWU7vuwqo3evgaar6QHRqfRXKhQiELFG1O6H3MZUyLpTIx24UMkNASbqZwZiN3AQsgKhZ6/VYR9OcDw/blg5xmKqPnIRBLQUZw4iIWQKydRcEcvLOOZ2A80Nv8SRv1iiHQWPXewbztm3MbObMYgpGCMwiwgwAIhJCAGBmjMD+KDJJThJzTI8TKZm5E9S7U3c0s6PrkVujvYbm0Qr1iceJ+GZ9772OMawNDNAgVm8cADcAQSgzCSiChZj8MRLwXCTPufQEC8SlVKPWNTJJ4BTDcds58tCaMsVoIQ8Nq2AgS97uVg2h7v29Dz86W86MGqB922F+djjsdbWE0eu233fbwF0opd57KYU43l5ewQ43N7d17CwUHJnlsl4QmUwkJJKZ5uXaLdBrnzl6EGbTbV2nVIiMuMU44EMwMjn76GMHeWAKhKuLvyXoC+F3IvXrfy9zmO/WKyUM6c1riWUY7btKiA+9UkyvPnk7KFMPtLz/uS9vrjVFLNqTUSEJNLN5hQL7gIXpsGytO0ekCduR/fg/hV+olVqSm3YAAAAASUVORK5CYII=",rightZag:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACt0lEQVR4Xg3LOW6eVRQG4PcM937DP9hYlkgUQ6RQsAiEWAC7YCWUtGyAFqhpEHRI0CCBIjpHJBSxEhzkxP6H+93pHPz0D3358IsbuyY/XlCs7/YU5zjFZgdGp07BEDq4KXwA0PvuqIfDGbT0u69/+hZvr/DrH1gc1WENwUAGM3RDcXQGRbA9/e3nJPX3F5dqdY/ja8ztx++/+YhX5S6P47REODW2Pra+qsbOR5VFWwjHVPKJJF1FevPn019++O7jeYo3h5VG8Ua5OLnCh25T7+RwYfZavVz993q5OehccfImnV3nqdLjD54gTiDAF3cnEJrBAbZNSS//vTKP1FcTk0ppsfYzkpEt58Pls8vb29vTabDWYZJzjsqnJ+vHjx9tVvf3qG3QVpXJ0Y5L2xWmYbPt7W5WeK7RKUqICic7poQY6q4Fw2AUDSykUGUlQ0cUy3XUqCxm8Obe4SypVoRwOC7kLE5szIoBHsmlO6NJO3Qv5GEozI3IiE25K2EeLAiYADiBOwi51NLdCRrGcQ5xTLVUcg1BVeFszXtaWinkIAcALigQDwISby0Vq3dpR8IA2r1cKNfZRTq9F2c1iLuYqQcHg2Dmvbam08QUG1V07zASqDCLouSSE0tojCbGablFoMgkpMxht9QukvICASIXtNLy7rDDakVDeGepzpIUup1mlIZs5Dbo9OknnwEELGgZJgBhHHDYIx/v8/r98+d/P2cVVSOkitRPN9uXfz0j2rRSh1CZDKRmFomgnns62Wyvrq+ncTy2JJ/rRXv76vx04ymr83pci9gYRYISS4N3cgRKvYb15EHOHzy8fPaPgtMe8zHG5y8uH6y3wa7LPbNOIIkQRpCOZt7KzatHFx+Ww0Ki9NX8ZHWy7Sltchtz2aj32nicjZkpLr1m760vp5tN2e8jtHX0Yf4f3da+1L4oEEQAAAAASUVORK5CYII=",leftZag:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACtElEQVR4Xg2Lu25cZRhF93f5L3OOPeOQmJuDhEIHDa/CC/B4SHSICqS0CERDE2MJAYKEmITEcewZz/nvH7O0taq16eTL++P66nhCDegOAEhghFYhDDM0hSgowQkKkDIwJi0pP/72G9j24vIi8S7nN34lYG1VyOKg0uVKFFIiY/XL+R8s977+6nvttBMkovTDz9/Np3G3fTlvYkoFJswzaxtya2haQ0nUdGa2PLY6GD/9+vjJ+Y+bD+K2vFxtrLS3cQq9t1rLwUZ7IpuOAmQQ8u9/PgFDWbG5708/jK/Ti9OzExErhYVU1TMrCZqV7fY2Or2+uQ5H7zgPMNQF5HL7+upZeFeHLU//etrraM2YedQBAXsnoPXHn8yrcHVzE0LICWoECTQf+SG19dRqK3tMUxSRZtkIZtqbsblW+vF8/Pzy1XoNvdthjDas7He7swdno+JkM21v997r6A1MIKNBwiCiXssqhNsbcAwQosPTeek1MzBa947NmnewYcGR8Oh1sZG8s5LvQoACaK0Yegi+965MNWXnxIAx0AdyWnqDMjuh1KoIkYGNUPqh0zHaYcpwoin1ZiBFjFBVEWLm1ppzTkQAsAQYQdwhTap+dBCRXzkW6g2lIpdqRkYE1v1+AZgEuiRo8G2YaCBo75ZylSCdiMnoYPVefO1k8AYm7rlAjUDi7/ZN18HIffbp5zFO22Vf0bzXfsBQUu4DIJ6P1/t/XowB9RGl4Xj94M62zy+vou2sDUySyhJjTDXpAeL9YFKXaxYnuoL2BRfnzxghj7YKm4liHkszGkOUjtxIYjKM9ncpTnPr4+HDj8j+U5/B5R5k/vfv344m6rfXHb3NSqKvdrs5xKUWeN95nUd69Oi9vpQI0PtfTAn7eE/eLF0Y92eUjrcDISBmrBjbgkrIDPFYCfoCLPgflXOjuIEFgMYAAAAASUVORK5CYII="}},modern:{background:"#000000",backgroundGrid:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAIAAAC0Ujn1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjZTg0NzU4MC00ODk3LTRkNjAtOWNhYi1mZTk1NzQ5NzhiNjkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTEzOEQwMDc5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTEzOEQwMDY5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDplNDRjOWZiNC0yNzE5LTQ3NDYtYmRmMi0wMmY2ZTA4ZjAxMmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzMwNTNEOTk5MDM1MTFFNDlBMzlFNzY4RjBCNkNENzMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7Y01+zAAAAMklEQVR42mJgGAWjYBSMgkEJGIlUd+j/WjjbjjGYGC1MtHP10DR6FIyCUTAKBikACDAA0NoDCLGGjH8AAAAASUVORK5CYII=",primary:null,secondary:null,stroke:null,blocks:{line:"#fa1e1e",square:"#f1fa1e",arrow:"#d838cb",rightHook:"#f5821f",leftHook:"#42c6f0",rightZag:"#4bd838",leftZag:"#fa1e1e"}},retro:{background:"#000000",backgroundGrid:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAIAAAC0Ujn1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjZTg0NzU4MC00ODk3LTRkNjAtOWNhYi1mZTk1NzQ5NzhiNjkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTEzOEQwMDc5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTEzOEQwMDY5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDplNDRjOWZiNC0yNzE5LTQ3NDYtYmRmMi0wMmY2ZTA4ZjAxMmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzMwNTNEOTk5MDM1MTFFNDlBMzlFNzY4RjBCNkNENzMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7Y01+zAAAAMklEQVR42mJgGAWjYBSMgkEJGIlUd+j/WjjbjjGYGC1MtHP10DR6FIyCUTAKBikACDAA0NoDCLGGjH8AAAAASUVORK5CYII=",primary:null,secondary:null,stroke:"#000000",innerStroke:"#000000",blocks:{line:"#fa1e1e",square:"#f1fa1e",arrow:"#d838cb",rightHook:"#f5821f",leftHook:"#42c6f0",rightZag:"#4bd838",leftZag:"#fa1e1e"}},monochrome:{background:"#000000",backgroundGrid:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAIAAAC0Ujn1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjZTg0NzU4MC00ODk3LTRkNjAtOWNhYi1mZTk1NzQ5NzhiNjkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTEzOEQwMDc5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTEzOEQwMDY5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDplNDRjOWZiNC0yNzE5LTQ3NDYtYmRmMi0wMmY2ZTA4ZjAxMmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzMwNTNEOTk5MDM1MTFFNDlBMzlFNzY4RjBCNkNENzMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7Y01+zAAAAMklEQVR42mJgGAWjYBSMgkEJGIlUd+j/WjjbjjGYGC1MtHP10DR6FIyCUTAKBikACDAA0NoDCLGGjH8AAAAASUVORK5CYII=",primary:"#ffffff",secondary:"#ffffff",stroke:"#000000",innerStroke:"#000000"},aerolab:{background:"#ffffff",primary:"#ff7b00",secondary:"#000000"},gameboy:{background:"#C4CFA1",primary:null,secondary:null,stroke:"#414141",innerStroke:"#414141",innerSquare:"#000000",blocks:{line:"#88926A",square:"#585E44",arrow:"#A4AC8C",rightHook:"#6B7353",leftHook:"#6B7353",rightZag:"#595F45",leftZag:"#595F45"}},vim:{background:"#000000",backgroundGrid:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAIAAAC0Ujn1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjZTg0NzU4MC00ODk3LTRkNjAtOWNhYi1mZTk1NzQ5NzhiNjkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTEzOEQwMDc5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTEzOEQwMDY5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDplNDRjOWZiNC0yNzE5LTQ3NDYtYmRmMi0wMmY2ZTA4ZjAxMmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzMwNTNEOTk5MDM1MTFFNDlBMzlFNzY4RjBCNkNENzMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7Y01+zAAAAMklEQVR42mJgGAWjYBSMgkEJGIlUd+j/WjjbjjGYGC1MtHP10DR6FIyCUTAKBikACDAA0NoDCLGGjH8AAAAASUVORK5CYII=",primary:"#C2FFAE",secondary:"#C2FFAE",stroke:"#000000",strokeWidth:3,innerStroke:null}}; \ No newline at end of file diff --git a/dist/blockrain.zip b/dist/blockrain.zip index 4c794ec32014254c2a05f4513e5094e512034f48..0487dc184099f0ab4d6c0b54857b451851e8fa1e 100644 GIT binary patch delta 45918 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

UEKZ1W0hoBNT8j}MCK9*vG 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 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..72ec975 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1854 @@ +{ + "name": "blockrain", + "version": "0.2.0", + "lockfileVersion": 1, + "dependencies": { + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-slice": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.0.0.tgz", + "integrity": "sha1-5zA08A3MH0CHYAj9IP6ud71LfC8=", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "cloneable-readable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", + "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-with-sourcemaps": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz", + "integrity": "sha1-9Vs74q60dgGxCi1SWcz7cP0vHdY=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true + }, + "dateformat": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", + "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=", + "dev": true + }, + "deap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/deap/-/deap-1.0.0.tgz", + "integrity": "sha1-sUi/gkMKJ2mbdIOgPra2dYW/yIg=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "detect-file": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", + "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true + }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true + }, + "expand-tilde": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true + }, + "fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true + }, + "findup-sync": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", + "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", + "dev": true + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "dependencies": { + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true + } + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", + "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true + }, + "fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true + }, + "global-modules": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", + "dev": true + }, + "global-prefix": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "dev": true + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true + } + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true + }, + "gulp-clean": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/gulp-clean/-/gulp-clean-0.3.2.tgz", + "integrity": "sha1-o0fUc6zqQBgvk1WHpFGUFnGSgQI=", + "dev": true, + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true + }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true + }, + "chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "dev": true + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true + }, + "gulp-util": { + "version": "2.2.20", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", + "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", + "dev": true, + "dependencies": { + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true + } + } + }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", + "dev": true + }, + "lodash.escape": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", + "dev": true + }, + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true + }, + "lodash.template": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", + "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", + "dev": true + }, + "lodash.templatesettings": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", + "dev": true + }, + "minimist": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + }, + "through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "dev": true, + "dependencies": { + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true + } + } + }, + "vinyl": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", + "dev": true + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + } + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "dev": true + } + } + }, + "gulp-header": { + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.8.tgz", + "integrity": "sha1-RQnGRneqtWte6ORmmnmxZVkzpJ4=", + "dev": true + }, + "gulp-uglify": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.4.tgz", + "integrity": "sha1-UkeI2HZm0J+dDCH7IXf5ADmmWMk=", + "dev": true + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true + }, + "gulp-zip": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/gulp-zip/-/gulp-zip-2.0.3.tgz", + "integrity": "sha1-iO8RbT8VvSCvzqyQFl0fxj88bh8=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "interpret": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", + "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", + "dev": true + }, + "is-absolute": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", + "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.3.tgz", + "integrity": "sha1-wVvz5LZrYtcu+vKSWEhmPsvGGbY=", + "dev": true, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-relative": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", + "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "dev": true + }, + "is-unc-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", + "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "jquery": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-1.11.3.tgz", + "integrity": "sha1-3Yt0J4snEC0p32Pq4oMIqM+htYM=" + }, + "jszip": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-2.6.1.tgz", + "integrity": "sha1-uI86ey5noqBIFSmCx6N1bZxIKPA=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "liftoff": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", + "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", + "dev": true + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true + } + } + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._escapehtmlchar": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", + "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", + "dev": true + }, + "lodash._escapestringchar": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", + "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._htmlescapes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._isnative": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", + "dev": true + }, + "lodash._objecttypes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._reunescapedhtml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", + "dev": true, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true + } + } + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash._shimkeys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", + "dev": true + }, + "lodash.defaults": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", + "dev": true, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true + } + } + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isobject": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true + }, + "lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true + }, + "lodash.values": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", + "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", + "dev": true, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true + }, + "natives": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", + "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true + }, + "object.pick": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.2.0.tgz", + "integrity": "sha1-tTkr7peC2m2ft9avr1OXefEjTCs=", + "dev": true + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "pako": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.5.tgz", + "integrity": "sha1-0iBd/ludqK95fnwWPbTR+E5GALw=", + "dev": true + }, + "parse-filepath": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", + "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true + }, + "regex-cache": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", + "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz", + "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "resolve": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", + "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", + "dev": true + }, + "resolve-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "dev": true, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + } + } + }, + "run-sequence": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-1.0.2.tgz", + "integrity": "sha1-hBdXc8OGJ+m70gxJab9z70K2tdU=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "stream-consume": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", + "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true + } + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "uglify-js": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", + "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", + "dev": true + }, + "uglify-save-license": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", + "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", + "dev": true + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true + }, + "which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + } + } + } + } +} diff --git a/src/blockrain.jquery.src.js b/src/blockrain.jquery.src.js index 7fa74e0..ec568e8 100644 --- a/src/blockrain.jquery.src.js +++ b/src/blockrain.jquery.src.js @@ -437,10 +437,30 @@ rotate: function(direction) { var orientation = (this.orientation + (direction === 'left' ? 1 : -1) + 4) % 4; - //TODO - when past limit - auto shift and remember that too! if (!game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { this.orientation = orientation; game._board.renderChanged = true; + } else { + this.orientation = orientation; + while (this.x >= 8){ + this.x--; + } + while (this.x < 0){ + this.x++; + } + if (this.blockType === "line" && this.x === 0) this.x++ + + //If there is vertical collision after rotation, piece will go up as much as needed. + + if (game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { + console.log(this.x + " " + this.y) + for(let i = this.y; i > 0; i--) { + if (game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { + this.y = i--; + } + } + } + game._board.renderChanged = true; } }, From 9726fe2bc01b3cfbab58ce891081bd9abb359acb Mon Sep 17 00:00:00 2001 From: Micael Robles Date: Tue, 11 Jul 2017 17:46:34 -0300 Subject: [PATCH 02/10] cleanup --- src/blockrain.jquery.src.js | 700 ++++++++++++++++++------------------ 1 file changed, 349 insertions(+), 351 deletions(-) diff --git a/src/blockrain.jquery.src.js b/src/blockrain.jquery.src.js index ec568e8..c3fe6b4 100644 --- a/src/blockrain.jquery.src.js +++ b/src/blockrain.jquery.src.js @@ -1,4 +1,4 @@ -((function ( $ ) { +((function ($) { "use strict"; @@ -24,37 +24,37 @@ scoreText: 'Score', // Basic Callbacks - onStart: function(){}, - onRestart: function(){}, - onGameOver: function(score){}, + onStart: function () { }, + onRestart: function () { }, + onGameOver: function (score) { }, // When a block is placed - onPlaced: function(){}, + onPlaced: function () { }, // When a line is made. Returns the number of lines, score assigned and total score - onLine: function(lines, scoreIncrement, score){} + onLine: function (lines, scoreIncrement, score) { } }, /** * Start/Restart Game */ - start: function() { + start: function () { this._doStart(); this.options.onStart.call(this.element); }, - restart: function() { + restart: function () { this._doStart(); this.options.onRestart.call(this.element); }, - gameover: function() { + gameover: function () { this.showGameOverMessage(); this._board.gameover = true; this.options.onGameOver.call(this.element, this._filled.score); }, - _doStart: function() { + _doStart: function () { this._filled.clearAll(); this._filled._resetScore(); this._board.cur = this._board.nextShape(); @@ -70,60 +70,60 @@ }, - pause: function() { + pause: function () { this._board.paused = true; }, - resume: function() { + resume: function () { this._board.paused = false; }, - autoplay: function(enable) { - if( typeof enable !== 'boolean' ){ enable = true; } + autoplay: function (enable) { + if (typeof enable !== 'boolean') { enable = true; } // On autoplay, start the game right away this.options.autoplay = enable; - if( enable && ! this._board.started ) { + if (enable && !this._board.started) { this._doStart(); } - this._setupControls( ! enable ); - this._setupTouchControls( ! enable ); + this._setupControls(!enable); + this._setupTouchControls(!enable); }, - controls: function(enable) { - if( typeof enable !== 'boolean' ){ enable = true; } + controls: function (enable) { + if (typeof enable !== 'boolean') { enable = true; } this._setupControls(enable); }, - touchControls: function(enable) { - if( typeof enable !== 'boolean' ){ enable = true; } + touchControls: function (enable) { + if (typeof enable !== 'boolean') { enable = true; } this._setupTouchControls(enable); }, - score: function(newScore) { - if( typeof newScore !== 'undefined' && parseInt(newScore) >= 0 ) { + score: function (newScore) { + if (typeof newScore !== 'undefined' && parseInt(newScore) >= 0) { this._filled.score = parseInt(newScore); this._$scoreText.text(this._filled_score); } return this._filled.score; }, - freesquares: function() { + freesquares: function () { return this._filled.getFreeSpaces(); }, - showStartMessage: function() { + showStartMessage: function () { this._$start.show(); }, - showGameOverMessage: function() { + showGameOverMessage: function () { this._$gameover.show(); }, /** * Update the sizes of the renderer (this makes the game responsive) */ - updateSizes: function() { + updateSizes: function () { this._PIXEL_WIDTH = this.element.innerWidth(); this._PIXEL_HEIGHT = this.element.innerHeight(); @@ -138,19 +138,19 @@ this._PIXEL_WIDTH = this._block_size * this._BLOCK_WIDTH; this._PIXEL_HEIGHT = this._block_size * this._BLOCK_HEIGHT; - this._$canvas .attr('width', this._PIXEL_WIDTH) - .attr('height', this._PIXEL_HEIGHT); + this._$canvas.attr('width', this._PIXEL_WIDTH) + .attr('height', this._PIXEL_HEIGHT); }, - theme: function(newTheme){ + theme: function (newTheme) { - if( typeof newTheme === 'undefined' ) { + if (typeof newTheme === 'undefined') { return this.options.theme || this._theme; } // Setup the theme properly - if( typeof newTheme === 'string' ) { + if (typeof newTheme === 'string') { this.options.theme = newTheme; this._theme = $.extend(true, {}, BlockrainThemes[newTheme]); } @@ -159,20 +159,20 @@ this._theme = newTheme; } - if( typeof this._theme === 'undefined' || this._theme === null ) { + if (typeof this._theme === 'undefined' || this._theme === null) { this._theme = $.extend(true, {}, BlockrainThemes['retro']); this.options.theme = 'retro'; } - if( isNaN(parseInt(this._theme.strokeWidth)) || typeof parseInt(this._theme.strokeWidth) !== 'number' ) { + if (isNaN(parseInt(this._theme.strokeWidth)) || typeof parseInt(this._theme.strokeWidth) !== 'number') { this._theme.strokeWidth = 2; } // Load the image assets this._preloadThemeAssets(); - if( this._board !== null ) { - if( typeof this._theme.background === 'string' ) { + if (this._board !== null) { + if (typeof this._theme.background === 'string') { this._$canvas.css('background-color', this._theme.background); } this._board.render(); @@ -202,7 +202,7 @@ // Initialization - _create: function() { + _create: function () { var game = this; @@ -215,7 +215,7 @@ this.updateSizes(); - $(window).resize(function(){ + $(window).resize(function () { //game.updateSizes(); }); @@ -227,13 +227,13 @@ this._info.init(); this._board.init(); - var renderLoop = function(){ + var renderLoop = function () { requestAnimationFrame(renderLoop); game._board.render(); }; renderLoop(); - if( this.options.autoplay ) { + if (this.options.autoplay) { this.autoplay(true); this._setupTouchControls(false); } else { @@ -243,12 +243,12 @@ }, - _checkCollisions: function(x, y, blocks, checkDownOnly) { + _checkCollisions: function (x, y, blocks, checkDownOnly) { // x & y should be aspirational values var i = 0, len = blocks.length, a, b; - for (; i= this._BLOCK_HEIGHT || this._filled.check(a, b)) { return true; @@ -268,46 +268,46 @@ /** * Draws the background */ - _drawBackground: function() { + _drawBackground: function () { - if( typeof this._theme.background !== 'string' ) { + if (typeof this._theme.background !== 'string') { return; } - if( this._theme.backgroundGrid instanceof Image ) { + if (this._theme.backgroundGrid instanceof Image) { // Not loaded - if( this._theme.backgroundGrid.width === 0 || this._theme.backgroundGrid.height === 0 ){ return; } + if (this._theme.backgroundGrid.width === 0 || this._theme.backgroundGrid.height === 0) { return; } this._ctx.globalAlpha = 1.0; - for( var x=0; x= 8){ + while (this.x >= 8) { this.x--; - } - while (this.x < 0){ + } + while (this.x < 0) { this.x++; } - if (this.blockType === "line" && this.x === 0) this.x++ - + if (this.blockType === "line" && this.x === 0) this.x++ + //If there is vertical collision after rotation, piece will go up as much as needed. - + if (game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { - console.log(this.x + " " + this.y) - for(let i = this.y; i > 0; i--) { + for (let i = this.y; i > 0; i--) { if (game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { this.y = i--; } @@ -464,19 +463,19 @@ } }, - moveRight: function() { + moveRight: function () { if (!game._checkCollisions(this.x + 1, this.y, this.getBlocks())) { this.x++; game._board.renderChanged = true; } }, - moveLeft: function() { + moveLeft: function () { if (!game._checkCollisions(this.x - 1, this.y, this.getBlocks())) { this.x--; game._board.renderChanged = true; } }, - drop: function() { + drop: function () { if (!game._checkCollisions(this.x, this.y + 1, this.getBlocks())) { this.y++; // Reset the drop count, as we dropped the block sooner @@ -486,29 +485,29 @@ } }, - getBlocks: function(orientation) { // optional param + getBlocks: function (orientation) { // optional param return this.orientations[orientation !== undefined ? orientation : this.orientation]; }, - draw: function(_x, _y, _orientation) { + draw: function (_x, _y, _orientation) { var blocks = this.getBlocks(_orientation), - x = _x === undefined ? this.x : _x, - y = _y === undefined ? this.y : _y, - i = 0, - index = 0; + x = _x === undefined ? this.x : _x, + y = _y === undefined ? this.y : _y, + i = 0, + index = 0; - for (; i maxx) { maxx = blocks[i]; } - if (blocks[i+1] < miny) { miny = blocks[i+1]; } - if (blocks[i+1] > maxy) { maxy = blocks[i+1]; } + if (blocks[i + 1] < miny) { miny = blocks[i + 1]; } + if (blocks[i + 1] > maxy) { maxy = blocks[i + 1]; } } return { left: minx, @@ -525,81 +524,81 @@ }; this._shapeFactory = { - line: function() { + line: function () { return new Shape(game, game._shapes.line, false, 'line'); }, - square: function() { + square: function () { return new Shape(game, game._shapes.square, false, 'square'); }, - arrow: function() { + arrow: function () { return new Shape(game, game._shapes.arrow, false, 'arrow'); }, - leftHook: function() { + leftHook: function () { return new Shape(game, game._shapes.leftHook, false, 'leftHook'); }, - rightHook: function() { + rightHook: function () { return new Shape(game, game._shapes.rightHook, false, 'rightHook'); }, - leftZag: function() { + leftZag: function () { return new Shape(game, game._shapes.leftZag, false, 'leftZag'); }, - rightZag: function() { + rightZag: function () { return new Shape(game, game._shapes.rightZag, false, 'rightZag'); } }; }, - _SetupFilled: function() { + _SetupFilled: function () { var game = this; - if( this._filled !== null ){ return; } + if (this._filled !== null) { return; } this._filled = { data: new Array(game._BLOCK_WIDTH * game._BLOCK_HEIGHT), score: 0, toClear: {}, - check: function(x, y) { + check: function (x, y) { return this.data[this.asIndex(x, y)]; }, - add: function(x, y, blockType, blockVariation, blockIndex, blockOrientation) { + add: function (x, y, blockType, blockVariation, blockIndex, blockOrientation) { if (x >= 0 && x < game._BLOCK_WIDTH && y >= 0 && y < game._BLOCK_HEIGHT) { this.data[this.asIndex(x, y)] = { - blockType: blockType, - blockVariation: blockVariation, - blockIndex: blockIndex, + blockType: blockType, + blockVariation: blockVariation, + blockIndex: blockIndex, blockOrientation: blockOrientation }; } }, - getFreeSpaces: function() { + getFreeSpaces: function () { var count = 0; - for( var i=0; i=0; i--) { - this.data[i] = (i >= game._BLOCK_WIDTH ? this.data[i-game._BLOCK_WIDTH] : undefined); + _popRow: function (row_to_pop) { + for (var i = game._BLOCK_WIDTH * (row_to_pop + 1) - 1; i >= 0; i--) { + this.data[i] = (i >= game._BLOCK_WIDTH ? this.data[i - game._BLOCK_WIDTH] : undefined); } }, - checkForClears: function() { + checkForClears: function () { var startLines = game._board.lines; var rows = [], i, len, count, mod; - for (i=0, len=this.data.length; i 1 ) { + if (game._board.lines % 10 == 0 && game._board.dropDelay > 1) { game._board.dropDelay *= 0.9; } } @@ -621,22 +620,22 @@ var clearedLines = game._board.lines - startLines; this._updateScore(clearedLines); }, - _updateScore: function(numLines) { - if( numLines <= 0 ) { return; } - var scores = [0,400,1000,3000,12000]; - if( numLines >= scores.length ){ numLines = scores.length-1 } + _updateScore: function (numLines) { + if (numLines <= 0) { return; } + var scores = [0, 400, 1000, 3000, 12000]; + if (numLines >= scores.length) { numLines = scores.length - 1 } this.score += scores[numLines]; game._$scoreText.text(this.score); game.options.onLine.call(game.element, numLines, scores[numLines], this.score); }, - _resetScore: function() { + _resetScore: function () { this.score = 0; game._$scoreText.text(this.score); }, - draw: function() { - for (var i=0, len=this.data.length, row, color; i= this.dropDelay) || - (game.options.autoplay) || - (this.holding.drop && (now - this.holding.drop) >= this.holdingThreshold) ) { + if ((this.dropCount >= this.dropDelay) || + (game.options.autoplay) || + (this.holding.drop && (now - this.holding.drop) >= this.holdingThreshold)) { drop = true; - moved = true; + moved = true; this.dropCount = 0; } // Move Left by holding - if( this.holding.left && (now - this.holding.left) >= this.holdingThreshold ) { + if (this.holding.left && (now - this.holding.left) >= this.holdingThreshold) { moved = true; this.cur.moveLeft(); } // Move Right by holding - if( this.holding.right && (now - this.holding.right) >= this.holdingThreshold ) { + if (this.holding.right && (now - this.holding.right) >= this.holdingThreshold) { moved = true; this.cur.moveRight(); } @@ -811,11 +810,11 @@ // Test for a collision, add the piece to the filled blocks and fetch the next one if (drop) { var cur = this.cur, x = cur.x, y = cur.y, blocks = cur.getBlocks(); - if (game._checkCollisions(x, y+1, blocks, true)) { + if (game._checkCollisions(x, y + 1, blocks, true)) { drop = false; var blockIndex = 0; - for (var i=0; i 0) { + } + else if (blockTheme.length > 0) { return blockTheme[0]; } else { return null; @@ -1064,19 +1062,19 @@ } } - if( typeof falling !== 'boolean' ){ falling = true; } - if( falling ) { - if( typeof game._theme.primary === 'string' && game._theme.primary !== '' ) { + if (typeof falling !== 'boolean') { falling = true; } + if (falling) { + if (typeof game._theme.primary === 'string' && game._theme.primary !== '') { return game._theme.primary; - } else if( typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null ) { + } else if (typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null) { return getBlockVariation(game._theme.blocks[blockType], blockVariation); } else { return getBlockVariation(game._theme.complexBlocks[blockType], blockVariation); } } else { - if( typeof game._theme.secondary === 'string' && game._theme.secondary !== '' ) { + if (typeof game._theme.secondary === 'string' && game._theme.secondary !== '') { return game._theme.secondary; - } else if( typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null ) { + } else if (typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null) { return getBlockVariation(game._theme.blocks[blockType], blockVariation); } else { return getBlockVariation(game._theme.complexBlocks[blockType], blockVariation); @@ -1090,31 +1088,31 @@ }, // Utility Functions - _randInt: function(a, b) { return a + Math.floor(Math.random() * (1 + b - a)); }, - _randSign: function() { return this._randInt(0, 1) * 2 - 1; }, - _randChoice: function(choices) { return choices[this._randInt(0, choices.length-1)]; }, + _randInt: function (a, b) { return a + Math.floor(Math.random() * (1 + b - a)); }, + _randSign: function () { return this._randInt(0, 1) * 2 - 1; }, + _randChoice: function (choices) { return choices[this._randInt(0, choices.length - 1)]; }, /** * Find base64 encoded images and load them as image objects, which can be used by the canvas renderer */ - _preloadThemeAssets: function() { + _preloadThemeAssets: function () { var game = this; var hexColorcheck = new RegExp('^#[A-F0-9+]{3,6}', 'i'); var base64check = new RegExp('^data:image/(png|gif|jpg);base64,', 'i'); - var handleAssetLoad = function() { + var handleAssetLoad = function () { // Rerender the board as soon as an asset loads - if( game._board ) { + if (game._board) { game._board.render(true); } }; - var loadAsset = function(src) { + var loadAsset = function (src) { var plainSrc = src; - if( ! hexColorcheck.test( plainSrc ) ) { + if (!hexColorcheck.test(plainSrc)) { // It's an image src = new Image(); src.src = plainSrc; @@ -1126,41 +1124,41 @@ return src; }; - var startAssetLoad = function(block) { + var startAssetLoad = function (block) { // Assets can be an array of variation so they can change color/design randomly - if( $.isArray(block) && block.length > 0 ) { - for( var i=0; i 0) { + for (var i = 0; i < block.length; i++) { block[i] = loadAsset(block[i]); } } - else if( typeof block === 'string' ) { + else if (typeof block === 'string') { block = loadAsset(block); } return block; }; - if( typeof this._theme.complexBlocks !== 'undefined' ){ + if (typeof this._theme.complexBlocks !== 'undefined') { var keys = Object.keys(this._theme.complexBlocks); // Load the complexBlocks - for( var i = 0; i < keys.length; i++ ) { - this._theme.complexBlocks[ keys[i] ] = startAssetLoad( this._theme.complexBlocks[ keys[i] ] ); + for (var i = 0; i < keys.length; i++) { + this._theme.complexBlocks[keys[i]] = startAssetLoad(this._theme.complexBlocks[keys[i]]); } } - else if( typeof this._theme.blocks !== 'undefined' ){ + else if (typeof this._theme.blocks !== 'undefined') { var keys = Object.keys(this._theme.blocks); // Load the blocks - for( var i = 0; i < keys.length; i++ ) { - this._theme.blocks[ keys[i] ] = startAssetLoad( this._theme.blocks[ keys[i] ] ); + for (var i = 0; i < keys.length; i++) { + this._theme.blocks[keys[i]] = startAssetLoad(this._theme.blocks[keys[i]]); } } // Load the bg - if( typeof this._theme.backgroundGrid !== 'undefined' ){ - if( typeof this._theme.backgroundGrid === 'string' ) { - if( ! hexColorcheck.test( this._theme.backgroundGrid ) ) { + if (typeof this._theme.backgroundGrid !== 'undefined') { + if (typeof this._theme.backgroundGrid === 'string') { + if (!hexColorcheck.test(this._theme.backgroundGrid)) { var src = this._theme.backgroundGrid; this._theme.backgroundGrid = new Image(); this._theme.backgroundGrid.src = src; @@ -1172,7 +1170,7 @@ }, - _createHolder: function() { + _createHolder: function () { // Create the main holder (it holds all the ui elements, the original element is just the wrapper) this._$gameholder = $('

'); @@ -1182,7 +1180,7 @@ // Create the game canvas and context this._$canvas = $(''); - if( typeof this._theme.background === 'string' ) { + if (typeof this._theme.background === 'string') { this._$canvas.css('background-color', this._theme.background); } this._$gameholder.append(this._$canvas); @@ -1193,45 +1191,45 @@ }, - _createUI: function() { + _createUI: function () { var game = this; // Score game._$score = $( - '
'+ - '
'+ - '
'+ this.options.scoreText +'
'+ - '
0
'+ - '
'+ + '
' + + '
' + + '
' + this.options.scoreText + '
' + + '
0
' + + '
' + '
').hide(); game._$scoreText = game._$score.find('.blockrain-score-num'); game._$gameholder.append(game._$score); // Create the start menu game._$start = $( - '
'+ - ''+ + '
' + + '
' + + '
' + this.options.playText + '
' + + '' + this.options.playButtonText + '' + + '
' + '
').hide(); game._$gameholder.append(game._$start); - game._$start.find('.blockrain-start-btn').click(function(event){ + game._$start.find('.blockrain-start-btn').click(function (event) { event.preventDefault(); game.start(); }); // Create the game over menu game._$gameover = $( - '
'+ - '
'+ - '
'+ this.options.gameOverText +'
'+ - ''+ this.options.restartButtonText +''+ - '
'+ + '
' + + '
' + + '
' + this.options.gameOverText + '
' + + '' + this.options.restartButtonText + '' + + '
' + '
').hide(); - game._$gameover.find('.blockrain-game-over-btn').click(function(event){ + game._$gameover.find('.blockrain-game-over-btn').click(function (event) { event.preventDefault(); game.restart(); }); @@ -1241,7 +1239,7 @@ }, - _createControls: function() { + _createControls: function () { var game = this; @@ -1254,16 +1252,16 @@ }, - _refreshBlockSizes: function() { + _refreshBlockSizes: function () { - if( this.options.autoBlockWidth ) { - this.options.blockWidth = Math.ceil( this.element.width() / this.options.autoBlockSize ); + if (this.options.autoBlockWidth) { + this.options.blockWidth = Math.ceil(this.element.width() / this.options.autoBlockSize); } }, - _getNiceShapes: function() { + _getNiceShapes: function () { /* * Things I need for this to work... * - ability to test each shape with this._filled data @@ -1273,24 +1271,24 @@ var game = this; var shapes = {}, - attr; + attr; - for( var attr in this._shapeFactory ) { + for (var attr in this._shapeFactory) { shapes[attr] = this._shapeFactory[attr](); } function scoreBlocks(possibles, blocks, x, y, filled, width, height) { - var i, len=blocks.length, score=0, bottoms = {}, tx, ty, overlaps; + var i, len = blocks.length, score = 0, bottoms = {}, tx, ty, overlaps; // base score - for (i=0; i best_score_for_shape) { @@ -1370,7 +1368,7 @@ } if ((evil && best_score_for_shape < best_score) || - (!evil && best_score_for_shape > best_score)) { + (!evil && best_score_for_shape > best_score)) { best_shape = shape; best_score = best_score_for_shape; best_orientation = best_orientation_for_shape; @@ -1389,10 +1387,10 @@ }, - _randomShapes: function() { + _randomShapes: function () { // Todo: The shapefuncs should be cached. var shapeFuncs = []; - $.each(this._shapeFactory, function(k,v) { shapeFuncs.push(v); }); + $.each(this._shapeFactory, function (k, v) { shapeFuncs.push(v); }); return this._randChoice(shapeFuncs); }, @@ -1401,55 +1399,55 @@ /** * Controls */ - _setupControls: function(enable) { + _setupControls: function (enable) { var game = this; - var moveLeft = function(start) { - if( ! start ) { game._board.holding.left = null; return; } - if( ! game._board.holding.left ) { - game._board.cur.moveLeft(); + var moveLeft = function (start) { + if (!start) { game._board.holding.left = null; return; } + if (!game._board.holding.left) { + game._board.cur.moveLeft(); game._board.holding.left = Date.now(); - game._board.holding.right = null; + game._board.holding.right = null; } } - var moveRight = function(start) { - if( ! start ) { game._board.holding.right = null; return; } - if( ! game._board.holding.right ) { - game._board.cur.moveRight(); - game._board.holding.right = Date.now(); - game._board.holding.left = null; + var moveRight = function (start) { + if (!start) { game._board.holding.right = null; return; } + if (!game._board.holding.right) { + game._board.cur.moveRight(); + game._board.holding.right = Date.now(); + game._board.holding.left = null; } } - var drop = function(start) { - if( ! start ) { game._board.holding.drop = null; return; } - if( ! game._board.holding.drop ) { - game._board.cur.drop(); + var drop = function (start) { + if (!start) { game._board.holding.drop = null; return; } + if (!game._board.holding.drop) { + game._board.cur.drop(); game._board.holding.drop = Date.now(); } } - var rotateLeft = function() { - game._board.cur.rotate('left'); + var rotateLeft = function () { + game._board.cur.rotate('left'); } - var rotateRight = function() { - game._board.cur.rotate('right'); + var rotateRight = function () { + game._board.cur.rotate('right'); } // Handlers: These are used to be able to bind/unbind controls - var handleKeyDown = function(evt) { - if( ! game._board.cur ) { return true; } + var handleKeyDown = function (evt) { + if (!game._board.cur) { return true; } var caught = false; caught = true; if (game.options.asdwKeys) { - switch(evt.keyCode) { + switch (evt.keyCode) { case 65: /*a*/ moveLeft(true); break; case 68: /*d*/ moveRight(true); break; case 83: /*s*/ drop(true); break; case 87: /*w*/ game._board.cur.rotate('right'); break; } } - switch(evt.keyCode) { + switch (evt.keyCode) { case 37: /*left*/ moveLeft(true); break; case 39: /*right*/ moveRight(true); break; case 40: /*down*/ drop(true); break; @@ -1463,19 +1461,19 @@ }; - var handleKeyUp = function(evt) { - if( ! game._board.cur ) { return true; } + var handleKeyUp = function (evt) { + if (!game._board.cur) { return true; } var caught = false; caught = true; if (game.options.asdwKeys) { - switch(evt.keyCode) { + switch (evt.keyCode) { case 65: /*a*/ moveLeft(false); break; case 68: /*d*/ moveRight(false); break; case 83: /*s*/ drop(false); break; } } - switch(evt.keyCode) { + switch (evt.keyCode) { case 37: /*left*/ moveLeft(false); break; case 39: /*right*/ moveRight(false); break; case 40: /*down*/ drop(false); break; @@ -1487,7 +1485,7 @@ function isStopKey(evt) { var cfg = { - stopKeys: {37:1, 38:1, 39:1, 40:1} + stopKeys: { 37: 1, 38: 1, 39: 1, 40: 1 } }; var isStop = (cfg.stopKeys[evt.keyCode] || (cfg.moreStopKeys && cfg.moreStopKeys[evt.keyCode])); @@ -1511,61 +1509,61 @@ // Unbind everything by default // Use event namespacing so we don't ruin other keypress events - $(document) .unbind('keydown.blockrain') - .unbind('keyup.blockrain'); + $(document).unbind('keydown.blockrain') + .unbind('keyup.blockrain'); - if( ! game.options.autoplay ) { - if( enable ) { - $(document) .bind('keydown.blockrain', keydown) - .bind('keyup.blockrain', keyup); + if (!game.options.autoplay) { + if (enable) { + $(document).bind('keydown.blockrain', keydown) + .bind('keyup.blockrain', keyup); } } }, - _setupTouchControls: function(enable) { + _setupTouchControls: function (enable) { var game = this; // Movements can be held for faster movement - var moveLeft = function(event){ + var moveLeft = function (event) { event.preventDefault(); game._board.cur.moveLeft(); game._board.holding.left = Date.now(); game._board.holding.right = null; game._board.holding.drop = null; }; - var moveRight = function(event){ + var moveRight = function (event) { event.preventDefault(); game._board.cur.moveRight(); game._board.holding.right = Date.now(); game._board.holding.left = null; game._board.holding.drop = null; }; - var drop = function(event){ + var drop = function (event) { event.preventDefault(); game._board.cur.drop(); game._board.holding.drop = Date.now(); }; - var endMoveLeft = function(event){ + var endMoveLeft = function (event) { event.preventDefault(); game._board.holding.left = null; }; - var endMoveRight = function(event){ + var endMoveRight = function (event) { event.preventDefault(); game._board.holding.right = null; }; - var endDrop = function(event){ + var endDrop = function (event) { event.preventDefault(); game._board.holding.drop = null; }; // Rotations can't be held - var rotateLeft = function(event){ + var rotateLeft = function (event) { event.preventDefault(); game._board.cur.rotate('left'); }; - var rotateRight = function(event){ + var rotateRight = function (event) { event.preventDefault(); game._board.cur.rotate('right'); }; @@ -1577,7 +1575,7 @@ game._$touchRotateRight.unbind('touchstart touchend click'); game._$touchDrop.unbind('touchstart touchend click'); - if( ! game.options.autoplay && enable ) { + if (!game.options.autoplay && enable) { game._$touchLeft.show().bind('touchstart click', moveLeft).bind('touchend', endMoveLeft); game._$touchRight.show().bind('touchstart click', moveRight).bind('touchend', endMoveRight); game._$touchDrop.show().bind('touchstart click', drop).bind('touchend', endDrop); From d8b1c452a9cba07614413e7dad713e24a1c398c8 Mon Sep 17 00:00:00 2001 From: Micael Robles Date: Tue, 11 Jul 2017 17:55:14 -0300 Subject: [PATCH 03/10] revert cleanup --- src/blockrain.jquery.src.js | 699 ++++++++++++++++++------------------ 1 file changed, 350 insertions(+), 349 deletions(-) diff --git a/src/blockrain.jquery.src.js b/src/blockrain.jquery.src.js index c3fe6b4..b2b8ddb 100644 --- a/src/blockrain.jquery.src.js +++ b/src/blockrain.jquery.src.js @@ -1,4 +1,4 @@ -((function ($) { +((function ( $ ) { "use strict"; @@ -24,37 +24,37 @@ scoreText: 'Score', // Basic Callbacks - onStart: function () { }, - onRestart: function () { }, - onGameOver: function (score) { }, + onStart: function(){}, + onRestart: function(){}, + onGameOver: function(score){}, // When a block is placed - onPlaced: function () { }, + onPlaced: function(){}, // When a line is made. Returns the number of lines, score assigned and total score - onLine: function (lines, scoreIncrement, score) { } + onLine: function(lines, scoreIncrement, score){} }, /** * Start/Restart Game */ - start: function () { + start: function() { this._doStart(); this.options.onStart.call(this.element); }, - restart: function () { + restart: function() { this._doStart(); this.options.onRestart.call(this.element); }, - gameover: function () { + gameover: function() { this.showGameOverMessage(); this._board.gameover = true; this.options.onGameOver.call(this.element, this._filled.score); }, - _doStart: function () { + _doStart: function() { this._filled.clearAll(); this._filled._resetScore(); this._board.cur = this._board.nextShape(); @@ -70,60 +70,60 @@ }, - pause: function () { + pause: function() { this._board.paused = true; }, - resume: function () { + resume: function() { this._board.paused = false; }, - autoplay: function (enable) { - if (typeof enable !== 'boolean') { enable = true; } + autoplay: function(enable) { + if( typeof enable !== 'boolean' ){ enable = true; } // On autoplay, start the game right away this.options.autoplay = enable; - if (enable && !this._board.started) { + if( enable && ! this._board.started ) { this._doStart(); } - this._setupControls(!enable); - this._setupTouchControls(!enable); + this._setupControls( ! enable ); + this._setupTouchControls( ! enable ); }, - controls: function (enable) { - if (typeof enable !== 'boolean') { enable = true; } + controls: function(enable) { + if( typeof enable !== 'boolean' ){ enable = true; } this._setupControls(enable); }, - touchControls: function (enable) { - if (typeof enable !== 'boolean') { enable = true; } + touchControls: function(enable) { + if( typeof enable !== 'boolean' ){ enable = true; } this._setupTouchControls(enable); }, - score: function (newScore) { - if (typeof newScore !== 'undefined' && parseInt(newScore) >= 0) { + score: function(newScore) { + if( typeof newScore !== 'undefined' && parseInt(newScore) >= 0 ) { this._filled.score = parseInt(newScore); this._$scoreText.text(this._filled_score); } return this._filled.score; }, - freesquares: function () { + freesquares: function() { return this._filled.getFreeSpaces(); }, - showStartMessage: function () { + showStartMessage: function() { this._$start.show(); }, - showGameOverMessage: function () { + showGameOverMessage: function() { this._$gameover.show(); }, /** * Update the sizes of the renderer (this makes the game responsive) */ - updateSizes: function () { + updateSizes: function() { this._PIXEL_WIDTH = this.element.innerWidth(); this._PIXEL_HEIGHT = this.element.innerHeight(); @@ -138,19 +138,19 @@ this._PIXEL_WIDTH = this._block_size * this._BLOCK_WIDTH; this._PIXEL_HEIGHT = this._block_size * this._BLOCK_HEIGHT; - this._$canvas.attr('width', this._PIXEL_WIDTH) - .attr('height', this._PIXEL_HEIGHT); + this._$canvas .attr('width', this._PIXEL_WIDTH) + .attr('height', this._PIXEL_HEIGHT); }, - theme: function (newTheme) { + theme: function(newTheme){ - if (typeof newTheme === 'undefined') { + if( typeof newTheme === 'undefined' ) { return this.options.theme || this._theme; } // Setup the theme properly - if (typeof newTheme === 'string') { + if( typeof newTheme === 'string' ) { this.options.theme = newTheme; this._theme = $.extend(true, {}, BlockrainThemes[newTheme]); } @@ -159,20 +159,20 @@ this._theme = newTheme; } - if (typeof this._theme === 'undefined' || this._theme === null) { + if( typeof this._theme === 'undefined' || this._theme === null ) { this._theme = $.extend(true, {}, BlockrainThemes['retro']); this.options.theme = 'retro'; } - if (isNaN(parseInt(this._theme.strokeWidth)) || typeof parseInt(this._theme.strokeWidth) !== 'number') { + if( isNaN(parseInt(this._theme.strokeWidth)) || typeof parseInt(this._theme.strokeWidth) !== 'number' ) { this._theme.strokeWidth = 2; } // Load the image assets this._preloadThemeAssets(); - if (this._board !== null) { - if (typeof this._theme.background === 'string') { + if( this._board !== null ) { + if( typeof this._theme.background === 'string' ) { this._$canvas.css('background-color', this._theme.background); } this._board.render(); @@ -202,7 +202,7 @@ // Initialization - _create: function () { + _create: function() { var game = this; @@ -215,7 +215,7 @@ this.updateSizes(); - $(window).resize(function () { + $(window).resize(function(){ //game.updateSizes(); }); @@ -227,13 +227,13 @@ this._info.init(); this._board.init(); - var renderLoop = function () { + var renderLoop = function(){ requestAnimationFrame(renderLoop); game._board.render(); }; renderLoop(); - if (this.options.autoplay) { + if( this.options.autoplay ) { this.autoplay(true); this._setupTouchControls(false); } else { @@ -243,12 +243,12 @@ }, - _checkCollisions: function (x, y, blocks, checkDownOnly) { + _checkCollisions: function(x, y, blocks, checkDownOnly) { // x & y should be aspirational values var i = 0, len = blocks.length, a, b; - for (; i < len; i += 2) { + for (; i= this._BLOCK_HEIGHT || this._filled.check(a, b)) { return true; @@ -268,46 +268,46 @@ /** * Draws the background */ - _drawBackground: function () { + _drawBackground: function() { - if (typeof this._theme.background !== 'string') { + if( typeof this._theme.background !== 'string' ) { return; } - if (this._theme.backgroundGrid instanceof Image) { + if( this._theme.backgroundGrid instanceof Image ) { // Not loaded - if (this._theme.backgroundGrid.width === 0 || this._theme.backgroundGrid.height === 0) { return; } + if( this._theme.backgroundGrid.width === 0 || this._theme.backgroundGrid.height === 0 ){ return; } this._ctx.globalAlpha = 1.0; - for (var x = 0; x < this._BLOCK_WIDTH; x++) { - for (var y = 0; y < this._BLOCK_HEIGHT; y++) { + for( var x=0; x= 8) { + while (this.x >= 8){ this.x--; - } - while (this.x < 0) { + } + while (this.x < 0){ this.x++; } - if (this.blockType === "line" && this.x === 0) this.x++ - + if (this.blockType === "line" && this.x === 0) this.x++ + //If there is vertical collision after rotation, piece will go up as much as needed. - + if (game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { - for (let i = this.y; i > 0; i--) { + for(let i = this.y; i > 0; i--) { if (game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { this.y = i--; } @@ -463,19 +463,19 @@ } }, - moveRight: function () { + moveRight: function() { if (!game._checkCollisions(this.x + 1, this.y, this.getBlocks())) { this.x++; game._board.renderChanged = true; } }, - moveLeft: function () { + moveLeft: function() { if (!game._checkCollisions(this.x - 1, this.y, this.getBlocks())) { this.x--; game._board.renderChanged = true; } }, - drop: function () { + drop: function() { if (!game._checkCollisions(this.x, this.y + 1, this.getBlocks())) { this.y++; // Reset the drop count, as we dropped the block sooner @@ -485,29 +485,29 @@ } }, - getBlocks: function (orientation) { // optional param + getBlocks: function(orientation) { // optional param return this.orientations[orientation !== undefined ? orientation : this.orientation]; }, - draw: function (_x, _y, _orientation) { + draw: function(_x, _y, _orientation) { var blocks = this.getBlocks(_orientation), - x = _x === undefined ? this.x : _x, - y = _y === undefined ? this.y : _y, - i = 0, - index = 0; + x = _x === undefined ? this.x : _x, + y = _y === undefined ? this.y : _y, + i = 0, + index = 0; - for (; i < this.blocksLen; i += 2) { - game._board.drawBlock(x + blocks[i], y + blocks[i + 1], this.blockType, this.blockVariation, index, this.orientation, true); + for (; i maxx) { maxx = blocks[i]; } - if (blocks[i + 1] < miny) { miny = blocks[i + 1]; } - if (blocks[i + 1] > maxy) { maxy = blocks[i + 1]; } + if (blocks[i+1] < miny) { miny = blocks[i+1]; } + if (blocks[i+1] > maxy) { maxy = blocks[i+1]; } } return { left: minx, @@ -524,81 +524,81 @@ }; this._shapeFactory = { - line: function () { + line: function() { return new Shape(game, game._shapes.line, false, 'line'); }, - square: function () { + square: function() { return new Shape(game, game._shapes.square, false, 'square'); }, - arrow: function () { + arrow: function() { return new Shape(game, game._shapes.arrow, false, 'arrow'); }, - leftHook: function () { + leftHook: function() { return new Shape(game, game._shapes.leftHook, false, 'leftHook'); }, - rightHook: function () { + rightHook: function() { return new Shape(game, game._shapes.rightHook, false, 'rightHook'); }, - leftZag: function () { + leftZag: function() { return new Shape(game, game._shapes.leftZag, false, 'leftZag'); }, - rightZag: function () { + rightZag: function() { return new Shape(game, game._shapes.rightZag, false, 'rightZag'); } }; }, - _SetupFilled: function () { + _SetupFilled: function() { var game = this; - if (this._filled !== null) { return; } + if( this._filled !== null ){ return; } this._filled = { data: new Array(game._BLOCK_WIDTH * game._BLOCK_HEIGHT), score: 0, toClear: {}, - check: function (x, y) { + check: function(x, y) { return this.data[this.asIndex(x, y)]; }, - add: function (x, y, blockType, blockVariation, blockIndex, blockOrientation) { + add: function(x, y, blockType, blockVariation, blockIndex, blockOrientation) { if (x >= 0 && x < game._BLOCK_WIDTH && y >= 0 && y < game._BLOCK_HEIGHT) { this.data[this.asIndex(x, y)] = { - blockType: blockType, - blockVariation: blockVariation, - blockIndex: blockIndex, + blockType: blockType, + blockVariation: blockVariation, + blockIndex: blockIndex, blockOrientation: blockOrientation }; } }, - getFreeSpaces: function () { + getFreeSpaces: function() { var count = 0; - for (var i = 0; i < this.data.length; i++) { + for( var i=0; i= 0; i--) { - this.data[i] = (i >= game._BLOCK_WIDTH ? this.data[i - game._BLOCK_WIDTH] : undefined); + _popRow: function(row_to_pop) { + for (var i=game._BLOCK_WIDTH*(row_to_pop+1) - 1; i>=0; i--) { + this.data[i] = (i >= game._BLOCK_WIDTH ? this.data[i-game._BLOCK_WIDTH] : undefined); } }, - checkForClears: function () { + checkForClears: function() { var startLines = game._board.lines; var rows = [], i, len, count, mod; - for (i = 0, len = this.data.length; i < len; i++) { + for (i=0, len=this.data.length; i 1) { + if( game._board.lines % 10 == 0 && game._board.dropDelay > 1 ) { game._board.dropDelay *= 0.9; } } @@ -620,22 +620,22 @@ var clearedLines = game._board.lines - startLines; this._updateScore(clearedLines); }, - _updateScore: function (numLines) { - if (numLines <= 0) { return; } - var scores = [0, 400, 1000, 3000, 12000]; - if (numLines >= scores.length) { numLines = scores.length - 1 } + _updateScore: function(numLines) { + if( numLines <= 0 ) { return; } + var scores = [0,400,1000,3000,12000]; + if( numLines >= scores.length ){ numLines = scores.length-1 } this.score += scores[numLines]; game._$scoreText.text(this.score); game.options.onLine.call(game.element, numLines, scores[numLines], this.score); }, - _resetScore: function () { + _resetScore: function() { this.score = 0; game._$scoreText.text(this.score); }, - draw: function () { - for (var i = 0, len = this.data.length, row, color; i < len; i++) { + draw: function() { + for (var i=0, len=this.data.length, row, color; i= this.dropDelay) || - (game.options.autoplay) || - (this.holding.drop && (now - this.holding.drop) >= this.holdingThreshold)) { + if( (this.dropCount >= this.dropDelay) || + (game.options.autoplay) || + (this.holding.drop && (now - this.holding.drop) >= this.holdingThreshold) ) { drop = true; - moved = true; + moved = true; this.dropCount = 0; } // Move Left by holding - if (this.holding.left && (now - this.holding.left) >= this.holdingThreshold) { + if( this.holding.left && (now - this.holding.left) >= this.holdingThreshold ) { moved = true; this.cur.moveLeft(); } // Move Right by holding - if (this.holding.right && (now - this.holding.right) >= this.holdingThreshold) { + if( this.holding.right && (now - this.holding.right) >= this.holdingThreshold ) { moved = true; this.cur.moveRight(); } @@ -810,11 +810,11 @@ // Test for a collision, add the piece to the filled blocks and fetch the next one if (drop) { var cur = this.cur, x = cur.x, y = cur.y, blocks = cur.getBlocks(); - if (game._checkCollisions(x, y + 1, blocks, true)) { + if (game._checkCollisions(x, y+1, blocks, true)) { drop = false; var blockIndex = 0; - for (var i = 0; i < cur.blocksLen; i += 2) { - game._filled.add(x + blocks[i], y + blocks[i + 1], cur.blockType, cur.blockVariation, blockIndex, cur.orientation); + for (var i=0; i 0) { + } + else if(blockTheme.length > 0) { return blockTheme[0]; } else { return null; @@ -1062,19 +1063,19 @@ } } - if (typeof falling !== 'boolean') { falling = true; } - if (falling) { - if (typeof game._theme.primary === 'string' && game._theme.primary !== '') { + if( typeof falling !== 'boolean' ){ falling = true; } + if( falling ) { + if( typeof game._theme.primary === 'string' && game._theme.primary !== '' ) { return game._theme.primary; - } else if (typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null) { + } else if( typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null ) { return getBlockVariation(game._theme.blocks[blockType], blockVariation); } else { return getBlockVariation(game._theme.complexBlocks[blockType], blockVariation); } } else { - if (typeof game._theme.secondary === 'string' && game._theme.secondary !== '') { + if( typeof game._theme.secondary === 'string' && game._theme.secondary !== '' ) { return game._theme.secondary; - } else if (typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null) { + } else if( typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null ) { return getBlockVariation(game._theme.blocks[blockType], blockVariation); } else { return getBlockVariation(game._theme.complexBlocks[blockType], blockVariation); @@ -1088,31 +1089,31 @@ }, // Utility Functions - _randInt: function (a, b) { return a + Math.floor(Math.random() * (1 + b - a)); }, - _randSign: function () { return this._randInt(0, 1) * 2 - 1; }, - _randChoice: function (choices) { return choices[this._randInt(0, choices.length - 1)]; }, + _randInt: function(a, b) { return a + Math.floor(Math.random() * (1 + b - a)); }, + _randSign: function() { return this._randInt(0, 1) * 2 - 1; }, + _randChoice: function(choices) { return choices[this._randInt(0, choices.length-1)]; }, /** * Find base64 encoded images and load them as image objects, which can be used by the canvas renderer */ - _preloadThemeAssets: function () { + _preloadThemeAssets: function() { var game = this; var hexColorcheck = new RegExp('^#[A-F0-9+]{3,6}', 'i'); var base64check = new RegExp('^data:image/(png|gif|jpg);base64,', 'i'); - var handleAssetLoad = function () { + var handleAssetLoad = function() { // Rerender the board as soon as an asset loads - if (game._board) { + if( game._board ) { game._board.render(true); } }; - var loadAsset = function (src) { + var loadAsset = function(src) { var plainSrc = src; - if (!hexColorcheck.test(plainSrc)) { + if( ! hexColorcheck.test( plainSrc ) ) { // It's an image src = new Image(); src.src = plainSrc; @@ -1124,41 +1125,41 @@ return src; }; - var startAssetLoad = function (block) { + var startAssetLoad = function(block) { // Assets can be an array of variation so they can change color/design randomly - if ($.isArray(block) && block.length > 0) { - for (var i = 0; i < block.length; i++) { + if( $.isArray(block) && block.length > 0 ) { + for( var i=0; i
'); @@ -1180,7 +1181,7 @@ // Create the game canvas and context this._$canvas = $(''); - if (typeof this._theme.background === 'string') { + if( typeof this._theme.background === 'string' ) { this._$canvas.css('background-color', this._theme.background); } this._$gameholder.append(this._$canvas); @@ -1191,45 +1192,45 @@ }, - _createUI: function () { + _createUI: function() { var game = this; // Score game._$score = $( - '
' + - '
' + - '
' + this.options.scoreText + '
' + - '
0
' + - '
' + + '
'+ + '
'+ + '
'+ this.options.scoreText +'
'+ + '
0
'+ + '
'+ '
').hide(); game._$scoreText = game._$score.find('.blockrain-score-num'); game._$gameholder.append(game._$score); // Create the start menu game._$start = $( - '
' + - '
' + - '
' + this.options.playText + '
' + - '' + this.options.playButtonText + '' + - '
' + + '
'+ + '
'+ + '
'+ this.options.playText +'
'+ + ''+ this.options.playButtonText +''+ + '
'+ '
').hide(); game._$gameholder.append(game._$start); - game._$start.find('.blockrain-start-btn').click(function (event) { + game._$start.find('.blockrain-start-btn').click(function(event){ event.preventDefault(); game.start(); }); // Create the game over menu game._$gameover = $( - '
' + - '
' + - '
' + this.options.gameOverText + '
' + - '' + this.options.restartButtonText + '' + - '
' + + '
'+ + '
'+ + '
'+ this.options.gameOverText +'
'+ + ''+ this.options.restartButtonText +''+ + '
'+ '
').hide(); - game._$gameover.find('.blockrain-game-over-btn').click(function (event) { + game._$gameover.find('.blockrain-game-over-btn').click(function(event){ event.preventDefault(); game.restart(); }); @@ -1239,7 +1240,7 @@ }, - _createControls: function () { + _createControls: function() { var game = this; @@ -1252,16 +1253,16 @@ }, - _refreshBlockSizes: function () { + _refreshBlockSizes: function() { - if (this.options.autoBlockWidth) { - this.options.blockWidth = Math.ceil(this.element.width() / this.options.autoBlockSize); + if( this.options.autoBlockWidth ) { + this.options.blockWidth = Math.ceil( this.element.width() / this.options.autoBlockSize ); } }, - _getNiceShapes: function () { + _getNiceShapes: function() { /* * Things I need for this to work... * - ability to test each shape with this._filled data @@ -1271,24 +1272,24 @@ var game = this; var shapes = {}, - attr; + attr; - for (var attr in this._shapeFactory) { + for( var attr in this._shapeFactory ) { shapes[attr] = this._shapeFactory[attr](); } function scoreBlocks(possibles, blocks, x, y, filled, width, height) { - var i, len = blocks.length, score = 0, bottoms = {}, tx, ty, overlaps; + var i, len=blocks.length, score=0, bottoms = {}, tx, ty, overlaps; // base score - for (i = 0; i < len; i += 2) { - score += possibles[game._filled.asIndex(x + blocks[i], y + blocks[i + 1])] || 0; + for (i=0; i best_score_for_shape) { @@ -1368,7 +1369,7 @@ } if ((evil && best_score_for_shape < best_score) || - (!evil && best_score_for_shape > best_score)) { + (!evil && best_score_for_shape > best_score)) { best_shape = shape; best_score = best_score_for_shape; best_orientation = best_orientation_for_shape; @@ -1387,10 +1388,10 @@ }, - _randomShapes: function () { + _randomShapes: function() { // Todo: The shapefuncs should be cached. var shapeFuncs = []; - $.each(this._shapeFactory, function (k, v) { shapeFuncs.push(v); }); + $.each(this._shapeFactory, function(k,v) { shapeFuncs.push(v); }); return this._randChoice(shapeFuncs); }, @@ -1399,55 +1400,55 @@ /** * Controls */ - _setupControls: function (enable) { + _setupControls: function(enable) { var game = this; - var moveLeft = function (start) { - if (!start) { game._board.holding.left = null; return; } - if (!game._board.holding.left) { - game._board.cur.moveLeft(); + var moveLeft = function(start) { + if( ! start ) { game._board.holding.left = null; return; } + if( ! game._board.holding.left ) { + game._board.cur.moveLeft(); game._board.holding.left = Date.now(); - game._board.holding.right = null; + game._board.holding.right = null; } } - var moveRight = function (start) { - if (!start) { game._board.holding.right = null; return; } - if (!game._board.holding.right) { - game._board.cur.moveRight(); - game._board.holding.right = Date.now(); - game._board.holding.left = null; + var moveRight = function(start) { + if( ! start ) { game._board.holding.right = null; return; } + if( ! game._board.holding.right ) { + game._board.cur.moveRight(); + game._board.holding.right = Date.now(); + game._board.holding.left = null; } } - var drop = function (start) { - if (!start) { game._board.holding.drop = null; return; } - if (!game._board.holding.drop) { - game._board.cur.drop(); + var drop = function(start) { + if( ! start ) { game._board.holding.drop = null; return; } + if( ! game._board.holding.drop ) { + game._board.cur.drop(); game._board.holding.drop = Date.now(); } } - var rotateLeft = function () { - game._board.cur.rotate('left'); + var rotateLeft = function() { + game._board.cur.rotate('left'); } - var rotateRight = function () { - game._board.cur.rotate('right'); + var rotateRight = function() { + game._board.cur.rotate('right'); } // Handlers: These are used to be able to bind/unbind controls - var handleKeyDown = function (evt) { - if (!game._board.cur) { return true; } + var handleKeyDown = function(evt) { + if( ! game._board.cur ) { return true; } var caught = false; caught = true; if (game.options.asdwKeys) { - switch (evt.keyCode) { + switch(evt.keyCode) { case 65: /*a*/ moveLeft(true); break; case 68: /*d*/ moveRight(true); break; case 83: /*s*/ drop(true); break; case 87: /*w*/ game._board.cur.rotate('right'); break; } } - switch (evt.keyCode) { + switch(evt.keyCode) { case 37: /*left*/ moveLeft(true); break; case 39: /*right*/ moveRight(true); break; case 40: /*down*/ drop(true); break; @@ -1461,19 +1462,19 @@ }; - var handleKeyUp = function (evt) { - if (!game._board.cur) { return true; } + var handleKeyUp = function(evt) { + if( ! game._board.cur ) { return true; } var caught = false; caught = true; if (game.options.asdwKeys) { - switch (evt.keyCode) { + switch(evt.keyCode) { case 65: /*a*/ moveLeft(false); break; case 68: /*d*/ moveRight(false); break; case 83: /*s*/ drop(false); break; } } - switch (evt.keyCode) { + switch(evt.keyCode) { case 37: /*left*/ moveLeft(false); break; case 39: /*right*/ moveRight(false); break; case 40: /*down*/ drop(false); break; @@ -1485,7 +1486,7 @@ function isStopKey(evt) { var cfg = { - stopKeys: { 37: 1, 38: 1, 39: 1, 40: 1 } + stopKeys: {37:1, 38:1, 39:1, 40:1} }; var isStop = (cfg.stopKeys[evt.keyCode] || (cfg.moreStopKeys && cfg.moreStopKeys[evt.keyCode])); @@ -1509,61 +1510,61 @@ // Unbind everything by default // Use event namespacing so we don't ruin other keypress events - $(document).unbind('keydown.blockrain') - .unbind('keyup.blockrain'); + $(document) .unbind('keydown.blockrain') + .unbind('keyup.blockrain'); - if (!game.options.autoplay) { - if (enable) { - $(document).bind('keydown.blockrain', keydown) - .bind('keyup.blockrain', keyup); + if( ! game.options.autoplay ) { + if( enable ) { + $(document) .bind('keydown.blockrain', keydown) + .bind('keyup.blockrain', keyup); } } }, - _setupTouchControls: function (enable) { + _setupTouchControls: function(enable) { var game = this; // Movements can be held for faster movement - var moveLeft = function (event) { + var moveLeft = function(event){ event.preventDefault(); game._board.cur.moveLeft(); game._board.holding.left = Date.now(); game._board.holding.right = null; game._board.holding.drop = null; }; - var moveRight = function (event) { + var moveRight = function(event){ event.preventDefault(); game._board.cur.moveRight(); game._board.holding.right = Date.now(); game._board.holding.left = null; game._board.holding.drop = null; }; - var drop = function (event) { + var drop = function(event){ event.preventDefault(); game._board.cur.drop(); game._board.holding.drop = Date.now(); }; - var endMoveLeft = function (event) { + var endMoveLeft = function(event){ event.preventDefault(); game._board.holding.left = null; }; - var endMoveRight = function (event) { + var endMoveRight = function(event){ event.preventDefault(); game._board.holding.right = null; }; - var endDrop = function (event) { + var endDrop = function(event){ event.preventDefault(); game._board.holding.drop = null; }; // Rotations can't be held - var rotateLeft = function (event) { + var rotateLeft = function(event){ event.preventDefault(); game._board.cur.rotate('left'); }; - var rotateRight = function (event) { + var rotateRight = function(event){ event.preventDefault(); game._board.cur.rotate('right'); }; @@ -1575,7 +1576,7 @@ game._$touchRotateRight.unbind('touchstart touchend click'); game._$touchDrop.unbind('touchstart touchend click'); - if (!game.options.autoplay && enable) { + if( ! game.options.autoplay && enable ) { game._$touchLeft.show().bind('touchstart click', moveLeft).bind('touchend', endMoveLeft); game._$touchRight.show().bind('touchstart click', moveRight).bind('touchend', endMoveRight); game._$touchDrop.show().bind('touchstart click', drop).bind('touchend', endDrop); From 8a082af851a20a69c4df4749e8c43450d7ae29bd Mon Sep 17 00:00:00 2001 From: Micael Robles Date: Wed, 12 Jul 2017 17:44:41 -0300 Subject: [PATCH 04/10] works on different block widths --- src/blockrain.jquery.src.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/blockrain.jquery.src.js b/src/blockrain.jquery.src.js index b2b8ddb..ecb2c87 100644 --- a/src/blockrain.jquery.src.js +++ b/src/blockrain.jquery.src.js @@ -9,7 +9,7 @@ autoplayRestart: true, // Restart the game automatically once a bot loses showFieldOnStart: true, // Show a bunch of random blocks on the start screen (it looks nice) theme: null, // The theme name or a theme object - blockWidth: 10, // How many blocks wide the field is (The standard is 10 blocks) + blockWidth: 12, // How many blocks wide the field is (The standard is 10 blocks) autoBlockWidth: false, // The blockWidth is dinamically calculated based on the autoBlockSize. Disabled blockWidth. Useful for responsive backgrounds autoBlockSize: 24, // The max size of a block for autowidth mode difficulty: 'normal', // Difficulty (normal|nice|evil). @@ -442,7 +442,8 @@ game._board.renderChanged = true; } else { this.orientation = orientation; - while (this.x >= 8){ + + while ( this.x >= ( game._BLOCK_WIDTH - 2 )){ this.x--; } while (this.x < 0){ From c3f953da42d29c414aa6002feb8f164192a09234 Mon Sep 17 00:00:00 2001 From: Micael Robles Date: Sun, 6 Aug 2017 17:41:44 -0300 Subject: [PATCH 05/10] solo sube 1 bloque cuando choca en los costados --- src/blockrain.jquery.src.js | 2902 ++++++++++++++++++----------------- 1 file changed, 1481 insertions(+), 1421 deletions(-) diff --git a/src/blockrain.jquery.src.js b/src/blockrain.jquery.src.js index ecb2c87..80035d0 100644 --- a/src/blockrain.jquery.src.js +++ b/src/blockrain.jquery.src.js @@ -1,1598 +1,1658 @@ -((function ( $ ) { - - "use strict"; - - $.widget('aerolab.blockrain', { - - options: { - autoplay: false, // Let a bot play the game - autoplayRestart: true, // Restart the game automatically once a bot loses - showFieldOnStart: true, // Show a bunch of random blocks on the start screen (it looks nice) - theme: null, // The theme name or a theme object - blockWidth: 12, // How many blocks wide the field is (The standard is 10 blocks) - autoBlockWidth: false, // The blockWidth is dinamically calculated based on the autoBlockSize. Disabled blockWidth. Useful for responsive backgrounds - autoBlockSize: 24, // The max size of a block for autowidth mode - difficulty: 'normal', // Difficulty (normal|nice|evil). - speed: 20, // The speed of the game. The higher, the faster the pieces go. - asdwKeys: true, // Enable ASDW keys - - // Copy - playText: 'Let\'s play some Tetris', - playButtonText: 'Play', - gameOverText: 'Game Over', - restartButtonText: 'Play Again', - scoreText: 'Score', - - // Basic Callbacks - onStart: function(){}, - onRestart: function(){}, - onGameOver: function(score){}, - - // When a block is placed - onPlaced: function(){}, - // When a line is made. Returns the number of lines, score assigned and total score - onLine: function(lines, scoreIncrement, score){} - }, - - - /** - * Start/Restart Game - */ - start: function() { - this._doStart(); - this.options.onStart.call(this.element); - }, - - restart: function() { - this._doStart(); - this.options.onRestart.call(this.element); - }, - - gameover: function() { - this.showGameOverMessage(); - this._board.gameover = true; - this.options.onGameOver.call(this.element, this._filled.score); - }, - - _doStart: function() { - this._filled.clearAll(); - this._filled._resetScore(); - this._board.cur = this._board.nextShape(); - this._board.started = true; - this._board.gameover = false; - this._board.dropDelay = 5; - this._board.render(true); - this._board.animate(); - - this._$start.fadeOut(150); - this._$gameover.fadeOut(150); - this._$score.fadeIn(150); - }, - - - pause: function() { - this._board.paused = true; - }, - - resume: function() { - this._board.paused = false; - }, - - autoplay: function(enable) { - if( typeof enable !== 'boolean' ){ enable = true; } - - // On autoplay, start the game right away - this.options.autoplay = enable; - if( enable && ! this._board.started ) { - this._doStart(); - } - this._setupControls( ! enable ); - this._setupTouchControls( ! enable ); - }, - - controls: function(enable) { - if( typeof enable !== 'boolean' ){ enable = true; } - this._setupControls(enable); - }, - - touchControls: function(enable) { - if( typeof enable !== 'boolean' ){ enable = true; } - this._setupTouchControls(enable); - }, - - score: function(newScore) { - if( typeof newScore !== 'undefined' && parseInt(newScore) >= 0 ) { - this._filled.score = parseInt(newScore); - this._$scoreText.text(this._filled_score); - } - return this._filled.score; - }, - - freesquares: function() { - return this._filled.getFreeSpaces(); - }, - - showStartMessage: function() { - this._$start.show(); - }, - - showGameOverMessage: function() { - this._$gameover.show(); - }, - - /** - * Update the sizes of the renderer (this makes the game responsive) - */ - updateSizes: function() { - - this._PIXEL_WIDTH = this.element.innerWidth(); - this._PIXEL_HEIGHT = this.element.innerHeight(); - - this._BLOCK_WIDTH = this.options.blockWidth; - this._BLOCK_HEIGHT = Math.floor(this.element.innerHeight() / this.element.innerWidth() * this._BLOCK_WIDTH); - - this._block_size = Math.floor(this._PIXEL_WIDTH / this._BLOCK_WIDTH); - this._border_width = 2; - - // Recalculate the pixel width and height so the canvas always has the best possible size - this._PIXEL_WIDTH = this._block_size * this._BLOCK_WIDTH; - this._PIXEL_HEIGHT = this._block_size * this._BLOCK_HEIGHT; - - this._$canvas .attr('width', this._PIXEL_WIDTH) - .attr('height', this._PIXEL_HEIGHT); - }, - - - theme: function(newTheme){ - - if( typeof newTheme === 'undefined' ) { - return this.options.theme || this._theme; - } - - // Setup the theme properly - if( typeof newTheme === 'string' ) { - this.options.theme = newTheme; - this._theme = $.extend(true, {}, BlockrainThemes[newTheme]); - } - else { - this.options.theme = null; - this._theme = newTheme; - } - - if( typeof this._theme === 'undefined' || this._theme === null ) { - this._theme = $.extend(true, {}, BlockrainThemes['retro']); - this.options.theme = 'retro'; - } - - if( isNaN(parseInt(this._theme.strokeWidth)) || typeof parseInt(this._theme.strokeWidth) !== 'number' ) { - this._theme.strokeWidth = 2; - } - - // Load the image assets - this._preloadThemeAssets(); - - if( this._board !== null ) { - if( typeof this._theme.background === 'string' ) { - this._$canvas.css('background-color', this._theme.background); - } - this._board.render(); - } - }, - - - // Theme - _theme: { - - }, - - - // UI Elements - _$game: null, - _$canvas: null, - _$gameholder: null, - _$start: null, - _$gameover: null, - _$score: null, - _$scoreText: null, - - - // Canvas - _canvas: null, - _ctx: null, - - - // Initialization - _create: function() { - - var game = this; - - this.theme(this.options.theme); - - this._createHolder(); - this._createUI(); - - this._refreshBlockSizes(); - - this.updateSizes(); - - $(window).resize(function(){ - //game.updateSizes(); - }); +((function($) { + + "use strict"; + + $.widget('aerolab.blockrain', { + + options: { + autoplay: false, // Let a bot play the game + autoplayRestart: true, // Restart the game automatically once a bot loses + showFieldOnStart: true, // Show a bunch of random blocks on the start screen (it looks nice) + theme: null, // The theme name or a theme object + blockWidth: 10, // How many blocks wide the field is (The standard is 10 blocks) + autoBlockWidth: false, // The blockWidth is dinamically calculated based on the autoBlockSize. Disabled blockWidth. Useful for responsive backgrounds + autoBlockSize: 24, // The max size of a block for autowidth mode + difficulty: 'normal', // Difficulty (normal|nice|evil). + speed: 20, // The speed of the game. The higher, the faster the pieces go. + asdwKeys: true, // Enable ASDW keys + + // Copy + playText: 'Let\'s play some Tetris', + playButtonText: 'Play', + gameOverText: 'Game Over', + restartButtonText: 'Play Again', + scoreText: 'Score', + + // Basic Callbacks + onStart: function() {}, + onRestart: function() {}, + onGameOver: function(score) {}, + + // When a block is placed + onPlaced: function() {}, + // When a line is made. Returns the number of lines, score assigned and total score + onLine: function(lines, scoreIncrement, score) {} + }, - this._SetupShapeFactory(); - this._SetupFilled(); - this._SetupInfo(); - this._SetupBoard(); - this._info.init(); - this._board.init(); + /** + * Start/Restart Game + */ + start: function() { + this._doStart(); + this.options.onStart.call(this.element); + }, - var renderLoop = function(){ - requestAnimationFrame(renderLoop); - game._board.render(); - }; - renderLoop(); + restart: function() { + this._doStart(); + this.options.onRestart.call(this.element); + }, - if( this.options.autoplay ) { - this.autoplay(true); - this._setupTouchControls(false); - } else { - this._setupControls(true); - this._setupTouchControls(false); - } + gameover: function() { + this.showGameOverMessage(); + this._board.gameover = true; + this.options.onGameOver.call(this.element, this._filled.score); + }, - }, + _doStart: function() { + this._filled.clearAll(); + this._filled._resetScore(); + this._board.cur = this._board.nextShape(); + this._board.started = true; + this._board.gameover = false; + this._board.dropDelay = 5; + this._board.render(true); + this._board.animate(); + + this._$start.fadeOut(150); + this._$gameover.fadeOut(150); + this._$score.fadeIn(150); + }, - _checkCollisions: function(x, y, blocks, checkDownOnly) { - // x & y should be aspirational values - var i = 0, len = blocks.length, a, b; - for (; i= this._BLOCK_HEIGHT || this._filled.check(a, b)) { - return true; - } else if (!checkDownOnly && a < 0 || a >= this._BLOCK_WIDTH) { - return true; - } - } - return false; - }, + pause: function() { + this._board.paused = true; + }, + resume: function() { + this._board.paused = false; + }, - _board: null, - _info: null, - _filled: null, + autoplay: function(enable) { + if (typeof enable !== 'boolean') { enable = true; } + // On autoplay, start the game right away + this.options.autoplay = enable; + if (enable && !this._board.started) { + this._doStart(); + } + this._setupControls(!enable); + this._setupTouchControls(!enable); + }, - /** - * Draws the background - */ - _drawBackground: function() { + controls: function(enable) { + if (typeof enable !== 'boolean') { enable = true; } + this._setupControls(enable); + }, - if( typeof this._theme.background !== 'string' ) { - return; - } + touchControls: function(enable) { + if (typeof enable !== 'boolean') { enable = true; } + this._setupTouchControls(enable); + }, - if( this._theme.backgroundGrid instanceof Image ) { + score: function(newScore) { + if (typeof newScore !== 'undefined' && parseInt(newScore) >= 0) { + this._filled.score = parseInt(newScore); + this._$scoreText.text(this._filled_score); + } + return this._filled.score; + }, - // Not loaded - if( this._theme.backgroundGrid.width === 0 || this._theme.backgroundGrid.height === 0 ){ return; } + freesquares: function() { + return this._filled.getFreeSpaces(); + }, - this._ctx.globalAlpha = 1.0; + showStartMessage: function() { + this._$start.show(); + }, - for( var x=0; x= ( game._BLOCK_WIDTH - 2 )){ - this.x--; - } - while (this.x < 0){ - this.x++; - } - if (this.blockType === "line" && this.x === 0) this.x++ - - //If there is vertical collision after rotation, piece will go up as much as needed. - - if (game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { - for(let i = this.y; i > 0; i--) { - if (game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { - this.y = i--; - } - } - } - game._board.renderChanged = true; + this.options.theme = null; + this._theme = newTheme; } - }, - moveRight: function() { - if (!game._checkCollisions(this.x + 1, this.y, this.getBlocks())) { - this.x++; - game._board.renderChanged = true; - } - }, - moveLeft: function() { - if (!game._checkCollisions(this.x - 1, this.y, this.getBlocks())) { - this.x--; - game._board.renderChanged = true; + if (typeof this._theme === 'undefined' || this._theme === null) { + this._theme = $.extend(true, {}, BlockrainThemes['retro']); + this.options.theme = 'retro'; } - }, - drop: function() { - if (!game._checkCollisions(this.x, this.y + 1, this.getBlocks())) { - this.y++; - // Reset the drop count, as we dropped the block sooner - game._board.dropCount = -1; - game._board.animate(); - game._board.renderChanged = true; - } - }, - - getBlocks: function(orientation) { // optional param - return this.orientations[orientation !== undefined ? orientation : this.orientation]; - }, - draw: function(_x, _y, _orientation) { - var blocks = this.getBlocks(_orientation), - x = _x === undefined ? this.x : _x, - y = _y === undefined ? this.y : _y, - i = 0, - index = 0; - - for (; i maxx) { maxx = blocks[i]; } - if (blocks[i+1] < miny) { miny = blocks[i+1]; } - if (blocks[i+1] > maxy) { maxy = blocks[i+1]; } + + if (isNaN(parseInt(this._theme.strokeWidth)) || typeof parseInt(this._theme.strokeWidth) !== 'number') { + this._theme.strokeWidth = 2; } - return { - left: minx, - right: maxx, - top: miny, - bottom: maxy, - width: maxx - minx, - height: maxy - miny - }; - } - }); - return this.init(); - }; + // Load the image assets + this._preloadThemeAssets(); - this._shapeFactory = { - line: function() { - return new Shape(game, game._shapes.line, false, 'line'); - }, - square: function() { - return new Shape(game, game._shapes.square, false, 'square'); - }, - arrow: function() { - return new Shape(game, game._shapes.arrow, false, 'arrow'); - }, - leftHook: function() { - return new Shape(game, game._shapes.leftHook, false, 'leftHook'); - }, - rightHook: function() { - return new Shape(game, game._shapes.rightHook, false, 'rightHook'); - }, - leftZag: function() { - return new Shape(game, game._shapes.leftZag, false, 'leftZag'); + if (this._board !== null) { + if (typeof this._theme.background === 'string') { + this._$canvas.css('background-color', this._theme.background); + } + this._board.render(); + } }, - rightZag: function() { - return new Shape(game, game._shapes.rightZag, false, 'rightZag'); - } - }; - }, - - - _SetupFilled: function() { - var game = this; - if( this._filled !== null ){ return; } - this._filled = { - data: new Array(game._BLOCK_WIDTH * game._BLOCK_HEIGHT), - score: 0, - toClear: {}, - check: function(x, y) { - return this.data[this.asIndex(x, y)]; - }, - add: function(x, y, blockType, blockVariation, blockIndex, blockOrientation) { - if (x >= 0 && x < game._BLOCK_WIDTH && y >= 0 && y < game._BLOCK_HEIGHT) { - this.data[this.asIndex(x, y)] = { - blockType: blockType, - blockVariation: blockVariation, - blockIndex: blockIndex, - blockOrientation: blockOrientation - }; - } - }, - getFreeSpaces: function() { - var count = 0; - for( var i=0; i=0; i--) { - this.data[i] = (i >= game._BLOCK_WIDTH ? this.data[i-game._BLOCK_WIDTH] : undefined); - } - }, - checkForClears: function() { - var startLines = game._board.lines; - var rows = [], i, len, count, mod; - - for (i=0, len=this.data.length; i 1 ) { - game._board.dropDelay *= 0.9; - } - } + // Theme + _theme: { - var clearedLines = game._board.lines - startLines; - this._updateScore(clearedLines); }, - _updateScore: function(numLines) { - if( numLines <= 0 ) { return; } - var scores = [0,400,1000,3000,12000]; - if( numLines >= scores.length ){ numLines = scores.length-1 } - this.score += scores[numLines]; - game._$scoreText.text(this.score); - - game.options.onLine.call(game.element, numLines, scores[numLines], this.score); - }, - _resetScore: function() { - this.score = 0; - game._$scoreText.text(this.score); - }, - draw: function() { - for (var i=0, len=this.data.length, row, color; i= this._BLOCK_HEIGHT || this._filled.check(a, b)) { + return true; + } else if (!checkDownOnly && a < 0 || a >= this._BLOCK_WIDTH) { + return true; + } } - } - - return result; + return false; }, - animate: function() { - var drop = false, - moved = false, - gameOver = false, - now = Date.now(); - if( this.animateTimeoutId ){ clearTimeout(this.animateTimeoutId); } + _board: null, + _info: null, + _filled: null, - //game.updateSizes(); - if( !this.paused && !this.gameover ) { + /** + * Draws the background + */ + _drawBackground: function() { - this.dropCount++; - - // Drop by delay or holding - if( (this.dropCount >= this.dropDelay) || - (game.options.autoplay) || - (this.holding.drop && (now - this.holding.drop) >= this.holdingThreshold) ) { - drop = true; - moved = true; - this.dropCount = 0; + if (typeof this._theme.background !== 'string') { + return; } - // Move Left by holding - if( this.holding.left && (now - this.holding.left) >= this.holdingThreshold ) { - moved = true; - this.cur.moveLeft(); - } + if (this._theme.backgroundGrid instanceof Image) { - // Move Right by holding - if( this.holding.right && (now - this.holding.right) >= this.holdingThreshold ) { - moved = true; - this.cur.moveRight(); - } + // Not loaded + if (this._theme.backgroundGrid.width === 0 || this._theme.backgroundGrid.height === 0) { return; } - // Test for a collision, add the piece to the filled blocks and fetch the next one - if (drop) { - var cur = this.cur, x = cur.x, y = cur.y, blocks = cur.getBlocks(); - if (game._checkCollisions(x, y+1, blocks, true)) { - drop = false; - var blockIndex = 0; - for (var i=0; i= (game._BLOCK_WIDTH - 2)) { + this.x--; + } + while (this.x < 0) { + this.x++; + } + + if (this.blockType === "line" && this.x === 0) this.x++ + + if (game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { + this.y--; + if (game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { + this.x = ogX; + this.y = ogY; + this.orientation = ogOrientation; + } + } + game._board.renderChanged = true; + } + }, + + moveRight: function() { + if (!game._checkCollisions(this.x + 1, this.y, this.getBlocks())) { + this.x++; + game._board.renderChanged = true; + } + }, + moveLeft: function() { + if (!game._checkCollisions(this.x - 1, this.y, this.getBlocks())) { + this.x--; + game._board.renderChanged = true; + } + }, + drop: function() { + if (!game._checkCollisions(this.x, this.y + 1, this.getBlocks())) { + this.y++; + // Reset the drop count, as we dropped the block sooner + game._board.dropCount = -1; + game._board.animate(); + game._board.renderChanged = true; + } + }, + + getBlocks: function(orientation) { // optional param + return this.orientations[orientation !== undefined ? orientation : this.orientation]; + }, + draw: function(_x, _y, _orientation) { + var blocks = this.getBlocks(_orientation), + x = _x === undefined ? this.x : _x, + y = _y === undefined ? this.y : _y, + i = 0, + index = 0; + + for (; i < this.blocksLen; i += 2) { + game._board.drawBlock(x + blocks[i], y + blocks[i + 1], this.blockType, this.blockVariation, index, this.orientation, true); + index++; + } + }, + getBounds: function(_blocks) { // _blocks can be an array of blocks, an orientation index, or undefined + var blocks = $.isArray(_blocks) ? _blocks : this.getBlocks(_blocks), + i = 0, + len = blocks.length, + minx = 999, + maxx = -999, + miny = 999, + maxy = -999; + for (; i < len; i += 2) { + if (blocks[i] < minx) { minx = blocks[i]; } + if (blocks[i] > maxx) { maxx = blocks[i]; } + if (blocks[i + 1] < miny) { miny = blocks[i + 1]; } + if (blocks[i + 1] > maxy) { maxy = blocks[i + 1]; } + } + return { + left: minx, + right: maxx, + top: miny, + bottom: maxy, + width: maxx - minx, + height: maxy - miny + }; + } + }); + + return this.init(); + }; + this._shapeFactory = { + line: function() { + return new Shape(game, game._shapes.line, false, 'line'); + }, + square: function() { + return new Shape(game, game._shapes.square, false, 'square'); + }, + arrow: function() { + return new Shape(game, game._shapes.arrow, false, 'arrow'); + }, + leftHook: function() { + return new Shape(game, game._shapes.leftHook, false, 'leftHook'); + }, + rightHook: function() { + return new Shape(game, game._shapes.rightHook, false, 'rightHook'); + }, + leftZag: function() { + return new Shape(game, game._shapes.leftZag, false, 'leftZag'); + }, + rightZag: function() { + return new Shape(game, game._shapes.rightZag, false, 'rightZag'); + } + }; }, - createRandomBoard: function() { - var start = [], blockTypes = [], i, ilen, j, jlen, blockType; + _SetupFilled: function() { + var game = this; + if (this._filled !== null) { return; } + + this._filled = { + data: new Array(game._BLOCK_WIDTH * game._BLOCK_HEIGHT), + score: 0, + toClear: {}, + check: function(x, y) { + return this.data[this.asIndex(x, y)]; + }, + add: function(x, y, blockType, blockVariation, blockIndex, blockOrientation) { + if (x >= 0 && x < game._BLOCK_WIDTH && y >= 0 && y < game._BLOCK_HEIGHT) { + this.data[this.asIndex(x, y)] = { + blockType: blockType, + blockVariation: blockVariation, + blockIndex: blockIndex, + blockOrientation: blockOrientation + }; + } + }, + getFreeSpaces: function() { + var count = 0; + for (var i = 0; i < this.data.length; i++) { + count += (this.data[i] ? 1 : 0); + } + }, + asIndex: function(x, y) { + return x + y * game._BLOCK_WIDTH; + }, + asX: function(index) { + return index % game._BLOCK_WIDTH; + }, + asY: function(index) { + return Math.floor(index / game._BLOCK_WIDTH); + }, + clearAll: function() { + delete this.data; + this.data = new Array(game._BLOCK_WIDTH * game._BLOCK_HEIGHT); + }, + _popRow: function(row_to_pop) { + for (var i = game._BLOCK_WIDTH * (row_to_pop + 1) - 1; i >= 0; i--) { + this.data[i] = (i >= game._BLOCK_WIDTH ? this.data[i - game._BLOCK_WIDTH] : undefined); + } + }, + checkForClears: function() { + var startLines = game._board.lines; + var rows = [], + i, len, count, mod; + + for (i = 0, len = this.data.length; i < len; i++) { + mod = this.asX(i); + if (mod == 0) count = 0; + if (this.data[i] && typeof this.data[i] !== 'undefined' && typeof this.data[i].blockType === 'string') { + count += 1; + } + if (mod == game._BLOCK_WIDTH - 1 && count == game._BLOCK_WIDTH) { + rows.push(this.asY(i)); + } + } + + for (i = 0, len = rows.length; i < len; i++) { + this._popRow(rows[i]); + game._board.lines++; + if (game._board.lines % 10 == 0 && game._board.dropDelay > 1) { + game._board.dropDelay *= 0.9; + } + } + + var clearedLines = game._board.lines - startLines; + this._updateScore(clearedLines); + }, + _updateScore: function(numLines) { + if (numLines <= 0) { return; } + var scores = [0, 400, 1000, 3000, 12000]; + if (numLines >= scores.length) { numLines = scores.length - 1 } + + this.score += scores[numLines]; + game._$scoreText.text(this.score); + + game.options.onLine.call(game.element, numLines, scores[numLines], this.score); + }, + _resetScore: function() { + this.score = 0; + game._$scoreText.text(this.score); + }, + draw: function() { + for (var i = 0, len = this.data.length, row, color; i < len; i++) { + if (this.data[i] !== undefined) { + row = this.asY(i); + var block = this.data[i]; + game._board.drawBlock(this.asX(i), row, block.blockType, block.blockVariation, block.blockIndex, block.blockOrientation); + } + } + } + }; + }, - // Draw a random blockrain screen - blockTypes = Object.keys(game._shapeFactory); - for (i=0, ilen=game._BLOCK_WIDTH; i= this.dropDelay) || + (game.options.autoplay) || + (this.holding.drop && (now - this.holding.drop) >= this.holdingThreshold)) { + drop = true; + moved = true; + this.dropCount = 0; + } + + // Move Left by holding + if (this.holding.left && (now - this.holding.left) >= this.holdingThreshold) { + moved = true; + this.cur.moveLeft(); + } + + // Move Right by holding + if (this.holding.right && (now - this.holding.right) >= this.holdingThreshold) { + moved = true; + this.cur.moveRight(); + } + + // Test for a collision, add the piece to the filled blocks and fetch the next one + if (drop) { + var cur = this.cur, + x = cur.x, + y = cur.y, + blocks = cur.getBlocks(); + if (game._checkCollisions(x, y + 1, blocks, true)) { + drop = false; + var blockIndex = 0; + for (var i = 0; i < cur.blocksLen; i += 2) { + game._filled.add(x + blocks[i], y + blocks[i + 1], cur.blockType, cur.blockVariation, blockIndex, cur.orientation); + if (y + blocks[i] < 0) { + gameOver = true; + } + blockIndex++; + } + game._filled.checkForClears(); + this.cur = this.nextShape(); + this.renderChanged = true; + + // Stop holding drop (and any other buttons). Just in case the controls get sticky. + this.holding.left = null; + this.holding.right = null; + this.holding.drop = null; + + game.options.onPlaced.call(game.element); + } + } + } + + // Drop + if (drop) { + moved = true; + this.cur.y++; + } + + if (drop || moved) { + this.renderChanged = true; + } + + if (gameOver) { + + this.gameover = true; + + game.gameover(); + + if (game.options.autoplay && game.options.autoplayRestart) { + // On autoplay, restart the game automatically + game.restart(); + } + this.renderChanged = true; + + } else { + + // Update the speed + this.animateDelay = 1000 / game.options.speed; + + this.animateTimeoutId = window.setTimeout(function() { + game._board.animate(); + }, this.animateDelay); + + } + + }, + + createRandomBoard: function() { + + var start = [], + blockTypes = [], + i, ilen, j, jlen, blockType; + + // Draw a random blockrain screen + blockTypes = Object.keys(game._shapeFactory); + + for (i = 0, ilen = game._BLOCK_WIDTH; i < ilen; i++) { + for (j = 0, jlen = game._randChoice([game._randInt(0, 8), game._randInt(5, 9)]); j < jlen; j++) { + if (!blockType || !game._randInt(0, 3)) blockType = game._randChoice(blockTypes); + + // Use a random piece and orientation + // Todo: Use an actual random variation + game._filled.add(i, game._BLOCK_HEIGHT - j, blockType, game._randInt(0, 3), null, game._randInt(0, 3)); + } + } + + /* + for (i=0, ilen=WIDTH; i 0) { + return blockTheme[0]; + } else { + return null; + } + } else { + return blockTheme; + } + } + + if (typeof falling !== 'boolean') { falling = true; } + if (falling) { + if (typeof game._theme.primary === 'string' && game._theme.primary !== '') { + return game._theme.primary; + } else if (typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null) { + return getBlockVariation(game._theme.blocks[blockType], blockVariation); + } else { + return getBlockVariation(game._theme.complexBlocks[blockType], blockVariation); + } + } else { + if (typeof game._theme.secondary === 'string' && game._theme.secondary !== '') { + return game._theme.secondary; + } else if (typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null) { + return getBlockVariation(game._theme.blocks[blockType], blockVariation); + } else { + return getBlockVariation(game._theme.complexBlocks[blockType], blockVariation); + } + } + } - /** - * Draws one block (Each piece is made of 4 blocks) - * The blockType is used to draw any block. - * The falling attribute is needed to apply different styles for falling and placed blocks. - */ - drawBlock: function(x, y, blockType, blockVariation, blockIndex, blockRotation, falling) { + }; - // convert x and y to pixel - x = x * game._block_size; - y = y * game._block_size; + game._niceShapes = game._getNiceShapes(); + }, - falling = typeof falling === 'boolean' ? falling : false; - var borderWidth = game._theme.strokeWidth; - var borderDistance = Math.round(game._block_size*0.23); - var squareDistance = Math.round(game._block_size*0.30); + // Utility Functions + _randInt: function(a, b) { return a + Math.floor(Math.random() * (1 + b - a)); }, + _randSign: function() { return this._randInt(0, 1) * 2 - 1; }, + _randChoice: function(choices) { return choices[this._randInt(0, choices.length - 1)]; }, - var color = this.getBlockColor(blockType, blockVariation, blockIndex, falling); - // Draw the main square - game._ctx.globalAlpha = 1.0; + /** + * Find base64 encoded images and load them as image objects, which can be used by the canvas renderer + */ + _preloadThemeAssets: function() { - // If it's an image, the block has a specific texture. Use that. - if( color instanceof Image ) { - game._ctx.globalAlpha = 1.0; + var game = this; - // Not loaded - if( color.width === 0 || color.height === 0 ){ return; } + var hexColorcheck = new RegExp('^#[A-F0-9+]{3,6}', 'i'); + var base64check = new RegExp('^data:image/(png|gif|jpg);base64,', 'i'); - // A square is the same style for all blocks - if( typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null ) { - game._ctx.drawImage(color, 0, 0, color.width, color.height, x, y, game._block_size, game._block_size); - } - // A custom texture - else if( typeof game._theme.complexBlocks !== 'undefined' && game._theme.complexBlocks !== null ) { - if( typeof blockIndex === 'undefined' || blockIndex === null ){ blockIndex = 0; } - - var getCustomBlockImageCoordinates = function(image, blockType, blockIndex) { - // The image is based on the first ("upright") orientation - var positions = game._shapes[blockType][0]; - // Find the number of tiles it should have - var minX = Math.min(positions[0], positions[2], positions[4], positions[6]); - var maxX = Math.max(positions[0], positions[2], positions[4], positions[6]); - var minY = Math.min(positions[1], positions[3], positions[5], positions[7]); - var maxY = Math.max(positions[1], positions[3], positions[5], positions[7]); - var rangeX = maxX - minX + 1; - var rangeY = maxY - minY + 1; - - // X and Y sizes should match. Should. - var tileSizeX = image.width / rangeX; - var tileSizeY = image.height / rangeY; - - return { - x: tileSizeX * (positions[blockIndex*2]-minX), - y: tileSizeY * Math.abs(minY-positions[blockIndex*2+1]), - w: tileSizeX, - h: tileSizeY - }; - }; + var handleAssetLoad = function() { + // Rerender the board as soon as an asset loads + if (game._board) { + game._board.render(true); + } + }; - var coords = getCustomBlockImageCoordinates(color, blockType, blockIndex); + var loadAsset = function(src) { + var plainSrc = src; + if (!hexColorcheck.test(plainSrc)) { + // It's an image + src = new Image(); + src.src = plainSrc; + src.onload = handleAssetLoad; + } else { + // It's a color + src = plainSrc; + } + return src; + }; - game._ctx.save(); + var startAssetLoad = function(block) { + // Assets can be an array of variation so they can change color/design randomly + if ($.isArray(block) && block.length > 0) { + for (var i = 0; i < block.length; i++) { + block[i] = loadAsset(block[i]); + } + } else if (typeof block === 'string') { + block = loadAsset(block); + } + return block; + }; - game._ctx.translate(x, y); - game._ctx.translate(game._block_size/2, game._block_size/2); - game._ctx.rotate(-Math.PI/2 * blockRotation); - game._ctx.drawImage(color, coords.x, coords.y, coords.w, coords.h, - -game._block_size/2, -game._block_size/2, game._block_size, game._block_size); - - game._ctx.restore(); - } else { - // ERROR - game._ctx.fillStyle = '#ff0000'; - game._ctx.fillRect(x, y, game._block_size, game._block_size); - } - } - else if( typeof color === 'string' ) - { - game._ctx.fillStyle = color; - game._ctx.fillRect(x, y, game._block_size, game._block_size); - - // Inner Shadow - if( typeof game._theme.innerShadow === 'string' ) { - game._ctx.globalAlpha = 1.0; - game._ctx.strokeStyle = game._theme.innerShadow; - game._ctx.lineWidth = 1.0; - - // Draw the borders - game._ctx.strokeRect(x+1, y+1, game._block_size-2, game._block_size-2); - } + if (typeof this._theme.complexBlocks !== 'undefined') { + var keys = Object.keys(this._theme.complexBlocks); - // Decoration (borders) - if( typeof game._theme.stroke === 'string' ) { - game._ctx.globalAlpha = 1.0; - game._ctx.fillStyle = game._theme.stroke; - game._ctx.strokeStyle = game._theme.stroke; - game._ctx.lineWidth = borderWidth; + // Load the complexBlocks + for (var i = 0; i < keys.length; i++) { + this._theme.complexBlocks[keys[i]] = startAssetLoad(this._theme.complexBlocks[keys[i]]); + } + } else if (typeof this._theme.blocks !== 'undefined') { + var keys = Object.keys(this._theme.blocks); - // Draw the borders - game._ctx.strokeRect(x, y, game._block_size, game._block_size); - } - if( typeof game._theme.innerStroke === 'string' ) { - // Draw the inner dashes - game._ctx.fillStyle = game._theme.innerStroke; - game._ctx.fillRect(x+borderDistance, y+borderDistance, game._block_size-borderDistance*2, borderWidth); - // The rects shouldn't overlap, to prevent issues with transparency - game._ctx.fillRect(x+borderDistance, y+borderDistance+borderWidth, borderWidth, game._block_size-borderDistance*2-borderWidth); + // Load the blocks + for (var i = 0; i < keys.length; i++) { + this._theme.blocks[keys[i]] = startAssetLoad(this._theme.blocks[keys[i]]); + } } - if( typeof game._theme.innerSquare === 'string' ) { - // Draw the inner square - game._ctx.fillStyle = game._theme.innerSquare; - game._ctx.globalAlpha = 0.2; - game._ctx.fillRect(x+squareDistance, y+squareDistance, game._block_size-squareDistance*2, game._block_size-squareDistance*2); + + // Load the bg + if (typeof this._theme.backgroundGrid !== 'undefined') { + if (typeof this._theme.backgroundGrid === 'string') { + if (!hexColorcheck.test(this._theme.backgroundGrid)) { + var src = this._theme.backgroundGrid; + this._theme.backgroundGrid = new Image(); + this._theme.backgroundGrid.src = src; + this._theme.backgroundGrid.onload = handleAssetLoad; + } + } } - } - // Return the alpha back to 1.0 so we don't create any issues with other drawings. - game._ctx.globalAlpha = 1.0; }, - getBlockColor: function(blockType, blockVariation, blockIndex, falling) { - /** - * The theme allows us to do many things: - * - Use a specific color for the falling block (primary), regardless of the proper color. - * - Use another color for the placed blocks (secondary). - * - Default to the "original" block color in any of those cases by setting primary and/or secondary to null. - * - With primary and secondary as null, all blocks keep their original colors. - */ - - var getBlockVariation = function(blockTheme, blockVariation) { - if( $.isArray(blockTheme) ) { - if( blockVariation !== null && typeof blockTheme[blockVariation] !== 'undefined' ) { - return blockTheme[blockVariation]; - } - else if(blockTheme.length > 0) { - return blockTheme[0]; - } else { - return null; - } - } else { - return blockTheme; - } - } - - if( typeof falling !== 'boolean' ){ falling = true; } - if( falling ) { - if( typeof game._theme.primary === 'string' && game._theme.primary !== '' ) { - return game._theme.primary; - } else if( typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null ) { - return getBlockVariation(game._theme.blocks[blockType], blockVariation); - } else { - return getBlockVariation(game._theme.complexBlocks[blockType], blockVariation); - } - } else { - if( typeof game._theme.secondary === 'string' && game._theme.secondary !== '' ) { - return game._theme.secondary; - } else if( typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null ) { - return getBlockVariation(game._theme.blocks[blockType], blockVariation); - } else { - return getBlockVariation(game._theme.complexBlocks[blockType], blockVariation); - } - } - } + _createHolder: function() { - }; + // Create the main holder (it holds all the ui elements, the original element is just the wrapper) + this._$gameholder = $('
'); + this._$gameholder.css('position', 'relative').css('width', '100%').css('height', '100%'); - game._niceShapes = game._getNiceShapes(); - }, + this.element.html('').append(this._$gameholder); - // Utility Functions - _randInt: function(a, b) { return a + Math.floor(Math.random() * (1 + b - a)); }, - _randSign: function() { return this._randInt(0, 1) * 2 - 1; }, - _randChoice: function(choices) { return choices[this._randInt(0, choices.length-1)]; }, + // Create the game canvas and context + this._$canvas = $(''); + if (typeof this._theme.background === 'string') { + this._$canvas.css('background-color', this._theme.background); + } + this._$gameholder.append(this._$canvas); + this._canvas = this._$canvas.get(0); + this._ctx = this._canvas.getContext('2d'); - /** - * Find base64 encoded images and load them as image objects, which can be used by the canvas renderer - */ - _preloadThemeAssets: function() { + }, - var game = this; - var hexColorcheck = new RegExp('^#[A-F0-9+]{3,6}', 'i'); - var base64check = new RegExp('^data:image/(png|gif|jpg);base64,', 'i'); + _createUI: function() { + + var game = this; + + // Score + game._$score = $( + '
' + + '
' + + '
' + this.options.scoreText + '
' + + '
0
' + + '
' + + '
').hide(); + game._$scoreText = game._$score.find('.blockrain-score-num'); + game._$gameholder.append(game._$score); + + // Create the start menu + game._$start = $( + '
' + + '
' + + '
' + this.options.playText + '
' + + '' + this.options.playButtonText + '' + + '
' + + '
').hide(); + game._$gameholder.append(game._$start); + + game._$start.find('.blockrain-start-btn').click(function(event) { + event.preventDefault(); + game.start(); + }); - var handleAssetLoad = function() { - // Rerender the board as soon as an asset loads - if( game._board ) { - game._board.render(true); - } - }; - - var loadAsset = function(src) { - var plainSrc = src; - if( ! hexColorcheck.test( plainSrc ) ) { - // It's an image - src = new Image(); - src.src = plainSrc; - src.onload = handleAssetLoad; - } else { - // It's a color - src = plainSrc; - } - return src; - }; - - var startAssetLoad = function(block) { - // Assets can be an array of variation so they can change color/design randomly - if( $.isArray(block) && block.length > 0 ) { - for( var i=0; i' + + '
' + + '
' + this.options.gameOverText + '
' + + '' + this.options.restartButtonText + '' + + '
' + + '
').hide(); + game._$gameover.find('.blockrain-game-over-btn').click(function(event) { + event.preventDefault(); + game.restart(); + }); + game._$gameholder.append(game._$gameover); + this._createControls(); + }, - if( typeof this._theme.complexBlocks !== 'undefined' ){ - var keys = Object.keys(this._theme.complexBlocks); - // Load the complexBlocks - for( var i = 0; i < keys.length; i++ ) { - this._theme.complexBlocks[ keys[i] ] = startAssetLoad( this._theme.complexBlocks[ keys[i] ] ); - } - } - else if( typeof this._theme.blocks !== 'undefined' ){ - var keys = Object.keys(this._theme.blocks); + _createControls: function() { - // Load the blocks - for( var i = 0; i < keys.length; i++ ) { - this._theme.blocks[ keys[i] ] = startAssetLoad( this._theme.blocks[ keys[i] ] ); - } - } - - // Load the bg - if( typeof this._theme.backgroundGrid !== 'undefined' ){ - if( typeof this._theme.backgroundGrid === 'string' ) { - if( ! hexColorcheck.test( this._theme.backgroundGrid ) ) { - var src = this._theme.backgroundGrid; - this._theme.backgroundGrid = new Image(); - this._theme.backgroundGrid.src = src; - this._theme.backgroundGrid.onload = handleAssetLoad; - } - } - } + var game = this; - }, + game._$touchLeft = $('').appendTo(game._$gameholder); + game._$touchRight = $('').appendTo(game._$gameholder); + game._$touchRotateRight = $('').appendTo(game._$gameholder); + game._$touchRotateLeft = $('').appendTo(game._$gameholder); + game._$touchDrop = $('').appendTo(game._$gameholder); + }, - _createHolder: function() { - // Create the main holder (it holds all the ui elements, the original element is just the wrapper) - this._$gameholder = $('
'); - this._$gameholder.css('position', 'relative').css('width', '100%').css('height', '100%'); + _refreshBlockSizes: function() { - this.element.html('').append(this._$gameholder); + if (this.options.autoBlockWidth) { + this.options.blockWidth = Math.ceil(this.element.width() / this.options.autoBlockSize); + } + + }, - // Create the game canvas and context - this._$canvas = $(''); - if( typeof this._theme.background === 'string' ) { - this._$canvas.css('background-color', this._theme.background); - } - this._$gameholder.append(this._$canvas); - this._canvas = this._$canvas.get(0); - this._ctx = this._canvas.getContext('2d'); + _getNiceShapes: function() { + /* + * Things I need for this to work... + * - ability to test each shape with this._filled data + * - maybe give empty spots scores? and try to maximize the score? + */ - }, + var game = this; + var shapes = {}, + attr; - _createUI: function() { + for (var attr in this._shapeFactory) { + shapes[attr] = this._shapeFactory[attr](); + } - var game = this; + function scoreBlocks(possibles, blocks, x, y, filled, width, height) { + var i, len = blocks.length, + score = 0, + bottoms = {}, + tx, ty, overlaps; - // Score - game._$score = $( - '
'+ - '
'+ - '
'+ this.options.scoreText +'
'+ - '
0
'+ - '
'+ - '
').hide(); - game._$scoreText = game._$score.find('.blockrain-score-num'); - game._$gameholder.append(game._$score); + // base score + for (i = 0; i < len; i += 2) { + score += possibles[game._filled.asIndex(x + blocks[i], y + blocks[i + 1])] || 0; + } - // Create the start menu - game._$start = $( - '
').hide(); - game._$gameholder.append(game._$start); + // overlap score -- //TODO - don't count overlaps if cleared? + for (i = 0; i < len; i += 2) { + tx = blocks[i]; + ty = blocks[i + 1]; + if (bottoms[tx] === undefined || bottoms[tx] < ty) { + bottoms[tx] = ty; + } + } + overlaps = 0; + for (tx in bottoms) { + tx = parseInt(tx); + for (ty = bottoms[tx] + 1, i = 0; y + ty < height; ty++, i++) { + if (!game._filled.check(x + tx, y + ty)) { + overlaps += i == 0 ? 2 : 1; //TODO-score better + //if (i == 0) overlaps += 1; + break; + } + } + } - game._$start.find('.blockrain-start-btn').click(function(event){ - event.preventDefault(); - game.start(); - }); + score = score - overlaps; - // Create the game over menu - game._$gameover = $( - '
'+ - '
'+ - '
'+ this.options.gameOverText +'
'+ - ''+ this.options.restartButtonText +''+ - '
'+ - '
').hide(); - game._$gameover.find('.blockrain-game-over-btn').click(function(event){ - event.preventDefault(); - game.restart(); - }); - game._$gameholder.append(game._$gameover); + return score; + } - this._createControls(); - }, + function resetShapes() { + for (var attr in shapes) { + shapes[attr].x = 0; + shapes[attr].y = -1; + } + } + //TODO -- evil mode needs to realize that overlap is bad... + var func = function(filled, checkCollisions, width, height, mode, _one_shape) { + if (!_one_shape) resetShapes(); + + var possibles = new Array(width * height), + evil = mode == 'evil', + x, y, py, + attr, shape, i, blocks, bounds, + score, best_shape, best_score = (evil ? 1 : -1) * 999, + best_orientation, best_x, + best_score_for_shape, best_orientation_for_shape, best_x_for_shape; + + for (x = 0; x < width; x++) { + for (y = 0; y <= height; y++) { + if (y == height || filled.check(x, y)) { + for (py = y - 4; py < y; py++) { + possibles[filled.asIndex(x, py)] = py; //TODO - figure out better scoring? + } + break; + } + } + } - _createControls: function() { + // for each shape... + var opts = _one_shape === undefined ? shapes : { cur: _one_shape }; //BOO + for (attr in opts) { //TODO - check in random order to prevent later shapes from winning + shape = opts[attr]; + best_score_for_shape = -999; + + // for each orientation... + for (i = 0; i < (shape.symmetrical ? 2 : 4); i++) { //TODO - only look at unique orientations + blocks = shape.getBlocks(i); + bounds = shape.getBounds(blocks); + + // try each possible position... + for (x = -bounds.left; x < width - bounds.width; x++) { + for (y = -1; y < height - bounds.bottom; y++) { + if (game._checkCollisions(x, y + 1, blocks, true)) { + // collision + score = scoreBlocks(possibles, blocks, x, y, filled, width, height); + if (score > best_score_for_shape) { + best_score_for_shape = score; + best_orientation_for_shape = i; + best_x_for_shape = x; + } + break; + } + } + } + } + + if ((evil && best_score_for_shape < best_score) || + (!evil && best_score_for_shape > best_score)) { + best_shape = shape; + best_score = best_score_for_shape; + best_orientation = best_orientation_for_shape; + best_x = best_x_for_shape; + } + } - var game = this; + best_shape.best_orientation = best_orientation; + best_shape.best_x = best_x; - game._$touchLeft = $('').appendTo(game._$gameholder); - game._$touchRight = $('').appendTo(game._$gameholder); - game._$touchRotateRight = $('').appendTo(game._$gameholder); - game._$touchRotateLeft = $('').appendTo(game._$gameholder); - game._$touchDrop = $('').appendTo(game._$gameholder); + return best_shape; + }; - }, + func.no_preview = true; + return func; + }, - _refreshBlockSizes: function() { + _randomShapes: function() { + // Todo: The shapefuncs should be cached. + var shapeFuncs = []; + $.each(this._shapeFactory, function(k, v) { shapeFuncs.push(v); }); - if( this.options.autoBlockWidth ) { - this.options.blockWidth = Math.ceil( this.element.width() / this.options.autoBlockSize ); - } + return this._randChoice(shapeFuncs); + }, - }, + /** + * Controls + */ + _setupControls: function(enable) { - _getNiceShapes: function() { - /* - * Things I need for this to work... - * - ability to test each shape with this._filled data - * - maybe give empty spots scores? and try to maximize the score? - */ + var game = this; - var game = this; + var moveLeft = function(start) { + if (!start) { game._board.holding.left = null; return; } + if (!game._board.holding.left) { + game._board.cur.moveLeft(); + game._board.holding.left = Date.now(); + game._board.holding.right = null; + } + } + var moveRight = function(start) { + if (!start) { game._board.holding.right = null; return; } + if (!game._board.holding.right) { + game._board.cur.moveRight(); + game._board.holding.right = Date.now(); + game._board.holding.left = null; + } + } + var drop = function(start) { + if (!start) { game._board.holding.drop = null; return; } + if (!game._board.holding.drop) { + game._board.cur.drop(); + game._board.holding.drop = Date.now(); + } + } + var rotateLeft = function() { + game._board.cur.rotate('left'); + } + var rotateRight = function() { + game._board.cur.rotate('right'); + } - var shapes = {}, - attr; + // Handlers: These are used to be able to bind/unbind controls + var handleKeyDown = function(evt) { + if (!game._board.cur) { return true; } + var caught = false; + + caught = true; + if (game.options.asdwKeys) { + switch (evt.keyCode) { + case 65: + /*a*/ + moveLeft(true); + break; + case 68: + /*d*/ + moveRight(true); + break; + case 83: + /*s*/ + drop(true); + break; + case 87: + /*w*/ + game._board.cur.rotate('right'); + break; + } + } + switch (evt.keyCode) { + case 37: + /*left*/ + moveLeft(true); + break; + case 39: + /*right*/ + moveRight(true); + break; + case 40: + /*down*/ + drop(true); + break; + case 38: + /*up*/ + game._board.cur.rotate('right'); + break; + case 88: + /*x*/ + game._board.cur.rotate('right'); + break; + case 90: + /*z*/ + game._board.cur.rotate('left'); + break; + default: + caught = false; + } + if (caught) evt.preventDefault(); + return !caught; + }; - for( var attr in this._shapeFactory ) { - shapes[attr] = this._shapeFactory[attr](); - } - function scoreBlocks(possibles, blocks, x, y, filled, width, height) { - var i, len=blocks.length, score=0, bottoms = {}, tx, ty, overlaps; + var handleKeyUp = function(evt) { + if (!game._board.cur) { return true; } + var caught = false; + + caught = true; + if (game.options.asdwKeys) { + switch (evt.keyCode) { + case 65: + /*a*/ + moveLeft(false); + break; + case 68: + /*d*/ + moveRight(false); + break; + case 83: + /*s*/ + drop(false); + break; + } + } + switch (evt.keyCode) { + case 37: + /*left*/ + moveLeft(false); + break; + case 39: + /*right*/ + moveRight(false); + break; + case 40: + /*down*/ + drop(false); + break; + default: + caught = false; + } + if (caught) evt.preventDefault(); + return !caught; + }; - // base score - for (i=0; i best_score_for_shape) { - best_score_for_shape = score; - best_orientation_for_shape = i; - best_x_for_shape = x; - } - break; - } - } + function keyup(evt) { + $.data(this, getKey(evt), 0); + handleKeyUp.call(this, evt); + return isStopKey(evt); } - } - - if ((evil && best_score_for_shape < best_score) || - (!evil && best_score_for_shape > best_score)) { - best_shape = shape; - best_score = best_score_for_shape; - best_orientation = best_orientation_for_shape; - best_x = best_x_for_shape; - } - } - - best_shape.best_orientation = best_orientation; - best_shape.best_x = best_x; - return best_shape; - }; + // Unbind everything by default + // Use event namespacing so we don't ruin other keypress events + $(document).unbind('keydown.blockrain') + .unbind('keyup.blockrain'); - func.no_preview = true; - return func; - }, + if (!game.options.autoplay) { + if (enable) { + $(document).bind('keydown.blockrain', keydown) + .bind('keyup.blockrain', keyup); + } + } + }, - _randomShapes: function() { - // Todo: The shapefuncs should be cached. - var shapeFuncs = []; - $.each(this._shapeFactory, function(k,v) { shapeFuncs.push(v); }); + _setupTouchControls: function(enable) { - return this._randChoice(shapeFuncs); - }, + var game = this; + // Movements can be held for faster movement + var moveLeft = function(event) { + event.preventDefault(); + game._board.cur.moveLeft(); + game._board.holding.left = Date.now(); + game._board.holding.right = null; + game._board.holding.drop = null; + }; + var moveRight = function(event) { + event.preventDefault(); + game._board.cur.moveRight(); + game._board.holding.right = Date.now(); + game._board.holding.left = null; + game._board.holding.drop = null; + }; + var drop = function(event) { + event.preventDefault(); + game._board.cur.drop(); + game._board.holding.drop = Date.now(); + }; + var endMoveLeft = function(event) { + event.preventDefault(); + game._board.holding.left = null; + }; + var endMoveRight = function(event) { + event.preventDefault(); + game._board.holding.right = null; + }; + var endDrop = function(event) { + event.preventDefault(); + game._board.holding.drop = null; + }; - /** - * Controls - */ - _setupControls: function(enable) { + // Rotations can't be held + var rotateLeft = function(event) { + event.preventDefault(); + game._board.cur.rotate('left'); + }; + var rotateRight = function(event) { + event.preventDefault(); + game._board.cur.rotate('right'); + }; - var game = this; + // Unbind everything by default + game._$touchLeft.unbind('touchstart touchend click'); + game._$touchRight.unbind('touchstart touchend click'); + game._$touchRotateLeft.unbind('touchstart touchend click'); + game._$touchRotateRight.unbind('touchstart touchend click'); + game._$touchDrop.unbind('touchstart touchend click'); + + if (!game.options.autoplay && enable) { + game._$touchLeft.show().bind('touchstart click', moveLeft).bind('touchend', endMoveLeft); + game._$touchRight.show().bind('touchstart click', moveRight).bind('touchend', endMoveRight); + game._$touchDrop.show().bind('touchstart click', drop).bind('touchend', endDrop); + game._$touchRotateLeft.show().bind('touchstart click', rotateLeft); + game._$touchRotateRight.show().bind('touchstart click', rotateRight); + } else { + game._$touchLeft.hide(); + game._$touchRight.hide(); + game._$touchRotateLeft.hide(); + game._$touchRotateRight.hide(); + game._$touchDrop.hide(); + } - var moveLeft = function(start) { - if( ! start ) { game._board.holding.left = null; return; } - if( ! game._board.holding.left ) { - game._board.cur.moveLeft(); - game._board.holding.left = Date.now(); - game._board.holding.right = null; - } - } - var moveRight = function(start) { - if( ! start ) { game._board.holding.right = null; return; } - if( ! game._board.holding.right ) { - game._board.cur.moveRight(); - game._board.holding.right = Date.now(); - game._board.holding.left = null; - } - } - var drop = function(start) { - if( ! start ) { game._board.holding.drop = null; return; } - if( ! game._board.holding.drop ) { - game._board.cur.drop(); - game._board.holding.drop = Date.now(); } - } - var rotateLeft = function() { - game._board.cur.rotate('left'); - } - var rotateRight = function() { - game._board.cur.rotate('right'); - } - - // Handlers: These are used to be able to bind/unbind controls - var handleKeyDown = function(evt) { - if( ! game._board.cur ) { return true; } - var caught = false; - - caught = true; - if (game.options.asdwKeys) { - switch(evt.keyCode) { - case 65: /*a*/ moveLeft(true); break; - case 68: /*d*/ moveRight(true); break; - case 83: /*s*/ drop(true); break; - case 87: /*w*/ game._board.cur.rotate('right'); break; - } - } - switch(evt.keyCode) { - case 37: /*left*/ moveLeft(true); break; - case 39: /*right*/ moveRight(true); break; - case 40: /*down*/ drop(true); break; - case 38: /*up*/ game._board.cur.rotate('right'); break; - case 88: /*x*/ game._board.cur.rotate('right'); break; - case 90: /*z*/ game._board.cur.rotate('left'); break; - default: caught = false; - } - if (caught) evt.preventDefault(); - return !caught; - }; - - - var handleKeyUp = function(evt) { - if( ! game._board.cur ) { return true; } - var caught = false; - - caught = true; - if (game.options.asdwKeys) { - switch(evt.keyCode) { - case 65: /*a*/ moveLeft(false); break; - case 68: /*d*/ moveRight(false); break; - case 83: /*s*/ drop(false); break; - } - } - switch(evt.keyCode) { - case 37: /*left*/ moveLeft(false); break; - case 39: /*right*/ moveRight(false); break; - case 40: /*down*/ drop(false); break; - default: caught = false; - } - if (caught) evt.preventDefault(); - return !caught; - }; - - function isStopKey(evt) { - var cfg = { - stopKeys: {37:1, 38:1, 39:1, 40:1} - }; - - var isStop = (cfg.stopKeys[evt.keyCode] || (cfg.moreStopKeys && cfg.moreStopKeys[evt.keyCode])); - if (isStop) evt.preventDefault(); - return isStop; - } - - function getKey(evt) { return 'safekeypress.' + evt.keyCode; } - - function keydown(evt) { - var key = getKey(evt); - $.data(this, key, ($.data(this, key) || 0) - 1); - return handleKeyDown.call(this, evt); - } - - function keyup(evt) { - $.data(this, getKey(evt), 0); - handleKeyUp.call(this, evt); - return isStopKey(evt); - } - - // Unbind everything by default - // Use event namespacing so we don't ruin other keypress events - $(document) .unbind('keydown.blockrain') - .unbind('keyup.blockrain'); - - if( ! game.options.autoplay ) { - if( enable ) { - $(document) .bind('keydown.blockrain', keydown) - .bind('keyup.blockrain', keyup); - } - } - }, - - - _setupTouchControls: function(enable) { - - var game = this; - - // Movements can be held for faster movement - var moveLeft = function(event){ - event.preventDefault(); - game._board.cur.moveLeft(); - game._board.holding.left = Date.now(); - game._board.holding.right = null; - game._board.holding.drop = null; - }; - var moveRight = function(event){ - event.preventDefault(); - game._board.cur.moveRight(); - game._board.holding.right = Date.now(); - game._board.holding.left = null; - game._board.holding.drop = null; - }; - var drop = function(event){ - event.preventDefault(); - game._board.cur.drop(); - game._board.holding.drop = Date.now(); - }; - var endMoveLeft = function(event){ - event.preventDefault(); - game._board.holding.left = null; - }; - var endMoveRight = function(event){ - event.preventDefault(); - game._board.holding.right = null; - }; - var endDrop = function(event){ - event.preventDefault(); - game._board.holding.drop = null; - }; - - // Rotations can't be held - var rotateLeft = function(event){ - event.preventDefault(); - game._board.cur.rotate('left'); - }; - var rotateRight = function(event){ - event.preventDefault(); - game._board.cur.rotate('right'); - }; - - // Unbind everything by default - game._$touchLeft.unbind('touchstart touchend click'); - game._$touchRight.unbind('touchstart touchend click'); - game._$touchRotateLeft.unbind('touchstart touchend click'); - game._$touchRotateRight.unbind('touchstart touchend click'); - game._$touchDrop.unbind('touchstart touchend click'); - - if( ! game.options.autoplay && enable ) { - game._$touchLeft.show().bind('touchstart click', moveLeft).bind('touchend', endMoveLeft); - game._$touchRight.show().bind('touchstart click', moveRight).bind('touchend', endMoveRight); - game._$touchDrop.show().bind('touchstart click', drop).bind('touchend', endDrop); - game._$touchRotateLeft.show().bind('touchstart click', rotateLeft); - game._$touchRotateRight.show().bind('touchstart click', rotateRight); - } else { - game._$touchLeft.hide(); - game._$touchRight.hide(); - game._$touchRotateLeft.hide(); - game._$touchRotateRight.hide(); - game._$touchDrop.hide(); - } - - } - - }); + + }); })(jQuery)); \ No newline at end of file From 764e972c1904d9952a6a3465f77ed1aaf98b7b53 Mon Sep 17 00:00:00 2001 From: Micael Robles Date: Sun, 6 Aug 2017 18:56:51 -0300 Subject: [PATCH 06/10] fix indentation --- src/blockrain.jquery.src.js | 3351 +++++++++++++++++++---------------- 1 file changed, 1843 insertions(+), 1508 deletions(-) diff --git a/src/blockrain.jquery.src.js b/src/blockrain.jquery.src.js index 80035d0..0480f9d 100644 --- a/src/blockrain.jquery.src.js +++ b/src/blockrain.jquery.src.js @@ -1,905 +1,1044 @@ -((function($) { - - "use strict"; - - $.widget('aerolab.blockrain', { - - options: { - autoplay: false, // Let a bot play the game - autoplayRestart: true, // Restart the game automatically once a bot loses - showFieldOnStart: true, // Show a bunch of random blocks on the start screen (it looks nice) - theme: null, // The theme name or a theme object - blockWidth: 10, // How many blocks wide the field is (The standard is 10 blocks) - autoBlockWidth: false, // The blockWidth is dinamically calculated based on the autoBlockSize. Disabled blockWidth. Useful for responsive backgrounds - autoBlockSize: 24, // The max size of a block for autowidth mode - difficulty: 'normal', // Difficulty (normal|nice|evil). - speed: 20, // The speed of the game. The higher, the faster the pieces go. - asdwKeys: true, // Enable ASDW keys - - // Copy - playText: 'Let\'s play some Tetris', - playButtonText: 'Play', - gameOverText: 'Game Over', - restartButtonText: 'Play Again', - scoreText: 'Score', - - // Basic Callbacks - onStart: function() {}, - onRestart: function() {}, - onGameOver: function(score) {}, - - // When a block is placed - onPlaced: function() {}, - // When a line is made. Returns the number of lines, score assigned and total score - onLine: function(lines, scoreIncrement, score) {} - }, - - - /** +(function($) { + "use strict"; + + $.widget("aerolab.blockrain", { + options: { + autoplay: false, // Let a bot play the game + autoplayRestart: true, // Restart the game automatically once a bot loses + showFieldOnStart: true, // Show a bunch of random blocks on the start screen (it looks nice) + theme: null, // The theme name or a theme object + blockWidth: 10, // How many blocks wide the field is (The standard is 10 blocks) + autoBlockWidth: false, // The blockWidth is dinamically calculated based on the autoBlockSize. Disabled blockWidth. Useful for responsive backgrounds + autoBlockSize: 24, // The max size of a block for autowidth mode + difficulty: "normal", // Difficulty (normal|nice|evil). + speed: 20, // The speed of the game. The higher, the faster the pieces go. + asdwKeys: true, // Enable ASDW keys + + // Copy + playText: "Let's play some Tetris", + playButtonText: "Play", + gameOverText: "Game Over", + restartButtonText: "Play Again", + scoreText: "Score", + + // Basic Callbacks + onStart: function() {}, + onRestart: function() {}, + onGameOver: function(score) {}, + + // When a block is placed + onPlaced: function() {}, + // When a line is made. Returns the number of lines, score assigned and total score + onLine: function(lines, scoreIncrement, score) {} + }, + + /** * Start/Restart Game */ - start: function() { - this._doStart(); - this.options.onStart.call(this.element); - }, - - restart: function() { - this._doStart(); - this.options.onRestart.call(this.element); - }, - - gameover: function() { - this.showGameOverMessage(); - this._board.gameover = true; - this.options.onGameOver.call(this.element, this._filled.score); - }, - - _doStart: function() { - this._filled.clearAll(); - this._filled._resetScore(); - this._board.cur = this._board.nextShape(); - this._board.started = true; - this._board.gameover = false; - this._board.dropDelay = 5; - this._board.render(true); - this._board.animate(); - - this._$start.fadeOut(150); - this._$gameover.fadeOut(150); - this._$score.fadeIn(150); - }, - - - pause: function() { - this._board.paused = true; - }, - - resume: function() { - this._board.paused = false; - }, - - autoplay: function(enable) { - if (typeof enable !== 'boolean') { enable = true; } - - // On autoplay, start the game right away - this.options.autoplay = enable; - if (enable && !this._board.started) { - this._doStart(); - } - this._setupControls(!enable); - this._setupTouchControls(!enable); - }, - - controls: function(enable) { - if (typeof enable !== 'boolean') { enable = true; } - this._setupControls(enable); - }, - - touchControls: function(enable) { - if (typeof enable !== 'boolean') { enable = true; } - this._setupTouchControls(enable); - }, - - score: function(newScore) { - if (typeof newScore !== 'undefined' && parseInt(newScore) >= 0) { - this._filled.score = parseInt(newScore); - this._$scoreText.text(this._filled_score); - } - return this._filled.score; - }, - - freesquares: function() { - return this._filled.getFreeSpaces(); - }, - - showStartMessage: function() { - this._$start.show(); - }, - - showGameOverMessage: function() { - this._$gameover.show(); - }, - - /** + start: function() { + this._doStart(); + this.options.onStart.call(this.element); + }, + + restart: function() { + this._doStart(); + this.options.onRestart.call(this.element); + }, + + gameover: function() { + this.showGameOverMessage(); + this._board.gameover = true; + this.options.onGameOver.call(this.element, this._filled.score); + }, + + _doStart: function() { + this._filled.clearAll(); + this._filled._resetScore(); + this._board.cur = this._board.nextShape(); + this._board.started = true; + this._board.gameover = false; + this._board.dropDelay = 5; + this._board.render(true); + this._board.animate(); + + this._$start.fadeOut(150); + this._$gameover.fadeOut(150); + this._$score.fadeIn(150); + }, + + pause: function() { + this._board.paused = true; + }, + + resume: function() { + this._board.paused = false; + }, + + autoplay: function(enable) { + if (typeof enable !== "boolean") { + enable = true; + } + + // On autoplay, start the game right away + this.options.autoplay = enable; + if (enable && !this._board.started) { + this._doStart(); + } + this._setupControls(!enable); + this._setupTouchControls(!enable); + }, + + controls: function(enable) { + if (typeof enable !== "boolean") { + enable = true; + } + this._setupControls(enable); + }, + + touchControls: function(enable) { + if (typeof enable !== "boolean") { + enable = true; + } + this._setupTouchControls(enable); + }, + + score: function(newScore) { + if (typeof newScore !== "undefined" && parseInt(newScore) >= 0) { + this._filled.score = parseInt(newScore); + this._$scoreText.text(this._filled_score); + } + return this._filled.score; + }, + + freesquares: function() { + return this._filled.getFreeSpaces(); + }, + + showStartMessage: function() { + this._$start.show(); + }, + + showGameOverMessage: function() { + this._$gameover.show(); + }, + + /** * Update the sizes of the renderer (this makes the game responsive) */ - updateSizes: function() { - - this._PIXEL_WIDTH = this.element.innerWidth(); - this._PIXEL_HEIGHT = this.element.innerHeight(); - - this._BLOCK_WIDTH = this.options.blockWidth; - this._BLOCK_HEIGHT = Math.floor(this.element.innerHeight() / this.element.innerWidth() * this._BLOCK_WIDTH); - - this._block_size = Math.floor(this._PIXEL_WIDTH / this._BLOCK_WIDTH); - this._border_width = 2; - - // Recalculate the pixel width and height so the canvas always has the best possible size - this._PIXEL_WIDTH = this._block_size * this._BLOCK_WIDTH; - this._PIXEL_HEIGHT = this._block_size * this._BLOCK_HEIGHT; - - this._$canvas.attr('width', this._PIXEL_WIDTH) - .attr('height', this._PIXEL_HEIGHT); - }, - - - theme: function(newTheme) { - - if (typeof newTheme === 'undefined') { - return this.options.theme || this._theme; - } - - // Setup the theme properly - if (typeof newTheme === 'string') { - this.options.theme = newTheme; - this._theme = $.extend(true, {}, BlockrainThemes[newTheme]); - } else { - this.options.theme = null; - this._theme = newTheme; - } - - if (typeof this._theme === 'undefined' || this._theme === null) { - this._theme = $.extend(true, {}, BlockrainThemes['retro']); - this.options.theme = 'retro'; - } - - if (isNaN(parseInt(this._theme.strokeWidth)) || typeof parseInt(this._theme.strokeWidth) !== 'number') { - this._theme.strokeWidth = 2; - } - - // Load the image assets - this._preloadThemeAssets(); - - if (this._board !== null) { - if (typeof this._theme.background === 'string') { - this._$canvas.css('background-color', this._theme.background); - } - this._board.render(); - } - }, - - - // Theme - _theme: { - - }, - - - // UI Elements - _$game: null, - _$canvas: null, - _$gameholder: null, - _$start: null, - _$gameover: null, - _$score: null, - _$scoreText: null, - - - // Canvas - _canvas: null, - _ctx: null, - - - // Initialization - _create: function() { - - var game = this; - - this.theme(this.options.theme); - - this._createHolder(); - this._createUI(); - - this._refreshBlockSizes(); - - this.updateSizes(); - - $(window).resize(function() { - //game.updateSizes(); - }); - - this._SetupShapeFactory(); - this._SetupFilled(); - this._SetupInfo(); - this._SetupBoard(); - - this._info.init(); - this._board.init(); - - var renderLoop = function() { - requestAnimationFrame(renderLoop); - game._board.render(); - }; - renderLoop(); - - if (this.options.autoplay) { - this.autoplay(true); - this._setupTouchControls(false); - } else { - this._setupControls(true); - this._setupTouchControls(false); - } - - }, - - _checkCollisions: function(x, y, blocks, checkDownOnly) { - // x & y should be aspirational values - var i = 0, - len = blocks.length, - a, b; - for (; i < len; i += 2) { - a = x + blocks[i]; - b = y + blocks[i + 1]; - - if (b >= this._BLOCK_HEIGHT || this._filled.check(a, b)) { - return true; - } else if (!checkDownOnly && a < 0 || a >= this._BLOCK_WIDTH) { - return true; - } - } - return false; - }, - - - _board: null, - _info: null, - _filled: null, + updateSizes: function() { + this._PIXEL_WIDTH = this.element.innerWidth(); + this._PIXEL_HEIGHT = this.element.innerHeight(); + + this._BLOCK_WIDTH = this.options.blockWidth; + this._BLOCK_HEIGHT = Math.floor( + this.element.innerHeight() / + this.element.innerWidth() * + this._BLOCK_WIDTH + ); + + this._block_size = Math.floor(this._PIXEL_WIDTH / this._BLOCK_WIDTH); + this._border_width = 2; + + // Recalculate the pixel width and height so the canvas always has the best possible size + this._PIXEL_WIDTH = this._block_size * this._BLOCK_WIDTH; + this._PIXEL_HEIGHT = this._block_size * this._BLOCK_HEIGHT; + + this._$canvas + .attr("width", this._PIXEL_WIDTH) + .attr("height", this._PIXEL_HEIGHT); + }, + + theme: function(newTheme) { + if (typeof newTheme === "undefined") { + return this.options.theme || this._theme; + } + + // Setup the theme properly + if (typeof newTheme === "string") { + this.options.theme = newTheme; + this._theme = $.extend(true, {}, BlockrainThemes[newTheme]); + } else { + this.options.theme = null; + this._theme = newTheme; + } + + if (typeof this._theme === "undefined" || this._theme === null) { + this._theme = $.extend(true, {}, BlockrainThemes["retro"]); + this.options.theme = "retro"; + } + + if ( + isNaN(parseInt(this._theme.strokeWidth)) || + typeof parseInt(this._theme.strokeWidth) !== "number" + ) { + this._theme.strokeWidth = 2; + } + + // Load the image assets + this._preloadThemeAssets(); + + if (this._board !== null) { + if (typeof this._theme.background === "string") { + this._$canvas.css("background-color", this._theme.background); + } + this._board.render(); + } + }, + + // Theme + _theme: {}, + + // UI Elements + _$game: null, + _$canvas: null, + _$gameholder: null, + _$start: null, + _$gameover: null, + _$score: null, + _$scoreText: null, + + // Canvas + _canvas: null, + _ctx: null, + + // Initialization + _create: function() { + var game = this; + + this.theme(this.options.theme); + + this._createHolder(); + this._createUI(); + + this._refreshBlockSizes(); + + this.updateSizes(); + + $(window).resize(function() { + //game.updateSizes(); + }); + + this._SetupShapeFactory(); + this._SetupFilled(); + this._SetupInfo(); + this._SetupBoard(); + + this._info.init(); + this._board.init(); + + var renderLoop = function() { + requestAnimationFrame(renderLoop); + game._board.render(); + }; + renderLoop(); + + if (this.options.autoplay) { + this.autoplay(true); + this._setupTouchControls(false); + } else { + this._setupControls(true); + this._setupTouchControls(false); + } + }, + + _checkCollisions: function(x, y, blocks, checkDownOnly) { + // x & y should be aspirational values + var i = 0, + len = blocks.length, + a, + b; + for (; i < len; i += 2) { + a = x + blocks[i]; + b = y + blocks[i + 1]; + + if (b >= this._BLOCK_HEIGHT || this._filled.check(a, b)) { + return true; + } else if ((!checkDownOnly && a < 0) || a >= this._BLOCK_WIDTH) { + return true; + } + } + return false; + }, + _board: null, + _info: null, + _filled: null, - /** + /** * Draws the background */ - _drawBackground: function() { - - if (typeof this._theme.background !== 'string') { - return; - } - - if (this._theme.backgroundGrid instanceof Image) { - - // Not loaded - if (this._theme.backgroundGrid.width === 0 || this._theme.backgroundGrid.height === 0) { return; } - - this._ctx.globalAlpha = 1.0; - - for (var x = 0; x < this._BLOCK_WIDTH; x++) { - for (var y = 0; y < this._BLOCK_HEIGHT; y++) { - var cx = x * this._block_size; - var cy = y * this._block_size; - - this._ctx.drawImage(this._theme.backgroundGrid, - 0, 0, this._theme.backgroundGrid.width, this._theme.backgroundGrid.height, - cx, cy, this._block_size, this._block_size); - } - } - - } else if (typeof this._theme.backgroundGrid === 'string') { - - var borderWidth = this._theme.strokeWidth; - var borderDistance = Math.round(this._block_size * 0.23); - var squareDistance = Math.round(this._block_size * 0.30); - - this._ctx.globalAlpha = 1.0; - this._ctx.fillStyle = this._theme.backgroundGrid; - - for (var x = 0; x < this._BLOCK_WIDTH; x++) { - for (var y = 0; y < this._BLOCK_HEIGHT; y++) { - var cx = x * this._block_size; - var cy = y * this._block_size; - - this._ctx.fillRect(cx + borderWidth, cy + borderWidth, this._block_size - borderWidth * 2, this._block_size - borderWidth * 2); - } - } - - } + _drawBackground: function() { + if (typeof this._theme.background !== "string") { + return; + } + + if (this._theme.backgroundGrid instanceof Image) { + // Not loaded + if ( + this._theme.backgroundGrid.width === 0 || + this._theme.backgroundGrid.height === 0 + ) { + return; + } - this._ctx.globalAlpha = 1.0; - }, + this._ctx.globalAlpha = 1.0; + + for (var x = 0; x < this._BLOCK_WIDTH; x++) { + for (var y = 0; y < this._BLOCK_HEIGHT; y++) { + var cx = x * this._block_size; + var cy = y * this._block_size; + + this._ctx.drawImage( + this._theme.backgroundGrid, + 0, + 0, + this._theme.backgroundGrid.width, + this._theme.backgroundGrid.height, + cx, + cy, + this._block_size, + this._block_size + ); + } + } + } else if (typeof this._theme.backgroundGrid === "string") { + var borderWidth = this._theme.strokeWidth; + var borderDistance = Math.round(this._block_size * 0.23); + var squareDistance = Math.round(this._block_size * 0.3); + + this._ctx.globalAlpha = 1.0; + this._ctx.fillStyle = this._theme.backgroundGrid; + + for (var x = 0; x < this._BLOCK_WIDTH; x++) { + for (var y = 0; y < this._BLOCK_HEIGHT; y++) { + var cx = x * this._block_size; + var cy = y * this._block_size; + + this._ctx.fillRect( + cx + borderWidth, + cy + borderWidth, + this._block_size - borderWidth * 2, + this._block_size - borderWidth * 2 + ); + } + } + } + this._ctx.globalAlpha = 1.0; + }, - /** + /** * Shapes */ - _shapeFactory: null, + _shapeFactory: null, - _shapes: { - /** + _shapes: { + /** * The shapes have a reference point (the dot) and always rotate left. * Keep in mind that the blocks should keep in the same relative position when rotating, * to allow for custom per-block themes. */ - /* + /* * X * O XOXX * X * X * . . */ - line: [ - [0, -1, 0, -2, 0, -3, 0, -4], - [2, -2, 1, -2, 0, -2, -1, -2], - [0, -4, 0, -3, 0, -2, 0, -1], - [-1, -2, 0, -2, 1, -2, 2, -2] - ], - /* + line: [ + [0, -1, 0, -2, 0, -3, 0, -4], + [2, -2, 1, -2, 0, -2, -1, -2], + [0, -4, 0, -3, 0, -2, 0, -1], + [-1, -2, 0, -2, 1, -2, 2, -2] + ], + /* * XX * XX */ - square: [ - [0, 0, 1, 0, 0, -1, 1, -1], - [1, 0, 1, -1, 0, 0, 0, -1], - [1, -1, 0, -1, 1, 0, 0, 0], - [0, -1, 0, 0, 1, -1, 1, 0] - ], - /* + square: [ + [0, 0, 1, 0, 0, -1, 1, -1], + [1, 0, 1, -1, 0, 0, 0, -1], + [1, -1, 0, -1, 1, 0, 0, 0], + [0, -1, 0, 0, 1, -1, 1, 0] + ], + /* * X X X * XOX XO XOX OX * . .X .X .X */ - arrow: [ - [0, -1, 1, -1, 2, -1, 1, -2], - [1, 0, 1, -1, 1, -2, 0, -1], - [2, -1, 1, -1, 0, -1, 1, 0], - [1, -2, 1, -1, 1, 0, 2, -1] - ], - /* + arrow: [ + [0, -1, 1, -1, 2, -1, 1, -2], + [1, 0, 1, -1, 1, -2, 0, -1], + [2, -1, 1, -1, 0, -1, 1, 0], + [1, -2, 1, -1, 1, 0, 2, -1] + ], + /* * X X XX * O XOX O XOX * .XX . .X X */ - rightHook: [ - [2, 0, 1, 0, 1, -1, 1, -2], - [2, -2, 2, -1, 1, -1, 0, -1], - [0, -2, 1, -2, 1, -1, 1, 0], - [0, 0, 0, -1, 1, -1, 2, -1] - ], - /* + rightHook: [ + [2, 0, 1, 0, 1, -1, 1, -2], + [2, -2, 2, -1, 1, -1, 0, -1], + [0, -2, 1, -2, 1, -1, 1, 0], + [0, 0, 0, -1, 1, -1, 2, -1] + ], + /* * X XX X * O XOX O XOX * XX . X .X . */ - leftHook: [ - [0, 0, 1, 0, 1, -1, 1, -2], - [2, 0, 2, -1, 1, -1, 0, -1], - [2, -2, 1, -2, 1, -1, 1, 0], - [0, -2, 0, -1, 1, -1, 2, -1] - ], - /* + leftHook: [ + [0, 0, 1, 0, 1, -1, 1, -2], + [2, 0, 2, -1, 1, -1, 0, -1], + [2, -2, 1, -2, 1, -1, 1, 0], + [0, -2, 0, -1, 1, -1, 2, -1] + ], + /* * X XX * XO OX * X . */ - leftZag: [ - [0, 0, 0, -1, 1, -1, 1, -2], - [2, -1, 1, -1, 1, -2, 0, -2], - [1, -2, 1, -1, 0, -1, 0, 0], - [0, -2, 1, -2, 1, -1, 2, -1] - ], - /* + leftZag: [ + [0, 0, 0, -1, 1, -1, 1, -2], + [2, -1, 1, -1, 1, -2, 0, -2], + [1, -2, 1, -1, 0, -1, 0, 0], + [0, -2, 1, -2, 1, -1, 2, -1] + ], + /* * X * XO OX * .X XX */ - rightZag: [ - [1, 0, 1, -1, 0, -1, 0, -2], - [2, -1, 1, -1, 1, 0, 0, 0], - [0, -2, 0, -1, 1, -1, 1, 0], - [0, 0, 1, 0, 1, -1, 2, -1] - ] - }, - - _SetupShapeFactory: function() { - var game = this; - if (this._shapeFactory !== null) { return; } - - - function Shape(game, orientations, symmetrical, blockType) { - - $.extend(this, { - x: 0, - y: 0, - symmetrical: symmetrical, - init: function() { - $.extend(this, { - orientation: 0, - x: Math.floor(game._BLOCK_WIDTH / 2) - 1, - y: -1 - }); - return this; - }, - - blockType: blockType, - blockVariation: null, - blocksLen: orientations[0].length, - orientations: orientations, - orientation: 0, // 4 possible - - rotate: function(direction) { - var orientation = (this.orientation + (direction === 'left' ? 1 : -1) + 4) % 4; - - if (!game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { - this.orientation = orientation; - game._board.renderChanged = true; - } else { - var ogOrientation = this.orientation; - var ogX = this.x; - var ogY = this.y; - - this.orientation = orientation; - - while (this.x >= (game._BLOCK_WIDTH - 2)) { - this.x--; - } - while (this.x < 0) { - this.x++; - } - - if (this.blockType === "line" && this.x === 0) this.x++ - - if (game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { - this.y--; - if (game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { - this.x = ogX; - this.y = ogY; - this.orientation = ogOrientation; - } - } - game._board.renderChanged = true; - } - }, - - moveRight: function() { - if (!game._checkCollisions(this.x + 1, this.y, this.getBlocks())) { - this.x++; - game._board.renderChanged = true; - } - }, - moveLeft: function() { - if (!game._checkCollisions(this.x - 1, this.y, this.getBlocks())) { - this.x--; - game._board.renderChanged = true; - } - }, - drop: function() { - if (!game._checkCollisions(this.x, this.y + 1, this.getBlocks())) { - this.y++; - // Reset the drop count, as we dropped the block sooner - game._board.dropCount = -1; - game._board.animate(); - game._board.renderChanged = true; - } - }, - - getBlocks: function(orientation) { // optional param - return this.orientations[orientation !== undefined ? orientation : this.orientation]; - }, - draw: function(_x, _y, _orientation) { - var blocks = this.getBlocks(_orientation), - x = _x === undefined ? this.x : _x, - y = _y === undefined ? this.y : _y, - i = 0, - index = 0; - - for (; i < this.blocksLen; i += 2) { - game._board.drawBlock(x + blocks[i], y + blocks[i + 1], this.blockType, this.blockVariation, index, this.orientation, true); - index++; - } - }, - getBounds: function(_blocks) { // _blocks can be an array of blocks, an orientation index, or undefined - var blocks = $.isArray(_blocks) ? _blocks : this.getBlocks(_blocks), - i = 0, - len = blocks.length, - minx = 999, - maxx = -999, - miny = 999, - maxy = -999; - for (; i < len; i += 2) { - if (blocks[i] < minx) { minx = blocks[i]; } - if (blocks[i] > maxx) { maxx = blocks[i]; } - if (blocks[i + 1] < miny) { miny = blocks[i + 1]; } - if (blocks[i + 1] > maxy) { maxy = blocks[i + 1]; } - } - return { - left: minx, - right: maxx, - top: miny, - bottom: maxy, - width: maxx - minx, - height: maxy - miny - }; - } - }); - - return this.init(); - }; - - this._shapeFactory = { - line: function() { - return new Shape(game, game._shapes.line, false, 'line'); - }, - square: function() { - return new Shape(game, game._shapes.square, false, 'square'); - }, - arrow: function() { - return new Shape(game, game._shapes.arrow, false, 'arrow'); - }, - leftHook: function() { - return new Shape(game, game._shapes.leftHook, false, 'leftHook'); - }, - rightHook: function() { - return new Shape(game, game._shapes.rightHook, false, 'rightHook'); - }, - leftZag: function() { - return new Shape(game, game._shapes.leftZag, false, 'leftZag'); - }, - rightZag: function() { - return new Shape(game, game._shapes.rightZag, false, 'rightZag'); + rightZag: [ + [1, 0, 1, -1, 0, -1, 0, -2], + [2, -1, 1, -1, 1, 0, 0, 0], + [0, -2, 0, -1, 1, -1, 1, 0], + [0, 0, 1, 0, 1, -1, 2, -1] + ] + }, + + _SetupShapeFactory: function() { + var game = this; + if (this._shapeFactory !== null) { + return; + } + + function Shape(game, orientations, symmetrical, blockType) { + $.extend(this, { + x: 0, + y: 0, + symmetrical: symmetrical, + init: function() { + $.extend(this, { + orientation: 0, + x: Math.floor(game._BLOCK_WIDTH / 2) - 1, + y: -1 + }); + return this; + }, + + blockType: blockType, + blockVariation: null, + blocksLen: orientations[0].length, + orientations: orientations, + orientation: 0, // 4 possible + + rotate: function(direction) { + var orientation = + (this.orientation + (direction === "left" ? 1 : -1) + 4) % 4; + + if ( + !game._checkCollisions( + this.x, + this.y, + this.getBlocks(orientation) + ) + ) { + this.orientation = orientation; + game._board.renderChanged = true; + } else { + var ogOrientation = this.orientation; + var ogX = this.x; + var ogY = this.y; + + this.orientation = orientation; + + while (this.x >= game._BLOCK_WIDTH - 2) { + this.x--; + } + while (this.x < 0) { + this.x++; + } + + if (this.blockType === "line" && this.x === 0) this.x++; + + if ( + game._checkCollisions( + this.x, + this.y, + this.getBlocks(orientation) + ) + ) { + this.y--; + if ( + game._checkCollisions( + this.x, + this.y, + this.getBlocks(orientation) + ) + ) { + this.x = ogX; + this.y = ogY; + this.orientation = ogOrientation; } - }; - }, - - - _SetupFilled: function() { - var game = this; - if (this._filled !== null) { return; } - - this._filled = { - data: new Array(game._BLOCK_WIDTH * game._BLOCK_HEIGHT), - score: 0, - toClear: {}, - check: function(x, y) { - return this.data[this.asIndex(x, y)]; - }, - add: function(x, y, blockType, blockVariation, blockIndex, blockOrientation) { - if (x >= 0 && x < game._BLOCK_WIDTH && y >= 0 && y < game._BLOCK_HEIGHT) { - this.data[this.asIndex(x, y)] = { - blockType: blockType, - blockVariation: blockVariation, - blockIndex: blockIndex, - blockOrientation: blockOrientation - }; - } - }, - getFreeSpaces: function() { - var count = 0; - for (var i = 0; i < this.data.length; i++) { - count += (this.data[i] ? 1 : 0); - } - }, - asIndex: function(x, y) { - return x + y * game._BLOCK_WIDTH; - }, - asX: function(index) { - return index % game._BLOCK_WIDTH; - }, - asY: function(index) { - return Math.floor(index / game._BLOCK_WIDTH); - }, - clearAll: function() { - delete this.data; - this.data = new Array(game._BLOCK_WIDTH * game._BLOCK_HEIGHT); - }, - _popRow: function(row_to_pop) { - for (var i = game._BLOCK_WIDTH * (row_to_pop + 1) - 1; i >= 0; i--) { - this.data[i] = (i >= game._BLOCK_WIDTH ? this.data[i - game._BLOCK_WIDTH] : undefined); - } - }, - checkForClears: function() { - var startLines = game._board.lines; - var rows = [], - i, len, count, mod; - - for (i = 0, len = this.data.length; i < len; i++) { - mod = this.asX(i); - if (mod == 0) count = 0; - if (this.data[i] && typeof this.data[i] !== 'undefined' && typeof this.data[i].blockType === 'string') { - count += 1; - } - if (mod == game._BLOCK_WIDTH - 1 && count == game._BLOCK_WIDTH) { - rows.push(this.asY(i)); - } - } - - for (i = 0, len = rows.length; i < len; i++) { - this._popRow(rows[i]); - game._board.lines++; - if (game._board.lines % 10 == 0 && game._board.dropDelay > 1) { - game._board.dropDelay *= 0.9; - } - } + } + game._board.renderChanged = true; + } + }, - var clearedLines = game._board.lines - startLines; - this._updateScore(clearedLines); - }, - _updateScore: function(numLines) { - if (numLines <= 0) { return; } - var scores = [0, 400, 1000, 3000, 12000]; - if (numLines >= scores.length) { numLines = scores.length - 1 } - - this.score += scores[numLines]; - game._$scoreText.text(this.score); - - game.options.onLine.call(game.element, numLines, scores[numLines], this.score); - }, - _resetScore: function() { - this.score = 0; - game._$scoreText.text(this.score); - }, - draw: function() { - for (var i = 0, len = this.data.length, row, color; i < len; i++) { - if (this.data[i] !== undefined) { - row = this.asY(i); - var block = this.data[i]; - game._board.drawBlock(this.asX(i), row, block.blockType, block.blockVariation, block.blockIndex, block.blockOrientation); - } - } - } + moveRight: function() { + if (!game._checkCollisions(this.x + 1, this.y, this.getBlocks())) { + this.x++; + game._board.renderChanged = true; + } + }, + moveLeft: function() { + if (!game._checkCollisions(this.x - 1, this.y, this.getBlocks())) { + this.x--; + game._board.renderChanged = true; + } + }, + drop: function() { + if (!game._checkCollisions(this.x, this.y + 1, this.getBlocks())) { + this.y++; + // Reset the drop count, as we dropped the block sooner + game._board.dropCount = -1; + game._board.animate(); + game._board.renderChanged = true; + } + }, + + getBlocks: function(orientation) { + // optional param + return this.orientations[ + orientation !== undefined ? orientation : this.orientation + ]; + }, + draw: function(_x, _y, _orientation) { + var blocks = this.getBlocks(_orientation), + x = _x === undefined ? this.x : _x, + y = _y === undefined ? this.y : _y, + i = 0, + index = 0; + + for (; i < this.blocksLen; i += 2) { + game._board.drawBlock( + x + blocks[i], + y + blocks[i + 1], + this.blockType, + this.blockVariation, + index, + this.orientation, + true + ); + index++; + } + }, + getBounds: function(_blocks) { + // _blocks can be an array of blocks, an orientation index, or undefined + var blocks = $.isArray(_blocks) ? _blocks : this.getBlocks(_blocks), + i = 0, + len = blocks.length, + minx = 999, + maxx = -999, + miny = 999, + maxy = -999; + for (; i < len; i += 2) { + if (blocks[i] < minx) { + minx = blocks[i]; + } + if (blocks[i] > maxx) { + maxx = blocks[i]; + } + if (blocks[i + 1] < miny) { + miny = blocks[i + 1]; + } + if (blocks[i + 1] > maxy) { + maxy = blocks[i + 1]; + } + } + return { + left: minx, + right: maxx, + top: miny, + bottom: maxy, + width: maxx - minx, + height: maxy - miny }; - }, - + } + }); - _SetupInfo: function() { + return this.init(); + } - var game = this; - - this._info = { - mode: game.options.difficulty, - modes: [ - 'normal', - 'nice', - 'evil' - ], - modesY: 170, - autopilotY: null, - - init: function() { - this.mode = game.options.difficulty; - }, - setMode: function(mode) { - this.mode = mode; - game._board.nextShape(true); - } + this._shapeFactory = { + line: function() { + return new Shape(game, game._shapes.line, false, "line"); + }, + square: function() { + return new Shape(game, game._shapes.square, false, "square"); + }, + arrow: function() { + return new Shape(game, game._shapes.arrow, false, "arrow"); + }, + leftHook: function() { + return new Shape(game, game._shapes.leftHook, false, "leftHook"); + }, + rightHook: function() { + return new Shape(game, game._shapes.rightHook, false, "rightHook"); + }, + leftZag: function() { + return new Shape(game, game._shapes.leftZag, false, "leftZag"); + }, + rightZag: function() { + return new Shape(game, game._shapes.rightZag, false, "rightZag"); + } + }; + }, + + _SetupFilled: function() { + var game = this; + if (this._filled !== null) { + return; + } + + this._filled = { + data: new Array(game._BLOCK_WIDTH * game._BLOCK_HEIGHT), + score: 0, + toClear: {}, + check: function(x, y) { + return this.data[this.asIndex(x, y)]; + }, + add: function( + x, + y, + blockType, + blockVariation, + blockIndex, + blockOrientation + ) { + if ( + x >= 0 && + x < game._BLOCK_WIDTH && + y >= 0 && + y < game._BLOCK_HEIGHT + ) { + this.data[this.asIndex(x, y)] = { + blockType: blockType, + blockVariation: blockVariation, + blockIndex: blockIndex, + blockOrientation: blockOrientation }; - + } }, + getFreeSpaces: function() { + var count = 0; + for (var i = 0; i < this.data.length; i++) { + count += this.data[i] ? 1 : 0; + } + }, + asIndex: function(x, y) { + return x + y * game._BLOCK_WIDTH; + }, + asX: function(index) { + return index % game._BLOCK_WIDTH; + }, + asY: function(index) { + return Math.floor(index / game._BLOCK_WIDTH); + }, + clearAll: function() { + delete this.data; + this.data = new Array(game._BLOCK_WIDTH * game._BLOCK_HEIGHT); + }, + _popRow: function(row_to_pop) { + for (var i = game._BLOCK_WIDTH * (row_to_pop + 1) - 1; i >= 0; i--) { + this.data[i] = + i >= game._BLOCK_WIDTH + ? this.data[i - game._BLOCK_WIDTH] + : undefined; + } + }, + checkForClears: function() { + var startLines = game._board.lines; + var rows = [], + i, + len, + count, + mod; + + for (i = 0, len = this.data.length; i < len; i++) { + mod = this.asX(i); + if (mod == 0) count = 0; + if ( + this.data[i] && + typeof this.data[i] !== "undefined" && + typeof this.data[i].blockType === "string" + ) { + count += 1; + } + if (mod == game._BLOCK_WIDTH - 1 && count == game._BLOCK_WIDTH) { + rows.push(this.asY(i)); + } + } + for (i = 0, len = rows.length; i < len; i++) { + this._popRow(rows[i]); + game._board.lines++; + if (game._board.lines % 10 == 0 && game._board.dropDelay > 1) { + game._board.dropDelay *= 0.9; + } + } - _SetupBoard: function() { - - var game = this; - var info = this._info; - - this._board = { - // This sets the tick rate for the game - animateDelay: 1000 / game.options.speed, - - animateTimeoutId: null, - cur: null, - - lines: 0, - - // DropCount increments on each animation frame. After n frames, the piece drops 1 square - // By making dropdelay lower (down to 0), the pieces move faster, up to once per tick (animateDelay). - dropCount: 0, - dropDelay: 5, //5, + var clearedLines = game._board.lines - startLines; + this._updateScore(clearedLines); + }, + _updateScore: function(numLines) { + if (numLines <= 0) { + return; + } + var scores = [0, 400, 1000, 3000, 12000]; + if (numLines >= scores.length) { + numLines = scores.length - 1; + } + + this.score += scores[numLines]; + game._$scoreText.text(this.score); + + game.options.onLine.call( + game.element, + numLines, + scores[numLines], + this.score + ); + }, + _resetScore: function() { + this.score = 0; + game._$scoreText.text(this.score); + }, + draw: function() { + for (var i = 0, len = this.data.length, row, color; i < len; i++) { + if (this.data[i] !== undefined) { + row = this.asY(i); + var block = this.data[i]; + game._board.drawBlock( + this.asX(i), + row, + block.blockType, + block.blockVariation, + block.blockIndex, + block.blockOrientation + ); + } + } + } + }; + }, - holding: { left: null, right: null, drop: null }, - holdingThreshold: 200, // How long do you have to hold a key to make commands repeat (in ms) + _SetupInfo: function() { + var game = this; - started: false, - gameover: false, + this._info = { + mode: game.options.difficulty, + modes: ["normal", "nice", "evil"], + modesY: 170, + autopilotY: null, - renderChanged: true, + init: function() { + this.mode = game.options.difficulty; + }, + setMode: function(mode) { + this.mode = mode; + game._board.nextShape(true); + } + }; + }, - init: function() { - this.cur = this.nextShape(); + _SetupBoard: function() { + var game = this; + var info = this._info; - if (game.options.showFieldOnStart) { - game._drawBackground(); - game._board.createRandomBoard(); - game._board.render(); - } + this._board = { + // This sets the tick rate for the game + animateDelay: 1000 / game.options.speed, - this.showStartMessage(); - }, + animateTimeoutId: null, + cur: null, - showStartMessage: function() { - game._$start.show(); - }, + lines: 0, - showGameOverMessage: function() { - game._$gameover.show(); - }, + // DropCount increments on each animation frame. After n frames, the piece drops 1 square + // By making dropdelay lower (down to 0), the pieces move faster, up to once per tick (animateDelay). + dropCount: 0, + dropDelay: 5, //5, - nextShape: function(_set_next_only) { - var next = this.next, - func, shape, result; + holding: { left: null, right: null, drop: null }, + holdingThreshold: 200, // How long do you have to hold a key to make commands repeat (in ms) - if (info.mode == 'nice' || info.mode == 'evil') { - func = game._niceShapes; - } else { - func = game._randomShapes(); - } + started: false, + gameover: false, - if (game.options.no_preview) { - this.next = null; - if (_set_next_only) return null; - shape = func(game._filled, game._checkCollisions, game._BLOCK_WIDTH, game._BLOCK_HEIGHT, info.mode); - if (!shape) throw new Error('No shape returned from shape function!', func); - shape.init(); - result = shape; - } else { - shape = func(game._filled, game._checkCollisions, game._BLOCK_WIDTH, game._BLOCK_HEIGHT, info.mode); - if (!shape) throw new Error('No shape returned from shape function!', func); - shape.init(); - this.next = shape; - if (_set_next_only) return null; - result = next || this.nextShape(); - } + renderChanged: true, - if (game.options.autoplay) { //fun little hack... - game._niceShapes(game._filled, game._checkCollisions, game._BLOCK_WIDTH, game._BLOCK_HEIGHT, 'normal', result); - result.orientation = result.best_orientation; - result.x = result.best_x; - } + init: function() { + this.cur = this.nextShape(); - if (typeof game._theme.complexBlocks !== 'undefined') { - if ($.isArray(game._theme.complexBlocks[result.blockType])) { - result.blockVariation = game._randInt(0, game._theme.complexBlocks[result.blockType].length - 1); - } else { - result.blockVariation = null; - } - } else if (typeof game._theme.blocks !== 'undefined') { - if ($.isArray(game._theme.blocks[result.blockType])) { - result.blockVariation = game._randInt(0, game._theme.blocks[result.blockType].length - 1); - } else { - result.blockVariation = null; - } - } + if (game.options.showFieldOnStart) { + game._drawBackground(); + game._board.createRandomBoard(); + game._board.render(); + } - return result; - }, - - animate: function() { - var drop = false, - moved = false, - gameOver = false, - now = Date.now(); - - if (this.animateTimeoutId) { clearTimeout(this.animateTimeoutId); } - - //game.updateSizes(); - - if (!this.paused && !this.gameover) { - - this.dropCount++; - - // Drop by delay or holding - if ((this.dropCount >= this.dropDelay) || - (game.options.autoplay) || - (this.holding.drop && (now - this.holding.drop) >= this.holdingThreshold)) { - drop = true; - moved = true; - this.dropCount = 0; - } - - // Move Left by holding - if (this.holding.left && (now - this.holding.left) >= this.holdingThreshold) { - moved = true; - this.cur.moveLeft(); - } - - // Move Right by holding - if (this.holding.right && (now - this.holding.right) >= this.holdingThreshold) { - moved = true; - this.cur.moveRight(); - } - - // Test for a collision, add the piece to the filled blocks and fetch the next one - if (drop) { - var cur = this.cur, - x = cur.x, - y = cur.y, - blocks = cur.getBlocks(); - if (game._checkCollisions(x, y + 1, blocks, true)) { - drop = false; - var blockIndex = 0; - for (var i = 0; i < cur.blocksLen; i += 2) { - game._filled.add(x + blocks[i], y + blocks[i + 1], cur.blockType, cur.blockVariation, blockIndex, cur.orientation); - if (y + blocks[i] < 0) { - gameOver = true; - } - blockIndex++; - } - game._filled.checkForClears(); - this.cur = this.nextShape(); - this.renderChanged = true; - - // Stop holding drop (and any other buttons). Just in case the controls get sticky. - this.holding.left = null; - this.holding.right = null; - this.holding.drop = null; - - game.options.onPlaced.call(game.element); - } - } - } + this.showStartMessage(); + }, - // Drop - if (drop) { - moved = true; - this.cur.y++; - } + showStartMessage: function() { + game._$start.show(); + }, - if (drop || moved) { - this.renderChanged = true; - } + showGameOverMessage: function() { + game._$gameover.show(); + }, - if (gameOver) { + nextShape: function(_set_next_only) { + var next = this.next, + func, + shape, + result; + + if (info.mode == "nice" || info.mode == "evil") { + func = game._niceShapes; + } else { + func = game._randomShapes(); + } + + if (game.options.no_preview) { + this.next = null; + if (_set_next_only) return null; + shape = func( + game._filled, + game._checkCollisions, + game._BLOCK_WIDTH, + game._BLOCK_HEIGHT, + info.mode + ); + if (!shape) + throw new Error("No shape returned from shape function!", func); + shape.init(); + result = shape; + } else { + shape = func( + game._filled, + game._checkCollisions, + game._BLOCK_WIDTH, + game._BLOCK_HEIGHT, + info.mode + ); + if (!shape) + throw new Error("No shape returned from shape function!", func); + shape.init(); + this.next = shape; + if (_set_next_only) return null; + result = next || this.nextShape(); + } + + if (game.options.autoplay) { + //fun little hack... + game._niceShapes( + game._filled, + game._checkCollisions, + game._BLOCK_WIDTH, + game._BLOCK_HEIGHT, + "normal", + result + ); + result.orientation = result.best_orientation; + result.x = result.best_x; + } + + if (typeof game._theme.complexBlocks !== "undefined") { + if ($.isArray(game._theme.complexBlocks[result.blockType])) { + result.blockVariation = game._randInt( + 0, + game._theme.complexBlocks[result.blockType].length - 1 + ); + } else { + result.blockVariation = null; + } + } else if (typeof game._theme.blocks !== "undefined") { + if ($.isArray(game._theme.blocks[result.blockType])) { + result.blockVariation = game._randInt( + 0, + game._theme.blocks[result.blockType].length - 1 + ); + } else { + result.blockVariation = null; + } + } - this.gameover = true; + return result; + }, - game.gameover(); + animate: function() { + var drop = false, + moved = false, + gameOver = false, + now = Date.now(); + + if (this.animateTimeoutId) { + clearTimeout(this.animateTimeoutId); + } + + //game.updateSizes(); + + if (!this.paused && !this.gameover) { + this.dropCount++; + + // Drop by delay or holding + if ( + this.dropCount >= this.dropDelay || + game.options.autoplay || + (this.holding.drop && + now - this.holding.drop >= this.holdingThreshold) + ) { + drop = true; + moved = true; + this.dropCount = 0; + } - if (game.options.autoplay && game.options.autoplayRestart) { - // On autoplay, restart the game automatically - game.restart(); - } - this.renderChanged = true; + // Move Left by holding + if ( + this.holding.left && + now - this.holding.left >= this.holdingThreshold + ) { + moved = true; + this.cur.moveLeft(); + } - } else { + // Move Right by holding + if ( + this.holding.right && + now - this.holding.right >= this.holdingThreshold + ) { + moved = true; + this.cur.moveRight(); + } - // Update the speed - this.animateDelay = 1000 / game.options.speed; + // Test for a collision, add the piece to the filled blocks and fetch the next one + if (drop) { + var cur = this.cur, + x = cur.x, + y = cur.y, + blocks = cur.getBlocks(); + if (game._checkCollisions(x, y + 1, blocks, true)) { + drop = false; + var blockIndex = 0; + for (var i = 0; i < cur.blocksLen; i += 2) { + game._filled.add( + x + blocks[i], + y + blocks[i + 1], + cur.blockType, + cur.blockVariation, + blockIndex, + cur.orientation + ); + if (y + blocks[i] < 0) { + gameOver = true; + } + blockIndex++; + } + game._filled.checkForClears(); + this.cur = this.nextShape(); + this.renderChanged = true; - this.animateTimeoutId = window.setTimeout(function() { - game._board.animate(); - }, this.animateDelay); + // Stop holding drop (and any other buttons). Just in case the controls get sticky. + this.holding.left = null; + this.holding.right = null; + this.holding.drop = null; - } + game.options.onPlaced.call(game.element); + } + } + } - }, + // Drop + if (drop) { + moved = true; + this.cur.y++; + } - createRandomBoard: function() { + if (drop || moved) { + this.renderChanged = true; + } - var start = [], - blockTypes = [], - i, ilen, j, jlen, blockType; + if (gameOver) { + this.gameover = true; - // Draw a random blockrain screen - blockTypes = Object.keys(game._shapeFactory); + game.gameover(); - for (i = 0, ilen = game._BLOCK_WIDTH; i < ilen; i++) { - for (j = 0, jlen = game._randChoice([game._randInt(0, 8), game._randInt(5, 9)]); j < jlen; j++) { - if (!blockType || !game._randInt(0, 3)) blockType = game._randChoice(blockTypes); + if (game.options.autoplay && game.options.autoplayRestart) { + // On autoplay, restart the game automatically + game.restart(); + } + this.renderChanged = true; + } else { + // Update the speed + this.animateDelay = 1000 / game.options.speed; + + this.animateTimeoutId = window.setTimeout(function() { + game._board.animate(); + }, this.animateDelay); + } + }, - // Use a random piece and orientation - // Todo: Use an actual random variation - game._filled.add(i, game._BLOCK_HEIGHT - j, blockType, game._randInt(0, 3), null, game._randInt(0, 3)); - } - } + createRandomBoard: function() { + var start = [], + blockTypes = [], + i, + ilen, + j, + jlen, + blockType; + + // Draw a random blockrain screen + blockTypes = Object.keys(game._shapeFactory); + + for (i = 0, ilen = game._BLOCK_WIDTH; i < ilen; i++) { + for ( + j = 0, jlen = game._randChoice([ + game._randInt(0, 8), + game._randInt(5, 9) + ]); + j < jlen; + j++ + ) { + if (!blockType || !game._randInt(0, 3)) + blockType = game._randChoice(blockTypes); + + // Use a random piece and orientation + // Todo: Use an actual random variation + game._filled.add( + i, + game._BLOCK_HEIGHT - j, + blockType, + game._randInt(0, 3), + null, + game._randInt(0, 3) + ); + } + } - /* + /* for (i=0, ilen=WIDTH; i 0) { - return blockTheme[0]; - } else { - return null; - } - } else { - return blockTheme; - } - } - - if (typeof falling !== 'boolean') { falling = true; } - if (falling) { - if (typeof game._theme.primary === 'string' && game._theme.primary !== '') { - return game._theme.primary; - } else if (typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null) { - return getBlockVariation(game._theme.blocks[blockType], blockVariation); - } else { - return getBlockVariation(game._theme.complexBlocks[blockType], blockVariation); - } - } else { - if (typeof game._theme.secondary === 'string' && game._theme.secondary !== '') { - return game._theme.secondary; - } else if (typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null) { - return getBlockVariation(game._theme.blocks[blockType], blockVariation); - } else { - return getBlockVariation(game._theme.complexBlocks[blockType], blockVariation); - } - } - } - - }; - - game._niceShapes = game._getNiceShapes(); - }, - - // Utility Functions - _randInt: function(a, b) { return a + Math.floor(Math.random() * (1 + b - a)); }, - _randSign: function() { return this._randInt(0, 1) * 2 - 1; }, - _randChoice: function(choices) { return choices[this._randInt(0, choices.length - 1)]; }, - - - /** - * Find base64 encoded images and load them as image objects, which can be used by the canvas renderer - */ - _preloadThemeAssets: function() { - - var game = this; - - var hexColorcheck = new RegExp('^#[A-F0-9+]{3,6}', 'i'); - var base64check = new RegExp('^data:image/(png|gif|jpg);base64,', 'i'); - - var handleAssetLoad = function() { - // Rerender the board as soon as an asset loads - if (game._board) { - game._board.render(true); - } - }; - - var loadAsset = function(src) { - var plainSrc = src; - if (!hexColorcheck.test(plainSrc)) { - // It's an image - src = new Image(); - src.src = plainSrc; - src.onload = handleAssetLoad; - } else { - // It's a color - src = plainSrc; - } - return src; - }; - - var startAssetLoad = function(block) { - // Assets can be an array of variation so they can change color/design randomly - if ($.isArray(block) && block.length > 0) { - for (var i = 0; i < block.length; i++) { - block[i] = loadAsset(block[i]); - } - } else if (typeof block === 'string') { - block = loadAsset(block); - } - return block; - }; - - - if (typeof this._theme.complexBlocks !== 'undefined') { - var keys = Object.keys(this._theme.complexBlocks); - - // Load the complexBlocks - for (var i = 0; i < keys.length; i++) { - this._theme.complexBlocks[keys[i]] = startAssetLoad(this._theme.complexBlocks[keys[i]]); - } - } else if (typeof this._theme.blocks !== 'undefined') { - var keys = Object.keys(this._theme.blocks); - - // Load the blocks - for (var i = 0; i < keys.length; i++) { - this._theme.blocks[keys[i]] = startAssetLoad(this._theme.blocks[keys[i]]); - } + var getBlockVariation = function(blockTheme, blockVariation) { + if ($.isArray(blockTheme)) { + if ( + blockVariation !== null && + typeof blockTheme[blockVariation] !== "undefined" + ) { + return blockTheme[blockVariation]; + } else if (blockTheme.length > 0) { + return blockTheme[0]; + } else { + return null; + } + } else { + return blockTheme; } - - // Load the bg - if (typeof this._theme.backgroundGrid !== 'undefined') { - if (typeof this._theme.backgroundGrid === 'string') { - if (!hexColorcheck.test(this._theme.backgroundGrid)) { - var src = this._theme.backgroundGrid; - this._theme.backgroundGrid = new Image(); - this._theme.backgroundGrid.src = src; - this._theme.backgroundGrid.onload = handleAssetLoad; - } - } + }; + + if (typeof falling !== "boolean") { + falling = true; + } + if (falling) { + if ( + typeof game._theme.primary === "string" && + game._theme.primary !== "" + ) { + return game._theme.primary; + } else if ( + typeof game._theme.blocks !== "undefined" && + game._theme.blocks !== null + ) { + return getBlockVariation( + game._theme.blocks[blockType], + blockVariation + ); + } else { + return getBlockVariation( + game._theme.complexBlocks[blockType], + blockVariation + ); } - - }, - - - _createHolder: function() { - - // Create the main holder (it holds all the ui elements, the original element is just the wrapper) - this._$gameholder = $('
'); - this._$gameholder.css('position', 'relative').css('width', '100%').css('height', '100%'); - - this.element.html('').append(this._$gameholder); - - // Create the game canvas and context - this._$canvas = $(''); - if (typeof this._theme.background === 'string') { - this._$canvas.css('background-color', this._theme.background); + } else { + if ( + typeof game._theme.secondary === "string" && + game._theme.secondary !== "" + ) { + return game._theme.secondary; + } else if ( + typeof game._theme.blocks !== "undefined" && + game._theme.blocks !== null + ) { + return getBlockVariation( + game._theme.blocks[blockType], + blockVariation + ); + } else { + return getBlockVariation( + game._theme.complexBlocks[blockType], + blockVariation + ); } - this._$gameholder.append(this._$canvas); - - this._canvas = this._$canvas.get(0); - this._ctx = this._canvas.getContext('2d'); - - }, - - - _createUI: function() { - - var game = this; - - // Score - game._$score = $( - '
' + - '
' + - '
' + this.options.scoreText + '
' + - '
0
' + - '
' + - '
').hide(); - game._$scoreText = game._$score.find('.blockrain-score-num'); - game._$gameholder.append(game._$score); - - // Create the start menu - game._$start = $( - '
').hide(); - game._$gameholder.append(game._$start); - - game._$start.find('.blockrain-start-btn').click(function(event) { - event.preventDefault(); - game.start(); - }); - - // Create the game over menu - game._$gameover = $( - '
' + - '
' + - '
' + this.options.gameOverText + '
' + - '' + this.options.restartButtonText + '' + - '
' + - '
').hide(); - game._$gameover.find('.blockrain-game-over-btn').click(function(event) { - event.preventDefault(); - game.restart(); - }); - game._$gameholder.append(game._$gameover); - - this._createControls(); - }, - - - _createControls: function() { - - var game = this; - - game._$touchLeft = $('').appendTo(game._$gameholder); - game._$touchRight = $('').appendTo(game._$gameholder); - game._$touchRotateRight = $('').appendTo(game._$gameholder); - game._$touchRotateLeft = $('').appendTo(game._$gameholder); - game._$touchDrop = $('').appendTo(game._$gameholder); - - }, - - - _refreshBlockSizes: function() { + } + } + }; + + game._niceShapes = game._getNiceShapes(); + }, + + // Utility Functions + _randInt: function(a, b) { + return a + Math.floor(Math.random() * (1 + b - a)); + }, + _randSign: function() { + return this._randInt(0, 1) * 2 - 1; + }, + _randChoice: function(choices) { + return choices[this._randInt(0, choices.length - 1)]; + }, + + /** + * Find base64 encoded images and load them as image objects, which can be used by the canvas renderer + */ + _preloadThemeAssets: function() { + var game = this; - if (this.options.autoBlockWidth) { - this.options.blockWidth = Math.ceil(this.element.width() / this.options.autoBlockSize); - } + var hexColorcheck = new RegExp("^#[A-F0-9+]{3,6}", "i"); + var base64check = new RegExp("^data:image/(png|gif|jpg);base64,", "i"); - }, + var handleAssetLoad = function() { + // Rerender the board as soon as an asset loads + if (game._board) { + game._board.render(true); + } + }; + + var loadAsset = function(src) { + var plainSrc = src; + if (!hexColorcheck.test(plainSrc)) { + // It's an image + src = new Image(); + src.src = plainSrc; + src.onload = handleAssetLoad; + } else { + // It's a color + src = plainSrc; + } + return src; + }; + + var startAssetLoad = function(block) { + // Assets can be an array of variation so they can change color/design randomly + if ($.isArray(block) && block.length > 0) { + for (var i = 0; i < block.length; i++) { + block[i] = loadAsset(block[i]); + } + } else if (typeof block === "string") { + block = loadAsset(block); + } + return block; + }; + if (typeof this._theme.complexBlocks !== "undefined") { + var keys = Object.keys(this._theme.complexBlocks); - _getNiceShapes: function() { - /* + // Load the complexBlocks + for (var i = 0; i < keys.length; i++) { + this._theme.complexBlocks[keys[i]] = startAssetLoad( + this._theme.complexBlocks[keys[i]] + ); + } + } else if (typeof this._theme.blocks !== "undefined") { + var keys = Object.keys(this._theme.blocks); + + // Load the blocks + for (var i = 0; i < keys.length; i++) { + this._theme.blocks[keys[i]] = startAssetLoad( + this._theme.blocks[keys[i]] + ); + } + } + + // Load the bg + if (typeof this._theme.backgroundGrid !== "undefined") { + if (typeof this._theme.backgroundGrid === "string") { + if (!hexColorcheck.test(this._theme.backgroundGrid)) { + var src = this._theme.backgroundGrid; + this._theme.backgroundGrid = new Image(); + this._theme.backgroundGrid.src = src; + this._theme.backgroundGrid.onload = handleAssetLoad; + } + } + } + }, + + _createHolder: function() { + // Create the main holder (it holds all the ui elements, the original element is just the wrapper) + this._$gameholder = $('
'); + this._$gameholder + .css("position", "relative") + .css("width", "100%") + .css("height", "100%"); + + this.element.html("").append(this._$gameholder); + + // Create the game canvas and context + this._$canvas = $( + '' + ); + if (typeof this._theme.background === "string") { + this._$canvas.css("background-color", this._theme.background); + } + this._$gameholder.append(this._$canvas); + + this._canvas = this._$canvas.get(0); + this._ctx = this._canvas.getContext("2d"); + }, + + _createUI: function() { + var game = this; + + // Score + game._$score = $( + '
' + + '
' + + '
' + + this.options.scoreText + + "
" + + '
0
' + + "
" + + "
" + ).hide(); + game._$scoreText = game._$score.find(".blockrain-score-num"); + game._$gameholder.append(game._$score); + + // Create the start menu + game._$start = $( + '
" + ).hide(); + game._$gameholder.append(game._$start); + + game._$start.find(".blockrain-start-btn").click(function(event) { + event.preventDefault(); + game.start(); + }); + + // Create the game over menu + game._$gameover = $( + '
' + + '
' + + '
' + + this.options.gameOverText + + "
" + + '' + + this.options.restartButtonText + + "" + + "
" + + "
" + ).hide(); + game._$gameover.find(".blockrain-game-over-btn").click(function(event) { + event.preventDefault(); + game.restart(); + }); + game._$gameholder.append(game._$gameover); + + this._createControls(); + }, + + _createControls: function() { + var game = this; + + game._$touchLeft = $( + '' + ).appendTo(game._$gameholder); + game._$touchRight = $( + '' + ).appendTo(game._$gameholder); + game._$touchRotateRight = $( + '' + ).appendTo(game._$gameholder); + game._$touchRotateLeft = $( + '' + ).appendTo(game._$gameholder); + game._$touchDrop = $( + '' + ).appendTo(game._$gameholder); + }, + + _refreshBlockSizes: function() { + if (this.options.autoBlockWidth) { + this.options.blockWidth = Math.ceil( + this.element.width() / this.options.autoBlockSize + ); + } + }, + + _getNiceShapes: function() { + /* * Things I need for this to work... * - ability to test each shape with this._filled data * - maybe give empty spots scores? and try to maximize the score? */ - var game = this; - - var shapes = {}, - attr; + var game = this; + + var shapes = {}, + attr; + + for (var attr in this._shapeFactory) { + shapes[attr] = this._shapeFactory[attr](); + } + + function scoreBlocks(possibles, blocks, x, y, filled, width, height) { + var i, + len = blocks.length, + score = 0, + bottoms = {}, + tx, + ty, + overlaps; + + // base score + for (i = 0; i < len; i += 2) { + score += + possibles[game._filled.asIndex(x + blocks[i], y + blocks[i + 1])] || + 0; + } - for (var attr in this._shapeFactory) { - shapes[attr] = this._shapeFactory[attr](); + // overlap score -- //TODO - don't count overlaps if cleared? + for (i = 0; i < len; i += 2) { + tx = blocks[i]; + ty = blocks[i + 1]; + if (bottoms[tx] === undefined || bottoms[tx] < ty) { + bottoms[tx] = ty; + } + } + overlaps = 0; + for (tx in bottoms) { + tx = parseInt(tx); + for (ty = bottoms[tx] + 1, i = 0; y + ty < height; ty++, i++) { + if (!game._filled.check(x + tx, y + ty)) { + overlaps += i == 0 ? 2 : 1; //TODO-score better + //if (i == 0) overlaps += 1; + break; } + } + } - function scoreBlocks(possibles, blocks, x, y, filled, width, height) { - var i, len = blocks.length, - score = 0, - bottoms = {}, - tx, ty, overlaps; + score = score - overlaps; - // base score - for (i = 0; i < len; i += 2) { - score += possibles[game._filled.asIndex(x + blocks[i], y + blocks[i + 1])] || 0; - } + return score; + } - // overlap score -- //TODO - don't count overlaps if cleared? - for (i = 0; i < len; i += 2) { - tx = blocks[i]; - ty = blocks[i + 1]; - if (bottoms[tx] === undefined || bottoms[tx] < ty) { - bottoms[tx] = ty; - } - } - overlaps = 0; - for (tx in bottoms) { - tx = parseInt(tx); - for (ty = bottoms[tx] + 1, i = 0; y + ty < height; ty++, i++) { - if (!game._filled.check(x + tx, y + ty)) { - overlaps += i == 0 ? 2 : 1; //TODO-score better - //if (i == 0) overlaps += 1; - break; - } - } - } - - score = score - overlaps; - - return score; + function resetShapes() { + for (var attr in shapes) { + shapes[attr].x = 0; + shapes[attr].y = -1; + } + } + + //TODO -- evil mode needs to realize that overlap is bad... + var func = function( + filled, + checkCollisions, + width, + height, + mode, + _one_shape + ) { + if (!_one_shape) resetShapes(); + + var possibles = new Array(width * height), + evil = mode == "evil", + x, + y, + py, + attr, + shape, + i, + blocks, + bounds, + score, + best_shape, + best_score = (evil ? 1 : -1) * 999, + best_orientation, + best_x, + best_score_for_shape, + best_orientation_for_shape, + best_x_for_shape; + + for (x = 0; x < width; x++) { + for (y = 0; y <= height; y++) { + if (y == height || filled.check(x, y)) { + for (py = y - 4; py < y; py++) { + possibles[filled.asIndex(x, py)] = py; //TODO - figure out better scoring? + } + break; } + } + } - function resetShapes() { - for (var attr in shapes) { - shapes[attr].x = 0; - shapes[attr].y = -1; + // for each shape... + var opts = _one_shape === undefined ? shapes : { cur: _one_shape }; //BOO + for (attr in opts) { + //TODO - check in random order to prevent later shapes from winning + shape = opts[attr]; + best_score_for_shape = -999; + + // for each orientation... + for (i = 0; i < (shape.symmetrical ? 2 : 4); i++) { + //TODO - only look at unique orientations + blocks = shape.getBlocks(i); + bounds = shape.getBounds(blocks); + + // try each possible position... + for (x = -bounds.left; x < width - bounds.width; x++) { + for (y = -1; y < height - bounds.bottom; y++) { + if (game._checkCollisions(x, y + 1, blocks, true)) { + // collision + score = scoreBlocks( + possibles, + blocks, + x, + y, + filled, + width, + height + ); + if (score > best_score_for_shape) { + best_score_for_shape = score; + best_orientation_for_shape = i; + best_x_for_shape = x; + } + break; } + } } + } + + if ( + (evil && best_score_for_shape < best_score) || + (!evil && best_score_for_shape > best_score) + ) { + best_shape = shape; + best_score = best_score_for_shape; + best_orientation = best_orientation_for_shape; + best_x = best_x_for_shape; + } + } - //TODO -- evil mode needs to realize that overlap is bad... - var func = function(filled, checkCollisions, width, height, mode, _one_shape) { - if (!_one_shape) resetShapes(); - - var possibles = new Array(width * height), - evil = mode == 'evil', - x, y, py, - attr, shape, i, blocks, bounds, - score, best_shape, best_score = (evil ? 1 : -1) * 999, - best_orientation, best_x, - best_score_for_shape, best_orientation_for_shape, best_x_for_shape; - - for (x = 0; x < width; x++) { - for (y = 0; y <= height; y++) { - if (y == height || filled.check(x, y)) { - for (py = y - 4; py < y; py++) { - possibles[filled.asIndex(x, py)] = py; //TODO - figure out better scoring? - } - break; - } - } - } - - // for each shape... - var opts = _one_shape === undefined ? shapes : { cur: _one_shape }; //BOO - for (attr in opts) { //TODO - check in random order to prevent later shapes from winning - shape = opts[attr]; - best_score_for_shape = -999; - - // for each orientation... - for (i = 0; i < (shape.symmetrical ? 2 : 4); i++) { //TODO - only look at unique orientations - blocks = shape.getBlocks(i); - bounds = shape.getBounds(blocks); - - // try each possible position... - for (x = -bounds.left; x < width - bounds.width; x++) { - for (y = -1; y < height - bounds.bottom; y++) { - if (game._checkCollisions(x, y + 1, blocks, true)) { - // collision - score = scoreBlocks(possibles, blocks, x, y, filled, width, height); - if (score > best_score_for_shape) { - best_score_for_shape = score; - best_orientation_for_shape = i; - best_x_for_shape = x; - } - break; - } - } - } - } - - if ((evil && best_score_for_shape < best_score) || - (!evil && best_score_for_shape > best_score)) { - best_shape = shape; - best_score = best_score_for_shape; - best_orientation = best_orientation_for_shape; - best_x = best_x_for_shape; - } - } - - best_shape.best_orientation = best_orientation; - best_shape.best_x = best_x; - - return best_shape; - }; - - func.no_preview = true; - return func; - }, + best_shape.best_orientation = best_orientation; + best_shape.best_x = best_x; + return best_shape; + }; - _randomShapes: function() { - // Todo: The shapefuncs should be cached. - var shapeFuncs = []; - $.each(this._shapeFactory, function(k, v) { shapeFuncs.push(v); }); + func.no_preview = true; + return func; + }, - return this._randChoice(shapeFuncs); - }, + _randomShapes: function() { + // Todo: The shapefuncs should be cached. + var shapeFuncs = []; + $.each(this._shapeFactory, function(k, v) { + shapeFuncs.push(v); + }); + return this._randChoice(shapeFuncs); + }, - /** + /** * Controls */ - _setupControls: function(enable) { - - var game = this; - - var moveLeft = function(start) { - if (!start) { game._board.holding.left = null; return; } - if (!game._board.holding.left) { - game._board.cur.moveLeft(); - game._board.holding.left = Date.now(); - game._board.holding.right = null; - } - } - var moveRight = function(start) { - if (!start) { game._board.holding.right = null; return; } - if (!game._board.holding.right) { - game._board.cur.moveRight(); - game._board.holding.right = Date.now(); - game._board.holding.left = null; - } - } - var drop = function(start) { - if (!start) { game._board.holding.drop = null; return; } - if (!game._board.holding.drop) { - game._board.cur.drop(); - game._board.holding.drop = Date.now(); - } - } - var rotateLeft = function() { - game._board.cur.rotate('left'); - } - var rotateRight = function() { - game._board.cur.rotate('right'); - } - - // Handlers: These are used to be able to bind/unbind controls - var handleKeyDown = function(evt) { - if (!game._board.cur) { return true; } - var caught = false; - - caught = true; - if (game.options.asdwKeys) { - switch (evt.keyCode) { - case 65: - /*a*/ - moveLeft(true); - break; - case 68: - /*d*/ - moveRight(true); - break; - case 83: - /*s*/ - drop(true); - break; - case 87: - /*w*/ - game._board.cur.rotate('right'); - break; - } - } - switch (evt.keyCode) { - case 37: - /*left*/ - moveLeft(true); - break; - case 39: - /*right*/ - moveRight(true); - break; - case 40: - /*down*/ - drop(true); - break; - case 38: - /*up*/ - game._board.cur.rotate('right'); - break; - case 88: - /*x*/ - game._board.cur.rotate('right'); - break; - case 90: - /*z*/ - game._board.cur.rotate('left'); - break; - default: - caught = false; - } - if (caught) evt.preventDefault(); - return !caught; - }; - - - var handleKeyUp = function(evt) { - if (!game._board.cur) { return true; } - var caught = false; - - caught = true; - if (game.options.asdwKeys) { - switch (evt.keyCode) { - case 65: - /*a*/ - moveLeft(false); - break; - case 68: - /*d*/ - moveRight(false); - break; - case 83: - /*s*/ - drop(false); - break; - } - } - switch (evt.keyCode) { - case 37: - /*left*/ - moveLeft(false); - break; - case 39: - /*right*/ - moveRight(false); - break; - case 40: - /*down*/ - drop(false); - break; - default: - caught = false; - } - if (caught) evt.preventDefault(); - return !caught; - }; - - function isStopKey(evt) { - var cfg = { - stopKeys: { 37: 1, 38: 1, 39: 1, 40: 1 } - }; - - var isStop = (cfg.stopKeys[evt.keyCode] || (cfg.moreStopKeys && cfg.moreStopKeys[evt.keyCode])); - if (isStop) evt.preventDefault(); - return isStop; - } - - function getKey(evt) { return 'safekeypress.' + evt.keyCode; } - - function keydown(evt) { - var key = getKey(evt); - $.data(this, key, ($.data(this, key) || 0) - 1); - return handleKeyDown.call(this, evt); - } - - function keyup(evt) { - $.data(this, getKey(evt), 0); - handleKeyUp.call(this, evt); - return isStopKey(evt); - } - - // Unbind everything by default - // Use event namespacing so we don't ruin other keypress events - $(document).unbind('keydown.blockrain') - .unbind('keyup.blockrain'); - - if (!game.options.autoplay) { - if (enable) { - $(document).bind('keydown.blockrain', keydown) - .bind('keyup.blockrain', keyup); - } - } - }, - - - _setupTouchControls: function(enable) { - - var game = this; - - // Movements can be held for faster movement - var moveLeft = function(event) { - event.preventDefault(); - game._board.cur.moveLeft(); - game._board.holding.left = Date.now(); - game._board.holding.right = null; - game._board.holding.drop = null; - }; - var moveRight = function(event) { - event.preventDefault(); - game._board.cur.moveRight(); - game._board.holding.right = Date.now(); - game._board.holding.left = null; - game._board.holding.drop = null; - }; - var drop = function(event) { - event.preventDefault(); - game._board.cur.drop(); - game._board.holding.drop = Date.now(); - }; - var endMoveLeft = function(event) { - event.preventDefault(); - game._board.holding.left = null; - }; - var endMoveRight = function(event) { - event.preventDefault(); - game._board.holding.right = null; - }; - var endDrop = function(event) { - event.preventDefault(); - game._board.holding.drop = null; - }; - - // Rotations can't be held - var rotateLeft = function(event) { - event.preventDefault(); - game._board.cur.rotate('left'); - }; - var rotateRight = function(event) { - event.preventDefault(); - game._board.cur.rotate('right'); - }; - - // Unbind everything by default - game._$touchLeft.unbind('touchstart touchend click'); - game._$touchRight.unbind('touchstart touchend click'); - game._$touchRotateLeft.unbind('touchstart touchend click'); - game._$touchRotateRight.unbind('touchstart touchend click'); - game._$touchDrop.unbind('touchstart touchend click'); - - if (!game.options.autoplay && enable) { - game._$touchLeft.show().bind('touchstart click', moveLeft).bind('touchend', endMoveLeft); - game._$touchRight.show().bind('touchstart click', moveRight).bind('touchend', endMoveRight); - game._$touchDrop.show().bind('touchstart click', drop).bind('touchend', endDrop); - game._$touchRotateLeft.show().bind('touchstart click', rotateLeft); - game._$touchRotateRight.show().bind('touchstart click', rotateRight); - } else { - game._$touchLeft.hide(); - game._$touchRight.hide(); - game._$touchRotateLeft.hide(); - game._$touchRotateRight.hide(); - game._$touchDrop.hide(); - } + _setupControls: function(enable) { + var game = this; + var moveLeft = function(start) { + if (!start) { + game._board.holding.left = null; + return; } + if (!game._board.holding.left) { + game._board.cur.moveLeft(); + game._board.holding.left = Date.now(); + game._board.holding.right = null; + } + }; + var moveRight = function(start) { + if (!start) { + game._board.holding.right = null; + return; + } + if (!game._board.holding.right) { + game._board.cur.moveRight(); + game._board.holding.right = Date.now(); + game._board.holding.left = null; + } + }; + var drop = function(start) { + if (!start) { + game._board.holding.drop = null; + return; + } + if (!game._board.holding.drop) { + game._board.cur.drop(); + game._board.holding.drop = Date.now(); + } + }; + var rotateLeft = function() { + game._board.cur.rotate("left"); + }; + var rotateRight = function() { + game._board.cur.rotate("right"); + }; + + // Handlers: These are used to be able to bind/unbind controls + var handleKeyDown = function(evt) { + if (!game._board.cur) { + return true; + } + var caught = false; + + caught = true; + if (game.options.asdwKeys) { + switch (evt.keyCode) { + case 65: + /*a*/ + moveLeft(true); + break; + case 68: + /*d*/ + moveRight(true); + break; + case 83: + /*s*/ + drop(true); + break; + case 87: + /*w*/ + game._board.cur.rotate("right"); + break; + } + } + switch (evt.keyCode) { + case 37: + /*left*/ + moveLeft(true); + break; + case 39: + /*right*/ + moveRight(true); + break; + case 40: + /*down*/ + drop(true); + break; + case 38: + /*up*/ + game._board.cur.rotate("right"); + break; + case 88: + /*x*/ + game._board.cur.rotate("right"); + break; + case 90: + /*z*/ + game._board.cur.rotate("left"); + break; + default: + caught = false; + } + if (caught) evt.preventDefault(); + return !caught; + }; - }); - -})(jQuery)); \ No newline at end of file + var handleKeyUp = function(evt) { + if (!game._board.cur) { + return true; + } + var caught = false; + + caught = true; + if (game.options.asdwKeys) { + switch (evt.keyCode) { + case 65: + /*a*/ + moveLeft(false); + break; + case 68: + /*d*/ + moveRight(false); + break; + case 83: + /*s*/ + drop(false); + break; + } + } + switch (evt.keyCode) { + case 37: + /*left*/ + moveLeft(false); + break; + case 39: + /*right*/ + moveRight(false); + break; + case 40: + /*down*/ + drop(false); + break; + default: + caught = false; + } + if (caught) evt.preventDefault(); + return !caught; + }; + + function isStopKey(evt) { + var cfg = { + stopKeys: { 37: 1, 38: 1, 39: 1, 40: 1 } + }; + + var isStop = + cfg.stopKeys[evt.keyCode] || + (cfg.moreStopKeys && cfg.moreStopKeys[evt.keyCode]); + if (isStop) evt.preventDefault(); + return isStop; + } + + function getKey(evt) { + return "safekeypress." + evt.keyCode; + } + + function keydown(evt) { + var key = getKey(evt); + $.data(this, key, ($.data(this, key) || 0) - 1); + return handleKeyDown.call(this, evt); + } + + function keyup(evt) { + $.data(this, getKey(evt), 0); + handleKeyUp.call(this, evt); + return isStopKey(evt); + } + + // Unbind everything by default + // Use event namespacing so we don't ruin other keypress events + $(document).unbind("keydown.blockrain").unbind("keyup.blockrain"); + + if (!game.options.autoplay) { + if (enable) { + $(document) + .bind("keydown.blockrain", keydown) + .bind("keyup.blockrain", keyup); + } + } + }, + + _setupTouchControls: function(enable) { + var game = this; + + // Movements can be held for faster movement + var moveLeft = function(event) { + event.preventDefault(); + game._board.cur.moveLeft(); + game._board.holding.left = Date.now(); + game._board.holding.right = null; + game._board.holding.drop = null; + }; + var moveRight = function(event) { + event.preventDefault(); + game._board.cur.moveRight(); + game._board.holding.right = Date.now(); + game._board.holding.left = null; + game._board.holding.drop = null; + }; + var drop = function(event) { + event.preventDefault(); + game._board.cur.drop(); + game._board.holding.drop = Date.now(); + }; + var endMoveLeft = function(event) { + event.preventDefault(); + game._board.holding.left = null; + }; + var endMoveRight = function(event) { + event.preventDefault(); + game._board.holding.right = null; + }; + var endDrop = function(event) { + event.preventDefault(); + game._board.holding.drop = null; + }; + + // Rotations can't be held + var rotateLeft = function(event) { + event.preventDefault(); + game._board.cur.rotate("left"); + }; + var rotateRight = function(event) { + event.preventDefault(); + game._board.cur.rotate("right"); + }; + + // Unbind everything by default + game._$touchLeft.unbind("touchstart touchend click"); + game._$touchRight.unbind("touchstart touchend click"); + game._$touchRotateLeft.unbind("touchstart touchend click"); + game._$touchRotateRight.unbind("touchstart touchend click"); + game._$touchDrop.unbind("touchstart touchend click"); + + if (!game.options.autoplay && enable) { + game._$touchLeft + .show() + .bind("touchstart click", moveLeft) + .bind("touchend", endMoveLeft); + game._$touchRight + .show() + .bind("touchstart click", moveRight) + .bind("touchend", endMoveRight); + game._$touchDrop + .show() + .bind("touchstart click", drop) + .bind("touchend", endDrop); + game._$touchRotateLeft.show().bind("touchstart click", rotateLeft); + game._$touchRotateRight.show().bind("touchstart click", rotateRight); + } else { + game._$touchLeft.hide(); + game._$touchRight.hide(); + game._$touchRotateLeft.hide(); + game._$touchRotateRight.hide(); + game._$touchDrop.hide(); + } + } + }); +})(jQuery); From 17a229e6cc62e345eefb70b47ee7a2054edf2942 Mon Sep 17 00:00:00 2001 From: Micael Robles Date: Sun, 6 Aug 2017 19:30:42 -0300 Subject: [PATCH 07/10] fix indentation --- src/blockrain.jquery.src.js | 1507 +++++++++++++---------------------- 1 file changed, 546 insertions(+), 961 deletions(-) diff --git a/src/blockrain.jquery.src.js b/src/blockrain.jquery.src.js index 0480f9d..7fa74e0 100644 --- a/src/blockrain.jquery.src.js +++ b/src/blockrain.jquery.src.js @@ -1,7 +1,9 @@ -(function($) { +((function ( $ ) { + "use strict"; - $.widget("aerolab.blockrain", { + $.widget('aerolab.blockrain', { + options: { autoplay: false, // Let a bot play the game autoplayRestart: true, // Restart the game automatically once a bot loses @@ -10,31 +12,32 @@ blockWidth: 10, // How many blocks wide the field is (The standard is 10 blocks) autoBlockWidth: false, // The blockWidth is dinamically calculated based on the autoBlockSize. Disabled blockWidth. Useful for responsive backgrounds autoBlockSize: 24, // The max size of a block for autowidth mode - difficulty: "normal", // Difficulty (normal|nice|evil). + difficulty: 'normal', // Difficulty (normal|nice|evil). speed: 20, // The speed of the game. The higher, the faster the pieces go. asdwKeys: true, // Enable ASDW keys // Copy - playText: "Let's play some Tetris", - playButtonText: "Play", - gameOverText: "Game Over", - restartButtonText: "Play Again", - scoreText: "Score", + playText: 'Let\'s play some Tetris', + playButtonText: 'Play', + gameOverText: 'Game Over', + restartButtonText: 'Play Again', + scoreText: 'Score', // Basic Callbacks - onStart: function() {}, - onRestart: function() {}, - onGameOver: function(score) {}, + onStart: function(){}, + onRestart: function(){}, + onGameOver: function(score){}, // When a block is placed - onPlaced: function() {}, + onPlaced: function(){}, // When a line is made. Returns the number of lines, score assigned and total score - onLine: function(lines, scoreIncrement, score) {} + onLine: function(lines, scoreIncrement, score){} }, + /** - * Start/Restart Game - */ + * Start/Restart Game + */ start: function() { this._doStart(); this.options.onStart.call(this.element); @@ -66,6 +69,7 @@ this._$score.fadeIn(150); }, + pause: function() { this._board.paused = true; }, @@ -75,35 +79,29 @@ }, autoplay: function(enable) { - if (typeof enable !== "boolean") { - enable = true; - } + if( typeof enable !== 'boolean' ){ enable = true; } // On autoplay, start the game right away this.options.autoplay = enable; - if (enable && !this._board.started) { + if( enable && ! this._board.started ) { this._doStart(); } - this._setupControls(!enable); - this._setupTouchControls(!enable); + this._setupControls( ! enable ); + this._setupTouchControls( ! enable ); }, controls: function(enable) { - if (typeof enable !== "boolean") { - enable = true; - } + if( typeof enable !== 'boolean' ){ enable = true; } this._setupControls(enable); }, touchControls: function(enable) { - if (typeof enable !== "boolean") { - enable = true; - } + if( typeof enable !== 'boolean' ){ enable = true; } this._setupTouchControls(enable); }, score: function(newScore) { - if (typeof newScore !== "undefined" && parseInt(newScore) >= 0) { + if( typeof newScore !== 'undefined' && parseInt(newScore) >= 0 ) { this._filled.score = parseInt(newScore); this._$scoreText.text(this._filled_score); } @@ -123,18 +121,15 @@ }, /** - * Update the sizes of the renderer (this makes the game responsive) - */ + * Update the sizes of the renderer (this makes the game responsive) + */ updateSizes: function() { + this._PIXEL_WIDTH = this.element.innerWidth(); this._PIXEL_HEIGHT = this.element.innerHeight(); this._BLOCK_WIDTH = this.options.blockWidth; - this._BLOCK_HEIGHT = Math.floor( - this.element.innerHeight() / - this.element.innerWidth() * - this._BLOCK_WIDTH - ); + this._BLOCK_HEIGHT = Math.floor(this.element.innerHeight() / this.element.innerWidth() * this._BLOCK_WIDTH); this._block_size = Math.floor(this._PIXEL_WIDTH / this._BLOCK_WIDTH); this._border_width = 2; @@ -143,50 +138,53 @@ this._PIXEL_WIDTH = this._block_size * this._BLOCK_WIDTH; this._PIXEL_HEIGHT = this._block_size * this._BLOCK_HEIGHT; - this._$canvas - .attr("width", this._PIXEL_WIDTH) - .attr("height", this._PIXEL_HEIGHT); + this._$canvas .attr('width', this._PIXEL_WIDTH) + .attr('height', this._PIXEL_HEIGHT); }, - theme: function(newTheme) { - if (typeof newTheme === "undefined") { + + theme: function(newTheme){ + + if( typeof newTheme === 'undefined' ) { return this.options.theme || this._theme; } // Setup the theme properly - if (typeof newTheme === "string") { + if( typeof newTheme === 'string' ) { this.options.theme = newTheme; this._theme = $.extend(true, {}, BlockrainThemes[newTheme]); - } else { + } + else { this.options.theme = null; this._theme = newTheme; } - if (typeof this._theme === "undefined" || this._theme === null) { - this._theme = $.extend(true, {}, BlockrainThemes["retro"]); - this.options.theme = "retro"; + if( typeof this._theme === 'undefined' || this._theme === null ) { + this._theme = $.extend(true, {}, BlockrainThemes['retro']); + this.options.theme = 'retro'; } - if ( - isNaN(parseInt(this._theme.strokeWidth)) || - typeof parseInt(this._theme.strokeWidth) !== "number" - ) { + if( isNaN(parseInt(this._theme.strokeWidth)) || typeof parseInt(this._theme.strokeWidth) !== 'number' ) { this._theme.strokeWidth = 2; } // Load the image assets this._preloadThemeAssets(); - if (this._board !== null) { - if (typeof this._theme.background === "string") { - this._$canvas.css("background-color", this._theme.background); + if( this._board !== null ) { + if( typeof this._theme.background === 'string' ) { + this._$canvas.css('background-color', this._theme.background); } this._board.render(); } }, + // Theme - _theme: {}, + _theme: { + + }, + // UI Elements _$game: null, @@ -197,12 +195,15 @@ _$score: null, _$scoreText: null, + // Canvas _canvas: null, _ctx: null, + // Initialization _create: function() { + var game = this; this.theme(this.options.theme); @@ -214,7 +215,7 @@ this.updateSizes(); - $(window).resize(function() { + $(window).resize(function(){ //game.updateSizes(); }); @@ -226,205 +227,194 @@ this._info.init(); this._board.init(); - var renderLoop = function() { + var renderLoop = function(){ requestAnimationFrame(renderLoop); game._board.render(); }; renderLoop(); - if (this.options.autoplay) { + if( this.options.autoplay ) { this.autoplay(true); this._setupTouchControls(false); } else { this._setupControls(true); this._setupTouchControls(false); } + }, _checkCollisions: function(x, y, blocks, checkDownOnly) { // x & y should be aspirational values - var i = 0, - len = blocks.length, - a, - b; - for (; i < len; i += 2) { + var i = 0, len = blocks.length, a, b; + for (; i= this._BLOCK_HEIGHT || this._filled.check(a, b)) { return true; - } else if ((!checkDownOnly && a < 0) || a >= this._BLOCK_WIDTH) { + } else if (!checkDownOnly && a < 0 || a >= this._BLOCK_WIDTH) { return true; } } return false; }, + _board: null, _info: null, _filled: null, + /** - * Draws the background - */ + * Draws the background + */ _drawBackground: function() { - if (typeof this._theme.background !== "string") { + + if( typeof this._theme.background !== 'string' ) { return; } - if (this._theme.backgroundGrid instanceof Image) { + if( this._theme.backgroundGrid instanceof Image ) { + // Not loaded - if ( - this._theme.backgroundGrid.width === 0 || - this._theme.backgroundGrid.height === 0 - ) { - return; - } + if( this._theme.backgroundGrid.width === 0 || this._theme.backgroundGrid.height === 0 ){ return; } this._ctx.globalAlpha = 1.0; - for (var x = 0; x < this._BLOCK_WIDTH; x++) { - for (var y = 0; y < this._BLOCK_HEIGHT; y++) { + for( var x=0; x= game._BLOCK_WIDTH - 2) { - this.x--; - } - while (this.x < 0) { - this.x++; - } - - if (this.blockType === "line" && this.x === 0) this.x++; - - if ( - game._checkCollisions( - this.x, - this.y, - this.getBlocks(orientation) - ) - ) { - this.y--; - if ( - game._checkCollisions( - this.x, - this.y, - this.getBlocks(orientation) - ) - ) { - this.x = ogX; - this.y = ogY; - this.orientation = ogOrientation; - } - } game._board.renderChanged = true; } }, @@ -519,54 +466,29 @@ } }, - getBlocks: function(orientation) { - // optional param - return this.orientations[ - orientation !== undefined ? orientation : this.orientation - ]; + getBlocks: function(orientation) { // optional param + return this.orientations[orientation !== undefined ? orientation : this.orientation]; }, draw: function(_x, _y, _orientation) { var blocks = this.getBlocks(_orientation), - x = _x === undefined ? this.x : _x, - y = _y === undefined ? this.y : _y, - i = 0, - index = 0; - - for (; i < this.blocksLen; i += 2) { - game._board.drawBlock( - x + blocks[i], - y + blocks[i + 1], - this.blockType, - this.blockVariation, - index, - this.orientation, - true - ); + x = _x === undefined ? this.x : _x, + y = _y === undefined ? this.y : _y, + i = 0, + index = 0; + + for (; i maxx) { - maxx = blocks[i]; - } - if (blocks[i + 1] < miny) { - miny = blocks[i + 1]; - } - if (blocks[i + 1] > maxy) { - maxy = blocks[i + 1]; - } + i=0, len=blocks.length, minx=999, maxx=-999, miny=999, maxy=-999; + for (; i maxx) { maxx = blocks[i]; } + if (blocks[i+1] < miny) { miny = blocks[i+1]; } + if (blocks[i+1] > maxy) { maxy = blocks[i+1]; } } return { left: minx, @@ -580,38 +502,37 @@ }); return this.init(); - } + }; this._shapeFactory = { line: function() { - return new Shape(game, game._shapes.line, false, "line"); + return new Shape(game, game._shapes.line, false, 'line'); }, square: function() { - return new Shape(game, game._shapes.square, false, "square"); + return new Shape(game, game._shapes.square, false, 'square'); }, arrow: function() { - return new Shape(game, game._shapes.arrow, false, "arrow"); + return new Shape(game, game._shapes.arrow, false, 'arrow'); }, leftHook: function() { - return new Shape(game, game._shapes.leftHook, false, "leftHook"); + return new Shape(game, game._shapes.leftHook, false, 'leftHook'); }, rightHook: function() { - return new Shape(game, game._shapes.rightHook, false, "rightHook"); + return new Shape(game, game._shapes.rightHook, false, 'rightHook'); }, leftZag: function() { - return new Shape(game, game._shapes.leftZag, false, "leftZag"); + return new Shape(game, game._shapes.leftZag, false, 'leftZag'); }, rightZag: function() { - return new Shape(game, game._shapes.rightZag, false, "rightZag"); + return new Shape(game, game._shapes.rightZag, false, 'rightZag'); } }; }, + _SetupFilled: function() { var game = this; - if (this._filled !== null) { - return; - } + if( this._filled !== null ){ return; } this._filled = { data: new Array(game._BLOCK_WIDTH * game._BLOCK_HEIGHT), @@ -620,36 +541,24 @@ check: function(x, y) { return this.data[this.asIndex(x, y)]; }, - add: function( - x, - y, - blockType, - blockVariation, - blockIndex, - blockOrientation - ) { - if ( - x >= 0 && - x < game._BLOCK_WIDTH && - y >= 0 && - y < game._BLOCK_HEIGHT - ) { + add: function(x, y, blockType, blockVariation, blockIndex, blockOrientation) { + if (x >= 0 && x < game._BLOCK_WIDTH && y >= 0 && y < game._BLOCK_HEIGHT) { this.data[this.asIndex(x, y)] = { - blockType: blockType, - blockVariation: blockVariation, - blockIndex: blockIndex, + blockType: blockType, + blockVariation: blockVariation, + blockIndex: blockIndex, blockOrientation: blockOrientation }; } }, getFreeSpaces: function() { var count = 0; - for (var i = 0; i < this.data.length; i++) { - count += this.data[i] ? 1 : 0; + for( var i=0; i= 0; i--) { - this.data[i] = - i >= game._BLOCK_WIDTH - ? this.data[i - game._BLOCK_WIDTH] - : undefined; + for (var i=game._BLOCK_WIDTH*(row_to_pop+1) - 1; i>=0; i--) { + this.data[i] = (i >= game._BLOCK_WIDTH ? this.data[i-game._BLOCK_WIDTH] : undefined); } }, checkForClears: function() { var startLines = game._board.lines; - var rows = [], - i, - len, - count, - mod; + var rows = [], i, len, count, mod; - for (i = 0, len = this.data.length; i < len; i++) { + for (i=0, len=this.data.length; i 1) { + if( game._board.lines % 10 == 0 && game._board.dropDelay > 1 ) { game._board.dropDelay *= 0.9; } } @@ -704,67 +602,60 @@ this._updateScore(clearedLines); }, _updateScore: function(numLines) { - if (numLines <= 0) { - return; - } - var scores = [0, 400, 1000, 3000, 12000]; - if (numLines >= scores.length) { - numLines = scores.length - 1; - } + if( numLines <= 0 ) { return; } + var scores = [0,400,1000,3000,12000]; + if( numLines >= scores.length ){ numLines = scores.length-1 } this.score += scores[numLines]; game._$scoreText.text(this.score); - game.options.onLine.call( - game.element, - numLines, - scores[numLines], - this.score - ); + game.options.onLine.call(game.element, numLines, scores[numLines], this.score); }, _resetScore: function() { this.score = 0; game._$scoreText.text(this.score); }, draw: function() { - for (var i = 0, len = this.data.length, row, color; i < len; i++) { + for (var i=0, len=this.data.length, row, color; i= this.dropDelay || - game.options.autoplay || - (this.holding.drop && - now - this.holding.drop >= this.holdingThreshold) - ) { + if( (this.dropCount >= this.dropDelay) || + (game.options.autoplay) || + (this.holding.drop && (now - this.holding.drop) >= this.holdingThreshold) ) { drop = true; - moved = true; + moved = true; this.dropCount = 0; } // Move Left by holding - if ( - this.holding.left && - now - this.holding.left >= this.holdingThreshold - ) { + if( this.holding.left && (now - this.holding.left) >= this.holdingThreshold ) { moved = true; this.cur.moveLeft(); } // Move Right by holding - if ( - this.holding.right && - now - this.holding.right >= this.holdingThreshold - ) { + if( this.holding.right && (now - this.holding.right) >= this.holdingThreshold ) { moved = true; this.cur.moveRight(); } // Test for a collision, add the piece to the filled blocks and fetch the next one if (drop) { - var cur = this.cur, - x = cur.x, - y = cur.y, - blocks = cur.getBlocks(); - if (game._checkCollisions(x, y + 1, blocks, true)) { + var cur = this.cur, x = cur.x, y = cur.y, blocks = cur.getBlocks(); + if (game._checkCollisions(x, y+1, blocks, true)) { drop = false; var blockIndex = 0; - for (var i = 0; i < cur.blocksLen; i += 2) { - game._filled.add( - x + blocks[i], - y + blocks[i + 1], - cur.blockType, - cur.blockVariation, - blockIndex, - cur.orientation - ); + for (var i=0; i 0) { + } + else if(blockTheme.length > 0) { return blockTheme[0]; } else { return null; @@ -1302,88 +1042,59 @@ } else { return blockTheme; } - }; - - if (typeof falling !== "boolean") { - falling = true; } - if (falling) { - if ( - typeof game._theme.primary === "string" && - game._theme.primary !== "" - ) { + + if( typeof falling !== 'boolean' ){ falling = true; } + if( falling ) { + if( typeof game._theme.primary === 'string' && game._theme.primary !== '' ) { return game._theme.primary; - } else if ( - typeof game._theme.blocks !== "undefined" && - game._theme.blocks !== null - ) { - return getBlockVariation( - game._theme.blocks[blockType], - blockVariation - ); + } else if( typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null ) { + return getBlockVariation(game._theme.blocks[blockType], blockVariation); } else { - return getBlockVariation( - game._theme.complexBlocks[blockType], - blockVariation - ); + return getBlockVariation(game._theme.complexBlocks[blockType], blockVariation); } } else { - if ( - typeof game._theme.secondary === "string" && - game._theme.secondary !== "" - ) { + if( typeof game._theme.secondary === 'string' && game._theme.secondary !== '' ) { return game._theme.secondary; - } else if ( - typeof game._theme.blocks !== "undefined" && - game._theme.blocks !== null - ) { - return getBlockVariation( - game._theme.blocks[blockType], - blockVariation - ); + } else if( typeof game._theme.blocks !== 'undefined' && game._theme.blocks !== null ) { + return getBlockVariation(game._theme.blocks[blockType], blockVariation); } else { - return getBlockVariation( - game._theme.complexBlocks[blockType], - blockVariation - ); + return getBlockVariation(game._theme.complexBlocks[blockType], blockVariation); } } } + }; game._niceShapes = game._getNiceShapes(); }, // Utility Functions - _randInt: function(a, b) { - return a + Math.floor(Math.random() * (1 + b - a)); - }, - _randSign: function() { - return this._randInt(0, 1) * 2 - 1; - }, - _randChoice: function(choices) { - return choices[this._randInt(0, choices.length - 1)]; - }, + _randInt: function(a, b) { return a + Math.floor(Math.random() * (1 + b - a)); }, + _randSign: function() { return this._randInt(0, 1) * 2 - 1; }, + _randChoice: function(choices) { return choices[this._randInt(0, choices.length-1)]; }, + /** - * Find base64 encoded images and load them as image objects, which can be used by the canvas renderer - */ + * Find base64 encoded images and load them as image objects, which can be used by the canvas renderer + */ _preloadThemeAssets: function() { + var game = this; - var hexColorcheck = new RegExp("^#[A-F0-9+]{3,6}", "i"); - var base64check = new RegExp("^data:image/(png|gif|jpg);base64,", "i"); + var hexColorcheck = new RegExp('^#[A-F0-9+]{3,6}', 'i'); + var base64check = new RegExp('^data:image/(png|gif|jpg);base64,', 'i'); var handleAssetLoad = function() { // Rerender the board as soon as an asset loads - if (game._board) { + if( game._board ) { game._board.render(true); } }; var loadAsset = function(src) { var plainSrc = src; - if (!hexColorcheck.test(plainSrc)) { + if( ! hexColorcheck.test( plainSrc ) ) { // It's an image src = new Image(); src.src = plainSrc; @@ -1397,40 +1108,39 @@ var startAssetLoad = function(block) { // Assets can be an array of variation so they can change color/design randomly - if ($.isArray(block) && block.length > 0) { - for (var i = 0; i < block.length; i++) { + if( $.isArray(block) && block.length > 0 ) { + for( var i=0; i
'); - this._$gameholder - .css("position", "relative") - .css("width", "100%") - .css("height", "100%"); + this._$gameholder.css('position', 'relative').css('width', '100%').css('height', '100%'); - this.element.html("").append(this._$gameholder); + this.element.html('').append(this._$gameholder); // Create the game canvas and context - this._$canvas = $( - '' - ); - if (typeof this._theme.background === "string") { - this._$canvas.css("background-color", this._theme.background); + this._$canvas = $(''); + if( typeof this._theme.background === 'string' ) { + this._$canvas.css('background-color', this._theme.background); } this._$gameholder.append(this._$canvas); this._canvas = this._$canvas.get(0); - this._ctx = this._canvas.getContext("2d"); + this._ctx = this._canvas.getContext('2d'); + }, + _createUI: function() { + var game = this; // Score game._$score = $( - '
' + - '
' + - '
' + - this.options.scoreText + - "
" + - '
0
' + - "
" + - "
" - ).hide(); - game._$scoreText = game._$score.find(".blockrain-score-num"); + '
'+ + '
'+ + '
'+ this.options.scoreText +'
'+ + '
0
'+ + '
'+ + '
').hide(); + game._$scoreText = game._$score.find('.blockrain-score-num'); game._$gameholder.append(game._$score); // Create the start menu game._$start = $( - '
" - ).hide(); + '
'+ + '
'+ + '
'+ this.options.playText +'
'+ + ''+ this.options.playButtonText +''+ + '
'+ + '
').hide(); game._$gameholder.append(game._$start); - game._$start.find(".blockrain-start-btn").click(function(event) { + game._$start.find('.blockrain-start-btn').click(function(event){ event.preventDefault(); game.start(); }); // Create the game over menu game._$gameover = $( - '
' + - '
' + - '
' + - this.options.gameOverText + - "
" + - '' + - this.options.restartButtonText + - "" + - "
" + - "
" - ).hide(); - game._$gameover.find(".blockrain-game-over-btn").click(function(event) { + '
'+ + '
'+ + '
'+ this.options.gameOverText +'
'+ + ''+ this.options.restartButtonText +''+ + '
'+ + '
').hide(); + game._$gameover.find('.blockrain-game-over-btn').click(function(event){ event.preventDefault(); game.restart(); }); @@ -1522,70 +1220,57 @@ this._createControls(); }, + _createControls: function() { + var game = this; - game._$touchLeft = $( - '' - ).appendTo(game._$gameholder); - game._$touchRight = $( - '' - ).appendTo(game._$gameholder); - game._$touchRotateRight = $( - '' - ).appendTo(game._$gameholder); - game._$touchRotateLeft = $( - '' - ).appendTo(game._$gameholder); - game._$touchDrop = $( - '' - ).appendTo(game._$gameholder); + game._$touchLeft = $('').appendTo(game._$gameholder); + game._$touchRight = $('').appendTo(game._$gameholder); + game._$touchRotateRight = $('').appendTo(game._$gameholder); + game._$touchRotateLeft = $('').appendTo(game._$gameholder); + game._$touchDrop = $('').appendTo(game._$gameholder); + }, + _refreshBlockSizes: function() { - if (this.options.autoBlockWidth) { - this.options.blockWidth = Math.ceil( - this.element.width() / this.options.autoBlockSize - ); + + if( this.options.autoBlockWidth ) { + this.options.blockWidth = Math.ceil( this.element.width() / this.options.autoBlockSize ); } + }, + _getNiceShapes: function() { /* - * Things I need for this to work... - * - ability to test each shape with this._filled data - * - maybe give empty spots scores? and try to maximize the score? - */ + * Things I need for this to work... + * - ability to test each shape with this._filled data + * - maybe give empty spots scores? and try to maximize the score? + */ var game = this; var shapes = {}, - attr; + attr; - for (var attr in this._shapeFactory) { + for( var attr in this._shapeFactory ) { shapes[attr] = this._shapeFactory[attr](); } function scoreBlocks(possibles, blocks, x, y, filled, width, height) { - var i, - len = blocks.length, - score = 0, - bottoms = {}, - tx, - ty, - overlaps; + var i, len=blocks.length, score=0, bottoms = {}, tx, ty, overlaps; // base score - for (i = 0; i < len; i += 2) { - score += - possibles[game._filled.asIndex(x + blocks[i], y + blocks[i + 1])] || - 0; + for (i=0; i best_score_for_shape) { best_score_for_shape = score; best_orientation_for_shape = i; @@ -1693,10 +1349,8 @@ } } - if ( - (evil && best_score_for_shape < best_score) || - (!evil && best_score_for_shape > best_score) - ) { + if ((evil && best_score_for_shape < best_score) || + (!evil && best_score_for_shape > best_score)) { best_shape = shape; best_score = best_score_for_shape; best_orientation = best_orientation_for_shape; @@ -1714,159 +1368,98 @@ return func; }, + _randomShapes: function() { // Todo: The shapefuncs should be cached. var shapeFuncs = []; - $.each(this._shapeFactory, function(k, v) { - shapeFuncs.push(v); - }); + $.each(this._shapeFactory, function(k,v) { shapeFuncs.push(v); }); return this._randChoice(shapeFuncs); }, + /** - * Controls - */ + * Controls + */ _setupControls: function(enable) { + var game = this; var moveLeft = function(start) { - if (!start) { - game._board.holding.left = null; - return; - } - if (!game._board.holding.left) { - game._board.cur.moveLeft(); + if( ! start ) { game._board.holding.left = null; return; } + if( ! game._board.holding.left ) { + game._board.cur.moveLeft(); game._board.holding.left = Date.now(); - game._board.holding.right = null; + game._board.holding.right = null; } - }; + } var moveRight = function(start) { - if (!start) { - game._board.holding.right = null; - return; - } - if (!game._board.holding.right) { - game._board.cur.moveRight(); - game._board.holding.right = Date.now(); - game._board.holding.left = null; + if( ! start ) { game._board.holding.right = null; return; } + if( ! game._board.holding.right ) { + game._board.cur.moveRight(); + game._board.holding.right = Date.now(); + game._board.holding.left = null; } - }; + } var drop = function(start) { - if (!start) { - game._board.holding.drop = null; - return; - } - if (!game._board.holding.drop) { - game._board.cur.drop(); + if( ! start ) { game._board.holding.drop = null; return; } + if( ! game._board.holding.drop ) { + game._board.cur.drop(); game._board.holding.drop = Date.now(); } - }; + } var rotateLeft = function() { - game._board.cur.rotate("left"); - }; + game._board.cur.rotate('left'); + } var rotateRight = function() { - game._board.cur.rotate("right"); - }; + game._board.cur.rotate('right'); + } // Handlers: These are used to be able to bind/unbind controls var handleKeyDown = function(evt) { - if (!game._board.cur) { - return true; - } + if( ! game._board.cur ) { return true; } var caught = false; caught = true; if (game.options.asdwKeys) { - switch (evt.keyCode) { - case 65: - /*a*/ - moveLeft(true); - break; - case 68: - /*d*/ - moveRight(true); - break; - case 83: - /*s*/ - drop(true); - break; - case 87: - /*w*/ - game._board.cur.rotate("right"); - break; + switch(evt.keyCode) { + case 65: /*a*/ moveLeft(true); break; + case 68: /*d*/ moveRight(true); break; + case 83: /*s*/ drop(true); break; + case 87: /*w*/ game._board.cur.rotate('right'); break; } } - switch (evt.keyCode) { - case 37: - /*left*/ - moveLeft(true); - break; - case 39: - /*right*/ - moveRight(true); - break; - case 40: - /*down*/ - drop(true); - break; - case 38: - /*up*/ - game._board.cur.rotate("right"); - break; - case 88: - /*x*/ - game._board.cur.rotate("right"); - break; - case 90: - /*z*/ - game._board.cur.rotate("left"); - break; - default: - caught = false; + switch(evt.keyCode) { + case 37: /*left*/ moveLeft(true); break; + case 39: /*right*/ moveRight(true); break; + case 40: /*down*/ drop(true); break; + case 38: /*up*/ game._board.cur.rotate('right'); break; + case 88: /*x*/ game._board.cur.rotate('right'); break; + case 90: /*z*/ game._board.cur.rotate('left'); break; + default: caught = false; } if (caught) evt.preventDefault(); return !caught; }; + var handleKeyUp = function(evt) { - if (!game._board.cur) { - return true; - } + if( ! game._board.cur ) { return true; } var caught = false; caught = true; if (game.options.asdwKeys) { - switch (evt.keyCode) { - case 65: - /*a*/ - moveLeft(false); - break; - case 68: - /*d*/ - moveRight(false); - break; - case 83: - /*s*/ - drop(false); - break; + switch(evt.keyCode) { + case 65: /*a*/ moveLeft(false); break; + case 68: /*d*/ moveRight(false); break; + case 83: /*s*/ drop(false); break; } } - switch (evt.keyCode) { - case 37: - /*left*/ - moveLeft(false); - break; - case 39: - /*right*/ - moveRight(false); - break; - case 40: - /*down*/ - drop(false); - break; - default: - caught = false; + switch(evt.keyCode) { + case 37: /*left*/ moveLeft(false); break; + case 39: /*right*/ moveRight(false); break; + case 40: /*down*/ drop(false); break; + default: caught = false; } if (caught) evt.preventDefault(); return !caught; @@ -1874,19 +1467,15 @@ function isStopKey(evt) { var cfg = { - stopKeys: { 37: 1, 38: 1, 39: 1, 40: 1 } + stopKeys: {37:1, 38:1, 39:1, 40:1} }; - var isStop = - cfg.stopKeys[evt.keyCode] || - (cfg.moreStopKeys && cfg.moreStopKeys[evt.keyCode]); + var isStop = (cfg.stopKeys[evt.keyCode] || (cfg.moreStopKeys && cfg.moreStopKeys[evt.keyCode])); if (isStop) evt.preventDefault(); return isStop; } - function getKey(evt) { - return "safekeypress." + evt.keyCode; - } + function getKey(evt) { return 'safekeypress.' + evt.keyCode; } function keydown(evt) { var key = getKey(evt); @@ -1902,85 +1491,78 @@ // Unbind everything by default // Use event namespacing so we don't ruin other keypress events - $(document).unbind("keydown.blockrain").unbind("keyup.blockrain"); + $(document) .unbind('keydown.blockrain') + .unbind('keyup.blockrain'); - if (!game.options.autoplay) { - if (enable) { - $(document) - .bind("keydown.blockrain", keydown) - .bind("keyup.blockrain", keyup); + if( ! game.options.autoplay ) { + if( enable ) { + $(document) .bind('keydown.blockrain', keydown) + .bind('keyup.blockrain', keyup); } } }, + _setupTouchControls: function(enable) { + var game = this; // Movements can be held for faster movement - var moveLeft = function(event) { + var moveLeft = function(event){ event.preventDefault(); game._board.cur.moveLeft(); game._board.holding.left = Date.now(); game._board.holding.right = null; game._board.holding.drop = null; }; - var moveRight = function(event) { + var moveRight = function(event){ event.preventDefault(); game._board.cur.moveRight(); game._board.holding.right = Date.now(); game._board.holding.left = null; game._board.holding.drop = null; }; - var drop = function(event) { + var drop = function(event){ event.preventDefault(); game._board.cur.drop(); game._board.holding.drop = Date.now(); }; - var endMoveLeft = function(event) { + var endMoveLeft = function(event){ event.preventDefault(); game._board.holding.left = null; }; - var endMoveRight = function(event) { + var endMoveRight = function(event){ event.preventDefault(); game._board.holding.right = null; }; - var endDrop = function(event) { + var endDrop = function(event){ event.preventDefault(); game._board.holding.drop = null; }; // Rotations can't be held - var rotateLeft = function(event) { + var rotateLeft = function(event){ event.preventDefault(); - game._board.cur.rotate("left"); + game._board.cur.rotate('left'); }; - var rotateRight = function(event) { + var rotateRight = function(event){ event.preventDefault(); - game._board.cur.rotate("right"); + game._board.cur.rotate('right'); }; // Unbind everything by default - game._$touchLeft.unbind("touchstart touchend click"); - game._$touchRight.unbind("touchstart touchend click"); - game._$touchRotateLeft.unbind("touchstart touchend click"); - game._$touchRotateRight.unbind("touchstart touchend click"); - game._$touchDrop.unbind("touchstart touchend click"); - - if (!game.options.autoplay && enable) { - game._$touchLeft - .show() - .bind("touchstart click", moveLeft) - .bind("touchend", endMoveLeft); - game._$touchRight - .show() - .bind("touchstart click", moveRight) - .bind("touchend", endMoveRight); - game._$touchDrop - .show() - .bind("touchstart click", drop) - .bind("touchend", endDrop); - game._$touchRotateLeft.show().bind("touchstart click", rotateLeft); - game._$touchRotateRight.show().bind("touchstart click", rotateRight); + game._$touchLeft.unbind('touchstart touchend click'); + game._$touchRight.unbind('touchstart touchend click'); + game._$touchRotateLeft.unbind('touchstart touchend click'); + game._$touchRotateRight.unbind('touchstart touchend click'); + game._$touchDrop.unbind('touchstart touchend click'); + + if( ! game.options.autoplay && enable ) { + game._$touchLeft.show().bind('touchstart click', moveLeft).bind('touchend', endMoveLeft); + game._$touchRight.show().bind('touchstart click', moveRight).bind('touchend', endMoveRight); + game._$touchDrop.show().bind('touchstart click', drop).bind('touchend', endDrop); + game._$touchRotateLeft.show().bind('touchstart click', rotateLeft); + game._$touchRotateRight.show().bind('touchstart click', rotateRight); } else { game._$touchLeft.hide(); game._$touchRight.hide(); @@ -1988,6 +1570,9 @@ game._$touchRotateRight.hide(); game._$touchDrop.hide(); } + } + }); -})(jQuery); + +})(jQuery)); \ No newline at end of file From 9632a46f07b482ec2e962a5cfe53abbe1ec84313 Mon Sep 17 00:00:00 2001 From: Micael Robles Date: Sun, 6 Aug 2017 19:33:39 -0300 Subject: [PATCH 08/10] fix indentation --- src/blockrain.jquery.src.js | 48 +++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/blockrain.jquery.src.js b/src/blockrain.jquery.src.js index 7fa74e0..e829c5f 100644 --- a/src/blockrain.jquery.src.js +++ b/src/blockrain.jquery.src.js @@ -435,12 +435,52 @@ orientation: 0, // 4 possible rotate: function(direction) { - var orientation = (this.orientation + (direction === 'left' ? 1 : -1) + 4) % 4; - - //TODO - when past limit - auto shift and remember that too! - if (!game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { + var orientation = + (this.orientation + (direction === "left" ? 1 : -1) + 4) % 4; + + if (!game._checkCollisions( + this.x, + this.y, + this.getBlocks(orientation) + )) { this.orientation = orientation; game._board.renderChanged = true; + } else { + var ogOrientation = this.orientation; + var ogX = this.x; + var ogY = this.y; + + this.orientation = orientation; + + while (this.x >= game._BLOCK_WIDTH - 2) { + this.x--; + } + while (this.x < 0) { + this.x++; + } + + if (this.blockType === "line" && this.x === 0) this.x++; + + if ( game._checkCollisions( + this.x, + this.y, + this.getBlocks(orientation) + ) + ) { + this.y--; + if ( + game._checkCollisions( + this.x, + this.y, + this.getBlocks(orientation) + ) + ) { + this.x = ogX; + this.y = ogY; + this.orientation = ogOrientation; + } + } + game._board.rendesrChanged = true; } }, From 43be543be8c888988501b32db28c9e6c0c0c17b1 Mon Sep 17 00:00:00 2001 From: Micael Robles Date: Sun, 6 Aug 2017 19:52:03 -0300 Subject: [PATCH 09/10] fix typo --- src/blockrain.jquery.src.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blockrain.jquery.src.js b/src/blockrain.jquery.src.js index e829c5f..d1b860b 100644 --- a/src/blockrain.jquery.src.js +++ b/src/blockrain.jquery.src.js @@ -480,7 +480,7 @@ this.orientation = ogOrientation; } } - game._board.rendesrChanged = true; + game._board.renderChanged = true; } }, From 4314a91973229585f8a5eabdf1f4b36ab106924d Mon Sep 17 00:00:00 2001 From: Micael Robles Date: Sun, 6 Aug 2017 20:06:00 -0300 Subject: [PATCH 10/10] build --- dist/blockrain.jquery.js | 46 +- dist/blockrain.jquery.min.js | 2 +- dist/blockrain.zip | Bin 55806 -> 56116 bytes package-lock.json | 996 ++++++++++++++++++++++++++++++----- package.json | 3 + 5 files changed, 908 insertions(+), 139 deletions(-) diff --git a/dist/blockrain.jquery.js b/dist/blockrain.jquery.js index f99f288..e065a00 100644 --- a/dist/blockrain.jquery.js +++ b/dist/blockrain.jquery.js @@ -447,11 +447,51 @@ orientation: 0, // 4 possible rotate: function(direction) { - var orientation = (this.orientation + (direction === 'left' ? 1 : -1) + 4) % 4; + var orientation = + (this.orientation + (direction === "left" ? 1 : -1) + 4) % 4; + + if (!game._checkCollisions( + this.x, + this.y, + this.getBlocks(orientation) + )) { + this.orientation = orientation; + game._board.renderChanged = true; + } else { + var ogOrientation = this.orientation; + var ogX = this.x; + var ogY = this.y; - //TODO - when past limit - auto shift and remember that too! - if (!game._checkCollisions(this.x, this.y, this.getBlocks(orientation))) { this.orientation = orientation; + + while (this.x >= game._BLOCK_WIDTH - 2) { + this.x--; + } + while (this.x < 0) { + this.x++; + } + + if (this.blockType === "line" && this.x === 0) this.x++; + + if ( game._checkCollisions( + this.x, + this.y, + this.getBlocks(orientation) + ) + ) { + this.y--; + if ( + game._checkCollisions( + this.x, + this.y, + this.getBlocks(orientation) + ) + ) { + this.x = ogX; + this.y = ogY; + this.orientation = ogOrientation; + } + } game._board.renderChanged = true; } }, diff --git a/dist/blockrain.jquery.min.js b/dist/blockrain.jquery.min.js index bf50ddc..7256d31 100644 --- a/dist/blockrain.jquery.min.js +++ b/dist/blockrain.jquery.min.js @@ -8,5 +8,5 @@ * Released under the MIT license * http://aerolab.github.io/blockrain.js/LICENSE.txt */ - !function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)}(function(t){var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var o,n,s;for(s=0;null!=(n=i[s]);s++)try{o=t._data(n,"events"),o&&o.remove&&t(n).triggerHandler("remove")}catch(r){}e(i)}}(t.cleanData),t.widget=function(e,i,o){var n,s,r,a,h={},l=e.split(".")[0];return e=e.split(".")[1],n=l+"-"+e,o||(o=i,i=t.Widget),t.expr[":"][n.toLowerCase()]=function(e){return!!t.data(e,n)},t[l]=t[l]||{},s=t[l][e],r=t[l][e]=function(t,e){return this._createWidget?void(arguments.length&&this._createWidget(t,e)):new r(t,e)},t.extend(r,s,{version:o.version,_proto:t.extend({},o),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(o,function(e,o){return t.isFunction(o)?void(h[e]=function(){var t=function(){return i.prototype[e].apply(this,arguments)},n=function(t){return i.prototype[e].apply(this,t)};return function(){var e,i=this._super,s=this._superApply;return this._super=t,this._superApply=n,e=o.apply(this,arguments),this._super=i,this._superApply=s,e}}()):void(h[e]=o)}),r.prototype=t.widget.extend(a,{widgetEventPrefix:s?a.widgetEventPrefix||e:e},h,{constructor:r,namespace:l,widgetName:e,widgetFullName:n}),s?(t.each(s._childConstructors,function(e,i){var o=i.prototype;t.widget(o.namespace+"."+o.widgetName,r,i._proto)}),delete s._childConstructors):i._childConstructors.push(r),t.widget.bridge(e,r),r},t.widget.extend=function(e){for(var o,n,s=i.call(arguments,1),r=0,a=s.length;a>r;r++)for(o in s[r])n=s[r][o],s[r].hasOwnProperty(o)&&void 0!==n&&(e[o]=t.isPlainObject(n)?t.isPlainObject(e[o])?t.widget.extend({},e[o],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,o){var n=o.prototype.widgetFullName||e;t.fn[e]=function(s){var r="string"==typeof s,a=i.call(arguments,1),h=this;return s=!r&&a.length?t.widget.extend.apply(null,[s].concat(a)):s,r?this.each(function(){var i,o=t.data(this,n);return"instance"===s?(h=o,!1):o?t.isFunction(o[s])&&"_"!==s.charAt(0)?(i=o[s].apply(o,a),i!==o&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+s+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; attempted to call method '"+s+"'")}):this.each(function(){var e=t.data(this,n);e?(e.option(s||{}),e._init&&e._init()):t.data(this,n,new o(s,this))}),h}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{disabled:!1,create:null},_createWidget:function(i,o){o=t(o||this.defaultElement||this)[0],this.element=t(o),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),o!==this&&(t.data(o,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===o&&this.destroy()}}),this.document=t(o.style?o.ownerDocument:o.document||o),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:t.noop,_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(t.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var o,n,s,r=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(r={},o=e.split("."),e=o.shift(),o.length){for(n=r[e]=t.widget.extend({},this.options[e]),s=0;o.length-1>s;s++)n[o[s]]=n[o[s]]||{},n=n[o[s]];if(e=o.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];r[e]=i}return this._setOptions(r),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!e),e&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(e,i,o){var n,s=this;"boolean"!=typeof e&&(o=i,i=e,e=!1),o?(i=n=t(i),this.bindings=this.bindings.add(i)):(o=i,i=this.element,n=this.widget()),t.each(o,function(o,r){function a(){return e||s.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof r?s[r]:r).apply(s,arguments):void 0}"string"!=typeof r&&(a.guid=r.guid=r.guid||a.guid||t.guid++);var h=o.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+s.eventNamespace,c=h[2];c?n.delegate(c,l,a):i.bind(l,a)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(i).undelegate(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?o[t]:t).apply(o,arguments)}var o=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){t(e.currentTarget).addClass("ui-state-hover")},mouseleave:function(e){t(e.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){t(e.currentTarget).addClass("ui-state-focus")},focusout:function(e){t(e.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(e,i,o){var n,s,r=this.options[e];if(o=o||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],s=i.originalEvent)for(n in s)n in i||(i[n]=s[n]);return this.element.trigger(i,o),!(t.isFunction(r)&&r.apply(this.element[0],[i].concat(o))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(o,n,s){"string"==typeof n&&(n={effect:n});var r,a=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),r=!t.isEmptyObject(n),n.complete=s,n.delay&&o.delay(n.delay),r&&t.effects&&t.effects.effect[a]?o[e](n):a!==e&&o[a]?o[a](n.duration,n.easing,s):o.queue(function(i){t(this)[e](),s&&s.call(o[0]),i()})}}),t.widget}),function(t){"use strict";t.widget("aerolab.blockrain",{options:{autoplay:!1,autoplayRestart:!0,showFieldOnStart:!0,theme:null,blockWidth:10,autoBlockWidth:!1,autoBlockSize:24,difficulty:"normal",speed:20,asdwKeys:!0,playText:"Let's play some Tetris",playButtonText:"Play",gameOverText:"Game Over",restartButtonText:"Play Again",scoreText:"Score",onStart:function(){},onRestart:function(){},onGameOver:function(t){},onPlaced:function(){},onLine:function(t,e,i){}},start:function(){this._doStart(),this.options.onStart.call(this.element)},restart:function(){this._doStart(),this.options.onRestart.call(this.element)},gameover:function(){this.showGameOverMessage(),this._board.gameover=!0,this.options.onGameOver.call(this.element,this._filled.score)},_doStart:function(){this._filled.clearAll(),this._filled._resetScore(),this._board.cur=this._board.nextShape(),this._board.started=!0,this._board.gameover=!1,this._board.dropDelay=5,this._board.render(!0),this._board.animate(),this._$start.fadeOut(150),this._$gameover.fadeOut(150),this._$score.fadeIn(150)},pause:function(){this._board.paused=!0},resume:function(){this._board.paused=!1},autoplay:function(t){"boolean"!=typeof t&&(t=!0),this.options.autoplay=t,t&&!this._board.started&&this._doStart(),this._setupControls(!t),this._setupTouchControls(!t)},controls:function(t){"boolean"!=typeof t&&(t=!0),this._setupControls(t)},touchControls:function(t){"boolean"!=typeof t&&(t=!0),this._setupTouchControls(t)},score:function(t){return"undefined"!=typeof t&&parseInt(t)>=0&&(this._filled.score=parseInt(t),this._$scoreText.text(this._filled_score)),this._filled.score},freesquares:function(){return this._filled.getFreeSpaces()},showStartMessage:function(){this._$start.show()},showGameOverMessage:function(){this._$gameover.show()},updateSizes:function(){this._PIXEL_WIDTH=this.element.innerWidth(),this._PIXEL_HEIGHT=this.element.innerHeight(),this._BLOCK_WIDTH=this.options.blockWidth,this._BLOCK_HEIGHT=Math.floor(this.element.innerHeight()/this.element.innerWidth()*this._BLOCK_WIDTH),this._block_size=Math.floor(this._PIXEL_WIDTH/this._BLOCK_WIDTH),this._border_width=2,this._PIXEL_WIDTH=this._block_size*this._BLOCK_WIDTH,this._PIXEL_HEIGHT=this._block_size*this._BLOCK_HEIGHT,this._$canvas.attr("width",this._PIXEL_WIDTH).attr("height",this._PIXEL_HEIGHT)},theme:function(e){return"undefined"==typeof e?this.options.theme||this._theme:("string"==typeof e?(this.options.theme=e,this._theme=t.extend(!0,{},BlockrainThemes[e])):(this.options.theme=null,this._theme=e),"undefined"!=typeof this._theme&&null!==this._theme||(this._theme=t.extend(!0,{},BlockrainThemes.retro),this.options.theme="retro"),(isNaN(parseInt(this._theme.strokeWidth))||"number"!=typeof parseInt(this._theme.strokeWidth))&&(this._theme.strokeWidth=2),this._preloadThemeAssets(),void(null!==this._board&&("string"==typeof this._theme.background&&this._$canvas.css("background-color",this._theme.background),this._board.render())))},_theme:{},_$game:null,_$canvas:null,_$gameholder:null,_$start:null,_$gameover:null,_$score:null,_$scoreText:null,_canvas:null,_ctx:null,_create:function(){var e=this;this.theme(this.options.theme),this._createHolder(),this._createUI(),this._refreshBlockSizes(),this.updateSizes(),t(window).resize(function(){}),this._SetupShapeFactory(),this._SetupFilled(),this._SetupInfo(),this._SetupBoard(),this._info.init(),this._board.init();var i=function(){requestAnimationFrame(i),e._board.render()};i(),this.options.autoplay?(this.autoplay(!0),this._setupTouchControls(!1)):(this._setupControls(!0),this._setupTouchControls(!1))},_checkCollisions:function(t,e,i,o){for(var n,s,r=0,a=i.length;r=this._BLOCK_HEIGHT||this._filled.check(n,s))return!0;if(!o&&n<0||n>=this._BLOCK_WIDTH)return!0}return!1},_board:null,_info:null,_filled:null,_drawBackground:function(){if("string"==typeof this._theme.background){if(this._theme.backgroundGrid instanceof Image){if(0===this._theme.backgroundGrid.width||0===this._theme.backgroundGrid.height)return;this._ctx.globalAlpha=1;for(var t=0;tr&&(r=i[o]),i[o+1]h&&(h=i[o+1]);return{left:s,right:r,top:a,bottom:h,width:r-s,height:h-a}}}),this.init()}var i=this;null===this._shapeFactory&&(this._shapeFactory={line:function(){return new e(i,i._shapes.line,(!1),"line")},square:function(){return new e(i,i._shapes.square,(!1),"square")},arrow:function(){return new e(i,i._shapes.arrow,(!1),"arrow")},leftHook:function(){return new e(i,i._shapes.leftHook,(!1),"leftHook")},rightHook:function(){return new e(i,i._shapes.rightHook,(!1),"rightHook")},leftZag:function(){return new e(i,i._shapes.leftZag,(!1),"leftZag")},rightZag:function(){return new e(i,i._shapes.rightZag,(!1),"rightZag")}})},_SetupFilled:function(){var t=this;null===this._filled&&(this._filled={data:new Array(t._BLOCK_WIDTH*t._BLOCK_HEIGHT),score:0,toClear:{},check:function(t,e){return this.data[this.asIndex(t,e)]},add:function(e,i,o,n,s,r){e>=0&&e=0&&i=0;i--)this.data[i]=i>=t._BLOCK_WIDTH?this.data[i-t._BLOCK_WIDTH]:void 0},checkForClears:function(){var e,i,o,n,s=t._board.lines,r=[];for(e=0,i=this.data.length;e1&&(t._board.dropDelay*=.9);var a=t._board.lines-s;this._updateScore(a)},_updateScore:function(e){if(!(e<=0)){var i=[0,400,1e3,3e3,12e3];e>=i.length&&(e=i.length-1),this.score+=i[e],t._$scoreText.text(this.score),t.options.onLine.call(t.element,e,i[e],this.score)}},_resetScore:function(){this.score=0,t._$scoreText.text(this.score)},draw:function(){for(var e,i=0,o=this.data.length;i=this.dropDelay||e.options.autoplay||this.holding.drop&&n-this.holding.drop>=this.holdingThreshold)&&(t=!0,i=!0,this.dropCount=0),this.holding.left&&n-this.holding.left>=this.holdingThreshold&&(i=!0,this.cur.moveLeft()),this.holding.right&&n-this.holding.right>=this.holdingThreshold&&(i=!0,this.cur.moveRight()),t)){var s=this.cur,r=s.x,a=s.y,h=s.getBlocks();if(e._checkCollisions(r,a+1,h,!0)){t=!1;for(var l=0,c=0;c0?e[0]:null:e};return"boolean"!=typeof s&&(s=!0),s?"string"==typeof e._theme.primary&&""!==e._theme.primary?e._theme.primary:"undefined"!=typeof e._theme.blocks&&null!==e._theme.blocks?r(e._theme.blocks[i],o):r(e._theme.complexBlocks[i],o):"string"==typeof e._theme.secondary&&""!==e._theme.secondary?e._theme.secondary:"undefined"!=typeof e._theme.blocks&&null!==e._theme.blocks?r(e._theme.blocks[i],o):r(e._theme.complexBlocks[i],o)}},e._niceShapes=e._getNiceShapes()},_randInt:function(t,e){return t+Math.floor(Math.random()*(1+e-t))},_randSign:function(){return 2*this._randInt(0,1)-1},_randChoice:function(t){return t[this._randInt(0,t.length-1)]},_preloadThemeAssets:function(){var e=this,i=new RegExp("^#[A-F0-9+]{3,6}","i"),o=(new RegExp("^data:image/(png|gif|jpg);base64,","i"),function(){e._board&&e._board.render(!0)}),n=function(t){var e=t;return i.test(e)?t=e:(t=new Image,t.src=e,t.onload=o),t},s=function(e){if(t.isArray(e)&&e.length>0)for(var i=0;i
'),this._$gameholder.css("position","relative").css("width","100%").css("height","100%"),this.element.html("").append(this._$gameholder),this._$canvas=t(''),"string"==typeof this._theme.background&&this._$canvas.css("background-color",this._theme.background),this._$gameholder.append(this._$canvas),this._canvas=this._$canvas.get(0),this._ctx=this._canvas.getContext("2d")},_createUI:function(){var e=this;e._$score=t('
'+this.options.scoreText+'
0
').hide(),e._$scoreText=e._$score.find(".blockrain-score-num"),e._$gameholder.append(e._$score),e._$start=t('
").hide(),e._$gameholder.append(e._$start),e._$start.find(".blockrain-start-btn").click(function(t){t.preventDefault(),e.start()}),e._$gameover=t('
'+this.options.gameOverText+'
'+this.options.restartButtonText+"
").hide(),e._$gameover.find(".blockrain-game-over-btn").click(function(t){t.preventDefault(),e.restart()}),e._$gameholder.append(e._$gameover),this._createControls()},_createControls:function(){var e=this;e._$touchLeft=t('').appendTo(e._$gameholder),e._$touchRight=t('').appendTo(e._$gameholder),e._$touchRotateRight=t('').appendTo(e._$gameholder),e._$touchRotateLeft=t('').appendTo(e._$gameholder),e._$touchDrop=t('').appendTo(e._$gameholder)},_refreshBlockSizes:function(){this.options.autoBlockWidth&&(this.options.blockWidth=Math.ceil(this.element.width()/this.options.autoBlockSize))},_getNiceShapes:function(){function t(t,e,i,n,s,r,a){var h,l,c,d,u=e.length,g=0,A={};for(h=0;hv&&(v=m,y=f,C=c);break}(B&&vG)&&(k=A,G=v,_=y,I=C)}return k.best_orientation=_,k.best_x=I,k};return s.no_preview=!0,s},_randomShapes:function(){var e=[];return t.each(this._shapeFactory,function(t,i){e.push(i)}),this._randChoice(e)},_setupControls:function(e){function i(t){var e={stopKeys:{37:1,38:1,39:1,40:1}},i=e.stopKeys[t.keyCode]||e.moreStopKeys&&e.moreStopKeys[t.keyCode];return i&&t.preventDefault(),i}function o(t){return"safekeypress."+t.keyCode}function n(e){var i=o(e);return t.data(this,i,(t.data(this,i)||0)-1),c.call(this,e)}function s(e){return t.data(this,o(e),0),d.call(this,e),i(e)}var r=this,a=function(t){return t?void(r._board.holding.left||(r._board.cur.moveLeft(),r._board.holding.left=Date.now(),r._board.holding.right=null)):void(r._board.holding.left=null)},h=function(t){return t?void(r._board.holding.right||(r._board.cur.moveRight(),r._board.holding.right=Date.now(),r._board.holding.left=null)):void(r._board.holding.right=null)},l=function(t){return t?void(r._board.holding.drop||(r._board.cur.drop(),r._board.holding.drop=Date.now())):void(r._board.holding.drop=null)},c=function(t){if(!r._board.cur)return!0;var e=!1;if(e=!0,r.options.asdwKeys)switch(t.keyCode){case 65:a(!0);break;case 68:h(!0);break;case 83:l(!0);break;case 87:r._board.cur.rotate("right")}switch(t.keyCode){case 37:a(!0);break;case 39:h(!0);break;case 40:l(!0);break;case 38:r._board.cur.rotate("right");break;case 88:r._board.cur.rotate("right");break;case 90:r._board.cur.rotate("left");break;default:e=!1}return e&&t.preventDefault(),!e},d=function(t){if(!r._board.cur)return!0;var e=!1;if(e=!0,r.options.asdwKeys)switch(t.keyCode){case 65:a(!1);break;case 68:h(!1);break;case 83:l(!1)}switch(t.keyCode){case 37:a(!1);break;case 39:h(!1);break;case 40:l(!1);break;default:e=!1}return e&&t.preventDefault(),!e};t(document).unbind("keydown.blockrain").unbind("keyup.blockrain"),r.options.autoplay||e&&t(document).bind("keydown.blockrain",n).bind("keyup.blockrain",s)},_setupTouchControls:function(t){var e=this,i=function(t){t.preventDefault(),e._board.cur.moveLeft(),e._board.holding.left=Date.now(),e._board.holding.right=null,e._board.holding.drop=null},o=function(t){t.preventDefault(),e._board.cur.moveRight(),e._board.holding.right=Date.now(),e._board.holding.left=null,e._board.holding.drop=null},n=function(t){t.preventDefault(),e._board.cur.drop(),e._board.holding.drop=Date.now()},s=function(t){t.preventDefault(),e._board.holding.left=null},r=function(t){t.preventDefault(),e._board.holding.right=null},a=function(t){t.preventDefault(),e._board.holding.drop=null},h=function(t){t.preventDefault(),e._board.cur.rotate("left")},l=function(t){t.preventDefault(),e._board.cur.rotate("right")};e._$touchLeft.unbind("touchstart touchend click"),e._$touchRight.unbind("touchstart touchend click"),e._$touchRotateLeft.unbind("touchstart touchend click"),e._$touchRotateRight.unbind("touchstart touchend click"),e._$touchDrop.unbind("touchstart touchend click"),!e.options.autoplay&&t?(e._$touchLeft.show().bind("touchstart click",i).bind("touchend",s),e._$touchRight.show().bind("touchstart click",o).bind("touchend",r),e._$touchDrop.show().bind("touchstart click",n).bind("touchend",a),e._$touchRotateLeft.show().bind("touchstart click",h),e._$touchRotateRight.show().bind("touchstart click",l)):(e._$touchLeft.hide(),e._$touchRight.hide(),e._$touchRotateLeft.hide(),e._$touchRotateRight.hide(),e._$touchDrop.hide())}})}(jQuery),window.BlockrainThemes={custom:{background:"#040304",backgroundGrid:"data:image/png;base64,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", + !function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)}(function(t){var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var o,n,s;for(s=0;null!=(n=i[s]);s++)try{o=t._data(n,"events"),o&&o.remove&&t(n).triggerHandler("remove")}catch(r){}e(i)}}(t.cleanData),t.widget=function(e,i,o){var n,s,r,a,h={},l=e.split(".")[0];return e=e.split(".")[1],n=l+"-"+e,o||(o=i,i=t.Widget),t.expr[":"][n.toLowerCase()]=function(e){return!!t.data(e,n)},t[l]=t[l]||{},s=t[l][e],r=t[l][e]=function(t,e){return this._createWidget?void(arguments.length&&this._createWidget(t,e)):new r(t,e)},t.extend(r,s,{version:o.version,_proto:t.extend({},o),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(o,function(e,o){return t.isFunction(o)?void(h[e]=function(){var t=function(){return i.prototype[e].apply(this,arguments)},n=function(t){return i.prototype[e].apply(this,t)};return function(){var e,i=this._super,s=this._superApply;return this._super=t,this._superApply=n,e=o.apply(this,arguments),this._super=i,this._superApply=s,e}}()):void(h[e]=o)}),r.prototype=t.widget.extend(a,{widgetEventPrefix:s?a.widgetEventPrefix||e:e},h,{constructor:r,namespace:l,widgetName:e,widgetFullName:n}),s?(t.each(s._childConstructors,function(e,i){var o=i.prototype;t.widget(o.namespace+"."+o.widgetName,r,i._proto)}),delete s._childConstructors):i._childConstructors.push(r),t.widget.bridge(e,r),r},t.widget.extend=function(e){for(var o,n,s=i.call(arguments,1),r=0,a=s.length;a>r;r++)for(o in s[r])n=s[r][o],s[r].hasOwnProperty(o)&&void 0!==n&&(e[o]=t.isPlainObject(n)?t.isPlainObject(e[o])?t.widget.extend({},e[o],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,o){var n=o.prototype.widgetFullName||e;t.fn[e]=function(s){var r="string"==typeof s,a=i.call(arguments,1),h=this;return s=!r&&a.length?t.widget.extend.apply(null,[s].concat(a)):s,r?this.each(function(){var i,o=t.data(this,n);return"instance"===s?(h=o,!1):o?t.isFunction(o[s])&&"_"!==s.charAt(0)?(i=o[s].apply(o,a),i!==o&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+s+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; attempted to call method '"+s+"'")}):this.each(function(){var e=t.data(this,n);e?(e.option(s||{}),e._init&&e._init()):t.data(this,n,new o(s,this))}),h}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{disabled:!1,create:null},_createWidget:function(i,o){o=t(o||this.defaultElement||this)[0],this.element=t(o),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),o!==this&&(t.data(o,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===o&&this.destroy()}}),this.document=t(o.style?o.ownerDocument:o.document||o),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:t.noop,_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(t.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var o,n,s,r=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(r={},o=e.split("."),e=o.shift(),o.length){for(n=r[e]=t.widget.extend({},this.options[e]),s=0;o.length-1>s;s++)n[o[s]]=n[o[s]]||{},n=n[o[s]];if(e=o.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];r[e]=i}return this._setOptions(r),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!e),e&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(e,i,o){var n,s=this;"boolean"!=typeof e&&(o=i,i=e,e=!1),o?(i=n=t(i),this.bindings=this.bindings.add(i)):(o=i,i=this.element,n=this.widget()),t.each(o,function(o,r){function a(){return e||s.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof r?s[r]:r).apply(s,arguments):void 0}"string"!=typeof r&&(a.guid=r.guid=r.guid||a.guid||t.guid++);var h=o.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+s.eventNamespace,c=h[2];c?n.delegate(c,l,a):i.bind(l,a)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(i).undelegate(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?o[t]:t).apply(o,arguments)}var o=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){t(e.currentTarget).addClass("ui-state-hover")},mouseleave:function(e){t(e.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){t(e.currentTarget).addClass("ui-state-focus")},focusout:function(e){t(e.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(e,i,o){var n,s,r=this.options[e];if(o=o||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],s=i.originalEvent)for(n in s)n in i||(i[n]=s[n]);return this.element.trigger(i,o),!(t.isFunction(r)&&r.apply(this.element[0],[i].concat(o))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(o,n,s){"string"==typeof n&&(n={effect:n});var r,a=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),r=!t.isEmptyObject(n),n.complete=s,n.delay&&o.delay(n.delay),r&&t.effects&&t.effects.effect[a]?o[e](n):a!==e&&o[a]?o[a](n.duration,n.easing,s):o.queue(function(i){t(this)[e](),s&&s.call(o[0]),i()})}}),t.widget}),function(t){"use strict";t.widget("aerolab.blockrain",{options:{autoplay:!1,autoplayRestart:!0,showFieldOnStart:!0,theme:null,blockWidth:10,autoBlockWidth:!1,autoBlockSize:24,difficulty:"normal",speed:20,asdwKeys:!0,playText:"Let's play some Tetris",playButtonText:"Play",gameOverText:"Game Over",restartButtonText:"Play Again",scoreText:"Score",onStart:function(){},onRestart:function(){},onGameOver:function(t){},onPlaced:function(){},onLine:function(t,e,i){}},start:function(){this._doStart(),this.options.onStart.call(this.element)},restart:function(){this._doStart(),this.options.onRestart.call(this.element)},gameover:function(){this.showGameOverMessage(),this._board.gameover=!0,this.options.onGameOver.call(this.element,this._filled.score)},_doStart:function(){this._filled.clearAll(),this._filled._resetScore(),this._board.cur=this._board.nextShape(),this._board.started=!0,this._board.gameover=!1,this._board.dropDelay=5,this._board.render(!0),this._board.animate(),this._$start.fadeOut(150),this._$gameover.fadeOut(150),this._$score.fadeIn(150)},pause:function(){this._board.paused=!0},resume:function(){this._board.paused=!1},autoplay:function(t){"boolean"!=typeof t&&(t=!0),this.options.autoplay=t,t&&!this._board.started&&this._doStart(),this._setupControls(!t),this._setupTouchControls(!t)},controls:function(t){"boolean"!=typeof t&&(t=!0),this._setupControls(t)},touchControls:function(t){"boolean"!=typeof t&&(t=!0),this._setupTouchControls(t)},score:function(t){return"undefined"!=typeof t&&parseInt(t)>=0&&(this._filled.score=parseInt(t),this._$scoreText.text(this._filled_score)),this._filled.score},freesquares:function(){return this._filled.getFreeSpaces()},showStartMessage:function(){this._$start.show()},showGameOverMessage:function(){this._$gameover.show()},updateSizes:function(){this._PIXEL_WIDTH=this.element.innerWidth(),this._PIXEL_HEIGHT=this.element.innerHeight(),this._BLOCK_WIDTH=this.options.blockWidth,this._BLOCK_HEIGHT=Math.floor(this.element.innerHeight()/this.element.innerWidth()*this._BLOCK_WIDTH),this._block_size=Math.floor(this._PIXEL_WIDTH/this._BLOCK_WIDTH),this._border_width=2,this._PIXEL_WIDTH=this._block_size*this._BLOCK_WIDTH,this._PIXEL_HEIGHT=this._block_size*this._BLOCK_HEIGHT,this._$canvas.attr("width",this._PIXEL_WIDTH).attr("height",this._PIXEL_HEIGHT)},theme:function(e){return"undefined"==typeof e?this.options.theme||this._theme:("string"==typeof e?(this.options.theme=e,this._theme=t.extend(!0,{},BlockrainThemes[e])):(this.options.theme=null,this._theme=e),"undefined"!=typeof this._theme&&null!==this._theme||(this._theme=t.extend(!0,{},BlockrainThemes.retro),this.options.theme="retro"),(isNaN(parseInt(this._theme.strokeWidth))||"number"!=typeof parseInt(this._theme.strokeWidth))&&(this._theme.strokeWidth=2),this._preloadThemeAssets(),void(null!==this._board&&("string"==typeof this._theme.background&&this._$canvas.css("background-color",this._theme.background),this._board.render())))},_theme:{},_$game:null,_$canvas:null,_$gameholder:null,_$start:null,_$gameover:null,_$score:null,_$scoreText:null,_canvas:null,_ctx:null,_create:function(){var e=this;this.theme(this.options.theme),this._createHolder(),this._createUI(),this._refreshBlockSizes(),this.updateSizes(),t(window).resize(function(){}),this._SetupShapeFactory(),this._SetupFilled(),this._SetupInfo(),this._SetupBoard(),this._info.init(),this._board.init();var i=function(){requestAnimationFrame(i),e._board.render()};i(),this.options.autoplay?(this.autoplay(!0),this._setupTouchControls(!1)):(this._setupControls(!0),this._setupTouchControls(!1))},_checkCollisions:function(t,e,i,o){for(var n,s,r=0,a=i.length;r=this._BLOCK_HEIGHT||this._filled.check(n,s))return!0;if(!o&&n<0||n>=this._BLOCK_WIDTH)return!0}return!1},_board:null,_info:null,_filled:null,_drawBackground:function(){if("string"==typeof this._theme.background){if(this._theme.backgroundGrid instanceof Image){if(0===this._theme.backgroundGrid.width||0===this._theme.backgroundGrid.height)return;this._ctx.globalAlpha=1;for(var t=0;t=e._BLOCK_WIDTH-2;)this.x--;for(;this.x<0;)this.x++;"line"===this.blockType&&0===this.x&&this.x++,e._checkCollisions(this.x,this.y,this.getBlocks(i))&&(this.y--,e._checkCollisions(this.x,this.y,this.getBlocks(i))&&(this.x=n,this.y=s,this.orientation=o)),e._board.renderChanged=!0}else this.orientation=i,e._board.renderChanged=!0},moveRight:function(){e._checkCollisions(this.x+1,this.y,this.getBlocks())||(this.x++,e._board.renderChanged=!0)},moveLeft:function(){e._checkCollisions(this.x-1,this.y,this.getBlocks())||(this.x--,e._board.renderChanged=!0)},drop:function(){e._checkCollisions(this.x,this.y+1,this.getBlocks())||(this.y++,e._board.dropCount=-1,e._board.animate(),e._board.renderChanged=!0)},getBlocks:function(t){return this.orientations[void 0!==t?t:this.orientation]},draw:function(t,i,o){for(var n=this.getBlocks(o),s=void 0===t?this.x:t,r=void 0===i?this.y:i,a=0,h=0;ar&&(r=i[o]),i[o+1]h&&(h=i[o+1]);return{left:s,right:r,top:a,bottom:h,width:r-s,height:h-a}}}),this.init()}var i=this;null===this._shapeFactory&&(this._shapeFactory={line:function(){return new e(i,i._shapes.line,(!1),"line")},square:function(){return new e(i,i._shapes.square,(!1),"square")},arrow:function(){return new e(i,i._shapes.arrow,(!1),"arrow")},leftHook:function(){return new e(i,i._shapes.leftHook,(!1),"leftHook")},rightHook:function(){return new e(i,i._shapes.rightHook,(!1),"rightHook")},leftZag:function(){return new e(i,i._shapes.leftZag,(!1),"leftZag")},rightZag:function(){return new e(i,i._shapes.rightZag,(!1),"rightZag")}})},_SetupFilled:function(){var t=this;null===this._filled&&(this._filled={data:new Array(t._BLOCK_WIDTH*t._BLOCK_HEIGHT),score:0,toClear:{},check:function(t,e){return this.data[this.asIndex(t,e)]},add:function(e,i,o,n,s,r){e>=0&&e=0&&i=0;i--)this.data[i]=i>=t._BLOCK_WIDTH?this.data[i-t._BLOCK_WIDTH]:void 0},checkForClears:function(){var e,i,o,n,s=t._board.lines,r=[];for(e=0,i=this.data.length;e1&&(t._board.dropDelay*=.9);var a=t._board.lines-s;this._updateScore(a)},_updateScore:function(e){if(!(e<=0)){var i=[0,400,1e3,3e3,12e3];e>=i.length&&(e=i.length-1),this.score+=i[e],t._$scoreText.text(this.score),t.options.onLine.call(t.element,e,i[e],this.score)}},_resetScore:function(){this.score=0,t._$scoreText.text(this.score)},draw:function(){for(var e,i=0,o=this.data.length;i=this.dropDelay||e.options.autoplay||this.holding.drop&&n-this.holding.drop>=this.holdingThreshold)&&(t=!0,i=!0,this.dropCount=0),this.holding.left&&n-this.holding.left>=this.holdingThreshold&&(i=!0,this.cur.moveLeft()),this.holding.right&&n-this.holding.right>=this.holdingThreshold&&(i=!0,this.cur.moveRight()),t)){var s=this.cur,r=s.x,a=s.y,h=s.getBlocks();if(e._checkCollisions(r,a+1,h,!0)){t=!1;for(var l=0,c=0;c0?e[0]:null:e};return"boolean"!=typeof s&&(s=!0),s?"string"==typeof e._theme.primary&&""!==e._theme.primary?e._theme.primary:"undefined"!=typeof e._theme.blocks&&null!==e._theme.blocks?r(e._theme.blocks[i],o):r(e._theme.complexBlocks[i],o):"string"==typeof e._theme.secondary&&""!==e._theme.secondary?e._theme.secondary:"undefined"!=typeof e._theme.blocks&&null!==e._theme.blocks?r(e._theme.blocks[i],o):r(e._theme.complexBlocks[i],o)}},e._niceShapes=e._getNiceShapes()},_randInt:function(t,e){return t+Math.floor(Math.random()*(1+e-t))},_randSign:function(){return 2*this._randInt(0,1)-1},_randChoice:function(t){return t[this._randInt(0,t.length-1)]},_preloadThemeAssets:function(){var e=this,i=new RegExp("^#[A-F0-9+]{3,6}","i"),o=(new RegExp("^data:image/(png|gif|jpg);base64,","i"),function(){e._board&&e._board.render(!0)}),n=function(t){var e=t;return i.test(e)?t=e:(t=new Image,t.src=e,t.onload=o),t},s=function(e){if(t.isArray(e)&&e.length>0)for(var i=0;i
'),this._$gameholder.css("position","relative").css("width","100%").css("height","100%"),this.element.html("").append(this._$gameholder),this._$canvas=t(''),"string"==typeof this._theme.background&&this._$canvas.css("background-color",this._theme.background),this._$gameholder.append(this._$canvas),this._canvas=this._$canvas.get(0),this._ctx=this._canvas.getContext("2d")},_createUI:function(){var e=this;e._$score=t('
'+this.options.scoreText+'
0
').hide(),e._$scoreText=e._$score.find(".blockrain-score-num"),e._$gameholder.append(e._$score),e._$start=t('
").hide(),e._$gameholder.append(e._$start),e._$start.find(".blockrain-start-btn").click(function(t){t.preventDefault(),e.start()}),e._$gameover=t('
'+this.options.gameOverText+'
'+this.options.restartButtonText+"
").hide(),e._$gameover.find(".blockrain-game-over-btn").click(function(t){t.preventDefault(),e.restart()}),e._$gameholder.append(e._$gameover),this._createControls()},_createControls:function(){var e=this;e._$touchLeft=t('').appendTo(e._$gameholder),e._$touchRight=t('').appendTo(e._$gameholder),e._$touchRotateRight=t('').appendTo(e._$gameholder),e._$touchRotateLeft=t('').appendTo(e._$gameholder),e._$touchDrop=t('').appendTo(e._$gameholder)},_refreshBlockSizes:function(){this.options.autoBlockWidth&&(this.options.blockWidth=Math.ceil(this.element.width()/this.options.autoBlockSize))},_getNiceShapes:function(){function t(t,e,i,n,s,r,a){var h,l,c,d,u=e.length,g=0,A={};for(h=0;hv&&(v=m,y=f,C=c);break}(B&&vG)&&(k=A,G=v,_=y,I=C)}return k.best_orientation=_,k.best_x=I,k};return s.no_preview=!0,s},_randomShapes:function(){var e=[];return t.each(this._shapeFactory,function(t,i){e.push(i)}),this._randChoice(e)},_setupControls:function(e){function i(t){var e={stopKeys:{37:1,38:1,39:1,40:1}},i=e.stopKeys[t.keyCode]||e.moreStopKeys&&e.moreStopKeys[t.keyCode];return i&&t.preventDefault(),i}function o(t){return"safekeypress."+t.keyCode}function n(e){var i=o(e);return t.data(this,i,(t.data(this,i)||0)-1),c.call(this,e)}function s(e){return t.data(this,o(e),0),d.call(this,e),i(e)}var r=this,a=function(t){return t?void(r._board.holding.left||(r._board.cur.moveLeft(),r._board.holding.left=Date.now(),r._board.holding.right=null)):void(r._board.holding.left=null)},h=function(t){return t?void(r._board.holding.right||(r._board.cur.moveRight(),r._board.holding.right=Date.now(),r._board.holding.left=null)):void(r._board.holding.right=null)},l=function(t){return t?void(r._board.holding.drop||(r._board.cur.drop(),r._board.holding.drop=Date.now())):void(r._board.holding.drop=null)},c=function(t){if(!r._board.cur)return!0;var e=!1;if(e=!0,r.options.asdwKeys)switch(t.keyCode){case 65:a(!0);break;case 68:h(!0);break;case 83:l(!0);break;case 87:r._board.cur.rotate("right")}switch(t.keyCode){case 37:a(!0);break;case 39:h(!0);break;case 40:l(!0);break;case 38:r._board.cur.rotate("right");break;case 88:r._board.cur.rotate("right");break;case 90:r._board.cur.rotate("left");break;default:e=!1}return e&&t.preventDefault(),!e},d=function(t){if(!r._board.cur)return!0;var e=!1;if(e=!0,r.options.asdwKeys)switch(t.keyCode){case 65:a(!1);break;case 68:h(!1);break;case 83:l(!1)}switch(t.keyCode){case 37:a(!1);break;case 39:h(!1);break;case 40:l(!1);break;default:e=!1}return e&&t.preventDefault(),!e};t(document).unbind("keydown.blockrain").unbind("keyup.blockrain"),r.options.autoplay||e&&t(document).bind("keydown.blockrain",n).bind("keyup.blockrain",s)},_setupTouchControls:function(t){var e=this,i=function(t){t.preventDefault(),e._board.cur.moveLeft(),e._board.holding.left=Date.now(),e._board.holding.right=null,e._board.holding.drop=null},o=function(t){t.preventDefault(),e._board.cur.moveRight(),e._board.holding.right=Date.now(),e._board.holding.left=null,e._board.holding.drop=null},n=function(t){t.preventDefault(),e._board.cur.drop(),e._board.holding.drop=Date.now()},s=function(t){t.preventDefault(),e._board.holding.left=null},r=function(t){t.preventDefault(),e._board.holding.right=null},a=function(t){t.preventDefault(),e._board.holding.drop=null},h=function(t){t.preventDefault(),e._board.cur.rotate("left")},l=function(t){t.preventDefault(),e._board.cur.rotate("right")};e._$touchLeft.unbind("touchstart touchend click"),e._$touchRight.unbind("touchstart touchend click"),e._$touchRotateLeft.unbind("touchstart touchend click"),e._$touchRotateRight.unbind("touchstart touchend click"),e._$touchDrop.unbind("touchstart touchend click"),!e.options.autoplay&&t?(e._$touchLeft.show().bind("touchstart click",i).bind("touchend",s),e._$touchRight.show().bind("touchstart click",o).bind("touchend",r),e._$touchDrop.show().bind("touchstart click",n).bind("touchend",a),e._$touchRotateLeft.show().bind("touchstart click",h),e._$touchRotateRight.show().bind("touchstart click",l)):(e._$touchLeft.hide(),e._$touchRight.hide(),e._$touchRotateLeft.hide(),e._$touchRotateRight.hide(),e._$touchDrop.hide())}})}(jQuery),window.BlockrainThemes={custom:{background:"#040304",backgroundGrid:"data:image/png;base64,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", complexBlocks:{line:["assets/blocks/custom/line.png","assets/blocks/custom/line.png"],square:["assets/blocks/custom/square.png"],arrow:"assets/blocks/custom/arrow.png",rightHook:["assets/blocks/custom/rightHook.png"],leftHook:"assets/blocks/custom/leftHook.png",rightZag:["assets/blocks/custom/rightZag.png"],leftZag:"assets/blocks/custom/leftZag.png"}},candy:{background:"#040304",backgroundGrid:"data:image/png;base64,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",blocks:{line:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACuklEQVR4Xi2MzW4cRRSFz/2p6p4eT2zjjE2MHBQWvAALNjwDS8SOFc/FIyCxQgh2LFHkBQgJyQo/wXKCEZ7x9E9VV93LBPNJ516dxXfo/U8+HTZ9uzrZympTjLo4DbtDiBpXSBGMocI5lkaMhKv0fz+LVX9P6ZuvvxqBby+3L3eJu6Zt27DL4qgIWW0KsxPC3Kjxz5fPT3z48csvtHSHd0C/1374RddPX/9xK6JdcjEutNfqFJMBsQat3By+i/7VxqJ6c/zd5avvn1+N7dl2V9Ad92M2ViI2ksyWSJ2QXQXc5/H25jYcHHKl1YYebcJqw/rW03OOzfr89NHbR8vH3Wq9Olofrddni+XhycXJhBSkKFLxWeHBZFFDVyD343Rzc/0XeYSXeXZIJaam2V9pLsBOtRIKYAorXqvAg8giaKsCKw1zJAGFbKhwtxrdG9E3BQxAIW1xyYUKUIwNxMAwDEwuSgA5iAw2l5ITOeE/GLRMihIOsnQZnKqOlWXRUWidyYkFpCxtCF1s8D+seBggYVYRhChkqqjmld3NKhhu1XKuKUf4g6egEitkvqc5ewo+3ZOVZJO4Q4OSEDGRRyAQkYH8QfMUCR07KS8DIsO8xhjcnUXnSv4GMRYShSUG2MFCeby/awOJFyvF3TU22ckk3E3FQjci+mJVggwz12rKVEvWOk3dwWpIr7ezrU4XZ+9ciBAxWCVlhDb2o5cZTgBR17R3w45hgg8/fu+Dj643adZVXzCmebsbp5T6fhr2L9W8z5xLNsyDpl2btrsXPynS9NvVVc28xzMLPDCUYbVUMy+TMgdinupCEapdvPv0lqGwjW9fHsXjF39eIzRpnFbLdiy918qCWmclnq3mcWhVnzw5v+83XYz0+LPP/8lL704NB3BBdbCDKlChAq8QgRvmGSFouyo3vz7Lr/8FMHqie3VCpNQAAAAASUVORK5CYII=",square:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACfUlEQVR4Xh3LvY5cRRBA4VNV3ffe+fEaZARgWfBExEhEZEg8A69AgkC8AzEiICMgJCdAxggsGRuW3Z3dmenbXVWskT6d7MiXnz3qclu87esm1qW3NteRuqaCIAmQABwPvPU2NyeaUa6P159/9QV3l/HqlWqN41El0PaadEJAoZBKqS9+eybL/tvvvi8PrHA4ku33pz9v5rafKmc0I7QhbiGaJSikyeCh1T7OG6fMluOvP/5+8csb+/RxhUtlEXA5KUMpiEpWwZKU3D799Zl1CtpEjsoh++HRxUMBVhgry4yUXLvstnE8qWi/HZndTEwpppj5XLIg7fZ4+fJlb91jzSlGhjc2O7RMj995nApRIRW0BHRl9UXLona6PYiGGKpaa50qPtQ96/5BCgkpBKghpI7VJZK5bmYju5IxQkZONqtbu+txd5ZEQFI0KaRRJxEZY0wjh/dqKqbZ/z9tqmJIqpQSnaD8T9sYkGqWmuTIZHgoWYupKh4SqSQimqrJfeV1gTECF4NKmUHwDFRqNSuJjMTxFQANNKGUyTBxYqSX6J6USdc1BquYFhEMFEQCUvSeC5rheL/Y74kAvX/OPXRZojIkqHkaLpMwWdYJm1fHlZIJotdXN7tFtczvvfuB5MIyRZwQ11pora2BTKOvva3zPKtStpsKLNNmmcr53xtFMtLaGLSR61IKKaPHenO1L2+qThqrn5FvPuGjjz8s4x+NI6Ptdvtxckywo0cjstZZZfZhNhSWNuoPP/5Udhebc8+tbp4//zPd6dcaGtJtWtUiVkhTWSJkTn3y5P15M19ervL1p9UZFzX9zHYmO1Ph3KFQK+rkIBMScbY7DicOzn+QRoW5iamqhgAAAABJRU5ErkJggg==",arrow:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACsklEQVR4XhWPu25bVxREZz/OuQ9RVKhXjBSu8gX5h+QD0udD8ilByjRpUqZxa6RxY8DuYlhwHhAc2qRIieK9vOfsvUMNBoPVrGLoh6+++7y7mbFfTNIVdShCxCGuAgE8tSilhOVWU6lrtPjPK33ffvvb6xd4KG9/+f1kenIYoAgOIc+AF9u5Rdteuvubty9LU168fqW9z7AFanr36uPZSOIgWHB1IJABKE0keSr3QdLolXitjw1n717++sfPP/7Ula6pfbYmeU7eaBybnzg6ewwpT8DW/vth2acFkzf9Pi0OOU1+/eVlM2/m14vZ+Rfz88t+Np+fnZ8tns1OL66vLss0FIughgppDumLzIpmYBrHz+uVsZVSsraorJoMQU5dOs3K3jaiSXGciNYoG3cQcbJjwiKC3Ny9ljhEEUlGBnh4IJwR+qQ6q7FbuMPBLEQCVjaYA0mYwcyIY6p5qYFQQqOexRMhHOqg6sV8mtiqQki51gSHV6YAMYMMxgIC2IOcBcIsQipBBCIjNqEQBWARjjAOHAtSh1eqk9bqLpBKQUSZE4ccIqpJFnWQiRSKypjUA1DgEDw5janNkgA4zKmGQtpgsNqhMoRCmRni4AgKJh6DB842TffENWWqU+m448eYje186GZT31nXo5EqPhUGIqoGwd1gtWFtRBeLxcXF1TydYh+td1E5lMdpOOxGr9bPOzdrtFGWk2lAg84e9/fYbGmsync0xD7mfkITgUMbJaKc26GOVn2sB61Gf958OE992wsoQjSSjBHUwEmlISTsxjEsOIsxP3v+/M3tey3wrRVh29wuA2Vo3Xoe3KP6Endhzh3v92NjKefcXZzETKxR+Sa+vt2s3/3z127YrYfN+mGz2m4+rT+tNuu77d3yfvn3+vbh8eH4bb3dLrer97c3q7L6H15gvODKB5u4AAAAAElFTkSuQmCC",rightHook:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACqElEQVR4Xh3PO2tlZRSH8f9a73XvPTkTExl1dLAIKFpNY2Fl4UcT7G3FwmIaO3sbEfQjWAxDAkIORDHJyXFf3stayzC/9qke+ubrF0u7zqwfsJNFXEKtCAJriBGBoB0gNAZ5WIekcC0f+br8++3Pr1AP5Y/f6Xgfx4RqoB2kI27QgkYQw5BA2L95M+vTn379y0c2HI+Y5Ob6z3B/M/ZmlTieV7ISj9rXZ2n338NciEMedGshJacbZ9X16vK3H76vh/1paCOWiWvos5M1U9llLIebKeqz0zG4PmZ/dfl6XWc/9p4Ox/fMwnIcXrwL6ohPg54OZhYTUUc+w1YQ83z3kMadEKdp8EmE54cnKifTBLOr17cqtwIf4gAuKhUd8Lh4+TKPowjyOK1l8cxAm9nK2nWnsQeAyNtgldnClCLntkrRrTBcFyPjYRg8AEAY4JDhkhp7uOBIRbyqrmK+KcBm1qU30UbSxHcGnIGpKYk63dQxnC2sPcWo2slZUCCGYXPkkBnUqjcCSAGFsaOUQk5koqUqPFV5G2sDai+tG3vv6ZF3BojBzFrvpeij4KtDZTjPXTWGBA91uWJTo1WkqTAZoAbpT3ejd0YOBW1zoAHE/tG8FThm52KOLnDv1dA8DACTwbRU6TxSaX1WZII/1qBgwLvWtgN6ieQc2hC9hwLGTFS35eTJ7uOL5xxTkZI44l7BDGpwBke8FFCA9Pj2EAipHbd8Qre3fxOMDWykGryyM2Vv67JwmCJ7cQRRM6JXX+CrLz97/uHJ4bgHFUdKBi8B5gECLLAys4grAkr5Vt758ZdLTwhuPNvfHP7ZPzjrBAHYLBlChwPQ+jrtpq2UJv3i0/clni/Y03efYzxPvZdBkAzeAKATukENAoTA86ynZ3GrVQl3Eu/yJ/8D33mmeKR3Cz8AAAAASUVORK5CYII=",leftHook:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACq0lEQVR4Xg3HO24mVRBH8X/Vrfv4ut02BjS8GSBAQuyCmE0gwSLICFgCBLASAhLiiQjQICFBMAMSFn63v+77qCp89EsO5U+/rus/0zQPPW8thXRQABLAjtHAAZ2gzGk2HRCG1YMPwgdf/fnXj1fX+O7732s/A0kzbwEUCW5Fgh8HGVdFTOn5H79NiZ/98rPATBVS8OzX5xTehYsxd3KFwXcGEljVOGVJ8a7W4Q4YT8sb33z70xdf/oB8HufzhjI0m2a3JLykuAyV4RGxrLVN5+f/3dxSKXJc59qfUk77djhdXhGx0/mMAg/rpm30bXq97Fp3su1mrMe19e46BLLw9Nb1w0WaZoO+fPmCNbTW3D1Fcjci77Cnn3wMhCBpWU7vuwqo3evgaar6QHRqfRXKhQiELFG1O6H3MZUyLpTIx24UMkNASbqZwZiN3AQsgKhZ6/VYR9OcDw/blg5xmKqPnIRBLQUZw4iIWQKydRcEcvLOOZ2A80Nv8SRv1iiHQWPXewbztm3MbObMYgpGCMwiwgwAIhJCAGBmjMD+KDJJThJzTI8TKZm5E9S7U3c0s6PrkVujvYbm0Qr1iceJ+GZ9772OMawNDNAgVm8cADcAQSgzCSiChZj8MRLwXCTPufQEC8SlVKPWNTJJ4BTDcds58tCaMsVoIQ8Nq2AgS97uVg2h7v29Dz86W86MGqB922F+djjsdbWE0eu233fbwF0opd57KYU43l5ewQ43N7d17CwUHJnlsl4QmUwkJJKZ5uXaLdBrnzl6EGbTbV2nVIiMuMU44EMwMjn76GMHeWAKhKuLvyXoC+F3IvXrfy9zmO/WKyUM6c1riWUY7btKiA+9UkyvPnk7KFMPtLz/uS9vrjVFLNqTUSEJNLN5hQL7gIXpsGytO0ekCduR/fg/hV+olVqSm3YAAAAASUVORK5CYII=",rightZag:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACt0lEQVR4Xg3LOW6eVRQG4PcM937DP9hYlkgUQ6RQsAiEWAC7YCWUtGyAFqhpEHRI0CCBIjpHJBSxEhzkxP6H+93pHPz0D3358IsbuyY/XlCs7/YU5zjFZgdGp07BEDq4KXwA0PvuqIfDGbT0u69/+hZvr/DrH1gc1WENwUAGM3RDcXQGRbA9/e3nJPX3F5dqdY/ja8ztx++/+YhX5S6P47REODW2Pra+qsbOR5VFWwjHVPKJJF1FevPn019++O7jeYo3h5VG8Ua5OLnCh25T7+RwYfZavVz993q5OehccfImnV3nqdLjD54gTiDAF3cnEJrBAbZNSS//vTKP1FcTk0ppsfYzkpEt58Pls8vb29vTabDWYZJzjsqnJ+vHjx9tVvf3qG3QVpXJ0Y5L2xWmYbPt7W5WeK7RKUqICic7poQY6q4Fw2AUDSykUGUlQ0cUy3XUqCxm8Obe4SypVoRwOC7kLE5szIoBHsmlO6NJO3Qv5GEozI3IiE25K2EeLAiYADiBOwi51NLdCRrGcQ5xTLVUcg1BVeFszXtaWinkIAcALigQDwISby0Vq3dpR8IA2r1cKNfZRTq9F2c1iLuYqQcHg2Dmvbam08QUG1V07zASqDCLouSSE0tojCbGablFoMgkpMxht9QukvICASIXtNLy7rDDakVDeGepzpIUup1mlIZs5Dbo9OknnwEELGgZJgBhHHDYIx/v8/r98+d/P2cVVSOkitRPN9uXfz0j2rRSh1CZDKRmFomgnns62Wyvrq+ncTy2JJ/rRXv76vx04ymr83pci9gYRYISS4N3cgRKvYb15EHOHzy8fPaPgtMe8zHG5y8uH6y3wa7LPbNOIIkQRpCOZt7KzatHFx+Ww0Ki9NX8ZHWy7Sltchtz2aj32nicjZkpLr1m760vp5tN2e8jtHX0Yf4f3da+1L4oEEQAAAAASUVORK5CYII=",leftZag:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAACtElEQVR4Xg2Lu25cZRhF93f5L3OOPeOQmJuDhEIHDa/CC/B4SHSICqS0CERDE2MJAYKEmITEcewZz/nvH7O0taq16eTL++P66nhCDegOAEhghFYhDDM0hSgowQkKkDIwJi0pP/72G9j24vIi8S7nN34lYG1VyOKg0uVKFFIiY/XL+R8s977+6nvttBMkovTDz9/Np3G3fTlvYkoFJswzaxtya2haQ0nUdGa2PLY6GD/9+vjJ+Y+bD+K2vFxtrLS3cQq9t1rLwUZ7IpuOAmQQ8u9/PgFDWbG5708/jK/Ti9OzExErhYVU1TMrCZqV7fY2Or2+uQ5H7zgPMNQF5HL7+upZeFeHLU//etrraM2YedQBAXsnoPXHn8yrcHVzE0LICWoECTQf+SG19dRqK3tMUxSRZtkIZtqbsblW+vF8/Pzy1XoNvdthjDas7He7swdno+JkM21v997r6A1MIKNBwiCiXssqhNsbcAwQosPTeek1MzBa947NmnewYcGR8Oh1sZG8s5LvQoACaK0Yegi+965MNWXnxIAx0AdyWnqDMjuh1KoIkYGNUPqh0zHaYcpwoin1ZiBFjFBVEWLm1ppzTkQAsAQYQdwhTap+dBCRXzkW6g2lIpdqRkYE1v1+AZgEuiRo8G2YaCBo75ZylSCdiMnoYPVefO1k8AYm7rlAjUDi7/ZN18HIffbp5zFO22Vf0bzXfsBQUu4DIJ6P1/t/XowB9RGl4Xj94M62zy+vou2sDUySyhJjTDXpAeL9YFKXaxYnuoL2BRfnzxghj7YKm4liHkszGkOUjtxIYjKM9ncpTnPr4+HDj8j+U5/B5R5k/vfv344m6rfXHb3NSqKvdrs5xKUWeN95nUd69Oi9vpQI0PtfTAn7eE/eLF0Y92eUjrcDISBmrBjbgkrIDPFYCfoCLPgflXOjuIEFgMYAAAAASUVORK5CYII="}},modern:{background:"#000000",backgroundGrid:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAIAAAC0Ujn1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjZTg0NzU4MC00ODk3LTRkNjAtOWNhYi1mZTk1NzQ5NzhiNjkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTEzOEQwMDc5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTEzOEQwMDY5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDplNDRjOWZiNC0yNzE5LTQ3NDYtYmRmMi0wMmY2ZTA4ZjAxMmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzMwNTNEOTk5MDM1MTFFNDlBMzlFNzY4RjBCNkNENzMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7Y01+zAAAAMklEQVR42mJgGAWjYBSMgkEJGIlUd+j/WjjbjjGYGC1MtHP10DR6FIyCUTAKBikACDAA0NoDCLGGjH8AAAAASUVORK5CYII=",primary:null,secondary:null,stroke:null,blocks:{line:"#fa1e1e",square:"#f1fa1e",arrow:"#d838cb",rightHook:"#f5821f",leftHook:"#42c6f0",rightZag:"#4bd838",leftZag:"#fa1e1e"}},retro:{background:"#000000",backgroundGrid:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAIAAAC0Ujn1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjZTg0NzU4MC00ODk3LTRkNjAtOWNhYi1mZTk1NzQ5NzhiNjkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTEzOEQwMDc5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTEzOEQwMDY5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDplNDRjOWZiNC0yNzE5LTQ3NDYtYmRmMi0wMmY2ZTA4ZjAxMmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzMwNTNEOTk5MDM1MTFFNDlBMzlFNzY4RjBCNkNENzMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7Y01+zAAAAMklEQVR42mJgGAWjYBSMgkEJGIlUd+j/WjjbjjGYGC1MtHP10DR6FIyCUTAKBikACDAA0NoDCLGGjH8AAAAASUVORK5CYII=",primary:null,secondary:null,stroke:"#000000",innerStroke:"#000000",blocks:{line:"#fa1e1e",square:"#f1fa1e",arrow:"#d838cb",rightHook:"#f5821f",leftHook:"#42c6f0",rightZag:"#4bd838",leftZag:"#fa1e1e"}},monochrome:{background:"#000000",backgroundGrid:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAIAAAC0Ujn1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjZTg0NzU4MC00ODk3LTRkNjAtOWNhYi1mZTk1NzQ5NzhiNjkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTEzOEQwMDc5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTEzOEQwMDY5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDplNDRjOWZiNC0yNzE5LTQ3NDYtYmRmMi0wMmY2ZTA4ZjAxMmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzMwNTNEOTk5MDM1MTFFNDlBMzlFNzY4RjBCNkNENzMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7Y01+zAAAAMklEQVR42mJgGAWjYBSMgkEJGIlUd+j/WjjbjjGYGC1MtHP10DR6FIyCUTAKBikACDAA0NoDCLGGjH8AAAAASUVORK5CYII=",primary:"#ffffff",secondary:"#ffffff",stroke:"#000000",innerStroke:"#000000"},aerolab:{background:"#ffffff",primary:"#ff7b00",secondary:"#000000"},gameboy:{background:"#C4CFA1",primary:null,secondary:null,stroke:"#414141",innerStroke:"#414141",innerSquare:"#000000",blocks:{line:"#88926A",square:"#585E44",arrow:"#A4AC8C",rightHook:"#6B7353",leftHook:"#6B7353",rightZag:"#595F45",leftZag:"#595F45"}},vim:{background:"#000000",backgroundGrid:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAIAAAC0Ujn1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjZTg0NzU4MC00ODk3LTRkNjAtOWNhYi1mZTk1NzQ5NzhiNjkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTEzOEQwMDc5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTEzOEQwMDY5MDQyMTFFNDlBMzlFNzY4RjBCNkNENzMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDplNDRjOWZiNC0yNzE5LTQ3NDYtYmRmMi0wMmY2ZTA4ZjAxMmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzMwNTNEOTk5MDM1MTFFNDlBMzlFNzY4RjBCNkNENzMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7Y01+zAAAAMklEQVR42mJgGAWjYBSMgkEJGIlUd+j/WjjbjjGYGC1MtHP10DR6FIyCUTAKBikACDAA0NoDCLGGjH8AAAAASUVORK5CYII=",primary:"#C2FFAE",secondary:"#C2FFAE",stroke:"#000000",strokeWidth:3,innerStroke:null}}; \ No newline at end of file diff --git a/dist/blockrain.zip b/dist/blockrain.zip index 0487dc184099f0ab4d6c0b54857b451851e8fa1e..ae434868eb07c5218a014c253afafca8e06e6500 100644 GIT binary patch delta 46466 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�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 W;Ew;h?lXa&K)&=AnRNDla{qtQ+?VYD diff --git a/package-lock.json b/package-lock.json index 72ec975..1f2d6dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2,12 +2,18 @@ "name": "blockrain", "version": "0.2.0", "lockfileVersion": 1, + "requires": true, "dependencies": { "align-text": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } }, "ansi-regex": { "version": "2.1.1", @@ -31,7 +37,10 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } }, "arr-flatten": { "version": "1.1.0", @@ -97,13 +106,22 @@ "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } }, "braces": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } }, "builtin-modules": { "version": "1.1.1", @@ -121,25 +139,45 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + } }, "center-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } }, "clone": { "version": "1.0.2", @@ -163,7 +201,12 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", - "dev": true + "dev": true, + "requires": { + "inherits": "2.0.3", + "process-nextick-args": "1.0.7", + "through2": "2.0.3" + } }, "concat-map": { "version": "0.0.1", @@ -175,7 +218,10 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz", "integrity": "sha1-9Vs74q60dgGxCi1SWcz7cP0vHdY=", - "dev": true + "dev": true, + "requires": { + "source-map": "0.5.6" + } }, "core-util-is": { "version": "1.0.2", @@ -187,7 +233,10 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } }, "dateformat": { "version": "2.0.0", @@ -211,7 +260,10 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true + "dev": true, + "requires": { + "clone": "1.0.2" + } }, "deprecated": { "version": "0.0.1", @@ -223,25 +275,37 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", - "dev": true + "dev": true, + "requires": { + "fs-exists-sync": "0.1.0" + } }, "duplexer2": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } }, "end-of-stream": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true + "dev": true, + "requires": { + "once": "1.3.3" + } }, "error-ex": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } }, "escape-string-regexp": { "version": "1.0.5", @@ -253,19 +317,28 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } }, "expand-range": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true + "dev": true, + "requires": { + "fill-range": "2.2.3" + } }, "expand-tilde": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", - "dev": true + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } }, "extend": { "version": "3.0.1", @@ -277,13 +350,20 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } }, "fancy-log": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", - "dev": true + "dev": true, + "requires": { + "chalk": "1.1.3", + "time-stamp": "1.1.0" + } }, "filename-regex": { "version": "2.0.1", @@ -295,7 +375,14 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } }, "find-index": { "version": "0.1.1", @@ -307,25 +394,45 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } }, "findup-sync": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", - "dev": true + "dev": true, + "requires": { + "detect-file": "0.1.0", + "is-glob": "2.0.1", + "micromatch": "2.3.11", + "resolve-dir": "0.1.1" + } }, "fined": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.3", + "object.defaults": "1.1.0", + "object.pick": "1.2.0", + "parse-filepath": "1.0.1" + }, "dependencies": { "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } } } }, @@ -351,7 +458,10 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true + "dev": true, + "requires": { + "for-in": "1.0.2" + } }, "fs-exists-sync": { "version": "0.1.0", @@ -369,7 +479,10 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true + "dev": true, + "requires": { + "globule": "0.1.0" + } }, "get-stdin": { "version": "4.0.1", @@ -381,37 +494,68 @@ "version": "4.5.3", "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.3.3" + } }, "glob-base": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } }, "glob-parent": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true + "dev": true, + "requires": { + "is-glob": "2.0.1" + } }, "glob-stream": { "version": "3.1.18", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + }, "dependencies": { "readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } }, "through2": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } } } }, @@ -419,37 +563,63 @@ "version": "0.0.6", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true + "dev": true, + "requires": { + "gaze": "0.5.2" + } }, "glob2base": { "version": "0.0.12", "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true + "dev": true, + "requires": { + "find-index": "0.1.1" + } }, "global-modules": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", - "dev": true + "dev": true, + "requires": { + "global-prefix": "0.1.5", + "is-windows": "0.2.0" + } }, "global-prefix": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", - "dev": true + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1", + "ini": "1.3.4", + "is-windows": "0.2.0", + "which": "1.2.14" + } }, "globule": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, "dependencies": { "glob": { "version": "3.1.21", "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } }, "graceful-fs": { "version": "1.2.3", @@ -467,7 +637,11 @@ "version": "0.2.14", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } } } }, @@ -475,25 +649,51 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", - "dev": true + "dev": true, + "requires": { + "sparkles": "1.0.0" + } }, "graceful-fs": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true + "dev": true, + "requires": { + "natives": "1.1.0" + } }, "gulp": { "version": "3.9.1", "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.0.3", + "liftoff": "2.3.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" + } }, "gulp-clean": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/gulp-clean/-/gulp-clean-0.3.2.tgz", "integrity": "sha1-o0fUc6zqQBgvk1WHpFGUFnGSgQI=", "dev": true, + "requires": { + "gulp-util": "2.2.20", + "rimraf": "2.6.1", + "through2": "0.4.2" + }, "dependencies": { "ansi-regex": { "version": "0.2.1", @@ -511,25 +711,50 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" + } }, "dateformat": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } }, "gulp-util": { "version": "2.2.20", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", "dev": true, + "requires": { + "chalk": "0.5.1", + "dateformat": "1.0.12", + "lodash._reinterpolate": "2.4.1", + "lodash.template": "2.4.1", + "minimist": "0.2.0", + "multipipe": "0.1.2", + "through2": "0.5.1", + "vinyl": "0.2.3" + }, "dependencies": { "through2": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "3.0.0" + } } } }, @@ -537,7 +762,10 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } }, "lodash._reinterpolate": { "version": "2.4.1", @@ -549,25 +777,48 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true + "dev": true, + "requires": { + "lodash._escapehtmlchar": "2.4.1", + "lodash._reunescapedhtml": "2.4.1", + "lodash.keys": "2.4.1" + } }, "lodash.keys": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } }, "lodash.template": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", - "dev": true + "dev": true, + "requires": { + "lodash._escapestringchar": "2.4.1", + "lodash._reinterpolate": "2.4.1", + "lodash.defaults": "2.4.1", + "lodash.escape": "2.4.1", + "lodash.keys": "2.4.1", + "lodash.templatesettings": "2.4.1", + "lodash.values": "2.4.1" + } }, "lodash.templatesettings": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "2.4.1", + "lodash.escape": "2.4.1" + } }, "minimist": { "version": "0.2.0", @@ -579,13 +830,22 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } }, "strip-ansi": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } }, "supports-color": { "version": "0.2.0", @@ -598,12 +858,19 @@ "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + }, "dependencies": { "xtend": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true + "dev": true, + "requires": { + "object-keys": "0.4.0" + } } } }, @@ -611,7 +878,10 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true + "dev": true, + "requires": { + "clone-stats": "0.0.1" + } }, "xtend": { "version": "3.0.0", @@ -626,6 +896,11 @@ "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", "dev": true, + "requires": { + "concat-with-sourcemaps": "1.0.4", + "through2": "2.0.3", + "vinyl": "2.1.0" + }, "dependencies": { "clone": { "version": "2.1.1", @@ -649,7 +924,15 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true + "dev": true, + "requires": { + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.0.0", + "remove-trailing-separator": "1.0.2", + "replace-ext": "1.0.0" + } } } }, @@ -657,37 +940,89 @@ "version": "1.8.8", "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.8.tgz", "integrity": "sha1-RQnGRneqtWte6ORmmnmxZVkzpJ4=", - "dev": true + "dev": true, + "requires": { + "concat-with-sourcemaps": "1.0.4", + "gulp-util": "3.0.8", + "object-assign": "3.0.0", + "through2": "2.0.3" + } }, "gulp-uglify": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.4.tgz", "integrity": "sha1-UkeI2HZm0J+dDCH7IXf5ADmmWMk=", - "dev": true + "dev": true, + "requires": { + "deap": "1.0.0", + "fancy-log": "1.3.0", + "gulp-util": "3.0.8", + "isobject": "2.1.0", + "through2": "2.0.3", + "uglify-js": "2.6.4", + "uglify-save-license": "0.4.1", + "vinyl-sourcemaps-apply": "0.2.1" + } }, "gulp-util": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.0.0", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + } }, "gulp-zip": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/gulp-zip/-/gulp-zip-2.0.3.tgz", "integrity": "sha1-iO8RbT8VvSCvzqyQFl0fxj88bh8=", "dev": true, + "requires": { + "chalk": "1.1.3", + "gulp-util": "3.0.8", + "jszip": "2.6.1", + "through2": "0.6.5" + }, "dependencies": { "readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } }, "through2": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } } } }, @@ -695,25 +1030,37 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true + "dev": true, + "requires": { + "glogg": "1.0.0" + } }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } }, "has-gulplog": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true + "dev": true, + "requires": { + "sparkles": "1.0.0" + } }, "homedir-polyfill": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } }, "hosted-git-info": { "version": "2.5.0", @@ -725,13 +1072,20 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true + "dev": true, + "requires": { + "repeating": "2.0.1" + } }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true + "dev": true, + "requires": { + "once": "1.3.3", + "wrappy": "1.0.2" + } }, "inherits": { "version": "2.0.3", @@ -755,7 +1109,11 @@ "version": "0.2.6", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", - "dev": true + "dev": true, + "requires": { + "is-relative": "0.2.1", + "is-windows": "0.2.0" + } }, "is-arrayish": { "version": "0.2.1", @@ -773,7 +1131,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } }, "is-dotfile": { "version": "1.0.3", @@ -785,7 +1146,10 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } }, "is-extendable": { "version": "0.1.1", @@ -803,25 +1167,37 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true + "dev": true, + "requires": { + "kind-of": "3.2.2" + } }, "is-plain-object": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.3.tgz", "integrity": "sha1-wVvz5LZrYtcu+vKSWEhmPsvGGbY=", "dev": true, + "requires": { + "isobject": "3.0.1" + }, "dependencies": { "isobject": { "version": "3.0.1", @@ -847,13 +1223,19 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", - "dev": true + "dev": true, + "requires": { + "is-unc-path": "0.1.2" + } }, "is-unc-path": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", - "dev": true + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } }, "is-utf8": { "version": "0.2.1", @@ -884,6 +1266,9 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, + "requires": { + "isarray": "1.0.0" + }, "dependencies": { "isarray": { "version": "1.0.0", @@ -902,13 +1287,19 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-2.6.1.tgz", "integrity": "sha1-uI86ey5noqBIFSmCx6N1bZxIKPA=", - "dev": true + "dev": true, + "requires": { + "pako": "1.0.5" + } }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } }, "lazy-cache": { "version": "1.0.4", @@ -920,13 +1311,31 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", - "dev": true + "dev": true, + "requires": { + "extend": "3.0.1", + "findup-sync": "0.4.3", + "fined": "1.1.0", + "flagged-respawn": "0.3.2", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.mapvalues": "4.6.0", + "rechoir": "0.6.2", + "resolve": "1.3.3" + } }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + }, "dependencies": { "graceful-fs": { "version": "4.1.11", @@ -938,7 +1347,10 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } } } }, @@ -970,7 +1382,10 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", - "dev": true + "dev": true, + "requires": { + "lodash._htmlescapes": "2.4.1" + } }, "lodash._escapestringchar": { "version": "2.4.1", @@ -1031,12 +1446,21 @@ "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", "dev": true, + "requires": { + "lodash._htmlescapes": "2.4.1", + "lodash.keys": "2.4.1" + }, "dependencies": { "lodash.keys": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } } } }, @@ -1050,19 +1474,31 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1" + } }, "lodash.defaults": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1", + "lodash.keys": "2.4.1" + }, "dependencies": { "lodash.keys": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } } } }, @@ -1070,7 +1506,10 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } }, "lodash.isarguments": { "version": "3.1.0", @@ -1088,7 +1527,10 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1" + } }, "lodash.isplainobject": { "version": "4.0.6", @@ -1106,7 +1548,12 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } }, "lodash.mapvalues": { "version": "4.6.0", @@ -1124,25 +1571,48 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } }, "lodash.templatesettings": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } }, "lodash.values": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", "dev": true, + "requires": { + "lodash.keys": "2.4.1" + }, "dependencies": { "lodash.keys": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } } } }, @@ -1156,7 +1626,11 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } }, "lru-cache": { "version": "2.7.3", @@ -1181,6 +1655,18 @@ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, "dependencies": { "object-assign": { "version": "4.1.1", @@ -1194,13 +1680,31 @@ "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.3" + } }, "minimatch": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } }, "minimist": { "version": "1.2.0", @@ -1213,6 +1717,9 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, + "requires": { + "minimist": "0.0.8" + }, "dependencies": { "minimist": { "version": "0.0.8", @@ -1226,7 +1733,10 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } }, "natives": { "version": "1.1.0", @@ -1238,13 +1748,22 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "4.3.6", + "validate-npm-package-license": "3.0.1" + } }, "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true + "dev": true, + "requires": { + "remove-trailing-separator": "1.0.2" + } }, "number-is-nan": { "version": "1.0.1", @@ -1269,12 +1788,21 @@ "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.0.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + }, "dependencies": { "for-own": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true + "dev": true, + "requires": { + "for-in": "1.0.2" + } }, "isobject": { "version": "3.0.1", @@ -1288,25 +1816,40 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } }, "object.pick": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.2.0.tgz", "integrity": "sha1-tTkr7peC2m2ft9avr1OXefEjTCs=", - "dev": true + "dev": true, + "requires": { + "isobject": "2.1.0" + } }, "once": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true + "dev": true, + "requires": { + "wrappy": "1.0.2" + } }, "orchestrator": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.0" + } }, "ordered-read-streams": { "version": "0.1.0", @@ -1330,19 +1873,33 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", - "dev": true + "dev": true, + "requires": { + "is-absolute": "0.2.6", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "dev": true, + "requires": { + "error-ex": "1.3.1" + } }, "parse-passwd": { "version": "1.0.0", @@ -1354,7 +1911,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } }, "path-is-absolute": { "version": "1.0.1", @@ -1372,7 +1932,10 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } }, "path-root-regex": { "version": "0.1.2", @@ -1385,6 +1948,11 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, "dependencies": { "graceful-fs": { "version": "4.1.11", @@ -1410,7 +1978,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true + "dev": true, + "requires": { + "pinkie": "2.0.4" + } }, "preserve": { "version": "0.2.0", @@ -1435,18 +2006,28 @@ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, "dependencies": { "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, + "requires": { + "kind-of": "3.2.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } } } }, @@ -1454,7 +2035,10 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } } } }, @@ -1462,37 +2046,63 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } }, "read-pkg-up": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } }, "readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true + "dev": true, + "requires": { + "resolve": "1.3.3" + } }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } }, "regex-cache": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", - "dev": true + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3", + "is-primitive": "2.0.0" + } }, "remove-trailing-separator": { "version": "1.0.2", @@ -1516,7 +2126,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true + "dev": true, + "requires": { + "is-finite": "1.0.2" + } }, "replace-ext": { "version": "0.0.1", @@ -1528,37 +2141,61 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", - "dev": true + "dev": true, + "requires": { + "path-parse": "1.0.5" + } }, "resolve-dir": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", - "dev": true + "dev": true, + "requires": { + "expand-tilde": "1.2.2", + "global-modules": "0.2.3" + } }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true + "dev": true, + "requires": { + "align-text": "0.1.4" + } }, "rimraf": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", "dev": true, + "requires": { + "glob": "7.1.2" + }, "dependencies": { "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } } } }, @@ -1566,7 +2203,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-1.0.2.tgz", "integrity": "sha1-hBdXc8OGJ+m70gxJab9z70K2tdU=", - "dev": true + "dev": true, + "requires": { + "chalk": "1.1.3" + } }, "safe-buffer": { "version": "5.1.1", @@ -1614,7 +2254,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", - "dev": true + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } }, "spdx-expression-parse": { "version": "1.0.4", @@ -1644,19 +2287,29 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } }, "strip-bom": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } }, "strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } }, "supports-color": { "version": "2.0.0", @@ -1669,6 +2322,10 @@ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + }, "dependencies": { "isarray": { "version": "1.0.0", @@ -1680,13 +2337,25 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } }, "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } } } }, @@ -1694,7 +2363,10 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } }, "time-stamp": { "version": "1.1.0", @@ -1712,7 +2384,13 @@ "version": "2.6.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", - "dev": true + "dev": true, + "requires": { + "async": "0.2.10", + "source-map": "0.5.6", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } }, "uglify-save-license": { "version": "0.4.1", @@ -1754,25 +2432,47 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true + "dev": true, + "requires": { + "user-home": "1.1.1" + } }, "validate-npm-package-license": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "dev": true + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } }, "vinyl": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } }, "vinyl-fs": { "version": "0.3.14", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", "dev": true, + "requires": { + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, "dependencies": { "clone": { "version": "0.2.0", @@ -1784,19 +2484,33 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } }, "through2": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } }, "vinyl": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } } } }, @@ -1804,13 +2518,19 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true + "dev": true, + "requires": { + "source-map": "0.5.6" + } }, "which": { "version": "1.2.14", "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", - "dev": true + "dev": true, + "requires": { + "isexe": "2.0.0" + } }, "window-size": { "version": "0.1.0", @@ -1841,6 +2561,12 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + }, "dependencies": { "camelcase": { "version": "1.2.1", diff --git a/package.json b/package.json index 7758de4..ce3370c 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,9 @@ "dependencies": { "jquery": "~1.11.3" }, + "scripts": { + "build": "gulp build" + }, "devDependencies": { "gulp": "^3.8.8", "gulp-clean": "^0.3.1",