//Runs a simulation with a given piece of scoring data, and board width and height, and runs one simulated game using that scoring for AI determination and //returns a valuation of the resulting gameplay using the scoring algorithm with those weights. public static double RunSimulation(StoredBoardState.TetrisScoringRuleData scoredata, int BoardWidth = 10, int BoardHeight = 22) { Debug.Print($"--------Running Simulation " + scoredata.ToString() + "-----"); //create the chooser. BlockGroupChooser bgc = new BagChooser(Tetromino.StandardTetrominoFunctions); List <Nomino> ChosenNominos = new List <Nomino>(); NominoBlock[][] Contents = new NominoBlock[TetrisField.DEFAULT_ROWCOUNT][]; for (int row = 0; row < TetrisField.DEFAULT_ROWCOUNT; row++) { Contents[row] = new NominoBlock[TetrisField.DEFAULT_COLCOUNT]; } int Placedpieces = 0; int rowsFinished = 9; bool GameEnded = false; int nominoCount = 0; while (!GameEnded) { //get the next Nomino. var nextNomino = bgc.RetrieveNext(); ChosenNominos.Add(nextNomino); //Debug.Print("Processing new Nomino:" + nextNomino.SpecialName); var PossibleBoardResults = StandardNominoAI.GetPossibleResults(Contents, nextNomino, scoredata); //score each one based on the scoring rules. var BestScore = (from p in PossibleBoardResults orderby p.GetScore(typeof(GameStates.GameHandlers.StandardTetrisHandler), scoredata) descending select p).FirstOrDefault(); if (BestScore != null) { // we go with the best scoring value of course. Contents = BestScore.State; String NewStateString = BestScore.GetBoardString(); //Debug.Print("Found best score location for new Nomino. Board State:"); //Debug.Print("\n\n" + NewStateString); Placedpieces++; } int RemoveLines = RemoveFinishedRows(ref Contents); rowsFinished += (RemoveLines * RemoveLines); //square it, reason is to give higher scores for AI that manages to land more multi-line clears. //if the top line has a block than we will consider it Game Ended. if (Contents[0].Any((r) => r != null)) { GameEnded = true; } } //Debug.Print("Final Score:" +rowsFinished + Placedpieces); //Debug.Print($"----------------Completed Simulation Bumpiness:{scoredata.BumpinessScore}, Height:{scoredata.AggregateHeightScore}, Hole:{scoredata.HoleScore}, Row:{scoredata.RowScore} --------"); return(rowsFinished + Placedpieces); //return score for this simulation. }
public StoredBoardState(NominoBlock[][] InitialState, Nomino pGroup, int pXOffset, int pRotationCount) { RowCount = InitialState.GetUpperBound(0); ColCount = InitialState[0].GetUpperBound(0); _BoardState = StandardNominoAI.DuplicateField(InitialState); _SourceGroup = new Nomino(pGroup); XOffset = pXOffset; RotationCount = pRotationCount; foreach (var resetblock in _SourceGroup) { resetblock.Block = new StandardColouredBlock(); } for (int i = 0; i < RotationCount; i++) { _SourceGroup.Rotate(false); } //move the Nomino by the specified offset... _SourceGroup.RecalcExtents(); /* * if(_SourceGroup.GroupExtents.Left+_SourceGroup.X+XOffset < 0 || _SourceGroup.GroupExtents.Right+XOffset+_SourceGroup.X > _BoardState[0].Length) * { * InvalidState = true; //nothing else to do- this is an invalid state as the move puts us "off" the board. * } * else*/ { //get our board state... try { DropBlock(_SourceGroup, ref _BoardState, pXOffset); } catch (Exception exx) { InvalidState = true; return; } } }