private IEnumerator CutWire(int index)
    {
        if (!_allWires[index][0].activeInHierarchy || ModuleSelectable.Children[0] == Placeholder)
        {
            yield break;
        }
        Audio.PlayGameSoundAtTransform(KMSoundOverride.SoundEffect.WireSnip, _allWires[index][0].transform);
        _allWires[index][0].SetActive(false);
        _allWires[index][1].SetActive(true);
        ModuleSelectable.Children[index] = null;
        ModuleSelectable.UpdateChildren();
        if (WiresDoorAnimator.GetBool("Transitioning"))
        {
            yield break;
        }
        WiresDoorAnimator.SetBool("Transitioning", true);
        if (!_secondStage && index + 1 == firstWireToCut)
        {
            Debug.LogFormat("[Thinking Wires #{0}] Wire {1} was cut which is correct. Progressing to the second stage.", _moduleId, firstWireToCut);
            _secondStage = true;
            StartCoroutine(DoorAnimation());
        }
        else if (_secondStage && (_secondWireToCutEnum == null || _wiresColors[index] == _secondWireToCutEnum))
        {
            if (_secondWireToCutEnum == null)
            {
                Debug.LogFormat("[Thinking Wires #{0}] A wire was cut which is always valid. Solving the module.", _moduleId);
            }
            else
            {
                Debug.LogFormat("[Thinking Wires #{0}] A {1} wire was cut which is the correct color. Solving the module.", _moduleId, _secondWireToCutEnum.ToString().ToLowerInvariant());
            }
            yield return(StartCoroutine(DoorAnimation(open: false)));

            SetDisplay(setGreen: true);
            moduleSolved = true;
            Audio.PlayGameSoundAtTransform(KMSoundOverride.SoundEffect.CorrectChime, transform);
            Module.HandlePass();
        }
        else
        {
            if (!_secondStage)
            {
                Debug.LogFormat("[Thinking Wires #{0}] Wire {1} was cut when wire {2} must be cut during stage 1. Resetting the module and initiating a strike.", _moduleId, index + 1, firstWireToCut);
            }
            else
            {
                Debug.LogFormat("[Thinking Wires #{0}] {1} wire was cut when any {2} wire must be cut during stage 2. Resetting the module and initiating a strike.", _moduleId, _wiresColors[index].ToString(), secondWireToCut.ToLowerInvariant());
            }
            Module.HandleStrike();
            _secondStage = false;
            _visitedNode.Clear();
            StartCoroutine(DoorAnimation());
        }
    }
Exemplo n.º 2
0
    void UpdateSelectable()
    {
        List <KMSelectable> children = new List <KMSelectable>();

        foreach (Transform child in Elements.transform)
        {
            GameObject element = child.gameObject;
            if (element != Halo)
            {
                children.Add(element.activeSelf ? element.GetComponent <KMSelectable>() : null);
            }
        }

        ModuleSelectable.Children = children.ToArray();
        ModuleSelectable.UpdateChildren();
    }
    private void Start()
    {
        moduleId = moduleIdCounter++;
        List <NumberComponent> numbers = new List <NumberComponent>();
        int index = 0;

        for (int z = 0; z < 3; z++)
        {
            for (int x = -1; x < 2; x++)
            {
                NumberComponent number = Instantiate(NumberComponentPrefab);
                number.transform.parent        = NumberScreensContainer;
                number.transform.localPosition = new Vector3(0.05f * x, 0f, -0.03f * z);
                number.transform.localScale    = Vector3.one;
                number.transform.localRotation = Quaternion.identity;
                number.Selectable.Parent       = SelfSelectable;
                number.OnActualized           += OnActualized;
                number.OnSelected          += () => Audio.PlaySoundAtTransform("BinaryShiftNumberOn", number.transform);
                number.OnManualyDeselected += () => Audio.PlaySoundAtTransform("BinaryShiftNumberOff", number.transform);
                number.index = index++;
                numbers.Add(number);
            }
        }
        this.numbers = numbers.ToArray();
        List <KMSelectable> children = new List <KMSelectable>(numbers.Select((n) => n.Selectable));

        children.Add(Stage.Selectable);
        Stage.Selectable.OnInteract += () => { OnNextStage(); return(false); };
        SelfSelectable.Children      = children.ToArray();
        SelfSelectable.UpdateChildren();
        Reset();
        BombModule.OnActivate += () => activated = true;
    }
Exemplo n.º 4
0
    private void Start()
    {
        moduleId = _moduleIdCounter++;
        KMSelectable selfSelectable = GetComponent <KMSelectable>();

        selfSelectable.Children = new KMSelectable[DIGITS_COUNT + 1];
        for (int i = 0; i < DIGITS_COUNT; i++)
        {
            SelectableDigit digit = Instantiate(SelectableDigitPrefab);
            digit.transform.parent = Display.transform;
            float x = DIGITS_INTERVAL * (i - (DIGITS_COUNT - 1) / 2f);
            digit.transform.localPosition = new Vector3(x, DIGITS_HEIGHT, 0f);
            digit.transform.localRotation = new Quaternion();
            digit.transform.localScale    = Vector3.one;
            digit.Actualized += () => OnDigitActualized();
            KMSelectable digitSelectable = digit.GetComponent <KMSelectable>();
            digitSelectable.Parent     = selfSelectable;
            selfSelectable.Children[i] = digitSelectable;
            int digitIndex = i;
            digitSelectable.OnInteract += () => OnDigitPressed(digitIndex);
            digits[i] = digit;
        }
        selfSelectable.Children[DIGITS_COUNT] = SkipButton;
        selfSelectable.UpdateChildren();
        SkipButton.OnInteract += () => OnSkipPressed();
        GetComponent <KMBombModule>().OnActivate += () => Activate();
    }
    private void RandomizePuzzle()
    {
        _tangram = GenerateTangram();
        _tangram.LogInfo(_bombModule);

        _chip = Instantiate(_tangram.Grid.Chip, transform);
        _chip.UnderlayTexture = _tangram.Grid.UnderlayTexture;
        _chip.Code            = _tangram.ChipCode;

        KMSelectable chipSelectable = _chip.Selectable;

        _selectable.ChildRowLength = chipSelectable.ChildRowLength;
        _selectable.Children       = chipSelectable.Children;

        for (int contactPointIndex = 0; contactPointIndex < chipSelectable.transform.childCount; ++contactPointIndex)
        {
            KMSelectable contactPoint = chipSelectable.transform.GetChild(contactPointIndex).GetComponent <KMSelectable>();
            contactPoint.Parent = _selectable;
        }

        _selectable.DefaultSelectableIndex = chipSelectable.DefaultSelectableIndex;
        _selectable.UpdateChildren(_selectable.Children[_selectable.DefaultSelectableIndex]);

        _chip.OnPinInteract += OnPinInteract;
    }
    void UpdateSelectables(int idxNum)
    {
        switch (idxNum)
        {
        case 0:
            selectableSelf.Children       = new KMSelectable[] { destinationButton, null, componentButton, null, goButton, null, };
            selectableSelf.ChildRowLength = 2;
            break;

        case 1:
            selectableSelf.Children       = new KMSelectable[] { prevSector, nextSector, prevArea, nextArea, destinationBack, null };
            selectableSelf.ChildRowLength = 2;
            break;

        case 2:
            selectableSelf.Children       = new KMSelectable[] { subBattery, addBattery, subIndicator, addIndicator, prevPort, nextPort, subManual, addManual, componentBack, null };
            selectableSelf.ChildRowLength = 2;
            break;

        default:
            selectableSelf.Children       = new KMSelectable[0];
            selectableSelf.ChildRowLength = 1;
            break;
        }
        selectableSelf.UpdateChildren();
        //selectableSelf.UpdateChildren(selectableSelf.Children.FirstOrDefault());
    }
    private void OnSelect(FluidSelectable currentSelectable)
    {
        KMSelectable[] children = parentSelectable.Children;

        int reserveChildCount = children.Length - 12;

        Array.Clear(children, reserveChildCount, 12);

        KMSelectable selectable = currentSelectable != null ? currentSelectable.selectable : null;

        children[reserveChildCount]     = selectable;
        children[reserveChildCount + 1] = selectable;
        children[reserveChildCount + 2] = selectable;
        children[reserveChildCount + 7] = selectable;

        if (currentSelectable != null)
        {
            children[reserveChildCount + 4]  = currentSelectable.up != null ? currentSelectable.up.selectable : null;
            children[reserveChildCount + 6]  = currentSelectable.left != null ? currentSelectable.left.selectable : null;
            children[reserveChildCount + 8]  = currentSelectable.right != null ? currentSelectable.right.selectable : null;
            children[reserveChildCount + 10] = currentSelectable.down != null ? currentSelectable.down.selectable : null;
        }

        parentSelectable.UpdateChildren(selectable);
    }
    private void Start()
    {
        moduleId         = moduleIdCounter++;
        mapRotationSpeed = Random.onUnitSphere;
        List <KMSelectable> children = new List <KMSelectable>();

        for (int i = 0; i < STARS_COUNT; i++)
        {
            StarComponent star = Instantiate(StarPrefab);
            star.transform.parent        = MapContainer.transform;
            star.transform.localPosition = Random.rotation * (Vector3.forward * SPAWN_RADIUS);
            star.transform.localRotation = Quaternion.identity;
            star.transform.localScale    = Vector3.one;
            stars[i]      = star;
            star.StarInfo = StarInfo;
            star.Selectable.OnInteract += () => { OnStarPressed(star); return(false); };
            star.Selectable.Parent      = Selectable;
            children.Add(star.Selectable);
        }
        children.Add(ClearButton);
        children.Add(SubmitButton);
        Selectable.Children = children.ToArray();
        Selectable.UpdateChildren();
        Selectable.OnFocus   += () => focused = true;
        Selectable.OnDefocus += () => focused = false;
        Module.OnActivate    += Activate;
    }
Exemplo n.º 9
0
    void UpdateSelectable()
    {
        List <KMSelectable> Children = new List <KMSelectable>();

        if (!Game.Solved)
        {
            foreach (Cell cell in Game.Cells)
            {
                if (StartFound)
                {
                    Children.Add(!cell.Dug || (cell.Number > 0 && Digging) ? cell._selectable : null);
                }
                else
                {
                    Children.Add(Picks.Contains(cell) ? cell._selectable : null);
                }
            }
        }

        if (StartFound)
        {
            Children.Add(ModeToggle.GetComponent <KMSelectable>());
        }

        foreach (KMSelectable selectable in GetComponentsInChildren <KMSelectable>().Except(new KMSelectable[] { ModuleSelectable }))
        {
            selectable.Highlight.gameObject.SetActive(Children.IndexOf(selectable) > -1);
        }

        ModuleSelectable.Children = Children.ToArray();
        ModuleSelectable.UpdateChildren(null);
    }
Exemplo n.º 10
0
#pragma warning restore 649

    public static void UpdateChildrenProperly(this KMSelectable selectable, KMSelectable childToSelect = null)
    {
        foreach (var child in selectable.Children)
        {
            child.UpdateSettings();
        }
        selectable.UpdateSettings();
        selectable.UpdateChildren(childToSelect);
    }
