1 --TODO: similar code: get_neighbour, is_surrounded. need TUPLEs?
3 inherit DIR_CONSTANT
; SDL_CONSTANT
; COLOR_TABLE
; CONFIG
6 tile_server_top
: INTEGER is 1
7 tile_server_bottom
: INTEGER is 2
8 tile_normal
: INTEGER is 3
9 tile_terminal
: INTEGER is 4
14 servertopi
: INTEGER is
18 servertopj
: INTEGER is
20 Result := height
// 2 + 1
25 Result := config
.bigfont
31 Result.render_string("Well Done", font
, white
)
43 connected_pipe_color
:= green
44 disconnected_pipe_color
:= darkred
45 connected_terminal_color
:= cyan
46 disconnected_terminal_color
:= darkpurple
55 !!board
.make(1, width
, 1, height
)
59 game_state
:= state_playing
60 if difficulty
> 0 then
67 state_none
: INTEGER is 0
68 state_playing
: INTEGER is 1
69 state_victory
: INTEGER is 2
70 state_quit
: INTEGER is 3
78 until game_state
= state_quit
83 if game_state
= state_playing
then
85 if check_connections
then
86 game_state
:= state_victory
89 if game_state
= state_victory
then
91 win_image
.blit(50, 400)
101 handle_event(e
: EVENT
) is
104 when sdl_keydown
then
106 when sdlk_escape
then
107 game_state
:= state_quit
109 difficulty
:= difficulty
+ 1
110 if difficulty
> 1 then
117 when sdl_mousebuttondown
then
123 handle_mbdown(e
: EVENT
) is
127 if game_state
= state_playing
then
128 i
:= e
.x
// cellwidth
129 j
:= e
.y
// cellheight
130 if on_board(i
, j
) then
140 rotatecw(i
, j
: INTEGER) is
146 t
:= board
.item(i
, j
)
147 if t
= server_top
or else t
= server_bottom
then
148 bak
:= server_top
.neighbour
.item(1)
149 server_top
.neighbour
.put(server_bottom
.neighbour
.item(4), 1)
150 server_bottom
.neighbour
.put(server_bottom
.neighbour
.item(3), 4)
151 server_bottom
.neighbour
.put(server_bottom
.neighbour
.item(2), 3)
152 server_bottom
.neighbour
.put(bak
, 2)
153 elseif t
/= Void
then
154 bak
:= t
.neighbour
.item(4)
158 t
.neighbour
.put(t
.neighbour
.item(dir
- 1), dir
)
161 t
.neighbour
.put(bak
, dir
)
165 rotateccw(i
, j
: INTEGER) is
171 t
:= board
.item(i
, j
)
172 if t
= server_top
or else t
= server_bottom
then
173 bak
:= server_top
.neighbour
.item(1)
174 server_top
.neighbour
.put(server_bottom
.neighbour
.item(2), 1)
175 server_bottom
.neighbour
.put(server_bottom
.neighbour
.item(3), 2)
176 server_bottom
.neighbour
.put(server_bottom
.neighbour
.item(4), 3)
177 server_bottom
.neighbour
.put(bak
, 4)
178 elseif t
/= Void
then
179 bak
:= t
.neighbour
.item(1)
183 t
.neighbour
.put(t
.neighbour
.item(dir
+ 1), dir
)
186 t
.neighbour
.put(bak
, dir
)
190 server_top
, server_bottom
: TILE
203 t
:= board
.item(i
, j
)
223 draw_tile(board
.item(i
, j
))
237 fill_rect(i
* cellwidth
, cellheight
, 1, height
* cellheight
, blue
)
244 fill_rect(cellwidth
, i
* cellheight
, width
* cellwidth
, 1, blue
)
249 cellwidth
: INTEGER is 32
250 cellheight
: INTEGER is 32
251 uppipex
: INTEGER is 13
252 uppipew
: INTEGER is 6
253 uppipeh
: INTEGER is 19
254 leftpipey
: INTEGER is 13
255 leftpipew
: INTEGER is 19
256 leftpipeh
: INTEGER is 6
258 check_connections
: BOOLEAN is
260 check_list
: LINKED_LIST
[TILE
]
271 t
:= board
.item(i
, j
)
281 check_list
.add_last(server_top
)
282 check_list
.add_last(server_bottom
)
284 server_bottom
.connect
287 until check_list
.is_empty
289 t
:= check_list
.first
290 check_list
.remove_first
294 if t
.neighbour
.item(dir
) then
295 t2
:= get_neighbour(t
, dir
)
296 if t2
/= Void
and then
297 t2
.neighbour
.item(dir_opposite(dir
)) and then
298 not t2
.is_connected
then
300 check_list
.add_last(t2
)
310 until i
> width
or else not Result
313 until j
> height
or else not Result
315 t
:= board
.item(i
, j
)
316 if t
/= Void
and then not t
.is_connected
then
325 maybe_wrapx(i
: INTEGER) : INTEGER is
331 elseif i
> width
then
337 maybe_wrapy(i
: INTEGER) : INTEGER is
343 elseif i
> height
then
349 get_neighbour(t
: TILE
; dir
: INTEGER) : TILE
is
356 elseif dir
= dir_down
then
360 if dir
= dir_left
then
362 elseif dir
= dir_right
then
365 x
:= maybe_wrapx(t
.x
+ x1
)
366 y
:= maybe_wrapy(t
.y
+ y1
)
367 if on_board(x
, y
) then
368 Result := board
.item(x
, y
)
372 on_board(x
, y
: INTEGER) : BOOLEAN is
374 Result := x
>= 1 and then x
<= width
375 and then y
>= 1 and then y
<= height
378 connected_pipe_color
: COLOR
379 disconnected_pipe_color
: COLOR
380 connected_terminal_color
: COLOR
381 disconnected_terminal_color
: COLOR
383 draw_tile(tile
: TILE
) is
390 x
:= tile
.x
* cellwidth
391 y
:= tile
.y
* cellheight
392 if tile
.is_connected
then
393 c
:= connected_pipe_color
394 c2
:= connected_terminal_color
396 c
:= disconnected_pipe_color
397 c2
:= disconnected_terminal_color
400 if tile
.neighbour
.item(dir_up
) then
401 fill_rect(x
+ uppipex
, y
, uppipew
, uppipeh
, c
)
403 if tile
.neighbour
.item(dir_left
) then
404 fill_rect(x
, y
+ leftpipey
, leftpipew
, leftpipeh
, c
)
406 if tile
.neighbour
.item(dir_right
) then
407 fill_rect(x
+ uppipex
, y
+ leftpipey
, leftpipew
, leftpipeh
, c
)
409 if tile
.neighbour
.item(dir_down
) then
410 fill_rect(x
+ uppipex
, y
+ leftpipey
, uppipew
, uppipeh
, c
)
414 when tile_server_top
then
415 fill_rect(x
+ 5, y
+ 5, cellwidth
- 10, cellheight
- 5, blue
)
416 when tile_server_bottom
then
417 fill_rect(x
+ 5, y
, cellwidth
- 10, cellheight
- 5, blue
)
418 when tile_terminal
then
419 fill_rect(x
+ 8, y
+ 8, 16, 16, c2
)
426 ext_fill_rect(x
, y
, w
, h
: INTEGER; c
: INTEGER) is
432 open_list
: LINKED_LIST
[TILE
]
442 !!server_bottom
.make_server_bottom
443 place_tile(server_bottom
, servertopi
, servertopj
+ 1)
444 !!server_top
.make_server_top
445 place_tile(server_top
, servertopi
, servertopj
)
449 open_list
.add_last(server_top
)
450 open_list
.add_last(server_bottom
)
453 until open_list
.is_empty
456 i
:= rand
.last_integer(open_list
.count
)
459 i
:= rand
.last_integer(4)
477 if board
.item(i
, j
) /= server_top
then
479 inspect rand
.last_integer(4)
499 try_extend(t
: TILE
; dir
: INTEGER) is
508 elseif dir
= dir_down
then
512 if dir
= dir_left
then
514 elseif dir
= dir_right
then
518 x
:= maybe_wrapx(t
.x
+ x1
)
519 y
:= maybe_wrapy(t
.y
+ y1
)
521 if on_board(x
, y
) then
522 t2
:= board
.item(x
, y
)
523 if t
= server_top
and then (dir
= dir_left
or else dir
= dir_right
) then
524 elseif t2
/= Void
then
528 t
.neighbour
.put(True, dir
)
529 t2
.neighbour
.put(True, dir_opposite(dir
))
530 open_list
.add_last(t2
)
532 from i
:= open_list
.lower
533 until i
> open_list
.upper
535 if is_surrounded(open_list @ i
) then
545 is_surrounded(t
: TILE
) : BOOLEAN is
556 if t
.neighbour
.item(dir
) then
562 elseif dir
= dir_down
then
567 if dir
= dir_left
then
569 elseif dir
= dir_right
then
573 x
:= maybe_wrapx(t
.x
+ x1
)
574 y
:= maybe_wrapy(t
.y
+ y1
)
576 if on_board(x
, y
) then
577 if board
.item(x
, y
) = Void
then
578 if t
= server_top
then
579 if dir
/= dir_left
and then dir
/= dir_right
then
594 place_tile(tile
: TILE
; x
, y
: INTEGER) is
597 board
.put(tile
, x
, y
)
600 poll_event
: EVENT
is
604 Result := ext_poll_event(em
)
611 ext_poll_event(em
: EVENTMAKER
) : EVENT
is
612 external "C" alias "ext_poll_event"
619 fill_rect(x
, y
, w
, h
: INTEGER; c
: COLOR
) is
621 --ext_fill_rect(x + offsetx, y + offsety, w, h, c.to_integer)
622 ext_fill_rect(x
, y
, w
, h
, c
.to_integer
)
627 fill_rect(0, 0, 640, 480, black
)