</pre>
<div id="control" style="display:flex;justify-content:center;align-items:center;height:100%">
<div style="padding-right:20px">
<h1>XENTRIS</h1>
<p><strong>Xenians, click on the playing field!</strong></p>
<p><strong>Left</strong> ↩<br>
<strong>Down</strong> ⇓
<br><strong>Right</strong> ⇒ </p>
<p><strong>A</strong> to rotate counter-clockwise<br>
<strong>S</strong> to rotate clockwise</p><br>
XEN: <a href="https://xen.network" target="_blank">xen.network</a><br>
Follow: <a href="https://twitter.com/jarosciak" target="_blank">@jarosciak</a>
</div>
<div style="width:100%;text-align:center" id="tetris">
</div>
</div>
</div>
<script>/*<![CDATA[*/var TETRIS={config:{BlockSize:25,ControlKey:{Left:"37",Right:"39",Down:"40",RotateLeft:"65",RotateRight:"83"},FieldHeight:22,FieldWidth:10,LevelUpRow:10,LevelUpSpeed:50,PieceColor:{I:"red",J:"orange",L:"magenta",O:"blue",S:"lime",T:"olive",Z:"cyan"},ScoreMultiplier:10,StartingSpeed:1000,VoidColor:"#fafafa"},state:{shape:{},form:[],color:"black",drop:!1,rotate:0,rows:0,score:0,level:1,next:"",over:!1,board:null,speed:0,interval:null},piece:{available:["I","J","L","O","S","T","Z"],type:{I:{start:[3,0],shape:[[[0,0],[1,0],[2,0],[3,0]],[[0,0],[0,1],[0,2],[0,3]]]},J:{start:[4,0],shape:[[[0,0],[0,1],[1,1],[2,1]],[[2,0],[1,0],[1,1],[1,2]],[[2,2],[2,1],[1,1],[0,1]],[[0,2],[1,2],[1,1],[1,0]]]},L:{start:[4,0],shape:[[[2,0],[2,1],[1,1],[0,1]],[[2,2],[1,2],[1,1],[1,0]],[[0,2],[0,1],[1,1],[2,1]],[[0,0],[1,0],[1,1],[1,2]]]},O:{start:[4,0],shape:[[[0,0],[1,0],[0,1],[1,1]]]},S:{start:[4,0],shape:[[[2,0],[1,0],[1,1],[0,1]],[[0,0],[0,1],[1,1],[1,2]]]},T:{start:[4,0],shape:[[[1,0],[0,1],[1,1],[2,1]],[[2,1],[1,0],[1,1],[1,2]],[[1,2],[2,1],[1,1],[0,1]],[[0,1],[1,2],[1,1],[1,0]]]},Z:{start:[4,0],shape:[[[0,0],[1,0],[1,1],[2,1]],[[2,0],[2,1],[1,1],[1,2]]]}}},play:function(c,a){for(var b in a=a||{},$T.config){a.hasOwnProperty(b)&&($T.config[b]=a[b])}$T.state.color=$T.config.VoidColor,$T.state.speed=$T.config.StartingSpeed,document.onkeydown=function(d){d=d||window.event,$T.fn.keyboardAction(d.keyCode,"event")},$T.fn.renderField(c),$T.fn.renderNextPiece(),$T.state.interval=setInterval($T.fn.stepInterval,$T.state.speed)},fn:{mod:function(b,a){return(b%a+a)%a},renderField:function(f){var c,d,g=document.getElementById(f);for(c=0,g.style.width=$T.config.BlockSize*$T.config.FieldWidth+"px",g.style.height=$T.config.BlockSize*$T.config.FieldHeight+"px",g.style.border="1px solid black";c<$T.config.FieldHeight;c++){var h=document.createElement("div");for(h.setAttribute("id","row-"+c),h.setAttribute("class","field-row"),d=0;d<$T.config.FieldWidth;d++){var b=document.createElement("div");b.setAttribute("id","row-"+c+"-col-"+d),b.setAttribute("class","field-column"),b.setAttribute("taken","0"),b.setAttribute("control","0"),b.style.width=$T.config.BlockSize+"px",b.style.height=$T.config.BlockSize+"px",b.style.cssFloat="left",b.style.backgroundColor=$T.config.VoidColor,h.appendChild(b)}g.appendChild(h)}$T.state.board=document.createElement("div"),$T.state.board.style.fontFamily="monospace",$T.state.board.style.fontSize="smaller",$T.state.board.style.textAlign="center",$T.fn.renderBoard(),g.appendChild($T.state.board)},renderBlock:function(g,d,f,h,i,c){var b=document.getElementById("row-"+i+"-col-"+h);b.style.backgroundColor=g,d?b.setAttribute("taken","1"):b.setAttribute("taken","0"),f?b.setAttribute("control","1"):b.setAttribute("control","0")},renderPiece:function(h,f,g,j){var k=$T.piece.type[h].shape,c=k[$T.fn.mod(f,k.length)],b=$T.config.PieceColor[h];$T.config.VoidColor,$T.state.shape=k,$T.state.color=$T.config.PieceColor[h];for(var d=0;d<4;d++){if(!$T.fn.isBlockAvailable(g+c[d][0],j+c[d][1])){return !1}}for(var d=0;d<4;d++){$T.fn.renderBlock(b,!0,!0,g+c[d][0],j+c[d][1],d),$T.state.form[d]=[g+c[d][0],j+c[d][1]]}return !0},renderNextPiece:function(){var c=Math.floor(Math.random()*$T.piece.available.length),a=$T.piece.available[c];if(""!=$T.state.next){var b=$T.state.next;$T.state.next=a,a=b}else{$T.state.next=a}var d=$T.piece.type[a];$T.fn.renderPiece(a,0,d.start[0],d.start[1])||($T.state.over=!0,clearInterval($T.state.interval)),$T.fn.renderBoard()},renderBoard:function(){var a="";a+="[ROW: <strong>"+$T.state.rows+"</strong>] • ",a+="[LVL: <strong>"+$T.state.level+"</strong>]<br />",a+="[PTS: <strong>"+$T.state.score+"</strong>] • ",a+="[NXT: <strong>"+$T.state.next+"</strong>]<br />",$T.state.over&&(a+="<br />• <strong>Game Over!</strong> •"),$T.state.board.innerHTML=a},isBlockAvailable:function(c,a){if(block=document.getElementById("row-"+a+"-col-"+c)){var b=block.getAttribute("taken"),d=block.getAttribute("control");if("1"!=b||"1"==d){return !0}}return !1},stepInterval:function(){if($T.state.drop){$T.state.shape;var h,m,b,c=$T.state.form,b=$T.state.color;$T.config.VoidColor;for(var d=0;d<4;d++){$T.fn.renderBlock(b,!0,!1,c[d][0],c[d][1],d)}for(var j=0,f=0,d=$T.config.FieldHeight-1;d>0;d--){f=0;for(var g=0;g<$T.config.FieldWidth;g++){"1"==(m=(h=document.getElementById("row-"+d+"-col-"+g)).getAttribute("taken"))&&f++}if(f==$T.config.FieldWidth){j++;for(var p=d-1;p>0;p--){for(var k=0;k<$T.config.FieldWidth;k++){m=(h=document.getElementById("row-"+p+"-col-"+k)).getAttribute("taken"),b=h.style.backgroundColor,$T.fn.renderBlock(b,"1"==m,!1,k,p+1,0)}}d+=1}}j&&($T.state.rows+=j,$T.state.score+=Math.pow(j,2)*$T.config.ScoreMultiplier,Math.floor($T.state.rows/$T.config.LevelUpRow+1)>$T.state.level&&($T.state.level++,clearInterval($T.state.interval),$T.state.speed=$T.state.speed-$T.config.LevelUpSpeed,$T.state.interval=setInterval($T.fn.stepInterval,$T.state.speed))),$T.state.shape={},$T.state.form=[],$T.state.color=$T.config.VoidColor,$T.state.drop=!1,$T.state.rotate=0,$T.fn.renderNextPiece();return}$T.fn.keyboardAction($T.config.ControlKey.Down,"interval")},keyboardAction:function(j,p){var b=$T.state.shape,c=$T.state.form,d=$T.state.color,k=$T.config.VoidColor;if(j==$T.config.ControlKey.Left){for(var f=0;f<4;f++){if(!$T.fn.isBlockAvailable(c[f][0]-1,c[f][1])){return}}for(var f=0;f<4;f++){$T.fn.renderBlock(k,!1,!1,c[f][0],c[f][1],f)}for(var f=0;f<4;f++){$T.fn.renderBlock(d,!0,!0,c[f][0]-1,c[f][1],f),$T.state.form[f]=[c[f][0]-1,c[f][1]]}}else{if(j==$T.config.ControlKey.Right){for(var f=0;f<4;f++){if(!$T.fn.isBlockAvailable(c[f][0]+1,c[f][1])){return}}for(var f=0;f<4;f++){$T.fn.renderBlock(k,!1,!1,c[f][0],c[f][1],f)}for(var f=0;f<4;f++){$T.fn.renderBlock(d,!0,!0,c[f][0]+1,c[f][1],f),$T.state.form[f]=[c[f][0]+1,c[f][1]]}}else{if(j==$T.config.ControlKey.RotateLeft){for(var h,q,m=b[$T.fn.mod($T.state.rotate,b.length)],g=b[$T.fn.mod($T.state.rotate-1,b.length)],f=0;f<4;f++){if(h=c[f][0]-m[f][0]+g[f][0],q=c[f][1]-m[f][1]+g[f][1],!$T.fn.isBlockAvailable(h,q)){return}}for(var f=0;f<4;f++){$T.fn.renderBlock(k,!1,!1,c[f][0],c[f][1],f)}for(var f=0;f<4;f++){h=c[f][0]-m[f][0]+g[f][0],q=c[f][1]-m[f][1]+g[f][1],$T.fn.renderBlock(d,!0,!0,h,q,f),$T.state.form[f]=[h,q]}$T.state.rotate--}else{if(j==$T.config.ControlKey.RotateRight){for(var h,q,m=b[$T.fn.mod($T.state.rotate,b.length)],g=b[$T.fn.mod($T.state.rotate+1,b.length)],f=0;f<4;f++){if(h=c[f][0]-m[f][0]+g[f][0],q=c[f][1]-m[f][1]+g[f][1],!$T.fn.isBlockAvailable(h,q)){return}}for(var f=0;f<4;f++){$T.fn.renderBlock(k,!1,!1,c[f][0],c[f][1],f)}for(var f=0;f<4;f++){h=c[f][0]-m[f][0]+g[f][0],q=c[f][1]-m[f][1]+g[f][1],$T.fn.renderBlock(d,!0,!0,h,q,f),$T.state.form[f]=[h,q]}$T.state.rotate++}else{if(j==$T.config.ControlKey.Down){for(var f=0;f<4;f++){if(!$T.fn.isBlockAvailable(c[f][0],c[f][1]+1)){"interval"==p&&($T.state.drop=!0);return}}for(var f=0;f<4;f++){$T.fn.renderBlock(k,!1,!1,c[f][0],c[f][1],f)}for(var f=0;f<4;f++){$T.fn.renderBlock(d,!0,!0,c[f][0],c[f][1]+1,f),$T.state.form[f]=[c[f][0],c[f][1]+1]}}}}}}}}},$T=TETRIS;TETRIS.play("tetris",{BlockSize:18,ScoreMultiplier:5});/*]]>*/</script>
<pre>