joo.classLoader.prepare("package net.jangaron",[

"import joo.css.Color",""],

"public class Trapez",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[

"public function setValues",function(color,x1,y1,x2,y2){
this.color=color;
if(x2<x1){

this.x1=x2;
this.y1=y2;
this.x2=x1;
this.y2=y1;
}else{
this.x1=x1;
this.y1=y1;
this.x2=x2;
this.y2=y2;
}
},

"public function intersects",function(trapez){
return Math.max(this.x1,trapez.x1)<=Math.min(this.x2,trapez.x2);
},

"public function toString",function(){
return"["+[this.color,this.x1,this.y1,this.x2,this.y2].join(",")+"]";
},

"public var",{color: undefined},
"public var",{x1: undefined},
"public var",{y1: undefined},
"public var",{x2: undefined},
"public var",{y2: undefined},
];},[]
);joo.classLoader.prepare("package net.jangaron",[

"import joo.lang.JOObject",
"import net.jangaron.Direction",
"import net.jangaron.Vector",
"import net.jangaron.Wall",
"import joo.css.Color",
"import joo.sound.Sound",
"import joo.util.HashSet",
"import joo.html.Event2",""],

"public class LightCycle extends JOObject",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(Direction);},

"private static const",{DEFAULT_MIN_SPEED:25},
"private static const",{DEFAULT_MAX_SPEED:80},
"private static const",{DEBUG:false},

"public function LightCycle",function(team,name,color,
vector,keyMap,
minSpeed,maxSpeed){
this[$super]();
this[$team]=team||name;
this[$name]=name;
this[$color]=this[$currentColor]=color;
this[$initialVector]=vector;
this[$vector]=new Vector(null,null,null);
this.keyMap=keyMap;
this.minSpeed=minSpeed?minSpeed:DEFAULT_MIN_SPEED;
this.maxSpeed=maxSpeed?maxSpeed:DEFAULT_MAX_SPEED;
},

"public function setGrid",function(grid){
this[$grid]=grid;
},

"public function setTeam",function(team){
this[$team]=team;
},

"public function getTeam",function(){
return this[$team];
},

"public function setName",function(name){
this[$name]=name;
},

"public function getName",function(){
return this[$name];
},

"public function isUser",function(){
return! !this.keyMap;
},

"public function setColor",function(color){
this[$color]=this[$currentColor]=color;
},

"public function getColor",function(){
return this[$currentColor];
},

"public function getOpacity",function(){
return this[$grid].startOpacity;
},

"public function getHeight",function(){
return this[$height];
},

"public function getVector",function(){
return this[$vector];
},

"function getKeyMap",function(){
return this.keyMap;
},

"public function init",function(){
if(this[$grid].soundVolume>0){
if(!this[$sound]){
this[$sound]={

derezz:new Sound(this.isUser()?"game/derezz.mp3":"game/derezz2.mp3",false),
turnLeft:new Sound("game/turn1.mp3",false),
turnRight:new Sound("game/turn2.mp3",false)
};


}
}
this[$dyingMillies]=null;
this[$currentColor]=this[$color];
this[$height]=1;
this[$opacity]=this[$grid].startOpacity;
this.speed=1;
this[$vector].setVector(this[$initialVector]);
this[$turnQueue]=[];
this[$prevCycleWall]=this[$cycleWall]=undefined;
this[$lastWall]=new Wall(this[$color],this[$vector].x,this[$vector].y,this);
this[$prevCycleWall]=this[$findCrashWall](this[$lastWall],new HashSet());
this[$cycleWall]=this[$createCycleWall](false);
this[$cycleHeadWall]=this[$createCycleWall](true);
this[$updateCycleHeadWall]();
},

"private function createCycleWall",function(isHeadWall){
var newCycleWall=new Wall(this[$color],this[$vector].x,this[$vector].y,isHeadWall?undefined:this);
newCycleWall.lightCycle=this;
this[$grid].addWall(newCycleWall);
return newCycleWall;
},

"private function updateCycleHeadWall",function(){
switch(this[$vector].dir){
case Direction.NORTH:
case Direction.SOUTH:
this[$cycleHeadWall].x1=this[$vector].x-0.5;
this[$cycleHeadWall].x2=this[$vector].x+0.5;
this[$cycleHeadWall].y1=this[$cycleHeadWall].y2=this[$vector].y;
break;
default:
this[$cycleHeadWall].y1=this[$vector].y-0.5;
this[$cycleHeadWall].y2=this[$vector].y+0.5;
this[$cycleHeadWall].x1=this[$cycleHeadWall].x2=this[$vector].x;
}
},

"public function getCycleWall",function(){
return this[$cycleWall];
},

"private function getLinePos",function(){
return Math.round(1/10*(this[$vector].dir.dx!=0?this[$vector].x:this[$vector].y));

},

"private static const",{ANGLE_TO_PAN:function(){return(100/(Math.PI/2));}},

"private function playSound",function(soundName){
if(!this[$sound])
return;
var primaryViewPort=this[$grid].getPrimaryViewPort();
var volume;
var pan;
if(primaryViewPort.getLightCycle()===this){
volume=1;
pan=0;
}else{
var microVector=primaryViewPort.getVector();
var thisVector=this.getVector();
var dx=thisVector.x-microVector.x;
var dy=thisVector.y-microVector.y;
var distance=Math.sqrt(dx*dx+dy*dy);
volume=1-distance/300;

var gradient=microVector.dir.dx==0
?microVector.dir.dy*dx/Math.abs(dy)
:-microVector.dir.dx*dy/Math.abs(dx);

var alpha=Math.atan(gradient);
pan=Math.round(alpha*ANGLE_TO_PAN);
if(DEBUG){
trace("dx "+dx+" dy "+dy+" dir.dx "+microVector.dir.dx+" dir.dy "+microVector.dir.dy+" distance "+distance+" gradient "+gradient+" sound "+soundName+": v "+volume+" p "+pan);
}
}
if(volume>0){
var theSound=this[$sound][soundName];
theSound.setVolume(this[$grid].soundVolume*volume);
theSound.setPan(pan);
theSound.start();
}
},

"private static const",{DIE_DELAY:1000},
"private static const",{FLASH_INTERVAL:500},
"private static const",{SHRINK_INTERVAL:1000},

"public function move",function(passedMillis){
if(!this.isDead()){
this[$updateSpeed](new Date().getTime());
if(this.speed<this.minSpeed){

this.speed=Math.min(this.minSpeed,this.speed+passedMillis*15/1000);
}

this[$vector].move(this.speed*passedMillis/1000);






}else if(this[$dyingMillies]<DIE_DELAY+SHRINK_INTERVAL){
this[$dyingMillies]+=passedMillis;
if(this[$dyingMillies]>=DIE_DELAY+SHRINK_INTERVAL){
this[$grid].removeLightCycle(this);
}else{
if(this[$dyingMillies]>DIE_DELAY){
if(this[$dyingMillies]<DIE_DELAY+FLASH_INTERVAL){

var saturation=this[$color].getSaturation();
var value=this[$color].getValue();
var brightness=1-Math.abs((this[$dyingMillies]-(DIE_DELAY+(FLASH_INTERVAL/2)))/(FLASH_INTERVAL/2));
var brightSaturation=saturation*(1-brightness);
var brightValue=value+(1-value)*brightness;
this[$currentColor]=Color.fromHSV(this[$color].getHue(),brightSaturation,brightValue);

}else{
this[$currentColor]=this[$color];
}

this[$height]=Math.max(1-(this[$dyingMillies]-DIE_DELAY)/SHRINK_INTERVAL,0.1);

}
}
}
},

"private function updateSpeed",function(now){
if(this[$fasterDown]){
if(this.speed<this.maxSpeed){
this.speed=Math.min(this.maxSpeed,this.speed+(now-this[$fasterDown])*0.005);
}
this[$fasterDown]=now;
}else if(this[$slowerDown]){
if(this.speed>this.minSpeed){
this.speed=Math.max(this.minSpeed,this.speed-(now-this[$slowerDown])*0.015);
}
this[$slowerDown]=now;
}
},

"public function update",function(){
if(!this.isDead()){
switch(this[$vector].dir){
case Direction.NORTH:
this[$lastWall].y1=this[$cycleWall].y2;
this[$cycleHeadWall].y1=this[$cycleHeadWall].y2=
this[$lastWall].y2=this[$cycleWall].y2=this[$vector].y;
break;
case Direction.EAST:
this[$lastWall].x1=this[$cycleWall].x2;
this[$cycleHeadWall].x1=this[$cycleHeadWall].x2=
this[$lastWall].x2=this[$cycleWall].x2=this[$vector].x;
break;
case Direction.SOUTH:
this[$lastWall].y2=this[$cycleWall].y1;
this[$cycleHeadWall].y1=this[$cycleHeadWall].y2=
this[$lastWall].y1=this[$cycleWall].y1=this[$vector].y;
break;
default:
this[$lastWall].x2=this[$cycleWall].x1;
this[$cycleHeadWall].x1=this[$cycleHeadWall].x2=
this[$lastWall].x1=this[$cycleWall].x1=this[$vector].x;
}
if(DEBUG){
this[$cycleWall].check();
this[$cycleHeadWall].check();
}
}
},

