Ejemplo n.º 1
0
    void Start()
    {
        moduleId = moduleIdCounter++;

        // Show the runes the first time the module is selected
        Activator.OnInteract += delegate
        {
            if (moduleStarted)
            {
                return(false);
            }
            StartCoroutine(CrashDownSetup());
            moduleStarted = true;
            Activator.gameObject.SetActive(false);
            // This doesn't appear to work on the latest version of KTaNE
            //GamepadSupport();
            Module.Children = RuneOrder.ToArray();
            UpdateChildren();
            return(false);
        };

        // Set the runes to invisible until they appear
        for (int i = 0; i < Runes.Length; i++)
        {
            Runes[i].gameObject.SetActive(false);
            Runes[i].OnInteract += RunePressed(i);
        }

        // Assign RuneLetters with the different positions
        RuneLetters = new[] { RuneLetters_1, RuneLetters_2, RuneLetters_3 };

        // Assign RuneTransforms with their childs
        RuneTransforms = Runes.Select(rune => rune.transform.parent).ToArray();
        RuneParentPos  = Runes.Select(rune => rune.transform.parent.localPosition).ToArray();

        // Shuffle positions
        var randPos   = Enumerable.Range(0, RuneTransforms.Length).ToList();
        var runeOrder = new KMSelectable[selectableLocations.Length];

        for (int i = 0; i < RuneTransforms.Length; i++)
        {
            int index = Random.Range(0, randPos.Count);
            RuneTransforms[i].localPosition            = RuneParentPos[randPos[index]];
            DustSystemRunes[i].transform.localPosition = RuneParentPos[randPos[index]];
            Vector3 DustPos = DustSystemRunes[i].transform.localPosition;
            DustPos.y = 0.01f;
            DustSystemRunes[i].transform.localPosition = DustPos;
            runeOrder[Array.IndexOf(selectableLocations, randPos[index])] = Runes[i];
            randPos.RemoveAt(index);
        }

        RuneOrder = runeOrder.ToArray();

        // Generate a random 3-letter word
        for (int i = 0; i < RuneLetters.Length; i++)
        {
            pickedRuneLetters[i] = Random.Range(0, RuneLetters[i].Length);
            pickedRuneNames[i]   = ElderFuthark[pickedRuneLetters[i]];
            Debug.LogFormat(@"[Elder Futhark #{0}] The {1} rune is {2}", moduleId, i == 0 ? "first" : i == 1 ? "second" : "third", pickedRuneNames[i]);
        }

        // Rule-seeded rules
        var rnd = RuleSeedable.GetRNG();

        Debug.LogFormat(@"[Elder Futhark #{0}] Using rule seed: {1}.", moduleId, rnd.Seed);
        var cycleLeft = rnd.Seed == 1 ? false : rnd.Next(0, 2) != 0;
        var order     = rnd.Seed == 1 ? new[] { 0, 1, 2 } : rnd.ShuffleFisherYates(Enumerable.Range(0, 3).ToArray());

        var edgeworkConditions = newArray
                                 (
            // the sum of the digits in the serial number
            Bomb.GetSerialNumberNumbers().Sum(),
            // the sum of the first three characters in the serial number (use alphabetic positions for letters)
            Bomb.GetSerialNumber().Take(3).Select(ch => ch >= 'A' && ch <= 'Z' ? ch - 'A' + 1 : ch - '0').Sum(),
            // the sum of the last three characters in the serial number (use alphabetic positions for letters)
            Bomb.GetSerialNumber().Skip(3).Select(ch => ch >= 'A' && ch <= 'Z' ? ch - 'A' + 1 : ch - '0').Sum(),
            // the number of ports
            Bomb.GetPortCount(),
            // the number of indicators
            Bomb.GetIndicators().Count(),
            // the number of batteries
            Bomb.GetBatteryCount(),
            // the number of ports plus indicators
            Bomb.GetPortCount() + Bomb.GetIndicators().Count(),
            // the number of ports plus batteries
            Bomb.GetPortCount() + Bomb.GetBatteryCount(),
            // the number of indicators plus batteries
            Bomb.GetIndicators().Count() + Bomb.GetBatteryCount()
                                 );
        var edgeworkCondition = rnd.Seed == 1 ? 0 : rnd.Next(0, edgeworkConditions.Length);
        var modulo            = rnd.Seed == 1 ? 6 : rnd.Next(4, 9);

        var rowShuffle    = rnd.ShuffleFisherYates(Enumerable.Range(0, 23).ToArray());
        var columnShuffle = rnd.ShuffleFisherYates(Enumerable.Range(0, 23).ToArray());

        // Find the encryption key
        var name1 = pickedRuneNames[order[0]].ToLowerInvariant();
        var name2 = pickedRuneNames[order[1]].ToLowerInvariant();
        var name3 = pickedRuneNames[order[2]].ToLowerInvariant();

        var maxLength = Math.Max(name1.Length, Math.Max(name2.Length, name3.Length));

        var interweaved = Enumerable.Range(0, maxLength).Select(ix => name1[ix % name1.Length].ToString() + name2[ix % name2.Length].ToString() + name3[ix % name3.Length].ToString()).Join("");
        var cycleAmount = edgeworkConditions[edgeworkCondition] % modulo;

        if (cycleLeft)
        {
            cycleAmount = interweaved.Length - cycleAmount;
        }
        var encryptionKey = (interweaved.Substring(interweaved.Length - cycleAmount) + interweaved.Substring(0, interweaved.Length - cycleAmount)).Substring(0, pickedRuneNames[0].Length + pickedRuneNames[1].Length + pickedRuneNames[2].Length);

        Debug.LogFormat(@"[Elder Futhark #{0}] The encryption key is {1}.", moduleId, encryptionKey);

        // Encrypt the name of both runes together
        var transliteratedRunes = (pickedRuneNames[0] + pickedRuneNames[1] + pickedRuneNames[2]).ToLowerInvariant().Select(ch => ElderFutharkTranslated.IndexOf(tr => tr.Contains(ch))).ToArray();

        Debug.LogFormat(@"[Elder Futhark #{0}] transliteratedRunes = {1}", moduleId, transliteratedRunes.Select(ix => ElderFuthark[ix]).Join(", "));
        var transliteratedKey = encryptionKey.Select(ch => ElderFutharkTranslated.IndexOf(tr => tr.Contains(ch))).ToArray();

        Debug.LogFormat(@"[Elder Futhark #{0}] transliteratedKey = {1}", moduleId, transliteratedKey.Select(ix => ElderFuthark[ix]).Join(", "));
        var ciphered = transliteratedRunes.Select((ch, ix) => (columnShuffle[ch] + rowShuffle[transliteratedKey[ix]]) % 23).ToArray();

        pickedRuneNamesCipher = newArray(
            ciphered.Take(pickedRuneNames[0].Length).ToArray(),
            ciphered.Skip(pickedRuneNames[0].Length).Take(pickedRuneNames[1].Length).ToArray(),
            ciphered.Skip(pickedRuneNames[0].Length + pickedRuneNames[1].Length).ToArray()
            );
        Debug.LogFormat(@"[Elder Futhark #{0}] The encrypted first rune is: {1}.", moduleId, pickedRuneNamesCipher[0].Select(ix => ElderFuthark[ix]).Join(", "));
        Debug.LogFormat(@"[Elder Futhark #{0}] The encrypted second rune is: {1}.", moduleId, pickedRuneNamesCipher[1].Select(ix => ElderFuthark[ix]).Join(", "));
        Debug.LogFormat(@"[Elder Futhark #{0}] The encrypted third rune is: {1}.", moduleId, pickedRuneNamesCipher[2].Select(ix => ElderFuthark[ix]).Join(", "));
    }