|
My brain is built of paths and slides and ladders and lasers and I have invited all of you to enter its pavilion. My brain, as you enter, will smell of tangerines and brand-new running shoes.
 Blah, blah, blah GINGER. Blah blah. |
Posted - 3/30/2006 12:42:46 AM | Just a quick dump of thoughts here before I stumble off.
- If you haven't already, check out the Pragmatic Programming Language for the Future discussion going on in the Software Engineering forum. There's some absolutely excellent feedback coming together from this thing, and I think that with some real effort, we might actually have a winner on our hands here. I firmly believe that someone can produce The Next Killer Language if they pay attention to real life issues while doing so, and it's frankly kind of cool to be a part of an attempt at such a project. Hop on board, even if you have no particular interest in programming language theory... customer feedback is good, too

- Household cleaning chores suck. That is all.
- I'm developing some kind of perverse addiction to bulleted lists lately. Meheh. Bulleted.
- If you haven't already, go read Zen and the Art of Motorcycle Maintenance. Read it now. It's a fascinating read, even if some of the concepts presented are a bit debatable, and it'll make you think about all manner of things. It isn't so much profound or deep in and of itself, but it's a very effective mental stimulus. It's definitely a "brain-must-be-on" work, which I almost always enjoy.
- My knees hurt. Anyone know any good physical therapy exercises for strengthening knees? Especially stuff that's good for building up durability for someone planning on taking a lot of repeated impacts on the knees in the near future? (Yeah, yeah, yeah, wrong forum, I know.)
Game Related Stuff
The design phase of the cutscene system is finally drawing to a close. We're having a meeting sometime in the next few days to try and sort out the last few areas of functionality that I can't really specify, since the art team (and not me) is the final user of the system, so they're the ones who know what it needs to do. It's annoyingly difficult to schedule meetings with a team that's six (currently seven, thanks to DST) hours apart, but that's life.
Once the feature requirements are set out, it's go time. I'll be planning up a complete roadmap for implementation, which I will start drafting tomorrow, leaving holes for the last few design areas that aren't locked in yet. That involves a comprehensive code architecture plan (how code will be structured to solve the requirements) as well as a preliminary division of labor (who gets to write what pieces of code). This kind of architectural engineering is one of my favorite parts of software development, so I'm really looking forward to it.
After the architecture is done (shouldn't take more than a few days all told) it's time to start writing code. I predict a few weeks to get a rough version going, enough to get a visible demo of the functionality and what the system is capable of. There's a chance we might try to demo some of this functionality (privately) at E3, so I have sort of a deadline to work under. Should be fun, though, and working under pressure always does good things for my motivation.
In the interests of keeping a relatively sane schedule, I'm off to read more Zen until I fall asleep.
| |
 It's aliiive! |
Posted - 3/27/2006 8:03:46 PM | Wow, that generated substantially more (and more positive) response than I had expected. I guess it shouldn't come as much of a shock to me that others are feeling the need for a better toolkit, but I would have expected at least some backlash against the heavy-handed pragmatism 
Yes, there's a real risk here of hitting "linguistic bloat" and trying to do too much with a single tool. However, I think that we also need to be wary of panicking over "bloated" languages. Sure, if we try to do too much in one tool, we're going to end up with a tool that does very little well. The question, though, is what delineates "too much." I think Ruby is a shining example of a very rich language that is done right.
Issues like semantic expressivity, contracts, and multiprocessing are real issues. These are things that I know, from in-the-trenches experience, cause major trouble when using existing languages. Those are the challenges that are genuinely going to shape the next decade of programming.
Software quality is not going to rise significantly without the ability to express semantic and contractual behavior within a language. The managed-everything model of .Net has proven a reasonably effective counter to the manual memory-management nightmare of the C/C++ world, but there are many monsters left to slay. I can state with absolute certainty that, in my experience, 90% of run-time bugs arise from violations of semantics (discounting multiprocessing issues). In probably 85% or more of those cases, the semantics should have been expressible in the language itself; if that feature were available, a good third of the bugs could have been nailed before compile-time, and the rest would have barfed at run-time during unit testing, long before a serious problem arose in production.
When multiprocessing comes into play, shared-state languages like C++ are simply massive failures waiting to happen. They are impossible to validate automatically. They cannot be tested rigorously on every possible hardware configuration, which is bad, because every hardware configuration (and even some software interactions) might subtly change the behavior, and lead to synchronicity issues that otherwise would never have manifested.
Those areas absolutely must be addressed. Without fixing those problems, we are going to take one of two routes. Either we'll continue to try to patch the holes in C++, with increasingly bad results, or we'll proliferate a group of domain-specific (or at least domain-restricted) languages. Already this proliferation is beginning to occur. I have absolutely no disagreement with having multiple languages; indeed, every problem space has its ideal language, and this will always be the case.
However, my dream here is to see a single language, or at least a very tightly-knit family of extremely similar language dialects, be able to cater to a wide array of problem domains. C++, with its multi-paradigm support and ability to live close to hardware, is frankly the closest thing we have to such a language for the time being. We can do much, much better than C++.
I see no reason why languages in different domains must, by necessity, have vastly different philosophies and syntaxes. Yes, there are going to be edge cases where certain highly distinct domains need highly distinct languages. I'm not concerned with those fringe cases, because they amount to a tiny fraction of software development. The real bulk is in three main areas: consumer applications, business logic, and games. Those three domains should be easily unifiable under a single language family.
Instead of writing my web server in C++ and my webpage logic in PHP, I should be able to write my web server in Foo at a low level of abstraction, and then build webpage logic in Foo at a high level of abstraction. Foo should then let me make use of a flexible compilation/execution model to either compile the logic directly into a binary executable (for, say, embedded hardware or highly performance-critical scenarios) or let me use a JIT-compiled setup similar to ASP.Net or the Zend engine, where external users can upload script files that are executed dynamically by my server software. I shouldn't need two different languages here.
Having a unified language structure gives me three advantages.
- Utter control over bindings between application layers.
If I develop a suite of tools called Quux in C++, and want to access it from PHP, I have to build an extension to the Zend engine. That's a waste of time. If Quux is written in low-level Foo, and my web logic is written in high-level Foo, the bindings already exist: the interface for Quux just needs to be imported (via a Java/.Net style system) into my web logic, and I now have access.
- Consistency of semantics across layers.
If Quux returns a value that may only range from -1 to 3, that contract can be expressed in Foo. Foo can then expose that contract to the web logic. I have now used a contract to help kill bugs in Quux, and now without any additional effort, my contract can help kill bugs in the web logic, too. Imagine the implications for things like web security. SQL injection would become a distant memory. Buffer overruns, covert data manipulation, and data-execution would all go away.
- Control over execution models.
In an ideal world, Foo should allow me to run in many ways. I should be able to compile suitably low-level Foo into machine code. That wins us portability, because now Foo frameworks are easy to port to new OSes and hardware. (That's why C and C++ are so ubiquitous even outside of Windows, while .Net, despite all of its awesomeness, is unlikely to do anything on other platforms any time in the visible future.) I should be able to JIT-compile Foo for performance and to insulate against changes in supporting library code, similar to the way the JVM and .Net models work. I should also have the option of interpreting Foo on the fly to allow for dynamic and self-modifying code at high levels of abstraction. There is no reason why any one language should be bound tightly to a particular compilation/execution model. We simply need to make sure that programmers are aware of the caveats of each.
I'm certainly interested in continuing this line of thought. Acting alone, it would probably take me the bulk of my career to really ever get anywhere with specifying and implementing such a huge project. I think the success of this kind of an initiative is going to depend entirely on massive support from the development community and from existing vendors.
IMHO, Foo absolutely has to have a simple interconnect mechanism for talking to C-style APIs. That immediately makes it a viable contender for Windows and Linux development, which is absolutely critical to adoption. That also allows for more cool stuff, like bindings to C++, which can then marshal to managed code in .Net.
Foo will not survive if it tries to recreate the programming paradigms of the world from scratch. Foo will only survive and succeed as a parasite, drawing on existing, established code, and allowing a gentle transition from current modes of thought and coding to more productive and safe ones. That kind of interconnection requires big-league backing, and lots of people looking over things to make sure it all works.
A couple of people have suggested opening up a more broad discussion someplace. I'm all for this. I'll put together a quick set of links to my journal entries and post it up in the Software Engineering forum, since that will make things much easier to discuss widely. If anyone has any ideas for an even better location, please let me know, and we'll work something out.
[Edit]
The thread is up. Enjoy!
| |
 Linguistic Wishlist |
Posted - 3/27/2006 10:01:06 AM | I'm really starting to get interested in the notion of building a new programming language. Every language I've ever used has had some really glaring shortcomings and problems, even aside from the normal quirks and personality flakiness that any language is going to have as a matter of course.
Now, I have no formal training in PL theory. Some people might say that makes me a bad candidate for trying to design a language. Perhaps I'm foolish to do so, but I disagree. My view is that the academics have had plenty of chances to design The Perfect Language. Thus far, they haven't done such a great job. On the flip side, people who are concerned primarily with getting crap done seem to be far more successful: PHP, Java, C#, and (to a far lesser extent) Ruby all come to mind.
By nature, as a professional programmer, I'm intensely concerned with getting crap done. I really don't care what some guy in some university thinks is the best way to build a language. Existing theory and "best practices" don't mean much to me, personally. I live out in the real world, and in the real world, the only metric by which we measure the goodness of a tool is whether or not it helps us get crap done. C++ is a good tool because it lets us get work accomplished (mainly by virtue of its sheer inertia, but that's another matter). Malbolge is a bad tool not because it's weird, quirky, or obtuse, but because it gets in the way of doing stuff. It doesn't let us get things done.
A lot of people in the academic sphere are big on stuff like functional programming, aspect-oriented programming, and all this. I've read papers dating as far back as the early 1980s claiming that such concepts are, by necessity, central to producing good software. Yet here we are, smack in the middle of 2006, and we still write code in imperative languages like C++. Why? Because we can get stuff done in them.
However, anyone who has had even fleeting experience with those concepts understands their appeal. There's some good stuff out there. People like and use (sort of) the obscure academic languages for good, practical reasons. There are certainly gaping holes in our current toolset that are going to need to get fixed soon.
So, in the interests of being highly pragmatic, I think it's time we sat down and built a new language. This time, though, let's avoid the trap of doing what sounds good to the PL theorists, and keep a heavy emphasis on just getting crap done. At the end of the day, I really don't give a good goddamn whether I can use a higher-order function, a lexical closure, or currying. I can tell you how many times those terms have come up in the process of me trying to get stuff done: 0. I don't care about being a good PL theorist or a good academic. I want to get crap done.
The Pragmatist's Programming Language Wishlist
- The minimal level of abstraction should be highly concrete.
It is my belief that C++ (and C before it) has had success largely because it allows freedom to build software close to the hardware. Sure, both languages allow the expression of abstract concepts - C++ much moreso than C - but there are far superior languages for expressing the abstract. It is not uncommon to embed languages into applications (especially games) so that abstract logic can be done in a language more suited to such things than C++. The longevity of C++ in particular has nothing to do with its abstract expressivity - it has everything to do with its ability to be concrete and unabstract. That's why C++ remains (incorrectly) synonymous with "performance-critical code" for many programmers.
A new language must realize this, and capitalize on it. If a new tool is to have any kind of penetration and staying power in today's language market, it will have to allow programmers to work in highly concrete terms. This is critical for two reasons: first, it allows the New Language to affect many problem domains, like 3D graphics engine development, where concreteness is important. Second, it allows easier portability. If some useful subset of the language can be used without runtime dependencies (like those of Java or .Net languages), the language will have a much quicker transition to platforms other than the one it was born on. Computers have changed a lot since C++ was designed, but we still use it, because C++'s concreteness allows for portability.
- Maximize the ability to express semantics in both abstract and technical terms.
We need a combination of C++'s ability to be very precise about data storage (unsigned 32 bit integers), and the ability of any reasonable high-level language to ignore those technical details. We need a way to be very specific about the way data is handled in hardware, when such things are appropriate. (This also ties in with having a low level of minimal abstraction inherent in the language; low-level programming is impossible without technical semantic expressivity.) At the same time, productive programming demands that we be able to quit worrying about stupid problems like overflow and signedness.
We need ways to think about data types more richly than "numeric" and "string." We need a combination of dimensional analysis, flexible type definition, and rigorous storage/behavior semantics. Allowing types to be validated implicitly would be ideal. We need a language that lets us express the fact that milliseconds-numbers are not interchangeable with pixels-numbers, and so on. The use of explicit conversion functions should let us forget, for once and for all, stupid things like measurement units (inches vs. kilometres, et. al.). However, it is unacceptable to have such functionality at the expense of control over the representation of data in hardware.
I have deposited more detailed thoughts on this concept here.
- Encourage the use of nested layers of abstraction to build domain-specific "dialects" on top of the base language.
I've burbled extensively about my feelings on abstraction before, so I'll refrain from repeating those thoughts. In essence, though, what we need is a way to define a sort of "sandbox" inside the language itself. That sandbox should be highly abstract, have a well-defined interface to lower levels of abstraction, and yet be highly domain-specific. Talking across domains should be forbidden. Talking to other layers of abstraction must be forbidden.
Languages like C++ let us define layers of abstraction via things like class inheritance trees. Yet they also allow us to talk between any two layers of abstraction at will. Any code can, with sufficient pressure on the compiler, talk to any other level of abstraction in the program. This is bad because it allows violations of encapsulation and modularity. By contrast, domain-specific languages are good because they do only what they need to do, and there is literally no way to do other stuff. You can't send network packets from a LaTeX document.
However, creating a DSL for every possible domain is not really practical. Embedding languages has some potential, but it also has a cost: you have to have two distinct languages. In some cases, the binding mechanisms required for this are highly nontrivial, and can even result in a net loss of both coding productivity and runtime performence. Clearly, the solution is not to add to the proliferation of languages.
Instead, we need a language that allows us to build little dialects of functionality and domain. Enforcing abstraction and encapsulation has proven good effects. I think the implementation of this might end up looking vaguely like Java packages or .Net modules, but it needs to be approached from the ground up with the express intent of restricting inter-module interaction, rather than promoting it.
- Provide highly expressive compile-time contract support.
Design By Contract is a very good thing. In general, we need a language that lets us express contracts, in a way that is inherent in the language itself, and verified as much as possible by the compiler as well as at run-time. We need contracts on data types. We need contracts on functions. We need contracts on objects.
We need to be able to specify the exact limits and expectations for every aspect of our code, and make sure that those contracts are obeyed. One of the great benefits of functional programming is the ability to validate code at many different levels, simply by validating that a function does as expected. We can have this benefit easily in imperative-style programming provided sufficiently expressive contract definition and enforcement mechanisms.
- Provide a high degree of introspective capability.
Code should know that it is code. Code should know that it runs alongside other code. Code should be able to express concepts in terms of other code.
This is really a multi-sided issue. On the one hand, we need the ability to do things like comprehensions, wherein a data structure knows how to traverse itself. We then need the ability to tell a structure to traverse itself, and do some operation on each element, or maybe on select elements based on some discrimination criteria. However, it goes deeper. We need to be able to look at a data type and see what we can do with it (ala concepts). We need to be able to ask a function what its semantics are and what sorts of data it can operate on. We need a way to think about objects and what they can do, at run-time.
We need to escape academic fluffery and jargon. The term "currying" needs to never be seen in the language's documentation. We need to keep an emphasis, when designing introspection features, on real life uses. If an introspective feature cannot be justified with an example that immediately reveals, to a moderately experienced imperative-language programmer, the benefit of that feature, then the feature is crap and should be axed. We should prefer to piss of the academics for not using the "right terminology" in favor of not pissing off people who still have never been told why they should care about these notions.
- Escape from stupid and counterproductive conventions.
The idea that functions should only return 0 or 1 values is stupid. This is a pointless convention that makes no sense. In real-life programming, multiple-return-value functions could save a lot of time and code complexity.
The notion that objects are only "of" certain types, defined by a rigid hierarchy of inheritance, is stupid. We need a sort of fuzzy model that lets us work in the realm of concepts and capabilities. Sometimes objects are best expressed in terms that are not definable by "is-a" and "has-a."
In general, both OO and procedural programming are too weak to really work. Procedural programming doesn't scale nicely to massive code bases with complex data entities. OO doesn't work nicely when the boundaries between object types are fuzzy. Attempts at generic-OO capabilities have been sort of successful, but still are mostly ugly hacks and have plenty of drawbacks. Existing paradigms for organizing logic and data are insufficient.
Entire modes of thought that worked great in single-thread universes will cease to be useful as multiprocessing technology becomes more widespread. Dealing with synchronicity and parallelism is going to be a major responsibility for languages in the future, and a new language must understand multiprocessing concepts deeply in order to remain a viable option. However, as with other areas, it is important to avoid extremes - the language must not forget that a lot of code still makes sense in a single-thread model.
These are just the beginnings of my thoughts here, and are admittedly rather fuzzy (which is a side effect of me not having a good sleeping pattern). I welcome any other thoughts, insights, and wishlist-items.
Let's get some crap done.
| |
 A Day in the Life |
Posted - 3/24/2006 2:45:19 PM | I've been wanting to do this for quite some time, but just never really got to it. My last attempt didn't turn out so well as a journal entry, but did very nicely at helping me track my own work habits. So I'm going to give it another shot.
9:45 AM
I stumble over to my cell phone and turn off the extremely annoying alarm. This is the fourth time it's gone off this morning, and I figure it's probably time I actually woke up and got about doing something useful. Of course, I went to bed at 5:30 AM, so I feel more than little justified in being groggy - but work calls, and I really need to take care of writing some emails.
10:09 AM
Quick morning troll of my email inbox, GDNet, and digg. I then hop onto Skype and the VPN to get ready for work. My IDE is already open (it rarely closes anymore) as well as the project wiki.
Soup of the day is to finish up specifications documentation for a new cutscene definition and management system, which includes both the data format and a comprehensive internal API. I have most of it planned out in my head, but need to get that on paper - this system is going to be a central part of many of our plans for the projects to come.
10:22 AM
Just had to send a quick status email to the rest of the team. We're trying to arrange a conference over Skype, which is actually fairly difficult when you're spread across three continents and a dozen time zones.
10:53 AM
Several areas have been specified and fleshed out. About 60% of the system still needs to be specified. Time for a quick break. I'm feeling my lack of sleep very acutely at the moment, and I know from harsh experience that the best way to keep myself awake is to consume a steady diet of complex carbs and protein all day. Not the healthiest thing in the world, but I'll make up for it when I go running tomorrow.
11:31 AM
Down to about 30% of the specifications remaining. One part is already specified, but in another mode of thought; I need to translate the concepts from those notes into a proper data-format and logic spec. The final chunk is something of an unknown, and the actual details will depend a lot on another bit of work being done by someone else. We will need to discuss that in detail to produce the final spec, so I don't have much to do at this particular time in order to be "done" with it for now. In any case, it's time for lunch.
12:13 PM
My nephew just told me to "keep your pants up" in a very cheery tone, as if he was saying "see you later" or something. Absolutely hilarious. But back to the microwaved pizza and random web surfing.
12:33 PM
OK, time to crack open a Bawls and get back to work. I'm really starting to feel fuzzy around the edges of my brain, which is a bad sign, but I've got practice with this so I'm sure I'll make it.
1:00 PM
Right, I mean it this time. That session of Crimsonland was for... uh... research. Time for a little Anontin Dvorak and some quality time with a sheet of blank paper.
1:27 PM
Down to the last straggler of unspecified functionality. Every aspect of the cutscene description system is now specced out, except for the actual stuff that will be displayed. Believe it or not, that's actually the simplest aspect of the system! Really the only complication is that cutscenes can either show "real" locations that are actually being simulated by the game engine, or totally fabricated situations. The ways of controlling these two alternatives are what I need to specify. The brain-fuzz is thick, though, so it's time for another short breather.
1:47 PM
After catching up on the GDC coverage, it's time to find some more music and finish up this spec.
2:19 PM
Whew... done! Well, sort of. There's still quite a few areas that need to be discussed with the rest of the team, and then the entire spec needs to be reviewed and approved (particularly by the art team) before we're ready to move on to code work. My next task is to run through the current documentation wiki pages and compile a list of the "To Do" notes that are scattered throughout. That will give us a rough agenda for the upcoming (and still unarranged) meeting on the whole subject.
2:40 PM
I've put together a list of everything that still needs work - it's pretty short and depends primarily on input from the art team as to what sorts of visual effects they want. With only one exception (transitions between shots in a cutscene) there is nothing that might affect the data structure at all, so it should be safe to begin working on the basics of the data format schema, and other such fun stuff.
In any case, at this point, I've done all I can for now; the entire thing needs review by the rest of the team, and seeing as it is currently 8:40 PM for them, chances are it will take a little while to get done. The sleepiness has taken a serious toll, so I'm going to go relax for a while and perhaps sleep a bit until my flatmate gets home from work. After that we'll have some Friday Night Shenanigans.
Can't stay up too late, though - I'm painfully behind on sleep, and my nephew has his first soccer game tomorrow morning.
So there you have it: a day (well, part of one) in the life of a game developer. Truly gripping drama, no?
I have no idea if this will be even remotely interesting to anyone else, but I'm finding it a very useful way to keep a sort of high-level, one-step-back overview of what I'm doing. It's also a great guilt tool for making sure I don't slack off too much. I'm definitely going to try to continue to do these, although unless someone thinks they're worth reading I won't bother making coherent sentences and posting them here.
And now to bed, and now to bed.
| |
 Assorted Thoughts |
Posted - 3/24/2006 4:17:59 AM | It's difficult to admit, but at the moment, the thought that weighs most heavily on my mind is that johnhattan needs to hurry the hell up and release a full version of ConFusebox. I am sickeningly, utterly addicted to that game, in a way that I've never felt drawn to a spin-the-pipes puzzle before. I almost feel dirty... but then I realize that this feeling is not true remorse, nor guilt, but merely the refusal of society at large to acknowledge the beauty of our lov--- wow, that got out of hand quickly. Moving along...
Motivation is a weird beast. I do my work over the Internet (a VPN/intranet setup, to be precise), from home, essentially unsupervised. Sure, I make regular status updates emails; sure, anyone can look at my checkin log in the source repository; sure, my documentation edits on the wiki are easy enough to track.
On a macro scale, getting work done isn't really a problem. The problem is more of a micro-scale thing: finish specifying that module, or read some more Children of Dune. Proofread that paragraph and commit it to the database, or play Battlefield 2. Finish the code plans for the feature set I'm supposed to be building, or take a 9 hour nap.
The trick is, those little things add up. It's not like I haven't done any work in the past two months... I just haven't done as much as I know I'm capable of. I mean, sure, relaxing and having a life is important and all - but there's a difference between having a life and having nothing but life and not doing anything useful. I'm not hitting potential, and that bugs me.
I'll figure out what to do about it as soon as I finish the final chapter of Crimsonland on Hardcore.
The weather here sucks. It was really nice most of last week, and now it's all rainy and cold again. My tropically-spoiled blood craves temperatures in excess of 80 degrees, and the bastard planet won't cooperate.
It really sucks realizing that there will never be enough time to do everything you want to do.
| |
 Whee, hornet's nests are fun! |
Posted - 3/21/2006 4:21:16 AM | Apparently, I've touched on a rather controversial nerve. Not unexpected, really - piracy and anti-piracy is a very hot debate, and will likely continue to be so for quite some time.
Given a few days to re-gather my own thoughts, and consider some of the great comments from my last rant, I've decided that I'm not done yet. It's not so much that I have more of the same to say; more precisely, I have a clearer idea of what I wanted to say in the first place, and that's been focused in part by some of the feedback I got last time around.
I'm a big fan of thinking iteratively: try something, see how well it works out as a thought process, get some alternative options; keep what works, chuck the rest, and try it again. So in that spirit, here's "Piracy Redux." I have another interest to serve, namely the interest that it's 4 AM and I'm kind of tired, so I'll drop this into a bullet-point format for convenience and brevity. (Heh, me being succint. Yeah right.)
- I'm just venting here. I don't honestly believe I have a solution - yet.
I've brought most of this up just to lament. It's self-indulgent, angsty, and more than a bit frivolous. But it's my opinion, and I feel like getting it out into the open. I don't pretend to know how to resolve this situation, although I'd like to believe that a solution exists, and I'd definitely love to be a part of the solution if one ever becomes apparent. For now, though, I'm not looking to lay blame, assign targets, draw lines in the sand, or rally the troops for the final battle - I'm just bitching 
Rightly or not, I feel like an innocent victim here. I feel like a kid who just wanted to go out and play Frisbee, and accidentally found a land mine. I shouldn't have to get caught up in this at all. Yeah, complaining about it is rather pointless, but I still feel like I should get to say my piece.
- I absolutely support the customer's right to avoid crappy copy protection.
Heck, as far as I'm concerned, the consumer doesn't get near enough respect these days. The DRM craze is just plain idiotic at this stage. Game copy protection is, if anything, even worse. The Sony music-CD rootkit fiasco was old hat to those of us who have been dealing with the likes of StarForce for years already in the PC gaming realm.
When I complain about consumers excercising their rights, I don't mean to suggest that they shouldn't be allowed to boycott or even avoid that which they find distasteful. Avoiding things we don't like and don't agree with is a fundamental freedom that I fully support. However, I think it is important that, in all things, we understand the consequences of that avoidance.
Say I dislike the fact that I cannot fly, and thus choose to avoid the reality of gravity. It's an extreme analogy, to be sure, but that's the point - ignoring gravity is not going to let me fly, it's going to make me a grease spot on the sidewalk.
Boycotting evil copy-protection systems is not just going to change the copy-protection arena. It's going to encourage these companies to produce ever more restrictive systems - the arms-race escalation I mentioned before. More importantly, it's going to cause collateral damage.
- Yes, it's the publisher's fault. No, that doesn't mean I can fix it.
At my place of employment, we develop a niche game. We're all acutely aware of that fact. Sometimes we've had to settle for suboptimal publishing deals just because that's the only way we can get anything published at all. Changing publishers is not really an option; getting the ones we have was hard enough. Anyone with real experience trying to publish a niche game knows the realities of this. We either accept publishers with controversial and arguably "poor" choices in copy-protection, or we work at McDonald's. Considering that I haven't spent 90% of my life dreaming about flipping burgers, the only real option here is Door Number One.
I don't speak much for groups like Stardock that can manage to wrangle CP-free publishing arrangements. I speak for those of us (in the minority as we may be) that don't have the luxury of telling our publishers they're making bad decisions. As much as I wish it could be different, that's the reality of the situation, and that's part of what makes this so annoying.
Publishers are, by and large, ignorant of or unwilling to face the fact that bad copy-protection costs sales. The only reason such systems are used at all is because publishers still believe they help sales in the long run by preventing piracy. For niche games, this is just plain moronic. The number of sales lost to piracy will never, by sheer virtue of the game's obscure nature, outweigh the sales lost to savvy consumers who are avoiding bad copy protection.
Net result: we, the small-time game developer, lose. We become collateral damage. We have no bargaining power: our niche game is a small part of the publisher's own bottom line, and losing us over a copy-protection fight only kills us, not them. We have none of this supposed leverage to force a change.
- Changing the publishers is not easy, and never will be.
First and most importantly, there's a little thing called a contract. Leaving a contract agreement with a publisher is a Huge Deal, and has drastic financial consequences. So in a lot of cases, it isn't that there's no alternative publisher out there - it's that we literally can't change at this point. But there's also more than just that to consider.
It's a pretty well-documented phenomenon that people will go to great things to bend reality to fit what they want to believe. Let's look at this from the publisher's perspective:
- I want to make money selling games
- Piracy undercuts sales
- I can invest a lot of money into anti-piracy systems
If sales go down, I'm going to think of it in a certain way. I don't want to believe that I made a dumb decision; in all likelihood, I believe that copy protection was a good decision. So if sales go down, I am naturally left to one of two conclusions: either the game sucks, or piracy is still running wild. If I conclude the second, I'll probably go looking for stronger copy protection - and you better believe that the CP industry is just going to love that. They're going to want to encourage that conclusion in my mind, because it means I buy more CP software.
I don't want to paint publishers as The Evil Empire here. I appreciate the real necessity of the publishing industry. Hell, one of our publishing partners is absolutely superb in what they've done for us as a small-name niche group. I don't believe that publishers are unintelligent, foolish, or naive. They just see things differently, and that's natural - that's a side effect of the business they are in.
Put yourself in the publisher's shoes: you've made a huge investment into supporting Copy Protection Scheme Foo. Now your customers and developers tell you it sucks. Are you going to sacrifice your credibility by renouncing Scheme Foo? (Yes, I know that 99% of us would love it for Foo to go away. That's not the point. The publishers do not see it that way, and fairly so.) You don't want to give up copy protection in general - your numbers seem to show that it helps sales overall - so what else do you turn to? Say Scheme Baz exists, but Baz sucks much harder than Foo, and is cracked five thousand times faster. Does it even remotely make business sense to use Baz over Foo? Not on paper, no.
You have to remember that publishing is a business, too. They've got their numbers and figures, and it's going to take a lot more than "people think you suck because you use Scheme Foo" to get them to see things differently. Actually, a few people in the publishing biz already see it that way - but lack the clout to do anything, either.
Change is not easy. Big change is especially hard. There is a lot of inertia to fight here, and historically, you don't beat corporate inertia by steering the boat. You blow the boat up and build a new one, and hope it sails in the right direction.
Want to know why GalCivII is such a big deal? Because breaking the publisher's iron grip on the business is not that easy. I think GalCivII is a ray of hope that the publisher can eventually be put back in their rightful place (as an enabler of creative media rather than a controller), but that happy time has not yet come. And not all of us are capable of wielding the weapons that it will take to accomplish that victory.
Yes, the cycle can be broken. Yes, there is hope. I just don't want to lose my dream job because my home town got pillaged by the raging armies.
| |
 And now, back to your regularly scheduled ranting. |
Posted - 3/16/2006 5:14:10 PM | For those who are getting linked here from who knows where - please read the follow-up post after this one. It makes things much more clear I think.
I've been reading up on the StarForce/Galactic Civilization II scandal this afternoon. I find the whole thing disgusting on several fronts. First and foremost, what StarForce did is obviously reprehensible and someone deserves to bleed (as in literal physical blood) for that kind of scummy behavior.
However, the more important issue here is that these calls for StarForce boycotts need to stop.
Now, lest I give the wrong impression, let me be clear about why this bugs me: as I read through dozens of pages of blogs, blog comments, news articles (to use the term loosely), and various forum postings, I see a lot of mention of boycotting StarForce and StarForce-protected games. One of the games that comes up quite often is X3. I literally can no longer count the number of people I've seen claiming to have not bought games like X3 simply because of StarForce's involvement. So, up-front, let me be perfectly clear that I'm pissed about this because it affects me, personally.
So I hope you understand me perfectly when I say that that kind of attitude is only slightly less scummy than StarForce's. That's a strong statement for me to make, so let me explain my position.
Most boycott activists whine about StarForce supposedly being invasive, incompatible, unstable, and so on. That was true - at one point in time. However, the current generation of their software is vastly improved from what it once was. It properly cleans up after itself (in most cases), does not have severe effects on performance (I've run protected and unprotected builds of X3 side by side, with a negligible difference in performance, and only a slight increase in load times), is far more compatible (based on technical support queries in the Egosoft forums), and I've yet to see any evidence whatsoever that the current generation is unstable.
The bottom line is that, in the current generation, there's vanishingly little reason to "hate" StarForce except on a purely philosophical level. I'm a professional game developer, for Bob's sake, and I hate the notion of copy protection. But I also realize that it is, more or less, a necessary evil these days.
The boycotters seem to believe that, by not buying protected games, they directly "injure" the protection companies like StarForce. It doesn't take much common sense to figure out that this is entirely ludicrous. They still get a very healthy cut. They're probably going to use reduced sales as "proof" of piracy, not as evidence that people hate their protection schemes. And they're certainly not going to shut themselves down and go out of business just because some people don't think they should exist. Wake up and join reality, folks - boycott activism rarely makes a real, positive difference.
It does make a real, negative difference, though. The most dangerous are the people who buy the games, and then crack them to bypass the protection schemes. I won't argue whether or not it is "acceptable" for someone to do this - but it is an idiotic behavior. It seems unfashionable in this day and age to consider the consequences of one's actions. Most of these "legit crackers" are serving only to escalate an arms race. Sure, the pirates themselves contribute to the escalation, but it would go a lot slower if the users would quit using cracks.
Arguably, at this point, it's too late. The activists have created a self-fulfilling prophecy. "I crack this game because protection schemes are too invasive." So the companies have to go and create more invasive, more "effective" schemes to retaliate. Can't you guys see you're digging your own graves deeper here?
All that is gravy, though. What really bugs me is how short-sighted and ignorant most of the activists are. At Egosoft, we use StarForce primarily at our publishers' insistence. Anyone with even passing familiarity with the game industry knows that publishers hold the power. We sell a niche game, one that struggles to even get shelf space next to more "famous" and money-laden publishers - even when their games are bilge. We had to fight hard to get a publishing deal at all. We either make some concessions to sell the game, or we don't sell it at all.
Most importantly, though, is what the hot-headed, ignorant, short-sighted boycott weenies do to sales. Every time you refuse to buy a game, you're not hurting StarForce. StarForce is going to make a boatload of money no matter what you do. You would literally have to boycott the entire games industry into nonexistence, and rebuild the entire industry from the ground up, to get them to go away - and you know what? Another one is just going to spring up to take their place. It's stupid - patently moronic - to believe that a boycott movement will ever really change things for the better.
You're not hurting StarForce. You're hurting the game developers. You're hurting us, on our small and relatively unknown team. Suppose the anti-StarForce mob successfully "prevents," say, 10,000 sales of X3. The publishers then compare us to other titles, which (maybe on merit, and maybe just on publicity) have sold better. Guess whose contract gets the axe? Guess who still sells copy protection by the boatload, blissfully unaffected? Guess who really goes out of business?
You may think you're pissing all over The Evil Greedy Corporations, but they're smarter than you are. They know how to duck. You're not getting your urine all over them, you're hosing us.
This lunacy isn't fixing the problem of rampant, excessive copy-protection. It's killing the small guys, the underdogs. Your religious fanatical war is slaughtering innocent bystanders by the millions while the real enemy laughs at you from inside their impenetrable bunkers - and just sits back and escalates the carnage still further when you refuse to back down.
The whole issue of piracy really comes down to respecting developers enough to support them for making a game. Yes, there are peripheral issues and other things that get lumped under the same banner, but that's really what it's all about, in the end. And yet people have gone so far that they're missing the forest for the trees. You may claim, on the surface, to be fighting for the rights of developers and consumers to live in a world free of ridiculous copy-protection schemes.
But when it all adds up, you're screwing the developers, too - and maybe even contributing to the death of the small-time studios out there. You're not even making the consumer's side of things better, either, because it just sparks an escalation that shows no signs of slowing down.
All of this craziness is supposed to keep pirates from destroying the creators of legitimate works like games. But, in the end, I don't think pirates are anywhere near as much of a threat as the supposedly upstanding consumers that are fuelling this war.
| |
| Wednesday, March 15, 2006 |
 Gives us the happy juice! |
Posted - 3/15/2006 1:58:10 PM | I'm officially addicted to this.
Today I've moved up from a single quad to a vertex buffer and index buffer, generating a flat mesh of several quads. The idea is to eventually turn this into a heightmapping system of sorts. Step one of course is to actually generate the mesh data.
I got the mesh generation working pretty quickly with the help of some Google and a little elbow-grease. I think that having a fairly comprehensive amount of experience thinking in 3D coordinate systems (from the Freon project) is making this a lot easier to go through. Despite the fact that I've barely touched polygon rasterization engines since I wrote my own software rasterizer 6 years ago, a lot of things are familiar and make a lot of sense.
The main thing I'm having trouble wrapping my head around at the moment is how I'm going to structure the code so that I can acheive optimal batching to the video hardware. I'm aware of all the tricks like texture baking (so multiple surfaces can be textured with a single SetTexture() call) and all that, but I've yet to really grok how to make my code do all this elegantly. This is of course made slightly more complex by the fact that I'm trying to learn C#'s design paradigms at the same time.
Once that's all sorted in my brain, I still have to find out how programmable shaders fit into all this mess. Incidentally, if anyone knows of a good online site that explains how all the modern pipeline stuff works at a reasonably abstract level, I'd much appreciate a link.
Needless to say, I'm finding all of this ridiculously fun 
Anyways, once I got the mesh generated, I wanted to confirm that it was working. A little bit of Google turned up the ever-handy FillMode flag, so I swapped the renderer over to wireframe mode. That, however, renders the edges of each polygon textured, which I wasn't wanting - I wanted to see nice white lines. So a little bit of playing around with IntelliSense turned up the appropriate flags, and I figured out how to render solid white wireframe overlays on top of the actual textured surface.
The actual technique is pretty stupid, as it basically brute-force renders the entire scene twice, but IMHO it's not bad for a DX newbie 
I absolutely love Managed DirectX, though. The code boils down to basically this:
dev.RenderState.FillMode = FillMode.Solid;
dev.TextureState[0].ColorOperation = TextureOperation.SelectArg1;
dev.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
geo.Render();
dev.RenderState.FillMode = FillMode.WireFrame;
dev.TextureState[0].ColorOperation = TextureOperation.SelectArg1;
dev.TextureState[0].ColorArgument1 = TextureArgument.Constant;
dev.TextureState[0].ConstantColorValue = 0xffffff;
geo.Render();
So much more readable and sensible than the C++ bindings. It's borderline orgasmic. Anyways, here's the rendered result:

So far it's just a blob of polygons on a flat plane; my next project is to build in proper world and camera transforms so I can look at this from a more isometric-style angle and show the effects of the heightfield. Woot.
| |
 I'm a very, very bad person. |
Posted - 3/14/2006 4:21:46 PM | Well, I've gone and put my foot in it, big time.
I just couldn't bring myself to go back to work, so after some procrastination of a more mundane variety, I ported the C++ version of Habanero over to C#. It isn't very clean code yet - most of it is just one experimental hack after another - but I've successfully gotten a textured quad rendering again. Yayy!
That took about 2 hours, down sharply (urgh, no pun intended) from the C++ attempt. This language rocks.

So there you have it. Now I really need to get some real work done 
| |
 Learning C#. Whee. |
Posted - 3/14/2006 1:59:03 PM | This afternoon I got back from Quiznos and decided to slack off for a bit before going back to work. (On a totally unrelated note, walking a 3 mile round trip and getting a sandwich out of the deal is absolutely awesome. Do it often if you at all possibly can.)
So about 1:25 I decided to have a shot at this whole C#/Habanero thing. Got to start somewhere, right? So I fire up my trusty Visual Studio 2005 and create a new Windows project in C#.
The first thing I notice is that the IDE has created a form for me. This is familiar from my glory days doing applications programming in VB. They still call the thing "Form1" for no apparently good reason, which has bugged me all the way back to VB3. I swear, VC++'s wizard is so much nicer: it asks you what you want to call your classes. Why they've never done that in VB, and now C#, is totally beyond me.
Anyways, that's just an idle curiosity, and easy to get past. I blow away the form since I'll want to dynamically create my render windows on the fly. If I need prefab forms later for config UI and such, I'll build them - but for now I'm going with pure code.
Goal #1: Get a message box on the screen
I figure this is a good place to start: really trivial, but probably different enough from the stuff I'm used to to provide a learning experience. Sure enough, I fumble around for about 10 minutes trying different magic incantations involving System.Windows.Form.MessageBox. I try treating a MessageBox as an object and statically allocating one. I try dynamically allocating one. For kicks I poke around in IntelliSense for a second and fail to find what I'm after.
Finally I break down and just Google "C# messagebox" and wham, there's the answer: MessageBox.Show(). Duhh. I guess this .Net stuff is going to be more of a mental paradigm shift than I thought 
So, drawing on my highly limited and utterly broken Spanish, I proudly accomplish Goal #1:

Current time: 1:39 PM. Yayy.
Goal #2: Get a dynamic window displayed
This is my second big test. Judging from experience with C and C++, this is probably going to take a while, so I mentally steel myself for going back to work as soon as I'm done on this phase.
When I tore out the prefab form from my new project's code, I noticed the Application.Run() call, which apparently is .Net's ready-made message pump loop. It can take an object of type System.Windows.Forms.Form. So I poke things a little bit, slap together some code, and produce this:
Form foo;
foo = new Form();
foo.Text = "Habanero";
foo.SetBounds(0, 0, 225, 150, BoundsSpecified.Size);
Application.Run(foo);
It takes a few seconds of juggling IntelliSense to figure out the correct parameters, but this time I get by without needing to touch Google or even MSDN. It literally takes more time to write this paragraph documenting my attempt than it took to write the code.

Current time: 1:51 PM.
Hot damn... now that's what I call rapid development. I think me and C# are going to get along very nicely.
This brings back my (very happy) memories of whipping up GUI tools in a matter of minutes in VB, back in the day. In fact, I still use VB fairly regularly to do quickie tools, like one-off file parsing/mangling utilities. It's a great thing to have in the toolkit, and I find the visual GUI design tools more than justify the fact that it's VB and not, say, Python. I've still got a very soft spot in my heart for VB; even though it supposedly teaches all these bad programming habits, my opinion is that bad programming is the fault of the programmer, not the language. I've seen some truly elegant and beautiful code produced in VB - although, admittedly, not very much.
C# though... I sort of feel like a dirty tramp for even saying this, but I think it's going to replace VB (even VB.Net) as my personal RAD tool of choice. The syntax very closely resembles the C++ and KC code I spend my time thinking in, and I'm not smart enough to deal with massive syntax shifts on a regular basis. When I do use VB or other languages I find my muscle memory putting semicolons and curly braces all over the place, which naturally causes some havoc.
C# also has delegates, which are just plain hot. I can already see entire aspects of my planned engine structure getting reduced to extremely simple, clean pieces of code by the mere power of delegates. I wrote a 500-line hacked imitation of delegate behavior for a customized callback system in C++ for the last Habanero attempt; it used multiple inheritance to do its work. With delegates I get all that power, plus more, without any code overhead of my own. I also get anonymous delegates, which make me want to jump around and giggle like a schoolgirl on crack.
So there we go... 35 minutes and I've finished a passable dynamic window dummy program, and written a journal entry about it. If I had any doubts before about this decision, they've been totally blown away.
This is going to be a whole heck of a lot of fun.
| |
 I am Stupid. |
Posted - 3/12/2006 12:57:03 PM | Well, I feel dumb. I just finally made a really simple mental connection that I wish I'd figured out a long time ago.
Several months ago I made an entry here about my Habanero project, one of the dreaded Game Engine Projects that I was intending to use to develop some game concepts that have been rolling around in my mind for a while. I've barely even touched the project since, largely because of time, and largely because of energy: when I have free time, I rarely have the energy to do programming work. When I have the energy, I'm sort of obligated (by means of the fact that I get paid) to spend that energy doing programming for my employer. So I've been trying to figure out a way to continue work on this project, and maybe explore some of my half-formed thoughts on domain-specific languages, within the constraints of time that I've got.
The whole point of Habanero originally was to let me do games without doing all the stupid mundane programming first. I wanted to explore some concepts and do some experimentation with game content, but I needed a framework to do it in. That's sort of an impossible goal given that I have to do a lot of programming to get the framework in the first place.
Another thing I want to do is learn C#. It's time I started picking up a new language. .Net is a great candidate because (as I think most people can see) it's going to continue to become a major player over the next few years.
Of all the .Net languages available, I'm leaning towards C# for a few reasons. First and foremost is syntax: I have a cozy love affair with curly braces, and I'll be damned if I'll be unfaithful to them with the likes of VB.Net or Python. Secondly, C# has anonymous delegates, which I've basically been wishing for very deeply for many years. (In fact, I'm strongly considering proposing that we integrate anonymous delegates into our KC scripting language at Egosoft - they're that awesome. They're juicy and powerful, like Lisp macros, except without all the icky Lisp to get in the way of the coolness.)
Unfortunately C# is not at all suited to what I'm doing right now (i.e. working with a large, established codebase) so the only time I could start picking it up is when doing rapid utilities and tools. However, the point of rapid tools is to get them done fast, which I can do faster in languages I already know.
Usually, when thinking about one or both of these wishlist items, I'd give up in defeat. I don't have time to do either one, let alone both, and I can't decide which one to go for. Laziness then wins the battle by suggesting I quit thinking about all this crap and go to the go-kart place instead.
At this point, you've probably all made the connection that I just now - after months of consideration - have made myself.
Yeah, that's right: write Habanero in C#. Duhhhh.
| |
 Hey, look! I'm actually talking about games! |
Posted - 3/9/2006 10:03:21 PM | On Conceptual Integrity
I've mentioned before how our team at Egosoft works. Basically, ideas and feedback are gathered from the community, filtered by a group of volunteers, then examined by the core team and merged with our own internal plans and concepts where appropriate. All of this is then passed on to a couple of people who basically act as the design leads, who then refine things and add some constraints to make them fit into the spirit and feel of the game. The concept is then handed back to the dev team for implementation, with certain amounts of freedom and room for interpretation.
This model is great, and works very well with the sort of evolutionary-sequel chain of games that we do. However, historically, we've had a minor discrepancy between the theory and the actual practice. In a few cases, too much leeway is given during development, and the result is that things implemented by one subteam feel and work totally different from things in another area of the game. In short, there is not enough control on the conceptual integrity of some aspects of the game - like missions, for example.
Part of the large-scale "fix our practices" initiative that has been going on involves addressing this problem. Traditionally, the inconsistencies have arisen because of poor documentation and communication between subteams; documentation is often left until after code is done, at which point it is too time-expensive to go back and rewrite it all just for consistency. Since subteams work independently for the most part, it can be a long time before two areas are integrated into a playable game build, so these discrepancies fester and are very hard to correct.
The biggest weapon we have to combat this problem is a wiki system (specifically Atlassian's Confluence package). This has so far been a tremendous success, and shows signs of making some major headway in the campaign for better practices. The policy now is that all new features and gameplay changes/improvements/enhancements/etc. must be documented and approved before code starts. By making this an explicit and strictly enforced rule, we make sure that there is always a chance to check things for consistency before the code is done and it is too late.
The net result is that we've already caught several misconceptions, fuzzy and vague bits of documentation, and outright inconsistent ideas - all before any code is written. The subteam model will still be in place, but for the first time in a long time there is an easy way to control the conceptual integrity of the project. In The Old Days, the leads could do this easily, because the team was small and basically all in the same office. As we've expanded to a three continent operation, this has stopped being practical, and communication and coordination between everyone is paramount. There are very real difficulties in doing design when you are not physically next to your coworkers, but I think we're doing a good job of addressing those problems this time around.
I'll probably have some more thoughts on the matter as time goes by and we begin seeing the real long-term consequences of some of these changes. So far, though, I think we have a very bright future ahead.
What I've Been Doing Lately
Part of this new pre-documentation kick involves finding people and subteams to actually take responsibility for different features, and work on the documentation. I've gotten paired up with a couple of interesting tasks, which mostly relate to prior work I've done on the games (missions, and user interface).
The first main goal is to unify the mission UI into a sort of "things I need to do" list. Basically, the idea is to make a kind of mini-PDA for the player, where they can track jobs they're getting paid for, help that people have asked for (distress calls, favors, save-the-universe type stuff, etc.), and even their own personal plans and ambitions. My concept right now is to build this as a sort of email-style arrangement (which fits the mail-message concept already established in the game) where you have an inbox showing subject/summary lines, and can open messages for detailed info.
This all is pretty simple, though (aside from actually designing the UI itself), so I've got another task. Previously all of our cutscene data has been modelled beforehand and then imported for realtime playback. This causes all manner of data format and viewing angle/resolution problems, on top of the more obvious and severe problem of requiring all cutscenes to be built by hand. We have some plans for making short-and-sweet animated sequences start to play a much bigger role in the player's interactions with the game world; I can't say more just yet, but it does have some interesting implications.
Clearly we can't do this if we still have to build and test every animation by hand, so the idea is to build a sort of library that generates animation data (keyframes, motion paths, etc.) dynamically, given some basic specs. For instance, you could say "give me a scene that shows 3 fighter ships attacking a freighter in the Blooblargh Sector," and bamf, there you have a dynamic scene. Throw in some random elements and a little magic, and it looks like a real "video feed" of stuff happening in the game universe.
This will require a lot of subtle gimmickery to make things look smooth and natural, but the bonus is that the gimmickery only has to be coded once; after it's implemented, all scenes automatically benefit, rather than having to tune them all by hand.
Actually figuring out how to generate these scenes is going the be the real technical challenge, and that's my current task. First step is to lay out all of the requirements: I have a wishlist of things from the art team that they want to be able to do, and I've got to make this jive with the overall technical side of things. Most importantly, we have another programmer who will be in charge of making a data format for serializing these scene descriptions, so I'll have to give him an API that he can easily use to convert data to actual animations.
Should be fun 
| |
 Happiness |
Posted - 3/8/2006 3:19:02 PM | Today is a good day for my auditory senses.
First, I took delivery of a shiny new pair of Altec Lansing AHP712i active noise-cancelling headphones. They're not exactly hardcore-audiophile equipment, but for the price ($80) they're definitely worth it. The noise cancellation doesn't catch loud or sharp noises, but it does amazing things to the ambient background noise in my flat (computer fans, central air, etc.) and with some good music going, it creates an absolutely exquisite listening "zone." Combined with the superb comfort of the headphones themselves, this is like a card for "go directly to an ideal thinking environment, do not pass Go, but collect $200 anyways."
Now, this in and of itself is enough to make me a very happy person. Music is a core part of my preferred thinking/working setup. The step up from my cheap no-name knockoff headphones to the Altec Lansings is a hefty one, which makes the music that much better, and the work therefore more enjoyable by extension. All that goodness, though, misses one important area: making loud noises.
Headphones are great, see, for certain things. Like listening to thinking music while working in a high-intensity situation that requires a lot of brain power. However, they have disadvantages - like being stuck to your head, and generally not being powerful enough to shake the floor. They're also slightly inconvenient to share with one's flatmate when trying to watch, say, a nice violent movie.
The solution to this, of course, is speakers. However, as I've lamented before, the amplifier for my 5.1 speakers died several months back. In its stead I've been using my flatmate's weak (but passable) Sharp bookcase stereo system, which does the job in terms of making noise that the whole room can hear, but sort of falls flat in the more subjective and trifling areas like not sounding like a dead cat in a tin can. The bass, in particular, leaves quite a lot to be desired. It's roughly comparable to eating handfuls of sand after one has been raised on veal and caesar salad; you can still get some of the essential vitamins and minerals, but it just isn't a pleasant experience.
To rectify this, I broke down and dropped the cash to replace my amp. I did this by actually buying a complete new 5.1 system at a steep discount, which brought it right into the range I paid for my current (used) system off of eBay. Net result: one shiny, shrinkwrapped new Klipsch ProMedia Ultra 5.1 set. This time, since I'm the original owner, I have a warranty that says I get a free replacement should (God himself forbid) anything go wrong.
So now, in addition to my nice little envelope of listening bliss that is my new headphone set, I have again a working 5.1 system, plus the working satellite speakers and subwoofers from the old system (less the amp). The extra speakers and subs aren't actually useful without the amp, but at least I have them, dammit, and that counts for something.
Tonight there shall be celebration, and it shall be loud. And with lots of bass. Crisp, deep, smooth, rich bass, with creamy bass filling, and a bass glaze. Garnished with bass.
| |
 Inventing Destiny |
Posted - 3/5/2006 4:20:12 AM | I aspire to greatness.
For as long as I can remember, I've had a sort of thread running in the CPU of my brain, monitoring my activities and recording things the way one might assemble a documentary. Sometimes this thread focuses on the mundane: "Here we see a sickly-looking specimen of Apoch brushing his teeth." Every now and then it gets presumptuous and starts interviewing other parts of my mind, constructing entire timelines of my life, and all the grand things I imagine I might do. It's a sort of biographer, talking to the future me at the end of my time, discussing all that happened and what I think about it - except that none of it has happened yet.
Maybe none of it ever will.
I imagine that many people have aspirations of greatness. It seems a deeply vital part of human society for someone to want to reach beyond, to look at what might be, and to make it so. These are the people that brought us fire, iron tools, and the Internet. These are the people that move us from a grunting herd of barbaric animals into a realm of suits, ties, and power lunches. These are the people who are history.
The term "youthful idealism" is not foreign to me. I think I have a particularly large dose of it, at least by comparison to many of my peers. I'm the annoying guy that always walks into a room and finds five things that could be done better. I'm the one that talks all that boring, level-headed nonsense about planning for the future while everyone else is having a grand old time getting drunk at the party of the week. I literally devote more of my time to figuring out the long-term career effects of my sleeping habits than figuring out what to eat, what to wear, and what to do on Friday night. Hell, on Friday nights I usually read a book.
Aspirations are not really great conversation pieces. They don't make one interesting at parties. Sometimes it seems like aspirations don't do a whole lot besides get in the way and waste a lot of time that could be spent doing stuff. And yet they stubbornly hang on, refusing to submit to the cold realities of practical daily life.
How is it, then, that one can aspire for so long, and wake up to discover that only aspiration has happened, and no accomplishment? How is it that this awakening can occur on a regular basis, even daily, and yet the problem is never cured? These aspirations are grand. These are the sorts of dreams that form history, change the world, utterly reshape the way people think of life. Very few people are priviledged with playing such a role, and yet I seem to expect no less of myself.
Some might talk of destiny, of things meant to be, of what a life should involve. These things hold no answers. It is foolish to spend a lifetime thinking intently on what is meant to be, and then slip off into the sleep of death with the sad realization that it never was. What could be a worse torment, than to aspire for so long, and fail to do?
Maybe some things are meant to be. I do not see nearly enough of the flow of reality to answer that question. But I do know that there is more than just meant to be, more than daydreams and aspirations and Time articles in the imagination. The true shapers of things did not merely aspire; indeed, many aspire, and yet never accomplish. To cross over into the realm of real deeds requires much more than mere vision, mere ambition, mere desire. Action is not a simple thought, nor an easy successor to careful planning.
I have no lack of aspiration. Some might even call it egomania, a narcissistic self-obsession, an arrogance. They may be right. I do not fear either lack or excess of ambition; for my purposes, I have the sufficient quantity, and that is comfort enough. I am not concerned with "failure" as it might be called; to aspire, and strive, and yet not meet the expectations of one's dream. Expectations are easy to inflate; reality is not so willing. To simply fall short of expectation is no failure, no loss, no shame. I fear none of this; it does not cost me sleep, nor haunt my thoughts.
I fear only that I may lack that unnamed quantity which moves a person to attempt any action at all. To dream, and be consumed by a dream, and then awaken - this is a harsh shock, a jolt of pain that lingers and aches. I fear awakening from the dreams of my life to find that they never came to be.
| |
 Games... and cars... and STUFF! |
Posted - 3/2/2006 6:10:00 PM | So yesterday I bought a black 2003 Taurus. Not the sexiest ride in the world, but it works, and it's a lot more fun to drive than a Buick. Dropping $13,000 in a single chunk is a bit surreal, but it was fun.
I got the car from CarMax, and the buying experience was great. This is a very good thing, because I've been feeling like total crap for the last three days, and if I'd had any problems buying the car, I would have shot someone. Or maybe just hacked up a lung all over them and given them a communicable disease. (I came close to doing that second one anyways.)
We're nearing the tail end of code cleanup work at Egosoft. Today I went through the script codebase and did a massive file reorganization, basically moving stuff into more sensible directory hierarchies and that sort of thing. There's a few more modules to clean up, and a lot of documentation to write, but for the most part the end is in sight. Later tonight I'll be finishing up some of the less drastic refactoring tweaks, and probably starting on the team's "Official Good Practices" manual, which is currently sorely out of date.
| |
In locus hic, omnes res dementes sunt.
|
| S | M | T | W | T | F | S | | | | 1 | | 3 | 4 | | 6 | 7 | | | 10 | 11 | | 13 | | | | 17 | 18 | 19 | 20 | | 22 | 23 | | 25 | 26 | | 28 | | 30 | 31 | |
OPTIONS
Track this Journal
ARCHIVES
July, 2009
June, 2009
May, 2009
April, 2009
March, 2009
February, 2009
January, 2009
October, 2008
September, 2008
August, 2008
July, 2008
June, 2008
May, 2008
April, 2008
March, 2008
February, 2008
January, 2008
December, 2007
November, 2007
October, 2007
September, 2007
August, 2007
July, 2007
June, 2007
May, 2007
April, 2007
March, 2007
February, 2007
January, 2007
December, 2006
November, 2006
October, 2006
September, 2006
August, 2006
July, 2006
June, 2006
May, 2006
April, 2006
March, 2006
February, 2006
January, 2006
December, 2005
November, 2005
October, 2005
|