Exemplo n.º 11
0
    private IEnumerator Initialize2()
    {
        yield return(null);

        if (_isMain)
        {
            _info.Links = new int[_info.Modules.Count - 1];
            for (int i = 1; i <= _info.Links.Length; i++)
            {
                _info.Links[i - 1] = i;
            }

            Debug.Log(_info.Links.Join());

            Shuffle <int>(_info.Links);

            Debug.Log(_info.Links.Join());

            for (int i = 1; i < _info.Modules.Count; i++)
            {
                GameObject Sphere = Instantiate(TestObject);
                Sphere.transform.SetPositionAndRotation(_info.Positions[i].position, _info.Positions[i].rotation);
                Sphere.transform.SetParent(Module.transform);
                Sphere.transform.localScale = new Vector3(1f, 1f, 1f);
                KMSelectable script = Sphere.GetComponentInChildren <KMSelectable>();

                KMSelectable[] outarr = new KMSelectable[_info.Modules[i].ModuleSelectable.Children.Length + 1];
                _info.Modules[i].ModuleSelectable.Children.CopyTo(outarr, 0);
                outarr[_info.Modules[i].ModuleSelectable.Children.Length] = script;

                _info.Modules[i].ModuleSelectable.Children = outarr;
                script.Parent = _info.Modules[i].ModuleSelectable;
                _info.Modules[i].ModuleSelectable.UpdateChildren();

                int j = _info.Links[i - 1];
                Sphere.GetComponentInChildren <KMSelectable>().OnInteract += delegate() { onSimp(j); return(false); };
            }

            GameObject Sphere2 = Instantiate(TestObject2);
            Sphere2.transform.SetPositionAndRotation(_info.Positions[0].position, _info.Positions[0].rotation);
            Sphere2.transform.SetParent(Module.transform);
            Sphere2.transform.localScale = new Vector3(1f, 1f, 1f);
            KMSelectable script2 = Sphere2.GetComponentInChildren <KMSelectable>();

            KMSelectable[] outarr2 = new KMSelectable[ModuleSelectable.Children.Length + 1];
            ModuleSelectable.Children.CopyTo(outarr2, 0);
            outarr2[ModuleSelectable.Children.Length] = script2;

            ModuleSelectable.Children = outarr2;
            script2.Parent            = ModuleSelectable;
            ModuleSelectable.UpdateChildren();

            Sphere2.GetComponentInChildren <KMSelectable>().OnInteract += delegate() { onSimp(0); return(false); };
        }
    }
Exemplo n.º 12
0
    private void SetSelectables(NextAction act)
    {
        List <KMSelectable> selectables = new List <KMSelectable>();

        switch (act)
        {
        case NextAction.None:
            break;

        case NextAction.WhiteFrom:
            for (var i = 0; i < _game.Board.Length; i++)
            {
                if (Piece.IsWhite(_game.Board[i]))
                {
                    selectables.Add(Squares.transform.Find("Square (" + i + ")").GetComponent <KMSelectable>());
                }
            }
            break;

        case NextAction.WhiteTo:
            for (var i = 0; i < _game.Board.Length; i++)
            {
                if (!Piece.IsWhite(_game.Board[i]))
                {
                    selectables.Add(Squares.transform.Find("Square (" + i + ")").GetComponent <KMSelectable>());
                }
            }
            break;

        case NextAction.BlackFrom:
            for (var i = 0; i < _game.Board.Length; i++)
            {
                if (Piece.IsBlack(_game.Board[i]))
                {
                    selectables.Add(Squares.transform.Find("Square (" + i + ")").GetComponent <KMSelectable>());
                }
            }
            break;

        case NextAction.BlackTo:
            for (var i = 0; i < _game.Board.Length; i++)
            {
                if (!Piece.IsBlack(_game.Board[i]))
                {
                    selectables.Add(Squares.transform.Find("Square (" + i + ")").GetComponent <KMSelectable>());
                }
            }
            break;
        }
        selectables.Add(Button);
        Module.Children = selectables.ToArray();
        Module.UpdateChildren();
    }
        public Alert MakeAlert(string title, string text, Transform parent, KMSelectable parentSelectable)
        {
            var alert = Instantiate(gameObject, parent).GetComponent <Alert>();

            alert.SetupAlert(title, text);

            var selectable = alert.Ok.GetComponent <KMSelectable>();

            selectable.Parent = parentSelectable;
            parentSelectable.Children[parentSelectable.Children.Length - parentSelectable.ChildRowLength] = selectable;
            parentSelectable.UpdateChildren();

            return(alert);
        }
Exemplo n.º 14
0
    private void UpdateSelectable()
    {
        List <KMSelectable> selectableList = new List <KMSelectable>();

        for (int row = 0; row < 2; row++)
        {
            for (int col = 4; col >= 0; col--)
            {
                selectableList.Add(ButtonSelectables[5 * row + col]);
            }
        }
        MainSelectable.Children = selectableList.ToArray();
        MainSelectable.UpdateChildren();
    }
    private void Activate()
    {
        _startingMinutes = remainingMinutesCount;
        Debug.LogFormat("[Space Traders #{0}] Bomb starting time in minutes is {1}", _moduleId, startingMinutes);
        KMSelectable selfSelectable = GetComponent <KMSelectable>();

        selfSelectable.Children = starByName.Values.Select((star) => {
            KMSelectable starSelectable = star.GetComponent <KMSelectable>();
            starSelectable.Parent       = selfSelectable;
            return(starSelectable);
        }).ToArray();
        selfSelectable.UpdateChildren();
        GenerateMaxTaxAndGoodsToSoldCount();
        activated = true;
    }
Exemplo n.º 16
0
        public Confirmation MakeConfirmation(string title, string message, Transform parent, KMSelectable parentSelectable, Action confirm)
        {
            var confirmation = Instantiate(gameObject, parent).GetComponent <Confirmation>();

            confirmation.SetupConfirmation(title, message, confirm);

            var confirmSelectable = confirmation.Confirm.GetComponent <KMSelectable>();
            var cancelSelectable  = confirmation.Cancel.GetComponent <KMSelectable>();

            confirmSelectable.Parent = cancelSelectable.Parent = parentSelectable;
            parentSelectable.Children[parentSelectable.Children.Length - parentSelectable.ChildRowLength]     = confirmSelectable;
            parentSelectable.Children[parentSelectable.Children.Length - parentSelectable.ChildRowLength + 1] = cancelSelectable;
            parentSelectable.UpdateChildren();

            return(confirmation);
        }
    private void OnInteractEnded()
    {
        if (thisPage != null)
        {
            thisPage.gameObject.SetActive(false);
        }

        if (linkPage != null)
        {
            linkPage.gameObject.SetActive(true);
            if (linkPage.GridSelectables != null && linkPage.GridSelectables.Length > 0)
            {
                _selectable.UpdateChildren(linkPage.GridSelectables[0].GetComponent <KMSelectable>());
            }
        }
    }
        public Prompt MakePrompt(string title, string defaultValue, Transform parent, KMSelectable parentSelectable, KMAudio audio, Action <string> confirm)
        {
            var prompt = Instantiate(gameObject, parent).GetComponent <Prompt>();

            prompt.SetupPrompt(title, defaultValue, audio, confirm);

            var confirmSelectable = prompt.Confirm.GetComponent <KMSelectable>();
            var cancelSelectable  = prompt.Cancel.GetComponent <KMSelectable>();

            confirmSelectable.Parent = cancelSelectable.Parent = parentSelectable;
            parentSelectable.Children[parentSelectable.Children.Length - parentSelectable.ChildRowLength]     = confirmSelectable;
            parentSelectable.Children[parentSelectable.Children.Length - parentSelectable.ChildRowLength + 1] = cancelSelectable;
            parentSelectable.UpdateChildren();

            return(prompt);
        }
Exemplo n.º 19
0
    private void Start()
    {
        colorblindModeEnabled = ColorblindMode.ColorblindModeActive;
        moduleId = moduleIdCounter++;
        foreach (Color color in allColors)
        {
            countOfColor[color] = 0;
        }
        List <KMSelectable> children            = new List <KMSelectable>();
        HashSet <Color>     colorsActiveAtStart = GetHalfRandomColors();

        buttonsGrid = new ButtonComponent[WIDTH][];
        for (int x = 0; x < WIDTH; x++)
        {
            buttonsGrid[x] = new ButtonComponent[HEIGHT];
            for (int z = 0; z < HEIGHT; z++)
            {
                ButtonComponent button = Instantiate(ButtonPrefab);
                button.transform.parent           = ButtonsCollection.transform;
                button.transform.localPosition    = new Vector3(x * 0.02f, 0.015f, (HEIGHT - z - 1) * 0.02f);
                button.transform.localScale       = new Vector3(0.0101f, 0.01f, 0.0101f);
                button.transform.localEulerAngles = Vector3.zero;
                Color color = allColors[Random.Range(0, allColors.Length)];
                button.primaryColor   = color;
                countOfColor[color]  += 1;
                button.active         = colorsActiveAtStart.Contains(color);
                button.colorblindMode = ColorblindMode.ColorblindModeActive;
                buttons.Add(button);
                button.Selectable.Parent = SelfSelectable;
                children.Add(button.Selectable);
                buttonsGrid[x][z] = button;
            }
        }
        foreach (Color color in allColors)
        {
            string prettier = colorNames[color];
            int    count    = countOfColor[color];
            Debug.LogFormat("[Colors Maximization #{0}] {1} color count = {2}", moduleId, prettier, count);
        }
        children.Add(SubmitButton);
        SelfSelectable.Children = children.ToArray();
        SelfSelectable.UpdateChildren();
        SubmitButton.OnInteract += OnSubmitPressed;
        BombModule.OnActivate   += OnActivate;
    }
Exemplo n.º 20
0
    IEnumerator HandleDisappearAnim()
    {
        canForceUpdateTiles = true;
        UpdateGrid();
        selfSelectable.Children = new KMSelectable[] { resetSelectable };
        selfSelectable.UpdateChildren();
        yield return(new WaitForSeconds(1f));

        mAudio.PlaySoundAtTransform("1_Shrink_Trimmed", transform);
        for (float x = 0; x < 1f; x += Time.deltaTime * 5)
        {
            yield return(null);

            entireGrid.localScale = Vector3.one * (1f - x);
        }
        entireGrid.localScale = Vector3.zero;
        entireGrid.gameObject.SetActive(false);
        yield break;
    }
    private void EnablePage(KMSelectable page)
    {
        RootSelectable.Children               = page.Children;
        RootSelectable.ChildRowLength         = page.ChildRowLength;
        RootSelectable.DefaultSelectableIndex = page.DefaultSelectableIndex;
        foreach (KMSelectable selectable in page.Children)
        {
            if (selectable != null)
            {
                selectable.Parent    = RootSelectable;
                selectable.OnCancel += OnCancel;
                selectable.Reproxy();
            }
        }
        page.gameObject.SetActive(true);

        RootSelectable.Reproxy();

        if (RootSelectable.DefaultSelectableIndex >= 0 && RootSelectable.DefaultSelectableIndex < RootSelectable.Children.Length)
        {
            RootSelectable.UpdateChildren(RootSelectable.Children[RootSelectable.DefaultSelectableIndex]);
        }
    }
