Planet Croquet
February 05, 2010
David Smith
Palm Pixi Rox
I just bought a new phone, and it wasn't an iPhone, but it is still very cool. I have been planning to buy an iPhone as my next communication device - all my friends have one. I am very glad that they no longer feel the urge to demonstrate how cool they are by showing me some stupid picture or new app on their iPhone - except for Frank, of course.
So why didn't I buy an iPhone? Well, it is a bit complicated. My family has five phones with Sprint. I actually had a Rumor, which is a pretty good texting phone, but not much use for anything else. I was reasonably happy with it, though the blue-tooth quality was pretty poor. It was not too useful in California - unless you are married to the governator. Sprint is pretty good for quality of reception, but I always thought the selections of their phones sucked. A few years ago, I decided I needed a Blackberry and tried to upgrade at Sprint. Believe it or not, they would not sell me one. They only sold them to businesses. Morons. I did buy a Blackberry from someone else and carried two phones. I dropped the Blackberry after a while, because I realized I could almost always check my email with my MacBook, even when I was traveling.
So why the new phone? Somehow, I must have either dropped or stepped on my Rumor. I had made two or three phone calls earlier in the day from my office. I put it in my pocket and went downstairs to talk to my wife and while I was talking to her I received another call. I took the phone out and pressed the answer button and then saw that it had a big crack in the center of the screen. Worse, the voice quality on the other end was totally garbled - like some sort of electronica convolution filter. It was basically toast. I needed my phone to work this week, as there are many things going on in my life (that I will be writing about soon) so whether I liked it or not, I had to go visit the Sprint store for a replacement.
When I got there I had a few nice surprises - first the selections of phones was not terrible. In fact it was getting interesting. No iPhone of course - this wasn't AT&T, but they had an Android phone and yes, they finally were offering Blackberries to real people, and a they had the new Palm WebOS-based phones. I was interested in the Google phone, but a friend of mine had just bought one and was trying to take some pictures in the bright sunlight. The screen was unusable. Also it was kind of big and bulky - sort of like what the old Soviet Union might build if they were trying to make an iPhone knock-off.
What really caught my eye was the Palm Pixi. It is the smaller and slightly cheaper brother to the Palm Pre (which had the very strange commercials last year). I like small phones, as I already carry too much hardware in my pockets. The Pixi was actually smaller than my old Rumor (which really wasn't that small) and it was a real smart phone. Better yet, Sprint was offering a hell of a data plan where my family's monthly costs, which did not include data, would actually drop with the new plan which did include it. The phone was $200 with a $100 rebate - including a new two year contract, but now, even that was pro-rated. Sprint is definitely getting aggressive.
So now the review of the Pixi. In a nutshell, it is terrific.
Here is a list of pros followed by cons:
Pros
- Setup was trivial. The guy at the Sprint store did most of the work and I had a working phone with all my contact info when I walked out.
- The phone perfectly integrates with Gmail, which is my main email connection these days. It pulled all of my contact info into the phone and I was immediately reading the most recent emails.
- It supports Google Calendar, which my wife and I share. And it issued calendar alerts. Very nice.
- It is quite small, but the built in thumb-keyboard is quite usable. It took a little getting used to, but it works fine and has a nicer feel than my Blackberry or my earlier RIM device. I do love the size - it is quite thin and feels very nice in my hands.
- Sprint's wireless network performance is great. I was at a Starbuck's with a friend of mine and wanted to show him a video I had posted to YouTube. He tried to access it with his iPhone, but I had it running on the Pixi well before he even had an connection. He never did get it to work, but he was using the AT&T network and not the local Wi-Fi.
- Web browsing works pretty good, given the size of the screen. Certain sites, like Boing Boing are excellent, because they have a mobile version automatically loaded. Amazon was a bit crappy, surprisingly.
Cons
- The text is too small, especially for us old guys.
- The sound volume is not quite loud enough, even with it maxed out.
- When I called my mother, she said the sound quality on her end was echo-y, like I was far away from the phone.
- I tried to read a PDF document using the included Adobe reader app, but it didn't word wrap, so this was basically a lost cause. Seriously - if I zoom into a document using PDF, you really need to provide an option to wrap the text so I don't have to scroll left and right.
- Camera quality is poor. Good enough for a random picture now and then, but it won't replace my Casio Exilim.
- Takes a long time to charge (maybe 4-5 hours?)
- Charge lasts about 3 days with use. Since it was a new phone, I probably did more with it than I normally will in the future, so this probably caused the battery to drain quickly.
- Some apps re-orient based on the orientation of the phone. Others don't.
- It really needs a search app that has instant access.
Overall, this is a great non-Android Google phone. It is really nice how cleanly and easily it interfaces with my Google life. And I love the size. It is really quite elegant. It has only been three days now, so let's see how it holds up over the next few months.
As an aside, I had a rental car last week - a Ford Flex. This included the Microsoft Sync software. I might comment more on this later, but short answer - it was terrible. I actually liked the car (more of an SUV actually), but this software was really opaque. After linking it to my now sadly demised phone via BlueTooth I could not figure out how to get to the phone interface to make a call. I nearly had an accident trying to figure this thing out. I never did figure out how to use the built-in GPS for directions. Luckily I had my Garmin Nuvi with me. Sync is Bad Bad Bad. If anyone from Ford is reading this - I did like the Flex, but will never buy anything with Sync installed.
by David A. Smith (noreply@blogger.com) at February 05, 2010 05:36 AM
February 03, 2010
Nikolay Suslov
Krestianstvo and CCSE in action [video]

For those who have not tried out the new Collaborative Curved Space Explorer in Krestianstvo SDK yet, here is the video which was recorded at Vologda State Technical University (Russia) during the "Virtual museum of geometry" opening event:
Данное видео с открытия "Интерактивного виртуального музея различных геометрий пространства" показывает работу многопользовательского исследователя искривленных пространств.
http://vimeo.com/nsuslovi
by Suslov Nikolay (noreply@blogger.com) at February 03, 2010 07:55 PM
January 29, 2010
Takashi Yamamiya
Recent Tamarin and ABC tools
Tamarin-central, the stable source tree of open source VM used by
Adobe Flash, was
updated last December (Dec 22 2009) after relatively long
blank. The newer tree has faster VM and includes updated ABC
assembler and disassembler. Especially those ABC utilities are quite
useful to a binary hacker of AVM2.
Download latest Flex SDK
I found that neither Flex SDK 3.5 nor 4.0 stable build can compile
abcdump. You need to download later version from the
Download
Flex site. Flex 4-Beta 2 (4.0.0.10485) works well. I would set the
Flex directory to environment variable FLEX.
$ export FLEX=~/Downloads/flex_sdk_4.0.0.10485_mpl
Download and build Tamarin-central
Building procedure is well documented in
Tamarin_Build_Documentation. Only
my additional suggestion is to add --enable-debugger, it makes error
messages easy to read, it helps you, really.
$ hg clone http://hg.mozilla.org/tamarin-central/
$ cd tamarin-central
$ mkdir objdir-release
$ cd objdir-release
$ python ../configure.py --enable-shell --enable-debugger
$ make
$ ./shell/avmshell -Dversion
shell 1.5 release-debugger build cyclone
features AVMSYSTEM_32BIT; ...
Build abcdump
There are various useful utilities in utils/ directory. Some utilizes
are written in ActionScript, so you need to compile them to
use. Abcdump, ABC disassembler, is one of such utilities.
$ cd ..
$ java -jar $FLEX/lib/asc.jar -import core/builtin.abc -import shell/shell_toplevel.abc utils/abcdump.as
core/builtin.abc and shell/shell_toplevel.abc are basic libraries
provided by tamarin, you can use them to try to see how abcdump
works. Note that you need to separate abc file names with --,
otherwise arguments are processed by avmshell instead of abcdump.
$ ./objdir-release/shell/avmshell ./utils/abcdump.abc -- core/builtin.abc
// magic 2e0010
// Cpool numbers size 158 0 %
...
I recommend you to make a tiny shell script to ease such a complicated command line.
#!/bin/sh
~/tmp/tamarin-central/objdir-release/shell/avmshell ~/tmp/tamarin-central/utils/abcdump.abc -- $@
How to use abcasm
Abcasm is a ABC assembler. It is written in java and shell script, so
you don't need to compile to try it. utils/abcasm/test/ directory
includes various interesting sample programs. You can test them easily
and quickly.
$ cd utils/abcasm/
$ ./abcasm.sh test/hello.abs
test/hello.abs
$ ../../objdir-release/shell/avmshell test/hello.abc
Hello, world
by Takashi (noreply@blogger.com) at January 29, 2010 09:58 PM
January 27, 2010
Bert Freudenberg
Interactive OLPC XO Display Simulation

Many people still have not seen the innovative display of the OLPC project's "XO" laptop. It has twice the resolution of a regular LCD (200 dpi), and works in bright daylight in gray-scale reflective mode. It's impossible for me to increase your screen's resolution by software, and I cannot make your display reflective, but here is an interactive simulation of the backlight mode with its interesting color pattern. This pattern is the source of a lot of confusion about the "color resolution" of the display. The LCD has 1200x900 square pixels, but the backlight puts a full color through each pixel. It is not made of red, green, and blue sub-pixels like a regular LCD, but the first pixel is full red, the second green, the third blue, and so on. The DCON chip (Display CONtroller) selects the color components from the full-color frame buffer.
My simulation of the DCON achieves the same effect by selecting either the red, green, or blue color component in each pixel. Just move the mouse pointer around to see how different colors are reproduced. You'll notice strong diagonal patterns, but remember, on the actual display the pixels are only half as large. Note that the actual DCON optionally applies a bit of anti-aliasing in hardware which is not simulated here. It helps reproducing fine structures and depicts colors more accurately. Additionally, the simulation shows a magnified image to better illustrate the principle, but it is not accurate because the reflective area of each pixel is not depicted. Maybe I can add this in a later version.
I made the simulation using Squeak / Etoys, which is one of the programming environments on the OLPC machine, but also works on Windows, Mac OS X, Linux, and many more systems. If you run the simulation on the actual laptop (download the project, place it in /home/olpc/.sugar/default/etoys/MyEtoys, run Etoys, choose Load Project), then you should close the small simulated screen and just leave the magnified view open.
For the interactive simulation, download Squeak (this version installs both, a regular application and a browser plugin), then click here to run the simulation in your browser, or download the project file, launch Squeak, and drop the project into it.
Intel-Mac users beware, the plugin is not supported directly yet. To see the project in Safari, you have to quit Safari, set it to open in Rosetta (select Safari in the finder, press Cmd-i), and reopen. Or, use the download method, Squeak itself is running fine on Intel Mac, it's just the browser plugin that's making problems.
by Bert (noreply@blogger.com) at January 27, 2010 03:37 PM
Etoys kid-tested on XO
I brought my green machine home this weekend, and my twins had fun with it. Enormous fun in fact for the two 7-year olds, pounding on TamTam furiously. I couldn't bear it anymore after half an hour or so.
Instead, I showed Jakob how to make a little figure bounce around on the screen in Etoys, while his sister went to practice her cello. He painted a simple head, and then we used the "forward by" and "bounce" tiles in a tiny two-line script making it move around. I made the mistake of pointing out that the "bounce" tile can produce some noise when bouncing. Endless fun trying the different noises ensued. Oh well.
Disturbed in her practice by these noises, Sophie came over and wanted to paint, too. So we saved Jakob's project and started a new one for her. I sat back to work on my email and let her brother teach. She spend like half an hour just painting the figure. The paint tool showed that it is not tuned to the XO's display resolution yet, it's far too small. But not giving up that easily, Sophie was erasing and repainting it over and over until she was satisfied with her "cow girl". Then Jakob proudly told her how to let it move and bounce, he had rembered almost everything needed. Together they quickly made it work, and just started exploring the noise-making possibilities again when we were saved by the call to dinner ...
by Bert (noreply@blogger.com) at January 27, 2010 03:37 PM
OLPC talk at design school
I gave a talk about the $100-laptop at the Magdeburg school of Industrial Design. We did some very inspiring projects using Squeak, Etoys, and Croquet together before. The designers always come up with interesting ideas, even though not everything is directly implementable by us developers.
Carola Zwick, dean of the school, wrote a book Designing for Small Screens that certainly gives valuable insight for OLPC developers, and she provided (though indirectly) some very important infrastructure for the OLPC office: her group designed the chairs they are sitting on. I got the actual invitation by Christine Strothotte, who got her PhD doing computer graphics in Smalltalk just a few years before I got mine from the same school. She's teaching interaction design nowadays. I'm looking forward to doing an OLPC-related project with these great folks.
A student took some photographs during the talk. Also, from his blog post it seems I convinced him of the merits of the OLPC project (it was a lively discussion). Thanks for posting, Cheng!
by Bert (noreply@blogger.com) at January 27, 2010 03:37 PM
Sophie, Tweak on the OLPC laptop
I just installed Sophie on my green machine. Sophie is a project of the Institute for the Future of the Book, is implemented in Squeak (just like my Etoys activity on the laptop) using Tweak as its UI framework (which is the original topic of my blog). Tweak is also the base for the next-gen Etoys.
Installation went pretty smooth. I downloaded the cross-platform zip file using the Web activity from Sugar
and unpacked it using the command line. The first start of Sophie failed, but after replacing the failing plugin with one from the pre-installed Squeak it started and worked. Yay!
This is an excellent example why it's a good idea to have a regular X11 installation on the kid's laptop: a lot of software will just work, even if it is not correctly integrated into the Sugar UI.
Michael Rüger of impara (a Squeak shop leading Sophie development here in Magdeburg, Germany) came over and made a little book, downloading two logos directly from the web (Sophie can do that!), adding a bit of text and color ... Tweak performance is not exactly blazing on the XO machine, I think we made the right decision to not use the Tweak-based Etoys but stick to the proven Morphic-based one. Of course one could optimize it a lot, but who has time for that? Anyway, it was useable - click the image to get a larger view:

by Bert (noreply@blogger.com) at January 27, 2010 03:37 PM
Squeak for every child

Lately I work on Squeak integration in the One Laptop Per Child (OLPC) project, perhaps better known as the "$100 laptop". The whole etoys group came over to OLPC's office in Cambridge. Squeak looks surprisingly well on the display prototype, and also etoys are reasonably fast. Ian Piumarta took some nice pictures, which might very well be the first photos of the actual display in the wild.
by Bert (noreply@blogger.com) at January 27, 2010 03:37 PM
January 25, 2010
Takashi Yamamiya
Wooden Half Adder Video
*UPDATED* New half adder video is released!
by Takashi (noreply@blogger.com) at January 25, 2010 01:19 AM
January 21, 2010
Howard Stearns
Corporatist Dawn
I remember how I felt when the media announced the fait accompli that W would be the next president. Twice. This is worse.
January 21, 2010 07:22 PM
January 05, 2010
Howard Stearns
Because You Can
Ever since Shelly's “Frankenstein”, the distinguishing characteristic of science fiction (as opposed to fantasy and other literature) has been the postulation that beings can change the circumstances of the world in which they live. We...
January 05, 2010 05:44 PM
January 04, 2010
Bert Freudenberg
Print-Quality Screenshots
For high-quality prints you need high-quality screenshots. This means very high resolution, and nice anti-aliasing. Just grabbing the screen produces rather unpleasant results (screenshot, 80 KB, 800x600 pixels). With normal OpenGL rendering you get rarely more than screen resolution, and anti-aliasing quality very much depends on your graphics board. So what to do?
Tiled Rendering comes to the rescue. Instead of rendering the whole image at once, we render smaller portions of the scene, and then arrange the tiles into a large picture. However, just pointing the camera at each tile will not work as intended, the perspective would change from tile to tile. What is needed instead is to construct partial viewing frustums that together exactly recreate the whole frustum. This sounds like a lot of math, but actually it is quite simple:
gluPerspective: fov aspect: aspect zNear: near zFar: far tile: rect
| cotangent radians w h |
radians := (fov/2.0) degreesToRadians.
cotangent := radians cos / radians sin.
h := near / cotangent.
w := h * aspect.
self glFrustum(rect left*w, rect right*w, rect bottom*h, rect top*h, near, far).
So I just extended the existing
gluPerspective:aspect:zNear:zFar: method with a
tile argument that gives the sub-rectangle in the viewing plane, where the whole picture ranges from -1 to 1. The only problem is to hand down that extra argument into the method. I ended up copying all the methods in the call chain, adding a
tile: parameter. With the methods in place and a utility method to construct the right sub-rectangles, I could render the image from the first screenshot again:
| m c f |
m := CroquetGlobals theTeapotMorph.
c := m activeCamera.
f := c root snapShot: m ogl camera: c tiled: 12.
f := f magnify: f boundingBox by: 0.5 smoothing: 4.
JPEGReadWriter2 putForm: f quality: 90 progressiveJPEG: false onFileNamed: 'croquet-bf-4800.jpg'.
Instead of 800x600, this renders 12x12 tiles, creating a 9600x7200 pixels image. The result is scaled down with smoothing to yield an anti-aliased 4800x3600 image, finally compressing as JPEG gives a 1.5 MB
hires screenshot.
Beauty, eh? Never noticed that guy on the bridge before ;-)
by Bert (noreply@blogger.com) at January 04, 2010 09:11 PM
How to write a Sugar activity in Squeak/Etoys
Milan just started a blog describing how to write activities in Squeak, see his
first post. There are already a few of these, most notably the
games by Robert Hirschfeld's students at the University of Potsdam, Germany. But so far the process is only documented in mailing list posts. Way to go, Milan!
by Bert (noreply@blogger.com) at January 04, 2010 12:36 PM
December 26, 2009
Nikolay Suslov
Collada file import in Kresetianstvo SDK
Thanks to Open Cobalt Collada file importer project, now this feature is available and in Krestianstvo SDK 1.0.1a.
So, that one could import the models in *.dae, *.kmz Collada format (for example from Google 3D Warehouse).
And then compose your space, while dragging/rotating the edit boxes with the models.

