]> git.jsancho.org Git - gacela.git/blob - games/tetris/tetris.scm
Adjustments for running games from emacs or shell.
[gacela.git] / games / tetris / tetris.scm
1 #!/usr/bin/guile \
2 -e gacela-script -s
3 !#
4
5 (use-modules (gacela gacela)
6              (gacela widgets timer))
7 (init-gacela)
8
9 (set-game-properties! #:title "Gacela Tetris" #:fps 15)
10
11 (define (tetramine-i)
12   (let ((color '(1 0 0)))
13     `((,color ,color ,color ,color))))
14
15 (define (tetramine-j)
16   (let ((color '(1 0.5 0)))
17     `((,color ,color ,color)
18       (#f #f ,color))))
19
20 (define (tetramine-l)
21   (let ((color '(1 0 1)))
22     `((#f #f ,color)
23       (,color ,color ,color))))
24
25 (define (tetramine-o)
26   (let ((color '(0 0 1)))
27     `((,color ,color)
28       (,color ,color))))
29
30 (define (tetramine-s)
31   (let ((color '(0 1 0)))
32     `((#f ,color ,color)
33       (,color ,color #f))))
34
35 (define (tetramine-t)
36   (let ((color '(0.5 0 0)))
37     `((,color ,color ,color)
38       (#f ,color #f))))
39
40 (define (tetramine-z)
41   (let ((color '(0 1 1)))
42     `((,color ,color #f)
43       (#f ,color ,color))))
44
45 (define (random-tetramine)
46   (let ((n (random 7)))
47     (cond ((= n 0) (tetramine-i))
48           ((= n 1) (tetramine-j))
49           ((= n 2) (tetramine-l))
50           ((= n 3) (tetramine-o))
51           ((= n 4) (tetramine-s))
52           ((= n 5) (tetramine-t))
53           ((= n 6) (tetramine-z)))))
54
55 (define (draw-cell cell)
56   (cond ((and cell (not (null? cell)))
57          (with-color cell (draw-square #:size 20)))))
58
59 (define (draw-row row)
60   (for-each (lambda (cell) (draw-cell cell) (translate 23 0)) row))
61
62 (define (draw-grid grid)
63   (for-each (lambda (row) (draw-row row) (translate (* -23 (length row)) -23)) grid))
64
65 (define* (join-rows source destination #:optional (offset 0))
66   (cond ((null? source) destination)
67         ((null? destination) '())
68         ((> offset 0) (cons (car destination) (join-rows source (cdr destination) (- offset 1))))
69         (else (cons (or (car source) (car destination))
70                     (join-rows (cdr source) (cdr destination) offset)))))
71
72 (define* (join-grids source destination #:optional (x 0) (y 0))
73   (cond ((null? source) destination)
74         ((null? destination) '())
75         ((> y 0) (cons (car destination)
76                        (join-grids source (cdr destination) x (- y 1))))
77         (else (cons (join-rows (car source) (car destination) x)
78                     (join-grids (cdr source) (cdr destination) x y)))))
79
80 (define* (collide-rows row1 row2 #:optional (offset 0))
81   (cond ((or (null? row1) (null? row2)) #f)
82         ((> offset 0) (collide-rows row1 (cdr row2) (- offset 1)))
83         (else (or (and (car row1) (car row2)) (collide-rows (cdr row1) (cdr row2))))))
84
85 (define* (collide-grids grid1 grid2 #:optional (x 0) (y 0))
86   (cond ((or (null? grid1) (null? grid2)) #f)
87         ((> y 0) (collide-grids grid1 (cdr grid2) x (- y 1)))
88         (else (or (collide-rows (car grid1) (car grid2) x)
89                   (collide-grids (cdr grid1) (cdr grid2) x y)))))
90
91 (define (rotate-tetramine grid)
92   (define (rot grid res)
93     (cond ((null? grid) res)
94           (else (rot (cdr grid) (map cons (car grid) res)))))
95   (rot grid (make-list (length (car grid)))))
96
97 (define (row-completed row)
98   (cond ((null? row) #t)
99         (else (and (car row) (row-completed (cdr row))))))
100
101 (define (remove-rows-completed grid)
102   (let ((res (filter (lambda (x) (not (row-completed x))) grid)))
103     (define (fill grid n)
104       (cond ((< n 1) grid)
105             (else (fill (cons (make-list 14 #f) grid) (- n 1)))))
106     (inc-points (- (length grid) (length res)))
107     (fill res (- 20 (length res)))))
108
109 (define get-points #f)
110 (define get-lines #f)
111 (define inc-points #f)
112
113 (let ((points 0) (lines 0))
114   (set! get-points
115         (lambda ()
116           points))
117
118   (set! get-lines
119         (lambda ()
120           lines))
121
122   (set! inc-points
123         (lambda (l)
124           (define (more-lines-better n)
125             (cond ((= n 0) n)
126                   (else (+ n (more-lines-better (- n 1))))))
127           (set! points (+ points (* (more-lines-better l) 10)))
128           (set! lines (+ lines l)))))
129
130 (define game-func #f)
131 (define display-game-over #f)
132 (define tetramine #f)
133
134 (let ((current-tetramine (random-tetramine)) (x 6) (y 0)
135       (next (random-tetramine))
136       (timer (make-timer))
137       (grid (make-list 20 (make-list 14 #f)))
138       (background (load-texture "fondo_tetris.png"))
139       (font (load-font "lazy.ttf" #:size 20))
140       (game-over #f))
141
142   (set! game-func
143         (lambda ()
144           (if game-over (display-game-over) (tetramine))))
145
146   (set! display-game-over
147         (lambda ()
148           (translate -100 0)
149           (render-text "Game Over" font #:size 50)))
150
151   (set! tetramine
152         (lambda ()
153           (cond ((eq? (get-state timer) 'stopped) (start-timer timer)))
154
155           (cond ((key? 'right)
156                  (cond ((not (collide-grids current-tetramine grid (+ x 1) y))
157                         (set! x (+ x 1))))))
158           (cond ((key? 'left)
159                  (cond ((not (collide-grids current-tetramine grid (- x 1) y))
160                         (set! x (- x 1))))))
161           (cond ((< x 0) (set! x 0))
162                 ((> (+ x (length (car current-tetramine))) 14) (set! x (- 14 (length (car current-tetramine))))))
163
164           (cond ((key-pressed? 'up)
165                  (let ((t1 (rotate-tetramine current-tetramine)))
166                    (cond ((not (collide-grids t1 grid x y))
167                           (set! current-tetramine t1))))))
168
169           (cond ((or (key? 'down) (> (get-time timer) 5000))
170                  (cond ((or (collide-grids current-tetramine grid x (+ y 1))
171                             (> (+ y 1 (length current-tetramine)) 20))
172                         (set! grid (remove-rows-completed (join-grids current-tetramine grid x y)))
173                         (set! current-tetramine next)
174                         (set! x 6)
175                         (set! y 0)
176                         (cond ((collide-grids current-tetramine grid x y) (set! game-over #t)))
177                         (set! next (random-tetramine)))
178                        (else
179                         (set! y (+ y 1))
180                         (start-timer timer)))))
181           (draw-texture background)
182           (translate -288 218)
183           (draw-grid (join-grids current-tetramine grid x y))
184           (translate 440 440)
185           (draw-grid next)
186           (translate -40 -100)
187           (render-text (format #f "Points: ~a" (get-points)) font)
188           (translate 0 -30)
189           (render-text (format #f "Lines: ~a" (get-lines)) font))))
190
191 (let ((frame 0.0) (fps (make-timer)) (update (make-timer)))
192   (start-timer update)
193   (start-timer fps)
194   (game
195    (game-func)
196    (set! frame (+ frame 1))
197    (cond ((> (get-time update) 1000)
198           (display (/ frame (/ (get-time fps) 1000.0)))
199           (newline)
200           (start-timer update)))))