const SDL = @import("sdl2"); const std = @import("std"); const Grid = @import("Grid.zig"); const Timer = @import("../Timer.zig"); const color = @import("../color.zig"); const Self = @This(); pub const Rot = enum { right, left, }; pub const RotStage = enum(i8) { init, right, flip, left, }; pub const Type = enum { o, i, l, j, s, z, t, }; const ncols = 4; const nrows = 4; // Positions relative to a grid row: i32, col: i32, // 4x4 grid indicating piece form structure: [4][4]bool, // Rotation Stage rot_stage: RotStage = RotStage.init, // Timer to drop the piece timer_dropped: Timer, // Should this be dropped and become part of the grid (flag) dropped: bool = false, // Has the piece been swapped? swapped: bool = false, piece_type: Type, color: SDL.Color, pub fn init(piece_type: Type) Self { return Self{ .row = Grid.buffer - 3, .col = (Grid.ncolumns / 2) - (ncols / 2), .piece_type = piece_type, .timer_dropped = Timer.init(500), .structure = switch (piece_type) { Type.o => .{ .{ false, true, true, false }, .{ false, true, true, false }, .{ false, false, false, false }, .{ false, false, false, false }, }, Type.i => .{ .{ false, false, false, false }, .{ true, true, true, true }, .{ false, false, false, false }, .{ false, false, false, false }, }, Type.l => .{ .{ false, false, true, false }, .{ true, true, true, false }, .{ false, false, false, false }, .{ false, false, false, false }, }, Type.j => .{ .{ true, false, false, false }, .{ true, true, true, false }, .{ false, false, false, false }, .{ false, false, false, false }, }, Type.s => .{ .{ false, true, true, false }, .{ true, true, false, false }, .{ false, false, false, false }, .{ false, false, false, false }, }, Type.z => .{ .{ true, true, false, false }, .{ false, true, true, false }, .{ false, false, false, false }, .{ false, false, false, false }, }, Type.t => .{ .{ false, true, false, false }, .{ true, true, true, false }, .{ false, false, false, false }, .{ false, false, false, false }, }, }, .color = switch (piece_type) { Type.o => color.yellow, Type.i => color.cyan, Type.l => color.orange, Type.j => color.blue, Type.s => color.green, Type.z => color.red, Type.t => color.purple, }, }; } pub fn rotate(self: Self, dir: Rot) Self { if (self.piece_type == Type.o) { return self; } var new_piece = self; // The "sequences" indicate square coords and are always the same when rotating, so we make all squares follow said rotation // [Inner/Outer][The sequence (0 -> 1 -> 2 -> 3 -> 0...)][Rows, Cols] if (self.piece_type == Type.i) { const sequences = .{ .{ .{ 1, 0 }, .{ 0, 2 }, .{ 2, 3 }, .{ 3, 1 } }, .{ .{ 2, 0 }, .{ 0, 1 }, .{ 1, 3 }, .{ 3, 2 } }, .{ .{ 1, 1 }, .{ 1, 2 }, .{ 2, 2 }, .{ 2, 1 } } }; if (dir == Rot.right) { // Cicle through rotation stage new_piece.rot_stage = @intToEnum(RotStage, @mod((@enumToInt(new_piece.rot_stage) + 1), 4)); // Rotate structure CW inline for (sequences) |seq| { inline for (seq, 0..) |_, i| { const refi = @mod((@intCast(i32, i) - 1), 4); new_piece.structure[seq[i][0]][seq[i][1]] = self.structure[seq[refi][0]][seq[refi][1]]; } } } else { // Cicle through rotation stage new_piece.rot_stage = @intToEnum(RotStage, @mod((@enumToInt(new_piece.rot_stage) - 1), 4)); // Rotate structure CCW inline for (sequences) |seq| { inline for (seq, 0..) |_, i| { const refi = @mod((@intCast(i32, i) + 1), 4); new_piece.structure[seq[i][0]][seq[i][1]] = self.structure[seq[refi][0]][seq[refi][1]]; } } } } else { const sequences = .{ .{ .{ 0, 0 }, .{ 0, 2 }, .{ 2, 2 }, .{ 2, 0 } }, .{ .{ 0, 1 }, .{ 1, 2 }, .{ 2, 1 }, .{ 1, 0 } } }; if (dir == Rot.right) { // Cicle through rotation stage new_piece.rot_stage = @intToEnum(RotStage, @mod((@enumToInt(new_piece.rot_stage) + 1), 4)); // Rotate structure CW inline for (sequences) |seq| { inline for (seq, 0..) |_, i| { const refi = @mod((@intCast(i32, i) - 1), 4); new_piece.structure[seq[i][0]][seq[i][1]] = self.structure[seq[refi][0]][seq[refi][1]]; } } } else { // Cicle through rotation stage new_piece.rot_stage = @intToEnum(RotStage, @mod((@enumToInt(new_piece.rot_stage) - 1), 4)); // Rotate structure CCW inline for (sequences) |seq| { inline for (seq, 0..) |_, i| { const refi = @mod((@intCast(i32, i) + 1), 4); new_piece.structure[seq[i][0]][seq[i][1]] = self.structure[seq[refi][0]][seq[refi][1]]; } } } } //[0,0][0,1][0,2] //[1,0][1,1][1,2] //[2,0][2,1][2,2] return new_piece; }