iT邦幫忙

2022 iThome 鐵人賽

DAY 5
1
自我挑戰組

Quest for Hyperskewb系列 第 5

[Part I] Shallow Tracing

  • 分享至 

  • xImage
  •  
Only one who wanted to find the Stone -- find it, but not use it -- would be able to get it.
-- Albus Dumbledore

Tracing MagicCube4D (MC4D) project

Simply skimming through the project, it is pretty obvious that all the core functions are in src/com/superliminal/magiccube4d directory, where the following java files lie:

Audio.java            MacroManager.java  MC4DSwing.java                  ProgressManager.java    Vec_h.java
Congratulations.java  MagicCube.java     MC4DView.java                   PuzzleDescription.java
History.java          Math4d.java        NdSolve.java                    PuzzleManager.java
MacroControls.java    MC4DApplet.java    PipelineUtils.java              RotationHandler.java
Macro.java            MC4DLauncher.java  PolytopePuzzleDescription.java  Sort.java

I will just skip setting up development environment because it is tedious. MC4D is a Java project so sure you can use Eclipse to compile a jar file. Choosing MC4DLauncher as the entry class works perfect for me.

MC4DLauncher looks entry-ish and it really is. After preliminary setup, the control is passed to MC4DSwing. Swing is a classic Java GUI framework. There are many more details to draw the MC4D window. The hypercubes are called puzzles in this project, so we can search this term in the MC4DSwing file. There may be graphic-related results mostly, but that's fine as well.

isSolved method

When tracing the file with our vague goal, I find this function interesting:

    private void updateEditMenuItems() {
        saveitem.setEnabled(true);
        cheatitem.setEnabled(hist.hasPreviousMove());
        solveitem.setEnabled(!puzzleManager.isSolved());
    }

There is a item (EditMenuItem ?) named solveitem. To enable it or not, the condition is the truth value of puzzleManager.isSolved. Intuitively, to tell if a puzzle is solved, the state of the puzzle must be checked. It is worth digging deeper.

The function is defined in PuzzleManager class, part 1 being

    public boolean isSolved()
    {
        int nFaces = puzzleDescription.nFaces();
        int faceState[] = new int[nFaces];
        VecMath.fillvec(faceState, -1);

From its naming, faceState array looks like what we expect at first, but soon we realize that it is a local variable, and being intitialized with -1. The size of this array represents the number of the faces. Still worth noting that, the term "face" here stands for "cell" or polyhedra. A simple way to understand this is, each face of a 3D object has 2 dimensions, so naturally each "face" of a 4D object (hypercubes or other 4D puzzles of our interests later) is 3D.

Personally I prefer the term cell, which is suggested by wikipedia: 4-polytope as well, and we should stick to it so that we won't mess up things, especially when we have to frequently revisit the concept or analogy in 3D space. However, the reason they chose face as the default term is still understandable, because human brain can quickly establish the link between the term face and the (n-1)-D boundaries of a n-D object. It is merely an anology, yet the usage can be seen all over the place. The intrinsic power of natural language is amazingly strong
.

puzzleDescription is a predefined object that we can perceive as the description of the puzzle object. It has a method nFaces(). For a 2x2x2x2 settings, since it is a regular tesseract, I believe the nFace method returns 8.

Part 2:

        // Cycle through all the stickers.
        for(int s = 0; s < puzzleState.length; s++)
        {
            int faceIndex = puzzleDescription.getSticker2Face()[s];
            if(faceState[faceIndex] == -1)
            {
                faceState[faceIndex] = puzzleState[s];
                continue;
            }

The term sticker is also a 3D analogy, representing the color attribute of each face of a cubie. Now it refers to the same thing for a 4D hypercube's 3D faces. Predefined variable puzzleState is used to retrieve the total number of stickers.

In part 1, we see the initialization of faceState array, and now in part 2, puzzleState[s] are assigned to each faceState, if it hasn't been assgined before. After part 3, we will get the whole picture of this algorithm,

            // Check for multiple colors on a single face.
            if(puzzleState[s] != faceState[faceIndex])
                return false;
        } // end for
        return true;
    } // end isSolved()

The first-line comment explains the trick. If the puzzle is not solved yet, which means at least some "face" of the puzzle is still a colorful mess. For such a face, after its value is assigned, eventually some s will exist such that the color of the sticker is different from itself. Thus, return false immediately in this case. Otherwise, when all the stickers are checked and false is never returned, true can be returned, because the puzzle is solved.

Conclusion

Well, the approach is different from what we expected, but not hard to understand. The approach naturally implements the net representation of a puzzle like we saw at ruwix.

During the tracing, I find evidences that draw me back on implementing hyperskewb as one of the puzzles in MC4D. While I will mention what I have found in later episodes, simply put, the core of MC4D project is not designed for puzzles like hyperskewb. I know I havn't even explain what hyperskewb is, but the day will come, and soon.

Today is the end of PART I: Basics. I expect that readers now already equipped with mental tools to imagine 4D puzzles. Even though I don't think in the rest of this series we will trace any more Java code, we will keep playing with MC4D in PART II: 2x2x2x2.

小結

沒有在 MC4D 找到想要參考的資料結構,但仍然可以作為一個第一部的收尾。


上一篇
[Part I] God's Number is 20
下一篇
[Part II] Control of MagicCube4D
系列文
Quest for Hyperskewb31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言