/* cTetris.txt * -> Created by Catalyst * -> v1.0 * -> import cTetris * * You also can play widh W and H parameters to change field size, * and figure_glyph_a/b to chane block sprite * */ disable abilities disable pause disable hud disable banner disable loadout input disable player var is_game_ended = false var score = 0 var lines = 0 var ticks = 0 var W = 10 // field width var H = 20 + 1 // field height var figure_glyph_a = "[" // any ascii symbol var figure_glyph_b = "]" // [] () {} ██ var game_x = screen.w/2 - (W*2 + 18)/2 var game_y = screen.h/2 - H/2 var gui_x = game_x + 2*W + 3 var gui_y = game_y var figure_x = W/2 - 2 var figure_y = 0 var figure_max_x = 22 var figure_min_x = -2 var figure = 15 var figure_next = 1 var clear_line = "" var full_line = "" var lower_border = " " var figures = [] var field = [] func coutField() var render_line = "" // field for y = 0..H-1 render_line = "|" ?field[y] = clear_line render_line += clear_line + clear_line : for x = 0..W-1 ?string.Sub(field[y], x, 1) = figure_glyph_a render_line += figure_glyph_a + figure_glyph_b : render_line += " " >`@game_x@,@game_y+y@,#white,@render_line@| >`@game_x@,@game_y+H@,#white,@lower_border@ // next figure >`@gui_x@,@gui_y + 1@,#white,Lines: @lines@ >`@gui_x@,@gui_y + 2@,#white,Score: @score@ >`@gui_x@,@gui_y + 3@,#white,Next figure: for y = 0..3 render_line = "" for x = 0..3 ?string.Sub(figures[figure_next], y*4+x, 1) = "@" render_line += figure_glyph_a + figure_glyph_b : render_line += " " >`@gui_x@,@gui_y + 4 + y@,#white,@render_line@ ?is_game_ended >`@gui_x@,@gui_y + H - 5@,#yellow,game is ended >`@gui_x@,@gui_y + H - 4@,#666,[Z] - restart game // controls >`@gui_x@,@gui_y + H - 3@,#666,[A], [D] - move >`@gui_x@,@gui_y + H - 2@,#666,[C] - rotate >`@gui_x@,@gui_y + H - 1@,#666,[X] - exit /* debug / >`@gui_x@,@gui_y + 10@,#yellow,x, y: @figure_x@, @figure_y@ GX, GY: @game_x@, @game_y@ >`@gui_x@,@gui_y + 11@,#yellow,figure: @figure@, next: @figure_next@ >`@gui_x@,@gui_y + 12@,#yellow,totaltime: @totaltime@, >`@gui_x@,@gui_y + 13@,#yellow,ticks: @ticks@, upd: @(30 - score/100)@ ?totaltime % 2 = 0 >`@gui_x@,@gui_y + 14@,#yellow,█ // */ func setFigure() for y = 0..3 for x = 0..3 ?string.Sub(figures[figure], x+y*4, 1) = "@" >`@game_x+figure_x*2+x*2+1@,@game_y+figure_y+y@,#white,@figure_glyph_a@@figure_glyph_b@ func setMaxXY() // max ?figure = 0 | figure = 2 | figure = 10 | figure = 14 | figure = 18 figure_max_x = W-3 : figure_max_x = W-4 // min ?figure = 2 | figure = 4 | figure = 6 | figure = 8 | figure = 12 | figure = 16 figure_min_x = -2 :?figure = 1 figure_min_x = 0 : figure_min_x = -1 // x normalization, especially when rotating ?figure_x < figure_min_x figure_x = figure_min_x ?figure_x > figure_max_x figure_x = figure_max_x func rotate() var figure_heap = figure var figure_x_heap = figure_x var figure_y_heap = figure_y // O I S Z L J T var rotations = [0, 2, 1, 4, 3, 6, 5, 10, 7, 8, 9, 14, 11, 12, 13, 18, 15, 16, 17] figure = rotations[figure] // if rotate is not possible setMaxXY() for y = 0..3 for x = 0..3 ?string.Sub(figures[figure], x+y*4, 1) = "@" & (figure_y+y>H-1 | string.Sub(field[figure_y+y], figure_x+x, 1) = figure_glyph_a) figure = figure_heap figure_x = figure_x_heap figure_y = figure_y_heap setMaxXY() return func move(move_direction) ?figure_x + move_direction < figure_min_x | figure_x + move_direction > figure_max_x return for y = 0..3 for x = 0..3 ?string.Sub(figures[figure], x+y*4, 1) = "@" & (string.Sub(field[figure_y+y], figure_x+x+move_direction, 1) = figure_glyph_a) return figure_x += move_direction func checkCollision() var figures_id = [0, 1, 3, 5, 7, 11, 15] var clip = false for y = 3..0 for x = 0..3 ?string.Sub(figures[figure], x+y*4, 1) = "@" & (figure_y+y = H-1 | string.Sub(field[figure_y+y+1], figure_x+x, 1) = figure_glyph_a) clip = true play pickup_bronze // break y = 0 x = 3 ?!clip return for y = 3..0 for x = 0..3 // place figure ?string.Sub(figures[figure], x+y*4, 1) = "@" field[figure_y+y] = string.Sub(field[figure_y+y], 0, figure_x+x) + figure_glyph_a + string.Sub(field[figure_y+y], figure_x+x+1) for y = 3..0 for x = 0..3 // if new figure can't be spawned ?string.Sub(figures[figure_next], x+y*4, 1) = "@" & (string.Sub(field[y], W/2 - 2+x, 1) = figure_glyph_a) is_game_ended = true play uulaa_voice // break y = 0 x = 3 figure_x = W/2 - 2 figure_y = -1 figure = figure_next figure_next = rng % 7 figure_next = figures_id[figure_next] func checkLines() for y = H-1..0 ?field[y] = full_line play quest_stone_jump score += 10 lines++ field[y] = clear_line for yy = y-1..0 field[yy+1] = field[yy] // break return func init() // generate figures figures.Add(".....@@..@@.....") // O figures.Add("....@@@@........") // I figures.Add("..@...@...@...@.") figures.Add("......@@.@@.....") // S figures.Add("..@...@@...@....") figures.Add(".....@@...@@....") // Z figures.Add("...@..@@..@.....") figures.Add(".....@@@.@......") // L figures.Add("..@...@...@@....") figures.Add("...@.@@@........") figures.Add(".@@...@...@.....") figures.Add(".....@@@...@....") // J figures.Add("..@@..@...@.....") figures.Add(".@...@@@........") figures.Add("..@...@..@@.....") figures.Add(".....@@@..@.....") // T figures.Add("..@...@@..@.....") figures.Add("..@..@@@........") figures.Add("..@..@@...@.....") // generate lines for x = 0..W-1 clear_line += " " full_line += figure_glyph_a lower_border += "--" // generate field for y = 0..H-1 field.Add(clear_line) func gameLoop() ?key = backBegin // X loc.Leave() ?!is_game_ended ?totaltime % (30 - score/100) = 0 | key = down // S setMaxXY() checkCollision() checkLines() figure_y++ ticks++ ?ticks % 10 = 0 score += 1 ?key = bumpRBegin // C rotate() play grappling_idle ?key = leftBegin // A move(-1) ?key = rightBegin // D move(1) :?key = bumpLEnd // Z is_game_ended = false score = 0 ticks = 0 lines = 0 field.Clear() for y = 0..H-1 field.Add(clear_line) // update board draw.Clear() coutField() ?!is_game_ended setFigure() ?loc.begin ambient.Stop() init() : gameLoop()