/// <summary> /// 削除できる可能性のあるスライムの分析する /// </summary> /// <param name="context">フィールド状態</param> /// <param name="player">プレイヤ</param> /// <param name="param">パラメータ</param> /// <returns>削除できる可能性のあるスライム数</returns> public int Analyze(FieldContext context, Player.Index player, Param param) { Debug.Assert(param.TargetSlime != Slime.None, "対象スライムがNoneはありえません"); var _context = context.DeepCopy(); // フィールドから削除対象のスライムを削除する foreach (var slime in param.ErasedSlimes) { if (slime == param.TargetSlime) { continue; } _context.SlimeFields[(int)player][slime] = Enumerable.Range(0, FieldContextConfig.FieldUnitCount).Select(i => 0u).ToArray(); } // 移動可能スライムも落下させたいので、情報のみ場外においやってしまう MovableSlime.ForEach(index => { var movable = _context.MovableSlimes[(int)player][(int)index]; movable.Index = 0; movable.Position = (int)index; }); // 重力ですべて落下させる this.Gravity.Update(_context, player, GravityParam); // スライムを消済にマーキングする this.ErasingMarker.Update(_context, player, ErasingMarkerParam); // 消済スライム数をカウントする return(SlimeCountHelper.GetSlimeCount(_context, player, Slime.Erased)); }
/// <summary> /// フィールドの特徴を生成します。 /// </summary> /// <param name="context"></param> /// <returns>フィールドの特徴</returns> public SparseVector <double> GetNext(FieldContext context) { var vector = new SparseVector <double>(0.0d); var param = new ErasedPotentialSlimeAnalyzer.Param(); param.ErasedSlimes = context.UsingSlimes; var players = new[] { Player.Index.First, Player.Index.Second }; foreach (var player in players) { if (!this.OwnConfig.BothPlayer && player != context.OperationPlayer) { continue; } var erasedPotentialCount = 0; var slimeCount = 0; foreach (var slime in context.UsingSlimes) { param.TargetSlime = slime; if (this.OwnConfig.TargetFeatue[Feature.ErasedPotentialCount]) { // 他の色を消すと消える個数 erasedPotentialCount += ErasedPotentialSlimeAnalyzer.Analyze(context, player, param); } if (this.OwnConfig.TargetFeatue[Feature.SlimeCount]) { // フィールドのスライム数 slimeCount += SlimeCountHelper.GetSlimeCount(context, player, slime); } } if (this.OwnConfig.TargetFeatue[Feature.ErasedPotentialCount]) { vector.Add(erasedPotentialCount); } if (this.OwnConfig.TargetFeatue[Feature.SlimeCount]) { vector.Add(slimeCount); } if (this.OwnConfig.TargetFeatue[Feature.ObstructionCount]) { // フィールドのおじゃまスライム数 var obstructionCount = SlimeCountHelper.GetSlimeCount(context, player, Slime.Obstruction); vector.Add(obstructionCount); } if (this.OwnConfig.TargetFeatue[Feature.NoticeObstruction]) { // 予告おじゃまスライム数 var noticeObstruction = ObstructionSlimeHelper.ObstructionsToCount(context.ObstructionSlimes[(int)player]); vector.Add(noticeObstruction); } if (this.OwnConfig.TargetFeatue[Feature.HeightDiff]) { // 高低差 var hDiff = DifferenceHeightAnalyzer.Analyze(context, player); vector.Add(hDiff); } if (this.OwnConfig.TargetFeatue[Feature.UpperCount]) { // 上部スライム数 var upperCount = 0; foreach (var u in UpperUnits) { foreach (var i in UpperIndexes) { upperCount += FieldContextHelper.ExistsSlime(context, player, FieldContextConfig.MaxHiddenUnitIndex + u, i) ? 1 : 0; } } vector.Add(upperCount); } if (this.OwnConfig.TargetFeatue[Feature.DangerCount]) { // 左から3番目のスライム数 var dangerCount = 0; foreach (var u in DangerUnits) { foreach (var i in DangerIndexes) { dangerCount += FieldContextHelper.ExistsSlime(context, player, FieldContextConfig.MaxHiddenUnitIndex + u, i) ? 1 : 0; } } vector.Add(dangerCount); } if (this.OwnConfig.TargetFeatue[Feature.Chain]) { // 起こりうる最大連鎖数 var chain = 0; if (player == context.OperationPlayer) { chain = this.ChainAnalyzer.Analyze(context, player); } vector.Add(chain); } } ; return(vector); }