Exemplo n.º 22
0
    void Start()
    {
        _moduleId = _moduleIdCounter++;
        var numbers = Enumerable.Range(0, 26).Where(i => i != 20).ToList(); // exclude “U” because that’s a valid command (u-turn = 180)

        for (int i = 0; i < 6; i++)
        {
            var ix = Rnd.Range(0, numbers.Count);
            _tpLetters[i]     = (char)('A' + numbers[ix]);
            TpLetters[i].text = _tpLetters[i].ToString();
            TpLetters[i].gameObject.SetActive(false);
            numbers.RemoveAt(ix);
        }

        for (int i = 0; i < 5; i++)
        {
            _selectableSymbolObjs[i] = SelectableBoxes[i].transform.Find("Symbol").GetComponent <MeshRenderer>();
            _selectableFrameObjs[i]  = SelectableBoxes[i].transform.Find("Frame").GetComponent <MeshRenderer>();
            _selectableScreenObjs[i] = SelectableBoxes[i].transform.Find("Screen").GetComponent <MeshRenderer>();
            _queues[i] = new Queue <RotateTask>();
            StartCoroutine(rotator(i));
        }
        for (int i = 0; i < 6; i++)
        {
            _placeableSymbolObjs[i] = PlaceableBoxes[i].transform.Find("Symbol").GetComponent <MeshRenderer>();
            _placeableFrameObjs[i]  = PlaceableBoxes[i].transform.Find("Frame").GetComponent <MeshRenderer>();
            _placeableScreenObjs[i] = PlaceableBoxes[i].transform.Find("Screen").GetComponent <MeshRenderer>();
        }

        for (int i = 0; i < 25; i++)
        {
            if (i % 5 != 0)
            {
                MainSelectable.Children[i] = null;
            }
        }

        // Generate the rules
        List <int> symbolIxs;
        var        rnd = RuleSeedable.GetRNG();

        Debug.LogFormat("[Pattern Cube #{0}] Using rule seed: {1}", _moduleId, rnd.Seed);

        string[] groupStrs = new string[2];
        if (rnd.Seed == 1)
        {
            groupStrs[0] =
                "X1,A3,B1;Y0,X1,A1;B0,D1,C2;Z1,A2,X0;Y2,B0,A2;Y3,C1,B0;" +
                "X2,C0,A1;X1,Y2,B0;C2,A3,D1;Z1,X3,B1;A2,C3,Y2;D1,B2,Y0;" +
                "X2,C2,B1;X1,A2,D2;X2,C3,Y0;D3,A0,B3;X0,Z2,C1;A0,Y3,D0;" +
                "D0,B0,X0;X1,C1,D0;Y0,D0,X3;C3,B3,A1;Z1,D0,X0;C1,D0,Y2";
            groupStrs[1] =
                "X1,E0,F0;X0,E3,Y1;H1,G1,F1;Y3,Z3,E1;Z3,F1,E2;G1,Z1,F1;" +
                "E0,X2,G1;X0,F0,Y2;G1,E2,H3;F1,Y2,Z0;G2,E2,Z1;F1,Z1,H2;" +
                "G1,X1,F0;H3,X2,E2;Y1,X3,G3;H1,E3,F0;G0,Z2,Y0;Z0,H2,E3;" +
                "X3,H1,F0;G1,H3,X0;X3,H3,Y0;E0,F0,G1;Z3,Y3,H1;Z2,H3,G2";
            symbolIxs = new List <int> {
                90, 91, 92, 93, 100, 101, 102, 103, 110, 111, 112
            };
        }
        else
        {
            var skip = rnd.Next(0, 100);
            for (var i = 0; i < skip; i++)
            {
                rnd.NextDouble();
            }

            symbolIxs = Enumerable.Range(0, 120).ToList();
            rnd.ShuffleFisherYates(symbolIxs);
            var groupsTemplates = new[] {
                "ABX,AXY,BCD,AXZ,ABY,BCY,ACX,BXY,ACD,BXZ,ACY,BDY,BCX,ADX,CXY,ABD,CXZ,ADY,BDX,CDX,DXY,ABC,DXZ,CDY",
                "EFX,EXY,FGH,EYZ,EFZ,FGZ,EGX,FXY,EGH,FYZ,EGZ,FHZ,FGX,EHX,GXY,EFH,GYZ,EHZ,FHX,GHX,HXY,EFG,HYZ,GHZ"
            };
            for (var i = 0; i < 2; i++)
            {
                var grs = groupsTemplates[i].Split(',');
                var arr = new List <string>();
                for (var j = 0; j < grs.Length; j++)
                {
                    var smbs = grs[j].Select(ch => ch.ToString()).ToList();
                    rnd.ShuffleFisherYates(smbs);
                    for (var k = 0; k < smbs.Count; k++)
                    {
                        smbs[k] = smbs[k] + rnd.Next(0, 4);
                    }
                    arr.Add(smbs.JoinString(","));
                }
                groupStrs[i] = arr.JoinString(";");
            }
        }

        HalfCube[][] groups = groupStrs.Select(str => str.Split(';').Select(hci => hci.Split(',').Select(fc => new FaceSymbol(fc[0], fc[1] - '0')).ToArray()).Select(arr => new HalfCube(arr[0], arr[1], arr[2])).ToArray()).ToArray();

        // Generate a puzzle
        _puzzle = Data.Nets[Rnd.Range(0, Data.Nets.Length)];
        HalfCube[] frontHalfCubes, backHalfCubes;
        if (Rnd.Range(0, 2) == 0)
        {
            frontHalfCubes = groups[0];
            backHalfCubes  = groups[1];
        }
        else
        {
            frontHalfCubes = groups[1];
            backHalfCubes  = groups[0];
        }
        var        frontHalfCube = frontHalfCubes[Rnd.Range(0, frontHalfCubes.Length)];
        var        symbolsAlready = new[] { frontHalfCube.Top.Symbol, frontHalfCube.Left.Symbol, frontHalfCube.Front.Symbol };
        var        backHalfCubeCandidates = backHalfCubes.Where(ag => !new[] { ag.Top.Symbol, ag.Left.Symbol, ag.Front.Symbol }.Intersect(symbolsAlready).Any()).ToArray();
        var        backHalfCube = backHalfCubeCandidates[Rnd.Range(0, backHalfCubeCandidates.Length)];
        FaceSymbol right, back, bottom;

        switch (Rnd.Range(0, 3))
        {
        case 0:
            back   = new FaceSymbol(backHalfCube.Front.Symbol, (backHalfCube.Front.Orientation + 3) % 4);
            right  = new FaceSymbol(backHalfCube.Top.Symbol, (backHalfCube.Top.Orientation + 3) % 4);
            bottom = new FaceSymbol(backHalfCube.Left.Symbol, (backHalfCube.Left.Orientation + 3) % 4);
            break;

        case 1:
            back   = new FaceSymbol(backHalfCube.Top.Symbol, backHalfCube.Top.Orientation);
            right  = new FaceSymbol(backHalfCube.Left.Symbol, (backHalfCube.Left.Orientation + 1) % 4);
            bottom = new FaceSymbol(backHalfCube.Front.Symbol, backHalfCube.Front.Orientation);
            break;

        default:
            back   = new FaceSymbol(backHalfCube.Left.Symbol, (backHalfCube.Left.Orientation + 2) % 4);
            right  = new FaceSymbol(backHalfCube.Front.Symbol, (backHalfCube.Front.Orientation + 2) % 4);
            bottom = new FaceSymbol(backHalfCube.Top.Symbol, (backHalfCube.Top.Orientation + 1) % 4);
            break;
        }
        _faceGivenByHighlight = Rnd.Range(0, 6);
        var faceGivenFully = (new[] { 0, 1, 4 }.Contains(_faceGivenByHighlight) ? new[] { 2, 3, 5 } : new[] { 0, 1, 4 })[Rnd.Range(0, 3)];

        _facesRevealed.Add(faceGivenFully);
        _solution          = new[] { frontHalfCube.Top, frontHalfCube.Front, right, back, frontHalfCube.Left, bottom };
        _selectableSymbols = _solution.Except(new[] { _solution[faceGivenFully] }).ToArray().Shuffle();
        for (int i = 0; i < _selectableSymbols.Length; i++)
        {
            _selectableSymbols[i] = new FaceSymbol(_selectableSymbols[i].Symbol, Rnd.Range(0, 4));
            if (_selectableSymbols[i].Symbol == _solution[_faceGivenByHighlight].Symbol)
            {
                _highlightedPosition = i;
            }
        }

        // Populate the selectable boxes
        for (int i = 0; i < 5; i++)
        {
            _selectableSymbolObjs[i].material.mainTexture       = SymbolTextures[symbolIxs["ABCDEFGHXYZ".IndexOf(_selectableSymbols[i].Symbol)]];
            _selectableSymbolObjs[i].transform.localEulerAngles = new Vector3(90, _selectableSymbols[i].Orientation * 90, 0);
            _selectableFrameObjs[i].material  = FrameRed;
            _selectableScreenObjs[i].material = _selectableSymbols[i].Symbol == _solution[_faceGivenByHighlight].Symbol ? ScreenLight : ScreenDark;
            SelectableBoxes[i].OnInteract     = GetSelectableHandler(i);
        }

        // Arrange the placeable boxes
        const float x1 = -.8f;
        const float x2 = .8f;
        const float y1 = -.8f;
        const float y2 = .8f;
        const float w = (x2 - x1) / 5.5f;
        const float h = (y2 - y1) / 5.5f;

        for (int y = 0; y < _puzzle.Faces.GetLength(1); y++)
        {
            for (int x = 0; x < _puzzle.Faces.GetLength(0); x++)
            {
                if (_puzzle.Faces[x, y] == null)
                {
                    continue;
                }
                var fi = _puzzle.Faces[x, y];
                _placeableSymbolObjs[fi.Face].transform.localEulerAngles = new Vector3(90, (fi.Orientation + _solution[fi.Face].Orientation) * 90, 0);
                _placeableSymbolObjs[fi.Face].material.mainTexture       = SymbolTextures[symbolIxs["ABCDEFGHXYZ".IndexOf(_solution[fi.Face].Symbol)]];
                _placeableSymbolObjs[fi.Face].gameObject.SetActive(fi.Face == faceGivenFully);
                _placeableFrameObjs[fi.Face].material           = fi.Face == faceGivenFully ? FrameGreen : FrameYellow;
                _placeableScreenObjs[fi.Face].material          = fi.Face == _faceGivenByHighlight ? ScreenLight : ScreenDark;
                PlaceableBoxes[fi.Face].transform.localPosition = new Vector3(x1 + w * (x + 2), 0, y1 + h * (_puzzle.Faces.GetLength(1) - y - .5f)) * .1f;
                PlaceableBoxes[fi.Face].OnInteract = GetPlaceableHandler(fi);
                MainSelectable.Children[(5 - _puzzle.Faces.GetLength(1) + y) * 5 + x + 1] = PlaceableBoxes[fi.Face];
            }
        }

        MainSelectable.UpdateChildren(SelectableBoxes[0]);

        // Set the correct mesh for the module front
        var id = "ModuleFront_" + _puzzle.ID;

        ModuleFront.mesh = NetMeshes.First(m => m.name == id);

        Log(@"=svg[Puzzle:]<svg xmlns='http://www.w3.org/2000/svg' viewBox='-3 -3 1206 {0}'>{1}</svg>",
            /* {0} */ 120 * _puzzle.Faces.GetLength(1) + 6,
            /* {1} */ Enumerable.Range(0, _puzzle.Faces.GetLength(1)).SelectMany(y => Enumerable.Range(0, _puzzle.Faces.GetLength(0)).Select(x =>
                                                                                                                                             _puzzle.Faces[x, y] == null ? null :
                                                                                                                                             _puzzle.Faces[x, y].Face == faceGivenFully ? svg(x, y, symbolIxs["ABCDEFGHXYZ".IndexOf(_solution[_puzzle.Faces[x, y].Face].Symbol)], (_solution[_puzzle.Faces[x, y].Face].Orientation + _puzzle.Faces[x, y].Orientation) % 4) :
                                                                                                                                             svg(x, y, highlighted: _puzzle.Faces[x, y].Face == _faceGivenByHighlight))).JoinString());

        Log(@"=svg[Symbols:]<svg xmlns='http://www.w3.org/2000/svg' viewBox='-3 -3 1206 126'>{0}</svg>",
            _selectableSymbols.Select((s, ix) => svgPath(ix, 0, symbolIxs["ABCDEFGHXYZ".IndexOf(s.Symbol)], 0)).JoinString());
        Log(@" The highlighted symbol is {0}.", "first,second,third,4th,5th".Split(',')[_highlightedPosition]);

        Log(@"=svg[Solution:]<svg xmlns='http://www.w3.org/2000/svg' viewBox='-3 -3 1206 {0}'>{1}</svg>",
            /* {0} */ 120 * _puzzle.Faces.GetLength(1) + 6,
            /* {1} */ Enumerable.Range(0, _puzzle.Faces.GetLength(1)).SelectMany(y => Enumerable.Range(0, _puzzle.Faces.GetLength(0)).Select(x =>
                                                                                                                                             _puzzle.Faces[x, y] == null ? null :
                                                                                                                                             svg(x, y, symbolIxs["ABCDEFGHXYZ".IndexOf(_solution[_puzzle.Faces[x, y].Face].Symbol)], (_solution[_puzzle.Faces[x, y].Face].Orientation + _puzzle.Faces[x, y].Orientation) % 4))).JoinString());

        AssignSymbols();
        // Because TP doesn’t set TwitchPlaysActive soon enough, we have to delay the TP letter initialization
        Module.OnActivate += delegate { AssignSymbols(); };
    }
