//GeneratePopParticles(pOwner, state, iterate);
        private void GeneratePopParticles(IStateOwner pOwner, GameplayGameState gstate, SKPointI pt)
        {
            var rgen    = TetrisGame.rgen;
            var popItem = gstate.PlayField.Contents[pt.Y][pt.X];

            BCColor[] useColor = YellowColors;
            if (popItem is LineSeriesBlock lsb)
            {
                switch (lsb.CombiningIndex)
                {
                case LineSeriesBlock.CombiningTypes.Red:
                    useColor = RedColors;
                    break;

                case LineSeriesBlock.CombiningTypes.Blue:
                    useColor = BlueColors;
                    break;

                case LineSeriesBlock.CombiningTypes.Yellow:
                    useColor = YellowColors;
                    break;

                case LineSeriesBlock.CombiningTypes.Orange:
                    useColor = OrangeColors;
                    break;

                case LineSeriesBlock.CombiningTypes.Magenta:
                    useColor = MagentaColors;
                    break;

                case LineSeriesBlock.CombiningTypes.Green:
                    useColor = GreenColors;
                    break;
                }
                for (int i = 0; i < ParticlesPerPop; i++)
                {
                    PointF  Offset   = new PointF((float)rgen.NextDouble(), (float)rgen.NextDouble());
                    BCColor selColor = TetrisGame.Choose(useColor);
                    BCPoint Velocity = TetrisGame.Choose(CardinalOptions);
                    float   Speed    = (float)rgen.NextDouble() * (MAX_SPEED - MIN_SPEED) + MIN_SPEED;
                    float   Sign     = TetrisGame.Choose(new float[] { -1f, 1f });

                    BCPoint VelocityUse = new BCPoint(Velocity.X * Speed * Sign, Velocity.Y * Speed * Sign);

                    BaseParticle bp = new BaseParticle(new BCPoint(pt.X + Offset.X, pt.Y + Offset.Y), VelocityUse, selColor);
                    gstate.Particles.Add(bp);
                }
            }

            /*for (int i=0;i<ParticlesPerPop;i++)
             * {
             *
             * }*/
        }
 private void DrMarioNominoTweaker(Nomino Source)
 {
     //tweak the nomino and set a random combining index.
     foreach (var iterate in Source)
     {
         if (iterate.Block is LineSeriesBlock lsb)
         {
             lsb.CombiningIndex = TetrisGame.Choose(GetValidBlockCombiningTypes());
         }
     }
 }
Beispiel #3
0
        private void AddParticles(IStateOwner pOwner, int BlockX, int BlockY, int DirectionMultiplier, int RowsCleared)
        {
            //the actual block we are clearing...
            var     ClearingBlock = _BaseState.PlayField.Contents[BlockY][BlockX];
            SKColor baseColor     = TetrisGame.Choose(ClearLineParticleColours);
            Bitmap  sourcebitmap  = null;

            if (ClearingBlock != null && ClearingBlock is ImageBlock ib)
            {
                sourcebitmap = new Bitmap(ib._RotationImages[MathHelper.mod(ib.Rotation, ib._RotationImages.Length)]);
            }
            var blockWidth  = _BaseState.PlayField.GetBlockWidth((SKRect)pOwner.LastDrawBounds);
            var blockHeight = _BaseState.PlayField.GetBlockHeight((SKRect)pOwner.LastDrawBounds);
            var CoordPos    = new BCPoint(BlockX,
                                          BlockY - 2);

            lock (_BaseState.Particles)
            {
                List <BaseParticle> ToAdd = new List <BaseParticle>(ParticleCountPerBlock);
                for (int i = 0; i < ParticleCountPerBlock; i++)
                {
                    BCPoint ParticlePos = new BCPoint((float)TetrisGame.rgen.NextDouble(), (float)TetrisGame.rgen.NextDouble());
                    //choose a new random position within the block.
                    BCPoint NewParticlePoint = new BCPoint(CoordPos.X + ParticlePos.X, CoordPos.Y + ParticlePos.Y);
                    BCPoint Velocity         = new BCPoint(

                        (float)(DirectionMultiplier * (TetrisGame.rgen.NextDouble() * 1 + (Math.Abs(BlockX - (_BaseState.PlayField.ColCount / 2)) / 5))), 0

                        );
                    BCColor ChosenColor = baseColor;

                    if (sourcebitmap != null)
                    {
                        Point TargetPixel = new Point((int)(ParticlePos.X * sourcebitmap.Width), (int)(ParticlePos.Y * sourcebitmap.Height));
                        ChosenColor = sourcebitmap.GetPixel(TargetPixel.X, TargetPixel.Y);
                    }


                    BaseParticle p = new BaseParticle(NewParticlePoint, Velocity, ChosenColor);
                    if (RowsCleared >= 4)
                    {
                        if (TetrisGame.rgen.NextDouble() > 0.25d)
                        {
                            p.ColorCalculatorFunction = BaseParticle.GetRainbowColorFunc(pOwner, 500);
                        }
                    }
                    p.TTL = (uint)ClearParticleTTL;
                    ToAdd.Add(p);
                }
                _BaseState.Particles.AddRange(ToAdd);
            }
        }
