From 2aa1602dc1e76bb3bda06ab381557a5102dabd13 Mon Sep 17 00:00:00 2001 From: Edward Shen Date: Sun, 22 Mar 2020 21:56:11 -0400 Subject: [PATCH] bugged --- src/game.rs | 43 ++++++++++++++++++++++++++++++++++++++----- src/main.rs | 2 ++ src/playfield.rs | 21 +++++++++++++++------ 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/game.rs b/src/game.rs index c6349fd..3e19f1c 100644 --- a/src/game.rs +++ b/src/game.rs @@ -25,6 +25,9 @@ pub struct Game { next_lock_tick: u64, next_spawn_tick: u64, is_game_over: bool, + /// The last clear action performed, used for determining if a back-to-back + /// bonus is needed. + last_clear_action: ClearAction, } impl fmt::Debug for Game { @@ -47,6 +50,7 @@ impl Default for Game { next_lock_tick: 0, next_spawn_tick: 0, is_game_over: false, + last_clear_action: ClearAction::Single, // Doesn't matter what it's initialized to } } } @@ -60,7 +64,6 @@ impl Tickable for Game { if self.is_game_over() { return; } - self.tick += 1; match self.tick { t if t == self.next_spawn_tick => self.spawn_tetromino(), @@ -79,6 +82,18 @@ impl Tickable for Game { } } +enum ClearAction { + Single, + Double, + Triple, + Tetris, + MiniTSpin, + TSpin, + TSpinSingle, + TSpinDouble, + TSpinTriple, +} + impl Game { pub fn is_game_over(&self) -> bool { self.is_game_over || !self.playfield.is_active_piece_in_valid_position() @@ -99,9 +114,22 @@ impl Game { } /// Returns if some lines were cleared - fn clear_lines(&mut self) -> bool { - // todo: award points based on how lines were cleared - return false; + fn clear_lines(&mut self) -> usize { + let rows = self + .playfield + .active_piece + .map(|t| t.get_cur_occupied_spaces()) + .map(|i| i.iter().map(|p| p.y).collect::>()) + .unwrap_or_default(); + + let mut rows_cleared = 0; + for row in rows { + if self.playfield.try_clear_row(row as usize).is_ok() { + rows_cleared += 1; + } + } + + rows_cleared } fn try_lock_tetromino(&mut self) -> bool { @@ -110,11 +138,14 @@ impl Game { let positions = self.playfield.lock_active_piece(); self.is_game_over = self.is_game_over || positions.iter().all(|Position { x: _, y }| *y < 20); - if self.clear_lines() { + + if self.clear_lines() > 0 { + self.playfield.active_piece = None; self.next_spawn_tick = self.tick + LINE_CLEAR_DELAY; } else { self.spawn_tetromino(); } + true } else { false @@ -191,6 +222,8 @@ impl Controllable for Game { if !self.try_lock_tetromino() { println!("couldn't lock tetromino despite hard dropping!"); } + + self.next_lock_tick = std::u64::MAX; } fn hold(&mut self) { diff --git a/src/main.rs b/src/main.rs index 0b67d1c..230261d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -85,5 +85,7 @@ async fn main() -> Result<(), Box> { interval.tick().await; } + dbg!(game); + Ok(()) } diff --git a/src/playfield.rs b/src/playfield.rs index bc22149..6b69628 100644 --- a/src/playfield.rs +++ b/src/playfield.rs @@ -171,19 +171,16 @@ impl PlayField { self.field[*y as usize][*x as usize] = Some(active_color); } - self.active_piece = None; new_pieces } - None => panic!("Tried to lock active piece while active piece doesn't exist!"), + None => vec![], } } pub fn is_active_piece_in_valid_position(&self) -> bool { match self.active_piece { - Some(active_piece) => { - self.can_piece_be_at_position(&active_piece) - }, - None => panic!("Tried checking if active piece is in a valid position but active piece doesn't exist") + Some(active_piece) => self.can_piece_be_at_position(&active_piece), + None => true, } } @@ -216,6 +213,18 @@ impl PlayField { Err(()) } + + pub fn try_clear_row(&mut self, row: usize) -> Result<(), ()> { + if self.field[row].iter().all(|cell| cell.is_some()) { + self.field[row] = [None; PLAYFIELD_WIDTH]; + for y in (1..=row).rev() { + self.field[y] = self.field[y - 1]; + } + Ok(()) + } else { + Err(()) + } + } } impl Renderable for PlayField {