Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Tuesday, 10 March 2009

predictive text isotaps

So, ever since getting a girlfriend, I've been texting like crazy. I actually know my way around the numpad, and I've gotten pretty fast at texting. This has pulled my attention toward the input method most people use for writing text messages on their phone nowadays, called predictive text.

Every button to on your phone is mapped to multiple characters. This is how you can resolve phone numbers like 1-800-pizza, but they are also used for texting. 2 maps to {'a', 'b', 'c'}, 3 to {'d', 'e', 'g'}, et cetera. In the old, traditional texting method, you would press the 2 key once to get an 'a,' twice for a 'b,' and so on. In predictive text you tap the 2 key only once, no matter which letter you want. The software uses a dictionary of words to see which word your sequence matches to. For example, to get 'you,' you type 968. The dictionary reveals that 'you' is the only word with this combination, and that word is printed to the screen. This is much more efficient than old style texting, since you need to press less buttons to get your word.

Of course, there are inevitable some words that have the same number sequence. For example, 'home,' 'good' and 'gone' all have the sequence 4663. These words are referred to as isotaps. In this case you can select the word you want with the arrow keys. The list is of course ordered by frequency of use.

Isotaps are quite annoying, because they require that you keep looking at the keyboard in case you meet one. So, I was wondering, how many isotaps are there in the english language? Using some python magic I got the answer, along with a few other random statistics. This was ran against the Ubuntu word list, which is usually more expansive than a cell phone one, but it gives an indication. It would be interesting to compare against other languages, to see which languages is most amenable to text prediction (for a better indication, weight isotaps with word frequency)
  • number of isotaps: 14152
  • longest isotap: size(14) 78873322846617 ["putrefaction's", "stupefaction's"]
  • sequence with most isotaps: (length: 12) 22737 ['acres', 'bards', 'barer', 'bares', 'barfs', 'baser', 'bases', 'caper', 'capes', 'cards', 'cares', 'cases']
amount of sequences with x isotaps:
x = 1: 0
x = 2: 4429
x = 3: 980
x = 4: 308
x = 5: 129
x = 6: 39
x = 7: 14
x = 8: 12
x = 9: 3
x = 10: 1
x = 11: 0
x = 12: 1

amount of isotaps of length x:
x = 1: 24
x = 2: 151
x = 3: 645
x = 4: 2134
x = 5: 2937
x = 6: 3389
x = 7: 2603
x = 8: 1366
x = 9: 517
x = 10: 218
x = 11: 81
x = 12: 49
x = 13: 11
x = 14: 5

Note that there are more isotaps of length 14. given is merely an example. The script is available here. I'm afraid I didn't do any fancy graphs, but the data is pretty interesting I think.

Friday, 13 February 2009

pygame: decoupling rendering from game logic

The basic execution profile of any computer game almost always looks basically the same. The devil is in the details, of course, but the basics are always like this:
  • listen to user input, change game data appropriately
  • update game objects (move objects, do collision detection, etc.)
  • render world to the screen
rinse and repeat that as fast as possible, and you have a game. However, there is a subtle problem with this approach. On faster computers, the game will run faster. If this seems desirable to you, think about networked games. Do we really want those fast computers to slow down just for the slow ones? and how exactly would we do that? And what about scenes that are harder to render? do we have to slow the game down just for that?

We can see that it is, therefore, desirable to make your game run at the same speed no matter what happens. With one caveat: We always want to render as many frames as we possibly can. More frames is a smoother experience, after all.

So we can see that it is in our interest to decouple the game logic updates from the rendering. The rendering should then proceed as fast as possible, but the game logic should proceed at a constant rate regardless of the frame rate.

The right way to do this, of course, is to look at the clock. First we must decide how many logic updates we want to do per second. For most games, about 20 to 25 will suffice. So the time between to updates should be 1/25 seconds. Then, every pass through the rendering loop (which still runs as fast as possible) we check to see how much time has passed, and, only if it is necessary, we make an update to the game. Then we proceed with rendering. If the update is skipped, we need the renderer to interpolate between the two logic updates, so that it does not just render the same world multiple times. This will result in a smoother game experience for fast computers, but will not slow down the game on the slower, older hardware.

in my gunge framework, there is a new Clock class in the experimental branch time-exp that handles this transparently for you. It watches over two things: real time, which advances continuously, and game time, which can be advanced by 1/(updates_per_second) by updating the game. It is worthy to note how game time advances in discrete units, since the game world is updated in steps every iteration of the main loop.