Beispiel #4
0
        public Duomino()
        {
            //generate a new Duomino. Duomino's don't actually use StandardColouredBlocks.


            BlockData = Nomino.GetNominoEntries(new[] { Duomino_Point_1, Duomino_Point_2 },
                                                (i) => new LineSeriesBlock()
            {
                CombiningIndex = TetrisGame.Choose(new LineSeriesBlock.CombiningTypes[] { LineSeriesBlock.CombiningTypes.Yellow, LineSeriesBlock.CombiningTypes.Red, LineSeriesBlock.CombiningTypes.Blue })
            }).ToList();

            base.SpecialName = "Pill";
            base.SetBlockOwner();
            base.RecalcExtents();
        }
Beispiel #5
0
        public override BlockTypeReturnData  GetBlockType(Nomino group, NominoElement element, TetrisField field)
        {
            var bg = group;

            if (bg is Tetromino_I || bg is Tetromino_T || bg is Tetromino_O)
            {
                return(new BlockTypeReturnData(NESBlockTypes.Boxed));
            }
            else if (bg is Tetromino_J || bg is Tetromino_Z)
            {
                return(new BlockTypeReturnData(NESBlockTypes.Darker));
            }
            else if (bg is Tetromino)
            {
                return(new BlockTypeReturnData(NESBlockTypes.Lighter));
            }
            else
            {
                return(new BlockTypeReturnData(TetrisGame.Choose(new NESBlockTypes[] { NESBlockTypes.Boxed, NESBlockTypes.Darker, NESBlockTypes.Lighter })));
            }
        }
