summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs118
1 files changed, 96 insertions, 22 deletions
diff --git a/src/main.rs b/src/main.rs
index 0ce3299..33a369c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -17,6 +17,9 @@ const CELLS_B: [u8; FIGURE_SIZE] = [0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0,
const CELLS_S: [u8; FIGURE_SIZE] = [0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0];
const CELLS_T: [u8; FIGURE_SIZE] = [0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0];
const CELLS_Z: [u8; FIGURE_SIZE] = [0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0];
+const NEXT_COUNT: usize = 4;
+const DISPLAY_NEXT_OFFSET_DOWN: usize = 4;
+const DISPLAY_HOLD_OFFSET_DOWN: usize = 4;
enum StepResult {
StateChanged,
@@ -27,9 +30,9 @@ enum StepResult {
#[derive(Debug)]
enum FigureKind {
I,
- L2,
+ J,
L,
- B,
+ O,
S,
T,
Z,
@@ -72,9 +75,9 @@ impl Figure {
fn from_kind(kind: FigureKind) -> Self {
match kind {
FigureKind::I => Self{ cells: CELLS_I, kind },
- FigureKind::L2 => Self{ cells: CELLS_L2, kind },
+ FigureKind::J => Self{ cells: CELLS_L2, kind },
FigureKind::L => Self{ cells: CELLS_L, kind },
- FigureKind::B => Self{ cells: CELLS_B, kind },
+ FigureKind::O => Self{ cells: CELLS_B, kind },
FigureKind::S => Self{ cells: CELLS_S, kind },
FigureKind::T => Self{ cells: CELLS_T, kind },
FigureKind::Z => Self{ cells: CELLS_Z, kind },
@@ -105,9 +108,9 @@ impl Figure {
fn rotate(&mut self) {
match self.kind {
FigureKind::I => self.rotate_cw_4x4(),
- FigureKind::L2 => self.rotate_cw_3x3(),
+ FigureKind::J => self.rotate_cw_3x3(),
FigureKind::L => self.rotate_cw_3x3(),
- FigureKind::B => {},
+ FigureKind::O => {},
FigureKind::S => self.rotate_cw_3x3(),
FigureKind::T => self.rotate_cw_3x3(),
FigureKind::Z => self.rotate_cw_3x3(),
@@ -197,9 +200,9 @@ impl Bag {
self.index += 1;
match self.pieces[i as usize] {
0 => FigureKind::I,
- 1 => FigureKind::L2,
+ 1 => FigureKind::J,
2 => FigureKind::L,
- 4 => FigureKind::B,
+ 4 => FigureKind::O,
5 => FigureKind::S,
3 => FigureKind::T,
6 => FigureKind::Z,
@@ -228,21 +231,32 @@ struct Game {
fall_timeout: Timeout,
place_timeout: Option<Timeout>,
bag: Bag,
+ figure_next: [Figure; NEXT_COUNT],
+ figure_on_hold: Figure,
}
impl Default for Game {
#[inline]
fn default() -> Self {
let mut bag = Bag::default();
- let kind = bag.next();
+ let figure_on_hold = Figure::from_kind(bag.next());
+ let figure = Figure::from_kind(bag.next());
+ let figure_next = [
+ Figure::from_kind(bag.next()),
+ Figure::from_kind(bag.next()),
+ Figure::from_kind(bag.next()),
+ Figure::from_kind(bag.next()),
+ ];
Self{
field: Field::default(),
- figure: Figure::from_kind(kind),
+ figure,
x: 3,
y: 17,
fall_timeout: Timeout::from_duration(std::time::Duration::from_millis(500)),
place_timeout: None,
bag,
+ figure_next,
+ figure_on_hold,
}
}
}
@@ -250,7 +264,11 @@ impl Default for Game {
impl Game {
fn place_figure(&mut self) {
self.field.render(&self.figure, self.x, self.y);
- self.figure = Figure::from_kind(self.bag.next());
+ self.figure = self.figure_next[0].clone();
+ for i in 0..NEXT_COUNT - 1 {
+ self.figure_next[i] = self.figure_next[i + 1].clone();
+ }
+ self.figure_next[NEXT_COUNT - 1] = Figure::from_kind(self.bag.next());
(self.x, self.y) = (3, 17);
self.stop_place_timeout();
for line in 0..FIELD_ROWS - 1 {
@@ -259,6 +277,10 @@ impl Game {
}
}
}
+ fn hold_figure(&mut self) {
+ (self.figure_on_hold, self.figure) = (Figure::from_kind(self.figure.kind.clone()), self.figure_on_hold.clone());
+ (self.x, self.y) = (3, 17);
+ }
fn reset_fall_timeout(&mut self) {
self.fall_timeout = Timeout::from_duration(std::time::Duration::from_millis(500));
}
@@ -282,12 +304,12 @@ impl Game {
}
self.place_figure()
},
- 'h' => {
+ 'j' => {
if !self.field.has_collision(&self.figure, self.x - 1, self.y) {
self.x -= 1;
}
}
- 'j' => {
+ 'k' => {
if !self.field.has_collision(&self.figure, self.x, self.y - 1) {
self.y -= 1;
self.reset_fall_timeout();
@@ -295,7 +317,7 @@ impl Game {
self.start_place_timeout();
}
}
- ';' | 'k' => {
+ ';' | 'i' => {
let mut figure = self.figure.clone();
figure.rotate();
if !self.field.has_collision(&figure, self.x, self.y) {
@@ -307,6 +329,10 @@ impl Game {
self.x += 1;
}
}
+ 'h' => {
+ self.hold_figure();
+ self.reset_fall_timeout();
+ }
_ => {},
}
self.reset_place_timeout();
@@ -350,27 +376,75 @@ impl Game {
}
}
-fn print_field(field: &Field) {
- cursor_to_home();
- for y in 0..FIELD_ROWS_VISIBLE {
- print!("|");
- for x in 0..FIELD_COLS {
- let c = field.cells[(FIELD_ROWS_VISIBLE - 1 - y) * FIELD_COLS + x];
+fn print_hold(figure: &Figure, y_global: usize) {
+ let offset = DISPLAY_HOLD_OFFSET_DOWN;
+ let at_figure = y_global >= (1 + offset) && y_global < FIGURE_SIZE_ROWS + (1 + offset);
+ if y_global == offset {
+ print!(" Hold: ");
+ } else if at_figure {
+ print!(" ");
+ let y = FIGURE_SIZE_ROWS - 1 - (y_global - 1 - offset);
+ for x in 0..FIGURE_SIZE_COLS {
+ let c = figure.cells[y * FIGURE_SIZE_COLS + x];
if c == 0 {
print!(" ");
} else {
print!("██");
}
}
- print!("|\r\x1b[1B");
+ print!(" ");
+ } else {
+ print!(" ");
+ }
+}
+
+fn print_next(figure: &[Figure; NEXT_COUNT], y_global: usize) {
+ let offset = DISPLAY_NEXT_OFFSET_DOWN;
+ if y_global == offset {
+ print!(" Next: ");
+ } else {
+ for i in 0..NEXT_COUNT {
+ let at_figure = y_global >= (1 + offset + FIGURE_SIZE_ROWS * i) && y_global < (1 + offset + FIGURE_SIZE_ROWS * (i + 1));
+ if at_figure {
+ print!(" ");
+ let y = FIGURE_SIZE_ROWS - 1 - (y_global - 1 - offset - FIGURE_SIZE_ROWS * i);
+ for x in 0..FIGURE_SIZE_COLS {
+ let c = figure[i].cells[y * FIGURE_SIZE_COLS + x];
+ if c == 0 {
+ print!(" ");
+ } else {
+ print!("██");
+ }
+ }
+ break;
+ }
+ }
}
}
+fn print_field(field: &Field, y: usize) {
+ print!("|");
+ for x in 0..FIELD_COLS {
+ let c = field.cells[(FIELD_ROWS_VISIBLE - 1 - y) * FIELD_COLS + x];
+ if c == 0 {
+ print!(" ");
+ } else {
+ print!("██");
+ }
+ }
+ print!("|");
+}
+
fn display_game(game: &Game) {
cursor_to_home();
let mut field = game.field.clone();
field.render(&game.figure, game.x, game.y);
- print_field(&field);
+ for y in 0..FIELD_ROWS_VISIBLE {
+ print_hold(&game.figure_on_hold, y);
+ print_field(&field, y);
+ print_next(&game.figure_next, y);
+ print!("\r\x1b[1B");
+ }
if game.field.has_collision(&game.figure, game.x, game.y) {
println!("Collision!");
} else {