|
Rebtris Game - Source CodeA game similar to Tetris. |
|
REBOL [ title: "REBtris" author: "Frank Sievertsen" version: 1.0.2 date: 2-Apr-2001 ;30-Jul-2000 copyright: "Freeware" ] rebtris: context [ field-size: 10x20 stone-size: 20x20 stones: { xxxx xxx x xxx x xxx x xx xx xx xx xx xx } walls: none lay: none pan: none stone: none akt-falling: none stoning: none pause: no points: 0 points-pane: none level: 1 preview: none start-button: none new-start: func [/local ex col rnd] [ if not empty? preview/pane [hide preview/pane/1 insert pan/pane akt-falling: preview/pane/1 clear preview/pane ] insert preview/pane make pick walls random length? walls [] preview/pane/1/parent-face: preview ex: preview/pane/1/pane col: poke 200.200.200 random 3 0 col: poke col random 3 0 forall ex [ change ex make first ex compose/deep [effect: [gradient 1x1 (col) (col / 2)]] ] preview/pane/1/rotate/norot preview/pane/1/offset: preview/size - preview/pane/1/size / 2 if not akt-falling [new-start exit] akt-falling/parent-face: pan akt-falling/offset: field-size * 1x0 / 2 - 1x0 * stone/size points: points + level show [points-pane preview pan akt-falling] ] init: func [/local ex] [ walls: copy/deep [[]] akt-column: akt-row: 1 layout [ stone: image (stone-size) 200.200.0 effect [gradient 1x1 200.200.0 100.100.0] ] if not parse/all stones [newline tabs some [end-up | no-stone | one-stone | new-row | new-wall]] [make error! [user message "parse error"]] forall walls [ layout [ ex: box 100x100 with [ old-pos: none rotate: func [/norot /local minx miny maxx maxy] [ foreach face pane [ if not norot [face/offset: reverse face/offset * -1x1] if none? minx [ minx: face/offset/x miny: face/offset/y ] minx: min minx face/offset/x miny: min miny face/offset/y ] maxx: maxy: 0 foreach face pane [ face/offset/x: face/offset/x - minx face/offset/y: face/offset/y - miny maxx: max maxx face/offset/x maxy: max maxy face/offset/y ] size: stone/size + to-pair reduce [maxx maxy] ] poses: func [/local out] [ out: make block! length? pane foreach face pane [ append out offset + face/offset + face/size ] out ] legal?: func [/local val out] [ out: make block! length? pane foreach val out: poses [ if any [ val/x > pan/size/x val/y > pan/size/y val/x < stone/size/x val/y < stone/size/y find stoning val ] [ restore-pos return false ] ] save-pos out ] del-line: func [num /local pos changed maxy] [ foreach pos poses [ either pos/y = num [ remove pane changed: yes ] [ if pos/y < num [changed: yes pane/1/offset/y: pane/1/offset/y + stone/size/y] pane: next pane ] ] pane: head pane if changed [ maxy: 0 foreach p pane [ maxy: max maxy p/offset/y ] size/y: maxy + stone/size/y show self ] ] save-pos: func [] [ old-pos: make block! 2 + length? pane repend/only old-pos [offset size] foreach face pane [ repend/only old-pos [face/offset] ] ] restore-pos: func [/local pos] [ if not old-pos [exit] set [offset size] first old-pos pos: next old-pos foreach face pane [ face/offset: pos/1/1 pos: next pos ] ] ] ] ex/pane: copy [] foreach pos first walls [ append ex/pane make stone [offset: pos - 1x1 * stone/size] ] change walls ex stoning: copy [] ] walls: head walls lay: layout [ backdrop effect [gradient 1x1 100.100.100 0.0.0] panel 0.0.0 effect [gradient 0x1 100.0.0 0.80.0] edge [color: gray size: 1x1] [ size (field-size * stone/size) sens: sensor 1x1 rate 2 feel [ engage: func [face action event /local tmp] [ switch action [ time [ if pause [exit] if akt-falling [ akt-falling/offset: akt-falling/offset + (stone/size * 0x1) if not akt-falling/legal? [ show akt-falling append stoning tmp: akt-falling/legal? check-lines new-start if not akt-falling/legal? [akt-falling: none start-button/text: "Start" show start-button] eat-queue exit ] show akt-falling ] ] ] ] ] ] return banner "REBtris" space 6x4 vh1 "Frank Sievertsen" with [font: [size: 12]] panel 0.0.0 [ size (stone/size * 5x4) ] start-button: btn 100 "Start" [ either akt-falling [start-button/text: "Start" show start-button akt-falling: none] [sens/rate: 2 show sens start-button/text: "Stop" show start-button pause: no points: 0 if points-pane [show points-pane] clear pan/pane clear stoning show pan new-start] ] btn 100 "Pause" sky [pause: not pause] pad 0x10 vh1 "Level:" level-pane: banner "888" feel [ redraw: func [face] [face/text: to-string level] ] with [font: [align: 'left]] vh1 "Points:" points-pane: banner "88888888" feel [ redraw: func [face /local mem tmp] [ mem: [1] if mem/1 < (tmp: to-integer points / 1000) [level: level + 1 show level-pane sens/rate: level + 1 show sens] mem/1: tmp face/text: to-string points ] ] with [font: [align: 'left]] pad 0x10 vtext 100x40 "Use cursor keys to control stones." ] lay/feel: make lay/feel [ detect: func [face event] [ if event/type = 'down [system/view/focal-face: none] event ] ] pan: lay/pane/2 if not pan/pane [pan/pane: copy []] preview: lay/pane/5 if not preview/pane [preview/pane: copy []] remove find pan/pane sens insert lay/pane sens ] check-lines: func [/local lines full tmp pos] [ lines: head insert/dup make block! field-size/y 0 field-size/y full: copy [] foreach e stoning [ e: e / stone/size poke lines e/y tmp: (pick lines e/y) + 1 if tmp = field-size/x [append full e/y] ] sort full foreach e full [ foreach face pan/pane [ face/del-line e * stone/size/y ] pos: pan/pane forall pos [ while [all [not tail? pos empty? pos/1/pane]] [hide pos/1 remove pos] ] points: 100 + points show points-pane ] clear stoning foreach face pan/pane [ append stoning face/poses ] ] akt-column: akt-row: 1 tabs: [some "^(tab)"] end-up: [newline tab end] no-stone: [" " (akt-column: akt-column + 1) ] one-stone: ["x" (append/only last walls to-pair reduce [akt-column akt-row]) (akt-column: akt-column + 1) ] new-row: [newline tabs (akt-row: akt-row + 1) (akt-column: 1) ] new-wall: [newline newline tabs (akt-row: akt-column: 1) (append/only walls copy []) ] eat-queue: func [/local port] [ port: open [scheme: 'event] while [wait [port 0]] [error? try [first port]] close port ] ] insert-event-func func [face event] bind [ if all [ event/type = 'key not system/view/focal-face find [up down left right #"p"] event/key akt-falling (not pause) or (event/key = #"p") ] [ switch event/key [ left [akt-falling/offset: akt-falling/offset - (stone/size * 1x0)] right [akt-falling/offset: akt-falling/offset + (stone/size * 1x0)] down [akt-falling/offset: akt-falling/offset + (stone/size * 0x1)] up [akt-falling/rotate] #"p" [pause: not pause] ] akt-falling/legal? show akt-falling return none ] event ] in rebtris 'self if any [not system/script/args empty? form system/script/args] [ random/seed now rebtris/init view rebtris/lay ] |