Beispiel #6
0
 private void InitDrawData(IStateOwner pOwner, PauseGameState Source, GameStateSkiaDrawParameters Element)
 {
     if (Source.PausedState is GameplayGameState std)
     {
         var        rgen            = new Random();
         SKBitmap[] availableImages = std.GetTetrominoSKBitmaps();
         var        Areause         = pOwner.GameArea;
         Source.FallImages = new List <PauseGameState.PauseFallImageBase>();
         for (int i = 0; i < PauseGameState.NumFallingItems; i++)
         {
             PauseGameState.PauseFallImageSkiaSharp pfi = new PauseGameState.PauseFallImageSkiaSharp();
             pfi.OurImage   = TetrisGame.Choose(availableImages);
             pfi.XSpeed     = 0;
             pfi.YSpeed     = (float)(rgen.NextDouble() * 5);
             pfi.AngleSpeed = 0; //(float)(rgen.NextDouble() * 20) - 10;
             pfi.XPosition  = (float)rgen.NextDouble() * (float)Areause.Width;
             pfi.YPosition  = (float)rgen.NextDouble() * (float)Areause.Height;
             Source.FallImages.Add(pfi);
         }
     }
 }
        public void PrepareField(GameplayGameState state, IStateOwner pOwner)
        {
            //likely will need to have stats and stuff abstracted to each Handler.
            state.PlayField.Reset();

            HashSet <SKPointI> usedPositions = new HashSet <SKPointI>();
            //primary count is based on our level.
            int numPrimaries = (int)((Level * 1.33f) + 4);

            for (int i = 0; i < numPrimaries; i++)
            {
                //choose a random primary type.
                var chosentype = TetrisGame.Choose(GetValidPrimaryCombiningTypes());
                LineSeriesPrimaryBlock lsmb = new LineSeriesPrimaryBlock()
                {
                    CombiningIndex = chosentype
                };
                var Dummino = new Nomino()
                {
                };
                Dummino.AddBlock(new Point[] { new Point(0, 0) }, lsmb);
                state.PlayField.Theme.ApplyTheme(Dummino, this, state.PlayField, NominoTheme.ThemeApplicationReason.Normal);
                lsmb.CriticalMass = 4; //TODO: should this be changed?

                int      RandomXPos = TetrisGame.rgen.Next(state.PlayField.ColCount);
                int      RandomYPos = state.PlayField.RowCount - 1 - TetrisGame.rgen.Next(state.PlayField.RowCount / 2);
                SKPointI randomPos  = new SKPointI(RandomXPos, RandomYPos);
                while (usedPositions.Contains(randomPos))
                {
                    int rndXPos = TetrisGame.rgen.Next(state.PlayField.ColCount);
                    int rndYPos = state.PlayField.RowCount - 1 - TetrisGame.rgen.Next(state.PlayField.RowCount / 2);
                    randomPos = new SKPointI(rndXPos, rndYPos);
                }
                state.PlayField.Contents[RandomYPos][RandomXPos] = lsmb;
                PrimaryBlockCount++;
            }
            PrimaryBlockAppearanceState appearstate = new PrimaryBlockAppearanceState(state);

            pOwner.CurrentState = appearstate;
        }
 private void InitDrawData(IStateOwner pOwner, PauseGameState Source, BaseDrawParameters Element)
 {
     if (Source.PausedState is GameplayGameState std)
     {
         var rgen = new Random();
         //TODO: well this clearly shouldn't be here...
         Image[] availableImages = std.GetTetronimoImages();
         var     Areause         = pOwner.GameArea;
         Source.FallImages = new List <PauseGameState.PauseFallImageBase>();
         for (int i = 0; i < PauseGameState.NumFallingItems; i++)
         {
             PauseGameState.PauseFallImageGDIPlus pfi = new PauseGameState.PauseFallImageGDIPlus();
             pfi.OurImage   = TetrisGame.Choose(availableImages);
             pfi.XSpeed     = (float)(rgen.NextDouble() * 10) - 5;
             pfi.YSpeed     = (float)(rgen.NextDouble() * 10) - 5;
             pfi.AngleSpeed = (float)(rgen.NextDouble() * 20) - 10;
             pfi.XPosition  = (float)rgen.NextDouble() * (float)Areause.Width;
             pfi.YPosition  = (float)rgen.NextDouble() * (float)Areause.Height;
             Source.FallImages.Add(pfi);
         }
     }
 }
        public SKBitmap GetTetrominoSKBitmap(String Source)
        {
            if (NominoSKBitmaps == null)
            {
                NominoSKBitmaps = new Dictionary <String, List <SKBitmap> >();
            }
            if (!NominoSKBitmaps.ContainsKey(Source))
            {
                if (NominoImages != null && NominoImages.ContainsKey(Source))
                {
                    NominoSKBitmaps.Add(Source, new List <SKBitmap>());
                    foreach (var copyGDI in NominoImages[Source])
                    {
                        NominoSKBitmaps[Source].Add(SkiaSharp.Views.Desktop.Extensions.ToSKBitmap(new Bitmap(copyGDI)));
                    }
                }
                else
                {
                    return(null);
                }
            }

            return(TetrisGame.Choose(NominoSKBitmaps[Source]));
        }
Beispiel #10
0
        private AudioThemeSelection GetThemeProperty(String pProp)
        {
            PropertyInfo      grabprop   = CurrentTheme.GetType().GetProperty(pProp, typeof(AudioThemeElement));
            Object            result     = grabprop.GetGetMethod().Invoke(CurrentTheme, new object[] { });
            AudioThemeElement CastResult = result as AudioThemeElement;

            if (CastResult.AudioKeys.Length == 1)
            {
                return(CastResult.AudioKeys[0]);
            }
            if (CastResult.ChooseFlag == AudioThemeElement.AudioThemeElementChooseFlags.Flag_Static)
            {
                if (!CachedStatics.ContainsKey(CastResult))
                {
                    CachedStatics[CastResult] = TetrisGame.Choose(CastResult.AudioKeys);
                }

                return(CachedStatics[CastResult]);
            }
            else
            {
                return(TetrisGame.Choose(CastResult.AudioKeys));
            }
        }
