bitsy.nv
· 14 KiB · Text
Brut
Playground
|| :\: OH, btw, the text stuff assumes you have this font installed
:\: managore.itch.io/m3x6
|:: get color for .|
:color: 51 68 85
|:: get color for #|
:color: 255 187 51
|:: get sprite 1 for .|
:sprite data: (
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
)
|:: get sprite 1 for p|
:sprite data: (
. # . # # # # .
. # # # # # . .
. . . . . . . .
. . # # # # . .
. # . # # . # .
. . # . . # . .
. . # . . # . .
. . # . . # . .
)
|:: is p actor| :actor: p yes
|:: get sprite 2 for p|
:sprite data: (
# . # # # # . .
# # # # # . . .
. . . . . . . .
. . # # # # . .
. # . # # . # .
. . # . . # . .
. . # . . # . .
. . # . . # . .
)
|:: is c actor| :actor: c yes
|:: touched c :angy:?|
|:: touched c :already pet:| :angy:
|:: touched c :touched once:| :already pet:
|:: touched c| :touched once:
|:: get dialogue for c :angy:? :current room: test2?|
:@text to draw: "still agny!!"
|:: get dialogue for c :angy:?|
:@text to draw: "no talk, me angy."
|:: get dialogue for c :already pet:?|
:@text to draw: "okay, enough."
|:: get dialogue for c| :@text to draw: "meow! meow!"
|:: get sprite 1 for c :angy:? :current room: test2?|
:sprite data: (
. . . . . . . .
. . . . . . . .
. . . . . # . #
. . . . . # # #
. . . . . # # #
. . . . # # # .
# . . # # # # .
. # # # # . # .
)
|:: get sprite 2 for c :angy:? :current room: test2?|
:sprite data: (
. . . . . . . .
. . . . . . . .
. . . . . # . #
. . . . . # # #
. . . . . # # #
. . . . # # # .
. # . # # # # .
. # # # # . # .
)
|:: get sprite 1 for c :angy:?|
:sprite data: (
. . . . . . . .
. . . . . . . .
# . # . . . . .
# # # . . . . .
# # # . . . . .
. # # # . . . .
. # # # # . . #
. # . # # # # .
)
|:: get sprite 2 for c :angy:?|
:sprite data: (
. . . . . . . .
. . . . . . . .
# . # . . . . .
# # # . . . . .
# # # . . . . .
. # # # . . . .
. # # # # . # .
. # . # # # # .
)
|:: get sprite 1 for c|
:sprite data: (
. . . . . . . .
. . . . . . . .
. . . . . # . #
. . . . . # # #
. # . . . # # #
. # . # # # # .
. . # # # # # .
. . . # # . # .
)
|:: get sprite 2 for c|
:sprite data: (
. . . . . . . .
. . . . . . . .
. . . . . # . #
. . . . . # # #
. . . . . # # #
# . . # # # # .
. # # # # # # .
. . . # # . # .
)
|:: is w solid| :solid: w yes
|:: get sprite 1 for w|
:sprite data: (
# # # # # # # #
# # . . . . # #
# . # # # # . #
# . # . . # . #
# . # . . # . #
# . # # # # . #
# # . . . . # #
# # # # # # # #
)
|:: is [ solid| :solid: [ yes
|:: get sprite 1 for [|
:sprite data: (
# # # # # # # #
# # . . . . . .
# . # # # # # #
# . # . . . . .
# . # . . . . .
# . # # # # # #
# # . . . . . .
# # # # # # # #
)
|:: is = solid| :solid: = yes
|:: get sprite 1 for =|
:sprite data: (
# # # # # # # #
. . . . . . . .
# # # # # # # #
. . . . . . . .
. . . . . . . .
# # # # # # # #
. . . . . . . .
# # # # # # # #
)
|:: is ] solid| :solid: ] yes
|:: get sprite 1 for ]|
:sprite data: (
# # # # # # # #
. . . . . . # #
# # # # # # . #
. . . . . # . #
. . . . . # . #
# # # # # # . #
. . . . . . # #
# # # # # # # #
)
|:: get sprite 1 for g|
:sprite data: (
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . # . . . . .
. . # . . # . .
. . # . . # . .
)
|:: get sprite 2 for g|
:sprite data: (
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. # . . . . . .
. # . . # . . .
. . # . . # . .
)
|:: is e exit| :exit: e yes
|:: is x exit| :exit: x yes
|:: is i exit| :exit: i yes
|:: is t exit| :exit: t yes
|:: e goes to :current room: test2?| :go to: test
|:: e goes to| :go to: test2
|:: x goes to| :: e goes to
|:: i goes to| :: e goes to
|:: t goes to| :: e goes to
|:: get sprite 1 for e :current room: test2?|
:sprite data: (
. . . . . . . .
. . . # . . . .
. . # # . . . .
. # # # # # # .
. # # # # # # .
. . # # . . . .
. . . # . . . .
. . . . . . . .
)
|:: get sprite 1 for e |
:sprite data: (
. . . . . . . .
. . . . # . . .
. . . . # # . .
. # # # # # # .
. # # # # # # .
. . . . # # . .
. . . . # . . .
. . . . . . . .
)
|:: get sprite 1 for x| :: get sprite 1 for e
|:: get sprite 1 for i| :: get sprite 1 for e
|:: get sprite 1 for t| :: get sprite 1 for e
|| :starting room: test
|:: player for test room| :player: p
|:: get tiles for test|
:room data: (
w w . . . . w w
w . . . . g . w
. . [ = = ] . e
. c . g . . p x
. . . . . . . i
. g [ = = ] . t
w . . . . g . w
w w . . . . w w
)
|:: player for test2 room| :player: p
|:: get tiles for test2|
:room data: (
w w w w w w w w
w . . . g . . w
e . w . . w . w
x p . . . c . w
i . . g . . g w
t . w . . w . w
w . . . g . . w
w w w w w w w w
)
|| :screen resolution: 64 64
:frame for sprites: 1
|:: start? :starting room: $room|
:: change rooms :go to: $room
|:: change rooms? :actors: $1 $2 $3|
|:: change rooms? :solids: $1 $2 $3|
|:: change rooms? :exits: $1 $2 $3|
|:: change rooms? :player actor: $1 $2 $3|
|:: change rooms? :current room: $_|
|:: change rooms :go to: $room|
:current room: $room
:: player for $room room
:: get actor locations
:: set player actor
|:: get actor locations :current room: $room?|
:: get tiles for $room :: find each actor :tile location: 0 0
:: get tiles for $room :: find each solid :tile location: 0 0
:: get tiles for $room :: find each exit :tile location: 0 0
|:: find each $type :room data: ($1 $2 $3 $4 $5 $6 $7 $8)|
:: is $1 $type :: add to $type list :: next tile column
:: is $2 $type :: add to $type list :: next tile column
:: is $3 $type :: add to $type list :: next tile column
:: is $4 $type :: add to $type list :: next tile column
:: is $5 $type :: add to $type list :: next tile column
:: is $6 $type :: add to $type list :: next tile column
:: is $7 $type :: add to $type list :: next tile column
:: is $8 $type :: add to $type list :: next tile row
:: find each $type
|:: find each $type :tile location: $x $y|
|:: add to actor list :actor: $who yes :tile location: $x $y?|
:actors: $who $x $y
|:: add to actor list :actor: $who no|
|:: add to solid list :solid: $what yes :tile location: $x $y?|
:solids: $what $x $y
|:: add to solid list :solid: $what no|
|:: add to exit list :exit: $what yes :tile location: $x $y?|
:exits: $what $x $y
|:: add to exit list :exit: $what no|
|:: set player actor :player: $actor :actors: $actor $x $y|
:: rollback actors :player actor: $actor $x $y
|:: set player actor :player: $actor :no more actors:|
|:: set player actor?|
:: next actor
|::start :screen resolution: $x $y?|
:@graphics: set-resolution fullscreen $x $y
::main loop
|:: draw? :go to: $room?|
:: change rooms
|:: draw|
:: move player actor
:: clear the screen
:: draw current room
:: draw npcs
:: draw player
:: get dialogue :: draw dialogue
:: tick frame
|:: get dialogue :player touching: $something?|
:: get dialogue for $something
|:: get dialogue|
|:: draw dialogue :@text to draw: $something?|
:@graphics: draw-text 0 48
|:: draw dialogue :no dialogue:|
|:: draw dialogue|
|:: is $x actor| :actor: $x no
|:: is $x solid| :solid: $x no
|:: is $x exit| :exit: $x no
|:: get dialogue for $what| :no dialogue:
|:: get sprite $frame for $id|
:: get sprite 1 for $id
|:: next actor :actors: $actor $x $y :actors: $more $_x $_y?|
:discarded actors: $actor $x $y
|:: next actor :actors: $actor $x $y|
:discarded actors: $actor $x $y
:no more actors:
|:: next actor|
:no more actors:
|:: rollback actors :discarded actors: $actor $x $y|
:actors: $actor $x $y
|:: rollback actors|
|:: next solid :solids: $actor $x $y :solids: $more $_x $_y?|
:discarded solids: $actor $x $y
|:: next solid :solids: $actor $x $y|
:discarded solids: $actor $x $y
:no more solids:
|:: next solid|
:no more solids:
|:: rollback solids? :discarded solids: $solid $x $y|
:solids: $solid $x $y
|:: rollback solids|
|:: next exit :exits: $exit $x $y :exits: $more $_x $_y?|
:discarded exits: $exit $x $y
|:: next exit :exits: $exit $x $y|
:discarded exits: $exit $x $y
:no more exits:
|:: next exit|
:no more exits:
|:: rollback exits? :discarded exits: $exit $x $y|
:exits: $exit $x $y
|:: rollback exits|
|:: draw current room :current room: $room?|
:tile location: 0 0
:: get tiles for $room
:: draw room
|:: draw room :room data: ($1 $2 $3 $4 $5 $6 $7 $8)|
:: render tile $1 to screen
:: render tile $2 to screen
:: render tile $3 to screen
:: render tile $4 to screen
:: render tile $5 to screen
:: render tile $6 to screen
:: render tile $7 to screen
:: render tile $8 to screen :: last column
:: draw room
|:: draw room :tile location: $x $y|
|:: render tile $id to screen :: last column|
:: is $id actor :: draw sprite $id :: next tile row
|:: render tile $id to screen|
:: is $id actor :: draw sprite $id :: next tile column
|:: draw npcs? :tile location: $x $y|
|:: draw npcs :no more actors:|
:: rollback actors
|:: draw npcs? :actors: $actor $x $y?|
:: draw sprite $actor :tile location: $x $y
:: next actor
|:: draw player :player actor: $actor $x $y?|
:: draw sprite $actor :tile location: $x $y
|:: draw sprite $actor :actor: $actor yes|
:: draw sprite .
|:: draw sprite $actor? :actor: $actor no|
|:: draw sprite $sprite :frame for sprites: $frame? :tile location: $x $y?|
:pixel location: $x $y
:: get sprite $frame for $sprite
:: draw sprite
|:: draw sprite :sprite data: ($1 $2 $3 $4 $5 $6 $7 $8)|
:: plot $1 :: next pixel column
:: plot $2 :: next pixel column
:: plot $3 :: next pixel column
:: plot $4 :: next pixel column
:: plot $5 :: next pixel column
:: plot $6 :: next pixel column
:: plot $7 :: next pixel column
:: plot $8 :: next pixel row
:: draw sprite
|:: draw sprite :pixel location: $x $y|
|:: plot . :pixel location: $x $y? :color: $r $g $b|
:@graphics: set-pixel $x $y $r $g $b
|:: plot # :pixel location: $x $y? :color: $r $g $b|
:@graphics: set-pixel $x $y $r $g $b
|:: plot $char?|
:: get color for $char
|:: next pixel column :@math: $x :pixel location: $_ $y|
:pixel location: $x $y
|:: next pixel column? :pixel location: $x $y?|
:@math: add $x 1
|:: next pixel row :@math: $y :pixel location: $_x $_y :tile location: $x $_?|
:pixel location: $x $y
|:: next pixel row? :pixel location: $x $y?|
:@math: add $y 1
|:: next tile column :@math: $x :tile location: $_ $y|
:tile location: $x $y
|:: next tile column? :tile location: $x $y?|
:@math: add $x 8
|:: next tile row :@math: $y :tile location: $x $_|
:tile location: 0 $y
|:: next tile row? :tile location: $x $y?|
:@math: add $y 8
|:: tick frame :frame for sprites: 1|
:frame for sprites: 2
|:: tick frame :frame for sprites: 2|
:frame for sprites: 1
|:: move player actor|
:: check if up is pressed :: move player
:: check if right is pressed :: move player
:: check if down is pressed :: move player
:: check if left is pressed :: move player
|:: move player :key pressed: up :player actor: $actor $x 0?|
|:: move player? :key pressed: up :player actor: $actor $x $y?|
:: move y :@math: subtract $y 8
|:: move player :key pressed: right :player actor: $actor 56 $y?|
|:: move player? :key pressed: right :player actor: $actor $x $y?|
:: move x :@math: add $x 8
|:: move player :key pressed: down :player actor: $actor $x 56?|
|:: move player? :key pressed: down :player actor: $actor $x $y?|
:: move y :@math: add $y 8
|:: move player :key pressed: left :player actor: $actor 0 $y?|
|:: move player? :key pressed: left :player actor: $actor $x $y?|
:: move x :@math: subtract $x 8
|:: move player|
|:: move x? :@math: $x :player actor: $actor $_ $y?|
:make move: $x $y
:: clear touching
:: check for solid $x $y
:: check for exit $x $y
:: check for actor $x $y
|:: move y? :@math: $y :player actor: $actor $x $_?|
:make move: $x $y
:: clear touching
:: check for solid $x $y
:: check for exit $x $y
:: check for actor $x $y
|:: move $axis :make move: $x $y :player actor: $actor $_x $_y|
:player actor: $actor $x $y
|:: move $axis|
|:: clear touching :player touching: $not-this|
|:: clear touching|
|:: check for solid $x $y :solids: $what $x $y? :make move: $x $y|
:: rollback solids
|:: check for solid $x $y :no more solids:|
:: rollback solids
|:: check for solid $x $y?|
:: next solid
|:: check for exit $x $y :exits: $what $x $y? :make move: $_x $_y|
:: rollback exits :: $what goes to
|:: check for exit $x $y :no more exits:|
:: rollback exits
|:: check for exit $x $y?|
:: next exit
|:: check for actor $x $y :actors: $what $x $y?|
:: rollback actors
:: touched $what
:player touching: $what
|:: check for actor $x $y :no more actors:|
:: rollback actors
|:: check for actor $x $y?|
:: next actor
1 | || :\: OH, btw, the text stuff assumes you have this font installed |
2 | :\: managore.itch.io/m3x6 |
3 | |
4 | |:: get color for .| |
5 | :color: 51 68 85 |
6 | |:: get color for #| |
7 | :color: 255 187 51 |
8 | |
9 | |:: get sprite 1 for .| |
10 | :sprite data: ( |
11 | . . . . . . . . |
12 | . . . . . . . . |
13 | . . . . . . . . |
14 | . . . . . . . . |
15 | . . . . . . . . |
16 | . . . . . . . . |
17 | . . . . . . . . |
18 | . . . . . . . . |
19 | ) |
20 | |
21 | |:: get sprite 1 for p| |
22 | :sprite data: ( |
23 | . # . # # # # . |
24 | . # # # # # . . |
25 | . . . . . . . . |
26 | . . # # # # . . |
27 | . # . # # . # . |
28 | . . # . . # . . |
29 | . . # . . # . . |
30 | . . # . . # . . |
31 | ) |
32 | |
33 | |:: is p actor| :actor: p yes |
34 | |:: get sprite 2 for p| |
35 | :sprite data: ( |
36 | # . # # # # . . |
37 | # # # # # . . . |
38 | . . . . . . . . |
39 | . . # # # # . . |
40 | . # . # # . # . |
41 | . . # . . # . . |
42 | . . # . . # . . |
43 | . . # . . # . . |
44 | ) |
45 | |
46 | |:: is c actor| :actor: c yes |
47 | |
48 | |:: touched c :angy:?| |
49 | |:: touched c :already pet:| :angy: |
50 | |:: touched c :touched once:| :already pet: |
51 | |:: touched c| :touched once: |
52 | |
53 | |:: get dialogue for c :angy:? :current room: test2?| |
54 | :@text to draw: "still agny!!" |
55 | |:: get dialogue for c :angy:?| |
56 | :@text to draw: "no talk, me angy." |
57 | |:: get dialogue for c :already pet:?| |
58 | :@text to draw: "okay, enough." |
59 | |:: get dialogue for c| :@text to draw: "meow! meow!" |
60 | |
61 | |:: get sprite 1 for c :angy:? :current room: test2?| |
62 | :sprite data: ( |
63 | . . . . . . . . |
64 | . . . . . . . . |
65 | . . . . . # . # |
66 | . . . . . # # # |
67 | . . . . . # # # |
68 | . . . . # # # . |
69 | # . . # # # # . |
70 | . # # # # . # . |
71 | ) |
72 | |:: get sprite 2 for c :angy:? :current room: test2?| |
73 | :sprite data: ( |
74 | . . . . . . . . |
75 | . . . . . . . . |
76 | . . . . . # . # |
77 | . . . . . # # # |
78 | . . . . . # # # |
79 | . . . . # # # . |
80 | . # . # # # # . |
81 | . # # # # . # . |
82 | ) |
83 | |
84 | |:: get sprite 1 for c :angy:?| |
85 | :sprite data: ( |
86 | . . . . . . . . |
87 | . . . . . . . . |
88 | # . # . . . . . |
89 | # # # . . . . . |
90 | # # # . . . . . |
91 | . # # # . . . . |
92 | . # # # # . . # |
93 | . # . # # # # . |
94 | ) |
95 | |:: get sprite 2 for c :angy:?| |
96 | :sprite data: ( |
97 | . . . . . . . . |
98 | . . . . . . . . |
99 | # . # . . . . . |
100 | # # # . . . . . |
101 | # # # . . . . . |
102 | . # # # . . . . |
103 | . # # # # . # . |
104 | . # . # # # # . |
105 | ) |
106 | |
107 | |:: get sprite 1 for c| |
108 | :sprite data: ( |
109 | . . . . . . . . |
110 | . . . . . . . . |
111 | . . . . . # . # |
112 | . . . . . # # # |
113 | . # . . . # # # |
114 | . # . # # # # . |
115 | . . # # # # # . |
116 | . . . # # . # . |
117 | ) |
118 | |:: get sprite 2 for c| |
119 | :sprite data: ( |
120 | . . . . . . . . |
121 | . . . . . . . . |
122 | . . . . . # . # |
123 | . . . . . # # # |
124 | . . . . . # # # |
125 | # . . # # # # . |
126 | . # # # # # # . |
127 | . . . # # . # . |
128 | ) |
129 | |
130 | |:: is w solid| :solid: w yes |
131 | |:: get sprite 1 for w| |
132 | :sprite data: ( |
133 | # # # # # # # # |
134 | # # . . . . # # |
135 | # . # # # # . # |
136 | # . # . . # . # |
137 | # . # . . # . # |
138 | # . # # # # . # |
139 | # # . . . . # # |
140 | # # # # # # # # |
141 | ) |
142 | |
143 | |:: is [ solid| :solid: [ yes |
144 | |:: get sprite 1 for [| |
145 | :sprite data: ( |
146 | # # # # # # # # |
147 | # # . . . . . . |
148 | # . # # # # # # |
149 | # . # . . . . . |
150 | # . # . . . . . |
151 | # . # # # # # # |
152 | # # . . . . . . |
153 | # # # # # # # # |
154 | ) |
155 | |
156 | |:: is = solid| :solid: = yes |
157 | |:: get sprite 1 for =| |
158 | :sprite data: ( |
159 | # # # # # # # # |
160 | . . . . . . . . |
161 | # # # # # # # # |
162 | . . . . . . . . |
163 | . . . . . . . . |
164 | # # # # # # # # |
165 | . . . . . . . . |
166 | # # # # # # # # |
167 | ) |
168 | |
169 | |:: is ] solid| :solid: ] yes |
170 | |:: get sprite 1 for ]| |
171 | :sprite data: ( |
172 | # # # # # # # # |
173 | . . . . . . # # |
174 | # # # # # # . # |
175 | . . . . . # . # |
176 | . . . . . # . # |
177 | # # # # # # . # |
178 | . . . . . . # # |
179 | # # # # # # # # |
180 | ) |
181 | |
182 | |
183 | |:: get sprite 1 for g| |
184 | :sprite data: ( |
185 | . . . . . . . . |
186 | . . . . . . . . |
187 | . . . . . . . . |
188 | . . . . . . . . |
189 | . . . . . . . . |
190 | . . # . . . . . |
191 | . . # . . # . . |
192 | . . # . . # . . |
193 | ) |
194 | |
195 | |:: get sprite 2 for g| |
196 | :sprite data: ( |
197 | . . . . . . . . |
198 | . . . . . . . . |
199 | . . . . . . . . |
200 | . . . . . . . . |
201 | . . . . . . . . |
202 | . # . . . . . . |
203 | . # . . # . . . |
204 | . . # . . # . . |
205 | ) |
206 | |
207 | |:: is e exit| :exit: e yes |
208 | |:: is x exit| :exit: x yes |
209 | |:: is i exit| :exit: i yes |
210 | |:: is t exit| :exit: t yes |
211 | |:: e goes to :current room: test2?| :go to: test |
212 | |:: e goes to| :go to: test2 |
213 | |:: x goes to| :: e goes to |
214 | |:: i goes to| :: e goes to |
215 | |:: t goes to| :: e goes to |
216 | |:: get sprite 1 for e :current room: test2?| |
217 | :sprite data: ( |
218 | . . . . . . . . |
219 | . . . # . . . . |
220 | . . # # . . . . |
221 | . # # # # # # . |
222 | . # # # # # # . |
223 | . . # # . . . . |
224 | . . . # . . . . |
225 | . . . . . . . . |
226 | ) |
227 | |:: get sprite 1 for e | |
228 | :sprite data: ( |
229 | . . . . . . . . |
230 | . . . . # . . . |
231 | . . . . # # . . |
232 | . # # # # # # . |
233 | . # # # # # # . |
234 | . . . . # # . . |
235 | . . . . # . . . |
236 | . . . . . . . . |
237 | ) |
238 | |:: get sprite 1 for x| :: get sprite 1 for e |
239 | |:: get sprite 1 for i| :: get sprite 1 for e |
240 | |:: get sprite 1 for t| :: get sprite 1 for e |
241 | |
242 | || :starting room: test |
243 | |:: player for test room| :player: p |
244 | |:: get tiles for test| |
245 | :room data: ( |
246 | w w . . . . w w |
247 | w . . . . g . w |
248 | . . [ = = ] . e |
249 | . c . g . . p x |
250 | . . . . . . . i |
251 | . g [ = = ] . t |
252 | w . . . . g . w |
253 | w w . . . . w w |
254 | ) |
255 | |
256 | |:: player for test2 room| :player: p |
257 | |:: get tiles for test2| |
258 | :room data: ( |
259 | w w w w w w w w |
260 | w . . . g . . w |
261 | e . w . . w . w |
262 | x p . . . c . w |
263 | i . . g . . g w |
264 | t . w . . w . w |
265 | w . . . g . . w |
266 | w w w w w w w w |
267 | ) |
268 | |
269 | |
270 | |
271 | || :screen resolution: 64 64 |
272 | :frame for sprites: 1 |
273 | |
274 | |:: start? :starting room: $room| |
275 | :: change rooms :go to: $room |
276 | |
277 | |:: change rooms? :actors: $1 $2 $3| |
278 | |:: change rooms? :solids: $1 $2 $3| |
279 | |:: change rooms? :exits: $1 $2 $3| |
280 | |:: change rooms? :player actor: $1 $2 $3| |
281 | |:: change rooms? :current room: $_| |
282 | |:: change rooms :go to: $room| |
283 | :current room: $room |
284 | :: player for $room room |
285 | :: get actor locations |
286 | :: set player actor |
287 | |
288 | |:: get actor locations :current room: $room?| |
289 | :: get tiles for $room :: find each actor :tile location: 0 0 |
290 | :: get tiles for $room :: find each solid :tile location: 0 0 |
291 | :: get tiles for $room :: find each exit :tile location: 0 0 |
292 | |
293 | |:: find each $type :room data: ($1 $2 $3 $4 $5 $6 $7 $8)| |
294 | :: is $1 $type :: add to $type list :: next tile column |
295 | :: is $2 $type :: add to $type list :: next tile column |
296 | :: is $3 $type :: add to $type list :: next tile column |
297 | :: is $4 $type :: add to $type list :: next tile column |
298 | :: is $5 $type :: add to $type list :: next tile column |
299 | :: is $6 $type :: add to $type list :: next tile column |
300 | :: is $7 $type :: add to $type list :: next tile column |
301 | :: is $8 $type :: add to $type list :: next tile row |
302 | :: find each $type |
303 | |:: find each $type :tile location: $x $y| |
304 | |
305 | |:: add to actor list :actor: $who yes :tile location: $x $y?| |
306 | :actors: $who $x $y |
307 | |:: add to actor list :actor: $who no| |
308 | |
309 | |:: add to solid list :solid: $what yes :tile location: $x $y?| |
310 | :solids: $what $x $y |
311 | |:: add to solid list :solid: $what no| |
312 | |
313 | |:: add to exit list :exit: $what yes :tile location: $x $y?| |
314 | :exits: $what $x $y |
315 | |:: add to exit list :exit: $what no| |
316 | |
317 | |
318 | |:: set player actor :player: $actor :actors: $actor $x $y| |
319 | :: rollback actors :player actor: $actor $x $y |
320 | |:: set player actor :player: $actor :no more actors:| |
321 | |:: set player actor?| |
322 | :: next actor |
323 | |
324 | |::start :screen resolution: $x $y?| |
325 | :@graphics: set-resolution fullscreen $x $y |
326 | ::main loop |
327 | |
328 | |
329 | |:: draw? :go to: $room?| |
330 | :: change rooms |
331 | |
332 | |:: draw| |
333 | :: move player actor |
334 | :: clear the screen |
335 | :: draw current room |
336 | :: draw npcs |
337 | :: draw player |
338 | :: get dialogue :: draw dialogue |
339 | :: tick frame |
340 | |
341 | |
342 | |:: get dialogue :player touching: $something?| |
343 | :: get dialogue for $something |
344 | |:: get dialogue| |
345 | |
346 | |:: draw dialogue :@text to draw: $something?| |
347 | :@graphics: draw-text 0 48 |
348 | |:: draw dialogue :no dialogue:| |
349 | |:: draw dialogue| |
350 | |
351 | |
352 | |:: is $x actor| :actor: $x no |
353 | |:: is $x solid| :solid: $x no |
354 | |:: is $x exit| :exit: $x no |
355 | |:: get dialogue for $what| :no dialogue: |
356 | |:: get sprite $frame for $id| |
357 | :: get sprite 1 for $id |
358 | |
359 | |
360 | |:: next actor :actors: $actor $x $y :actors: $more $_x $_y?| |
361 | :discarded actors: $actor $x $y |
362 | |:: next actor :actors: $actor $x $y| |
363 | :discarded actors: $actor $x $y |
364 | :no more actors: |
365 | |:: next actor| |
366 | :no more actors: |
367 | |:: rollback actors :discarded actors: $actor $x $y| |
368 | :actors: $actor $x $y |
369 | |:: rollback actors| |
370 | |
371 | |:: next solid :solids: $actor $x $y :solids: $more $_x $_y?| |
372 | :discarded solids: $actor $x $y |
373 | |:: next solid :solids: $actor $x $y| |
374 | :discarded solids: $actor $x $y |
375 | :no more solids: |
376 | |:: next solid| |
377 | :no more solids: |
378 | |:: rollback solids? :discarded solids: $solid $x $y| |
379 | :solids: $solid $x $y |
380 | |:: rollback solids| |
381 | |
382 | |
383 | |:: next exit :exits: $exit $x $y :exits: $more $_x $_y?| |
384 | :discarded exits: $exit $x $y |
385 | |:: next exit :exits: $exit $x $y| |
386 | :discarded exits: $exit $x $y |
387 | :no more exits: |
388 | |:: next exit| |
389 | :no more exits: |
390 | |:: rollback exits? :discarded exits: $exit $x $y| |
391 | :exits: $exit $x $y |
392 | |:: rollback exits| |
393 | |
394 | |
395 | |:: draw current room :current room: $room?| |
396 | :tile location: 0 0 |
397 | :: get tiles for $room |
398 | :: draw room |
399 | |:: draw room :room data: ($1 $2 $3 $4 $5 $6 $7 $8)| |
400 | :: render tile $1 to screen |
401 | :: render tile $2 to screen |
402 | :: render tile $3 to screen |
403 | :: render tile $4 to screen |
404 | :: render tile $5 to screen |
405 | :: render tile $6 to screen |
406 | :: render tile $7 to screen |
407 | :: render tile $8 to screen :: last column |
408 | :: draw room |
409 | |:: draw room :tile location: $x $y| |
410 | |
411 | |:: render tile $id to screen :: last column| |
412 | :: is $id actor :: draw sprite $id :: next tile row |
413 | |:: render tile $id to screen| |
414 | :: is $id actor :: draw sprite $id :: next tile column |
415 | |
416 | |
417 | |
418 | |:: draw npcs? :tile location: $x $y| |
419 | |:: draw npcs :no more actors:| |
420 | :: rollback actors |
421 | |:: draw npcs? :actors: $actor $x $y?| |
422 | :: draw sprite $actor :tile location: $x $y |
423 | :: next actor |
424 | |
425 | |
426 | |
427 | |:: draw player :player actor: $actor $x $y?| |
428 | :: draw sprite $actor :tile location: $x $y |
429 | |
430 | |
431 | |
432 | |:: draw sprite $actor :actor: $actor yes| |
433 | :: draw sprite . |
434 | |:: draw sprite $actor? :actor: $actor no| |
435 | |:: draw sprite $sprite :frame for sprites: $frame? :tile location: $x $y?| |
436 | :pixel location: $x $y |
437 | :: get sprite $frame for $sprite |
438 | :: draw sprite |
439 | |
440 | |:: draw sprite :sprite data: ($1 $2 $3 $4 $5 $6 $7 $8)| |
441 | :: plot $1 :: next pixel column |
442 | :: plot $2 :: next pixel column |
443 | :: plot $3 :: next pixel column |
444 | :: plot $4 :: next pixel column |
445 | :: plot $5 :: next pixel column |
446 | :: plot $6 :: next pixel column |
447 | :: plot $7 :: next pixel column |
448 | :: plot $8 :: next pixel row |
449 | :: draw sprite |
450 | |:: draw sprite :pixel location: $x $y| |
451 | |
452 | |
453 | |:: plot . :pixel location: $x $y? :color: $r $g $b| |
454 | :@graphics: set-pixel $x $y $r $g $b |
455 | |:: plot # :pixel location: $x $y? :color: $r $g $b| |
456 | :@graphics: set-pixel $x $y $r $g $b |
457 | |:: plot $char?| |
458 | :: get color for $char |
459 | |
460 | |:: next pixel column :@math: $x :pixel location: $_ $y| |
461 | :pixel location: $x $y |
462 | |:: next pixel column? :pixel location: $x $y?| |
463 | :@math: add $x 1 |
464 | |:: next pixel row :@math: $y :pixel location: $_x $_y :tile location: $x $_?| |
465 | :pixel location: $x $y |
466 | |:: next pixel row? :pixel location: $x $y?| |
467 | :@math: add $y 1 |
468 | |
469 | |:: next tile column :@math: $x :tile location: $_ $y| |
470 | :tile location: $x $y |
471 | |:: next tile column? :tile location: $x $y?| |
472 | :@math: add $x 8 |
473 | |:: next tile row :@math: $y :tile location: $x $_| |
474 | :tile location: 0 $y |
475 | |:: next tile row? :tile location: $x $y?| |
476 | :@math: add $y 8 |
477 | |
478 | |:: tick frame :frame for sprites: 1| |
479 | :frame for sprites: 2 |
480 | |:: tick frame :frame for sprites: 2| |
481 | :frame for sprites: 1 |
482 | |
483 | |
484 | |
485 | |:: move player actor| |
486 | :: check if up is pressed :: move player |
487 | :: check if right is pressed :: move player |
488 | :: check if down is pressed :: move player |
489 | :: check if left is pressed :: move player |
490 | |
491 | |:: move player :key pressed: up :player actor: $actor $x 0?| |
492 | |:: move player? :key pressed: up :player actor: $actor $x $y?| |
493 | :: move y :@math: subtract $y 8 |
494 | |:: move player :key pressed: right :player actor: $actor 56 $y?| |
495 | |:: move player? :key pressed: right :player actor: $actor $x $y?| |
496 | :: move x :@math: add $x 8 |
497 | |:: move player :key pressed: down :player actor: $actor $x 56?| |
498 | |:: move player? :key pressed: down :player actor: $actor $x $y?| |
499 | :: move y :@math: add $y 8 |
500 | |:: move player :key pressed: left :player actor: $actor 0 $y?| |
501 | |:: move player? :key pressed: left :player actor: $actor $x $y?| |
502 | :: move x :@math: subtract $x 8 |
503 | |:: move player| |
504 | |
505 | |
506 | |:: move x? :@math: $x :player actor: $actor $_ $y?| |
507 | :make move: $x $y |
508 | :: clear touching |
509 | :: check for solid $x $y |
510 | :: check for exit $x $y |
511 | :: check for actor $x $y |
512 | |
513 | |:: move y? :@math: $y :player actor: $actor $x $_?| |
514 | :make move: $x $y |
515 | :: clear touching |
516 | :: check for solid $x $y |
517 | :: check for exit $x $y |
518 | :: check for actor $x $y |
519 | |
520 | |:: move $axis :make move: $x $y :player actor: $actor $_x $_y| |
521 | :player actor: $actor $x $y |
522 | |:: move $axis| |
523 | |
524 | |:: clear touching :player touching: $not-this| |
525 | |:: clear touching| |
526 | |
527 | |
528 | |:: check for solid $x $y :solids: $what $x $y? :make move: $x $y| |
529 | :: rollback solids |
530 | |:: check for solid $x $y :no more solids:| |
531 | :: rollback solids |
532 | |:: check for solid $x $y?| |
533 | :: next solid |
534 | |
535 | |:: check for exit $x $y :exits: $what $x $y? :make move: $_x $_y| |
536 | :: rollback exits :: $what goes to |
537 | |:: check for exit $x $y :no more exits:| |
538 | :: rollback exits |
539 | |:: check for exit $x $y?| |
540 | :: next exit |
541 | |
542 | |:: check for actor $x $y :actors: $what $x $y?| |
543 | :: rollback actors |
544 | :: touched $what |
545 | :player touching: $what |
546 | |:: check for actor $x $y :no more actors:| |
547 | :: rollback actors |
548 | |:: check for actor $x $y?| |
549 | :: next actor |
nova.py
· 36 KiB · Python
Brut
Playground
#!/usr/bin/env python3
import sys, time, random, copy
try:
import warnings
warnings.filterwarnings("ignore")
from os import environ
environ['PYGAME_HIDE_SUPPORT_PROMPT'] = '1'
import pygame
import pygame.midi
pygame_supported = True
except:
pygame_supported = False
pass
try:
import nfc, ndef, zlib, base64
from nfc.clf import RemoteTarget
nfc_supported = True
except:
nfc_supported = False
pass
def parse_container(string):
left = []
right = []
target = left
characters = (character for character in list(string) + [None])
delimiter = None
for character in characters:
if character in {' ', '\n', '\r', '\t'}:
continue
delimiter = character
break
if delimiter is None:
return None
for character in characters:
if character in {delimiter, None}:
if target is left:
target = right
else:
target = left
yield (left.copy(), right.copy())
left.clear()
right.clear()
else:
target.append(character)
def parse_labels(rules):
left = []
right = []
pair = ([], [])
target = left
delimiter = None
for condition, result in rules:
for side in (condition, result):
characters = (character for character in side + [None])
state = "find delimiter"
for character in characters:
if character == None:
label = "".join(pair[0]).strip()
pattern = "".join(pair[1]).strip()
if not(len(label) == 0 and len(pattern) == 0):
target.append((label, pattern))
pair[0].clear()
pair[1].clear()
break
elif state == "find delimiter":
if character in {' ', '\n', '\r', '\t'}:
continue
delimiter = character
state = "parse label"
elif state == "parse label":
if character == delimiter:
state = "parse pattern"
continue
pair[0].append(character)
elif state == "parse pattern":
if character in {delimiter, None}:
state = "parse label"
label = "".join(pair[0]).strip()
pattern = "".join(pair[1]).strip()
if not(len(label) == 0 and len(pattern) == 0):
target.append((label, pattern))
pair[0].clear()
pair[1].clear()
continue
pair[1].append(character)
if target is left:
target = right
else:
target = left
yield (left.copy(), right.copy())
left.clear()
right.clear()
def parse_patterns(rules):
for condition, result in rules:
left = []
right = []
preserves = []
for label, pattern in condition:
preserve = False
if pattern.endswith('?'):
pattern = pattern[:-1]
preserve = True
if (pattern.startswith('"') or pattern.startswith("'")) and (pattern.endswith('"') or pattern.endswith("'")):
for character in pattern[1:-1]:
left.append((label, [str(ord(character))]))
if preserve:
right.append((label, [str(ord(character))]))
elif pattern.startswith('(') and pattern.endswith(')'):
for token in pattern[1:-1].split():
left.append((label, [token]))
if preserve:
right.append((label, [token]))
elif pattern.startswith('.'):
for tuple in pattern.split('.'):
tuple = tuple.strip()
if len(tuple) != 0:
left.append((label, tuple.split()))
if preserve:
right.append((label, tuple.split()))
else:
left.append((label, pattern.split()))
if preserve:
preserves.append((label, pattern.split()))
for label, pattern in result:
if (pattern.startswith('"') or pattern.startswith("'")) and (pattern.endswith('"') or pattern.endswith("'")):
for character in pattern[1:-1]:
right.append((label, [str(ord(character))]))
elif pattern.startswith('(') and pattern.endswith(')'):
for token in pattern[1:-1].split():
right.append((label, [token]))
elif pattern.startswith('.'):
for tuple in pattern.split('.'):
tuple = tuple.strip()
if len(tuple) != 0:
right.append((label, tuple.split()))
else:
right.append((label, pattern.split()))
yield (left.copy(), right.copy() + preserves.copy())
left.clear()
right.clear()
preserves.clear()
def parse(string):
return parse_patterns(parse_labels(parse_container(string)))
def facts(ruleset):
for left, right in ruleset:
if not left:
for element in right:
yield element
def rules(ruleset):
for left, right in ruleset:
if left:
yield (left, right)
def match(pattern, knowledge, variables=None):
if variables is None:
variables = {}
label, elements = pattern
if label not in knowledge or not knowledge[label][0]:
return None
if knowledge[label][1] >= len(knowledge[label][0]):
knowledge[label][1] = 0
return None
top = knowledge[label][0][(-1 - knowledge[label][1])]
len_top = len(top)
if len_top != len(elements):
knowledge[label][1] = 0
return None
for index in range(len_top):
left = elements[index]
right = top[index]
if left[0] == '$':
variable = left[1:]
if variable not in variables:
variables[variable] = right
elif variables[variable] != right:
knowledge[label][1] = 0
return None
elif left != right:
knowledge[label][1] = 0
return None
knowledge[label][1] += 1
return variables
def consume(pattern, knowledge):
if type(pattern) == str:
knowledge[pattern][0].pop()
knowledge[pattern][1] = 0
else:
label, _ = pattern
knowledge[label][0].pop()
knowledge[label][1] = 0
def produce(pattern, knowledge, variables=None):
if variables is None:
variables = {}
label, elements = pattern
len_elements = len(elements)
fact = [None] * len_elements
for index in range(len_elements):
element = elements[index]
if element[0] == '$':
variable = element[1:]
if variable in variables:
element = variables[variable]
fact[index] = element
if label not in knowledge:
knowledge[label] = [[], 0]
knowledge[label][0].append(fact)
knowledge[label][1] = 0
def reset(pattern, knowledge):
label, _ = pattern
if label in knowledge:
knowledge[label][1] = 0
def prepare(ruleset, knowledge=None):
if knowledge == None:
knowledge = {}
for fact in reversed(list(facts(ruleset))):
label, elements = fact
if label not in knowledge:
knowledge[label] = [[], 0]
knowledge[label][0].append(elements)
return knowledge
def print_knowledge(knowledge, debug=0, maximum=10):
for label, facts in knowledge.items():
facts = facts[0]
if not facts:
continue
if not label:
label = ":"
print(label + ': ', end="")
if len(facts) >= maximum and debug % 2:
print("...", len(facts), "...")
continue
if facts:
if len(facts[-1]) == 0:
print("<blank>")
else:
print(" ".join(facts[-1]))
for fact in reversed(facts[:-1]):
if len(fact) == 0:
fact = ["<blank>"]
print(' ' * (len(label) + 1), " ".join(fact))
def step(ruleset, primitives=[], knowledge=None, snapshots=[], debug=0, trace=False):
variables = {}
steps = 0
if debug >= 3:
print_knowledge(knowledge, debug)
print("")
matched = False
for primitive in primitives:
steps += 1
if primitive(ruleset, knowledge, snapshots):
matched = True
break
if matched:
return (True, steps, knowledge)
for left, right in ruleset:
steps += 1
matched = True
variables.clear()
for pattern in left:
if match(pattern, knowledge, variables) is None:
matched = False
for pattern in left:
reset(pattern, knowledge)
break
if matched:
for pattern in left:
consume(pattern, knowledge)
for pattern in reversed(right):
produce(pattern, knowledge, variables)
break
return (matched, steps, knowledge)
def run(ruleset, primitives=[], knowledge=None, debug=0, trace=False):
knowledge = prepare(ruleset, knowledge)
ruleset = list(rules(ruleset))
matched = True
steps = 0
snapshots = []
while matched:
matched, completed, knowledge = step(ruleset, primitives, knowledge, snapshots, debug, trace)
steps += completed
if trace:
snapshots.append(copy.deepcopy(knowledge))
if debug:
print("Took", steps, "steps.")
return (knowledge, snapshots)
def usage(name):
print(name, ":: a nova interpreter")
print("usage:")
print('\t' + name, "<file> [-d] [-r]")
def math(ruleset, knowledge, snapshots=[], trace=False):
if (variables := match(("@math", ["$operation", "$x", "$y"]), knowledge)) is not None:
try:
operation = variables["operation"]
x = int(variables["x"])
y = int(variables["y"])
if operation == "add":
variables["z"] = str(x + y)
elif operation == "subtract":
variables["z"] = str(x - y)
elif operation == "multiply":
variables["z"] = str(x * y)
elif operation == "divide":
variables["z"] = str(x // y)
elif operation == "modulo":
variables["z"] = str(x % y)
elif operation == "compare":
if x < y:
variables["z"] = "less"
elif x == y:
variables["z"] = "equal"
else:
variables["z"] = "greater"
elif operation == "random":
if y < x:
x, y = y, x
variables["z"] = str(random.randrange(x, y))
consume("@math", knowledge)
produce(("@math", ["$z"]), knowledge, variables)
return True
except Exception as e:
print(e)
pass
return False
def arrays():
arrays = {}
def create(ruleset, knowledge, snapshots=[], trace=False):
nonlocal arrays
if (variables := match(("@array", ["create", "$array", "$size"]), knowledge)) is not None:
try:
array = variables["array"]
size = int(variables["size"])
consume("@array", knowledge)
if array in arrays:
produce(("@array", ["$array", "exists"]), knowledge, variables)
else:
arrays[array] = [None] * size
return True
except:
pass
return False
def set(ruleset, knowledge, snapshots=[], trace=False):
nonlocal arrays
if (variables := match(("@array", ["set", "$array", "$index", "$value"]), knowledge)) is not None:
try:
array = variables["array"]
index = int(variables["index"])
value = variables["value"]
consume("@array", knowledge)
if array not in arrays:
produce(("@array", ["$array", "not", "found"]), knowledge, variables)
elif index >= len(arrays[array]):
produce(("@array", ["$index", "out", "of", "bounds", "for", "$array"]), knowledge, variables)
else:
arrays[array][index] = value
return True
except:
pass
return False
def get(ruleset, knowledge, snapshots=[], trace=False):
nonlocal arrays
if (variables := match(("@array", ["get", "$array", "$index"]), knowledge)) is not None:
try:
array = variables["array"]
index = int(variables["index"])
consume("@array", knowledge)
if array not in arrays:
produce(("@array", ["$array", "not", "found"]), knowledge, variables)
elif index >= len(arrays[array]):
produce(("@array", ["$index", "out", "of", "bounds", "for", "$array"]), knowledge, variables)
else:
if arrays[array][index] == None:
produce(("@array", ["$array", "$index"]), knowledge, variables)
else:
variables["value"] = str(arrays[array][index])
produce(("@array", ["$array", "$index", "$value"]), knowledge, variables)
return True
except:
pass
return False
return [
create,
set,
get
]
def graphics():
keys = {}
mouse_buttons = {}
screen = None
pixels = None
clock = None
font = None
resolution = (0, 0)
def poll_input(ruleset, knowledge, snapshots=[]):
nonlocal keys
nonlocal mouse_buttons
if match(("@input", ["poll-input"]), knowledge) is not None:
consume("@input", knowledge)
for event in pygame.event.get():
if event.type == pygame.QUIT:
produce(("@signal", ["quit"]), knowledge)
keys = pygame.key.get_pressed()
mouse_buttons = pygame.mouse.get_pressed()
return True
return False
def check_key(ruleset, knowledge, snapshots=[]):
nonlocal keys
if (variables := match(("@input", ["check-key", "$key"]), knowledge)) is not None:
consume("@input", knowledge)
keycode = pygame.key.key_code(variables["key"])
if keys[keycode]:
produce(("@input", ["key-pressed", "$key"]), knowledge, variables)
else:
produce(("@input", ["key-released", "$key"]), knowledge, variables)
return True
return False
def check_mouse_button(ruleset, knowledge, snapshots=[]):
nonlocal mouse_buttons
if (variables := match(("@input", ["check-mouse-button", "$button"]), knowledge)) is not None:
consume("@input", knowledge)
button = int(variables["button"])
if mouse_buttons[button]:
produce(("@input", ["mouse-button-pressed", "$button"]), knowledge, variables)
else:
produce(("@input", ["mouse-button-released", "$button"]), knowledge, variables)
return True
return False
def get_mouse_position(ruleset, knowledge, snapshots=[]):
if (variables := match(("@input", ["get-mouse-position"]), knowledge)) is not None:
consume("@input", knowledge)
position = pygame.mouse.get_pos()
variables["x"], variables["y"] = (str(position[0]), str(position[1]))
produce(("@input", ["mouse-position", "$x", "$y"]), knowledge, variables)
return True
return False
def set_pixel(ruleset, knowledge, snapshots=[]):
nonlocal pixels
if (variables := match(("@graphics", ["set-pixel", "$x", "$y", "$r", "$g", "$b"]), knowledge)) is not None:
try:
x = int(variables["x"])
y = int(variables["y"])
r = int(variables["r"])
g = int(variables["g"])
b = int(variables["b"])
pixels[x % resolution[0], y % resolution[1]] = (r % 256, g % 256, b % 256)
consume("@graphics", knowledge)
return True
except:
pass
return False
def draw_line(ruleset, knowledge, snapshots=[]):
nonlocal screen
if (variables := match(("@graphics", ["draw-line", "$x1", "$y1", "$x2", "$y2", "$r", "$g", "$b", "$w"]), knowledge)) is not None:
try:
x1 = int(variables["x1"])
y1 = int(variables["y1"])
x2 = int(variables["x2"])
y2 = int(variables["y2"])
r = int(variables["r"])
g = int(variables["g"])
b = int(variables["b"])
w = int(variables["w"])
pygame.draw.line(screen, (r % 256, g % 256, b % 256), (x1, y1), (x2, y2), w)
consume("@graphics", knowledge)
return True
except:
pass
return False
def draw_rect(ruleset, knowledge, snapshots=[]):
nonlocal screen
if (variables := match(("@graphics", ["draw-rect", "$x1", "$y1", "$x2", "$y2", "$r", "$g", "$b", "$w"]), knowledge)) is not None:
try:
x1 = int(variables["x1"])
y1 = int(variables["y1"])
x2 = int(variables["x2"])
y2 = int(variables["y2"])
r = int(variables["r"])
g = int(variables["g"])
b = int(variables["b"])
w = int(variables["w"])
pygame.draw.rect(screen, (r % 256, g % 256, b % 256), (x1, y1, x2, y2), w)
consume("@graphics", knowledge)
return True
except:
pass
return False
def draw_circle(ruleset, knowledge, snapshots=[]):
nonlocal screen
if (variables := match(("@graphics", ["draw-circle", "$x", "$y", "$d", "$r", "$g", "$b", "$w"]), knowledge)) is not None:
try:
x = int(variables["x"])
y = int(variables["y"])
d = int(variables["d"])
r = int(variables["r"])
g = int(variables["g"])
b = int(variables["b"])
w = int(variables["w"])
pygame.draw.circle(screen, (r % 256, g % 256, b % 256), (x, y), d, w)
consume("@graphics", knowledge)
return True
except:
pass
return False
def clear_screen(ruleset, knowledge, snapshots=[]):
nonlocal screen
if (variables := match(("@graphics", ["clear-screen", "$r", "$g", "$b"]), knowledge)) is not None:
try:
r = int(variables["r"])
g = int(variables["g"])
b = int(variables["b"])
screen.fill((r % 256, g % 256, b % 256))
consume("@graphics", knowledge)
return True
except:
pass
return False
def draw_fps(ruleset, knowledge, snapshots=[]):
nonlocal pixels
nonlocal screen
nonlocal clock
nonlocal font
if match(("@graphics", ["draw-fps"]), knowledge) is not None:
if clock is None:
clock = pygame.time.Clock()
clock.tick()
if font is None:
font = pygame.font.SysFont("m3x6", 16)
framerate = clock.get_fps()
if framerate <= 1_000_000:
fps = font.render(str(int(clock.get_fps())) , 1, pygame.Color("RED"))
pixels.close()
screen.blit(fps, (0, 0))
pixels = pygame.PixelArray(screen)
consume("@graphics", knowledge)
return True
return False
def display(ruleset, knowledge, snapshots=[]):
nonlocal pixels
if match(("@graphics", ["display"]), knowledge) is not None:
pixels.close()
pygame.display.flip()
pixels = pygame.PixelArray(screen)
consume("@graphics", knowledge)
return True
return False
def draw_text(ruleset, knowledge, snapshots=[]):
nonlocal font
nonlocal screen
nonlocal pixels
if (variables := match(("@graphics", ["draw-text", "$x", "$y"]), knowledge)) is not None:
x = int(variables["x"])
y = int(variables["y"])
if font is None:
font = pygame.font.SysFont("m3x6", 16)
text = ''.join(chr(int(n[0])) for n in reversed(knowledge["@text to draw"][0]))
knowledge["@text to draw"] = [[], 0]
drawn_text = font.render(text, False, pygame.Color("WHITE"))
pixels.close()
pygame.draw.rect(screen, (0, 0, 0), (0, 48, 64, 64))
screen.blit(drawn_text, (x, y))
pixels = pygame.PixelArray(screen)
consume("@graphics", knowledge)
return True
return False
def set_resolution(ruleset, knowledge, snapshots=[]):
nonlocal screen
nonlocal pixels
nonlocal resolution
if (variables := match(("@graphics", ["set-resolution", "$x", "$y"]), knowledge)) is not None:
try:
if screen is None:
pygame.init()
x = int(variables["x"])
y = int(variables["y"])
screen = pygame.display.set_mode((x, y))
pygame.display.set_caption("Nova")
icon = pygame.Surface((32, 32))
icon.fill("black")
icon.set_colorkey((0, 0, 0))
pygame.display.set_icon(icon)
pixels = pygame.PixelArray(screen)
resolution = (x, y)
consume("@graphics", knowledge)
return True
except:
pass
elif (variables := match(("@graphics", ["set-resolution", "fullscreen", "$x", "$y"]), knowledge)) is not None:
try:
if screen is None:
pygame.init()
x = int(variables["x"])
y = int(variables["y"])
screen = pygame.display.set_mode((x, y), flags=pygame.FULLSCREEN | pygame.SCALED)
pygame.display.set_caption("Nova")
icon = pygame.Surface((32, 32))
icon.fill("black")
icon.set_colorkey((0, 0, 0))
pygame.display.set_icon(icon)
pixels = pygame.PixelArray(screen)
resolution = (x, y)
consume("@graphics", knowledge)
return True
except:
pass
elif (variables := match(("@graphics", ["set-resolution", "fullscreen"]), knowledge)) is not None:
try:
if screen is None:
pygame.init()
screen = pygame.display.set_mode((0, 0), flags=pygame.FULLSCREEN)
pygame.display.set_caption("Nova")
icon = pygame.Surface((32, 32))
icon.fill("black")
icon.set_colorkey((0, 0, 0))
pygame.display.set_icon(icon)
pixels = pygame.PixelArray(screen)
resolution = pygame.display.get_surface().get_size()
consume("@graphics", knowledge)
return True
except:
pass
return False
return [
set_pixel,
draw_line,
draw_rect,
draw_circle,
draw_text,
display,
poll_input,
draw_fps,
clear_screen,
check_key,
check_mouse_button,
get_mouse_position,
set_resolution
]
def midi():
output = None
def set_output(ruleset, knowledge, snapshots=[]):
nonlocal output
if (variables := match(("@midi", ["set-output", "$x"]), knowledge)) is not None:
try:
if output is None:
pygame.midi.init()
else:
del output
output = pygame.midi.Output(int(variables["x"]))
consume("@midi", knowledge)
return True
except:
pass
return False
def abort(ruleset, knowledge, snapshots=[]):
nonlocal output
if (variables := match(("@midi", ["abort"]), knowledge)) is not None:
try:
output.abort()
consume("@midi", knowledge)
return True
except:
pass
return False
def set_instrument(ruleset, knowledge, snapshots=[]):
nonlocal output
if (variables := match(("@midi", ["set-instrument", "$x"]), knowledge)) is not None:
try:
output.set_instrument(int(variables["x"]))
consume("@midi", knowledge)
return True
except:
pass
return False
def note(ruleset, knowledge, snapshots=[]):
nonlocal output
if (variables := match(("@midi", ["note", "$x", "$y", "$z", "$w"]), knowledge)) is not None:
try:
state = variables["x"]
note = int(variables["y"])
velocity = int(variables["z"])
channel = int(variables["w"])
if state == "on":
output.note_on(note, velocity, channel)
elif state == "off":
output.note_off(note, velocity, channel)
else:
return False
consume("@midi", knowledge)
return True
except:
pass
elif (variables := match(("@midi", ["note", "$x", "$y", "$z"]), knowledge)) is not None:
try:
state = variables["x"]
note = int(variables["y"])
velocity = int(variables["z"])
if state == "on":
output.note_on(note, velocity)
elif state == "off":
output.note_off(note, velocity)
else:
return False
consume("@midi", knowledge)
return True
except:
pass
return False
return [
set_output,
abort,
set_instrument,
note
]
def _time():
def sleep(ruleset, knowledge, snapshots=[]):
if (variables := match(("@time", ["sleep", "$x", "$y"]), knowledge)) is not None:
try:
duration = int(variables["x"])
unit = variables["y"]
if unit == "seconds":
time.sleep(duration)
elif unit == "milliseconds":
time.sleep(0.001 * duration)
else:
return False
consume("@time", knowledge)
return True
except:
pass
return False
return [
sleep
]
def stdio():
def read(ruleset, knowledge, snapshots=[]):
if (variables := match(("@stdio", ["read", "$x"]), knowledge)) is not None:
try:
amount = int(variables["x"])
bytes = sys.stdin.read(amount)
consume("@stdio", knowledge)
for byte in reversed(bytes.encode()):
variables["x"] = str(byte)
produce(("@stdio", ["$x"]), knowledge, variables)
return True
except KeyboardInterrupt:
consume("@stdio", knowledge)
return True
except:
pass
elif (variables := match(("@stdio", ["read"]), knowledge)) is not None:
try:
variables["x"] = str(ord(sys.stdin.read(1)))
consume("@stdio", knowledge)
produce(("@stdio", ["$x"]), knowledge, variables)
return True
except KeyboardInterrupt:
consume("@stdio", knowledge)
return True
except:
pass
return False
def write(ruleset, knowledge, snapshots=[]):
if (variables := match(("@stdio", ["write", "$x", "$y"]), knowledge)) is not None:
try:
byte = int(variables["x"])
length = int(variables["y"])
if byte < 0:
sys.stdout.buffer.write(byte.to_bytes(length, signed=True))
else:
sys.stdout.buffer.write(byte.to_bytes(length))
sys.stdout.buffer.flush()
consume("@stdio", knowledge)
variables["x"] = str(length)
produce(("@stdio", ["wrote", "$x"]), knowledge, variables)
return True
except OverflowError:
length = (byte.bit_length() + 7) // 8
if length == 0:
length = 1
if byte < 0:
sys.stdout.buffer.write(byte.to_bytes(length, signed=True))
else:
sys.stdout.buffer.write(byte.to_bytes(length))
sys.stdout.buffer.flush()
consume("@stdio", knowledge)
variables["x"] = str(length)
produce(("@stdio", ["wrote", "$x"]), knowledge, variables)
return True
except:
pass
elif (variables := match(("@stdio", ["write", "$x"]), knowledge)) is not None:
try:
byte = int(variables["x"])
length = (byte.bit_length() + 7) // 8
if length == 0:
length = 1
if byte < 0:
sys.stdout.buffer.write(byte.to_bytes(length, signed=True))
else:
sys.stdout.buffer.write(byte.to_bytes(length))
sys.stdout.buffer.flush()
consume("@stdio", knowledge)
variables["x"] = str(length)
produce(("@stdio", ["wrote", "$x"]), knowledge, variables)
return True
except:
pass
return False
return [
read, write
]
def _nfc():
clf = None
last_card = None
def nfc_read_card():
nonlocal clf
payload = []
identifier = None
card_types = [RemoteTarget('106A'), RemoteTarget('106B'), RemoteTarget('212F')]
target = clf.sense(*card_types)
if target is not None:
tag = nfc.tag.activate(clf, target)
if tag is not None and tag.ndef is not None:
for record in tag.ndef.records:
text = zlib.decompress(base64.b64decode(record.text)).decode()
payload += list(parse(text))
identifier = tag.identifier
return (payload, identifier)
def open(ruleset, knowledge, snapshots=[]):
nonlocal clf
if (variables := match(("@nfc", ["open"]), knowledge)) is not None:
try:
consume("@nfc", knowledge)
clf = nfc.ContactlessFrontend('usb')
return True
except:
produce(("@nfc", ["no-device"]), knowledge)
return True
return False
def close(ruleset, knowledge, snapshots=[]):
nonlocal clf
if (variables := match(("@nfc", ["close"]), knowledge)) is not None:
try:
consume("@nfc", knowledge)
clf.close()
return True
except:
produce(("@nfc", ["no-device"]), knowledge)
return True
return False
def read_card(ruleset, knowledge, snapshots=[]):
nonlocal last_card
if (variables := match(("@nfc", ["read-card"]), knowledge)) is not None:
try:
consume("@nfc", knowledge)
(payload, identifier) = nfc_read_card()
variables["x"] = "".join([hex(byte)[2:] for byte in identifier])
last_card = payload
produce(("@nfc", ["card", "$x"]), knowledge, variables)
return True
except:
produce(("@nfc", ["read-failed"]), knowledge)
return True
return False
def load_card_rules(ruleset, knowledge, snapshots=[]):
nonlocal last_card
if (variables := match(("@nfc", ["load-rules"]), knowledge)) is not None:
try:
for rule in rules(reversed(last_card)):
ruleset.insert(0, rule)
consume("@nfc", knowledge)
return True
except:
pass
return False
def load_card_facts(ruleset, knowledge, snapshots=[]):
if (variables := match(("@nfc", ["load-facts"]), knowledge)) is not None:
try:
prepare(last_card, knowledge)
consume("@nfc", knowledge)
return True
except:
pass
return False
return [
open,
close,
read_card,
load_card_rules,
load_card_facts
]
def repl(rulesets, primitives, debug):
try:
knowledge, _ = run(rulesets)
print_knowledge(knowledge, debug)
current_stack = ""
command = input("::> ")
while command != "@quit":
if command in {"@run", '!'}:
knowledge, _ = run(rulesets, primitives, knowledge)
if debug:
print_knowledge(knowledge, debug)
if match(("@signal", ["quit"]), knowledge) != None:
break
elif command.startswith('@'):
current_stack = command[1:]
elif command.startswith('.'):
command = command[1:]
knowledge, _ = run(list(parse(command)) + list(rules(rulesets)), primitives, knowledge, debug)
if debug:
print_knowledge(knowledge, debug)
if match(("@signal", ["quit"]), knowledge) != None:
break
elif command.startswith(':'):
command = command[1:]
rulesets = list(parse(command)) + rulesets
knowledge, _ = run(rulesets, primitives, knowledge, debug)
if debug:
print_knowledge(knowledge, debug)
if match(("@signal", ["quit"]), knowledge) != None:
break
elif len(command) != 0:
command = "||:" + current_stack + ':' + command
knowledge, _ = run(list(parse(command)) + list(rules(rulesets)), primitives, knowledge, debug)
if debug:
print_knowledge(knowledge, debug)
if match(("@signal", ["quit"]), knowledge) != None:
break
else:
if debug:
print_knowledge(knowledge, debug)
command = input(":" + current_stack + ":> ")
except EOFError:
pass
except KeyboardInterrupt:
pass
def main(name, arguments):
primitives = _time() + [math] + arrays() + stdio()
if pygame_supported:
primitives += graphics() + midi()
if nfc_supported:
primitives += _nfc()
rulesets = []
debug = 0
prompt = False
trace = False
if not arguments:
usage(name)
return
for argument in arguments:
if argument == '-d':
debug += 1
elif argument == '-r':
prompt = True
elif argument == '-t':
trace = True
else:
with open(argument) as file:
rulesets += list(parse(file.read()))
if prompt:
repl(rulesets, primitives, debug)
else:
if len(rulesets) == 0:
usage(name)
return
if debug:
knowledge, snapshots = run(rulesets, primitives, None, debug, trace)
if trace:
for index in range(len(snapshots)):
print("Snapshot", str(index) + ':')
print("----------------")
print_knowledge(snapshots[index], debug)
print("")
else:
print_knowledge(knowledge, debug)
else:
run(rulesets, primitives, None, debug, trace)
if __name__ == "__main__":
main(sys.argv[0], sys.argv[1:])
1 | #!/usr/bin/env python3 |
2 | |
3 | import sys, time, random, copy |
4 | |
5 | try: |
6 | import warnings |
7 | warnings.filterwarnings("ignore") |
8 | from os import environ |
9 | environ['PYGAME_HIDE_SUPPORT_PROMPT'] = '1' |
10 | import pygame |
11 | import pygame.midi |
12 | pygame_supported = True |
13 | except: |
14 | pygame_supported = False |
15 | pass |
16 | |
17 | try: |
18 | import nfc, ndef, zlib, base64 |
19 | from nfc.clf import RemoteTarget |
20 | nfc_supported = True |
21 | except: |
22 | nfc_supported = False |
23 | pass |
24 | |
25 | def parse_container(string): |
26 | left = [] |
27 | right = [] |
28 | target = left |
29 | characters = (character for character in list(string) + [None]) |
30 | delimiter = None |
31 | for character in characters: |
32 | if character in {' ', '\n', '\r', '\t'}: |
33 | continue |
34 | delimiter = character |
35 | break |
36 | if delimiter is None: |
37 | return None |
38 | for character in characters: |
39 | if character in {delimiter, None}: |
40 | if target is left: |
41 | target = right |
42 | else: |
43 | target = left |
44 | yield (left.copy(), right.copy()) |
45 | left.clear() |
46 | right.clear() |
47 | else: |
48 | target.append(character) |
49 | |
50 | def parse_labels(rules): |
51 | left = [] |
52 | right = [] |
53 | pair = ([], []) |
54 | target = left |
55 | delimiter = None |
56 | for condition, result in rules: |
57 | for side in (condition, result): |
58 | characters = (character for character in side + [None]) |
59 | state = "find delimiter" |
60 | for character in characters: |
61 | if character == None: |
62 | label = "".join(pair[0]).strip() |
63 | pattern = "".join(pair[1]).strip() |
64 | if not(len(label) == 0 and len(pattern) == 0): |
65 | target.append((label, pattern)) |
66 | pair[0].clear() |
67 | pair[1].clear() |
68 | break |
69 | elif state == "find delimiter": |
70 | if character in {' ', '\n', '\r', '\t'}: |
71 | continue |
72 | delimiter = character |
73 | state = "parse label" |
74 | elif state == "parse label": |
75 | if character == delimiter: |
76 | state = "parse pattern" |
77 | continue |
78 | pair[0].append(character) |
79 | elif state == "parse pattern": |
80 | if character in {delimiter, None}: |
81 | state = "parse label" |
82 | label = "".join(pair[0]).strip() |
83 | pattern = "".join(pair[1]).strip() |
84 | if not(len(label) == 0 and len(pattern) == 0): |
85 | target.append((label, pattern)) |
86 | pair[0].clear() |
87 | pair[1].clear() |
88 | continue |
89 | pair[1].append(character) |
90 | if target is left: |
91 | target = right |
92 | else: |
93 | target = left |
94 | yield (left.copy(), right.copy()) |
95 | left.clear() |
96 | right.clear() |
97 | |
98 | def parse_patterns(rules): |
99 | for condition, result in rules: |
100 | left = [] |
101 | right = [] |
102 | preserves = [] |
103 | for label, pattern in condition: |
104 | preserve = False |
105 | if pattern.endswith('?'): |
106 | pattern = pattern[:-1] |
107 | preserve = True |
108 | if (pattern.startswith('"') or pattern.startswith("'")) and (pattern.endswith('"') or pattern.endswith("'")): |
109 | for character in pattern[1:-1]: |
110 | left.append((label, [str(ord(character))])) |
111 | if preserve: |
112 | right.append((label, [str(ord(character))])) |
113 | elif pattern.startswith('(') and pattern.endswith(')'): |
114 | for token in pattern[1:-1].split(): |
115 | left.append((label, [token])) |
116 | if preserve: |
117 | right.append((label, [token])) |
118 | elif pattern.startswith('.'): |
119 | for tuple in pattern.split('.'): |
120 | tuple = tuple.strip() |
121 | if len(tuple) != 0: |
122 | left.append((label, tuple.split())) |
123 | if preserve: |
124 | right.append((label, tuple.split())) |
125 | else: |
126 | left.append((label, pattern.split())) |
127 | if preserve: |
128 | preserves.append((label, pattern.split())) |
129 | for label, pattern in result: |
130 | if (pattern.startswith('"') or pattern.startswith("'")) and (pattern.endswith('"') or pattern.endswith("'")): |
131 | for character in pattern[1:-1]: |
132 | right.append((label, [str(ord(character))])) |
133 | elif pattern.startswith('(') and pattern.endswith(')'): |
134 | for token in pattern[1:-1].split(): |
135 | right.append((label, [token])) |
136 | elif pattern.startswith('.'): |
137 | for tuple in pattern.split('.'): |
138 | tuple = tuple.strip() |
139 | if len(tuple) != 0: |
140 | right.append((label, tuple.split())) |
141 | else: |
142 | right.append((label, pattern.split())) |
143 | yield (left.copy(), right.copy() + preserves.copy()) |
144 | left.clear() |
145 | right.clear() |
146 | preserves.clear() |
147 | |
148 | def parse(string): |
149 | return parse_patterns(parse_labels(parse_container(string))) |
150 | |
151 | def facts(ruleset): |
152 | for left, right in ruleset: |
153 | if not left: |
154 | for element in right: |
155 | yield element |
156 | |
157 | def rules(ruleset): |
158 | for left, right in ruleset: |
159 | if left: |
160 | yield (left, right) |
161 | |
162 | def match(pattern, knowledge, variables=None): |
163 | if variables is None: |
164 | variables = {} |
165 | label, elements = pattern |
166 | if label not in knowledge or not knowledge[label][0]: |
167 | return None |
168 | if knowledge[label][1] >= len(knowledge[label][0]): |
169 | knowledge[label][1] = 0 |
170 | return None |
171 | top = knowledge[label][0][(-1 - knowledge[label][1])] |
172 | len_top = len(top) |
173 | if len_top != len(elements): |
174 | knowledge[label][1] = 0 |
175 | return None |
176 | for index in range(len_top): |
177 | left = elements[index] |
178 | right = top[index] |
179 | if left[0] == '$': |
180 | variable = left[1:] |
181 | if variable not in variables: |
182 | variables[variable] = right |
183 | elif variables[variable] != right: |
184 | knowledge[label][1] = 0 |
185 | return None |
186 | elif left != right: |
187 | knowledge[label][1] = 0 |
188 | return None |
189 | knowledge[label][1] += 1 |
190 | return variables |
191 | |
192 | def consume(pattern, knowledge): |
193 | if type(pattern) == str: |
194 | knowledge[pattern][0].pop() |
195 | knowledge[pattern][1] = 0 |
196 | else: |
197 | label, _ = pattern |
198 | knowledge[label][0].pop() |
199 | knowledge[label][1] = 0 |
200 | |
201 | def produce(pattern, knowledge, variables=None): |
202 | if variables is None: |
203 | variables = {} |
204 | label, elements = pattern |
205 | len_elements = len(elements) |
206 | fact = [None] * len_elements |
207 | for index in range(len_elements): |
208 | element = elements[index] |
209 | if element[0] == '$': |
210 | variable = element[1:] |
211 | if variable in variables: |
212 | element = variables[variable] |
213 | fact[index] = element |
214 | if label not in knowledge: |
215 | knowledge[label] = [[], 0] |
216 | knowledge[label][0].append(fact) |
217 | knowledge[label][1] = 0 |
218 | |
219 | def reset(pattern, knowledge): |
220 | label, _ = pattern |
221 | if label in knowledge: |
222 | knowledge[label][1] = 0 |
223 | |
224 | def prepare(ruleset, knowledge=None): |
225 | if knowledge == None: |
226 | knowledge = {} |
227 | for fact in reversed(list(facts(ruleset))): |
228 | label, elements = fact |
229 | if label not in knowledge: |
230 | knowledge[label] = [[], 0] |
231 | knowledge[label][0].append(elements) |
232 | return knowledge |
233 | |
234 | def print_knowledge(knowledge, debug=0, maximum=10): |
235 | for label, facts in knowledge.items(): |
236 | facts = facts[0] |
237 | if not facts: |
238 | continue |
239 | if not label: |
240 | label = ":" |
241 | print(label + ': ', end="") |
242 | if len(facts) >= maximum and debug % 2: |
243 | print("...", len(facts), "...") |
244 | continue |
245 | if facts: |
246 | if len(facts[-1]) == 0: |
247 | print("<blank>") |
248 | else: |
249 | print(" ".join(facts[-1])) |
250 | for fact in reversed(facts[:-1]): |
251 | if len(fact) == 0: |
252 | fact = ["<blank>"] |
253 | print(' ' * (len(label) + 1), " ".join(fact)) |
254 | |
255 | def step(ruleset, primitives=[], knowledge=None, snapshots=[], debug=0, trace=False): |
256 | variables = {} |
257 | steps = 0 |
258 | if debug >= 3: |
259 | print_knowledge(knowledge, debug) |
260 | print("") |
261 | matched = False |
262 | for primitive in primitives: |
263 | steps += 1 |
264 | if primitive(ruleset, knowledge, snapshots): |
265 | matched = True |
266 | break |
267 | if matched: |
268 | return (True, steps, knowledge) |
269 | for left, right in ruleset: |
270 | steps += 1 |
271 | matched = True |
272 | variables.clear() |
273 | for pattern in left: |
274 | if match(pattern, knowledge, variables) is None: |
275 | matched = False |
276 | for pattern in left: |
277 | reset(pattern, knowledge) |
278 | break |
279 | if matched: |
280 | for pattern in left: |
281 | consume(pattern, knowledge) |
282 | for pattern in reversed(right): |
283 | produce(pattern, knowledge, variables) |
284 | break |
285 | return (matched, steps, knowledge) |
286 | |
287 | def run(ruleset, primitives=[], knowledge=None, debug=0, trace=False): |
288 | knowledge = prepare(ruleset, knowledge) |
289 | ruleset = list(rules(ruleset)) |
290 | matched = True |
291 | steps = 0 |
292 | snapshots = [] |
293 | while matched: |
294 | matched, completed, knowledge = step(ruleset, primitives, knowledge, snapshots, debug, trace) |
295 | steps += completed |
296 | if trace: |
297 | snapshots.append(copy.deepcopy(knowledge)) |
298 | if debug: |
299 | print("Took", steps, "steps.") |
300 | return (knowledge, snapshots) |
301 | |
302 | def usage(name): |
303 | print(name, ":: a nova interpreter") |
304 | print("usage:") |
305 | print('\t' + name, "<file> [-d] [-r]") |
306 | |
307 | def math(ruleset, knowledge, snapshots=[], trace=False): |
308 | if (variables := match(("@math", ["$operation", "$x", "$y"]), knowledge)) is not None: |
309 | try: |
310 | operation = variables["operation"] |
311 | x = int(variables["x"]) |
312 | y = int(variables["y"]) |
313 | if operation == "add": |
314 | variables["z"] = str(x + y) |
315 | elif operation == "subtract": |
316 | variables["z"] = str(x - y) |
317 | elif operation == "multiply": |
318 | variables["z"] = str(x * y) |
319 | elif operation == "divide": |
320 | variables["z"] = str(x // y) |
321 | elif operation == "modulo": |
322 | variables["z"] = str(x % y) |
323 | elif operation == "compare": |
324 | if x < y: |
325 | variables["z"] = "less" |
326 | elif x == y: |
327 | variables["z"] = "equal" |
328 | else: |
329 | variables["z"] = "greater" |
330 | elif operation == "random": |
331 | if y < x: |
332 | x, y = y, x |
333 | variables["z"] = str(random.randrange(x, y)) |
334 | consume("@math", knowledge) |
335 | produce(("@math", ["$z"]), knowledge, variables) |
336 | return True |
337 | except Exception as e: |
338 | print(e) |
339 | pass |
340 | return False |
341 | |
342 | def arrays(): |
343 | arrays = {} |
344 | def create(ruleset, knowledge, snapshots=[], trace=False): |
345 | nonlocal arrays |
346 | if (variables := match(("@array", ["create", "$array", "$size"]), knowledge)) is not None: |
347 | try: |
348 | array = variables["array"] |
349 | size = int(variables["size"]) |
350 | consume("@array", knowledge) |
351 | if array in arrays: |
352 | produce(("@array", ["$array", "exists"]), knowledge, variables) |
353 | else: |
354 | arrays[array] = [None] * size |
355 | return True |
356 | except: |
357 | pass |
358 | return False |
359 | def set(ruleset, knowledge, snapshots=[], trace=False): |
360 | nonlocal arrays |
361 | if (variables := match(("@array", ["set", "$array", "$index", "$value"]), knowledge)) is not None: |
362 | try: |
363 | array = variables["array"] |
364 | index = int(variables["index"]) |
365 | value = variables["value"] |
366 | consume("@array", knowledge) |
367 | if array not in arrays: |
368 | produce(("@array", ["$array", "not", "found"]), knowledge, variables) |
369 | elif index >= len(arrays[array]): |
370 | produce(("@array", ["$index", "out", "of", "bounds", "for", "$array"]), knowledge, variables) |
371 | else: |
372 | arrays[array][index] = value |
373 | return True |
374 | except: |
375 | pass |
376 | return False |
377 | def get(ruleset, knowledge, snapshots=[], trace=False): |
378 | nonlocal arrays |
379 | if (variables := match(("@array", ["get", "$array", "$index"]), knowledge)) is not None: |
380 | try: |
381 | array = variables["array"] |
382 | index = int(variables["index"]) |
383 | consume("@array", knowledge) |
384 | if array not in arrays: |
385 | produce(("@array", ["$array", "not", "found"]), knowledge, variables) |
386 | elif index >= len(arrays[array]): |
387 | produce(("@array", ["$index", "out", "of", "bounds", "for", "$array"]), knowledge, variables) |
388 | else: |
389 | if arrays[array][index] == None: |
390 | produce(("@array", ["$array", "$index"]), knowledge, variables) |
391 | else: |
392 | variables["value"] = str(arrays[array][index]) |
393 | produce(("@array", ["$array", "$index", "$value"]), knowledge, variables) |
394 | return True |
395 | except: |
396 | pass |
397 | return False |
398 | return [ |
399 | create, |
400 | set, |
401 | get |
402 | ] |
403 | |
404 | def graphics(): |
405 | keys = {} |
406 | mouse_buttons = {} |
407 | screen = None |
408 | pixels = None |
409 | clock = None |
410 | font = None |
411 | resolution = (0, 0) |
412 | def poll_input(ruleset, knowledge, snapshots=[]): |
413 | nonlocal keys |
414 | nonlocal mouse_buttons |
415 | if match(("@input", ["poll-input"]), knowledge) is not None: |
416 | consume("@input", knowledge) |
417 | for event in pygame.event.get(): |
418 | if event.type == pygame.QUIT: |
419 | produce(("@signal", ["quit"]), knowledge) |
420 | keys = pygame.key.get_pressed() |
421 | mouse_buttons = pygame.mouse.get_pressed() |
422 | return True |
423 | return False |
424 | def check_key(ruleset, knowledge, snapshots=[]): |
425 | nonlocal keys |
426 | if (variables := match(("@input", ["check-key", "$key"]), knowledge)) is not None: |
427 | consume("@input", knowledge) |
428 | keycode = pygame.key.key_code(variables["key"]) |
429 | if keys[keycode]: |
430 | produce(("@input", ["key-pressed", "$key"]), knowledge, variables) |
431 | else: |
432 | produce(("@input", ["key-released", "$key"]), knowledge, variables) |
433 | return True |
434 | return False |
435 | def check_mouse_button(ruleset, knowledge, snapshots=[]): |
436 | nonlocal mouse_buttons |
437 | if (variables := match(("@input", ["check-mouse-button", "$button"]), knowledge)) is not None: |
438 | consume("@input", knowledge) |
439 | button = int(variables["button"]) |
440 | if mouse_buttons[button]: |
441 | produce(("@input", ["mouse-button-pressed", "$button"]), knowledge, variables) |
442 | else: |
443 | produce(("@input", ["mouse-button-released", "$button"]), knowledge, variables) |
444 | return True |
445 | return False |
446 | def get_mouse_position(ruleset, knowledge, snapshots=[]): |
447 | if (variables := match(("@input", ["get-mouse-position"]), knowledge)) is not None: |
448 | consume("@input", knowledge) |
449 | position = pygame.mouse.get_pos() |
450 | variables["x"], variables["y"] = (str(position[0]), str(position[1])) |
451 | produce(("@input", ["mouse-position", "$x", "$y"]), knowledge, variables) |
452 | return True |
453 | return False |
454 | def set_pixel(ruleset, knowledge, snapshots=[]): |
455 | nonlocal pixels |
456 | if (variables := match(("@graphics", ["set-pixel", "$x", "$y", "$r", "$g", "$b"]), knowledge)) is not None: |
457 | try: |
458 | x = int(variables["x"]) |
459 | y = int(variables["y"]) |
460 | r = int(variables["r"]) |
461 | g = int(variables["g"]) |
462 | b = int(variables["b"]) |
463 | pixels[x % resolution[0], y % resolution[1]] = (r % 256, g % 256, b % 256) |
464 | consume("@graphics", knowledge) |
465 | return True |
466 | except: |
467 | pass |
468 | return False |
469 | def draw_line(ruleset, knowledge, snapshots=[]): |
470 | nonlocal screen |
471 | if (variables := match(("@graphics", ["draw-line", "$x1", "$y1", "$x2", "$y2", "$r", "$g", "$b", "$w"]), knowledge)) is not None: |
472 | try: |
473 | x1 = int(variables["x1"]) |
474 | y1 = int(variables["y1"]) |
475 | x2 = int(variables["x2"]) |
476 | y2 = int(variables["y2"]) |
477 | r = int(variables["r"]) |
478 | g = int(variables["g"]) |
479 | b = int(variables["b"]) |
480 | w = int(variables["w"]) |
481 | pygame.draw.line(screen, (r % 256, g % 256, b % 256), (x1, y1), (x2, y2), w) |
482 | consume("@graphics", knowledge) |
483 | return True |
484 | except: |
485 | pass |
486 | return False |
487 | def draw_rect(ruleset, knowledge, snapshots=[]): |
488 | nonlocal screen |
489 | if (variables := match(("@graphics", ["draw-rect", "$x1", "$y1", "$x2", "$y2", "$r", "$g", "$b", "$w"]), knowledge)) is not None: |
490 | try: |
491 | x1 = int(variables["x1"]) |
492 | y1 = int(variables["y1"]) |
493 | x2 = int(variables["x2"]) |
494 | y2 = int(variables["y2"]) |
495 | r = int(variables["r"]) |
496 | g = int(variables["g"]) |
497 | b = int(variables["b"]) |
498 | w = int(variables["w"]) |
499 | pygame.draw.rect(screen, (r % 256, g % 256, b % 256), (x1, y1, x2, y2), w) |
500 | consume("@graphics", knowledge) |
501 | return True |
502 | except: |
503 | pass |
504 | return False |
505 | def draw_circle(ruleset, knowledge, snapshots=[]): |
506 | nonlocal screen |
507 | if (variables := match(("@graphics", ["draw-circle", "$x", "$y", "$d", "$r", "$g", "$b", "$w"]), knowledge)) is not None: |
508 | try: |
509 | x = int(variables["x"]) |
510 | y = int(variables["y"]) |
511 | d = int(variables["d"]) |
512 | r = int(variables["r"]) |
513 | g = int(variables["g"]) |
514 | b = int(variables["b"]) |
515 | w = int(variables["w"]) |
516 | pygame.draw.circle(screen, (r % 256, g % 256, b % 256), (x, y), d, w) |
517 | consume("@graphics", knowledge) |
518 | return True |
519 | except: |
520 | pass |
521 | return False |
522 | def clear_screen(ruleset, knowledge, snapshots=[]): |
523 | nonlocal screen |
524 | if (variables := match(("@graphics", ["clear-screen", "$r", "$g", "$b"]), knowledge)) is not None: |
525 | try: |
526 | r = int(variables["r"]) |
527 | g = int(variables["g"]) |
528 | b = int(variables["b"]) |
529 | screen.fill((r % 256, g % 256, b % 256)) |
530 | consume("@graphics", knowledge) |
531 | return True |
532 | except: |
533 | pass |
534 | return False |
535 | def draw_fps(ruleset, knowledge, snapshots=[]): |
536 | nonlocal pixels |
537 | nonlocal screen |
538 | nonlocal clock |
539 | nonlocal font |
540 | if match(("@graphics", ["draw-fps"]), knowledge) is not None: |
541 | if clock is None: |
542 | clock = pygame.time.Clock() |
543 | clock.tick() |
544 | if font is None: |
545 | font = pygame.font.SysFont("m3x6", 16) |
546 | framerate = clock.get_fps() |
547 | if framerate <= 1_000_000: |
548 | fps = font.render(str(int(clock.get_fps())) , 1, pygame.Color("RED")) |
549 | pixels.close() |
550 | screen.blit(fps, (0, 0)) |
551 | pixels = pygame.PixelArray(screen) |
552 | consume("@graphics", knowledge) |
553 | return True |
554 | return False |
555 | def display(ruleset, knowledge, snapshots=[]): |
556 | nonlocal pixels |
557 | if match(("@graphics", ["display"]), knowledge) is not None: |
558 | pixels.close() |
559 | pygame.display.flip() |
560 | pixels = pygame.PixelArray(screen) |
561 | consume("@graphics", knowledge) |
562 | return True |
563 | return False |
564 | def draw_text(ruleset, knowledge, snapshots=[]): |
565 | nonlocal font |
566 | nonlocal screen |
567 | nonlocal pixels |
568 | if (variables := match(("@graphics", ["draw-text", "$x", "$y"]), knowledge)) is not None: |
569 | x = int(variables["x"]) |
570 | y = int(variables["y"]) |
571 | if font is None: |
572 | font = pygame.font.SysFont("m3x6", 16) |
573 | text = ''.join(chr(int(n[0])) for n in reversed(knowledge["@text to draw"][0])) |
574 | knowledge["@text to draw"] = [[], 0] |
575 | drawn_text = font.render(text, False, pygame.Color("WHITE")) |
576 | pixels.close() |
577 | pygame.draw.rect(screen, (0, 0, 0), (0, 48, 64, 64)) |
578 | screen.blit(drawn_text, (x, y)) |
579 | pixels = pygame.PixelArray(screen) |
580 | consume("@graphics", knowledge) |
581 | return True |
582 | return False |
583 | |
584 | |
585 | def set_resolution(ruleset, knowledge, snapshots=[]): |
586 | nonlocal screen |
587 | nonlocal pixels |
588 | nonlocal resolution |
589 | if (variables := match(("@graphics", ["set-resolution", "$x", "$y"]), knowledge)) is not None: |
590 | try: |
591 | if screen is None: |
592 | pygame.init() |
593 | x = int(variables["x"]) |
594 | y = int(variables["y"]) |
595 | screen = pygame.display.set_mode((x, y)) |
596 | pygame.display.set_caption("Nova") |
597 | icon = pygame.Surface((32, 32)) |
598 | icon.fill("black") |
599 | icon.set_colorkey((0, 0, 0)) |
600 | pygame.display.set_icon(icon) |
601 | pixels = pygame.PixelArray(screen) |
602 | resolution = (x, y) |
603 | consume("@graphics", knowledge) |
604 | return True |
605 | except: |
606 | pass |
607 | elif (variables := match(("@graphics", ["set-resolution", "fullscreen", "$x", "$y"]), knowledge)) is not None: |
608 | try: |
609 | if screen is None: |
610 | pygame.init() |
611 | x = int(variables["x"]) |
612 | y = int(variables["y"]) |
613 | screen = pygame.display.set_mode((x, y), flags=pygame.FULLSCREEN | pygame.SCALED) |
614 | pygame.display.set_caption("Nova") |
615 | icon = pygame.Surface((32, 32)) |
616 | icon.fill("black") |
617 | icon.set_colorkey((0, 0, 0)) |
618 | pygame.display.set_icon(icon) |
619 | pixels = pygame.PixelArray(screen) |
620 | resolution = (x, y) |
621 | consume("@graphics", knowledge) |
622 | return True |
623 | except: |
624 | pass |
625 | elif (variables := match(("@graphics", ["set-resolution", "fullscreen"]), knowledge)) is not None: |
626 | try: |
627 | if screen is None: |
628 | pygame.init() |
629 | screen = pygame.display.set_mode((0, 0), flags=pygame.FULLSCREEN) |
630 | pygame.display.set_caption("Nova") |
631 | icon = pygame.Surface((32, 32)) |
632 | icon.fill("black") |
633 | icon.set_colorkey((0, 0, 0)) |
634 | pygame.display.set_icon(icon) |
635 | pixels = pygame.PixelArray(screen) |
636 | resolution = pygame.display.get_surface().get_size() |
637 | consume("@graphics", knowledge) |
638 | return True |
639 | except: |
640 | pass |
641 | return False |
642 | return [ |
643 | set_pixel, |
644 | draw_line, |
645 | draw_rect, |
646 | draw_circle, |
647 | draw_text, |
648 | display, |
649 | poll_input, |
650 | draw_fps, |
651 | clear_screen, |
652 | check_key, |
653 | check_mouse_button, |
654 | get_mouse_position, |
655 | set_resolution |
656 | ] |
657 | |
658 | def midi(): |
659 | output = None |
660 | def set_output(ruleset, knowledge, snapshots=[]): |
661 | nonlocal output |
662 | if (variables := match(("@midi", ["set-output", "$x"]), knowledge)) is not None: |
663 | try: |
664 | if output is None: |
665 | pygame.midi.init() |
666 | else: |
667 | del output |
668 | output = pygame.midi.Output(int(variables["x"])) |
669 | consume("@midi", knowledge) |
670 | return True |
671 | except: |
672 | pass |
673 | return False |
674 | def abort(ruleset, knowledge, snapshots=[]): |
675 | nonlocal output |
676 | if (variables := match(("@midi", ["abort"]), knowledge)) is not None: |
677 | try: |
678 | output.abort() |
679 | consume("@midi", knowledge) |
680 | return True |
681 | except: |
682 | pass |
683 | return False |
684 | def set_instrument(ruleset, knowledge, snapshots=[]): |
685 | nonlocal output |
686 | if (variables := match(("@midi", ["set-instrument", "$x"]), knowledge)) is not None: |
687 | try: |
688 | output.set_instrument(int(variables["x"])) |
689 | consume("@midi", knowledge) |
690 | return True |
691 | except: |
692 | pass |
693 | return False |
694 | def note(ruleset, knowledge, snapshots=[]): |
695 | nonlocal output |
696 | if (variables := match(("@midi", ["note", "$x", "$y", "$z", "$w"]), knowledge)) is not None: |
697 | try: |
698 | state = variables["x"] |
699 | note = int(variables["y"]) |
700 | velocity = int(variables["z"]) |
701 | channel = int(variables["w"]) |
702 | if state == "on": |
703 | output.note_on(note, velocity, channel) |
704 | elif state == "off": |
705 | output.note_off(note, velocity, channel) |
706 | else: |
707 | return False |
708 | consume("@midi", knowledge) |
709 | return True |
710 | except: |
711 | pass |
712 | elif (variables := match(("@midi", ["note", "$x", "$y", "$z"]), knowledge)) is not None: |
713 | try: |
714 | state = variables["x"] |
715 | note = int(variables["y"]) |
716 | velocity = int(variables["z"]) |
717 | if state == "on": |
718 | output.note_on(note, velocity) |
719 | elif state == "off": |
720 | output.note_off(note, velocity) |
721 | else: |
722 | return False |
723 | consume("@midi", knowledge) |
724 | return True |
725 | except: |
726 | pass |
727 | return False |
728 | return [ |
729 | set_output, |
730 | abort, |
731 | set_instrument, |
732 | note |
733 | ] |
734 | |
735 | def _time(): |
736 | def sleep(ruleset, knowledge, snapshots=[]): |
737 | if (variables := match(("@time", ["sleep", "$x", "$y"]), knowledge)) is not None: |
738 | try: |
739 | duration = int(variables["x"]) |
740 | unit = variables["y"] |
741 | if unit == "seconds": |
742 | time.sleep(duration) |
743 | elif unit == "milliseconds": |
744 | time.sleep(0.001 * duration) |
745 | else: |
746 | return False |
747 | consume("@time", knowledge) |
748 | return True |
749 | except: |
750 | pass |
751 | return False |
752 | return [ |
753 | sleep |
754 | ] |
755 | |
756 | def stdio(): |
757 | def read(ruleset, knowledge, snapshots=[]): |
758 | if (variables := match(("@stdio", ["read", "$x"]), knowledge)) is not None: |
759 | try: |
760 | amount = int(variables["x"]) |
761 | bytes = sys.stdin.read(amount) |
762 | consume("@stdio", knowledge) |
763 | for byte in reversed(bytes.encode()): |
764 | variables["x"] = str(byte) |
765 | produce(("@stdio", ["$x"]), knowledge, variables) |
766 | return True |
767 | except KeyboardInterrupt: |
768 | consume("@stdio", knowledge) |
769 | return True |
770 | except: |
771 | pass |
772 | elif (variables := match(("@stdio", ["read"]), knowledge)) is not None: |
773 | try: |
774 | variables["x"] = str(ord(sys.stdin.read(1))) |
775 | consume("@stdio", knowledge) |
776 | produce(("@stdio", ["$x"]), knowledge, variables) |
777 | return True |
778 | except KeyboardInterrupt: |
779 | consume("@stdio", knowledge) |
780 | return True |
781 | except: |
782 | pass |
783 | return False |
784 | def write(ruleset, knowledge, snapshots=[]): |
785 | if (variables := match(("@stdio", ["write", "$x", "$y"]), knowledge)) is not None: |
786 | try: |
787 | byte = int(variables["x"]) |
788 | length = int(variables["y"]) |
789 | if byte < 0: |
790 | sys.stdout.buffer.write(byte.to_bytes(length, signed=True)) |
791 | else: |
792 | sys.stdout.buffer.write(byte.to_bytes(length)) |
793 | sys.stdout.buffer.flush() |
794 | consume("@stdio", knowledge) |
795 | variables["x"] = str(length) |
796 | produce(("@stdio", ["wrote", "$x"]), knowledge, variables) |
797 | return True |
798 | except OverflowError: |
799 | length = (byte.bit_length() + 7) // 8 |
800 | if length == 0: |
801 | length = 1 |
802 | if byte < 0: |
803 | sys.stdout.buffer.write(byte.to_bytes(length, signed=True)) |
804 | else: |
805 | sys.stdout.buffer.write(byte.to_bytes(length)) |
806 | sys.stdout.buffer.flush() |
807 | consume("@stdio", knowledge) |
808 | variables["x"] = str(length) |
809 | produce(("@stdio", ["wrote", "$x"]), knowledge, variables) |
810 | return True |
811 | except: |
812 | pass |
813 | elif (variables := match(("@stdio", ["write", "$x"]), knowledge)) is not None: |
814 | try: |
815 | byte = int(variables["x"]) |
816 | length = (byte.bit_length() + 7) // 8 |
817 | if length == 0: |
818 | length = 1 |
819 | if byte < 0: |
820 | sys.stdout.buffer.write(byte.to_bytes(length, signed=True)) |
821 | else: |
822 | sys.stdout.buffer.write(byte.to_bytes(length)) |
823 | sys.stdout.buffer.flush() |
824 | consume("@stdio", knowledge) |
825 | variables["x"] = str(length) |
826 | produce(("@stdio", ["wrote", "$x"]), knowledge, variables) |
827 | return True |
828 | except: |
829 | pass |
830 | return False |
831 | return [ |
832 | read, write |
833 | ] |
834 | |
835 | def _nfc(): |
836 | clf = None |
837 | last_card = None |
838 | def nfc_read_card(): |
839 | nonlocal clf |
840 | payload = [] |
841 | identifier = None |
842 | card_types = [RemoteTarget('106A'), RemoteTarget('106B'), RemoteTarget('212F')] |
843 | target = clf.sense(*card_types) |
844 | if target is not None: |
845 | tag = nfc.tag.activate(clf, target) |
846 | if tag is not None and tag.ndef is not None: |
847 | for record in tag.ndef.records: |
848 | text = zlib.decompress(base64.b64decode(record.text)).decode() |
849 | payload += list(parse(text)) |
850 | identifier = tag.identifier |
851 | return (payload, identifier) |
852 | def open(ruleset, knowledge, snapshots=[]): |
853 | nonlocal clf |
854 | if (variables := match(("@nfc", ["open"]), knowledge)) is not None: |
855 | try: |
856 | consume("@nfc", knowledge) |
857 | clf = nfc.ContactlessFrontend('usb') |
858 | return True |
859 | except: |
860 | produce(("@nfc", ["no-device"]), knowledge) |
861 | return True |
862 | return False |
863 | def close(ruleset, knowledge, snapshots=[]): |
864 | nonlocal clf |
865 | if (variables := match(("@nfc", ["close"]), knowledge)) is not None: |
866 | try: |
867 | consume("@nfc", knowledge) |
868 | clf.close() |
869 | return True |
870 | except: |
871 | produce(("@nfc", ["no-device"]), knowledge) |
872 | return True |
873 | return False |
874 | def read_card(ruleset, knowledge, snapshots=[]): |
875 | nonlocal last_card |
876 | if (variables := match(("@nfc", ["read-card"]), knowledge)) is not None: |
877 | try: |
878 | consume("@nfc", knowledge) |
879 | (payload, identifier) = nfc_read_card() |
880 | variables["x"] = "".join([hex(byte)[2:] for byte in identifier]) |
881 | last_card = payload |
882 | produce(("@nfc", ["card", "$x"]), knowledge, variables) |
883 | return True |
884 | except: |
885 | produce(("@nfc", ["read-failed"]), knowledge) |
886 | return True |
887 | return False |
888 | def load_card_rules(ruleset, knowledge, snapshots=[]): |
889 | nonlocal last_card |
890 | if (variables := match(("@nfc", ["load-rules"]), knowledge)) is not None: |
891 | try: |
892 | for rule in rules(reversed(last_card)): |
893 | ruleset.insert(0, rule) |
894 | consume("@nfc", knowledge) |
895 | return True |
896 | except: |
897 | pass |
898 | return False |
899 | def load_card_facts(ruleset, knowledge, snapshots=[]): |
900 | if (variables := match(("@nfc", ["load-facts"]), knowledge)) is not None: |
901 | try: |
902 | prepare(last_card, knowledge) |
903 | consume("@nfc", knowledge) |
904 | return True |
905 | except: |
906 | pass |
907 | return False |
908 | return [ |
909 | open, |
910 | close, |
911 | read_card, |
912 | load_card_rules, |
913 | load_card_facts |
914 | ] |
915 | |
916 | def repl(rulesets, primitives, debug): |
917 | try: |
918 | knowledge, _ = run(rulesets) |
919 | print_knowledge(knowledge, debug) |
920 | current_stack = "" |
921 | command = input("::> ") |
922 | while command != "@quit": |
923 | if command in {"@run", '!'}: |
924 | knowledge, _ = run(rulesets, primitives, knowledge) |
925 | if debug: |
926 | print_knowledge(knowledge, debug) |
927 | if match(("@signal", ["quit"]), knowledge) != None: |
928 | break |
929 | elif command.startswith('@'): |
930 | current_stack = command[1:] |
931 | elif command.startswith('.'): |
932 | command = command[1:] |
933 | knowledge, _ = run(list(parse(command)) + list(rules(rulesets)), primitives, knowledge, debug) |
934 | if debug: |
935 | print_knowledge(knowledge, debug) |
936 | if match(("@signal", ["quit"]), knowledge) != None: |
937 | break |
938 | elif command.startswith(':'): |
939 | command = command[1:] |
940 | rulesets = list(parse(command)) + rulesets |
941 | knowledge, _ = run(rulesets, primitives, knowledge, debug) |
942 | if debug: |
943 | print_knowledge(knowledge, debug) |
944 | if match(("@signal", ["quit"]), knowledge) != None: |
945 | break |
946 | elif len(command) != 0: |
947 | command = "||:" + current_stack + ':' + command |
948 | knowledge, _ = run(list(parse(command)) + list(rules(rulesets)), primitives, knowledge, debug) |
949 | if debug: |
950 | print_knowledge(knowledge, debug) |
951 | if match(("@signal", ["quit"]), knowledge) != None: |
952 | break |
953 | else: |
954 | if debug: |
955 | print_knowledge(knowledge, debug) |
956 | command = input(":" + current_stack + ":> ") |
957 | except EOFError: |
958 | pass |
959 | except KeyboardInterrupt: |
960 | pass |
961 | |
962 | def main(name, arguments): |
963 | primitives = _time() + [math] + arrays() + stdio() |
964 | if pygame_supported: |
965 | primitives += graphics() + midi() |
966 | if nfc_supported: |
967 | primitives += _nfc() |
968 | rulesets = [] |
969 | debug = 0 |
970 | prompt = False |
971 | trace = False |
972 | if not arguments: |
973 | usage(name) |
974 | return |
975 | for argument in arguments: |
976 | if argument == '-d': |
977 | debug += 1 |
978 | elif argument == '-r': |
979 | prompt = True |
980 | elif argument == '-t': |
981 | trace = True |
982 | else: |
983 | with open(argument) as file: |
984 | rulesets += list(parse(file.read())) |
985 | if prompt: |
986 | repl(rulesets, primitives, debug) |
987 | else: |
988 | if len(rulesets) == 0: |
989 | usage(name) |
990 | return |
991 | if debug: |
992 | knowledge, snapshots = run(rulesets, primitives, None, debug, trace) |
993 | if trace: |
994 | for index in range(len(snapshots)): |
995 | print("Snapshot", str(index) + ':') |
996 | print("----------------") |
997 | print_knowledge(snapshots[index], debug) |
998 | print("") |
999 | else: |
1000 | print_knowledge(knowledge, debug) |
1001 | else: |
1002 | run(rulesets, primitives, None, debug, trace) |
1003 | |
1004 | if __name__ == "__main__": |
1005 | main(sys.argv[0], sys.argv[1:]) |
1006 |