Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / scrambling / ScrambleStateLocallyBandaged.java @ 6777e712

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2022 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.scrambling;
11

    
12
import org.distorted.objectlib.signature.ObjectSignature;
13

    
14
///////////////////////////////////////////////////////////////////////////////////////////////////
15
// Info about a scramble state of any bandaged cuboids or pyraminxes.
16

    
17
public class ScrambleStateLocallyBandaged
18
{
19
  public static int MAX_SUPPORTED_SIZE = 7;
20
  public static final int AXIS_NONE = -1;
21

    
22
  private final ObjectSignature[] mMoves;
23
  private final ObjectSignature mSignature;
24
  private final int[] mLayer, mTurns, mSize, mStart;
25
  private final int mNumMoves;
26
  private final boolean[][] mIsUnblocked;
27
  private final int mNumAxis;
28

    
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30

    
31
  public ScrambleStateLocallyBandaged(int[] numLayers, ObjectSignature signature, BlacklistedSignatures blacklisted)
32
    {
33
    mNumAxis = numLayers.length;
34

    
35
    mLayer = new int[mNumAxis];
36
    mTurns = new int[mNumAxis];
37
    mSize  = new int[mNumAxis];
38
    mStart = new int[mNumAxis+1];
39

    
40
    mIsUnblocked = new boolean[mNumAxis][MAX_SUPPORTED_SIZE];
41

    
42
    for(int a=0; a<mNumAxis; a++)
43
      {
44
      mLayer[a] = numLayers[a];
45
      }
46

    
47
    if( mNumAxis==3 )
48
      {
49
      mTurns[0] = (mLayer[1]==mLayer[2] ? 3 : 1);
50
      mTurns[1] = (mLayer[0]==mLayer[2] ? 3 : 1);
51
      mTurns[2] = (mLayer[0]==mLayer[1] ? 3 : 1);
52
      }
53
    else if( mNumAxis==4 )
54
      {
55
      mTurns[0] = 2;
56
      mTurns[1] = 2;
57
      mTurns[2] = 2;
58
      mTurns[3] = 2;
59
      }
60
    else if( mNumAxis==6 )
61
      {
62
      mTurns[0] = 4;
63
      mTurns[1] = 4;
64
      mTurns[2] = 4;
65
      mTurns[3] = 4;
66
      mTurns[4] = 4;
67
      mTurns[5] = 4;
68
      }
69

    
70
    int numMoves = 0;
71

    
72
    for(int a=0; a<mNumAxis; a++)
73
      {
74
      mSize[a] = (mLayer[a]>1 ? mLayer[a] : 0);
75
      int tmp = mTurns[a]*mSize[a];
76
      numMoves += tmp;
77

    
78
      if( a==0 ) mStart[a] = 0;
79
      else       mStart[a] = mStart[a-1] + tmp;
80
      }
81

    
82
    mStart[mNumAxis] = numMoves;
83
    mNumMoves = numMoves;
84

    
85
    mSignature = signature;
86
    mMoves = createMoves(blacklisted);
87
    }
88

    
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90

    
91
  public ObjectSignature getSignature()
92
    {
93
    return mSignature;
94
    }
95

    
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97

    
98
  public ObjectSignature getMove(int index)
99
    {
100
    return (index>=0 && index<mNumMoves) ? mMoves[index] : null;
101
    }
102

    
103
///////////////////////////////////////////////////////////////////////////////////////////////////
104

    
105
  public void removeMoves(ObjectSignature signature)
106
    {
107
    for(int m=0; m<mNumMoves; m++)
108
      if( mMoves[m]!=null && signature.isEqual(mMoves[m]) ) mMoves[m]=null;
109
    }
110

    
111
///////////////////////////////////////////////////////////////////////////////////////////////////
112

    
113
  public int numAxis()
114
    {
115
    int num = 0;
116

    
117
    for(int a=0; a<mNumAxis; a++)
118
      for(int x=mStart[a]; x<mStart[a+1]; x++)
119
        if( mMoves[x]!=null ) { num++; break; }
120

    
121
    return num;
122
    }
123

    
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125

    
126
  private int numMovesInAx(int ax)
127
    {
128
    int num=0;
129
    for(int x=mStart[ax]; x<mStart[ax+1]; x++) if( mMoves[x]!=null ) num++;
130
    return num;
131
    }
132

    
133
///////////////////////////////////////////////////////////////////////////////////////////////////
134

    
135
  private int numMovesInAx(int ax, int excludedLayer)
136
    {
137
    int num=0;
138
    for(int x=mStart[ax]; x<mStart[ax+1]; x++)
139
      if( mMoves[x]!=null && (x-mStart[ax])%mLayer[ax]!=excludedLayer ) num++;
140

    
141
    return num;
142
    }
143

    
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145

    
146
  private int numAllMoves()
147
    {
148
    int num=0;
149
    for(int x=0; x<mNumMoves; x++) if( mMoves[x]!=null ) num++;
150
    return num;
151
    }
152

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

    
155
  private int numAllMoves(int excludedLayer)
156
    {
157
    int num=0;
158

    
159
    for(int a=0; a<mNumAxis; a++)
160
      for(int x=mStart[a]; x<mStart[a+1]; x++)
161
        if( mMoves[x]!=null && (x-mStart[a])%mLayer[a]!=excludedLayer ) num++;
162

    
163
    return num;
164
    }
165

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

    
168
  public int numMoves(int excludedAxis)
169
    {
170
    if( excludedAxis>=0 && excludedAxis<mNumAxis )
171
      return numAllMoves() - numMovesInAx(excludedAxis);
172

    
173
    return numAllMoves();
174
    }
175

    
176
///////////////////////////////////////////////////////////////////////////////////////////////////
177

    
178
  public int numMoves(int excludedAxis, int excludedLayer)
179
    {
180
    if( excludedAxis>=0 && excludedAxis<mNumAxis )
181
      return numAllMoves(excludedLayer) - numMovesInAx(excludedAxis, excludedLayer);
182

    
183
    return numAllMoves(excludedLayer);
184
    }
185

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

    
188
  public int getNthMove(int n, int excludedAxis)
189
    {
190
    int num = 0;
191

    
192
    for(int a=0; a<mNumAxis; a++)
193
      if( excludedAxis!=a )
194
        {
195
        for(int m=mStart[a]; m<mStart[a+1]; m++)
196
          if( mMoves[m]!=null )
197
            {
198
            if( num==n ) return m;
199
            num++;
200
            }
201
        }
202

    
203
    return -1;
204
    }
205

    
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

    
208
  public int getNthMove(int n, int excludedAxis, int excludedLayer)
209
    {
210
    int num = 0;
211

    
212
    for(int a=0; a<mNumAxis; a++)
213
      if( excludedAxis!=a )
214
        {
215
        for(int m=mStart[a]; m<mStart[a+1]; m++)
216
          if( mMoves[m]!=null && (m-mStart[a])%mLayer[a]!=excludedLayer )
217
            {
218
            if( num==n ) return m;
219
            num++;
220
            }
221
        }
222

    
223
    return -1;
224
    }
225

    
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227

    
228
  private ObjectSignature[] createMoves(BlacklistedSignatures blacklisted)
229
    {
230
    ObjectSignature[] ret = new ObjectSignature[mNumMoves];
231
    int index = 0;
232

    
233
    for(int axis=0; axis<mNumAxis; axis++)
234
      for(int layer=0; layer<mLayer[axis]; layer++)
235
        {
236
        mIsUnblocked[axis][layer] = mSignature.isUnblockedFromLeft(axis,layer);
237
        }
238

    
239
    for(int axis=0; axis<mNumAxis; axis++)
240
      if( mLayer[axis]>1 )
241
        for(int turn=1; turn<=mTurns[axis]; turn++)
242
          {
243
          boolean allLayersLocked = true;
244
          int begIndex = index;
245

    
246
          for(int layer=0; layer<mLayer[axis]; layer++)
247
            {
248
            if( mIsUnblocked[axis][layer] )
249
              {
250
              if( layer>0 ) allLayersLocked = false;
251
              ret[index] = mSignature.turn(axis,layer,turn);
252
              }
253
            else
254
              {
255
              ret[index] = ret[index-1].turn(axis,layer,turn);
256
              ret[index-1] = null;
257
              }
258

    
259
            index++;
260
            }
261

    
262
          for(int i=begIndex; i<index; i++)
263
            {
264
            if( ret[i]!=null && blacklisted.contains(ret[i]) ) ret[i]=null;
265
            }
266

    
267
          if( allLayersLocked ) ret[index-1] = null;
268
          }
269

    
270
    return ret;
271
    }
272

    
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274

    
275
  public void fillOutScramble(int[] scramble, int moveIndex)
276
    {
277
    for(int axis=0; axis<mNumAxis; axis++)
278
      {
279
      int size = mTurns[axis]*mSize[axis];
280

    
281
      if( moveIndex<size )
282
        {
283
        scramble[0] = axis;
284
        scramble[1] = moveIndex % mSize[axis];
285

    
286
        switch( mTurns[axis] )
287
          {
288
          case 2: switch(moveIndex/mSize[axis])
289
                    {
290
                    case 0: scramble[2] =-1; break;
291
                    case 1: scramble[2] = 1; break;
292
                    }
293
                  break;
294
          case 3: switch(moveIndex/mSize[axis])
295
                    {
296
                    case 0: scramble[2] =-1; break;
297
                    case 1: scramble[2] = 2; break;
298
                    case 2: scramble[2] = 1; break;
299
                    }
300
                  break;
301
          case 4: switch(moveIndex/mSize[axis])
302
                    {
303
                    case 0: scramble[2] =-1; break;
304
                    case 1: scramble[2] =-2; break;
305
                    case 2: scramble[2] = 2; break;
306
                    case 3: scramble[2] = 1; break;
307
                    }
308
                  break;
309
          default:scramble[2] = 1;
310
                  android.util.Log.e("D", "ScrambleStateLocallyBandaged: unsupported turns: "+mTurns[axis]);
311
          }
312

    
313
        return;
314
        }
315

    
316
      moveIndex -= size;
317
      }
318

    
319
    android.util.Log.e("D", "ERROR in fillOutScramble moveIndex="+moveIndex);
320
    }
321

    
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323

    
324
  private void printMoves()
325
    {
326
    for(int i=0; i<mNumMoves; i++)
327
      {
328
      android.util.Log.e("D", "move "+i+" : "+(mMoves[i]!=null ? " "+mMoves[i].getString() : " NULL") );
329
      }
330
    }
331

    
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333

    
334
  private static String printBits(long id)
335
    {
336
    String ret = "[";
337
    boolean first = true;
338

    
339
    for(int i=0; i<64; i++)
340
      {
341
      if( ( (id>>i)&0x1)==1 )
342
        {
343
        String num = (i<10 ? " "+i : ""+i);
344

    
345
        if( first ) { ret += num; first=false; }
346
        else          ret += (","+num);
347
        }
348
      }
349

    
350
    return ret + "]";
351
    }
352
}
(6-6/7)