public SimplePipe this[int x, int y] { get { var v = ByIndex(x, y).FirstOrDefault(k => !k.Value.IsVirtualPipe); if (v == null) return null; return v.Value; } set { // assigning null currently does not register spill detection var IsVirtualPipe = false; if (value != null) IsVirtualPipe = value.IsVirtualPipe; #region Spill Action<int, int, SimplePipeOnTheField> Spill = (ox, oy, SpillTarget) => { if (SpillTarget.Value.Output[ox, oy] == null) if (SpillTarget.Value.SupportedOutput[ox, oy] != null) { // once the water gets here we need to spill it on the floor // it can happen when the pipe is not there or even when the pipe does not accept input // when the correct pipe is built this event is effectevly detatched SpillTarget.Value.Output[ox, oy] = delegate { // SpillTarget has filled itself with water // and needs to continue on the next pipe // but as we are inside here there is no matching pipe there var s = new SimplePipe.Missing(); this[SpillTarget.X + ox, SpillTarget.Y + oy] = s; RefreshPipes(); s.Output.Spill = delegate { // game over!!! }; // we need to trigger the event s.Input[-ox, -oy](); // and when the water hits the floor // we should trigger end game }; } }; #endregion var DemolitionCost = 0; if (!IsVirtualPipe) { #region remove old pipe PipesList.Where(k => k.Y == y).Where(k => k.X == x).ToArray().ForEach( target => { DemolitionCost += target.Value.DemolitionCost; Console.WriteLine("remove: " + new { target.Value.GetType().Name, target.X, target.Y }); target.Value.Dispose(); PipesList.Remove(target); new FindSiblings { FoundLeft = Left => { Left.Value.Output.Right = null; if (value != null) value.Output.Left = null; Spill(1, 0, Left); }, FoundRight = Right => { Right.Value.Output.Left = null; if (value != null) value.Output.Right = null; Spill(-1, 0, Right); }, FoundTop = Top => { Top.Value.Output.Bottom = null; if (value != null) value.Output.Top = null; Spill(0, 1, Top); }, FoundBottom = Bottom => { Bottom.Value.Output.Top = null; if (value != null) value.Output.Bottom = null; Spill(0, -1, Bottom); } }.Apply(PipesList, target); } ); #endregion } if (value != null) { value.PipeParts.ForEach(k => k.Color = this.DefaultPipeColor); var target = new SimplePipeOnTheField { Value = value, X = x, Y = y }; PipesList.Add( target ); Console.WriteLine("add: " + new { target.Value.GetType().Name, target.X, target.Y }); var px = x * Tile.Size + Tile.ShadowBorder; var py = (1 + y) * Tile.SurfaceHeight + Tile.ShadowBorder - Tile.Size; value.Container.AttachTo(this.Pipes).MoveTo(px, py); value.InfoOverlay.AttachTo(this.InfoOverlay).MoveTo(px, py); if (!IsVirtualPipe) { new FindSiblings { FoundLeft = Left => { Left.Value.Output.Right = value.Input.Left; value.Output.Left = Left.Value.Input.Right; Spill(1, 0, Left); }, FoundRight = Right => { Right.Value.Output.Left = value.Input.Right; value.Output.Right = Right.Value.Input.Left; Spill(-1, 0, Right); }, FoundTop = Top => { Top.Value.Output.Bottom = value.Input.Top; value.Output.Top = Top.Value.Input.Bottom; Spill(0, 1, Top); }, FoundBottom = Bottom => { Bottom.Value.Output.Top = value.Input.Bottom; value.Output.Bottom = Bottom.Value.Input.Top; Spill(0, -1, Bottom); } }.Apply(PipesList, target); Spill(1, 0, target); Spill(-1, 0, target); Spill(0, 1, target); Spill(0, -1, target); value.ShowBonusPoints(DemolitionCost); } } } }
public void Apply(IEnumerable<SimplePipeOnTheField> source, SimplePipeOnTheField target) { source.Where(k => k.Y == target.Y).FirstOrDefault(k => k.X == target.X - 1).DoIfAny( FoundLeft ); source.Where(k => k.Y == target.Y).FirstOrDefault(k => k.X == target.X + 1).DoIfAny( FoundRight ); source.Where(k => k.X == target.X).FirstOrDefault(k => k.Y == target.Y - 1).DoIfAny( FoundTop ); source.Where(k => k.X == target.X).FirstOrDefault(k => k.Y == target.Y + 1).DoIfAny( FoundBottom ); }