Efectos Especiales

Ramblings, rants, musings, ideas and observations. Topics include (but are not limited to): programming (especially Python), books, games (especially CCGs and board games), astrology, design, writing, painting, etc.

icon:hurricane #609 (old comments) My First Hurricane

Hurricane Charley is expected to hit the Tampa area later today (Friday). Let's see what it does to the Gainesville area. More later. I hope.

[Update 2004-08-13 20:10] It made landfall near Fort Myers, and is slowly moving north-northeast. With a little luck, we won't see much of it except rain. I don't know how they can predict it will be in North Carolina by Saturday, when it's obviously moving slower than snail$#!1. (Answer: because they (= wunderground.com, in this case) have peculiar notions about when the day begins and ends.)

[Update 2004-08-14 02:13] The damn thing is at the east coast now, and has not bothered us at all. emoticon:dance

/* Posted by Hans "and it's Friday the 13th too" Nowak at 2004-08-13 02:07 */

icon:python #608 (old comments) Go forth and obfuscate

OK, the one-liner in the Not safe for work post wasn't really obfuscated. It's just several lines compressed into one, using a simple trick to add dictionaries. (Adding dictionaries with d1 + d2 does not work, but dict(d1.items() + d2.items()) does.)

However, stuff like this *can* be used to obfuscate things. It's a building block. Given a hypothetical Obfuscated Python Contest, you can turn a simple function call f(a, b) into this monstrosity:

(lambda f, *args, **kwargs: lambda *cargs, **ckwargs: \
        f(*(args+cargs), **dict(kwargs.items() + ckwargs.items())))(f, a)(b)

Let's discuss some more building blocks. One of the basic obfuscation techniques is to replace operators with functions in the operator module. For example, operator.add(4, 5) is a verbose way of saying 4+5. Combine this with the curry function above for extra fun:

(lambda f, *args, **kwargs: lambda *cargs, **ckwargs: \
        f(*(args+cargs), **dict(kwargs.items() + ckwargs.items())))(operator.add, 4)(18)

Those numbers are still too obvious. Fortunately, Python 2.3 provided us with booleans. emoticon:devilish So, True + True is a nice way to spell 2. You can also add or subtract arbitrary Falses to your result, because they evaluate to 0. If you actually need the value 0, then you can use an expression that returns False, rather than False itself. For example:

>>> True + True
>>> x = (True + True) < (True)
>>> x = x + (True + True) * (True + True + True)
>>> x

Another technique: instance attribute lookup obj.x is easily replaced with getattr(obj, "x"), and setting an attribute can be done with setattr(obj, "x", value). For example, the line

setattr(self, "data", operator.add(getattr(self, "data"), x))

is obfuscese for self.data = self.data + x.

Even more fun is using new.instance rather than creating an instance the usual way. Note that new.instance doesn't call __init__, which may cause extra confusion.

>>> class Foo:
...     def __init__(self, this, that):
...         self.this = this
...         # ...etc..., who cares, it's never called
>>> import new
>>> foo = new.instance(Foo, {"data": (True+True < True-False)})

One-liners are nice. You can turn a number of statements into expressions, making them chainable in one long line. We already saw that a.b = c can be written using setattr, which is a function. Since setattr returns None, we can chain multiple calls using or:

setattr(obj, "x", 2) or setattr(obj, "y", 3) or sys.stdout.write("Done!\n")

Also, don't forget to use magic methods explicitly:

(1, 2, 3).__len__()  # rather than len((1, 2, 3))
alist.__getitem__(0) # rather than alist[0]
adict.__setitem__(key, value) # rather than adict[key] = value

These were just a few things off the top of my head. I'm sure I've only scratched the surface. There must be a lot more of these techniques. Feel free to post more of them in the comments. emoticon:smile

A final word: It's nice that in Python you have to go out of your way to write code like this...

/* Posted by Hans Nowak at 2004-08-12 12:47 */

icon:default #607 (old comments) Kamigawa

The next Magic the Gathering set will be Champions of Kamigawa. This isn't news, of course, but so far preciously little is known about the new set.

However, mtgnews.com has three spoilers. The only complete card is Kitsune Healer, which has the intriguing type "Fox Cleric". Hmm, I wonder if that means that we will get fox people in this set, much like Mirrodon had elephant people (loxodons), etc? That would be an interesting twist. The art certainly suggests so... looks like a guy with big ears and a tail. (And the card text could be a hint that this block will be heavy on Legends.)

I'm curious to see what WotC is going to make of this new block. There are already card games out there with a Japanese flavor, most notably Legend of the 5 Rings. It will be really hard to make something decent that does not look like a L5R ripoff.