"private function moveWall",function(distance,turn){
var startVector=this[$vector];
var endVector=startVector.clone();
if(turn){
endVector[turn]();
}
endVector.move(distance);
return new Wall(this[$color],
[Math.min(startVector.x,endVector.x),Math.max(startVector.x,endVector.x)],
[Math.min(startVector.y,endVector.y),Math.max(startVector.y,endVector.y)]);
},

"protected function computeTurn",function(){
var theTurn;
var excludedWalls=new HashSet([this[$cycleHeadWall],this[$cycleWall],this[$prevCycleWall]]);
if(this[$findCrashWall](this[$moveWall](this.speed/3,undefined),excludedWalls)){
theTurn=Math.random()<0.5?"turnLeft":"turnRight";
if(this[$findCrashWall](this[$moveWall](this.speed/10,theTurn),excludedWalls)){
theTurn=theTurn=="turnLeft"?"turnRight":"turnLeft";
if(this[$findCrashWall](this[$moveWall](this.speed/10,theTurn),excludedWalls)){
theTurn=undefined;
}
}
}
return theTurn;
},

"private function mayTurn",function(){
return!this.isDead()&&
(this[$cycleWall].x2-this[$cycleWall].x1>=1||
this[$cycleWall].y2-this[$cycleWall].y1>=1);
},

"public function nextTurnTime",function(){
return this[$turnQueue].length>0&&this[$mayTurn]()?this[$turnQueue][0]["time"]:undefined;
},

"public function turn",function(eventTime){
if(!this[$mayTurn]()){

return;
}
var theTurn;
if(this.keyMap){
if(eventTime&&this.nextTurnTime()<=eventTime){
theTurn=this[$turnQueue].shift()["dir"];
}
}else{
theTurn=this.computeTurn();
}
if(theTurn){
this[$playSound](theTurn);
switch(this[$vector].dir){
case Direction.NORTH:
this[$vector].y=Math.ceil(this[$vector].y);
break;
case Direction.EAST:
this[$vector].x=Math.ceil(this[$vector].x);
break;
case Direction.SOUTH:
this[$vector].y=Math.floor(this[$vector].y);
break;
default:
this[$vector].x=Math.floor(this[$vector].x);
}
this.update();
this[$vector].dir=this[$vector].dir[theTurn];
this[$lastWall].x1=this[$lastWall].x2=this[$vector].x;
this[$lastWall].y1=this[$lastWall].y2=this[$vector].y;
if(DEBUG)
this[$lastWall].check();
this[$prevCycleWall]=this[$cycleWall];
this[$cycleWall]=this[$createCycleWall](false);
this[$vector].move(0.1);
this.update();
this[$updateCycleHeadWall]();
}
},

"public function checkCrashed",function(){
if(this.isDead())
return;
var excludedWalls=new HashSet([this[$cycleHeadWall],this[$cycleWall],this[$prevCycleWall]]);
var crashWall=this[$findCrashWall](this[$lastWall],excludedWalls);
if(crashWall){


switch(this[$vector].dir){
case Direction.NORTH:
this[$vector].y=Math.max(this[$lastWall].y1,crashWall.y1);
break;
case Direction.EAST:
this[$vector].x=Math.max(this[$lastWall].x1,crashWall.x1);
break;
case Direction.SOUTH:
this[$vector].y=Math.min(this[$lastWall].y2,crashWall.y2);
break;
default:
this[$vector].x=Math.min(this[$lastWall].x2,crashWall.x2);
}
++this.deaths;
this.update();
this[$grid].removeWall(this[$cycleHeadWall]);
this[$dyingMillies]=0;

this[$playSound]("derezz");
this[$grid].crashed(this);
}
},

"private function findCrashWall",function(lastWall,excludedWalls){

var walls=this[$grid].walls;
for(var i=0;i<walls.length;++i){
var wall=walls[i];
if((!wall.opacityHolder||wall.opacityHolder.getOpacity()>.5)&&!excludedWalls.contains(wall)&&lastWall.intersects(wall)){
return walls[i];
}
}
return undefined;
},

"public function isDead",function(){
return this[$dyingMillies]!==null;
},

"public function onkeydown",function(event){
var keys=this.keyMap;
if(keys){
switch(event.getKeyCode()){
case keys.left:this[$turnQueue].push({"time":event.getTime(),"dir":"turnLeft"});break;
case keys.right:this[$turnQueue].push({"time":event.getTime(),"dir":"turnRight"});break;
case keys.faster:
if(!this[$fasterDown]){
this[$fasterDown]=event.getTime();
}
break;
case keys.slower:
if(!this[$slowerDown]){
this[$slowerDown]=event.getTime();
}
break;
default:return true;
}
return false;
}
return true;
},

"public function onkeyup",function(event){
var keys=this.keyMap;
if(keys){
switch(event.getKeyCode()){
case keys.faster:
this[$updateSpeed](event.getTime());
this[$fasterDown]=undefined;
break;
case keys.slower:
this[$updateSpeed](event.getTime());
this[$slowerDown]=undefined;
break;
default:return true;
}
return false;
}
return true;
},

"private var",{grid: undefined},
"private var",{team: undefined},
"private var",{name: undefined},
"private var",{color: undefined},
"private var",{currentColor: undefined},
"private var",{opacity: undefined},
"private var",{height: undefined},
"private var",{dyingMillies: undefined},
"public var",{minSpeed: undefined},
"public var",{maxSpeed: undefined},
"private var",{initialVector: undefined},
"private var",{vector: undefined},
"private var",{turnQueue: undefined},
"public var",{keyMap: undefined},




"private var",{lastWall: undefined},



"private var",{cycleWall: undefined},



"private var",{prevCycleWall: undefined},



"private var",{cycleHeadWall: undefined},
"private var",{sound: undefined},
"private var",{fasterDown: undefined},
"private var",{slowerDown: undefined},
"public var",{speed: undefined},
"public var",{deaths:0},
"public var",{wins:0},
];},[]
);joo.classLoader.prepare("package net.jangaron",[

"import joo.css.Color",""],

"public class SlantLine",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(Color);},

"public function SlantLine",function(viewPort,gx){this[$super]();
this.viewPort=viewPort;
this.gx=gx;
},

"private function clippedPoint",function(x){
var vp=this.viewPort;
x=Math.abs(x);
if(x>vp.SIDE){




return{x:vp.SIDE,y:Math.round(vp.HEIGHT-(vp.HEIGHT-vp.HORIZON)*(1-vp.SIDE/x))};
}else{
return{x:x,y:vp.HEIGHT};
}
},

"public function update",function(index){
var vp=this.viewPort;
var HALF_LINE_WIDTH=vp.HALF_SLANT_LINE_WIDTH;
var gxRel=(this.gx+index/vp.GRID_LINE_DISTANCE)*vp.SIDE;
if(Math.abs(gxRel)<=HALF_LINE_WIDTH){
vp.slantLineLayer.addSlant(Color.WHITE,
vp.SIDE,vp.HORIZON,vp.SIDE+gxRel-HALF_LINE_WIDTH,vp.HEIGHT,
vp.SIDE,vp.HORIZON,vp.SIDE+gxRel+HALF_LINE_WIDTH,vp.HEIGHT);
}else{
var left=this[$clippedPoint](gxRel-HALF_LINE_WIDTH);
var right=this[$clippedPoint](gxRel+HALF_LINE_WIDTH);

var off;
if(gxRel<0){
vp.slantLineLayer.addSlant(Color.WHITE,
0,vp.HORIZON,0,right.y,
vp.SIDE,vp.HORIZON,vp.SIDE-right.x,right.y);
off=left.y<vp.HEIGHT?1:0;
vp.slantLineLayer.addSlant(Color.BLACK,
0,vp.HORIZON-off,0,left.y-off,
vp.SIDE,vp.HORIZON-off,vp.SIDE-left.x,left.y-off);
}else{
vp.slantLineLayer.addSlant(Color.WHITE,
vp.SIDE,vp.HORIZON,vp.SIDE+left.x,left.y,
vp.WIDTH,vp.HORIZON,vp.WIDTH,left.y);
off=right.y<vp.HEIGHT?1:0;
vp.slantLineLayer.addSlant(Color.BLACK,
vp.SIDE,vp.HORIZON-off,vp.SIDE+right.x,right.y-off,
vp.WIDTH,vp.HORIZON-off,vp.WIDTH,right.y-off);
}
}
},

