Archive for the ‘technology’ Category

a first look at c#

June 29th, 2006

The first I heard of c#, Microsoft's flagship new language for seamless software development from 2000, one of the first reviews of c# came from some higher-up in the Java hierarchy of Sun. His conclusion paraphrased here for your convenience, was "c# is basically a botched ripoff off java". He was saying that what java had done right, c# had changed for the worse, otherwise it was pretty much the same.

As I got my first introduction to c# recently, I wouldn't entirely agree with that. I'd say c# is (as announced), indeed a hybrid java/c++ combo. At first sight, it looks like java, but certain things are basically ripped right out of c++:

  • pass by reference for primitive types
  • virtual methods
  • operator overloading
  • user defined copy constructors
  • namespace declarations

And some things are completely new and wacky:

  • properties defined implicitly with accessors (not unlike ruby)
  • overriding base class constructors in derived classes (what does this say of encapsulation? hm)
  • sealed (non-derivable) classes
  • structs (from c) as lightweight alternative to classes
  • foreach statement (similar to php)
  • delegates (a bit like function pointers in c++)

In a way it looks like c# went completely java, but they couldn't bare to leave behind certain features of c++. And that's reasonable, it becomes some sort of superset of the two and with a rich library. My impression so far is that it seems to be java without some of the pain.

libraries to applications ratio

June 27th, 2006

As I browse through Sourceforge, I can't help but get the impression that there seems to be a lot of libraries in development, as opposed to not as many applications. Is it because people have don't need as many new apps anymore, whereas technology keeps advancing and libraries for just about anything spring up, with bindings for c all the way to ruby?

Another thing is that while innovative or useful apps are pretty far between, the same things are often reproduced countless times. I cannot remember how many im chat clients I've seen over the years, meanwhile gaim remains the reference point. But even with so many clients, there hasn't been one that was actually great. So why do people start new im projects? And since they are, why aren't those new projects better than gaim and all the "old" apps we have? And how many CMSs do we really need? There isn't a forum system out there that rivals vbulletin on functionality (phpbb is primitive in comparison), but there are countless frontends for xinelib, even though they're all the same and still inferior to mplayer, which has been around for ages.

keeping track of train routes

June 5th, 2006

OpenTTD is an open source game based on the old classic Transport Tycoon Deluxe. The original game was reverse engineered and the code is all written from scratch. The idea of rewriting this venerable game is very good, as those who loved the original have a chance to implement all kinds of improvements they may have conceived while playing the commercial game, which of course did not allow for any hacking. Not to mention that with new code in c, it could be made cross platform (the old game only ran on Windows)! I found OpenTTD a very cool initiative, and after a relatively short period of time, the developers had managed to improve lots of little usability issues, while adding new and desirable features.

The game is about building a transportation network and there are four kinds of transportation available - aircraft, ships, buses/trucks, and trains. But this game is really mostly about trains and the magnificent networks of trains its gamers have concocted. One thing I found to be a little troublesome was to keep track of the trains as they grew in numbers, and keep track of their routes. If you build a junction such as the one shown in the screenshot, then how, by just looking at trains going by, are you going to keep track of which train has which route?

openttd_junction.png

There could be lots of ways to make this common problem less of a problem, but my idea was to keep track of routes by keeping track of names. If you were to have a set of trains called South Western 1, South Western 2 etc, all of which had the same route, then you could easily tell trains apart, and see where a train has gone where it shouldn't have. It would still require the user to set up the routes and name the trains, but from that point on, the game could assign the correct names, so if you cloned a train called New York - San Francisco 7, the clone would be assigned the name New York - San Francisco 8.

So to make that happen I wrote a patch against revision 5125 in svn.

*** vehicle.c	2006-06-05 14:59:24.000000000 +0200
--- vehicle.c	2006-06-05 15:00:35.000000000 +0200
***************
*** 30,35 ****
--- 30,37 ----
  #include "station_map.h"
  #include "water_map.h"
  
+ #include <ctype.h>
+ 
  #define INVALID_COORD (-0x8000)
  #define GEN_HASH(x,y) (((x & 0x1F80)>>7) + ((y & 0xFC0)))
  
