I think I've nearly fixed converting text to scratch blocks!
I'm working on a compiler that takes a folder structure of scripts and images and outputs an .sb file. You can decompile a project into its parts, edit the scripts in a text editor (and images in an image editor!), then recompile
Gratuitous screenshot:
(It's not very exciting, I'll admit — but editing the text file and then recompiling does actually update the scratch file!)
Offline
blob8108 wrote:
I think I've nearly fixed converting text to scratch blocks!
I'm working on a compiler that takes a folder structure of scripts and images and outputs an .sb file. You can decompile a project into its parts, edit the scripts in a text editor (and images in an image editor!), then recompile
Gratuitous screenshot:
http://i.imgur.com/18Pvc.png
(It's not very exciting, I'll admit — but editing the text file and then recompiling does actually update the scratch file!)
*gasp* That's amazing!
Hey blob, mind giving me a quick Python primer? I may have to hack a Mac next Monday with it at some competition. Don't ask why...
EDIT: A couple of links will be fine.
Last edited by Hardmath123 (2012-08-20 07:48:44)
Offline
Hardmath123 wrote:
*gasp* That's amazing!
Thank you
Hey blob, mind giving me a quick Python primer? I may have to hack a Mac next Monday with it at some competition. Don't ask why...
EDIT: A couple of links will be fine.
Sounds cool! I assume you mean hacking *on* the Mac, not cracking; not that it matters
The most obvious thing I can think of:
Last week I helped lead on a Scripture Union holiday called Livewires, where we do loads of techy stuff including teaching people Python, which I helped with. You can download the packages and worksheets we use and go through them. They're intended for people who've never programmed before, which is not you; but it still might be worth trying at least some of the beginner's stuff (sheets 1-5) to get the feel of Python.
At the other extreme — there's also a summary called Python for the impatient (also written by a guy who used to be on LW team) written for programmers, which looks nice, and may suit you better.
Hope either of those help — if not, I can try finding you something else
roijac wrote:
Wanna help integrate into M30W?
(or at least commit to github? )
I'll commit to github once I've tested the thing. It's still not quite perfect yet...
Offline
blob8108 wrote:
Hardmath123 wrote:
*gasp* That's amazing!
Thank you
Hey blob, mind giving me a quick Python primer? I may have to hack a Mac next Monday with it at some competition. Don't ask why...
EDIT: A couple of links will be fine.Sounds cool! I assume you mean hacking *on* the Mac, not cracking; not that it matters
The most obvious thing I can think of:
Last week I helped lead on a Scripture Union holiday called Livewires, where we do loads of techy stuff including teaching people Python, which I helped with. You can download the packages and worksheets we use and go through them. They're intended for people who've never programmed before, which is not you; but it still might be worth trying at least some of the beginner's stuff (sheets 1-5) to get the feel of Python.
At the other extreme — there's also a summary called Python for the impatient (also written by a guy who used to be on LW team) written for programmers, which looks nice, and may suit you better.
Hope either of those help — if not, I can try finding you something else
Thanks, I'm obviously an "impatient".
I'm actually, believe it or not, hacking a Mac emulator from Windows (I think, the competition organizers are very stingy about information). Which is terrible, because I grew up on my Mac ever since I could say "mouse". There are rumors of them making you use Ubuntu, though.
Last edited by Hardmath123 (2012-08-20 08:36:07)
Offline
blob8108 wrote:
I'm working on a compiler that takes a folder structure of scripts and images and outputs an .sb file
Great! I (and some other scratchers, I'm sure) are ready to test it
blob8108 wrote:
(It's not very exciting, I'll admit
What do you mean this is not exciting?!? This IS exciting!!!!
Offline
Hardmath123 wrote:
Thanks, I'm obviously an "impatient".
I thought you might be...
I'm actually, believe it or not, hacking a Mac emulator from Windows (I think, the competition organizers are very stingy about information).
That's... interesting. It sounds very difficult.
Just some points I wanted to add to that "Python for the impatient" thing:
He points out that the / operator does integer division by default: so 10 / 3 gives you 3. You can do "from __future__ import division" at the top of your program to fix this; then 10 / 3 gives 3.3333333333333335. Alternatively, just make one of the arguments a float: float(10) / 3.
Traditional C-style "for" loops become something like "for i in range(10):", but most of the time it's easier to iterate over the list/iterable directly, as he suggests. As he says, use xrange for very large ranges, as it returns a generator, not a list. (Generators are cool).
A little more on modules:
To make a Python module, so you can separate your code into separate files, just make a file called "mymodule.py" and then use "import mymodule" from a different .py file in the same folder.
You can alternatively make a folder called "mymodule" with a (can be empty) file called "__init__.py". "import mymodule" then imports "mymodule/__init__.py" as "mymodule" in the local namespace, the same as before. You can also put more .py files inside the folder as submodules, say "mymodule/cheesecake.py", and then access them as "mymodule.cheesecake".
The "string" module he mentions is outdated — there are .lower() , .upper(), .find(), .replace() methods on the str type itself, so you can do things like "fish".upper().
Also, dir() is really useful — it returns a list of the the attributes of an object, eg:
>>> my_list = [] >>> dir(my_list) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
help() on an object gives you similar (sometimes more useful!) output.
Offline
s_federici wrote:
blob8108 wrote:
I'm working on a compiler that takes a folder structure of scripts and images and outputs an .sb file
Great! I (and some other scratchers, I'm sure) are ready to test it
Awesome! I'll test it until it works for me, and then I'll let you know when it's ready
blob8108 wrote:
(It's not very exciting, I'll admit
What do you mean this is not exciting?!? This IS exciting!!!!
I was referring to the screenshot it occurred to me that I could easily have mocked up a text file and identical Scratch file and you'd never know...
Offline
blob8108 wrote:
Hardmath123 wrote:
Thanks, I'm obviously an "impatient".
I thought you might be...
I'm actually, believe it or not, hacking a Mac emulator from Windows (I think, the competition organizers are very stingy about information).
That's... interesting. It sounds very difficult.
Just some points I wanted to add to that "Python for the impatient" thing:
He points out that the / operator does integer division by default: so 10 / 3 gives you 3. You can do "from __future__ import division" at the top of your program to fix this; then 10 / 3 gives 3.3333333333333335. Alternatively, just make one of the arguments a float: float(10) / 3.
Traditional C-style "for" loops become something like "for i in range(10):", but most of the time it's easier to iterate over the list/iterable directly, as he suggests. As he says, use xrange for very large ranges, as it returns a generator, not a list. (Generators are cool).
A little more on modules:
To make a Python module, so you can separate your code into separate files, just make a file called "mymodule.py" and then use "import mymodule" from a different .py file in the same folder.
You can alternatively make a folder called "mymodule" with a (can be empty) file called "__init__.py". "import mymodule" then imports "mymodule/__init__.py" as "mymodule" in the local namespace, the same as before. You can also put more .py files inside the folder as submodules, say "mymodule/cheesecake.py", and then access them as "mymodule.cheesecake".
The "string" module he mentions is outdated — there are .lower() , .upper(), .find(), .replace() methods on the str type itself, so you can do things like "fish".upper().
Also, dir() is really useful — it returns a list of the the attributes of an object, eg:Code:
>>> my_list = [] >>> dir(my_list) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']help() on an object gives you similar (sometimes more useful!) output.
Thanks a ton! I'm gonna email myself a link here, it's so useful.
Then again, I'm not logging in to one of those computers; who knows what sort of rotten stuff the previous contestant rigged?
Offline
Hardmath123 wrote:
Then again, I'm not logging in to one of those computers; who knows what sort of rotten stuff the previous contestant rigged?
What do you mean by that?
Offline
blob8108 wrote:
Hardmath123 wrote:
Then again, I'm not logging in to one of those computers; who knows what sort of rotten stuff the previous contestant rigged?
What do you mean by that?
I plan to leave a little surprise of my own somewhere on the computer... I always do at these sorts of competitions.
Offline
s_federici wrote:
blob8108 wrote:
I'm working on a compiler that takes a folder structure of scripts and images and outputs an .sb file
Great! I (and some other scratchers, I'm sure) are ready to test it :)
That's actually really encouraging :)
I've been running some tests: decompiling projects to generate the scratchblocks code, parsing it back to scripts, and then comparing the parsed version with the original.
Here's what I've fixed yesterday/so far:
* trailing newlines at beginning or end
* differentiating variables and built-in reporters ("x position", "timer"... vs "myvariable")
* less than & greater than < >
* C-blocks require special keywords 'forever', 'if', 'else', 'repeat', 'until', 'end' to parse the structure properly
* 'until' is a keyword but is *also* used in normal blocks ("wait until...")
* 'X of Y' — differentiating 'computeFunction:of:' (eg "sqrt of 4") and 'getAttribute:of:' (eg "x position of Sprite1")
* I'd previously added comments starting with hashes # — bad idea (think "costume #"... :P)
* empty inserts () <>
Still to fix:
* obsolete blocks (the online detector I used in my roads game uses these, so they're important to me)
* 'getAttribute:of:' (the "[property] of [sprite]" block) stores a reference to the Sprite *Morph*, not its name. This is a slightly massive architectural problem, as at the moment I read the directories recursively — so I haven't created later Sprite objects when I'm reading a particular script. :/
* recover better from reaching EOF when expecting "end" — 'if <>' on its own is accepted by blocksplugin.js, so should be valid syntax.
You can take a sneak peek at the parser and the lexer to get an idea of how complicated the scratchblocks syntax is to parse...
Last edited by blob8108 (2012-08-21 06:52:24)
Offline
I made a test project by importing a hundred or so frames of my portal stop motion. I exported the frames from Final Cut Pro as an image sequence.
I copied a bunch of them (about 5-700ish) into a new folder, under "portal files/00 Stage/backgrounds". I resized them to 480x360 using Imagemagick: "mogrify -resize 480x360 *.jpg".
The stop motion's done at 12 fps, but the movie's rendered at 24 (it contains some video elements as well). So I used the following Python snippet to delete every other costume in the folder:
import os rm = True for f in sorted(os.listdir('.')): if rm: os.remove(f) rm = not rm
Then I just compiled the folder using Kurt, and I have my Scratch project! It took literally about a second. Compiling lots of JPEGs with Kurt is much faster than drag/dropping them into Scratch — I'm sure you've experienced how slow Scratch is at that. I've waited for whole minutes before...
Unfortunately, Kurt's much slower at importing PNG images, and doesn't compress them, so you get a bigger file. I might try optimising the image processing code, and I can certainly implement the compression algorithm Scratch uses.
A lot of other things are easier, too, like moving 150 costumes from the stage to a separate sprite: just decompile the project, move the images to the new folder, and then compile it again!
The parser is working okay, too. And the cycle of — edit the project as text/images, compile to Scratch, test, save, decompile again, repeat — seems quite nice. Some operations are easier to do in Scratch, for example tweaking things where you want instant feedback; and some operations, like moving around lots of images, and doing lots of copy/pasting of scripts, are easier with the decompiled file/folder structure version.
Hopefully this gives you an idea of what using Kurt is/would be like — what do you think?
Offline
blob8108 wrote:
I made a test project by importing a hundred or so frames of my portal stop motion. I exported the frames from Final Cut Pro as an image sequence.
I copied a bunch of them (about 5-700ish) into a new folder, under "portal files/00 Stage/backgrounds". I resized them to 480x360 using Imagemagick: "mogrify -resize 480x360 *.jpg".
The stop motion's done at 12 fps, but the movie's rendered at 24 (it contains some video elements as well). So I used the following Python snippet to delete every other costume in the folder:Code:
import os rm = True for f in sorted(os.listdir('.')): if rm: os.remove(f) rm = not rmThen I just compiled the folder using Kurt, and I have my Scratch project! It took literally about a second. Compiling lots of JPEGs with Kurt is much faster than drag/dropping them into Scratch — I'm sure you've experienced how slow Scratch is at that. I've waited for whole minutes before...
Unfortunately, Kurt's much slower at importing PNG images, and doesn't compress them, so you get a bigger file. I might try optimising the image processing code, and I can certainly implement the compression algorithm Scratch uses.
A lot of other things are easier, too, like moving 150 costumes from the stage to a separate sprite: just decompile the project, move the images to the new folder, and then compile it again!
The parser is working okay, too. And the cycle of — edit the project as text/images, compile to Scratch, test, save, decompile again, repeat — seems quite nice. Some operations are easier to do in Scratch, for example tweaking things where you want instant feedback; and some operations, like moving around lots of images, and doing lots of copy/pasting of scripts, are easier with the decompiled file/folder structure version.
Hopefully this gives you an idea of what using Kurt is/would be like — what do you think?
I'm thinking...
$ git commit -am "here you go" $ git push
Offline
MathWizz wrote:
I'm thinking...
Code:
$ git commit -am "here you go" $ git push
...
You'll find it under the scratchblocks branch (still highly experimental and very messy, of course); it's not on pip yet. Follow the instructions under "Option 3" to install. Enjoy!
WARNING: BACK UP YOUR PROJECTS FIRST, use at your own risk, etc.
---
Parser bugs:
* weird graphic effect [ v] bug
* make sure we integerify number inserts? eg [42]
* this:
if <(background #) = (54)>
wait (0.92) secs
else
if <(background #) = (73)>
wait (5.92) secs
else
end
end
* obsolete blocks
* 'getAttribute:of:' (the "[property] of [sprite]" block) stores a reference to the Sprite *Morph*, not its name. This is a slightly massive architectural problem, as at the moment I read the directories recursively — so I haven't created later Sprite objects when I'm reading a particular script.
* recover better from reaching EOF when expecting "end" — 'if <>' on its own is accepted by blocksplugin.js, so should be valid syntax.
* 'of' block when argument two is a reporter.
Compiler bugs:
* fix sprite list order
* doesn't select blank stage background
* remove image extensions from costume names
* add warning for variables named after blocks
* allow empty stage/sprite/images/scripts folders
* variables
* lists
Restrictions (won't fix):
* variable names:
* can't have special characters, rather obviously: like any of "[]()<>".
* can't be named after a block: you can't have a variable called "wait until", as I just discovered: screenshot
* definitely can't contain special identifiers (like "end", "if", etc.) — FIX
The same possibly applies to broadcasts, etc, not sure.
Last edited by blob8108 (2012-08-23 09:37:32)
Offline
It is finished.
I've reached my long-term goal: to be able to decompile my roads game to text/images, compile it again, and have it (mostly) working. Now I can edit projects as text!
There are a few tweaks and bugs left to fix, and general polishing to do, but it's mostly minor stuff. And I'm currently on holiday and don't really have internet -- so I'll hopefully push to Github sometime before next Tuesday evening; that is, a week and a bit -- which should give me time to fix them.
I'm rather excited...
Offline
Nice job! I've been playing with Python recently, as you know, and I can see how much effort you put into this.
Offline
Thanks, both of you!
Hardmath123 wrote:
I can see how much effort you put into this.
Yeah; I had fun, though And it gets easier. Especially with semi-automated testing. The hardest part is figuring out what it's supposed to do, as you can probably guess...
It does feel amazing when you get near to the end, though
Offline
I know... I wrote myself a rudimentary chat program in Python to warm up for tomorrow's competition. It's fun to code it, but just awesome to show it off to your parents.
Offline
blob8108 wrote:
I'll hopefully push to Github sometime before next Tuesday evening
What a long time to wait...
Offline
Hardmath123 wrote:
I know... I wrote myself a rudimentary chat program in Python to warm up for tomorrow's competition. It's fun to code it, but just awesome to show it off to your parents.
Heh I'm not entirely sure my parents understand Kurt -- despite the number of times I've mentioned it...
What kind of chat program? And have you tried Twisted yet?
Offline
blob8108 wrote:
Hardmath123 wrote:
I know... I wrote myself a rudimentary chat program in Python to warm up for tomorrow's competition. It's fun to code it, but just awesome to show it off to your parents.
Heh I'm not entirely sure my parents understand Kurt -- despite the number of times I've mentioned it...
What kind of chat program? And have you tried Twisted yet?
Err... an embarrassingly nonsecure socket-based chat.
Offline
I have no idea. I have been looking at ways to optimize my PNG code... Is PIL faster? If you could find out for me that'd be great
Offline