Exemplo n.º 23
0
    // Use this for initialization
    void Start()
    {
        modID = modIdCounter++;
        needySelf.OnNeedyActivation += delegate
        {
            if (!permDeactivate)
            {
                isActive    = true;
                blockLifter = HandleHeightManagment();
                timeManager = ModifyNeedyTimer();
                StartCoroutine(blockLifter);
                StartCoroutine(timeManager);
                interactable = true;
            }
            else
            {
                needySelf.HandlePass();
            }
        };
        allSelectablesDefault         = new List <KMSelectable>(); // Mainly for compacting lines, required for usage otherwise.
        allSelectablesDuringAnimation = new List <KMSelectable>();
        for (int i = 0; i < rowRenderersWithSelectables.Length; i++)
        {
            RowRendererPlus rowRenderer = rowRenderersWithSelectables[i];
            allSelectablesDefault.AddRange(rowRenderer.rowSelectables);
            if (i != 14)
            {
                allSelectablesDuringAnimation.AddRange(rowRenderer.rowSelectables);
            }
            startRowCoords.Add(rowRenderer.transform.localPosition);

            for (int x = 0; x < rowRenderer.rowSelectables.Length; x++)
            {
                int tRow = x, tCol = i;
                rowRenderer.rowSelectables[x].OnInteract += delegate {
                    rowRenderer.rowSelectables[tRow].AddInteractionPunch(0.1f);
                    mAudio.PlaySoundAtTransform("tick", rowRenderer.rowSelectables[tRow].transform);
                    if (isActive && interactable)
                    {
                        ProcessTile(tRow, tCol);
                    }
                    return(false);
                };
            }
        }
        bombInfo.OnBombExploded += delegate {
            if (!permDeactivate)
            {
                QuickLog("Board upon detonation: ");
                LogBoard();
            }
        };

        modSelfSelectable.Children = allSelectablesDefault.ToArray();
        modSelfSelectable.UpdateChildren(); // Required for gamepad usage and updating.
        StartCoroutine(delayRotation());
        needySelf.OnNeedyDeactivation += delegate {
            isActive = false;
            if (!permDeactivate)
            {
                QuickLog("Board upon deactivation: ");
                LogBoard();
            }
        };
        UpdateGrid();
        rowRenderersNextSet.transform.localPosition = new Vector3(0, 0, -6.5f);
        rowRenderersNextSet.transform.localScale    = new Vector3(1, 1, 0);
        rowRenderersNextSet.gameObject.SetActive(false);
        colorIdxSet.Shuffle();
    }
Exemplo n.º 24
0
    void Generate2x2Empty()
    {
        symbolCenterIdxes = new List <int>();
        symbolMetadata    = new List <string>();
        var allSelectables = new List <KMSelectable>()
        {
            btnBase
        };
        var offsetValues = new[] { -1f, 0, 1f };

        for (int x = 0; x < 3; x++)
        {
            for (int y = 0; y < 3; y++)
            {
                if (x == 0 && y == 0)
                {
                    continue;
                }
                var clonedObject = Instantiate(btnBase);
                clonedObject.transform.parent               = btnsContainer;
                clonedObject.name                           = btnBase.name + "(" + (3 * x + y).ToString() + ")";
                clonedObject.transform.localPosition        = new Vector3(offsetValues[y], 0, offsetValues[x]);
                clonedObject.transform.localScale           = btnBase.transform.localScale;
                clonedObject.Highlight.transform.localScale = btnBase.Highlight.transform.localScale;
                allSelectables.Add(clonedObject.GetComponent <KMSelectable>());
            }
        }
        selfSelectable.Children = allSelectables.ToArray();
        selfSelectable.UpdateChildren();

        startIdx = 6;
        endIdx   = 2;
        startLineRenderer.SetPositions(Enumerable.Repeat(new Vector3(offsetValues[startIdx % 3], offsetValues[startIdx / 3], 0), 2).ToArray());
        lineCenterTraceRenderer.SetPositions(Enumerable.Repeat(new Vector3(offsetValues[startIdx % 3], offsetValues[startIdx / 3], 0), 2).ToArray());
        var modifiedEndPoints = Enumerable.Repeat(new Vector3(offsetValues[endIdx % 3], offsetValues[endIdx / 3], 0), 2).ToArray();

        for (var x = 0; x < modifiedEndPoints.Length; x++)
        {
            modifiedEndPoints[x] += x == 0 ? Vector3.zero : (Vector3.right + Vector3.down) * 0.25f;
        }
        endLineRenderer.SetPositions(modifiedEndPoints);
        // Assign Selectables;
        for (var x = 0; x < allSelectables.Count; x++)
        {
            int y = x;
            allSelectables[x].OnInteract += delegate {
                if (interactable)
                {
                    mAudio.PlayGameSoundAtTransform(KMSoundOverride.SoundEffect.ButtonPress, allSelectables[y].transform);
                    if (y == startIdx && !curPathDrawn.Any())
                    {
                        curPathDrawn.Add(y);
                    }
                    else if (curPathDrawn.Any() && curPathDrawn.Last() == endIdx)
                    {
                        if (possibleValidPaths.Any(a => a.SequenceEqual(curPathDrawn)))
                        {
                            QuickLogFormat("The drawn path [{0}] is one of the provided solutions. Module disarmed.", curPathDrawn.Select(a => a + 1).Join(","));
                            modSelf.HandlePass();
                            StartCoroutine(AnimateSolve());
                            mAudio.PlaySoundAtTransform("disarmed", transform);
                            interactable = false;
                            return(false);
                        }
                        else
                        {
                            QuickLogFormat("The drawn path [{0}] is not one of the provided solutions. Does it meet the symbol rules?", curPathDrawn.Select(a => a + 1).Join(","));
                            if (CheckPath(possiblePath: curPathDrawn, logStatus: true))
                            {
                                QuickLog("The answer is yes. Module disarmed.");
                                modSelf.HandlePass();
                                StartCoroutine(AnimateSolve());
                                mAudio.PlaySoundAtTransform("disarmed", transform);
                                interactable = false;
                            }
                            else
                            {
                                modSelf.HandleStrike();
                                curPathDrawn.Clear();
                            }
                            return(false);
                        }
                    }
                    else if (curPathDrawn.Any())
                    {
                        curPathDrawn.Clear();
                    }
                    UpdateLine();
                }
                return(false);
            };
            allSelectables[x].OnHighlight += delegate {
                if (interactable)
                {
                    if (curPathDrawn.Contains(startIdx))
                    {
                        if (!curPathDrawn.Contains(y))
                        {
                            var lastSpotX = curPathDrawn.LastOrDefault() % 3;
                            var lastSpotY = curPathDrawn.LastOrDefault() / 3;
                            var hlSpotX   = y % 3;
                            var hlSpotY   = y / 3;
                            var deltaModifierChecksAdjacent = new Dictionary <int, bool>()
                            {
                                { -1, lastSpotX > 0 },
                                { 1, lastSpotX < 2 },
                                { -3, lastSpotY > 0 },
                                { 3, lastSpotY < 2 },
                            };
                            var passChecksAdjacent = false;
                            foreach (KeyValuePair <int, bool> deltaModifier in deltaModifierChecksAdjacent)
                            {
                                passChecksAdjacent |= deltaModifier.Value && y - curPathDrawn.LastOrDefault() == deltaModifier.Key;
                            }
                            if (passChecksAdjacent)
                            {
                                curPathDrawn.Add(y);
                            }
                        }
                        else if (curPathDrawn.Count > 1 && curPathDrawn.ElementAt(curPathDrawn.Count - 2) == y)
                        {
                            curPathDrawn.RemoveAt(curPathDrawn.Count - 1);
                        }
                    }
                    UpdateLine();
                }
            };
        }
        StartCoroutine(GeneratePuzzle());
    }
    void Start()
    {
        _moduleId = _moduleIdCounter++;
        _all      = new[] { Rock, Paper, Scissors, Lizard, Spock };
        var names = "Rock,Paper,Scissors,Lizard,Spock".Split(',');

        for (int i = 0; i < 5; i++)
        {
            _all[i].OnInteract += GetButtonPressHandler(i, _all[i], names[i]);
        }

        // Now shuffle them randomly
        for (int i = 4; i > 0; i--)
        {
            var ix = Rnd.Range(0, i);
            var t  = _all[ix];
            _all[ix] = _all[i];
            _all[i]  = t;
        }

        // Choose one of the possible arrangements
        int?[] children = null;
        switch (Rnd.Range(0, 10))
        {
        case 0:     // pentagon
            for (int i = 0; i < 5; i++)
            {
                _all[i].transform.LocalTranslate(new Vector3((float)(.055 * Math.Sin(Math.PI / 5 * 2 * i)), 0, (float)(-.055 * Math.Cos(Math.PI / 5 * 2 * i))));
            }
            _decoy   = null;
            children = new int?[] { 1, 0, 4, 2, 2, 3 };
            break;

        case 1:     // in two rows
            for (int i = 0; i < 5; i++)
            {
                _all[i].transform.LocalTranslate(new Vector3((i < 2 ? i : i - 3) * .055f, 0, (i < 2 ? -.035f : .035f)));
            }
            _decoy   = _all[3];
            children = new int?[] { 1, 0, null, 4, 3, 2 };
            break;

        case 2:     // in two columns
            for (int i = 0; i < 5; i++)
            {
                _all[i].transform.LocalTranslate(new Vector3((i < 2 ? -.035f : .035f), 0, (i < 2 ? i : i - 3) * .055f));
            }
            _decoy   = _all[3];
            children = new int?[] { 2, null, null, 3, 0, null, 4, 1, null };
            break;

        case 3:     // X, bottom
            for (int i = 0; i < 5; i++)
            {
                _all[i].transform.LocalTranslate(new Vector3(.055f * (2 * i % 3 - 1), 0, .035f * (2 * i / 3 - 1) + .015f));
            }
            _decoy   = _all[2];
            children = new int?[] { 1, 2, 0, 4, 2, 3 };
            break;

        case 4:     // X, left
            for (int i = 0; i < 5; i++)
            {
                _all[i].transform.LocalTranslate(new Vector3(.035f * (2 * i % 3 - 1) + .02f, 0, .055f * (2 * i / 3 - 1)));
            }
            _decoy   = _all[2];
            children = new int?[] { 1, 0, null, 2, 2, null, 4, 3, null };
            break;

        case 5:     // quarter circle with a bottom-left pivot
            for (int i = 0; i < 4; i++)
            {
                _all[i].transform.LocalTranslate(new Vector3((float)(-.07 * Math.Sin(Math.PI * (i * .25 - .125)) + .02), 0, (float)(-.07 * Math.Cos(Math.PI * (i * .25 - .125)) + .02)));
            }
            _all[4].transform.LocalTranslate(new Vector3(.02f, 0, .02f));
            _decoy   = _all[4];
            children = new int?[] { 0, 1, null, 4, 4, 2, 4, 4, 3 };
            break;

        case 6:     // quarter circle with a top-right pivot
            for (int i = 0; i < 4; i++)
            {
                _all[i].transform.LocalTranslate(new Vector3((float)(.07 * Math.Sin(Math.PI * (i * .25 - .125)) - .02), 0, (float)(.07 * Math.Cos(Math.PI * (i * .25 - .125)) - .02)));
            }
            _all[4].transform.LocalTranslate(new Vector3(-.02f, 0, -.02f));
            _decoy   = _all[4];
            children = new int?[] { 3, 4, 4, 2, 4, 4, null, 1, 0 };
            break;

        case 7:     // +
            _all[0].transform.LocalTranslate(new Vector3(.055f, 0, 0));
            _all[1].transform.LocalTranslate(new Vector3(0, 0, .055f));
            _all[2].transform.LocalTranslate(new Vector3(-.055f, 0, 0));
            _all[3].transform.LocalTranslate(new Vector3(0, 0, -.055f));
            _decoy   = _all[4];
            children = new int?[] { null, 3, null, 0, 4, 2, null, 1, null };
            break;

        case 8:     // Z
            _all[0].transform.LocalTranslate(new Vector3(.055f, 0, -.055f));
            _all[1].transform.LocalTranslate(new Vector3(0, 0, .055f));
            _all[2].transform.LocalTranslate(new Vector3(-.055f, 0, .055f));
            _all[3].transform.LocalTranslate(new Vector3(0, 0, -.055f));
            _decoy   = _all[4];
            children = new int?[] { 0, 3, null, null, 4, null, null, 1, 2 };
            break;

        case 9:     // S
            _all[0].transform.LocalTranslate(new Vector3(.055f, 0, -.0275f));
            _all[1].transform.LocalTranslate(new Vector3(0, 0, .055f));
            _all[2].transform.LocalTranslate(new Vector3(-.055f, 0, .0275f));
            _all[3].transform.LocalTranslate(new Vector3(0, 0, -.055f));
            _decoy   = _all[4];
            children = new int?[] { 0, 3, null, 0, 4, 2, null, 1, 2 };
            break;
        }

        if (_decoy != null)
        {
            Debug.LogFormat("[Rock-Paper-Scissors-Lizard-Spock #{0}] Decoy is {1}.", _moduleId, _names[Array.IndexOf(new[] { Rock, Paper, Scissors, Lizard, Spock }, _decoy)]);
        }
        else
        {
            Debug.LogFormat("[Rock-Paper-Scissors-Lizard-Spock #{0}] There is no decoy.", _moduleId);
        }

        MainSelectable.Children = children.Select(nint => nint == null ? null : _all[nint.Value].GetComponent <KMSelectable>()).ToArray();
        MainSelectable.UpdateChildren();

        // So much for arranging the signs on the module. Now for generating the rules!
        var rnd = RuleSeedable.GetRNG();

        Debug.LogFormat("[Rock-Paper-Scissors-Lizard-Spock #{0}] Using rule seed: {1}", _moduleId, rnd.Seed);

        var letters = "SYHREAGCUPMZKNBJQDFLXVWIOT".OrderBy(ch => rnd.NextDouble()).ToArray();
        var ports = new[] { Port.RJ45, Port.StereoRCA, Port.DVI, Port.Parallel, Port.Serial, Port.PS2 }.OrderBy(port => rnd.NextDouble()).ToArray();
        var litIndicators = new[] { "IND", "TRN", "SIG", "CAR", "NSA", "FRK", "CLR", "MSA", "SND", "FRQ", "BOB" }.OrderBy(ind => rnd.NextDouble()).ToArray();
        var unlitIndicators = new[] { "CLR", "CAR", "FRQ", "IND", "MSA", "NSA", "TRN", "SIG", "SND", "BOB", "FRK" }.OrderBy(ind => rnd.NextDouble()).ToArray();
        var digits = "9574831602".OrderBy(ch => rnd.NextDouble()).ToArray();

        var serial = Bomb.GetSerialNumber();
        var decoy  = Array.IndexOf(new[] { Rock, Paper, Scissors, Lizard, Spock }, _decoy);

        var scores = newArray(
            // ports
            Bomb.GetPortCount(ports[0]) > 0 ? null : newArray(
                /* Rock */ Bomb.GetPortCount(ports[1]),
                /* Paper */ Bomb.GetPortCount(ports[2]),
                /* Scissors */ Bomb.GetPortCount(ports[3]),
                /* Lizard */ Bomb.GetPortCount(ports[4]),
                /* Spock */ Bomb.GetPortCount(ports[5])
                ),

            // serial number digits
            newArray(
                /* Rock */ serial.Count(c => c == digits[0] || c == digits[1]),
                /* Paper */ serial.Count(c => c == digits[2] || c == digits[3]),
                /* Scissors */ serial.Count(c => c == digits[4] || c == digits[5]),
                /* Lizard */ serial.Count(c => c == digits[6] || c == digits[7]),
                /* Spock */ serial.Count(c => c == digits[8] || c == digits[9])
                ),

            // unlit indicators
            Bomb.IsIndicatorOff(unlitIndicators[0]) ? null : newArray(
                /* Rock */ Bomb.GetOffIndicators().Count(i => i == unlitIndicators[1] || i == unlitIndicators[2]),
                /* Paper */ Bomb.GetOffIndicators().Count(i => i == unlitIndicators[3] || i == unlitIndicators[4]),
                /* Scissors */ Bomb.GetOffIndicators().Count(i => i == unlitIndicators[5] || i == unlitIndicators[6]),
                /* Lizard */ Bomb.GetOffIndicators().Count(i => i == unlitIndicators[7] || i == unlitIndicators[8]),
                /* Spock */ Bomb.GetOffIndicators().Count(i => i == unlitIndicators[9] || i == unlitIndicators[10])
                ),

            // serial number letters
            serial.Contains(letters[0]) || serial.Contains(letters[1]) ? null : newArray(
                /* Rock */ serial.Count(c => c == letters[2] || c == letters[3]),
                /* Paper */ serial.Count(c => c == letters[4] || c == letters[5]),
                /* Scissors */ serial.Count(c => c == letters[6] || c == letters[7]),
                /* Lizard */ serial.Count(c => c == letters[8] || c == letters[9]),
                /* Spock */ serial.Count(c => c == letters[10] || c == letters[11])
                ),

            // lit indicators
            Bomb.IsIndicatorOn(litIndicators[0]) ? null : newArray(
                /* Rock */ Bomb.GetOnIndicators().Count(i => i == litIndicators[1] || i == litIndicators[2]),
                /* Paper */ Bomb.GetOnIndicators().Count(i => i == litIndicators[3] || i == litIndicators[4]),
                /* Scissors */ Bomb.GetOnIndicators().Count(i => i == litIndicators[5] || i == litIndicators[6]),
                /* Lizard */ Bomb.GetOnIndicators().Count(i => i == litIndicators[7] || i == litIndicators[8]),
                /* Spock */ Bomb.GetOnIndicators().Count(i => i == litIndicators[9] || i == litIndicators[10])
                )
            )
                     .OrderBy(row => rnd.NextDouble()).ToArray();

        var result = scores
                     .Select((row, ix) => row == null ? null : row.Max().Apply(maxScore => new { Row = ix, Winners = row.SelectIndexWhere(sc => sc == maxScore).ToArray() }))
                     .Where(inf => inf != null && inf.Winners.Length == 1 && inf.Winners[0] != decoy)
                     .FirstOrDefault();

        if (result != null)
        {
            Debug.LogFormat("[Rock-Paper-Scissors-Lizard-Spock #{2}] {0} wins on account of Row #{1}.", _names[result.Winners[0]], result.Row + 1, _moduleId);

            switch (result.Winners[0])
            {
            case 0: _mustPress = new[] { 1, 4 }; break;

            case 1: _mustPress = new[] { 2, 3 }; break;

            case 2: _mustPress = new[] { 0, 4 }; break;

            case 3: _mustPress = new[] { 0, 2 }; break;

            default: _mustPress = new[] { 1, 3 }; break;
            }
        }
        else
        {
            Debug.LogFormat("[Rock-Paper-Scissors-Lizard-Spock #{1}] No winner{0}.", decoy == -1 ? " and no decoy" : null, _moduleId);
            _mustPress = Enumerable.Range(0, 5).Where(i => i != decoy).ToArray();
        }

        Debug.LogFormat("[Rock-Paper-Scissors-Lizard-Spock #{1}] Must press: {0}", string.Join(", ", _mustPress.Select(m => _names[m]).ToArray()), _moduleId);
    }
