static void generate()

in src/apps/miscapps/generateBaseCellNeighbors.c [84:251]


static void generate() {
    int baseCellNeighbors[NUM_BASE_CELLS][7];
    int baseCellRotations[NUM_BASE_CELLS][7];

    for (int i = 0; i < NUM_BASE_CELLS; i++) {
        if (!_isBaseCellPentagon(i)) {
            for (int dir = CENTER_DIGIT; dir <= NUM_DIRS; dir++) {
                FaceIJK fijk;
                _baseCellToFaceIjk(i, &fijk);
                _neighbor(&fijk.coord, dir);

                // Should never happen, but just in case :)
                if (fijk.coord.i < 3 && fijk.coord.j < 3 && fijk.coord.k < 3) {
                    baseCellNeighbors[i][dir] = _faceIjkToBaseCell(&fijk);
                    baseCellRotations[i][dir] =
                        _faceIjkToBaseCellCCWrot60(&fijk);
                } else {
                    printf("UH OH: Went out of bounds\n");
                }
            }
        } else {
            baseCellNeighbors[i][0] = i;
            baseCellRotations[i][0] = 0;

            for (int dir = 1; dir <= NUM_DIRS; dir++) {
                baseCellNeighbors[i][dir] = INVALID_BASE_CELL;
                baseCellRotations[i][dir] = -1;
            }

            for (int f = 0; f < NUM_ICOSA_FACES; f++) {
                for (int axis = 0; axis < 3; axis++) {
                    FaceIJK fijk = {f, {0, 0, 0}};
                    switch (axis) {
                        case 0:
                            fijk.coord.k = 2;
                            break;
                        case 1:
                            fijk.coord.j = 2;
                            break;
                        case 2:
                            fijk.coord.i = 2;
                            break;
                    }

                    // Determine if we found a face that can traverse to the
                    // pentagon
                    if (_faceIjkToBaseCell(&fijk) == i) {
                        // fijk of the neighboring base cell
                        FaceIJK neighborFijk = {
                            fijk.face,
                            {fijk.coord.i / 2, fijk.coord.j / 2,
                             fijk.coord.k / 2}};

                        // number of rotations from the neighboring base cell
                        // into the pentagon
                        int rotations = _faceIjkToBaseCellCCWrot60(&fijk);

                        // direction from the neighboring base cell to the
                        // pentagon
                        CoordIJK ijk = neighborFijk.coord;
                        // turn that into the direction within the pentagon
                        // (direction for continuing straight inside the
                        // pentagon)
                        for (int currRot = 0; currRot < rotations; currRot++) {
                            _ijkRotate60ccw(&ijk);
                        }
                        // invert that
                        for (int currRot = 0; currRot < 3; currRot++) {
                            _ijkRotate60ccw(&ijk);
                        }
                        // direction from the pentagon towards the neighboring
                        // base cell
                        Direction dir = _unitIjkToDigit(&ijk);

                        // the direction was detected as being the i direction,
                        // but this can't be because i is deleted from the
                        // pentagon. We need to choose a different direction.
                        if (dir == K_AXES_DIGIT) {
                            // 4 and 117 are 'polar' type pentagons, which have
                            // some different behavior.
                            if (_isBaseCellPentagon(i)) {
                                _ijkRotate60cw(&ijk);
                                _ijkRotate60cw(&ijk);
                            } else {
                                _ijkRotate60ccw(&ijk);
                            }
                            dir = _unitIjkToDigit(&ijk);
                        }

                        // Adjust for the deleted k-subsequence distortion
                        int rotAdj = 0;
                        if (_isBaseCellPolarPentagon(i)) {
                            // 'polar' type pentagon with all faces pointing
                            // towards i
                            if (dir == IK_AXES_DIGIT) {
                                rotAdj = 2;
                            } else if (dir == IJ_AXES_DIGIT) {
                                rotAdj = 4;
                            }
                        } else {
                            // the deleted k subsequence causes 4 and 5 to
                            // 'warp', need to adjust for that.
                            if (dir == I_AXES_DIGIT || dir == IK_AXES_DIGIT) {
                                rotAdj = dir;
                            }
                        }
                        rotations = (rotations + rotAdj) % 6;

                        int neighborBc = _faceIjkToBaseCell(&neighborFijk);

                        // The poles are totally different, although the
                        // rotations are correctly generated, so only overwrite
                        // the neighbor information. It was easier to manually
                        // derive the neighbors than to write the generation
                        // program.
                        if (i == 4) {
                            int realNeighbors[] = {
                                4, INVALID_BASE_CELL, 15, 8, 3, 0, 12};
                            neighborBc = realNeighbors[dir];
                        } else if (i == 117) {
                            int realNeighbors[] = {
                                117, INVALID_BASE_CELL, 109, 118, 113, 121,
                                106};
                            neighborBc = realNeighbors[dir];
                        }

                        // the actual neighboring base cell
                        baseCellNeighbors[i][dir] = neighborBc;
                        // rotations from the pentagon into the neighboring base
                        // cell
                        baseCellRotations[i][dir] = rotations;
                    }
                }
            }
        }
    }

    auditBaseCellNeighbors(baseCellNeighbors, baseCellRotations);

    printf("const int baseCellNeighbors[NUM_BASE_CELLS][7] = {\n");
    for (int i = 0; i < NUM_BASE_CELLS; i++) {
        printf("    {");
        for (int j = 0; j < 7; j++) {
            if (j > 0) {
                printf(", ");
            }
            if (baseCellNeighbors[i][j] != INVALID_BASE_CELL) {
                printf("%d", baseCellNeighbors[i][j]);
            } else {
                printf("INVALID_BASE_CELL");
            }
        }
        printf("}, // base cell %d%s\n", i,
               _isBaseCellPentagon(i) ? " (pentagon)" : "");
    }
    printf("};\n");
    printf("\n");
    printf("const int baseCellNeighbor60CCWRots[NUM_BASE_CELLS][7] = {\n");
    for (int i = 0; i < NUM_BASE_CELLS; i++) {
        printf("    {%d, %d, %d, %d, %d, %d, %d}, // base cell %d%s\n",
               baseCellRotations[i][0], baseCellRotations[i][1],
               baseCellRotations[i][2], baseCellRotations[i][3],
               baseCellRotations[i][4], baseCellRotations[i][5],
               baseCellRotations[i][6], i,
               _isBaseCellPentagon(i) ? " (pentagon)" : "");
    }
    printf("};\n");
}