

soundManager.waitForWindowLoad = true;



Array.prototype.remove = function(from, to) {
    var rest = this.slice((to || from) + 1 || this.length);
    this.length = from < 0 ? this.length + from : from;
    return this.push.apply(this, rest);
};

Array.max = function (array) {
    return Math.max.apply(Math, array);
};

Array.min = function (array) {
    return Math.min.apply(Math, array);
};


DIFFICULTY = 1;
LEVEL = 0;
CANVAS_HEIGHT = 600;
CANVAS_WIDTH = 800;
ENEMY_FIREPOWER = 5000;

spawn = object;

soundfx = function () {
    
    var bites = {},
        adv = "1";
    
    return {
        play: function (snd, continuous) {
            if (bites[snd]) {
                if (continuous) {
                    bites[snd].play({
                        onfinish: function () {
                            this.play();
                        }
                    });
                } else {
                    bites[snd].play();
                }
            }
            
            if (snd === "advance") {
                if (adv === "1") {
                    bites.advance = bites.advance2;
                    adv = "2";
                } else if (adv === "2") {
                    bites.advance = bites.advance3;
                    adv = "3";
                } else if (adv === "3") {
                    bites.advance = bites.advance4;
                    adv = "4";
                } else {
                    bites.advance = bites.advance1;
                    adv = "1";
                }
            }
        },
        stop: function (snd) {
            if (bites[snd]) {
                bites[snd].stop();
            }
        },
        init: function () {
            bites.fire = soundManager.createSound({
                id: 'fire',
                url: 'sounds/shoot.mp3'
            });
            
            bites.advance1 = soundManager.createSound({
                id: 'advance1',
                url: 'sounds/fastinvader4.mp3'
            });
            
            bites.advance2 = soundManager.createSound({
                id: 'advance2',
                url: 'sounds/fastinvader1.mp3'
            });
            
            bites.advance3 = soundManager.createSound({
                id: 'advance3',
                url: 'sounds/fastinvader2.mp3'
            });
            
            bites.advance4 = soundManager.createSound({
                id: 'advance4',
                url: 'sounds/fastinvader3.mp3'
            });
            
            bites.death = soundManager.createSound({
                id: 'death',
                url: 'sounds/explosion.mp3'
            });
            
            bites.hit = soundManager.createSound({
                id: 'hit',
                url: 'sounds/invaderkilled.mp3'
            });
            
            bites.mothership = soundManager.createSound({
                id: 'mothership',
                url: 'sounds/ufo_highpitch.mp3'
            })
            
            bites.advance = bites.advance1;
  

        }
    };
}();