Exemplo n.º 26
0
    void Start()
    {
        _moduleId = _moduleIdCounter++;


        // STEP 1: DECIDE WHICH WIRES SKIP WHICH PLUGS
        _wireInfos = new List <WireInfo>();
        var currentPeg = 0;

        do
        {
            // Randomly skip a peg about 25% of the time, but we have to
            // go back to peg #0 if we’re on peg #11. Also, we want at least
            // 8 wires, so we need to stop skipping if we don’t have enough wires.
            var skip    = currentPeg >= 11 || currentPeg >= _wireInfos.Count + 4 ? false : Rnd.Range(0, 4) == 0;
            var nextPeg = (currentPeg + (skip ? 2 : 1)) % 12;
            _wireInfos.Add(new WireInfo
            {
                ConnectedFrom = currentPeg + 1,
                ConnectedTo   = nextPeg + 1,
                WireColor     = (WireColor)Rnd.Range(0, 6)
            });
            currentPeg = nextPeg;
        }while (currentPeg != 0);

        // Since the above will never skip peg #0, rotate the arrangement by a random amount
        // so that all pegs have equal chances of being skipped.
        var rotation = Rnd.Range(0, 12);

        for (int i = 0; i < _wireInfos.Count; i++)
        {
            _wireInfos[i].ConnectedFrom = (_wireInfos[i].ConnectedFrom + rotation - 1) % 12 + 1;
            _wireInfos[i].ConnectedTo   = (_wireInfos[i].ConnectedTo + rotation - 1) % 12 + 1;
        }

        // Disable all the wires
        foreach (var skip in new[] { false, true })
        {
            for (int from = 0; from < 12; from++)
            {
                Module.transform.Find(string.Format("Wire {0}-to-{1}", from + 1, (from + (skip ? 2 : 1)) % 12 + 1)).gameObject.SetActive(false);
            }
        }

        // Re-enable the wires we need and set up their click handler and color-blind mode
        _colorblind = ColorblindMode.ColorblindModeActive;
        for (int i = 0; i < _wireInfos.Count; i++)
        {
            _wireInfos[i].Activate(Module.transform.Find(string.Format("Wire {0}-to-{1}", _wireInfos[i].ConnectedFrom, _wireInfos[i].ConnectedTo)), this, TextTemplObj, _colorblind);
        }

        Selectable.Children       = _wireInfos.OrderBy(wi => wi.ConnectedFrom).Select(wi => wi.Selectable).ToArray();
        Selectable.ChildRowLength = Selectable.Children.Length;
        Selectable.UpdateChildren();


        // STEP 2: GENERATE THE RULES (KMRuleSeedable)
        var rnd = RuleSeedable.GetRNG();

        Debug.LogFormat(@"[Follow the Leader #{0}] Using rule seed: {1}", _moduleId, rnd.Seed);

        var ports        = new[] { Port.Parallel, Port.Serial, Port.RJ45, Port.PS2, Port.DVI, Port.StereoRCA };
        var hasRule1Port = Bomb.IsPortPresent(ports[rnd.Next(0, ports.Length)]);

        var snLetters = Bomb.GetSerialNumberLetters().ToArray();
        var snDigits  = Bomb.GetSerialNumberNumbers().ToArray();
        var startingPlugConditions = Ex.NewArray(
            Bomb.GetIndicators().Count(),
            Bomb.GetOnIndicators().Count(),
            Bomb.GetOffIndicators().Count(),
            Bomb.GetBatteryCount(),
            Bomb.GetBatteryHolderCount(),
            Bomb.GetBatteryCount(Battery.AA) + Bomb.GetBatteryCount(Battery.AAx3) + Bomb.GetBatteryCount(Battery.AAx4),
            Bomb.GetBatteryCount(Battery.D),
            Bomb.GetPortCount(),
            Bomb.GetPortPlateCount(),
            Bomb.CountUniquePorts(),
            Bomb.GetModuleNames().Count,
            Bomb.GetSolvableModuleNames().Count,
            snLetters[0] - 'A' + 1,
            snLetters[1] - 'A' + 1,
            snLetters[snLetters.Length - 1] - 'A' + 1,
            snLetters[snLetters.Length - 2] - 'A' + 1,
            snDigits[snDigits.Length - 1],
            snDigits[1],
            snDigits[0]);

        var rule2ConditionIx = rnd.Next(0, startingPlugConditions.Length);
        var rule3ConditionIx = rnd.Next(0, startingPlugConditions.Length - 1);

        if (rule3ConditionIx >= rule2ConditionIx)
        {
            rule3ConditionIx++;
        }
        var rule2Plug = startingPlugConditions[rule2ConditionIx];
        var rule3Plug = startingPlugConditions[rule3ConditionIx];

        var rule1StartPlug    = rnd.Next(1, 13);
        var rule4Indicator    = _rule4Indicators[rnd.Next(0, _rule4Indicators.Length)];
        var rule1EndPlug      = (rnd.Next(rule1StartPlug + 1, rule1StartPlug + 3) - 1) % 12 + 1;
        var hasRule4Indicator = rnd.Next(0, 2) != 0 ? Bomb.IsIndicatorOn(rule4Indicator) : Bomb.IsIndicatorOff(rule4Indicator);

        var rule5StartAt = (rnd.Next(0, 12) + 5) % 12;  // Starting wire is at plug this +1, or +2 if the +1 doesn’t have a wire

        var startingLetters = Ex.NewArray(
            Bomb.GetIndicators().SelectMany(s => s).DefaultIfEmpty().Min(),
            Bomb.GetIndicators().SelectMany(s => s).DefaultIfEmpty().Max(),
            snLetters[1],
            snLetters[snLetters.Length - 2],
            snLetters[snLetters.Length - 1],
            snLetters[0]);
        var startingLetter = startingLetters[rnd.Next(0, startingLetters.Length)];
        var fallbackLetter = (char)('A' + (rnd.Next(0, 26) + 17) % 26);

        if (startingLetter == '\0')
        {
            startingLetter = fallbackLetter;
        }

        var colors = new[] { WireColor.Red, WireColor.Green, WireColor.Blue, WireColor.White, WireColor.Black, WireColor.Yellow };

        rnd.ShuffleFisherYates(colors);
        var useReverseIf = colors.Take(3).ToArray();

        var rules = new List <RuleInfo>();

        if (rnd.Seed == 1)
        {
            rules.Add(((MakeColorRule)_tableRules[35])("A or N", new[] { WireColor.Yellow, WireColor.Blue, WireColor.Green }));
            rules.Add(((MakeSimpleRule)_tableRules[2])("B or O"));
            rules.Add(((MakeSimpleRule)_tableRules[6])("C or P"));
            rules.Add(((MakeColorRule)_tableRules[34])("D or Q", new[] { WireColor.Red, WireColor.Blue, WireColor.Black }));
            rules.Add(((MakeSimpleRule)_tableRules[10])("E or R"));
            rules.Add(((MakeSimpleRule)_tableRules[16])("F or S"));
            rules.Add(((MakeColorRule)_tableRules[34])("G or T", new[] { WireColor.Yellow, WireColor.White, WireColor.Green }));
            rules.Add(((MakeSimpleRule)_tableRules[7])("H or U"));
            rules.Add(((MakeSimpleRule)_tableRules[21])("I or V"));
            rules.Add(((MakeColorRule)_tableRules[35])("J or W", new[] { WireColor.White, WireColor.Black, WireColor.Red }));
            rules.Add(((MakeSimpleRule)_tableRules[9])("K or X"));
            rules.Add(((MakeNumberRule12)_tableRules[29])("L or Y", 6));
            rules.Add(((MakeColorRule)_tableRules[41])("M or Z", new[] { WireColor.White, WireColor.Black }));
        }
        else
        {
            var tableRules = rnd.ShuffleFisherYates(_tableRules.ToArray());
            for (var i = 0; i < 13; i++)
            {
                var name = string.Format("{0} or {1}", (char)('A' + i), (char)('N' + i));
                if (tableRules[i] is MakeSimpleRule)
                {
                    rules.Add(((MakeSimpleRule)tableRules[i])(name));
                }
                else if (tableRules[i] is MakeNumberRule12)
                {
                    rules.Add(((MakeNumberRule12)tableRules[i])(name, rnd.Next(2, 12)));
                }
                else if (tableRules[i] is MakeNumberRule6)
                {
                    rules.Add(((MakeNumberRule6)tableRules[i])(name, rnd.Next(9, 12)));
                }
                else if (tableRules[i] is MakeColorRule)
                {
                    rnd.ShuffleFisherYates(colors);
                    rules.Add(((MakeColorRule)tableRules[i])(name, colors.ToArray()));  // important to take a copy of the array here so it doesn’t get re-shuffled
                }
            }
        }


        // STEP 3: DETERMINE WHICH WIRES NEED TO BE CUT

        // Figure out the starting wire (as index into wireInfos, rather than peg number)
        int startIndex;

        if (hasRule1Port && (startIndex = _wireInfos.IndexOf(wi => wi.ConnectedFrom == rule1StartPlug && wi.ConnectedTo == rule1EndPlug)) != -1)
        {
            Debug.LogFormat("[Follow the Leader #{0}] Starting at wire {1} because of rule 1.", _moduleId, _wireInfos[startIndex]);
        }
        else if ((startIndex = _wireInfos.IndexOf(wi => wi.ConnectedFrom == rule2Plug)) != -1)
        {
            Debug.LogFormat("[Follow the Leader #{0}] Starting at wire {1} because of rule 2.", _moduleId, _wireInfos[startIndex]);
        }
        else if ((startIndex = _wireInfos.IndexOf(wi => wi.ConnectedFrom == rule3Plug)) != -1)
        {
            Debug.LogFormat("[Follow the Leader #{0}] Starting at wire {1} because of rule 3.", _moduleId, _wireInfos[startIndex]);
        }
        else if (hasRule4Indicator)
        {
            Debug.LogFormat("[Follow the Leader #{0}] Cut everything in reverse order because of rule 4.", _moduleId);
            foreach (var wi in _wireInfos)
            {
                wi.Justification = "Rule 4.";
            }
            _expectedCuts = _wireInfos.OrderByDescending(w => w.ConnectedFrom).ToList();
            goto end;
        }
        else if ((startIndex = _wireInfos.IndexOf(wi => wi.ConnectedFrom == rule5StartAt + 1)) != -1)
        {
            Debug.LogFormat("[Follow the Leader #{0}] Starting at wire {1} because of rule 5.", _moduleId, _wireInfos[startIndex]);
        }
        else
        {
            startIndex = _wireInfos.IndexOf(wi => wi.ConnectedFrom == (rule5StartAt + 1) % 12 + 1);
            Debug.LogFormat("[Follow the Leader #{0}] Starting at wire {1} because of rule 5.", _moduleId, _wireInfos[startIndex]);
        }

        var curStep = (startingLetter - 'A') % rules.Count;
        var reverse = useReverseIf.Contains(_wireInfos[startIndex].WireColor);

        Debug.LogFormat("[Follow the Leader #{0}] Start at rule {1} and go {2}.", _moduleId, startingLetter, reverse ? "backwards" : "forwards");

        _expectedCuts = new List <WireInfo>();
        var wiresSinceStart = new List <WireInfo>();

        // Finally, determine which wires need cutting
        for (int i = 0; i < _wireInfos.Count; i++)
        {
            var curIndex = (i + startIndex) % _wireInfos.Count;
            var wire     = _wireInfos[curIndex];
            if (i == 0)
            {
                // Always cut the first one.
                wire.MustCut       = true;
                wire.Justification = "Cut because this is the starting wire.";
            }
            else
            {
                wire.MustCut       = rules[curStep].Evaluate(getWire, curIndex, _wireInfos.Count, wiresSinceStart);
                wire.Justification = string.Format("Rule {0}: {1} ⇒ {2}", rules[curStep].Name, rules[curStep].Phrasing, wire.MustCut ? "CUT" : "DON’T CUT");
                curStep            = (curStep + (reverse ? -1 : 1) + rules.Count) % rules.Count;
            }
            wiresSinceStart.Add(wire);
            if (wire.MustCut)
            {
                _expectedCuts.Add(wire);
            }
        }

        Debug.LogFormat("[Follow the Leader #{0}] Wire state:\n{1}", _moduleId, string.Join("\n", Enumerable.Range(0, _wireInfos.Count).Select(i => _wireInfos[(i + startIndex) % _wireInfos.Count].ToStringFull()).ToArray()));
end:
        Debug.LogFormat("[Follow the Leader #{0}] Expectation:\n{1}", _moduleId, string.Join("\n", _expectedCuts.Select(wi => wi.ToString()).ToArray()));
    }