"public var",{viewPort: undefined},
"public var",{gx: undefined},
];},[]
);joo.classLoader.prepare("package net.jangaron",[

"import joo.lang.JOObject",
"import joo.css.Color",""],

"public class TeamColor extends JOObject",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[

"public static const",{TEAM_GOLD:"Gold"},
"public static const",{TEAM_BLUE:"Blue"},
"public static const",{TEAM_GREEN:"Green"},
"public static const",{TEAM_EARTH:"Earth"},
"public static const",{TEAM_WATER:"Water"},
"public static const",{TEAM_PINK:"Pink"},

"public static const",{COLOR_ORANGE:"Orange"},
"public static const",{COLOR_RED:"Red"},
"public static const",{COLOR_YELLOW:"Yellow"},
"public static const",{COLOR_VIOLET:"Violet"},
"public static const",{COLOR_BLUE:"Blue"},
"public static const",{COLOR_CYAN:"Cyan"},
"public static const",{COLOR_GREEN:"Green"},
"public static const",{COLOR_SILICON:"Silicon"},
"public static const",{COLOR_BROWN:"Brown"},
"public static const",{COLOR_AQUA:"Aqua"},
"public static const",{COLOR_PINK:"Pink"},

"public static const",{UNDEFINED:function(){return(new TeamColor("",null));}},
"public static const",{GOLD_ORANGE:function(){return(new TeamColor(TEAM_GOLD,COLOR_ORANGE));}},
"public static const",{GOLD_RED:function(){return(new TeamColor(TEAM_GOLD,COLOR_RED));}},
"public static const",{GOLD_YELLOW:function(){return(new TeamColor(TEAM_GOLD,COLOR_YELLOW));}},
"public static const",{BLUE_VIOLET:function(){return(new TeamColor(TEAM_BLUE,COLOR_VIOLET));}},
"public static const",{BLUE_BLUE:function(){return(new TeamColor(TEAM_BLUE,COLOR_BLUE));}},
"public static const",{GREEN_CYAN:function(){return(new TeamColor(TEAM_GREEN,COLOR_CYAN));}},
"public static const",{GREEN_GREEN:function(){return(new TeamColor(TEAM_GREEN,COLOR_GREEN));}},
"public static const",{EARTH_SILICON:function(){return(new TeamColor(TEAM_EARTH,COLOR_SILICON));}},
"public static const",{EARTH_BROWN:function(){return(new TeamColor(TEAM_EARTH,COLOR_BROWN));}},
"public static const",{WATER_AQUA:function(){return(new TeamColor(TEAM_WATER,COLOR_AQUA));}},
"public static const",{PINK_PINK:function(){return(new TeamColor(TEAM_PINK,COLOR_PINK));}},

"public static const",{TEAMS_AND_COLORS:function(){return([
GOLD_ORANGE,
GOLD_RED,
GOLD_YELLOW,
BLUE_VIOLET,
BLUE_BLUE,
GREEN_CYAN,
GREEN_GREEN,
EARTH_SILICON,
EARTH_BROWN,
WATER_AQUA,
PINK_PINK
]);}},function()

{
for(var i=0;i<TEAMS_AND_COLORS.length;++i){
var teamColor=TEAMS_AND_COLORS[i];
teamColor.index=i;
}
},

"public function TeamColor",function(team,colorName){
this[$super]();
this[$team]=team;
this[$colorName]=colorName;
},

"public function getTeam",function(){
return this[$team];
},

"public function getColorName",function(){
return this[$colorName];
},

"private static const",{COLOR_BY_NAME:function(){return({
"Orange":new Color(228,108,10),
"Red":new Color(228,75,10),
"Yellow":new Color(245,169,10),
"Violet":new Color(125,0,150),
"Blue":new Color(64,0,192),
"Cyan":new Color(23,211,145),
"Green":new Color(10,228,108),
"Silicon":new Color(186,177,149),
"Brown":new Color(166,149,103),
"Aqua":new Color(115,209,193),
"Pink":new Color(227,166,193)
});}},

"public function getColor",function(){
return COLOR_BY_NAME[this[$colorName]];
},

"override public function hashCode",function(){
return this.toString();
},

"override public function equals",function(teamColor){
return this.index==teamColor["index"];
},

"override public function toString",function(){
return[this[$team]," (",this[$colorName],")"].join("");
},

"private var",{team: undefined},
"private var",{colorName: undefined},
"public var",{index: undefined},
];},[]
);joo.classLoader.prepare("package net.jangaron",[""],

"public class Direction",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[
"public static const",{DIRS:function(){return([]);}},
"public static const",{NORTH:function(){return(new Direction("N",0,1,String.fromCharCode(parseInt("25B2",16))));}},
"public static const",{EAST:function(){return(new Direction("E",1,0,String.fromCharCode(parseInt("25C4",16))));}},
"public static const",{SOUTH:function(){return(new Direction("S",0,-1,String.fromCharCode(parseInt("25BC",16))));}},
"public static const",{WEST:function(){return(new Direction("W",-1,0,String.fromCharCode(parseInt("25BA",16))));}},
"public static var",{DIRS_COUNT:0},

"private static function getDir",function(index){
return DIRS[index%DIRS_COUNT];
},function()

{
for(var d=0;d<DIRS_COUNT;++d){
var dir=DIRS[d];
dir.opposite=getDir(d+DIRS_COUNT/2);
dir.turnRight=getDir(d+1);
dir.turnLeft=getDir(d+DIRS_COUNT-1);
}
},

"public function Direction",function(name,dx,dy,compassArrow){this[$super]();
DIRS.push(this);++DIRS_COUNT;
this[$name]=name;
this.dx=dx;
this.dy=dy;
this[$compassArrow]=compassArrow;
},

"public function getCompassArrow",function(){
return this[$compassArrow];
},

"public function toString",function(){
return this[$name];
},

"private var",{name: undefined},
"private var",{compassArrow: undefined},
"public var",{dx: undefined},
"public var",{dy: undefined},
"public var",{opposite: undefined},
"public var",{turnLeft: undefined},
"public var",{turnRight: undefined},
];},[]
);joo.classLoader.prepare("package net.jangaron",[

"import joo.lang.JOObject",
"import net.jangaron.Direction",
"import net.jangaron.Trapez",
"import joo.util.HashSet",""],




















"public class RelativeWall extends JOObject",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(Direction);},

"private static const",{DEBUG:false},

"public function RelativeWall",function(wall){
this[$super]();
this.wall=wall;
this.wallProjection=new Trapez();
},

"public function update",function(vector){
this[$maybeHides]=[];
this.hiddenByCnt=0;
this.zIndex=10000;
var thisWall=this.wall;
var rx1=thisWall.x1-vector.x;
var ry1=thisWall.y1-vector.y;
var rx2=thisWall.x2-vector.x;
var ry2=thisWall.y2-vector.y;
switch(vector.dir){
case Direction.NORTH:
return this.setValues(rx1,ry1,rx2,ry2);
case Direction.SOUTH:
return this.setValues(-rx2,-ry2,-rx1,-ry1);
case Direction.EAST:
if(ry1===ry2)
return this.setValues(-ry1,rx1,-ry2,rx2);
return this.setValues(-ry2,rx2,-ry1,rx1);
case Direction.WEST:
if(rx1===rx2)
return this.setValues(ry1,-rx1,ry2,-rx2);
return this.setValues(ry2,-rx2,ry1,-rx1);
}
throw"Unknown direction "+vector.dir;
},

"public function setValues",function(x1,y1,x2,y2){
this.x1=x1;
this.y1=y1;
this.x2=x2;
this.y2=y2;


if(this.x1==0&&this.x2==0){
this[$mayHideWall]=this[$mayHideWallSpecial];
}else{
delete this[$mayHideWall];
this.mayHidePoint=


this.x1<0&&this.x2>0?this[$mayHidePointMiddle]


:this.x2<=0?this[$mayHidePointLeft]

:this.x1>=0?this[$mayHidePointRight]
:null;

}
return this;
},

"private function mayHideWall",function(other){
return this.mayHidePoint(other.x1,other.y1)||this.mayHidePoint(other.x2,other.y2);
},

"private bound function mayHideWallSpecial",function(other){
return other.x1<=0&&other.x2>=0&&other.y1>=this.y2;
},"bound\n"+







"function mayHidePoint",function(x,y){

},


"private bound function mayHidePointMiddle",function(x,y){
return y>this.y1;
},

"private bound function mayHidePointLeft",function(x,y){

return x<this.x2&&(y>this.y1);
},

"private bound function mayHidePointRight",function(x,y){

return x>this.x1&&(y>this.y1);
},





"public function updateMaybeHides",function(other,unhiddenElements){
if(this[$mayHideWall](other)){
this[$maybeHides].push(other);
if(other.hiddenByCnt++ ==0){
unhiddenElements.remove(other);
}
return true;
}
return false;
},

"public function removedFromUnhidden",function(unhiddenElements){
this[$maybeHides].forEach(function(other){
if(--other.hiddenByCnt==0){
unhiddenElements.add(other);
}
});
},

"public function toString1",function(){
return"["+[this.wall.getColor(),this.wall.getOpacity(),this.x1,this.y1,this.x2,this.y2].join(",")+"]";
},

"public var",{wall: undefined},
"public var",{wallProjection: undefined},
"public var",{x1: undefined},
"public var",{y1: undefined},
"public var",{x2: undefined},
"public var",{y2: undefined},
"private var",{maybeHides:function(){return([]);}},
"public var",{hiddenByCnt:0},
"public var",{zIndex:10000},
];},[]
);joo.classLoader.prepare("package net.jangaron",[

"import joo.css.Color",
"import joo.lang.JOObject",""],

"public class Wall extends JOObject",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[

"private static const",{DEBUG:false},

"public function Wall",function(color,p1,p2,opacityHolder){
this[$super]();
this.relativeWalls={};
this[$color]=color;
if(typeof p1=="number"){
this.x1=this.x2=p1;
}else{
this.x1=p1[0];
this.x2=p1[1];
}
if(typeof p2=="number"){
this.y1=this.y2=p2;
}else{
this.y1=p2[0];
this.y2=p2[1];
}
this.opacityHolder=opacityHolder;
if(DEBUG){
this.check();
}
},

"public function getOpacity",function(){
return this.opacityHolder?this.opacityHolder.getOpacity():1;
},

"public function getColor",function(){
return this.opacityHolder?this.opacityHolder.getColor():this[$color];
},

"public function getHeight",function(){
return this.opacityHolder?this.opacityHolder.getHeight():1;
},

"public function check",function(){

},

"public function intersects",function(wall){
return Math.max(this.x1,wall.x1)<=Math.min(this.x2,wall.x2)
&&Math.max(this.y1,wall.y1)<=Math.min(this.y2,wall.y2);
},

"override public function toString",function(){
return["[",this.x1,",",this.y1,"|",this.x2,",",this.y2,"]"].join("");
},

"private var",{color: undefined},
"public var",{opacityHolder: undefined},
"public var",{x1: undefined},
"public var",{y1: undefined},
"public var",{x2: undefined},
"public var",{y2: undefined},
"public var",{relativeWalls: undefined},
"public var",{lightCycle: undefined},
];},[]
);joo.classLoader.prepare("package net.jangaron",[

"import net.jangaron.Direction",""],

"public class Vector",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(Direction);},