To decide whether the game should update, the Clock has the concept of game latency, or how far game time lags behind the real time. The continuously advancing real time increases the game latency, and it is decreased when the game updates, by 1/(updates_per_second). There are two strategies for deciding when to update the game:
  • game_latency > 1/(updates_per_second) -- this updates the game if the latency lags behind more than one update_length
  • |game_latency - update_length| < |game_latency| -- this updates if it reduces the absolute value of the latency, i.e. if the game time comes closer to real time because of the update.
The caveat of the second method is that it allows game time to be ahead of real time, with the advantage that this may allow the game time to get closer to the real time than it could if it must always lag behind. Another disadvantage of the second method is that it becomes harder to calculate the interpolation factor for renders, but it allows for updates at times when the first method must helplessly fall further behind real time.

Wednesday, 11 February 2009

pyton: everything is an object

Remember that python game framework I was creating? The one with the silly name? (I won't actually tell you what the silly name was, dig through the archives or something). Well, I don't have access to the original code, since it is all in a nice git repository on my pc at home. But this has not prevented me from working on the code.

I've started a new fresh repository on my system here, and to make sure I won't make the same mistake, I've set up a github repository. The new name for the framework is gunge, but the only part that is currently available is the event handling part. I have, however, come across an interesting design challenge that really made me appreciate the fact that in python, everything is an object.

You see, the event system provides a decorator called bind that allows you to statically bind events. It would be used something like so:

class SomeClass(gunge.event.Handler):
@gunge.event.bind(pygame.KEYDOWN, {'unicode': 'a'})
def on_keya(self, event):
print "some code"

The function on_keya would then be called whenever a KEYDOWN event occurs, and furthermore, only if event.unicode is equal to 'a.' There are a few more powerful features to this second argument, called the attribute filter, but that is for another time. How would this be implemented? there is a difference between this function and an actual instance method, bound to an instance.

My first idea was to store the information in some class variable called handlers, and have each instance use this variable to bind its actual methods upon initialization. This works in the simple cases, but becomes problematic with inheritance. A class variable does not carry over nicely between inherited classes, and furthermore, there is the problem of overidden functions. If a function is bound to a certain event in the parent class, and that function is overidden in the child, what should happen? should the parent binding still count, and how would this be implemented?

Implementation issues aside, this method also requires the user to create a new class variable in each class that is an event handler, and pass this handler into the bind decorator so that it can be used for annotation. The problem seemed insolvable. But then a wise lesson came to me: If you're design runs into implementation issues, do not try to solve the implementation issues. It is likely that you need a different design.

It came to me that functions, like pretty much everything in python, are just objects. With types, attributes, the whole shenanigans. So, it seemed much simpler to simply store the binding information as an attribute of the function. Since introspection can be used to find all of an instances methods, it is trivial to retrieve this information. This means that the boiler plate code of the class variable is gone, and that derived classes will retain the bindings of their parent class, unless that particular function is overridden. In that case, the parent functions is not part of the child class, and the binding must be respecified. And this is actually desirable, for clarity's sake.

Furthermore, we can allow a single event Binder object to allow multiple callbacks. This means that a class method can simply store its own Binder object, and each new class instance can simply add its own callback to this object. This reduces the amount of event Binder objects in the event manager drastically, as a class with one method bound to an event will have one Binder object, no matter how many instances of that class exist. This can have huge benefits in both space and speed, since an event has to be tested against an attribute filter just once.

The 'everything is an object' paradigm, together with powerful introspection capabilities, allow you to do a lot more with functions than would normally be possible. And the lesson for this week, of course: If your design has problems, don't try to work around them. Instead, change the design.

Thursday, 5 February 2009

variable assignment in python

Hello everyone, welcome to the blog that rarely has posts! I should really stop making jokes about this. I think it's time for another programming blog post.

The following confusion often arises with programmers new to python, who come to understand that assignments in python are done by reference, not by value. This is correct, after a fashion, and not really that different from other languages. But a little knowledge is often more dangerous than no knowledge at all. While the following statement is not all that confusing for a c programmer who knows nothing about python, it is confusing if he has learned that all assignments are reference assignments:

>>> a = 1
>>> b = a
>>> a = 2
>>> b
1

>>>

The expected result, of course, is 2, not 1. Doesn't a reference the same data as b after the second statement? So shouldn't b reflect the change that was made in a?

No, it, shouldn't, because integers are immutable, which means we can't change them. This might seem strange. We could change the value of a without problems, couldn't we? how can it be immutable then? Well, Let's look at what happens when a simple kind of assignment happens in a fresh python interpreter. What goes on inside if we do this:

Python 2.5.2 (r252:60911, Jul 31 2008, 17:28:52)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]
on linux2
Type "help", "copyright", "credits
" or "license" for more information.
>>> a = 1