Exemplo n.º 27
0
 public void UpdateChildren()
 {
     Module.UpdateChildren(Module);
 }
Exemplo n.º 28
0
    private void Update()
    {
        if (_isSolved)
        {
            return;
        }

        if (_isStage2)
        {
            var timer = (int)Bomb.GetTime();
            if (timer != _prevTimer)
            {
                Stage2Houses.Shuffle();
                for (int i = 0; i < 4; i++)
                {
                    ModuleSelectable.Children[i + 2] = Stage2Houses[i];
                }
                Stage2Houses[0].transform.localPosition = new Vector3(-.045f, 0, .045f);
                Stage2Houses[1].transform.localPosition = new Vector3(.028f, 0, .03f);
                Stage2Houses[2].transform.localPosition = new Vector3(-.028f, 0, -.03f);
                Stage2Houses[3].transform.localPosition = new Vector3(.045f, 0, -.045f);
                ModuleSelectable.UpdateChildren();
                _prevTimer = timer;
            }
            return;
        }

        var newSolvedModules = Bomb.GetSolvedModuleNames();

        if (newSolvedModules.Count == _prevSolvedModules.Length)
        {
            return;
        }

        var newSolvedModulesCopy = newSolvedModules.ToArray();

        // Remove all the modules that were already solved before, leaving only the newest solved module(s)
        foreach (var module in _prevSolvedModules)
        {
            newSolvedModules.Remove(module);
        }
        _prevSolvedModules = newSolvedModulesCopy;

        var selAssoc = _moduleAssociations[_selectedIndex];

        foreach (var solvedModule in newSolvedModules)
        {
            if (solvedModule == selAssoc.Module)
            {
                Debug.LogFormat(@"[Hogwarts #{0}] You solved {1} while it was selected, earning {2} points for {3}.", _moduleId, selAssoc.Module, selAssoc.Points, selAssoc.House);
                _points[selAssoc.House] = selAssoc.Points;

                // Is there a tie that can no longer be broken?
                var maxScore = _points.Max(kvp => kvp.Value);
                if (_points.Count(kvp => kvp.Value == maxScore) > 1 && !_moduleAssociations.Any(asc => asc.Points > maxScore))
                {
                    Debug.LogFormat(@"[Hogwarts #{0}] Strike because there is now a tie between {1} that can no longer be broken by another house.", _moduleId, _points.Where(kvp => kvp.Value == maxScore).Select(kvp => kvp.Key).JoinString(" and "));
                    Module.HandleStrike();
                }

                // Remove all the other modules for the same house
                _moduleAssociations.RemoveAll(asc => asc.House == selAssoc.House);
                if (_moduleAssociations.Count == 0)
                {
                    Audio.PlaySoundAtTransform("Transition" + Rnd.Range(1, 4), transform);
                    ActivateStage2();
                    break;
                }
                Audio.PlaySoundAtTransform("Solve" + Rnd.Range(1, 6), transform);
                select(Rnd.Range(0, _moduleAssociations.Count));
            }
            else
            {
                Debug.LogFormat(@"[Hogwarts #{0}] You solved {1} while it was NOT selected.", _moduleId, solvedModule);
                var curSel = _moduleAssociations[_selectedIndex].Module;
                _moduleAssociations.RemoveAll(asc => asc.Module == solvedModule);
                _selectedIndex = _moduleAssociations.IndexOf(asc => asc.Module == curSel);

                // Is there a house that is now losing out entirely?
                var missedHouse = Enumerable.Range(0, 4).IndexOf(house => !_points.ContainsKey((House)house) && !_moduleAssociations.Any(asc => asc.House == (House)house && !_specialModules.Contains(asc.Module)));
                if (missedHouse != -1)
                {
                    Audio.PlaySoundAtTransform("Strike", transform);
                    Debug.LogFormat(@"[Hogwarts #{0}] Strike because you solved all {1} modules unselected.", _moduleId, (House)missedHouse);
                    Module.HandleStrike();
                    _points[(House)missedHouse] = -1;
                }
            }
        }
    }
    private IEnumerator Initialize()
    {
        yield return(null);

        var retries = 0;

retry:

        //
        // STEP 1: Decide on all the arrows, filled stars and LED states
        //
        _arrows = new Arrow[ArrowMeshes.Length];
        for (int i = 0; i < ArrowMeshes.Length; i++)
        {
            _arrows[i] = (Arrow)((Rnd.Range(0, 4) << 0) | (Rnd.Range(0, 5) << 2));
            ArrowMeshes[i].material.mainTexture = Arrows[(int)_arrows[i]];
            ArrowCB[i].text = "RGBYP".Substring((int)(_arrows[i] & Arrow.ColorMask) >> 2, 1);
        }

        _filledStars = new bool[StarMeshes.Length];
        for (int i = 0; i < StarMeshes.Length; i++)
        {
            _filledStars[i] = Rnd.Range(0, 2) != 0;
            StarMeshes[i].material.mainTexture = Stars[_filledStars[i] ? 1 : 0];
        }

        _ledsOn = new bool[LedMeshes.Length];
        for (int i = 0; i < LedMeshes.Length; i++)
        {
            _ledsOn[i]            = Rnd.Range(0, 2) != 0;
            LedMeshes[i].material = LedMaterials[_ledsOn[i] ? 1 : 0];
        }

        //
        // STEP 2: Assign the wires to their connectors and decide their colors
        //
        var shuffledBottom = Enumerable.Range(0, 6).ToList().Shuffle();

        for (int i = 0; i < 6; i++)
        {
            _wires[i] = new WireInfo
            {
                TopConnector    = i < 4 ? i : Rnd.Range(0, 4),
                BottomConnector = shuffledBottom[i],
                Color           = (WireColor)Rnd.Range(0, 8),
                Level           = 1,
                HasBeenCut      = false
            };
            WireCB[_wires[i].BottomConnector].text = "RYBWGOPK".Substring((int)_wires[i].Color, 1);
            for (int j = 0; j < i; j++)
            {
                if ((_wires[j].TopConnector > _wires[i].TopConnector && _wires[j].BottomConnector < _wires[i].BottomConnector) ||
                    (_wires[j].TopConnector <_wires[i].TopConnector && _wires[j].BottomConnector> _wires[i].BottomConnector))
                {
                    _wires[i].Level = Math.Max(_wires[i].Level, _wires[j].Level + 1);
                }
            }
        }

        //
        // STEP 3: Determine the solution. Make sure that at least one wire needs to be cut.
        //
        const string rules            = "LWIPMVIFIUCCFRHHTVUDLRJBQWBPJTQD";
        var          colorsForRedRule = new[] { WireColor.Red, WireColor.Yellow, WireColor.Blue, WireColor.White };

        for (int i = 0; i < 6; i++)
        {
            var applicable = new List <string>();
            var rule       = 0;
            var arrowColor = _arrows[_wires[i].BottomConnector] & Arrow.ColorMask;

            // Red: The wire is red, yellow, blue, or white.
            if (colorsForRedRule.Contains(_wires[i].Color))
            {
                rule += 8;
                applicable.Add("Red");
            }
            // Orange: The wire shares the same color as its arrow.
            if ((_wires[i].Color == WireColor.Red && arrowColor == Arrow.Red) ||
                (_wires[i].Color == WireColor.Green && arrowColor == Arrow.Green) ||
                (_wires[i].Color == WireColor.Blue && arrowColor == Arrow.Blue) ||
                (_wires[i].Color == WireColor.Yellow && arrowColor == Arrow.Yellow) ||
                (_wires[i].Color == WireColor.Purple && arrowColor == Arrow.Purple))
            {
                rule += 16;
                applicable.Add("Orange");
            }
            // Yellow: The wire’s star is black.
            if (_filledStars[_wires[i].TopConnector])
            {
                rule += 2;
                applicable.Add("Yellow");
            }
            // Green: The wire’s position on the bottom is even.
            if (_wires[i].BottomConnector % 2 != 0)
            {
                rule += 4;
                applicable.Add("Green");
            }
            // Blue: The wire crosses over another wire.
            if (_wires.Any(w => (w.BottomConnector > _wires[i].BottomConnector && w.TopConnector < _wires[i].TopConnector) || (w.BottomConnector <_wires[i].BottomConnector && w.TopConnector> _wires[i].TopConnector)))
            {
                rule += 1;
                applicable.Add("Blue");
            }

            _wires[i].VennColors = applicable.ToArray();
            _wires[i].Reason     = rules[rule];

            var dir = (_arrows[_wires[i].BottomConnector] & Arrow.DirectionMask);
            switch (rules[rule])
            {
            // C: Cut the wire.
            case 'C': _wires[i].CutRule = CutRule.Cut; break;

            // F: Always cut the wire, but only cut it first.
            case 'F': _wires[i].CutRule = CutRule.CutFirst; break;

            // L: Always cut the wire, but only cut it last.
            case 'L': _wires[i].CutRule = CutRule.CutLast; break;

            // W: Cut the wire if more of the LEDs are on than off.
            case 'W': _wires[i].CutRule = _ledsOn.Count(l => l) > 1 ? CutRule.Cut : CutRule.DontCut; break;

            // T: Cut the wire if the first LED is on.
            case 'T': _wires[i].CutRule = _ledsOn[0] ? CutRule.Cut : CutRule.DontCut; break;

            // U: Cut the wire if its arrow points up or down.
            case 'U': _wires[i].CutRule = dir == Arrow.Up || dir == Arrow.Down ? CutRule.Cut : CutRule.DontCut; break;

            // M: Cut the wire if the arrow points down or right.
            case 'M': _wires[i].CutRule = dir == Arrow.Right || dir == Arrow.Down ? CutRule.Cut : CutRule.DontCut; break;

            // H: Cut the wire if the wire shares a star with another wire.
            case 'H': _wires[i].CutRule = _wires.Where((w, ix) => ix != i).Any(w => w.TopConnector == _wires[i].TopConnector) ? CutRule.Cut : CutRule.DontCut; break;

            // P: Cut the wire if its position at the bottom is equal to the number of ports.
            case 'P': _wires[i].CutRule = _wires[i].BottomConnector + 1 == Bomb.GetPortCount() ? CutRule.Cut : CutRule.DontCut; break;

            // B: Cut the wire if its position at the bottom is equal to the number of batteries.
            case 'B': _wires[i].CutRule = _wires[i].BottomConnector + 1 == Bomb.GetBatteryCount() ? CutRule.Cut : CutRule.DontCut; break;

            // I: Cut the wire if its position at the bottom is equal to the number of indicators.
            case 'I': _wires[i].CutRule = _wires[i].BottomConnector + 1 == Bomb.GetIndicators().Count() ? CutRule.Cut : CutRule.DontCut; break;

            // Q: Cut the wire if the color of the wire is unique.
            case 'Q': _wires[i].CutRule = _wires.Where((w, ix) => ix != i).Any(w => w.Color == _wires[i].Color) ? CutRule.DontCut : CutRule.Cut; break;

            // J: Cut the wire if, at the bottom, it is adjacent to an orange or purple wire.
            case 'J': _wires[i].CutRule = _wires.Any(w => (w.BottomConnector == _wires[i].BottomConnector - 1 || w.BottomConnector == _wires[i].BottomConnector + 1) && (w.Color == WireColor.Orange || w.Color == WireColor.Purple)) ? CutRule.Cut : CutRule.DontCut; break;

            // V: Cut the wire if the serial number has a vowel, or if the bomb has a USB port.
            case 'V': _wires[i].CutRule = Bomb.GetSerialNumberLetters().Any(ch => "AEIOU".Contains(ch)) || Bomb.GetPortCount("USB") > 0 ? CutRule.Cut : CutRule.DontCut; break;

            // R: Cut the wire if its arrow direction is unique.
            case 'R': _wires[i].CutRule = _arrows.Where((a, ix) => ix != _wires[i].BottomConnector).Any(a => (a & Arrow.DirectionMask) == dir) ? CutRule.DontCut : CutRule.Cut; break;

            // D: Do not cut the wire.
            case 'D': _wires[i].CutRule = CutRule.DontCut; break;
            }
        }
        if (_wires.All(w => w.CutRule == CutRule.DontCut))
        {
            retries++;
            goto retry;
        }
        Array.Sort(_wires, (w1, w2) => w1.BottomConnector.CompareTo(w2.BottomConnector));

        for (int i = 0; i < StarMeshes.Length; i++)
        {
            Debug.LogFormat("[Perplexing Wires #{0}] (h) Star #{1} is {2}.", _moduleId, i + 1, _filledStars[i] ? "filled" : "empty");
        }
        for (int i = 0; i < ArrowMeshes.Length; i++)
        {
            Debug.LogFormat("[Perplexing Wires #{0}] (h) Arrow #{1} is {2} and pointing {3}.", _moduleId, i + 1, arrowColorStr(_arrows[i]), arrowDirStr(_arrows[i]));
        }
        for (int i = 0; i < LedMeshes.Length; i++)
        {
            Debug.LogFormat("[Perplexing Wires #{0}] (h) LED #{1} is {2}.", _moduleId, i + 1, _ledsOn[i] ? "on" : "off");
        }

        //
        // STEP 4: Generate the actual wire meshes. (This also logs the wire states and rules.)
        //
        var wiresParent = Module.transform.Find("Wires");

        for (int wIx = 0; wIx < _wires.Length; wIx++)
        {
            var wireObj = wiresParent.Find("Wire" + (wIx + 1)).gameObject;

            // Determine the “original” control points and raise height.
            var topConnector = Module.transform.Find("Strip2").Find("Connector" + (_wires[wIx].TopConnector + 1));
            var topControl   = topConnector.Find("Control");
            topControl.localPosition = new Vector3(0, .2f, 0);
            var bottomConnector = Module.transform.Find("Strip1").Find("Connector" + (_wires[wIx].BottomConnector + 1));
            var bottomControl   = bottomConnector.Find("Control");
            var raiseBy         = 1.5 * (_wires[wIx].Level - 1) * (Pt)(transform.InverseTransformPoint(bottomControl.position) - transform.InverseTransformPoint(bottomConnector.position) + transform.InverseTransformPoint(topControl.position) - transform.InverseTransformPoint(topConnector.position));

            // Slightly move the control point at the top connector to mitigate the incidence of wire collisions.
            var topControlX = 0f;
            if (_wires.Any(w => w.TopConnector == _wires[wIx].TopConnector && w.BottomConnector < _wires[wIx].BottomConnector) && !_wires.Any(w => w.TopConnector == _wires[wIx].TopConnector && w.BottomConnector > _wires[wIx].BottomConnector))
            {
                topControlX = -.07f;
            }
            else if (_wires.Any(w => w.TopConnector == _wires[wIx].TopConnector && w.BottomConnector > _wires[wIx].BottomConnector) && !_wires.Any(w => w.TopConnector == _wires[wIx].TopConnector && w.BottomConnector < _wires[wIx].BottomConnector))
            {
                topControlX = .07f;
            }
            var topControlZ = 0f;
            if (_wires.Any(w => Math.Sign(w.TopConnector - _wires[wIx].TopConnector) != Math.Sign(w.BottomConnector - _wires[wIx].BottomConnector) && w.Level < _wires[wIx].Level))
            {
                topControlZ = .05f;
            }
            else if (_wires.Any(w => Math.Sign(w.TopConnector - _wires[wIx].TopConnector) != Math.Sign(w.BottomConnector - _wires[wIx].BottomConnector) && w.Level > _wires[wIx].Level))
            {
                topControlZ = -.05f;
            }
            topControl.localPosition = new Vector3(topControlX, .2f, topControlZ);

            // Generate the meshes for this wire.
            var seed = Rnd.Range(0, int.MaxValue);
            var mesh = MeshGenerator.GenerateWire(
                transform.InverseTransformPoint(topConnector.position),
                transform.InverseTransformPoint(topControl.position),
                transform.InverseTransformPoint(bottomControl.position),
                transform.InverseTransformPoint(bottomConnector.position),
                5,
                MeshGenerator.WirePiece.Uncut,
                MeshGenerator.Mode.Wire,
                seed,
                raiseBy);
            _wires[wIx].MeshFilter      = wireObj.GetComponent <MeshFilter>();
            _wires[wIx].MeshFilter.mesh = mesh;
            wireObj.GetComponent <MeshRenderer>().material = WireMaterials[(int)_wires[wIx].Color];

            _wires[wIx].CutMesh = MeshGenerator.GenerateWire(
                transform.InverseTransformPoint(topConnector.position),
                transform.InverseTransformPoint(topControl.position),
                transform.InverseTransformPoint(bottomControl.position),
                transform.InverseTransformPoint(bottomConnector.position),
                5,
                MeshGenerator.WirePiece.Cut,
                MeshGenerator.Mode.Wire,
                seed,
                raiseBy);
            _wires[wIx].CutHighlightMesh = MeshGenerator.GenerateWire(
                transform.InverseTransformPoint(topConnector.position),
                transform.InverseTransformPoint(topControl.position),
                transform.InverseTransformPoint(bottomControl.position),
                transform.InverseTransformPoint(bottomConnector.position),
                5,
                MeshGenerator.WirePiece.Cut,
                MeshGenerator.Mode.Highlight,
                seed,
                raiseBy);
            _wires[wIx].CopperMesh = MeshGenerator.GenerateWire(
                transform.InverseTransformPoint(topConnector.position),
                transform.InverseTransformPoint(topControl.position),
                transform.InverseTransformPoint(bottomControl.position),
                transform.InverseTransformPoint(bottomConnector.position),
                5,
                MeshGenerator.WirePiece.Copper,
                MeshGenerator.Mode.Wire,
                seed,
                raiseBy);

            var highlightMesh = MeshGenerator.GenerateWire(
                transform.InverseTransformPoint(topConnector.position),
                transform.InverseTransformPoint(topControl.position),
                transform.InverseTransformPoint(bottomControl.position),
                transform.InverseTransformPoint(bottomConnector.position),
                5,
                MeshGenerator.WirePiece.Uncut,
                MeshGenerator.Mode.Highlight,
                seed,
                raiseBy);
            var highlight = wireObj.transform.Find("Highlight");
            _wires[wIx].HighlightMeshFilter      = highlight.GetComponent <MeshFilter>();
            _wires[wIx].HighlightMeshFilter.mesh = highlightMesh;
            var highlight2 = highlight.Find("Highlight(Clone)");
            if (highlight2 != null)
            {
                _wires[wIx].HighlightMeshFilter      = highlight2.GetComponent <MeshFilter>();
                _wires[wIx].HighlightMeshFilter.mesh = highlightMesh;
            }

            wireObj.GetComponent <MeshCollider>().sharedMesh = MeshGenerator.GenerateWire(
                transform.InverseTransformPoint(topConnector.position),
                transform.InverseTransformPoint(topControl.position),
                transform.InverseTransformPoint(bottomControl.position),
                transform.InverseTransformPoint(bottomConnector.position),
                5,
                MeshGenerator.WirePiece.Uncut,
                MeshGenerator.Mode.Collider,
                seed,
                raiseBy);

            // Fix for a possible bug in Unity
            wireObj.GetComponent <MeshCollider>().enabled = true;
            wireObj.GetComponent <MeshCollider>().enabled = false;

            Debug.LogFormat("[Perplexing Wires #{6}] (h) Wire {0} to {1} is {2}: {3} (Venn: {4} = {5})",
                            _wires[wIx].TopConnector + 1,
                            _wires[wIx].BottomConnector + 1,
                            _wires[wIx].Color,
                            cutRuleStr(_wires[wIx].CutRule),
                            _wires[wIx].VennColors.Length == 0 ? "none" : _wires[wIx].VennColors.JoinString("+"),
                            _wires[wIx].Reason,
                            _moduleId);
            _wires[wIx].Selectable            = wireObj.GetComponent <KMSelectable>();
            _wires[wIx].Selectable.OnInteract = getWireHandler(wIx);
        }

        // Output the generated SVG to the logfile.
        var svg                   = new StringBuilder();
        var starsCoordsX          = new[] { 123.3 - 5, 161 - 5, 198.5 - 5, 236 - 5 };
        var starsCoordsY          = new[] { 36.2, 50, 63.6, 77.2 };
        var starsConnectorCoordsX = new[] { 115.6 - 5, 153.2 - 5, 190.8 - 5, 228.4 - 5 };
        var starsConnectorCoordsY = new[] { 69.8, 83.5, 97.2, 111 };

        // Wires
        for (var i = 0; i < 6; i++)
        {
            svg.AppendFormat(
                "<path d='M{0} 250 {0} 200 {1} {2} {3} {4}' stroke='#543' stroke-linecap='round' stroke-linejoin='round' stroke-width='16'/>" +
                "<path d='M{0} 250 {0} 200 {1} {2} {3} {4}' stroke='{5}' stroke-linecap='round' stroke-linejoin='round' stroke-width='13'/>" +
                "<text x='{0}' y='370' text-anchor='middle'>{6}</text>" +
                "<text x='{0}' y='390' text-anchor='middle' stroke='none' fill='{7}'>{8}</text>",
                /* {0} */ 40 + 40 * i,
                /* {1} */ starsConnectorCoordsX[_wires[i].TopConnector],
                /* {2} */ starsConnectorCoordsY[_wires[i].TopConnector],
                /* {3} */ starsCoordsX[_wires[i].TopConnector],
                /* {4} */ starsCoordsY[_wires[i].TopConnector],
                /* {5} */ colorSvg(_wires[i].Color),
                /* {6} */ _wires[i].Reason,
                /* {7} */ _wires[i].CutRule == CutRule.DontCut ? "#a00" : "#080",
                /* {8} */ cutRuleSvg(_wires[i].CutRule)
                );
        }

        // Lettering at the bottom
        var vennColors     = new[] { "#eb1414", "#ffb100", "#ee0", "#00be00", "#09f" };
        var vennColorNames = new[] { "Red", "Orange", "Yellow", "Green", "Blue" };

        for (var i = 0; i < 6; i++)
        {
            for (var cIx = 0; cIx < _wires[i].VennColors.Length; cIx++)
            {
                var c = Array.IndexOf(vennColorNames, _wires[i].VennColors[cIx]);
                svg.AppendFormat("<rect x='{0}' y='{1}' width='20' height='10' stroke='none' fill='{2}'/>", 30 + 40 * i, 275 + 15 * c, vennColors[c]);
            }
        }

        // Frames
        svg.Append(
            "<path d='M10 10h50v110H10z'/>" +                                       // LEDs frame
            "<path d='M95.5 10l169.2 61.7-10.2 28.2L85.3 38.2z' fill='#fff'/>" +    // stars
            "<path d='M10 230h260v40H10z' fill='#fff'/>");                          // arrows

        // LEDs
        svg.AppendFormat("<path d='M35 22  l8.7 4   2.2 9.6-6 7.6H30l-6-7.6 2-9.5z' fill='{0}'/>", _ledsOn[0] ? "lime" : "#234");
        svg.AppendFormat("<path d='M35 54.5l8.7 4   2.2 9.5-6 7.7H30L24 68l2-9.4z'  fill='{0}'/>", _ledsOn[1] ? "lime" : "#234");
        svg.AppendFormat("<path d='M35 86.8l8.7 4.3 2.2 9.5-6 7.5H30l-6-7.5 2-9.7z' fill='{0}'/>", _ledsOn[2] ? "lime" : "#234");

        // Stars
        for (var i = 0; i < 4; i++)
        {
            svg.AppendFormat("<path transform='translate({0}, {1}) rotate(20)' d='M0-10l2.2 7h7.3l-6 4.2 2.4 7-6-4.4-6 4.3 2.4-6.8-6-4.3H-2z' fill='{2}'/>", starsCoordsX[i], starsCoordsY[i], _filledStars[i] ? "black" : "white");
        }

        // Arrows
        for (var i = 0; i < 6; i++)
        {
            svg.AppendFormat("<path transform='translate({0}, 250) rotate({1})' d='M0-15L11 0H5.7v15H-5.7v-15H-11z' fill='{2}'/>", 40 + 40 * i, arrowDirSvg(_arrows[i]), colorSvg(_arrows[i]));
        }

        Debug.LogFormat("[Perplexing Wires #{0}]=svg[Module:]<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 462 400' fill='none' stroke='#000' stroke-width='2' font-family='Trebuchet MS'>{1}</svg>", _moduleId, svg.ToString());

        // Finally, get rid of the extra Wire objects that only exist to hold the colored materials.
        var dwIx = _wires.Length;

        while (true)
        {
            var wireObj = wiresParent.Find("Wire" + (dwIx + 1));
            if (wireObj == null)
            {
                break;
            }
            Destroy(wireObj.gameObject);
            dwIx++;
        }

        // Object that will be cloned to create the wire copper when a wire is cut.
        _wireCopper = wiresParent.Find("WireCopper").gameObject;
        _wireCopper.SetActive(false);

        MainSelectable.Children = _wires.Select(w => w.Selectable).ToArray();
        MainSelectable.UpdateChildren();

        if (ColorblindMode.ColorblindModeActive)
        {
            ActivateColorblindMode();
        }
    }
