Пример #1
0
        public Map(string serialNumber, string[] litIndicators, string[] unlitIndicators, int moduleId, MonoRandom rnd)
        {
            var    mazes = new List <MapNode[, ]>();
            string rowPhrase, colPhrase;

            Debug.LogFormat("[3D Maze #{0}] Using rule seed: {1}", moduleId, rnd.Seed);
            if (rnd.Seed == 1)
            {
                string[] labels;
                string[] n_walls;
                string[] w_walls;

                for (var mapIndex = 0; mapIndex < 10; mapIndex++)
                {
                    var rawMapData = new MapNode[WIDTH, WIDTH];
                    switch (mapIndex)
                    {
                    // ABC
                    case 0:
                        labels = new string[] {
                            "     A  ",
                            " *A    B",
                            "A  B C  ",
                            " C  *  B",
                            "    A   ",
                            " B C  B ",
                            "* C     ",
                            "    A C "
                        };
                        n_walls = new string[] {
                            "11000110",
                            "00001000",
                            "01011100",
                            "00100011",
                            "10011001",
                            "00000100",
                            "00110010",
                            "11000001"
                        };
                        w_walls = new string[] {
                            "10101001",
                            "10100100",
                            "00010001",
                            "01010110",
                            "01010001",
                            "01100100",
                            "01001101",
                            "00101100"
                        };
                        break;

                    // ABD
                    case 1:
                        labels = new string[] {
                            "A  B  A*",
                            "  D     ",
                            "     D B",
                            " A B    ",
                            "  *   A ",
                            "D   A   ",
                            "  B  D  ",
                            " D  *  B"
                        };
                        n_walls = new string[] {
                            "10100011",
                            "01100100",
                            "00011010",
                            "00100000",
                            "11100110",
                            "00010100",
                            "10100001",
                            "00011000"
                        };
                        w_walls = new string[] {
                            "10000010",
                            "11000100",
                            "00010001",
                            "01000100",
                            "10010001",
                            "00010100",
                            "01000101",
                            "00010100"
                        };
                        break;

                    // ABH
                    case 2:
                        labels = new string[] {
                            "B    A H",
                            "* H     ",
                            "B   B   ",
                            "    * HA",
                            " A H    ",
                            "    A B ",
                            " B   *  ",
                            "A  H    "
                        };
                        n_walls = new string[] {
                            "11101011",
                            "01011000",
                            "10001101",
                            "01010000",
                            "00001000",
                            "00110100",
                            "00101110",
                            "01100000"
                        };
                        w_walls = new string[] {
                            "10010000",
                            "01000001",
                            "00110011",
                            "11010101",
                            "11010010",
                            "11100000",
                            "00010101",
                            "00000001"
                        };
                        break;

                    // ACD
                    case 3:
                        labels = new string[] {
                            "D       ",
                            "  C D* C",
                            " *   C  ",
                            " A      ",
                            "D  C D  ",
                            "  A  * A",
                            "   A  D ",
                            "A    C  "
                        };
                        n_walls = new string[] {
                            "10111011",
                            "01100110",
                            "00000111",
                            "01000000",
                            "11101110",
                            "01100100",
                            "00010110",
                            "01101100"
                        };
                        w_walls = new string[] {
                            "00001000",
                            "11001100",
                            "01110010",
                            "10011001",
                            "10001001",
                            "01100101",
                            "01010000",
                            "10000010"
                        };
                        break;

                    // ACH
                    case 4:
                        labels = new string[] {
                            "H C   A ",
                            "*   H   ",
                            "      *C",
                            " A   H  ",
                            "C H C A ",
                            " *     A",
                            "   C H  ",
                            "  A     "
                        };
                        n_walls = new string[] {
                            "00111100",
                            "11010000",
                            "01100110",
                            "00000000",
                            "01000100",
                            "00000001",
                            "11100010",
                            "01011011"
                        };
                        w_walls = new string[] {
                            "10000110",
                            "10010001",
                            "01010101",
                            "10000001",
                            "11000000",
                            "01010101",
                            "10010000",
                            "01000010"
                        };
                        break;

                    // ADH
                    case 5:
                        labels = new string[] {
                            "D D  *  ",
                            "    H  A",
                            " *H   A ",
                            "A  D    ",
                            "    HD  ",
                            "* H    A",
                            "D       ",
                            "   A H  "
                        };
                        n_walls = new string[] {
                            "01110101",
                            "00001110",
                            "00000111",
                            "01001100",
                            "00110101",
                            "11100000",
                            "01100000",
                            "11001000"
                        };
                        w_walls = new string[] {
                            "10100100",
                            "11110000",
                            "11011000",
                            "01110000",
                            "10000101",
                            "10001110",
                            "00011111",
                            "10000101"
                        };
                        break;

                    // BCD
                    case 6:
                        labels = new string[] {
                            "     B  ",
                            "C D   * ",
                            " * B  C ",
                            " C    B ",
                            "    C  D",
                            "B    D  ",
                            " C  * D ",
                            "D  B    "
                        };
                        n_walls = new string[] {
                            "01011110",
                            "01101011",
                            "01100100",
                            "10000111",
                            "10110011",
                            "10011001",
                            "01100010",
                            "10111001"
                        };
                        w_walls = new string[] {
                            "10010000",
                            "00001010",
                            "11101000",
                            "00001000",
                            "00100010",
                            "00010001",
                            "00000110",
                            "00100001"
                        };
                        break;

                    // BCH
                    case 7:
                        labels = new string[] {
                            "C   H   ",
                            "  C    H",
                            "  * B   ",
                            "B  H*   ",
                            " H   B C",
                            "   *    ",
                            "  B C   ",
                            " C   H B"
                        };
                        n_walls = new string[] {
                            "10110011",
                            "01010111",
                            "10101100",
                            "00000110",
                            "01111110",
                            "00100010",
                            "10010100",
                            "00000110"
                        };
                        w_walls = new string[] {
                            "10000100",
                            "01001000",
                            "01111001",
                            "10001000",
                            "10001000",
                            "01101101",
                            "01101001",
                            "00010010"
                        };
                        break;

                    // BDH
                    case 8:
                        labels = new string[] {
                            "  D B  H",
                            "   *  D ",
                            "  H *  B",
                            "D    B  ",
                            "    D  H",
                            "  B     ",
                            "   H  H*",
                            "D    B  "
                        };
                        n_walls = new string[] {
                            "00100001",
                            "00010001",
                            "11011000",
                            "11011011",
                            "00010011",
                            "10000000",
                            "01101100",
                            "01001111"
                        };
                        w_walls = new string[] {
                            "01101000",
                            "11010111",
                            "00000110",
                            "00100000",
                            "00110100",
                            "10001110",
                            "11000000",
                            "00011010"
                        };
                        break;

                    // CDH
                    default:
                        labels = new string[] {
                            "  H  D  ",
                            "    C*  ",
                            "   H   D",
                            "H    D  ",
                            "  C     ",
                            "C  D C H",
                            "*D  H * ",
                            "       C"
                        };
                        n_walls = new string[] {
                            "01011010",
                            "00100100",
                            "00000000",
                            "01000010",
                            "01000010",
                            "01100110",
                            "01011010",
                            "10100101"
                        };
                        w_walls = new string[] {
                            "11001001",
                            "11110111",
                            "00100010",
                            "00011100",
                            "10011100",
                            "10001000",
                            "11000001",
                            "00101010"
                        };
                        break;
                    }

                    for (int y = 0; y < WIDTH; y++)
                    {
                        for (int x = 0; x < WIDTH; x++)
                        {
                            rawMapData[x, y] = new MapNode(labels[y][x], n_walls[y][x] == '1', w_walls[y][x] == '1');
                        }
                    }
                    mazes.Add(rawMapData);
                }

                rowPhrase = "MAZEGAMER";
                colPhrase = "HELPIMLOST";
            }
            else
            {
                // RULE SEEDED CODE starts here
                var mazeLabels = "ABC,ABD,ABH,ACD,ACH,ADH,BCD,BCH,BDH,CDH".Split(',');
                foreach (var labels in mazeLabels)
                {
                    var mapData = new MapNode[WIDTH, WIDTH];
                    for (var x = 0; x < WIDTH; x++)
                    {
                        for (var y = 0; y < WIDTH; y++)
                        {
                            mapData[x, y] = new MapNode(' ', true, true);
                        }
                    }
                    var todo    = Enumerable.Range(0, WIDTH * WIDTH).Select(i => new Coordinate(i % WIDTH, i / WIDTH)).ToList();
                    var visited = new List <Coordinate>();
                    var done    = new List <Coordinate>();

                    // Choose a random square to start from
                    var startIx = rnd.Next(0, todo.Count);
                    visited.Add(todo[startIx]);
                    todo.RemoveAt(startIx);

                    // Generate a maze
                    while (todo.Count > 0)
                    {
                        var cellIx = rnd.Next(0, visited.Count);
                        var cell   = visited[cellIx];

                        var validWalls = Enumerable.Range(0, 4).Select(dir => new { Dir = dir, Cell = Neighbor(cell, dir) }).Where(c => todo.Contains(c.Cell)).ToArray();
                        if (validWalls.Length == 0)
                        {
                            visited.RemoveAt(cellIx);
                            done.Add(cell);
                            continue;
                        }

                        var wallIx = rnd.Next(0, validWalls.Length);
                        var wall   = validWalls[wallIx];
                        switch (wall.Dir)
                        {
                        case NORTH: mapData[cell.X, cell.Y].n_wall = false; break;

                        case WEST: mapData[cell.X, cell.Y].w_wall = false; break;

                        case SOUTH: mapData[wall.Cell.X, wall.Cell.Y].n_wall = false; break;

                        default: mapData[wall.Cell.X, wall.Cell.Y].w_wall = false; break;
                        }
                        todo.Remove(wall.Cell);
                        visited.Add(wall.Cell);
                    }

                    // Remove 20–35% of the remaining walls to make the maze more spacious
                    var remainingWalls = new List <int>();
                    for (var x = 0; x < WIDTH; x++)
                    {
                        for (var y = 0; y < WIDTH; y++)
                        {
                            if (mapData[x, y].n_wall)
                            {
                                remainingWalls.Add((WIDTH * y + x) * 2);
                            }
                            if (mapData[x, y].w_wall)
                            {
                                remainingWalls.Add((WIDTH * y + x) * 2 + 1);
                            }
                        }
                    }
                    var percentage  = (rnd.NextDouble() * .15) + .2;
                    var removeWalls = (int)(remainingWalls.Count * percentage);
                    while (removeWalls > 0)
                    {
                        var wallIx = rnd.Next(0, remainingWalls.Count);
                        var wall   = remainingWalls[wallIx];
                        remainingWalls.RemoveAt(wallIx);
                        var x = (wall / 2) % WIDTH;
                        var y = (wall / 2) / WIDTH;

                        if (wall % 2 == 1)
                        {
                            // Make sure not to remove a wall that would leave an entire row devoid of walls
                            if (Enumerable.Range(0, WIDTH).Count(xx => mapData[xx, y].w_wall) == 1)
                            {
                                continue;
                            }
                            mapData[x, y].w_wall = false;
                        }
                        else
                        {
                            // Make sure not to remove a wall that would leave an entire column devoid of walls
                            if (Enumerable.Range(0, WIDTH).Count(yy => mapData[x, yy].n_wall) == 1)
                            {
                                continue;
                            }
                            mapData[x, y].n_wall = false;
                        }
                        removeWalls--;
                    }

                    // Select 33 random cells for the labels (letters and cardinals)
                    done.AddRange(visited);
                    rnd.ShuffleFisherYates(done);
                    // Add the labels (5 of each letter)
                    for (var letterIx = 0; letterIx < labels.Length; letterIx++)
                    {
                        for (var i = 0; i < 5; i++)
                        {
                            mapData[done[5 * letterIx + i].X, done[5 * letterIx + i].Y].label = labels[letterIx];
                        }
                    }
                    // Add the 3 asterisks
                    for (var i = 0; i < 3; i++)
                    {
                        mapData[done[30 + i].X, done[30 + i].Y].label = '*';
                    }

                    mazes.Add(mapData);
                }

                var phrases = new List <string>
                {
                    "MAZE GAMER",
                    "MAZE TRAVELER",
                    "MAZE CORRIDOR",
                    "MAZE SOJOURNER",
                    "MAZE VOYAGER",
                    "HELP IM LOST",
                    "WINDING MAZE",
                    "TWISTY PASSAGES",
                    "ADVENTURING",
                    "FIND THE EXIT",
                    "WHERES THE EXIT",
                    "GO TO THE EXIT",
                    "FIND THE WALL",
                    "UPON DISCOVERY",
                    "ON A JOURNEY",
                    "SOS WHERE AM I",
                    "SHOW ME AROUND",
                    "I NEED ASSISTANCE",
                    "LABYRINTHIAN",
                    "PATH FINDER",
                    "CARDINAL DIRECTION",
                    "WHAT IS THIS PLACE",
                    "GO IN CIRCLES",
                    "DEAD END",
                    "TURN AROUND"
                };
                var ix = rnd.Next(0, phrases.Count);
                rowPhrase = phrases[ix];
                phrases.RemoveAt(ix);
                colPhrase = phrases[rnd.Next(0, phrases.Count)];
                Debug.LogFormat("<3D Maze #{0}> Row phrase: {1}", moduleId, rowPhrase);
                Debug.LogFormat("<3D Maze #{0}> Column phrase: {1}", moduleId, colPhrase);
            }

            // Calculate the goal position from the edgework
            var firstDigit = serialNumber.Where(ch => ch >= '0' && ch <= '9').First();
            var lastDigit  = serialNumber.Where(ch => ch >= '0' && ch <= '9').Last();
            var rowMsg     = firstDigit.ToString();
            var numUnlit   = 0;

            foreach (string unlit in unlitIndicators)
            {
                // MAZE GAMER
                if (unlit.Intersect(rowPhrase).Any())
                {
                    numUnlit++;
                    rowMsg += " + " + unlit;
                }
            }
            if (numUnlit == 0)
            {
                rowMsg = "no unlit indicators";
            }

            var colMsg = lastDigit.ToString();
            var numLit = 0;

            foreach (string lit in litIndicators)
            {
                // HELP I'M LOST
                if (lit.Intersect(colPhrase).Any())
                {
                    numLit++;
                    colMsg += " + " + lit;
                }
            }
            if (numLit == 0)
            {
                colMsg = "no lit indicators";
            }

            sol_x = (lastDigit + numLit) % WIDTH;
            sol_y = (firstDigit + numUnlit) % WIDTH;

            mapData = mazes[Random.Range(0, 10)];
            end_dir = Random.Range(0, 4);
            var decoy_dir = Random.Range(0, 3);

            if (decoy_dir >= end_dir)
            {
                decoy_dir++;
            }

            Debug.LogFormat("[3D Maze #{0}] Selected map: {1}", moduleId, join("", Enumerable.Range(0, WIDTH * WIDTH).Select(ix => mapData[ix % WIDTH, ix / WIDTH].label).Where("ABCDH".Contains).Distinct().OrderBy(c => c)));
            Debug.LogFormat("[3D Maze #{0}] Column: {1} ({2}), Row: {3} ({4}), Cardinal: {5}", moduleId, sol_x, colMsg, sol_y, rowMsg, new[] { "North", "East", "South", "West" }[end_dir]);

            // Replace the asterisks in the map with the true cardinal direction
            for (var x = 0; x < WIDTH; x++)
            {
                for (var y = 0; y < WIDTH; y++)
                {
                    if (mapData[x, y].label == '*')
                    {
                        mapData[x, y].label = dirToChar(end_dir);
                    }
                }
            }

            // Add three decoy cardinal directions
            for (int i = 0; i < 3; i++)
            {
                int x = Random.Range(0, WIDTH);
                int y = Random.Range(0, WIDTH);
                while (mapData[x, y].label != ' ')
                {
                    x = Random.Range(0, WIDTH);
                    y = Random.Range(0, WIDTH);
                }
                mapData[x, y].label = dirToChar(decoy_dir);
            }

            pl_x   = Random.Range(0, WIDTH);
            pl_y   = Random.Range(0, WIDTH);
            pl_dir = Random.Range(0, 4);

            while (!getEdge(sol_x, sol_y, end_dir, 0, 0, end_dir))
            {
                sol_x = bound(sol_x + xMod(1, 0, end_dir), WIDTH);
                sol_y = bound(sol_y + yMod(1, 0, end_dir), WIDTH);
            }

            win_x1 = sol_x;
            win_y1 = sol_y;

            win_x2 = bound(sol_x + xMod(1, 0, end_dir), WIDTH);
            win_y2 = bound(sol_y + yMod(1, 0, end_dir), WIDTH);
        }