by Suslov Nikolay (noreply@blogger.com) at December 26, 2009 11:31 AM
December 25, 2009
Nikolay Suslov
Krestianstvo SDK v1.0.1a is updated to Seaside 3.0 and Magritte 2.0
The new updated Krestianstvo SDK 1.0.1a is available for download.
It includes all recent updates from the Krestianstvo SDK 1.0a version:
- Collaborative Curved Space Explorer with the new avatar logic
- Seaside 3.0 (up to 24 December 2009)
- Magritte 2.0 (up to 24 December 2009)
- Krestianstvo XUL 3D
- Sophie XUL 2D
- OMeta
- Lazy collections
- OSC protocol support
- Smalltalk programming on Russian
Also, I have updated the scripts for loading Seaside 3.0 and Magritte 2.0 to any Croquet based image.
Just file in them into the image:
1. Croquet-Seaside3.0-24.12.2009.st2. Croquet-Magritte2-24.12.2009.st------
Обновленная версия
Крестьянство SDK 1.0.1a доступна для
скачивания.
Включает в себя все обновления из Крестьянство SDK 1.0a:
- Многопользовательский исследователь искривленных пространств с новой логикой Виртуального Я
- Seaside 3.0 (24 Декабря 2009)
- Magritte 2.0 (24 Декабря 2009)
- Крестьянство XUL 3D
- Sophie XUL 2D
- OMeta
- Ленивые коллекции (Lazy collections)
- OSC протокол
- Smalltalk программирование на Русском языке
Так же я подготовил сценарии для загрузки Seaside 3.0 and Magritte 2.0 в любой (практически) образ Croquet.
1. Croquet-Seaside3.0-24.12.2009.st2. Croquet-Magritte2-24.12.2009.st
by Suslov Nikolay (noreply@blogger.com) at December 25, 2009 10:17 AM
December 17, 2009
Nikolay Suslov
Avatars collaboration in CCSE shared space
In the recent update, the Croquet TUserAvatarReplica logic for CCSpaceExplorer ship was presented.
It allows to see yourself ship and other user's ships, while flying in the same space at the same time.
On screen shot one's can see the two space-ships, they represents the two Croquet avatars, entered the Curved space. Physically, they are running on two different machines and controled by real users.
So, potentially there could be any number of participants, observing self rotations/translations/ actions in space as and others at the same time.

by Suslov Nikolay (noreply@blogger.com) at December 17, 2009 11:11 PM
December 14, 2009
Nikolay Suslov
Collaborative Curved Space Explorer v1.0 on Croquet
November 29, 2009
Takashi Yamamiya
A group exhibition "First Passage"
I'm going to Osaka in the chiristmas season to join the exhibition. This is a kind of "college reunion show" and all of artists were students of Prof. Hitoshi Nomura. I'm very excited to see old friends of the sculpture course. Now I'm quite busy to build a new version of wooden half adder. This is my first exhibition since 1999 anyway. Time is running so fast.
ARTCOURT Gallery Tenmabashi 1-8-5, Kita-ku, Osaka 530-0042 Japan
Hitoshi Nomura, Koji Nishimatsu, Kawai+Okamura, Osamu Kokufu, Tamaki Nagatani,
Takashi Yamamiya, Yui Ishiyama, Kohei Nawa, Yasutaka Yamada, Yoshihiko Maeda,
Ichiro Okada, Takao Machiba, Kenta Ogaya, Takayuki Okamoto, SHINCHIKA,
Yasuyoshi Uchiyama and Taro Okumura
- December 15 - 26, 2009
- Gallery Hours: 11:00 - 19:00 ( - 17:00 on Saturdays) Closed on Sundays
- Event : Artists Talk Show
- Saturday, Dec.19, 14:00 - 15:30 (*15:30 - 17:00 Reception)
by Takashi (noreply@blogger.com) at November 29, 2009 06:36 AM
November 07, 2009
David Smith
Virtus Walkthrough
I just posted the video I made of Virtus Walkthrough. I created this in 1990 with David Easter and Mark Uland. I am actually demonstrating Virtus 4 here. Scott Haynes was responsible for this version, and I think it is the best version of Walkthrough we ever did. It was also, unfortunately the last. The overall design and interaction is almost identical to the original 1990 version, though. This is using a software renderer that I wrote and was greatly enhanced by the team led by Greg Rivera. It uses portals extensively, and though you won't notice it, it does not actually have a z-buffer. The objects are sorted using a kind of BSP thing I did that is extremely fast. I am actually running this on Parallels on an older Macbook, and it feels faster to me than Sketchup 7.1, which I run native. But of course, considering that this had to run in real time on sub-20 mHz 68010 and 68020 machines, this had to be pretty damn fast to work at all.
This is the system I first prototyped the virtual collaboration space in that I showed to Alan Kay. This led to the development of ICE (see previous post), OpenSpace, the Croquet Project, and Teleplace.
Virtus Walkthrough won many awards, including the very first Breakthrough Product of the Year from MacUser Magazine, and the PC Computing Best Drawing Program, where we beat Adobe Photoshop.
Here is the demo:
by David A. Smith (noreply@blogger.com) at November 07, 2009 12:22 AM
November 06, 2009
Takashi Yamamiya
Wooden half adder

Since I encountered an essay by A. K. Dewdney over ten years ago,
somewhat I had been obsessed about mechanical implementation of
boolean logic. The essay introduced ideas of kinetic binary
calculator as an imaginary story of ancient civilization. This
fantastic tale attracted me, and my theme at the art college became
how to make a computer made from wood.
Last year, my boss gave me a Dewdney's book "The Tinkertoy
Computer and Other Machinations", which includes the essay, and my
enthusiasm came back. I made a couple of prototypes to realize
boolean logic without electronics. This is the latest attempt.
I chose a half adder as the motive because half adders are used
everywhere in a computer hardware, and it seems nice complexity for
the project. I thought this is the best example to show the idea
that computer's concept is independent with hardware. In other
words, I wanted to prove that computer is purely conceptual entity
and you can make it from any material besides electronics parts.
I first built a wooden AND operator. Can you tell how this toy
work? The top two holes show the input, and the center hole shows
the answer. Background board shows two kind of state T (True) and F
(False). Because of gravity, initial state is T AND T = T, once you
pull one of bars up, the center piece is also pulled up, and the
answer becomes F. This is how AND works.
Basically, any boolean logic can be possible with AND, and
another operator NOT (even OR can be constructed from AND and NOT).
Let's think about a half adder. A half adder is a primitive adder
and you can only add two bits. There are only four positions.
- 0 + 0 = 0 0
- 0 + 1 = 0 1
- 1 + 0 = 0 1
- 1 + 1 = 1 0
Let the inputs A and B, and the outputs S (sum, the low bit) and
C (carry, the high bit). A half adder can be shown two boolean
equations from AND(∧) and NOT(¬).
- C = A ∧ B
- S = A xor B = ¬(A ∧ B) ∧ ¬(¬ A ∧
¬B)
Finally, I constructed parts along with this formula. I used
gears as NOT operator.
 |
 |
 |
 |
| 1 + 1 = 1 0 |
1 + 0 = 0 1 |
0 + 1 = 0 1 |
0 + 0 = 0 0 |
by Takashi (noreply@blogger.com) at November 06, 2009 06:44 AM
November 05, 2009
Nikolay Suslov
Smalltalk Sophie XUL in 3D for Croquet / Krestianstvo space description - разметка пространства в 3D
In this post I want to show, how the Sophie's 1.x (the true project, based on Smalltalk and not Java's one) XUL 2D logic for describing Tweak interfaces, could be used for describing 3D content of the Croquet spaces naturally.
Now it is included in Krestianstvo SDK, as XUL 3D feature.
To try out and to extend for the concrete needs, check for the recent updates from the SDK.
1. So, one could describe the content in plain XML file/string, like:
КрестьянствоБиблиотека class>>примерXUL3DSpacexml
^'<?xml version="1.0"?>
<krestianstvo3D>
<space name="mySpace">
<imageWindow name="one" src ="checker.png" x="-10" y="0" z="-5"/>
<imageWindow name="two" src ="checker.png" x="10" y="0" z="-5"/>
</space>
<imageWindow name="three" src ="checker.png" x="-10" y="0" z="-5"/>
<space name="mySpaceA">
<imageWindow name="some" src ="checker.png" x="-10" y="0" z="-5"/>
<imageWindow name="other" src ="checker.png" x="10" y="0" z="-5"/>
</space>
<!-- ..etc... -->
</krestianstvo3D>'
2. Then this file is parsed into the real objects, node by node:
Крестьянство3DXulЗагрузчик>>readXmlFrom: xmlNode
|tframeClass tframe|
tframeClass := self croquetFrames at: xmlNode name ifAbsent:[nil].
tframeClass ifNotNil:[tframe := tframeClass new readXmlFrom: xmlNode in: self.].
^tframe
3. Every XML node is parsed according to the methods defined in
Крестьянство3DXulЗагрузчик class,
for example 'imageWindow' is parsed as TWindow instance:Крестьянство3DXulЗагрузчик>>readWindowFrame: aFrame from: xmlNode
| attr pic p attrX attrY attrZ matNorm |
(attr := xmlNode attributeAt: 'name') ifNotNil:[
nodeAttributes remove:'name'.
aFrame objectName: attr asSymbol.
].
(attr := xmlNode attributeAt: 'src') ifNotNil:[
nodeAttributes remove:'src'.
p := TRectangle new.
aFrame contents: p.
(attr asString) ifNotNil:[
pic := TTexture new.
pic initializeWithFileName: (attr asString)
mipmap: true
shrinkFit: false.
].
p texture: pic.
aFrame extent: pic extent.].
matNorm := TMaterial new.
matNorm ambientColor: #(0.8 0.8 0.8 0.8).
matNorm diffuseColor: #(0.8 0.8 0.8 0.8).
aFrame rectFront material: matNorm.
"...........ect......"
4. In TWindow class (or any other needed TFrame subclass) we add the method, which points to the method to parse the XML node with:
TWindow>>readFrame3DSpecificFrom: xmlNode in: uiLoader
super readFrame3DSpecificFrom: xmlNode in: uiLoader.
uiLoader readWindowFrame: self from: xmlNode
5. All, recognizable names of XML tags are defined in :
Крестьянство3DXulЗагрузчик class>>croquetFrames
^Dictionary newFrom:
{
#imageWindow ->TWindow.
#space ->TSpace.
#window -> TWindow.
#portal -> TPortal;
"any other stuff"
}
6. Finally, the created instances are serialized on to the shared island:
КрестьянствоОснова>>addTFToSpace: aFrame space: aSpace
| frameData tframe |
frameData := TIslandCopier new export: aFrame.
tframe := TIslandCopier new import: frameData to: self activeIsland.
tframe := aFrame copyOntoIsland: self activeIsland.
tframe future registerGlobal: aFrame objectName.
aSpace future addChild: tframe.
..and appeared in the World for collaborative interaction..