Exemplo n.º 30
0
    private IEnumerator Initialize()
    {
        yield return(null);

        ConnectingWallParent.SetActive(false);

        _hieroglyphsDisplayed = Enumerable.Range(0, 6).ToArray();
        var serial     = Bomb.GetSerialNumber();
        var serialProc = serial.Select(ch => ch == '0' ? 'Z' : ch >= '1' && ch <= '9' ? (char)(ch - '1' + 'A') : ch).JoinString();
        var ports      = Ut.NewArray(
            KMBombInfoExtensions.KnownPortType.PS2,
            KMBombInfoExtensions.KnownPortType.Parallel,
            KMBombInfoExtensions.KnownPortType.RJ45,
            KMBombInfoExtensions.KnownPortType.StereoRCA,
            KMBombInfoExtensions.KnownPortType.Serial,
            KMBombInfoExtensions.KnownPortType.DVI
            );
        var hasPorts = ports.Select(port => Bomb.IsPortPresent(port)).ToArray();

retry:
        _hieroglyphsDisplayed.Shuffle();
        var team = _teams[Rnd.Range(0, _teams.Length)];

        var matches = new int[6];

        for (int i = 0; i < 6; i++)
        {
            if (_hieroglyphsDisplayed[i] == i)
            {
                matches[i]++;
            }
            if (team.ToUpperInvariant().Contains(serialProc[i]))
            {
                matches[i]++;
            }
            if (hasPorts[i])
            {
                matches[i]++;
            }
        }

        var unique = Ut.NewArray(4, c => matches.Count(i => i == c) == 1);

        if (unique.Count(c => c) != 1)
        {
            goto retry;
        }

        TeamName.text = team;
        var uniqueCount = Array.IndexOf(unique, true);

        _round1Answer = Array.IndexOf(matches, uniqueCount);

        Debug.LogFormat(@"[Only Connect #{0}] Team name: {1}", _moduleId, team);
        var format = @"[Only Connect #{0}] {1,-13} {2,-9} {3,-8} {4,-9} {5,-3} {6}";

        Debug.LogFormat(format, _moduleId, "Hieroglyph", "Position", "Serial#", "Ports", "num", "");
        var positions = new[] { "TL", "TM", "TR", "BL", "BM", "BR" };

        for (int i = 0; i < 6; i++)
        {
            EgyptianHieroglyphButtons[i].GetComponent <MeshRenderer>().material = EgyptianHieroglyphs[_hieroglyphsDisplayed[i]];
            Debug.LogFormat(format, _moduleId, _hieroglyphs[i], positions[Array.IndexOf(_hieroglyphsDisplayed, i)] + "=" + (_hieroglyphsDisplayed[i] == i), serialProc[i] + "=" + team.Contains(serialProc[i]), ports[i].ToString().Substring(0, 2) + "=" + hasPorts[i], matches[i], i == _round1Answer ? "← ✓" : "");
            if (_hieroglyphsDisplayed[i] == _round1Answer)
            {
                EgyptianHieroglyphButtons[i].OnInteract = StartRound2(EgyptianHieroglyphButtons[i]);
            }
            else
            {
                EgyptianHieroglyphButtons[i].OnInteract = Round1Strike(i, _hieroglyphsDisplayed[i]);
            }
        }

        MainSelectable.Children = EgyptianHieroglyphButtons;
        MainSelectable.UpdateChildren(EgyptianHieroglyphButtons[0]);
    }