Project

General

Profile

Download (33 KB) Statistics
| Branch: | Revision:

sokoban / distorted-sokoban / src / main / java / org / distorted / sokoban / SokobanLevel.java @ 1f6d1786

1
package org.distorted.sokoban;
2

    
3
import java.util.Vector;
4

    
5
import android.graphics.Bitmap;
6
import android.graphics.Paint;
7
import android.graphics.Canvas;
8
import android.graphics.Paint.Align;
9
import android.graphics.Paint.Style;
10

    
11
import android.content.Context;
12

    
13
//import android.util.Log;
14

    
15
///////////////////////////////////////////////////////////////////////////////////////////////////
16

    
17
public class SokobanLevel
18
  {
19
  public static final int COLOR_BACK = 0xff6a7900;
20
  public static final int COLOR_GRID = 0xff2e3500;
21
  public static final int COLOR_EMPT = 0xffffffff;
22
  public static final int COLOR_CRES = 0xff0000ff;
23
  
24
  private static final int MAX_PACKS = 100;    
25
  
26
  public static final int WALL = 0;
27
  public static final int EMPT = 1;
28
  public static final int DEST = 2;
29
  public static final int PACK = 3;
30
  public static final int DPCK = 4;
31
  public static final int PLAY = 5;
32
  public static final int PLAD = 6;
33

    
34
  private static final int DIR_N = 0;
35
  private static final int DIR_W = 1;
36
  private static final int DIR_E = 2;
37
  private static final int DIR_S = 3;
38
 
39
  private static final int SHOWING_MINE = 0;
40
  private static final int SHOWING_RECO = 1;
41
  
42
  private static int mShowing = SHOWING_MINE;
43
  
44
  private static int sWidth, sHeight;
45
  private static int mGapI, mGapO;
46
  private static int smallSize;
47
  private static int mMaxRecords;
48

    
49
  private int numLevel, intrinsicNumLevel, recordId=-1;
50
  private boolean mDirty = false;
51
  private String author, country;
52
  private static String strAuthor, strLevel, strYourBest, strWorldsBest;
53
  private Bitmap cImg;
54
  private boolean submitted;
55
  private static Paint mPaint = new Paint();
56
  private static int mRecordH;
57
  
58
  private int mRows, mCols, mPacks;
59
  private byte[][] cells;
60
  private byte[][] movableS, movableC;
61

    
62
  static class Move
63
    {
64
    byte index;
65
    byte move;
66

    
67
    public Move(int i, int m)
68
      {
69
      index = (byte)i;
70
      move  = (byte)m;
71
      }
72
    }
73
  private static Vector<Move> moves = new Vector<>();
74

    
75
  private SokobanRecordInfo[] recordList;
76
  private SokobanRecordInfo recordMine;
77

    
78
  private static byte[][] validateScratch;
79

    
80
///////////////////////////////////////////////////////////////////////////////////////////////////
81

    
82
  public SokobanLevel(Context context, int width,int height, int gap)
83
  {  
84
      submitted = false;
85
      author    = null;
86
      country   = null;
87
      cImg      = null;
88
      recordMine= new SokobanRecordInfo();
89

    
90
      movableC = new byte[MAX_PACKS+1][2];
91
      movableS = new byte[MAX_PACKS+1][2];
92

    
93
      strAuthor     = context.getString(R.string.author);
94
      strLevel      = context.getString(R.string.level);
95
      strYourBest   = context.getString(R.string.yourbest);
96
      strWorldsBest = context.getString(R.string.worldsbest);
97

    
98
      mPaint.setAntiAlias(true);
99
      mPaint.setStyle(Style.FILL);
100

    
101
      allocate(width,height,gap);
102
  }
103

    
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105
  
106
  public SokobanLevel(String a, String c, int mm, int mt, SokobanRecordInfo w, boolean sb, int cols, String position )
107
  {
108
      submitted= sb;
109

    
110
      author = a;
111
      country= c;
112

    
113
      SokobanDatabase db = SokobanDatabase.getInstance();
114

    
115
      if( db!=null )
116
        {
117
        recordMine = new SokobanRecordInfo(mm,mt,db.getName(),db.getCountry());
118
        }
119
      else
120
        {
121
        recordMine = new SokobanRecordInfo(mm,mt,"","");
122
        }
123

    
124
      cutAuthor();
125

    
126
      cImg = (author==null ? null:SokobanLevels.getInstance().getFlag(c));
127

    
128
      recordList = new SokobanRecordInfo[mMaxRecords];
129
      for(int i=0; i<mMaxRecords; i++) recordList[i]=null;
130

    
131
      recordList[0] = w;
132

    
133
      decodeLevel(cols,position);
134
  }
135

    
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

    
138
  public void allocate(int width,int height, int gap)
139
  {
140
      sWidth = width;
141
      sHeight= height-gap+2;
142
       
143
      mCols  = SokobanLevels.bDrawnX1;
144
      mRows  = SokobanLevels.bDrawnY1;
145

    
146
      mGapI = SokobanLevels.mGapI;
147
      mGapO = SokobanLevels.mGapO;
148
      smallSize = SokobanLevels.backSmallH;
149
      
150
      mRecordH = (int)(SokobanLevels.levelInfoH*0.4);
151
      if( mRecordH<SokobanLevels.FLAG_H+2 ) mRecordH = SokobanLevels.FLAG_H+2;
152
      
153
      mMaxRecords = (SokobanLevels.levelBigH - mGapI - (int)(SokobanLevels.levelInfoH*0.4) )/mRecordH;
154
    		  
155
      validateScratch = new byte[mRows][mCols]; 
156
      cells = new byte[mRows][mCols];
157

    
158
      recordList = new SokobanRecordInfo[mMaxRecords];
159
      for(int i=0; i<mMaxRecords; i++) recordList[i]=null;
160

    
161
      resetCreated();
162
  }
163
  
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165
  
166
  public void resetCreated()
167
  {
168
      for(int row=0; row<mRows; row++)
169
        for( int col=0; col<mCols; col++)
170
          {
171
          cells[row][col] = WALL;
172
          }
173

    
174
      movableC[0][0] = (byte)(SokobanLevels.bDrawnX1/2);
175
      movableC[0][1] = (byte)(SokobanLevels.bDrawnY1/2);
176
      movableS[0][0] = (byte)(SokobanLevels.bDrawnX1/2);
177
      movableS[0][1] = (byte)(SokobanLevels.bDrawnY1/2);
178

    
179
      mPacks = 0;
180
  }
181

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183

    
184
  private void cutAuthor()
185
  {
186
    if( author!=null )
187
      {
188
      mPaint.setTextSize(SokobanRecordInfo.getFontSize());
189

    
190
      float len2 = mPaint.measureText(strAuthor);
191
      float len1 = mPaint.measureText(author);
192
      int len0 = SokobanLevels.levelInfoW-10-28;
193

    
194
      if( len1+len2>len0 )
195
        {
196
        int l = author.length();
197

    
198
        while( l>=2 && len1+len2>len0 )
199
          {
200
          l--;
201
          author = author.substring(0,l);
202
          len1 = mPaint.measureText(author);
203
          }
204
        }
205
      }
206
  }
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

    
210
  public void drop(int stuff)
211
  {
212
      int row = movableC[0][1];
213
      int col = movableC[0][0];
214

    
215
      switch(stuff)
216
        {
217
        case WALL: cells[row][col] = WALL;
218
                   removePacksFrom(row,col);
219
                   break;
220
        case EMPT: cells[row][col] = EMPT;
221
                   removePacksFrom(row,col);
222
                   break;
223
        case DEST: cells[row][col] = DEST;
224
                   break;
225
        case PACK: if( mPacks<MAX_PACKS )
226
                     {
227
                     if( cells[row][col]==WALL ) cells[row][col]=EMPT;
228
                     mPacks++;
229
                     movableC[mPacks][0] = (byte)col;
230
                     movableC[mPacks][1] = (byte)row;
231
                     movableS[mPacks][0] = (byte)col;
232
                     movableS[mPacks][1] = (byte)row;
233
                     }
234
                   break;
235
        }
236
  }
237

    
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239

    
240
  private void removePacksFrom(int row, int col)
241
  {
242
       for(int i=1; i<=mPacks; i++)
243
         if( movableC[i][0]==col && movableC[i][1]==row )
244
            {
245
            movableC[i][0] = movableC[mPacks][0];
246
            movableC[i][1] = movableC[mPacks][1];
247
            movableS[i][0] = movableS[mPacks][0];
248
            movableS[i][1] = movableS[mPacks][1];
249
            mPacks--;
250
            break;
251
            }
252
  }
253

    
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255

    
256
  public int validate()
257
  {
258
      if( cells[movableC[0][1]][movableC[0][0]]==WALL ) return -1;
259
      if( hasPack(movableC[0][1], movableC[0][0])!=0 )  return -2;
260
      if( isDisconnected() )                            return -3;
261
      if( mPacks<1 )                                    return -4;
262
      if( isSolved() )                                  return -5;
263
      
264
      int numDest=0;
265

    
266
      for(int row=0; row<mRows; row++)
267
        for( int col=0; col<mCols; col++)
268
          {
269
          if( cells[row][col]==DEST ) numDest++;
270
          }
271

    
272
      if( mPacks != numDest ) return numDest+1;
273

    
274
      return 0;
275
  }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

    
279
  private boolean isDisconnected()
280
  {
281
      int numOfOnes=-1;
282

    
283
      for(int row=0; row<mRows; row++)
284
        for( int col=0; col<mCols; col++)
285
          {
286
          if( cells[row][col]==WALL ) validateScratch[row][col]=0;
287
          else
288
            {
289
            validateScratch[row][col]=1;
290
            numOfOnes++;
291
            }
292
          }
293

    
294
      validateScratch[movableC[0][1]][movableC[0][0]] = 2;
295

    
296
      int marked = 1;
297

    
298
      while( marked>0 )
299
        {
300
        marked=0;
301

    
302
        for(int row=0; row<mRows; row++)
303
          {
304
          for( int col=0; col<mCols; col++)
305
            {
306
            if( validateScratch[row][col]==1 )
307
              {
308
              if( ( row>0       && validateScratch[row-1][col]==2 ) ||
309
                  ( row+1<mRows && validateScratch[row+1][col]==2 ) ||
310
                  ( col>0       && validateScratch[row][col-1]==2 ) ||
311
                  ( col+1<mCols && validateScratch[row][col+1]==2 )  )
312
                {
313
                validateScratch[row][col]=2;
314
                marked++;
315
                }
316
              }
317
            }
318
          }
319
        numOfOnes-=marked;
320
        }
321

    
322
      return (numOfOnes>0);
323
  }
324

    
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326

    
327
  private void decodeLevel(int cols, String position)
328
  {
329
      int tmp;
330
      mPacks=0;
331

    
332
      try
333
        {
334
        mCols = cols;
335
        mRows = position.length()/cols;
336

    
337
        cells = new byte[mRows][mCols];
338

    
339
        for(int row=0; row<mRows; row++)
340
          for( int col=0; col<mCols; col++)
341
            {
342
            tmp = position.charAt(row*mCols+col)-'0';
343

    
344
            switch(tmp)
345
              {
346
              case PACK: cells[row][col] = EMPT; mPacks++; break;
347
              case DPCK: cells[row][col] = DEST; mPacks++; break;
348
              case WALL: cells[row][col] = WALL; break;
349
              case EMPT: cells[row][col] = EMPT; break;
350
              case DEST: cells[row][col] = DEST; break;
351
              case PLAY: cells[row][col] = EMPT; break;
352
              case PLAD: cells[row][col] = DEST; break;
353
              }
354
            }
355

    
356
        movableS = new byte[mPacks+1][2];
357
        movableC = new byte[mPacks+1][2];
358

    
359
        int num=1;
360

    
361
        for(int row=0; row<mRows; row++)
362
          for( int col=0; col<mCols; col++)
363
            {
364
            tmp = position.charAt(row*mCols+col)-'0';
365

    
366
            if( tmp==PACK || tmp==DPCK )
367
              {
368
              movableS[num][0]= (byte)col;
369
              movableS[num][1]= (byte)row;
370
              movableC[num][0]= (byte)col;
371
              movableC[num][1]= (byte)row;
372
              num++;
373
              }
374
            if( tmp==PLAY || tmp==PLAD )
375
              {
376
              movableS[0][0] = (byte)col;
377
              movableS[0][1] = (byte)row;
378
              movableC[0][0] = (byte)col;
379
              movableC[0][1] = (byte)row;
380
              }
381
            }
382
        }
383
      catch( Exception ex)
384
        {
385
        System.out.println("Exception trying to parse level: "+ex.toString());
386
        }
387
  }
388

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
  public String encodeLevel()
392
  {
393
      int beginC=0, endC=0, beginR=0, endR=0;
394
      boolean allWalls=true;
395

    
396
      for(int col=0; col<mCols && allWalls; col++)
397
        {
398
        for(int row=0; row<mRows; row++)
399
          {
400
          if( cells[row][col]!=WALL ) { allWalls=false; break; }
401
          }
402

    
403
        if( allWalls ) beginC++;
404
        }
405

    
406
      allWalls=true;
407

    
408
      for(int col=mCols-1; col>=0 && allWalls; col--)
409
        {
410
        for(int row=0; row<mRows; row++)
411
          {
412
          if( cells[row][col]!=WALL ) { allWalls=false; break; }
413
          }
414

    
415
        if( allWalls ) endC++;
416
        }
417

    
418
      allWalls=true;
419

    
420
      for(int row=0; row<mRows && allWalls; row++)
421
        {
422
        for(int col=0; col<mCols; col++)
423
          {
424
          if( cells[row][col]!=WALL ) { allWalls=false; break; }
425
          }
426

    
427
        if( allWalls ) beginR++;
428
        }
429

    
430
      allWalls=true;
431

    
432
      for(int row=mRows-1; row>=0 && allWalls; row--)
433
        {
434
        for(int col=0; col<mCols; col++)
435
          {
436
          if( cells[row][col]!=WALL ) { allWalls=false; break; }
437
          }
438

    
439
        if( allWalls ) endR++;
440
        }
441

    
442
      int index;
443
      StringBuffer ret = new StringBuffer();
444

    
445
      for(int row=beginR; row<mRows-endR; row++)
446
        for( int col=beginC; col<mCols-endC; col++)
447
          {
448
          switch( cells[row][col])
449
            {
450
            case WALL: ret.append('0'); break;
451
            case EMPT: ret.append('1'); break;
452
            case DEST: ret.append('2'); break;
453
            }
454
          }
455

    
456
      char setTo = (cells[movableS[0][1]][movableS[0][0]]==DEST ? '6':'5');
457

    
458
      ret.setCharAt( (movableS[0][1]-beginR)*(mCols-beginC-endC)+(movableS[0][0]-beginC), setTo);
459

    
460
      for(int i=1; i<=mPacks; i++)
461
        {
462
        index = (movableS[i][1]-beginR)*(mCols-beginC-endC)+(movableS[i][0]-beginC);
463
        ret.setCharAt(index, (ret.charAt(index)=='1' ? '3' : '4'));
464
        }
465

    
466
      return ret.toString();
467
  }
468

    
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470
 
471
  public void setRecordId(int id)
472
  {
473
     recordId = id;
474
  }
475

    
476
///////////////////////////////////////////////////////////////////////////////////////////////////
477

    
478
  public int getRecordId()
479
  {
480
     return recordId;
481
  }
482

    
483
///////////////////////////////////////////////////////////////////////////////////////////////////
484
 
485
  public void setDirty()  
486
  {
487
     mDirty = true;
488
  }
489

    
490
///////////////////////////////////////////////////////////////////////////////////////////////////
491

    
492
  public boolean isDirty()
493
  {
494
     return mDirty;
495
  }
496

    
497
///////////////////////////////////////////////////////////////////////////////////////////////////
498

    
499
  public void resetPrivate()
500
    {
501
    SokobanDatabase db = SokobanDatabase.getInstance();
502
    recordMine.set(SokobanDatabase.INVALID, SokobanDatabase.INVALID, db.getName(), db.getCountry());
503
    }
504

    
505
///////////////////////////////////////////////////////////////////////////////////////////////////
506

    
507
  public int getMyTime()
508
  {
509
      return recordMine.getTime();
510
  }
511

    
512
///////////////////////////////////////////////////////////////////////////////////////////////////
513

    
514
  public void setName(String n)
515
  {
516
      recordMine.set(n);
517
  }
518
  
519
///////////////////////////////////////////////////////////////////////////////////////////////////
520

    
521
  public void setMyInfo(int m, int t, String n, String c)
522
  {
523
      recordMine.set(m, t, n, c);
524
  }
525
  
526
///////////////////////////////////////////////////////////////////////////////////////////////////
527

    
528
  public int getMyMoves()
529
  {
530
      return recordMine.getMove();
531
  }
532

    
533
///////////////////////////////////////////////////////////////////////////////////////////////////
534

    
535
  public SokobanRecordInfo getRecordInfo(int num)
536
  {
537
      return (num>=0 && num<mMaxRecords ? recordList[num]:null);
538
  }
539

    
540
///////////////////////////////////////////////////////////////////////////////////////////////////
541

    
542
  public boolean isSubmitted()
543
  {
544
      return submitted;
545
  }
546

    
547
///////////////////////////////////////////////////////////////////////////////////////////////////
548

    
549
  public void setSubmitted(boolean sb)
550
  {
551
      submitted = sb;
552
  }
553

    
554
///////////////////////////////////////////////////////////////////////////////////////////////////
555

    
556
  public void setNum(int num)
557
  {
558
      numLevel = num;
559
  }
560

    
561
///////////////////////////////////////////////////////////////////////////////////////////////////
562

    
563
  public void setIntrinsicNum(int num)
564
  {
565
      intrinsicNumLevel = num;
566
  }
567

    
568
///////////////////////////////////////////////////////////////////////////////////////////////////
569

    
570
  public int getIntrinsicNum()
571
  {
572
      return intrinsicNumLevel;
573
  }
574

    
575
///////////////////////////////////////////////////////////////////////////////////////////////////
576

    
577
  public int getCols()
578
  {
579
      int begin=0, end=0;
580
      boolean allWalls=true;
581

    
582
      for(int col=0; col<mCols && allWalls; col++)
583
        {
584
        for(int row=0; row<mRows; row++)
585
          {
586
          if( cells[row][col]!=WALL ) { allWalls=false; break; }
587
          }
588

    
589
        if( allWalls ) begin++;
590
        }
591

    
592
      allWalls=true;
593

    
594
      for(int col=mCols-1; col>=0 && allWalls; col--)
595
        {
596
        for(int row=0; row<mRows; row++)
597
          {
598
          if( cells[row][col]!=WALL ) { allWalls=false; break; }
599
          }
600

    
601
        if( allWalls ) end++;
602
        }
603

    
604
      return mCols-begin-end;
605
  }
606

    
607
///////////////////////////////////////////////////////////////////////////////////////////////////
608

    
609
  public String getAuthor()
610
  {
611
      return author==null ? "":author;
612
  }
613

    
614
///////////////////////////////////////////////////////////////////////////////////////////////////
615

    
616
  public String getCountry()
617
  {
618
      return country==null ? "":country;
619
  }
620

    
621
///////////////////////////////////////////////////////////////////////////////////////////////////
622

    
623
  public void addRecordInfo(int m, int t,int p, String n, String c)
624
  {
625
      if( p>=0 && p<mMaxRecords )
626
        {
627
    	if( recordList[p]==null ) recordList[p] = new SokobanRecordInfo(m,t,n,c);
628
        else recordList[p].set(m,t,n,c);
629
        }
630
  }
631

    
632
///////////////////////////////////////////////////////////////////////////////////////////////////
633

    
634
  public void rollback()
635
  {
636
     for(int i=0; i<=mPacks; i++) 
637
       {
638
       movableC[i][0] = movableS[i][0];
639
       movableC[i][1] = movableS[i][1];
640
       }
641

    
642
     moves.removeAllElements();
643
  }
644

    
645
///////////////////////////////////////////////////////////////////////////////////////////////////
646

    
647
  public boolean canWithdraw()
648
  {
649
     return moves.size()>0;
650
  }
651

    
652
///////////////////////////////////////////////////////////////////////////////////////////////////
653

    
654
  public boolean withdraw()
655
  {
656
     int size = moves.size();
657

    
658
     if( size>0 )
659
       {
660
       Move m = (Move)moves.lastElement();
661
       int index = (int)m.index;
662
       moves.removeElementAt(size-1);
663

    
664
       switch(m.move)
665
         {
666
         case DIR_W: movableC[0][0]++; if( index>0 ) movableC[index][0]++; break;
667
         case DIR_E: movableC[0][0]--; if( index>0 ) movableC[index][0]--; break;
668
         case DIR_N: movableC[0][1]++; if( index>0 ) movableC[index][1]++; break;
669
         case DIR_S: movableC[0][1]--; if( index>0 ) movableC[index][1]--; break;
670
         }
671
       return true;
672
       }
673

    
674
     return false;
675
  }
676

    
677
///////////////////////////////////////////////////////////////////////////////////////////////////
678

    
679
  public boolean isSolved()
680
  {
681
     for(int i=1; i<=mPacks; i++)
682
        {
683
        if( cells[movableC[i][1]][movableC[i][0]]!=DEST ) return false;
684
        }
685

    
686
     return true;
687
  }
688

    
689
///////////////////////////////////////////////////////////////////////////////////////////////////
690

    
691
  private int hasPack(int row, int col)
692
  {
693
     for(int i=1; i<=mPacks; i++)
694
        {
695
        if( movableC[i][0]==col && movableC[i][1]==row ) return i;
696
        }
697

    
698
     return 0;
699
  }
700

    
701
///////////////////////////////////////////////////////////////////////////////////////////////////
702

    
703
  private int retDir(int dx, int dy)
704
  {
705
      if( dx>=dy ) return (dx>=-dy ? DIR_W:DIR_S);
706
      else         return (dx>=-dy ? DIR_N:DIR_E);
707
  }
708

    
709
///////////////////////////////////////////////////////////////////////////////////////////////////
710

    
711
  public boolean movePlayerFreely(int dx, int dy)
712
  {
713
      switch( retDir(dx,dy) )
714
      {
715
          case DIR_W: if( movableC[0][0]>0       ) { movableC[0][0]--; movableS[0][0]--; return true; }
716
                      return false;
717
          case DIR_E: if( movableC[0][0]+1<mCols ) { movableC[0][0]++; movableS[0][0]++; return true; }
718
                      return false;
719
          case DIR_N: if( movableC[0][1]>0       ) { movableC[0][1]--; movableS[0][1]--; return true; }
720
                      return false;
721
          case DIR_S: if( movableC[0][1]+1<mRows ) { movableC[0][1]++; movableS[0][1]++; return true; }
722
                      return false;      
723
      }
724

    
725
      return false;
726
  }
727

    
728
///////////////////////////////////////////////////////////////////////////////////////////////////
729

    
730
  public boolean movePlayer(int dx,int dy)
731
  { 
732
      int row = movableC[0][1];
733
      int col = movableC[0][0];
734
      int pack;
735

    
736
      switch( retDir(dx,dy) )
737
      {
738
           case DIR_N: if( row>0 && cells[row-1][col]!=WALL )
739
                         {
740
                         pack = hasPack(row-1,col);
741

    
742
                         if( pack==0 )
743
                           {
744
                           movableC[0][1]--;
745
                           moves.addElement( new Move(pack, DIR_N) );
746
                           return true;
747
                           }
748
                         else if( row>1 && cells[row-2][col]!=WALL && hasPack(row-2,col)==0 )
749
                           {
750
                           movableC[pack][1]--;
751
                           movableC[0][1]--;
752
                           moves.addElement( new Move(pack, DIR_N) );
753
                           return true;
754
                           }
755
                         }
756
                       break;
757
           case DIR_S: if( row+1<mRows && cells[row+1][col]!=WALL )
758
                         {
759
                         pack = hasPack(row+1,col);
760
                         
761
                         if( pack==0 )
762
                           {
763
                           movableC[0][1]++;
764
                           moves.addElement( new Move(pack, DIR_S) );
765
                           return true;
766
                           }
767
                         else if( row+2<mRows && cells[row+2][col]!=WALL && hasPack(row+2,col)==0 )
768
                           {
769
                           movableC[pack][1]++;
770
                           movableC[0][1]++;
771
                           moves.addElement( new Move(pack, DIR_S) );
772
                           return true;
773
                           }
774
                         }
775
                       break;
776
           case DIR_W: if( col>0 && cells[row][col-1]!=WALL )
777
                         {
778
                         pack = hasPack(row,col-1);
779

    
780
                         if( pack==0 )
781
                           {
782
                           movableC[0][0]--;
783
                           moves.addElement( new Move(pack, DIR_W) );
784
                           return true;
785
                           }
786
                         else if( col>1 && cells[row][col-2]!=WALL && hasPack(row,col-2)==0 )
787
                           {
788
                           movableC[pack][0]--;
789
                           movableC[0][0]--;
790
                           moves.addElement( new Move(pack, DIR_W) );
791
                           return true;
792
                           }
793
                         }
794
                       break;
795
           case DIR_E: if( col+1<mCols && cells[row][col+1]!=WALL )
796
                         {
797
                         pack = hasPack(row,col+1);
798

    
799
                         if( pack==0 )
800
                           {
801
                           movableC[0][0]++;
802
                           moves.addElement( new Move(pack, DIR_E) );
803
                           return true;
804
                           }
805
                         else if( col+2<mCols && cells[row][col+2]!=WALL && hasPack(row,col+2)==0 )
806
                           {
807
                           movableC[pack][0]++;
808
                           movableC[0][0]++;
809
                           moves.addElement( new Move(pack, DIR_E) );
810
                           return true;
811
                           }
812
                         }
813
                       break;
814
      }
815

    
816
      return false;
817
  }
818

    
819
///////////////////////////////////////////////////////////////////////////////////////////////////
820

    
821
  public void renderRecords(Canvas c, int y1)
822
    { 
823
	if( mShowing==SHOWING_MINE )  
824
	  {
825
	  mShowing = SHOWING_RECO;
826
	  SokobanLevelBuffer.invalidateAllR();
827
	  }
828
	c.drawBitmap( SokobanLevels.bkgUnClick, 0, y1, null);
829
    
830
    int buff, y= y1+mGapO/2+mGapI;
831
    
832
    buff= SokobanLevelBuffer.isLBuffered(numLevel);
833
    
834
    if( buff<0 )
835
      {
836
      buff = SokobanLevelBuffer.whereL(numLevel);	
837
      
838
      if( buff>=0 )
839
        {
840
        drawSmall(SokobanLevelBuffer.lC[buff]);
841
        SokobanLevelBuffer.setLBuffered(buff, numLevel);
842
        }
843
    //  Log.e("Level", "renderRecords: drawSmall: level "+numLevel+" to bank "+buff);
844
      }
845
    if( buff>=0 ) c.drawBitmap( SokobanLevelBuffer.lB[buff],               mGapO+mGapI, y, null);
846
    
847
    buff= SokobanLevelBuffer.isRBuffered(numLevel);
848
    
849
    if( buff<0 )
850
      {
851
      buff = SokobanLevelBuffer.whereR(numLevel);
852
      
853
      if( buff>=0 )
854
        {
855
        drawRecords(SokobanLevelBuffer.rC[buff]);
856
        SokobanLevelBuffer.setRBuffered(buff, numLevel);
857
        }
858
    //  Log.e("Level", "renderRecords: drawRecords: level "+numLevel+" to bank "+buff);
859
      }
860
    if( buff>=0 ) c.drawBitmap( SokobanLevelBuffer.rB[buff], mGapO+2*mGapI+smallSize-2, y, null);
861
    }
862
 
863
///////////////////////////////////////////////////////////////////////////////////////////////////
864
  
865
  public void renderSmall(Canvas c, int y1, boolean clicked)
866
  {
867
	  if( mShowing==SHOWING_RECO )  
868
        {
869
        mShowing = SHOWING_MINE;
870
        SokobanLevelBuffer.invalidateAllR();
871
        }
872
	  c.drawBitmap( clicked ? SokobanLevels.bkgClicked:SokobanLevels.bkgUnClick, 0, y1, null);
873
      
874
	  int buff, y = y1+mGapO/2+mGapI;
875
	  
876
	  buff= SokobanLevelBuffer.isLBuffered(numLevel);
877
	    
878
	  if( buff<0 )
879
	    {
880
	    buff = SokobanLevelBuffer.whereL(numLevel);	
881
	    
882
	    if( buff>=0 )
883
	      {
884
	      drawSmall(SokobanLevelBuffer.lC[buff]);
885
	      SokobanLevelBuffer.setLBuffered(buff, numLevel);
886
	      }
887
	  //  Log.e("Level", "renderSmall: drawSmall: level "+numLevel+" to bank "+buff);
888
	    }
889
	  if( buff>=0 ) c.drawBitmap( SokobanLevelBuffer.lB[buff], mGapO+mGapI, y, null);
890
	  
891
	  buff= SokobanLevelBuffer.isRBuffered(numLevel);
892
	    
893
	  if( buff<0 )
894
	    {
895
	    buff = SokobanLevelBuffer.whereR(numLevel);	
896
	    
897
	    if( buff>=0 )
898
	      {
899
	      drawMine(SokobanLevelBuffer.rC[buff]);
900
	      SokobanLevelBuffer.setRBuffered(buff, numLevel);
901
	      }
902
	  //  Log.e("Level", "renderSmall: drawMine: level "+numLevel+" to bank "+buff);
903
	    }
904
      if( buff>=0 ) c.drawBitmap( SokobanLevelBuffer.rB[buff], mGapO+2*mGapI+smallSize-2, y, null);    
905
  }
906
  
907
///////////////////////////////////////////////////////////////////////////////////////////////////
908

    
909
  private void drawMine(Canvas c)
910
    {   
911
	int m = SokobanLevels.levelInfoW/2;
912
    int h = (int)(SokobanLevels.levelInfoH*0.4);
913
    
914
    mPaint.setColor(SokobanLevels.COLOR_BLACK);
915
	mPaint.setTextSize(h);
916
	mPaint.setTextAlign(Align.CENTER);
917
	  
918
	c.drawBitmap( SokobanLevels.levelInfo, 0, 0                                 , null);
919
	c.drawBitmap( SokobanLevels.levelInfo, 0,   (SokobanLevels.levelInfoH+mGapI), null);
920
	c.drawBitmap( SokobanLevels.levelInfo, 0, 2*(SokobanLevels.levelInfoH+mGapI), null);
921
      
922
    if( author==null )
923
      {
924
      c.drawText(strLevel+" "+numLevel, m, SokobanLevels.levelInfoH/2+h/3, mPaint);
925
      }
926
    else
927
      {
928
      int h1 = 2+  SokobanLevels.levelInfoH/4+h/3;
929
      int h2 =-2+3*SokobanLevels.levelInfoH/4+h/3;
930
      int x1 = SokobanLevels.levelInfoW-3*mGapI/2-SokobanLevels.FLAG_W;
931
        
932
      c.drawText(strLevel+" "+numLevel, m, h1, mPaint);
933
      mPaint.setTextAlign(Align.LEFT);
934
      c.drawText(strAuthor, mGapI-2, h2+1, mPaint);
935
      mPaint.setTextAlign(Align.RIGHT);
936
      c.drawText(author    , x1          , h2+1                       , mPaint);
937
      c.drawBitmap(cImg    , x1+mGapI/2+2, h2-SokobanRecordInfo.mCorr ,   null);
938
      mPaint.setTextSize(h);
939
      }
940

    
941
    mPaint.setTextAlign(Align.CENTER);
942
    c.drawText(strYourBest  , m, 2+  (SokobanLevels.levelInfoH+mGapI)+ SokobanLevels.levelInfoH/4+h/3 ,mPaint );
943
    recordMine.draw( 0, -2+(SokobanLevels.levelInfoH+mGapI)+ 3*SokobanLevels.levelInfoH/4+h/3, c);
944
    c.drawText(strWorldsBest, m, 2+2*(SokobanLevels.levelInfoH+mGapI)+ SokobanLevels.levelInfoH/4+h/3 ,mPaint );
945
      
946
    if( recordList[0]!=null )
947
      recordList[0].draw( 0, -2+2*(SokobanLevels.levelInfoH+mGapI)+ 3*SokobanLevels.levelInfoH/4+h/3, c);
948
    }
949

    
950
///////////////////////////////////////////////////////////////////////////////////////////////////
951

    
952
  private void drawRecords(Canvas c)
953
    {
954
    int h = (int)(SokobanLevels.levelInfoH*0.4);
955
    int y=(h+mGapI/2);
956

    
957
    mPaint.setColor(SokobanLevels.COLOR_BLACK);
958
    mPaint.setTextSize(h);
959
    mPaint.setTextAlign(Align.CENTER);
960

    
961
    c.drawBitmap( SokobanLevels.levelBig, 0, 0, null);
962
    c.drawText(strLevel+" "+numLevel, SokobanLevels.levelBigW/2, y, mPaint);
963

    
964
    for(int i=0; i<mMaxRecords; i++)
965
      {
966
      if( recordList[i]!=null )
967
        {
968
        y+=mRecordH;    
969
        recordList[i].draw(0,y,c);
970
        }
971
      }
972
    }
973

    
974
///////////////////////////////////////////////////////////////////////////////////////////////////
975

    
976
  private void drawSmall(Canvas c)
977
  {
978
      int tmpCol, tmpRow, dCol, dRow;
979
      int v = SokobanLevels.sDrawnY-mRows;
980
      int h = SokobanLevels.sDrawnX-mCols;
981
      int cellx, celly;
982

    
983
      int vgap = v<0 ? 0    :v/2;
984
      int hgap = h<0 ? 0    :h/2;
985
      int varr = v<0 ?-(v/2):  0;
986
      int harr = h<0 ?-(h/2):  0;
987
      int vlen = v<0 ? SokobanLevels.sDrawnY:mRows;
988
      int hlen = h<0 ? SokobanLevels.sDrawnX:mCols;
989

    
990
      c.drawBitmap(SokobanLevels.backgroundSmall, 0, 0, null);
991
      
992
      for(int row=varr; row<varr+vlen; row++)
993
        for( int col=harr; col<harr+hlen; col++)
994
          {
995
          cellx = SokobanLevels.sMargin+(col+hgap-harr)*SokobanLevels.sCell;
996
          celly = SokobanLevels.sMargin+(row+vgap-varr)*SokobanLevels.sCell;
997
          
998
          switch( cells[row][col] )
999
            {
1000
            case EMPT: c.drawBitmap( SokobanLevels.emptySmall, cellx,celly, null);
1001
                       break;
1002
            case DEST: c.drawBitmap( SokobanLevels.destSmall , cellx,celly, null);
1003
                       break;
1004
            }
1005
          }
1006

    
1007
      for(int i=0; i<=mPacks; i++)
1008
        {
1009
        tmpCol = movableS[i][0];
1010
        tmpRow = movableS[i][1];
1011

    
1012
        dRow = tmpRow+vgap-varr;
1013
        dCol = tmpCol+hgap-harr;
1014

    
1015
        if( dRow>=0 && dRow< +SokobanLevels.sDrawnY && dCol>=0 && dCol< +SokobanLevels.sDrawnX  )
1016
          {
1017
          cellx = SokobanLevels.sMargin+dCol*SokobanLevels.sCell;
1018
          celly = SokobanLevels.sMargin+dRow*SokobanLevels.sCell;
1019

    
1020
          if( i==0 )
1021
        	  c.drawBitmap( SokobanLevels.playSmall , cellx,celly, null);
1022
          else if( cells[tmpRow][tmpCol]==DEST )
1023
        	  c.drawBitmap( SokobanLevels.dpckSmall , cellx,celly, null);
1024
          else
1025
        	  c.drawBitmap( SokobanLevels.packSmall , cellx,celly, null);
1026
          }
1027
        }
1028
  }
1029

    
1030
///////////////////////////////////////////////////////////////////////////////////////////////////
1031

    
1032
  public void renderBig(Canvas c, int x, int y)
1033
  {
1034
	  boolean isBig = (mRows>SokobanLevels.bDrawnY1);
1035
	  
1036
	  int drawnX, drawnY, gapX, gapY, bCell;
1037
	  
1038
	  if( isBig )
1039
	    {
1040
		drawnX = SokobanLevels.bDrawnX2;
1041
		drawnY = SokobanLevels.bDrawnY2;
1042
		gapX   = SokobanLevels.gapX2;
1043
		gapY   = SokobanLevels.gapY2;
1044
		bCell  = SokobanLevels.bCell2;
1045
	    }
1046
	  else
1047
	    {
1048
		drawnX = SokobanLevels.bDrawnX1;
1049
		drawnY = SokobanLevels.bDrawnY1;
1050
		gapX   = SokobanLevels.gapX1;
1051
		gapY   = SokobanLevels.gapY1;      
1052
		bCell  = SokobanLevels.bCell1;
1053
	    }
1054
	  
1055
      int i,tmpCol, tmpRow, dCol, dRow;
1056
      int v = drawnY-mRows;
1057
      int h = drawnX-mCols;
1058
      int cellx, celly;
1059

    
1060
      int vgap = v<0 ? 0    :v/2;
1061
      int hgap = h<0 ? 0    :h/2;
1062
      int varr = v<0 ?-(v/2):  0;
1063
      int harr = h<0 ?-(h/2):  0;
1064
      int vlen = v<0 ? drawnY:mRows;
1065
      int hlen = h<0 ? drawnX:mCols;
1066
      
1067
      mPaint.setColor(COLOR_BACK);
1068
      c.drawRect(x,y-5, x+sWidth, y+sHeight+5, mPaint);
1069
      mPaint.setColor(COLOR_GRID);
1070
      
1071
      celly = y+gapY;
1072
      
1073
      for( i=0; i<=drawnY; i++ )
1074
        {
1075
    	c.drawRect(0, celly, sWidth, celly+SokobanLevels.bMargin , mPaint);
1076
    	celly+=bCell;
1077
    	}
1078
      
1079
      cellx = x+gapX;
1080
      
1081
      for( i=0; i<=drawnX; i++ ) 
1082
        {
1083
    	c.drawRect(cellx, y-5, cellx+SokobanLevels.bMargin,y+sHeight+5, mPaint);
1084
    	cellx+=bCell;
1085
    	}
1086
      
1087
      for(int row=varr; row<varr+vlen; row++)
1088
        for( int col=harr; col<harr+hlen; col++)
1089
          {
1090
          cellx = SokobanLevels.bMargin+x+gapX+(col+hgap-harr)*bCell;
1091
          celly = SokobanLevels.bMargin+y+gapY+(row+vgap-varr)*bCell;
1092
          
1093
          switch( cells[row][col] )
1094
            {
1095
            case EMPT: c.drawBitmap( isBig ? SokobanLevels.emptyBig2:SokobanLevels.emptyBig1, cellx,celly, null);
1096
                       break;
1097
            case DEST: c.drawBitmap( isBig ? SokobanLevels.destBig2 :SokobanLevels.destBig1 , cellx,celly, null);
1098
                       break;
1099
            }
1100
          }
1101

    
1102
      for(i=0; i<=mPacks; i++)
1103
        {
1104
        tmpCol = movableC[i][0];
1105
        tmpRow = movableC[i][1];
1106

    
1107
        dRow = tmpRow+vgap-varr;
1108
        dCol = tmpCol+hgap-harr;
1109

    
1110
        if( dRow>=0 && dRow< drawnY && dCol>=0 && dCol< drawnX  )
1111
          {
1112
          cellx = SokobanLevels.bMargin+x+gapX+dCol*bCell;
1113
          celly = SokobanLevels.bMargin+y+gapY+dRow*bCell;
1114

    
1115
          if( i==0 )
1116
        	  c.drawBitmap( isBig ? SokobanLevels.playBig2 : SokobanLevels.playBig1 ,cellx,celly, null);
1117
          else if( cells[tmpRow][tmpCol]==DEST )
1118
        	  c.drawBitmap( isBig ? SokobanLevels.dpckBig2 : SokobanLevels.dpckBig1 ,cellx,celly, null);
1119
          else
1120
        	  c.drawBitmap( isBig ? SokobanLevels.packBig2 : SokobanLevels.packBig1 ,cellx,celly, null);
1121
          }
1122
        }
1123
  }
1124

    
1125
///////////////////////////////////////////////////////////////////////////////////////////////////
1126
// end of SokobanLevel class
1127
  }
(4-4/12)