I was apprehensive about the Mirrodin block as well, since at first it looked like Magic had gone SF... but it turned out to be really good, both in flavor and functionality. So we'll see what the new block brings.

/* Posted by Hans Nowak at 2004-08-11 23:02 */

icon:default #606 (old comments) Slim

If you thought you were pretty smart, here's a little reality check. Check out this chick Alia Sabur who is a Ph.D. candidate at age 14.

/* Posted by Hans Nowak at 2004-08-11 19:09 */

icon:music #605 (old comments) The merchant of grooves

I think this Wikipedia article about 3rd Bass contains an error. I must have listened to Derelicts of Dialect at least a thousand times. <0.2 wink> So, I'm pretty sure that Nas does *not* appear on that album. Others do, like KMD, Chubb Rock and Nice & Smooth, but not Nas. Rather, he makes his debut (as "Nasty Nas") on Serch's Return of the Product.

I've heard about Wikipedia's alleged inaccuracies before, but this is the first time that I actually see information that I (pretty much) know not to be correct.

I also think the Wikipedia article was inspired by this one on MSN Entertainment. Or maybe it's the other way around... hard to say.

[Update #1] I fixed it. Well, that was easy. emoticon:smile Let's see if it stays...

[Update #2] I also edited the entry for MC Serch, which only mentioned one 3rd Bass album.

/* Posted by Hans Nowak at 2004-08-11 01:49 */

icon:python #604 (old comments) Not safe for work

Upon reading PEP 309, I saw the implementations of the curry class/function. Note that curry can be written as a one-liner:

curry = lambda f, *args, **kwargs: lambda *cargs, **ckwargs: \
        f(*(args+cargs), **dict(kwargs.items() + ckwargs.items()))

def bar(x, y, z=42):
    return x*3 + y*2 + z

b = curry(bar, 1)
print b(2, z=3)

It's not very readable, of course, and it has no practical use. I just wrote it so I had something to do during my break. emoticon:smile Although it might be the start of an entry for the Obfuscated Python contest?

/* Posted by Hans Nowak at 2004-08-10 12:51 */

icon:eclipse #603 (old comments) Why Eclipse?

This post, Why Eclipse Demolishes other Alternative Languages, talks about how Eclipse makes features in other languages (other than Java, that is) irrelevant.

So, what's the big deal about Eclipse? I've used it (though admittedly not a lot), but to me it seems like just another IDE. Sure, it has code completion, project management and all that, but so do most modern IDEs (and I don't even want those features anyway). So what are those powerful features that make Eclipse stand out? I'm not criticizing, just wondering... I must have overlooked them during the (relatively short) period I was tinkering with Java, or maybe I didn't realize their full power.

Also, I don't know that with Python I "spend most of my time digging through the reference manuals"... that's actually not such a common occasion. (And if I do need to, Charm has "lookup name with pydoc" and "look at module source" options, so I don't have to leave my editor.) With Java I was looking up stuff all the time, but that can be attributed to learning.

If anybody here uses Eclipse, I'd like to hear more about your experiences.

/* Posted by Hans Nowak at 2004-08-09 15:14 */

icon:games #602 (old comments) The noble art of breaking out

Arkanoid.com has a bunch of breakout games. [1]

You know breakout; hit a ball with a bat to destroy bricks, until all bricks are gone. Repeat. But if you think all there is to it is just mindlessly hitting a ball, watching random bricks break, then you're seriously mistaken. A good breakout game offers more and gameplay can actually be quite subtle.

A friend of mine once complained that he didn't like breakout games, and suggested that you should be able to steer the ball somehow. Well, you actually can, sort of. You can influence where the ball goes by making it hit the bat in the right spot. Doing this correctly is not easy; as a result, breakout is often eschewed by heavy-handed joystick-wagglers.

/* ...way back into time while Hans sings the saga of the ancient breakout games... */

The first industrial strength breakout clone that I played was Arkanoid, on the C64, somewhere in the middle 80s. I believe it set the standard for pretty much every decent breakout game made after it, and was cloned often. It has all the features that are considered staples today... bricks that take a few hits, indestructible brick, magnetic bat, laser gun, powerups that make the ball faster or slower, bat grows or shrinks, multiple balls, etc. Levels become more difficult as you go on; I remember a really nasty one with a row of indestructible bricks and one tiny gap. It did *not* have the option to save your progress, so it was not uncommon to play it for hours and hours just to lose all your lives in a difficult level, with no means of picking up where you left off. [2] And unlike most other breakouts I've seen, this one has a boss. (You know, like a boss fight at the end of a level...)

Arkanoid's successor was the unsurprisingly named Arkanoid II, with the cryptic subtitle "Revenge of Doh". (I wonder why it was called that... maybe because you say "doh!" when you lose a ball?) Much of the same stuff, with some new features, like a red ball that rips through everything, and moving bricks.

There were other good breakout games back then. One of them was Breaker, by Radarsoft (a Dutch software house, IIRC). Not very sophisticated, but fun, with (for the time) futuristic graphics.

Traz stood apart from the rest because of its level editor. Also, it had bricks in various sizes, a rather novel feature back then.

Where all of these games have the bat at the bottom, Krakout has it on the side. This seemingly small detail makes for very different gameplay.

I don't recall that Batty was very good, but it supported dual gameplay. I never played Impact (although I could now); I believe it was originally an Amiga game.

But the wackiest of all breakout games was Ricochet. It has a bunch of weirdly layed out screens, but that's not all. At the top of the screen there are the letters G-R-A-V-Y. Destroyed bricks don't just drop powerups, but also colored blobs, that correspond to a letter. When you've collected enough blobs of a certain color, the appropriate letter becomes "active", and you get a certain feature, like the "magno bat", or the "angry yag" (a face that appears onscreen and starts spitting out balls that destroy bricks). Also, there are bonus screens where you get to destroy baddies with your bat. You should buy an old C64 on eBay for this game alone. emoticon:wink

/* ...back to 2004... */

Anyway, back to that site. I tried Magic Ball, played it quite a lot in fact. It's a decent breakout clone, fun to play, with a good soundtrack, but it doesn't have many innovative features, and its lastability is a bit lacking. It has 3D screens, which is a nice touch, but it doesn't really change gameplay much. (The ball still moves in a 2D plane.)

You can play random levels. The problem with this approach is that the game doesn't actually become any more difficult as you proceed, nor does it introduce new things. Some levels are more difficult than others because the bricks can be real close, giving you lots of opportunity to goof up as the ball gets faster. When that happens, you can just reload and try the same level again, until you get some crucial powerups (magnet, big ball, fireball), which take care of all problems.

Another game on this site, Ricochet Xtreme (no relation with the old Ricochet), doesn't seem to have these problems. It starts you off with relatively simple levels, introducing new features one by one. I haven't played it much yet; more about this game later (maybe).

[Update #1] Those old C64 games were made to be played with joysticks. Playing them in an emulator using the cursor keys (or any keys) appears to be much more difficult. Or maybe I'm just too old now... emoticon:nosmile

[1] I got this link via some weblog, but I forgot where exactly.

[2] With emulators, this is no longer a problem. It does take away a bit from the original experience though...

/* Posted by Hans "ta me old china" Nowak at 2004-08-08 23:27 */

icon:python #601 (old comments) The "Py spot"

Wow, lots of comments on the Creeping Featurism entry. I have a lot more to say about this subject, and some related topics, but I'm not sure if I should post it. It could easily be misinterpreted as "Python sucks", which is not what I am trying to say.

As Ian Bicking points out in the comments, Python isn't (and has never been) a minimalistic language. Rather, it has often managed to hit a "sweet spot" between extremes. Not too much syntax, not too little. Not too much power, not too little. Not too many modules in the standard library, not too few. Not too verbose, not too terse. Not hung up on one programming paradigm. Not too small, not too large.

YMMV... People coming from different languages would often like to see Python lean more towards certain sides. I can imagine that Java fans would like to see more libraries, or that Lisp fans would want more expressivity. But generally speaking, this sweet spot exists, and IMHO it's very important.

My point is, that Python is slowly moving away from this sweet spot. Slow enough that many people probably don't even notice it's moving. I find this change a bit disturbing, though. Python isn't a small language anymore, and TOOWTDI is a thing of the past.

All these changes don't make the language ugly, or badly designed, or less usable. So far, they're not even enough to make it bloated (Python is still a far cry from Ada or C++). But it's a change in spirit from the old Python. Practicality beats purity, yes. But let's not forget that "special cases aren't special enough to break the rules".

I really hope that Python 3.0 isn't too far away, and that it will make a clean break, backward incompatible or not, and then settles on a new "Py-spot". I don't care if New Python has gencomps or metaclasses, as long as its design is relatively clean, and the core language is relatively small. As long as it's... well, Pythonic.

I guess it's time I end this discussion now and go write some nice code. emoticon:smile

/* Posted by Hans Nowak at 2004-08-06 14:08 */

icon:default #600 (old comments) Ice Age week at magicthegathering.com

The "sages" in this column have... interesting names. ^_^

/* Posted by Hans Nowak at 2004-08-05 11:42 */