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()); } }
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; }
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; }
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); }
#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); }
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); }; } }
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); }
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; }
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); }
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; }
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]); } }
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(); }; }
// 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(); }
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); }
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())); }
public void UpdateChildren() { Module.UpdateChildren(Module); }
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(); } }
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]); }