private bool AddBroken( AnalizeData result, int rate = 1 ){ result.Score += BrokenScore * 1; result.BrokenCount++; if( result.BrokenCount > BrokenLimit ) return true; return false; }
// //Trueを返した場合、中断して十分に低いスコアを返す private bool CheckSolidGroup( AnalizeData result, BlockGroup g, bool first, int pos, int sum, ModelBlock empty = null, int emptyCount = 0 ){ if( g.Counter != AnalizeCounter ){ g.Reset(); g.Counter = AnalizeCounter; }else if( g.Broken || g.Success ) return false; var blocks = g.Blocks; for( int l = blocks.Count, max = l + 1; pos < l; pos++ ){ var b = blocks[pos]; if( b.Number > 0 ) sum += b.Number; else if( emptyCount++ == 0 ) empty = b; } if( sum > Sum - emptyCount ){ g.Success = true; //if( first ) result.Score += SolidScore * g.FamilyNum; return false; }else{ if( emptyCount == 0 ){ if( sum == Sum ){ if( AddBrokenGroup( result, g ) ) return true; return false; }else if( sum > Sum ){ g.Success = true; return false; //if( first ) result.Score += SolidScore * g.FamilyNum; } }else if( emptyCount == 1 ){ int bc = empty.LifeNum; int c = empty.KillAt( Sum - sum ); if( bc != c ){ if( c == 0 ){ if( AddBrokenBlock( result, empty ) ) return true; return false; }else{ Changed = true; if( c == 1 ){ empty.Number = Array.IndexOf( empty.DeadList, false ) + 1; sum += empty.Number; empty = null; emptyCount--; if( sum > Sum ){ g.Success = true; return false; } } } } } } var children = g.Children; if( children != null ) for( int i = 0, l = children.Count; i < l; i++ ) if( CheckSolidGroup( result, children[i], first, pos, sum, empty, emptyCount ) ) return true; return false; }
private bool AddBrokenGroup( AnalizeData result, BlockGroup g ){ if( g.Broken ) return false; g.Broken = true; foreach( var b in g.Blocks ) b.GroundNG = true; return AddBroken(result); }
private bool AddBrokenBlock( AnalizeData result, ModelBlock b ){ if( b.Broken ) return false; b.GroundNG = b.Broken = true; return AddBroken(result); }
//連鎖の一部の数字チェック private bool CheckChainGroup( AnalizeData result, BlockGroup g, int num, bool first ){ if( g.Broken || g.Success ) return false; List<ModelBlock> emptys = new List<ModelBlock>(); var emptyCount = 0; int sum = 0; SegAdded = false; for( int j = g.Blocks.Count - 1; j >= 0; j-- ){ var b = g.Blocks[j]; if( b.Number > 0 ){ int bn = b.Number; sum += bn; if( bn > Sum ) if( AddBrokenBlock( result, b ) ) return true; if( sum + j + emptyCount > Sum ){ if( AddBrokenGroup( result, g ) ) return true; return false; } }else{ emptyCount++; emptys.Add( b ); } } if( emptyCount == 0 ){ if( sum == Sum ){ g.Success = true; if( first ){ int d = 4 + num; if( d > 40 ) d = 40; result.Score += BingoScore * g.Blocks[0].ScoreRate * 40 / d; result.BingoCount++; SegCount++; SegAdded = true; } }else{ if( AddBrokenGroup( result, g ) ) return true; } }else{ if( first ){ int d = 4 + num; if( d > 40 ) d = 40; result.Score += (g.Blocks.Count - emptyCount) * LizhiScore * g.Blocks[0].ScoreRate * 40 / d; } if( emptyCount == 1 ){ emptys[0].Number = Sum - sum; g.Success = true; }else if( emptyCount == 2 && !first ){ //片方の候補の消去を、もう片方に反映。 int max = Sum - sum - 1; if(emptys[0].LifeNum < max || emptys[1].LifeNum < max){ var e0 = emptys[0]; var e1 = emptys[1]; var d0 = e0.DeadList; var d1 = e1.DeadList; for( int i = 0; i < max; i++ ){ if( d0[i] == true ) e1.KillAt( max - i ); if( d1[i] == true ) e0.KillAt( max - i ); } int c = e0.LifeNum; if( c == 0 ){ if( AddBrokenBlock( result, e0 ) ) return true; if( AddBrokenBlock( result, e1 ) ) return true; g.Broken = true; }else if( c == 1 ){ e0.Number = Array.IndexOf( e0.DeadList, false ) + 1; e1.Number = Array.IndexOf( e1.DeadList, false ) + 1; g.Success = true; } } } } return false; }
//連鎖の進行度計算 public void CalcScore( Game game, AnalizeData result ){ AnalizeCounter++; Changed = false; //空領域を確認 foreach( ModelBlock b in MustBlocks ) if( b.MustNumber == b.Number){ if( b.End && b.Number != 0 ) AddBrokenBlock( result, b ); else{ result.Score += BingoScore * b.ScoreRate * 8; result.BingoCount++; } }else{ if( b.Number != 0 ){ if( b.Number > Sum ) AddBrokenBlock( result, b ); else{ result.Score += GroundNGScore; b.GroundNG = true; } } b.Number = b.MustNumber; } foreach( ModelBlock b in CeilBlocks ) if( b.Number != 0 ) if(b.Number > Sum) result.Score += CeilScore * 4; else result.Score += CeilScore; foreach( ModelBlock b in GroundBlocks ) if( b.Number > Sum ){ result.Score += GroundScore * b.ScoreRate; result.Score += (Height - b.Y) * GroundHScore; }else if(b.Number != 0){ result.Score += GroundNGScore; b.GroundNG = true; }else{ b.Number = Sum + 1; } SegCount = 0; var first = true; int count = 0; do{ Changed = false; for(int i = 0, l = ChainGroups.Count; i < l; i++){ if( CheckChainGroup( result, ChainGroups[i], i, first ) ) return; if( first && !SegAdded && SegCount > 0 ){ result.ChainSegs.Add( SegCount ); SegCount = 0; } } for( int i = 0, il = RootSolidGroups.Count; i < il; i++ ) if( CheckSolidGroup( result, RootSolidGroups[i], first, 0, 0 ) ) return; first = false; }while( Changed || count++ < 2 ); //間違ったブロックの上に邪魔ブロックを置かない for( int i = 0; i < Width; i++ ){ double c = 0; var row = Model[i]; for( int j = Bottom; j < Height; j++ ){ var b = row[j]; if( c > 0 ){ var n = game.Field[i][j]; if( n > Sum ){ result.Score += BrokenScore * c; }else{ result.Score += GroundNGScore * c; } } if( b.GroundNG ) c += b.ScoreRate; } } }
//連鎖の状態を分析する。 public AnalizeData Analize( Game game, bool outon = false ){ AnalizeData result = new AnalizeData(); Reset( game ); CalcScore( game, result ); //SimulateChain( game, result, outon ); result.Score += result.MaxChain * MaxChainScore; foreach( int c in result.ChainSegs ) result.Score += (c - 1) * ChainScore; return result; }