Beispiel #11
0
        public override void RenderStats(IStateOwner pOwner, Graphics pRenderTarget, GameplayGameState Source, BaseDrawParameters Element)
        {
            var Bounds = Element.Bounds;
            var g      = pRenderTarget;

            bool RedrawsNeeded = !LastDrawStat.Equals(Bounds);

            LastDrawStat = Bounds;
            if (StatisticsBackground == null || RedrawsNeeded || GeneratedImageTheme != Source.PlayField.Theme)
            {
                GenerateStatisticsBackground(Source);
            }

            g.DrawImage(StatisticsBackground, Bounds);
            //g.Clear(Color.Black);
            if (!Source.HasTetrominoImages() || RedrawsNeeded)
            {
                RedrawStatusbarTetrominoBitmaps(pOwner, Source, Bounds);
            }

            lock (Source.LockTetImageRedraw)
            {
                var    useStats = Source.GameStats;
                double Factor   = Bounds.Height / 644d;
                int    DesiredFontPixelHeight = (int)(Bounds.Height * (23d / 644d));
                using (Font standardFont = new Font(TetrisGame.RetroFont, DesiredFontPixelHeight, FontStyle.Bold, GraphicsUnit.Pixel))
                {
                    var LocalScores    = Source.GetLocalScores();
                    var TopScore       = LocalScores == null ? 0 : LocalScores.GetScores().First().Score;
                    int MaxScoreLength = Math.Max(TopScore.ToString().Length, useStats.Score.ToString().Length);

                    String CurrentScoreStr = useStats.Score.ToString().PadLeft(MaxScoreLength + 2);
                    String TopScoreStr     = TopScore.ToString().PadLeft(MaxScoreLength + 2);
                    //TODO: redo this segment separately, so we can have the labels left-aligned and the values right-aligned.
                    // String BuildStatString = "Time:  " + FormatGameTime(pOwner).ToString().PadLeft(MaxScoreLength + 2) + "\n" +
                    //                          "Score: " + CurrentScoreStr + "\n" +
                    //                          "Top:   " + TopScoreStr + " \n" +
                    //                          "Lines: " + GameStats.LineCount.ToString().PadLeft(MaxScoreLength+2);

                    g.FillRectangle(LightenBrush, 0, 5, Bounds.Width, (int)(450 * Factor));
                    String[] StatLabels   = new string[] { "Time:", "Score:", "Top:", "Lines:" };
                    int      LineCount    = Source.GameStats is TetrisStatistics ? (Source.GameStats as TetrisStatistics).LineCount : 0;
                    String[] StatValues   = new string[] { FormatGameTime(pOwner), useStats.Score.ToString(), TopScore.ToString(), LineCount.ToString() };
                    Point    StatPosition = new Point((int)(7 * Factor), (int)(7 * Factor));

                    int CurrentYPosition = StatPosition.Y;
                    for (int statindex = 0; statindex < StatLabels.Length; statindex++)
                    {
                        var   MeasureLabel = g.MeasureString(StatLabels[statindex], standardFont);
                        var   MeasureValue = g.MeasureString(StatValues[statindex], standardFont);
                        float LargerHeight = Math.Max(MeasureLabel.Height, MeasureValue.Height);

                        //we want to draw the current stat label at position StatPosition.X,CurrentYPosition...

                        TetrisGame.DrawText(g, standardFont, StatLabels[statindex], Brushes.Black, Brushes.White, StatPosition.X, CurrentYPosition);

                        //we want to draw the current stat value at Bounds.Width-ValueWidth.
                        TetrisGame.DrawText(g, standardFont, StatValues[statindex], Brushes.Black, Brushes.White, (float)(Bounds.Width - MeasureValue.Width - (5 * Factor)), CurrentYPosition);

                        //add the larger of the two heights to the current Y Position.
                        CurrentYPosition += (int)LargerHeight;
                        CurrentYPosition += 2;
                    }



                    Type[] useTypes = new Type[] { typeof(Tetromino_I), typeof(Tetromino_O), typeof(Tetromino_J), typeof(Tetromino_T), typeof(Tetromino_L), typeof(Tetromino_S), typeof(Tetromino_Z) };

                    int[] PieceCounts = null;

                    if (useStats is TetrisStatistics ts)
                    {
                        PieceCounts = new int[] { ts.I_Piece_Count, ts.O_Piece_Count, ts.J_Piece_Count, ts.T_Piece_Count, ts.L_Piece_Count, ts.S_Piece_Count, ts.Z_Piece_Count };
                    }
                    else
                    {
                        PieceCounts = new int[] { 0, 0, 0, 0, 0, 0, 0 };
                    }


                    int             StartYPos = (int)(140 * Factor);
                    int             useXPos   = (int)(30 * Factor);
                    ImageAttributes ShadowTet = TetrisGame.GetShadowAttributes();
                    if (Source.GameHandler is StandardTetrisHandler)
                    {
                        for (int i = 0; i < useTypes.Length; i++)
                        {
                            PointF BaseCoordinate = new PointF(useXPos, StartYPos + (int)((float)i * (40d * Factor)));
                            PointF TextPos        = new PointF(useXPos + (int)(100d * Factor), BaseCoordinate.Y);
                            String StatText       = "" + PieceCounts[i];
                            SizeF  StatTextSize   = g.MeasureString(StatText, standardFont);
                            String sNomTypeKey    = Source.PlayField.Theme.GetNominoTypeKey(useTypes[i], Source.GameHandler, Source.PlayField);
                            Image  TetrominoImage = TetrisGame.Choose(Source.NominoImages[sNomTypeKey]);
                            PointF ImagePos       = new PointF(BaseCoordinate.X, BaseCoordinate.Y + (StatTextSize.Height / 2 - TetrominoImage.Height / 2));

                            g.DrawImage(TetrominoImage, ImagePos);
                            g.DrawString(StatText, standardFont, Brushes.White, new PointF(TextPos.X + 4, TextPos.Y + 4));
                            g.DrawString(StatText, standardFont, Brushes.Black, TextPos);
                        }
                    }

                    Point NextDrawPosition = new Point((int)(40f * Factor), (int)(420 * Factor));
                    Size  NextSize         = new Size((int)(200f * Factor), (int)(200f * Factor));
                    Point CenterPoint      = new Point(NextDrawPosition.X + NextSize.Width / 2, NextDrawPosition.Y + NextSize.Height / 2);
                    //now draw the "Next" Queue. For now we'll just show one "next" item.
                    if (Source.NextBlocks.Count > 0)
                    {
                        var QueueList = Source.NextBlocks.ToArray();
                        //(from t in QueueList select Source.GetTetrominoSKBitmap(pOwner,t)).ToArray()
                        Image[] NextTetrominoes = (from t in QueueList select Source.GetTetrominoImage(pOwner, t)).ToArray(); //  TetrisGame.Choose(Source.NominoImages[Source.PlayField.Theme.GetNominoKey(t,Source.GameHandler,Source.PlayField)])).ToArray();
                        Image   DisplayBox      = TetrisGame.Imageman["display_box"];
                        //draw it at 40,420. (Scaled).
                        float ScaleDiff = 0;
                        iActiveSoundObject PlayingMusic;
                        if ((PlayingMusic = TetrisGame.Soundman.GetPlayingMusic_Active()) != null)
                        {
                            Source.StoredLevels.Enqueue(PlayingMusic.Level);
                        }

                        if (Source.StoredLevels.Count >= 4)
                        {
                            ScaleDiff = Math.Min(30, 10 * Source.StoredLevels.Dequeue());
                        }

                        if (!TetrisGame.DJMode)
                        {
                            ScaleDiff = 0;
                        }

                        g.DrawImage
                            (DisplayBox,
                            new Rectangle(new Point((int)(NextDrawPosition.X - ScaleDiff), (int)(NextDrawPosition.Y - ScaleDiff)), new Size((int)(NextSize.Width + (ScaleDiff * 2)), (int)(NextSize.Height + (ScaleDiff * 2)))), 0, 0, DisplayBox.Width, DisplayBox.Height, GraphicsUnit.Pixel);

                        g.FillEllipse(Brushes.Black, CenterPoint.X - 5, CenterPoint.Y - 5, 10, 10);

                        for (int i = NextTetrominoes.Length - 1; i > -1; i--)
                        {
                            double StartAngle         = Math.PI;
                            double AngleIncrementSize = (Math.PI * 1.8) / (double)NextTetrominoes.Length;
                            //we draw starting at StartAngle, in increments of AngleIncrementSize.
                            //i is the index- we want to increase the angle by that amount (well, obviously, I suppose...

                            double UseAngleCurrent = StartAngle + AngleIncrementSize * (float)i + Source.NextAngleOffset;

                            double UseXPosition = CenterPoint.X + ((float)((NextSize.Width) / 2.2) * Math.Cos(UseAngleCurrent));
                            double UseYPosition = CenterPoint.Y + ((float)((NextSize.Height) / 2.2) * Math.Sin(UseAngleCurrent));


                            var NextTetromino = NextTetrominoes[i];

                            float Deviation = (i - NextTetrominoes.Length / 2);
                            Point Deviate   = new Point((int)(Deviation * 20 * Factor), (int)(Deviation * 20 * Factor));

                            Point DrawTetLocation = new Point((int)UseXPosition - (NextTetromino.Width / 2), (int)UseYPosition - NextTetromino.Height / 2);
                            //Point DrawTetLocation = new Point(Deviate.X + (int)(NextDrawPosition.X + ((float)NextSize.Width / 2) - ((float)NextTetromino.Width / 2)),
                            //    Deviate.Y + (int)(NextDrawPosition.Y + ((float)NextSize.Height / 2) - ((float)NextTetromino.Height / 2)));
                            double AngleMovePercent = Source.NextAngleOffset / AngleIncrementSize;
                            double NumAffect        = Source.NextAngleOffset == 0 ? 0 : AngleIncrementSize / Source.NextAngleOffset;
                            Size   DrawTetSize      = new Size
                                                      (
                                (int)((float)NextTetromino.Width * (0.3 + (1 - ((float)(i) * 0.15f) - .15f * AngleMovePercent))),
                                (int)((float)NextTetromino.Height * (0.3 + (1 - ((float)(i) * 0.15f) - .15f * AngleMovePercent))));


                            //g.TranslateTransform(CenterPoint.X,CenterPoint.Y);

                            g.TranslateTransform(DrawTetLocation.X + DrawTetSize.Width / 2, DrawTetLocation.Y + DrawTetSize.Width / 2);


                            double DrawTetAngle = UseAngleCurrent;
                            DrawTetAngle += (Math.PI * AngleMovePercent);
                            float useDegrees = 180 + (float)(DrawTetAngle * (180 / Math.PI));

                            g.RotateTransform((float)useDegrees);

                            g.TranslateTransform(-(DrawTetLocation.X + DrawTetSize.Width / 2), -(DrawTetLocation.Y + DrawTetSize.Height / 2));
                            //g.TranslateTransform(-CenterPoint.X,-CenterPoint.Y);


                            if (DrawTetSize.Width > 0 && DrawTetSize.Height > 0)
                            {
                                //ImageAttributes Shade = GetShadowAttributes(1.0f - ((float)i * 0.3f));
                                ImageAttributes Shade = new ImageAttributes();
                                Shade.SetColorMatrix(ColorMatrices.GetFader(1.0f - ((float)i * 0.1f)));


                                g.DrawImage
                                    (NextTetromino, new Rectangle((int)DrawTetLocation.X, (int)DrawTetLocation.Y, DrawTetSize.Width, DrawTetSize.Height), 0f, 0f,
                                    (float)NextTetromino.Width, (float)NextTetromino.Height, GraphicsUnit.Pixel, Shade);
                            }

                            g.ResetTransform();
                        }
                    }

                    if (Source.HoldBlock != null)
                    {
                        var   GetKey        = Source.PlayField.Theme.GetNominoKey(Source.HoldBlock, Source.GameHandler, Source.PlayField);
                        Image HoldTetromino = Source.GetTetrominoImage(pOwner, Source.HoldBlock);
                        g.DrawImage(HoldTetromino, CenterPoint.X - HoldTetromino.Width / 2, CenterPoint.Y - HoldTetromino.Height / 2);
                    }
                }
            }
        }
 public Image GetTetrominoImage(String TetrominoType)
 {
     return(TetrisGame.Choose(NominoImages[TetrominoType]));
 }
        public FieldChangeResult ProcessFieldChange(GameplayGameState state, IStateOwner pOwner, Nomino Trigger)
        {
            var HotLines                    = new List <HotLine>();
            FieldChangeResult FCR           = new FieldChangeResult();
            int           rowsfound         = 0;
            List <int>    CompletedRows     = new List <int>();
            List <Action> AfterClearActions = new List <Action>();
            var           PlayField         = state.PlayField;
            var           Sounds            = state.Sounds;
            var           GameOptions       = state.GameOptions;

            //checks the field contents for lines. If there are lines found, they are removed, and all rows above it are shifted down.
            for (int r = 0; r < PlayField.RowCount; r++)
            {
                if (PlayField.Contents[r].All((d) => d != null))
                {
                    Debug.Print("Found completed row at row " + r);
                    if (PlayField.Flags.HasFlag(TetrisField.GameFlags.Flags_Hotline) && PlayField.HotLines.ContainsKey(r))
                    {
                        Debug.Print("Found hotline row at row " + r);
                        HotLines.Add(PlayField.HotLines[r]);
                    }
                    CompletedRows.Add(r);
                    rowsfound++;
                    //enqueue an action to perform the clear. We'll be replacing the current state with a clear action state, so this should execute AFTER that state returns control.
                    var r1 = r;
                    AfterClearActions.Add
                        (() =>
                    {
                        for (int g = r1; g > 0; g--)
                        {
                            Debug.Print("Moving row " + (g - 1).ToString() + " to row " + g);

                            for (int i = 0; i < PlayField.ColCount; i++)
                            {
                                PlayField.Contents[g][i] = PlayField.Contents[g - 1][i];
                            }
                        }
                    });
                }
            }
            AfterClearActions.Add(() => { PlayField.HasChanged = true; });

            long PreviousLineCount = Statistics.LineCount;

            if (Trigger != null)
            {
                Statistics.AddLineCount(Trigger.GetType(), rowsfound);
            }

            if ((PreviousLineCount % 10) > (Statistics.LineCount % 10))
            {
                state.InvokePlayFieldLevelChanged(state, new TetrisField.LevelChangeEventArgs((int)Statistics.LineCount / 10));
                Statistics.SetLevelTime(pOwner.GetElapsedTime());

                state.Sounds.PlaySound(pOwner.AudioThemeMan.LevelUp.Key, pOwner.Settings.std.EffectVolume);
                PlayField.SetFieldColors(this);
                state.f_RedrawStatusBitmap = true;
            }

            if (rowsfound > 0 && rowsfound < 4)
            {
                Sounds.PlaySound(pOwner.AudioThemeMan.ClearLine.Key, pOwner.Settings.std.EffectVolume * 2);
            }
            else if (rowsfound == 4)
            {
                Sounds.PlaySound(pOwner.AudioThemeMan.ClearTetris.Key, pOwner.Settings.std.EffectVolume * 2);
            }


            int topmost = PlayField.RowCount;

            //find the topmost row with any blocks.
            for (int i = 0; i < PlayField.RowCount; i++)
            {
                if (PlayField.Contents[i].Any((w) => w != null))
                {
                    topmost = i;
                    break;
                }
            }

            topmost = topmost + rowsfound; //subtract the rows that were cleared to get an accurate measurement.
            if (topmost < 9)
            {
                if (state.currenttempo == 1)
                {
                    state.currenttempo = 68;
                    if (GameOptions.MusicRestartsOnTempoChange)
                    {
                        if (GameOptions.MusicEnabled)
                        {
                            Sounds.PlayMusic(pOwner.AudioThemeMan.BackgroundMusic.Key, pOwner.Settings.std.MusicVolume, true);
                        }
                    }

                    var grabbed = Sounds.GetPlayingMusic_Active();
                    if (grabbed != null)
                    {
                        Sounds.GetPlayingMusic_Active().Tempo = 75f;
                    }
                }
            }
            else
            {
                if (state.currenttempo != 1)
                {
                    state.currenttempo = 1;
                    if (GameOptions.MusicRestartsOnTempoChange)
                    {
                        if (GameOptions.MusicEnabled)
                        {
                            if (pOwner.Settings.std.MusicOption == "<RANDOM>")
                            {
                                Sounds.PlayMusic(pOwner.AudioThemeMan.BackgroundMusic.Key, pOwner.Settings.std.MusicVolume, true);
                            }
                            else
                            {
                                Sounds.PlayMusic(pOwner.Settings.std.MusicOption, pOwner.Settings.std.MusicVolume, true);
                            }
                        }
                    }
                    var grabbed = Sounds.GetPlayingMusic_Active();
                    if (grabbed != null)
                    {
                        grabbed.Tempo = 1f;
                    }
                }
            }

            PlayField.HasChanged |= rowsfound > 0;

            if (rowsfound > 0)
            {
                var ClearState = new FieldLineActionGameState(state, CompletedRows.ToArray(), AfterClearActions);
                ClearState.ClearStyle = TetrisGame.Choose((FieldLineActionGameState.LineClearStyle[])(Enum.GetValues(typeof(FieldLineActionGameState.LineClearStyle))));

                pOwner.CurrentState = ClearState;
            }

            //if(rowsfound > 0) pOwner.CurrentState = new FieldLineActionDissolve(this,CompletedRows.ToArray(),AfterClearActions);
            var scoreresult = GetScore(rowsfound, HotLines, state, pOwner, Trigger);

            pOwner.Feedback(0.9f * (float)scoreresult, scoreresult * 250);
            FCR.ScoreResult = rowsfound;
            return(FCR);
        }