As a note: the Tweak menu bar on the top of the Participant window is described using the native Sophie's XUL 2D logic also.
by Suslov Nikolay (noreply@blogger.com) at November 05, 2009 09:43 AM
November 01, 2009
David Smith
Colony Walkthrough
Searching through my digital archives, I found the following walkthough for "The Colony". Not terribly useful anymore, but it will give you an idea of the depth of the game. This walkthrough was written 20 years ago...
"The Colony" Revealed
Copyright © 1989 by David A. Smith
GETTING STARTED
Where am I?
You are on the DAS cruiser on the bridge. You have just crash landed on the colony planet 5-DELTA-5.
Why is everything so dark and nothing seems to be working?
The ships reactor is out; you need to turn on the emergency power.
How do I use the console?
Run into it.
Why does the right button of the bridge console blow up the ship?
That is not its intention.
How do I turn on the emergency power?
Press the left button on the bridge console.
I can't open the airlock.
You must unlock it using the decoder and the console directly to the left of the airlock. Don't forget to press the "E" (Enter) key after entering the code. Unlocking it does not open it. You still need to press the +/- button on the airlock door.
When I go out the second airlock door I die.
Did you close the first door behind you first?
How do you close the inner door once inside the airlock?
Simply turn around and run into the airlock door again (the one you just came through) and press the +/- button.
Yes, I closed the inside airlock door. I still die.
Are you wearing your power spacesuit?
How do I put on my power spacesuit?
Use the power spacesuit installer.
What is that?
That is the strange looking device you see as you come down the stairs. Run into it and set your armor and weapons power levels.
I die when I go into the room on the lower level just to the left of the stairway.
Don't go in that room, it is a holding cell for prisoners (you are a Space Marshall remember?), you were standing on an electrified security grid on the floor.
What's wrong with the spaceship?
The reactor core has been damaged.
How do I fix the reactor?
You need to visit the colony first.
ON THE PLANET SURFACE
What are the pyramid shaped objects all over the planet surface?
These are "natural occurring rock formations".
How many 'bug' creatures are there?
There are an infinite number of creatures on the surface of the planet.
I keep getting killed when I fight them.
Then don't fight them.
They chase me.
You can run faster than they can.
Even if I don't fight the creatures I do not last very long on the planet surface.
See Power Spacesuit.
FINDING THE COLONY
Where is the colony?
It is outside of the ship.
It is underground.
The entrance looks like a large box with a door in it.
It is not far.
You can see both the colony and your spaceship when you are directly between them.
Go north-east from the space ship.
POWER SPACESUIT
I found the power spacesuit installer but I can't get it to work. Nothing happens when I run into it.
The emergency power needs to be on before the installer will work.
Why do I die so quickly, even when I use the heavy armor and weapons?
The power spacesuit drains your energy in proportion to the level you set it at. The heavier your setting the faster the drain. When all of your energy is gone you are dead.
What is the meaning of the power suit scale on the left of the screen?
This indicates the energy levels of you weapons, armor and life force. When the life force level reaches zero you are dead.
What kind of scale does it use?
It is logarithmic. For example, the lowest bar is equal to 1, then next up is 2 or more, then 4 or more, then 8,16,32,...
INSIDE THE COLONY
I found the colony but when I try to open the inside airlock door I died.
See GETTING STARTED.
Once inside the colony, just past the airlock, there is a door that is always blocked. What's on the other side?
You don't need to know yet.
I keep running out of energy, how can I raise my energy levels?
Eat the small "eggs" of the creatures. These are energy pods that will hatch later but when they are in the dormant state your power spacesuit can absorb the energy they contain.
What are these creatures inside the colony?
Search for the Conference Room on level 1. There you will find some interesting information on the different alien types and their capabilities.
EGGS
Where do the "eggs" come from?
From the creatures. They are actually dormant creatures that may "hatch" at any time. Note that most creatures can lay eggs but only of the same type. The queens can lay any type of egg.
What are they good for?
Your power spacesuit can actually absorb the energy they contain, at the same time destroying the creature that would normally be hatching from it. Note that different eggs help your power ratings in different ways, compare the eggs shapes to your power suit display.
REACTORS
How do I fix the reactor on the spaceship?
The reactor core is damaged, it needs to be replaced.
Where can I get a new reactor core?
Somewhere inside the colony.
How do I get to the reactor core?
You need to lower the core from the ceiling. Use the console in front of the reactor.
What are the codes I need to enter at the console to lower the reactor cores?
The code for the ship reactor is inside a desk on the ship.
The code for the colony reactor is inside a desk in the colony.
Where is the code for the colony reactor?
On level 1.
I tried to retrieve the colony reactor core and tote it to the ship. Succeeded admirably. But when I lowered it to the floor prior to switching it with the ship's reactor core, guess what? It disintegrated. Poof! No more colony reactor.
The only place that you can put the reactor core without breaking it is inside a reactor (either one).
Then how do I put the colony reactor core in the ship's reactor?
You need to have already taken out the ship's reactor core!
TELEPORTERS
Where are the teleporters?
On level 4 and in Lab A.
I can not get any of the teleporters to work, what do I need to do?
Keep looking for other teleporters.
I found the teleporters in Lab A but can't move them anywhere to make use of their capabilities.
You need a forklift.
What is the order of the teleporters in Lab A?
1 to 2, 2 to 3, 3 to 4, and 4 to nowhere!
How are the teleporters going to help me play the game?
If you manage to get them to strategic locations, you will be able to make many effortless trips (such as between your ship and the colony) with the various objects you need to successfully complete the game.
If I'm inside the forklift and try to enter a teleporter, the forklift thinks I want to lift the teleporter.
Try picking up something else (a box is usually handy) with the forklift before entering the teleporter.
If I'm in the forklift and want to pick up a transporter WITHOUT entering it...how is that done?
Teleporters and forklifts work this way:
1. You can enter a teleporter if you are not inside a forklift.
2. If you are in a forklift and you are carrying an object (such as a
box) you will also enter the teleporter.
3. If you are not carrying any objects with the forklift you
will pick up the teleporter with the forklift.
The reason for this is simply that the user interface was much simpler
to build and understand. The alternative was to have the user answer
a dialog about whether he/she wished to enter or lift the teleporter.
I did not want to have a dialog box anywhere in Colony (except for
saving games of course). This was to keep the game as natural as
possible. In this case the forklift is allowed to make the decision
for you.
Similarly, a number of things are the way they are to make the game players life easier. I would have preferred all doors to be opened AND closed by the game player but this gets tedious quickly. So the compromise is the airlock. A number of things are the way they are to make the game players life more miserable but that is the nature of these things.
FORKLIFT
Where is the forklift?
In the colony.
On level 5.
In storage room 5.
What is it good for?
It can carry large objects.
What large objects?
Teleporters, cryogenic chambers, boxes, and reactor cores.
I have trouble getting out of the forklift sometimes.
The forklift will not let you exit if there is an object directly
behind you (something about not allowing two objects to occupy the
same space at the same time). It will also not allow you to exit
into a wall. This may seem slightly random until you start considering
exactly what is around you. Remember this game takes place in 360
degrees. Just because you can't see an object does not mean that it is not there.
I have trouble dropping objects sometimes.
The forklift drops the object in the square you are in. Since only one object can occupy a square, you (and the forklift) get pushed back a square. However if there is something behind you ( wall, post, alien, etc), it appears to drop it but doesn't. You can tell because the forklift thinks it is still carrying the object (which it is) and the object is not sitting in front of you ready to be picked up again.
The forklift can not go upstairs.
That's right.
How do I get the forklift up the stairs to the colony airlock?
There is another way to the airlock that does not use stairs.
Can the forklift go outside?
Yes.
Does the forklift protect me from the creatures shooting?
Not at all, in fact you can not even shoot back while inside!
CRYOGENIC CHAMBERS
How many cryogenic chambers are there?
There are 6 of them.
Where are the cryogenic chambers?
Level 1 - 1
Level 2 - 0
Level 3 - 1
Level 4 - 2
Level 5 - 1
Level 6 - 1
Can you be a little more specific?
The first cryogenic chamber is in the security area on level 1. Be careful of the security grid as you make your way to it. It is in the upper part of the level 1 map.
The second chamber is on level 3. It is actually near the stairs located in the upper right hand corner but you need to go through apartment 33 to get to it. It is through the door behind the dining room table.
The next two chambers are on level 4. One is located inside of Lab 1 at the lower right of the map but you need to be pretty strong to get across all of the security grids that you will encounter on the way. Don't forget that you need to come back the same way. The next one is located in the maze found in the lower left. Just follow the map to be safe, you may make a wrong turn and wind up in the Dave Bowman memorial room.
The next chamber is found on level 5. It is in the very center of the maze in the lower left of the level 5 map. See STRANGE ROOMS AND MAZES for more information. You can get out of it if you do not go into the same room as the cryogenic chamber is in, however, then you can not rescue that child. Something to think about.
The last chamber is found on level 6. It is also in a maze (see the level 6 map) that starts behind a column after you have gone down one level of stairs from level 5.
STRANGE ROOMS AND MAZES
Is there a way out of the David Bowman suite?
Niy,ha,ha,...There is no way out of the David Bowman Suite. Yes, you have fallen into my trap! You will be in there FOREVER!!!!!
(or at least until you load the game you saved right before entering it.....)
I am lost in the Level 5 maze. I feel like I am going around and around in circles.
Yes, you probably are. You can sometimes use the pattern of eggs in each room to map out the maze. Or use boxes and the forklift.
I still can't figure out the Level 5 maze!
This maze is actually a 5X5 set of 3X3 rooms that folds in on itself.
I just got into the room with the cryogenic chamber in the maze on Level 5. I have the forklift to carry the cryogenic chamber but I can't get out of the room! There is no door!
You need to carry a teleporter in with you to teleport out again with the cryogenic chamber.
If you go east five squares from the east elevator on Level 5, you can look east across a vent grid into another area, but I never found an access point to that area. Am I missing something, or is there really no way to get there?
The vent grid area that you referred to is actually a joke. I thought that I would create this really interesting room that no one could ever get to thus creating a great mystery. Turned out that Peter Sills of Mindscape figured out a way to get into that room so I guess the joke is on me.
I can't seem to get into Lab 1 on Level 4...the security grids suck me dry before I can get anywhere.
You need to be pretty strong to get by this. Also try going very quickly through these corridors, the less time you spend on them the better.
On Level 4, just around the corner from the elevators is a door that leads to an infinite corridor that also contains a security grid. Does it lead anywhere?
No, it simply wraps on itself.
QUEENS
What happens when I kill a queen on a level?
Almost all of the creatures on that level revert to eggs. Munch, munch. Keep in mind that once you have done this and have already eaten all the eggs on this level you may wind up starving yourself to death.
I have located the Prime Queen at the reactor, but everytime I get through the security grid and attempt to attack - I'M DEAD.
Although she can be destroyed if you are strong enough, ask yourself, "is that really what I want to do with the next few hours of my life?".
END GAME
I have six frozen kids on my ship. I have a new reactor core. I killed the Prime Queen. What the heck do I do now? I am really lost. I can't get the ship to take off. I'm getting old. Help, please!
Go to the main console on the bridge of the space ship and press the bar on the far right. This will take you into orbit.
How do I blow up the colony without blowing up myself with it?
Use the planet smasher, remember the button on the bridge console that tends to self destruct? Remember it is the button on the right!
MISCELLANEOUS
The aliens get stronger the further you descend into the colony. This is due
to the proximity to both the Prime Queen and the central reactor. Also, the
eggs laid by the creatures get more potent as well.
Medium and Heavy Weapons use more energy than light! On the first couple of levels the energy you are picking up per egg is relatively weak and does not lend a lot of power to the weapons and armor you are carrying. However, as light weapons and armor use significantly less power, a little can go a long way.
It takes less energy to kill the aliens on the higher levels. You can "overkill" the aliens on level 1 for example if you were using heavy weapons. Sort of like using 10 sticks of TNT when one will do.
Don't duke it out with the aliens if you do not have to!!! We won't think you're a coward if you just run for it.
THE STORY OF THE COLONISTS
Many research scientists, military personnel and other professionals (along with their families) lived here. The purpose of the colony was to conduct teleportation research. The risks involved in this sort of pioneering work warranted the isolated location. It was classified just how much progress had been made, but it was known that a prototype teleportation system was in the works. The scientists closest to the project knew, however, just how far they had come. They had successfully transported objects and, yes, people with no adverse effects. It was actually possible to short-cut space and time!
But then unexplainable things started occuring. First it was noticed that rooms and walls in some parts of the colony were warping. Colonists would go out a door on one level and emerge on another. Corridors became labyrinthine. Rooms became exitless. And then strange creatures were sighted. There was speculation that these creatures had been either created by, or emerged from another dimension because of, the teleportation experiments.
It was also quickly realized that these creatures were dangerous. Every possible measure was taken. The experiments were stopped. Colonists tried desperately to fight back. They were largely unsuccessful, but discoveries were made about the nature of the creatures' existence: if they were shot at enough, instead of being killed they reverted to a pure energy form.
Eventually, the colonists realized that it was hopeless. They sent out a distress call, and used the few cryogenic chambers they had to keep the children out of danger. All they could do was pray that somehow, someone would come and discover the horrors that had happened, rescue their precious children and destroy the results of their hasty research.
THE WALKTHROUGH
TRUST ME... it's really an easy game... heh heh ...
Note that the following is to be used only as an example solution to "The Colony". There are many other ways to complete the game!
5-DELTA-5 REPORT
2/11/57
After crash landing on the planet where colony 5-DELTA-5 is located, I slowly regained consciousness. I realized that my reactor core was damaged. So was my memory. I did remember to press the left button on the bridge console (instead of the right, which would have been an instant disaster!). I went downstairs to the power spacesuit installer and, since my energy reserves were low, installed my suit at lowest levels for both weapons and armor.
"So far so good" I thought to myself as I used the security console to the left of the airlock to unlock the airlock control button. I entered the corresponding code from my decoder, pressed the "E" button (for "Enter") and went to the airlock, pressed the now unlocked +/- button and stepped through. I almost forgot to go back to the inside door to close it again, but once that was done I opened the outside airlock door and stepped out onto the planet.
BANG! Something shot at me! I looked around and saw a squat giant bug like creature coming straight at me. It was obvious that this was no friendly hello so I ran away from it as fast as I could go. Since I didn't know where the entrance to the colony was and since I didn't want to get lost, I kept the ship in sight as I circled it, trying to keep away from the creature and all of his friends at the same time.
I finally saw the entrance directly north-east of the ship and ran to it with the creatures close behind. If these things were indicative of what I was to find inside of the colony, I was in real trouble! I got to the colony and found, much to my relief, that the airlock door was open and that the airlock was the same model type as the one on the spaceship.
I went inside, closed the airlock behind me and turning around noticed a large pyramidal shaped creature eyeing me suspiciously. It didn't eye long for it immediately began an attack. Since I was not in any position to run now all I could do was shoot back. After about two or three shots the creature shuddered and actually began to shrink. I went up to it to study the remains a little closer and when I went too near my power spacesuit began to whir and the collapsed creature disappeared! I checked my power levels and noted that all of them had increased, which was useful because I was very near a terminal condition when I found the entrance to the colony. So these creatures, or at least their remains, were useful after all.
Entering the inside airlock door, I noticed a door on the other side of the room. I tried to go through it but there was something on the other side blocking the entrance. Turning around, I noticed the stairs and went down these instead. I looked around this area, saw a hallway leading from the stairs and, double doors leading to an auditorium. I went down the hallway and made a right turn. I found an office at the end of this corridor and inside it in the lower left drawer, found a reactor code of the same type I kept in my desk on the ship. "Great", I thought to myself, "They have the same kind of reactor as I use on my ship, all I have to do is borrow theirs to get things working again!".
I didn't have long to rejoice about my good fortune because another one of the creatures came up behind me and started blasting. This one was just like the previous except that he was kind of upside down. I dispatched with him, and this time decided to examine the little beastie. After a short time the collapsed creature began to shudder again and then it grew back to its full size. Knowing what to expect this time I shot it down to size again and this time stopped to let my suit suck up the remains.
I went out of the office back into the hall and saw yet another creature, looking away from me. This one was diamond shaped. As I watched it I saw it actually lay a miniature carbon copy of itself. "So the collapsed creatures are actually eggs!" I said to myself. Not waiting for an invitation from the creature I started blasting away at it. This time instead of shrinking away it just blew up! I guess that since it was standing on one of its eggs it had no where to go. I ran to the newly laid egg and feasted my suit on it. Things were definitely improving!
Further down the hall I saw a cafeteria on one side and a conference room on the other. Inside the conference room on the table I found a slide projector. Turning it on, I flipped through the slides while the voice over told me all about what I was up against. Looked like there was going to be a tough battle ahead.
I walked back out into the hall and needless to say I ran into even more of the creatures and their eggs. I avoided the creatures because I didn't feel like my suit was up to the fight but the eggs were delicious, thank you. After a little of this, my power spacesuit was beginning to look healthier. I just had to make sure that I ate as many eggs as I could.
I came to the elevators next. I decided to explore this level a little more and build up my strength before I went down there. In my exploration of level one I found a library, a storage area, and a security area. One thing I didn't find was people. Not even any bodies. That is until I came to the first cell in the security area. There inside was a cryogenic chamber. Not only that, but it was occupied. A couple of creatures were hanging around so I took care of them. The cryochamber had a note warning not to open it up so I had to figure out a way to get this thing back to the ship intact. Well, it would have to wait until later.
I went back to the elevators, and took one to level 2. As soon as I stepped off I ran into the biggest eyeball I had ever seen. I thought it might be one of the kid's balloons until it fired at me. I shot back. This one was a little tougher than the creatures on level one. In fact all of the creatures were a bit nastier. I could hardly wait till I got to the bottom level.
This was an apartment level. Nothing really useful that I could find. There weren't any cryochambers here. Just a lot of empty beds and a school. Very depressing. I did run into a queen. Very nasty thing. I nearly lost it all here. A number of other creatures were standing around, looking pretty disinterested in the battle. They are not very smart. When I did kill the queen, she didn't shrink like the others, she just blew up. When she was gone all of the other creatures seemed to lose the will to live also and they collapsed to their egg state. Needless to say, this did wonders for my ego and my power spacesuit.
The next level was another apartment level. Here I found another cryochamber in apartment 33. I could also tell that things were beginning to get weird. I went through a closet door and found myself on another level at one point. The creatures must have had something to do with it.
The next level was the lab area. Here I found a number of labs with partially working teleporters. They didn't look particularly safe so I stayed away from them. I did find another cryochamber in Lab 1, however. This was not easy to get to. There were a lot of security grids to cross. Another cryochamber was in a maze on this level. Well, I would have to come back for them later.
Inside of Lab 2, in the closet of all places, was a corridor that led to tunnel that brought me out to a hidden laboratory. Inside this lab there were four teleporters. These looked like they were ready to go, so I decided to try one out. I entered teleporter number 1 and after closing the door there was a tremendous burst. I opened the door and found myself coming out of teleporter 2. "This may prove to be useful", I said to myself, having expected to come out of teleporter one again.
I went back to level 4 and took the elevator down to level 5. This was the storage area. Inside of storage room 5 was a nice big forklift. This was going to be easy, I thought. Also, while I was on this level, a voice came to me (suspension of disbelief required here) that told me there was yet another child somewhere in a maze on this level and that it was inside a room that had doors into it, but no doors out. Well, since I always listen to voices, I stayed out of the maze, but I did keep the teleporters in mind for use later.
Since this was the lowest level that the elevator went to I took the stairs down to the next level. I found another cryochamber here, inside a maze that was hidden behind a column. I took the stairs down two more levels where I not only found the reactor, but I found a set of security grids protecting it and what looked to be the Prime Queen of the creatures. Not wanting to deal with her just yet I decided to first rescue all of the children.
The first thing I did was to go back to level five and retrieve the forklift out of storage room 5. I took this up the elevator and into Lab 2, down the secret hall into the tunnel and I picked up teleporter number 3. I took it back to where the elevators were, then up to level 1. I carried it to the stairs leading to the airlock and then came to the numbing realization that forklifts can't go up stairs. Well, that was a disappointment. But they must have gotten it into the colony in some way. Then I remembered the blocked door just as you enter the colony from the airlocks. What was on the other side? After a little more exploration I found that inside the storage area on this level was a number of boxes blocking a door. I put down the teleporter, picked up the boxes and moved them out of the way, and then picked the teleporter up again and went out. Lo and behold, I found myself in front of the airlock doors! I simply went through them, turned southwest, and carried the teleporter back to the ship.
Once inside the ship I was being really clever. I put the teleporter down inside of the reactor room and then tried to take the forklift into it instead of lifting it. This did not work. The forklift insisted on trying to carry it. I realized that since that was what it was programmed to do I had no choice but to carry something with me when I went through it. So I went to the ship store and picked up a box with the forklift and, since the forklift could not carry more than one object at a time it was forced to enter the teleporter. After closing the door, I was teleported back to teleporter number 4, just like before. I put down the box , picked up teleporter 2, and carried it back to the elevators on level 4.
Now I was ready to do some serious rescuing. I took the forklift up to security area in level one and picked up the first cryochamber. I carried it down to level 4 and into the teleporter and teleported to the ship. I carried it to the front empty room of the ship. One down and five to go. I picked up another box, and teleported back to the lab. This time I picked up teleporter 4 and carried it back, and placed it beside teleporter 2.
I then went to level 3 and apartment 33 and carried the cryo back down the elevator, through teleporter 2 back to the ship, got another box and was back in a flash. This was almost too easy. But then I realized I was running out of boxes on the ship.
The next cryochamber was in the maze on level 4 so I went in and, carefully avoiding the Dave Bowman memorial room, retrieved it (I'm really good at mazes). Teleporting back to the ship I placed it beside the other two. I was halfway done! I grabbed another box and noted that there was only one left after this. Back to the colony and into Lab 1.
By this time I was pretty strong, so the security plates in this area were not too much of a problem. I also went over them as fast as I could; they can hurt if you stick around. I had to pause every so often to dispatch a creature or two, nothing serious. I got to the lab, retrieved the cryochamber and went back the same way I came, much faster this time since there were no creatures blocking my path. I then teleported back to the ship with cryochamber number 4.
Alas, I was down to my last box. I picked it up and teleported back to the colony. Now I was going to have to think. The next cryochamber was somewhere in the maze on level 5, inside a room with no exit doors. Luckily, I had another teleporter that I could waste on this project so I went back through Lab 2 to the tunnel and the hidden lab and picked up the last teleporter. I carried it back up, then down the elevator to level 5 and into the maze. I quickly found the room with the cryochamber in it, put down the teleporter, picked up the chamber and stepped into teleporter 1 inside the room and was transported to teleporter 2 near the elevators. Then I turned around, got back into teleporter 2 and found myself back on the ship.
Well, there were five of the cryogenic chambers sitting next to each other. Only one left. Unfortunately, I had to walk back to the colony because I didn't have any boxes left. It was a short trip.
Emerging from the airlock, I wasn't paying attention and walked down the stairs while I was inside the forklift. When I woke up, I was down at the bottom of the stairs. I could tell that getting cryochamber number 6 was not going to be fun.
I took the elevator down to level 4, picked up teleporter number 2 and went down the elevator again to level 5. There I took the stairs down to level 6 (yet another fall, nothing damaged though) and went into the maze to recover the sixth and last cryogenic chamber. Once this was done and I had placed it next to the other five on the ship I realized that I had no boxes left to carry into the teleporter and that the outside airlock door was open. I was stuck!
I then remembered that I had to replace the ship's reactor core. I got out of the forklift, went upstairs to my desk and read the code inside the drawer. I went back down to the reactor console and entered the code, being very careful because the wrong code would blow it up. The reactor core dropped down from the ceiling and I got back into the forklift and picked it up and then got back into the teleporter. I found myself back on level 4. I took the elevator back down to where I had left teleporter 2 and put down the spent reactor core. Since these cores are very fragile, when I dropped it, it smashed into a million pieces. No great loss however. I picked up the teleporter and carried it back to the stairs down to level 7 and then to level 8. I then ran across the security grid, dropped the teleporter, jumped out of the forklift and ran smack into the Prime Queen. Boy, was she mad. I didn't feel up to arguing with her so I ran around to the other side of the teleporter. She lost interest in chasing after me. All I had to do was enter the reactor code I found in the desk back on level one. I entered the code, the reactor core dropped, I jumped back into the forklift and amid a flurry of shots from the Queen and her friend, I grabbed the reactor core, and got back into the teleporter. I noticed that the lights went out in the colony when the core was removed, but there wasn't anybody left to miss it.
I closed the teleporter door and the next thing I knew, I was back on the ship. I placed the new core into the reactor. Got out of the forklift, entered the reactor code to lift the core back inside and went upstairs.
All systems were "GO" when I got back to my console. I pulled up the accelerator and the next thing I saw was the planet shrinking under me as I went into orbit. I looked down at the innocent sphere which I was about to crush the life out of and said "No matter where you go, there you are." I smiled as I pressed the planet smasher button and sat back to watch one of the best fireworks displays this side of the galaxy. The only thing left to do was to collect my medals.
SPACE MARSHALL ACADEMY ENTRANCE EXAM
What happens when you set the date to 12/25?
How many queens are there inside the Colony?
Where do you go when you lift teleporter 3 with the lifter and enter teleporter 2?
What is the voice saying in the slide shows (Only on Macintosh version)? (Hint: .sdrawkcab s'tI)
What year does the adventure take place? Bonus: what is its significance?
Where are the chattering teeth?
What topological shape is the planet?
Assuming that at your slowest speed each step is a distance of 1 meter what is the radius of the planet?
Where do the doors in the room on the other side of the big pit on level 5 lead?
What happens when you hold down both the mouse button and the space bar when you are in the middle of a fight?
If you don't have the will or the energy to fight a creature, but it is blocking your path, how can you get by it?
How many movies can you name that influenced some aspect of the design of "The Colony"?
by David A. Smith (noreply@blogger.com) at November 01, 2009 08:33 PM
October 11, 2009
Howard Stearns
How to Think
During the post-9/11 dot com bubble-bursting, I worked at a dying company that had an “offsite” guided brainstorming session on how to save the business. I think it was on a disused floor of our rapidly emptying Tech Square office buil...
October 11, 2009 03:52 PM
October 10, 2009
Howard Stearns
Does this mean we can win the Nobel Prize?
Almost two years ago, I claimed that virtual worlds could help the physical environment, and it seems that there are now some measurable effects (if arguable as to how to attribute the causes).
Since then, techies of various stripes have been ...
October 10, 2009 09:19 PM
October 05, 2009
Takashi Yamamiya
An Assembler for AVM2 using S-Expression
These days, I have been writing a documentation about my latest AVM2
assembler. Because it took very long time, I tempted to copy it here
to make my blog seem substantial.
Overview
ABCSX is an assembler and disassembler for the ActionScript
Virtual Machine 2 (AVM2) [1] and the
ActionScript Byte Code (ABC). It runs on Cola/Amino language or
PLT-Scheme. The syntax consists of s-expressions and a program
can be constructed with normal list operations in Scheme like
language. The goal of this utility is to build a high level
language compiler for Adobe Flash Player. To get the idea, "Hello
World!" programs for both ABCSX and abcasm (a standard assembler
utility consisted in the AVM2 source tree [4]) are shown.
;;;; A "Hello World!" program in ABCSX ASM-form
(asm
(method
(((signature
((return_type *) (param_type ()) (name "hello")
(flags 0) (options ()) (param_names ())))
(code
((getlocal 0)
(pushscope)
(findpropstrict ((package "") "print"))
(pushstring "Hello, World!!")
(callproperty ((package "") "print") 1)
(returnvoid))))))
(script (((init (method 0)) (trait ())))))
// A "Hello world World!" program in abcasm
function hello():*
{
getlocal 0
pushscope
findpropstrict print
pushstring "Hello, World!!"
callproperty print (1)
returnvoid
}
Although a program written in abcasm syntax is more concise
than ABCSX, the semantics is rather ambiguous. For example, in
spite of each symbol name in ABC belongs to namespace(s), the
syntax of abcasm doesn't describe it clearly. In this case,
"print" is implicitly interpreted to a Multiple Namespace Name
with a namespace set including PackageNamespace with no name. In
case of ABCSX, it is explicitly represented as PackageNamespace
with no name by ((package "") "print"). This implicit
behavior might be useful for writing a program by hand, but not
necessary for a machine generated code. ABCSX rather takes a
direction toward verbose but unambiguous style.
ABCSX offers two forms of syntax. ASM-form is higher level
syntax introduced above. ABC-form is identical to an abstract
syntax tree of ABC binary file. This is useful when exact
behavior is need to know while debug.
;;;; A "Hello World!" program in ABCSX ABC-form
(abc
(minor_version 16)
(major_version 46)
(constant_pool
((integer ())
(uinteger ())
(double ())
(string ("hello" "" "print" "Hello, World!!"))
(namespace ((package (string 2))))
(ns_set ())
(multiname (((namespace 1) (string 3))))))
(method (((return_type (multiname 0)) (param_type ())
(name (string 1)) (flags 0) (options ()) (param_names ()))))
(metadata ())
(instance ())
(class ())
(script (((init (method 0)) (trait ()))))
(method_body
(((method 0) (max_stack 2) (local_count 1)
(init_scope_depth 0) (max_scope_depth 1)
(code
((getlocal 0)
(pushscope)
(findpropstrict (multiname 1))
(pushstring (string 4))
(callproperty (multiname 1) 1)
(returnvoid)))
(exception ())
(trait ())))))
Using ASM-form, a compiler writer doesn't have to care about
building a constant pool, or code hint information (AVM2 requires
a frame information like stack size and register size used in a
code).
Background
One of goals of the STEPS project [3] and
COLA programming language is to provide full control of computer
environment from application level to machine language level, so
that users could experiment and design their own programming
language best fit to their task. It also will be used as a basis
of next generation of EToys programming environment for kids.
We chose Adobe Flash Player as one of platforms of the system
because of its popularity and usability. Using Flash's virtual
machine on a web browser, we could deliver our programming
environment without concerning about installation or security
issue.
AVM2 has some disadvantages compared to Java VM. AVM2 lacks
multi task support, and its dynamic dispatching function is
relatively slow. But the startup speed and memory footage are
good, and these aspects are essential to casual users. Especially
AVM2 will be good platform to implement EToys.
ABCSX is designed to be a back end module for COLA, command
line assembler / disassembler, and a Scheme library. While it is
a part of COLA/ABC compiler, it also can be used as a command
line tool to examine and debug ABC binary file.
Usage
Command line tool
A version of ABCSX is publicly available on the github
repository [2]. It includes command line
tools run on PLT-Scheme. There are also example programs at
examples/ directory. The assembler and disassembler use
same file format and the assembler asm.ss can read an
output file generated by disassembler dump.ss.
- asm.ss filename.sx
- Generate an ABC binary file from ASM-form or ABC-form. The
output file name is filename.sx.abc.
- dump.ss [-abc] filename.abc
- Disassemble an ABC binary file. The output is printed to
stdout. If -abc option is specified, ABC-form is
chosen as output format.
- runasm.sh filename.sx
- Assemble ASM-form or ABC-form and execute it by avmshell.
It requires avmshell installed. Avmshell is included in Tamarin
VM's source tree [4].
- swf_abc.erl width height classname
abcfile.abc
- A helper program to generate a flash file from an abc file.
It requires Erlang.
Function
- (write-asm list
port) procedure
- Assemble ASM- or ABC-form to a binary stream.
- (read-asm port)
procedure
- Disassemble a binary stream to ASM-form.
- (from-asm list)
procedure
- Convert ASM-form to ABC-form. This is a part of process of
assemble. Each literal value is replaced to a reference, and a
constant pool is created
- (to-asm list)
procedure
- Convert ABC-form to ASM-form. This is a part of process of
disassemble. Each constant reference in the ABC-form is
replaced to a literal value based on the constant pool.
Data Type
ABC's data is expressed as scheme expression in ABCSX. In
ASM-form, data conversion has subtle context dependency in
code-subsection.
- integer - An integer value in Scheme is converted to ABC
integer value depend on the context.
- int (s32) - In code-subsection, an integer is converted
to a signed 32 bit integer if the opcode requires integer
e.g. pushint.
- uint (u32) - In code-subsection, an integer is
converted to a unsigned 32 bit integer if the opcode
requires integer e.g. pushuint.
- u30 - An integer is converted to a unsigned 30 bit
integer in ABC anywhere else.
- double (d64) - A floating point number value is converted
to a 64-bit double precision IEEE 754 value.
- string - A string is converted a string value in ABC.
- namespace - Some list expressions are converted to
namespace values in ABC. The format is (kind
string). For example, (package
"org.vpri") is converted to a package namespace named
"org.vpri".
- Namespace - (ns string) is converted to
Namespace
- PackageNamespace - (package string) is
converted to PackageNamespace
- PackageInternalNs - (internal string)
is converted to PackageInternalNs
- ProtectedNamespace - (protected string)
is converted to ProtectedNamespace
- ExplicitNamespace - (explicit string)
is converted to ExplicitNamespace
- StaticProtectedNs - (static string) is
converted to StaticProtectedNs
- PrivateNs - (private string) is
converted to PrivateNs
- namespace set - A namespace set can not be described as a
literal. Instead, it is declared in a constant pool of
ns_set-section at first, and be made reference by index e.g.
(ns_set 1).
- multiname - Some list expressions are converted to
multiname (symbol) in ABC.
- QName - (namespace string) is
converted as QName e.g. ((package
"flash.display") "Sprite"))
- RTQName - is not supported.
- RTQNameL - is not supported.
- Multiname - ((ns_set integer)
string) is converted as a Multiname e.g.
((ns_set 1) "addChild")
- MultinameL - is not supported.
Syntax
The syntax of ASM-form is explained. ABCSX uses
same symbol names as "ActionScript Virtual Machine 2 (AVM2)
Overview" unless it is too strange. Especially, underline
delimited names and capital names are derived from the document.
ASM-form
(asm [ns_set-section] method-section
[metadata-section] [instance-section]
[class-section] script-section)
ASM-form begins with a symbol asm, and contents are
followed. ns_set-section, instance-section, and class-section are
optional.
ns_set-section
(ns_set (ns_set namespace ...) ...)
Ns_set-section will be a part of constant pool, and it is only
necessary if namespace set is used in other part of the ASM-form.
You can not specify a namespace set directly as a literal, but
you need to define it in ns_set-section and point it with the
index number.
Ns_set-section begins with a symbol ns_set and a list
of ns_set_info is followed. A ns_set_info begins with a symbol
ns_set and it includes a list of namespaces. A namespace
set is referred with one-based index by other part. For example,
the first namespace set is referred as (ns_set 1).
method-section
(method (signature-subsection code-subsection)
...)
Method-section includes a list of pairs of signature and code.
A method is referred by zero-based index. For example, the first
method is referred as (method 0).
signature-subsection
(signature (return_type multiname) (param_type
(multiname ...)) (name string) (flags
integer) (options (option...)) (param_names
(multiname ...)))
Signature-subsection describes method's signature. If * is
specified at the return_type. It is treated as Any Type. A name
entry is not used as a method name in a program. In a typical
case, methods are explicitly bound to named slots in
initialization code at script-section or object constructor.
code-subsection
(code (instructions...))
Code subsection describes a sequence of instruction code of
the method. A label is specified as a symbol, and normal
instruction is specified as a list as:
([offset-number] inst-name args
...)
offset-number is optional and used just as a place holder. It
can be a integer or symbol _. ABCSX's disassembler put a
byte offset number at this place, but the assembler ignores
it.
metadata-section
(metadata (metadata_info ...))
Metadata-section describes a list of metadata entries.
instance-section
(instance (((name multiname) (super_name
multiname) (flags integer) (interface
(multiname ...)) (iinit method) (trait
(trait_info ...)) ...)))
Instance-section describes a list of class definitions. Class
members are defined by a list of trait_info.
class-section
(class (((cinit method) (trait
(trait_info...))) ...))
Class-section describes a list of static members of class
definition. The number of this list is same as instance-section,
and each entry of class-section corresponds to instance-section.
A definition consists of a class initializer and trait_info
definitions.
script-section
(script (((init method) (trait
(trait_info...))) ...))
Script-section defines a list of static functions. It is also
used as a program's startup code. Once the virtual machine reads
a program, the last entry of script-section is invoked. Each
entry consists of a method reference and a list of trait_info.
Trait_info is used as a function's environment.
trait_info
Trait_info defines a fixed property of an object, class, or
method. ABCSX only supports Trait_Slot and Trait_Class.
Trait_Slot
((kind slot) (name multiname) (slot_id
integer) (type_name multiname) (vindex
integer) (vkind integer) (metadata
(metadata_info...)))
Trait_Slot defines a named slot in the context.
Trait_Class
((kind class) (name multiname) (slot_id
integer) (classi class) (metadata
(metadata_info...)))
Trait_Class defines a named slot with a class in the
context.
metadata_info
((name string) (items (((key string) (value
string)) ...)))
Metadata_info defines an entry including arbitrary key/value
pairs.
Current Status
Currently, only major elements in AVM2 are implemented.
- All primitive data types are implemented.
- 75 instructions (about a half of the whole instruction set)
are implemented.
- Only QName (Qualified Name) and Multiname (Multiple
Namespace Name) are implemented.
- Optional parameters or parameter names are not
implemented.
- Trait_Method, Trait_Getter, Trait_Setter, Trait_Function,
or Trait_Const are not implemented.
- Exception is not implemented.
Example
As a complete example, A GUI version of "Hello World!" program
is shown with commentary. This file is available at
examples/textField.sx on the source tree.
(asm
(ns_set
((ns_set (package "") (package "flash.text"))))
An ASM-form begins with a symbol
asm, and a
ns_set-section follows if necessary. This example declare one
namespace set including package namespaces
"" and
"flash.text" as
(ns_set 1). Ns_set's index number
starts with 1 because this is a member of constant pool. Other kind
of index number (method, class) starts with 0.
(method
(((signature ((return_type *) (param_type ()) (name "")
(flags 0) (options ()) (param_names ())))
(code
((returnvoid))))
The first method is referred as (method 0). It is
used as a class initializer in the class-section, but nothing to
do in this case.
((signature ((return_type *) (param_type ()) (name "")
(flags 0) (options ()) (param_names ())))
(code
((getlocal_0)
(pushscope)
(getlocal_0)
(constructsuper 0)
(findpropstrict ((ns_set 1) "TextField"))
(constructprop ((package "flash.text") "TextField") 0)
(coerce ((package "flash.text") "TextField"))
(setlocal_1)
(getlocal_1)
(pushstring "Hello, World!")
(setproperty ((package "") "text"))
(findpropstrict ((package "") "addChild"))
(getlocal_1)
(callproperty ((package "") "addChild") 1)
(pop)
(returnvoid))))
The second method is later used in the instance-section as
class Hello's constructor. It builds an instance of
flash.text.TextField and set "Hello, World!" to the
property named text. Finally, the text field is added to
this (Hello) object.
((signature ((return_type *) (param_type ()) (name "")
(flags 0) (options ()) (param_names ())))
(code
((getlocal_0)
(pushscope)
(getscopeobject 0)
(findpropstrict ((package "") "Object"))
(getproperty ((package "") "Object"))
(pushscope)
(findpropstrict ((package "flash.display") "Sprite"))
(getproperty ((package "flash.display") "Sprite"))
(pushscope)
(findpropstrict ((package "flash.display") "Sprite"))
(getproperty ((package "flash.display") "Sprite"))
(newclass 0)
(popscope)
(popscope)
(initproperty ((package "") "Hello"))
(returnvoid))))))
The third method is used as the startup script. It creates an
environment and initialize a new class defined in
instance-section and class-section by newclass
instruction.
(instance
(((name ((package "") "Hello"))
(super_name ((package "flash.display") "Sprite"))
(flags 0)
(interface ())
(iinit (method 1))
(trait ()))))
(class (((cinit (method 0)) (trait ()))))
Instance-section and class section define classes. In this
case, A class named
Hello is defined as a subclass of
flash.display.Sprite. When a SWF file is created from ABC
file, a SymbolClass tag in the SWF creates association between a
class name defined here and the main timeline of the SWF. In
ABCSX tool set, script
swf_abc.erl's third argument does
this task.
(script
(((init (method 2))
(trait
(((kind class)
(name ((package "") "Hello"))
(slot_id 1)
(classi (class 0))
(metadata ()))))))))
Script-section defines the startup script and predefined named
slot.
References
by Takashi (noreply@blogger.com) at October 05, 2009 06:30 AM
October 02, 2009
Howard Stearns
летающий фаллоl...
In December, 2006, flying phalli disrupted a Second Life press conference at a CNET event reflectively dedicated to making money in SL.
Two months later, US Presidential candidate John Edwards had his SL headquarters vandalized in a roughly sim...
October 02, 2009 03:00 PM
October 01, 2009
Nikolay Suslov
self = я or programming / программирование in Krestianstvo