***************
*** 1567,1572 ****
--- 1569,1580 ----
  				w_front = w;
  				w->service_interval = v->service_interval;
  				DoCommand(0, (v->index << 16) | w->index, p2 & 1 ? CO_SHARE : CO_COPY, flags, CMD_CLONE_ORDER);
+         
+ 				// if orders are shared, increment vehicle number
+ 				if (p2) {
+ 					IncrementVehicleNameOnClone(v, w, flags);
+ 				}
+         
  			}
  			w_rear = w;	// trains needs to know the last car in the train, so they can add more in next loop
  		}
***************
*** 1579,1584 ****
--- 1587,1672 ----
  	return total_cost;
  }
  
+ /** Increment the cloned' vehicles name
+ * @param v the original vehicle's index
+ * @param w the clone's index
+ */
+ void IncrementVehicleNameOnClone(Vehicle *v, Vehicle *w, uint32 flags)
+ {
+ 	int len = 32;
+ 	char vehicle_name[len];
+ 	char vehicle_number[len];
+ 	Vehicle *nvehicle;	// the next vehicle in array to check
+ 	char nvehicle_name[len];	// the next vehicle's name
+ 	uint16 e;
+ 	uint16 pool = GetVehiclePoolSize();
+ 	int i, j, f, n, largest;
+ 	int numbers[pool];	// the array of numbers our new number must fit into
+ 	
+ 	// Get the name of the old vehicle
+ 	if ((v->string_id & 0xF800) != 0x7800) {
+ 		vehicle_name[0] = '\0';
+ 	} else {
+ 		GetName(v->string_id & 0x7FF, vehicle_name);
+ 	}
+ 	
+ 	// find out how far into the name the digits start, save the index
+ 	i = 0;
+ 	while (!isdigit(vehicle_name[i]) && (i < len)) {
+ 		i++;
+ 	}
+ 	
+ 	// use the index to read an integer from the vehicle name
+ 	n = atoi(&vehicle_name[i]);
+ 	if (n != 0) {
+ 		
+ 		// find a vacant number to assign the new vehicle, check all existing
+ 		// vehicles which have the same name
+ 		memset(numbers, 0, pool);
+ 		e = 0;
+ 		j = 0;
+ 		for (e = 0; e < pool; e++) {
+ 			// verify vehicle owner and type to match this vehicle
+ 			nvehicle = GetVehicle(e);
+ 			if (CheckOwnership(nvehicle->owner) && (v->type == nvehicle->type)) {
+ 				
+ 				// get string_id
+ 				if ((nvehicle->string_id & 0xF800) != 0x7800) {
+ 					nvehicle_name[0] = '\0';
+ 				} else {
+ 					GetName(nvehicle->string_id & 0x7FF, nvehicle_name);
+ 				}
+ 				
+ 				// filter string_id's that are empty or non-equal
+ 				if (strncmp(nvehicle_name, vehicle_name, i) == 0) {
+ 					numbers[j] = atoi( &nvehicle_name[i]);
+ 					j++;
+ 				}
+ 				
+ 			}
+ 		}
+ 		
+ 		// resulting array 'numbers' has the numbers of vehicles we need to examine
+ 		largest = 0;
+ 		for (f = 0; f < j; f++) {
+ 			if (numbers[f] > largest) largest = numbers[f];
+ 		}
+ 		
+ 		// assign number to vehicle
+ 		n = largest+1;
+ 		vehicle_name[i] = '\0';
+ 		sprintf(vehicle_number, "%d", n);
+ 		strcat(vehicle_name, vehicle_number);
+ 	
+ 		// Set the name of the new vehicle
+ 		if ((flags & DC_EXEC) && vehicle_name[0] != '\0') {
+ 			_cmd_text = vehicle_name;
+ 			DoCommand(0, w->index, 0, DC_EXEC, CMD_NAME_VEHICLE);
+ 		}
+ 	}
+ 
+ }
+ 
  /*
   * move the cargo from one engine to another if possible
   */
*** vehicle.h	2006-06-05 14:59:24.000000000 +0200
--- vehicle.h	2006-06-05 14:59:52.000000000 +0200
***************
*** 297,302 ****
--- 297,304 ----
  void AgeVehicle(Vehicle *v);
  void VehicleEnteredDepotThisTick(Vehicle *v);
  
