-
Notifications
You must be signed in to change notification settings - Fork 0
/
snake.new.nk
120 lines (88 loc) · 3.08 KB
/
snake.new.nk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
"""
Snake game rewritten using more up-to-date vocabulary.
$ novika console examples/snake.new.nk
"""
needsCapability: console
[ "( X Y -- P ): leaves a console Point object for the given X, Y position."
${ x y }
[ "( Q -- ): prints Quote in console at the X, Y of this point."
x y console:appendEcho
] @: put
[ "( O -- true/false ): leaves whether this and Other points are equal."
bi: [ .x x = ] [ .y y = ] and
] @: equal?
[ "( O -- true/false ): leaves whether this and Other points have opposite
component signs, and therefore, whether they are opposite to each other."
bi: [ .x x * negative? ] [ .y y * negative? ] or
] @: opposite?
[ "( O -- P ): sums the components of this and Other points, and leaves
the resulting Point."
bi: [ .x x + console:width mod ]
[ .y y + console:height mod ]
console:point
] @: addWithWrap
[ "( -- ): sets this point's X and Y components to random values within
console bounds."
0 randTo: [ console:width 1 - ] =: x
0 randTo: [ console:height 1 - ] =: y
] @: moveToRandomPosition
[ [ x '@' y ] ~* ] @: __quote__
this
] @: console:point
[ "( -- ): starts the snake game."
(1 0) console:point $: heading
(0 0) console:point $: apple
[ (0 0) console:point ] vals $: snake
[ "( -- P ): leaves the snake's head Point."
snake first
] @: head
[ "( -- true/false ): leaves whether the snake is dead."
snake # [ head.equal? ] 1 >
] @: dead?
[ "( -- ): adds a point to the snake's body."
snake (dup count) [ dup ] |hydrate
] @: grow
[ "( H -- ): sets Heading unless it is opposite of the current heading."
dup heading.opposite? br: drop [ =: heading ]
] @: setHeading
[ "( -- ): executes a tick of the game."
head heading.addWithWrap $: head
snake ||~> [ head swap =: head ]
] @: tick
[ "( -- ): puts the characters on the screen."
('O' head.put) (snake |~> [ 'o' over.put ]) ('@' apple.put)
] @: render
[ "( -- ): handles keyboard input."
console:hadCtrlPressed? (console:getCharPressed 'c' =) and
=> stopGameLoop
console:hadUpPressed? => [ ( 0 -1) console:point setHeading ^ ]
console:hadDownPressed? => [ ( 0 +1) console:point setHeading ^ ]
console:hadLeftPressed? => [ (-1 0) console:point setHeading ^ ]
console:hadRightPressed? => [ (+1 0) console:point setHeading ^ ]
] @: handleKeyboardInput
[ "( -- ): the game loop. `stopGameLoop` can be used to pause
the game loop, and `startGame` can be used to start/re-start."
console:readKey
dead? => stopGameLoop
apple head.equal? => [ (grow) (apple.moveToRandomPosition) ]
handleKeyboardInput
tick
console:clear
render
console:present
20 nap
] createLoop
drop
@: stopGameLoop
@: startGameLoop
"Die gracefully in case an error occurs. Otherwise, the terminal
will be messed up and most of the error will be omitted."
[ console:off die ] @: __died__
console:on
0 console:setTimeout "Do not wait for input."
apple.moveToRandomPosition
startGameLoop
console:off
] @: game
game
'Bye!' echo