In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: Megasokoban

This fork adds the official Sokoban skin, 
counts your moves and tells you when you win.

The game features 16579 levels from
http://www.sourcecode.se/sokoban/levels.php

At the rate of five minutes per level, it
would take you two months of non-stop playing
to beat them all :)

Controls: 
- HJKL, WASD or arrows.
- Numpad +/- to zoom in/out

Have fun!
Get Adobe Flash player
by elsassph 10 Oct 2010
  • Forked from makc3d's Megasokoban
  • Diff: 305
  • Related works: 5
  • Talk

    makc3d at 10 Oct 2010 02:45
    zip2.readBytes (zip1, zip1.length) copies zip2 into zip1, no?
    makc3d at 10 Oct 2010 02:52
    also without that ";" skip loop you're making bogus empty levels )
    elsassph at 10 Oct 2010 03:06
    Oh you're right about the levels - not sure what I had in mind. What's this skip loop? An example?
    makc3d at 10 Oct 2010 03:11
    check "diff" link, I probably added it after your fork.
    makc3d at 10 Oct 2010 03:12
    (it skips multiple ";" lines after each level; initially I thought there's only one such line)
    elsassph at 10 Oct 2010 03:17
    Ok I applied your fix.

    Tags

    Embed
/**
 * Copyright elsassph ( http://wonderfl.net/user/elsassph )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/n0KB
 */

// This fork adds the official Sokoban skin, 
// counts your moves and tells you when you win.
//
// The game features 16579 levels from
// http://www.sourcecode.se/sokoban/levels.php
//
// At the rate of five minutes per level, it
// would take you two months of non-stop playing
// to beat them all :)
//
// Controls: 
// - HJKL, WASD or arrows.
// - Numpad +/- to zoom in/out
//
// Have fun!
package {
    import com.bit101.components.Label;
    import com.bit101.components.List;
    import com.bit101.components.Panel;
    import com.bit101.components.ProgressBar;
    import com.bit101.components.TextArea;
    import flash.display.*;
    import flash.events.*;
    import flash.geom.Matrix;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.utils.ByteArray;
    import flash.utils.setTimeout;
    import mx.utils.Base64Decoder;
    
    [SWF(width=465,height=465)]
    public class Sokoban extends Sprite {
        private var T:int = 16;
        private var s:Array;
        private var b:Array,f:Array,v:Array,wa:Array;
        private var u:int,w:int;

        private var progress:ProgressBar;
        private var list1:List;
        private var list2:List;
        private var info:TextArea;
        private var zip1:ByteArray = new ByteArray;
        private var zip2:ByteArray = new ByteArray;
        private var skin:BitmapData;
        private var defs:Object;
        private var rows:int;
        private var cols:int;
        private var infoPanel:Panel;
        private var moves:int = 0;
        
        public function Sokoban () {
            progress = new ProgressBar (this, 100, 300);
            progress.width = 265;

            loadSkin();
        }
        
        private function loadSkin():void 
        {
            var loader:URLLoader = new URLLoader();
            loader.dataFormat = "binary";
            loader.addEventListener (ProgressEvent.PROGRESS, onProgress0);
            loader.addEventListener(Event.COMPLETE, skin_complete);
            loader.load(new URLRequest(/*"skin.gif"*/"http://assets.wonderfl.net/images/related_images/d/df/df99/df999684a5544c7d7b8571e4e19205e3de08c1fd"));
        }
        private function skin_complete(e:Event):void 
        {
            var loader:URLLoader = URLLoader(e.target);
            var ba:ByteArray = ByteArray(loader.data);
            ba.position = 2305;
            var zip:ByteArray = new ByteArray();
            ba.readBytes(zip, 0);
            zip.uncompress();
            
            var src:Array = String(zip.readUTFBytes(zip.length)).split(/\[[A-Z]+\]/);
            var lines:Array = src[2].split(/[\r\n]+/);
            defs = { };
            for each(var line:String in lines) {
                var p:Array = line.split(/\s*=\s*/);
                if (p[0].length) defs[p[0]] = parseInt(p[1]);
            }
            
            var rawImg:String = src[3];
            var dec:Base64Decoder = new Base64Decoder();
            dec.decode(rawImg);
            ba = dec.toByteArray();
            var img:Loader = new Loader();
            img.loadBytes(ba);
            img.contentLoaderInfo.addEventListener(Event.COMPLETE, skin_loaded);
        }
        private function skin_loaded(e:Event):void 
        {
            skin = (e.target.content as Bitmap).bitmapData;
            loadLevels();
        }
        
        private function loadLevels():void {
            var loader:URLLoader = new URLLoader;
            loader.dataFormat = "binary";
            loader.addEventListener (ProgressEvent.PROGRESS, onProgress1);
            loader.addEventListener (Event.COMPLETE, onComplete1);
            loader.load (new URLRequest (/*"levels_1.gif"*/"http://assets.wonderfl.net/images/related_images/d/db/db35/db35aa47d5233b80ac22d4548a27e9770f8b3c8d"));
        }
        private function onProgress0 (e:ProgressEvent):void {
            progress.value = 0.33 * e.bytesLoaded / e.bytesTotal;
        }
        private function onProgress1 (e:ProgressEvent):void {
            progress.value = 0.33 * e.bytesLoaded / e.bytesTotal + 0.33;
        }
        private function onProgress2 (e:ProgressEvent):void {
            progress.value = 0.33 * e.bytesLoaded / e.bytesTotal + 0.66;
        }
        private function onComplete1 (e:Event):void {
            var loader:URLLoader = URLLoader (e.target);
            loader.removeEventListener (ProgressEvent.PROGRESS, onProgress1);
            loader.removeEventListener (Event.COMPLETE, onComplete1);
            ByteArray (loader.data).position = 2305;
            ByteArray (loader.data).readBytes (zip1, 0);
            zip1.uncompress ();

            loader = new URLLoader;
            loader.dataFormat = "binary";
            loader.addEventListener (ProgressEvent.PROGRESS, onProgress2);
            loader.addEventListener (Event.COMPLETE, onComplete2);
            loader.load (new URLRequest (/*"levels_2.gif"*/"http://assets.wonderfl.net/images/related_images/8/80/804d/804ddc40164b123939dfc729483def6d22d41584"));
        }
        private function onComplete2 (e:Event):void {
            var loader:URLLoader = URLLoader (e.target);
            loader.removeEventListener (ProgressEvent.PROGRESS, onProgress2);
            loader.removeEventListener (Event.COMPLETE, onComplete2);

            ByteArray (loader.data).position = 2305;
            ByteArray (loader.data).readBytes (zip2, 0);
            zip2.uncompress ();

            // merge
            zip2.readBytes (zip1, zip1.length);

            // parse
            setTimeout (parse, 123);
        }
        private function parse ():void {
            var lines:Array = zip1.toString ().split (/[\n\r]+/);
            var items:Array = [];
            var collection:LevelCollection = new LevelCollection;
            for (var i:int = 6; i < lines.length; i++) {
                // start parsing collection
                var line:String = String (lines [i]);
                if (line == "") line = ";";
                if (line.charAt (0) == ";") {
                    var line1:String = line.substr (1);
                    if (collection.label == "")
                        collection.label = line1;
                    collection.description += line1 + "\n";
                } else {
                    // this is 1st line of level 1
                    while (line.charAt (0) != "<") {
                        var level:Level = new Level;
                        while (line.charAt (0) != ";") {
                            if (line != "")
                                level.map.push (line);
                            i++; line = String (lines [i]);
                        }
                        level.label = line.substr (1);
                        collection.levels.push (level);
                        while (line.charAt (0) == ";") {
                            // skip other ;-ed lines
                            i++; line = String (lines [i]);
                        }
                    }
                    items.push (collection);
                    collection = new LevelCollection;
                    // skip to next html, if any
                    i += 8;
                }
            }

            // set up basic ui
            removeChild (progress);
            list1 = new List (this, 0, 365);
            list2 = new List (this, list1.width, 365);
            info = new TextArea (this, list1.width * 2, 365);
            info.editable = false; info.width = 465 - info.x;

            list1.items = items;

            list1.addEventListener (Event.SELECT, onSelect1);
            list2.addEventListener (Event.SELECT, onSelect2);

            stage.addEventListener (KeyboardEvent.KEY_DOWN, onKeyDown);
        }
        private function onSelect1 (e:Event):void {
            // show collection info
            info.text = LevelCollection (list1.selectedItem).description;
            // show levels list
            list2.items = LevelCollection (list1.selectedItem).levels;
        }
        private function onSelect2 (e:Event):void {
            if (infoPanel) { removeChild(infoPanel); infoPanel = null; }
            moves = 0;
            s = Level (list2.selectedItem).map;
            b = []; f = []; 
            rows = s.length;
            cols = 0;
            for (var j:int = 0; j < rows; ++j) {
                b[j] = [];
                f[j] = [];
                var l:String = s[j];
                if (cols < l.length) cols = l.length;
                for (var i:int = 0; i < l.length; ++i) {
                    switch (l.charAt(i)) {
                    case '#':
                        b[j][i] = 1;
                        break;
                    case '.':
                        b[j][i] = 2;
                        break;
                    case '$':
                        f[j][i] = 3;
                        break;
                    case '@':
                        f[j][i] = 4;
                        u = i;
                        w = j;
                        break;
                    case '*':
                        b[j][i] = 2;
                        f[j][i] = 3;
                        break;
                    case '+':
                        b[j][i] = 2;
                        f[j][i] = 4;
                        u = i;
                        w = j;
                        break;
                    default:
                        b[j][i]=f[j][i]=0;
                    }
                }
            }
            
            var cpt:int = 0;
            wa = [];
            for (j = 0; j < rows; ++j) {
                wa[j] = [];
                for (i = 0; i < cols; ++i) {
                    if (b[j][i] != 1) continue;
                    var n:int = 0;
                    if (j > 0 && b[j - 1][i] == 1) n = 1;
                    if (b[j][i + 1] == 1) n += 2;
                    if (j < rows - 1 && b[j + 1][i] == 1) n += 4;
                    if (i > 0 && b[j][i - 1] == 1) n += 8;
                    wa[j][i] = n.toString(16).toUpperCase();
                }
            }
            T = int(Math.min (25, Math.min(365 / rows, 465 / cols)));
            redraw();
        }
        private function onKeyDown (e:KeyboardEvent):void {
            if (list2.selectedItem == null) return;
                v = null;
                switch (e.keyCode) {
                case 72: // H
                case 37: // left
                case 65: // A
                    v = [-1,0];
                    break;
                case 74: // J
                case 40: // down
                case 83: // S
                    v = [0,1];
                    break;
                case 75: // K
                case 38: // up
                case 87: // W
                    v = [0,-1];
                    break;
                case 76: // L
                case 39: // right
                case 68: // D
                    v = [1,0];
                    break;
                case 107: // +
                    T++;
                    break;
                case 109: // -
                    T--;
                    break;
                }
                if (v) {
                    var s:String="";
                    for(var i:int=u,j:int=w;0<=j&&j<b.length&&0<=i&&i<b[j].length;i+=v[0],j+=v[1])
                        s+=int(f[j][i]?f[j][i]:b[j][i]);
                    if (s.search(/[02]/)==1)
                        move(v);
                    if (s.search(/3[02]/)==1){
                        move(v);
                        f[w + v[1]][u + v[0]] = 3;
                    }
                }
                redraw();
        }

        private function move(v:Array):void {
            f[w][u] = 0;
            u += v[0];
            w += v[1];
            f[w][u] = 4;
            moves ++;
        }

        private function redraw():void {
            graphics.clear();
            var s:Number = T / skin.height;
            var m:Matrix = new Matrix();
            var finished:Boolean = true;
            for (var j:int = 0; j < rows; ++j) {
                for (var i:int = 0; i < cols; ++i) {
                    var tex:String = null;
                    switch (f[j][i]?f[j][i]:b[j][i]) {
                    case 1:
                        tex = "Wall_" + wa[j][i];
                        break;
                    case 2:
                        tex = "Goal";
                        break;
                    case 3:
                        tex = b[j][i] == 2 ? "Pack_Goal" : "Pack";
                        if (tex == "Pack") finished = false;
                        break;
                    case 4:
                        tex = b[j][i] == 2 ? "Man_Goal" : "Man";
                       break;
                    default: tex = "Floor";
                    }
                    if (!(tex in defs)) tex = "Floor";
                    var idx:int = defs[tex];
                    var cx:int = i * T;
                    var cy:int = j * T;
                    m.identity(); m.scale(s, s); 
                    m.translate(cx - idx * T, cy);
                    graphics.beginBitmapFill(skin, m, false, true);
                    graphics.drawRect(cx, cy, T, T);
                    graphics.endFill();
                }
            }
            
            if (finished && !infoPanel)
            {
                infoPanel = new Panel(this, 100, 150);
                infoPanel.setSize(265, 65);
                var l:Label = new Label(infoPanel, 20, 25, "Congratulations, you solved it in " + moves + " moves!");
                l.x = (265 - l.width) / 2;
                setTimeout(function ():void { infoPanel.visible = false; }, 3000);
            }
        }
    }
}

class Level {
    public var label:String = "";
    public var map:Array = [];
}

class LevelCollection {
    public var label:String = "";
    public var levels:Array = [];
    public var description:String = "";
}