EN: Just want to show, how Russian language is already could be used to program in Smalltalk using Krestianstvo.
Here is a program for building L-systems and drawing them with Pen or any other Object later in Smalltalk (for example Croquet's TObjects in OpenGL).
You will see some fragments of source code in Russian - all are the executable Smalltalk code. The whole version is available here (also it is available in update stream). The changeset (*.cs) or source code (*.st) files, which could contain Unicode symbols (russian here), could be exported or imported into the Krestianstvo system without any trouble.
RU: Представляю вашему вниманию пример, показывающий как уже сейчас можно программировать в среде Крестьянство на Smalltalk используя Русский язык. Мы запрограммируем алгоритм пострения L - систем и их рисования с помощью Карандаша или других объектов в дальнейшем (например Croquet TObjects в OpenGL).
Ниже приведены фрагменты исполняемого кода, полная версия доступна для скачивания здесь (так же в потоке обновлений для системы). Файлы изменений (*.cs) или исходного кода (*.st), содерджащие символы Unicode (в данном случае - русские), могут экспортироваться или импортироваться в систему Крестьянство без ошибок.
Smalltalk in Russian/ Smalltalk'а по Русски
self = я
to: do: = по: делай:
at: = в:
at: put: = в: значение:
ifNotNil:[] = еслиНеПусто:[]
ifTrue:[] = еслиИстина:[]
or:[] = или:[]
L - система (code fragments)/
(фрагменты кода)
1. Объявление класса / Creating the class:
Объект подкласс: #ЛСистема
именаПеременныхЭкземпляраКласса: 'предложение наборПравил генерация'
именаПеременныхКласса: ''
глобальныеСловари: ''
категория: 'Математика-ЛСистемы'
3. Метод инициализаци / Initialization
ЛСистема>>определитьЛСистемуАксиома: аксиома наборПравил: набор
я предложение: аксиома.
я наборПравил: набор.
я генерация: 0.
2. Определение метода генерации / Defining the generation method:
ЛСистема>>генерировать
| текущийСимвол строкаЗамены заменаИзПравил следующаяГенерация |
следующаяГенерация := ''.
1 по: предложение размер делай:[:индекс|
текущийСимвол := (предложение в: индекс) какСтрока.
строкаЗамены := '',текущийСимвол.
заменаИзПравил := (я искатьИзНабораПравил: текущийСимвол).
заменаИзПравил еслиНеПусто:[ строкаЗамены := заменаИзПравил].
следующаяГенерация := следующаяГенерация, строкаЗамены.
].
предложение := следующаяГенерация.
генерация := генерация + 1.
4. Рисование / Painting:
ЛСистема>>нарисовать
| символ карандаш длинаЛинии уголПоворота |
карандаш := Карандаш новый.
длинаЛинии := 20.
уголПоворота := 60.
1 по: предложение размер делай:[:индекс|
символ := (предложение в: индекс) какСтрока.
((символ = 'F') или:[ (символ = 'G')]) еслиИстина:[
карандаш иди: длинаЛинии.
].
(символ = '+') еслиИстина:[
карандаш повернуть: уголПоворота.
].
(символ = '-') еслиИстина:[
карандаш повернуть: (-1) * уголПоворота.
].
].

5. Выполнение / Executing:
ЛСистема класс>>примерПостроенияЛСистемыСерпинский
| правила лСистема |
правила := Массив новый: 2.
правила в: 1 значение: ((ЛСистемаПравило новый) определитьПравило: 'F' строка: 'F--F--F--G').
правила в: 2 значение: ((ЛСистемаПравило новый) определитьПравило: 'G' строка: 'GG').
лСистема := (ЛСистема новый) определитьЛСистемуАксиома: 'F--F--F' наборПравил: правила.
"генерировать 5 раз"
1 по: 5 делай:[:i|
лСистема генерировать.
].
лСистема нарисовать.
by Suslov Nikolay (noreply@blogger.com) at October 01, 2009 08:46 PM
September 30, 2009
Howard Stearns
Where We've Been
The Teleplace release is a mature application for getting work done in realtime collaboration with others. This makes a good occasion to look at some direct progenitors. The first two are the 1994 Interactive Collaboration Environment prototype b...
September 30, 2009 04:52 PM
September 27, 2009
Howard Stearns
The Colony
Our company CTO, David Smith, has been the principle architect of Croquet since the beginning. Long before that, he wrote the first commercial 3D game for a personal computer. Here's some video (made with an actual video camera on old Mac) of how...
September 27, 2009 04:46 PM
September 23, 2009
Howard Stearns
The Treachery of Names
Would any other smell as sweet?
We changed the name of the company today. The geeks formerly known as Qwaq are now Teleplace.
I like it. Qwaq was a kind of goofy Google/Twitter/Yahoo sort of thing into which you could project whatever you wa...
September 23, 2009 04:23 AM
September 21, 2009
Howard Stearns
Under the Radar
This is five minutes of live demo and eight minutes of discussion at an Under the Radar conference last spring. It is a very info-dense presentation before specialized industry insiders. (There are lots of side references all around to Google ...
September 21, 2009 08:13 PM
September 20, 2009
Howard Stearns
Project Collaboration at Intel
Yesterday I posted an example of a Virtual Operations Center, which is turning out to be one of the classic enterprise use cases for virtual worlds today. Above is a tiny blurb representing another, more common case: Project Collaboration. Not...
September 20, 2009 08:12 PM
Operations Center +1
David Smith made this video a year ago, showing how you could have:
virtual world objects automatically populated by real world objects;
scripted behavior for those interactive objects that:
gives realtime display of real world data ass...
September 20, 2009 04:21 AM
September 16, 2009
Nikolay Suslov
Krestianstvo SDK - Smalltalk | Croquet | Seaside... programming on Russian
From now it will be entirely native spoken language based (Russian). This means that all String's objects and the sources of the methods, selectors, class names, etc. will be translated (as possible), moving forward SDK to fully functional modern programming environment accessible to people of all ages, without forcing them to learn English to program.

All new source code will be written on native spoken language (Russian), as possible also.
The SDK is updated through change set's
update stream and source code could be easily filed in/filed out containing unicode chars.

The current developed version of the Krestianstvo SDK could be downloaded
here (one-click image for Windows, Linux, Mac OS X).

Представляем вашему вниманию открытый проект
Крестьянство SDK.
Наконец-то, стало возможным программирование в SmallTalk, Croquet, Seaside на родном языке (Русском).
Мы еще только в начале пути, но тем неменее уже доступен для скачивания базовый образ для основных платформ (Windows, Linux, Mac OS X).
Крестьянство SDK построен на основе OpenCroquet SDK с предустановленными пакетами (некоторые из списка: Sophie XUL-CSS, Seaside, OMeta и Крестьянство).
Отныне она будет разрабатываться полностью на родном языке (русский).
Крестьянство обновляется путем потока изменений и исходный код может быть легко (загружаться в/ выгружаться из) образа приложения.
Текущий вариант Крестьянство SDK можно загрузить
здесь.
by Suslov Nikolay (noreply@blogger.com) at September 16, 2009 02:01 PM
September 03, 2009
Howard Stearns
Google My House
A little experiment. I'm trying — again — to sell my house(1). In looking to buy or rent a house now, I always google the address to see what I can find. So now my wife is blogging about her experiences in having it professionally sta...
September 03, 2009 04:50 PM
July 24, 2009
Nikolay Suslov
Live and collaborative coding in Croquet

Open Croquet and
Cobalt SDK are built on top of the
Squeak self-exploratory environment, where everything could be modified/inspected in real time. It means that the environment is just created for live coding and interactive programming in SmallTalk.
Everything is OK, when you use just one computer with only one running vm/image on it (default for Squeak programming model).
But, Croquet/Cobalt were built for creating replicated 3D environments, which are distributed over the network, and several vm's/images running at the same time define the Island.
And so, for saving the identity of replicas of the shared Island, nobody from the participants couldn't change anything in the code in the local images. They are allowed just modify parameters had been programed earlier, or update their images using changeSets, Monticello etc. or just copy/paste the whole image.
But, if we want to program on the Island in all replicas at the same time?
For example it is often needed, when you have already run several images defining Island, but need to modify something in code, without stopping everything.
Or for collaborative coding between several programmers at the same time, forming one image, but working on it's replicas, being at different places.
The feature is missed in the current Croquet SDK (may be
XPForums project for collaborative programming using Croquet will solve this, but it is closed yet).
So, as proof of "live coding" concept in Croquet we could do the following:
1. Create the new TObject or TFrame subclass, with instance method like:
TLiveCode>> compileMethod: aCodeString inClass: aClassName
Utilities authorInitialsPerSe isEmpty ifTrue:[ Utilities setAuthorInitials: 'sn'].
aClassName compile: aCodeString.
2. Add this object into the existed island (or register during initialization):
liveCodeFrame := self harness activeIsland future new: TLiveCode.
liveCodeFrame future registerGlobal: #liveCoding.
3. Then add instance method to the used harness class, like:
CroquetHarness>> makeMethodInFuture: aCodeString inClass: aClassName
| liveCodeFrame|
liveCodeFrame := self activeIsland future at: #liveCode.
liveCodeFrame whenResolved:[
liveCodeFrame futureDo: #compileMethod:inClass: at:0 args: {aCodeString. aClassName}
].
The calling of this method on any participant will leads to the equal modification of the source code in all connected Island replicas.
This proof of concept code for Croquet/Cobalt image can be downloaded
here.
Experimental Seaside based ClassBrowser with support for live coding in Croquet island directly from web-browser is
here (the
Croquet-Seaside 2.9 imge and above code is needed to run).
Next steps could be the development of corresponding tools using existed SystemBrowser or OmniBrowser for full support of live coding/collaborative programming in the shared Islands.
by Suslov Nikolay (noreply@blogger.com) at July 24, 2009 12:02 AM
July 20, 2009
Takashi Yamamiya
A simple boolean logic table generator in Javascript
http://languagegame.org/pub/booltable/booltable.html
Boolean logic is a basic knowledge for all programmers. The idea is
very simple and straightforward, yet still it often annoys you a
lot. One of the reasons might be that boolean logic is not continuous
behavior, and just a bit of changes makes completely different
result. This is why it is hard to grab whole character of a boolean
expression, I think.
This tiny program shows every possible state of a boolean expression
to make sure your logic is correct. I wrote this to help me reading a
textbook about logic, and to make programming nested condition
statements easy.
One nice thing is "permlink" function. You can bookmark your favorite
boolean expressions to play again. It works even in file URL as this
is written entirely in Javascript. So feel free to download to your
local disk.
Here are a couple of examples to link boolean tables:
by Takashi (noreply@blogger.com) at July 20, 2009 12:00 AM
July 13, 2009
Nikolay Suslov
Seaside 2.9 and Comet to control replicated Croquet islands.
I want to share some of my experiments in combination of Open Croquet and Seaside/Comet at image level.
The main aim is: to allow multi-user interactions with shared content on the Croquet island just from web browser in real time (from any place, device like smart-phone, low-end machine (sometimes without OpenGL) etc. so, that a connection to the network and http web based browser just needed.
Also, it could help to implement open source "Forum pages" like features , which are existed only in Qwaq forums 2.0 (access recent activity from your web browser etc.).
I have prepared the ready-to-go image for those, who want to explore the infinite possibilities :)
1.
CroquetSDK.v1.0.18 with new image.
2.
Just one image for using with manual downloaded any
Croquet SDK.
Also, I prepared the
Script for loading Seaside 2.9 alpha updated (13-07-09) into any fresh OpenCroquet image (1.0.18 users should
update from sources to the latest, or use this one
Croquet.1.0.25 )
For examples look at
SmotriniWorldControl class.

Here on the screen-shot there are two participants and two opened web browsers (Safari, Firefox).
Just only one participant run Seaside/Comet application.
Changing any of the RGB sliders (in one of browser window) causes the change of the active space color, and glad to Comet in all opened Web browsers slider's handles change their visual state automatically (without manual refreshing).
All callbacks from seaside to croquet island are future events, like from proper harness in Croquet, so they dose not destroy the replicated state.
-----
onSlide: (html jQuery ajax
callback: [ :value |
aColor = #red ifTrue:[self class valueRGB red: value asNumber.
aFrame future color: (Color r: self class valueRGB red g: aFrame color green b: aFrame color blue)].
-----
How to run:
1. Start WAListenerAdaptor (support Comet Seaside applications)
WAListenerAdaptor startOn: 8888. (different ports for several participants, if needed)
2. Open Croquet master (KAT Demo harness is used in this example, from default Croquet SDK).
KCroquetParticipant new openInWorld.When it asks about interactivity server, leave it blank, as (www.croquetcollaborative.org) could not work, so it will start locally.
3. Point your any web browser (Firefox, Safari preferable) to:
http://localhost:8888/seaside/croquet4. To test Comet functions (RGB Slider), just open another browser window and point it also to:
http://localhost:8888/seaside/croquet

To be continued..
by Suslov Nikolay (noreply@blogger.com) at July 13, 2009 12:57 PM
June 12, 2009
Takashi Yamamiya
Lazy list and Data flow in Squeak
Introduction
I have been working on lazy list these days. A lazy list is a
collection where each element is evaluated only when it's
necessary. Lazy lists are very useful to express mathematical infinite
sequence naturally like all natural numbers, entire prime numbers, or
so.
Lazy lists are also practical when you deal with a large sequence
of data. Imagine that you want to replace particular words in a large
text, and print out just the first 100 characters. Without lazy list,
you must either, 1) replace all words and take first 100 characters,
or 2) count character position carefully each time when a word is
replaced. 1) requires time, and 2) tend to lost modularity. With lazy
lists, you can write such program as simple as former way, but
performance is still reasonable.
Non-strict functional language like Haskell supports this feature
in everywhere, but I was also interested in implementations of lazy
lists in "normal" languages. Even though its long history, lazy lists
have not been widely used. Lazy lists are sometimes called as
"Stream", and indeed, Unix's pipe can be seen as a kind of lazy
list. But it lacks generality. I wondered if I can find some traps to
be solved when I implement it myself. Squeak is a powerful tool for
the purpose because it has flexible runtime debugging support. And I
believe most part of difficulty in the concept comes from difficulty
of its runtime behavior.
SICP
is a good tutorial and I found further discussions
in SRFI-40
and
SRFI-41. Ruby
has good implementation
similar to SRFI-41. And even Squeak has two implementations
(LazyList
and LazyCollections)!
And here is my story.
Natural numbers
You can download a demo image
from LazyList.zip
or current source code from
Collections-Lazy-tak.5.mcz.
This source only uses basic functions in my home brewed image, but
please let me know if it doesn't work in your Squeak image.
This is an expression to make natural numbers with LazyList.
list := LazyList nat.
I took advantage of Squeak tools, inspector and explore. If you
inspect the variable "list" (select "inspect it" in the context menu),
you will see internal structure of the list. And if you explore the
list (select "explore it"), you see public "interface" of the
list. I'll show you what I meant.