Beispiel #14
0
        public override Nomino PerformGetNext()
        {
            //First, we need to see what we CAN choose from.
            //We are slightly limited- if the functions give back varied results or something then it might act weird.
            //Take all the available groups and turn it into a Nomino.
            var availablegroups = from b in _Available select b();

            NominoBlock[][] CurrentState = BestCaseScenario != null ? BestCaseScenario.State : _State.PlayField.Contents;
            //alrighty. Now, we take those available groups and get available board states for each one.
            Dictionary <Nomino, IEnumerable <StoredBoardState> > StateEvaluation = new Dictionary <Nomino, IEnumerable <StoredBoardState> >();

            foreach (Nomino b in availablegroups)
            {
                StateEvaluation.Add(b, StandardNominoAI.GetPossibleResults(CurrentState, b, AIRules));
            }

            Dictionary <Nomino, double>           FinalScores = new Dictionary <Nomino, double>();
            Dictionary <Nomino, StoredBoardState> BestStates  = new Dictionary <Nomino, StoredBoardState>();
            Dictionary <Nomino, StoredBoardState> WorstStates = new Dictionary <Nomino, StoredBoardState>();

            //OK, now we need to evaluate the possibilities returned by each. Basically turn them into an array of scores and create the appropriate data in the Dictionaries.
            foreach (var kvp in StateEvaluation)
            {
                List <double>    AllScores      = new List <double>();
                double           Maximum        = double.MinValue;
                double           Minimum        = double.MaxValue;
                StoredBoardState CurrentMaximum = null;
                StoredBoardState CurrentMinimum = null;
                foreach (var iterate in kvp.Value)
                {
                    double GrabScore = iterate.GetScore(typeof(GameStates.GameHandlers.StandardTetrisHandler), AIRules);
                    if (GrabScore > Maximum)
                    {
                        Maximum        = GrabScore;
                        CurrentMaximum = iterate;
                    }

                    if (GrabScore < Minimum)
                    {
                        Minimum        = GrabScore;
                        CurrentMinimum = iterate;
                    }

                    AllScores.Add(GrabScore);
                }

                if (AllScores.Count > 0)
                {
                    BestStates[kvp.Key]  = CurrentMaximum;
                    WorstStates[kvp.Key] = CurrentMinimum;
                    var Average = AllScores.Average();
                    FinalScores.Add(kvp.Key, Maximum);
                    //FinalScores.Add(kvp.Key, new double[] { Average, Maximum, Minimum }.Average());
                }
            }

            var ordered = FinalScores.OrderBy((o) => o.Value).ToList();
            //select the "winning" FinalScore.
            var crappiest = ordered.FirstOrDefault(); //the lowest value. This is the block with the lowest "maximum" in terms of positive aspects.

            if (crappiest.Key == null)
            {
                BestCaseScenario = null;
                return(TetrisGame.Choose(availablegroups));
            }
            else
            {
                Nomino ChosenGroup = crappiest.Key;

                //now, what was the best possible board state possible with this crappiest one?
                BestCaseScenario = BestStates[ChosenGroup];

                return(ChosenGroup);
            }
        }