<title>dwin.net - web application - sokoban</title>
<body>
Written by David NG @ <a href="http://dwin.net">http://dwin.net</a><BR>
Copyright(c) 1998-2007 dwin.net all rights reserved<BR>
<style>
.Ground{}
.Floor{}
.Wall{overflow:hidden;border:2px outset #ADFF2F;background-color:#888888;z-index:0}
.Aim{overflow:hidden;background-color:#FF69B4;opacity:0.4;-moz-opacity:0.4;filter:Alpha(opacity=100,FinishOpacity=0,Style=3);z-index:0}
.Box{overflow:hidden;background-color:#87CEFA;opacity:0.5;-moz-opacity:0.5;filter:Alpha(opacity=0,FinishOpacity=100,Style=3);z-index:1}
.Man{overflow:hidden;z-index:1;}
</style>
<br>
Current Map : <input id="CurrentMap" size=5 ><br>
<input type=button value='Previous Map' οnmοusedοwn='ChangeMap(-1)'>
<input type=button value='Next Map' οnmοusedοwn='ChangeMap(1)'><br><br>
<textarea id="SolutionInfo" style="word-wrap:break-word; word-break:break-all" wrap="virtual" rows=20></textarea><br>
<input type=button value='copy' οnclick='document.getElementById("SolutionInfo").select();document.execCommand("Copy")'>
<input type=button value='paste' οnclick='document.getElementById("SolutionInfo").focus();if(!/[^(l|r|u|d|L|R|U|D)]/g.exec(window.clipboardData.getData("Text")))document.execCommand("Paste")'>
<input type=button value='Clear' οnclick='document.getElementById("SolutionInfo").value=""'>
<input type=button value='Auto Run' οnmοusedοwn='AutoRun()'><br><br>
Boxes has Moved<br><input id=BoxMoveInfo readonly> Steps<br>
Man has Moved<br><input id=ManMoveInfo readonly> Steps
<div id=Base style='position:absolute;overflow:hidden'></div>
<script>
// firefox
if(typeof HTMLElement!="undefined" && !HTMLElement.prototype.insertAdjacentElement)
{
HTMLElement.prototype.insertAdjacentElement = function(where,parsedNode)
{
switch( where )
{
case 'beforeBegin':
this.parentNode.insertBefore(parsedNode,this)
break;
case 'afterBegin':
this.insertBefore(parsedNode,this.firstChild);
break;
case 'beforeEnd':
this.appendChild(parsedNode);
break;
case 'afterEnd':
if (this.nextSibling)
this.parentNode.insertBefore(parsedNode,this.nextSibling);
else
this.parentNode.appendChild(parsedNode);
break;
}
}
HTMLElement.prototype.insertAdjacentHTML = function(where,htmlStr)
{
var r = this.ownerDocument.createRange();
r.setStartBefore(this);
var parsedHTML = r.createContextualFragment(htmlStr);
this.insertAdjacentElement(where,parsedHTML)
}
HTMLElement.prototype.insertAdjacentText = function(where,txtStr)
{
var parsedText = document.createTextNode(txtStr)
this.insertAdjacentElement(where,parsedText)
}
}
/*
Written by David NG @ http://dwin.net
Copyright(c) 1998-2004 dwin.net all rights reserved
Start: 2002-10-02 17:50
Finish: 2002-10-15 22:41
2003-06-11 18:55
bug fix
2007-08-08 19:44
firefox support
*/
Map = [];
Solution = [];
FormatAry = [];
CurrentMapPtr = 0;
function init( MapPtr )
{
MainMap = [];
CurrentMapPtr = MapPtr;
FormatPtr = 0;
MaxWidth = 0;
RePlayTime = 100 //million second
MapW = MapH = 30;
PushScrollNo = 30;
BoxCompletes = 0;
TotalBox = 0;
Timer = null;
canMove = true
BoxMoves = 0;
Count = -1;
BackRecord = [];
document.getElementById('BoxMoveInfo').value = 0;
document.getElementById('ManMoveInfo').value = 0;
document.getElementById('CurrentMap').value = CurrentMapPtr;
document.getElementById('SolutionInfo').value = Solution[CurrentMapPtr];
}
function ReadMap( MapPtr )
{
init( MapPtr );
for( var y=0; y<Map[MapPtr].length; y++ )
{
if( Map[MapPtr][y].indexOf('$') != -1 )
FormatPtr = 1;
if( MaxWidth < Map[MapPtr][y].length )
MaxWidth = Map[MapPtr][y].length;
}
var h = Map[MapPtr].length*MapW;
var w = MaxWidth*MapW;
var baseObj = document.getElementById('Base')
baseObj.innerHTML = '';
baseObj.style.width = w;
baseObj.style.height = h;
baseObj.style.left = (w>document.body.clientWidth)?0:(document.body.offsetWidth-w)/2;
baseObj.style.top = 10;
for( var y=0; y<Map[MapPtr].length; y++ )
{
MainMap[y] = new Array(MaxWidth)
for( var x=0; x<MaxWidth; x++ )
{
try{ MainMap[y][x] = Map[MapPtr][y].charAt(x); }
catch(e){ MainMap[y][x] = FormatAry[FormatPtr].Floor; }
if( MainMap[y][x] == FormatAry[FormatPtr].Wall )
iHtml( x, y, 'Wall' );
else
{
iHtml( x, y, 'Ground' );
switch( MainMap[y][x] )
{
case FormatAry[FormatPtr].Box : iBox(x,y,0);
break;
case FormatAry[FormatPtr].Aim : iHtml(x,y,'Aim');
break;
case FormatAry[FormatPtr].BoxOnAim : iHtml(x,y,'Aim');
iBox(x,y,1);
BoxCompletes++;
break;
case FormatAry[FormatPtr].Player : iMan(x,y,0);
break;
case FormatAry[FormatPtr].PlayerOnAim : iHtml(x,y,'Aim');
iMan(x,y,1);
break;
}
}
}
}
}
function iHtml( x, y, k )
{
document.getElementById('Base').insertAdjacentHTML("beforeEnd","<span style='position:absolute;left:"+x*MapW+";top:"+y*MapH+";width:"+MapW+";height:"+MapH+"' class='"+k+"' x="+x+" y="+y+">");
}
function iBox( x, y, k )
{
var obj = document.createElement("span");
obj.style.position = 'absolute';
obj.style.left = x*MapW;
obj.style.top = y*MapH;
obj.style.width = MapW;
obj.style.height = MapH;
obj.className = 'Box';
obj.setAttribute('class','Box');
obj.setAttribute('complete', k);
document.getElementById('Base').appendChild( obj );
MainMap[y][x] = obj;
TotalBox++;
}
function iMan( x, y, k)
{
Man = document.createElement("img");
Man.src = 'http://dwin.net/webapp/cow.gif';
Man.style.position = 'absolute';
Man.style.left = x*MapW;
Man.style.top = y*MapH;
Man.style.width = MapW;
Man.style.height = MapH;
Man.className = 'Man';
Man.setAttribute('class','Man');
Man.setAttribute('x',x);
Man.setAttribute('y',y);
document.getElementById('Base').appendChild( Man );
MainMap[y][x] = (k==0)?FormatAry[FormatPtr].Floor:FormatAry[FormatPtr].Aim;
}
function Dir( x, y, k)
{
if( !canMove || y+(Man.getAttribute('y')|0)<0 || y+(Man.getAttribute('y')|0)>=Map[CurrentMapPtr].length || x+(Man.getAttribute('x')|0)<0 || x+(Man.getAttribute('x')|0)>=MaxWidth )
return
var ManFront = MainMap[y+(Man.getAttribute('y')|0)][x+(Man.getAttribute('x')|0)];
if( ManFront==FormatAry[FormatPtr].Floor || ManFront==FormatAry[FormatPtr].Aim )
{
if( k != null )
Move1( x, y, k.toLowerCase() );
else
Move1(x,y);
}
else
{
if( typeof(ManFront) == 'object' )
{
var ManFrontFront = MainMap[2*y+(Man.getAttribute('y')|0)][2*x+(Man.getAttribute('x')|0)];
if( ManFrontFront == FormatAry[FormatPtr].Floor )
{
if( k != null )
Move1( x, y, k.toUpperCase() );
else
Move1( x, y );
Move2( ManFront, x, y );
}
else if( ManFrontFront == FormatAry[FormatPtr].Aim )
{
if( k != null )
Move1( x, y, k.toUpperCase() );
else
Move1( x, y );
Move3( ManFront, x, y );
}
BoxMoves++
}
}
}
function Move1( x, y, k)
{
if( k != null )
{
BackRecord[++Count] = k
BackRecord.length = Count+1
}
Man.setAttribute('x', x+(Man.getAttribute('x')|0) );
Man.setAttribute('y', y+(Man.getAttribute('y')|0) );
Man.style.left = (Man.getAttribute('x')|0)*MapW;
Man.style.top = (Man.getAttribute('y')|0)*MapH;
}
function Move2( obj, x, y)
{
obj.style.left = (x+(Man.getAttribute('x')|0))*MapW;
obj.style.top = (y+(Man.getAttribute('y')|0))*MapH;
MainMap[y+(Man.getAttribute('y')|0)][x+(Man.getAttribute('x')|0)] = obj;
if( obj.getAttribute('complete') == 0 )
MainMap[Man.getAttribute('y')|0][Man.getAttribute('x')|0]=FormatAry[FormatPtr].Floor;
else
{
MainMap[Man.getAttribute('y')|0][Man.getAttribute('x')|0] = FormatAry[FormatPtr].Aim;
BoxCompletes --;
}
obj.setAttribute('complete', 0);
}
function Move3( obj, x, y)
{
obj.style.left = (x+(Man.getAttribute('x')|0))*MapW;
obj.style.top = (y+(Man.getAttribute('y')|0))*MapH;
MainMap[y+(Man.getAttribute('y')|0)][x+(Man.getAttribute('x')|0)] = obj;
if( obj.getAttribute('complete') == 1 )
MainMap[Man.getAttribute('y')|0][Man.getAttribute('x')|0]=FormatAry[FormatPtr].Aim;
else
{
MainMap[Man.getAttribute('y')|0][Man.getAttribute('x')|0] = FormatAry[FormatPtr].Floor;
if(++BoxCompletes == TotalBox)
oWin();
}
obj.setAttribute('complete', 1);
}
function UnDo()
{
if(Count >= 0)
{
canMove = true
switch( BackRecord[Count] )
{
//not object
case 'l':Move1(1,0);break;//left -> right
case 'u':Move1(0,1);break;//up -> down
case 'r':Move1(-1,0);break;//right -> left
case 'd':Move1(0,-1);break;//down -> up
//object
case 'L':UnGo(1,0);break;//left -> right
case 'U':UnGo(0,1);break;//up -> down
case 'R':UnGo(-1,0);break;//right -> left
case 'D':UnGo(0,-1);break;//down -> up
}
iSelects(--Count)
}
}
function UnGo( x, y )
{
BoxMoves--;
var obj = MainMap[-y+(Man.getAttribute('y')|0)][-x+(Man.getAttribute('x')|0)];
if( MainMap[Man.getAttribute('y')|0][Man.getAttribute('x')|0]==FormatAry[FormatPtr].Floor )
{
if( obj.getAttribute('complete') == 0 )
MainMap[-y+(Man.getAttribute('y')|0)][-x+(Man.getAttribute('x')|0)]=FormatAry[FormatPtr].Floor;
else
{
MainMap[-y+(Man.getAttribute('y')|0)][-x+(Man.getAttribute('x')|0)]=FormatAry[FormatPtr].Aim;
BoxCompletes --;
}
obj.setAttribute('complete', 0);
}
else
{
if( obj.getAttribute('complete') == 0 )
{
MainMap[-y+(Man.getAttribute('y')|0)][-x+(Man.getAttribute('x')|0)]=FormatAry[FormatPtr].Floor;
if( ++BoxCompletes == TotalBox )
oWin();
}
else
MainMap[-y+(Man.getAttribute('y')|0)][-x+(Man.getAttribute('x')|0)]=FormatAry[FormatPtr].Aim;
obj.setAttribute('complete', 1);
}
obj.style.left = (Man.getAttribute('x')|0)*MapW;
obj.style.top = (Man.getAttribute('y')|0)*MapH;
MainMap[Man.getAttribute('y')|0][Man.getAttribute('x')|0] = obj;
Move1( x, y );
}
function ReDo()
{
if( Count+1 < BackRecord.length )
{
switch( BackRecord[++Count] )
{
case 'l': case 'L': Dir(-1,0);break;//left
case 'u': case 'U': Dir(0,-1);break;//up
case 'r': case 'R': Dir(1,0);break;//right
case 'd': case 'D': Dir(0,1);break;//down
}
iSelects(Count)
}
else
clearInterval(Timer);
}
function oWin()
{
canMove = false
alert('Congratulation!')
}
function AutoRun()
{
var temp = document.getElementById('SolutionInfo').value;
if(temp == '')
return;
ReadMap(CurrentMapPtr);
BackRecord = temp.split("");
Timer = setInterval(ReDo,RePlayTime);
}
function iSelects(x)
{
var obj = document.getElementById('SolutionInfo');
if( obj.createTextRange )
{
var iRange = obj.createTextRange()
iRange.collapse(true)
iRange.moveStart("character",x)
iRange.moveEnd("character",1)
iRange.select()
}
else if( obj.setSelectionRange )
{
obj.selectionStart = x;
obj.selectionEnd = x+1;
}
document.getElementById('BoxMoveInfo').value = BoxMoves;
document.getElementById('ManMoveInfo').value = x+1;
}
function ChangeMap( ptr )
{
var GoMap = (CurrentMapPtr+ptr) % Map.length;
GoMap = GoMap<0 ? Map.length-1:GoMap;
ReadMap( GoMap );
}
document.getElementById('CurrentMap').onkeydown = ChangeMapHandler;
function ChangeMapHandler( evt )
{
if( typeof(evt) == 'undefined' )
evt = window.event||window.Event;
var keyCode = 0;
if( evt.keyCode )
keyCode = evt.keyCode;
else if( typeof(evt.which) != 'undefined')
keyCode = evt.which;
if( keyCode == 13 )
ChangeMap( this.value|0 );
evt.cancelBubble = true
if( evt.preventDefault )
evt.stopPropagation();
}
document.onkeydown = function( evt )
{
if( typeof(evt) == 'undefined' )
evt = window.event||window.Event;
var keyCode = 0;
if( evt.keyCode )
keyCode = evt.keyCode;
else if( typeof(evt.which) != 'undefined')
keyCode = evt.which;
if( evt.ctrlKey )
{
switch( keyCode )
{
case 37 : document.body.scrollLeft-=PushScrollNo;break;//left
case 38 : document.body.scrollTop-=PushScrollNo;break;//up
case 39 : document.body.scrollLeft+=PushScrollNo;break;//right
case 40 : document.body.scrollTop+=PushScrollNo;break;//down
}
}
else
{
switch( keyCode )
{
case 37 : Dir(-1,0,'l');break;//left
case 38 : Dir(0,-1,'u');break;//up
case 39 : Dir(1,0,'r');break;//right
case 40 : Dir(0,1,'d');break;//down
}
if( evt.returnValue != false )
evt.returnValue = false;
if( evt.preventDefault )
evt.preventDefault();
document.getElementById('SolutionInfo').value = BackRecord.join("")
iSelects(Count)
}
}
document.onmouseup = function( evt )
{
if( typeof(evt) == 'undefined' )
evt = window.event||window.Event;
if( evt.button==1 || evt.button==0 )
ReDo()
}
document.oncontextmenu = function( evt )
{
if( typeof(evt) == 'undefined' )
evt = window.event||window.Event;
if( evt.returnValue != false )
evt.returnValue = false;
if( evt.preventDefault )
evt.preventDefault();
UnDo();
}
window.onload = function()
{
ReadMap( CurrentMapPtr % Map.length );
document.body.scroll='no'
window.focus();
document.getElementById('Base').focus();
}
/*
XSB Format:
$ = Box
* = Box on Aim
@ = Player
+ = Player on Aim
# = Wall
. = Aim
= Floor
My Format:
0 = Box
@ = Box on Aim
* = Player
# = Player on Aim
W = Wall
. = Aim
= Floor
*/
FormatAry[0] = {
Box : "0",
BoxOnAim : "@",
Player : "*",
PlayerOnAim : "#",
Wall : "W",
Aim : ".",
Floor : " "
}
FormatAry[1] = {
Box : "$",
BoxOnAim : "*",
Player : "@",
PlayerOnAim : "+",
Wall : "#",
Aim : ".",
Floor : " "
}
Map[Map.length] = [
'WWWWWWWWWWW',
'W W* W',
'W 00000 0 W',
'W W',
'WWWWW WWWWW',
' W .W ',
' W .W ',
' W...W ',
' W .W ',
' WWWWW ']
Solution[Solution.length] = 'rddlllllluurDurrDLdRRRRuulDrdLuLDDDDuuulluullddRRRluurDrDDDrddLUluRuurruurrdLrdLLLulDDDDrddllURuuuuruurDrdLLulDDDDDldRuuuuuulldRurDDDlDRuuulluulDldRRRurDDDD';
Map[Map.length] = [
' ## ##',
' ## # ##',
' ## ##',
'# *$#$* #',
'# $...$ #',
' # #.@.# #',
'# $...$ #',
'# *$#$* #',
' ## ##',
' ## # ##',
' ## ##']
Solution[Solution.length] = 'luULuurDDDrrRUrrdLLLddDRddlUUUllLDlluRRRlluuRuurrrDrrdddLddlllUddlUrrrruurrdLuuuulluurDllllddlluR';
Map[Map.length] = [
' #####',
' # #',
' ## $ ##',
' ### $.$ ###',
' # $.*.$ #',
' ## $.*.*.$ ##',
'### $.*.$.*.$ ###',
'# $.*.$ $.*.$ #',
'# $.*.$ $.*.$ #',
'# $.*.$ $.*.$ #',
'### $.*.$.*.$ ###',
' ## $.*.*.$ ##',
' # $.*.$ #',
' ### $.$ ###',
' ## $ ##',
' # @ #',
' #####']
Solution[Solution.length] = 'ruUrUrruUrUrruulLuLuulLuLuulldDlDlldDlDllddrRdRddrRdRddrruururruulUlUdrdrrurruulluluulldLdLruruuluullddldllddrDrDululldllddrrdrddrruRuRlUddldlluululluurrurrdrdRdddlddrUdddrruuLrddlUlUlulluRdrdrdrrururruululLLrrrdrddlldldllulululululluurrRlllddrUluRRuruurDururuurrddrddldldLdDrrrrdrruLLdrddlUruurrruulDrdLLruululuulldldldlddrrRllluurDldRRuluuruUUdddlddrUUUruulDDurrrdLrdrdrddldlddlldldllulululululuururuurruruurrDDDuuulldRurDD';
Map[Map.length] = [
' ####',
' # ##',
' ## $####',
' ###. . #',
' #### $ # $ #',
' # # . .####',
' ## $####$ # ##',
'###. . $. $# $####',
'# $ # $ **.#. . #',
'# . .#.** $ # $ #',
'####$ #$ .$ . .###',
' ## # $####$ ##',
' ####. . # #',
' # $ # $ ####',
' # . .###',
' ####$ ##',
' ## @#',
' ####']
Solution[Solution.length] = '';
</script>