"public function Vector",function(x,y,dir){this[$super]();
this.x=x;
this.y=y;
this.dir=dir;
},

"public function clone",function(){
return new Vector(this.x,this.y,this.dir);
},

"public function setVector",function(vector){
this.x=vector.x;
this.y=vector.y;
this.dir=vector.dir;
},

"public function getVector",function(distance){
var thisDir=this.dir;
return new Vector(this.x+thisDir.dx*distance,this.y+thisDir.dy*distance,thisDir);
},

"public function getOffset",function(steps){
return this[$offset](this.dir,steps);
},

"public function getLeftOffset",function(steps){
return this[$offset](this.dir.turnRight,steps);
},

"private function offset",function(dir,steps){
switch(dir){
case Direction.NORTH:return this.y%steps;
case Direction.EAST:return this.x%steps;
case Direction.SOUTH:return(steps-this.y%steps)%steps;
default:return(steps-this.x%steps)%steps;
}
},

"public function move",function(distance,theDir){
if(!theDir)
theDir=this.dir;
if(theDir.dx)
this.x+=theDir.dx*distance;
else
this.y+=theDir.dy*distance;
},

"public function turnLeft",function(){
this.dir=this.dir.turnLeft;
},

"public function turnRight",function(){
this.dir=this.dir.turnRight;
},

"public function toString",function(){
return[this.x,"px ",this.y,"px"].join("");
},

"public var",{x: undefined},
"public var",{y: undefined},
"public var",{dir: undefined},
];},[]
);joo.classLoader.prepare("package net.jangaron",[

"import joo.util.PropertyAware",""],

"public class KeyMap extends PropertyAware",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[

"public function KeyMap",function(props){
this[$super](props);
},

"public var",{left: undefined},
"public var",{right: undefined},
"public var",{lookLeft: undefined},
"public var",{lookRight: undefined},
"public var",{lookBackwards: undefined},
"public var",{changeView: undefined},
"public var",{faster: undefined},
"public var",{slower: undefined},

];},[]
);joo.classLoader.prepare("package net.jangaron",[

"import joo.lang.Comparable",
"import joo.util.Arrays",
"import joo.util.Interval",""],

"public class ZBuffer",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[

"public function ZBuffer",function(){this[$super]();
this[$intervals]=[];
},

"public function isIntervalVisible",function(a,b){
var thisIntervals=this[$intervals];
var aIndex=Arrays.binarySearch(thisIntervals,a);

return aIndex<0||b>(thisIntervals[aIndex]).b;
},

"public function addInterval",function(a,b){
var thisIntervals=this[$intervals];
var aIndex=Arrays.binarySearch(thisIntervals,a);
if(aIndex>=0){
var aInterval=thisIntervals[aIndex];

if(b<=aInterval.b){
return false;
}
a=aInterval.a;
}else{
aIndex=-aIndex-1;
}
var bIndex=Arrays.binarySearch(thisIntervals,b);
if(bIndex>=0){
b=(thisIntervals[bIndex]).b;
}else{
bIndex=-bIndex-2;
}
var newInterval=new Interval(a,b);

thisIntervals.splice(aIndex,bIndex-aIndex+1,newInterval);
return true;
},

"public function toString",function(){
return this[$intervals].join(" ");
},

"private var",{intervals:function(){return([]);}},
];},[]
);joo.classLoader.prepare("package net.jangaron",[

"import joo.html.Browser",
"import joo.html.Document2",
"import joo.html.Dimensions",
"import joo.html.Element2",
"import joo.html.Event2",
"import joo.html.EventType",
"import joo.html.slant.SlantCanvas",
"import joo.html.TextNode2",
"import joo.css.Color",
"import joo.css.Length",
"import joo.css.Position",
"import joo.css.Style2",
"import joo.util.Arrays",
"import joo.util.NumberUtil",
"import joo.util.HashSet",
"import net.jangaron.Vector",
"import net.jangaron.Line",
"import net.jangaron.SlantLine",
"import net.jangaron.RelativeWall",
"import net.jangaron.ZBuffer",""],

"public class ViewPort extends Element2",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(Browser,Position,EventType,Color);},

"private static const",{COLOR_BY_DIR:function(){return({N:"brighter",S:"darker"});}},
"private static const",{NUMBER_OF_GRID_LINES:20},
"private static const",{DEBUG:false},

"private static const",{TURN_DELAY_MS:200},






"public static function create",function(document,style){
if(!document){
var gameWindow=window.open();
document=new Document2(gameWindow.document);
document.write("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>"
+"<html xmlns='http://www.w3.org/1999/xhtml'>"

+"<head><title>Jangaron</title><style>"
+"html { height: 100%; overflow: hidden; }"
+"body { overflow: hidden; padding: 0; margin: 0; border: 0; width: 100%; height: 100%; background-color: black; }"
+".canvas { display: block; overflow: hidden; margin: 0; padding: 0; left: 0; background-color: black; position: absolute; width: 100%; height: 100%; }"
+".slant { position: absolute; padding: 0; margin: 0; line-height: 0; width: 0; height: 0; border-style: solid; border-color: transparent; border-width: 0; }"
+"</style>"
+"<script>"
+"window.opener.joo$prepareWindow(window);"
+"</script>"
+"</head>"
+"<body></body>"
+"</html>");
document.close();
}
var div=document.createElement("div").setStyle(style);
document.getBody().appendChild(div);
return new ViewPort(document,div.getPeer());
},

"public function ViewPort",function(document,viewPort){
this[$super](document,viewPort);
this.setClassName("viewport");
this.GRID_LINE_DISTANCE=10;
this.GRID_LINE_WIDTH=1;
this.VIEW_DEPTH=1e10;
this[$initDimensions]();
this.slantLineLayer=this[$createLayer]();
this.lineLayer=this[$createLayer]();
this[$wallLayer]=this[$createLayer]();
this[$hudLayer]=this[$createHUD]();
this[$createGridLines]();
document.getWindow().addEventListener(EventType.RESIZE,function(){
this[$sizeDirty]=true;
return true;
}.bind(this),false);
},

"private function createLayer",function(){
var div=this.ownerDocument.createElement("div").setStyle({zIndex:String(++this[$layerCount])});
this.appendChild(div);
return new SlantCanvas(this.ownerDocument,div.getPeer());
},

"private function initDimensions",function(){
this[$sizeDirty]=false;
var dim=this.getDimensions();
this.WIDTH=dim.width;
this.HEIGHT=Math.min(dim.height,Math.round(this.WIDTH*3/4));
this.HORIZON=Math.round(this.HEIGHT*this[$horizon]);
this.SIDE=Math.round(this.WIDTH/2);
this.X_FACTOR=this.SIDE/(this.HEIGHT-this.HORIZON)/this.GRID_LINE_DISTANCE;
this.Y_FACTOR=(this.HEIGHT-this.HORIZON)*this.GRID_LINE_DISTANCE;
this.HALF_SLANT_LINE_WIDTH=this.GRID_LINE_WIDTH/2*this.SIDE/this.GRID_LINE_DISTANCE;
this[$leftOffset]=undefined;
this[$offset]=undefined;
},

"public function setLightCycle",function(lightCycle){
this[$lightCycle]=lightCycle;
this[$initHUD](lightCycle);
},

"public function getLightCycle",function(){
return this[$lightCycle];
},

"public function setGrid",function(grid){
this.grid=grid;
},

"public function getVector",function(){
return this[$vector];
},

"public function updateVector",function(passedMillis){
if(passedMillis&&this[$horizon]!=this[$targetHorizon]){
var delta=NumberUtil.sgn(this[$targetHorizon]-this[$horizon]);
this[$horizon]=this[$horizon]+delta*passedMillis/10000;
if(delta<0&&this[$horizon]<this[$targetHorizon]||delta>0&&this[$horizon]>this[$targetHorizon])
this[$horizon]=this[$targetHorizon];
this[$sizeDirty]=true;
}

var lcVector=this[$lightCycle].getVector();
if(lcVector.dir==this[$lastDir]){
this[$lastTurnTime]=undefined;
}else{
if(!this[$lastDir]||this[$targetHorizon]==.5){
this[$lastDir]=lcVector.dir;
}else{
var now=new Date().getTime();
if(!this[$lastTurnTime]){
this[$lastTurnTime]=now;
}else if(now-this[$lastTurnTime]>TURN_DELAY_MS){
this[$lastDir]=lcVector.dir;
}
}
}
this[$vector].x=lcVector.x;
this[$vector].y=lcVector.y;
if(this[$viewTurn]){

this[$vector].move(-2*this[$targetHorizon]+1.1,this[$lastDir]);
this[$vector].dir=this[$lastDir][this[$viewTurn]];

this[$vector].move(4*this[$targetHorizon]-1.5);
}else{
this[$vector].dir=this[$lastDir];
this[$vector].move(.1);
if(this[$horizon]<.5){

this[$vector].move(-20*(.5-this[$horizon]));

this[$vector].move(.5-this[$horizon],this[$vector].dir.turnRight);
}
}
if(this[$vector].x<=0)
this[$vector].x=0.1;
else if(this[$vector].x>=this.grid.width)
this[$vector].x=this.grid.width-0.1;
if(this[$vector].y<=0)
this[$vector].y=0.1;
else if(this[$vector].y>=this.grid.height)
this[$vector].y=this.grid.height-0.1;
},

