Skip to content

Commit

Permalink
fix conflicts (accept incoming)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianKurz committed Jun 1, 2018
2 parents d30298d + 8b193ac commit 9fe1953
Show file tree
Hide file tree
Showing 11 changed files with 200 additions and 170 deletions.
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
# REPLTetris.jl
This started as an exercise to learn terminal rendering and key-input.
Rendering is greatily improved through only rendering diffs to the last screen.
This started as an exercise to learn terminal rendering and key-input. Tile-colors, scoring, button-mapping, speed and levels are in accordance to the [Tetris Guideline][1]. T-spins and wall kicks are not yet available, but will be added soon.

This is a screenshot playing in the VSCode REPL:

![Julia REPL Screenshot of a lost game of REPLTetris](resources/Screenshot.PNG)

# Installation & Usage
The package is not yet registered in Meta-Data. You will need to clone it from this site:
The package is registered in Meta-Data. Simply install it using `Pkg.add`:
```julia
julia> Pkg.add("REPLTetris")
```

After using the Package, you can start a game with `tetris()`:

```julia-REPL
Julia> Pkg.clone("https://github.com/ChristianKurz/REPLTetris.jl")
Julia> using REPLTetris
Julia> tetris()
```julia
julia> using REPLTetris
julia> tetris()
```

Game is controlled via arrow-keys and space:
The game is controlled via arrow-keys, X, Z and space:
- `Up`: Rotate Clockwise
- `Left` / `Right` / `Down`: Move Current Tile
- `Space`: Drop Current Tile to Bottom
- `X`: Rotate Clockwise
- `Z`: Rotate Counter Clockwise
- `C`: Swap current tile with tile on hold
- `CTRL-C`: Abort Game

[1]: http://tetris.wikia.com/wiki/Tetris_Guideline
1 change: 1 addition & 0 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
julia 0.6
Crayons
Compat v0.65.1
4 changes: 2 additions & 2 deletions Terminal.jl/Terminal.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
module Terminal

using Compat, Compat.REPL
using Compat, Compat.REPL, Crayons
export rawmode, clear_screen, readKey, cursor_move_abs, put, cursor_deleteline

@compat function __init__()
global terminal
terminal = REPL.Terminals.TTYTerminal(get(ENV, "TERM", is_windows() ? "" : "dumb"),stdin, stdout, stderr)
terminal = REPL.Terminals.TTYTerminal(get(ENV, "TERM", is_windows() ? "" : "dumb"), stdin, stdout, stderr)
end

include("rawmode.jl")
Expand Down
7 changes: 7 additions & 0 deletions Terminal.jl/cursor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,10 @@ function put(buf::IO, pos::Vector, s::String)
cursor_restore_position(buf)
end
put(pos::Vector, s::String) = put(terminal.out_stream, pos::Vector, s::String)

function put(buf::IO, pos::Vector, color::Crayon, s::String)
print(buf, color)
put(buf, pos, s)
end

put(buf::IO, pos::Vector, c::Symbol, s::String) = put(buf, pos, Crayon(foreground=c), s)
Binary file modified resources/Screenshot.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 16 additions & 17 deletions src/REPLTetris.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,40 @@ module REPLTetris

using Crayons, Compat
export tetris
import Base.copy

include("../Terminal.jl/Terminal.jl")
using .Terminal

include("tiles.jl")
include("board.jl")
include("printboard.jl")
include("actions.jl")

function tetris(board = Board(), tile = rand(Tiles)())
function tetris(board = Board())
rawmode() do
clear_screen()
update_board!(Board(ones(Int, (20,10)),1,1,1), board)

update_board!(board)
abort = [false]
@async while !abort[1] && add_tile!(board, tile)
nexttile = rand(Tiles)()
print_tile_preview(nexttile)

while !abort[1] && drop!(board, tile)
@async while !abort[1] && add_tile!(board)
board.allowhold = true
print_preview(board)
print_hold(board)
while !abort[1] && drop!(board)
sleep((0.8 - (board.level-1) * 0.007)^(board.level-1))
end

delete_lines!(board)
tile = nexttile
end

while !abort[1]
c = readKey()
c == "Up" && rot_right!(board, tile)
c == "Down" && drop!(board, tile)
c == "Right" && move_right!(board, tile)
c == "Left" && move_left!(board, tile)
c == " " && fast_drop!(board, tile)
c == "Ctrl-C" && (abort[1]=true)
c in ["Up", "x"] && rot_right!(board)
c in ["Down"] && drop!(board)
c in ["Right"] && move_right!(board)
c in ["Left"] && move_left!(board)
c in [" "] && fast_drop!(board)
c in ["Ctrl", "z"] && rot_left!(board)
c in ["c"] && hold!(board)
c in ["Ctrl-C"] && (abort[1]=true)
end
end
end
Expand Down
66 changes: 33 additions & 33 deletions src/actions.jl
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
function checkcollision(b::Board, newtile::Tile)
shape = data(newtile)
x,y = newtile.location
dy, dx = size(shape) .-1
x+dx <= 10 && x >= 1 && y+dy <= 20 && !any((b[newtile] .!= 0 ) .& (shape .!= 0)) && return true
function checkcollision(b::Board)
x,y = b.location
dy, dx = size(rotatedtile(b)) .-1
x+dx <= 10 && x >= 1 && y+dy <= 20 && !any((b[] .!= 0 ) .& (rotatedtile(b) .!= 0))
end

function affine!(board::Board, tile::Tile, rotation=0, translation=[0,0])
oldboard = copy(board)
newtile = copy(tile)
newtile.orientation -= rotation
newtile.location += translation
function affine!(b::Board, rotation=0, translation=[0,0])
oldboard = copy(b)

board[tile] -= data(tile)
if checkcollision(board,newtile)
tile.orientation -= rotation
tile.location[:] += translation
board[tile] += data(tile)
update_board!(oldboard, board)
b[] -= rotatedtile(b)
b.orientation -= rotation
b.location += translation
if checkcollision(b)
b[] += rotatedtile(b)
update_board!(oldboard, b)
return true
end
board[tile] += data(tile)
b.orientation += rotation
b.location -= translation
b[] += rotatedtile(b)
return false
end

rot_right!(b::Board, tile::Tile) = affine!(b, tile, -1, [ 0, 0])
rot_left!(b::Board, tile::Tile) = affine!(b, tile, 1, [ 0, 0])
move_right!(b::Board, tile::Tile) = affine!(b, tile, 0, [ 1, 0])
move_left!(b::Board, tile::Tile) = affine!(b, tile, 0, [-1, 0])
drop!(b::Board, tile::Tile) = affine!(b, tile, 0, [ 0, 1])
rot_right!(b::Board) = affine!(b, -1, [ 0, 0])
rot_left!(b::Board) = affine!(b, 1, [ 0, 0])
move_right!(b::Board) = affine!(b, 0, [ 1, 0])
move_left!(b::Board) = affine!(b, 0, [-1, 0])
drop!(b::Board) = affine!(b, 0, [ 0, 1])
fast_drop!(b::Board) = (while drop!(b) end; return false)

function fast_drop!(b::Board, tile::Tile)
while drop!(b, tile) end
return false
end
function hold!(b::Board)
if b.allowhold
oldboard = copy(b)

function add_tile!(board::Board, tile::Tile)
if all(board[tile] .== 0)
oldboard = copy(board)
board[tile] += data(tile)
update_board!(oldboard, board)
return true
b[] -= rotatedtile(b)
b.tile, b.holdtile = b.holdtile, b.tile
b.orientation = 0
b.location = start_location(b.tile)
b[] += rotatedtile(b)
print_hold(b)
b.allowhold = false

update_board!(oldboard, b)
end
false
end
110 changes: 52 additions & 58 deletions src/board.jl
Original file line number Diff line number Diff line change
@@ -1,78 +1,72 @@
import Base: getindex, setindex!, copy

mutable struct Board
data::Array{Int}
score::Int
level::Int
lines_to_goal::Int
tile::Tile
location::Vector{Int}
orientation::Int
nexttiles::Vector{Tile}
holdtile::Tile
allowhold::Bool
end
Board() = Board(zeros(Int, 20, 10), 0, 1, 5)
copy(b::Board) = Board(copy(b.data), b.score, b.level, b.lines_to_goal)
Board(i=0) = Board(ones(Int, 20, 10)*i, 0, 1+i, 5,
rand(Tiles)(), [4,1], 0,
[rand(Tiles)() for i in 1:3], rand(Tiles)(), true)

copy(b::Board) = Board(copy(b.data), b.score, b.level, b.lines_to_goal,
b.tile, b.location, b.orientation,
copy(b.nexttiles), b.holdtile, b.allowhold)

import Base: getindex, setindex!
function getindex(b::Board, tile::Tile)
dy,dx = size(data(tile)) .-1
x,y = tile.location
function getindex(b::Board)
dy,dx = size(rotatedtile(b)) .-1
x,y = b.location
return b.data[y:y+dy, x:x+dx]
end
function setindex!(b::Board, s::AbstractArray, tile::Tile)
dy,dx = size(data(tile)) .-1
x,y = tile.location

function setindex!(b::Board, s::AbstractArray)
dy,dx = size(rotatedtile(b)) .-1
x,y = b.location
b.data[y:y+dy, x:x+dx] = s
end

function delete_lines!(board::Board)
oldboard = copy(board)
nr_lines = 0
for i in 1:20
if all(board.data[i, :] .!= 0)
board.data[2:i, :] = board.data[1:i-1, :]
board.data[1,:] .= 0
nr_lines += 1
end
end
board.lines_to_goal -= nr_lines
board.score += [0 1 3 5 8][nr_lines+1] * board.level * 100
if board.lines_to_goal 0
board.level += 1
board.lines_to_goal += board.level*5
end
update_board!(oldboard, board)
end
rotatedtile(b::Board) = rotr90(data(b.tile), b.orientation)

function blocks(i)
buf = IOBuffer()
block = ""
if i==0
block =""
i += 8
end
print(buf, Crayon(foreground = i), block )
return String(take!(buf))
function nexttile!(b::Board)
push!(b.nexttiles, rand(Tiles)())
b.tile = popfirst!(b.nexttiles)
end

@compat function update_board!(b1::Board, b2::Board)
buf = IOBuffer()
for i in findall(b1.data .⊻ b2.data .!= 0)
y,x = ind2sub((20,10), i)
put(buf, [(3*x)-2,y], blocks(b2.data[y,x]))
function add_tile!(b::Board)
nexttile!(b)
b.location = start_location(b.tile)
b.orientation = 0
if all(b[] .== 0)
oldboard = copy(b)
b[] += data(b.tile)
update_board!(oldboard, b)
return true
end
if (b1.level != b2.level) || (b1.score != b2.score)
cursor_move_abs(buf, [0,21])
print(buf, Crayon(foreground = 7), " Level: $(b2.level)\tScore:$(b2.score)")
end
print(String(take!(buf)))
false
end

function print_tile_preview(tile::Tile)
buf = IOBuffer()
print(buf, Crayon(foreground = 7))
put(buf, [35, 9], string("Next Tile:"))
for i in 1:4
put(buf, [35, 10+i], string(" "^15))
function delete_lines!(b::Board)
oldboard = copy(b)
nr_lines = 0
for i in 1:20
if all(b.data[i, :] .!= 0)
b.data[2:i, :] = b.data[1:i-1, :]
b.data[1,:] .= 0
nr_lines += 1
end
end
dt = data(tile)'
_, dy = size(dt)
for i in 1:dy
put(buf, [35, 10+i], string(blocks.(dt[:, i])...))
b.lines_to_goal -= nr_lines
b.score += [0 1 3 5 8][nr_lines+1] * b.level * 100
if b.lines_to_goal 0
b.level += 1
b.lines_to_goal += b.level*5
end
print(String(take!(buf)))
end
update_board!(oldboard, b)
end
48 changes: 48 additions & 0 deletions src/printboard.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
function block(i)
color = [:dark_gray, :red, :light_red, :yellow, :green, :cyan, :blue, :magenta][i+1]
return string(Crayon(foreground = color), i==0 ? "": "")
end

@compat function update_board!(old::Board, b::Board)
buf = IOBuffer()
for i in findall(old.data .⊻ b.data .!= 0)
if VERSION < v"0.7.0-DEV.3025"
y,x = ind2sub((20,10), i)
else
y,x = Tuple(i)
end
put(buf, [(3*x)-2,y], string(block.(b.data[y,x])...))
end
if (old.level != b.level) || (old.score != b.score)
put(buf, [3,21], :dark_gray, "Level: $(b.level)\tScore:$(b.score)")
end
print(String(take!(buf)))
end

update_board!(b::Board) = update_board!(Board(2), b)


function print_preview(b::Board)
buf = IOBuffer()
put(buf, [33, 2], :dark_gray, string("Next Tiles:"))
for (nr, tile) in enumerate(b.nexttiles)
_print_tile(buf, tile, 2+(nr-1)*4)
end
print(String(take!(buf)))
end

function print_hold(b::Board)
buf = IOBuffer()
put(buf, [33, 16], :dark_gray, string("Hold Tile:"))
_print_tile(buf, b.holdtile, 16)
print(String(take!(buf)))
end

function _print_tile(buf, tile, x)
dt = data(tile)'
_, dy = size(dt)
for i in 1:2
put(buf, [35, x+i+1], :dark_gray, string(""^4))
i <= dy && put(buf, [35, x+i+1], string(block.(dt[:, i])...))
end
end
Loading

0 comments on commit 9fe1953

Please sign in to comment.