Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / signature / ObjectSignature.java @ 3a0990b1

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.signature;
11

    
12
import static org.distorted.objectlib.scrambling.ScrambleStateLocallyBandaged.MAX_SUPPORTED_SIZE;
13

    
14
///////////////////////////////////////////////////////////////////////////////////////////////////
15

    
16
public class ObjectSignature implements Comparable<ObjectSignature>
17
{
18
  public static final int SIZE = computeNum();
19

    
20
  private String mName=null;
21
  int[] mFactoryLayer;
22
  int mParam;
23
  long[] mSignature;
24
  int[] mLayer;
25
  float[][] mCubitTouch;
26
  int[][] mTouchRows;
27
  int mNumCubitTouches;
28
  int[][][][] mCycles;
29
  int[] mNumLeftCyclesPerLayer;
30
  int[] mNumCentCyclesPerLayer;
31
  int[] mNumInneCyclesPerLayer;
32
  float[] mTmp;
33

    
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35
// a cube of size N has 12*(N-1)^2 possible places two adjacent cubies can be 'glued'; therefore
36
// the signature must contain ceil( 12*(N-1)^2 / 64 ) bytes.
37
// a Pyraminx of size N has 4 + 6*(N-1)(N-2) places two adjacent cubies can be 'glued' so much less.
38

    
39
// Gigaminx has 540 such places (so more if N<=7)
40

    
41
  private static int computeNum()
42
    {
43
    int max = MAX_SUPPORTED_SIZE-1;
44
    int ret = (int)(0.99f + (12*max*max)/64.0f);
45
    int giga= (int)(0.99f + (       540)/64.0f);
46

    
47
    return Math.max(ret,giga);
48
    }
49

    
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51

    
52
  void setUpSignature(long[] signature)
53
    {
54
    int size = signature.length;
55
    int diff = SIZE-size;
56

    
57
    if( diff==0 ) mSignature = signature;
58
    else
59
      {
60
      mSignature = new long[SIZE];
61
      for(int i=0; i<size; i++) mSignature[diff+i] = signature[i];
62
      }
63
    }
64

    
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66

    
67
  public ObjectSignature(ObjectSignature sig)
68
    {
69
    int len = sig.mSignature.length;
70
    mSignature = new long[len];
71
    for(int i=0; i<len; i++) mSignature[i] = sig.mSignature[i];
72

    
73
    mLayer        = sig.mLayer;
74
    mCycles       = sig.mCycles;
75
    mCubitTouch   = sig.mCubitTouch;
76
    mTouchRows    = sig.mTouchRows;
77
    mName         = sig.mName;
78
    mParam        = sig.mParam;
79
    mFactoryLayer = sig.mFactoryLayer;
80
    mTmp          = sig.mTmp;
81

    
82
    mNumCubitTouches       = sig.mNumCubitTouches;
83
    mNumCentCyclesPerLayer = sig.mNumCentCyclesPerLayer;
84
    mNumLeftCyclesPerLayer = sig.mNumLeftCyclesPerLayer;
85
    mNumInneCyclesPerLayer = sig.mNumInneCyclesPerLayer;
86
    }
87

    
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89
// built-in objects; objects created from JSON (version1)
90

    
91
  public ObjectSignature(long signature)
92
    {
93
    mSignature = new long[SIZE];
94
    mSignature[SIZE-1] = signature;
95
    }
96

    
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98

    
99
  ObjectSignature()
100
    {
101

    
102
    }
103

    
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105
// other objects created from JSON (version2)
106

    
107
  public ObjectSignature(long[] signature)
108
    {
109
    setUpSignature(signature);
110
    }
111

    
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113

    
114
  public void setSignature(int signature)
115
    {
116
    for(int i=0; i<SIZE-1; i++) mSignature[i]=0;
117
    mSignature[SIZE-1] = signature;
118
    }
119

    
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121

    
122
  public int compareTo(ObjectSignature sig)
123
    {
124
    for(int i=0; i<SIZE; i++)
125
      {
126
      long diff = mSignature[i] - sig.mSignature[i];
127

    
128
           if( diff>0 ) return +1;
129
      else if( diff<0 ) return -1;
130
      }
131

    
132
    return 0;
133
    }
134

    
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

    
137
  public boolean isEqual(ObjectSignature sig)
138
    {
139
    for(int i=0; i<SIZE; i++)
140
      {
141
      if( mSignature[i] != sig.mSignature[i] ) return false;
142
      }
143

    
144
    return true;
145
    }
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148

    
149
  public long[] getArray()
150
    {
151
    return mSignature;
152
    }
153

    
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155

    
156
  public String getString()
157
    {
158
    if( mName==null )
159
      {
160
      StringBuilder sb = new StringBuilder();
161

    
162
      for(int i=0; i<SIZE; i++)
163
        {
164
        String sig = String.format("0x%016X", mSignature[i]);
165
        if( i>0 ) sb.append('_');
166
        sb.append(sig);
167
        }
168

    
169
      mName = sb.toString();
170
      }
171

    
172
    return mName;
173
    }
174

    
175
///////////////////////////////////////////////////////////////////////////////////////////////////
176

    
177
  public boolean isUnblockedFromLeft(int axis, int layer)
178
    {
179
    if(layer>0)
180
      {
181
      int[] touch = mTouchRows[axis];
182

    
183
      for( int index=0; index<mNumCubitTouches; index++)
184
        if( touch[index]==layer && getBit(index)!=0 ) return false;
185
      }
186

    
187
    return true;
188
    }
189

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191

    
192
  public ObjectSignature turn(int ax, int layer, int turn)
193
    {
194
    ObjectSignature ret = new ObjectSignature(this);
195

    
196
    // I don't understand it, but Firebase shows mCycles is occasionally null here.
197
    if( mCycles!=null && mCycles[ax]!=null )
198
      {
199
      int[][] cycles = mCycles[ax][layer];
200

    
201
      // it can happen that there are no cycles in this layer: 2x1x2 axis 0 layer 0.
202
      if( cycles!=null && cycles.length>0 && cycles[0]!=null )
203
        {
204
             if( cycles[0].length==5 ) for(int[] cyc : cycles) ret.cycle5(turn,cyc);
205
        else if( cycles[0].length==4 ) for(int[] cyc : cycles) ret.cycle4(turn,cyc);
206
        else if( cycles[0].length==3 ) for(int[] cyc : cycles) ret.cycle3(turn,cyc);
207
        else if( cycles[0].length==2 ) for(int[] cyc : cycles) ret.cycle2(cyc);
208
        }
209
      }
210

    
211
    return ret;
212
    }
213

    
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215

    
216
  private void cycle2(int[] cyc)
217
    {
218
    int index0 = cyc[0];
219
    int index1 = cyc[1];
220

    
221
    long b0 = getBit(index0);
222
    long b1 = getBit(index1);
223

    
224
    setBit(index1,b0);
225
    setBit(index0,b1);
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  private void cycle3(int turn, int[] cyc)
231
    {
232
    int index0 = cyc[0];
233
    int index1 = cyc[1];
234
    int index2 = cyc[2];
235

    
236
    long b0 = getBit(index0);
237
    long b1 = getBit(index1);
238
    long b2 = getBit(index2);
239

    
240
    switch(turn)
241
      {
242
      case 1: setBit(index0,b2);
243
              setBit(index1,b0);
244
              setBit(index2,b1);
245
              break;
246
      case 2: setBit(index0,b1);
247
              setBit(index1,b2);
248
              setBit(index2,b0);
249
              break;
250
      }
251
    }
252

    
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

    
255
  private void cycle4(int turn, int[] cyc)
256
    {
257
    int index0 = cyc[0];
258
    int index1 = cyc[1];
259
    int index2 = cyc[2];
260
    int index3 = cyc[3];
261

    
262
    long b0 = getBit(index0);
263
    long b1 = getBit(index1);
264
    long b2 = getBit(index2);
265
    long b3 = getBit(index3);
266

    
267
    switch(turn)
268
      {
269
      case 1: setBit(index0,b3);
270
              setBit(index1,b0);
271
              setBit(index2,b1);
272
              setBit(index3,b2);
273
              break;
274
      case 2: setBit(index0,b2);
275
              setBit(index1,b3);
276
              setBit(index2,b0);
277
              setBit(index3,b1);
278
              break;
279
      case 3: setBit(index0,b1);
280
              setBit(index1,b2);
281
              setBit(index2,b3);
282
              setBit(index3,b0);
283
              break;
284
      }
285
    }
286

    
287
///////////////////////////////////////////////////////////////////////////////////////////////////
288

    
289
  private void cycle5(int turn, int[] cyc)
290
    {
291
    int index0 = cyc[0];
292
    int index1 = cyc[1];
293
    int index2 = cyc[2];
294
    int index3 = cyc[3];
295
    int index4 = cyc[4];
296

    
297
    long b0 = getBit(index0);
298
    long b1 = getBit(index1);
299
    long b2 = getBit(index2);
300
    long b3 = getBit(index3);
301
    long b4 = getBit(index4);
302

    
303
    switch(turn)
304
      {
305
      case 1: setBit(index0,b4);
306
              setBit(index1,b0);
307
              setBit(index2,b1);
308
              setBit(index3,b2);
309
              setBit(index4,b3);
310
              break;
311
      case 2: setBit(index0,b3);
312
              setBit(index1,b4);
313
              setBit(index2,b0);
314
              setBit(index3,b1);
315
              setBit(index4,b2);
316
              break;
317
      case 3: setBit(index0,b2);
318
              setBit(index1,b3);
319
              setBit(index2,b4);
320
              setBit(index3,b0);
321
              setBit(index4,b1);
322
              break;
323
      case 4: setBit(index0,b1);
324
              setBit(index1,b2);
325
              setBit(index2,b3);
326
              setBit(index3,b4);
327
              setBit(index4,b0);
328
              break;
329
    }
330
  }
331

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

    
334
  float[] getPosition(int index, float[][][] centers, int len)
335
    {
336
    int num=0, i1=0, i2=0;
337

    
338
    for(int i=0; i<len; i++)
339
      {
340
      int t = centers[i].length;
341

    
342
      if( t > index-num )
343
        {
344
        i1 = i;
345
        i2 = index-num;
346
        break;
347
        }
348
      else
349
        {
350
        num += t;
351
        }
352
      }
353

    
354
    return centers[i1][i2];
355
    }
356

    
357
///////////////////////////////////////////////////////////////////////////////////////////////////
358

    
359
  int getIndexOfCubitTouch(float x, float y, float z)
360
    {
361
    for(int i=0; i<mNumCubitTouches; i++)
362
      {
363
      float[] touch = mCubitTouch[i];
364

    
365
      float dx = touch[0] - x;
366
      float dy = touch[1] - y;
367
      float dz = touch[2] - z;
368

    
369
      if( dx*dx + dy*dy + dz*dz < 0.01f ) return i;
370
      }
371

    
372
    return -1;
373
    }
374

    
375
///////////////////////////////////////////////////////////////////////////////////////////////////
376

    
377
  float[] getCubitTouchOfIndex(int index)
378
    {
379
    return mCubitTouch[index];
380
    }
381

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383

    
384
  long getBit(int index)
385
    {
386
    int sigIndex = SIZE-1-(index/64);
387
    return (mSignature[sigIndex]>>(index%64))&0x1;
388
    }
389

    
390
///////////////////////////////////////////////////////////////////////////////////////////////////
391

    
392
  void setBit(int index, long bit)
393
    {
394
    long diff    = (1L<<(index%64));
395
    int sigIndex = SIZE-1-(index/64);
396
    if( bit!=0 ) mSignature[sigIndex] |= diff;
397
    else         mSignature[sigIndex] &=~diff;
398
    }
399
}
(1-1/6)