//パターンを配置 public void SetPattern( ModelBlock[][] model, Pattern pattern, int chain, int x, int y, int dir ){ object[,] data = pattern.Data; for( int i = 0; i < pattern.Width; i++ ){ for( int j = 0; j < pattern.Height; j++ ){ object cell = data[j,i]; int mx = x + i * dir; int my = y + pattern.Height - j - 1; if( cell is int ){ int num = chain + (int)cell; model[mx][my] = new ModelBlock(IDCount++, mx, my, num, num, false, pattern.ScoreRate); }else if( cell == ChainConfig.E ){ model[mx][my] = new ModelBlock(IDCount++, mx, my, -1, int.MaxValue, true, 1, 0 ); }else if( cell is int[] ){ int[] nums = cell as int[]; model[mx][my] = new ModelBlock(IDCount++, mx, my, nums[0], nums[2], false, 1, nums[1]); }else{ if( model[mx][my] == null ){ model[mx][my] = new ModelBlock(IDCount++, mx, my, -1, int.MaxValue, false, pattern.ScoreRate); }else{ if( model[mx][my].ScoreRate < pattern.ScoreRate ) model[mx][my].ScoreRate = pattern.ScoreRate; } } } } }
//足場の保存期間を指定、ブロックの空きを埋める。 public void SetupModel( ModelBlock[][] model, Game game, int bottom ){ for( int i = 0, w = model.Length; i < w; i++ ){ int min = int.MaxValue; for( int j = model[i].Length - 1; j >= 0; j--){ if( model[i][j] == null ){ if( j < bottom && game.Field[i][j] > Game.Sum ) model[i][j] = new ModelBlock(IDCount++, i, j, -1, min, false, 1, game.Field[i][j] ); else model[i][j] = new ModelBlock(IDCount++, i, j, -1, min); continue; } var block = model[i][j]; if( block.Chain >= 0 ) if( min > block.Chain ) min = block.Chain; if( block.Ground == int.MaxValue ) block.Ground = min; } } }
public ChainModel( Game game, ChainFactory factory, int chainLimit, bool haiteiMode, ModelSetting setting ){ setting.Setup( this ); Width = Game.Width; Height = Game.Height + Game.Size; Sum = Game.Sum; ChainLimit = chainLimit; HaiteiMode = haiteiMode; AllBlocks = new List<ModelBlock>(); ChainGroups = new List<BlockGroup>(); SolidGroups = new List<BlockGroup>[Sum - 1]; for(int i = 0; i < (Sum - 1); i++) SolidGroups[i] = new List<BlockGroup>(); Model = new ModelBlock[Width][]; for(int i = 0; i < Width; i++) Model[i] = new ModelBlock[Height]; factory.Make( this, game, ChainLimit ); for(int i = 0; i < ChainLimit; i++) ChainGroups.Add( new BlockGroup( new List<ModelBlock>() ) ); SetupGroup( game ); Reset( game ); }
/* private void SimulateChain(Game game, AnalizeData result, bool outon){ Output = ""; //ChainBlocksの位置にあるブロックを後ろから消していき、 //発生した連鎖数を数える。 for(int i = ChainLimit - 1; i >= 0; ){ if( outon ) { Output += ModelOutput(Model,game); } i = DeleteChain( game, result, i ); } //result.Score += result.Chain * ChainScore; } //ゲーム状態の変化に連鎖モデルの変化を同期させる。 private int DeleteChain( Game game, AnalizeData result, int headNum ){ List<ModelBlock> delete = ChainGroups[headNum].Blocks; var Field = game.Field; var HeightList = game.HeightList; //消去位置をマーク int count = 0, l = delete.Count, sum = 0; for(int i = 0; i < l; i++){ ModelBlock b = delete[i]; if( b == null || b.Dead ){ continue; } var val = Field[b.X][b.Y]; if( val == 0 ) continue; sum += val; Field[b.X][b.Y] |= 0x800000; game.Marked[b.X] = true; } if( sum != Game.Sum ){ for(int i = 0; i < l; i++){ ModelBlock b = delete[i]; sum += Field[b.X][b.Y]; } } bool perfect = true; int chain = 0; int num = headNum; int next = headNum - 1; Output += "start:" + headNum + "\n"; game.ChangedLeft = 0; game.ChangedRight = Game.Width; game.ChangedBottom = 0; game.ChangedTop = Game.Height + Game.Size; //連鎖を見る do{ Output += "count:" + count + "\n"; chain++; int hitNum = 0; //目印を付けた部分を削除 for(int i = 0, il = Width; i < il; i++){ if(! game.Marked[i] ){ game.Marked[i] = false; continue; } var row = Field[i]; var mr = Model[i]; int h = HeightList[i]; int k = 0; for(int j = 0; j < h; j++ ){ int val = row[j]; if( j != k ){ row[k] = val; var b = mr[k] = mr[j]; if( b != null ){ b.Y = k; } } if( (val & 0x800000) == 0 ) k++; else{ var b = mr[j]; if( b != null ){ b.Dead = true; if( b.Chain == num ){ hitNum++; } } } } for(; k < Height; k++){ row[k] = 0; mr[k] = null; } } Output += "num:" + num + "\n"; if( perfect && num != headNum && num >= 0 ){ if( hitNum != ChainGroups[num].Blocks.Count ){ perfect = false; next = num - 1; if( headNum - num > 1 ){ result.ChainSegs.Add( headNum - num - 1 ); } } } num--; //新しい消去フラグを探す。 count = game.Mark(); }while( count > 0 ); if( perfect ){ next = num; if( headNum - num > 1 ) result.ChainSegs.Add( headNum - num - 1 ); if( num < 0 ) result.Chain = headNum; } return next; } */ // public string ModelOutput( ModelBlock[][] model, Game game ){ string result = ""; for(int i = Height - 1; i >= 0; i--){ for(int j = 0; j < Width; j++){ var b = game.Field[j][i]; result +=( " " + b.ToString( "D2" ) ); } result +=( "\n" ); } result +=( "\n" ); for(int i = Height - 1; i >= 0; i--){ for(int j = 0; j < Width; j++){ var b = model[j][i]; if( b == null ) result +=( " Nul" ); else if( b.Chain >= 0 ) result +=( " C" + b.Chain.ToString( "D2" ) ); else if( b.MustNumber >= 0 ) result +=( " M" + b.MustNumber.ToString( "D2" ) ); else if( b.Ground != int.MaxValue ) result +=( " G" + b.Ground.ToString( "D2" ) ); else result +=( " Xxx" ); } result +=( "\n" ); } return result + "\n"; }
// //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 AddBrokenBlock( AnalizeData result, ModelBlock b ){ if( b.Broken ) return false; b.GroundNG = b.Broken = true; return AddBroken(result); }
//海底用に発火ブロックの数字をそろえる public void SetHeadNumber( Game game, ModelBlock fire, ModelBlock fired ){ int max = 0; var block = Game.DefaultBlocks[ Game.StepNum - 1 ]; for( int x = 0; x < Game.Size; x++ ){ for( int y = 0; y < Game.Size; y++ ){ var d = block.Data[x,y]; if( d > max && d < Sum ) max = d; } } if( max > 0 ){ fire.MustNumber = max; fired.MustNumber = Sum - max; MustBlocks.Add( fired ); } }