And when you open a list at the explorer (the right window), values of
public accessors
head and
tail are shown,
and also the inspector is updated. The first element 1 is made only
because someone send
head message. And you can get further numbers with
clicking
tail accessor. Note that while explorer triggers
the list, inspector is inert so that you can freely observe internal
behavior of the list.
You can do this by a program. Message head answers the
first element of a list, and tail answers following
list. This is same as CAR and CDR pair in lisp. Many other methods are
defined e.g. take: returns a LazyList including first n
elements, and contents convert LazyList to Array.
list head. "=> returns 1"
list tail. "=> returns LazyList .."
(list take: 10) contents. "=> #(1 2 3 4 5 6 7 8 9 10)"
And then, try next expression. You might know that select: is a
message where a selected collection specified by a block as a
condition is returned (this is "filter" in other language). But how
possibly all natural numbers can be used with select:? Unlike other
collection methods, it doesn't evaluate a condition block
immediately. Instead, this method returns a new list which will be
behave as a filter of natural numbers.
list select: [:e | e odd].
Define a new LazyList
Most useful way to construct a new lazy list would be using
followedBy: method. The receiver becomes head of new
list, and the argument becomes tail. You can use it with any receiver,
and the argument must be a LazyList or block that returns a
LazyList. LazyList nil is used to specify end of the list.
1 followedBy: (2 followedBy: (3 followedBy: LazyList nil))
"=> same as LazyList withAll: #(1 2 3)"
You can define natural numbers using
followedBy: like
this.
nat := 1 followedBy: [nat collect: [:e | e + 1]].
It seems very strange! But please be relax. The first element of the
list is obviously 1. How about the second?
collect: is
sometimes called as map function in other languages, and
nat
collect: [:e | e + 1] answers a LazyList with all element is
just larger by 1 than nat itself. Therefore the sequence is generated
by recursive fashion. How clever!
nat = 1, ...
nat collect: [:e | e + 1] = 2, ...
nat = 1 followedBy: nat collect: [:e | e + 1] = 1, 2, ...
nat collect: [:e | e + 1] = 2, 3, ...
nat = 1 followedBy: nat collect: [:e | e + 1] = 1, 2, 3, ...
nat collect: [:e | e + 1] = 2, 3, 4, ...
nat = 1 followedBy: nat collect: [:e | e + 1] = 1, 2, 3, 4, ...
Squeak Smalltalk has some great heritage from APL. Many arithmetic
functions are defined in collections. So does LazyList. There is a
much simple definition of natural number.
nat := 1 followedBy: [nat + 1].
It reminds me an ugly assignment expression with side effect.
x := x + 1.
This is ugly because it looks like an equation but it is
not. x is never equal to x + 1! Sometimes
it confuses a beginner programmer. Still, it is too useful to
ignore. We need some reasoning of such side effect to use safely. On
the other hand, nat := 1 followedBy: [nat + 1] is similar
enough to x := x + 1 yet, it is actually an
equation. This is a significant coincidence, isn't it?
Iteration, Data flow, Lazy list, and Polymorphic functions
One of the problems in x := x + 1 is that value of x
depends on the position in the source code. So you have to be careful
about order of each expression. Are there any better ways? You can
imagine more mathematical programming language to allow you to define
a function as a equation.
x1 = 1 --- some initial number
xn = xn - 1 + 1
In this equations, it is clear that right hand side of x is older
than left hand side of x. This is pure and easy to reason. But another
problem occurs. In practice, the program requires whole history of xs
because now a programmer can specify any old value like xn -
100.
So I would add a restriction. What if only addition is allowed in
subscript. In other words, what if only "future" value can be referred
but "past" so that we can forget our unnecessary past conveniently (it
is possible with nice GC).
x1 = 1 --- some initial number
xn + 1 = xn + 1
It makes the relationship between an iteration
x := x + 1
and a lazy list more clear. This iteration can be converted a lazy
list definition directly.
nat := 1 followedBy: [nat + 1].
~~~ ~~~~~~~~~
x1 = 1; xn + 1 = x + 1
I know this discussion is still rough. You can find better
discussion
from Lucid. However,
my theory is that data flow structures (mathematical iteration) can be
expressed by lazy lists and polymorphic methods without special
language.
Here is another example of definition of a lazy list in iterative
way to compute Fibonnaci numbers. next is a synonym
of tail.
fib := 1 followedBy: [1 followedBy: [fib + fib next]].
This corresponds next mathematical equations.
fib1 = 1
fib2 = 2
fibn + 2 = fibn + fibn + 1
Simulations
As a little bit more realistic example, I will show you a gravity
simulation using lazy lists. In this demo, a global variable Y shows
height of an object, the first position is 400, and it is increased by
Speed. The initial value of Speed is 0 and the value is decreased by 1
while the hight Y is positive. If Y is negative, Speed is negated
which means the object is bounced by the ground!
Y := 400 followedBy: [Y + Speed next].
Speed := 0 followedBy: [Y > 0 whenTrue: Speed - 1
whenFalse: Speed negated].

