public static IEnumerable <StoredBoardState> GetPossibleResults(NominoBlock[][] Source, Nomino bg, StoredBoardState.BoardScoringRuleData rules) { //Debug.Print("Calculating possible results:" + Source.Sum((u)=>u.Count((y)=>y!=null)) + " Non null entries."); for (int useRotation = 0; useRotation < 4; useRotation++) { for (int x = -5; x < Source[0].Length + 5; x++) { if (rules.StupidFactor < 1) { if (TetrisGame.rgen.NextDouble() < rules.StupidFactor) { continue; } } Nomino cloneFor = new Nomino(bg); foreach (var resetblock in cloneFor) { resetblock.Block = new StandardColouredBlock(); } int XOffset = x - bg.X; StoredBoardState BuildState = new StoredBoardState(Source, cloneFor, XOffset, useRotation); if (!BuildState.InvalidState) { yield return(BuildState); } } } }
private void PushButtonInputs(StoredBoardState sbs) { for (int i = 0; i < sbs.RotationCount; i++) { PressKeyQueue.Enqueue(GameState.GameKeys.GameKey_RotateCW); } if (sbs.XOffset < 0) { for (int i = 0; i < Math.Abs(sbs.XOffset); i++) { PressKeyQueue.Enqueue(GameState.GameKeys.GameKey_Left); } } else if (sbs.XOffset > 0) { for (int i = 0; i < Math.Abs(sbs.XOffset); i++) { PressKeyQueue.Enqueue(GameState.GameKeys.GameKey_Right); } } for (int i = 0; i < 5; i++) { PressKeyQueue.Enqueue(GameState.GameKeys.GameKey_Null); } PressKeyQueue.Enqueue(GameState.GameKeys.GameKey_Drop); }
public override void AIActionFrame() { //do our hard thinking here. //first we only do stuff with the standard game state. if (_Owner == null) { return; } if (_Owner.CurrentState is GameplayGameState) { GameplayGameState stdState = _Owner.CurrentState as GameplayGameState; //next, we only want to do stuff if there is one active blockgroup... if (stdState.PlayField.GetActiveBlockGroups().Count == 1) { //todo: we want to copy the playfield for our inspection here... we'll want to see what happens based on moving the blockgroup left or right up to each side and dropping it and evaluate the result to select the ideal //then slap those keys into the queue. Nomino ActiveGroup = stdState.PlayField.BlockGroups[0]; var PossibleStates = GetPossibleResults(stdState.PlayField.Contents, ActiveGroup, ScoringRules).ToList(); Debug.Print("Found " + PossibleStates.Count + " possible states..."); var Sorted = (ScoringRules.Moronic?PossibleStates.OrderByDescending((w) => TetrisGame.rgen.Next()): PossibleStates.OrderByDescending((w) => w.GetScore(stdState.GameHandler.GetType(), ScoringRules))).ToList(); //var Scores = (from p in PossibleStates orderby p.GetScore(ScoringRules) descending select new Tuple<StoredBoardState, double>(p, p.GetScore(ScoringRules))).ToArray(); /*foreach (var writedebug in Scores) * { * Debug.Print("Possible State: Move " + writedebug.Item1.XOffset + ", Rotate " + writedebug.Item1.RotationCount + " To get score " + writedebug.Item1.GetScore(ScoringRules)); * Debug.Print("What it will look like\n" + writedebug.Item1.GetBoardString()); * Debug.Print("------"); * }*/ var maximumValue = Sorted.FirstOrDefault(); Debug.Print("Best Move: Move " + maximumValue.XOffset + ", Rotate " + maximumValue.RotationCount + " To get score " + maximumValue.GetScore(stdState.GameHandler.GetType(), ScoringRules)); Debug.Print("What it will look like\n" + maximumValue.GetBoardString()); Debug.Print("------"); //int randomint = TetrisGame.rgen.Next(Scores.Length); //int randomint2 = TetrisGame.rgen.Next(Scores.Length); //StoredBoardState FirstState = Scores[randomint2].Item1; StoredBoardState IdealState = maximumValue; PushButtonInputs(IdealState); //if(maximumValue!=null) //{ // PushButtonInputs(maximumValue); //} } } }
public double CalculateScore(StoredBoardState.BoardScoringRuleData data, StoredBoardState state) { StoredBoardState.DrMarioScoringRuleData dat = data as StoredBoardState.DrMarioScoringRuleData; var FieldColumnScore = GetFieldColumnScore(dat, state); Debug.Print("Field Column Score:" + FieldColumnScore); double MassScore = 0; foreach (var iterate in FindMasses(dat, state)) { int VirusCount = (from c in iterate.MassContents where c is LineSeriesPrimaryBlock select c).Count(); double AddScore = ((double)VirusCount) * dat.MasterBlockMassValue + iterate.MassSize; MassScore += AddScore; } return(FieldColumnScore + MassScore); //basically random, I think. //throw new NotImplementedException(); }
public double CalculateScore(BoardScoringRuleData Data, StoredBoardState state) { var Rules = Data as TetrisScoringRuleData; int Rows = GetCompletedLines(state.State); int Aggregate = GetAggregateHeight(state.State); int Holes = GetHoles(state.State); int Bumpy = GetBumpiness(state.State); int Crevice = GetCrevasses(state.State); //Debug.Print("Rows=" + Rows + " Aggregate=" + Aggregate + " Holes=" + Holes + " Bumps=" + Bumpy); //double a = -0.610066f; //double b = 0.760666; //double c = -0.55663; ////double d = -.184483; //double d = -.384483; double CreviceScore = (Rules.CrevasseScore * (double)Crevice); return((Rules.AggregateHeightScore * (double)Aggregate) + (Rules.RowScore * (double)Rows) + (Rules.HoleScore * (double)Holes) + (Rules.BumpinessScore * (double)Bumpy) + CreviceScore); }
private IEnumerable <LineSeriesBlock> FindHorizontalMass(StoredBoardState.DrMarioScoringRuleData data, StoredBoardState state, int pRow, int pCol, LineSeriesBlock.CombiningTypes MatchingIndex, List <LineSeriesBlock> InConsiderables) { int CurrR = pRow, CurrC = pCol; //look to the left while (state.State[CurrR][CurrC] is LineSeriesBlock lsb && lsb.CombiningIndex == MatchingIndex && CurrC > 0) { CurrC--; } int FirstC = CurrC; int CheckC = FirstC; if (CurrC != FirstC) { //we have a horizontal group. let's grab the blocks. while (state.State[CurrR][CheckC] is LineSeriesBlock lsb && lsb.CombiningIndex == MatchingIndex && CurrC < state.ColCount - 1) { if (InConsiderables.Contains(lsb)) { break; } CheckC++; yield return(lsb); } } }
public double GetFieldColumnScore(StoredBoardState.DrMarioScoringRuleData data, StoredBoardState state) { List <List <double> > AllColumnRuns = new List <List <double> >(); for (int c = 0; c < state.ColCount; c++) { List <double> ColumnRuns = new List <double>(); int CurrentRun = 0; int MasterCount = 0; int Interfacecount = 0; //number of changes. bool ResetHandled = false; LineSeriesBlock.CombiningTypes?currentType = null; for (int r = 0; r < state.RowCount; r++) { ResetHandled = false; if (state.State[r][c] is LineSeriesBlock lsb) { if (state.State[r][c] is LineSeriesPrimaryBlock) { MasterCount++; } if (currentType == null) { currentType = lsb.CombiningIndex; } if (currentType == lsb.CombiningIndex) { CurrentRun++; } else if (currentType != lsb.CombiningIndex) { Interfacecount++; ResetHandled = true; ColumnRuns.Add(CurrentRun * ((MasterCount + 1) * data.MasterBlockColumnMultiplier)); CurrentRun = 1; MasterCount = 0; currentType = lsb.CombiningIndex; } } } if (!ResetHandled) { ColumnRuns.Add(CurrentRun * ((MasterCount + 1) * data.MasterBlockColumnMultiplier)); } AllColumnRuns.Add(ColumnRuns); } //want longer runs, but, we also want to avoid stacking colours on top of unmatched colours, so we give weight to //the number of scores we accumulated in the row. return((from co in AllColumnRuns select(co.Sum() - (co.Count * co.Count))).Sum()); }
//DrMario Scoring: //Lines are worthless, obviously //Critical Masses add lots of value //groups of the same colour add value //additionally, columns of a colour with only air in-between as well as possible colour drops //(if the bottom colour of a stuck stack fell as far as it could would line up with other of the same colour public IEnumerable <MassItem> FindMasses(StoredBoardState.DrMarioScoringRuleData data, StoredBoardState state) { List <LineSeriesBlock> ConsideredResults = new List <LineSeriesBlock>(); for (int r = 0; r < state.RowCount; r++) { for (int c = 0; c < state.ColCount; c++) { if (state.State[r][c] is LineSeriesBlock lsb) { //check for a mass here. var HorizontalMass = FindHorizontalMass(data, state, r, c, lsb.CombiningIndex, ConsideredResults).ToList(); var VerticalMass = FindVerticalMass(data, state, r, c, lsb.CombiningIndex, ConsideredResults).ToList(); ConsideredResults.Add(lsb); if (HorizontalMass.Count > 1) { MassItem HorzMass = new MassItem(HorizontalMass); yield return(HorzMass); } if (VerticalMass.Count > 1) { MassItem VertMass = new MassItem(VerticalMass); yield return(VertMass); } } } } }
private IEnumerable <LineSeriesBlock> FindVerticalMass(StoredBoardState.DrMarioScoringRuleData data, StoredBoardState state, int pRow, int pCol, LineSeriesBlock.CombiningTypes MatchingIndex, List <LineSeriesBlock> InConsiderables) { int CurrR = pRow, CurrC = pCol; //look above. while (state.State[CurrR][CurrC] is LineSeriesBlock lsb && lsb.CombiningIndex == MatchingIndex && CurrR > 0) { CurrR--; } int FirstR = CurrR; int CheckR = FirstR; if (CurrR != FirstR) { //we have a vertical group. Lets see what blocks. So from the starting point, //check each block until air, or until we see a different coloured block OR we reach the other side of the stage. while (state.State[CheckR][CurrC] is LineSeriesBlock lsb && lsb.CombiningIndex == MatchingIndex && CurrC < state.ColCount - 1) { if (InConsiderables.Contains(lsb)) { break; } CheckR++; yield return(lsb); } } }