Anonymous user
Tetris/Julia: Difference between revisions
→{{header|Julia}}
Line 1:
=={{header|Julia}}==
This is a fairly complete, configurable pure Julia implementation of Tetris, played in the standard Julia terminal. No external packages are used.
Detailed notes are in the long comment below the Julia script, to be attached to the code. At least its first few lines are needed, as they are shown as info, upon the request of the user.
{{works with|Julia|1.0}}
Line 120 ⟶ 15:
end end
# print tetromino on playfield
function draw(b
print("\e[$(clr & b.bg)m") # set color. (0 = default colors)
for i=1:4 print("\e[$(r+b.d[i,1]);$(c+2b.d[i,2])H ") end
end
# hit other B4s or border?
function hit(B
for i=1:4 BD[r+B.d[i,1],c>>1+B.d[i,2]+2]>0 && return true end
return false
end
# move tetrominos left/right/down, if no hit
function mov(B
hit(B,r+x,c+y) || (draw(B,r,c,0);draw(B,r+=x,c+=y))
TMv || (global tmr = Timer(tm)); return (r,c)
end
# rotate tetrominos left/right, if no hit
function rot(B
A = deepcopy(B)
for i=1:4 A.d[i,:]=
A.d .-= sum.(extrema(A.d,dims=1)).>>1 # centralize
TMv || (global tmr = Timer(tm))
for j = c.+(0,+2,-2) # try shifted positions
hit(A,r,j) || (draw(B,r,c,0); draw(A,r,j); return (A,j))
Line 146 ⟶ 41:
end
# record-place,clear-full-lines,drop-above,score
function mark(B
global lines, score, level; ln = 0
for i=1:4 BD[r+B.d[i,1],c>>1+B.d[i,2]+2]=B.bg end # record stuck B4
Line 158 ⟶ 53:
level=isqrt(lines>>3) # updates lines, score, level
end
# function for dialog confirmation
function conf(t) # t: prompt, w/o new line!
print("$t - Enter confirms, other keys ignore")
t = take!(chnl); println("\e[2K"); t==[0xd]
end
# show basic usage- and status info
info()=print("\e[0m\e[26H\e[2K i: Info, l: Locked drop ($LDr), t: Timed move ($TMv)")
# Setup nonblocking, non-echoed keyboard input
ccall(:jl_tty_set_mode,Cint,(Ptr{Cvoid},Cint),stdin.handle,1)==0 ||
throw("Terminal cannot enter raw mode.") # raw terminal mode to catch keystrokes
const chnl = Channel{Array{UInt8,1}}(0) #
@async while true put!(chnl,readavailable(stdin)) end
I = B4(106,[0 0; 0 1; 0 2; 0 3]) # define the 7 tetrominos
Line 168 ⟶ 71:
S = B4(102,[0 1; 0 2; 1 0; 1 1]); Z = B4(101,[0 0; 0 1; 1 1; 1 2])
J = B4(104,[0 0; 1 0; 1 1; 1 2]); L = B4(107,[0 2; 1 0; 1 1; 1 2])
LDr,TMv,Ifo = falses(3)
begin @label RESTART # @label - @goto: require begin..end
global lines,score,level,s20 = 0,0,0," "^20
BD=fill(0,24,15); for j=3:12 BD[23,j]=BD[24,j]=1 end
for i=1:24,j=∪(1,2,13
print("\e[0m\e[2J\e[?25l") # default colors/clear screen/hide cursor
for i=1:22 print("\e[$i;
print("\e[
print("\n\n$s20\n$s20"); X0 = (I,T,O,S,Z,J,L)[rand(1:7)]
while true # random B4, timer to drop, act on keystrokes
global lines,score,level,tm,tmr,LDr,TMv,Ifo
draw(X0,24,10,0)
global X0,X,r,c = (I,T,O,S,Z,J,L)[rand(1:7)],X0,2,10
draw(X0,24,10); info()
print("\
tm=(.8-level*.007)^level; tmr=Timer(0.5) # fixed 0.5s first delay
hit(X,r,c) && (
while isready(chnl) take!(chnl)
while true
global X,r,c,tm,tmr
Line 204 ⟶ 107:
elseif ch==[0x61] X,c=rot(X,r,c) # a
elseif ch==[0x64] X,c=rot(X,r,c,1) # d
elseif ch==[0x20] r0=r;
while !hit(X,r+=1,c) end; draw(X,r-=1,c);score+=2r-2r0; continue
elseif ch==[0x1b,0x5b,0x31,0x7e] # HOME
elseif ch==[0x1b,0x5b,0x34,0x7e] # END
elseif ch == [0x6c] LDr=!LDr; info() # l: Locked drop
elseif ch == [0x74] TMv=!TMv; info() # t: Timed move
elseif ch == [0x69] # i: Info
if (Ifo = !Ifo) io = open(Base.source_path()); readuntil(io,"="^6)
println("\e[0m\e[32H$(readuntil(io,"="^6))"); close(io)
else
print("\e[0m\e[32H\e[J") # erase txt
end end end
sleep(0.01) # not to take all CPU core time
end end end</lang>
The following long comment block has to be appended to program code:
<pre>#====== Julia-TETRIS by Laszlo Hars, Version 1.1 10/21/2018
- Set Terminal window to 49+ rows, don't scroll!
- Key assignments
↑: rotate 90° counterclockwise
↓: soft drop (one line per press)
←: shift left
→: shift right
a: rotate 90° counterclockwise
d: rotate 90° clockwise
I: Info about the program on/off
L: Locked-drop on/off(move after hard drop)
T: Timed move on/off (restart drop timer after move)
SPACE: hard drop until hit
HOME: restart game
END: exit
======
The game is played in the Julia standard Unicode character based Terminal
Controlled by ANSI escape sequences (Windows conhost, ConEmu...)
Set font to e.g. Fantasque Sans Mono
Monospace, height:width = 2:1, line drawing chars
Playfield rows*cols: 10x20 active, +2 extra rows on top
Tetrominos appear centered in row 2 (and 1)
Rotate is around the center of the tetromino. It is not unique
thus the rotated tetromino is also shifted left, then right.
The first of the 3 positions, which does not hit anything is taken.
Naive gravity is used
Full rows (lines) get cleared
Rows above it move down, but floating blocks can remain
Information is displayed under the board
PREVIEW next tetromino
Game LEVEL
Number of LINES cleared
SCORE
Keys for short Info, Locked-drop-, and Timed move status
Game LEVEL: 0,1...= [sqrt(LINES/8)]
Increase at 8,32,72,128,200... lines cleared
SCORE: Cleared_Line values: *(LEVEL+1)
Single = 100
Double = 300
Triple = 500
Tetris = 800
Bonus points: (not increasing with level)
Soft drop = 1 point per line
Hard drop = 2 points per line
Time_delay per drop one line, decreasing with LEVEL
(0.8-LEVEL*0.007)^LEVEL (seconds)
Timing values
Initial delay for new tetromino = 0.5s
Cleared line is shown for 0.3s
Tetrominos are drawn by blocks of 2 space characters with color background
Background color is set by ANSI codes, e.g print("\e[101m ")
bg-color_code shape
Black 100
████
Red 101 Z ████
████
Green 102 S ████
████
Yellow 103 O ████
██
Blue 104 J ██████
██
Magenta 105 T ██████
Cyan 106 I ████████
██
White 107 L ██████
Julia specific notes
Terminal is switched to RAW mode to catch keystrokes.
Non-blocking read is achieved via asynchronous (maybe blocked) 2nd TASK.
Keystrokes are transferred to the main program through a CHANNEL.
A TIMER controls the dropping speed of tetrominos.
In loops Julia 1.0 assumes local variables, when values get assigned,
therefore many GLOBAL variables have to be declared and used
For simplicity Int variables are used; in 64-bit OS versions: 8 Bytes.
In most places Int8 (or Int16, Int32) would work. When changing:
take special care as: Int8(x)+1 -> Int64, Int8(x)+0x1 -> UInt8.
Only the variable "score" needs to be UInt32 or longer.
Assigning Struct to a variable only creates a reference.
For a new instance we need "deepcopy", and rely on garbage collection.
Label - GoTo (for restart) require the main loop enclosed in Begin..End.
Several instructions are written in single lines of at most 84 chars,
to keep the program less than 110 non-comment lines!
#.. Comments denote tasks, explain important points.
The program has embedded Unicode characters. They can be replaced with
\u{hex_digits} in strings, and "∪" replaced with "union"
to make the program all ASCII. Otherwise editing must handle Unicode.
======#</pre>
|