Two things are being created here. First, a name. Second, some data. These things exist separately, something that becomes relevant later. Let's visualize the names and data in the interpreter at this time (cheesy graphics will follow):



Right, so we have one name, "a," pointing to some data, in this case an integer object with the value of 1. Pretty straightforward so far. Let's continue along this line. We'll execute the second statement in the above little piece of code:

>>> b = a
The result of this is that a second name is created, b. This is pointed at the same integer object as a, as we specified in the statement:



Now, let's shake things up: we're going to reassign a to something else:

>>> a = 2

Most people would think that the data would simply change it's value to 2, and the picture would remain basically the same. But this is where python catches you: integers are Immutable. That means their value can not change. Ever. So, what happens instead? A new integer object is created:



a is now pointing at the new integer object specified. But what about b? Well, we never told it to point to something else, so it is still pointing at the same old object that a used to be pointing at.

Here, then, is the fundamental aspect to grasp. You can make two names point to the same thing, but if that thing is immutable, it cannot be changed. Therefore, it makes no sense to think changes to one name would be reflected in the other. Because you cannot make changes, only make that name point to something else, which, indeed, messes up your synchronization.

In a language like C, creating two integers a and b will immedeately result in the creation of two integer objects in memory. The above behaviour of these two is expected, since the two names are pointing to two different objects. Upon learning that in python, the assignment b = a results in what is essentially the behaviour caused by the C statement int * b = &a, confusion arises. The missing gem here is the immutability, which makes the python behaviour sane again.

python: intuitive to the newbie, yet without being inconsistent.

Tuesday, 19 August 2008

academic programming

School has started over here in Wisconsin, and so far I have had a Web development class and a Visual Basic class. So far, I'm okay with each of them, but not particularly impressed. I guess my level of skill exceeds either of these classes, but they are prerequisites for the more interesting C# classes that I'll get in the second semester.

The web development class jumped right into coding HTML, which I regard as a good thing to do. Though I think more effort could have gone into explaining the nature of HTML code, like the differences between content and markup, I was happy to learn that old ways of doing styling were no longer used, and basic CSS was taught in the class.
The teacher explained to us how she had learned that it was okay not to close your p tags, but that this was regarded as wrong these days. So far so good. I did, however, regret that she did not always use strict XHTML, and sometimes lapsed into incorrect structures like these:
<.tag1><.tag2>some content<./tag1><./tag2>
To be clear, what I'm referring to here is the incorrect order in closing tags. (sorry about the dots and everything, I'm trying to get blogger not to eat HTML tags but I'm so far unsuccessful. Entities, on the other hand, are not recognised).

The visual Basic class was a bit more disappointing. First off, we did not get into any coding whatsoever the first class. Most of the class was spent looking at different types of flowcharts and UML stuff. Second, I was quite disappointed to learn that the software development lifecycle we were taught was basically the waterfall. Then the class went of trying to explain OO design, inheritance, polymorphism... these are things that cannot be taught without knowing some coding. The result was that the subjects were being dumbed down and incorrectly explained.