Morphic part of this demo used a special morph named ListPointer
that worked as an interface between LazyList and Morphs.
I began this library as a replacement of Stream and
OrderedCollection. But it turned out that combination of polymorphic
methods and LazyList has unexpected cute property as data flow. I'm
very happy about the fact! If you are interested in rather practical
aspect of lazy lists, please check out List >> show method in this
library. printString for LazyList is implemented this framework
itself.
I already noticed that there are a lot of rooms I could improve
it. The design was briefly along with SRFI-40, but I will include more
ideas in SRFI-41 and Ruby's lazylist. I have ignored them so far
simply because I am lazy!
by Takashi (noreply@blogger.com) at June 12, 2009 09:42 PM
May 26, 2009
Takashi Yamamiya
A complete example of generating a sound in Flash with SampleDataEvent
Flash version 10 has significant feature about audio, SampleDataEvent. Until
this version, there was no way to generate a sound wave easily. Some
people have tried to do that by rather magical way of how to make
actionscript 3 play generated pcm wave data in Flash 9, however,
now we have a straightforward API from Flash 10. I think this is a
great improvement for hobby programmers who are interested in computer
generated music. While it's shame from some perspective. Just this API
finally brings us a point where old BASIC and PLAY statement could
do a quarter centry ago!
You would find a lot of examples about SampleDataEvent, but some of
those are wrong or uncompleted, since I think this API have been
changed so often in beta version. And I wrote my version of simplest
example for exercise.
There are a couple of tricks you might trap.
- If you get an error message: "Flex error: type was not found or was
not a compile-time constant: SampleDataEvent", you have to specify the
Flash version to 10.0.0. Set -target-player option or Flex builder's
Project's Properties - ActionScript Compiler - HTML Wrapper
- Some documentation might use Event.SAMPLE_DATA, but this is not true.
Generated SWF file:
http://languagegame.org/pub/SineSound.swf
by Takashi (noreply@blogger.com) at May 26, 2009 09:01 PM
May 20, 2009
Julian Lombardi
Julian Lombardi's Blog Has Moved
I've moved my blog to another address and will no longer post here. Please go to julianlombardi.blogspot.com to see all my posts, both old and new.
-Julian
by Julian Lombardi (noreply@blogger.com) at May 20, 2009 02:27 AM
May 01, 2009
Takashi Yamamiya
A Prolog In Haskell
Prolog In Haskell
I have been obsessed by Prolog language recent weeks. While I first
learned Prolog long time ago, and actually I was attracted, I have
never used it fluently because it's too hard to get familiar without
any practical necessity. Although, there are a lot of interesting
literatures which require certain knowledge of logic programming in
computer science. So, I decided to do another approach; writing a
Prolog interpreter to learn Prolog.
I chose Haskell as the implementation language because of its
succinctness. I'm a beginner Haskell programmer, and I thought it was
also a good opportunity to learn Prolog and Haskell same time! The
starting point was a Prolog implementation in Hug98 distribution
http://darcs.haskell.org/hugs98/demos/prolog/. I
think this is a great Haskell program, but its too difficult to
me. Rewriting it as my level would be a good exercise.
Data structures
Here is my version of Prolog in Haskell. Entire program is about
200+ lines. There is no cut operator but it has a list notation so
that you can write [apple, orange | banana] stile literal. Let's take
a look at the first part.
module Prolog
(Term(..), Clause(..), w, s, cons,
parse, parse',
atom, variable, struct, list, nil, terms, arguments, term, clause, clauses, query,
display,
unify, unifyList, applyTerm, prove, rename, solveString) where
import Text.ParserCombinators.Parsec
import Data.Maybe
import Char
I used Parsec as a parser, and defined some data structures.
infix 6 :-
data Term = Var String Int | Struct String [Term] deriving (Show, Eq)
data Clause = Term :- [Term] deriving (Show, Eq)
data Command = Fact Clause | Query [Term] | ShowAll | Noop
type Rules = [Clause]
type Substitution = [(Term, Term)]
Term represents Prolog's term like "apple" or "father(abe,
homer)". It can be a variable, or a structure. A variable has an index
number which I used it later to distinct a same variable name in
different contexts. A simple term like "apple" is also represented as
a structure without elements like Struct "apple" [].
Clause is a Prolog rule like "mortal(X) :- man(X)". I stole a user
defined operator constructor ":-" from original Hugs' Prolog to write
a Haskell expression in Prolog like. So "mortal(X) :- man(X)" in
Haskell expression becomes Struct "mortal" [Var "X" 0] :-
[(Struct "man" [Var "X" 0])]. Well, it's not quite
nice. Although the parser will provide better notation later, I have
to use this expression when debugging the interpreter meanwhile. Its
cumbersome. So I made up tiny utility functions to make Prolog data
easier.
-- Utility constructors for debugging
w :: String -> Term
w s@(x:xs) | isUpper x = Var s 0
| otherwise = Struct s []
s :: String -> [Term] -> Term
s n xs = Struct n xs
cons s cdr = (Struct "cons" [w s, cdr])
Using this functions, now "mortal(X) :- man(X)" is written as
s"mortal" [w"X"] :- [s"man" [w"X"]] . It is much better, isn't
it?
Unification
By the way, I like the word unification. It sounds peace and
spiritual! Unification is one of two most peculiar concept in Prolog
(another one is the control structure by depth first
search). Unification is solving a logical equation. For example, the
answer of "[X, orange] = [apple, Y]" must be X = apple, and Y =
orange. It is almost same as variable binding in a normal programming
language, but tricky part is that a direction is symmetry, so X = Y
and Y = X is same meaning. How can it be possibly implemented?? Think
about the data structure of the answer at first.
---- Unification ----
type Substitution = [(Term, Term)]
true = []
I used a list of tuples of terms, or an associate list to
represent a substitution. For example, "X = apple, Y = orange" is
represented as [(X, apple), (Y, orange)] (in actual Haskell
code, [(w"X", w"apple"), (w"Y", w"orange")] ). A tuple
of left hand side is always a variable name, and right hand side is
any term, concrete value preferably. The goal of unification is making
associations with variable and term. To make this process easier,
"transitive" substitution is allowed. Think about an equation "X = Y,
Y = banana". It is represented like [(X, Y), (Y, banana)], which is
solved as X = banana, and Y = banana in apply function. Let's look at
the implementation.
-- apply [(w"X", w"Y"), (w"Y", w"Z")] [(w"X"), (w"Y")] == [(w"Z"), (w"Z")]
apply :: Substitution -> [Term] -> [Term]
apply s ts = [applyTerm s t | t <- ts]
applyTerm [] (Var y n) = Var y n
applyTerm ((Var x i, t):s) (Var y j) | x == y && i == j = applyTerm s t
| otherwise = applyTerm s (Var y j)
applyTerm s (Struct n ts) = Struct n (apply s ts)
The function apply substitutes a variable name of its value. To
support transitive apply, applyTerm is called recursively if the value
is also a variable. But it can solve only one way. Think about opposite
case "Y = banana, X = Y". Apply can't find the fact X = banana because
"Y = banana" is appeared before. So what I should do is applying X = Y
before adding the substitution.
| Equation | Substitution(solution) |
| 1 | Y = banana, X = Y | |
| 2 | X = Y | Y = banana (append) |
| 3 | X = banana (apply: Y = banana) | Y = banana |
| 4 | | Y = banana, X = banana (append) |
I suppose that this two fold way solve all of logical
equation. Apply is always needed before append it to the
solution. Actual source implementation seems to be complicated because
there are cases where a variable can appears any side, and sometimes
there is no solution. To represent no-answer case, a Maybe monad is
used. So there are variations such as;
- No Answer : Nothing
- Always true (like apple = apple) : Just true (true is a synonym of empty list [])
- Substitution found : Just [X = some answer...]
-- unify (w"X") (w"apple") == Just [(w"X", w"apple")]
unify :: Term -> Term -> Maybe Substitution
unify (Var x n) (Var y m) = Just [(Var x n, Var y m)]
unify (Var x n) y = Just [(Var x n, y)]
unify x (Var y m) = Just [(Var y m, x)]
unify (Struct a xs) (Struct b ys)
| a == b = unifyList xs ys
| otherwise = Nothing
unifyList :: [Term] -> [Term] -> Maybe Substitution
unifyList [] [] = Just true
unifyList [] _ = Nothing
unifyList _ [] = Nothing
unifyList (x:xs) (y:ys) = do s <- unify x y
s' <- unifyList (apply s xs) (apply s ys)
return (s ++ s')
Note that I just use append (++) to add a new substation in
unifyList. But if you design carefully, recursive apply is not
necessary. Using something like a map is a better idea.
Solver
As a programming language, Prolog is unique as it has no explicit
control structure. Instead, a Prolog program can be seen as a big
nested if then else statement. This find and branch functions are
implemented of this behavior. While unification is a technique of how
to solve a equation, solver deals with when each equation should be
solved. There are two most important concepts to understand control
structures in Prolog.
- Goals (AND relationship) : are terms which should be solved.
- Branches (OR relationship) : are options which might have a solution
A proof's fate is decided by branch function, branch function
returns a list of goals (with corresponding substitutions). If the
list is empty, this branch is failed. If the list includes empty goal,
it is actually succeed because empty goal means that it is unified
against a fact like "food(apple).". Well, is it complicated?
- If branch returns [] <--- this is failed
- If branch returns [ [some goals] [some goals] [(empty)] <--- this is succeed! ]
The goal of find function is traverse all of goals to find whether if
it is true or false.
---- Solver ----
prove :: Rules -> [Term] -> [Substitution]
prove rules goals = find rules 1 goals
-- Depth first search
-- find (parse' clauses "p(X):-q(X). q(a).") 1 [parse' term "p(X)"]
find :: Rules -> Int -> [Term] -> [Substitution]
find rules i [] = [true]
find rules i goals = do let rules' = rename rules i
(s, goals') <- branch rules' goals
solution <- find rules (i + 1) goals'
return (s ++ solution)
-- Find next branches. A branch is a pair of substitution and next goals.
-- branch (parse' clauses "n(z). n(s(X)):-n(X).") (parse' query "?-n(X).")
branch :: Rules -> [Term] -> [(Substitution, [Term])]
branch rules (goal:goals) = do head :- body <- rules
s <- maybeToList (unify goal head)
return (s, apply s (body ++ goals))
Find function has an argument for index number to show the depth
of the tree. This number is used to rename all variables used in whole
rules. This is necessary because same variable name in different
clauses are actually represented different variables.
-- Rename all variables in the rules to split namespaces.
rename :: Rules -> Int -> Rules
rename rules i = [ renameVar head :- renameVars body | head :- body <- rules]
where renameVar (Var s _) = Var s i
renameVar (Struct s ts) = Struct s (renameVars ts)
renameVars ts = [renameVar t | t <- ts]
I have only explained evaluator part of the REPL, but still there are
reader, printer, and loop. You can browse and download whole source
code
from
http://github.com/propella/prolog/tree.
Someday I might write some of interesting topics in the program...
by Takashi (noreply@blogger.com) at May 01, 2009 06:26 PM
April 05, 2009
Takashi Yamamiya
Learning Erlang and Adobe Flash format same time part 2
I have already written most important part about SWF format and
Erlang's bit syntax
at previous
post. But just for the record, I take a note of miscellaneous
knowledge to construct an interesting Flash shape. This entire note
doesn't have any practical value because there are already many other
useful libraries to build a swf file. But some of historical esoteric
magical peculiar internal might interests you.
In the previous example, I only made three control tags:
- End (Tag type = 0)
- ShowFrame (Tag type = 1)
- SetBackgroundColor (Tag type = 9)
Here, I introduce you two additional tags,
- DefineShape (Tag type = 2) defines a vector graphics, and
- PlaceObject2 (Tag type = 26) shows the graphics to an actual screen.
I designed new data structure to represent a SWF shape. While
spec/0 is almost same as previous program, I add sample_shape/0 to
define DefineShape.
% an example shape.
spec() ->
{{frame_size, 6000, 3000},
{frame_rate, 16},
{frame_count, 160},
[{set_background_color, {rgb, 240, 250, 250}},
sample_shape(),
{place_object2, 1},
{show_frame},
{end_tag}]}.
sample_shape() ->
{define_shape,
{shape_id, 1},
{bounds, {rectangle, 2000, 3000, 1000, 2000}},
{shapes, {{fills, [{solid_fill, {rgb, 50, 200, 50}}]},
{lines, [{line_style, 100, {rgb, 100, 255, 100}},
{line_style, 100, {rgb, 50, 150, 50}}]},
{shape_records,
[{style_change, [{move_to, 2000, 2000}]},
{style_change, [{line_style, 1},
{fill_style0, 1}]},
{straight_edge, 0, -1000},
{straight_edge, 1000, 0},
{style_change, [{line_style, 2},
{fill_style0, 1}]},
{straight_edge, 0, 1000},
{straight_edge, -1000, 0},
{end_shape}]
}}}}.
It looks complicated though, it is actually very
straightforward. A DefineShape has a shape ID (or character ID), its
bounding box, and actual shapes. "shape_id", "bounds", and "shapes"
tuples at sample_shape/0 denote these information. Shape ID is used
later for a reference by PlaceObject2.
A Shapes part consists of further sub elements, fills, lines and
shape records. Every style information are defined in advance, and
referenced with corresponding ID. In this case, one solid fill and two
line styles are defined. After styles are defined, shape records are
followed. A shape record is the most interesting and complicated
part. I'll draw a moss green rectangle in 1000 x 1000 twips (20 twips
= 1 pixel) with light and dark green borders in a pseudo 3-D
style.
This is an actual implementation of DefineShape and
PlaceObject2. I'm afraid it seems to be complicated, but it is just a
direct translation from the specification. Thanks to Erlang's pattern
matching syntax, It is easy to add a new tag by putting a new
pattern. But sometimes distinction between ; (semi colon is used
between patterns in a function) and . (dot is used after a function
definition) annoys me.
tag({define_shape,
{shape_id, ShapeId},
{bounds, Bounds},
{shapes, ShapesWithStyle}}) ->
BoundsBits = rectangle(Bounds),
Shapes = shape_with_style(ShapesWithStyle),
record_header_body(2, list_to_binary([<<ShapeId:16/unsigned-little>>, BoundsBits, Shapes]));
tag({place_object2, CharacterId}) ->
PlaceFlagHasClipActions = 0,
PlaceFlagHasClipDepth = 0,
PlaceFlagHasName = 0,
PlaceFlagHasRatio = 0,
PlaceFlagHasColorTransform = 0,
PlaceFlagHasMatrix = 0,
PlaceFlagHasCharacter = 1,
PlaceFlagMove = 0,
Depth = 1,
record_header_body(26, <<PlaceFlagHasClipActions:1,
PlaceFlagHasClipDepth:1,
PlaceFlagHasName:1,
PlaceFlagHasRatio:1,
PlaceFlagHasColorTransform:1,
PlaceFlagHasMatrix:1,
PlaceFlagHasCharacter:1,
PlaceFlagMove:1,
Depth:16/unsigned-little,
CharacterId:16/unsigned-little>>).
shape_with_style/1 is used to construct SHAPEWITHSTYLE structure
in the specification.
shape_with_style({{fills, Fills}, {lines, Lines}, {shape_records, Shapes}}) ->
FillBits = nbits_unsigned([length(Fills)]),
LineBits = nbits_unsigned([length(Lines)]),
ShapeRecords = shape_records({shape_records, Shapes}, FillBits, LineBits),
[fill_style_array({fills, Fills}),
line_style_array({lines, Lines}),
<<FillBits:4,
LineBits:4>>,
ShapeRecords].
The tricky part is FillBits and LineBits. As I have already
mentioned when explaining a rectangle format in previous post, the SWF
format tries to shorten a file size by all means, bit by bit. FillBits
defines maximum bit size needed by fill style id. For example, if you
use only one fill style, one is enough for FillBits. But if you use
seven, FillBits is three (because seven is 111 as a binary). After
FillBits and LineBits are calculated, they are needed in next helper
function shape_records/3. But before I show you shape_records/3, some
simple functions to construct styles are followed.
fill_style_array({fills, FillStyleArray}) ->
FillStyleCount = length(FillStyleArray),
[<<FillStyleCount:8>>, [fill_style(X) || X <- FillStyleArray]].
fill_style({solid_fill, RGB}) -> [<<16#00:8>>, rgb(RGB)].
line_style_array({lines, LineStyleArray}) ->
LineStyleCount = length(LineStyleArray),
[<<LineStyleCount:8>>, [line_style(X) || X <- LineStyleArray]].
line_style({line_style, Width, RGB}) ->
[<<Width:16/unsigned-little>>, rgb(RGB)].
I think these are straightforward. Perhaps, next is the most
tricky part of the SWF shape. Shape records include a number of
records, each record represents style change or position change or
so. While a rectangle format must to be byte aligned, each record must
not be aligned, but whole shape records including them must be
aligned! This fact is described in the specification very obscure way,
so I didn't find out what to do unless many try-and-errors. Although,
I might misunderstood what is a shape record...
Each individual shape record is byte-aligned within an array of shape records; one shape
record is padded to a byte boundary before the next shape record begins. --- SWF File Format Specification Version 10
To concatenate many bit strings into one, and align whole bits, I made
two functions padding/1 and concat_bits/1 (padding/1 is same one as
previous post). It is likely that concatenating bitstrings exists
already, but I couldn't find out from the library.
shape_records({shape_records, ShapeRecords}, FillBits, LineBits) ->
padding(concat_bit([shape_record(X, FillBits, LineBits) || X <- ShapeRecords])).
padding(Bits) ->
Padding = 8 - bit_size(Bits) rem 8,
<<Bits/bitstring, 0:Padding>>.
concat_bit(XS) -> lists:foldl(fun(X, Y) -> <<Y/bitstring, X/bitstring>> end, <<>>, XS).
Rest of the source is definitions of each record. I omitted a lot of
features to the explanation purpose. EndShapeRecord and
StraightEdgeRecord are quite simple.
shape_record({end_shape}, _, _) -> <<0:1, 0:5>>;
shape_record({straight_edge, DeltaX, DeltaY}, _, _) ->
NumBits = nbits_signed([DeltaX, DeltaY]),
GeneralLineFlag = 1,
<<1:1, 1:1, (NumBits - 2):4, GeneralLineFlag:1, DeltaX:NumBits, DeltaY:NumBits>>;
But StyleChangeRecord is the second tricky and daunting part in
spite of Erlang's succinct syntax. A part of reasons of the complexity
is that StyleChangeRecord allows to define a couple of operations at
once optionally; line style, fill style, and pen move. So we need some
data structure to represent such option.
In object oriented languages, a dictionary or a map is commonly
used while an associated list is popular in functional languages. In
Erlang, a list of tuples might be enough. lists:keysearch/3 find a
tuple in a list where first argument is matched, so we can use it as a
dictionary like structure. In our example, [{line_style, 1},
{fill_style0, 1}] means we want to change line style and fill style
same time. and lists:keysearch(line_style, 1, ChangeSpec) detects a
line style change option.
shape_record({style_change, ChangeSpec}, FillBits, LineBits) ->
TypeFlag = 0,
StateNewStyles = 0,
StateFillStyle1 = 0,
{StateLineStyle, LineStyleData} =
case lists:keysearch(line_style, 1, ChangeSpec) of
{value, {_, LineStyle}} -> {1, <<LineStyle:LineBits>>};
false -> {0, <<>>} end,
{StateFillStyle0, FillStyle0Data} =
case lists:keysearch(fill_style0, 1, ChangeSpec) of
{value, {_, FillStyle0}} -> {1, <<FillStyle0:FillBits>>};
false -> {0, <<>>} end,
{StateMoveTo, MoveData} =
case lists:keysearch(move_to, 1, ChangeSpec) of
{value, {_, MoveDeltaX, MoveDeltaY}} ->
MoveBits = nbits_signed([MoveDeltaX, MoveDeltaY]),
{1, <<MoveBits:5,
MoveDeltaX:MoveBits/signed,
MoveDeltaY:MoveBits/signed>>};
false -> {0, <<>>} end,
<<TypeFlag:1,
StateNewStyles:1,
StateLineStyle:1,
StateFillStyle1:1,
StateFillStyle0:1,
StateMoveTo:1,
MoveData/bitstring,
FillStyle0Data/bitstring,
LineStyleData/bitstring>>.
I uploaded final
program
http://languagegame.org/pub/swf.erl.
by Takashi (noreply@blogger.com) at April 05, 2009 07:02 AM
March 27, 2009
Takashi Yamamiya
Learning Erlang and Adobe Flash format same time
Since Luke Gorrie
encouraged me to learn Erlang, I have been playing with a bit with the
language. One of the most attracting points is
bit
syntax. When you want a byte array with 65, 66, 67. I can write it
as <<65,66,67>>. Further more, When you want a bit pattern of 4 in
four bits, 1 in four bits and 0x4243 in 16 bits, you may say <<4:4,
1:4, 16#4243:16>>. What a cool!
$ erl
Eshell V5.6.4 (abort with ^G)
1> <<65,66,67>>. % numbers are printed with ASCII
<<"ABC">>
2> <<4:4, 1:4, 16#4243:16>>.
<<"ABC">>
I was soon tempted to build a meaningful binary data with this
syntax. What does suit? Adobe Flash format would be the weirdest and
coolest. It's weirdest because of very bits oriented taste by perhaps
historical reasons. It's coolest because it's popular. I want to show
you how Erlang is powerful by writing complicated SWF format in the
sophisticated
syntax. Fortunately, the
SWF specification is now free and everybody can write a flash
editor by themselves.
First of all, I
chose scripting
style because I'm too lazy to wait for a compiler. And I start a
shell bang line.
#!/usr/bin/env escript
%% -*- erlang -*-
%%! debug verbose
I don't understand how it works, but I just copied from the
manual. And then, I have to decide what my first flash file looks
like. I'm modest enough to satisfy just a salmon colored window. This
is a spec file representing my flash.
% an example flash contents.
spec() ->
{{frame_size, 2000, 3000},
{frame_rate, 10},
{frame_count, 10},
[{set_background_color, {rgb, 250, 100, 100}},
{show_frame},
{end_tag}]}.
This is already reflected by the structure of a flash file. A flash
file starts with meta data of file size, frame rate, and frame
count. And a bunch of tagged data are followed. Tagged data is the key
of extensibility of the flash format. You can embed various kinds of
media as various type of tags in a file. In Erlang, fixed sized data
is represented as {tuples}, and variable sized data is [lists]. I
write each element as {key, arg1, arg2, ...} style, and tags are
represented as a list. You might understand each tuple's meaning. You
can change the color or size if you like.
Rest of the program reads this data and write a SWF file. I'll
explain the program in a top down fashion. The simple main function
opens a file and write something. Actual data is created by swf/0
(name/arity is Erlang's way to point to a function) as a sequence of
binary.
main(_) ->
Filename = "simple.swf",
{ok, S} = file:open(Filename, [binary, write]),
file:write(S, swf(spec())),
file:close(S).
Now interesting part begins. If you read Chapter 2: SWF Structure
Summary in the SWF specification, you may find that the Erlang program
is much more concise and easier to understand than long description in
the specification (although, I admit that I omitted some
details). Especially, a bit syntax part is obvious, "FWS" is three
byte characters, 'Version:8/unsigned-little' is a 8 bits integer for
version number, and 'FileLength:32/unsigned-little' follows as a 32
bits little endian unsigned integer for file length. 'Rest/binary'
looks tricky, but it means that another binary data Rest is embedded
here.
% SWF Structure
swf(Spec) ->
Version = 10,
Rest = swf_rest(Spec),
FileLength = size(Rest) + 8,
<<"FWS",
Version:8/unsigned-little,
FileLength:32/unsigned-little,
Rest/binary>>.
Because I needed to know the file size in advance, I had to split
the main part in two. Swf_rest/1 composes every elements in data, and
swf/1 mesures its file size and puts to the top. To pass my sample
data to swf_rest/1, I
use patterns. Thanks
to to tuples and patterns, I don't have to remember an order of
arguments. It looks
like keyword
arguments and more generic. Note that words begins with a lower
case like 'frame_size' are symbols and words begins with a capital
like 'Width' are variables in Erlang, in my case, 2000 is set to
Width. In SWF file, a special unit 'twips' is used, 20 twips are a
pixel.
A list
comprehensions is another useful feature. I only used it as a
shorthand of "map" function like [tag(X) || X <- Tags], which means
apply tag/1 function to each element in Tags, but it saved many
typing.
swf_rest({{frame_size, Width, Height},
{frame_rate, FrameRate},
{frame_count, FrameCount},
Tags}) ->
FrameSize = rectangle({rectangle, 0, Width, 0, Height}),
FrameRateData = fixed8dot8(FrameRate),
TagsData = list_to_binary([tag(X) || X <- Tags]),
<<FrameSize/binary,
FrameRateData/binary,
FrameCount:16/unsigned-little,
TagsData/binary>>.
Let's take a look at some detail of data type used in SWF. Color is
simple, it is just an array of three bytes for Red, Green, and Blue.
The description of 16-bit 8.8 fixed-point number in the specification
looks very complicated, but it just said that you have to put the
integer part last.
% Basic Data Types
rgb({rgb, R, G, B}) -> <<R:8, G:8, B:8>>.
fixed8dot8(N)->
IntegerPart = trunc(N),
SmallPart = trunc((N - IntegerPart) / 1 * 256),
<<SmallPart:8, IntegerPart:8>>.
This is my favorite part. Rectangles are stored as very
bit-oriented way. First, you must get a enough bit size to store each
element (Nbits). Second, four elements are stored in this bit
size. Third, entire bits should be byte-aligned. This kind of tasks
are very tricky in other languages, it require a lots of shifts, ands,
ors, etc. But Erlang's bit syntax helps me a lot.
I wrote two (actually three) helper functions to make rectangle/1
simpler. nbits_signed/1 calculate enough bit size for a list of signed
integers, and padding/1 fills zeros to align byte width. '/bitstring'
is same as '/binary', but you can use it for any odd size of bits data
while binary works only byte arrays.
rectangle({rectangle, Xmin, Xmax, Ymin, Ymax}) ->
Nbits = nbits_signed([Xmin, Xmax, Ymin, Ymax]),
padding(<< Nbits:5,
Xmin:Nbits/signed-big,
Xmax:Nbits/signed-big,
Ymin:Nbits/signed-big,
Ymax:Nbits/signed-big>>).
nbits_unsigned(XS) -> % Necessary bits size for a list of integer values.
Max = lists:max([abs(X) || X <- XS]),
trunc(math:log(Max) / math:log(2)) + 1.
nbits_signed(XS) -> nbits_unsigned(XS) + 1.
padding(Bits) ->
Padding = 8 - bit_size(Bits) rem 8,
<<Bits/bitstring, 0:Padding>>.
Tags are the most important data structure in SWF. There are short
and long tags. Short one is used for 62 bytes of data or less. Because
tag code and length is packed in one place, you can save precious 16
bits space with short tag! Tricky part is here. In short tag, type
code and length are stored respectively 10 bits and 6 bits, however,
you have to save it as whole 16 bits integer in a little endian.
Big endian
|Type |Length |
|9|8|7|6|5|4|3|2|1|0|5|4|3|2|1|0|
Little endian
|Typ|Length |Type |
|1|0|5|4|3|2|1|0|9|8|7|6|5|4|3|2|
What a crazy?! (actually, it is not so strange than it looks if you
see carefully. Hint: bits runs right to left, bytes runs left to
right). Even these funny endianess conversion is handled easily in
Erlang because bit syntax can be used in patterns (input).
% Tag Format
record_header_body(Type, Body) -> record_header_body(Type, Body, size(Body)).
record_header_body(Type, Body, Length) when Length < 63 ->
<<TagCodeAndLength:16/unsigned-big>> = <<Type:10, Length:6>>,
[<<TagCodeAndLength:16/unsigned-little>>, Body];
record_header_body(Type, Body, Length) ->
<<TagCodeAndLength:16/unsigned-big>> = <<Type:10, 63:6>>,
[<<TagCodeAndLength:16/unsigned-little>>,
<<Length:32/unsigned-little>>,
Body].
Finally, I'll show you the format of actual contents. Now I have only
three tags for End (type=0), ShowFrame(type=1), and
SetBackgroundColor(type=9). You might easily add new tags to support
more convincing flash contents. Latest tag number is 91 for
DefineFont4, see APPENDIX B Reverse index of tag values in the
specification.
% Control Tags
tag({end_tag}) -> record_header_body(0, <<>>);
tag({show_frame}) -> record_header_body(1, <<>>);
tag({set_background_color, RGB}) -> record_header_body(9, rgb(RGB)).
I uploaded an entire program
at
swf_simple.erl Erlang
is famous for its concurrent programming model, but I found another
aspects like bit syntax and pattern matching are also attractive and
useful to real application.
by Takashi (noreply@blogger.com) at March 27, 2009 08:41 PM
February 05, 2009
David Smith
On/off world
Brandon Boyer at Boing Boing Offworld was kind enough to post a link to the Colony videos I made. You can see it here:
A Look Back At the Colony
by David A. Smith (noreply@blogger.com) at February 05, 2009 08:16 PM
January 21, 2009
David Smith
The ICE Videos
ICE stands for Interactive Collaboration Environment. This is the real proto-Croquet architecture I built at Virtus. The ideas were strongly influenced by Apple's OpenDoc architecture and conversations with Alan Kay. There were two versions of this, one with some really neat recursive drag and drop capabilities. This system was collaborative from the start, including voice and video. The "avatars" were flying TVs with video images of the other users on them. The video was from some special cards that are long gone, so I could not show that in this demo. Once again, thanks to David Easter for providing the machine I used to record this demo. David also designed much of the component architecture that we built here. The second video is in some ways even more interesting than the first. We actually made the entire ICE system itself a component which meant that we could drag and drop ICE into a 3D window in the space. Early portals!
Enjoy it.
ICE Version 1
ICE Version 2
by David A. Smith (noreply@blogger.com) at January 21, 2009 03:27 AM
January 20, 2009
David Smith
The Colony Videos
I finally got around to posting the videos I made of The Colony. I had to borrow an old Macintosh from David Easter (who also did the ports to the PC and the Amiga) to make these, and I used a video camera to record them. This demonstrates the game, and I talk a bit about the technology behind it and why I designed the game play the way I did. Let me know what you think. I will also be posting some videos of Virtus ICE (Interactive Collaboration Environment). This was where the ideas for what became Croquet and then Qwaq Forums began.
The Colony videos are in two parts and you can see them here.
Part 1:
Part 2:
by David A. Smith (noreply@blogger.com) at January 20, 2009 03:51 AM
December 31, 2008
Bert Freudenberg
Peaceful Holidays ...

... and a Happy 2009 to everyone from me and my family.
Presented by my XO-hugging
USB men (who seem to have more memory capacity than me at times).
Featuring a seriously tree-infested Etoys project, with snow (for those living south who cannot enjoy the white fluff this time of the year).
And see you at
25C3 I hope!
by Bert (noreply@blogger.com) at December 31, 2008 06:52 PM
December 11, 2008
Julian Lombardi
Collaborative CAD in Cobalt!
Thanks again to the work of Aik-Siong Koh and his team, Cobalt now makes it possible for users to work in a deeply collaborative CAD environment. This video shows how two Cobalt users on separate computers can work with relatively sophisticated CAD capabilities over a LAN. This newly-implemented collaborative CAD capability in Cobalt opens up a wide range of possibilities for engineers and others at a distance to develop sophisticated simulations and architectures in Cobalt worlds. The ability to develop animated content within a full-featured virtual world CAD environment sets Cobalt apart from other virtual world technologies in a very significant way.
by Julian Lombardi (noreply@blogger.com) at December 11, 2008 11:53 AM
December 05, 2008
Bert Freudenberg
European grassroots meeting
I went to Brussels last weekend, meeting with folks from OLPC Europe, OLPC Boston, and some other European grassroots (me representing
OLPC Germany e.V.). We mostly discussed how to implement the new
Give-1-Get-1 program as well as
Give-many here in Europe. Some
notes are available.

And, while sitting together at a nice Cafe on Sunday I made this little Etoys project to celebrate OLPC Europe. Just click
here if you are on an
XO or have the
Squeakland plugin installed (as everyone should of course). For those who were there and took the huge file home on their USB drives - this is a fixed version that does not keep growing indefinitely while animating.
For the Etoyers out there - if you put a copy of a player in one of its own variables repeatedly, this creates an evergrowing "linked list" of player copies. Bad idea. Reset the variable first (by assigning dot for example) then do the copy: see my example.
by Bert (noreply@blogger.com) at December 05, 2008 10:13 PM
November 22, 2008
Julian Lombardi
VNC in Cobalt!

Rajeev Lochan has just been successful in getting VNC to work within a shared Cobalt space! VNC is a graphical desktop sharing system which uses the RFB protocol to remotely control another computer. This is a big breakthrough for our open project. It means that a Cobalt-based VNC client can connect to a VNC server on any other operating system. Cobalt users will soon be able to view and interact with remote applications (including full featured web browsers) or even collaboratively access remote desktops within the Cobalt application. Because the VNC protocol can use a lot of bandwidth, we still have some optimization to deal with - but this progress is great to see. Thank you Rajeev!
by Julian Lombardi (noreply@blogger.com) at November 22, 2008 01:19 PM
November 13, 2008
Matt Schmidt
Quick and Dirty Guide to Launching a Croquet World
OK, as promised, here is the first installment of how to get a simple world running in Croquet.
Learning outcomes:
Upon completion of this lesson, the learner will be able to successfully initiate the KCroquetParticipant subclass from within Squeak.
Step by Step Guide
Note: This guide was made under OSX. If you are running Croquet under Windows or Linux, your results may vary.
1. Launch the Croquet image

2. Click on the "Scratch" project. You will be presented with a new desktop. For simplicity's sake, close all windows on this project "page."

3. Open up a workspace. Advanced users may also want to open a class browser.
3.1. To open a workspace, left click on the Squeak desktop, select "open..."-->"workspace."
Alternately, Alternately, left click on the Squeak desktop, and select "objects." You are presented with a green "Objects" window. In the "Objects" window, select "Tools" (if you receive an error to the effect of "The map on disk is more than 10 days old. Update it from the Internet?" or something similar, go ahead and select "yes"). Left click and drag the "Workspace" button from the "Tools" section of the "Objects" window onto your Squeak desktop.

3.2. Advanced users: to open a package browser, left click on the Squeak desktop and select "open..."-->"class browser" from the menu.
Alternately, from the "Tools" section of the "Objects" window, left click and drag the button labeled "Browser" onto your Squeak desktop.

4. Copy the below text and paste it into your workspace window. Don't worry about the particulars of the following script. The goal of this lesson is just to get a simple world to load.
| w |
w := KCroquetParticipant new.
w position: 50@50.
w extent: World extent - w position.
^w openInWorld
5. Now it is time to initiate the world. First, select all of the text that you just copied into your workspace.

Now alt-click the selected text. You are presented with a contextual menu. Select "accept" from this menu.

Now alt-click the selected text again. You are again presented with a contextual menu. Select "do it" from this menu.

You should be presented with a dialogue stating "Enter interactivity server address, or leave blank to run your own locally." Delete the text in the dialogue's text box and select "Accept."

In a few moments, you should be presented with the below Croquet world.

6.
Advanced users: You may want to investigate the code for the world that you just initiated. To do this, return to the "System Browser" window. Alt-click in the left-most pane of the window. You are presented with a contextual menu. From this menu, select "find class."

Enter "KCroquetParticipant" into the search field and select "Accept."

You are presented with the subclass "KCroquetParticipant." Discussion of this subclass is beyond the scope of the current lesson. A deeper investigation of the underlying structure of the objects, classes, subclasses, instances, and methods of the Croquet system will be presented in a future lesson.
SummaryIn this lesson, the learner interfaced with the Squeak system in order to execute a script which is used to launch a simple Croquet world, based on the University of Wisconsin's "KCroquetParticipant" subclass.
by Matt Schmidt (noreply@blogger.com) at November 13, 2008 03:59 PM
Quick and Dirty Guide Part II: Squeak/Smalltalk Syntax
Introduction:
I'm no Smalltalk guru. Anyone who reads the Croquet-Dev list can assure you of this. But when you start small with Smalltalk/Squeak's syntax (no pun intended), it's not too difficult to grasp. So, without further ado, here is the second installment in my set of Croquet tutorials.
Learning outcomes:
Upon completion of this lesson, the learner will be able to identify basic elements of a Squeak script and will be able to make minor changes to provided code examples.
Note:
The following tutorial will use the below screenshot throughout. It is recommended to open this screenshot in another window or tab in your web browser in order to reference it during the tutorial.

You will notice that the above screenshot is annotated with numbers one through ten. Please refer to these numbers while working through the tutorial.
Tutorial:
The above screenshot provides you with two scripts. You will recognize the script in the workspace on the left from the previous lesson. The script on the right is new. We will use these two scripts to compare and contrast the various elements within them in order to gain a better understanding of what is going on with the syntax.
1. This is how you declare a variable in Squeak/Smalltalk (referred to as Squeak from now on). You can name your variable in a number of ways. Just make sure that you don't name your variable something that is reserved by the system (e.g., "win"). Note that the line ends with a period.
5. Notice that in the new script I have named my variable differently.
2. Here, I call the KCroquetParticipant subclass and assign it to the variable "w". You may find that it is easier for a beginner to read Squeak code from right to left. In this manner, you can interpret this code to mean, "Create a new instance of the KCroquetParticipant subclass and assign it to the variable 'w'."
7. Notice that in the new script I am calling a different subclass, CroquetMaster. The syntax is the same. Calling CroquetMaster will initialize a different world than KCroquetParticipant. But don't worry, we'll get to that at the end of the lesson.
3. Here, I assign a base position in the Squeak project space for where the world should launch. The number to the left of the "@" sign is the horizontal offset, in pixels. The number to the right of the "@" sign is the vertical offset. As you can see, when this script is executed, the world will launch 110 pixels below the top of the Squeak project space. Of particular note is the use of the "@" sign. You may be familiar with other programming languages that use "x" (e.g., 640x480). This is not the case with Squeak. Make a mental note of this.
8. Notice in the new script that I have changed things up a bit. When this script is executed, the world will launch 100 pixels from the left-hand side of the Squeak project space, and 100 pixels below the top.
4. Here, I assign a size for the Croquet world. This is a bit fancy, and is a nice way to show off some features of Squeak. The section "w extent: World extent" can be translated into plain English to mean, "make the size of the Croquet world just as big as the Squeak project space." So, if this line ended here, the Croquet world would take up the whole space available in the window. However, there is more to this line. The section "- w position" tells the Croquet world to subtract the position from line 3. In plain English, this code says, "make the size of the Croquet world as big as the Squeak project space, but subtract 110 pixels from the top."
9. Notice in the new script that things are a lot easier. Here, I have assigned a simple value of 640 by 480 pixels for the size of the Croquet world. You may want to start building your worlds using simple syntax like this and build up to the fancier stuff over time.
5. This last line ties everything together. You may be wondering, "What's that arrow, and where is it on my keyboard?" The up arrow is actually a caret symbol (^), which you can type in by selecting the shift key and pressing 6 on most U.S. mapped keyboards. It is displayed in Squeak as an up arrow symbol. The caret symbol is used to return a value. In this example, the variable "w" is returned and opened in the Squeak project space.
10. Notice in the new script that everything is exactly the same except for the variable name.
Now that you have spent some time investigating Squeak syntax, let's get another world running.
Step-by-Step Guide
1. Select all of the text in the workspace.

2. Alt+click and select "accept" from the contextual menu.

3. Alt+click again and select "do it" from the contextual menu.

4. You are presented with a world running the CroquetMaster subclass. Notice the offset of the world (100 pixels from the left and 100 pixels from the top), and notice the size of the world (640 pixels wide by 480 pixels high).

Summary:
In this lesson, the learner compared and contrasted two similar Squeak scripts and was introduced to some of the basic programmatic and syntactical elements of Squeak scripting. In addition, the learner launched a new world, based on the "CroquetMaster" subclass.
by Matt Schmidt (noreply@blogger.com) at November 13, 2008 03:59 PM
Quick and Dirty Guide Part III: Adding a script to a button
Introduction:
In the first two parts of this quick and dirty series, you learned how to write a script to run a Croquet world, and how to execute that script within the Squeak environment. But selecting your code, doing an "accept" and "do it" every time you want to start a world can become tedious. Wouldn't it be great if you could just click a button to start your world?
That is precisely what we are going to learn how to do in this tutorial.
Learning Outcomes:
Upon completion of this lesson, the learner will be able to assign a script to a button in Squeak and change the name of the button.
Step by Step Guide:
1. Launch Squeak and open a new project.

2. Open up an "Objects" window.

3. Select "Basic" from the "Objects" window.

4. Click and drag the "button" icon from the "Objects" window into your workspace.

5. Command-click (or right-click) the button you just dragged into the workspace. You are presented with a halo.

6. Select the green button towards the bottom-right of the halo. You are presented with a tile pane.


7. Click on the "world" section of the tile pane. You are presented with a contextual menu.

8. Select "show code textually" from the contextual menu. An editing space will appear.

9. Delete all text in the editing space except for the word "button".

10. Copy and paste the following code into the editing space below the word "button":
| myVariable |
myVariable := CroquetMaster new.
myVariable position: 100@100.
myVariable extent: 640@480.
^myVariable openInWorld.

11. Select all of the text
except for the word button, alt-click, and select "accept" from the contextual menu.

12. Select the "O" button (second from the left) at the top of the tile pane. This will close the tile pane.

13. Since the title on the button ("press me") is not very descriptive, let's change the title. Command click (right-click) the button. You are presented with a halo. Select the "Menu" button. You are presented with a contextual menu.

14. Select "change label" from the contextual menu. You are presented with a dialogue to add a new label to your button.

15. Provide a name for your button and select "Accept." I have chosen to name the button "My Croquet World."

16. Success! You can now click on the button to run your script. You will be presented with a world based on the CroquetMaster subclass.
Advanced users:Experiment with the various options using the halo and its contextual menus to create a more attractive button.
Challenge:
Can you create a button that looks like the following?

Summary:In this lesson, the learner learned to assign a script to a button in Squeak and how to change the name of that button.
ConclusionThis concludes the quick and dirty series on getting a Croquet world running. In this series, the learner acquired the following abilities regarding the core concepts of the Croquet SDK:
1. How to create a new Squeak project.
2. How to open and use a workspace.
3. How to open and use a class browser in a fundamental manner.
4. How to execute scripts in the Squeak environment ("accept" and "do it")
5. How to understand basic scripting syntax in Squeak, from a fundamental and conceptual perspective.
6. How to work with the halo in a fundamental manner.
7. How to assign a script to a button.
I hope that you have enjoyed the Quick and Dirty tutorial series, and I also hope that you have been able to become more familiar with the Croquet SDK.
If you have feedback, questions or comments, please leave a comment in the comments section of this blog. I will do my best to answer your questions.
by Matt Schmidt (noreply@blogger.com) at November 13, 2008 03:59 PM
How To Set Up VNC in a Croquet World
Introduction
I have witnessed quite a few folks asking how they can get VNC running within a Croquet world. Thanks to the excellent KCroquetParticipant subclass, getting VNC up and running within a Croquet world is a fairly easy task. However, to date, nobody has provided a reasonable explanation for non-technical users to perform this task. This tutorial will instruct you on how to do just this.
An explanation of what VNC is and why it is useful is beyond the scope of this tutorial. For more information on VNC, a good starting point is at the Wikipedia entry for VNC.
Learning Outcomes
Upon completion of this tutorial, you will be able to run a VNC server on a host computer, and connect to that VNC server from within a Croquet world.
Prerequisites
In order to complete this tutorial, you will need the following software:
1. REQUIRED: A VNC server. Below are some options that are free of cost:
2.
REQUIRED: A second computer on which to run the VNC server. Although it is possible to run a VNC server and client on the same machine, the technical details involved in such a task are beyond the scope of this tutorial.
3.
RECOMMENDED: The latest build of the Croquet SDK, available
here.
Step by Step Guide
Mac OS X was used to create this tutorial. Much of the information herein should be readily transferable to other operating environments; however, your results may vary.
Part 1: Steps for VNC server computer
1.
Open your VNC server software and configure it (in this case, we are using Vine Server).
The important values to note are:
- IP Address
- Display Number
- Port
- Password
Write these values down so that you can reference them later.
Note the values outlined in red, as
you will need them when you are
configuring the VNC client in Croquet.2. Start the VNC server software
Select "Start Server" in Vine Server's connection
dialogue to start the server
You should be provided with some system feedback indicating that the server is running.
The Server Running message indicates that the VNC server
is indeed running.
The VNC server computer is now hosting a VNC session. We will connect to this VNC session from within Croquet in the next section.
Part 2: Steps for Croquet Computer1. Launch Croquet and open the KAT Demo (this is the KCroquetParticipant subclass)
Locate the KAT Demo in the Objects browser.
Drag the KAT Demo icon from the Objects browser into the Squeak
project space (click image to enlarge).
You are presented with the above dialogue. Select "Cancel."
After a few moments of loading, you are presented with
the above Croquet world (click to enlarge).
2. Configure and start VNC from within the Croquet world.
2.1 From the menu, select "Admin-->New raw RFB"

2.2. Enter the IP address of your VNC server, followed by a colon, followed by the port number that the VNC server is running on. Then select "OK.
"
The structure of the VNC server's address should be the server's IP, followed by the server port.
2.3. Enter the VNC display number; then select "OK."

2.4. Enter the password; then select "OK."

2.5. You should be presented with a Croquet window showing the desktop of the computer on which you are running a VNC server.

You may want to spend some time playing with Croquet's VNC implementation, as it does have some quirks.
Congratulations! You've gotten VNC to work in a Croquet world.
Demo
Here is a video demonstrating VNC being used in a Croquet world.
Summary
In this tutorial, you learned how to start and configure a VNC server on one computer, and how to access that VNC server from within a Croquet world that is running on a separate computer.
by Matt Schmidt (noreply@blogger.com) at November 13, 2008 03:59 PM
iSocial: Virtually a social space for youth with autism
For the past few months, I've been working on a dissertation proposal that will investigate the use of a 3D Virtual Learning Environment for the treatment of autism spectrum disorders. In the process of putting together funding proposals to various granting and gifting entities, I put together a hypothetical use case and a website that outlines the project in broad terms. Since we've decided to use Squeak and OpenCroquet as the development platform for this application, it seemed appropriate to post the use case here.
From the iSocial website:
The iSocial project proposes to develop a three-dimensional virtual learning environment (3D VLE) for students who have been identified with Autism Spectrum Disorders (ASD). Participation in iSocial will enable social interaction and support the development of social competence for participation in both virtual and natural settings. The envisioned system integrates (1) a social space attuned to the capabilities and needs of students identified with ASD, (2) a curriculum of activities and scaffolding for developing social competence, and (3) a networked community for students, parents and teachers to motivate, support and sustain social interaction and progress toward social competence.
As illustrated in the video, youth will experience a 3D VLE customized to support social interaction and learning for the ASD population and adapted to the needs of the individual. The customization and adaptivity of features (e.g., representation, orthotics, and notification) and the study of the impact of that customization and adaptivity on presence, co-presence, behavior management and learning social competence guide the design and development of the system. By customization we mean being attuned to the needs and preferences of youth with ASD. For example the conversation console is a feature of iSocial customized to the needs of youth with ASD to have a mechanism for regulating some aspects of conversation, such as turn taking. By adaptivity we mean that the interface adjusts to how the social deficit or learning objective is manifest for this individual and to changes and development of the individual over time. For example, once a youth learns “turn taking” and is ready to practice this skill in conversation, the console can reduce the control it exerts or remove that feature. Similarly if a youth does not adopt the turn taking controls in the console, other forms of control can be substituted such as removing other members from view until it is the youth’s turn to speak.
I am interested in feedback from anyone from the Squeak and Croquet communities.
by Matt Schmidt (noreply@blogger.com) at November 13, 2008 03:59 PM
Tutorial for Building a Simple Croquet World, Part 1: Setting Up a Croquet World

I am working on putting together a tutorial on how to build your own Croquet world. The entire tutorial will consist of 1.) setting up a Croquet world 2.) customizing a Croquet world and 3.) connecting to other Croquet worlds.
I have finished the first installment of the tutorial series, which will instruct you on how to set up your own Croquet world. Because of the volume of the tutorial, it made sense to make it available as a PDF.
You can download the PDF here.
As always, your feedback and suggestions for improvement are welcome and encouraged.
by Matt Schmidt (noreply@blogger.com) at November 13, 2008 03:59 PM
Update: iSocial Funded!

