module GameApp . Models { 'use strict' ; export interface IJsonLevel { tiles : number [ ] [ ] ; targetScore : number ; moves : number ; } export class Level { cookies : Cookie [ ] [ ] ; tiles : Tile [ ] [ ] ; possibleSwaps : Swap [ ] ; config : Config ; constructor ( gameConfig ) { this . config = gameConfig ; this . createCookiesArray ( ) ; } shuffle ( ) { var set ; do { set = this . createInitialCookies ( ) ; this . detectPossibleSwaps ( ) ; } while ( this . possibleSwaps . length == 0 ) ; console . log ( this . possibleSwaps ) ; return set ; } isPossibleSwap ( other ) { for ( var i = 0 ; i < this . possibleSwaps . length ; i ++ ) { var possibleSwap = this . possibleSwaps [ i ] ; var isPossible = ( this . isTwoCookiesEquals ( other . cookieA , possibleSwap . cookieA ) && this . isTwoCookiesEquals ( other . cookieB , possibleSwap . cookieB ) ) || ( this . isTwoCookiesEquals ( other . cookieB , possibleSwap . cookieA ) && this . isTwoCookiesEquals ( other . cookieA , possibleSwap . cookieB ) ) ; if ( isPossible ) return true ; } return false ; } getPossibleSwaps ( ) { return this . possibleSwaps ; } createInitialCookies ( ) { var array = [ ] ; for ( var row = 0 ; row < this . config . numRows ; row ++ ) { for ( var column = 0 ; column < this . config . numColumns ; column ++ ) { if ( this . tiles [ column ] [ row ] != null ) { var cookieType = this . calculateCookieType ( column , row ) ; var cookie = this . createCookieAtColumn ( column , row , cookieType ) ; array . push ( cookie ) ; } else { this . cookies [ column ] [ row ] = null ; } } } return array ; } cookieAtPosition ( column , row ) { return this . cookies [ column ] [ row ] ; } tileAtColumn ( column , row ) { return this . tiles [ column ] [ row ] ; } initWithData ( level ) { this . createTilesArray ( ) ; for ( var row = 0 ; row < this . config . numRows ; row ++ ) { for ( var column = 0 ; column < this . config . numColumns ; column ++ ) { var tile = level . tiles [ column ] [ row ] ; if ( tile == 1 ) { this . tiles [ column ] [ row ] = new Tile ( ) ; } else { this . tiles [ column ] [ row ] = null ; } } } } performSwap ( swap ) { var columnA = swap . cookieA . column , rowA = swap . cookieA . row , columnB = swap . cookieB . column , rowB = swap . cookieB . row ; this . cookies [ columnA ] [ rowA ] = swap . cookieB ; swap . cookieB . column = columnA ; swap . cookieB . row = rowA ; this . cookies [ columnB ] [ rowB ] = swap . cookieA ; swap . cookieA . column = columnB ; swap . cookieA . row = rowB ; } removeMatches ( ) { var horizontalChains = this . detectHorizontalMatches ( ) ; var verticalChains = this . detectVerticalMatches ( ) ; this . removeCookies ( horizontalChains ) ; this . removeCookies ( verticalChains ) ; this . calculateScores ( horizontalChains ) ; this . calculateScores ( verticalChains ) ; return horizontalChains . concat ( verticalChains ) ; } calculateScores ( chains ) { chains . forEach ( ( chain ) => { chain . score = 60 * ( chain . cookies . length - 2 ) ; } ) ; } fillHoles ( ) { var columns = [ ] ; for ( var column = 0 ; column < this . config . numColumns ; column ++ ) { var array ; for ( var row = 0 ; row < this . config . numRows ; row ++ ) { if ( this . tiles [ column ] [ row ] != null && this . cookies [ column ] [ row ] == null ) { for ( var lookup = row + 1 ; lookup < this . config . numRows ; lookup ++ ) { var cookie = this . cookies [ column ] [ lookup ] ; if ( cookie != null ) { this . cookies [ column ] [ lookup ] = null ; this . cookies [ column ] [ row ] = cookie ; cookie . row = row ; if ( array == null ) { array = [ ] ; columns . push ( array ) ; } array . push ( cookie ) ; break ; } } } } } return columns ; } topUpCookies ( ) { var columns = [ ] ; var cookieType = 0 ; for ( var column = 0 ; column < this . config . numColumns ; column ++ ) { var array ; for ( var row = this . config . numRows - 1 ; row >= 0 && this . cookies [ column ] [ row ] == null ; row -- ) { if ( this . tiles [ column ] [ row ] != null ) { var newCookieType ; do { newCookieType = GameHelpers . getRandomNumber ( 6 ) ; } while ( newCookieType == cookieType ) ; cookieType = newCookieType ; var cookie = this . createCookieAtColumn ( column , row , newCookieType ) ; if ( array == null ) { array = [ ] ; columns . push ( array ) ; } array . push ( cookie ) ; } } } this . detectPossibleSwaps ( ) ; return columns ; } private createCookieAtColumn ( column , row , cookieType ) { var cookie = new Cookie ( column , row , cookieType ) ; this . cookies [ column ] [ row ] = cookie ; return cookie ; } private createCookiesArray ( ) { this . cookies = new Array ( this . config . numColumns - 1 ) ; for ( var i = 0 ; i < this . config . numColumns ; i ++ ) { this . cookies [ i ] = new Array ( this . config . numRows - 1 ) ; } } private createTilesArray ( ) { this . tiles = new Array ( this . config . numColumns - 1 ) ; for ( var i = 0 ; i < this . config . numColumns ; i ++ ) { this . tiles [ i ] = new Array ( this . config . numRows - 1 ) ; } } private isTwoCookiesEquals ( cookieA , cookieB ) { return cookieA . column == cookieB . column && cookieA . row == cookieB . row && cookieA . cookieType == cookieB . cookieType ; } private hasChainAtColumn ( column , row ) { var cookie = this . cookies [ column ] [ row ] , cookieType ; if ( cookie ) { cookieType = cookie . cookieType ; } else { cookieType = 0 ; } var horzLength = 1 ; for ( var i = column - 1 ; i >= 0 && this . cookies [ i ] [ row ] && this . cookies [ i ] [ row ] . cookieType == cookieType ; i -- , horzLength ++ ) ; for ( var i = column + 1 ; i < this . config . numColumns && this . cookies [ i ] [ row ] && this . cookies [ i ] [ row ] . cookieType == cookieType ; i ++ , horzLength ++ ) ; if ( horzLength >= 3 ) return true ; var vertLength = 1 ; for ( var i = row - 1 ; i >= 0 && this . cookies [ column ] [ i ] && this . cookies [ column ] [ i ] . cookieType == cookieType ; i -- , vertLength ++ ) ; for ( var i = row + 1 ; i < this . config . numRows && this . cookies [ column ] [ i ] && this . cookies [ column ] [ i ] . cookieType == cookieType ; i ++ , vertLength ++ ) ; return ( vertLength >= 3 ) ; } private detectPossibleSwaps ( ) { var possibleSwaps = [ ] ; for ( var row = 0 ; row < this . config . numRows ; row ++ ) { for ( var column = 0 ; column < this . config . numColumns ; column ++ ) { var cookie = this . cookies [ column ] [ row ] ; if ( cookie ) { if ( column < this . config . numColumns - 1 ) { var other = this . cookies [ column + 1 ] [ row ] ; if ( other ) { this . cookies [ column ] [ row ] = other ; this . cookies [ column + 1 ] [ row ] = cookie ; if ( this . hasChainAtColumn ( column + 1 , row ) || this . hasChainAtColumn ( column , row ) ) { var swap = new Swap ( ) ; swap . cookieA = cookie ; swap . cookieB = other ; possibleSwaps . push ( swap ) ; } this . cookies [ column ] [ row ] = cookie ; this . cookies [ column + 1 ] [ row ] = other ; } } if ( row < this . config . numRows - 1 ) { var other = this . cookies [ column ] [ row + 1 ] ; if ( other ) { this . cookies [ column ] [ row ] = other ; this . cookies [ column ] [ row + 1 ] = cookie ; if ( this . hasChainAtColumn ( column , row + 1 ) || this . hasChainAtColumn ( column , row ) ) { var swap = new Swap ( ) ; swap . cookieA = cookie ; swap . cookieB = other ; possibleSwaps . push ( swap ) ; } this . cookies [ column ] [ row ] = cookie ; this . cookies [ column ] [ row + 1 ] = other ; } } } } } this . possibleSwaps = possibleSwaps ; } private calculateCookieType ( column , row ) { var cookieType ; do { cookieType = GameHelpers . getRandomNumber ( this . config . numCookieTypes ) ; } while ( this . whereIsAlreadyTwoCookies ( column , row , cookieType ) ) ; return cookieType ; } private whereIsAlreadyTwoCookies ( column , row , cookieType ) { return ( column >= 2 && this . cookies [ column - 1 ] [ row ] && this . cookies [ column - 2 ] [ row ] && this . cookies [ column - 1 ] [ row ] . cookieType == cookieType && this . cookies [ column - 2 ] [ row ] . cookieType == cookieType ) || ( row >= 2 && this . cookies [ column ] [ row - 1 ] && this . cookies [ column ] [ row - 2 ] && this . cookies [ column ] [ row - 1 ] . cookieType == cookieType && this . cookies [ column ] [ row - 2 ] . cookieType == cookieType ) ; } private detectHorizontalMatches ( ) { var set = [ ] ; for ( var row = 0 ; row < this . config . numRows ; row ++ ) { for ( var column = 0 ; column < this . config . numColumns - 2 ; ) { if ( this . cookies [ column ] [ row ] != null ) { var matchType = this . cookies [ column ] [ row ] . cookieType ; if ( this . cookies [ column + 1 ] [ row ] && this . cookies [ column + 1 ] [ row ] . cookieType == matchType && this . cookies [ column + 2 ] [ row ] && this . cookies [ column + 2 ] [ row ] . cookieType == matchType ) { var chain = new Chain ( ) ; chain . chainType = ChainType . chainTypeHorizontal ; do { chain . addCookie ( this . cookies [ column ] [ row ] ) ; column += 1 ; } while ( column < this . config . numColumns && this . cookies [ column ] [ row ] && this . cookies [ column ] [ row ] . cookieType == matchType ) ; set . push ( chain ) ; continue ; } } column += 1 ; } } return set ; } private detectVerticalMatches ( ) { var set = [ ] ; for ( var column = 0 ; column < this . config . numColumns ; column ++ ) { for ( var row = 0 ; row < this . config . numRows - 2 ; ) { if ( this . cookies [ column ] [ row ] != null ) { var matchType = this . cookies [ column ] [ row ] . cookieType ; if ( this . cookies [ column ] [ row + 1 ] && this . cookies [ column ] [ row + 1 ] . cookieType == matchType && this . cookies [ column ] [ row + 2 ] && this . cookies [ column ] [ row + 2 ] . cookieType == matchType ) { var chain = new Chain ( ) ; chain . chainType = ChainType . chainTypeVertical ; do { chain . addCookie ( this . cookies [ column ] [ row ] ) ; row += 1 ; } while ( row < this . config . numRows && this . cookies [ column ] [ row ] && this . cookies [ column ] [ row ] . cookieType == matchType ) ; set . push ( chain ) ; continue ; } } row += 1 ; } } return set ; } private removeCookies ( chains ) { chains . forEach ( ( chain ) => { chain . cookies . forEach ( ( cookie ) => { this . cookies [ cookie . column ] [ cookie . row ] = null ; } ) ; } ) ; } } }