"public function getY",function(yIndex){
return this.Y_FACTOR/(this.GRID_LINE_DISTANCE+yIndex);
},

"public function project",function(rw){
var y1=this.getY(Math.max(rw.y1,0));
var y2;
var x1;
var x2;
var xFactor=this.X_FACTOR;
var dir=this.getVector().dir;
var isXWall=rw.y1==rw.y2;
if(isXWall||rw.x1==0&&rw.x2==0){
y2=y1;
if(isXWall){
xFactor*=y1;
x1=rw.x1*xFactor;
x2=rw.x2*xFactor;
if(x1>this.SIDE||x2<-this.SIDE){
return false;
}

x1=Math.max(x1,-this.SIDE-1);
x2=Math.min(x2,this.SIDE+1);
}else{
x1=0;
x2=1;
}
}else{
dir=rw.x1>0?dir.turnRight:dir.turnLeft;
y2=this.getY(rw.y2);
xFactor*=rw.x1;
x2=xFactor*y2;
if(Math.abs(x2)>this.SIDE){
return false;
}
x1=xFactor*y1;
var x1abs=Math.abs(x1);
if(x1abs>this.SIDE||rw.y1<=0&&rw.y2>0&&x1abs<this.SIDE){

var side=rw.x1<0?-this.SIDE-1:this.SIDE+1;
y1=side*y1/x1;
x1=side;
}
}
var color=rw.wall.getColor();
var colorChange=COLOR_BY_DIR[dir];
if(colorChange){
color=color[colorChange]();
}
rw.wallProjection.setValues(color,x1,y1,x2,y2);
return true;
},

"private function insertRelativeWall",function(relativeWalls,newRelativeWall,
unhiddenRelativeWalls){


var isUnhidden=true;
for(var ws=0;ws<relativeWalls.length;++ws){
var relativeWall=relativeWalls[ws];
if(newRelativeWall.wallProjection.intersects(relativeWall.wallProjection)){
if(!newRelativeWall.updateMaybeHides(relativeWall,unhiddenRelativeWalls)){
if(relativeWall.updateMaybeHides(newRelativeWall,unhiddenRelativeWalls)){
isUnhidden=false;
}
}
}
}
relativeWalls.push(newRelativeWall);
if(isUnhidden){
unhiddenRelativeWalls.add(newRelativeWall);
}
},

"public function update",function(passedMillis){
this.updateVector(passedMillis);
if(this[$sizeDirty]){
this[$initDimensions]();
}
this[$updateHUD]();
var viewVector=this.getVector();
this[$updateSlantLines](viewVector);
this[$updateLines](viewVector);
var relativeWalls=[];
var unhiddenRelativeWalls=new HashSet();
var walls=this.grid.walls;
var relativeWall;
var viewPortKey="_"+this.hashCode();
for(var w=0;w<walls.length;++w){
var wall=walls[w];
var relativeWallsByViewPort=wall.relativeWalls;
relativeWall=relativeWallsByViewPort[viewPortKey];
if(!relativeWall){
relativeWallsByViewPort[viewPortKey]=relativeWall=new RelativeWall(walls[w]);
}
relativeWall.update(viewVector);
if((relativeWall.y1>=0||relativeWall.y2>=0)&&(relativeWall.y1<this.VIEW_DEPTH||relativeWall.y2<this.VIEW_DEPTH)){

if(this.project(relativeWall)){
this[$insertRelativeWall](relativeWalls,relativeWall,unhiddenRelativeWalls);
}
}
}
var zIndex=10000;
var zBuffer=new ZBuffer();
var slant;
var WHITE=new Color(245,245,245);
this[$wallLayer].rewind();
var viewHeightFactor=4*this[$horizon];
while(relativeWall=unhiddenRelativeWalls.pop()){
relativeWall.removedFromUnhidden(unhiddenRelativeWalls);
if(DEBUG&&!Arrays.remove(relativeWalls,relativeWall)){
throw"Element not present: "+relativeWall+" in ["+relativeWalls.join(",")+"]";
}
var wallProjection=relativeWall.wallProjection;
var x1=this.SIDE+wallProjection.x1;
var x2=this.SIDE+wallProjection.x2;

var opacity=relativeWall.wall.getOpacity();
var isHighRim=this.grid.highRim&&relativeWall.wall.getColor()===Color.GRAY;

var heightFactor=relativeWall.wall.getHeight();
var isVisible=isHighRim
||(viewHeightFactor<=0&&opacity==1&&heightFactor==1?zBuffer.addInterval(x1,x2):zBuffer.isIntervalVisible(x1,x2));
if(isVisible){
var y1=wallProjection.y1;
var y2=wallProjection.y2;
var opaque=opacity==1?1:0;
var hf=1-viewHeightFactor*heightFactor;
var y1top=isHighRim?-opaque:this.HORIZON+hf*y1;
if(y1==y2){
slant=this[$wallLayer].addRect(wallProjection.color,
x1,y1top,x2,this.HORIZON+y1,
zIndex--,opacity,WHITE,-opaque);
}else{
var y2top=isHighRim?-opaque:this.HORIZON+hf*y2;
var x1border=x1+opaque;
var x2border=x2-opaque;






















if(x1border<=x2border){
slant=this[$wallLayer].addSlant(wallProjection.color,
x1border,y1top+opaque,x1border,this.HORIZON+y1-opaque,
x2border,y2top+opaque,x2border,this.HORIZON+y2-opaque,
zIndex--,opacity);
}
if(opaque){
slant=this[$wallLayer].addSlant(WHITE,
x1,y1top,x1,this.HORIZON+y1,
x2,y2top,x2,this.HORIZON+y2,
zIndex--,opacity);
}
}
if(DEBUG){
slant["id"]="rw"+relativeWall.hashCode();slant["rw"]=relativeWall;
}
}else if(DEBUG){
trace("hidden wall: "+relativeWall.toString1());
}
}
if(DEBUG&&relativeWalls.length!=0){
throw"Some walls not rendered: ["+relativeWalls.join(",")+"]";
}
this[$wallLayer].clearRest();
if(Browser.ENGINE===Browser.ENGINE_OPERA){
this[$operaClassToggle]=!this[$operaClassToggle];
this.setClassName("viewport"+(this[$operaClassToggle]?" foo":""));
}
},

"private function createGridLines",function(){
this[$slantLines]=[];
for(var i=0;i<NUMBER_OF_GRID_LINES/2;++i){
this[$slantLines].push(new SlantLine(this,-i));
this[$slantLines].push(new SlantLine(this,i+1));
}
this[$lines]=[];
for(i=1;i<=NUMBER_OF_GRID_LINES;++i){
this[$lines].push(new Line(this,i*this.GRID_LINE_DISTANCE));
}
},

"private function updateSlantLines",function(vector){
var newLeftOffset=vector.getLeftOffset(this.GRID_LINE_DISTANCE);
if(newLeftOffset!=this[$leftOffset]){
this[$leftOffset]=newLeftOffset;
this.slantLineLayer.rewind();
Arrays.broadcast(this[$slantLines],"update",this.GRID_LINE_DISTANCE-newLeftOffset);
}
},

"private function updateLines",function(vector){
var newOffset=vector.getOffset(this.GRID_LINE_DISTANCE);
if(newOffset!=this[$offset]){
this[$offset]=newOffset;
Arrays.broadcast(this[$lines],"update",newOffset);
var furthestLine=(this.lineLayer.getLastChild()).getStyle();
furthestLine.setHeight(Length.px(furthestLine.getTop().floatValue+furthestLine.getHeight().floatValue-this.HORIZON));
furthestLine.setTop(Length.px(this.HORIZON));

}
},

"private function createHUD",function(){
var newHudLayer=this[$createLayer]();
var document=this.ownerDocument;

var hud=document.createElement("div").setClassName("hud");
hud.getStyle()
.setColor(Color.WHITE)
.setZIndex(20000)
.setOpacity(.75);
hud.appendChild(document.createTextNode(""));
newHudLayer.appendChild(hud);

var speedContainer=document.createElement("div").setClassName("speed");
speedContainer.getStyle()
.setZIndex(20000)
.setOpacity(.75);
var speedIndicator=document.createElement("div");
speedIndicator.appendChild(document.createTextNode(String.fromCharCode(160)));
speedContainer.appendChild(speedIndicator);
var speed=document.createElement("div");
speed.getStyle()
.setColor(Color.WHITE)
.setPosition(Position.ABSOLUTE);
speed.appendChild(document.createTextNode("0"));
speedContainer.appendChild(speed);
newHudLayer.appendChild(speedContainer);
this[$renderedSpeed]=0;





return newHudLayer;
},



















