|
Reblox - Source CodeChallenging stacking block game. |
|
REBOL [
Title: "REBLOX"
Author: "Allen Kamp"
Email: allen@aussieweb.com.au
Version: 1.0.2
Date: 20-Feb-2002
Purpose: {Fun & Addictive block-matching game}
Thanks: {Thanks to Chris RG for introducing me to this game.
thanks to Robert Condon for help with the scoring system
And thanks to Anop Boonthaveepath for writing the java applet version I played}
History: [2-mar-2004 1.0.2 "Modified for REBOL/Plugin"]
]
reblox: context [
types: reduce [
[color: red text: "R"]
[color: blue text: "E"]
[color: green text: "B"]
[color: pink text: "O"]
[color: orange text: "L"]
]
rows: 10
columns: 20
tiles: rows * columns
tile-size: 30x30
grid-size: to-pair reduce [columns * tile-size/x rows * tile-size/y]
title-height: 28
tface: none
max-type: rows * columns / length? types
if not integer? max-type [alert "max-type must be an integer"]
random/seed now/precise
puzzle: random 30000
;--Game State
locked: off
game-over?: false
last-found: none
tile-set: copy []
selected: copy []
score-table: copy []
patterns: [0x-1 -1x0 1x0 0x1]
to-index: func [rc [pair!]][
either all [rc/x <= rows rc/y <= columns rc/x > 0 rc/y > 0][
return ((rc/y - 1) * rows) + rc/x
][
return none
]
]
make-tile-set: does [
foreach type types [insert/dup tile-set context type max-type]
]
make-score-table: has [s1 s2 s3 table][
s1: 0.0
s2: 2.0
table: copy [0 [0] 1 [0]]
repeat i max-type - 1 [
append table reduce [i + 1 reduce [s3: s1 + s2]]
s1: s2
s2: s3
]
table
]
scores-obj: context [
selected: 0 worth: 0 tally: 0 removals: copy []
]
scores: make scores-obj []
remove-tiles: does [
foreach face selected [
hide-tile face
]
show selected
move-tiles
clear selected
]
sort-cols: func [a b][a/1 < b/1]
move-tiles: has [cols col][
cols: copy []
foreach face selected [
either col: select cols face/rc/2 [
append col face/rc
][
repend cols [face/rc/2 reduce [face/rc]]
]
]
sort/skip cols 2
move-down cols
move-left cols
]
move-down: func [cols /local bottom top][
foreach [col rcs] cols [
sort/compare rcs :sort-cols
bottom: last rcs
top: -1x0 + bottom
top/1: max top/1 1
while [top/1 > 0][
either copy-tile top bottom [
bottom: bottom + -1x0
top: -1x0 + bottom
][top: -1x0 + top]
]
]
]
move-left: func [cols /local face rc rc-from rc-to count][
count: 0
foreach [col rcs] cols [
face: get-tile rc: to-pair reduce [rows col - count]
if not face/text [
count: count + 1
for c rc/2 columns 1 [
repeat r rows [
copy-tile rc-from: to-pair reduce [r c] rc-to: to-pair reduce [r c - 1]
]
]
]
]
]
find-moves: has [face below right match][
;-- last found is still there?
if all [
last-found
last-found/1/text
last-found/2/text
last-found/1/text = last-found/2/text
][return last-found]
;-- search for a new one
moves?: false
repeat r rows [
repeat c columns [
face: get-tile to-pair reduce [r c]
below: get-tile to-pair reduce [r + 1 c]
right: get-tile to-pair reduce [r c + 1]
if any [
if all [face below face/text below/text][if face/text = below/text [match: below]]
if all [face right face/text right/text][if face/text = right/text [match: right]]
][
return reduce [face match]
]
]
]
return none
]
get-tile: func [rc /local index][
index: to-index rc
if index [pick lay/pane index]
]
copy-tile: func [rc-from rc-to][
rc-from: get-tile rc-from
rc-to: get-tile rc-to
if all [rc-from rc-from/text][
rc-to/color: rc-from/color
rc-to/edge: make rc-to/edge [size: 3x3 color: rc-from/color + 30]
set-font rc-to 'color white
rc-to/text: rc-from/text
hide-tile rc-from
true
]
]
hide-tile: func [face][
face/edge: make face/edge [size: 0x0]
face/color: white
set-font face 'color white
face/text: none
]
clear-selected: does [
foreach face selected [
face/edge: make face/edge [size: 3x3]
face/color: face/font/color
set-font face 'color white
]
show selected
clear selected
]
mark-selected: func [face][
set-font face 'color face/color
face/color: white
face/edge: make face/edge [size: 0x0]
append selected face
]
find-same: func [face target /mark /local f][
if all [face face/text = target not find selected face] [
mark-selected face
foreach pattern patterns [
if f: get-tile (face/rc + pattern) [find-same f target]
]
]
]
update-scores: has [value][
tsel/text: scores/selected
twth/text: to-integer scores/worth
tscr/text: join "Score: " to-integer scores/tally
show [tscr twth tsel]
]
click-action: [
if locked [exit]
locked: true
either face/text [
either find selected face [
append scores/removals length? selected
remove-tiles
scores/tally: scores/tally + scores/worth
show lay
if none? last-found: find-moves [
update-scores
game-over?: true
game-msg/show?: true
show game-msg
locked: true
exit
]
][
clear-selected
find-same face face/text
scores/selected: length? selected
scores/worth: first select score-table (scores/selected)
either (1 < length? selected) [show selected][clear-selected]
]
][
clear-selected
scores/selected: 0
scores/worth: 0
]
update-scores
locked: false
]
lay: [
style bx box tile-size :click-action font [size: 14 shadow: none] edge [size: 3x3 effect: 'bevel] with [id: 0 rc: 0x0]
space 0x0 origin 0x0 across
]
lay: layout/size head insert/dup tail lay 'bx (rows * columns) grid-size
make-grid: has [count face][
count: 0
repeat column columns [
repeat row rows [
count: count + 1
face: pick lay/pane count
face/rc: to-pair reduce [row column]
face/offset: to-pair reduce [(column - 1) * tile-size/x (row - 1) * tile-size/y]
face/offset/y: face/offset/y + title-height
face/id: count
]
]
]
make-game-msg: does [
game-msg: layout/offset [
origin 0x0
text font-size 18 bold "GAME OVER" red
] 0x2
game-msg/color: none
game-msg/offset/x: lay/size/x / 2 - (game-msg/size/x / 2)
game-msg/offset/y: 30
append lay/pane game-msg
]
; Add a title area because plugin doesn't have one, and the original script used one
title-face: copy []
add-title: does [
title-face: layout [origin 0x0 space 0x0 at 0x0 tface: label right " " 600x26 white silver effect [emboss gradcol 1x1 140.140.140 100.100.100]
at 1x1 image logo.gif
]
append lay/pane title-face/pane
]
make-score-board: has [req][
score-board: layout [
style text text middle left
origin 0x0 space 0x0
across
at 0x0 box 600x26 silver effect [emboss gradcol 1x1 140.140.140 100.100.100]
at 2x2 btn "New Game" [puzzle: random 30000 new-game]
btn "Replay Game" [new-game]
btn "Select Game" [
if req: request-text/title "Game Puzzle Number?" [
if not error? try [req: to-integer req][puzzle: req new-game]
]
]
btn-help [show-help]
pad 10
text "Selected:" tsel: text "000"
text "Worth:" twth: text "204668310"
tscr: text "Score: 204668310" right bold
]
score-board/size/x: tile-size/x * columns
score-board/size/y: score-board/size/y + 8
score-board/offset/y: title-height + grid-size/y + 2
score-board/offset/x: 0
score-board/edge: make face/edge [size: 3x3 color: silver effect: 'ibevel]
lay/size/y: title-height + lay/size/y + score-board/size/y + 1
]
help-lay: none
show-help: does [
if not help-lay [
help-lay: center-face layout [origin 5x5 backcolor silver
text as-is black ivory - 20 {
Objective: To achieve a high score or Remove all the blocks.
Play: Remove blocks which touch each other either vertically or horizontally.
Controls: Click once to select, and once again to remove blocks.
(If you change your mind, click on another set of blocks to unselect)
Bonus Points: The more blocks selected/removed in one go, the higher the score.
} 450 bold edge [size: 1x1 color: navy]
]
]
unview/only help-lay
view/new help-lay
]
new-game: has [type mixed][
random/seed: puzzle
scores: make scores-obj []
locked: off
game-over?: false
game-msg/show?: false
last-found: none
selected: head clear selected
update-scores
mixed: random copy tile-set
repeat i tiles [
type: mixed/:i
tile: lay/pane/:i
tile/text: copy type/text
tile/color: type/color
tile/edge: make tile/edge [color: type/color + 30 size: 3x3]
set-font tile 'color white
]
lay/text: join " REBLOX - Puzzle " puzzle
tface/text: lay/text
lay/changes: 'text
show lay
]
init: does [
score-table: make-score-table
make-tile-set
make-grid
make-score-board
add-title
make-game-msg
new-game
view/new center-face lay
append lay/pane score-board
show lay
do-events []
]
]
reblox/init
|