commit a67dccf08719d55513410a26f447532330fb5f18
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sat Jul 16 11:47:50 2022 +0200

    Init commit of the new version with refreshed UI

diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..5a7c7fc
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,25 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+    repositories {
+        google()
+        mavenCentral()
+    }
+    dependencies {
+        classpath "com.android.tools.build:gradle:4.2.2"
+
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        mavenCentral()
+        jcenter() // Warning: this repository is going to shut down soon
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/distorted-sokoban/build.gradle b/distorted-sokoban/build.gradle
new file mode 100644
index 0000000..1629bb9
--- /dev/null
+++ b/distorted-sokoban/build.gradle
@@ -0,0 +1,19 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 31
+    buildToolsVersion "30.0.3"
+
+    defaultConfig {
+        applicationId "com.threedcell.sokoban"
+        minSdkVersion 7
+        targetSdkVersion 31
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
+        }
+    }
+}
diff --git a/distorted-sokoban/src/main/AndroidManifest.xml b/distorted-sokoban/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..cbe87e6
--- /dev/null
+++ b/distorted-sokoban/src/main/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.threedcell.sokoban"
+    android:versionCode="7"
+    android:versionName="1.2.10" >
+
+    <supports-screens android:smallScreens="true" 
+                        android:normalScreens="true" 
+                        android:largeScreens="true" 
+                        android:anyDensity="true"/>
+    
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-feature android:name="android.hardware.touchscreen"/>
+    
+    <application android:icon="@drawable/icon" android:label="@string/app_name">
+        <activity android:name=".Sokoban"
+                  android:label="@string/app_name"
+                  android:screenOrientation="portrait"
+                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+                  android:noHistory="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".SokobanMain"
+                  android:screenOrientation="portrait"
+                  android:label="@string/app_name"
+                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+                  android:finishOnTaskLaunch="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/Sokoban.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/Sokoban.java
new file mode 100644
index 0000000..2dc5dfe
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/Sokoban.java
@@ -0,0 +1,99 @@
+package com.threedcell.sokoban;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+///////////////////////////////////////////////////////////////////
+
+public class Sokoban extends Activity 
+{
+	private static final String TAG_SPLASH = "SokobanSplash";
+    public static final boolean DEBUG = false;
+    private int sleepTime=2000;
+    
+    private class SplashThread extends Thread
+    {
+    	private boolean bootup=true;
+		
+		public void run() 
+		{
+			int milis=0;
+			
+			while(bootup)
+			{
+				try
+				{
+					milis+=100;
+					Thread.sleep(100);
+				}
+				catch( InterruptedException ex) {}
+			}
+			
+			if( milis<sleepTime )
+			{
+				try
+				{
+					Thread.sleep(sleepTime-milis);
+				}
+				catch( InterruptedException ex) {}
+			}
+			finish();
+			Intent mainInt = new Intent( getApplicationContext(), SokobanMain.class);     
+			startActivity(mainInt);
+		}
+		public void bootupReady()
+		{
+			bootup=false;
+		}
+    };
+    
+///////////////////////////////////////////////////////////////////
+	
+    public void onCreate(Bundle savedInstanceState) 
+    {
+    	Log.d( TAG_SPLASH, "onCreate");
+    	
+    	super.onCreate(savedInstanceState);
+        
+        if( getResources().getInteger(R.integer.is_korean) == 1 )
+  	      {
+  	      setContentView(R.layout.grb);
+          sleepTime=3500;  	
+  	      }
+  	    else
+  	      {
+  	      setContentView(R.layout.splash);
+          sleepTime=2000;  		
+  	      }
+    }
+
+///////////////////////////////////////////////////////////////////
+
+    public void onStart()
+    {
+    	Log.d( TAG_SPLASH, "onStart");
+    	
+    	super.onStart();
+    	
+    	SplashThread splashThread = new SplashThread();
+    	splashThread.start();
+    	
+    	SokobanLevels.init(this);
+        SokobanLevels sl = SokobanLevels.getInstance();
+        
+    	SokobanCanvas.init(this);
+    	SokobanCanvas.setActivity(this);
+    	
+    	SokobanDatabase.init(this);
+        SokobanTimer.init();
+        SokobanCanvas.setLevels(sl);
+        SokobanRecords.setLevels(sl);
+    	
+        splashThread.bootupReady();
+    }
+
+///////////////////////////////////////////////////////////////////
+// end of file
+}
\ No newline at end of file
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanCanvas.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanCanvas.java
new file mode 100644
index 0000000..5c5bea4
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanCanvas.java
@@ -0,0 +1,538 @@
+package com.threedcell.sokoban;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.telephony.TelephonyManager;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+
+///////////////////////////////////////////////////////////////////
+
+public class SokobanCanvas extends SurfaceView implements SurfaceHolder.Callback
+{
+	private static final String TAG_CANVAS = "SokobanCanvas";
+	private static String strEmail, strName;
+	
+	public static final int STATE_MAIN = 1;
+    public static final int STATE_PLAY = 2;
+      public static final int STATE_TIME =3;
+      public static final int STATE_NEWR =4;
+        public static final int STATE_SUBM = 5;
+          public static final int STATE_FAIL = 6; 
+          public static final int STATE_RECO = 7; 
+          public static final int STATE_EXIS = 8;
+          public static final int STATE_SECU = 9;
+        public static final int STATE_NAME = 10;
+    public static final int STATE_MENU = 11;
+      public static final int STATE_DOWN = 12;
+        public static final int STATE_FAID = 13;
+        public static final int STATE_SUCD = 14;
+      public static final int STATE_DOWL = 15;
+        public static final int STATE_FAIE = 16;
+        public static final int STATE_SUCE = 17;
+      public static final int STATE_CREA = 18;
+        public static final int STATE_CRED = 19;
+          public static final int STATE_CRES = 20;
+            public static final int STATE_SUBC = 21;
+              public static final int STATE_FAIC = 22;
+              public static final int STATE_SUCC = 23;
+      public static final int STATE_HELP = 24;
+
+  	public  static final int COLOR_BAR   = 0xfffde051;
+  	public  static final int COLOR_BLACK = 0xff000000;
+  	public  static final int COLOR_RED   = 0xffff0000;
+  	public  static final int COLOR_GREY  = 0xff444444;
+  	public  static final int COLOR_WHITE = 0xffffffff;
+  	public  static final int COLOR_DIALOG= 0xff447da7;
+
+  	private static final int FRAME_INTERVAL = 70;
+
+    private static int currState = STATE_MAIN;
+    private static int scrWidth, scrHeight;
+
+    private static SokobanMenu    mMenu;
+    private static SokobanLevels  mLevels;
+    private static SokobanRecords mRecords;
+    private static Activity       mAct;
+    private static SokobanCanvas  mCanvas;
+    
+	private static boolean mDestroy = true;
+	private static boolean refreshScreen = true;
+	private static boolean mFinishedBooting=false;  
+	private GraphicsThread mThread;
+	public  static String mVersionStr="";
+	private Paint mPaint = new Paint();
+	private static int isKorean;
+	
+    private class GraphicsThread extends Thread 
+    {
+        private SurfaceHolder mSurfaceHolder;
+        private SokobanCanvas mCanvas;
+        private boolean mRun = false;
+     
+        public GraphicsThread(SurfaceHolder surfaceHolder, SokobanCanvas c) 
+        {
+            mSurfaceHolder = surfaceHolder;
+            mCanvas = c;
+        }
+     
+        public void setRunning(boolean run) 
+        {
+            mRun = run;
+        }
+     
+        public void run() 
+          {	
+          Canvas c;
+          long time;
+        	
+          while (mRun) 
+            {
+            c = null;
+            time = 0;
+                
+            if( refreshScreen && mFinishedBooting )
+              {
+              refreshScreen=false;	
+              time = System.currentTimeMillis();
+                  
+              try 
+                {
+                c = mSurfaceHolder.lockCanvas(null);
+                synchronized (mSurfaceHolder) { mCanvas.drawSurface(c); }
+                } 
+              finally 
+                {
+                if (c != null)  mSurfaceHolder.unlockCanvasAndPost(c);
+                }
+              
+              time = System.currentTimeMillis() -time;
+              }
+                
+            if( time<FRAME_INTERVAL )
+              {
+              try { Thread.sleep(FRAME_INTERVAL-time); }
+              catch(InterruptedException ex) {}
+              }
+            }
+          }
+    };
+    
+///////////////////////////////////////////////////////////////////
+	
+	private SokobanCanvas(Context context)
+	{		
+		super(context);
+		  
+	    try 
+	      {
+	      PackageManager pm = context.getPackageManager();   
+	      PackageInfo pi =  pm.getPackageInfo( "com.threedcell.sokoban", 0);
+	      mVersionStr = pi.versionName;
+	      } 
+	    catch (NameNotFoundException e)  { }
+	    
+	    mMenu   = new SokobanMenu(context,this);    
+	    mRecords= new SokobanRecords();
+	    
+	    mPaint.setColor(SokobanLevels.COLOR_BLACK);
+	    mPaint.setStyle(Style.FILL);
+	    
+	    getHolder().addCallback(this);
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+	    
+        strEmail = context.getString(R.string.email);
+        strName  = context.getString(R.string.app_name);
+        
+        mFinishedBooting=true;
+	}
+	
+
+///////////////////////////////////////////////////////////////////
+
+	public synchronized void deallocate()
+	{
+		stopThread();
+		
+	}
+
+///////////////////////////////////////////////////////////////////
+	
+	public static void setActivity(Activity act)
+	{
+		mAct = act;
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public Activity getActivity()
+	{
+		return mAct;
+	}
+	
+///////////////////////////////////////////////////////////////////
+	
+	public static void init(Activity act)
+	{
+		Log.d(TAG_CANVAS, "init");
+		
+		Resources res = act.getResources();
+		isKorean = res.getInteger(R.integer.is_korean);
+		
+	    if( scrWidth<=0 || scrHeight<=0 )
+		  {
+		  DisplayMetrics dm = new DisplayMetrics();
+		  act.getWindowManager().getDefaultDisplay().getMetrics(dm);
+		  
+		  scrWidth = Math.min(dm.widthPixels,dm.heightPixels);
+		  scrHeight= Math.max(dm.widthPixels,dm.heightPixels);
+		  }
+		
+		if( mCanvas==null ) mCanvas = new SokobanCanvas((Context)act);
+	}
+	
+///////////////////////////////////////////////////////////////////
+	
+	public static SokobanCanvas getCanvas(Activity act)
+	{
+		init(act);
+		return mCanvas;
+	}
+	
+///////////////////////////////////////////////////////////////////
+
+	public static boolean isCreated()
+	{
+		return mCanvas!=null;
+	}
+	
+///////////////////////////////////////////////////////////////////
+
+	public int getScrWidth()
+	{
+		return scrWidth;
+	}
+	
+///////////////////////////////////////////////////////////////////
+
+	public int getScrHeight()
+	{
+		return scrHeight;
+	}
+	
+///////////////////////////////////////////////////////////////////
+	
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) 
+    {
+    	Log.e( TAG_CANVAS, "surfaceChanged: width="+w+" height="+h);   
+    	
+    	int width  = Math.min(w,h);
+    	int height = Math.max(w,h);
+    	
+    	if( mMenu  !=null ) mMenu.setScrDimensions(width,height);
+    	if( mLevels!=null) mLevels.setScrDimensions(width,height);
+    	
+    	scrWidth = width;
+    	scrHeight= height;
+   	    refreshScreen = true;
+    }
+ 
+///////////////////////////////////////////////////////////////////
+
+    public void surfaceCreated(SurfaceHolder holder) 
+    {
+    	Log.e( TAG_CANVAS, "surfaceCreated");
+    	
+    	mThread = new GraphicsThread(getHolder(), this);
+    	mThread.setRunning(true);
+        mThread.start();
+    }
+
+///////////////////////////////////////////////////////////////////
+    
+    public void surfaceDestroyed(SurfaceHolder holder) 
+    {
+    	Log.e( TAG_CANVAS, "surfaceDestroyed");
+    	      
+        stopThread();
+        mRecords.setDirty();
+    }
+
+///////////////////////////////////////////////////////////////////
+
+    private void stopThread()
+    {
+        if( mThread!=null )
+        {
+        	boolean retry = true;
+        	mThread.setRunning(false);
+        
+        	while (retry) 
+        	{
+        		try 
+        		{
+        			mThread.join();
+        			retry = false;
+        		} 
+        		catch (InterruptedException e) { Log.e( TAG_CANVAS, "Joining thread interrupted!"); }
+        	}
+        	mThread=null;
+        }
+    }
+
+///////////////////////////////////////////////////////////////////
+
+    public static void setLevels(SokobanLevels sl)
+    {
+    	mLevels = sl;    
+    }
+
+///////////////////////////////////////////////////////////////////
+
+    public SokobanRecords getRecords()
+    {
+    	return mRecords;
+    }
+
+///////////////////////////////////////////////////////////////////
+    
+	protected void onDraw(Canvas c)
+	{
+	drawSurface(c);
+	}
+
+///////////////////////////////////////////////////////////////////
+
+  private void drawSurface(Canvas c)
+		{
+	  if( c!=null )
+		  {
+			if( mLevels!=null ) mLevels.render(currState,c);
+			if( mMenu  !=null ) mMenu.render(currState,c);
+		  }
+		}
+
+///////////////////////////////////////////////////////////////////
+
+    public static void setRepaint()
+    {
+    	refreshScreen=true;
+    }
+   
+///////////////////////////////////////////////////////////////////
+
+	public boolean onKeyDown( int keyCode, KeyEvent event)
+	{
+		if( mMenu==null || mLevels==null ) return false;
+	         
+		switch(keyCode)
+		{
+		case KeyEvent.KEYCODE_MENU: mMenu.setPointerState(currState,  scrWidth/4,scrHeight,true);
+			 					    refreshScreen = true;
+			  					    break;
+		case KeyEvent.KEYCODE_BACK: mMenu.setPointerState(currState,3*scrWidth/4,scrHeight,true);	
+		  		                    refreshScreen = true;
+		                            break;                     
+		}
+		  
+		if( currState==STATE_PLAY || currState==STATE_CREA || currState==STATE_CRES )
+		{
+			switch(keyCode)
+			{
+			case KeyEvent.KEYCODE_DPAD_UP   : mLevels.keyboardMovePlayer(currState,1);
+			  		                          refreshScreen = true; 
+			  		                          break;
+			case KeyEvent.KEYCODE_DPAD_DOWN : mLevels.keyboardMovePlayer(currState,3);
+			                                  refreshScreen = true; 
+			                                  break;
+			case KeyEvent.KEYCODE_DPAD_LEFT : mLevels.keyboardMovePlayer(currState,4);
+			                                  refreshScreen = true; 
+			                                  break;
+			case KeyEvent.KEYCODE_DPAD_RIGHT: mLevels.keyboardMovePlayer(currState,2);
+			                                  refreshScreen = true; 
+			                                  break;
+			}
+		}
+		  
+		return true;
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	  public boolean onKeyUp( int keyCode, KeyEvent event)
+	  {
+		  if( mMenu==null ) return false;
+		  
+		  switch(keyCode)
+		  {
+		  case KeyEvent.KEYCODE_MENU: mMenu.tryPress(currState,  scrWidth/4,scrHeight);
+								      refreshScreen = true;
+				  					  break;
+		  case KeyEvent.KEYCODE_BACK: mMenu.tryPress(currState,3*scrWidth/4,scrHeight);
+			  		                  refreshScreen = true;
+			                          break;                     
+		  }
+		  
+		  return true;
+	  }
+	  
+///////////////////////////////////////////////////////////////////
+
+	  public boolean onTouchEvent(MotionEvent event)
+	  {
+		  int action = event.getAction();
+
+		  switch(action)
+		  {
+		  case MotionEvent.ACTION_DOWN: pointerPressed( (int)event.getX(), (int)event.getY() );
+		  								break;
+		  case MotionEvent.ACTION_UP  : pointerReleased((int)event.getX(), (int)event.getY() );
+		  								break;
+		  case MotionEvent.ACTION_MOVE: pointerDragged( (int)event.getX(), (int)event.getY() );
+		  								break;
+		  }
+
+		  return true;
+	  }
+
+///////////////////////////////////////////////////////////////////
+
+	private void pointerPressed(int x, int y)
+	{
+		if( mLevels==null || mMenu==null ) return;    
+         
+		mMenu.setPointerState(currState,x,y,true);
+		if( currState==STATE_PLAY || currState==STATE_MAIN || currState==STATE_SUCD || currState==STATE_CREA || currState==STATE_CRES )
+			mLevels.click(currState,x,y);
+
+		refreshScreen = true;
+	}
+	
+///////////////////////////////////////////////////////////////////
+
+	private void pointerReleased(int x, int y)
+	{
+		if( mLevels==null || mMenu==null ) return;    
+         
+		mMenu.tryPress(currState,x,y);
+		if( currState==STATE_PLAY || currState==STATE_MAIN || currState==STATE_SUCD || currState==STATE_CREA || currState==STATE_CRES )
+			mLevels.unclick(currState,x,y);
+
+		refreshScreen = true;
+	}
+	
+///////////////////////////////////////////////////////////////////
+
+	private void pointerDragged(int x, int y)
+	{
+		if( mLevels==null || mMenu==null ) return;    
+	        
+		mMenu.setPointerState(currState,x,y,false);
+		if( currState==STATE_PLAY || currState==STATE_MAIN || currState==STATE_SUCD || currState==STATE_CREA || currState==STATE_CRES )
+			mLevels.drag(currState,x,y);
+
+		refreshScreen= true;
+	}
+	
+///////////////////////////////////////////////////////////////////
+
+	  
+	public static String getIso()
+	{
+		if( isKorean==1 )
+		  {
+		  return "kr";
+		  }
+		else
+		  {
+          String ret="";
+		
+		  TelephonyManager tM =((TelephonyManager) mAct.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE));
+		
+		  if( tM!=null )
+	        {
+		    ret = tM.getSimCountryIso();
+		  
+		    if( ret==null || ret.length()<=1 )
+		      {
+			  ret = tM.getNetworkCountryIso();  
+		      }
+		    }
+		
+		  return ret;
+		  }		
+	}
+	
+///////////////////////////////////////////////////////////////////
+
+	public static void setDestroy(boolean d)
+	{
+		mDestroy = d;
+	}
+	
+///////////////////////////////////////////////////////////////////
+
+	public static boolean getDestroy()
+	{
+		return mDestroy;
+	}
+		   
+
+///////////////////////////////////////////////////////////////////
+
+	public void sendMail()
+	{
+		try
+		  {
+		  mDestroy = false;	
+		  final Intent email = new Intent(android.content.Intent.ACTION_SEND);
+		  email.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+		  email.setType("message/rfc822");
+		  email.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{strEmail});
+		  email.putExtra(android.content.Intent.EXTRA_SUBJECT, strName+" v."+mVersionStr);
+		  mAct.startActivity(Intent.createChooser(email, "Send mail..."));
+		  }
+		catch( Exception ex )
+		  {
+		  Log.e( TAG_CANVAS, "No email application!");		
+		  }
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public static void setState(int state)
+	{
+		currState = state;
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public static int getState()
+	{
+		return currState;
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public static SokobanMenu getMenu()
+	{
+		return mMenu;
+	}
+
+///////////////////////////////////////////////////////////////////
+// end of SokobanCanvas
+}
\ No newline at end of file
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanDatabase.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanDatabase.java
new file mode 100644
index 0000000..b502044
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanDatabase.java
@@ -0,0 +1,1441 @@
+package com.threedcell.sokoban;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.provider.Settings.Secure;
+import android.util.Log;
+import android.app.Activity;
+
+import java.util.Map;
+
+///////////////////////////////////////////////////////////////////
+
+public class SokobanDatabase 
+{ 
+	private static final String TAG_DB = "SokobanDatabase";
+	private static final String PREFS_NAME = "sokobanPrefsFile";	
+	
+	public static final int BEGIN_LEVELS = 1000;
+	public static final int INVALID = 1000000;
+
+	private static int numrunnings;
+	private static int numplayings;
+	private static int hash;
+	private static String username;
+	private static String veriname;
+	private static int uniqueid;
+	private static int scrollpos;
+	private static boolean finishedBootup = false;
+	private static String iso = null;
+	 
+	private static SokobanLevels mLevels;
+	private static SokobanDatabase rms =null;
+	
+	private static Context  context;
+	
+
+	private static final String[] bl = new String[]
+	  {
+	  "4", "12001100451111311100", // tmp/microban1.1
+	  "4", "11111051134112411111", // tmp/microban1.2
+	  "4", "0111010211111112010003350111", // tmp/microban1.3
+	  "4", "111012101410141013111511", // tmp/microban1.4
+	  "5", "000111111112321135311232111111", // tmp/microban1.5
+	  "4", "1111133113111100012001200120111010101510", // tmp/microban1.6
+	  "5", "111111232113231123211323111511", // tmp/microban1.7
+	  "6", "001225001331000100000100000100000100111100101110111010001110", // tmp/microban1.8
+	  "4", "21105331011100110002", // tmp/microban1.9
+	  "6", "000111000501000111000301000111000301222111100300111100", // tmp/microban1.10
+	  "6", "000111000211111210100010101110153310001110", // tmp/microban1.11
+	  "6", "110000131000113011011511000221000101000111", // tmp/microban1.12
+	  "5", "21000251002130003100013110111101100", // tmp/microban1.13
+	  "4", "11211011113110401150", // tmp/microban1.14
+	  "5", "01100011000110001000021315410101111", // tmp/microban1.15
+	  "6", "000211111111110212010000011111011531001331000011", // tmp/microban1.16
+	  "4", "15102220333011111111", // tmp/microban1.17
+	  "5", "11111212111001011310003100051000110", // tmp/microban1.18
+	  "6", "111221115331000010000110000110000110", // tmp/microban1.19
+	  "6", "110000110000150111131111130100020100021100", // tmp/microban1.20
+	  "4", "11101231013102010151", // tmp/microban1.21
+	  "5", "11100212111110101011053310111101100", // tmp/microban1.22
+	  "5", "1141111111010100352001110", // tmp/microban1.23
+	  "5", "0011100335111001111112121", // tmp/microban1.24
+	  "5", "0110001331022211153111100", // tmp/microban1.25
+	  "4", "015101110031122213310011", // tmp/microban1.26
+	  "5", "1112010010113351011121100", // tmp/microban1.27
+	  "5", "1110015100133000212101111", // tmp/microban1.28
+	  "7", "000011100013010001101000130100011011101501111010111121210111000", // tmp/microban1.29
+	  "4", "11001331222115311110", // tmp/microban1.30
+	  "5", "0011005320133111212100111", // tmp/microban1.31
+	  "5", "0110011111244351110001100", // tmp/microban1.32
+	  "5", "2101111311213051131121011", // tmp/microban1.33
+	  "4", "0151013111411141014101210111", // tmp/microban1.34
+	  "5", "0011002130023100231002310021300111500111", // tmp/microban1.35
+	  "3", "111132012032012032011031011031011051011", // tmp/microban1.36
+	  "6", "011100011300011100003100001351000101222111", // tmp/microban1.37
+	  "5", "1111010020101101235010331101011020111111", // tmp/microban1.38
+	  "7", "11101111010101111111100100000133500021210000011000001100", // tmp/microban1.39
+	  "4", "00111132113611320011", // tmp/microban1.40
+	  "4", "151013111301132111210020", // tmp/microban1.41
+	  "5", "000110005100032111321013211110", // tmp/microban1.42
+	  "7", "0000015000001100000121113112113301211110000011000", // tmp/microban1.43
+	  "1", "532", // tmp/microban1.44
+	  "4", "22211131103011311151", // tmp/microban1.45
+	  "5", "011111100110131114120105001110", // tmp/microban1.46
+	  "5", "011110305111011130201111011020110110001100011", // tmp/microban1.47
+	  "6", "115100110100120110123331120111000111", // tmp/microban1.48
+	  "6", "151100130100131100131000001000011011022211011111", // tmp/microban1.49
+	  "5", "0110001300131111110101101051010200102111", // tmp/microban1.50
+	  "5", "111001110001311014210050100111", // tmp/microban1.51
+	  "4", "001511311142114211310011", // tmp/microban1.52
+	  "5", "0212014141110111313101510", // tmp/microban1.53
+	  "6", "000110000351001131001131000311000100110110122220111110111000", // tmp/microban1.54
+	  "6", "110000510000110000010000113131111111000020000020", // tmp/microban1.55
+	  "4", "11001141131101210115", // tmp/microban1.56
+	  "6", "001100005100001100001000111141113111000021", // tmp/microban1.57
+	  "5", "1100024311123010151101110", // tmp/microban1.58
+	  "7", "11111001000300101131010111101013000101100010110001011011111002115111210011121", // tmp/microban1.59
+	  "8", "0111111105000001110111011101113211003002030011021113110211101100", // tmp/microban1.60
+	  "7", "11111101000010102225010003001011111113313100011100002000", // tmp/microban1.61
+	  "4", "01110111031113101310121012000200020013101510", // tmp/microban1.62
+	  "4", "11001100111101110100010001000300111121210030001000100010001100510011", // tmp/microban1.63
+	  "7", "01100001110000113100013322221110011000011000005300000110", // tmp/microban1.64
+	  "7", "0011110001131000003100131310222201011111510110111", // tmp/microban1.65
+	  "7", "000500000030000112110110101110111011011101101110111010110131310002120000111000011100", // tmp/microban1.66
+	  "5", "111001011053420011210130100111", // tmp/microban1.67
+	  "5", "0011111222110050113101300031000110001100", // tmp/microban1.68
+	  "6", "111151111111000201011102011211001000111311113131000111", // tmp/microban1.69
+	  "6", "151000111111131331030011111000122110022110000110", // tmp/microban1.70
+	  "7", "11111111300001150110113111011101101000100111011011211101110110101000010211111", // tmp/microban1.71
+	  "8", "001100000113115101130111000100001101110011113100122011001120000011000000", // tmp/microban1.72
+	  "6", "110000133131111111010010222050100010111111110111", // tmp/microban1.73
+	  "6", "000110131110110311053101003111011000011000011200022200", // tmp/microban1.74
+	  "5", "0110011100211102031020131203110013100511", // tmp/microban1.75
+	  "8", "011100001111000011020111510201311102011011110110011003300011111000110000", // tmp/microban1.76
+	  "5", "110005111111031201112011020310201101331000110", // tmp/microban1.77
+	  "6", "011000113150131011113011131021113121011021000020000020", // tmp/microban1.78
+	  "4", "00111111132210301321005111111111", // tmp/microban1.79
+	  "8", "110000001121001213011112010010120111101100001011001531000013310000111100", // tmp/microban1.80
+	  "4", "0111012101411140115001310111", // tmp/microban1.81
+	  "6", "111000121110040311120131150010111110", // tmp/microban1.82
+	  "6", "111100131310013311010111010010011212015212011000", // tmp/microban1.83
+	  "8", "11100000111111112000001120151011203330101111111000111010000000110000001100000011", // tmp/microban1.84
+	  "9", "000000011013111111011131311010000000010121100110101100115121000010101000011121000", // tmp/microban1.85
+	  "6", "000111001522013022031310111310110100011100", // tmp/microban1.86
+	  "7", "00000111111111112221203000001311000111300001131100015110", // tmp/microban1.87
+	  "9", "000001100000111100000110100000310200000110100000310200000110100000310200151111100111011000", // tmp/microban1.88
+	  "7", "11000001300000110000001122220300011151111110313111110000", // tmp/microban1.89
+	  "5", "0001111011131315102211022131311101100011", // tmp/microban1.90
+	  "3", "111131131150220022031131111", // tmp/microban1.91
+	  "8", "00001100000011001110110011113000000131000003010000011100000100000001000000010000012221510101011101111100", // tmp/microban1.92
+	  "9", "011101110111101111113101311111424111000252000111424111113101311111101111011101110", // tmp/microban1.93
+	  "6", "110110533110110210030200110210111111110111", // tmp/microban1.94
+	  "6", "511111123321132231132231123321111111", // tmp/microban1.95
+	  "9", "001111000001111000000011000111020000111353111000020111000010010000111320000111000", // tmp/microban1.96
+	  "8", "001511000010131100103101113010111311111101100000031000000200000002000000020000000200000002000000", // tmp/microban1.97
+	  "8", "1110110011313100131311100110111000100000003000000010000001101110022222110000001100000111000001110000151100001110", // tmp/microban1.98
+	//"8", "0011110000111100001501000011110000111000000010000000100000002000000020000011211100112011000000100011011000111310001103101111011010110310111001100000131000001110", // tmp/microban1.99
+	  "6", "150110231110210130230111210131110111", // tmp/microban1.100
+	  "11", "0011100000000101000000001141101110001001110100111110411001010101001140361110010111001000111011411000000001010000000011100", // tmp/microban1.101
+	  "6", "211100211100205100211100011100110011130011131331111111", // tmp/microban1.102
+	  "6", "001210001311121305103121113100012100", // tmp/microban1.103
+	  "7", "0000111111131111303050010111001222100001100000110", // tmp/microban1.104
+	  "9", "011000110111010111114212411003111300011151110003111300114212411111010111011000110", // tmp/microban1.105
+	  "7", "00011001512300110210011023001102100133231111101010000111", // tmp/microban1.106
+	  "6", "111111134441141141141141144421111115", // tmp/microban1.107
+	  "6", "112120112121010501011111000110000110000110000010000110131310110110131310011100", // tmp/microban1.108
+	  "7", "00111110010101001513100100011110001131100201311020013112000130200001020000111", // tmp/microban1.109
+	  "7", "0011000001300000212111310131112120000031000001500", // tmp/microban1.110
+	  "7", "1111000111122211112220000011001101100133100015311001331100013010001111", // tmp/microban1.111
+	  "8", "0111000011333110101113101113001000110211001101110000010001110100015222200111111001110110", // tmp/microban1.112
+	  "11", "001111000000011110000001102000000111011000001021252000011101110000000003000000000111100000001111111000001333110000001110000000011000", // tmp/microban1.113
+	  "7", "111011011111311030011111023103512100110230000021000002300000210", // tmp/microban1.114
+	  "6", "011000011131010131012051112031102131112030012110011000011000", // tmp/microban1.115
+	  "5", "0011000510003100231002311123011231112100", // tmp/microban1.116
+	  "8", "000121101121201011212030010101110101331101011310111011101511030001111100", // tmp/microban1.117
+	  "8", "0111000011311000131311000030121000101211001002110151121001110110", // tmp/microban1.118
+	  "7", "00111100010011013310101531010111101000101111222101111100", // tmp/microban1.119
+	  "9", "000000110131111110130000011115011011010022111110122000131100000130000000110000000", // tmp/microban1.120
+	  "9", "012110000032010000114110000122000000031000000010000111110000101111513131011011111", // tmp/microban1.121
+	  "9", "111000000103110000131110000131310000130110000115000000010000000111111222111111111000000022", // tmp/microban1.122
+	  "9", "110000000130000000110000000130000000131313111115110111000111100000000100002120100001211110002120110001111100001100000", // tmp/microban1.123
+	  "7", "110000013111111500001130110113111011101101000100111011011211101110110112000011211111", // tmp/microban1.124
+	  "6", "000112000212000112000110000010000110110310131110110331015101000111", // tmp/microban1.125
+	  "5", "01111231012311123000231102301023110230101511011000", // tmp/microban1.126
+	  "7", "00011110111151030131011101001310110022221001301100110000", // tmp/microban1.127
+	  "6", "011000041011111011133451111010020110110100121100110000", // tmp/microban1.128
+	  "6", "011000041011111011533411111010040110121100121000111000", // tmp/microban1.129
+	  "5", "11100131001311103351010000111001111212012120111111", // tmp/microban1.130
+	  "5", "111001210025200020111131113111033110110001100", // tmp/microban1.131
+	  "6", "122000542111010101013111003100001100003110001110", // tmp/microban1.132
+	  "6", "000110110110121530210331120111210111020330011110", // tmp/microban1.133
+	  "8", "01100000011000000131111100100051001221100111113003022110010000101111311011100110", // tmp/microban1.134
+	  "5", "111101301013130101111510300111001010211202112", // tmp/microban1.135
+	  "6", "002121113201101201101111101010135330001110", // tmp/microban1.136
+	  "8", "0011100000111111000100010002120100021211000010010111511111301000131310000131000001110000", // tmp/microban1.137
+	  "9", "011111000010501000111111000112200000001211100002203131000013311000011101000011311000001100", // tmp/microban1.138
+	  "10", "01111000001111100000111110000002200000110221511031022013111100000101110000010100000001310000000011100000003310000000131000000111000000011100", // tmp/microban1.139
+	  "7", "112222011000110111101115110111111111100100000130000131000131100131100011100001100000", // tmp/microban1.140
+	  "7", "00001110000131111011111131050100100121011124423311210111", // tmp/microban1.141
+	  "7", "0011000001100000323111125211113230000011000001100", // tmp/microban1.142
+	  "7", "1100000131110012011001301000121100000010000001000000100001131100103010131513112202210011100", // tmp/microban1.143
+	  "10", "0001100000013310111001312123300122102131001044121111214401001312012210033252131001110133100000011000", // tmp/microban1.144
+	  "9", "000151000000111000002333200113222311113202311113222311002333200000111000000111000", // tmp/microban1.145
+	  "7", "0112110123332113212312315132132123112333210112110", // tmp/microban1.146
+	  "8", "02100000011111000103331101011001020111110110111001110000151100001011000012110000", // tmp/microban1.147
+	  "5", "11100101102201111201112010501111131110311101100031000110003100011", // tmp/microban1.148
+	  "8", "01100000531110000013100001100000011322220110100000101000013010000111100001100000", // tmp/microban1.149
+	  "6", "000110011310010110010310011310112010132311000111001100001500002100002110002110", // tmp/microban1.150
+	  "8", "00011110001100100011313111303111111111100000005000000110000001100000011200000222", // tmp/microban1.151
+	  "7", "1213112101100110111151100101111110100101011310101101011310110111101104011011100110020001111", // tmp/microban1.152
+	  "8", "2222222200000022131111115313131101000000111111111131313100000010111111111313131111100000", // tmp/microban1.153
+	//"15", "000000000000002111111111111131100000000000005101111111111111101000000000000101011111111111101010000000001101010111111101101010100000101101010101110101101010101010101101010101010101101010101010101101010101010101101010101010101101010101010101101010101010101101010101010101101010101010101101010101010101101010111010101101010000010101101011111110101101000000000101101111111111101100000000000001111111111111111", // tmp/microban1.154
+	//"15", "011000000000111011000011011101011111111010111001000111011110001011100000010001021111111010111000000101010111111000111010010101000000010010111111000010010101011000010010111010000010010000010011011010111110111111010110110110110010010000010000011011111010110011011011010131010000010010115010111110010110010110110010010010010000011010011011111111010011011000010010010000011010011110110111011111111111111011000011011011000000", // tmp/microban1.155
+
+	  "4", "110011001100233511211100", // tmp/microban2.1
+	  "4", "011102011151113110401110", // tmp/microban2.2
+	  "5", "000111101112121153311010011100", // tmp/microban2.3
+	  "6", "011100110310501311111111011011021200011100001100", // tmp/microban2.4
+	  "5", "110001300013110115110012200110", // tmp/microban2.5
+	  "6", "051000021000040000111110111111000301000111", // tmp/microban2.6
+	  "5", "0011111301112310100201115", // tmp/microban2.7
+	  "5", "110001100011211543411101111000", // tmp/microban2.8
+	  "4", "11111035124210311111", // tmp/microban2.9
+	  "4", "11321132113200510011", // tmp/microban2.10
+	  "4", "2011533122310111", // tmp/microban2.11
+	  "6", "011011011031011246111031111011011000011000", // tmp/microban2.12
+	  "5", "111001111111111002001343111611", // tmp/microban2.13
+	  "5", "0110012311523111231001100", // tmp/microban2.14
+	  "5", "1100011011234450111101110", // tmp/microban2.15
+	  "6", "000011001331001011012035111111122000", // tmp/microban2.16
+	  "4", "011103050131111024211111", // tmp/microban2.17
+	  "5", "011100305101311011001321121211", // tmp/microban2.18
+	  "5", "111111333201052010120110100111", // tmp/microban2.19
+	  "5", "011000311101201042111310015100", // tmp/microban2.20
+	  "7", "000011002121100110151001011100100110131100011310001010000111000", // tmp/microban2.21
+	  "7", "000011111001011311111110002013000100100020111511011101100000110", // tmp/microban2.22
+	  "6", "000111150111133111110010011011001111001011121000121100111100", // tmp/microban2.23
+	  "10", "0000011100111001010013531111000010001000111111111011100012210000111101000010110100001100110000011110", // tmp/microban2.24
+	  "5", "011101232113031123211111001500", // tmp/microban2.25
+	  "6", "111111100031101131102435102011112011", // tmp/microban2.26
+	  "5", "1161114341210121101111011110111303111011", // tmp/microban2.27
+	  "6", "001100002100112300104311101511101100111000", // tmp/microban2.28
+	  "6", "111100100300101311152421011111011000", // tmp/microban2.29
+	  "7", "002221000110110011111001501000110100011010000001000110100011011113103110111311110111", // tmp/microban2.30
+	  "7", "00001100000510111021011112100300210110001111313111101110", // tmp/microban2.31
+	  "6", "111111111101002232001030001151000131000101000111", // tmp/microban2.32
+	  "5", "000000001100015013310213102101121011000111111", // tmp/microban2.33
+	  "7", "111000011201100122110010015101011110131000013000001310000111000", // tmp/microban2.34
+	  "9", "000000011111111111110000222011110100013110100110501100101131000101310000110010000011110000", // tmp/microban2.35
+	  "6", "000110001510001310001400111411101201101101110011011110", // tmp/microban2.36
+	  "6", "011100010100131110113021013121011021000015000011", // tmp/microban2.37
+	  "6", "001111001001122211113100103000113100115100", // tmp/microban2.38
+	  "6", "011110110010501310114220010300011111000111", // tmp/microban2.39
+	  "4", "0111012111411010113101410151", // tmp/microban2.40
+	  "5", "111101005011330022410110101111", // tmp/microban2.41
+	  "6", "001100111100102211102001101011133350011100011000", // tmp/microban2.42
+	  "6", "001100001110002121001121000100111110533310011010001110", // tmp/microban2.43
+	  "8", "000001110111110101100201013102011135021111100100030111100111111000000110", // tmp/microban2.44
+	  "5", "0111001220002200011000110013000131001350113001111011110", // tmp/microban2.45
+	  "8", "11100011111111210100001111000020111111101101302000013110000031000000510000001100", // tmp/microban2.46
+	  "7", "111100013151101100010133131011111000010011122221111111111100000", // tmp/microban2.47
+	  "5", "0011001311013010622201301113111010011100", // tmp/microban2.48
+	  "5", "01110111101232003031023210111101510", // tmp/microban2.49
+	  "5", "00111112111143100500134111121111100", // tmp/microban2.50
+	  "5", "110151101133133221221101111011", // tmp/microban2.51
+	  "6", "000110000310000110000500113111112241111011", // tmp/microban2.52
+	  "5", "000111203111311121101253000110", // tmp/microban2.53
+	  "9", "000001110000011010000011510000011110000000200001111211001030211113311000101111000111000000", // tmp/microban2.54
+	  "7", "00011000131310011101000311100011010000101000210100020010002001011111111115111", // tmp/microban2.55
+	  "6", "000111001201113435111201001011001110", // tmp/microban2.56
+	  "6", "000111011111144310114120001050001110", // tmp/microban2.57
+	  "7", "0000110011113101011010103335122110012210000011000", // tmp/microban2.58
+	  "6", "000011110021133111110020111510030021011111000011", // tmp/microban2.59
+	  "5", "001111113111010110111103111011010100501101031020110201002011111111101111000", // tmp/microban2.60
+	  "4", "11321132113200320012003100110051", // tmp/microban2.61
+	  "6", "000011000011000031113131122221015300011100", // tmp/microban2.62
+	  "7", "1100000111000011300000310000011000003102100111110003221100121110001510", // tmp/microban2.63
+	  "5", "1110013111010010312113210141201501001110", // tmp/microban2.64
+	  "7", "11110001001000101410010541101014111101413110010201111000", // tmp/microban2.65
+	  "12", "000001110000000001010000000001110000000000310000111132230000101321120111111021123101000032231111000013000000000011100000000010100000000015100000", // tmp/microban2.66
+	  "8", "0001100000141100013123101121514114111211013213100011410000011000", // tmp/microban2.67
+	  "9", "000020000000131000001111100011444110231454132011444110001111100000131000000020000", // tmp/microban2.68
+	  "5", "1212123332135312333212121", // tmp/microban2.69
+	  "6", "110111110221133333110222110111115111", // tmp/microban2.70
+	  "6", "111011132321021131131120123231110115", // tmp/microban2.71
+	  "7", "1111111143434113222311421241132223114343411111115", // tmp/microban2.72
+	  "7", "1111111123232113232311235321132323112323211111111", // tmp/microban2.73
+	  "7", "1111111132323112323210325230123232113232311111111", // tmp/microban2.74
+	  "7", "1110111123232113232310235320132323112323211110111", // tmp/microban2.75
+	  "7", "0112100013211111343312245422133431111123100012110", // tmp/microban2.76
+	  "9", "001110000001011100011230111010323201113252311102323010111032110001110100000011100", // tmp/microban2.77
+	  "7", "0111110113231113020310225221130203111323111110110", // tmp/microban2.78
+	  "7", "0000110011111002010105313011123111102300110210000", // tmp/microban2.79
+	  "7", "011000011200001214111012011100300000111100113050013111001100000", // tmp/microban2.80
+	  "9", "000000011111000011111111111001001010113100010111321030020121112011300011005100011001100000", // tmp/microban2.81
+	  "6", "000111122201103401101201105311101101113001113111111100", // tmp/microban2.82
+	  "8", "11200000212000001120000011200000010000000111000005333111110111311111310000111000", // tmp/microban2.83
+	  "6", "110011112211121121001000011110013351000131001101111131111100", // tmp/microban2.84
+	  "11", "0000000011000000000110000000111100000011030000000131311000000311110000001100011111011000115110011001101122220011110000000", // tmp/microban2.85
+	  "8", "0011100001101000011110001131000011330210003111100011011000000210000502100001121100011111", // tmp/microban2.86
+	  "10", "00000110000000012110000021211100002110510000010011000011000000013100000013110000013110000013110000001110000000", // tmp/microban2.87
+	  "5", "000112103111311241101253000110", // tmp/microban2.88
+	  "6", "111111102011114111034310114500102000111000", // tmp/microban2.89
+	  "5", "0111001110034310212112520134300111001110", // tmp/microban2.90
+	  "7", "00110000011000001100000313101135311111011100000100001212001121200111110011000", // tmp/microban2.91
+	  "6", "000110111110512110102010112010012110010000031000013100011310010131111111111000", // tmp/microban2.92
+	  "6", "000011001211011111123210131000123000001111003011011011011510000110", // tmp/microban2.93
+	  "8", "00000110000111110001101100003111011311000103330001011100110100001021200010212000110120000100101101115111000110110001011000011100", // tmp/microban2.94
+	  "6", "110510111212110212110210100010101110113310001310113310111110110000", // tmp/microban2.95
+	  "9", "000001100000001100011313100012011000012033110012011111114000511111111110012000000", // tmp/microban2.96
+	  "10", "110000111011111113101100000100010131331101013101110101115100010120000001012000000100200000111120000010002000001111100000", // tmp/microban2.97
+	  "7", "11100001013100101311110230051023111112000001211000111100", // tmp/microban2.98
+	  "9", "000011110000011011111222221111111010110000050000001110000003311000011131000011331000011100", // tmp/microban2.99
+	  "10", "01111100000100011000011100111101131000010003122222000110000100033011110113101000011510100001000010000111111000", // tmp/microban2.100
+	  "6", "011000011000123100213231132312001321000510000110", // tmp/microban2.101
+	  "10", "000110000000111000000011111110001110111000011112000000000200000000020000111112110011030211113313100011131510000011000000", // tmp/microban2.102
+	  "10", "001100000000110000001111110000121111000012000000000200500000111111111112011133311000000100111111310000000011100000001110", // tmp/microban2.103
+	  "8", "000111101111001010011111101101111133033100313130001111100000500001121221012212110120011100000111", // tmp/microban2.104
+	  "6", "011000011110114121143431012321051100", // tmp/microban2.105
+	  "5", "0011011210104111320503201113111110011000", // tmp/microban2.106
+	  "7", "001100001133110101101013130101011010501101010301112222201110000", // tmp/microban2.107
+	  "9", "000110000000130000001121100001232111132353231111232100001121100000031000000011000", // tmp/microban2.108
+	  "8", "0121000003133131012212120311123113211130212122105313313000001210", // tmp/microban2.109
+	  "8", "0011011100222121111101001511110000110100000013100001311000131100113110001111011111001111111111100110110000001100", // tmp/microban2.110
+	  "10", "0011000000001100000011312000001130200011113120111100002013110000203051001121131100111000110001100000", // tmp/microban2.111
+	  "5", "11111133311242102520124211333111111", // tmp/microban2.112
+	  "5", "110111141114341114111252011411143411141111011", // tmp/microban2.113
+	//"13", "0000001110000000011101000000001011100000000131300000111001010111010131222130101111025201111010312221310101110101001110000031310000000011101000000001011100000000111000000", // tmp/microban2.114
+	  "11", "0000010000000001110000000123210000012323210001231313210113235323110123131321000123232100000123210000000111000000000100000", // tmp/microban2.115
+	  "9", "111000011111111111010000011110000010111111020110111110000003020000111010000113020000111010000113020000111010000113010000111510", // tmp/microban2.116
+	  "9", "000000011011100111111101131101003110101113100501203100112211000002100000001100000", // tmp/microban2.117
+	  "10", "00112120000011212000001121200000110500000001111111110011001111100001101311001310013113311000131111000001110000", // tmp/microban2.118
+	  "8", "011111000100021101012101010222115111200011011000010000001331110011331110001331100011111000011100", // tmp/microban2.119
+	  "10", "0000011121000101512100011011210131100121011011112111111310211131010000010101000001001100000111300000010331000001111100000000110000", // tmp/microban2.120
+	  "8", "000121110011211101342010010121100101210011000100101115001333011011111010001110100030011000111100", // tmp/microban2.121
+	  "5", "000110144101135111411102101110", // tmp/microban2.122
+	  "9", "011000000013100000110100000130100000111100000011111000033002200011112111000002151000001100", // tmp/microban2.123
+	  "7", "111011113141312201022131013112353211310131220102213141311110111", // tmp/microban2.124
+	  "12", "000000001110002120001110002121151100001110001111000200001111111100000000101100000000101000000000101111000000101303100000110113100000131130100000111011100000011111000000", // tmp/microban2.125
+	  "12", "011111000000013311000000011300000000010110000000010310000000010110000000010010000000111122000000500022211111111020000131001020131331001121111011000000000011", // tmp/microban2.126
+	  "5", "5121011411132310141100200011000130001100", // tmp/microban2.127
+	  "7", "001500000131000114100110410010141111012101101110111000110111110", // tmp/microban2.128
+	  "9", "000000011111113111110020011030011210011213010010002011010001511011131000011000000", // tmp/microban2.129
+	//"15", "000000000000111000000000001141000000000011440000000000114410000000001144110000000011441100000000114411000000001144110000000011441100000000114411000000001144110000000011441100000000114411000000000153110000000000011100000000000012000000000000", // tmp/microban2.130
+	//"15", "000000000002000000000000023150000000000232310000000002323310000000023233232000000232332320000002323323200000023233232000000232332320000002323323200000023233232000000032332320000000123323200000000113232000000000012320000000000011000000000000", // tmp/microban2.131
+	//"25", "0000000000000000001110000000000000000111000101000000000000000010111111100000000001110001110000100000111000101000001000010000010111151100000100001000001110000300000010000111000001000012111111011110100000100001100110111101110000010000011001111010000000011111111100110001000000001010001011000001100000000111000111100011110001110000000011000001101000101000000001000110011111111100000000101111001100000100000111011110110011000010000010111101111111100001000001110000100000010000111000001000010000011111110100000100001000001010001110000010000111000111000000000011111110100000000000000001010001110000000000000000111000000000000000000", // tmp/microban2.132
+	//"32", "0000111110111111111111111111000000011011011000000000000000011000001101101101111111111111111011000110110110110000000000000011011011011011011011111111111111011011101101101101100000000000011011011010110110110111111111111011011110101011011011000000000011011011101010101101101111111111011011011010101010110110000000011011011010101010101011011111111011011011101010101010101100000011011011011010101010101010111111011011010110101010101010101000011011010101101010101010101111111011010101011010101010101110010011010101010110101010101100100111010101010101101010101101111523010101010101011010101101100001010101010101010110101101101111110101010101010101101101101100000011010101010101011101101101111111101101010101010101101101100000000110110101010101101101101111111111011011010101011101101100000000001101101101010111101101111111111110110110110101101101100000000000011011011011011101101111111111111101101101101101101100000000000000110110110110001101111111111111111011011011000001100000000000000001101101100000001111111111111111110111110000", // tmp/microban2.133
+	//"35", "0000000000001110000001100000000000000000000000011111111111000000000000000000000000010000000110000000000000000000001110110000001001100000000000000000011111100000111111000000000000000000010011001001110110000000000000001110110000111000001001100000000000011111100011111000111111000000000000010011001101111001110110000000001110110000111010111000001001100000011111100011110101111000111111000000010011001111101010111001110110001110110000111001011101111000001001111111100011111111101010111000111111010011001110000001110101111001110110100000111111111110101111111000001001000011100010100101010000011000010010001111111111115111111111111000100100001100000101010010100011100001001000001111111010111111111110000010110111001111010111000000111001100101111110001110101011111111100011111111001000001111011101001110000110111000110111001110101011111001100100000001111110001111010111100011111100000011001000001110101110000110111000000000110111001111011001100100000000000001111110001111100011111100000000000011001000001110000110111000000000000000110111001001100100000000000000000001111110111011111100000000000000000011001001010110111000000000000000000000110010100100000000000000000000000001113101211100000000000000000000000011000000111000000000000", // tmp/microban2.134
+	//"39", "000000000000000000000001100000000000000000000000000000000000001100000000000000000000000000000000000001101110000000000000000000000000000000000111110000000000000000000000000000000111110000011000000000000001100000000110111010011011000000001100001100000000110000010011011011100001100001101110000110000010011001111100001100000111110000011111110001111100000000111111110000011111000111111100110000111110000010111011101100100000110110000111011000011111000001100100000110110000000011011111000000001100101110110000000000011011101011100000000111110000000000000000000001111100000111110000000000000000000001111100000000111010111000000000000000001110101110000000011111000000000000000000000111110000011111000001100000000000000111110000011011101001101100000000000110111010011011000001001101101110000110110000010011011000001001100113250000110110000010011001111111000111110000000110011111110001111100011111110011000000011111000111111100110010000011011000011111001100100000110110010000011011000011101101100100000110110010111011000000000001101100101110110000011111000000000000001100000111110000011111000000000000000000000111110000000011101011100000000000000000111010111000000001111100000000000000000000011111000001111100000000000000000000011111000000001110101110110000000000011011101001100000000111110110000000011011000001001100000111110000110111000011011000001001101110111010000011111000011001111111000111110000011111111000000001111100011111110000011111000001100001111100110010000011000011101100001100001110110110010000011000000001100001100000000110110010111011000000001100000000000000110000011111000000000000000000000000000000011111000000000000000000000000000000000011101100000000000000000000000000000000000001100000000000000000000000000000000000001100000000000000000000000", // tmp/microban2.135
+
+	  "6", "110000110000110000233135112121110000", // tmp/microban3.1
+	  "4", "01110311124415110011", // tmp/microban3.2
+	  "5", "111111231102300115111230111111", // tmp/microban3.3
+	  "4", "1151103112420031114111110011", // tmp/microban3.4
+	  "4", "11001100113113210120032001500110", // tmp/microban3.5
+	  "5", "111111445100111133101221000110", // tmp/microban3.6
+	  "7", "0110000031113101202110100010132021015111300000110", // tmp/microban3.7
+	  "6", "111111113111020000111111111111004000111111111511000400111111111111000020111311111111", // tmp/microban3.8
+	  "6", "000011011032111151110032010011010111010000010110011210010310010210011310000110", // tmp/microban3.9
+	  "5", "11011133311222110300123101251000110", // tmp/microban3.10
+	  "6", "111110115110100100200110223110000100011311013111111000111000110000", // tmp/microban3.11
+	  "6", "110000222110200110113131003131005111", // tmp/microban3.12
+	  "5", "011000141101405014111123011110", // tmp/microban3.13
+	  "6", "111151131131010010130130112210012210", // tmp/microban3.14
+	  "6", "150000111110120211033331121200111100", // tmp/microban3.15
+	  "6", "000510011110030221113101101311122030011110011000", // tmp/microban3.16
+	  "6", "110011111331113011001210004210001251000111", // tmp/microban3.17
+	  "5", "11100134111141120102114111143500111", // tmp/microban3.18
+	  "6", "121000132100133210123321012335001231000121", // tmp/microban3.19
+	  "7", "000110001211000131100000500011111001414110014141100141110001110", // tmp/microban3.20
+	  "7", "00001110001151000101021211211100011013131001131000001100", // tmp/microban3.21
+	  "9", "111000111111100111011113310011011310000110110000150000000111100000100100011110100022120100001000100001111100", // tmp/microban3.22
+	//"13", "0000110000000000011210000000001131000000000010000000000001110011101101141111110230145410320111111411011011100111000000000000100000000001311000000000121100000000000110000", // tmp/microban3.23
+	//"13", "0000110000000000011210000000001131000000000010000000000001100011101100141111110230141410320111111410011011100011000000000000100000000001311000000000125100000000000110000", // tmp/microban3.24
+	  "6", "111000101100103200112311103201102301113215002301001101000111", // tmp/microban3.25
+	  "9", "000000011000000111121212151103010110111101100001010100001011100001011000001131000001030000001110000", // tmp/microban3.26
+	  "8", "0110000001111111010010110131011001010110115101102222101000011010000033100001311000011100", // tmp/microban3.27
+	  "5", "1110013210033210121501211033211321011100", // tmp/microban3.28
+	  "6", "001111013335011111013000022220022220000310111110133310111100", // tmp/microban3.29
+	  "6", "110000110000411111230111460300230110411110110110110000", // tmp/microban3.30
+	  "9", "001110000001310000013131100013131100011000100010111100011101011112221151212001011000001110", // tmp/microban3.31
+	  "9", "111110000115110000110100000222200000000100000111100000113100000010000000111101110131301011003111101001111101000110011000011110", // tmp/microban3.32
+	  "10", "00000001110000011101000002120100000111010000021201000001110100000212010000011101000000100100111151110113101000113100110010130131001031001100101310000011111000000001100000", // tmp/microban3.33
+	  "5", "01110032101321053200132100321001110", // tmp/microban3.34
+	  "6", "111000123210134110011431012321000115", // tmp/microban3.35
+	  "9", "111011111112310011102300221100111330110111011033111001122003201110013211111510111", // tmp/microban3.36
+	  "6", "111211111311000320000110000320000110000320000510", // tmp/microban3.37
+	  "6", "150000110000233100112100110000233131112121110000", // tmp/microban3.38
+	  "8", "00000011000001510001131100011110000010000013310012222200111331001010110011100000", // tmp/microban3.39
+	  "9", "000111011000111111000003001011101001011101102001131102001101102003000002001011001111111115130011011111111000", // tmp/microban3.40
+	  "8", "111001105031111011330010011110100030021100110212000112000001111000001110", // tmp/microban3.41
+	  "8", "110011001110110011303100021012000230320002151200013031110110111101100000", // tmp/microban3.42
+	  "9", "000110000000110000000321000001323311112252211113323100000123000000011000000011000", // tmp/microban3.43
+	  "6", "001100111111131313424242131313424242151111", // tmp/microban3.44
+	  "9", "001100000001313100001020200111110111101020201101313101110110101011011101001100011000115110", // tmp/microban3.45
+	  "12", "110000000111131000001131113100011310011310113100001122221000000120020000000020021000000122221100001311013110013110001311131100000131511000000011", // tmp/microban3.46
+	  "11", "00114141100001111111000001020100001110201110031102011301131020131110100500101113102013110311020113001110201110000102010000011111110000114141100", // tmp/microban3.47
+	  "5", "11000511101441000111133111221100110", // tmp/microban3.48
+	  "6", "000110001110112431114235011100011000", // tmp/microban3.49
+	  "6", "000110001110112431114235011100001100", // tmp/microban3.50
+	  "7", "0000111011131101103001412110114105000121100011000", // tmp/microban3.51
+	  "7", "00001110111311011030014121101141050011411001210000011000", // tmp/microban3.52
+	  "7", "00001110111311011030014121101141050011411001412000011100", // tmp/microban3.53
+	  "10", "11100000001130000000011000000001301100000111110000011015000001101101100000111110001130001000111310200001001021000110222100031000000001100000", // tmp/microban3.54
+	  "9", "111000111102101101113231321011323210003252300012323110123132311101101201111000111", // tmp/microban3.55
+	  "9", "000111000000123000000321000131323311122252221113323131000123000000321000000111000", // tmp/microban3.56
+	  "11", "0011111110000101010100113232323111023232320111320102311102315132011132010231110232323201113232323110010101010000111111100", // tmp/microban3.57
+	//"13", "1111111111111101010101010111323232323111023232323201113232323231110232323232011132325232311102323232320111323232323111023232323201113232323231110101010101011111111111111", // tmp/microban3.58
+	  "9", "123232111132323101123232101132323101123232101101010101101010101101010305101010101101010101101010101101010101101010101101010101111111111", // tmp/microban3.59
+	  "6", "001110001011003201113205103201101111110100011100", // tmp/microban3.60
+	  "5", "111111010113331122201500011000", // tmp/microban3.61
+	  "5", "00000110001110013335022210110001100", // tmp/microban3.62
+	  "5", "001100011000320113201032111151", // tmp/microban3.63
+	  "6", "110000111000111100011110001111000100153331112221", // tmp/microban3.64
+	  "6", "111000103211112305003211001100001100", // tmp/microban3.65
+	  "6", "001111111001103211502300103200111110001110", // tmp/microban3.66
+	  "5", "015110100113231123211010011100", // tmp/microban3.67
+	  "6", "000111113201502311103200101100111100", // tmp/microban3.68
+	  "5", "00110012100141001400113101151011000", // tmp/microban3.69
+	  "6", "110000111110112010004010054111013111000110", // tmp/microban3.70
+	  "4", "012101410141114115311100", // tmp/microban3.71
+	  "5", "0121101401054110141000311011110101001110", // tmp/microban3.72
+	  "6", "111000112100113100014151003101002011001110", // tmp/microban3.73
+	  "6", "111000102100113151004111113100102000111000", // tmp/microban3.74
+	  "4", "1110121013100410131112150011", // tmp/microban3.75
+	  "5", "0001101215013110041011310102101110001100", // tmp/microban3.76
+	  "6", "011000011000011000003311113211102200150100011100", // tmp/microban3.77
+	  "5", "111001010053320032210101101111", // tmp/microban3.78
+	  "5", "011100101003320132215110100111", // tmp/microban3.79
+	  "5", "01110010100151003300132111220100111", // tmp/microban3.80
+	  "5", "000110011111311124200131000510", // tmp/microban3.81
+	  "4", "001100311242103111511110", // tmp/microban3.82
+	  "7", "0001110000101101131011124211101311011050000111000", // tmp/microban3.83
+	  "5", "00111005010121103430112101010011100", // tmp/microban3.84
+	  "6", "111000113100034210012511011011000011", // tmp/microban3.85
+	  "6", "111000105311113421000210011110011100", // tmp/microban3.86
+	  "6", "001111001111115300103421101201101101100001111111", // tmp/microban3.87
+	  "8", "0011000000111111001000111531101113421010002000100111111001110110", // tmp/microban3.88
+	  "5", "001110011111410125301141001100", // tmp/microban3.89
+	  "5", "0110001410125311141111011", // tmp/microban3.90
+	  "5", "0011101411125301141100111", // tmp/microban3.91
+	  "6", "011100010110141011253101141101001111001100", // tmp/microban3.92
+	  "6", "001100001100013411114215111000110000", // tmp/microban3.93
+	  "5", "11000111111134100420015100111001100", // tmp/microban3.94
+	  "6", "005100001100003410114211111111000011", // tmp/microban3.95
+	  "6", "011100011111001011003450014210111100111000", // tmp/microban3.96
+	  "4", "511013310312012200110011", // tmp/microban3.97
+	  "5", "11000510001331013121002210111001110", // tmp/microban3.98
+	  "5", "1111011110013300135200122", // tmp/microban3.99
+	  "4", "01110331135210221111", // tmp/microban3.100
+	//"40", "000001110000000111000000011100000000000000000101011000010101100001010110011100000000011111110001111111000111111101211000000000010111100001011110000101111015110000000011101111001110111100111011110111101110001111011110111101111011110111101110101011011110111101111011110111101111010011111110111101111011110111101111011111110010111101111011110111101111011110110101011101111011110111101111011110111100011101111011110111101111011110111101111000000011110111101111011110111101111011110000000111101111011110111101111011110111100000001111011110111101111011110111101111000000011110111101111011110111101111011110111000111101111011110111101111011110111010101101111011110111101111011110111101001111111011110111101111011110111101111111001011110111101111011110111101111011010101110111101111011110111101111011110001110111101111011110111101111011110111100000001111011110111101111011110111101111000000011110111101111011110111101111011110000000111101111011110111101111011110111100000001111011110111101111011110111101111011100011110111101111011110111101111011101010110111101111011110111101111011110100111111101111011110111101111011110111111100101111011110111101111011110111101101010111011110111101111011110111101111000111011110111101111011110111101111011110000000111101111011110111101111011110111100000001111011110111101111011110111101111000000011110111101111011110111101111011110000000111101111011110111101111011110111101110001111011110111101111011110111101110101011011110111101111011110111101111010011111110111101111011110111101111011111110010111101111011110111101111011110110101011101111011110111101111011110111100011101111011110111001111011100111101110000000011110111101000011110100001111010000000000113101111111000111111100011111110000000001110011010100001101010000110101000000000000000001110000000111000000011100000", // tmp/microban3.101
+
+	  "4", "011101110310541012101100", // tmp/microban4.1
+	  "5", "001110015100310014100121003100141001210011000", // tmp/microban4.2
+	  "5", "111111322103141141301223111151", // tmp/microban4.3
+	  "4", "1231132113215230132113211231", // tmp/microban4.4
+	  "5", "00000010000110001511011310020000200002001311111311001110001100001", // tmp/microban4.5
+	  "6", "100000110000131000113110111110002000002000002000002000131111113111001510000110000010", // tmp/microban4.6
+	  "7", "01100000111310030202011050101302021111131100010110001110", // tmp/microban4.7
+	  "6", "121121233332132231132631233332121121", // tmp/microban4.8
+	  "9", "000011000000032000001111100121141100131454131001444121001111100000230000000110000", // tmp/microban4.9
+	  "10", "000011000000001100000000110000111010000011134011000005411110000320111100012001110003200000000120000000031000000001100000", // tmp/microban4.10
+	  "5", "110151323112321123211323111011", // tmp/microban4.11
+	  "5", "11511131310242001110132311232111011", // tmp/microban4.12
+	  "5", "01511014310120001331112211110011000", // tmp/microban4.13
+	  "6", "001511003211121300103210101010111110011100", // tmp/microban4.14
+	  "5", "001101211013110005001110011411041110141100110", // tmp/microban4.15
+	  "5", "00111011010230104111141001510011000", // tmp/microban4.16
+	  "5", "111001151103402011330122101141", // tmp/microban4.17
+	  "7", "00001100011110112031011414100141411013021101151000110000", // tmp/microban4.18
+	  "6", "001100113110503010123212001111001100", // tmp/microban4.19
+	  "5", "001111141111430112100023100151", // tmp/microban4.20
+	  "6", "001100014100113110503010123212001111001100", // tmp/microban4.21
+	  "5", "00000110111141123432105011111100000", // tmp/microban4.22
+	  "7", "000000001101100513110011421000414000124110011311001101100000000", // tmp/microban4.23
+	  "8", "001100000053000001210000012300000141111000200010013111110111011100000000", // tmp/microban4.24
+	  "6", "001110011310020310025310020310020110010000011110111010101111111101010111011100", // tmp/microban4.25
+	  "6", "000111000111112230112231030501131111111000", // tmp/microban4.26
+	  "6", "000110000110011410011140010212133101110151110000", // tmp/microban4.27
+	  "7", "000110001111110144411004241101151001310000104110011111000011100", // tmp/microban4.28
+	  "7", "00110000111000114110014111000141000031000001151000042411014441101111110001100", // tmp/microban4.29
+	  "11", "000000011000000000122100000001331000000001000000011011100001111111000011003200110050011002300110000111111100001110110000000100000000133100000001221000000000110000000", // tmp/microban4.30
+	  "6", "011000112110112011134331002110001150", // tmp/microban4.31
+	  "8", "0110110002301221123113311110010000000111121111111315032000110110", // tmp/microban4.32
+	  "7", "1110111101010111434110025200114341110101011111111", // tmp/microban4.33
+	  "6", "011100111110143431012121023430010521011111", // tmp/microban4.34
+	  "7", "1112111103030113212312011102132123110303011116111", // tmp/microban4.35
+	  "10", "1111111115103000000110201112311012312001101100310110130011011002132101132111020110000003011111111111", // tmp/microban4.36
+	  "7", "0012100023132013141312145412131413102313200012100", // tmp/microban4.37
+	  "7", "0111110132323112323211325231123232113232310111110", // tmp/microban4.38
+	  "10", "001100000001110000000103110000111311000011130000000011000000001000000000100000000010000000011000110001111111000000000100000000010000000001000001110100001111011100105121220011100000", // tmp/microban4.39
+	//"8", "0000110000111100012111001121100021200000010000000100000001000000011111110110001100000010000000100000001000000110000011100000353100013301000111010000111100001110", // tmp/microban4.40
+	  "9", "000000110111111110110000010010000110010000111013200311011131110000200110000100000000200000000100000000100000011110000011511000000111000000011000", // tmp/microban4.41
+	//"10", "0000001110000000101000000011100000113100110010010011101001001131311311013130010101131101050110011101000000011100000001000000000100000000010000000001000000000100011000010001110001000112110100001211010000120001000011220100001111111000122101100000000110", // tmp/microban4.42
+	  "5", "01100013000131501301011010110102101010111212011110", // tmp/microban4.43
+	  "6", "011000011000013011131131113011011010011050021010020110121200111100", // tmp/microban4.44
+	  "8", "111100001001100011101211053442111110210011301000013110000101000001110000", // tmp/microban4.45
+	  "9", "000000110111111110100051030111000011011011011131122031131022010101022011131022311101011011111000030001111131000000111", // tmp/microban4.46
+	  "7", "11111002000100201313120113112013131200051011111101100000", // tmp/microban4.47
+	  "7", "11111002000100201313120113112013131200150011111001100000", // tmp/microban4.48
+	  "7", "11111002000100201313120113112013131205100011110001100000", // tmp/microban4.49
+	  "12", "011000011000011110113111010110110001110100011102110111113102110110001101010110100105110000110101111111110102000000010002000001033101000001111111000001110111", // tmp/microban4.50
+	  "5", "00111023211323012321132310111500000", // tmp/microban4.51
+	  "5", "01111023211323112320132310111500110", // tmp/microban4.52
+	  "5", "01111023211323012320132310111500011", // tmp/microban4.53
+	  "5", "00111023211323012320132310111501100", // tmp/microban4.54
+	  "7", "001100012110001311000005000011110001141411041411101410110111000", // tmp/microban4.55
+	  "9", "110011111131113102110001002010001102131113102111001102001000002003011312111111111130110151111110111", // tmp/microban4.56
+	  "7", "01111000141111114444111454111444411111141000111100001000000100000010000001000013310001221000001100", // tmp/microban4.57
+	//"13", "0000000000000000000000000000000111000000000112100000000013431100000113020311000012425242100001130203110000011343100000000012110000000001110000000000000000000000000000000", // tmp/microban4.58
+	  "11", "0001100000000011000000000112100000001343111100130203111002425242001113020310011113431000000012110000000001100000000011000", // tmp/microban4.59
+	  "11", "0000111000000002320000000131310000013232310012324242321131320231311232424232100132323100000131310000000232000000001510000", // tmp/microban4.60
+	  "8", "000011101110101013111110042043000121121000340240011151310101011101110000", // tmp/microban4.61
+	  "9", "000011100111010100131111100042023000011141100003202300001141110000320240001115131001010111001110000", // tmp/microban4.62
+	  "7", "011111001000101113111132224104363301322241111311101000100111110", // tmp/microban4.63
+	  "7", "011111001001301110111142224104363401321231111011103100100111110", // tmp/microban4.64
+	  "7", "1110110113431011232100021100012521101343110110111", // tmp/microban4.65
+	  "7", "0111110014431013232111025201112323101443100111110", // tmp/microban4.66
+	  "6", "000011131331122411021301022511021301122411131331000011", // tmp/microban4.67
+	  "7", "000001101313310122411002030113225111121300002110000031000001100", // tmp/microban4.68
+	  "9", "000001100000133131001222111012001310032324300132002110111222110013133500000110000", // tmp/microban4.69
+	  "9", "000111000000111000113333310111212110010202000010462110000202010011212111013333311000111000000111000", // tmp/microban4.70
+	  "6", "110000153131122211032310012300032100122211131331000011000011", // tmp/microban4.71
+	  "9", "000110000000153131000122211000132331111002100111232000001021100011313100011000000011000000", // tmp/microban4.72
+	  "8", "0000110013231400112121000042133101252111032132001310310011111100", // tmp/microban4.73
+	  "7", "1100000110000013350000121000032000001200000320000112221013133111100111", // tmp/microban4.74
+	  "11", "000011100000000131000000011110000000330001100001151111100042224031110210110111303222303111021011011130422240001111131100001100001111000000131010000001011100000011100", // tmp/microban4.75
+	  "9", "110000011130000031131101131112222211030201030015141110030102030112222211131101131130000031110000011", // tmp/microban4.76
+	  "7", "011100001010000132411012314100403251123141103241111110111110000", // tmp/microban4.77
+	  "8", "000011000000130000001100001313000012231100025411000221000002330011121311111001110000011000000110", // tmp/microban4.78
+	  "7", "011100001010110132411012314100403251123231103232111110110000011", // tmp/microban4.79
+	  "10", "11000000001300000000110000000053313131001122222100002020300011212231311014332111111101100000001310000000111000", // tmp/microban4.80
+	  "8", "011000000113131001042210112111001332233100111251012240100131311000000110", // tmp/microban4.81
+	  "8", "000001100011011000133310002222201103230011132100131121510003231100011000", // tmp/microban4.82
+	  "8", "000011000110110003203200132312111120323103251230013421100011100000111000", // tmp/microban4.83
+	  "8", "0110110002303210023132110121213103202300131213101510111001100000", // tmp/microban4.84
+	  "11", "000011100000000131000000001111000011000330001111151100013042223000110100120111301222303111010012011000222230310001131111111110000110101310000001110100000000111000000", // tmp/microban4.85
+	  "7", "011111001030101213121132123100141001325231121312101030100111110", // tmp/microban4.86
+	  "7", "1101100230320014141111121131014100011410001150000", // tmp/microban4.87
+	  "10", "11100110001122435000013121100000020000000121110000014443000001113111110000301111000110001100011111100000000110", // tmp/microban4.88
+	  "7", "0000000011215001232100233320012321001323100134310013231001232100233320012321001121100000000", // tmp/microban4.89
+	  "7", "0000000012325001323100114110011411002343200321230023432001141100114110013231001232100000000", // tmp/microban4.90
+	  "7", "0000000011115001111100343430021212001232100134310012321002121200343430011111001111100000000", // tmp/microban4.91
+	  "7", "0000000011115003243200141410014141001141100114110011411001414100141410023423001111100000000", // tmp/microban4.92
+	  "7", "0000000011215001323100132310024242001323100134310013231002424200132310013231001121100000000", // tmp/microban4.93
+	  "7", "0000000011415001232100132310011321001323100232320013231001241100132310012321001141100000000", // tmp/microban4.94
+	  "7", "0000000011215001343100232120014441001113100234320013111001444100212320013431001121100000000", // tmp/microban4.95
+	  "7", "0000000011415001333100223220013331002212200134310022122001333100223220013331001141100000000", // tmp/microban4.96
+	  "8", "0000000001323250012323100132321001132310011232100123231001323210012321100132311001232310013232100123231000000000", // tmp/microban4.97
+	  "8", "0000000001411450014114100123321001422410014133100132231001322310013314100142241001233210014114100141141000000000", // tmp/microban4.98
+	  "8", "0000000001111150013433100142241002313320024223200132131001312310023224200233132001422410013343100111111000000000", // tmp/microban4.99
+	  "8", "0000000001123150031321200132321002132130013232100321132002311230012323100312312001232310021231300113211000000000", // tmp/microban4.100
+	//"40", "0000000000000000000000110000011100011000000011100001101110000011000001111111100000001111111110111111111100000000100110001110000011111001000000100110111011010000111111111000001101110111111011111101011001000000100110111111011101100100110101100101110111111011001000000100011000010110011111011101100001101110111111101101010011001000000100110111111011100110111111001101101110111111011001000000000011001100110111111011101100000100111101100100110000011001000000100110010111110111111011100000000100110111111111011000011011101110000111011011011100110100101100100000000000011111101100000000011010111111011101100000100110111111111111101011011101111110111011000001100001101100100100000010011011111101100000110010000110011011101101000010110111111111101101111011101111110100001000011000100110000100101100010011010000101100100011010010000110010001100001000010111111011101111011011111111110110100001011011101100110000100110000011011111101100100000010010011011000011000001101110111111011101101011111111111110110010000011011101111110101100000000011011111100000000000010011010010110011101101101110000111011101100001101111111110110010000000011101111110111110100110010000001001100000110010011011110010000011011101111110110011001100000000001001101111110111011011001111110110011101111110110010000001001100101011011111110111011000011011101111100110100001100010000001001101111110111010011010110010011011101111110110010000001001101011111101111110111011000003251111110000101101110110010000001001111100000111000110010000000011111111110111111111000000011111111000001100000111011000011100000001100011100000110000000000000000000000", // tmp/microban4.101
+	//"42", "000001100000000110110000000001101100000000000001100000001111111000000011111110000000000001100000001100011000000011000110000000000011011000110110110110001101101101100000000011111101111110111111011111101111110000000001101101101100011011011011000110110000000000001000100000000010001000000000100000000001101101101100011011011011000110110000000011111101111110111111011111101111110000000011011000110110110110001101101101100000000001000000000100010000000001000100000000000011011000110110110110001101101101100000000011111101111110111111011111101111110000000001101101101100011011011011000110110000000000011000110000000110001100000001100110011011011111110110110111111101101101111111111111101101101111111011011011111110110011110001100000001100011000000011000110000010010011011000110110110110001101101101100110011011111101111110111111011111101111110110011001101101101100011011011011000110110010010000011000110000000110001100000001100011110110011111110110110111111101101101111111111111001101101111111011011011111110110110011011000000001100011000000011000110000000000110011000110110110110001101101101100000000111111101111110111111011111101111110000000011001101101100011011011011000110110000000000001000100000000010001000000000100000000001101101101100011011011011000110110000000011111101111110111111011111101111110000000011011000110110110110001101101101100000000001000000000100010000000001000100000000000011011000110110110110001101101101100000000011111101111110111111011111101111110000000001101101101100011011011011000110110000000000001000100000000010001000000000100000000001101101101100011011011011000110110000000011111101111110111111011111101111110000000011011000110110110110001101101101100000000001000000000100010000000001000100000000000011011000110110110110001101101101100000000011111101111110111111011111101111110000000001101101101100011011011011000110110000000000011000110000000110001100000001300000000000011111110000000111111100000005100000000000001101100000000011011000000001200000", // tmp/microban4.102
+
+	  "6", "001110131010101121111101010111051100", // tmp/minicosmos.1
+	  "6", "001110131010101121111101030211051100", // tmp/minicosmos.2
+	  "6", "001110131010101121121101030231051100", // tmp/minicosmos.3
+	  "6", "000011111311112011010010111111150111110000", // tmp/minicosmos.4
+	  "6", "000011111311142011010010111111150111110000", // tmp/minicosmos.5
+	  "6", "000011111411142011010010131111150111110000", // tmp/minicosmos.6
+	  "6", "011100010310131111212011001510001010001110", // tmp/minicosmos.7
+	  "6", "011100020310131111212031001510001010001110", // tmp/minicosmos.8
+	  "6", "011100030100111351101101102121111000", // tmp/minicosmos.9
+	  "6", "011100030100112351101101102231111000", // tmp/minicosmos.10
+	  "6", "011100120100111111120101010311011310000510", // tmp/minicosmos.11
+	  "6", "011100120100111111120101010311021330000510", // tmp/minicosmos.12
+	  "7", "0000110013111011010302521110010101101111110110000", // tmp/minicosmos.13
+	  "7", "0000110013111011010302522110010101101113110110000", // tmp/minicosmos.14
+	  "6", "000110131110112010010211151131111000", // tmp/minicosmos.15
+	  "6", "000110131310112010010211151131211000", // tmp/minicosmos.16
+	  "7", "00001110001141001131001111001211000105000011110000111000", // tmp/minicosmos.17
+	  "7", "00001110001141001131001141001211000105000011110000111000", // tmp/minicosmos.18
+	  "6", "110000111110111110001000133110121251000111", // tmp/minicosmos.19
+	  "6", "110000111110111110001000133310122251000111", // tmp/minicosmos.20
+	  "5", "11100111110111100030113101511100212", // tmp/minicosmos.21
+	  "5", "11100121110131100030113101511100212", // tmp/minicosmos.22
+	  "7", "011100001110000133100011010001001100121512110010111111110000110", // tmp/minicosmos.23
+	  "7", "011100001130000133100011020001001100121512110010111111110000110", // tmp/minicosmos.24
+	  "7", "0000011000122101330110101050111111111101110000011", // tmp/minicosmos.25
+	  "7", "0000011000122101330110101050114111111101110000011", // tmp/minicosmos.26
+	  "6", "011000011111010211040030111111101511111100", // tmp/minicosmos.27
+	  "6", "011000011111010211040030111141101511111100", // tmp/minicosmos.28
+	  "6", "111011111111010211111100101210133010001150", // tmp/minicosmos.29
+	  "6", "111011111111010212111100101410133010001150", // tmp/minicosmos.30
+	  "5", "111001011021031115112003011110", // tmp/minicosmos.31
+	  "5", "110001111012031015110203001110", // tmp/minicosmos.32
+	  "5", "00111111111411004050131101210001100", // tmp/minicosmos.33
+	  "5", "01100111001411004050131101211100111", // tmp/minicosmos.34
+	  "5", "011110100111111141400302001510", // tmp/minicosmos.35
+	  "6", "111000101100111431001105001421001100", // tmp/minicosmos.36
+	  "5", "00110011101143110105114210011000110", // tmp/minicosmos.37
+	  "6", "001100001211053331121210111000110000", // tmp/minicosmos.38
+	  "6", "001110111110110200053331020201011111011000", // tmp/minicosmos.39
+	  "5", "001100121053331212011011111100", // tmp/minicosmos.40
+
+	  "7", "011100001111110014401110414511141001100110011111002301100110000", // tmp/picocosmos.1
+	  "8", "00000011000001110000125200013311001412000113110002320000113100001010000011100000", // tmp/picocosmos.2
+	  "7", "00011000001100114341111454010124411010111011110001110000", // tmp/picocosmos.3
+	  "7", "0001100014141011414101141411113141500210000011000", // tmp/picocosmos.4
+	  "6", "001600011100014100111311104141111410014100001100", // tmp/picocosmos.5
+	  "6", "001100013231112311123205012321013231000110", // tmp/picocosmos.6
+	  "6", "011000011311042221111311144440111350011000", // tmp/picocosmos.7
+	  "7", "000110000111110044421011111011440001111100004345000111100011000", // tmp/picocosmos.8
+	  "7", "00110001113110114041001141610140411001414000111100011100", // tmp/picocosmos.9
+	  "7", "01100001111110144544101101110144310011411000121000001100", // tmp/picocosmos.10
+	  "7", "00011000001110001241000414111144411111310001451000110000", // tmp/picocosmos.11
+	  "5", "016100323001410014100141001411114111111001100", // tmp/picocosmos.12
+	  "6", "011000014110011111004141001100000100011311014441111110116000110000", // tmp/picocosmos.13
+	  "7", "00110110111111010101111444105041130114441000121100000110", // tmp/picocosmos.14
+	  "7", "0011000051310001241001334241102210111131110011000", // tmp/picocosmos.15
+	  "6", "001500114141143411114141121410001110000110", // tmp/picocosmos.16
+	  "5", "016100323001410014100141011410114111141100110", // tmp/picocosmos.17
+	  "6", "001100124111114101114435014110114410111100", // tmp/picocosmos.18
+	  "6", "000011000131114111114411011401014211054100001100", // tmp/picocosmos.19
+	  "6", "001100011100114441114501014421011111010300011100", // tmp/picocosmos.20
+	  /*
+	  "5", "000110001111111101311110000100003000010000100111312221100150", // tmp/microban5.1
+	  "11", "0000000111100000001151000000012000000110320000001101200000013132001110110120011113300000000011000000000110000000001100000", // tmp/microban5.2
+	  "9", "001101100003203200121131131131121121003252300121121131131131121002302300001101100", // tmp/microban5.3
+	  "10", "111100000011210000000021000000001111111111100013115022200310112220011000011003100000011310000001110000000011100000001310000000031000000001100000000310000000131100000111110000011100", // tmp/microban5.4
+	  "5", "001110111111441144110324514411114410111100111", // tmp/microban5.5
+	  "6", "111100144100141110114411111441054230111441114411141110144100111100", // tmp/microban5.6
+	  "7", "01100000111310010031001001100100310015011001003100100110010001111222211110110", // tmp/microban5.7
+	  "9", "110000011111111111130000001010112222010101000010101110010111111010050111011110000000031000000013100000011310000001110000000110", // tmp/microban5.8
+	  "8", "01100000013000000221100011301110111000500100011101110311000112200000031000000110", // tmp/microban5.9
+	  "6", "011510011011023032011411023032011011001111", // tmp/microban5.10
+	  "6", "011510011011023032011011023432011011023032011011001111", // tmp/microban5.11
+	  "7", "1100110112321111030110114115010301011232101110110", // tmp/microban5.12
+	  "5", "01110011110243102200113311151100011", // tmp/microban5.13
+	  "6", "001100003110014221113131152240001131000111", // tmp/microban5.14
+	  "6", "111100110100143411124211143411110100015100", // tmp/microban5.15
+	  "6", "011000013000111000143211542211143211111000013000011000", // tmp/microban5.16
+	  "6", "001100003100001100001000112210134211110315000111", // tmp/microban5.17
+	  "7", "01100001111110110133001000100512131112140112141110011000", // tmp/microban5.18
+	  "11", "0000010000000001210000000114110000011323110001132323110124235324210113232311000113231100000114110000000121000000000100000", // tmp/microban5.19
+	  "7", "1121110123230123132311235321132313210323210111211", // tmp/microban5.20
+	  "8", "1111111112323231132323211230023113200321123232311323232151111111", // tmp/microban5.21
+	  "9", "000121100011313110110020010130111031212151212130111031010020011011313110001121000", // tmp/microban5.22
+	  "9", "111000111101000101113131311001222100003202300001222100113131311101001005111001111", // tmp/microban5.23
+	  "9", "111101111101101101114434411114212411003151300114212411114434411101101101111101111", // tmp/microban5.24
+	  "8", "1321112123321233123323321121132112351211233233213321233212111231", // tmp/microban5.25
+	  "11", "2111121111210011011001100013100011100333001111132223111203325233021113222311111003330011100013100011001101100121111211112", // tmp/microban5.26
+	  
+	  */
+	  };
+
+	  public static final int BUILTIN_LEVELS = bl.length/2;
+
+///////////////////////////////////////////////////////////////////
+
+	private SokobanDatabase( Context co )
+	{
+	    context= co;
+	    
+	    mLevels = SokobanLevels.getInstance();
+	    numrunnings = 0;
+	    numplayings = 0;
+	    uniqueid    = 0;
+	    username    ="";
+	    veriname    ="";
+	    scrollpos   = 0;
+	    
+	    for(int i=0; i<BUILTIN_LEVELS; i++)
+	      {
+	      int xlen = Integer.valueOf(bl[2*i]).intValue();
+	      SokobanLevel sl = new SokobanLevel( null, null, INVALID, INVALID, null, false,xlen, bl[2*i+1]);
+	      mLevels.addLevel(sl,i);
+	      }
+
+	    hash = computeHash();
+	    
+	    try
+		  {
+		  SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
+		  readPreferences(settings);
+		  }
+		catch( Exception ex )
+		  {
+		  Log.e( TAG_DB, "Failed to retrieve preferences: "+ex.toString());
+		  }
+	    
+	    if( veriname==null ) veriname="";
+	    if( username==null ) username="";  
+	    if( uniqueid==0 ) uniqueid = getDeviceID();
+
+	    mLevels.setScroll(scrollpos);
+	    mLevels.updateMyRecords(username);
+
+	    if( numrunnings==0 ) SokobanCanvas.setState(SokobanCanvas.STATE_HELP);
+
+	    if( hash != computeHash() )  // someone has been messing with RMS !
+	      {
+	    Log.e(TAG_DB, "messing in DB");	
+	    	
+	      SokobanLevel sl;
+	      veriname = "";
+
+	      for(int i=0; ; i++)
+	        {
+	        sl = SokobanLevels.getLevel(i);
+	        if( sl==null ) break;
+	        sl.resetPrivate();
+	        }
+	      }
+
+	    finishedBootup = true;
+	    SokobanCanvas.setRepaint();
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	private void readPreferences(SharedPreferences settings)
+	{
+		String key, sett;
+		int num;
+		
+		for (Map.Entry<String, ?> entry : settings.getAll().entrySet()) 
+		{
+            Object val = entry.getValue();
+        
+            if( val!=null )
+            {
+            	key = entry.getKey();
+            
+            	try
+            	{
+            		num = Integer.valueOf(key).intValue();
+            		sett= String.valueOf(val);
+            		
+            		switch(num)
+            		{
+            		case 1 : username    = sett; break;
+            		case 2 : veriname    = sett; break;
+            		case 3 : hash        = Integer.valueOf(sett).intValue(); break;
+            		case 4 : numrunnings = Integer.valueOf(sett).intValue(); break;
+            		case 5 : numplayings = Integer.valueOf(sett).intValue(); break;
+            		case 6 : uniqueid    = Integer.valueOf(sett).intValue(); break;
+            		case 7 : scrollpos   = Integer.valueOf(sett).intValue(); break;
+            		default: recoverLevel(num,sett); break;
+            		}
+            	}
+            	catch( Exception ex )
+            	{
+            		Log.e(TAG_DB, "error retrieving preference "+String.valueOf(val)+" :"+ex.toString());
+            	}                     	     
+            }   
+        }
+	}
+
+///////////////////////////////////////////////////////////////////
+	  
+	private void recoverLevel(int id, String value)
+	{
+		int begin=0,end=0,lvlNum;
+		String tmp;
+
+		//Log.d(TAG_DB, "recovering level "+id+" :"+value);
+		
+		end = value.indexOf(" ", begin+1);
+
+		if( end<0 )
+		{
+			Log.e(TAG_DB, "error recovering level! value: "+value);
+			return;
+		}
+
+		tmp = value.substring(begin,end);
+		lvlNum = Integer.valueOf(tmp).intValue();
+		
+		recoverLevelData(id,lvlNum,end,value);
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	private void recoverLevelData(int id, int num, int begin, String value)
+	{
+		int end;
+		String tmp;
+		SokobanLevel sl;
+		int intrinsic   = INVALID;
+		int mytime      = INVALID;
+		int mymoves     = INVALID;
+		int worldtime   = INVALID;
+		int worldmoves  = INVALID;
+		String worldname   = "";
+		String worldcountry= "";
+		boolean submitted  = false;
+
+		// recover intrinsic num
+		end = value.indexOf(" ", begin+1);
+
+		if( end<0 )
+		{
+			Log.e(TAG_DB, "1 error recovering builtin level, value: "+value);
+			return;
+		}
+
+		try
+		{
+			tmp = value.substring( begin+1,end);
+			intrinsic = Integer.valueOf(tmp).intValue();
+		}
+		catch(Exception ex1 ) {Log.e(TAG_DB, "1: "+ex1.toString()); }
+
+		begin = end;
+
+		// recover mytime
+		end = value.indexOf(" ", begin+1);
+
+		if( end<0 )
+		{
+			Log.e(TAG_DB, "1 error recovering builtin level, value: "+value);
+			return;
+		}
+
+		try
+		{
+			tmp = value.substring( begin+1,end);
+			mytime = Integer.valueOf(tmp).intValue();
+		}
+		catch(Exception ex1 ) {Log.e(TAG_DB, "1: "+ex1.toString()); }
+
+		begin = end;
+
+		// recover mymoves
+		end = value.indexOf(" ", begin+1);
+
+		if( end<0 )
+		{
+			Log.e(TAG_DB, "2 error recovering builtin level, value: "+value);
+			return;
+		}
+
+		try
+		{
+			tmp = value.substring( begin+1,end);
+			mymoves = Integer.valueOf(tmp).intValue();
+		}
+		catch(Exception ex1 ) {Log.e(TAG_DB, "2: "+ex1.toString()); }
+
+		begin = end;
+
+		// recover worldtime
+		end = value.indexOf(" ", begin+1);
+
+		if( end<0 )
+		{
+			Log.e(TAG_DB, "3 error recovering builtin level, value: "+value);
+			return;
+		}
+
+		try
+		{
+			tmp = value.substring( begin+1,end);
+			worldtime = Integer.valueOf(tmp).intValue();
+		}
+		catch(Exception ex1 ) {Log.e(TAG_DB, "3: "+ex1.toString()); }
+
+		begin = end;
+
+		// recover worldmoves
+		end = value.indexOf(" ", begin+1);
+
+		if( end<0 )
+		{
+			Log.e(TAG_DB, "4 error recovering builtin level, value: "+value);
+			return;
+		}
+
+		try
+		{
+			tmp = value.substring( begin+1,end);
+			worldmoves = Integer.valueOf(tmp).intValue();
+		}
+		catch(Exception ex1 ) {Log.e(TAG_DB, "4: "+ex1.toString()); }
+
+		begin = end;
+
+		// 	recover worldname
+		end = value.indexOf(" ", begin+1);
+
+		if( end<0 )
+		{
+			Log.e(TAG_DB, "5 error recovering builtin level, value: "+value);
+			return;
+		}
+
+		try
+		{
+			worldname = value.substring( begin+1,end);
+		}
+		catch(Exception ex1 ) {Log.e(TAG_DB, "5: "+ex1.toString()); }
+
+		begin = end;
+
+		// recover worldcountry
+		end = value.indexOf(" ", begin+1);
+
+		if( end<0 )
+		{
+			Log.e(TAG_DB, "6 error recovering builtin level, value: "+value);
+			return;
+		}
+
+		try
+		{
+			worldcountry = value.substring( begin+1,end);
+		}
+		catch(Exception ex1 ) {Log.e(TAG_DB,"6: "+ex1.toString()); }
+
+		begin = end;
+
+		// recover submitted
+		end = value.indexOf(" ", begin+1);
+
+		if( end<0 )
+		{
+			Log.e(TAG_DB, "7 error recovering builtin level, value: "+value);
+			return;
+		}
+
+		try
+		{
+			tmp = value.substring( begin+1,end);
+			submitted = (Integer.valueOf(tmp).intValue()==1 ? true:false);
+		}
+		catch(Exception ex1 ) {Log.e(TAG_DB, "7: "+ex1.toString()); }
+
+		begin = end;
+
+		if( num<BUILTIN_LEVELS )
+		{
+			sl = SokobanLevels.getLevel(num);
+
+			if( sl==null ) { Log.e(TAG_DB, "Error recovering builtin level "+num); return; }
+
+		//	Log.d(TAG_DB, "setting my info: "+mymoves+" "+mytime+" "+username+" "+getCountry() );
+			
+			sl.setMyInfo(mymoves,mytime, username, getCountry() );
+			sl.addRecordInfo(worldmoves,worldtime,0,worldname,worldcountry);
+			sl.setSubmitted(submitted);
+			sl.setRecordId(id);
+		}
+		else
+		{
+			String author="", coun="", position="";
+			int cols=0;
+
+			// recover author
+			end = value.indexOf(" ", begin+1);
+
+			if( end<0 )
+			{
+				Log.e(TAG_DB, "8 error recovering builtin level, value: "+value);
+				return;
+			}
+
+			try
+			{
+				author = value.substring( begin+1,end);
+			}
+			catch(Exception ex1 ) {Log.e(TAG_DB, "8: "+ex1.toString()); }
+
+			begin = end;
+
+			// recover country
+			end = value.indexOf(" ", begin+1);
+
+			if( end<0 )
+			{
+				Log.e(TAG_DB, "9 error recovering builtin level, value: "+value);
+				return;
+			}
+
+			try
+			{
+				coun = value.substring( begin+1,end);
+			}
+			catch(Exception ex1 ) {Log.e(TAG_DB, "9: "+ex1.toString()); }
+
+			begin = end;
+
+			// recover cols
+			end = value.indexOf(" ", begin+1);
+
+			if( end<0 )
+			{
+				Log.e(TAG_DB, "10 error recovering builtin level, value: "+value);
+				return;
+			}
+
+			try
+			{
+				tmp = value.substring( begin+1,end);
+				cols = Integer.valueOf(tmp).intValue();
+			}
+			catch(Exception ex1 ) {Log.e(TAG_DB, "10: "+ex1.toString()); }
+
+			begin = end;
+
+			// recover position
+			end = value.indexOf(" ", begin+1);
+
+			if( end<0 )
+			{
+				Log.e(TAG_DB, "11 error recovering builtin level, value: "+value);
+				return;
+			}
+
+			try
+			{
+				position = value.substring( begin+1,end);
+			}
+			catch(Exception ex1 ) {Log.e(TAG_DB, "11: "+ex1.toString()); }
+
+			begin = end;
+
+	//		Log.d(TAG_DB, "loading created level: "+author+" "+coun+" "+mymoves+" "+mytime);
+			
+			SokobanRecordInfo sri = new SokobanRecordInfo(worldmoves,worldtime,worldname,worldcountry);
+			sl = new SokobanLevel(author,coun,mymoves,mytime,sri,submitted,cols,position);
+			mLevels.insertLevel(sl,num,intrinsic,id);
+		}	
+}
+
+///////////////////////////////////////////////////////////////////
+	
+	private int getDeviceID()
+	{	
+		int ret;
+		
+		try
+		  {
+		  String s = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);	
+		  ret = s!=null ? s.hashCode():0;
+		  }
+		catch(Exception ex)
+		  {
+		  ret =0;
+		  Log.e(TAG_DB, "Exception in getDeviceID()");	
+		  }
+		
+		return ret<0 ? -ret:ret;
+	}	  
+
+///////////////////////////////////////////////////////////////////
+	
+	public static boolean saveValues()
+	    {
+		//Log.e(TAG_DB, "saveValues: "+finishedBootup);
+		
+	    if( finishedBootup==false ) return false;
+
+	    boolean ret = false;
+	   
+	    numrunnings++;
+	    hash = computeHash();
+	    scrollpos = SokobanLevels.getScroll();
+	    
+	    try
+	      {
+          SharedPreferences settings = context.getSharedPreferences(PREFS_NAME,Context.MODE_PRIVATE);
+          SharedPreferences.Editor editor = settings.edit();
+	      
+          editor.putString("1", username);
+          editor.putString("2", veriname);
+          editor.putInt("3", hash);
+          editor.putInt("4", numrunnings);
+          editor.putInt("5", numplayings);
+          editor.putInt("6", uniqueid);
+          editor.putInt("7", scrollpos);
+        
+         // Log.d(TAG_DB, "saving: username="+username+" veriname="+veriname+" hash="+hash+" numrunnings="+numrunnings+" numplayings="+numplayings+" uniqueid="+uniqueid+" scrollpos="+scrollpos);
+  		
+	      if( saveLevels(editor)==false ) return false;
+
+	      editor.commit();
+	      ret = true;
+	      }
+	    catch( Exception ex)
+	      {
+	      Log.e(TAG_DB, "Failed to save preferences: "+ex.toString() );	
+	      }
+
+	    return ret;
+	    }
+ 
+///////////////////////////////////////////////////////////////////
+
+	private static boolean saveLevels(SharedPreferences.Editor editor)
+	{
+		String tmp;
+		int sb;
+		SokobanLevel level;
+		SokobanRecordInfo wr;
+
+		for(int i=0; ; i++)
+		{
+			level = SokobanLevels.getLevel(i);
+			if( level==null ) break;
+
+			if( level.isDirty() )
+			{
+				wr = level.getRecordInfo(0);
+				sb = level.isSubmitted()==true?1:0;
+
+				if( wr!=null )
+					tmp = i+" "+level.getIntrinsicNum()+" "+level.getMyTime()+" "+
+						  level.getMyMoves()+" "+wr.getTime()+" "+wr.getMove()+" "+
+						  wr.getName()+" "+wr.getCountry()+" "+sb+" ";
+				else
+					tmp = i+" "+level.getIntrinsicNum()+" "+level.getMyTime()+" "+
+						  level.getMyMoves()+" "+INVALID+" "+INVALID+" unk unk "+sb+" ";
+
+				if( i>=BUILTIN_LEVELS )
+				{
+					tmp+=level.getAuthor()+" "+level.getCountry()+" "+level.getCols()+" "+level.encodeLevel()+" ";
+				}
+
+				editor.putString(String.valueOf(level.getRecordId()), tmp);
+				
+				//Log.d(TAG_DB, "saving level "+i+" record id:"+level.getRecordId()+": "+tmp);
+				
+			}
+		}
+
+		return true;
+	}
+	
+///////////////////////////////////////////////////////////////////
+
+	public static void init(Activity act)
+	{
+		rms = new SokobanDatabase((Context)act);
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	private static int computeHash()
+	{
+		 
+		final int MODULO = 227;
+		int ret = 0;
+		SokobanLevel sl;
+
+		for(int i=0; ; i++)
+		   {
+		   sl = SokobanLevels.getLevel(i);
+		   if( sl==null ) break;
+
+		   ret +=   sl.getMyMoves();
+		   ret += 2*sl.getMyTime();
+		   }
+
+		int length = veriname==null ? 0 : veriname.length();
+
+		for(int i=0;i<length;i++)
+		   ret += i*veriname.charAt(i);
+
+		return (ret%=MODULO);
+	}
+	
+///////////////////////////////////////////////////////////////////
+
+	public static int getNumRunnings()
+	{
+		return numrunnings;
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public static int getId()
+	{
+	    return uniqueid;
+	}
+
+///////////////////////////////////////////////////////////////////
+	
+	public static int getNumPlayings()
+	{
+		return numplayings;
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public static void incNumPlayings()
+	{
+		numplayings++;
+	}
+
+///////////////////////////////////////////////////////////////////
+	
+	public static void setName(String newname)
+	{
+		username = newname;
+	}
+
+///////////////////////////////////////////////////////////////////
+	
+	public static String getName()
+	{
+		return username;
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public static void setVeri(String newveri)
+	{
+		veriname = newveri;
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public static String getVeri()
+	{
+		return veriname;
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public static SokobanDatabase getInstance()
+	{
+		return rms;
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public static String getCountry()
+	{
+		if( iso==null ) iso = SokobanCanvas.getIso();
+	
+		char digit1, digit2;
+		
+		try
+		  {
+		  digit1 = iso.charAt(0);
+		  digit2 = iso.charAt(1);
+		  }
+		catch( Exception ex )
+		  {
+		  return "usa";	
+		  }
+		
+        if (digit1 == 'a')
+        {
+            if (digit2=='z') return "aze";
+            if (digit2=='e') return "uae";
+            if (digit2=='f') return "afg";
+            if (digit2=='u') return "aus";
+            if (digit2=='r') return "arg";
+            if (digit2=='t') return "aut";
+            if (digit2=='d') return "and";
+            if (digit2=='m') return "arm";
+            if (digit2=='l') return "alb";
+        }
+        else if (digit1 == 'b')
+        {
+            if (digit2=='t') return "bhu";
+            if (digit2=='h') return "bah";
+            if (digit2=='d') return "ban";
+            if (digit2=='n') return "bru";
+            if (digit2=='o') return "bol";
+            if (digit2=='r') return "bra";
+            if (digit2=='z') return "blz";
+            if (digit2=='a') return "bos";
+            if (digit2=='y') return "blr";
+            if (digit2=='g') return "bul";
+            if (digit2=='e') return "bel";
+        }
+        else if (digit1 == 'c')
+        {
+            if (digit2=='a') return "can";
+            if (digit2=='n') return "chn";
+            if (digit2=='o') return "col";
+            if (digit2=='l') return "chi";
+            if (digit2=='u') return "cub";
+            if (digit2=='r') return "cos";
+            if (digit2=='z') return "cze";
+            if (digit2=='h') return "swi";
+            if (digit2=='y') return "cyp";
+        }
+        else if (digit1 == 'd')
+        {
+            if (digit2=='o') return "dom";
+            if (digit2=='e') return "ger";
+            if (digit2=='k') return "den";
+            if (digit2=='j') return "dij";
+            if (digit2=='z') return "alg";
+        }
+        else if (digit1 == 'e')
+        {
+            if (digit2=='c') return "ecu";
+            if (digit2=='e') return "est";
+            if (digit2=='s') return "esp";
+            if (digit2=='g') return "egy";
+        }
+        else if (digit1 == 'f')
+        {
+            if (digit2=='k') return "fal";
+            if (digit2=='i') return "fin";
+            if (digit2=='r') return "fra";
+        }
+        else if (digit1 == 'g')
+        {
+            if (digit2=='e') return "geo";
+            if (digit2=='f') return "fgu";
+            if (digit2=='y') return "guy";
+            if (digit2=='u') return "gum";
+            if (digit2=='t') return "gua";
+            if (digit2=='b') return "uk";
+            if (digit2=='i') return "gib";
+            if (digit2=='q') return "egu";
+            if (digit2=='r') return "gre";
+        }
+        else if (digit1 == 'h')
+        {
+            if (digit2=='k') return "hk";
+            if (digit2=='t') return "hai";
+            if (digit2=='n') return "hon";
+            if (digit2=='r') return "cro";
+            if (digit2=='u') return "hun";
+        }
+        else if (digit1 == 'i')
+        {
+            if (digit2=='r') return "irn";
+            if (digit2=='l') return "isr";
+            if (digit2=='q') return "irq";
+            if (digit2=='n') return "ind";
+            if (digit2=='d') return "ina";
+            if (digit2=='t') return "ita";
+            if (digit2=='e') return "irl";
+            if (digit2=='s') return "isl";
+        }
+        else if (digit1 == 'j')
+        {
+            if (digit2=='o') return "jor";
+            if (digit2=='m') return "jam";
+            if (digit2=='p') return "jap";
+        }
+        else if (digit1 == 'k')
+        {
+            if (digit2=='z') return "kaz";
+            if (digit2=='g') return "kyr";
+            if (digit2=='w') return "kuw";
+            if (digit2=='h') return "cam";
+            if (digit2=='p') return "prk";
+            if (digit2=='r') return "kor";
+            if (digit2=='e') return "ken";
+        }
+        else if (digit1 == 'l')
+        {
+            if (digit2=='b') return "leb";
+            if (digit2=='k') return "cey";
+            if (digit2=='a') return "lao";
+            if (digit2=='i') return "lie";
+            if (digit2=='v') return "lat";
+            if (digit2=='t') return "lit";
+            if (digit2=='u') return "lux";
+            if (digit2=='y') return "lib";
+        }
+        else if (digit1 == 'm')
+        {
+            if (digit2=='n') return "mon";
+            if (digit2=='v') return "mld";
+            if (digit2=='m') return "bir";
+            if (digit2=='o') return "mac";
+            if (digit2=='y') return "mly";
+            if (digit2=='x') return "mex";
+            if (digit2=='k') return "mna";
+            if (digit2=='e') return "mnt";
+            if (digit2=='c') return "mco";
+            if (digit2=='d') return "mda";
+            if (digit2=='t') return "mal";
+            if (digit2=='a') return "mor";
+            if (digit2=='l') return "mli";
+        }
+        else if (digit1 == 'n')
+        {
+            if (digit2=='p') return "nep";
+            if (digit2=='z') return "nz";
+            if (digit2=='i') return "nic";
+            if (digit2=='o') return "nor";
+            if (digit2=='l') return "ned";
+            if (digit2=='g') return "nig";
+        }
+        else if (digit1 == 'o')
+        {
+            if (digit2=='m') return "omn";
+        }
+        else if (digit1 == 'p')
+        {
+            if (digit2=='k') return "pak";
+            if (digit2=='g') return "pap";
+            if (digit2=='h') return "phi";
+            if (digit2=='y') return "par";
+            if (digit2=='e') return "per";
+            if (digit2=='m') return "miq";
+            if (digit2=='a') return "pan";
+            if (digit2=='l') return "pol";
+            if (digit2=='t') return "por";
+        }
+        else if (digit1 == 'q')
+        {
+            if (digit2=='q') return "qat";
+        }
+        else if (digit1 == 'r')
+        {
+            if (digit2=='u') return "rus";
+            if (digit2=='o') return "rom";
+            if (digit2=='s') return "srb";
+        }
+        else if (digit1 == 's')
+        {
+            if (digit2=='a') return "sar";
+            if (digit2=='y') return "syr";
+            if (digit2=='g') return "sin";
+            if (digit2=='r') return "sur";
+            if (digit2=='v') return "sal";
+            if (digit2=='e') return "swe";
+            if (digit2=='k') return "svk";
+            if (digit2=='i') return "slo";
+            if (digit2=='m') return "sma";
+            if (digit2=='n') return "sen";
+        }
+        else if (digit1 == 't')
+        {
+            if (digit2=='m') return "tkm";
+            if (digit2=='j') return "tjk";
+            if (digit2=='r') return "tur";
+            if (digit2=='w') return "twn";
+            if (digit2=='h') return "tha";
+            if (digit2=='n') return "tun";
+        }
+        else if (digit1 == 'u')
+        {
+            if (digit2=='z') return "uzb";
+            if (digit2=='y') return "uru";
+            if (digit2=='s') return "usa";
+            if (digit2=='a') return "ukr";
+        }
+        else if (digit1 == 'v')
+        {
+            if (digit2=='n') return "vie";
+            if (digit2=='e') return "ven";
+        }
+        else if (digit1 == 'y')
+        {
+            if (digit2=='e') return "yem";
+        }
+        else if (digit1 == 'z')
+        {
+            if (digit2=='a') return "za";
+        }
+        
+    return "unk";
+}
+	
+///////////////////////////////////////////////////////////////////
+// end of SokobanDatabase
+}
\ No newline at end of file
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanLevel.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanLevel.java
new file mode 100644
index 0000000..7cd587b
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanLevel.java
@@ -0,0 +1,1117 @@
+package com.threedcell.sokoban;
+
+import java.util.Vector;
+
+import android.graphics.Bitmap;
+import android.graphics.Paint;
+import android.graphics.Canvas;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.Style;
+
+import android.content.Context;
+
+//import android.util.Log;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class SokobanLevel
+  {
+  public static final int COLOR_BACK = 0xff6a7900;
+  public static final int COLOR_GRID = 0xff2e3500;
+  public static final int COLOR_EMPT = 0xffffffff;
+  public static final int COLOR_CRES = 0xff0000ff;
+  
+  private static final int MAX_PACKS = 100;    
+  
+  public static final int WALL = 0;
+  public static final int EMPT = 1;
+  public static final int DEST = 2;
+  public static final int PACK = 3;
+  public static final int DPCK = 4;
+  public static final int PLAY = 5;
+  public static final int PLAD = 6;
+
+  private static final int DIR_N = 0;
+  private static final int DIR_W = 1;
+  private static final int DIR_E = 2;
+  private static final int DIR_S = 3;
+ 
+  private static final int SHOWING_MINE = 0;
+  private static final int SHOWING_RECO = 1;
+  
+  private static int mShowing = SHOWING_MINE;
+  
+  private static int sWidth, sHeight;
+  private static int mGapI, mGapO;
+  private static int smallSize;
+  private static int mMaxRecords;
+
+  private int numLevel, intrinsicNumLevel, recordId=-1;
+  private boolean mDirty = false;
+  private String author, country;
+  private static String strAuthor, strLevel, strYourBest, strWorldsBest;
+  private Bitmap cImg;
+  private boolean submitted;
+  private static Paint mPaint = new Paint();
+  private static int mRecordH;
+  
+  private int mRows, mCols, mPacks;
+  private byte[][] cells;
+  private byte[][] movableS, movableC;
+
+  static class Move
+    {
+    byte index;
+    byte move;
+
+    public Move(int i, int m)
+      {
+      index = (byte)i;
+      move  = (byte)m;
+      }
+    }
+  private static Vector<Move> moves = new Vector<Move>();
+
+  private SokobanRecordInfo[] recordList;
+  private SokobanRecordInfo recordMine;
+
+  private static byte[][] validateScratch;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public SokobanLevel(Context context, int width,int height, int gap)
+  {  
+      submitted = false;
+      author    = null;
+      country   = null;
+      cImg      = null;
+      recordMine= new SokobanRecordInfo();
+
+      movableC = new byte[MAX_PACKS+1][2];
+      movableS = new byte[MAX_PACKS+1][2];
+
+      strAuthor     = context.getString(R.string.author);
+      strLevel      = context.getString(R.string.level);
+      strYourBest   = context.getString(R.string.yourbest);
+      strWorldsBest = context.getString(R.string.worldsbest);
+
+      mPaint.setAntiAlias(true);
+      mPaint.setStyle(Style.FILL);
+
+      allocate(width,height,gap);
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+  
+  public SokobanLevel(String a, String c, int mm, int mt, SokobanRecordInfo w, boolean sb, int cols, String position )
+  {
+      submitted= sb;
+
+      author = a;
+      country= c;
+      
+      recordMine = new SokobanRecordInfo(mm,mt,SokobanDatabase.getName(),SokobanDatabase.getCountry());
+
+      cutAuthor();
+
+      cImg = (author==null ? null:SokobanLevels.getInstance().getFlag(c));
+      
+      recordList = new SokobanRecordInfo[mMaxRecords];
+      for(int i=0; i<mMaxRecords; i++) recordList[i]=null;
+
+      recordList[0] = w;
+
+      decodeLevel(cols,position);
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void allocate(int width,int height, int gap)
+  {
+      sWidth = width;
+      sHeight= height-gap+2;
+       
+      mCols  = SokobanLevels.bDrawnX1;
+      mRows  = SokobanLevels.bDrawnY1;
+
+      mGapI = SokobanLevels.mGapI;
+      mGapO = SokobanLevels.mGapO;
+      smallSize = SokobanLevels.backSmallH;
+      
+      mRecordH = (int)(SokobanLevels.levelInfoH*0.4);
+      if( mRecordH<SokobanLevels.FLAG_H+2 ) mRecordH = SokobanLevels.FLAG_H+2;
+      
+      mMaxRecords = (SokobanLevels.levelBigH - mGapI - (int)(SokobanLevels.levelInfoH*0.4) )/mRecordH;
+    		  
+      validateScratch = new byte[mRows][mCols]; 
+      cells = new byte[mRows][mCols];
+      
+      recordList = new SokobanRecordInfo[mMaxRecords];
+      for(int i=0; i<mMaxRecords; i++) recordList[i]=null;
+
+      resetCreated();
+  }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+  
+  public void resetCreated()
+  {
+      for(int row=0; row<mRows; row++)
+        for( int col=0; col<mCols; col++)
+          {
+          cells[row][col] = WALL;
+          }
+
+      movableC[0][0] = (byte)(SokobanLevels.bDrawnX1/2);
+      movableC[0][1] = (byte)(SokobanLevels.bDrawnY1/2);
+      movableS[0][0] = (byte)(SokobanLevels.bDrawnX1/2);
+      movableS[0][1] = (byte)(SokobanLevels.bDrawnY1/2);
+
+      mPacks = 0;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void cutAuthor()
+  {
+    if( author!=null )
+      {  
+      mPaint.setTextSize(SokobanRecordInfo.getFontSize());	
+    	
+      float len2 = mPaint.measureText(strAuthor);
+      float len1 = mPaint.measureText(author);
+      int len0 = SokobanLevels.levelInfoW-10-28;
+      
+      if( len1+len2>len0 )
+        {
+        int l = author.length();
+
+        while( l>=2 && len1+len2>len0 )
+          {
+          l--;
+          author = author.substring(0,l);
+          len1 = mPaint.measureText(author);
+          }
+        }
+      }  
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void drop(int stuff)
+  {
+      int row = movableC[0][1];
+      int col = movableC[0][0];
+
+      switch(stuff)
+        {
+        case WALL: cells[row][col] = WALL;
+                   removePacksFrom(row,col);
+                   break;
+        case EMPT: cells[row][col] = EMPT;
+                   removePacksFrom(row,col);
+                   break;
+        case DEST: cells[row][col] = DEST;
+                   break;
+        case PACK: if( mPacks<MAX_PACKS )
+                     {
+                     if( cells[row][col]==WALL ) cells[row][col]=EMPT;
+                     mPacks++;
+                     movableC[mPacks][0] = (byte)col;
+                     movableC[mPacks][1] = (byte)row;
+                     movableS[mPacks][0] = (byte)col;
+                     movableS[mPacks][1] = (byte)row;
+                     }
+                   break;
+        }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void removePacksFrom(int row, int col)
+  {
+       for(int i=1; i<=mPacks; i++)
+         if( movableC[i][0]==col && movableC[i][1]==row )
+            {
+            movableC[i][0] = movableC[mPacks][0];
+            movableC[i][1] = movableC[mPacks][1];
+            movableS[i][0] = movableS[mPacks][0];
+            movableS[i][1] = movableS[mPacks][1];
+            mPacks--;
+            break;
+            }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int validate()
+  {
+      if( cells[movableC[0][1]][movableC[0][0]]==WALL ) return -1;
+      if( hasPack(movableC[0][1], movableC[0][0])!=0 )  return -2;
+      if( isDisconnected() )                            return -3;
+      if( mPacks<1 )                                    return -4;
+      if( isSolved() )                                  return -5;
+      
+      int numDest=0;
+
+      for(int row=0; row<mRows; row++)
+        for( int col=0; col<mCols; col++)
+          {
+          if( cells[row][col]==DEST ) numDest++;
+          }
+
+      if( mPacks != numDest ) return numDest+1;
+
+      return 0;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private boolean isDisconnected()
+  {
+      int numOfOnes=-1;
+
+      for(int row=0; row<mRows; row++)
+        for( int col=0; col<mCols; col++)
+          {
+          if( cells[row][col]==WALL ) validateScratch[row][col]=0;
+          else
+            {
+            validateScratch[row][col]=1;
+            numOfOnes++;
+            }
+          }
+
+      validateScratch[movableC[0][1]][movableC[0][0]] = 2;
+
+      int marked = 1;
+
+      while( marked>0 )
+        {
+        marked=0;
+
+        for(int row=0; row<mRows; row++)
+          {
+          for( int col=0; col<mCols; col++)
+            {
+            if( validateScratch[row][col]==1 )
+              {
+              if( ( row>0       && validateScratch[row-1][col]==2 ) ||
+                  ( row+1<mRows && validateScratch[row+1][col]==2 ) ||
+                  ( col>0       && validateScratch[row][col-1]==2 ) ||
+                  ( col+1<mCols && validateScratch[row][col+1]==2 )  )
+                {
+                validateScratch[row][col]=2;
+                marked++;
+                }
+              }
+            }
+          }
+        numOfOnes-=marked;
+        }
+
+      return (numOfOnes>0);
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void decodeLevel(int cols, String position)
+  {
+      int tmp;
+      mPacks=0;
+
+      try
+        {
+        mCols = cols;
+        mRows = position.length()/cols;
+
+        cells = new byte[mRows][mCols];
+
+        for(int row=0; row<mRows; row++)
+          for( int col=0; col<mCols; col++)
+            {
+            tmp = position.charAt(row*mCols+col)-'0';
+
+            switch(tmp)
+              {
+              case PACK: cells[row][col] = EMPT; mPacks++; break;
+              case DPCK: cells[row][col] = DEST; mPacks++; break;
+              case WALL: cells[row][col] = WALL; break;
+              case EMPT: cells[row][col] = EMPT; break;
+              case DEST: cells[row][col] = DEST; break;
+              case PLAY: cells[row][col] = EMPT; break;
+              case PLAD: cells[row][col] = DEST; break;
+              }
+            }
+
+        movableS = new byte[mPacks+1][2];
+        movableC = new byte[mPacks+1][2];
+
+        int num=1;
+
+        for(int row=0; row<mRows; row++)
+          for( int col=0; col<mCols; col++)
+            {
+            tmp = position.charAt(row*mCols+col)-'0';
+
+            if( tmp==PACK || tmp==DPCK )
+              {
+              movableS[num][0]= (byte)col;
+              movableS[num][1]= (byte)row;
+              movableC[num][0]= (byte)col;
+              movableC[num][1]= (byte)row;
+              num++;
+              }
+            if( tmp==PLAY || tmp==PLAD )
+              {
+              movableS[0][0] = (byte)col;
+              movableS[0][1] = (byte)row;
+              movableC[0][0] = (byte)col;
+              movableC[0][1] = (byte)row;
+              }
+            }
+        }
+      catch( Exception ex)
+        {
+        System.out.println("Exception trying to parse level: "+ex.toString());
+        }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public String encodeLevel()
+  {
+      int beginC=0, endC=0, beginR=0, endR=0;
+      boolean allWalls=true;
+
+      for(int col=0; col<mCols && allWalls; col++)
+        {
+        for(int row=0; row<mRows; row++)
+          {
+          if( cells[row][col]!=WALL ) { allWalls=false; break; }
+          }
+
+        if( allWalls ) beginC++;
+        }
+
+      allWalls=true;
+
+      for(int col=mCols-1; col>=0 && allWalls; col--)
+        {
+        for(int row=0; row<mRows; row++)
+          {
+          if( cells[row][col]!=WALL ) { allWalls=false; break; }
+          }
+
+        if( allWalls ) endC++;
+        }
+
+      allWalls=true;
+
+      for(int row=0; row<mRows && allWalls; row++)
+        {
+        for(int col=0; col<mCols; col++)
+          {
+          if( cells[row][col]!=WALL ) { allWalls=false; break; }
+          }
+
+        if( allWalls ) beginR++;
+        }
+
+      allWalls=true;
+
+      for(int row=mRows-1; row>=0 && allWalls; row--)
+        {
+        for(int col=0; col<mCols; col++)
+          {
+          if( cells[row][col]!=WALL ) { allWalls=false; break; }
+          }
+
+        if( allWalls ) endR++;
+        }
+
+      int index;
+      StringBuffer ret = new StringBuffer();
+
+      for(int row=beginR; row<mRows-endR; row++)
+        for( int col=beginC; col<mCols-endC; col++)
+          {
+          switch( cells[row][col])
+            {
+            case WALL: ret.append('0'); break;
+            case EMPT: ret.append('1'); break;
+            case DEST: ret.append('2'); break;
+            }
+          }
+
+      char setTo = (cells[movableS[0][1]][movableS[0][0]]==DEST ? '6':'5');
+
+      ret.setCharAt( (movableS[0][1]-beginR)*(mCols-beginC-endC)+(movableS[0][0]-beginC), setTo);
+
+      for(int i=1; i<=mPacks; i++)
+        {
+        index = (movableS[i][1]-beginR)*(mCols-beginC-endC)+(movableS[i][0]-beginC);
+        ret.setCharAt(index, (ret.charAt(index)=='1' ? '3' : '4'));
+        }
+
+      return ret.toString();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+ 
+  public void setRecordId(int id)
+  {
+     recordId = id;
+  }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+ 
+  public int getRecordId()
+  {
+     return recordId;
+  }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+ 
+  public void setDirty()  
+  {
+     mDirty = true;
+  }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+ 
+  public boolean isDirty()
+  {
+     return mDirty;
+  }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+ 
+  public void resetPrivate()
+  {  
+      recordMine.set(SokobanDatabase.INVALID, SokobanDatabase.INVALID, SokobanDatabase.getName(),SokobanDatabase.getCountry());
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getMyTime()
+  {
+      return recordMine.getTime();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void setName(String n)
+  {
+      recordMine.set(n);
+  }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void setMyInfo(int m, int t, String n, String c)
+  {
+      recordMine.set(m, t, n, c);
+  }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getMyMoves()
+  {
+      return recordMine.getMove();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public SokobanRecordInfo getRecordInfo(int num)
+  {
+      return (num>=0 && num<mMaxRecords ? recordList[num]:null);
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public boolean isSubmitted()
+  {
+      return submitted;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void setSubmitted(boolean sb)
+  {
+      submitted = sb;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void setNum(int num)
+  {
+      numLevel = num;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void setIntrinsicNum(int num)
+  {
+      intrinsicNumLevel = num;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getIntrinsicNum()
+  {
+      return intrinsicNumLevel;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getCols()
+  {
+      int begin=0, end=0;
+      boolean allWalls=true;
+
+      for(int col=0; col<mCols && allWalls; col++)
+        {
+        for(int row=0; row<mRows; row++)
+          {
+          if( cells[row][col]!=WALL ) { allWalls=false; break; }
+          }
+
+        if( allWalls ) begin++;
+        }
+
+      allWalls=true;
+
+      for(int col=mCols-1; col>=0 && allWalls; col--)
+        {
+        for(int row=0; row<mRows; row++)
+          {
+          if( cells[row][col]!=WALL ) { allWalls=false; break; }
+          }
+
+        if( allWalls ) end++;
+        }
+
+      return mCols-begin-end;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public String getAuthor()
+  {
+      return author==null ? "":author;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public String getCountry()
+  {
+      return country==null ? "":country;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void addRecordInfo(int m, int t,int p, String n, String c)
+  {
+      if( p>=0 && p<mMaxRecords )
+        {
+    	if( recordList[p]==null ) recordList[p] = new SokobanRecordInfo(m,t,n,c);
+        else recordList[p].set(m,t,n,c);
+        }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void rollback()
+  {
+     for(int i=0; i<=mPacks; i++) 
+       {
+       movableC[i][0] = movableS[i][0];
+       movableC[i][1] = movableS[i][1];
+       }
+
+     moves.removeAllElements();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public boolean canWithdraw()
+  {
+     return moves.size()>0;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public boolean withdraw()
+  {
+     int size = moves.size();
+
+     if( size>0 )
+       {
+       Move m = (Move)moves.lastElement();
+       int index = (int)m.index;
+       moves.removeElementAt(size-1);
+
+       switch(m.move)
+         {
+         case DIR_W: movableC[0][0]++; if( index>0 ) movableC[index][0]++; break;
+         case DIR_E: movableC[0][0]--; if( index>0 ) movableC[index][0]--; break;
+         case DIR_N: movableC[0][1]++; if( index>0 ) movableC[index][1]++; break;
+         case DIR_S: movableC[0][1]--; if( index>0 ) movableC[index][1]--; break;
+         }
+       return true;
+       }
+
+     return false;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public boolean isSolved()
+  {
+     for(int i=1; i<=mPacks; i++)
+        {
+        if( cells[movableC[i][1]][movableC[i][0]]!=DEST ) return false;
+        }
+
+     return true;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int hasPack(int row, int col)
+  {
+     for(int i=1; i<=mPacks; i++)
+        {
+        if( movableC[i][0]==col && movableC[i][1]==row ) return i;
+        }
+
+     return 0;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int retDir(int dx, int dy)
+  {
+      if( dx>=dy ) return (dx>=-dy ? DIR_W:DIR_S);
+      else         return (dx>=-dy ? DIR_N:DIR_E);
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public boolean movePlayerFreely(int dx, int dy)
+  {
+      switch( retDir(dx,dy) )
+      {
+          case DIR_W: if( movableC[0][0]>0       ) { movableC[0][0]--; movableS[0][0]--; return true; }
+                      return false;
+          case DIR_E: if( movableC[0][0]+1<mCols ) { movableC[0][0]++; movableS[0][0]++; return true; }
+                      return false;
+          case DIR_N: if( movableC[0][1]>0       ) { movableC[0][1]--; movableS[0][1]--; return true; }
+                      return false;
+          case DIR_S: if( movableC[0][1]+1<mRows ) { movableC[0][1]++; movableS[0][1]++; return true; }
+                      return false;      
+      }
+
+      return false;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public boolean movePlayer(int dx,int dy)
+  { 
+      int row = movableC[0][1];
+      int col = movableC[0][0];
+      int pack;
+
+      switch( retDir(dx,dy) )
+      {
+           case DIR_N: if( row>0 && cells[row-1][col]!=WALL )
+                         {
+                         pack = hasPack(row-1,col);
+
+                         if( pack==0 )
+                           {
+                           movableC[0][1]--;
+                           moves.addElement( new Move(pack, DIR_N) );
+                           return true;
+                           }
+                         else if( row>1 && cells[row-2][col]!=WALL && hasPack(row-2,col)==0 )
+                           {
+                           movableC[pack][1]--;
+                           movableC[0][1]--;
+                           moves.addElement( new Move(pack, DIR_N) );
+                           return true;
+                           }
+                         }
+                       break;
+           case DIR_S: if( row+1<mRows && cells[row+1][col]!=WALL )
+                         {
+                         pack = hasPack(row+1,col);
+                         
+                         if( pack==0 )
+                           {
+                           movableC[0][1]++;
+                           moves.addElement( new Move(pack, DIR_S) );
+                           return true;
+                           }
+                         else if( row+2<mRows && cells[row+2][col]!=WALL && hasPack(row+2,col)==0 )
+                           {
+                           movableC[pack][1]++;
+                           movableC[0][1]++;
+                           moves.addElement( new Move(pack, DIR_S) );
+                           return true;
+                           }
+                         }
+                       break;
+           case DIR_W: if( col>0 && cells[row][col-1]!=WALL )
+                         {
+                         pack = hasPack(row,col-1);
+
+                         if( pack==0 )
+                           {
+                           movableC[0][0]--;
+                           moves.addElement( new Move(pack, DIR_W) );
+                           return true;
+                           }
+                         else if( col>1 && cells[row][col-2]!=WALL && hasPack(row,col-2)==0 )
+                           {
+                           movableC[pack][0]--;
+                           movableC[0][0]--;
+                           moves.addElement( new Move(pack, DIR_W) );
+                           return true;
+                           }
+                         }
+                       break;
+           case DIR_E: if( col+1<mCols && cells[row][col+1]!=WALL )
+                         {
+                         pack = hasPack(row,col+1);
+
+                         if( pack==0 )
+                           {
+                           movableC[0][0]++;
+                           moves.addElement( new Move(pack, DIR_E) );
+                           return true;
+                           }
+                         else if( col+2<mCols && cells[row][col+2]!=WALL && hasPack(row,col+2)==0 )
+                           {
+                           movableC[pack][0]++;
+                           movableC[0][0]++;
+                           moves.addElement( new Move(pack, DIR_E) );
+                           return true;
+                           }
+                         }
+                       break;
+      }
+
+      return false;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void renderRecords(Canvas c, int y1)
+    { 
+	if( mShowing==SHOWING_MINE )  
+	  {
+	  mShowing = SHOWING_RECO;
+	  SokobanLevelBuffer.invalidateAllR();
+	  }
+	c.drawBitmap( SokobanLevels.bkgUnClick, 0, y1, null);
+    
+    int buff, y= y1+mGapO/2+mGapI;
+    
+    buff= SokobanLevelBuffer.isLBuffered(numLevel);
+    
+    if( buff<0 )
+      {
+      buff = SokobanLevelBuffer.whereL(numLevel);	
+      
+      if( buff>=0 )
+        {
+        drawSmall(SokobanLevelBuffer.lC[buff]);
+        SokobanLevelBuffer.setLBuffered(buff, numLevel);
+        }
+    //  Log.e("Level", "renderRecords: drawSmall: level "+numLevel+" to bank "+buff);
+      }
+    if( buff>=0 ) c.drawBitmap( SokobanLevelBuffer.lB[buff],               mGapO+mGapI, y, null);
+    
+    buff= SokobanLevelBuffer.isRBuffered(numLevel);
+    
+    if( buff<0 )
+      {
+      buff = SokobanLevelBuffer.whereR(numLevel);
+      
+      if( buff>=0 )
+        {
+        drawRecords(SokobanLevelBuffer.rC[buff]);
+        SokobanLevelBuffer.setRBuffered(buff, numLevel);
+        }
+    //  Log.e("Level", "renderRecords: drawRecords: level "+numLevel+" to bank "+buff);
+      }
+    if( buff>=0 ) c.drawBitmap( SokobanLevelBuffer.rB[buff], mGapO+2*mGapI+smallSize-2, y, null);
+    }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+  
+  public void renderSmall(Canvas c, int y1, boolean clicked)
+  {
+	  if( mShowing==SHOWING_RECO )  
+        {
+        mShowing = SHOWING_MINE;
+        SokobanLevelBuffer.invalidateAllR();
+        }
+	  c.drawBitmap( clicked ? SokobanLevels.bkgClicked:SokobanLevels.bkgUnClick, 0, y1, null);
+      
+	  int buff, y = y1+mGapO/2+mGapI;
+	  
+	  buff= SokobanLevelBuffer.isLBuffered(numLevel);
+	    
+	  if( buff<0 )
+	    {
+	    buff = SokobanLevelBuffer.whereL(numLevel);	
+	    
+	    if( buff>=0 )
+	      {
+	      drawSmall(SokobanLevelBuffer.lC[buff]);
+	      SokobanLevelBuffer.setLBuffered(buff, numLevel);
+	      }
+	  //  Log.e("Level", "renderSmall: drawSmall: level "+numLevel+" to bank "+buff);
+	    }
+	  if( buff>=0 ) c.drawBitmap( SokobanLevelBuffer.lB[buff], mGapO+mGapI, y, null);
+	  
+	  buff= SokobanLevelBuffer.isRBuffered(numLevel);
+	    
+	  if( buff<0 )
+	    {
+	    buff = SokobanLevelBuffer.whereR(numLevel);	
+	    
+	    if( buff>=0 )
+	      {
+	      drawMine(SokobanLevelBuffer.rC[buff]);
+	      SokobanLevelBuffer.setRBuffered(buff, numLevel);
+	      }
+	  //  Log.e("Level", "renderSmall: drawMine: level "+numLevel+" to bank "+buff);
+	    }
+      if( buff>=0 ) c.drawBitmap( SokobanLevelBuffer.rB[buff], mGapO+2*mGapI+smallSize-2, y, null);    
+  }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void drawMine(Canvas c)
+    {   
+	int m = SokobanLevels.levelInfoW/2;
+    int h = (int)(SokobanLevels.levelInfoH*0.4);
+    
+    mPaint.setColor(SokobanLevels.COLOR_BLACK);
+	mPaint.setTextSize(h);
+	mPaint.setTextAlign(Align.CENTER);
+	  
+	c.drawBitmap( SokobanLevels.levelInfo, 0, 0                                 , null);
+	c.drawBitmap( SokobanLevels.levelInfo, 0,   (SokobanLevels.levelInfoH+mGapI), null);
+	c.drawBitmap( SokobanLevels.levelInfo, 0, 2*(SokobanLevels.levelInfoH+mGapI), null);
+      
+    if( author==null )
+      {
+      c.drawText(strLevel+" "+numLevel, m, SokobanLevels.levelInfoH/2+h/3, mPaint);
+      }
+    else
+      {
+      int h1 = 2+  SokobanLevels.levelInfoH/4+h/3;
+      int h2 =-2+3*SokobanLevels.levelInfoH/4+h/3;
+      int x1 = SokobanLevels.levelInfoW-3*mGapI/2-SokobanLevels.FLAG_W;
+        
+      c.drawText(strLevel+" "+numLevel, m, h1, mPaint);
+      mPaint.setTextAlign(Align.LEFT);
+      c.drawText(strAuthor, mGapI-2, h2+1, mPaint);
+      mPaint.setTextAlign(Align.RIGHT);
+      c.drawText(author    , x1          , h2+1                       , mPaint);
+      c.drawBitmap(cImg    , x1+mGapI/2+2, h2-SokobanRecordInfo.mCorr ,   null);
+      mPaint.setTextSize(h);
+      }
+
+    mPaint.setTextAlign(Align.CENTER);
+    c.drawText(strYourBest  , m, 2+  (SokobanLevels.levelInfoH+mGapI)+ SokobanLevels.levelInfoH/4+h/3 ,mPaint );
+    recordMine.draw( 0, -2+(SokobanLevels.levelInfoH+mGapI)+ 3*SokobanLevels.levelInfoH/4+h/3, c);
+    c.drawText(strWorldsBest, m, 2+2*(SokobanLevels.levelInfoH+mGapI)+ SokobanLevels.levelInfoH/4+h/3 ,mPaint );
+      
+    if( recordList[0]!=null )
+      recordList[0].draw( 0, -2+2*(SokobanLevels.levelInfoH+mGapI)+ 3*SokobanLevels.levelInfoH/4+h/3, c);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void drawRecords(Canvas c)
+    {
+    int h = (int)(SokobanLevels.levelInfoH*0.4);
+    int y=(h+mGapI/2);
+
+    mPaint.setColor(SokobanLevels.COLOR_BLACK);
+    mPaint.setTextSize(h);
+    mPaint.setTextAlign(Align.CENTER);
+
+    c.drawBitmap( SokobanLevels.levelBig, 0, 0, null);
+    c.drawText(strLevel+" "+numLevel, SokobanLevels.levelBigW/2, y, mPaint);
+
+    for(int i=0; i<mMaxRecords; i++)
+      {
+      if( recordList[i]!=null )
+        {
+        y+=mRecordH;    
+        recordList[i].draw(0,y,c);
+        }
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void drawSmall(Canvas c)
+  {
+      int tmpCol, tmpRow, dCol, dRow;
+      int v = SokobanLevels.sDrawnY-mRows;
+      int h = SokobanLevels.sDrawnX-mCols;
+      int cellx, celly;
+
+      int vgap = v<0 ? 0    :v/2;
+      int hgap = h<0 ? 0    :h/2;
+      int varr = v<0 ?-(v/2):  0;
+      int harr = h<0 ?-(h/2):  0;
+      int vlen = v<0 ? SokobanLevels.sDrawnY:mRows;
+      int hlen = h<0 ? SokobanLevels.sDrawnX:mCols;
+
+      c.drawBitmap(SokobanLevels.backgroundSmall, 0, 0, null);
+      
+      for(int row=varr; row<varr+vlen; row++)
+        for( int col=harr; col<harr+hlen; col++)
+          {
+          cellx = SokobanLevels.sMargin+(col+hgap-harr)*SokobanLevels.sCell;
+          celly = SokobanLevels.sMargin+(row+vgap-varr)*SokobanLevels.sCell;
+          
+          switch( cells[row][col] )
+            {
+            case EMPT: c.drawBitmap( SokobanLevels.emptySmall, cellx,celly, null);
+                       break;
+            case DEST: c.drawBitmap( SokobanLevels.destSmall , cellx,celly, null);
+                       break;
+            }
+          }
+
+      for(int i=0; i<=mPacks; i++)
+        {
+        tmpCol = movableS[i][0];
+        tmpRow = movableS[i][1];
+
+        dRow = tmpRow+vgap-varr;
+        dCol = tmpCol+hgap-harr;
+
+        if( dRow>=0 && dRow< +SokobanLevels.sDrawnY && dCol>=0 && dCol< +SokobanLevels.sDrawnX  )
+          {
+          cellx = SokobanLevels.sMargin+dCol*SokobanLevels.sCell;
+          celly = SokobanLevels.sMargin+dRow*SokobanLevels.sCell;
+
+          if( i==0 )
+        	  c.drawBitmap( SokobanLevels.playSmall , cellx,celly, null);
+          else if( cells[tmpRow][tmpCol]==DEST )
+        	  c.drawBitmap( SokobanLevels.dpckSmall , cellx,celly, null);
+          else
+        	  c.drawBitmap( SokobanLevels.packSmall , cellx,celly, null);
+          }
+        }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void renderBig(Canvas c, int x, int y)
+  {
+	  boolean isBig = (mRows>SokobanLevels.bDrawnY1);
+	  
+	  int drawnX, drawnY, gapX, gapY, bCell;
+	  
+	  if( isBig )
+	    {
+		drawnX = SokobanLevels.bDrawnX2;
+		drawnY = SokobanLevels.bDrawnY2;
+		gapX   = SokobanLevels.gapX2;
+		gapY   = SokobanLevels.gapY2;
+		bCell  = SokobanLevels.bCell2;
+	    }
+	  else
+	    {
+		drawnX = SokobanLevels.bDrawnX1;
+		drawnY = SokobanLevels.bDrawnY1;
+		gapX   = SokobanLevels.gapX1;
+		gapY   = SokobanLevels.gapY1;      
+		bCell  = SokobanLevels.bCell1;
+	    }
+	  
+      int i,tmpCol, tmpRow, dCol, dRow;
+      int v = drawnY-mRows;
+      int h = drawnX-mCols;
+      int cellx, celly;
+
+      int vgap = v<0 ? 0    :v/2;
+      int hgap = h<0 ? 0    :h/2;
+      int varr = v<0 ?-(v/2):  0;
+      int harr = h<0 ?-(h/2):  0;
+      int vlen = v<0 ? drawnY:mRows;
+      int hlen = h<0 ? drawnX:mCols;
+      
+      mPaint.setColor(COLOR_BACK);
+      c.drawRect(x,y-5, x+sWidth, y+sHeight+5, mPaint);
+      mPaint.setColor(COLOR_GRID);
+      
+      celly = y+gapY;
+      
+      for( i=0; i<=drawnY; i++ )
+        {
+    	c.drawRect(0, celly, sWidth, celly+SokobanLevels.bMargin , mPaint);
+    	celly+=bCell;
+    	}
+      
+      cellx = x+gapX;
+      
+      for( i=0; i<=drawnX; i++ ) 
+        {
+    	c.drawRect(cellx, y-5, cellx+SokobanLevels.bMargin,y+sHeight+5, mPaint);
+    	cellx+=bCell;
+    	}
+      
+      for(int row=varr; row<varr+vlen; row++)
+        for( int col=harr; col<harr+hlen; col++)
+          {
+          cellx = SokobanLevels.bMargin+x+gapX+(col+hgap-harr)*bCell;
+          celly = SokobanLevels.bMargin+y+gapY+(row+vgap-varr)*bCell;
+          
+          switch( cells[row][col] )
+            {
+            case EMPT: c.drawBitmap( isBig ? SokobanLevels.emptyBig2:SokobanLevels.emptyBig1, cellx,celly, null);
+                       break;
+            case DEST: c.drawBitmap( isBig ? SokobanLevels.destBig2 :SokobanLevels.destBig1 , cellx,celly, null);
+                       break;
+            }
+          }
+
+      for(i=0; i<=mPacks; i++)
+        {
+        tmpCol = movableC[i][0];
+        tmpRow = movableC[i][1];
+
+        dRow = tmpRow+vgap-varr;
+        dCol = tmpCol+hgap-harr;
+
+        if( dRow>=0 && dRow< drawnY && dCol>=0 && dCol< drawnX  )
+          {
+          cellx = SokobanLevels.bMargin+x+gapX+dCol*bCell;
+          celly = SokobanLevels.bMargin+y+gapY+dRow*bCell;
+
+          if( i==0 )
+        	  c.drawBitmap( isBig ? SokobanLevels.playBig2 : SokobanLevels.playBig1 ,cellx,celly, null);
+          else if( cells[tmpRow][tmpCol]==DEST )
+        	  c.drawBitmap( isBig ? SokobanLevels.dpckBig2 : SokobanLevels.dpckBig1 ,cellx,celly, null);
+          else
+        	  c.drawBitmap( isBig ? SokobanLevels.packBig2 : SokobanLevels.packBig1 ,cellx,celly, null);
+          }
+        }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// end of SokobanLevel class
+  }
\ No newline at end of file
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanLevelBuffer.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanLevelBuffer.java
new file mode 100644
index 0000000..84084c5
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanLevelBuffer.java
@@ -0,0 +1,157 @@
+package com.threedcell.sokoban;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+
+import android.util.Log;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class SokobanLevelBuffer 
+  {
+  public static int INVALID = -1;	
+	
+  private static int numBuffers;
+  private static int levelHeight;
+  private static int scrHeight;
+  
+  private static int[] lD;
+  private static int[] rD;
+
+  public static Canvas[] lC;
+  public static Canvas[] rC;
+  public static Bitmap[] lB;
+  public static Bitmap[] rB;
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+  
+  public SokobanLevelBuffer(int lh, int sh)
+    {
+	int tmp1 = (sh-SokobanLevels.mGap);
+	int tmp2 = tmp1/lh;
+	
+	numBuffers = (tmp2*lh == tmp1 ? tmp2+1:tmp2+2);
+	
+	lB = new Bitmap[numBuffers];
+	rB = new Bitmap[numBuffers];
+	lD = new int[numBuffers];
+	rD = new int[numBuffers];
+	lC = new Canvas[numBuffers];
+	rC = new Canvas[numBuffers];
+	
+    allocate(lh,sh);	
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+  public static void allocate(int lh,int sh)
+    {
+	levelHeight= lh;
+	scrHeight  = sh;
+		
+	for(int i=0; i<numBuffers; i++)
+	  {
+	  lB[i] = Bitmap.createBitmap( SokobanLevels.backSmallW, SokobanLevels.backSmallH,  Bitmap.Config.ARGB_8888 );
+	  rB[i] = Bitmap.createBitmap( SokobanLevels.levelBigW , SokobanLevels.backSmallH,  Bitmap.Config.ARGB_8888 );
+	  }
+		
+	invalidateAllL();
+	invalidateAllR();
+		
+	for(int i=0; i<numBuffers; i++)
+	  {
+	  lC[i] = new Canvas(lB[i]);
+	  rC[i] = new Canvas(rB[i]);
+	  }  
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+  
+  public static int isLBuffered(int lvl)
+    {
+	for(int i=0; i<numBuffers; i++) if( lD[i]==lvl ) return i;
+	return INVALID;
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static int isRBuffered(int lvl)
+    {
+    for(int i=0; i<numBuffers; i++) if( rD[i]==lvl ) return i;
+    return INVALID;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void setLBuffered(int num,int lvl)
+    {
+	lD[num]=lvl;  
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void setRBuffered(int num,int lvl)
+    {
+    rD[num]=lvl;  
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void invalidateAllL()
+    {
+	for(int i=0; i<numBuffers; i++)
+	  {
+	  lD[i]=INVALID;
+	  lB[i].eraseColor(0);
+	  }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void invalidateAllR()
+    {
+    for(int i=0; i<numBuffers; i++)
+      {
+      rD[i]=INVALID;
+      rB[i].eraseColor(0);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static int whereL(int lvl)
+    {
+	int scrollPos = SokobanLevels.getScroll();  
+	
+	int beg = 1+Math.max( scrollPos/levelHeight, 0);
+	int end = 1+(scrollPos+scrHeight-SokobanLevels.mGap)/levelHeight;
+	
+	for(int i=0; i<numBuffers; i++) 
+	  if( lD[i]<beg || lD[i]>end ) return i;
+	
+	Log.e("Buffer", "whereL lvl="+lvl+" beg="+beg+" end="+end+" returning -1");
+	
+	return INVALID;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static int whereR(int lvl)
+    {
+    int scrollPos = SokobanLevels.getScroll();  
+   
+    int beg = 1+Math.max( scrollPos/levelHeight, 0);
+    int end = 1+(scrollPos+scrHeight-SokobanLevels.mGap)/levelHeight;
+
+    for(int i=0; i<numBuffers; i++) 
+      if( rD[i]<beg || rD[i]>end ) return i;
+
+    Log.e("Buffer", "whereR lvl="+lvl+" beg="+beg+" end="+end+" returning -1");
+
+    return INVALID;
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// end of SokobanLevelBuffer class
+  }
\ No newline at end of file
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanLevels.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanLevels.java
new file mode 100644
index 0000000..3340612
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanLevels.java
@@ -0,0 +1,1152 @@
+package com.threedcell.sokoban;
+
+import android.graphics.Canvas;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Paint;
+import android.graphics.Region;
+import android.graphics.Paint.Style;
+import android.graphics.drawable.NinePatchDrawable;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+
+import android.util.Log;
+import android.util.DisplayMetrics;
+
+import java.util.Vector;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class SokobanLevels
+  {
+  private static final String TAG_LEVELS = "SokobanLevels";
+  
+  public static final int COLOR_GREEN = 0xff6a7900;
+  public static final int COLOR_BLACK = 0xff000000;
+  public static final int COLOR_WHITE = 0xffffffff;
+  public static final int COLOR_GRAY  = 0xff999999;
+  private static final int COLOR_EMPT = 0xaaffffff;
+ 
+  private static final int    SAMPLE_SIZE     =   5;
+  private static final double SPRING_CONST    = 1.8;
+  private static final int    MAX_SPRING_SPEED=   8;
+  private static final int    MIN_CLICK_DIST  =   8;
+  private static final int    PLAY_MIN_DIST   =  20;
+
+  public static final int FLAG_H = 15;
+  public static final int FLAG_W = 22;
+  
+  public static Bitmap emptyBig1 , packBig1, destBig1, dpckBig1, playBig1;
+  public static Bitmap emptyBig2 , packBig2, destBig2, dpckBig2, playBig2;
+  public static Bitmap backgroundSmall, destSmall, emptySmall, packSmall, playSmall, dpckSmall;
+  public static Bitmap bkgClicked, bkgUnClick;
+  public static Bitmap levelBig, levelInfo;
+  
+  private int levelHeight;
+
+  public static int mGap;
+  private int amountDrag = -1;
+  
+  private static boolean mVertical;
+  private static SokobanTimer timer =null;
+  private static SokobanLevels levels;
+  private boolean mSpringing = false;
+  private boolean canMove = false;
+  private int cX, cY;
+  private static int mNumLevels, clickedLevel=-1;
+  private static int currLevel;
+  private static int mScrollPos;
+  private double mScrollSpeed;
+  private static Vector<SokobanLevel> mLevels;
+  private Paint mPaint;
+  private double sample[];
+  private int samplePtr;
+  private boolean mDragging = false;
+  private static int currTime;
+  private static int currMoves;
+  private static boolean timerRunning=false;
+  
+  public static int levelInfoH, levelInfoW, sCell ,levelBigH ,levelBigW ,bCell1 ,bCell2, backSmallH, backSmallW;
+  public static int sMargin, bMargin;
+  public static int bDrawnX1, bDrawnY1, bDrawnX2, bDrawnY2, sDrawnX, sDrawnY; 
+  public static int mGapO, mGapI;
+  public static int gapX1, gapY1, gapX2, gapY2;
+
+  private static Resources res; 
+  private static SokobanLevel created;
+  private static int scrWidth, scrHeight;
+  public  static SokobanLevelBuffer slBuffer;
+  
+  static class Flag
+  {
+      public Bitmap flag;
+      public String name;
+
+      Flag()
+        {
+        flag = null;
+        name = null;
+        }
+      Flag(String n)
+        {
+        name = n;
+
+        try
+          {
+          int resID = res.getIdentifier(name, "drawable", "com.threedcell.sokoban");
+          flag = BitmapFactory.decodeResource(res, resID!=0 ? resID:R.drawable.unk);  	
+          }
+        catch( Exception ex )
+          {
+          flag=null;
+          }
+        }
+  }
+
+  private static Vector<Flag> mFlags;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private SokobanLevels(Context context)
+  {
+      mNumLevels = 0;
+      mScrollPos = 0;
+      mScrollSpeed=0;
+      
+      res = context.getResources();
+      
+      mVertical = (scrWidth<=scrHeight);
+      mGap = scrHeight/6;
+      levelHeight = (scrHeight-mGap)/3;
+      
+      if( levelHeight<120 ) levelHeight = 120;
+      if( levelHeight>260 ) levelHeight = 260;
+      
+      sample = new double[SAMPLE_SIZE];
+      samplePtr = -1;
+
+      cX = -(MIN_CLICK_DIST+1);
+      cY = -(MIN_CLICK_DIST+1);
+      
+      mPaint = new Paint();
+      mPaint.setStyle(Style.FILL);
+      
+      mLevels = new Vector<SokobanLevel>();
+      mFlags  = new Vector<Flag>();
+      
+      createImages();
+      
+      created = new SokobanLevel(context,scrWidth,scrHeight,mGap);
+      slBuffer= new SokobanLevelBuffer(levelHeight,scrHeight);
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void init(Activity act)
+  {
+	  if( scrWidth<=0 || scrHeight<=0 )
+		{
+		DisplayMetrics dm = new DisplayMetrics();
+		act.getWindowManager().getDefaultDisplay().getMetrics(dm);
+		  
+		scrWidth = Math.min(dm.widthPixels,dm.heightPixels);
+		scrHeight= Math.max(dm.widthPixels,dm.heightPixels);
+		}
+		
+      levels = new SokobanLevels((Context)act);
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void createImages()
+  {
+      NinePatchDrawable play,pack,dpck,levl, dpck_small, pack_small, dialog, dlgred;
+	  Canvas c;
+	  
+      try
+      {
+    	  play = (NinePatchDrawable)res.getDrawable(R.drawable.play);
+    	  pack = (NinePatchDrawable)res.getDrawable(R.drawable.pack);
+    	  dpck = (NinePatchDrawable)res.getDrawable(R.drawable.dpck);
+    	  levl = (NinePatchDrawable)res.getDrawable(R.drawable.level_info);
+    	  
+    	  pack_small = (NinePatchDrawable)res.getDrawable(R.drawable.pack_small);
+    	  dpck_small = (NinePatchDrawable)res.getDrawable(R.drawable.dpck_small);
+    	  
+    	  dialog     = (NinePatchDrawable)res.getDrawable(R.drawable.dialog);
+          dlgred     = (NinePatchDrawable)res.getDrawable(R.drawable.dialog_clicked);
+    	  
+      }
+      catch( Exception ex ) { Log.e(TAG_LEVELS, "Failed to create 9Patches!"); return; }
+
+      mGapO   = scrHeight/80;
+      mGapI   = scrHeight/80;
+      sDrawnX = 10;
+      sDrawnY = 10;
+      
+      bDrawnX1= 12;
+      bDrawnY1= (scrHeight-mGap)/(scrWidth/bDrawnX1);
+      bDrawnY2= 18;
+      bDrawnX2= scrWidth/((scrHeight-mGap)/bDrawnY2);
+      
+      sCell   = (levelHeight-mGapO-2*mGapI)/sDrawnX;
+      bCell1  = scrWidth/bDrawnX1;
+      bCell2  = (scrHeight-mGap)/bDrawnY2;
+     
+      sMargin = sCell /10;
+      bMargin = bCell1/12;
+      
+      if( sMargin<=0 ) sMargin=1;
+      if( bMargin<=0 ) bMargin=1;
+      
+      int sCross1  = (int)(sCell *0.42);
+      int sCross2  = (int)(sCell *0.38);
+      int bCross11 = (int)(bCell1*0.42);
+      int bCross21 = (int)(bCell1*0.38);
+      int bCross12 = (int)(bCell2*0.42);
+      int bCross22 = (int)(bCell2*0.38);
+      
+      int sS  = sCell  - sMargin;
+      int bS1 = bCell1 - bMargin;
+      int bS2 = bCell2 - bMargin;
+
+      int fB1 = bCell1/8;
+      int fB2 = bCell2/8;
+      int fS  = sCell /8;
+      
+      if( fB1<=0 ) fB1=1;
+      if( fB2<=0 ) fB2=1;
+      if( fS <=0 ) fS =1;
+      
+      backSmallW = sDrawnX*sCell + sMargin;
+      backSmallH = sDrawnY*sCell + sMargin;
+      
+      mGapI = (levelHeight-mGapO-backSmallH)/2;
+      
+      levelInfoH = (backSmallH-2*mGapI)/3;
+      levelInfoW = scrWidth-2*mGapO-3*mGapI-backSmallW+2;		  
+      levelBigH  = backSmallH;
+      levelBigW  = scrWidth-2*mGapO-3*mGapI-backSmallW+2;			  
+     
+      gapX1= (scrWidth      -bDrawnX1*bCell1-bMargin)/2;
+      gapY1= (scrHeight-mGap-bDrawnY1*bCell1-bMargin)/2;
+      
+      gapX2= (scrWidth      -bDrawnX2*bCell2-bMargin)/2;
+      gapY2= (scrHeight-mGap-bDrawnY2*bCell2-bMargin)/2;
+     
+      bkgClicked = Bitmap.createBitmap(scrWidth,levelHeight,  Bitmap.Config.ARGB_8888 );
+      bkgUnClick = Bitmap.createBitmap(scrWidth,levelHeight,  Bitmap.Config.ARGB_8888 );
+      
+      backgroundSmall = Bitmap.createBitmap(backSmallW,backSmallH, Bitmap.Config.ARGB_8888);
+      
+      levelInfo = Bitmap.createBitmap(levelInfoW,levelInfoH, Bitmap.Config.ARGB_8888);
+      levelBig  = Bitmap.createBitmap(levelBigW ,levelBigH , Bitmap.Config.ARGB_8888);
+      
+      emptySmall= Bitmap.createBitmap(sS ,sS , Bitmap.Config.ARGB_8888);
+      packSmall = Bitmap.createBitmap(sS ,sS , Bitmap.Config.ARGB_8888);
+      destSmall = Bitmap.createBitmap(sS ,sS , Bitmap.Config.ARGB_8888);
+      dpckSmall = Bitmap.createBitmap(sS ,sS , Bitmap.Config.ARGB_8888);
+      playSmall = Bitmap.createBitmap(sS ,sS , Bitmap.Config.ARGB_8888);
+      
+      emptyBig1 = Bitmap.createBitmap(bS1,bS1, Bitmap.Config.ARGB_8888);
+      packBig1  = Bitmap.createBitmap(bS1,bS1, Bitmap.Config.ARGB_8888);
+      destBig1  = Bitmap.createBitmap(bS1,bS1, Bitmap.Config.ARGB_8888);
+      dpckBig1  = Bitmap.createBitmap(bS1,bS1, Bitmap.Config.ARGB_8888);
+      playBig1  = Bitmap.createBitmap(bS1,bS1, Bitmap.Config.ARGB_8888);
+
+      emptyBig2 = Bitmap.createBitmap(bS2,bS2, Bitmap.Config.ARGB_8888);
+      packBig2  = Bitmap.createBitmap(bS2,bS2, Bitmap.Config.ARGB_8888);
+      destBig2  = Bitmap.createBitmap(bS2,bS2, Bitmap.Config.ARGB_8888);
+      dpckBig2  = Bitmap.createBitmap(bS2,bS2, Bitmap.Config.ARGB_8888);
+      playBig2  = Bitmap.createBitmap(bS2,bS2, Bitmap.Config.ARGB_8888);
+
+      // bkgClicked
+      c = new Canvas(bkgClicked);
+      mPaint.setColor(COLOR_BLACK);
+      c.drawRect(0,0, scrWidth, levelHeight, mPaint);
+      dlgred.setBounds(mGapO, mGapO/2, scrWidth-mGapO, levelHeight-mGapO/2);
+	  dlgred.draw(c);
+      
+      // bkgUnClick
+      c = new Canvas(bkgUnClick);
+      mPaint.setColor(COLOR_BLACK);
+      c.drawRect(0,0, scrWidth, levelHeight, mPaint);
+      dialog.setBounds(mGapO, mGapO/2, scrWidth-mGapO, levelHeight-mGapO/2);
+	  dialog.draw(c);
+
+      // backgroundSmall
+      c = new Canvas(backgroundSmall);
+      mPaint.setColor(SokobanLevel.COLOR_BACK);
+      c.drawRect(0,0, backSmallW, backSmallH, mPaint);
+      mPaint.setColor(SokobanLevel.COLOR_GRID);
+      
+      for( int i=0; i<=sDrawnY; i++ ) c.drawRect(0, i*sCell, backSmallW, i*sCell+sMargin , mPaint);
+      for( int i=0; i<=sDrawnX; i++ ) c.drawRect(i*sCell, 0, i*sCell+sMargin, backSmallH , mPaint);
+  	  
+      // levelInfo
+      c = new Canvas(levelInfo);
+      levelInfo.eraseColor(0);
+      levl.setBounds(0,0,levelInfoW,levelInfoH);
+      levl.draw(c);
+      
+      // levelBig
+      c = new Canvas(levelBig);
+      levelBig.eraseColor(0);
+      levl.setBounds(0,0,levelBigW,levelBigH);
+      levl.draw(c);
+      
+      //emptySmall
+      emptySmall.eraseColor(COLOR_EMPT);
+      
+      //packSmall
+      c = new Canvas(packSmall);
+      packSmall.eraseColor(0);
+      
+      pack_small.setBounds( fS, fS, sS-fS, sS-fS );
+      pack_small.draw(c);
+      
+      //destSmall
+      c = new Canvas(destSmall);
+      destSmall.eraseColor(COLOR_EMPT);
+      
+      mPaint.setColor(SokobanLevel.COLOR_CRES);
+      c.drawRect( sCross2, sCross2, sS-sCross2, sS-sCross2 ,mPaint);
+      c.drawRect( fS, sCross1, sS-fS, sS-sCross1 ,mPaint);
+      c.drawRect( sCross1, fS, sS-sCross1, sS-fS ,mPaint);
+      
+      //dpckSmall
+      c = new Canvas(dpckSmall);
+      dpckSmall.eraseColor(0);
+      
+      dpck_small.setBounds( fS, fS, sS-fS, sS-fS );
+      dpck_small.draw(c);
+      
+      //playSmall
+      c = new Canvas(playSmall);
+      playSmall.eraseColor(0);
+      
+      play.setBounds( fS, fS, sS-fS, sS-fS );
+      play.draw(c);
+      
+      //emptyBig1
+      emptyBig1.eraseColor(COLOR_EMPT);
+      
+      //emptyBig2
+      emptyBig2.eraseColor(COLOR_EMPT);
+      
+      //packBig1
+      c = new Canvas(packBig1);
+      packBig1.eraseColor(0);
+      
+      pack.setBounds( fB1, fB1, bS1-fB1, bS1-fB1 );
+      pack.draw(c);
+      
+      //packBig2
+      c = new Canvas(packBig2);
+      packBig2.eraseColor(0);
+      
+      pack.setBounds( fB2, fB2, bS2-fB2, bS2-fB2 );
+      pack.draw(c);
+      
+      //destBig1
+      c = new Canvas(destBig1);
+      destBig1.eraseColor(COLOR_EMPT);
+      
+      mPaint.setColor(SokobanLevel.COLOR_CRES);
+      c.drawRect( bCross21, bCross21, bS1-bCross21, bS1-bCross21 ,mPaint);
+      c.drawRect( fB1, bCross11, bS1-fB1, bS1-bCross11 ,mPaint);
+      c.drawRect( bCross11, fB1, bS1-bCross11, bS1-fB1 ,mPaint);
+      
+      //destBig2
+      c = new Canvas(destBig2);
+      destBig2.eraseColor(COLOR_EMPT);
+      
+      mPaint.setColor(SokobanLevel.COLOR_CRES);
+      c.drawRect( bCross22, bCross22, bS2-bCross22, bS2-bCross22 ,mPaint);
+      c.drawRect( fB2, bCross12, bS2-fB2, bS2-bCross12 ,mPaint);
+      c.drawRect( bCross12, fB2, bS2-bCross12, bS2-fB2 ,mPaint);
+      
+      //dpckBig1
+      c = new Canvas(dpckBig1);
+      dpckBig1.eraseColor(0);
+      
+      dpck.setBounds( fB1, fB1, bS1-fB1, bS1-fB1 );
+      dpck.draw(c);
+      
+      //dpckBig2
+      c = new Canvas(dpckBig2);
+      dpckBig2.eraseColor(0);
+      
+      dpck.setBounds( fB2, fB2, bS2-fB2, bS2-fB2 );
+      dpck.draw(c);
+      
+      //playBig1
+      c = new Canvas(playBig1);
+      playBig1.eraseColor(0);
+      
+      play.setBounds( fB1, fB1, bS1-fB1, bS1-fB1 );
+      play.draw(c);
+      
+      //playBig2
+      c = new Canvas(playBig2);
+      playBig2.eraseColor(0);
+      
+      play.setBounds( fB2, fB2, bS2-fB2, bS2-fB2 );
+      play.draw(c);
+  }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+  
+  public static SokobanLevels getInstance()
+  {
+      return levels;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static SokobanLevel getLevel(int i)
+  {
+      if( i>=0 && i<mNumLevels ) return (SokobanLevel)mLevels.elementAt(i);
+
+      return null;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Bitmap getFlag(String s)
+  {
+      if( s==null ) return null;
+
+      int size = mFlags.size();
+      Flag tmp;
+
+      for(int i=0; i<size; i++)
+        {
+        tmp = (Flag)mFlags.elementAt(i);
+        if( tmp.name.equals(s) ) return tmp.flag;
+        }
+
+      tmp = new Flag(s);
+      mFlags.addElement(tmp);
+
+      return tmp.flag;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void updateMyRecords(String n)
+  {
+      SokobanLevel sl;
+      int move;
+
+      for(int i=0; i<mNumLevels; i++)
+        {
+        sl = (SokobanLevel)mLevels.elementAt(i);
+        if( sl==null ) continue;
+
+        move = sl.getMyMoves();
+
+        if( move<SokobanDatabase.INVALID ) sl.setName(n);
+        }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void resetCurrTime()
+  {
+      stopTimer();
+      currTime = 0;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void setScrDimensions(int w, int h)
+  {
+	  if( scrWidth!=w || scrHeight!=h )
+        {
+		Log.e(TAG_LEVELS, "Correcting SokobanLevels images!");  
+		  
+        scrWidth    = w;
+        scrHeight   = h;
+        mVertical   = (w<=h);
+        
+        levelHeight = (h-mGap)/3;
+        
+        if( levelHeight<120 ) levelHeight = 120;
+        if( levelHeight>200 ) levelHeight = 200;
+        
+        createImages();
+        SokobanLevelBuffer.allocate(levelHeight,scrHeight);
+        created.allocate(scrWidth,scrHeight,mGap);
+        }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void scrollToEnd()
+  {
+      if( mVertical ) mScrollPos=mNumLevels*levelHeight-(scrHeight-mGap);
+      else mScrollPos=mNumLevels*levelHeight-scrWidth;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void setScroll(int s)
+  {
+      mScrollPos = s;
+
+      if( mScrollPos<0 ) mScrollPos = 0;
+      
+      if( mVertical )
+      {
+    	  if( mScrollPos> mNumLevels*levelHeight-(scrHeight-mGap) )
+    		  mScrollPos=mNumLevels*levelHeight-(scrHeight-mGap);
+      }
+      else
+      {
+    	  if( mScrollPos>mNumLevels*levelHeight-scrWidth )
+    		  mScrollPos=mNumLevels*levelHeight-scrWidth;
+      }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static int getScroll()
+  {
+      return mScrollPos;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void scroll()
+  {
+	  mScrollPos+=mScrollSpeed;
+
+      if( mVertical )
+        {
+        if( mScrollPos<0 )
+          {
+          mSpringing = true;
+          mScrollSpeed+=SPRING_CONST;
+          if( mScrollSpeed<-MAX_SPRING_SPEED ) mScrollSpeed=-MAX_SPRING_SPEED;
+          }
+        else if( mScrollPos> mNumLevels*levelHeight-(scrHeight-mGap))
+          {
+          mSpringing = true;
+          mScrollSpeed-=SPRING_CONST;
+          if( mScrollSpeed> MAX_SPRING_SPEED ) mScrollSpeed= MAX_SPRING_SPEED;
+          }
+        else
+          {
+          if( mSpringing )
+            {
+            if( mScrollPos<mScrollSpeed ) mScrollPos = 0;
+            else mScrollPos = mNumLevels*levelHeight-(scrHeight-mGap);
+
+            mSpringing = false;
+            mScrollSpeed = 0;
+            }
+          else
+            {
+        	     if( mScrollSpeed> 1 ) mScrollSpeed-=1;
+        	else if( mScrollSpeed<-1 ) mScrollSpeed+=1;
+        	else                       mScrollSpeed=0;     
+            }
+          }
+        }
+      else
+        {
+        if( mScrollPos<0 )
+          {
+          mSpringing = true;
+          mScrollSpeed+=SPRING_CONST;
+          if( mScrollSpeed<-MAX_SPRING_SPEED ) mScrollSpeed=-MAX_SPRING_SPEED;
+          }
+        else if( mScrollPos> mNumLevels*levelHeight-scrWidth )
+          {
+          mSpringing = true;
+          mScrollSpeed-=SPRING_CONST;
+          if( mScrollSpeed> MAX_SPRING_SPEED ) mScrollSpeed= MAX_SPRING_SPEED;
+          }
+        else
+          {
+          if( mSpringing )
+            {
+            if( mScrollPos<mScrollSpeed ) mScrollPos = 0;
+            else mScrollPos = mNumLevels*levelHeight-scrWidth;
+
+            mSpringing = false;
+            mScrollSpeed = 0;
+            }
+          else
+            {
+        	     if( mScrollSpeed> 1 ) mScrollSpeed-=1;
+            else if( mScrollSpeed<-1 ) mScrollSpeed+=1;
+            else                       mScrollSpeed=0;     
+            }
+          }
+        }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static int getNumLevels()
+  {
+      return mNumLevels;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static int getIntrinsic()
+  {
+      SokobanLevel sl= getLevel(mNumLevels-1);
+
+      if( sl!=null ) return sl.getIntrinsicNum();
+
+      return -1;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void addLevel(SokobanLevel l, int num)
+  {
+      mLevels.addElement(l);
+      mNumLevels++;
+      l.setNum(mNumLevels);
+      l.setIntrinsicNum(num);
+      l.setRecordId(num+SokobanDatabase.BEGIN_LEVELS);
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void insertLevel(SokobanLevel l, int pos,int intrinsic, int recordid)
+  {
+      if( pos>=mNumLevels )
+        {
+        for(int i=mNumLevels; i<=pos; i++)
+          {
+          mLevels.addElement(null);
+          }
+     
+        mNumLevels = pos+1;
+        }
+
+      mLevels.setElementAt(l, pos);
+      l.setNum(pos+1);
+      l.setIntrinsicNum(intrinsic);
+      l.setRecordId(recordid);
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void render(int state, Canvas c)
+  { 
+      if( state==SokobanCanvas.STATE_MAIN ||
+          state==SokobanCanvas.STATE_MENU ||
+          state==SokobanCanvas.STATE_DOWN ||
+          state==SokobanCanvas.STATE_DOWL ||
+          state==SokobanCanvas.STATE_FAID ||
+          state==SokobanCanvas.STATE_FAIE ||
+          state==SokobanCanvas.STATE_SUCE ||
+          state==SokobanCanvas.STATE_SUCD ||
+          state==SokobanCanvas.STATE_HELP  )
+        {
+        if( (mScrollSpeed!=0 || mSpringing) && !mDragging )
+          {
+          scroll();
+          SokobanCanvas.setRepaint();
+          }
+
+        int beg = Math.max(mScrollPos/levelHeight, 0);
+        int end = Math.min(( mVertical ? (mScrollPos+scrHeight-mGap):(mScrollPos+scrWidth) )/levelHeight, mNumLevels-1);
+        int height = mVertical ? (mGap/2-mScrollPos+(beg-1)*levelHeight):((beg-1)*levelHeight-mScrollPos);
+        int begHeight = height+levelHeight;
+        
+        mPaint.setColor(COLOR_BLACK);
+        c.drawRect(0, scrHeight-mGap/2-mGapO, scrWidth,scrHeight-mGap/2+7, mPaint);
+        
+        try
+          {
+          c.clipRect(0, mGap/2, scrWidth, scrHeight-mGap/2+6, Region.Op.REPLACE);	
+        	
+          for(int i=beg; i<=end; i++)
+            {
+            SokobanLevel sl = (SokobanLevel)mLevels.elementAt(i);
+            height+=levelHeight;
+
+            if( sl!=null && height+mGap/2+mGapO<scrHeight)
+              {
+              if( state!=SokobanCanvas.STATE_SUCD )
+                sl.renderSmall(  c, height, i==clickedLevel);
+              else
+                sl.renderRecords(c, height );
+              }
+            }
+          
+          c.clipRect(0, 0, scrWidth, scrHeight, Region.Op.REPLACE);	
+          }
+        catch( ArrayIndexOutOfBoundsException aiofb ) { System.out.println("render1: level out of bounds??"); }
+
+        if( begHeight>mGap/2-5 )
+          {
+          c.drawRect(0, mGap/2-5, scrWidth,begHeight, mPaint);
+          }
+        if( height+levelHeight<scrHeight-mGap/2-mGapO )
+          {
+          c.drawRect(0, height+levelHeight, scrWidth, scrHeight-mGap/2-mGapO, mPaint);
+          }
+        }
+      else if( state==SokobanCanvas.STATE_PLAY ||
+               state==SokobanCanvas.STATE_TIME ||
+               state==SokobanCanvas.STATE_NEWR ||
+               state==SokobanCanvas.STATE_NAME ||
+               state==SokobanCanvas.STATE_EXIS ||
+               state==SokobanCanvas.STATE_FAIL ||
+               state==SokobanCanvas.STATE_RECO ||
+               state==SokobanCanvas.STATE_SECU ||
+               state==SokobanCanvas.STATE_SUBM  )
+        {
+        SokobanLevel sl;
+
+        try
+          {
+          sl = (SokobanLevel)mLevels.elementAt(currLevel);
+          }
+        catch( ArrayIndexOutOfBoundsException aiofb ) { System.out.println("render2: level out of bounds??"); return; }
+
+        sl.renderBig(c,0,mGap/2  );
+        }
+      else if( state==SokobanCanvas.STATE_CREA ||
+               state==SokobanCanvas.STATE_CRED ||
+               state==SokobanCanvas.STATE_CRES ||
+               state==SokobanCanvas.STATE_SUBC  )
+        {
+        created.renderBig(c,0,mGap/2  );
+        mPaint.setColor(COLOR_BLACK);
+        c.drawRect(0, 0, scrWidth, 7, mPaint);
+        }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int stopTimer()
+    {
+    timerRunning = false;
+    return timer!=null ? timer.stop() : -2;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void startTimer(int time)
+    {
+    currTime = time/10;
+    timerRunning= true;
+    timer = SokobanTimer.getInstance();
+    timer.start(time);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int retClickedLevel(int x, int y)
+  {
+    int ret;
+
+    if( mVertical ) ret =(y+mScrollPos-mGap/2)/levelHeight;
+    else            ret =(x+mScrollPos       )/levelHeight;
+
+    return ret>=mNumLevels ? mNumLevels-1:ret;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static int getCurrLevel()
+  {
+    return currLevel;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static int getCurrTime()
+  {  
+    return currTime;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static int getCurrMoves()
+  {
+    return currMoves;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void setTime(int t)
+  {
+    currTime = t;
+    if( currTime%100==0 ) SokobanCanvas.getMenu().updatePlayState();
+    SokobanCanvas.setRepaint();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void rollbackCreated()
+  {
+    created.rollback();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void rollback()
+  {
+    SokobanLevel sl;
+
+    try
+      {
+      sl = (SokobanLevel)mLevels.elementAt(currLevel);
+      }
+    catch( ArrayIndexOutOfBoundsException aiofb ) { System.out.println("rollback: level out of bounds??"); return; }
+
+    currMoves = 0;
+    sl.rollback();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void withdrawCreated()
+  {
+    created.withdraw();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void withdraw()
+  {
+    SokobanLevel sl;
+
+    try
+      {
+      sl = (SokobanLevel)mLevels.elementAt(currLevel);
+      }
+    catch( ArrayIndexOutOfBoundsException aiofb ) { System.out.println("withdraw: level out of bounds??"); return; }
+
+    if( sl.withdraw() ) currMoves--;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void resetCreated()
+  {
+    created.resetCreated();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void drop(int stuff)
+  {
+    created.drop(stuff);
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static int validate()
+  {
+    return created.validate();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public boolean canWithdrawCreated()
+  {
+    return created.canWithdraw();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public boolean canWithdraw()
+  {
+    SokobanLevel sl;
+
+    try
+      {
+      sl = (SokobanLevel)mLevels.elementAt(currLevel);
+      }
+    catch( ArrayIndexOutOfBoundsException aiofb ) { System.out.println("withdraw: level out of bounds??"); return false; }
+
+    return sl.canWithdraw();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void click(int state,int x,int y)
+    {
+    if( y<mGap/2 || y>scrHeight-mGap/2 ) { clickedLevel=-1; return; }
+
+    cX = x;
+    cY = y;
+    mDragging = true;
+
+    if( state==SokobanCanvas.STATE_MAIN || state==SokobanCanvas.STATE_SUCD )
+      {
+      amountDrag = mVertical ? y:x;
+      if( mScrollSpeed<=1 && mScrollSpeed>=-1 ) clickedLevel = retClickedLevel(x,y);
+      else                                      clickedLevel = -1;
+      samplePtr =-1;
+      for(int i=0; i<SAMPLE_SIZE; i++) sample[i]=0;
+      mScrollSpeed = 0;
+      }
+    else if( state==SokobanCanvas.STATE_PLAY || state==SokobanCanvas.STATE_CREA || state==SokobanCanvas.STATE_CRES )
+      {
+      canMove = true;
+      }
+
+    mScrollSpeed = 0;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void unclick(int state,int x,int y)
+    {
+    if( y<mGap/2 || y>scrHeight-mGap/2 ) { clickedLevel=-1; mDragging=false; return; }
+
+    int dx = cX-x;
+    int dy = cY-y;
+    mDragging = false;
+
+    if( state==SokobanCanvas.STATE_MAIN || state==SokobanCanvas.STATE_SUCD )
+      {
+      if( state==SokobanCanvas.STATE_MAIN && clickedLevel>=0 && dx*dx+dy*dy<=MIN_CLICK_DIST*MIN_CLICK_DIST)
+        {
+        SokobanDatabase.incNumPlayings();
+        currLevel = clickedLevel;
+        currMoves = 0;
+        SokobanCanvas.getMenu().enterPlayState(currLevel);
+        SokobanCanvas.setRepaint();
+        }
+      
+      clickedLevel = -1;
+      cX = -(MIN_CLICK_DIST+1);
+      cY = -(MIN_CLICK_DIST+1);
+      amountDrag = -1;
+
+      mScrollSpeed=0;
+      for(int i=0; i<SAMPLE_SIZE; i++) mScrollSpeed +=sample[i];
+      mScrollSpeed/=SAMPLE_SIZE;
+      }
+    else if( state==SokobanCanvas.STATE_PLAY )
+      {
+      movePlayer(dx,dy);
+      }
+    else if( state==SokobanCanvas.STATE_CRES )
+      {
+      movePlayerCreated(dx,dy);
+      }
+    else if( state==SokobanCanvas.STATE_CREA )
+      {
+      movePlayerFreely(dx,dy);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void drag(int state,int x,int y)
+    {
+    if( y<mGap/2 || y>scrHeight-mGap/2 ) { clickedLevel=-1; return; }
+
+    int dx = cX-x;
+    int dy = cY-y;
+
+    if( state==SokobanCanvas.STATE_MAIN || state==SokobanCanvas.STATE_SUCD )
+      {
+      int nDrag = mVertical ? y:x;
+ 
+      if( mSpringing==false ) mScrollSpeed = amountDrag-nDrag;
+      amountDrag = nDrag;
+      
+      scroll();
+
+      if( samplePtr<0 )
+        {
+        samplePtr=0;
+        for(int i=0; i<SAMPLE_SIZE; i++) sample[i] = mScrollSpeed;
+        }
+      else
+        {
+        samplePtr++;
+        if( samplePtr>=SAMPLE_SIZE ) samplePtr=0;
+        sample[samplePtr] = mScrollSpeed;
+        }
+
+      if( dx*dx+dy*dy>MIN_CLICK_DIST*MIN_CLICK_DIST)
+        {
+        clickedLevel= -1;
+        }
+      }
+    else if( state==SokobanCanvas.STATE_PLAY )
+      {
+      movePlayer(dx,dy);
+      }
+    else if( state==SokobanCanvas.STATE_CRES )
+      {
+      movePlayerCreated(dx,dy);
+      }
+    else if( state==SokobanCanvas.STATE_CREA )
+      {
+      movePlayerFreely(dx,dy);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void setSubmitted(int lvl)
+    {
+    SokobanLevel sl;
+
+    if( lvl>=0 )
+      {
+      sl = getLevel(lvl);
+      if( sl!=null ) sl.setSubmitted(true);
+      }
+    else
+      {
+      for(int i=0; ; i++)
+        {
+        sl = getLevel(i);
+        if( sl==null ) break;
+        sl.setSubmitted(true);
+        }
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public SokobanLevel getCreated()
+    {
+    return created;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void fillLevelInfo(int lvl, int moves, int time, int place, String name, String country)
+    {
+    SokobanLevel sl = getLevel(lvl);
+    if( sl!=null )
+      {
+      if( place==0 )
+        {
+        SokobanRecordInfo wr = sl.getRecordInfo(0);
+ 
+        if( wr==null ) sl.setDirty();
+        else
+          {
+          int wm = wr.getMove();
+          if( moves<wm || (moves==wm && time<wr.getTime()) ) sl.setDirty();
+          }
+        }
+ 
+      sl.addRecordInfo(moves,time,place,name,country);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void keyboardMovePlayer(int state, int dir)
+    {
+    int dx=0,dy=0;    
+      
+    switch(dir)    
+      {
+      case 1: canMove=true; dy= PLAY_MIN_DIST; break;
+      case 2: canMove=true; dx=-PLAY_MIN_DIST; break;
+      case 3: canMove=true; dy=-PLAY_MIN_DIST; break;
+      case 4: canMove=true; dx= PLAY_MIN_DIST; break;
+      default: return;   
+      }
+        
+    if( state==SokobanCanvas.STATE_PLAY )
+      {
+      movePlayer(dx,dy);
+      }
+    else if( state==SokobanCanvas.STATE_CRES )
+      {
+      movePlayerCreated(dx,dy);
+      }
+    else if( state==SokobanCanvas.STATE_CREA )
+      {
+      movePlayerFreely(dx,dy);
+      }    
+    }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void movePlayerFreely(int dx, int dy)
+    {
+    if( !canMove || dx*dx+dy*dy<PLAY_MIN_DIST*PLAY_MIN_DIST) return;
+
+    canMove = false;
+    created.movePlayerFreely(dx,dy);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void movePlayerCreated(int dx, int dy)
+    {
+    if( !canMove || dx*dx+dy*dy<PLAY_MIN_DIST*PLAY_MIN_DIST) return;
+
+    canMove = false;
+
+    if( created.movePlayer(dx,dy) && created.isSolved() )
+      {
+      SokobanCanvas.setState(SokobanCanvas.STATE_SUBC);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void movePlayer(int dx, int dy)
+    {
+    if( !canMove || dx*dx+dy*dy<PLAY_MIN_DIST*PLAY_MIN_DIST) return;
+
+    canMove = false;
+    SokobanLevel sl;
+
+    try
+      {
+      sl = (SokobanLevel)mLevels.elementAt(currLevel);
+      }
+    catch( ArrayIndexOutOfBoundsException aiofb )
+      {
+      System.out.println("movePlayer: level out of bounds??");
+      return;
+      }
+
+    if( sl.movePlayer(dx,dy) )
+      {
+      currMoves++;
+
+      if( currMoves%100==0 ) SokobanCanvas.getMenu().updatePlayState();
+
+      if( timerRunning==false ) startTimer(0);
+
+      if( sl.isSolved() )
+        {
+        currTime = stopTimer()/10;
+        int m = sl.getMyMoves();
+
+        if( currMoves < m || (currMoves==m && currTime<sl.getMyTime() ) )
+          {
+          sl.setMyInfo(currMoves,currTime,SokobanDatabase.getName(), SokobanDatabase.getCountry());
+          sl.setDirty();
+          SokobanLevelBuffer.invalidateAllR();
+          SokobanCanvas.setState(SokobanCanvas.STATE_NEWR);
+          }
+        else
+          SokobanCanvas.setState(SokobanCanvas.STATE_TIME);
+        }
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// end of SokobanLevels class
+  }
\ No newline at end of file
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanMain.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanMain.java
new file mode 100644
index 0000000..5d65edf
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanMain.java
@@ -0,0 +1,108 @@
+package com.threedcell.sokoban;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.ViewGroup;
+
+///////////////////////////////////////////////////////////////////
+
+public class SokobanMain extends Activity 
+{
+	private static final String TAG_MAIN = "SokobanMain";
+	private SokobanCanvas rrc=null;
+	private int runningTime = -1;
+	
+///////////////////////////////////////////////////////////////////
+	
+    public void onCreate(Bundle savedInstanceState) 
+    {
+    	super.onCreate(savedInstanceState);
+    	Log.d( TAG_MAIN, "onCreate");
+    	initCanvas();
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public void onStart() 
+	{	
+		super.onStart();
+		Log.d( TAG_MAIN, "onStart");
+		if( !SokobanCanvas.isCreated() ) initCanvas();
+		if( rrc!=null ) SokobanCanvas.setRepaint();
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public void onStop()
+	{
+		Log.d( TAG_MAIN, "onStop");
+		
+		if( SokobanCanvas.getDestroy() )
+		  {
+          SokobanDatabase.saveValues();
+          if( rrc!=null ) rrc.deallocate();
+          System.gc();
+          }
+		SokobanCanvas.setDestroy(true);
+		  
+		super.onStop();
+	}
+	
+///////////////////////////////////////////////////////////////////
+
+	public void onDestroy() 
+	{
+		Log.d( TAG_MAIN, "onDestroy");
+		
+		if( rrc!=null )
+		  {
+		  ViewGroup vg = (ViewGroup)(rrc.getParent());
+		  if( vg!=null ) vg.removeView(rrc);
+		  }
+		
+		super.onDestroy();		
+	}
+
+
+///////////////////////////////////////////////////////////////////
+
+	public void onPause()
+	{
+		Log.d( TAG_MAIN, "onPause");
+
+    	runningTime=SokobanLevels.getInstance().stopTimer();
+    	  
+		super.onPause();	
+	}
+
+///////////////////////////////////////////////////////////////////
+
+	public void onResume()
+	{
+		Log.d( TAG_MAIN, "onResume");
+		super.onResume();
+		   
+        if( runningTime>=0 )
+          SokobanLevels.getInstance().startTimer(runningTime);
+	}
+	
+///////////////////////////////////////////////////////////////////
+
+	private void initCanvas()
+	{
+		rrc = SokobanCanvas.getCanvas(this);
+		  
+		if( rrc!=null ) 
+		  {
+		  ViewGroup vg = (ViewGroup)(rrc.getParent());
+		  if( vg!=null ) vg.removeView(rrc);
+		  setContentView(rrc);
+		  SokobanCanvas.setActivity(this);
+		  }
+		else setContentView(R.layout.error);
+	}
+	
+///////////////////////////////////////////////////////////////////
+// end of file
+}
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanMenu.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanMenu.java
new file mode 100644
index 0000000..f0093c5
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanMenu.java
@@ -0,0 +1,1256 @@
+package com.threedcell.sokoban;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Canvas;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.Style;
+import android.graphics.drawable.NinePatchDrawable;
+import android.graphics.Rect;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+//import android.util.Log;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public final class SokobanMenu implements TouchKeyboard.VirtualKeyboardListener
+  {  
+  //private static final String TAG_MENU = "SokobanMenu";	
+	
+  private static final int SOFT_NOT = 0;
+  private static final int SOFT_LEF = 1;
+  private static final int SOFT_RIG = 2;
+  private static final int SOFT_LEL = 3;
+  private static final int SOFT_LER = 4;
+
+  public static final int ACTION_NONE = 0;
+  public static final int ACTION_SUBL = 1;
+  public static final int ACTION_SUBR = 2;
+
+  private static final int GAP=20;
+
+  private static String strHelptxt, strEmail, strLevel, strNewr, strSubm, strMoves, strSeconds;
+  private static String strSolved, strName, strOptions, strSolveNL, strSubmitNL, strFirst, strChoose;
+  private static String strSubmitted, strSuccessfully, strOk, strBack, strExit, strYes, strNo, strRecords;
+  private static String strDone, strSubmit, strSolve, strAbort, strDownloaded, strHelp, strFailed;
+  private static String strFTS, strIAT, strTagain, strSubmitting, strNoper, strTun, strLeaderboard;
+  private static String strNtaken, strCname, strDlevels, strDownloading, strCNL, strFTD;
+  private static String strNewLevels, strNewLevel, strNoNewLevels, strDownloaded2;
+  private static String strSolveIt, strYWL, strOTS, strUL, strIncorrect;
+  private static String strPNTS, strOAES, strPA, strID, strNCF, strLISA, strNOCD, strNETN, strODS;
+  
+  private static SokobanCanvas mCanvas;
+
+  private int scrWidth;
+  private int scrHeight;
+  public static int lFontH,mFontH,hFontH,sFontH;
+  
+  private static NinePatchDrawable mDialog, mDlgRed, mButtonClicked, mButtUnClicked;
+  private Bitmap mRollBlack, mRollGray, mBackBlack, mBackGray, mMaskBackground=null;
+  private Paint mPaint;
+  
+  private int menuItem = -1;
+  private int dialogX,dialogY0,dialogY1,dialogY2,dialogY3,dialogM;
+  private TouchKeyboard tkb = null;
+  private static int nameChangeAction =ACTION_NONE;
+  private SokobanStringBlock blockHelptext;
+
+  private int softkeyState = SOFT_NOT;
+  private int comeBackState=SokobanCanvas.STATE_MAIN;
+  private int numDownloaded;
+  private int upperSoftkeyState;
+  private int createdLevelError;
+
+  private String levelNumStr;
+  private boolean fontSmall;
+  private int maxStrLen;
+  private static Resources res;
+  private int mRollH, mRollW, mBackH, mBackW;
+  private static boolean mEmailClicked;
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public SokobanMenu(Context context, SokobanCanvas c)
+    {
+    mCanvas  = c; 
+    scrWidth = mCanvas.getScrWidth();
+    scrHeight= mCanvas.getScrHeight();
+
+    res = context.getResources();
+    
+    try 
+      {
+      mDialog         = (NinePatchDrawable)res.getDrawable(R.drawable.dialog);
+      mDlgRed         = (NinePatchDrawable)res.getDrawable(R.drawable.dialog_clicked);
+      mButtonClicked  = (NinePatchDrawable)res.getDrawable(R.drawable.btn_clicked);
+      mButtUnClicked  = (NinePatchDrawable)res.getDrawable(R.drawable.btn_unclicked); 
+      
+      mBackBlack      = BitmapFactory.decodeResource(res, R.drawable.back_black);
+      mBackGray       = BitmapFactory.decodeResource(res, R.drawable.back_gray);
+      mRollBlack      = BitmapFactory.decodeResource(res, R.drawable.roll_black);
+      mRollGray       = BitmapFactory.decodeResource(res, R.drawable.roll_gray);
+      }
+    catch( Exception ex ) {}
+
+    mEmailClicked = false;
+    
+    mPaint = new Paint();
+    mPaint.setAntiAlias(true);
+    mPaint.setStyle(Style.FILL);
+    
+    mRollH = mRollBlack.getHeight()/2;
+    mRollW = mRollBlack.getWidth()/2;
+    mBackH = mBackBlack.getHeight()/2;
+    mBackW = mBackBlack.getWidth()/2;
+    
+    if( mRollH > SokobanLevels.mGap/4 - 5 )
+      {
+      float f = ((float)(SokobanLevels.mGap/4 - 5))/mRollH;
+    	
+      mRollW = (int)(f*mRollW);
+      mRollH = (int)(f*mRollH);
+      mBackW = (int)(f*mBackW);
+      mBackH = (int)(f*mBackH);
+      
+      mRollBlack = Bitmap.createScaledBitmap(mRollBlack, 2*mRollW, 2*mRollH, true);
+      mRollGray  = Bitmap.createScaledBitmap(mRollGray , 2*mRollW, 2*mRollH, true);
+      mBackBlack = Bitmap.createScaledBitmap(mBackBlack, 2*mBackW, 2*mBackH, true);
+      mBackGray  = Bitmap.createScaledBitmap(mBackGray , 2*mBackW, 2*mBackH, true);
+      }
+    
+    strEmail        = context.getString(R.string.questions)+" "+context.getString(R.string.email);
+    strHelptxt      = context.getString(R.string.helptxt);
+    strLevel        = context.getString(R.string.level)+" ";
+    strNewr         = context.getString(R.string.newr);
+    strSubm         = context.getString(R.string.subm);
+    strMoves        = " "+context.getString(R.string.moves);
+    strSeconds      = " "+context.getString(R.string.seconds );
+    strSolved       = context.getString(R.string.solved);
+    strName         = context.getString(R.string.app_name);
+    strOptions      = context.getString(R.string.options);
+    strSolveNL      = context.getString(R.string.solvenl);
+    strSubmitNL     = context.getString(R.string.submitnl);
+    strFirst        = context.getString(R.string.first);
+    strChoose       = context.getString(R.string.choose);
+    strSubmitted    = context.getString(R.string.submitted);
+    strSuccessfully = context.getString(R.string.successfully);		
+    strOk           = context.getString(R.string.ok);
+    strBack         = context.getString(R.string.back);
+    strYes          = context.getString(R.string.yes);
+    strNo           = context.getString(R.string.no);
+    strExit         = context.getString(R.string.exit);
+    strDone         = context.getString(R.string.done);
+    strSolve        = context.getString(R.string.solve);
+    strSubmit       = context.getString(R.string.submit);
+    strAbort        = context.getString(R.string.abort);
+    strDownloaded   = context.getString(R.string.downloaded);
+    strHelp         = context.getString(R.string.help);
+    strRecords      = context.getString(R.string.records);
+    strFTS          = context.getString(R.string.fts);
+    strIAT          = context.getString(R.string.iat);
+    strTagain       = context.getString(R.string.tagain);
+    strNoper        = context.getString(R.string.noper);
+    strSubmitting   = context.getString(R.string.submitting);
+    strTun          = context.getString(R.string.tun);
+    strLeaderboard  = context.getString(R.string.leaderboard);
+    strFailed       = context.getString(R.string.failed);
+    strDlevels      = context.getString(R.string.dlevels);
+    strCname        = context.getString(R.string.cname);
+    strNtaken       = context.getString(R.string.ntaken);
+    strDownloading  = context.getString(R.string.downloading);
+    strCNL          = context.getString(R.string.cnl);
+    strFTD          = context.getString(R.string.ftd);
+    strNewLevels    = context.getString(R.string.newlevels);
+    strNewLevel     = context.getString(R.string.newlevel);
+    strNoNewLevels  = context.getString(R.string.nonewlevels);
+    strDownloaded2  = context.getString(R.string.downloaded2);
+    strSolveIt      = context.getString(R.string.solveit);
+    strYWL          = context.getString(R.string.ywl);
+    strOTS          = context.getString(R.string.ots);
+    strUL           = context.getString(R.string.ul);
+    strIncorrect    = context.getString(R.string.incorrect);
+    strPNTS         = context.getString(R.string.pnts);
+    strOAES         = context.getString(R.string.oaes);
+    strPA           = context.getString(R.string.pa);
+    strID           = context.getString(R.string.id);
+    strNCF          = context.getString(R.string.ncf);
+    strLISA         = context.getString(R.string.lisa);
+    strLISA         = context.getString(R.string.lisa);
+    strNOCD         = context.getString(R.string.nocd);
+    strNETN         = context.getString(R.string.netn);
+    strODS          = context.getString(R.string.ods);
+    
+    setUpDialogSizeAndFonts();
+    }  
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void setUpDialogSizeAndFonts()
+    {
+	if( scrWidth<=240 )
+	  {
+	  lFontH = 32;
+	  mFontH = 24;
+	  hFontH = 20;
+	  sFontH = 14;
+	  dialogX = scrWidth-10;
+	  }
+    else if( scrWidth<=320 )
+	  {
+      lFontH = 38;
+      mFontH = 30;
+      hFontH = 24;
+      sFontH = 18;
+      dialogX = scrWidth-20;
+      }
+    else if( scrWidth<=360 )
+      {
+      lFontH = 42;
+      mFontH = 32;
+      hFontH = 28;
+      sFontH = 20;
+      dialogX = scrWidth-30;
+      }
+	else if( scrWidth<=480 )
+	  {
+      lFontH = 50;
+      mFontH = 40;
+      hFontH = 34;
+      sFontH = 28;
+      dialogX = scrWidth-50;
+      }
+	else
+	  {
+      lFontH = 70;
+      mFontH = 50;
+      hFontH = 40;
+      sFontH = 30;
+      dialogX = 480;
+      }  
+	
+    dialogM = dialogX/16;
+    dialogY0= 3*scrHeight/4;
+    dialogY1= 4*mFontH;
+    dialogY2= 4*mFontH+3*GAP + 60;
+    dialogY3= 6*mFontH;
+    
+    if( dialogY0 > 400 ) dialogY0= 400;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void enterPlayState(int levelNum)
+    {
+    levelNumStr=strLevel+(levelNum+1);
+    mPaint.setTextSize(3*SokobanLevels.mGap/8);
+    maxStrLen=scrWidth-30-(int)mPaint.measureText(levelNumStr);
+    fontSmall=false;
+
+    SokobanCanvas.setState(SokobanCanvas.STATE_PLAY);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void updatePlayState()
+    {
+    String tmp= SokobanLevels.getCurrMoves()+"m "+SokobanLevels.getCurrTime()+"s"; 
+    mPaint.setTextSize(3*SokobanLevels.mGap/8);
+    if( mPaint.measureText(tmp)>maxStrLen ) fontSmall=true;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void setScrDimensions(int w, int h)
+    {
+	if( scrWidth!=w || scrHeight!=h )
+	  {
+      scrWidth = w;
+      scrHeight= h;
+      setUpDialogSizeAndFonts();
+	  }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void comeBackTo(int state)
+    {
+    comeBackState = state;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void setAction(int action)
+    {
+    nameChangeAction = action;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static Resources getResources()
+    {
+	return res;  
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void setPointerState(int state,int x,int y,boolean pressed)
+    {
+    if( pressed )
+      {
+      softkeyState = retSoftkey(state,x,y);
+      SokobanCanvas.setRepaint();
+
+      if( state==SokobanCanvas.STATE_CREA && y<=SokobanLevels.mGap/2 )
+        {
+        upperSoftkeyState = 1+(x/(scrWidth/5));
+        }
+      }
+
+    if( state==SokobanCanvas.STATE_MENU )
+      {
+      if( x>=(scrWidth-dialogX)/2 && x<=(scrWidth+dialogX)/2 )
+        {
+        menuItem = -1+(y+3*(mFontH+GAP)-(scrHeight+GAP)/2)/(mFontH+GAP);
+        }
+      }
+    else if( state==SokobanCanvas.STATE_HELP )
+      {
+      int len=scrWidth-10;
+      int gap=scrWidth/48;
+      if(len>500) len=500;
+      
+      if( x>=(scrWidth-len)/2+gap && y>=(scrHeight-dialogY0)/2+gap && 
+          x<=(scrWidth+len)/2-gap && y<=(scrHeight-dialogY0)/2+2*gap+sFontH+mFontH )
+        {
+    	mEmailClicked = true;  
+        }
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void tryPress(int state,int x,int y)
+    {
+    if( softkeyState!=SOFT_NOT ) 
+      {
+      if( y>= scrHeight-SokobanLevels.mGap/2 )
+        {
+        switch(softkeyState)
+          {
+          case SOFT_LEF: lefSoftkey(state); break;
+          case SOFT_RIG: rigSoftkey(state); break;
+          case SOFT_LEL: lelSoftkey(state); break;
+          case SOFT_LER: lerSoftkey(state); break;
+          }
+        }
+
+      softkeyState = SOFT_NOT;
+      SokobanCanvas.setRepaint();
+      }
+
+    if( state==SokobanCanvas.STATE_CREA )
+      {
+      switch( upperSoftkeyState )
+        {
+        case 1: SokobanLevels.drop(SokobanLevel.WALL); break;
+        case 2: SokobanLevels.drop(SokobanLevel.EMPT); break;
+        case 3: SokobanLevels.drop(SokobanLevel.PACK); break;
+        case 4: SokobanLevels.drop(SokobanLevel.DEST); break;
+        case 5: SokobanLevels.resetCreated();          break;
+        }
+      upperSoftkeyState=0;
+      }
+    else if( state==SokobanCanvas.STATE_MENU )
+      {
+      SokobanRecords sr;
+
+      switch(menuItem)
+        {
+        case 0: sr = mCanvas.getRecords();
+                if( sr.isDirtyRecords() )
+                  {
+                  mCanvas.getRecords().downloadRecords();
+                  SokobanCanvas.setState(SokobanCanvas.STATE_DOWN);
+                  }
+                else
+                  SokobanCanvas.setState(SokobanCanvas.STATE_SUCD);
+                break;
+        case 1: SokobanCanvas.setState(SokobanCanvas.STATE_CREA); break;
+        case 2: mCanvas.getRecords().downloadLevels();
+                SokobanCanvas.setState(SokobanCanvas.STATE_DOWL);
+                break;
+        case 3: SokobanCanvas.setState(SokobanCanvas.STATE_HELP); break;
+        }
+
+      menuItem = -1;
+      }
+    else if( state==SokobanCanvas.STATE_HELP )
+      {
+      int len=scrWidth-10;
+      int gap=scrWidth/48;
+      if(len>500) len=500;
+        
+      if( x>=(scrWidth-len)/2+gap && y>=(scrHeight-dialogY0)/2+gap && mEmailClicked && 
+          x<=(scrWidth+len)/2-gap && y<=(scrHeight-dialogY0)/2+gap+sFontH+mFontH )
+        {
+      	mCanvas.sendMail();  
+        }	
+      mEmailClicked = false;
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void lefSoftkey(int state)
+    {
+    switch(state)
+      {
+      case SokobanCanvas.STATE_NEWR: if( mCanvas.getRecords().submitRecord(SokobanLevels.getCurrLevel()) )
+                                       SokobanCanvas.setState(SokobanCanvas.STATE_SUBM);
+                                     else
+                                       {
+                                       nameChangeAction = ACTION_SUBR;
+                                       SokobanCanvas.setState(SokobanCanvas.STATE_NAME);
+                                       }
+                                     break;
+      case SokobanCanvas.STATE_NAME:
+      case SokobanCanvas.STATE_EXIS: changeName();
+                                     SokobanCanvas.setState(SokobanCanvas.STATE_SUBM);
+                                     break;
+      case SokobanCanvas.STATE_MAIN: SokobanCanvas.setState(SokobanCanvas.STATE_MENU);
+                                     break;
+      case SokobanCanvas.STATE_CREA: createdLevelError = SokobanLevels.validate();
+                                     SokobanCanvas.setState(SokobanCanvas.STATE_CRED);
+                                     break;
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void rigSoftkey(int state)
+    {
+    switch(state)
+      {
+      case SokobanCanvas.STATE_MAIN: mCanvas.getActivity().finish();
+                                     break;
+      case SokobanCanvas.STATE_DOWL:
+      case SokobanCanvas.STATE_DOWN: mCanvas.getRecords().abortNetworkTransaction();
+                                     SokobanCanvas.setState(SokobanCanvas.STATE_MENU);
+                                     break;
+      case SokobanCanvas.STATE_SUBM: mCanvas.getRecords().abortNetworkTransaction();
+      case SokobanCanvas.STATE_FAIL:
+      case SokobanCanvas.STATE_RECO:
+      case SokobanCanvas.STATE_NEWR:
+      case SokobanCanvas.STATE_TIME:
+      case SokobanCanvas.STATE_PLAY: SokobanLevels.getInstance().rollback();
+                                     SokobanLevels.getInstance().resetCurrTime();
+                                     SokobanCanvas.setState(SokobanCanvas.STATE_MAIN);
+                                     break;
+      case SokobanCanvas.STATE_CRES: SokobanLevels.getInstance().rollbackCreated();
+                                     SokobanCanvas.setState(SokobanCanvas.STATE_CREA);
+                                     break;
+      case SokobanCanvas.STATE_SECU: SokobanLevels.getInstance().rollback();
+                                     SokobanLevels.getInstance().resetCurrTime();
+                                     SokobanCanvas.setState(comeBackState);
+                                     break;
+      case SokobanCanvas.STATE_SUCE:
+      case SokobanCanvas.STATE_MENU: SokobanCanvas.setState(SokobanCanvas.STATE_MAIN);
+                                     break;
+      case SokobanCanvas.STATE_FAID:
+      case SokobanCanvas.STATE_SUCD:
+      case SokobanCanvas.STATE_FAIE:
+      case SokobanCanvas.STATE_CREA: SokobanCanvas.setState(SokobanCanvas.STATE_MENU);
+                                     break;
+      case SokobanCanvas.STATE_CRED: if( createdLevelError==0 )
+                                       SokobanCanvas.setState(SokobanCanvas.STATE_CRES);
+                                     else
+                                       SokobanCanvas.setState(SokobanCanvas.STATE_CREA);
+                                     break;
+      case SokobanCanvas.STATE_SUBC: SokobanLevel c = SokobanLevels.getInstance().getCreated();
+                                     if( mCanvas.getRecords().submitLevel(c.getCols(),c.encodeLevel()) )
+                                       SokobanCanvas.setState(SokobanCanvas.STATE_SUBM);
+                                     else
+                                       {
+                                       nameChangeAction = ACTION_SUBL;
+                                       SokobanCanvas.setState(SokobanCanvas.STATE_NAME);
+                                       }
+                                     break;
+      case SokobanCanvas.STATE_HELP: if( SokobanDatabase.getNumRunnings()==0 )
+                                       SokobanCanvas.setState(SokobanCanvas.STATE_MAIN);
+                                     else
+                                       SokobanCanvas.setState(SokobanCanvas.STATE_MENU);
+                                     break;
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void lelSoftkey(int state)
+    {
+    if( state==SokobanCanvas.STATE_PLAY )
+      {
+      SokobanLevels.getInstance().rollback();
+      }
+    else if( state==SokobanCanvas.STATE_CRES )
+      {
+      SokobanLevels.getInstance().rollbackCreated();
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void lerSoftkey(int state)
+    {
+    if( state==SokobanCanvas.STATE_PLAY )
+      {
+      SokobanLevels.getInstance().withdraw();
+      }
+    else if( state==SokobanCanvas.STATE_CRES )
+      {
+      SokobanLevels.getInstance().withdrawCreated();
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void downloadRecordsReady()
+    {
+	SokobanLevelBuffer.invalidateAllR();  
+    SokobanCanvas.setState(SokobanCanvas.STATE_SUCD);
+    SokobanCanvas.setRepaint();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void downloadLevelsReady(int num)
+    {
+    numDownloaded = num;
+    if( num>0 ) SokobanLevels.getInstance().scrollToEnd();
+    SokobanCanvas.setState(SokobanCanvas.STATE_SUCE);
+    SokobanCanvas.setRepaint();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void render(int state, Canvas c)
+    {  
+    switch(state)
+      {
+      case SokobanCanvas.STATE_NEWR: renderNewR(c); break;
+      case SokobanCanvas.STATE_TIME: renderTime(c); break;
+      case SokobanCanvas.STATE_RECO: renderReco(c); break;
+      case SokobanCanvas.STATE_NAME: renderName(c); break;
+      case SokobanCanvas.STATE_FAIL: renderFail(c); break;
+      case SokobanCanvas.STATE_EXIS: renderExis(c); break;
+      case SokobanCanvas.STATE_SUBM: renderSubm(c); break;
+      case SokobanCanvas.STATE_SECU: renderSecu(c); break;
+      case SokobanCanvas.STATE_MENU: renderMenu(c); break;
+      case SokobanCanvas.STATE_DOWN:
+      case SokobanCanvas.STATE_DOWL: renderDown(c); break;
+      case SokobanCanvas.STATE_HELP: renderHelp(c); break;
+      case SokobanCanvas.STATE_FAID:
+      case SokobanCanvas.STATE_FAIE: renderFaid(c); break;
+      case SokobanCanvas.STATE_SUCE: renderSuce(c); break;
+      case SokobanCanvas.STATE_CRED: renderCred(c); break;
+      case SokobanCanvas.STATE_SUBC: renderSubc(c); break;
+      }
+
+    if( state!=SokobanCanvas.STATE_CREA &&
+        state!=SokobanCanvas.STATE_CRED  ) renderUpperPane(state,c);
+    else                                   renderCreatedPane(c);
+
+    renderLowerPane(state,c); 
+    renderSoftkeyCaptions(state,c);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// private part
+
+  private void renderNewR( Canvas c )
+    {
+    maskBackground(c);
+    
+    drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY3)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY3)/2, false,c );
+
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+    
+    c.drawText(strNewr, scrWidth/2, scrHeight/2 - 3*mFontH/2, mPaint);
+    c.drawText(strSubm, scrWidth/2, scrHeight/2 + 5*mFontH/2, mPaint);
+
+    int seconds = SokobanLevels.getCurrTime();
+    int moves   = SokobanLevels.getCurrMoves();
+
+    mPaint.setFakeBoldText(true);
+
+    c.drawText(moves+strMoves    , scrWidth/2, scrHeight/2       , mPaint);
+    c.drawText(seconds+strSeconds, scrWidth/2, scrHeight/2+mFontH, mPaint);
+    
+    mPaint.setFakeBoldText(false);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderTime(Canvas c)
+    {
+    maskBackground(c);
+
+    drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY1)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY1)/2, false,c );
+
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+    
+    c.drawText(strSolved, scrWidth/2, scrHeight/2 - mFontH/2 -2,mPaint);
+
+    int seconds = SokobanLevels.getCurrTime();
+    int moves   = SokobanLevels.getCurrMoves();
+
+    mPaint.setFakeBoldText(true);
+
+    c.drawText(moves+strMoves    , scrWidth/2, scrHeight/2+  mFontH/2 +2,mPaint);
+    c.drawText(seconds+strSeconds, scrWidth/2, scrHeight/2+3*mFontH/2 +2,mPaint);      
+    
+    mPaint.setFakeBoldText(false);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderName(Canvas c)
+    {
+    maskBackground(c);
+
+    drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY1)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY1)/2, false,c );
+    
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+    
+    c.drawText(strFirst  , scrWidth/2, scrHeight/2         ,mPaint);
+    c.drawText(strChoose , scrWidth/2, scrHeight/2 +mFontH ,mPaint);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderReco(Canvas c)
+    {
+    maskBackground(c);
+
+    drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY1)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY1)/2, false,c );
+    
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+    
+    c.drawText(strSubmitted   , scrWidth/2, scrHeight/2         ,mPaint);
+    c.drawText(strSuccessfully, scrWidth/2, scrHeight/2 +mFontH ,mPaint);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderFail(Canvas c)
+    {
+    maskBackground(c);
+
+    drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY1)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY1)/2, false,c );
+    
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+    
+    c.drawText(strFTS, scrWidth/2, scrHeight/2 + mFontH/2, mPaint);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderExis(Canvas c)
+    {
+    maskBackground(c);
+
+    drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY1)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY1)/2, false,c );
+    
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+    
+    c.drawText( "'"+SokobanDatabase.getName()+"'", scrWidth/2, scrHeight/2 -   mFontH/2, mPaint);
+    c.drawText( strIAT                           , scrWidth/2, scrHeight/2 +   mFontH/2, mPaint);
+    c.drawText( strTagain                        , scrWidth/2, scrHeight/2 + 3*mFontH/2, mPaint);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderSubm(Canvas c)
+    {
+    maskBackground(c);
+
+    drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY1)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY1)/2, false,c );
+    
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+    
+    c.drawText(strSubmitting+"...", scrWidth/2, scrHeight/2 + mFontH/2, mPaint);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderSecu(Canvas c)
+    {
+    maskBackground(c);
+
+    drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY1)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY1)/2, false,c );
+    
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+    
+    c.drawText(strNoper, scrWidth/2, scrHeight/2         , mPaint);
+    c.drawText(strTun  , scrWidth/2, scrHeight/2 + mFontH, mPaint);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderMenu(Canvas c)
+    {
+	int h = mFontH+GAP;  
+	int h2= scrHeight/2 -h/2 +mFontH/3;
+	
+    maskBackground(c);
+
+    drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY2)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY2)/2, false,c );
+    
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+
+    if( menuItem>=0 && menuItem<=3 )
+      {
+      drawHighlight( (scrWidth-dialogX)/2+dialogM,scrHeight/2+(menuItem-2)*h,(scrWidth+dialogX)/2-dialogM, scrHeight/2+(menuItem-1)*h, true, c);
+      }
+    
+    c.drawText(strLeaderboard, scrWidth/2, h2-  h, mPaint);
+    c.drawText(strCNL        , scrWidth/2, h2    , mPaint);
+    c.drawText(strDlevels    , scrWidth/2, h2+  h, mPaint);
+    c.drawText(strHelp       , scrWidth/2, h2+2*h, mPaint);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderDown(Canvas c)
+    {
+    maskBackground(c);
+
+    drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY1)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY1)/2, false,c );
+    
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+    
+    c.drawText( strDownloading  , scrWidth/2, (scrHeight+mFontH)/2,  mPaint);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderHelp(Canvas c)
+    {
+    maskBackground(c);
+    int len = scrWidth-10;
+    int gap = scrWidth/48;
+
+    if( len>500 ) len=500;
+    
+    drawDialog( (scrWidth-len)/2,(scrHeight-dialogY0)/2, (scrWidth+len)/2, (scrHeight+dialogY0)/2, false,c );
+    
+    drawHighlight((scrWidth-len)/2+gap,(scrHeight-dialogY0)/2+gap, (scrWidth+len)/2-gap, (scrHeight-dialogY0)/2+2*gap+sFontH+mFontH, mEmailClicked,c);
+    
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+    
+    c.drawText( strName+" v."+SokobanCanvas.mVersionStr, scrWidth/2, (scrHeight-dialogY0)/2+gap+mFontH, mPaint);
+    mPaint.setTextSize(sFontH);
+    c.drawText( strEmail, scrWidth/2, (scrHeight-dialogY0)/2+gap+mFontH+sFontH, mPaint);
+
+    if( blockHelptext==null )
+      {
+      int helpHeight  = dialogY0-3*gap-mFontH-sFontH;
+      blockHelptext   = new SokobanStringBlock( strHelptxt, helpHeight, len-2*gap);
+      }
+    blockHelptext.draw(c,(scrWidth-len)/2+gap,(scrHeight-dialogY0)/2+mFontH+sFontH+2*gap, SokobanCanvas.COLOR_BLACK);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderFaid(Canvas c)
+    {
+    maskBackground(c);
+
+    drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY1)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY1)/2, false,c );
+    
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+    
+    c.drawText( strFTD, scrWidth/2, (scrHeight+mFontH)/2, mPaint);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderSuce(Canvas c)
+    {
+    maskBackground(c);
+
+    drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY1)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY1)/2, false,c );
+    
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(mFontH);
+    mPaint.setTextAlign(Align.CENTER);
+
+    if( numDownloaded>1 )
+      {
+      c.drawText(strDownloaded                 , scrWidth/2, scrHeight/2       , mPaint);
+      c.drawText(numDownloaded+" "+strNewLevels, scrWidth/2, scrHeight/2+mFontH, mPaint);
+      }
+    else if( numDownloaded==1 )
+      {
+      c.drawText(strDownloaded  , scrWidth/2, scrHeight/2        , mPaint);
+      c.drawText(strNewLevel  , scrWidth/2, scrHeight/2 +mFontH, mPaint);
+      }
+    else
+      {
+      c.drawText(strNoNewLevels, scrWidth/2, scrHeight/2        , mPaint);
+      c.drawText(strDownloaded2, scrWidth/2, scrHeight/2 +mFontH, mPaint);
+      }
+    }
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderSubc(Canvas c)
+    {
+    maskBackground(c);
+
+    
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderCred(Canvas c)
+    {
+    maskBackground(c);
+
+    if( createdLevelError==0 )
+      {
+      drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY3)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY3)/2, false,c );
+      
+      mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+      mPaint.setTextSize(mFontH);
+      mPaint.setTextAlign(Align.CENTER);
+      
+      c.drawText(strSolveIt, scrWidth/2, scrHeight/2- 2*mFontH  +SokobanLevels.mGapO, mPaint );
+      c.drawText(strYWL    , scrWidth/2, scrHeight/2+   mFontH/2-SokobanLevels.mGapO, mPaint );
+      c.drawText(strOTS    , scrWidth/2, scrHeight/2+ 3*mFontH/2-SokobanLevels.mGapO, mPaint );
+      c.drawText(strUL     , scrWidth/2, scrHeight/2+ 5*mFontH/2-SokobanLevels.mGapO, mPaint );
+      }
+    else
+      {
+      drawDialog( (scrWidth-dialogX)/2,(scrHeight-dialogY3)/2, (scrWidth+dialogX)/2, (scrHeight+dialogY3)/2, false,c );
+      
+      mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+      mPaint.setTextSize(mFontH);
+      mPaint.setTextAlign(Align.CENTER);
+      
+      c.drawText(strIncorrect, scrWidth/2, (scrHeight-dialogY3+3*mFontH)/2, mPaint);
+
+      mPaint.setTextSize(hFontH);
+
+      switch( createdLevelError )
+        {
+        case -1:
+        case -2: c.drawText(strPNTS  , scrWidth/2, scrHeight/2+  mFontH/2, mPaint );
+                 c.drawText(strOAES  , scrWidth/2, scrHeight/2+3*mFontH/2, mPaint );
+                 break;
+        case -3: c.drawText(strPA    , scrWidth/2, scrHeight/2+  mFontH/2, mPaint );
+                 c.drawText(strID    , scrWidth/2, scrHeight/2+3*mFontH/2, mPaint );
+                 break;
+        case -4: c.drawText(strNCF   , scrWidth/2, scrHeight/2+  mFontH  , mPaint );
+                 break;
+        case -5: c.drawText(strLISA  , scrWidth/2, scrHeight/2+  mFontH  , mPaint );
+                 break;
+        default: c.drawText(strNOCD  , scrWidth/2, scrHeight/2           , mPaint );
+                 c.drawText(strNETN  , scrWidth/2, scrHeight/2+  mFontH  , mPaint );
+                 c.drawText(strODS   , scrWidth/2, scrHeight/2+2*mFontH  , mPaint );
+                 break;
+        }
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void maskBackground(Canvas c)
+    {
+    if( mMaskBackground==null )
+      {
+      try
+        {
+        mMaskBackground = BitmapFactory.decodeResource(res, R.drawable.mask);
+        }
+      catch(Exception ex) { return; }
+      }
+    if( mMaskBackground!=null )
+      {
+      int mh = mMaskBackground.getHeight();
+      int mw = mMaskBackground.getWidth();
+
+      int h = (scrHeight-1)/mh;
+      int w = (scrWidth -1)/mw;
+
+      for(int i=0; i<=h; i++)
+        for(int j=0; j<=w; j++ )
+          c.drawBitmap(mMaskBackground, j*mw, i*mh, null);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int retSoftkey(int state, int x,int y)
+    {
+    if ( y>=scrHeight-SokobanLevels.mGap/2 )
+      {
+      if( x>scrWidth/2 )                     return SOFT_RIG;
+      if( state!=SokobanCanvas.STATE_PLAY &&
+          state!=SokobanCanvas.STATE_CRES  ) return SOFT_LEF;
+      
+      return x>scrWidth/4 ? SOFT_LER:SOFT_LEL;
+      }
+
+    return SOFT_NOT;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderUpperPane(int state, Canvas c)
+    {
+    drawDialog(0,0,scrWidth, SokobanLevels.mGap/2, false, c);
+
+    mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(3*SokobanLevels.mGap/8);
+    mPaint.setTextAlign(Align.CENTER);
+
+    int hei = 3*SokobanLevels.mGap/8;
+
+    switch(state)
+      {
+      case SokobanCanvas.STATE_MAIN: c.drawText(strName    , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_MENU: c.drawText(strOptions , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_PLAY: mPaint.setTextAlign(Align.LEFT);
+    	                             c.drawText(levelNumStr, 12,hei,mPaint );
+                                     if( fontSmall )
+                                       {
+                                       mPaint.setTextSize(SokobanLevels.mGap/4);
+                                       hei = SokobanLevels.mGap/3;
+                                       }
+                                     mPaint.setTextAlign(Align.RIGHT);
+                                     c.drawText(SokobanLevels.getCurrMoves()+"m "+SokobanLevels.getCurrTime()+"s", scrWidth-12,hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_CRES: c.drawText(strSolveNL , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_SUBC: c.drawText(strSubmitNL, scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_NEWR:
+      case SokobanCanvas.STATE_TIME: c.drawText(strSolved     , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_RECO: c.drawText(strSubmitted  , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_NAME: c.drawText(strCname      , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_FAID:
+      case SokobanCanvas.STATE_FAIE:
+      case SokobanCanvas.STATE_FAIL: c.drawText(strFailed     , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_EXIS: c.drawText(strNtaken     , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_SUBM: c.drawText(strSubmitting , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_SECU: c.drawText(strNoper      , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_DOWN: c.drawText(strLeaderboard, scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_DOWL: c.drawText(strDlevels    , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_HELP: c.drawText(strHelp       , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_SUCD: c.drawText(strRecords    , scrWidth/2, hei, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_SUCE: c.drawText(strDownloaded , scrWidth/2, hei, mPaint);
+                                     break;
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderCreatedPane(Canvas c)
+    {
+    int len = scrWidth/5;
+    int l2 = SokobanLevels.bCell1/2 - SokobanLevels.bMargin;
+    int h2 = SokobanLevels.mGap/4- l2;
+    int h  = SokobanLevels.packBig1.getHeight();
+    int h1 = (int)(0.32f*SokobanLevels.mGap);
+    	
+    drawHighlight(0*len, 0,   len, SokobanLevels.mGap/2, upperSoftkeyState==1, c);
+    drawHighlight(1*len, 0, 2*len, SokobanLevels.mGap/2, upperSoftkeyState==2, c);
+    drawHighlight(2*len, 0, 3*len, SokobanLevels.mGap/2, upperSoftkeyState==3, c);
+    drawHighlight(3*len, 0, 4*len, SokobanLevels.mGap/2, upperSoftkeyState==4, c);
+    drawHighlight(4*len, 0, 5*len, SokobanLevels.mGap/2, upperSoftkeyState==5, c);
+
+    mPaint.setColor(SokobanCanvas.COLOR_WHITE);
+    
+    if( h1 >= h )
+      {
+      c.drawBitmap(SokobanLevels.playBig1,    len/2-l2, h2, mPaint);
+      c.drawRect(3*len/2- l2, h2, 3*len/2+l2, h2+2*l2, mPaint);
+      c.drawBitmap(SokobanLevels.packBig1, 5*len/2- l2, h2, mPaint);
+      c.drawBitmap(SokobanLevels.destBig1, 7*len/2- l2, h2, mPaint);
+      }
+    else
+      {
+      Rect src = new Rect();
+      Rect dst = new Rect();
+      
+      int off= (h-h1)/2;
+      
+      src.top    = off;
+      src.left   = off;
+      src.bottom = h-off;
+      src.right  = h-off;
+
+      dst.top    = SokobanLevels.mGap/4 - h1/2;
+      dst.bottom = SokobanLevels.mGap/4 + h1/2;
+      
+      dst.left   = len/2 - h1/2;
+      dst.right  = len/2 + h1/2;
+      c.drawBitmap(SokobanLevels.playBig1, src, dst, mPaint);
+      
+      c.drawRect(3*len/2- h1/2, dst.top, 3*len/2+h1/2, dst.bottom, mPaint);
+      
+      dst.left   = 5*len/2 - h1/2;
+      dst.right  = 5*len/2 + h1/2;
+      c.drawBitmap(SokobanLevels.packBig1, src, dst, mPaint);
+      
+      dst.left   = 7*len/2 - h1/2;
+      dst.right  = 7*len/2 + h1/2;
+      c.drawBitmap(SokobanLevels.destBig1, src, dst, mPaint);
+      }
+    
+    c.drawBitmap(mRollBlack, 9*len/2- mRollW, SokobanLevels.mGap/4-mRollH, mPaint);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderLowerPane(int state, Canvas c)
+    {
+    boolean leftFocused = false;
+    boolean rightFocused= false;
+    boolean lelFocused  = false;
+    boolean lerFocused  = false;
+
+    if( softkeyState==SOFT_RIG )
+      {
+      if( state==SokobanCanvas.STATE_MAIN ||
+          state==SokobanCanvas.STATE_PLAY ||
+          state==SokobanCanvas.STATE_FAIL ||
+          state==SokobanCanvas.STATE_RECO ||
+          state==SokobanCanvas.STATE_SECU ||
+          state==SokobanCanvas.STATE_MENU ||
+          state==SokobanCanvas.STATE_NEWR ||
+          state==SokobanCanvas.STATE_SUBM ||
+          state==SokobanCanvas.STATE_DOWN ||
+          state==SokobanCanvas.STATE_CREA ||
+          state==SokobanCanvas.STATE_CRED ||
+          state==SokobanCanvas.STATE_CRES ||
+          state==SokobanCanvas.STATE_SUBC ||
+          state==SokobanCanvas.STATE_DOWL ||
+          state==SokobanCanvas.STATE_HELP ||
+          state==SokobanCanvas.STATE_SUCD ||
+          state==SokobanCanvas.STATE_SUCE ||
+          state==SokobanCanvas.STATE_FAID ||
+          state==SokobanCanvas.STATE_FAIE ||
+          state==SokobanCanvas.STATE_TIME  ) rightFocused = true;
+      }
+    else if ( softkeyState==SOFT_LEF )
+      {
+      if( state==SokobanCanvas.STATE_MAIN ||
+          state==SokobanCanvas.STATE_NEWR ||
+          state==SokobanCanvas.STATE_EXIS ||
+          state==SokobanCanvas.STATE_CREA ||
+          state==SokobanCanvas.STATE_NAME  ) leftFocused  = true;
+      }
+    else if ( softkeyState==SOFT_LEL )
+      {
+      if( state==SokobanCanvas.STATE_PLAY && SokobanLevels.getInstance().canWithdraw()       ==true ) lelFocused=true;
+      if( state==SokobanCanvas.STATE_CRES && SokobanLevels.getInstance().canWithdrawCreated()==true ) lelFocused=true;
+      }
+    else if ( softkeyState==SOFT_LER )
+      {
+      if( state==SokobanCanvas.STATE_PLAY && SokobanLevels.getInstance().canWithdraw()       ==true ) lerFocused=true;
+      if( state==SokobanCanvas.STATE_CRES && SokobanLevels.getInstance().canWithdrawCreated()==true ) lerFocused=true;
+      }
+
+    if( state!=SokobanCanvas.STATE_PLAY && state!=SokobanCanvas.STATE_CRES )
+      {
+      drawHighlight(         0, scrHeight-SokobanLevels.mGap/2, scrWidth/2, scrHeight, leftFocused, c);
+      }
+    else
+      {
+      mPaint.setColor(0xff000000);
+      mPaint.setStyle(Style.FILL);
+      c.drawRect(scrWidth/4-5, scrHeight-10, scrWidth/4+5, scrHeight, mPaint);
+      drawHighlight(         0, scrHeight-SokobanLevels.mGap/2, scrWidth/4, scrHeight, lelFocused, c);
+      drawHighlight(scrWidth/4, scrHeight-SokobanLevels.mGap/2, scrWidth/2, scrHeight, lerFocused, c);
+      }
+
+    drawHighlight(scrWidth/2, scrHeight-SokobanLevels.mGap/2, scrWidth, scrHeight, rightFocused, c);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void renderSoftkeyCaptions(int state, Canvas c)
+    {
+	mPaint.setColor(SokobanCanvas.COLOR_BLACK);
+    mPaint.setTextSize(3*SokobanLevels.mGap/8);
+    mPaint.setTextAlign(Align.CENTER);
+      
+    String tmp="";
+    int hei = scrHeight-SokobanLevels.mGap/8;
+
+    switch(state)
+      {
+      case SokobanCanvas.STATE_DOWN:
+      case SokobanCanvas.STATE_DOWL:
+      case SokobanCanvas.STATE_SUBM: tmp= strAbort; break;
+      case SokobanCanvas.STATE_PLAY:
+      case SokobanCanvas.STATE_TIME:
+      case SokobanCanvas.STATE_FAIL:
+      case SokobanCanvas.STATE_SECU:
+      case SokobanCanvas.STATE_CREA:
+      case SokobanCanvas.STATE_HELP:
+      case SokobanCanvas.STATE_RECO:
+      case SokobanCanvas.STATE_FAID:
+      case SokobanCanvas.STATE_FAIE:
+      case SokobanCanvas.STATE_SUCD:
+      case SokobanCanvas.STATE_CRES:
+      case SokobanCanvas.STATE_MENU: tmp= strBack ; break;
+      case SokobanCanvas.STATE_MAIN: tmp= strExit ; break;
+      case SokobanCanvas.STATE_SUCE: tmp= strOk   ; break;
+      case SokobanCanvas.STATE_CRED: tmp= (createdLevelError==0 ? strSolve:strBack); break;
+      case SokobanCanvas.STATE_SUBC: tmp= strSubmit; break;
+      case SokobanCanvas.STATE_NEWR: tmp= strNo    ; break;
+      }
+    c.drawText( tmp,3*scrWidth/4,hei, mPaint);
+    tmp ="";
+
+    switch(state)
+      {
+      case SokobanCanvas.STATE_CREA: tmp= strDone    ; break;
+      case SokobanCanvas.STATE_EXIS:
+      case SokobanCanvas.STATE_NAME: tmp= strOk      ; break;
+      case SokobanCanvas.STATE_MAIN: tmp= strOptions ; break;
+      case SokobanCanvas.STATE_NEWR: tmp= strYes     ; break;
+      case SokobanCanvas.STATE_CRES: boolean isBlack1 = SokobanLevels.getInstance().canWithdrawCreated();
+                                     c.drawBitmap(isBlack1?mRollBlack:mRollGray,  scrWidth/8-mRollW, scrHeight-SokobanLevels.mGap/4-mRollH, mPaint);
+                                     c.drawBitmap(isBlack1?mBackBlack:mBackGray,3*scrWidth/8-mBackW, scrHeight-SokobanLevels.mGap/4-mBackH, mPaint);
+                                     break;
+      case SokobanCanvas.STATE_PLAY: boolean isBlack2 = SokobanLevels.getInstance().canWithdraw();
+                                     c.drawBitmap(isBlack2?mRollBlack:mRollGray,  scrWidth/8-mRollW, scrHeight-SokobanLevels.mGap/4-mRollH, mPaint);
+                                     c.drawBitmap(isBlack2?mBackBlack:mBackGray,3*scrWidth/8-mBackW, scrHeight-SokobanLevels.mGap/4-mBackH, mPaint);
+                                     break;
+      }
+    c.drawText(tmp ,scrWidth/4, hei, mPaint );
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void drawDialog(int x1, int y1, int x2, int y2, boolean clicked, Canvas c)
+    {
+	if( clicked )
+	  {
+	  mDlgRed.setBounds(x1, y1, x2, y2);
+	  mDlgRed.draw(c);
+	  }
+	else
+	  {
+	  mDialog.setBounds(x1, y1, x2, y2);
+	  mDialog.draw(c);	
+	  }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void drawHighlight(int x1, int y1, int x2, int y2, boolean clicked, Canvas c)
+    {
+	if( clicked )
+	  {
+	  mButtonClicked.setBounds(x1, y1, x2, y2);
+	  mButtonClicked.draw(c);
+	  }
+	else
+	  {
+	  mButtUnClicked.setBounds(x1, y1, x2, y2);
+	  mButtUnClicked.draw(c);	
+	  }
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void changeName()
+    {
+	if( tkb==null )
+	  {
+	  tkb = new TouchKeyboard( mCanvas.getActivity().getApplicationContext(), scrWidth, scrHeight);
+	  tkb.setTextFieldBkgColor(0xFFE0DBCA);
+	  tkb.setTextFieldBorderColor(0xFF040477);
+	  tkb.setTextFieldFontColor(0xFF0033CC);
+	  tkb.setBackgroundColor(Color.BLACK);
+	  tkb.setVirtualKeyboardListener(this);
+	  tkb.resetKeyBoard();
+	  tkb.setMaxSize(10);
+	  tkb.setMinSize(1);
+	  }
+
+	tkb.setText(SokobanDatabase.getName());
+	mCanvas.getActivity().setContentView(tkb);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void okPressed(String text)
+    { 
+    SokobanDatabase.setName(text);
+    SokobanLevels.getInstance().updateMyRecords(text);
+    mCanvas.getActivity().setContentView(mCanvas);
+    SokobanCanvas.setRepaint();
+
+    if( nameChangeAction==ACTION_SUBR )
+      {
+      mCanvas.getRecords().submitRecord(SokobanLevels.getCurrLevel());
+      }
+    if( nameChangeAction==ACTION_SUBL )
+      {
+      SokobanLevel c = SokobanLevels.getInstance().getCreated();
+      mCanvas.getRecords().submitLevel(c.getCols(),c.encodeLevel());
+      }
+
+    nameChangeAction = ACTION_NONE;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// end of SokobanMenu class
+}
\ No newline at end of file
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanRecordInfo.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanRecordInfo.java
new file mode 100644
index 0000000..6112712
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanRecordInfo.java
@@ -0,0 +1,171 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Leszek Koltunski, 2011-04-09
+//
+package com.threedcell.sokoban;
+
+import android.graphics.Bitmap;
+import android.graphics.Paint;
+import android.graphics.Canvas;
+import android.graphics.Paint.Align;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class SokobanRecordInfo
+{
+private static int mFontSize;	
+public  static int mCorr;
+
+private int move;
+private int time;
+private String name, cutname, country, movetime;
+private Bitmap img;
+private static Paint mPaint;
+private boolean mine;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+SokobanRecordInfo()
+  { 
+  mFontSize = (int)(SokobanLevels.levelInfoH*0.4);
+  mCorr = 1+ mFontSize/3 + SokobanLevels.FLAG_H/2;
+  mPaint = new Paint();
+  mPaint.setAntiAlias(true);
+  mPaint.setTextSize(mFontSize);
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+SokobanRecordInfo(int m, int t, String n, String c)
+  {
+  set(m,t,n,c);
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public void set(int m, int t, String n, String c)
+  {
+  move = m;
+  time = t;
+  name = n;
+  country = c;
+  movetime = move<SokobanDatabase.INVALID ? move+"m "+time+"s" : null;
+  img = SokobanLevels.getInstance().getFlag(c);
+  mine = SokobanDatabase.getName().equals(n);
+
+  setCut();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public void set(int m, int t)
+  {
+  move = m;
+  time = t;
+  movetime = move<SokobanDatabase.INVALID ? move+"m "+time+"s" : null;
+  setCut();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public void set(String n)
+  {
+  name = n;
+  mine = SokobanDatabase.getName().equals(n);
+  setCut();
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public static int getFontSize()
+  {
+  return mFontSize;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public int getMove()
+  {
+  return move;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public int getTime()
+  {
+  return time;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public String getName()
+  {
+  return name;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public String getCountry()
+  {
+  return country;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public void draw(int x, int y, Canvas c)
+  {
+  if( move<SokobanDatabase.INVALID )
+    {
+    boolean red = (mine && SokobanCanvas.getState()==SokobanCanvas.STATE_SUCD);
+    int x2 = x+SokobanLevels.levelInfoW-SokobanLevels.mGapI-SokobanLevels.FLAG_W+2;
+
+    if( red ) mPaint.setColor(0xffff0000);
+    
+    if( movetime!=null )
+      {
+      mPaint.setTextAlign(Align.LEFT);	
+      c.drawText( movetime, x+SokobanLevels.mGapI-2, y+1, mPaint);
+      }
+    
+    mPaint.setTextAlign(Align.RIGHT);	
+    
+    if( name!=null )
+      {
+      c.drawText(cutname==null? name:cutname, x2-SokobanLevels.mGapI/2 , y+1, mPaint);
+      }
+    if( img!=null )
+      {
+      c.drawBitmap( img, x2, y-mCorr, null);
+      }
+    
+    if( red ) mPaint.setColor(0xff000000);
+    }
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+private void setCut()
+  {
+  if( name==null || move==SokobanDatabase.INVALID ) { cutname=null; return; }
+
+  float len2 = mPaint.measureText(movetime);
+  float len1 = mPaint.measureText(name);
+  int len0 = SokobanLevels.levelInfoW-5*SokobanLevels.mGapI/2-SokobanLevels.FLAG_W+4;
+
+  if( len1+len2>len0 )
+    {
+    int l = name.length();
+
+    while( l>=2 && len1+len2>len0 )
+      {
+      l--;
+      cutname = name.substring(0,l);
+      len1 = mPaint.measureText(cutname);
+      }
+    }
+  else cutname = null;
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// end of SokobanRecordInfo
+}
\ No newline at end of file
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanRecords.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanRecords.java
new file mode 100644
index 0000000..27dc4e5
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanRecords.java
@@ -0,0 +1,679 @@
+package com.threedcell.sokoban;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.BufferedInputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import android.util.Log;
+
+///////////////////////////////////////////////////////////////////
+
+public class SokobanRecords implements Runnable
+{
+	private static final String TAG_RECORDS = "SokobanRecords";
+		
+	public static final int MAX_PLACES = 9;
+	public static final int DOWNLOADR  = 0;
+	public static final int DOWNLOADL  = 1;
+	public static final int SUBMITR    = 2;
+	public static final int SUBMITL    = 3;
+	public static final int IDLE       = 4;
+
+	private static final int MAX_SUBMIT = 10;
+
+	private static boolean mRunning;
+	private static boolean mDirtyRecords;
+	private static Thread mNetworkThrd = null;
+	private static int mode;
+
+	private static int lv;
+	private static int mCols;
+    
+	private static final String URL  = "http://koltunski.pl/sokoban/cgi-bin";
+    private static String iso = null;
+	private String name,veri;
+	private String mLevel;
+    
+	private static SokobanLevels mLevels=null;
+    
+	private static final String[] hex = {
+	  "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",
+	  "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f",
+	  "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
+	  "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f",
+	  "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27",
+	  "%28", "%29", "%2a", "%2b", "%2c", "%2d", "%2e", "%2f",
+	  "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37",
+	  "%38", "%39", "%3a", "%3b", "%3c", "%3d", "%3e", "%3f",
+	  "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47",
+	  "%48", "%49", "%4a", "%4b", "%4c", "%4d", "%4e", "%4f",
+	  "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57",
+	  "%58", "%59", "%5a", "%5b", "%5c", "%5d", "%5e", "%5f",
+	  "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67",
+	  "%68", "%69", "%6a", "%6b", "%6c", "%6d", "%6e", "%6f",
+	  "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77",
+	  "%78", "%79", "%7a", "%7b", "%7c", "%7d", "%7e", "%7f",
+	  "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87",
+	  "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f",
+	  "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97",
+	  "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f",
+	  "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",
+	  "%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae", "%af",
+	  "%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7",
+	  "%b8", "%b9", "%ba", "%bb", "%bc", "%bd", "%be", "%bf",
+	  "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7",
+	  "%c8", "%c9", "%ca", "%cb", "%cc", "%cd", "%ce", "%cf",
+	  "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
+	  "%d8", "%d9", "%da", "%db", "%dc", "%dd", "%de", "%df",
+	  "%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7",
+	  "%e8", "%e9", "%ea", "%eb", "%ec", "%ed", "%ee", "%ef",
+	  "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
+	  "%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff"
+	  };
+		
+///////////////////////////////////////////////////////////////////
+	
+	  public SokobanRecords()
+	    {
+		mRunning     = false;
+		mDirtyRecords= true;
+		mode         = IDLE;
+	    }
+
+///////////////////////////////////////////////////////////////////
+	  
+	  public static void setLevels(SokobanLevels sl)
+	    {
+		mLevels = sl;    
+	    }
+
+///////////////////////////////////////////////////////////////////
+
+	  private boolean start()
+	    {
+	    if( !mRunning )
+	      {
+	      mRunning = true;
+	      mNetworkThrd = new Thread(this);
+	      mNetworkThrd.start();
+
+	      return true;
+	      }
+
+	    return false;
+	    }
+	  
+///////////////////////////////////////////////////////////////////
+	  
+	  public void run()
+	    {
+		try
+		  {
+		  String message="";
+		  int run = SokobanDatabase.getNumRunnings();
+
+		  if(mode==SUBMITR)
+		    {
+		    int hash = computeSubmitHash(name,veri,getSMSC(),lv,run);
+            message=URL+"/submitr.cgi";
+		    message+=("?l="+generateLevelsList(lv));
+		    message+=("&m="+generateMovesList(lv));
+		    message+=("&t="+generateTimesList(lv));
+		    message+=("&v="+URLencode(veri));
+		    message+=("&n="+URLencode(name));
+		    message+=("&s="+URLencode(getSMSC()));
+		    message+=("&h="+hash);
+		    message+=("&r="+run);
+		    message+=("&p="+SokobanDatabase.getNumPlayings());
+		    message+=("&i="+SokobanDatabase.getId());
+		    message+=("&e="+SokobanCanvas.mVersionStr+"a");
+		    }
+		  else if(mode==DOWNLOADR)
+		    {
+		    message=URL+"/downloadr.cgi";
+		    message+="?n="+URLencode(veri);
+		    message+="&r="+run;
+		    message+="&e="+SokobanCanvas.mVersionStr+"a";
+		    }
+		  else if(mode==SUBMITL )
+		    {
+		    message=URL+"/submitl.cgi";
+		    message+="?n="+URLencode(name);
+		    message+="&l="+(SokobanLevels.getIntrinsic()-(SokobanDatabase.BUILTIN_LEVELS-1));
+		    message+="&s="+URLencode(getSMSC());
+	        message+="&w="+(mLevel.length()/mCols);
+		    message+="&c="+mCols;
+		    message+="&p="+mLevel;
+		    message+="&r="+run;
+		    message+="&e="+SokobanCanvas.mVersionStr+"a";
+		    }
+		  else if(mode==DOWNLOADL)
+		    {
+		    message=URL+"/downloadl.cgi";
+		    message+="?n="+URLencode(name);
+		    message+="&l="+(SokobanLevels.getIntrinsic()-(SokobanDatabase.BUILTIN_LEVELS-1));
+		    message+="&x="+SokobanLevels.bDrawnX1;   //12 x
+		    message+="&y="+SokobanLevels.bDrawnY2;   //18  
+		    message+="&r="+run;
+		    message+="&e="+SokobanCanvas.mVersionStr+"a";
+		    }
+		  
+		  String data = download(message);
+		  
+		  if(mode==SUBMITR)
+		    {
+		    parseResponse(data);
+		    fillData(data);
+		    }
+		  else if(mode==DOWNLOADR)
+		    {
+		    fillData(data);
+		    SokobanCanvas.getMenu().downloadRecordsReady();
+		    }
+		  else if(mode==SUBMITL)
+		    {
+		    int numDownloaded = getResponseNum(data);
+		    fillLevelsData(data);
+		    SokobanCanvas.getMenu().downloadLevelsReady(numDownloaded);
+		    SokobanLevels.getInstance().rollbackCreated();
+		    }
+	      else if(mode==DOWNLOADL)
+		    {
+		    int numDownloaded = getResponseNum(data);
+		    fillLevelsData(data);
+		    SokobanCanvas.getMenu().downloadLevelsReady(numDownloaded);
+		    }
+		  }
+		catch( IOException ioe )
+		  {
+		  if( mode==SUBMITR  ) SokobanCanvas.setState(SokobanCanvas.STATE_FAIL);
+		  if( mode==SUBMITL  ) SokobanCanvas.setState(SokobanCanvas.STATE_FAIC);
+		  if( mode==DOWNLOADR) SokobanCanvas.setState(SokobanCanvas.STATE_FAID);
+		  if( mode==DOWNLOADL) SokobanCanvas.setState(SokobanCanvas.STATE_FAIE);
+		  SokobanCanvas.setRepaint();
+		  }
+		catch( SecurityException ioe )
+		  {
+		  SokobanCanvas.setState(SokobanCanvas.STATE_SECU);
+		  SokobanCanvas.getMenu().comeBackTo( mode==SUBMITR ? SokobanCanvas.STATE_PLAY:SokobanCanvas.STATE_MAIN);
+		  SokobanCanvas.setRepaint();
+		  }
+		 
+		mRunning = false;
+		mode = IDLE;
+	    }
+
+///////////////////////////////////////////////////////////////////
+
+	  private String getSMSC()
+	    {
+		if( iso==null) iso = SokobanCanvas.getIso();
+		return iso;
+	    }
+	  
+
+///////////////////////////////////////////////////////////////////
+
+	  private int getResponseNum(String data)
+        {
+        int newline = data.indexOf('\n',1);
+        if( newline<0 ) newline = data.length();
+
+        int ret=-1;
+
+        try
+          {
+          ret= Integer.parseInt(data.substring(0, newline));
+          }
+        catch(NumberFormatException nfe) 
+          {
+          Log.e(TAG_RECORDS, "exception trying to parse "+data); 
+          }
+
+        return ret;
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  private void parseResponse(String data)
+        {
+        int responseNum = getResponseNum(data);
+
+        switch(responseNum)
+          {
+          case  0: SokobanCanvas.setState(SokobanCanvas.STATE_RECO);// success
+                   SokobanDatabase.setVeri(name);
+                   submitLevelsList(lv);
+                   break;
+          case -2: SokobanMenu.setAction(SokobanMenu.ACTION_SUBR);
+                   SokobanCanvas.setState(SokobanCanvas.STATE_EXIS);// name exists
+                   break;
+          case -3: // wrong hash 
+          default: SokobanCanvas.setState(SokobanCanvas.STATE_FAIL);// other error
+          }
+
+        SokobanCanvas.setRepaint();
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  private int computeSubmitHash(String n, String v, String s, int lvl, int r)
+        {
+        byte[] raw;
+        int ret=0;
+
+        try                                    { raw = n.getBytes("UTF-8"); }
+        catch(UnsupportedEncodingException ex) { raw = n.getBytes(       ); }
+
+        for(int i=0;i<raw.length;i++) ret += i*(raw[i] <0 ? ((int)raw[i]+256):raw[i]);
+
+        try                                    { raw = v.getBytes("UTF-8"); }
+        catch(UnsupportedEncodingException ex) { raw = v.getBytes(       ); }
+
+        for(int i=0;i<raw.length;i++) ret += i*(raw[i] <0 ? ((int)raw[i]+256):raw[i]);
+
+        try                                    { raw = s.getBytes("UTF-8"); }
+        catch(UnsupportedEncodingException ex) { raw = s.getBytes(       ); }
+
+        for(int i=0;i<raw.length;i++) ret += i*(raw[i] <0 ? ((int)raw[i]+256):raw[i]);
+
+        int num=0, move, time;
+        SokobanLevel sl = SokobanLevels.getLevel(lvl);
+        if( sl!=null )
+          {
+          move = sl.getMyMoves();
+          time = sl.getMyTime();
+          ret += (lvl+1)*time;
+          ret += (lvl+2)*move;
+          }
+
+        for(int i=0; num<MAX_SUBMIT; i++)
+          {
+          if( i==lvl ) continue;
+          sl = SokobanLevels.getLevel(i);
+          if( sl==null ) break;
+
+          if( !sl.isSubmitted() )
+            {
+            move = sl.getMyMoves();
+            time = sl.getMyTime();
+
+            if( move<SokobanDatabase.INVALID )
+              {
+              ret += (i+1)*time;
+              ret += (i+2)*move;
+              num++;
+              }
+            }
+          }
+
+        ret += 41*r;
+        ret %= 541;
+
+        return ret<0 ? -ret:ret;
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  private void fillLevelsData( String data )
+	    {
+        int len = data.length();
+        int begin=-1 ,end = -1;
+
+        while( begin<len )
+          {
+          end = data.indexOf('\n', begin+1);
+          if( end<0 ) end = len;
+
+          fillLevelsRow(data.substring(begin+1,end));
+          begin = end;
+          }
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  public void fillLevelsRow(String row)
+        {
+        int s1 = row.indexOf(' ',   0);
+        int s2 = row.indexOf(' ',s1+1);
+        int s3 = row.indexOf(' ',s2+1);
+        int s4 = row.indexOf(' ',s3+1);
+        int s5 = row.indexOf(' ',s4+1);
+        int s6 = row.length();
+
+        if( s6>s5 && s5>s4 & s4>s3 && s3>s2 && s2>s1 && s1>0 )
+          {
+          try
+            {
+            int level= Integer.valueOf( row.substring(   0,s1) ).intValue();
+            String n = row.substring(s1+1,s2);
+            String c = row.substring(s2+1,s3);
+       //   int rows = Integer.valueOf( row.substring(s3+1,s4) ).intValue();
+            int cols = Integer.valueOf( row.substring(s4+1,s5) ).intValue();
+            String p = row.substring(s5+1,s6);
+
+            SokobanLevel sl = new SokobanLevel(n,c,SokobanDatabase.INVALID, SokobanDatabase.INVALID,null,false,cols,p);
+            mLevels.addLevel(sl, SokobanDatabase.BUILTIN_LEVELS+level-1);
+            sl.setDirty();
+            }
+          catch( Exception ex ) { System.out.println("Exception trying to fillLevelsRow: "+ex.toString()); }
+          }
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  private void fillData( String data )
+        {
+        int len = data.length();
+        int begin=-1 ,end = -1;
+
+        while( begin<len )
+          {
+          end = data.indexOf('\n', begin+1);
+          if( end<0 ) end = len;
+
+          fillRow(data.substring(begin+1,end));
+          begin = end;
+          }
+
+        mDirtyRecords = false;  
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  public void fillRow(String row)
+	    {
+        int s1 = row.indexOf(' ',   0);
+        int s2 = row.indexOf(' ',s1+1);
+        int s3 = row.indexOf(' ',s2+1);
+        int s4 = row.indexOf(' ',s3+1);
+        int s5 = row.indexOf(' ',s4+1);
+        int s6 = row.length();
+ 
+        if( s6>s5 && s5>s4 & s4>s3 && s3>s2 && s2>s1 && s1>0 )
+          {
+          try
+            {
+            int l = Integer.valueOf( row.substring(   0,s1) ).intValue();
+            int m = Integer.valueOf( row.substring(s1+1,s2) ).intValue();
+            int t = Integer.valueOf( row.substring(s2+1,s3) ).intValue();
+            int p = Integer.valueOf( row.substring(s3+1,s4) ).intValue();
+            String n = row.substring(s4+1,s5);
+            String c = row.substring(s5+1,s6);
+
+            mLevels.fillLevelInfo(l,m,t,p,n,c);
+            }
+          catch( Exception ex ) { Log.e(TAG_RECORDS, "Exception trying to fillRow: "+ex.toString()); }
+          }
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  public void downloadLevels()
+        {   
+        mode = DOWNLOADL;
+        name = SokobanDatabase.getName();
+        start();
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  public void downloadRecords()
+        {
+        if( mDirtyRecords==true )
+          {
+          mode = DOWNLOADR;
+          name = SokobanDatabase.getName();
+          veri = SokobanDatabase.getVeri();
+          start();
+          }
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  public boolean submitRecord(int lvl)
+	    {
+        name = SokobanDatabase.getName();
+        if( name==null || name.length()==0 ) return false;
+        veri = SokobanDatabase.getVeri();
+        mode = SUBMITR;
+        lv = lvl;
+
+        start();
+        return true;
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  public boolean submitLevel(int cols, String level)
+        {
+        name = SokobanDatabase.getName();
+        if( name==null || name.length()==0 ) return false;
+        veri = SokobanDatabase.getVeri();
+        mode = SUBMITL;
+        mCols = cols;
+        mLevel= level;
+
+        start();
+        return true;
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  public void abortNetworkTransaction()
+	    {
+		mRunning = false;
+	    }
+
+///////////////////////////////////////////////////////////////////
+
+	  public boolean isDirtyRecords()
+        {
+        return mDirtyRecords;
+        }
+	  
+///////////////////////////////////////////////////////////////////
+
+	  public void setDirty()
+	  {
+		  mDirtyRecords=true;
+	  }
+
+///////////////////////////////////////////////////////////////////
+
+	  private static String URLencode(String s)
+        {
+        if( s==null ) return "";
+
+        StringBuffer sbuf = new StringBuffer();
+        int len = s.length();
+
+        for (int i = 0; i < len; i++) 
+          {
+          int ch = s.charAt(i);
+
+               if ('A' <= ch && ch <= 'Z') sbuf.append((char)ch);
+          else if ('a' <= ch && ch <= 'z') sbuf.append((char)ch);
+          else if ('0' <= ch && ch <= '9') sbuf.append((char)ch);
+          else if (ch == ' '             ) sbuf.append('+');
+          else if (ch == '-' || ch == '_'
+                || ch == '.' || ch == '!'
+                || ch == '~' || ch == '*'
+                || ch == '\'' || ch == '('
+                || ch == ')'             ) sbuf.append((char)ch);
+          else if (ch <= 0x007f)           sbuf.append(hex[ch]);
+          else if (ch <= 0x07FF) 
+            {
+            sbuf.append(hex[0xc0 | (ch >> 6)]);
+            sbuf.append(hex[0x80 | (ch & 0x3F)]);
+            } 
+          else 
+            {       
+            sbuf.append(hex[0xe0 | (ch >> 12)]);
+            sbuf.append(hex[0x80 | ((ch >> 6) & 0x3F)]);
+            sbuf.append(hex[0x80 | (ch & 0x3F)]);
+            }
+          }
+
+        return sbuf.toString();
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  private static void submitLevelsList(int lvl)
+	    {
+        int num=0;
+        SokobanLevel sl = SokobanLevels.getLevel(lvl);
+        if( sl!=null )
+          {
+          sl.setSubmitted(true);
+          sl.setDirty();
+          }
+
+        for(int i=0; num<MAX_SUBMIT; i++)
+          {
+          if( i==lvl ) continue;
+          sl = SokobanLevels.getLevel(i);
+          if( sl==null ) break;
+
+          if( !sl.isSubmitted() && sl.getMyMoves()<SokobanDatabase.INVALID )
+            {
+            sl.setSubmitted(true);
+            sl.setDirty();
+            num++;
+            }
+          }
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  private static String generateMovesList(int lvl)
+        {
+        int move, num=0;
+        SokobanLevel sl = SokobanLevels.getLevel(lvl);
+        String ret= (sl==null ? "" : sl.getMyMoves()+"");
+
+        for(int i=0; num<MAX_SUBMIT; i++)
+          {
+          if( i==lvl ) continue;
+          sl = SokobanLevels.getLevel(i);
+          if( sl==null ) break;
+
+          if( !sl.isSubmitted() )
+            {
+            move = sl.getMyMoves();
+
+            if( move<SokobanDatabase.INVALID )
+              {
+              ret += (","+move);
+              num++;
+              }
+            }
+          }
+
+        return ret;
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  private static String generateTimesList(int lvl)
+        {
+        int time, num=0;
+        SokobanLevel sl = SokobanLevels.getLevel(lvl);
+        String ret= (sl==null ? "" : sl.getMyTime()+"");
+
+        for(int i=0; num<MAX_SUBMIT; i++)
+          {
+          if( i==lvl ) continue;
+          sl = SokobanLevels.getLevel(i);
+          if( sl==null ) break;
+
+          if( !sl.isSubmitted() )
+            {
+            time = sl.getMyTime();
+
+            if( time<SokobanDatabase.INVALID )
+              {
+              ret += (","+time);
+              num++;
+              }
+            }
+          }
+
+        return ret;
+        }
+
+///////////////////////////////////////////////////////////////////
+
+	  private static String generateLevelsList(int lvl)
+        {
+        String ret=lvl+"";
+        SokobanLevel sl;
+        int num=0;  
+
+        for(int i=0; num<MAX_SUBMIT; i++)
+          {
+          if( i==lvl ) continue;  
+          sl = SokobanLevels.getLevel(i);
+          if( sl==null ) break;
+
+          if( !sl.isSubmitted() && sl.getMyMoves()<SokobanDatabase.INVALID )
+            {
+            ret+=(","+i);
+            num++;
+            }
+          }  
+
+        return ret;
+        }
+ 
+	  
+///////////////////////////////////////////////////////////////////
+
+	  private String download(String url) throws IOException, SecurityException
+	    {
+		URL connectURL = new URL(url);
+		HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection(); 
+
+		conn.setDoInput(true); 
+		conn.setDoOutput(true); 
+		conn.setRequestMethod("GET"); 
+        conn.connect();
+		conn.getOutputStream().flush();
+
+        InputStream is=null;
+	    try 
+	      {	 
+	      is = new BufferedInputStream(conn.getInputStream());
+	      int ch; 
+	      StringBuffer sb = new StringBuffer(); 
+	  
+	      while( ( ch = is.read() ) != -1 ) 
+	        { 
+	        sb.append( (char)ch ); 
+	        } 
+	      return sb.toString(); 
+	      }
+	    catch(Exception e)
+	      {
+	      Log.e(TAG_RECORDS, "biffed it getting HTTPResponse");
+	      }
+	    finally 
+	      {
+	      try 
+	        {
+	        if (is != null)
+	       	  is.close();
+	        } 
+	      catch (Exception e) {}
+	      }
+
+	    return "";
+	    }
+
+///////////////////////////////////////////////////////////////////
+// end of SokobanRecords
+}
\ No newline at end of file
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanStringBlock.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanStringBlock.java
new file mode 100644
index 0000000..cb7b83f
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanStringBlock.java
@@ -0,0 +1,201 @@
+package com.threedcell.sokoban;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class SokobanStringBlock 
+{
+	//private static final String TAG_BLOCK="SokobanStringBlock";
+	
+	private String str;
+	private int height,length;
+	private int realheight;
+	private int size, len;
+	private Paint mPaint;
+	private String buffer;
+	
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+	public SokobanStringBlock(String s, int h, int l)
+	{
+		str    =s;
+		length =l;
+		height =h;
+		len    = str.length();
+		
+		mPaint = new Paint();
+		buffer = new String();
+		
+		mPaint.setTextAlign(Align.LEFT);
+	    mPaint.setAntiAlias(true);
+	    mPaint.setFakeBoldText(true);
+	    
+	    size = computeOptimalSize();
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+	
+	public void draw(Canvas c, int x,int y, int color)
+	{
+		String tmp;
+	    int begin=0, end=0;
+	    int delta = (height-realheight)/2;
+	    
+	    mPaint.setColor(color);
+	    mPaint.setTextSize(size);
+		
+	    while( end>=0 && end<len )
+	      {
+	      end = getLine(str,size,begin,length);
+
+	      if( end>=0 )
+	        {
+	        if( str.charAt(begin) == '\n' ) begin++;
+
+	        if( end>begin )
+	          {
+	          tmp = str.substring(begin,end);
+
+	          if( end<len && str.charAt(end+1) != '\n' )
+	            displayJustified( tmp, size, x, y+delta, length, c);
+	          else  
+	        	c.drawText( tmp, x, y+delta+size, mPaint);  
+	          }
+
+	        y += (begin==end ? size/2 : size);
+	        begin = end;
+	        }
+	      }	
+	}
+	
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+	private void displayJustified(String str, int fontHeight, int x, int y, int length, Canvas c)
+    { 
+		int len       = str.length();
+		int numspaces = retNumSpaces(str);
+    
+		if( str.charAt(len-1) == ' ' ) numspaces--;
+
+		float left=x,w = (numspaces>0 ? (float)(length-mPaint.measureText(str))/numspaces : 0);
+		String tmp;
+		int begin,end=0;
+
+		while( end<len )
+		{
+			begin=end;
+			end = str.indexOf(' ', begin)+1;
+			if( end<=0 ) end = len;
+
+			tmp = str.substring(begin,end);
+			c.drawText( tmp, left, y+fontHeight, mPaint);
+			left+= (mPaint.measureText(tmp)+w);
+		}  
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+	
+	private int retNumSpaces(String str)
+    {
+		int begin=0, ret=0;
+
+		while( true )
+		{
+			begin = str.indexOf(' ', begin) +1;
+
+			if( begin>0 ) ret++;
+			else break;
+		}
+
+		return ret;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+	
+	  private int getLine(String text, int fontHeight, int begin, int width)
+	    {
+	    int nearestSpace   = text.indexOf(' ' , begin+1);
+	    int nearestNewline = text.indexOf('\n', begin+1);
+	    int len=0;
+	    
+	    mPaint.setTextSize(fontHeight);
+		
+	    if( nearestNewline>=0 && nearestNewline<nearestSpace ) return nearestNewline;
+	    if( nearestSpace<0 ) return text.length();
+	      
+	    buffer = text.substring(begin,nearestSpace);
+	        
+	    len = (int)mPaint.measureText(buffer);
+
+	    if( len>=width ) return nearestSpace+1;
+	        
+	    int lastSpace = nearestSpace;
+
+	    while( len<width )
+	      {
+	      lastSpace = nearestSpace;
+
+	      nearestNewline = text.indexOf('\n', lastSpace+1);
+	      nearestSpace   = text.indexOf(' ' , lastSpace+1);
+
+	      if( nearestNewline>=0 && nearestNewline<nearestSpace )
+	        {
+	        buffer = text.substring(begin,nearestNewline);
+	        len = (int)mPaint.measureText(buffer);
+	        return len<width ? nearestNewline : lastSpace+1;
+	        }
+	      if( nearestSpace<0 )
+	        {
+	    	buffer = text.substring(begin);      
+	    	len= (int)mPaint.measureText(buffer);
+	    	return len<width ? text.length()  : lastSpace+1;             
+	        }
+
+	      buffer = text.substring(begin,nearestSpace);
+	      len = (int)mPaint.measureText(buffer);
+	      }
+	    return lastSpace+1;
+	    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+	  private int computeOptimalSize()
+	  {
+		  int h=0, trysize=10;
+
+		  while( h<height )  
+			{
+			realheight = h;  
+			h = height(++trysize);
+			}
+  
+		  return trysize-1;
+	  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+	  
+	  private int height(int trySize)
+	  {
+		  int y=0 , begin=0, end=0;
+		     
+		  while( end>=0 && end<len )
+		  {
+		      end = getLine(str,trySize,begin,length);
+
+		      if( end>=0 )
+		        {
+		        if( str.charAt(begin) == '\n' ) begin++;
+		        y += (begin==end ? trySize/2 : trySize);
+		        begin = end;
+		        }
+		  }
+ 
+		  return y;
+	  }
+		
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// end of RRStringBlock	
+}
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanTimer.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanTimer.java
new file mode 100644
index 0000000..8fc8f1a
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/SokobanTimer.java
@@ -0,0 +1,92 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Leszek Koltunski, 2011-04-09
+//
+package com.threedcell.sokoban;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class SokobanTimer implements Runnable
+  {
+  private static boolean mRunning;
+  private static Thread mTimerThrd = null;
+  private static SokobanTimer timer = null;
+ 
+  private int runningTime;
+  private long startTime;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private SokobanTimer()
+    {
+    mRunning = false;
+    }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void init()
+    {
+    timer = new SokobanTimer();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static SokobanTimer getInstance()
+    {
+    return timer;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public boolean start(int time)
+    {
+    if( !mRunning && time>=0 )
+      {
+      mRunning = true;
+      mTimerThrd = new Thread(this);
+      mTimerThrd.start();
+
+      runningTime = time/10;
+      startTime = System.currentTimeMillis() - 100*time;
+ 
+      return true;
+      }
+
+    return false;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int stop()
+    {
+    if( mRunning )
+      {
+      mRunning = false;
+      return (int)(System.currentTimeMillis()-startTime)/100;
+      }
+
+    return -1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+        
+  public void run()
+    {
+    while( mRunning )
+      {
+      try { Thread.sleep(997); }
+      catch(InterruptedException ie) {}
+
+      runningTime++;
+
+      if( runningTime%10 ==0 )
+        runningTime = (int)(System.currentTimeMillis()-startTime)/1000;
+
+      if( mRunning ) SokobanLevels.setTime(runningTime);
+      } 
+    mTimerThrd = null;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// end of SokobanTimer class
+  }
\ No newline at end of file
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/TextFieldArea.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/TextFieldArea.java
new file mode 100644
index 0000000..6978fed
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/TextFieldArea.java
@@ -0,0 +1,144 @@
+package com.threedcell.sokoban;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+
+///////////////////////////////////////////////////////////////////
+
+public class TextFieldArea 
+    {
+	//private static final String TAG_TEXT = "RRText";
+	
+    private StringBuffer text;
+ 
+    private int textFieldBkgColor    = 0xFFEEEEEE;
+    private int textFieldBorderColor = 0xFF000000;
+    private int textFieldFontColor   = 0xFF000000;
+   
+    private int maxSize = -1;
+    private int strLen;
+    private Paint mPaint;
+    
+///////////////////////////////////////////////////////////////////
+    
+    public TextFieldArea() 
+    {
+        text   = new StringBuffer();
+        strLen = 0;
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+    }
+
+///////////////////////////////////////////////////////////////////
+    
+    public void deleteLastChar() 
+    {
+        if (strLen > 0) 
+        {
+            text.deleteCharAt(strLen-1);
+            strLen--;
+        }
+    }
+
+///////////////////////////////////////////////////////////////////
+    
+    public void insertNewChar(char aChar) 
+    {
+        if ( ((maxSize > 0) && (text.length() < maxSize)) || (maxSize < 0)) 
+        { 
+            if (aChar != 0) 
+            {
+                text.insert(strLen, aChar);
+                strLen++;
+            }
+        }
+    }
+
+///////////////////////////////////////////////////////////////////
+    
+    public String getText() 
+    {
+        return text.toString();
+    }
+
+///////////////////////////////////////////////////////////////////
+    
+    public void setText(String newText) 
+    {
+        text   = null;
+        text   = new StringBuffer(newText);
+        strLen = newText.length();
+    }
+
+///////////////////////////////////////////////////////////////////
+   
+    public void clearTextField() 
+    {
+        text = null;
+        text = new StringBuffer();
+        strLen = 0;
+    }
+
+///////////////////////////////////////////////////////////////////
+    
+    public void paint( Canvas canvas, int left, int top, int right, int bottom) 
+    {
+    	int fontH = (int)((bottom-top)*0.7);
+    	
+        mPaint.setColor(textFieldBkgColor);
+        mPaint.setStyle(Style.FILL);
+        canvas.drawRect(left, top, right, bottom, mPaint);
+        mPaint.setColor(textFieldBorderColor);
+        mPaint.setStyle(Style.STROKE);
+        canvas.drawRect(left, top, right, bottom, mPaint);
+        mPaint.setColor(textFieldFontColor);
+        mPaint.setTextSize(fontH);   
+        
+        String t = text.toString();
+        
+        while( mPaint.measureText(t) > right-left-(bottom-top)/2 )
+          {
+          mPaint.setTextSize(--fontH);
+          }
+        
+        canvas.drawText( t, left+(bottom-top)/4, (bottom+top+fontH)/2-fontH/8, mPaint);
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+    
+    public void setTextFieldBkgColor(int textFieldBkgColor) 
+    {
+        this.textFieldBkgColor = textFieldBkgColor;
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+    
+    public void setTextFieldBorderColor(int textFieldBorderColor)
+    {
+        this.textFieldBorderColor = textFieldBorderColor;
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+ 
+    public void setTextFieldFontColor(int textFieldFontColor) 
+    {
+        this.textFieldFontColor = textFieldFontColor;
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+
+    public int getMaxSize() 
+    {
+        return maxSize;
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+  
+    public void setMaxSize(int maxSize) 
+    {
+        this.maxSize = maxSize;
+    }
+////////////////////////////////////////////////////////////////////////////////
+// end of TextFieldArea    
+}
diff --git a/distorted-sokoban/src/main/java/com/threedcell/sokoban/TouchKeyboard.java b/distorted-sokoban/src/main/java/com/threedcell/sokoban/TouchKeyboard.java
new file mode 100644
index 0000000..c464d0a
--- /dev/null
+++ b/distorted-sokoban/src/main/java/com/threedcell/sokoban/TouchKeyboard.java
@@ -0,0 +1,459 @@
+package com.threedcell.sokoban;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.Style;
+import android.graphics.drawable.NinePatchDrawable;
+
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+
+//import android.util.Log;
+
+////////////////////////////////////////////////////////////////////////////////
+
+public class TouchKeyboard extends View
+  {
+  //private static final String TAG_KEYBOARD = "RubikKeyboard";    
+       
+  private static final int  MARGIN = 2;
+  private static final int WMARGIN = 8;
+  private static final int BUTTON_NONE = -4;
+  private static final int BUTTON_OK   = -3;
+  private static final int BUTTON_BKSP = -2;
+  private static final int BUTTON_CAPS = -1;
+ 
+  private int currPressed;
+ 
+  private TextFieldArea textField;
+  private Paint mPaint;
+  private NinePatchDrawable keyBlue, keyRed, keyWhite;
+  private Bitmap ok, bksp, caps;
+ 
+  private int bmpSize;
+ 
+  char[][] lowerCaseL =
+      { {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'},
+        {'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r'},
+        {'s', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0'},
+        {'1', '2', '3', '4', '5', '6', '7', '8', '9'}
+      };
+   
+  char[][] upperCaseL =
+      { {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'},
+        {'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R'},
+        {'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0'},
+        {'1', '2', '3', '4', '5', '6', '7', '8', '9'}
+      };
+ 
+  char[][] lowerCaseP =
+      { {'a', 'b', 'c', 'd', 'e', 'f'},
+        {'g', 'h', 'i', 'j', 'k', 'l'},
+        {'m', 'n', 'o', 'p', 'q', 'r'},
+        {'s', 't', 'u', 'v', 'w', 'x'},
+        {'y', 'z', '0', '1', '2', '3'},
+        {'4', '5', '6', '7', '8', '9'}
+      };
+
+  char[][] upperCaseP =
+      { {'A', 'B', 'C', 'D', 'E', 'F'},
+        {'G', 'H', 'I', 'J', 'K', 'L'},
+        {'M', 'N', 'O', 'P', 'Q', 'R'},
+        {'S', 'T', 'U', 'V', 'W', 'X'},
+        {'Y', 'Z', '0', '1', '2', '3'},
+        {'4', '5', '6', '7', '8', '9'}
+      };
+ 
+  private int width, height;
+ 
+  private int textFieldWidth;  
+  private int textFieldHeight;
+  private int textTopLeftX;  
+  private int textTopLeftY;
+  private int keyWidth, keyHeight;
+  private int sKeyWidth, sKeyHeight;
+     
+  private VirtualKeyboardListener invoker;
+   
+  private int charH;
+   
+  private int backgroundColor = 0xffffffff;
+  private int buttonsColor    = 0xff000000;
+ 
+  private boolean uppercase;
+  private int minSize=0;
+ 
+  public interface VirtualKeyboardListener
+    {    
+    void okPressed(String string);
+    }
+ 
+////////////////////////////////////////////////////////////////////////////////
+
+  public TouchKeyboard(Context context, int scrWid, int scrHei)
+    {
+    super(context);
+    mPaint = new Paint();
+    mPaint.setAntiAlias(true);
+   
+    currPressed = BUTTON_NONE;
+    width = scrWid;
+    height= scrHei;
+   
+    Resources res = context.getResources();
+
+    keyBlue = (NinePatchDrawable)res.getDrawable(R.drawable.keys_blue);
+    keyRed  = (NinePatchDrawable)res.getDrawable(R.drawable.keys_red);
+    keyWhite= (NinePatchDrawable)res.getDrawable(R.drawable.keys_white);
+   
+    ok  = BitmapFactory.decodeResource(res, R.drawable.ok  );
+    bksp= BitmapFactory.decodeResource(res, R.drawable.bksp);
+    caps= BitmapFactory.decodeResource(res, R.drawable.caps);
+   
+    if( width<=height )
+      {
+      sKeyWidth = width/3;
+      sKeyHeight= width/5;
+      keyWidth  = width/6;
+      keyHeight = (height-2*sKeyHeight)/6;
+     
+      textFieldHeight = height-sKeyHeight-6*keyHeight;
+      textFieldWidth = width;
+      textTopLeftX = 0;
+      textTopLeftY = sKeyHeight;
+      }
+    else
+      {
+      sKeyWidth = sKeyHeight = keyHeight = height/5;
+      keyWidth = (width+1)/9;
+               
+      textFieldHeight= sKeyHeight;
+      textFieldWidth = width-3*sKeyWidth;
+      textTopLeftX = sKeyWidth;
+      textTopLeftY = 0;
+      }
+ 
+    bmpSize = ok.getHeight();
+   
+    if( bmpSize> 0.8*sKeyHeight )
+      {
+      bmpSize = (int)(0.8*sKeyHeight);
+      ok   = Bitmap.createScaledBitmap(ok  , bmpSize, bmpSize, true);
+      bksp = Bitmap.createScaledBitmap(bksp, bmpSize, bmpSize, true);
+      caps = Bitmap.createScaledBitmap(caps, bmpSize, bmpSize, true);
+      }
+   
+    textField = new TextFieldArea();
+    charH= (int)(keyHeight*0.7);  
+    uppercase = true;
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+
+  public void resetKeyBoard()
+    {
+    textField.clearTextField();
+    invalidate();
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+
+  protected void onDraw(Canvas c)
+    {      
+    mPaint.setColor(backgroundColor);
+    mPaint.setStyle(Style.FILL);
+    mPaint.setTextSize(charH);
+    mPaint.setTextAlign(Align.CENTER);
+   
+    c.drawRect(0, 0, width, height, mPaint);
+   
+    mPaint.setColor(buttonsColor);
+   
+    textField.paint( c, textTopLeftX+1, textTopLeftY+MARGIN/2+1, textTopLeftX+textFieldWidth-1, textTopLeftY+textFieldHeight-MARGIN/2-1);
+   
+    if( currPressed==BUTTON_OK )
+      {
+      keyRed.setBounds( MARGIN/2, MARGIN/2, sKeyWidth-MARGIN/2, sKeyHeight-MARGIN/2);
+      keyRed.draw(c);
+      }
+    else
+      {
+      keyBlue.setBounds( MARGIN/2, MARGIN/2,sKeyWidth-MARGIN/2, sKeyHeight-MARGIN/2);
+      keyBlue.draw(c); 
+      }
+   
+    if( currPressed==BUTTON_BKSP )
+      {
+      keyRed.setBounds( width-2*sKeyWidth+MARGIN/2, MARGIN/2, width-sKeyWidth-MARGIN/2,sKeyHeight-MARGIN/2);
+      keyRed.draw(c);
+      }
+    else
+      {
+      keyBlue.setBounds(width-2*sKeyWidth+MARGIN/2, MARGIN/2, width-sKeyWidth-MARGIN/2,sKeyHeight-MARGIN/2);
+      keyBlue.draw(c); 
+      }
+   
+    if( currPressed==BUTTON_CAPS )
+      {
+      keyRed.setBounds( width-sKeyWidth+MARGIN/2, MARGIN/2, width-MARGIN/2,sKeyHeight-MARGIN/2);
+      keyRed.draw(c);
+      }
+    else
+      {
+      keyBlue.setBounds(width-sKeyWidth+MARGIN/2, MARGIN/2, width-MARGIN/2,sKeyHeight-MARGIN/2);
+      keyBlue.draw(c); 
+      }
+   
+    c.drawBitmap(ok  ,                   MARGIN/2+sKeyWidth/2-bmpSize/2, MARGIN/2+sKeyHeight/2-bmpSize/2, mPaint);
+    c.drawBitmap(bksp, width-2*sKeyWidth+MARGIN/2+sKeyWidth/2-bmpSize/2, MARGIN/2+sKeyHeight/2-bmpSize/2, mPaint);
+    c.drawBitmap(caps, width-  sKeyWidth+MARGIN/2+sKeyWidth/2-bmpSize/2, MARGIN/2+sKeyHeight/2-bmpSize/2, mPaint);
+   
+    int hei = (width<=height ? textFieldHeight+sKeyHeight : textFieldHeight);
+    int numCol = (width<=height ? lowerCaseP[0].length : lowerCaseL[0].length);
+    int numRow = (width<=height ? lowerCaseP.length : lowerCaseL.length);
+   
+    for(int j=0; j<numRow; j++)
+      {
+      for(int i=0; i<numCol; i++)
+        {  
+        if( currPressed==j*numCol+i )
+          {
+          keyRed.setBounds(  i*width/numCol+ MARGIN/2, hei+ MARGIN/2,
+                                     (i+1)*width/numCol- MARGIN/2, hei+ MARGIN/2 +keyHeight );
+          keyRed.draw(c);
+          keyWhite.setBounds(i*width/numCol+WMARGIN/2, hei+WMARGIN/2-keyHeight,
+                                 (i+1)*width/numCol-WMARGIN/2, hei-WMARGIN/2 );
+          keyWhite.draw(c);              
+         
+          if( width<=height )
+            c.drawText( uppercase? upperCaseP[j]:lowerCaseP[j], i,1,(float)(i*width/numCol+keyWidth/2),
+                        (float)(hei-keyHeight/2+charH*0.4), mPaint);
+          else
+                c.drawText( uppercase? upperCaseL[j]:lowerCaseL[j], i,1,(float)(i*width/numCol+keyWidth/2),
+                        (float)(hei-keyHeight/2+charH*0.4), mPaint);  
+          }
+        else
+          {
+          keyBlue.setBounds(  i*width/numCol+ MARGIN/2, hei+ MARGIN/2,
+                                  (i+1)*width/numCol- MARGIN/2, hei+ MARGIN/2 +keyHeight );
+          keyBlue.draw(c);
+          }
+       
+        if( width<=height )
+            c.drawText( uppercase? upperCaseP[j]:lowerCaseP[j], i,1,(float)(i*width/numCol+keyWidth/2),
+                        (float)(hei+keyHeight/2+charH*0.4), mPaint);
+        else
+            c.drawText( uppercase? upperCaseL[j]:lowerCaseL[j], i,1,(float)(i*width/numCol+keyWidth/2),
+                        (float)(hei+keyHeight/2+charH*0.4), mPaint);
+        }
+      hei+=keyHeight;
+      }
+    }
+
+///////////////////////////////////////////////////////////////////
+
+  public boolean onTouchEvent(MotionEvent event)
+    {
+    switch(event.getAction())
+      {
+      case MotionEvent.ACTION_DOWN: buttonPressed( (int)event.getX(), (int)event.getY() );
+                                    break;
+      case MotionEvent.ACTION_UP  : buttonReleased();
+                                    break;
+      case MotionEvent.ACTION_MOVE: buttonPressed( (int)event.getX(), (int)event.getY() );
+                                    break;
+      }
+
+    invalidate();
+    return true;
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+
+  private void buttonPressed(int x, int y)
+    {    
+    if( width<height )
+        {
+        if( y>=0 && y<sKeyHeight )
+              {
+                   if( x<=  sKeyWidth ) currPressed = BUTTON_OK;
+              else if( x<=2*sKeyWidth ) currPressed = BUTTON_BKSP;
+              else                      currPressed = BUTTON_CAPS;
+              }
+        else if( y>=sKeyHeight+textFieldHeight && y<=height )
+              {
+              currPressed = (int)((y-sKeyHeight-textFieldHeight)/keyHeight)*lowerCaseP[0].length + x/keyWidth;
+              }
+        }
+    else
+        {
+        if( y>=0 && y<textFieldHeight )
+              {
+                   if( x<=sKeyWidth )                               currPressed = BUTTON_OK;
+              else if( x>=width-2*sKeyWidth && x<=width-sKeyWidth ) currPressed = BUTTON_BKSP;
+              else if( x>=width- sKeyWidth && x<=width )            currPressed = BUTTON_CAPS;
+              else                                                  currPressed = BUTTON_NONE;
+              }
+        else if( y>=textFieldHeight && y<=height)
+              {
+              currPressed = (int)((y-textFieldHeight)/keyHeight)*lowerCaseL[0].length + x/keyWidth;
+              }
+        }
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+
+  private void buttonReleased()
+    {
+         if( currPressed==BUTTON_OK   ) okButtonAction();
+    else if( currPressed==BUTTON_BKSP ) bkspButtonAction();  
+    else if( currPressed==BUTTON_CAPS ) capsButtonAction();  
+    else if( currPressed>=0           ) charAreaAction(currPressed);        
+               
+    currPressed = BUTTON_NONE;
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+ 
+  @Override public boolean onKeyDown(int keyCode, KeyEvent event)
+    {
+    if( currPressed!=BUTTON_NONE ) return false;
+   /*
+    switch( keyCode )
+      {
+      case Keypad.KEY_ALT        :
+      case Keypad.KEY_SHIFT_RIGHT:
+      case Keypad.KEY_SHIFT_LEFT : currPressed= BUTTON_CAPS; invalidate(); break;
+      case Keypad.KEY_ENTER      : currPressed= BUTTON_OK  ; invalidate(); break;
+      case Keypad.KEY_DELETE     :
+      case Keypad.KEY_BACKSPACE  : currPressed= BUTTON_BKSP; invalidate(); break;
+      }
+   
+    if( key>='A' && key<='Z' ) { currPressed = key-'A'          ; invalidate(); }
+    if( key>='a' && key<='z' ) { currPressed = key-'a'          ; invalidate(); }
+    if( key>='0' && key<='9' ) { currPressed = 'z'-'a'+1+key-'0'; invalidate(); }
+   */
+    return true;
+    }
+   
+////////////////////////////////////////////////////////////////////////////////
+   
+  @Override public boolean onKeyUp(int keyCode, KeyEvent event)
+    {
+    buttonReleased();
+    return true;
+    }
+   
+////////////////////////////////////////////////////////////////////////////////
+
+  private void capsButtonAction()
+    {
+    uppercase = !uppercase;
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+
+  private void okButtonAction()
+    {
+    if ( invoker != null )
+      {
+      String text = textField.getText();
+
+      if( text.length()>= minSize )
+        invoker.okPressed(text);
+      }
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+
+  private void bkspButtonAction()
+    {
+    textField.deleteLastChar();
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+
+  private void charAreaAction(int pressed)
+    {    
+    int numCol = (width<height ? lowerCaseP[0].length:lowerCaseL[0].length);
+    int j = pressed/numCol;
+    int i = pressed%numCol;
+             
+    if( width<height )
+      textField.insertNewChar( uppercase ? upperCaseP[j][i]:lowerCaseP[j][i]);
+    else
+      textField.insertNewChar( uppercase ? upperCaseL[j][i]:lowerCaseL[j][i]);
+    }
+ 
+////////////////////////////////////////////////////////////////////////////////
+
+  public void setText(String text)
+    {
+    textField.setText( (text==null||text.length()==0)?"":text);
+    invalidate();
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+ 
+  public void setTextFieldBkgColor(int color)
+    {
+    textField.setTextFieldBkgColor(color);  
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+ 
+  public void setTextFieldBorderColor(int color)
+    {
+    textField.setTextFieldBorderColor(color);  
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+ 
+  public void setTextFieldFontColor(int color)
+    {
+    textField.setTextFieldFontColor(color);  
+    }
+ 
+////////////////////////////////////////////////////////////////////////////////
+
+  public int getBackgroundColor()
+    {
+    return backgroundColor;
+    }
+ 
+////////////////////////////////////////////////////////////////////////////////
+
+  public void setBackgroundColor(int backgroundColor)
+    {
+    this.backgroundColor = backgroundColor;
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+
+  public void setMaxSize(int maxSize)
+    {
+    textField.setMaxSize(maxSize);
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+
+  public void setMinSize(int minSize)
+    {
+    this.minSize = minSize;
+    }
+
+////////////////////////////////////////////////////////////////////////////////
+
+  public void setVirtualKeyboardListener(VirtualKeyboardListener invoker)
+    {
+    this.invoker = invoker;
+    }
+////////////////////////////////////////////////////////////////////////////////
+// end of TouchKeyboard  
+}
\ No newline at end of file
diff --git a/distorted-sokoban/src/main/res/drawable-hdpi/grb.jpg b/distorted-sokoban/src/main/res/drawable-hdpi/grb.jpg
new file mode 100644
index 0000000..fed7dc8
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-hdpi/grb.jpg differ
diff --git a/distorted-sokoban/src/main/res/drawable-hdpi/icon.png b/distorted-sokoban/src/main/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..ce817df
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-hdpi/icon.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-hdpi/icon_korean.png b/distorted-sokoban/src/main/res/drawable-hdpi/icon_korean.png
new file mode 100644
index 0000000..f149efc
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-hdpi/icon_korean.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-hdpi/icon_playbook.png b/distorted-sokoban/src/main/res/drawable-hdpi/icon_playbook.png
new file mode 100644
index 0000000..21f90d4
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-hdpi/icon_playbook.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-mdpi/splash.png b/distorted-sokoban/src/main/res/drawable-mdpi/splash.png
new file mode 100644
index 0000000..3aca36d
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-mdpi/splash.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/afg.png b/distorted-sokoban/src/main/res/drawable-nodpi/afg.png
new file mode 100644
index 0000000..2d83227
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/afg.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/alb.png b/distorted-sokoban/src/main/res/drawable-nodpi/alb.png
new file mode 100644
index 0000000..54f2407
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/alb.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/alg.png b/distorted-sokoban/src/main/res/drawable-nodpi/alg.png
new file mode 100644
index 0000000..c98c9eb
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/alg.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/and.png b/distorted-sokoban/src/main/res/drawable-nodpi/and.png
new file mode 100644
index 0000000..7aaaf16
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/and.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/arg.png b/distorted-sokoban/src/main/res/drawable-nodpi/arg.png
new file mode 100644
index 0000000..234d14d
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/arg.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/arm.png b/distorted-sokoban/src/main/res/drawable-nodpi/arm.png
new file mode 100644
index 0000000..ad4008e
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/arm.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/aus.png b/distorted-sokoban/src/main/res/drawable-nodpi/aus.png
new file mode 100644
index 0000000..6b04be9
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/aus.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/aut.png b/distorted-sokoban/src/main/res/drawable-nodpi/aut.png
new file mode 100644
index 0000000..a0bd158
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/aut.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/aze.png b/distorted-sokoban/src/main/res/drawable-nodpi/aze.png
new file mode 100644
index 0000000..1c41b05
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/aze.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/back_black.png b/distorted-sokoban/src/main/res/drawable-nodpi/back_black.png
new file mode 100644
index 0000000..c34be69
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/back_black.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/back_gray.png b/distorted-sokoban/src/main/res/drawable-nodpi/back_gray.png
new file mode 100644
index 0000000..1e86979
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/back_gray.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/bah.png b/distorted-sokoban/src/main/res/drawable-nodpi/bah.png
new file mode 100644
index 0000000..c41dbed
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/bah.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/ban.png b/distorted-sokoban/src/main/res/drawable-nodpi/ban.png
new file mode 100644
index 0000000..04d5218
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/ban.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/bel.png b/distorted-sokoban/src/main/res/drawable-nodpi/bel.png
new file mode 100644
index 0000000..f72586c
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/bel.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/bhu.png b/distorted-sokoban/src/main/res/drawable-nodpi/bhu.png
new file mode 100644
index 0000000..5850970
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/bhu.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/bir.png b/distorted-sokoban/src/main/res/drawable-nodpi/bir.png
new file mode 100644
index 0000000..1422b1c
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/bir.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/bksp.png b/distorted-sokoban/src/main/res/drawable-nodpi/bksp.png
new file mode 100644
index 0000000..88c092f
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/bksp.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/blr.png b/distorted-sokoban/src/main/res/drawable-nodpi/blr.png
new file mode 100644
index 0000000..34a10c7
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/blr.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/blz.png b/distorted-sokoban/src/main/res/drawable-nodpi/blz.png
new file mode 100644
index 0000000..e0d5aab
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/blz.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/bol.png b/distorted-sokoban/src/main/res/drawable-nodpi/bol.png
new file mode 100644
index 0000000..bf72279
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/bol.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/bos.png b/distorted-sokoban/src/main/res/drawable-nodpi/bos.png
new file mode 100644
index 0000000..86fa653
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/bos.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/bra.png b/distorted-sokoban/src/main/res/drawable-nodpi/bra.png
new file mode 100644
index 0000000..240fea3
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/bra.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/bru.png b/distorted-sokoban/src/main/res/drawable-nodpi/bru.png
new file mode 100644
index 0000000..c43f70b
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/bru.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/btn_clicked.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/btn_clicked.9.png
new file mode 100644
index 0000000..f5a125f
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/btn_clicked.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/btn_unclicked.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/btn_unclicked.9.png
new file mode 100644
index 0000000..4563dcb
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/btn_unclicked.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/bul.png b/distorted-sokoban/src/main/res/drawable-nodpi/bul.png
new file mode 100644
index 0000000..d488f2e
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/bul.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/can.png b/distorted-sokoban/src/main/res/drawable-nodpi/can.png
new file mode 100644
index 0000000..c6c01c9
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/can.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/caps.png b/distorted-sokoban/src/main/res/drawable-nodpi/caps.png
new file mode 100644
index 0000000..bc4c097
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/caps.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/cey.png b/distorted-sokoban/src/main/res/drawable-nodpi/cey.png
new file mode 100644
index 0000000..4e4cfab
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/cey.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/chi.png b/distorted-sokoban/src/main/res/drawable-nodpi/chi.png
new file mode 100644
index 0000000..6a92eb0
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/chi.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/chn.png b/distorted-sokoban/src/main/res/drawable-nodpi/chn.png
new file mode 100644
index 0000000..4aef943
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/chn.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/col.png b/distorted-sokoban/src/main/res/drawable-nodpi/col.png
new file mode 100644
index 0000000..d3b1f76
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/col.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/cos.png b/distorted-sokoban/src/main/res/drawable-nodpi/cos.png
new file mode 100644
index 0000000..9edd60d
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/cos.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/cro.png b/distorted-sokoban/src/main/res/drawable-nodpi/cro.png
new file mode 100644
index 0000000..c843463
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/cro.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/cub.png b/distorted-sokoban/src/main/res/drawable-nodpi/cub.png
new file mode 100644
index 0000000..1708014
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/cub.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/cyp.png b/distorted-sokoban/src/main/res/drawable-nodpi/cyp.png
new file mode 100644
index 0000000..038dd75
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/cyp.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/cze.png b/distorted-sokoban/src/main/res/drawable-nodpi/cze.png
new file mode 100644
index 0000000..a359daf
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/cze.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/den.png b/distorted-sokoban/src/main/res/drawable-nodpi/den.png
new file mode 100644
index 0000000..646acbe
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/den.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/dialog.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/dialog.9.png
new file mode 100644
index 0000000..c78c2cc
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/dialog.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/dialog_clicked.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/dialog_clicked.9.png
new file mode 100644
index 0000000..d822f05
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/dialog_clicked.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/dom.png b/distorted-sokoban/src/main/res/drawable-nodpi/dom.png
new file mode 100644
index 0000000..ebcb9af
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/dom.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/dpck.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/dpck.9.png
new file mode 100644
index 0000000..f9e500f
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/dpck.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/dpck_small.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/dpck_small.9.png
new file mode 100644
index 0000000..718b708
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/dpck_small.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/ecu.png b/distorted-sokoban/src/main/res/drawable-nodpi/ecu.png
new file mode 100644
index 0000000..e5ffbbd
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/ecu.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/egy.png b/distorted-sokoban/src/main/res/drawable-nodpi/egy.png
new file mode 100644
index 0000000..0352973
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/egy.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/esp.png b/distorted-sokoban/src/main/res/drawable-nodpi/esp.png
new file mode 100644
index 0000000..7bda8f9
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/esp.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/est.png b/distorted-sokoban/src/main/res/drawable-nodpi/est.png
new file mode 100644
index 0000000..ba8738d
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/est.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/fin.png b/distorted-sokoban/src/main/res/drawable-nodpi/fin.png
new file mode 100644
index 0000000..8c1f704
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/fin.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/fra.png b/distorted-sokoban/src/main/res/drawable-nodpi/fra.png
new file mode 100644
index 0000000..f9dc3e7
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/fra.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/geo.png b/distorted-sokoban/src/main/res/drawable-nodpi/geo.png
new file mode 100644
index 0000000..e14132e
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/geo.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/ger.png b/distorted-sokoban/src/main/res/drawable-nodpi/ger.png
new file mode 100644
index 0000000..9de865f
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/ger.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/gre.png b/distorted-sokoban/src/main/res/drawable-nodpi/gre.png
new file mode 100644
index 0000000..7ef08fb
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/gre.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/gua.png b/distorted-sokoban/src/main/res/drawable-nodpi/gua.png
new file mode 100644
index 0000000..6ca3f4e
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/gua.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/gum.png b/distorted-sokoban/src/main/res/drawable-nodpi/gum.png
new file mode 100644
index 0000000..3625608
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/gum.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/guy.png b/distorted-sokoban/src/main/res/drawable-nodpi/guy.png
new file mode 100644
index 0000000..fbf082e
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/guy.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/hai.png b/distorted-sokoban/src/main/res/drawable-nodpi/hai.png
new file mode 100644
index 0000000..74633b0
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/hai.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/hk.png b/distorted-sokoban/src/main/res/drawable-nodpi/hk.png
new file mode 100644
index 0000000..4f59b03
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/hk.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/hon.png b/distorted-sokoban/src/main/res/drawable-nodpi/hon.png
new file mode 100644
index 0000000..502f340
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/hon.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/hun.png b/distorted-sokoban/src/main/res/drawable-nodpi/hun.png
new file mode 100644
index 0000000..ad2f913
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/hun.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/ina.png b/distorted-sokoban/src/main/res/drawable-nodpi/ina.png
new file mode 100644
index 0000000..497a5c2
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/ina.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/ind.png b/distorted-sokoban/src/main/res/drawable-nodpi/ind.png
new file mode 100644
index 0000000..549b167
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/ind.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/irl.png b/distorted-sokoban/src/main/res/drawable-nodpi/irl.png
new file mode 100644
index 0000000..f19e962
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/irl.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/irn.png b/distorted-sokoban/src/main/res/drawable-nodpi/irn.png
new file mode 100644
index 0000000..b5eba7e
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/irn.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/irq.png b/distorted-sokoban/src/main/res/drawable-nodpi/irq.png
new file mode 100644
index 0000000..005aee7
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/irq.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/isl.png b/distorted-sokoban/src/main/res/drawable-nodpi/isl.png
new file mode 100644
index 0000000..66cca16
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/isl.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/isr.png b/distorted-sokoban/src/main/res/drawable-nodpi/isr.png
new file mode 100644
index 0000000..d705a21
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/isr.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/ita.png b/distorted-sokoban/src/main/res/drawable-nodpi/ita.png
new file mode 100644
index 0000000..eee4b34
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/ita.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/jam.png b/distorted-sokoban/src/main/res/drawable-nodpi/jam.png
new file mode 100644
index 0000000..98be5eb
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/jam.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/jap.png b/distorted-sokoban/src/main/res/drawable-nodpi/jap.png
new file mode 100644
index 0000000..6a2cfd6
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/jap.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/jor.png b/distorted-sokoban/src/main/res/drawable-nodpi/jor.png
new file mode 100644
index 0000000..0ccb7a3
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/jor.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/kaz.png b/distorted-sokoban/src/main/res/drawable-nodpi/kaz.png
new file mode 100644
index 0000000..7107ce3
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/kaz.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/keys_blue.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/keys_blue.9.png
new file mode 100644
index 0000000..c91c1dd
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/keys_blue.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/keys_red.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/keys_red.9.png
new file mode 100644
index 0000000..0c8ab50
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/keys_red.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/keys_white.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/keys_white.9.png
new file mode 100644
index 0000000..b264081
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/keys_white.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/kor.png b/distorted-sokoban/src/main/res/drawable-nodpi/kor.png
new file mode 100644
index 0000000..e633b32
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/kor.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/kuw.png b/distorted-sokoban/src/main/res/drawable-nodpi/kuw.png
new file mode 100644
index 0000000..6d1af47
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/kuw.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/kyr.png b/distorted-sokoban/src/main/res/drawable-nodpi/kyr.png
new file mode 100644
index 0000000..ada941b
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/kyr.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/lao.png b/distorted-sokoban/src/main/res/drawable-nodpi/lao.png
new file mode 100644
index 0000000..7deb33a
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/lao.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/lat.png b/distorted-sokoban/src/main/res/drawable-nodpi/lat.png
new file mode 100644
index 0000000..2c0fb61
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/lat.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/leb.png b/distorted-sokoban/src/main/res/drawable-nodpi/leb.png
new file mode 100644
index 0000000..8e6b0a9
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/leb.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/level_info.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/level_info.9.png
new file mode 100644
index 0000000..ef54f7c
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/level_info.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/lib.png b/distorted-sokoban/src/main/res/drawable-nodpi/lib.png
new file mode 100644
index 0000000..bcdb258
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/lib.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/lie.png b/distorted-sokoban/src/main/res/drawable-nodpi/lie.png
new file mode 100644
index 0000000..fb04261
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/lie.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/lit.png b/distorted-sokoban/src/main/res/drawable-nodpi/lit.png
new file mode 100644
index 0000000..3cd22d8
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/lit.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/lux.png b/distorted-sokoban/src/main/res/drawable-nodpi/lux.png
new file mode 100644
index 0000000..9ee38ef
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/lux.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/mac.png b/distorted-sokoban/src/main/res/drawable-nodpi/mac.png
new file mode 100644
index 0000000..a471cf2
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/mac.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/mal.png b/distorted-sokoban/src/main/res/drawable-nodpi/mal.png
new file mode 100644
index 0000000..71ea0b7
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/mal.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/mask.png b/distorted-sokoban/src/main/res/drawable-nodpi/mask.png
new file mode 100644
index 0000000..cf2c423
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/mask.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/mco.png b/distorted-sokoban/src/main/res/drawable-nodpi/mco.png
new file mode 100644
index 0000000..24cb3f3
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/mco.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/mda.png b/distorted-sokoban/src/main/res/drawable-nodpi/mda.png
new file mode 100644
index 0000000..86540bc
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/mda.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/mex.png b/distorted-sokoban/src/main/res/drawable-nodpi/mex.png
new file mode 100644
index 0000000..ac97ec7
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/mex.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/miq.png b/distorted-sokoban/src/main/res/drawable-nodpi/miq.png
new file mode 100644
index 0000000..070a55b
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/miq.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/mld.png b/distorted-sokoban/src/main/res/drawable-nodpi/mld.png
new file mode 100644
index 0000000..0988276
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/mld.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/mly.png b/distorted-sokoban/src/main/res/drawable-nodpi/mly.png
new file mode 100644
index 0000000..baa5524
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/mly.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/mna.png b/distorted-sokoban/src/main/res/drawable-nodpi/mna.png
new file mode 100644
index 0000000..bcf28dd
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/mna.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/mnt.png b/distorted-sokoban/src/main/res/drawable-nodpi/mnt.png
new file mode 100644
index 0000000..969a65c
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/mnt.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/mon.png b/distorted-sokoban/src/main/res/drawable-nodpi/mon.png
new file mode 100644
index 0000000..f8f36cd
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/mon.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/mor.png b/distorted-sokoban/src/main/res/drawable-nodpi/mor.png
new file mode 100644
index 0000000..0141c38
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/mor.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/ned.png b/distorted-sokoban/src/main/res/drawable-nodpi/ned.png
new file mode 100644
index 0000000..c84fcfb
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/ned.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/nep.png b/distorted-sokoban/src/main/res/drawable-nodpi/nep.png
new file mode 100644
index 0000000..bc74fae
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/nep.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/nic.png b/distorted-sokoban/src/main/res/drawable-nodpi/nic.png
new file mode 100644
index 0000000..eeef391
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/nic.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/nig.png b/distorted-sokoban/src/main/res/drawable-nodpi/nig.png
new file mode 100644
index 0000000..05c98cb
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/nig.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/nor.png b/distorted-sokoban/src/main/res/drawable-nodpi/nor.png
new file mode 100644
index 0000000..29b3df1
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/nor.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/nz.png b/distorted-sokoban/src/main/res/drawable-nodpi/nz.png
new file mode 100644
index 0000000..15fc4f1
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/nz.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/ok.png b/distorted-sokoban/src/main/res/drawable-nodpi/ok.png
new file mode 100644
index 0000000..94f65ea
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/ok.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/omn.png b/distorted-sokoban/src/main/res/drawable-nodpi/omn.png
new file mode 100644
index 0000000..b6abf4a
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/omn.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/pack.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/pack.9.png
new file mode 100644
index 0000000..635d3a4
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/pack.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/pack_small.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/pack_small.9.png
new file mode 100644
index 0000000..3132c55
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/pack_small.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/pak.png b/distorted-sokoban/src/main/res/drawable-nodpi/pak.png
new file mode 100644
index 0000000..e0d97bb
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/pak.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/pan.png b/distorted-sokoban/src/main/res/drawable-nodpi/pan.png
new file mode 100644
index 0000000..afb4c06
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/pan.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/pap.png b/distorted-sokoban/src/main/res/drawable-nodpi/pap.png
new file mode 100644
index 0000000..a3c0bb7
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/pap.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/par.png b/distorted-sokoban/src/main/res/drawable-nodpi/par.png
new file mode 100644
index 0000000..f610919
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/par.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/per.png b/distorted-sokoban/src/main/res/drawable-nodpi/per.png
new file mode 100644
index 0000000..8360c4c
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/per.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/phi.png b/distorted-sokoban/src/main/res/drawable-nodpi/phi.png
new file mode 100644
index 0000000..3d5ccae
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/phi.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/play.9.png b/distorted-sokoban/src/main/res/drawable-nodpi/play.9.png
new file mode 100644
index 0000000..3e9eab3
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/play.9.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/pol.png b/distorted-sokoban/src/main/res/drawable-nodpi/pol.png
new file mode 100644
index 0000000..3e98f4c
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/pol.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/por.png b/distorted-sokoban/src/main/res/drawable-nodpi/por.png
new file mode 100644
index 0000000..540115e
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/por.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/prk.png b/distorted-sokoban/src/main/res/drawable-nodpi/prk.png
new file mode 100644
index 0000000..c719fae
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/prk.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/qat.png b/distorted-sokoban/src/main/res/drawable-nodpi/qat.png
new file mode 100644
index 0000000..5c8ce2f
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/qat.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/roll_black.png b/distorted-sokoban/src/main/res/drawable-nodpi/roll_black.png
new file mode 100644
index 0000000..0e6bce7
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/roll_black.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/roll_gray.png b/distorted-sokoban/src/main/res/drawable-nodpi/roll_gray.png
new file mode 100644
index 0000000..779ffff
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/roll_gray.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/rom.png b/distorted-sokoban/src/main/res/drawable-nodpi/rom.png
new file mode 100644
index 0000000..2c2f864
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/rom.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/rus.png b/distorted-sokoban/src/main/res/drawable-nodpi/rus.png
new file mode 100644
index 0000000..317ed07
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/rus.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/sal.png b/distorted-sokoban/src/main/res/drawable-nodpi/sal.png
new file mode 100644
index 0000000..0d8e918
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/sal.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/sar.png b/distorted-sokoban/src/main/res/drawable-nodpi/sar.png
new file mode 100644
index 0000000..03cff07
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/sar.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/sin.png b/distorted-sokoban/src/main/res/drawable-nodpi/sin.png
new file mode 100644
index 0000000..f0dd79d
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/sin.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/slo.png b/distorted-sokoban/src/main/res/drawable-nodpi/slo.png
new file mode 100644
index 0000000..2b9ac6a
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/slo.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/sma.png b/distorted-sokoban/src/main/res/drawable-nodpi/sma.png
new file mode 100644
index 0000000..a214a39
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/sma.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/srb.png b/distorted-sokoban/src/main/res/drawable-nodpi/srb.png
new file mode 100644
index 0000000..36a8808
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/srb.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/sur.png b/distorted-sokoban/src/main/res/drawable-nodpi/sur.png
new file mode 100644
index 0000000..c11073a
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/sur.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/svk.png b/distorted-sokoban/src/main/res/drawable-nodpi/svk.png
new file mode 100644
index 0000000..76ed967
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/svk.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/swe.png b/distorted-sokoban/src/main/res/drawable-nodpi/swe.png
new file mode 100644
index 0000000..3e4af23
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/swe.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/swi.png b/distorted-sokoban/src/main/res/drawable-nodpi/swi.png
new file mode 100644
index 0000000..86f858b
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/swi.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/syr.png b/distorted-sokoban/src/main/res/drawable-nodpi/syr.png
new file mode 100644
index 0000000..64bf2de
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/syr.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/tha.png b/distorted-sokoban/src/main/res/drawable-nodpi/tha.png
new file mode 100644
index 0000000..00236d9
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/tha.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/tjk.png b/distorted-sokoban/src/main/res/drawable-nodpi/tjk.png
new file mode 100644
index 0000000..dc77671
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/tjk.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/tkm.png b/distorted-sokoban/src/main/res/drawable-nodpi/tkm.png
new file mode 100644
index 0000000..033c031
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/tkm.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/tun.png b/distorted-sokoban/src/main/res/drawable-nodpi/tun.png
new file mode 100644
index 0000000..3b4541a
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/tun.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/tur.png b/distorted-sokoban/src/main/res/drawable-nodpi/tur.png
new file mode 100644
index 0000000..1a2d7a6
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/tur.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/twn.png b/distorted-sokoban/src/main/res/drawable-nodpi/twn.png
new file mode 100644
index 0000000..7344986
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/twn.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/uae.png b/distorted-sokoban/src/main/res/drawable-nodpi/uae.png
new file mode 100644
index 0000000..c6bbf02
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/uae.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/uk.png b/distorted-sokoban/src/main/res/drawable-nodpi/uk.png
new file mode 100644
index 0000000..5d5c608
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/uk.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/ukr.png b/distorted-sokoban/src/main/res/drawable-nodpi/ukr.png
new file mode 100644
index 0000000..be02497
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/ukr.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/unk.png b/distorted-sokoban/src/main/res/drawable-nodpi/unk.png
new file mode 100644
index 0000000..ff7a8d5
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/unk.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/uru.png b/distorted-sokoban/src/main/res/drawable-nodpi/uru.png
new file mode 100644
index 0000000..0b55892
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/uru.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/usa.png b/distorted-sokoban/src/main/res/drawable-nodpi/usa.png
new file mode 100644
index 0000000..3990d13
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/usa.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/uzb.png b/distorted-sokoban/src/main/res/drawable-nodpi/uzb.png
new file mode 100644
index 0000000..d2c1859
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/uzb.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/ven.png b/distorted-sokoban/src/main/res/drawable-nodpi/ven.png
new file mode 100644
index 0000000..8924e94
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/ven.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/vie.png b/distorted-sokoban/src/main/res/drawable-nodpi/vie.png
new file mode 100644
index 0000000..b0d5f59
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/vie.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/yem.png b/distorted-sokoban/src/main/res/drawable-nodpi/yem.png
new file mode 100644
index 0000000..fc80d02
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/yem.png differ
diff --git a/distorted-sokoban/src/main/res/drawable-nodpi/za.png b/distorted-sokoban/src/main/res/drawable-nodpi/za.png
new file mode 100644
index 0000000..a5348ff
Binary files /dev/null and b/distorted-sokoban/src/main/res/drawable-nodpi/za.png differ
diff --git a/distorted-sokoban/src/main/res/layout/error.xml b/distorted-sokoban/src/main/res/layout/error.xml
new file mode 100644
index 0000000..3d043b7
--- /dev/null
+++ b/distorted-sokoban/src/main/res/layout/error.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+<TextView  
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" 
+    android:text="@string/error"
+    />
+</LinearLayout>
diff --git a/distorted-sokoban/src/main/res/layout/grb.xml b/distorted-sokoban/src/main/res/layout/grb.xml
new file mode 100644
index 0000000..b8f528a
--- /dev/null
+++ b/distorted-sokoban/src/main/res/layout/grb.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+  xmlns:android="http://schemas.android.com/apk/res/android"
+  android:layout_width="fill_parent"
+  android:layout_height="fill_parent"
+  android:gravity="center"
+  android:background="#FFFFFF">
+  <ImageView 
+      android:id="@+id/grbimage"
+      android:src="@drawable/grb"
+      android:layout_gravity="center"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:layout_centerHorizontal="true"/>
+</RelativeLayout>
diff --git a/distorted-sokoban/src/main/res/layout/splash.xml b/distorted-sokoban/src/main/res/layout/splash.xml
new file mode 100644
index 0000000..18b6464
--- /dev/null
+++ b/distorted-sokoban/src/main/res/layout/splash.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+  xmlns:android="http://schemas.android.com/apk/res/android"
+  android:layout_width="fill_parent"
+  android:layout_height="fill_parent"
+  android:gravity="center"
+  android:background="#FFFFFF">
+  <ImageView 
+      android:id="@+id/splashimage"
+      android:src="@drawable/splash"
+      android:layout_gravity="center"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:layout_centerHorizontal="true"/>
+  <TextView 
+  	  android:id="@+id/splashtext"
+  	  android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:text="@string/splash"
+      android:textColor="#65bd45"
+      android:textSize="24dp"
+      android:layout_centerHorizontal="true"
+      android:layout_below="@id/splashimage"/>
+</RelativeLayout>
diff --git a/distorted-sokoban/src/main/res/values-ko/strings.xml b/distorted-sokoban/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000..3796e9e
--- /dev/null
+++ b/distorted-sokoban/src/main/res/values-ko/strings.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <integer name="is_korean">1</integer>
+    <string name="app_name">Sokoban</string>
+    <string name="splash">ThreeDCell presents</string>
+    <string name="error">실행 에러!!</string>
+    <string name="email">sokoban@koltunski.pl</string>
+    <string name="level">레벨</string>
+    <string name="author">개발자:</string>
+    <string name="questions">질문하기?</string>
+    <string name="yourbest">베스트 스코어:</string>
+    <string name="worldsbest">세계 베스트 스코어:</string>
+    <string name="helptxt">노란사각형의 상자를 파란색으로 표시된 곳으로 이동시키는 게임입니다. 상자를 밀수만 있고 당길 수는 없습니다.\n\n레벨을 만들 수도 있습니다. (옵션 -> 새로운 레벨 만들기) 그리고 다른사람이 만든 레벨을 플레이 할 수 있습니다. 즐거운 시간되세요!</string>
+    <string name="newr">새 기록</string>
+    <string name="subm">온라인 등록?</string>
+    <string name="moves">이동</string>
+    <string name="seconds">초</string> 
+    <string name="solved">완료</string>
+    <string name="options">옵션</string>
+    <string name="solvenl">새 레벨 하기</string>
+    <string name="submitnl">새레벨 등록하기</string> 
+    <string name="first">먼저</string> 
+    <string name="choose">이름을 선택하세요</string>
+    <string name="submitted">등록됨</string>
+    <string name="successfully">성공적으로</string>
+    <string name="ok">Ok</string>
+    <string name="back">뒤로</string>
+    <string name="yes">예</string>
+    <string name="no">아니오</string>
+    <string name="exit">나가기</string> 
+    <string name="done">완료</string>
+    <string name="solve">풀기</string>
+    <string name="submit">등록</string>          
+    <string name="abort">나가기</string>          
+    <string name="downloaded">다운로드</string>
+    <string name="downloading">다운로드...</string>
+    <string name="help">도움말</string>   
+    <string name="records">기록</string>
+    <string name="fts">실패하였습니다</string>  
+    <string name="iat">이미 존재합니다</string>  
+    <string name="tagain">다시 시도 해주세요</string>  
+    <string name="submitting">등록</string>  
+    <string name="noper">이용권한이 없습니다</string>  
+    <string name="tun">네트워크 사용에</string>  
+    <string name="leaderboard">명예의 전당</string>  
+    <string name="failed">실패</string>  
+    <string name="dlevels">레벨 다운로드</string>  
+    <string name="ntaken">이름이 존재합니다</string>  
+    <string name="cname">이름을 선택하세요</string>  
+    <string name="cnl">새 레벨 만들기</string>           
+    <string name="ftd">다운로드 실패</string>     
+    <string name="newlevels">새 레벨</string>     
+    <string name="newlevel">1개의 새 레벨</string>     
+    <string name="nonewlevels">새로운 레벨 없음</string>     
+    <string name="downloaded2">다운로드됨</string>     
+    <string name="solveit">이제 풀어보세요</string>     
+    <string name="ywl">(다른사람이</string>     
+    <string name="ots">먼저 풀지 못한 레벨을</string>     
+    <string name="ul">등록하세요)</string>     
+    <string name="incorrect">레벨 불일치:</string>     
+    <string name="pnts">플레이어는</string>     
+    <string name="oaes">빈 자리에 위치해야 합니다</string>     
+    <string name="pa">플레이 지역에</string>  
+    <string name="id">접속할 수 없습니다</string>     
+    <string name="ncf">찾을 수 없습니다</string>     
+    <string name="lisa">레벨이 이미 완료되었습니다</string>     
+    <string name="nocd">숫자가</string>     
+    <string name="netn">일치하지 않습니다</string>     
+    <string name="ods">스퀘어를 확인하세요</string>
+</resources>
diff --git a/distorted-sokoban/src/main/res/values/strings.xml b/distorted-sokoban/src/main/res/values/strings.xml
new file mode 100644
index 0000000..cbe97d6
--- /dev/null
+++ b/distorted-sokoban/src/main/res/values/strings.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <integer name="is_korean">0</integer>
+    <string name="app_name">Sokoban</string>
+    <string name="splash">ThreeDCell presents</string>
+    <string name="error">Startup error!!</string>
+    <string name="email">sokoban@koltunski.pl</string>
+    <string name="level">Level</string>
+    <string name="author">Author:</string>
+    <string name="questions">Questions?</string>
+    <string name="yourbest">Your best:</string>
+    <string name="worldsbest">World\'s best:</string>
+    <string name="helptxt">Your goal is to move all the crates (yellow squares) to destination squares (marked with blue crosses). You can only push a crate, never pull it.\n\nYou can also create your own levels (go to Options -> Create New Level) and download levels created by others. Enjoy!</string>
+    <string name="newr">New Record</string>
+    <string name="subm">Submit it online?</string>
+    <string name="moves">moves</string>
+    <string name="seconds">seconds</string> 
+    <string name="solved">solved</string>
+    <string name="options">Options</string>
+    <string name="solvenl">Solve New Level</string>
+    <string name="submitnl">Submit New Level</string> 
+    <string name="first">First you have to</string> 
+    <string name="choose">choose your name</string>
+    <string name="submitted">Submitted</string>
+    <string name="successfully">successfully</string>
+    <string name="ok">Ok</string>
+    <string name="back">Back</string>
+    <string name="yes">Yes</string>
+    <string name="no">No</string>
+    <string name="exit">Exit</string> 
+    <string name="done">Done</string>
+    <string name="solve">Solve</string>
+    <string name="submit">Submit</string>          
+    <string name="abort">Abort</string>          
+    <string name="downloaded">Downloaded</string>
+    <string name="downloading">Downloading...</string>
+    <string name="help">Help</string>   
+    <string name="records">Records</string>
+    <string name="fts">Failed to submit</string>  
+    <string name="iat">is already taken</string>  
+    <string name="tagain">Try again</string>  
+    <string name="submitting">Submitting</string>  
+    <string name="noper">No permission</string>  
+    <string name="tun">to use network</string>  
+    <string name="leaderboard">Leaderboard</string>  
+    <string name="failed">Failed</string>  
+    <string name="dlevels">Download Levels</string>  
+    <string name="ntaken">Name taken</string>  
+    <string name="cname">Choose name</string>  
+    <string name="cnl">Create New Level</string>           
+    <string name="ftd">Failed To Download</string>     
+    <string name="newlevels">new levels</string>     
+    <string name="newlevel">1 new level</string>     
+    <string name="nonewlevels">No new levels</string>     
+    <string name="downloaded2">downloaded</string>     
+    <string name="solveit">Now please solve it</string>     
+    <string name="ywl">(You wouldn\'t like</string>     
+    <string name="ots">others to submit</string>     
+    <string name="ul">unsolvable levels?)</string>     
+    <string name="incorrect">Level incorrect:</string>     
+    <string name="pnts">Player needs to stand</string>     
+    <string name="oaes">on an empty square</string>     
+    <string name="pa">Playing area</string>  
+    <string name="id">is disconnected</string>     
+    <string name="ncf">No crates found</string>     
+    <string name="lisa">Level is solved already</string>     
+    <string name="nocd">Number of crates does</string>     
+    <string name="netn">not equal the number</string>     
+    <string name="ods">of destination squares</string>
+</resources>
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..6826e61
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..81dc0dc
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sat Jul 16 11:19:43 CEST 2022
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..ad1304a
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = "Magic Sokoban"
+include ':distorted-sokoban'