+ void IncrementVehicleNameOnClone(Vehicle *v, Vehicle *w, uint32 flags);
+ 
  void BeginVehicleMove(Vehicle *v);
  void EndVehicleMove(Vehicle *v);

It was a bit of a struggle, as I've never actually written an application in c. It also took me a while to figure out how things are done in OpenTTD, but sure enough, it does what I set out to do.

I've played the game with this patch applied, and I prefer it that way. However, the developers didn't think it was a good idea, neither for technical reasons nor gameplay, and it's not going to be an actual thing in the game. I think problem is a legitimate problem and that it should, and probably will, be addressed at some point.

give it up for scons

May 19th, 2006

Isn't it nice when you have an idea of something that would improve your life (and possibly the lives of many others) and you think to yourself "well if I were to do it, it would take me lots of time and hassle, someone should do it" and then you discover no less that someone has already?

A while back I was praising ant for being an improvement over make. And it is, it's smoother, it's nicer, it's more suited to the needs we have from a build tool today, make is ancient afterall. But then ant has it's problems.. the xml configuration scripts are a bit cumbersome and unnecessarily complicated (I mean who actually enjoys writing xml?) aaaand it's java based. Nice for portability, bad for speed. If you're building eclipse and you set up ant to do it, big deal, it takes forever anyway, the overhead in a java build tool won't bother you. But if you have a dozen java source files and you're working on some small project, you could still use a build tool to keep building more streamlined and organized, but ant won't feel like such a great choice anymore. Because making one small change in a source file will launch ant to rebuild that class. And even though compiling java doesn't take that long, launching ant itself probably takes longer. So there's a tangible overhead. Launching the vm itself takes a little while.

So if I'm writing a java application, I'll still use ant (probably), because it's a java environment anyway. But if I want to automize building latex documents or conceivably anything that could use the power of a build tool, I'm going back to make, it's quicker both to write the script and at every launch. But since make is far from ideal, how about a python based build tool? Python is quick and powerful. The first time I thought of that must have been a few months ago. Fast forward to today and....

Enter scons. scons is a python build tool, just like I conceived. As I started looking at the manual, it seemed very c-centric (with java support as well). But, it turns out that scons ships with build definitions for many languages and compilers, including jar, qt, latex, tar, swig.. well you get the idea. Not only that, build definitions are just simple python files which are easy to write. So the next time I need a build tool, I'll definitely see how far I can get with scons.

what you didn't[?] know about Firefox

April 18th, 2006
  • Do you know how html forms work? Most people would probably say "no".
  • But do you know how Google works? I'm gonna go out on a limb here and assume that most people would say "yes".

Why am I talking about this? Because I just found a cool feature in Firefox that I didn't know about before. To give a little background first.. have you ever wanted bookmark a search result? But they're not usually "bookmarkable", are they? Well you can, if you know how. It has something with how searches (or in general: form submissions) are handled on the server side. If the form is a post, then bookmarking the url in the navigation bar won't work. If the form is a get (eg. Google), then you can bookmark the search.

So picking up user patterns like that is what makes good software and Firefox has done something to make searching nicer for us. The idea is very simple, but it's the kind of thing that is done easily in software which is inconvenient to do manually by the user.

Seeing is believing so try this one for size. Open http://www.imdb.com/ in Firefox [duh], right click on the input box where you type in your search words and select Add a Keyword for this Search.... I'm not sure which version of Firefox you need for this, but I'm on 1.5.0.2. You will see a dialog box that looks like this:

I have filled it in already, you can copy mine if you like. Now, in your location bar, type m paul walker and hit Enter.

See what happens now? You search imdb for the term paul walker just by typing m searchword in the location bar. What you've set up here is essentially a bookmark, with a keyword. The keyword is m, what you type in to run a search. It could just as well have been imdb or moviedatabasesearch, then again m is shorter, no?

Needless[?] to say, this isn't limited to imdb.com, you can use this function to create a bookmark for every search box anywhere and set up short keywords to run searches more conveniently. I didn't demo this with google because Firefox already has the google search integrated, but I think this is actually a nicer way to google than using the google input box.