a must-have feature added
[Leditor.git] / src / tetris.lua
blobe03f50a85b781a520b6bc93769f8e76a7fc61787
1 #!/usr/bin/lua
3 ---[[
5 require'QTimer'
7 --[[
8 local tetris = QGraphicsView.new()
9 local game = QGraphicsScene.new()
10 tetris:setScene(qt.pass(game))
13 tetris:setViewportUpdateMode'NoViewportUpdate'
14 --]]
16 local tetris = QTextEdit.new()
17 tetris:setFont(QFont.new('Monospace', 20))
18 qt.derive(tetris)
19 tetris:setReadOnly(true)
20 tetris:setFixedSize(200,400)
21 tetris:show()
23 tetris.lines = { }
24 tetris.piece = { }
26 local pieces = {
27 --X1 = { cw='X2', ccw='X2', desc = {}, },
28 --X2 = { cw='X1', ccw='X1', desc = {}, },
29 H1 = { cw='H2', ccw='H2', desc = {}, },
30 H2 = { cw='H1', ccw='H1', desc = {}, },
31 Z1 = { cw='Z2', ccw='Z2', desc = {}, },
32 Z2 = { cw='Z1', ccw='Z1', desc = {}, },
33 S1 = { cw='S2', ccw='S2', desc = {}, },
34 S2 = { cw='S1', ccw='S1', desc = {}, },
35 L1 = { cw='L2', ccw='L4', desc = {}, },
36 L2 = { cw='L3', ccw='L1', desc = {}, },
37 L3 = { cw='L4', ccw='L2', desc = {}, },
38 L4 = { cw='L1', ccw='L3', desc = {}, },
39 T1 = { cw='T2', ccw='T4', desc = {}, },
40 T2 = { cw='T3', ccw='T1', desc = {}, },
41 T3 = { cw='T4', ccw='T2', desc = {}, },
42 T4 = { cw='T1', ccw='T3', desc = {}, },
43 B = { desc = {}, },
46 local function put_box(t, i, j)
47 if not t.desc[i] then t.desc[i] = {} end
48 t.desc[i][j] = true
49 end
51 --put_box(pieces.X1, 0, 0)
52 --put_box(pieces.X1, 0, 1)
53 --put_box(pieces.X2, 0, 0)
54 --put_box(pieces.X2, 1, 0)
56 put_box(pieces.H1, 0, -1)
57 put_box(pieces.H1, 0, 0)
58 put_box(pieces.H1, 0, 1)
59 put_box(pieces.H1, 0, 2)
60 put_box(pieces.H2, -1, 0)
61 put_box(pieces.H2, 0, 0)
62 put_box(pieces.H2, 1, 0)
63 put_box(pieces.H2, 2, 0)
65 put_box(pieces.Z1, 0, -1)
66 put_box(pieces.Z1, 0, 0)
67 put_box(pieces.Z1, 1, 0)
68 put_box(pieces.Z1, 1, 1)
69 put_box(pieces.Z2, -1, 0)
70 put_box(pieces.Z2, 0, 0)
71 put_box(pieces.Z2, 0, -1)
72 put_box(pieces.Z2, 1, -1)
74 put_box(pieces.S1, 0, 1)
75 put_box(pieces.S1, 0, 0)
76 put_box(pieces.S1, 1, 0)
77 put_box(pieces.S1, 1, -1)
78 put_box(pieces.S2, -1, 0)
79 put_box(pieces.S2, 0, 0)
80 put_box(pieces.S2, 0, 1)
81 put_box(pieces.S2, 1, 1)
83 put_box(pieces.L1, 0, -1)
84 put_box(pieces.L1, 0, 0)
85 put_box(pieces.L1, 0, 1)
86 put_box(pieces.L1, -1, 1)
87 put_box(pieces.L2, -1, 0)
88 put_box(pieces.L2, 0, 0)
89 put_box(pieces.L2, 1, 0)
90 put_box(pieces.L2, 1, 1)
91 put_box(pieces.L3, 0, -1)
92 put_box(pieces.L3, 0, 0)
93 put_box(pieces.L3, 0, 1)
94 put_box(pieces.L3, 1, -1)
95 put_box(pieces.L4, -1, 0)
96 put_box(pieces.L4, 0, 0)
97 put_box(pieces.L4, 1, 0)
98 put_box(pieces.L4, -1, -1)
100 put_box(pieces.T1, 0, -1)
101 put_box(pieces.T1, 0, 0)
102 put_box(pieces.T1, 0, 1)
103 put_box(pieces.T1, 1, 1)
104 put_box(pieces.T2, -1, 0)
105 put_box(pieces.T2, 0, 0)
106 put_box(pieces.T2, 1, 0)
107 put_box(pieces.T2, 1, -1)
108 put_box(pieces.T3, 0, -1)
109 put_box(pieces.T3, 0, 0)
110 put_box(pieces.T3, 0, 1)
111 put_box(pieces.T3, -1, -1)
112 put_box(pieces.T4, -1, 0)
113 put_box(pieces.T4, 0, 0)
114 put_box(pieces.T4, 1, 0)
115 put_box(pieces.T4, -1, 1)
117 put_box(pieces.B, 0, 0)
118 put_box(pieces.B, 0, 1)
119 put_box(pieces.B, 1, 0)
120 put_box(pieces.B, 1, 1)
124 local null_piece = function(t, k) return {} end
125 for _, t in pairs(pieces) do
126 setmetatable(t.desc, {__index = null_piece })
130 setmetatable(tetris.piece, {
131 __index = function(t, i)
132 local ret = {}
133 setmetatable(ret, {
134 __index = function(s, j)
135 return pieces[t.piece_type].desc[i-t.position.y][j-t.position.x] and string.sub(t.piece_type, 1, 1) or nil
138 return ret
144 local function drawGame()
145 local t = {}
146 for i = 1,10 do for j = 1,10 do
147 t[i] = (t[i] or '|')..(tetris.lines[i][j] or tetris.piece[i][j] or ' ')
148 end end
149 tetris:setText(table.concat(t, '|\n')..'|\n\\==========/')
150 --print(tetris:toPlainText())
153 local function isLegal()
154 for i = 0,11 do
155 for j = 0,11 do
156 if (tetris.piece[i][j]) and ((i>10) or (j>10) or (j<1)) then return false end
157 if tetris.piece[i][j] and tetris.lines[i][j] then return false end
160 return true
163 local function checkLines()
164 for i = 1,10 do
165 local completed = true
166 for j = 1,10 do
167 if not tetris.lines[i][j] then completed=nil end
169 if completed then
170 --print('completed line', i)
171 for k = i,2,-1 do tetris.lines[k] = tetris.lines[k-1] end
172 tetris.lines[1] = {}
175 drawGame()
178 local function placePiece()
179 local t = nil
180 local n = math.random(15)
182 while not t do
183 for _=1,n do t = next(pieces, t) end
185 tetris.piece.piece_type = t
186 tetris.piece.position = { x=5, y=1 }
189 local function pieceDown()
190 --print'piece down'
192 tetris.piece.position.y = tetris.piece.position.y+1
193 local cannot = not isLegal()
194 if cannot then
195 --print'hit'
196 tetris.piece.position.y = tetris.piece.position.y-1
197 for i = 1,10 do for j = 1,10 do
198 tetris.lines[i][j] = tetris.lines[i][j] or tetris.piece[i][j]
199 end end
200 checkLines()
201 placePiece()
203 drawGame()
206 function tetris.reset()
207 for i = 0,10 do
208 tetris.lines[i] = {}
210 placePiece()
212 tetris.reset()
215 local sc
216 sc = QShortcut.new(QKeySequence.new(Qt.Key['Key_Right']), tetris) qt.pass(sc)
217 sc:connect(qt.signal'activated()', qt.slot(
218 function()
219 --print'right'
220 tetris.piece.position.x = tetris.piece.position.x+1
221 local cannot = not isLegal()
222 if cannot then
223 tetris.piece.position.x = tetris.piece.position.x-1
225 drawGame()
228 sc = QShortcut.new(QKeySequence.new(Qt.Key['Key_Left']), tetris) qt.pass(sc)
229 sc:connect(qt.signal'activated()', qt.slot(
230 function()
231 --print'left'
232 tetris.piece.position.x = tetris.piece.position.x-1
233 local cannot = not isLegal()
234 if cannot then
235 tetris.piece.position.x = tetris.piece.position.x+1
237 drawGame()
241 sc = QShortcut.new(QKeySequence.new(Qt.Key['Key_Down']), tetris) qt.pass(sc)
242 sc:connect(qt.signal'activated()', qt.slot(pieceDown))
243 sc = QShortcut.new(QKeySequence.new(Qt.Key['Key_R']), tetris) qt.pass(sc)
244 sc:connect(qt.signal'activated()', qt.slot(tetris.reset))
246 sc = QShortcut.new(QKeySequence.new(Qt.Key['Key_A']), tetris) qt.pass(sc)
247 sc:connect(qt.signal'activated()', qt.slot(
248 function()
249 local old = tetris.piece.piece_type
250 if not pieces[old].ccw then return end
251 tetris.piece.piece_type = pieces[old].ccw
252 local cannot = not isLegal()
253 if cannot then
254 tetris.piece.piece_type = old
256 drawGame()
259 sc = QShortcut.new(QKeySequence.new(Qt.Key['Key_S']), tetris) qt.pass(sc)
260 sc:connect(qt.signal'activated()', qt.slot(
261 function()
262 local old = tetris.piece.piece_type
263 if not pieces[old].cw then return end
264 tetris.piece.piece_type = pieces[old].cw
265 local cannot = not isLegal()
266 if cannot then
267 tetris.piece.piece_type = old
269 drawGame()
273 timer = qt.pass(QTimer.new(tetris))
274 tetris.timer = timer
275 timer:connect(qt.signal'timeout()', qt.slot(pieceDown))
276 timer:start(1000)
277 tetris:show()
278 placePiece()
279 drawGame()
281 --tetris:delete()
283 return tetris
285 --]]