Project

General

Profile

Download (20.3 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / objects / TwistyMegaminx.java @ f6e46300

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objects;
21

    
22
import android.content.res.Resources;
23
import android.graphics.Canvas;
24
import android.graphics.Paint;
25

    
26
import org.distorted.library.effect.MatrixEffectQuaternion;
27
import org.distorted.library.main.DistortedEffects;
28
import org.distorted.library.main.DistortedTexture;
29
import org.distorted.library.mesh.MeshBase;
30
import org.distorted.library.mesh.MeshSquare;
31
import org.distorted.library.type.Static3D;
32
import org.distorted.library.type.Static4D;
33
import org.distorted.main.R;
34
import org.distorted.main.RubikSurfaceView;
35

    
36
import static org.distorted.objects.FactoryCubit.COS18;
37
import static org.distorted.objects.FactoryCubit.COS54;
38
import static org.distorted.objects.FactoryCubit.SIN18;
39
import static org.distorted.objects.FactoryCubit.SIN54;
40

    
41
///////////////////////////////////////////////////////////////////////////////////////////////////
42

    
43
public class TwistyMegaminx extends TwistyMinx
44
{
45
  static final float MEGA_D = 0.04f;
46

    
47
  private static final int NUM_CORNERS = 20;
48
  private static final int NUM_CENTERS = 12;
49
  private static final int NUM_EDGES   = 30;
50

    
51
  // the five vertices that form a given face. Order: the same as colors
52
  // of the faces in TwistyMinx.
53
  private static final int[][] mCenterMap =
54
         {
55
           { 0, 12,  4, 14,  2},
56
           { 0,  2, 18,  6, 16},
57
           { 6, 18, 11, 19,  7},
58
           { 3, 15,  9, 11, 19},
59
           { 4,  5, 15,  9, 14},
60
           { 1, 13,  5, 15,  3},
61
           { 1,  3, 19,  7, 17},
62
           {10, 16,  6,  7, 17},
63
           { 0, 12,  8, 10, 16},
64
           { 8, 13,  5,  4, 12},
65
           { 1, 13,  8, 10, 17},
66
           { 2, 14,  9, 11, 18},
67
         };
68

    
69
  // the quadruple ( vertex1, vertex2, face1, face2 ) defining an edge.
70
  // In fact the 2 vertices already define it, the faces only provide easy
71
  // way to get to know the colors. Order: arbitrary. Face1 arbitrarily on
72
  // the 'left' or right of vector vertex1 --> vertex2, according to Quat.
73
  private static final int[][] mEdgeMap =
74
         {
75
           {  0, 12,  0,  8},
76
           { 12,  4,  0,  9},
77
           {  4, 14,  0,  4},
78
           { 14,  2,  0, 11},
79
           {  2,  0,  0,  1},
80
           { 14,  9,  4, 11},
81
           {  9, 11,  3, 11},
82
           { 11, 18,  2, 11},
83
           { 18,  2,  1, 11},
84
           { 18,  6,  1,  2},
85
           {  6, 16,  1,  7},
86
           { 16,  0,  8,  1},
87
           { 16, 10,  7,  8},
88
           { 10,  8, 10,  8},
89
           {  8, 12,  9,  8},
90
           {  8, 13,  9, 10},
91
           { 13,  5,  9,  5},
92
           {  5,  4,  9,  4},
93
           {  5, 15,  5,  4},
94
           { 15,  9,  3,  4},
95
           { 11, 19,  2,  3},
96
           { 19,  7,  2,  6},
97
           {  7,  6,  2,  7},
98
           {  7, 17,  7,  6},
99
           { 17, 10,  7, 10},
100
           { 17,  1, 10,  6},
101
           {  1,  3,  5,  6},
102
           {  3, 19,  3,  6},
103
           {  1, 13, 10,  5},
104
           {  3, 15,  3,  5},
105
         };
106

    
107

    
108
  private static final int[] QUAT_EDGE_INDICES =
109
      {
110
        56, 40, 43, 59,  0, 55, 10, 17, 25, 49,
111
        48, 57, 18,  7, 53, 32, 20, 11, 31, 38,
112
        37, 30,  8, 28, 36, 44,  1, 46, 12, 14
113
      };
114

    
115
  private static final int[] QUAT_CENTER_INDICES =
116
      {
117
        16, 18, 22,  1, 20, 13, 14, 15,  0, 12,  2,  3
118
      };
119

    
120
  private static final float[][] mCenterCoords = new float[NUM_CENTERS][3];
121

    
122
  static
123
    {
124
    for(int center=0; center<NUM_CENTERS; center++)
125
      {
126
      int[] map = mCenterMap[center];
127

    
128
      float x = CORNERS[map[0]][0] +
129
                CORNERS[map[1]][0] +
130
                CORNERS[map[2]][0] +
131
                CORNERS[map[3]][0] +
132
                CORNERS[map[4]][0] ;
133

    
134
      float y = CORNERS[map[0]][1] +
135
                CORNERS[map[1]][1] +
136
                CORNERS[map[2]][1] +
137
                CORNERS[map[3]][1] +
138
                CORNERS[map[4]][1] ;
139

    
140
      float z = CORNERS[map[0]][2] +
141
                CORNERS[map[1]][2] +
142
                CORNERS[map[2]][2] +
143
                CORNERS[map[3]][2] +
144
                CORNERS[map[4]][2] ;
145

    
146
      mCenterCoords[center][0] = x/5;
147
      mCenterCoords[center][1] = y/5;
148
      mCenterCoords[center][2] = z/5;
149
      }
150
    }
151

    
152
  private static MeshBase[] mCenterMeshes, mCornerMeshes;
153
  private static MeshBase[][] mEdgeMeshes;
154

    
155
  private static final Static4D[] mBasicCornerV, mCurrCornerV;
156

    
157
  static
158
    {
159
    mBasicCornerV = new Static4D[3];
160
    mCurrCornerV  = new Static4D[3];
161

    
162
    mBasicCornerV[0] = new Static4D( (SQ5+1)*0.125f, (SQ5-1)*0.125f, -0.250f, 0.0f );
163
    mBasicCornerV[1] = new Static4D(-(SQ5+1)*0.125f, (SQ5-1)*0.125f, -0.250f, 0.0f );
164
    mBasicCornerV[2] = new Static4D(              0,        -0.500f,    0.0f, 0.0f );
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  TwistyMegaminx(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
170
                 DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
171
    {
172
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.MEGA, res, scrWidth);
173
    }
174

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

    
177
  private int numCubitsPerCorner(int numLayers)
178
    {
179
    return 3*((numLayers-1)/2)*((numLayers-3)/2) + 1;
180
    }
181

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

    
184
  private int numCubitsPerEdge(int numLayers)
185
    {
186
    return numLayers-2;
187
    }
188

    
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190

    
191
  float getScreenRatio()
192
    {
193
    return 1.07f;
194
    }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

    
198
  int getNumStickerTypes(int numLayers)
199
    {
200
    return (numLayers+3)/2;
201
    }
202

    
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204

    
205
  float[] getCuts(int numLayers)
206
    {
207
    float[] cuts = new float[numLayers-1];
208
    float D = numLayers*MovementMinx.DIST3D;
209
    float E = 2*C1;           // 2*cos(36 deg)
210
    float X = 2*D*E/(1+2*E);  // height of the 'upper' part of a dodecahedron, i.e. put it on a table,
211
                              // its height is then D*2*DIST3D, it has one 'lower' part of height X, one
212
                              // 'middle' part of height Y and one upper part of height X again.
213
                              // It's edge length = numLayers/3.0f.
214
    int num = (numLayers-1)/2;
215
    float G = X*(0.5f-MEGA_D)/num; // height of one Layer
216

    
217
    for(int i=0; i<num; i++)
218
      {
219
      cuts[        i] = -D + (i+0.5f)*G;
220
      cuts[2*num-1-i] = -cuts[i];
221
      }
222

    
223
    return cuts;
224
    }
225

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

    
228
  private float[] computeCenter(int center, int numLayers)
229
    {
230
    float[] coords = mCenterCoords[center];
231
    float A = numLayers/3.0f;
232

    
233
    return new float[] { A*coords[0], A*coords[1], A*coords[2] };
234
    }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237
// Fill out mCurrCorner{X,Y,Z} by applying appropriate Quat to mBasicCorner{X,Y,Z}
238
// Appropriate one: QUATS[QUAT_INDICES[corner]].
239

    
240
  private void computeBasicCornerVectors(int corner)
241
    {
242
    Static4D quat = QUATS[QUAT_CORNER_INDICES[corner]];
243

    
244
    mCurrCornerV[0] = RubikSurfaceView.rotateVectorByQuat(mBasicCornerV[0],quat);
245
    mCurrCornerV[1] = RubikSurfaceView.rotateVectorByQuat(mBasicCornerV[1],quat);
246
    mCurrCornerV[2] = RubikSurfaceView.rotateVectorByQuat(mBasicCornerV[2],quat);
247
    }
248

    
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250

    
251
  private float[] computeCorner(int numCubitsPerCorner, int numLayers, int corner, int part)
252
    {
253
    float D = numLayers/3.0f;
254
    float[] corn = CORNERS[corner];
255

    
256
    if( part==0 )
257
      {
258
      return new float[] { corn[0]*D, corn[1]*D, corn[2]*D };
259
      }
260
    else
261
      {
262
      float E = 2.0f*(numLayers/3.0f)*(0.5f-MEGA_D)/(0.5f*(numLayers-1));
263
      int N = (numCubitsPerCorner-1)/3;
264
      int block = (part-1) % N;
265
      int index = (part-1) / N;
266
      Static4D pri = mCurrCornerV[index];
267
      Static4D sec = mCurrCornerV[(index+2)%3];
268

    
269
      int multP = (block % ((numLayers-3)/2)) + 1;
270
      int multS = (block / ((numLayers-3)/2));
271

    
272
      return new float[] {
273
                          corn[0]*D + (pri.get0()*multP + sec.get0()*multS)*E,
274
                          corn[1]*D + (pri.get1()*multP + sec.get1()*multS)*E,
275
                          corn[2]*D + (pri.get2()*multP + sec.get2()*multS)*E
276
                         };
277
      }
278
    }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

    
282
  private int computeEdgeType(int cubit, int numCubitsPerCorner, int numCubitsPerEdge)
283
    {
284
    int part = (cubit - NUM_CORNERS*numCubitsPerCorner) % numCubitsPerEdge;
285
    return (part+1)/2;
286
    }
287

    
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289

    
290
  private float[] computeEdge(int numLayers, int edge, int part)
291
    {
292
    float corr = numLayers/3.0f;
293

    
294
    float[] c1 = CORNERS[ mEdgeMap[edge][0] ];
295
    float[] c2 = CORNERS[ mEdgeMap[edge][1] ];
296
    float x = corr * (c1[0]+c2[0]) / 2;
297
    float y = corr * (c1[1]+c2[1]) / 2;
298
    float z = corr * (c1[2]+c2[2]) / 2;
299

    
300
    if( part==0 )
301
      {
302
      return new float[] { x, y, z };
303
      }
304
    else
305
      {
306
      int mult = (part+1)/2;
307
      int dir  = (part+1)%2;
308
      float[] center = mCenterCoords[ mEdgeMap[edge][dir+2] ];
309

    
310
      float vX = corr*center[0] - x;
311
      float vY = corr*center[1] - y;
312
      float vZ = corr*center[2] - z;
313

    
314
      float len = (float)Math.sqrt(vX*vX+vY*vY+vZ*vZ);
315
      float A = mult*corr*(0.5f-MEGA_D)*COS18/((numLayers-1)*0.5f)/len;
316

    
317
      return new float[] { x+A*vX, y+A*vY, z+A*vZ };
318
      }
319
    }
320

    
321
///////////////////////////////////////////////////////////////////////////////////////////////////
322

    
323
  float[][] getCubitPositions(int numLayers)
324
    {
325
    int numCubitsPerCorner = numCubitsPerCorner(numLayers);
326
    int numCubitsPerEdge   = numCubitsPerEdge(numLayers);
327
    int numCubits = NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge + NUM_CENTERS;
328
    int index=0;
329

    
330
    final float[][] CENTERS = new float[numCubits][];
331

    
332
    for(int corner=0; corner<NUM_CORNERS; corner++)
333
      {
334
      computeBasicCornerVectors(corner);
335

    
336
      for(int part=0; part<numCubitsPerCorner; part++, index++)
337
        {
338
        CENTERS[index] = computeCorner(numCubitsPerCorner,numLayers,corner,part);
339
        }
340
      }
341

    
342
    for(int edge=0; edge<NUM_EDGES; edge++)
343
      {
344
      for(int part=0; part<numCubitsPerEdge; part++, index++)
345
        {
346
        CENTERS[index] = computeEdge(numLayers, edge, part );
347
        }
348
      }
349

    
350
    for(int center=0; center<NUM_CENTERS; center++, index++)
351
      {
352
      CENTERS[index] = computeCenter(center, numLayers);
353
      }
354

    
355
    return CENTERS;
356
    }
357

    
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359

    
360
  private int getQuat(int cubit, int numCubitsPerCorner, int numCubitsPerEdge)
361
    {
362
    if( cubit < NUM_CORNERS*numCubitsPerCorner )
363
      {
364
      int corner = cubit/numCubitsPerCorner;
365
      return QUAT_CORNER_INDICES[corner];
366
      }
367

    
368
    if( cubit < NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge )
369
      {
370
      int edge = (cubit-NUM_CORNERS*numCubitsPerCorner)/numCubitsPerEdge;
371
      return QUAT_EDGE_INDICES[edge];
372
      }
373

    
374
    int center = cubit - NUM_CORNERS*numCubitsPerCorner - NUM_EDGES*numCubitsPerEdge;
375
    return QUAT_CENTER_INDICES[center];
376
    }
377

    
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

    
380
  MeshBase createCubitMesh(int cubit, int numLayers)
381
    {
382
    int numCubitsPerCorner = numCubitsPerCorner(numLayers);
383
    int numCubitsPerEdge   = numCubitsPerEdge(numLayers);
384
    int index = (numLayers-3)/2;
385
    int[] sizes = ObjectList.MEGA.getSizes();
386
    int variants = sizes.length;
387
    MeshBase mesh;
388

    
389
    if( mCornerMeshes==null ) mCornerMeshes = new MeshBase[variants];
390
    if( mEdgeMeshes  ==null ) mEdgeMeshes   = new MeshBase[variants][(sizes[variants-1]-1)/2];
391
    if( mCenterMeshes==null ) mCenterMeshes = new MeshBase[variants];
392

    
393
    if( cubit < NUM_CORNERS*numCubitsPerCorner )
394
      {
395
      if( mCornerMeshes[index]==null )
396
        {
397
        mCornerMeshes[index] = FactoryCubit.getInstance().createMegaminxCornerMesh(numLayers);
398
        }
399
      mesh = mCornerMeshes[index].copy(true);
400
      }
401
    else if( cubit<NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge )
402
      {
403
      int type = computeEdgeType(cubit,numCubitsPerCorner,numCubitsPerEdge);
404

    
405
      if( mEdgeMeshes[index][type]==null )
406
        {
407
        float height= (numLayers/3.0f)*(0.5f-MEGA_D)*COS18/((numLayers-1)*0.5f);
408
        float width = (numLayers/3.0f)*2*MEGA_D + 2*type*height*SIN18/COS18;
409

    
410
        mEdgeMeshes[index][type] = FactoryCubit.getInstance().createMegaminxEdgeMesh(numLayers,width,height);
411
        }
412

    
413
      mesh = mEdgeMeshes[index][type].copy(true);
414
      }
415
    else
416
      {
417
      if( mCenterMeshes[index]==null )
418
        {
419
        float width = 2 * (numLayers/3.0f) * (MEGA_D+(0.5f-MEGA_D)*SIN18);
420
        mCenterMeshes[index] = FactoryCubit.getInstance().createMegaminxCenterMesh(numLayers,width);
421
        }
422

    
423
      mesh = mCenterMeshes[index].copy(true);
424
      }
425

    
426
    Static4D q = QUATS[getQuat(cubit,numCubitsPerCorner,numCubitsPerEdge)];
427
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( q, new Static3D(0,0,0) );
428
    mesh.apply(quat,0xffffffff,0);
429

    
430
    return mesh;
431
    }
432

    
433
///////////////////////////////////////////////////////////////////////////////////////////////////
434

    
435
  int getCornerColor(int cubit, int cubitface, int numLayers, int numCubitsPerCorner)
436
    {
437
    if( cubitface<0 || cubitface>2 ) return NUM_TEXTURES;
438

    
439
    int part  = cubit % numCubitsPerCorner;
440
    int corner= cubit / numCubitsPerCorner;
441

    
442
    if( part==0 )
443
      {
444
      return mCornerFaceMap[corner][cubitface];
445
      }
446
    else
447
      {
448
      int N = (numCubitsPerCorner-1)/3;
449
      int block = (part-1) % N;
450
      int index = (part-1) / N;
451

    
452
      if( block< (numLayers-3)/2 )
453
        {
454
        switch(index)
455
          {
456
          case 0: return cubitface==1 ? NUM_TEXTURES : mCornerFaceMap[corner][cubitface];
457
          case 1: return cubitface==0 ? NUM_TEXTURES : mCornerFaceMap[corner][cubitface];
458
          case 2: return cubitface==2 ? NUM_TEXTURES : mCornerFaceMap[corner][cubitface];
459
          }
460
        }
461
      else
462
        {
463
        switch(index)
464
          {
465
          case 0: return cubitface==0 ? mCornerFaceMap[corner][cubitface] : NUM_TEXTURES;
466
          case 1: return cubitface==2 ? mCornerFaceMap[corner][cubitface] : NUM_TEXTURES;
467
          case 2: return cubitface==1 ? mCornerFaceMap[corner][cubitface] : NUM_TEXTURES;
468
          }
469
        }
470
      }
471

    
472
    return NUM_TEXTURES;
473
    }
474

    
475
///////////////////////////////////////////////////////////////////////////////////////////////////
476

    
477
  int getEdgeColor(int edge, int cubitface, int numCubitsPerEdge)
478
    {
479
    if( cubitface<0 || cubitface>1 ) return NUM_TEXTURES;
480

    
481
    int part    = edge % numCubitsPerEdge;
482
    int variant = edge / numCubitsPerEdge;
483

    
484
    return (part==0 || cubitface==((part+1)%2)) ? mEdgeMap[variant][cubitface+2] + ((part+3)/2)*NUM_FACES : NUM_TEXTURES;
485
    }
486

    
487
///////////////////////////////////////////////////////////////////////////////////////////////////
488

    
489
  int getCenterColor(int center, int cubitface, int numLayers)
490
    {
491
    return cubitface>0 ? NUM_TEXTURES : center + NUM_FACES*(numLayers+1)/2;
492
    }
493

    
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495

    
496
  int getFaceColor(int cubit, int cubitface, int numLayers)
497
    {
498
    int numCubitsPerCorner = numCubitsPerCorner(numLayers);
499
    int numCubitsPerEdge   = numCubitsPerEdge(numLayers);
500

    
501
    if( cubit < NUM_CORNERS*numCubitsPerCorner )
502
      {
503
      return getCornerColor(cubit,cubitface,numLayers,numCubitsPerCorner);
504
      }
505
    else if( cubit<NUM_CORNERS*numCubitsPerCorner + NUM_EDGES*numCubitsPerEdge )
506
      {
507
      int edge = cubit - NUM_CORNERS*numCubitsPerCorner;
508
      return getEdgeColor(edge,cubitface,numCubitsPerEdge);
509
      }
510
    else
511
      {
512
      int center = cubit-NUM_CORNERS*numCubitsPerCorner-NUM_EDGES*numCubitsPerEdge;
513
      return getCenterColor( center, cubitface, numLayers);
514
      }
515
    }
516

    
517
///////////////////////////////////////////////////////////////////////////////////////////////////
518

    
519
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
520
    {
521
    int COLORS = FACE_COLORS.length;
522
    float R,S;
523
    float[] vertices;
524

    
525
    int variant = face/COLORS;
526

    
527
    if( variant==0 )
528
      {
529
      float Y = COS54/(2*SIN54);
530
      R = 0.070f;
531
      S = 0.08f;
532
      vertices = new float[] { -0.5f, 0.0f, 0.0f, -Y, 0.5f, 0.0f, 0.0f, Y };
533
      }
534
    else
535
      {
536
      int numLayers = getNumLayers();
537
      float height= (numLayers/3.0f)*(0.5f-MEGA_D)*COS18/((numLayers-1)*0.5f);
538
      float W = height*SIN18/COS18;
539
      float width = (numLayers/3.0f)*2*MEGA_D + 2*(variant-1)*W;
540

    
541
      if( variant < (numLayers+1)/2 )
542
        {
543
        float X1 = 0.5f*height;
544
        float Y1 = 0.5f*width;
545
        float Y2 = 0.5f*width + W;
546

    
547
        R = 0.05f;
548
        S = 0.07f;
549
        vertices = new float[] { -X1, Y1, -X1, -Y1, X1, -Y2, X1, Y2 };
550
        }
551
      else
552
        {
553
        float Z  = 0.5f;
554
        float X1 = Z*COS54;
555
        float Y1 = Z*SIN54;
556
        float X2 = Z*COS18;
557
        float Y2 = Z*SIN18;
558

    
559
        R = 0.10f;
560
        S = 0.08f;
561
        vertices = new float[] { -X1,+Y1, -X2,-Y2, 0.0f,-Z, +X2,-Y2, +X1,+Y1 };
562
        }
563
      }
564

    
565
    FactorySticker factory = FactorySticker.getInstance();
566
    factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face%COLORS], R);
567
    }
568

    
569
///////////////////////////////////////////////////////////////////////////////////////////////////
570
// PUBLIC API
571

    
572
  public boolean isSolved()
573
    {
574
    int index = CUBITS[0].mQuatIndex;
575

    
576
    for(int i=1; i<NUM_CUBITS; i++)
577
      {
578
      if( thereIsVisibleDifference(CUBITS[i], index) ) return false;
579
      }
580

    
581
    return true;
582
    }
583

    
584
///////////////////////////////////////////////////////////////////////////////////////////////////
585

    
586
  public int getObjectName(int numLayers)
587
    {
588
    if( numLayers==3 ) return R.string.minx3;
589
    if( numLayers==5 ) return R.string.minx5;
590

    
591
    return 0;
592
    }
593

    
594
///////////////////////////////////////////////////////////////////////////////////////////////////
595

    
596
  public int getInventor(int numLayers)
597
    {
598
    if( numLayers==3 ) return R.string.minx3_inventor;
599
    if( numLayers==5 ) return R.string.minx5_inventor;
600

    
601
    return 0;
602
    }
603

    
604
///////////////////////////////////////////////////////////////////////////////////////////////////
605

    
606
  public int getComplexity(int numLayers)
607
    {
608
    if( numLayers==3 ) return 4;
609

    
610
    return 5;
611
    }
612
}
(29-29/35)