I haven't posted in quite a while - basically since the Cobalt build was released.
I just wanted to assure everyone that I am indeed very much alive and still working with Croquet/Cobalt. I've just been very busy writing my dissertation proposal (which I defended May 9 and have had accepted - hooray!) and ramping up for full-on development of the iSocial project.
The major news is that iSocial has received a small amount of start-up funds to design and develop a functional prototype. This week is the first week of me working in my official position as project manager for this endeavor. First steps are to create a "generic" Cobalt world that supports all of the functional requirements of the iSocial system and to build a visual design that supports the social skills curriculum we are using. This is an exciting time for us, as things are finally starting to move forward.
We are 100% committed to Open Source. Although our project may not be able to contribute code to the project, we will contribute experience and provide assistance. Our developer will be helping out on the IRC channel, and I'll be putting together the occasional how-to. We are looking in to donating our models and avatars to the project. Stay tuned, as more details are certain to follow.
by Matt Schmidt (noreply@blogger.com) at November 13, 2008 03:59 PM
Two Croquet-Specific Blender Tutorials

Croqueteer Waufrepi has created two tutorials to complement the DMU guides. These are focused on Blender, but are specific to Croquet and will show you how to set up your Croquet exporter in Blender and how to export a Blender 3D model in a format that is compatible with Croquet. Cool!
http://www.youtube.com/user/waufrepi
by Matt Schmidt (noreply@blogger.com) at November 13, 2008 03:59 PM
Wonderland's World Builder
How did I go from this

to this?

With the Wonderland World Builder of course.
The world builder is a simple browser-based application that makes it possible to create Wonderland worlds. Using a simple drag-and-drop interface, one simply drags tiles onto a 2D grid and positions them. After saving the world, it can be easily accessed from the Wonderland client.
The software itself comes with a set of very functional tiles. It is also possible to create tiles using Blender and the Gimp.
The world builder has been discussed at the Wonderblog.
It would be disingenuous to say that it was easy to set everything up on my development machine. However, the Wonderland Community is refreshingly fast at providing solutions when one gets stuck.
by Matt Schmidt (noreply@blogger.com) at November 13, 2008 03:59 PM