si = (function () {
    
    var viewport,
        sprites = {
            invader1s: [],
            invader2s: [],
            invader3s: [],
            invader4s: [],
            motherships: []
        },
        velocity = 2000/DIFFICULTY,
        columns = 11,
        lasers = [],
        invaders = [],
        motherships = [],
        silos = [],
        bombs = [],
        melee = function () {
            var fns = [], tt, round, lowest = Infinity, incrs = [], now = new Date().getTime(), lastRound, killed = false, cycle = 0, prevDown = false;
            
            return {
                down: false,
                track: function (f) {
                    fns.push(f);
                },
                listen: function () {
                    
                    round = function () {
                        var i, reaction, delta, delay = velocity;
                        
                        if (killed) {
                            return;
                        }
                        
                        
                        now = new Date().getTime();
                        
                        delta = (now - lastRound) || 0;
                        if (delta > velocity) {
                            delay = Math.max(1, delay - (delta - delay))
                        }

                        soundfx.play("advance");
                                                
                        
                        if (!prevDown && (melee.xmin(cycle) <= 0 || melee.xmax(cycle) >= 750)) {
                            melee.down = true;
                            prevDown = true;
                        } else {
                            melee.down = false;
                            prevDown = false;
                        }
                            
                        
                        for (i = 0; i != fns.length; i++) {
                            reaction = fns[i](melee.down);
                            
                            if (reaction.stop) {
                                window.clearTimeout(tt);
                            }
                            if (reaction.clear) {
                                fns.remove(i);
                            }
                            
                            if (reaction.low < lowest) {
                                lowest = reaction.low;
                            }   
                        }
                        
                        if (melee.down) {
                            melee.increaseSpeed("lower" + lowest);
                        }
                        
                        melee.down = false;
                        
                        
                        
                        if (/(4|2|1)/.test(Math.round(invaders.length/11) + "")) {
                            melee.increaseSpeed("dwindling" + Math.round(invaders.length/11));
                        }
                        
                        if (invaders.length === 1) {
                            melee.increaseSpeed("oneleft" + lowest);
                        }
                        
                       
                        
                        
                        lastRound = now;
                        tt = window.setTimeout(round, delay);
                        
                        ++cycle;

                    };
                    
                    tt = window.setTimeout(round, velocity);
                },
                stop: function () {
                    window.clearTimeout(tt);
                },
                increaseSpeed: function (because) {
                    if (incrs.indexOf(because) >= 0) {
                        return;
                    }
                    incrs.push(because);
                    velocity = velocity/1.5;
                },
                xmax: function (cyc) {
                    return Array.max(invaders.map(function (inv) { if (inv.cycle() === cyc) { return inv.x*1; } else { return -Infinity; } }));
                },
                xmin: function (cyc) {
                    return Array.min(invaders.map(function (inv) { if (inv.cycle() === cyc) { return inv.x*1; } else { return Infinity; } }));
                },
                ylow: function () {
                    return CANVAS_HEIGHT - Array.max(invaders.map(function (inv) { return inv.y*1; }));
                },
                reset: function () {
                    fns = [];
                    incrs = [];
                    cycle = 0;
                    prevDown = false;
                }
            };
        }(),
        win = function () {
            LEVEL++;
            DIFFICULTY = DIFFICULTY*2;
            GM.init(LEVEL);
        },
        lost = function () {
            viewport.image("game-over.png", 0, 0, 800, 600);
            
            si.defender.fire = function () {};
            si.defender.left = function () {};
            si.defender.right = function () {};
            
            melee.stop();
            
            // alow user to enter high score
            scoreboard.record();
        },
        scoreboard = function () {
            var livesLeft = 3,
                totalScore = 0,
                livesElem,
                scoreElem,
                hasScored = false,
                key = "";
                  
            return {
                start: function () {
                    livesElem = document.createElement("div");
                    livesElem.id = "lives";
                    scoreElem = document.createElement("div");
                    scoreElem.id = "score";
                    T("#bn").ls(0).appendChild(livesElem);
                    T("#bn").ls(0).appendChild(scoreElem);
                    
                    livesElem.innerHTML = "lives: " + livesLeft;
                    scoreElem.innerHTML = "score: " + totalScore;
                },
                lives: function (a) {
                    livesLeft += a;
                    livesElem.innerHTML = "lives: " + livesLeft;
                },
                points: function (a) {
                    totalScore += a;
                    scoreElem.innerHTML = "score: " + totalScore;
                },
                record: function () {
                    var sdiv = document.createElement("div"),
                        sform  = document.createElement("form"),
                        ref = this;
                    
                    sdiv.id = "enter-score";
                    
                    // yuk!
                    T(window).on("keypress", function() {
                        if (hasScored) {
                            return;
                        }
                        sform.innerHTML = "" +
                        "<fieldset>" +
                        "<legend>Your score: " + totalScore + "</legend>" +
                        "<label>" +
                        "Enter your name:" +
                        "<input type=\"text\" id=\"user-name\">" +
                        "</label>" +
                        "<input class=\"submit\" type=\"submit\" value=\"Go\">" +
                        "</fieldset>";
                        
                        hasScored = true;
                        
                        T(sform).on("submit", function (ev) {
                            
                            var uname = T("#user-name").ls(0).value;
                            
                            tanto.ajax.callbackJSON("http://si.boundvariable.com/add?access=" + key + "&name=" + uname + "&score=" + totalScore + "&callback=tanto.ajax.callbackHandler", function (data) {  
                                ref.display(data);
                            }, true, false, true);
                            
                            
                            ev.stopPropagation();
                            ev.preventDefault();
                        });
                        
                        sdiv.appendChild(sform);
                        document.body.appendChild(sdiv);
                    });
                      
                },
                display: function (data) {
                    var decorate = function (d) {
                        var s = "<h3 style=\"margin:0;padding:0;color:#fff;\">Top Scores</h3><br><ul style=\"margin:0;padding:0;font-size:0.82em;color:#fff;list-style-type:none\">";
                        
                        d.ten.forEach(function (item) {
                            s += "<li>" + item.name + " -- " + item.score + "</li>";
                        });
                        return s + "</ul> <br><a href=\"\">Start again</a>";
                    };
                    
                    T("#enter-score").ls(0).style.height = "440px";
                    T("#enter-score").ls(0).style.padding = "10px";
                    T("#enter-score").el().html(decorate(data));
                    
                },
                setKey: function (k) {
                    key = k;
                }
            };
        }(),
        mothership = function () {
            var isAlive = false,
                boost = 20;
            
            return {
                live: function () {
                    motherships.push(this);
                    this.x = 0;
                    this.y = 0;
                    this.isAlive = true;
                    this.points = 250;
                    this.sprite = viewport.image("sprites/mothership.png", this.x, this.y, 45, 30);
                    this.live = function () {
                        return this;
                    };
                    this.die = function () {
                        var rt, that = this;
                        this.sprite.remove();
                        this.sprite = viewport.image("sprites/invader-explode.png", this.x, this.y, 45, 30);
                        soundfx.play("hit");
                        scoreboard.points(this.points);
                        rt = window.setTimeout( function () {
                            soundfx.stop("mothership");
                            that.sprite.remove();
                        }, 200);
                    };
                    return this;
                },
                invade: function () {
                    var ref = this,
                        t = window.setInterval( function () {
                            if (!ref.isAlive) {
                                window.clearInterval(t);
                                return false;
                            }
                            ref.x += 3;
                            ref.sprite.translate(3, 0);
                            
                            if (ref.x > CANVAS_WIDTH) {
                                window.clearInterval(t);
                                soundfx.stop("mothership");
                                return false;
                            }
                            
                            
                        }, velocity/boost);
                        
                    soundfx.play("mothership", true);
                }
            };
        }(),
        invader = function () {
            var isAlive = false,
                spath = "";
          
            return {
                cycle: function () {
                    return this.cyc || 0;
                },
                pos: function (xy) {
                    this.x = xy.x;
                    this.y = xy.y;
                    
                    return this;
                },
                live: function () {
                    invaders.push(this);
                    this.isAlive = true;
                    this.points = this.points || 0;
                    this.live = function () {   
                        return this;
                    };
                    this.cyc = 0;
                    this.die = function () {
                        this.isAlive = false;
                        scoreboard.points(this.points);
                        soundfx.play("hit");
                        
                        return viewport.image("sprites/invader-explode.png", this.x, this.y, 45, 30);
                    };
                    this.stype = "";
                    return this;
                },
                fire: function () {
                    var gcof = 20,
                        drop = this.y,
                        ref = this,
                        bomb = viewport.image("sprites/bomb.png", this.x, this.y + 20, 7, 15).toFront(),
                        t = window.setInterval(function () {
                            drop += 10;
                            bomb.translate(0, 10);
                            theBomb.y = theBomb.y + 10;
                            if (!!bombs.length && theBomb.y > CANVAS_HEIGHT) {
                                bomb.remove();
                                bombs.shift();
                                window.clearInterval(t);
                            }
                        }, velocity/gcof),
                        theBomb = {"sprite": bomb, "x": this.x, "y": this.y};
                        
                        bombs.push(theBomb);

                    
                },
                invade: function (i) {
                    var ii = i,
                        ref = this,
                        dir = 1,
                        down = 0,
                        rval = "",
                        alt = "-alt",
                        invadeFn = function (goDown) {
                            var firing = Math.floor(Math.random()*1000000);
                            if (!ref.isAlive) {
                                return {"dead": true};
                            }
                            
                            if (invaders.indexOf(ref) < 0) {
                                return {"clear": true};
                            }
                            
                            
                            if (firing > (1000000 - ENEMY_FIREPOWER)) {
                                ref.fire();
                            }
                            
                            
                            if (dir === 1 &&  goDown) {
                                down = 40;
                                dir = -1;
                            } else if (dir === -1 && goDown) {
                                down = 40;
                                dir = 1;
                            } else {
                                down = 0;
                                ref.x += dir*10;
                            }
                            
                        
                            
                            
                            ref.y += down;
                            rval = {"low": CANVAS_HEIGHT - ref.y};
                            
                            if (ref.y > CANVAS_HEIGHT - 40) {
                                rval = {"stop": true};
                            }

                            if (!!down) {
                                sprites[ref.stype][ii].remove();
                                sprites[ref.stype][ii] = viewport.image("sprites/" + (ref.spath || spath) + alt + ".png", ref.x, ref.y, 45, 30);
                            } else {
                                sprites[ref.stype][ii].remove();
                                sprites[ref.stype][ii] = viewport.image("sprites/" + (ref.spath || spath) + alt + ".png", ref.x, ref.y, 45, 30);
                            }
                            if (alt === "-alt") {
                                alt = "";
                            } else {
                                alt ="-alt";
                            }
                            ref.sprite = sprites[ref.stype][ii];
                            
                            ++ref.cyc;
                            
                            return rval;
                        };
                        
                        melee.track(invadeFn);
                        
                        
                },
                setSpriteFileName: function (path) {
                    this.spath = path;
                },
                setSpriteType: function (s) {
                    this.stype = s;
                },
                setPoints: function (points) {
                    this.points = points;
                }
                
            };
            
        }(),
        silo = function () {
            var lookup = function (xy) {
                    var tbl = [[0,0], [0,16], [4,8],
                          [5,5], [5,6], [5,7], [5,8], [5,9], [5,10], [5,11],
                          [6,5], [6,6], [6,7], [6,8], [6,9], [6,10], [6,11],
                          [7,5], [7,6], [7,7], [7,8], [7,9], [7,10], [7,11]];
                    
                    return tbl.indexOf(xy);
                },
                findY = function (dir, x) {
                    var gx = Math.round(x/(67/17)), i;
                    
                    if (dir === "above") {
                    
                        for (i = 0; i != 7; i++) {
                            if (this.shield[gx][i]) {
                                this.shield[gx][i] = 0;
                                return i;
                            }
                        }
                        return -1;
                    
                    } else if (dir === "below") {
                        for (i = 7; i !== 0; i--) {
                            if (this.shield[gx][i]) {
                                this.shield[gx][i] = 0;
                                return i;
                            }
                        }
                        return -1;
                    }
                    
                    return -1;
                    
                };
            
            return {
                hit: function (dir, loc) {
                    var fy = findY.apply(this, [dir, loc]),
                        r;
                    
                    if (fy >= 0) {
                        r = viewport.rect(this.x + loc - 2, this.y + fy*9 - 9, 8, 13);
                        r.attr("fill", "black");
                        return true;
                    }
                    
                    
                    return false;
                },
                activate: function (offset) {
                    var i, j;
                    
                    silos.push(this);
                    this.shield = [];
                    this.x = Math.round(CANVAS_WIDTH/4*offset + CANVAS_WIDTH/12);
                    this.y = CANVAS_HEIGHT - 108;
                    this.w = 67;
                    this.h = 58;
                    this.sprite = viewport.image("sprites/silo.png", this.x, this.y, this.w, this.h);
                    
                    for (i = 0; i != 17; i++) {
                        for (j = 0; j != 7; j++) {
                            if (lookup([i, j]) < 0) {
                                this.shield[i] = this.shield[i] || [];
                                this.shield[i][j] = 1;
                            } else {
                                this.shield[i] = this.shield[i] || [];
                                this.shield[i][j] = 0;
                            }
                        }
                    }
                    return this;
                },
                box: function () {
                    return {"x": this.x, "y": this.y, "w": this.w, "h": this.h};
                }
                
            };
        }();
            
    
    return {
        viewport: function () {
            viewport = Raphael(T("#si").ls(0), 800, 600);
            scoreboard.start();
        },
        remote: function (k) {
            scoreboard.setKey(k);
        },
        defender: function () {
            
            var pos = (CANVAS_WIDTH - 80)/9,
                lpos = pos,
                lives = 3,
                laserlock = 0;
            
            sprites.defender = viewport.image("sprites/defender.png", pos, CANVAS_HEIGHT - 28, 45, 30);
            
            si.defender = {
                left: function (multiplier) {
                    lpos = pos;
                    pos += -1*multiplier;
                    if (pos <= 0) {
                        pos = 0;
                        sprites.defender.translate(-1*lpos, 0);
                        lpos = 0;
                        return;
                    }
                    sprites.defender.translate(-1*multiplier, 0);
                },
                right: function (multiplier) {
                    lpos = pos;
                    pos += 1*multiplier;
                    if (pos >= (CANVAS_WIDTH - 44)) {
                        
                        sprites.defender.translate(CANVAS_WIDTH - lpos - 44, 0);
                        pos = CANVAS_WIDTH - 44;
                        return;
                    }
                    sprites.defender.translate(1*multiplier, 0);
                },
                fire: function () {
                    var laser = viewport.rect(pos + 20, CANVAS_HEIGHT - 40, 4, 9);
                    
                    soundfx.play("fire");
                    
                    laser.attr("fill", "#10e60f");
                    laser.animate({y: 0}, 1000);
                    lasers.push({"start": new Date(), x: pos + 20, sprite: laser});
                },
                x: function () {
                    return pos;
                },
                kill: function () {
                    var tt, tpos = pos;
                    
                    sprites.defender.remove();
                    sprites.defender = viewport.image("sprites/defender-dead.png", pos, CANVAS_HEIGHT - 28, 45, 30);
                    
                    soundfx.play("death");
                    
                    lives = lives - 1;
                    scoreboard.lives(-1);
                    if (lives === 0) {
                        pos = NaN;
                        lost();
                    } else {
                        tpos = pos;
                        pos = NaN;
                        tt = window.setTimeout(function () {
                            pos = (CANVAS_WIDTH - 80)/9;
                            sprites.defender.remove();
                            sprites.defender = viewport.image("sprites/defender.png", pos, CANVAS_HEIGHT - 28, 45, 30);
                        }, 500);
                    }
                }
            };
        },
        invaders: function () {
            var thisInvader, i = 0,
                sploop = ["invader1s", "invader2s", "invader3s", "invader4s", "invader5s"],
                sploopi = ["invader-1", "invader-2", "invader-3", "invader-4", "invader-5"],
                spoints = [40, 20, 20, 10, 10],
                j;
            
            sprites.invader1s = [];
            sprites.invader2s = [];
            sprites.invader3s = [];
            sprites.invader4s = [];
            sprites.invader5s = [];
            sprites.motherships = [];

            for (j = 0; j != sploop.length; j++) {
                for (i = 0; i != columns; i++) {
                    thisInvader = spawn(invader).live();
                    thisInvader.pos({x: 0 + (50*i) + 120, y: 0 + 50*j});
                    thisInvader.setSpriteFileName(sploopi[j]);
                    thisInvader.setPoints(spoints[j]);
                    thisInvader.setSpriteType(sploop[j]);
                    sprites[sploop[j]][i] = viewport.image("sprites/" + sploopi[j] + ".png", 0 + (50*i) + 120, 0 + 50*j, 45, 30); 
                    thisInvader.sprite = sprites[sploop[j]][i];
                    thisInvader.invade(i);   
                }
            }
            melee.listen();
        },

        collisions: function () {
            var i, j, xDiff, yDiff, explosion;
            
            window.setInterval(function () {
                var scrub = false;
                for (i = 0; i < lasers.length; i++) {
                    if (!lasers[i]) {
                        continue;
                    }
                    
                    // estimate laser y
                    lasers[i].y = ((CANVAS_HEIGHT - 40) - (((new Date()) - lasers[i].start)/1000)*(CANVAS_HEIGHT - 40));
                    if (lasers[i].y < 0) {
                        lasers[i].sprite.remove();
                        lasers.remove(i);
                        break;
                    }
                    
                    for(j = 0; j < invaders.length; j++) {
                        if (typeof invaders[j] === "undefined") {
                            return;
                        }
                        
                        
                        // collision detection 
                        xDiff = lasers[i].x - invaders[j].x;
                        yDiff = lasers[i].y - invaders[j].y;
                        if (xDiff > 0 && xDiff < 40) {
                            if (yDiff > 5 && yDiff < 40) {
                                lasers[i].sprite.remove();
                                lasers.remove(i);
                                      
                                invaders[j].sprite.remove();
                                explosion = invaders[j].die();
                                window.setTimeout(function () {
                                    explosion.remove();
                                }, 300);
                                invaders.remove(j);
                                if (invaders.length === 0) {
                                    win();
                                }
                                break;
                            }
                        }
                    }
                    for (j = 0; j < silos.length; j++) {
                        if (lasers.length === 0) {
                            break;
                        }
                        if (lasers[i].y > (silos[j].box().y - silos[j].box().h)) {
                            if (lasers[i].x > silos[j].box().x && lasers[i].x < silos[j].box().x + silos[j].box().w) {
                                if (silos[j].hit("below", lasers[i].x - silos[j].box().x)) {
                                    lasers[i].sprite.remove();
                                    lasers.remove(i);
                                    break;
                                }
                            }
                        }
                    }
                    
                    for (j = 0; j < motherships.length; j++) {    
                        if (lasers[i].y < 80 && lasers[i].x > motherships[j].x && lasers[i].x < motherships[j].x + 50) {
                           
                            lasers[i].sprite.remove();
                            lasers.remove(i);
                            motherships[j].die();
                            motherships.remove(j);
                            break;
                        }
                    }
                    
                }
                
                
                for(i = 0; i < bombs.length; i++) {
                    if (!bombs[i]) {
                        continue;
                    }
                    if (bombs[i] && (bombs[i].y > (CANVAS_HEIGHT - 30)) && (bombs[i].y < CANVAS_HEIGHT)) {
                        if (bombs[i].x < (si.defender.x() + 60) &&  bombs[i].x > (si.defender.x())) {
                            bombs[i].sprite.remove();
                            si.defender.kill();
                            break;
                        }
                    }
                    for (j = 0; j != silos.length; j++) {
                        if (!silos[j]) {
                            continue;
                        }
                        if (bombs[i].y > silos[j].box().y - silos[j].box().h) {
                            if (bombs[i].x > silos[j].box().x && bombs[i].x < silos[j].box().x + silos[j].box().w) {
                                if (silos[j].hit("above", bombs[i].x - silos[j].box().x)) {
                                    if (bombs[i]) {
                                        bombs[i].sprite.remove();
                                        bombs.remove(i);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
                
                
                if (melee.ylow() < 40) {
                    lost();
                }
                
            }, 50);
        },
        motherships: function () {
            var i;
            
            window.setTimeout(function () {
                window.setInterval(function () {
                    var theMothership;
                    
                    if (Math.floor(Math.random()*1000000) > 900000) {
                        if (motherships.length === 0) {
                            theMothership = spawn(mothership).live();
                            theMothership.invade();
                        }
                    }
                }, 2000);
            }, 15000*DIFFICULTY);
        },
        silos: function () {
            var n = 4, i = 0, theSilo;
            
            for (; i != n; i++) {
                theSilo = spawn(silo).activate(i);
            }
        },
        nlasers: function () {
            return lasers.length;
        },
        reset: function () {
            melee.stop();
            melee.reset();
        }
    };   
}());

GM = (function () {
    var build = function (level) {
            if (level === 0) {
                si.viewport();
                si.silos();
                si.defender();
            }
            si.reset();
            si.invaders();
            si.collisions();
            si.motherships();
        },
        gameKey;
        
    tanto.ajax.callbackJSON("http://si.boundvariable.com/key?callback=tanto.ajax.callbackHandler", function (data) {
        gameKey = data.access;
        si.remote(gameKey);
    });
  
    
    return {
        init: function (level) {  
            var m = null,
                mult = 1,
                last = null,
                since = 0,
                prev = 0,
                iv = 5,
                keylasers = 0,
                keylistening = true,
                SPACE = 32,
                LEFT = 37,
                RIGHT = 39,
                userMove = function (ev) {
                    var intent = (ev || {keyCode: last}).keyCode,
                        now = new Date().getTime(),
                        delta = now - prev,
                        delay = iv;
                        
                    //if (prev && (delta > iv)) {
                    //    console.log(delta);
                    //    delay = delta - iv;  //Math.max(iv, delay - (delta - delay));
                    //}
                    
                    if (intent === LEFT) {
                        si.defender.left(4);
                        last = LEFT;
                    } else if (intent === RIGHT) {
                        si.defender.right(4);
                        last = RIGHT;
                    } else {
                        return;
                    }
                    
                    m = window.setTimeout(function () {
                        userMove();
                    }, delay);
                    
                    prev = now;
        
                    if (keylistening) {
                        tanto.dom.events.remove(document, "keydown", userMove);
                        keylistening = false;
                    }
                    
                }, userFire = function (ev) {
                    var intent = (ev || {keyCode: last}).keyCode;
                    if (intent === SPACE) {
                        if (si.nlasers() === 0) {
                            si.defender.fire();
                        }
                    }
                };
    
            T(window).on("keyup", function (ev) {
                if (ev.keyCode === 37 || ev.keyCode === 39) {
                    window.clearTimeout(m);
                    last = null;
                    m = null;
                }
                tanto.dom.events.add(document, "keydown", userMove);
                keylistening = true;
            });
            
            tanto.dom.events.add(document, "keydown", userMove);
            tanto.dom.events.add(document, "keydown", userFire);
            keylistening = true;
    
            build(level);
        }
    };

}());


T(window).on("load", function () {

    soundManager.onload = function () {
        soundfx.init();
    };
    
    window.onkeydown = function (ev) {
        if (ev.keyCode === 32) {
            window.onkeydown = null;
            document.getElementById("si").style.background = "#000";
            GM.init(0);
        }
    };
});