Пример #2
0
        private static Dictionary <string, string> GetRulesInternal(int ruleSeed)
        {
            if (ruleSeed == 1)
            {
                return new Dictionary <string, string>(StringComparer.CurrentCultureIgnoreCase)
                       {
                           { "shell", "3.505" },
                           { "halls", "3.515" },
                           { "slick", "3.522" },
                           { "trick", "3.532" },
                           { "boxes", "3.535" },
                           { "leaks", "3.542" },
                           { "strobe", "3.545" },
                           { "bistro", "3.552" },
                           { "flick", "3.555" },
                           { "bombs", "3.565" },
                           { "break", "3.572" },
                           { "brick", "3.575" },
                           { "steak", "3.582" },
                           { "sting", "3.592" },
                           { "vector", "3.595" },
                           { "beats", "3.600" }
                       }
            }
            ;

            var random      = new MonoRandom(ruleSeed);
            var frequencies = random.Shuffle((string[])MorseCodeSolver.frequencies.Clone()).Take(FrequenciesUsed).ToArray();

            var words = new string[FrequenciesUsed];

            Array.Copy(random.Shuffle((string[])MorseCodeSolver.words.Clone()), words, FrequenciesUsed / 2);

            int i = FrequenciesUsed / 2;

            for (int j = 0; j < FrequenciesUsed / 2; ++j)
            {
                var s     = words[j].Substring(1);
                var toAdd = (from w in MorseCodeSolver.words where !words.Contains(w) && !w.EndsWith(s)
                             select(word: w, pref: random.NextDouble(), dist: CyclingLevenshteinDistance(w, words[j]))).ToArray();
                Array.Sort(toAdd, (a, b) => {
                    var r = a.dist - b.dist;
                    return(r != 0 ? r : a.pref.CompareTo(b.pref));
                });

                var numberToAdd = Math.Min(random.Next(1, 4), Math.Min(FrequenciesUsed - i, toAdd.Length));
                for (int k = 0; k < numberToAdd; ++k)
                {
                    words[i] = toAdd[k].word;
                    ++i;
                }
            }

            var dictionary = new Dictionary <string, string>(StringComparer.CurrentCultureIgnoreCase);

            for (i = 0; i < FrequenciesUsed; ++i)
            {
                dictionary.Add(words[i], frequencies[i]);
            }

            return(dictionary);
        }