@@ -9,10 +9,15 @@ export default () => {
99 const DIV_PUZ_INFO = document . getElementById ( 'puz_info' ) ;
1010 const DIV_TARGET_INFO = document . getElementById ( 'target_info' ) ;
1111 const [ ALT_ORB , ALT_OBJECT , ALT_FIELD ] = [ "□🔴🔵🟢🟡🟣" , "□🧱🌸" , "□🥬" ] ;
12+ const ENUM_STATUS = Object . freeze ( {
13+ CHAINING : 0 ,
14+ IDLE : 1 ,
15+ ANIMATION : 2
16+ } ) ;
1217 // SECTOR_2:変数群
13- let [ chain_now , chainable ] = [ false , false ] ;
14- let chain_color = null ;
15- let chain_yx = new Array ( ) ; //[i].(x | y)
18+ let game_state = ENUM_STATUS . CHAINING ;
19+ let chain_color = null ;
20+ let chain_yx = new Array ( ) ; //[i].(x | y)
1621 let adj_list = new Array ( ) ; //[i].(y | x)
1722 //SECTOR_2.5:準const変数群
1823 let PUZ_BOARD_BONE = new Array ( ) ;
@@ -38,9 +43,9 @@ export default () => {
3843 alert ( "GAME CLEAR" ) ;
3944 endscene ( ) ;
4045 }
41- const addScore = score_mult => {
46+ const addScore = ( score_mult , base = BASE_SCORE ) => {
4247 const wasNegativeScore = DATA . target . score < 0 ;
43- DATA . target . score += Math . floor ( BASE_SCORE * score_mult ) ;
48+ DATA . target . score += Math . floor ( base * score_mult ) ;
4449 wasNegativeScore && DATA . target . score >= 0 && gameClear ( ) ;
4550 }
4651 const getType = obj => obj [ 0 ] ;
@@ -88,7 +93,7 @@ export default () => {
8893 return true ;
8994 }
9095 const falling_orb = ( ) => {
91- chainable = false ;
96+ game_state = ENUM_STATUS . ANIMATION ;
9297 const FALL_TIMER = setInterval ( ( ) => {
9398 let refall = false ;
9499 for ( let i = DATA . size . Height - 1 ; i > 0 ; i -- ) /*性質上、下から探索したほうがいい*/ {
@@ -99,64 +104,70 @@ export default () => {
99104 DATA . board . obj [ 0 ] = DATA . board . obj [ 0 ] . map ( x => isnullobj ( x ) ?( refall = true , [ ~ ~ ( Math . random ( ) * ORB_COLORS ) + 1 , 1 ] ) :x ) ;
100105 if ( ! refall ) {
101106 clearInterval ( FALL_TIMER ) ;
102- chainable = true ;
107+ game_state = ENUM_STATUS . IDLE ;
103108 }
104109 update_display ( ) ;
105110 } , ANIM_SPEED ) ;
106111 }
107112 const chain_connect = cell => {
108- if ( ! chain_now ) return ;
113+ if ( game_state !== ENUM_STATUS . CHAINING ) return ;
109114 const [ CELL_Y , CELL_X ] = [ cell . target . parentNode . rowIndex , cell . target . cellIndex ] ;
110115 const CELL_COLOR = getType ( DATA . board . obj [ CELL_Y ] [ CELL_X ] ) ;
111116 if ( ! ( Math . abs ( chain_yx . at ( - 1 ) . y - CELL_Y ) <= 1 && Math . abs ( chain_yx . at ( - 1 ) . x - CELL_X ) <= 1 ) ) return ; /*位置チェック*/
112117 if ( chain_color !== CELL_COLOR || chain_yx . some ( e => e . x === CELL_X && e . y === CELL_Y ) ) return ; /*条件チェック*/
113118 cell . target . querySelector ( "img" ) . classList . add ( "chaining" ) ;
114119 chain_yx . push ( { x : CELL_X , y : CELL_Y } ) ;
115120 }
116- /** @todo 比較的複雑なため、複数の関数に分ける*/
117- const chain_toggler = cell => {
118- if ( ! chainable ) return ;
121+ const chain_over = ( ) => {
122+ if ( ! ( chain_yx . length < SHORTEST_CHAIN ) ) {
123+ addScore ( chain_yx . length ** SCORE_EXPONENT ) ;
124+ DATA . target . hand -- ;
125+ chain_yx . forEach ( pos => {
126+ break_obj ( pos . y , pos . x , true ) ;
127+ for ( let dy = - 1 ; dy <= 1 ; dy ++ ) {
128+ const NEWY = pos . y + dy ;
129+ for ( let dx = - 1 ; dx <= 1 ; dx ++ ) {
130+ const NEWX = pos . x + dx ;
131+ DATA . board . obj [ NEWY ] ?. [ NEWX ] && ( adj_list . some ( e => e . x === NEWX && e . y === NEWY ) || adj_list . push ( { y : NEWY , x : NEWX } ) ) ;
132+ }
133+ }
134+ } ) ;
135+ adj_list . forEach ( pos => is_adj_break ( DATA . board . obj [ pos . y ] [ pos . x ] ) && break_obj ( pos . y , pos . x , false ) ) ;
136+ update_display ( ) ;
137+ falling_orb ( ) ;
138+ }
139+ game_state = ENUM_STATUS . IDLE ;
140+ chain_yx . forEach ( pos => PUZ_BOARD_BONE [ pos . y ] [ pos . x ] . querySelector ( "img" ) . classList . remove ( "chaining" ) ) ;
141+ chain_color = null ;
142+ adj_list = chain_yx = [ ] ;
143+ if ( DATA . target . hand <= 0 ) {
144+ alert ( `ゲームオーバー! スコアは${ DATA . target . score } でした!` ) ;
145+ endscene ( ) ;
146+ }
147+ }
148+ const chain_start = cell => {
119149 const [ CELL_Y , CELL_X ] = [ cell . target . parentNode . rowIndex , cell . target . cellIndex ] ;
120150 const CELL_COLOR = getType ( DATA . board . obj [ CELL_Y ] [ CELL_X ] ) ;
121- if ( chain_now ) { //チェイン終了時の処理
122- chain_now = false ;
123- if ( ! ( chain_yx . length < SHORTEST_CHAIN ) ) {
124- addScore ( chain_yx . length ** SCORE_EXPONENT ) ;
125- DATA . target . hand -- ;
126- chain_yx . forEach ( pos => {
127- break_obj ( pos . y , pos . x , true ) ;
128- for ( let dy = - 1 ; dy <= 1 ; dy ++ ) {
129- const NEWY = pos . y + dy ;
130- for ( let dx = - 1 ; dx <= 1 ; dx ++ ) {
131- const NEWX = pos . x + dx ;
132- DATA . board . obj [ NEWY ] ?. [ NEWX ] && ( adj_list . some ( e => e . x === NEWX && e . y === NEWY ) || adj_list . push ( { y : NEWY , x : NEWX } ) ) ;
133- }
134- }
135- } ) ;
136- adj_list . forEach ( pos => is_adj_break ( DATA . board . obj [ pos . y ] [ pos . x ] ) && break_obj ( pos . y , pos . x , false ) ) ;
137- update_display ( ) ;
138- falling_orb ( ) ;
139- }
140- chain_yx . forEach ( pos => PUZ_BOARD_BONE [ pos . y ] [ pos . x ] . querySelector ( "img" ) . classList . remove ( "chaining" ) ) ;
141- chain_color = null ;
142- adj_list = chain_yx = [ ] ;
143- if ( DATA . target . hand <= 0 ) {
144- alert ( `ゲームオーバー! スコアは${ DATA . target . score } でした!` ) ;
145- endscene ( ) ;
146- }
147- } else if ( CELL_COLOR > 0 ) { //チェイン開始の処理
148- chain_now = true ;
149- chain_color = CELL_COLOR ;
150- chain_yx . push ( { x : CELL_X , y : CELL_Y } ) ;
151- cell . target . querySelector ( "img" ) . classList . add ( "chaining" ) ;
151+ if ( ! ( CELL_COLOR > 0 ) ) return ;
152+ game_state = ENUM_STATUS . CHAINING ;
153+ chain_color = CELL_COLOR ;
154+ chain_yx . push ( { x : CELL_X , y : CELL_Y } ) ;
155+ cell . target . querySelector ( "img" ) . classList . add ( "chaining" ) ;
156+ }
157+ const chain_toggler = cell => {
158+ switch ( game_state ) {
159+ case ENUM_STATUS . ANIMATION : return ;
160+ case ENUM_STATUS . CHAINING : chain_over ( ) ; break ;
161+ case ENUM_STATUS . IDLE : chain_start ( cell ) ; break ;
162+ default : endscene ( TypeError ( `GUARD! unknown game_state : ${ game_state } ` ) ) ;
152163 }
153164 }
154165 const load_board = ( ) => {
155166 const [ HEIGHT , WIDTH ] = [ DATA . size . Height , DATA . size . Width ] ;
156167 PUZ_BOARD_BONE = new Array ( HEIGHT ) . fill ( ) . map ( _ => Array ( WIDTH ) ) ;
157168 MAIN_BOARD . innerHTML = null ;
158169 if ( HEIGHT <= 0 ) endscene ( RangeError ( `GUARD! Height : ${ HEIGHT } isn't positive` ) ) ;
159- if ( WIDTH <= 0 ) endscene ( RangeError ( `GUARD! Height : ${ WIDTH } isn't positive` ) ) ;
170+ if ( WIDTH <= 0 ) endscene ( RangeError ( `GUARD! Width : ${ WIDTH } isn't positive` ) ) ;
160171 for ( let i = 0 ; i < HEIGHT ; i ++ ) {
161172 const TR = document . createElement ( "tr" ) ;
162173 TR . classList . add ( "puz_board_tr" ) ;
0 commit comments