"private function initHUD",function(lightCycle){
var hud=this[$hudLayer].getChildElement(0);
var speedContainer=hud.getNextSibling();
var lightCycleColor=lightCycle.getColor();
speedContainer.getStyle().setBackgroundColor(lightCycleColor);
hud.getStyle().setBackgroundColor(lightCycleColor);
var speedometer=speedContainer.getFirstChild();
speedometer.getStyle().setBackgroundColor(lightCycleColor.darker());
},

"private function updateHUD",function(){
var lcVector=this[$lightCycle].getVector();
var hudText=this[$hudLayer].getChildElement(0).getFirstChild();
hudText.setData([this[$lightCycle].getName(),
"| x",NumberUtil.format(Math.round(lcVector.x),3),
"y",NumberUtil.format(Math.round(lcVector.y),3),
lcVector.dir.getCompassArrow()].join(" "));

var newRenderedSpeed=Math.round(this[$lightCycle].speed);
if(newRenderedSpeed!=this[$renderedSpeed]){
var speedContainer=this[$hudLayer].getChildElement(1);
var speedIndicator=speedContainer.getFirstChild();
var maxSpeed=this[$lightCycle].maxSpeed;
var widthPercent=Math.round(100*newRenderedSpeed/maxSpeed);
speedIndicator.getStyle().setWidth(Length.percent(widthPercent));
var speedText=speedContainer.getLastChild().getFirstChild();
speedText.setData(String(newRenderedSpeed));
this[$renderedSpeed]=newRenderedSpeed;
}
},

"private function getKeyMap",function(){
return this[$lightCycle].getKeyMap();
},

"public function onkeydown",function(event){
var keys=this[$getKeyMap]();
if(keys){
switch(event.getKeyCode()){
case keys.lookLeft:this[$viewTurn]="turnLeft";break;
case keys.lookRight:this[$viewTurn]="turnRight";break;
case keys.lookBackwards:this[$viewTurn]="opposite";break;
default:return true;
}
return false;
}
return true;
},

"public function onkeyup",function(event){
var keys=this[$getKeyMap]();
if(keys){
switch(event.getKeyCode()){
case keys.lookLeft:
case keys.lookRight:
case keys.lookBackwards:
this[$viewTurn]=undefined;
return false;
case keys.changeView:
this[$targetHorizon]=this[$targetHorizon]==.5?.1:this[$targetHorizon]==.1?.2:.5;
return false;
}
}
return true;
},

"public var",{GRID_LINE_DISTANCE: undefined},
"public var",{GRID_LINE_WIDTH: undefined},
"public var",{HALF_SLANT_LINE_WIDTH: undefined},
"public var",{VIEW_DEPTH: undefined},
"public var",{WIDTH: undefined},
"public var",{HEIGHT: undefined},
"public var",{HORIZON: undefined},
"private var",{vector:function(){return(new Vector());}},
"private var",{lastDir: undefined},
"private var",{lastTurnTime: undefined},
"private var",{horizon:0.1},
"private var",{targetHorizon:.5},
"private var",{viewTurn: undefined},
"public var",{SIDE: undefined},
"public var",{X_FACTOR: undefined},
"public var",{Y_FACTOR: undefined},
"public var",{grid: undefined},
"private var",{layerCount:0},
"private var",{lightCycle: undefined},
"private var",{sizeDirty: undefined},
"private var",{leftOffset: undefined},
"private var",{slantLines: undefined},
"private var",{offset: undefined},
"private var",{lines: undefined},
"public var",{lineLayer: undefined},
"public var",{slantLineLayer: undefined},
"private var",{wallLayer: undefined},
"private var",{hudLayer: undefined},
"private var",{renderedSpeed: undefined},
"private var",{operaClassToggle:false},
];},["create"]
);joo.classLoader.prepare("package net.jangaron",[

"import joo.css.Color",""],

"public class Line",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(Color);},

"public function Line",function(viewPort,y){this[$super]();
this.viewPort=viewPort;
this[$y]=y;
this.HALF_LINE_WIDTH=viewPort.GRID_LINE_WIDTH/2;
},

"public function update",function(offset){
var y0=this[$y]-offset;
var y1=this.viewPort.getY(y0+this.HALF_LINE_WIDTH);
var y2=this.viewPort.getY(y0-this.HALF_LINE_WIDTH)+1;
if(!this[$div]){
this[$div]=this.viewPort.lineLayer.addRect(Color.WHITE,
0,this.viewPort.HORIZON+y1,
this.viewPort.WIDTH,this.viewPort.HORIZON+y2);
}else{
this[$div].style.top=Math.round(this.viewPort.HORIZON+y1)+"px";
this[$div].style.height=Math.round(y2-y1)+"px";
this[$div].style.width=this.viewPort.WIDTH+"px";
}
},