On another note, our VB teacher is female (which I find surprising, though I carry no judgement) and used to work as a COBOL programmer (well, nobody's perfect). She also teaches the C# and information security classes, though my info security class is not taught by her. I'm feeling lucky that I already have programming experience, because I think I would feel very confused coming out of the VB class had I had no previous experience.

Overall, I liked the HTML class better than the VB one. I think the teacher was a lot better (should I note my WebDev teacher is also female?), and it at least adheres to current development standards, or at least makes an effort in that direction. We'll see how things progress

Friday, 4 July 2008

for the sake of content

So, after almost a month hiatus, I am now back to entertain you with another post. I'm not going to think up any more excuses for not posting. Frankly, with my day job progressing normally, there's just not much going on worth blogging about. I am of course kept busy, implementing the A* algorithm in python and other such niceties. This one jumps out at me since the use of a heuristic makes A* annoyingly unpredictable. Moving around the goal or start points of a graph might work just fine. Alternatively, it could blow up in your face for no apparent reason and take off finding a path to China.

I'm writing this at work right now, to keep myself from falling asleep. Yesterday was my friend's birthday party. The main dish was the movie The Happening, a horror/disaster movie not unlike The Day After Tomorrow. This time around, the plants are angry at us and dispense a neurotoxin that makes people want to literally kill themselves. I am not joking. The movie started with construction workers jumping off their buildings en masse, in an enactment of the infamous lemmings. Though we noted and appreciated the ties between this movie and the suicide bunnies, we feel safe in recommending that you do not go see this movie.

Despite resolutions to the contrary I was (mis)led by temptation to party on far too long, finally hitting the sack at about 3:30 AM. Of course our little kittens no longer have any qualms about going into my bedroom, jumping on my bed, and start hunting one of my body parts that happens to be moving at the time. This was not appreciated, and I conveyed this message to them in clear and concise manner. No excessive violence was used, of course.

I will make a feeble attempt at dragging myself through the day. I am afraid that with my limited concentration, the bugs/lines of code ratio would exceed one, which makes programming an extremely bad idea at the moment. I've decided to focus on the simple things, letting the hard ones for after the weekend, when my mental state has returned to normal levels.

Monday, 26 May 2008

Brushing up on history

I just discovered phrack, and I find it endlessly fascinating to read up on old issues. Especially the phreak world news is really awesome. I don't understand half of what they're saying, but still all stories about old hacker groups and phone phreaks are enthralling. Just now I'm reading issue 3, and I quote:
Finally, after several months of promises, Brainstorm (ELITE)
now has a 10 Meg Hard-drive
To me, the idea of a 10 Meg hdd by itself is hilarious. But a group of people actually using it together is almost incomprehensible, despite the knowledge of 'ye olde days' I already have.

Other highlights are philes (articles) on how to make different types of bombs and pipe guns, in-depth information on long lost and obscure PDP-11 system variants, and informative articles on picking locks, tapping phones, and electrifying school lockers.
Issue 3 was released in 1986. So this all happened a bit more than twenty years ago, when internet barely existed. I'm looking forward to slightly more recent articles that I can actually relate to, but these old articles are fun purely for historic reasons.

Sunday, 13 April 2008

Happy Birthday Simone

Today (well yesterday technically) is my sisters fifteenth birthday, so let's sing everyone. The real party starts tomorrow, so there's lots more fun to come! Happy birthday, Simone.

I also bought Mario Kart Wii today. I've been playing it all day, and I really do love it. The steering wheel is awesome (an awesome piece of plastic, how about that) and the online capabilities should really up the replay value. The rankings particularly sound pretty awesome to me. The competitions should also be pretty cool when they start coming. This game is a solid buy if you ask me (I advise you don't, though. I'm not unbiased at all).

I fixed the bug that made my library crash under windows. It turns out I was accidentally blitting an image onto itself, which under linux is perfectly fine, but windows starts complaining and segfaults for some reason. Either way, it is fixed now. Updated versions should be coming out soon.

Before I leave, I will give you this fine piece of advice: Don't ever try chinese rice wine. It's a warm alcoholic beverage that is almost, but not quite, entirely unlike wine. It's also not at all tasty. So don't drink it. And consider yourselves lucky, because I had to find this out the hard way.

Wednesday, 2 April 2008

stdtools update


stdtools, my pygame-based game library, is moving along smoothly. I have implemented a bit more sane GUI elements (buttons, menu's) that all work through my event system. The package structure is still a mess, but I will attend to that eventually. I also have plans for some documentation, which will require me to rewrite a lot of the docstrings and organise it in a sane way. I will do that shortly as well.

The new pygame version 1.8 came out recently, which means a lot of new stuff to work with. Of particular interest are the video and mask packages, the first one of which enables video playback (obviously) and the other one can be used for fast pixel-perfect collision detection. I haven't downloaded it yet, but the documentation is up and it looks promising.

I recently saw this google tech talk by Linus Torvalds, about the Git source control management system. I was intrigued, and wanted to try it out. So the stdtools package is as of now on a Git repository. The repo Isn't publicly accesible yet, since I don't have a good place to put it. I'll ask my father (who is in charge of the network here) if I can put on our server. Then everyone will have access to the latest bleeding-edge development code.

I've included a little screenshot of the pong game I'm developing with my library. It's main use is to test the features available, to see if the library is pleaseant to work with and get a better picture of necessary features.

P.S.: I should note that the menu is mostly there to show off the possibilities. None of the buttons work, except for 'new game' and 'quit.'

Sunday, 30 March 2008

Containment Versus Inheritance

In the stdtools package I recently released, there is a class called ResourceLoader. It's purpose is to provide a dictionary-like object that loads resources a game might need, like sound and images. The point is that the images are not loaded until they are accessed. A lazy loading mechanism, one might say. I wanted the object to behave like a dictionary, and make it generic enough so it could be easily adapted for a partical resource type.

The ResourceLoader class does exactly that. It overrides the __getitem__ and __delitem__ hooks to behave like a dictionary, and you can adapt it for a particular resource type by subclassing it, and overriding the load and locate methods. This is all very nice. However, there is a design issue in the class: It uses the dictionary through containment.

What I mean by that, is that the class has an attribute, self.resources, that is a dictionary of all the resources I have currently loaded. If the __getitem__ method is called, the class first tries to retrieve the requested item from the dictionary, and if it is not available, attempts to load it:
class ResourceLoader:
def __init__(self, paths):
self.paths = paths
self.resources = {}

def __getitem__(self, key):
if key not in self.resources:
self.resources[key] = self.locate(key)
return self.resources[key]
So why is this wrong? Remember that this class essentially is a dictionary, with some altered access mechanics. Therefore, it makes much more sense if the class is also derived from a dictionary, instead of containing one. This is the difference between an is-a and a has-a relationship. It makes no sense for this object to have a dictionary attribute if all access of the object is passed onto that dictionary anyway.

There are also concrete benefits to using inheritance in this case. Most importantly, we get all the nice things a dictionary can do, like iterating over it, retrieving it's length, etc. Another bonus is that it is a bit faster, since we don't have to look up self.resources each time. Another benefit we get in this case is that we can forget about the __getitem__ hook, and simply implement the __missing__ method, which is called if a key is missing.

It is not always so clear when to use inheritance, and when to use containment. Think about how your class should behave. If it's behavior is mostly like a dictionary or other type, and the class would benefit from having the methods that type has, inherit it. If the class uses the dictionary more as an implementation detail, and it makes no sense to call something like has_key on your object, it is better to use containment.

I have rewritten the ResourceLoader class as described here, and I'm going to push a new version of it out sometime in the future.

Friday, 28 March 2008

using reduce

Recently I've been reading this blog, about a guy who has set some goals for his life and is now trying to complete them. While I'm not especially interested in all that stuff, the guy is also trying to learn python. I have a sizable amount of experience with the language, so I've been sort of helping him along with his code, pointing out things that could be improved. recently he posted this code, about a function translating text to morse code. You can go over there and read that post, but basically he wrote this:
def translate(text):
text = text.lower()
for char in text:
print morse_code[char] + ' ',
morse_code represents a dictionary mapping characters to their morse code equivalents. Now this function is actually pretty pythonic and overall good, but as I commented, it is unnecessarily limited. The job of the function is to translate text, but it also prints it. What if you wanted to save the text to a file? to accomplish this, the 'what you do with the data' part (printing) should be moved out of the function. A function should do only one thing and return it's results.
You could easily modify this function: declare an empty string, add the characters to it in the loop, then return the result. But this makes the function a little bit unpythonic. There is a simpler, more elegant way to do it.

Cue reduce. Reduce is a really nice functional tool of python that in select situations simplifies the code A lot. It's not needed often, but when it is, marvel at it's simplicity. So, you ask eagerly, how do we use it?

reduce is a function used to reduce (aha) a sequence of values into a single value. It takes to arguments: a function, and a sequence. First, the function is called with the first and second arguments of the sequence. Then, it is called with the result of this call and the third argument. Then, with the result of this call and the next argument. This carries on until there is no more next sequence to apply the function to. At that point the result of the call is returned.
Let's look at a specific scenarion:
import operator
reduce(operator.add, [1, 2, 3, 4, 5])
operator.add is simply a function that adds its two arguments together. So, reduces takes the first and second elements, and calls the function with them. The resulting value is of course 1 + 2 = 3. Then, it takes this result and the next value, and calls the function again. The result is 3 + 3 = 6. As we go on like this, we can see that the result of reduce, in this case, is the sum of the numbers in the sequence. (note that, for adding a sequence of numbers, we have the sum function, which is better, cleaner and faster than this method)

using reduce to rewrite the translation method above, we can obtain the following:
def translate(text):
return reduce(str.__add__, (morse_code[c]+' ' for c in text.lower()))
Now there is a short function. I use a generator expression to obtain the translated text, and sum the characters together with the reduce function. the str.__add__ function is what is called behind the scenes if you add to strings together (i.e. 'str' + 'str2'). A generator expression is another one of those really useful tools to clear up your code. They are, however, an advanced subject. If you don't know what they are yet, first go look up list comprehensions. then, check out generators and finally generator expressions.

P.S.: while proofreading this post, I decided to check out the python documentation. It turns out that summing a sequence of strings is also such a common operation that it has a function just for that. Here is the correct, fastest and pythonic way to do write the above function:
def translate(text):
return ' '.join(morse_code[c] for c in text.lower())
the join function joins together the strings in the sequence, and uses the string it is called on as a separator. I didn't know about this function. The things we learn, right?

Tuesday, 25 March 2008

restructuring pygame flow

I've been programming in Python for quite some time now, and I have really fallen in love with the language. It's simple yet powerful, and there's a whole slew of libraries included. And even more out in the wild. Almost everything I do is in python now, and I'm liking it.

One of the things that has always had my particular attention is game programming. Python as no built-in library just for that, but there is an excellent library available for that called Pygame. It consists mostly of bindings to the SDL library (which is also pretty good), and a bit of python specific stuff to make everything easy for you. So I've been writing small games with pygame for a while, and it's mostly been good. One gripe I have with it, however, is the way the program is structured. I'm talking about the event loop:
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
player.move("up")
#et cetera et cetera
In short, checking for all events occurs in a single loop. That's good, but the actual handling of the event (player.move) occurs in the same single loop. This I find bad. Code used handling the player, enemies, menu options, all of it is gathered up in this single loop, which will grow into monstrous proportions because of that.

To counter this behavior, I have written an EventManager class that is based on callbacks: objects can register functions with the event manager, and these functions will be called if the event is triggered. The function is passed the event in question as an argument, and can act on the event accordingly. With this class checking for events occurs in the EventManager instance, and handling of events occurs inside the relevant objects. All the code is where it belongs, and everyone is happy.

Allow me to demonstrate how a simple class may make use of the eventmanager:
class SimpleObject:
def __init__(self):
EventManager.bindToGlobal(
(KEYDOWN, self.onKeydown),
(KEYUP, self.onKeyup),
(MOUSEBUTTONDOWN, self.onLeftMousebutton, {'button':1}))

def onKeydown(self, event):
print "keydown:", event.key

def onKeyup(self, event):
print "keyup", event.key

def onLeftMouseButton(self, event):
print "left mouse button pressed!"
the above is a simple example of how the event manager may be used. The bindToGloblal method is a class method which makes the requested event bindings to the global EventManager instance, which is stored inside the class itself (usually only one global instance is needed. This method simplifies acces to this instance). The arguments to the function are tuples consisting of the event type, the handling function, and optionally a filter which can make sure only events with certain attributes trigger the handler. In the above example, onLeftMouseButton is only called if event.type equals MOUSEBUTTONDOWN, and event.button equals 1.

So, you ask, where is the source to this elegant class, so I may use it in my games and reach ascension? Good Question. The EventManager class is part of a package that I now use to develop all of my games. Other parts of the package are collision detection, resource management (images, sounds), a primitive GUI, a simple vector class, and some more random tidbits I find useful in my projects. The entire package together is a complete mess, and I really wanted to clean things up a bit before I throw it to you wolves out there.

That said, though, the functionality is there for those who want it. I've tarred the package together under the (slightly) dubious name of stdtools, and it's available here. The entire package is unstable and subject to change. It's also under the GPL.

Monday, 24 March 2008

random backgrounds

Excuse me for all the posts. Since I'm only just starting, I'm trying to get a lot of content out in a short time (get a good start, so to speak).

Recently I got bored with the default Ubuntu background. It's really nice looking with all the swirls and stuff, but I'd been staring at orange for long enough now. So I decided to find some cool looking new backgrounds. Sounds simple, right?

Well, not really. Sure finding a cool wallpaper is not that hard at all. In fact, it's so easy I couldn't decide which one to pick. What I really wanted was a way to get a different wallpaper each time I started my computer. Unfortunately, gnome offers no such option. So I decided to write a little script for it myself. Here's what I came up with:

path="/usr/share/backgrounds"
file=`ls $path | perl -e '@a=<>;print $a[rand(@a)]'`
gconftool-2 --type string --set /desktop/gnome/background/picture_filename "$path/$file"

It's really even simpler than I expected it would be. picking a file is a one-liner, as is changing the background. I put in a path variable so you can set the location of your backgrounds.
Now all you need is some hot backgrounds, and set this to run every time you log in (using gnome session management at system/preferences/sessions), and you have a random new background image every time you log in.