"public var",{HALF_LINE_WIDTH: undefined},
"public var",{viewPort: undefined},
"private var",{y: undefined},
"private var",{div: undefined},
];},[]
);joo.classLoader.prepare("package net.jangaron",[

"import joo.lang.JOObject",
"import joo.html.Window2",
"import joo.html.Browser",
"import joo.html.Document2",
"import joo.html.Element2",
"import joo.html.TextNode2",
"import joo.html.EventType",
"import joo.html.Event2",
"import joo.css.Color",
"import joo.css.Display",
"import joo.css.Length",
"import joo.css.Style2",
"import joo.css.Overflow",
"import joo.util.Arrays",
"import joo.util.HashSet",
"import joo.util.TimedExecutor",
"import joo.sound.Sound",
"import net.jangaron.ViewPort",
"import net.jangaron.Direction",
"import net.jangaron.Vector",
"import net.jangaron.LightCycle",
"import net.jangaron.Wall",
"import joo.util.NumberUtil",
"import KeyEvent",""],

"public class Grid extends JOObject",function($jooPublic,$jooPrivate){with(net.jangaron)with($jooPublic)with($jooPrivate)return[function(){joo.classLoader.init(KeyEvent,Overflow,Browser,Display,EventType,Direction,Color);},

"public static const",{MIN_INTERVAL_MS:40},

"private static const",{SOUND_AMBIENT:"ambient"},
"private static const",{SOUND_WON:"won"},
"private static const",{SOUND_LOST:"lost"},
"private static const",{SOUND_START:"start"},
"private static const",{SOUND_BEEP:"beep"},

"public static function main",function(width,height,highRim,
startOpacity,obstacleCnt,
musicVolume,soundVolume,
viewPortDefs,
minIntervalMS){
var STYLES=
[[{height:"95%",top:"5%",width:"100%",left:"0%"}],
[{height:"47%",top:"4.5%",width:"100%",left:"0%"},
{height:"47%",top:"52.5%",width:"100%",left:"0%"}],
[{height:"47%",top:"4.5%",width:"100%",left:"0%"},
{height:"47%",top:"52.5%",width:"49%",left:"0%"},
{height:"49%",top:"52.5%",width:"49%",left:"50.5%"}],
[{height:"47%",top:"4.5%",width:"49%",left:"0%"},
{height:"47%",top:"4.5%",width:"49%",left:"50.5%"},
{height:"47%",top:"52.5%",width:"49%",left:"0%"},
{height:"47%",top:"52.5%",width:"49%",left:"50.5%"}]
];
var startVectors=
[new Vector(width/2,10,Direction.NORTH),
new Vector(width/2,height-10,Direction.SOUTH),
new Vector(width/2-10,10,Direction.NORTH),
new Vector(width/2+10,height-10,Direction.SOUTH),
new Vector(width/2+10,10,Direction.NORTH),
new Vector(width/2-10,height-10,Direction.SOUTH)];
var viewPortCnt=0;
var viewPortDef;
for(var i=0;i<viewPortDefs.length;++i){
viewPortDef=viewPortDefs[i];
if(viewPortDef.user||viewPortDef.visible){
++viewPortCnt;
}
}
var styles=STYLES[viewPortCnt-1];
var gameDocument=Document2.getInstance();
if(Browser.ENGINE!=Browser.ENGINE_GECKO){
gameDocument.getDocumentElement().getStyle().setOverflow(Overflow.HIDDEN);
}
var lightcycles=[];
var viewports=[];
for(i=0;i<viewPortDefs.length;++i){
viewPortDef=viewPortDefs[i];
var lightCycle=new LightCycle(viewPortDef.teamColor["getTeam"](),viewPortDef.name,viewPortDef.teamColor["getColor"](),viewPortDef.startVector||startVectors[i],
viewPortDef.user?viewPortDef.keyMap:null,
viewPortDef.minSpeed,viewPortDef.maxSpeed);
lightcycles.push(lightCycle);
if(viewPortDef.user||viewPortDef.visible){
var style=viewPortDef.style?viewPortDef.style:styles[viewports.length];
var viewPort=ViewPort.create(gameDocument,style);
viewPort.setLightCycle(lightCycle);
viewports.push(viewPort);
}
}
Sound.init(function(hasSound){
if(!hasSound){
musicVolume=soundVolume=0;
}
window["grid"]=new Grid(width,height,highRim,startOpacity,obstacleCnt,lightcycles,viewports,musicVolume,soundVolume,minIntervalMS);
});
},

"public function Grid",function(width,height,highRim,
startOpacity,obstacleCnt,
lightCycles,viewPorts,
musicVolume,soundVolume,
minIntervalMS){
this[$super]();
this[$lightCycles]=lightCycles;
Arrays.broadcast(this[$lightCycles],"setGrid",this);
this[$viewPorts]=viewPorts;
Arrays.broadcast(this[$viewPorts],"setGrid",this);
if(!minIntervalMS)
minIntervalMS=MIN_INTERVAL_MS;
this[$stepExecutor]=new TimedExecutor(this[$doStep],minIntervalMS);
this.width=width;
this.height=height;
this.highRim=highRim;
this.startOpacity=startOpacity;
this.obstacleCnt=obstacleCnt;

var document=Document2.getInstance();
this[$createStatusLine](document);
var htmlElement=document.getDocumentElement();
this[$terminalAnimationExecutor]=new TimedExecutor(this[$animateTerminal],40);
this[$terminal]=document.createElement("div").setClassName("terminal");
this[$terminal].getStyle().setOpacity(0.8);
this[$terminal].addEventListener(EventType.CLICK,function(event){

event.getType=function(){return EventType.KEYDOWN;};
event.getKeyCode=function(){return KeyEvent.DOM_VK_RETURN;};
this[$onkeydown](event);
return false;
}.bind(this));
document.getBody().appendChild(this[$terminal]);
htmlElement.addEventListener(EventType.KEYDOWN,this[$onkeydown],true);
htmlElement.addEventListener(EventType.KEYUP,this[$onkeyup],true);
var window=document.getWindow();
window.addEventListener(EventType.BLUR,this[$onblur],true);
window.addEventListener(EventType.FOCUS,this[$onfocus],true);
this.soundVolume=soundVolume;
this.musicVolume=musicVolume;
if(musicVolume||soundVolume){
this[$sounds]={};
if(musicVolume>0){
var ambient=new Sound();
ambient.loadSound("http://dl.dropbox.com/u/7433264/Recognizer.mp3"); // ambient.loadSound("game/Recognizer.mp3",true);
ambient.stop();
ambient.setVolume(musicVolume);

ambient.onSoundComplete=function(){
ambient.start();
};
this[$sounds][SOUND_AMBIENT]=ambient;
this[$sounds][SOUND_WON]=new Sound("game/won.mp3",false).setVolume(musicVolume);
this[$sounds][SOUND_LOST]=new Sound("game/lost.mp3",false).setVolume(musicVolume);
}
if(soundVolume>0){

this[$sounds][SOUND_BEEP]=new Sound("game/beep.mp3",false).setVolume(soundVolume);
}
}

for(var vp=0;vp<this[$viewPorts].length;++vp){
var viewPort=this[$viewPorts][vp];
if(viewPort.getLightCycle().isUser()){
this[$primaryViewPort]=viewPort;
break;
}
}
if(!this[$primaryViewPort]){
this[$primaryViewPort]=this[$viewPorts][0];
}
this[$init]();
},

"private function getSound",function(name){
return this[$sounds][name];
},

"private function createStatusLine",function(document){
this[$statusLine]=document.createElement("div").setClassName("status");
document.getBody().appendChild(this[$statusLine]);
this[$statusLines]={};
this[$lightCycles].forEach(this[$addToStatusLine],this);
var fpsDisplay=document.createElement("div").setClassName("fps");
fpsDisplay.appendChild(document.createTextNode(""));
this[$statusLine].appendChild(fpsDisplay);
},

"private static function cssPercent",function(n){
return Math.floor(n*100)/100+"%";
},

"private bound function addToStatusLine",function(lightCycle,index){
var document=Document2.getInstance();
var lightCycleStatus=this[$statusLines][lightCycle]=
document.createElement("div").setStyle({
color:Color.WHITE,backgroundColor:lightCycle.getColor(),
left:cssPercent(index*100/this[$lightCycles].length),
width:cssPercent(100/this[$lightCycles].length)
});
lightCycleStatus.appendChild(document.createTextNode(lightCycle.getName()));
this[$statusLine].appendChild(lightCycleStatus);
},

"public function getLightCycles",function(){
return this[$lightCycles];
},

"public function getPrimaryViewPort",function(){
return this[$primaryViewPort];
},

"private function init",function(){
if(this.musicVolume){
this[$getSound](SOUND_WON).stop();
this[$getSound](SOUND_LOST).stop();
this[$getSound](SOUND_AMBIENT).start();
}
this[$terminal].setStyle({display:"none"});
this[$terminalAnimationExecutor].stop();
this[$inGame]=true;
this[$keyQueue]=[];
this.walls=[];
var GRAY=Color.GRAY;
([new Wall(GRAY,0,[0,this.height]),
new Wall(GRAY,this.width,[0,this.height]),
new Wall(GRAY,[0,this.width],0),
new Wall(GRAY,[0,this.width],this.height)]).forEach(this.addWall,this);
this[$createRandomWalls](this.obstacleCnt);
this[$livingCount]=this[$lightCycles].length;
this[$livingCountByTeam]={};
this[$livingTeams]=0;
this[$livingUserCount]=0;
this[$userLightCycles]=[];
for(var lc=0;lc<this[$livingCount];++lc){
var lightCycle=this[$lightCycles][lc];
if(lightCycle.isUser()){
this[$userLightCycles].push(this[$lightCycles][lc]);
}
var team=lightCycle.getTeam();
if(lightCycle.isUser()||team!==lightCycle.getName()){
if(!this[$livingCountByTeam][team]){
this[$livingCountByTeam][team]=0;
++this[$livingTeams];
}
++this[$livingCountByTeam][team];
}
}
this[$livingUserCount]=this[$userLightCycles].length;
Arrays.broadcast(this[$lightCycles],"init");
if(window.parent==window){

if(!this[$stepExecutor].start()){

}
}else{
Arrays.broadcast(this[$viewPorts],"update");
}
},

"private function createRandomWalls",function(number){
var GRAY=new Color(120,120,140);
for(var i=0;i<number;++i){
var wall;
do{
var x1=Math.round(20+Math.random()*(this.width-40));
var x2=Math.round(20+Math.random()*(this.width-40));
var y1=Math.round(20+Math.random()*(this.height-40));
var y2=Math.round(20+Math.random()*(this.height-40));
wall=Math.random()>0.5
?new Wall(GRAY,[Math.min(x1,x2),Math.max(x1,x2)],y1)
:new Wall(GRAY,x1,[Math.min(y1,y2),Math.max(y1,y2)]);
}while(this[$hasIntersectingWall](wall));

if(wall.x1==wall.x2){
this.addWall(new Wall(GRAY,wall.x1-.5,[wall.y1,wall.y2]));
this.addWall(new Wall(GRAY,wall.x1+.5,[wall.y1,wall.y2]));
this.addWall(new Wall(GRAY,[wall.x1-.5,wall.x1+.5],y1));
this.addWall(new Wall(GRAY,[wall.x1-.5,wall.x1+.5],y2));
}else{
this.addWall(new Wall(GRAY,[wall.x1,wall.x2],wall.y1-.5));
this.addWall(new Wall(GRAY,[wall.x1,wall.x2],wall.y1+.5));
this.addWall(new Wall(GRAY,x1,[wall.y1-.5,wall.y1+.5]));
this.addWall(new Wall(GRAY,x2,[wall.y1-.5,wall.y1+.5]));
}
}
},

"private function hasIntersectingWall",function(wall){
for(var i=0;i<this.walls.length;++i){
var w=this.walls[i];
if(w.intersects(wall)){
return true;
}
}
return false;
},

"public bound function addWall",function(wall){
this.walls.push(wall);
},

"public function removeWall",function(wall){
return Arrays.remove(this.walls,wall);
},

"private bound function doStep",function(passedMillis,tie){
if(!this[$inGame])
return undefined;
this[$updateFrameRate](passedMillis);
var oldLivingCount=this[$livingCount];
var lastStartTime=tie.getLastTriggerStartTime();
var startTime=tie.getTriggerStartTime();

do{
var nextTurnTime=this[$getNextTurnTime]();

Arrays.broadcast(this[$lightCycles],"move",(nextTurnTime>startTime?nextTurnTime:startTime)-lastStartTime);
Arrays.broadcast(this[$lightCycles],"update");
Arrays.broadcast(this[$lightCycles],"checkCrashed");
lastStartTime=nextTurnTime;
Arrays.broadcast(this[$lightCycles],"turn",nextTurnTime);
}while(nextTurnTime);
Arrays.broadcast(this[$viewPorts],"update",passedMillis);
Arrays.broadcast(this[$lightCycles],"update");
Arrays.broadcast(this[$lightCycles],"checkCrashed");
this[$lightCycles].forEach(this[$updateStatusLine]);
if(oldLivingCount!=this[$livingCount]&&this[$isGameOver]()){
Arrays.broadcast(this[$viewPorts],"update");

this[$inGame]=false;
window.setTimeout(this[$gameOver],0);
return false;
}
return undefined;
},

"private function getNextTurnTime",function(){
for(var ulc=0;ulc<this[$userLightCycles].length;++ulc){
var lightCycle=this[$userLightCycles][ulc];
var nextTurnTime=lightCycle.nextTurnTime();
if(nextTurnTime){
return nextTurnTime;
}
}
return undefined;
},


"internal function crashed",function(lightCycle){
if(lightCycle.isUser()){

var exchangeLC=this[$findExchangeLightCycle](lightCycle);
if(exchangeLC){

for(var vp=0;vp<this[$viewPorts].length;++vp){
var viewPort=this[$viewPorts][vp];
if(viewPort.getLightCycle()===lightCycle){

Arrays.remove(this[$userLightCycles],lightCycle);
this[$userLightCycles].push(exchangeLC);
exchangeLC.keyMap=lightCycle.keyMap;
lightCycle.keyMap=undefined;
viewPort.setLightCycle(exchangeLC);
return;
}
}
throw new Error("View port of user-controlled lightcycle "+lightCycle.getName()+" not found!");
}
}
},

"private function findExchangeLightCycle",function(lightCycle){
var team=lightCycle.getTeam();
for(var i=0;i<this[$lightCycles].length;++i){
var lc=this[$lightCycles][i];
if(lc!==lightCycle&&!lc.isDead()&&!lc.isUser()&&lc.getTeam()==team){
return lc;
}
}
return null;
},

"private function isGameOver",function(){
if(this[$livingCount]<=1
||this[$userLightCycles].length>0&&this[$livingUserCount]==0){
return true;
}
for(var team in this[$livingCountByTeam]){
if(this[$livingCountByTeam][team]==0){
delete this[$livingCountByTeam][team];
--this[$livingTeams];
if(this[$livingTeams]<=1){
return true;
}
}
}
return false;
},
"private bound function updateStatusLine",function(lightCycle){
var sl=this[$statusLines][lightCycle];

sl.getStyle().setBackgroundColor(lightCycle.getColor());
sl.getStyle().setOpacity(lightCycle.isDead()?0.5:1);

var textNode=sl.getFirstChild();
textNode.setData([lightCycle.getName(),
" | w",NumberUtil.format(lightCycle.wins,2),
" | d",NumberUtil.format(lightCycle.deaths,2)].join(""));
},

"private function updateFrameRate",function(passedMillis){
this[$passedMillisSum]+=passedMillis;
++this[$renderedFrames];
if(this[$passedMillisSum]>=1000){
var fps=this[$renderedFrames]*1000/this[$passedMillisSum];
(this[$statusLine].getLastChild().getFirstChild()).setData(NumberUtil.format(fps,2,2));
this[$passedMillisSum]=0;
this[$renderedFrames]=0;
}
},

"public function removeLightCycle",function(lightCycle){
for(var i=0;i<this.walls.length;){
var w=this.walls[i];
if(w.lightCycle===lightCycle){
this.walls.splice(i,1);
}else{
++i;
}
}
--this[$livingCount];
if(lightCycle.isUser()){
--this[$livingUserCount];
}
--this[$livingCountByTeam][lightCycle.getTeam()];
},

"private bound function onkeydown",function(event){
if(!this[$inGame]){
if(event.getKeyCode()==KeyEvent.DOM_VK_RETURN){
this[$init]();
event.preventDefault();
return false;
}
return true;
}
switch(event.getKeyCode()){
case KeyEvent.DOM_VK_SPACE:
if(this[$stepExecutor].isRunning()){
this[$stepExecutor].stop();
}else{
this[$stepExecutor].start();
}
event.preventDefault();
return false;
}
for(var lc=this[$userLightCycles].length-1;lc>=0;--lc){
var lightCycle=this[$userLightCycles][lc];
if(!lightCycle.onkeydown(event)){
event.preventDefault();
return false;
}
}
for(var vp=this[$viewPorts].length-1;vp>=0;--vp){
var viewPort=this[$viewPorts][vp];
if(!viewPort.onkeydown(event)){
event.preventDefault();
return false;
}
}
return true;
},

"private bound function onkeyup",function(event){
if(!this[$inGame]){
return true;
}
for(var lc=this[$userLightCycles].length-1;lc>=0;--lc){
var lightCycle=this[$userLightCycles][lc];
if(!lightCycle.onkeyup(event)){
event.preventDefault();
return false;
}
}
for(var vp=this[$viewPorts].length-1;vp>=0;--vp){
var viewPort=this[$viewPorts][vp];
if(!viewPort.onkeyup(event)){
event.preventDefault();
return false;
}
}
return true;
},

"private bound function onblur",function(){
if(this[$userLightCycles].length>0){
this[$stepExecutor].stop();
}
},

"private bound function onfocus",function(){
if(this[$inGame]){
this[$stepExecutor].start();
}
},

"private static function displayName",function(lc){
var output=[lc.isUser()?"USER":"PROGRAM"," ",lc.getName().toUpperCase()];
if(lc.getTeam()!=lc.getName()){
output.push(" [",lc.getTeam().toUpperCase()," TEAM]");
}
return output.join("");
},

"private bound function gameOver",function(){









var survivingPrograms=[];
var survivingUser;
var survivingTeams=new HashSet();
var survivor;
for(var s=0;s<this[$lightCycles].length;++s){
var lc=this[$lightCycles][s];
if(!lc.isDead()){
if(lc.isUser()){
survivor=survivingUser=lc;
}else{
survivingPrograms.push(lc);
}
if(lc.isUser()||lc.getTeam()!==lc.getName()){
survivingTeams.add(lc.getTeam());
}
}
}
if(!survivor&&survivingPrograms.length>0){

survivor=survivingPrograms[Math.floor(Math.random()*survivingPrograms.length)];
survivingPrograms.forEach(function(s){if(s!==survivor)++s.deaths;});
}
var survivorName;
if(survivor){
survivorName=displayName(survivor);
++survivor.wins;
survivorName=displayName(survivor);
}else{
survivorName="NOBODY";
}
var msg;
switch(this[$userLightCycles].length){
case 0:
msg=["GAME OVER"];
break;
case 1:
if(survivingUser){
if(this.musicVolume){
this[$getSound](SOUND_AMBIENT).stop();
this[$getSound](SOUND_WON).start();
}
var manyPrograms=this[$lightCycles].length-this[$userLightCycles].length>1;
msg=["NO! THIS IS IMPOSSIBLE!",
survivorName+" HAS BEATEN MY BEST PROGRAM"+(manyPrograms?"S":""),
"WAIT UNTIL I'VE GOTTEN 2,415 TIMES SMARTER..."];
break;
}
}
if(this.musicVolume){
this[$getSound](SOUND_AMBIENT).stop();
this[$getSound](SOUND_LOST).start();
}
msg=["ILLEGAL CODE"];
for(var u=0;u<this[$userLightCycles].length;++u){
var ulc=this[$userLightCycles][u];
if(ulc.isDead()){
msg.push(displayName(ulc)+" DETACHED FROM SYSTEM");
}
}
msg.push(survivorName+" HAS WON THE GAME");
msg.push("END OF LINE");
msg.push("<HIT RETURN TO PLAY AGAIN>");
this[$terminal].getPeer().innerHTML="<div></div><p><span class='cursor'>&nbsp;</span></p>";
var docWidth=Document2.getInstance().getDocumentElement().getDimensions().width;
this[$terminal].getStyle().setDisplay(Display.BLOCK).setFontSize(Length.px(docWidth/30));
this[$message]=msg;
this[$messageLineIndex]=0;
this[$terminalAnimationExecutor].start();
},

"private bound function animateTerminal",function(passedMillis){

var line=this[$message][0];
var p=this[$terminal].getLastChild();
var cursor=p.getLastChild();
if(!line){

var cursorStyle=cursor.getStyle();
cursorStyle.setDisplay(cursorStyle.getDisplay()!=Display.NONE?Display.NONE:Display.INLINE);
return 500;
}
if(this[$messageLineIndex]>=line.length){
this[$message].shift();
if(this[$message].length==0){
return 500;
}
p.removeChild(cursor);
this[$messageLineIndex]=0;
p=p.ownerDocument.createElement("p");
p.setInnerHTML("<span class='cursor'>&nbsp;</span>");
this[$terminal].appendChild(p);
return 200;
}
if(this[$messageLineIndex]==0){
if(this.soundVolume){
this[$getSound](SOUND_BEEP).start();
}
p.insertBefore(p.ownerDocument.createTextNode(""),p.getFirstChild());
this[$messageLineIndex]=1;
}else{
this[$messageLineIndex]+=Math.round(passedMillis/20);
}
var textNode=p.getFirstChild();
textNode.setData(line.substring(0,this[$messageLineIndex]));
return 40;
},

"public var",{width: undefined},
"public var",{height: undefined},
"public var",{highRim: undefined},
"public var",{obstacleCnt: undefined},
"public var",{startOpacity:1},
"public var",{musicVolume:100},
"public var",{soundVolume:100},
"private var",{lightCycles: undefined},
"private var",{primaryViewPort: undefined},
"private var",{userLightCycles: undefined},
"private var",{livingCount: undefined},
"private var",{livingCountByTeam: undefined},
"private var",{livingUserCount: undefined},
"private var",{livingTeams: undefined},
"private var",{viewPorts: undefined},
"private var",{stepExecutor: undefined},
"private var",{keyQueue: undefined},
"public var",{walls: undefined},
"private var",{passedMillisSum:0},
"private var",{renderedFrames:0},
"private var",{statusLine: undefined},
"private var",{statusLines: undefined},
"private var",{sounds: undefined},
"private var",{terminalAnimationExecutor: undefined},
"private var",{inGame:false},
"private var",{terminal: undefined},
"private var",{messageLineIndex: undefined},
"private var",{message: undefined},
"private var",{insideStep: undefined},
];},["main"]
);