• entries
109
175
• views
116869

This journal is approved by the Get A Life Commitee. I swear.

## It's about frustration...

Granted, I rarely play games. As a direct consequence to this, there are lots of things I'm not good at when playing: I am slow at typing specific keys, I don't see patterns that have been added to please hardcode gamers (you know, things like "if you find a hidden way to a hidden place, then you'll find good stuff at this place").

And since I'm the proud father of a 15 month baby, I have limited time to play anyway, so there is little chance for me to enhance my playing skills (not to mention that I'm not sure that I really want to enhance them).

But mind you, I play. Mostly single-player RPGs or RTS - I tend to prefer the former. I've been long time adept of pen & paper role playing games, and when I believe a CRPG is to be tested, I buy it. Over the time, my collection has become quite interesting :

• Baldur's gate I & II
• TES 1: Arena
• TES 2: Daggerfall
• TES 3: Morrowind
• TES 4: Oblivion
• Neverwinter Nights 1
• Return to the Temple of Element Evil
• Ultima Undeworld I & II
• Dragon Age: Origins
• The Witcher 1 & 2

I believe I have some other CRPG lying around - and this is not counting adventure games (Raymon, I still have my copy of Morning Wrath) or hack-n-slash with a RPG twist. I just love them.

When I play, I tend to follow a simple pattern: when possible, I set the difficulty to the lowest level (I cannot afford to play the same section of the game again and again), I try to be always higher level than needed (to minimize the risks of restarting the same sequence again and again because I'm too weak to overcome the challenge) and I try to follow the base story as much as I can (in sandbox-like games such as the TES series, I try to avoid side quests unless they offer a very good reward or unless I need to level more in order to fight a big boss). The goal is simple: since they are games whose duration lie between 30 and 150 hours, and since I can play at most 4-6 hours per week, I must make sure that these hours are not lost doing things that are unnecessary. I'm looking for fun, not completeness.

Most of the time this simple strategy works fine. In fact, until recently, it worked each time I played - and it was fun.

I think what I find of interest in a CRPG is not the challenge. I don't mind challenge - especially when it fits the story - but I prefer the discovery of the story (this is why I'm not going to spend much time in a MMORPG: the story is secondary in these games). What I really dislike is everything that can frustrate me of this pleasure.

And this is here I wanted to come. I cannot understand why recent CRPGs are more akin to create moments of frustration than older ones. I remember I spent 30 minutes to one hour to understand how Morrowind's Shrine of Azura worked (my fault ; I don't remember why it took so much time, but I beleive I misread something at some point) - but I can afford to lost 30 minutes here and there. I also remember a few particular frustration moments in this game or that game but I was able to overcome the difficulty (sometimes by changing my way of doing something). After all, I have saves to allow me to start again later if I'm a bit stuck.

Take Obivion for instance: the choice made by designers to level the monsters as you level is just plain silly. Let me play as I want to play, damn it! But then, most of the time the difficulty during fights only happen on random encounters, so you just have to reload the latest save and you're done.

Then comes DA:O. If you play the whole game in "Easy" difficulty (or whatever it's named), then the whole game will be quite kind with you (you will die a few time - the challenge does not disapear) - that is, until you get to the final part of the game. Then you'll have to start and start again (and again, and again, and again) the same stupid fights because suddenly the game difficulty changed drastically. After 6 hours full of restarting again and again the same fight, I uninstalled the game with the following verdict: "that was a good game, too bad the game designers went kind of stupid at the end".

And more rencently, I decided to go for a ride with The Witcher 2. And frankly, this is a good game. Except that I'm stuck in a stupid village, trying to rescue this stupid bard, with this stupid "please, no blood" attitude. Which mean "you have to fight with your bare hands and if you lose, you die" (how stupid: they are allowed to kill me, but I can't?).

Dear Red Projeckt game designer, if you ever read this: this is just plain silly. I set the difficulty level to the lowest possible value because I'm not good at gaming. I only have my keyboard. And you ask me to punch a guy in the face with the following conditions:

• if he touches me 3 to 4 times, I'm dead
• I need to punch them 6 to 8 times to k.o. one guy
• there are two of them (or more, depending on the dialog) in a row
• I cannot save between the fights (meaning that if I die before I k.o. the last one, I must redo everythign, including the lengthy dialog at the beginning)

Not only the conditions are unfair but they are also directly responsible for the frustration moment. That and the (damn "I don't play on a console, you freak" stupid) fight system

• wait for one to two second. The tempo is just here so that you cannot rely on the system to know when you're going to be active. In other words, it's here to artificially increase the difficulty.
• press the key (one of QSDZ) that appear on the screen. you have less than (I'd say) 300ms to do that, and you must press the key only once (which means: go away, you little guy with disabilities, we don't want you to play) . At this point, if you fail, you might take a severe hit and loose 1/3 of your life. If you success then...
• one time out of three? (random: it can be 3 times in a row) you have to press another key in - guestimate - (300 - the time you used to press the first key) millisecond. If you fail, you might take a severe hit again. Remeber that you have to press the first key once or you second keypress will directly be interpreted as a wrong key - and you'll take a hit.
• If you succeed, then once in a while you will punch the stupid guy in front of you. A bit. Enough for him to scream "my nails!" or something like that.

Having two fights in a row using this system is just plain impossible for many people, including me. Now, if I manage to do a perfect on the first fight (I did this one - out of 20 tries), you still have to defeat the second guy. If you fail, you start over - and over - and over - and over... Repeat ad nauseam.

So here is my verdict, after 3 hours of play: "it's a good game, too bad it's not meant to be played". Uninstall (bonus: frees a few GB on the drive), sell DVD, and insult designers (during the frustration rampage).

The frustration is doubled, because it hurts to buy a 50EUR game just to see that a stupid game design decision prevent you to have any kind of pleasure once you hit that stupid village. That's 2 or 3 hours of game if you decided to let the cinematic play as I did.

Red Projekt guys, this is a failure - and an upseting one.

--
Bonus: count the number of time I wrote the word "stupid" and win a bonus cookie!

## Video game source code

This is more or less a reminder, as most of you already know this stuff. Here is a (incomplete) list of games whose source code is available, together with links (or, when not available, information on how to retrieve the source code). The origine of this entry can be found on my own personnal French blog.

Gish, Cryptic Sea.
Aquaria, Ryan Gordon (via mercurial)
Quake III, id Software (direct zip d/l)
Quake II, id Software (direct zip d/l).
Quake, id Software (direct zip d/l)
0 A.D., Wildfire Games.
Rise of the Triad, 3DRealms
Ryzom, Nevrax (stopped business a few years ago ; the game is now supported by another company)
Seven Kingdoms, Enlight.
Arx Fatalis, Arkane Studio
Return to Castle Wolfentstein single player and multiplayer, id Software (sirect zip d/l).
MechCommander 2, Microsoft
No One Lives Forever 2, Sierra : toolkit contains the source code of the game
Wolfenstein: Ennemy Territory
Duke Nukem 3D, 3DRealms
Lugaru, Wolfire Games
Penumbra - Overture, Frictional Games, via git
Alien Swarm, on steam (the source code is available in the SDK (URL = steam://install/513 ; you might need to install Steam to get it)
Allegiance, Microsoft

This is not (by far) a complete list. Some old games have been removed (mostly Doom-generation and before), some other are missing (Allegiance ; anybody have a link on this one ? It seems it disapeared from MS Reasearch downloads ; Hexen, Heven II and Heretic: cannot find a reliable download site; The Operative - NOLF : went AWOL a few years back, the Wayback machine doesn't help much ; and so on).

Do not assume that this post is not connected to my previous entries. There are evil forces in this world you can't know anything about, and I'm in a deal with some of them.

## It's been a tough week

Yep, companones, it's been a tough week. I'm not speaking of work (that, too was a tough week, mostly because bash 2.3 and bash 4.1 do not work the same way, for unknown reasons (apparently, introducing breaking changes that deny the right to exist to myriads of old Makefiles is now called "bug fixing")).

I'm speaking of the next iteration of [ekogen] (the library name still evolves; see, I added brackets!) and it's upcoming addition : the network library. In my previous entry, I showed how Asio (and consequently boost.asio) is quite short when it comes to addressing some particular issue. The library has some design limitations that I find weird and unconvenient for many uses. So my goal is to address these limitations - and this cannot be done by pushing the proposed modifications to boost.asio, as such modification would break existing code (hey, bash team: existing code is precious). There are other C++ network libraries out there but none of them provide the level of abstraction provided by Asio so there is the place for yet another network library that do things correctly. This is the intent behind [ekogen]'s network component.

The technicalities of providing both synchronous and asynchronous operations is of limited interest to me (because it's well known since Steven's book on communication programming in the Unix environment). Sure, there are some platform specific issues to address (Windows Socket API version 2 does asynchronous operation differently from POSIX systems) but in the end ther's nothing complicated here.

On the architecture side, things are more complicated. Choices that seems unnatural are to be made (do I provide a tcp_server class? should sockets be copiable or movable ? and so on). Here are my observations :

* copying sockets is of limited use; most of the time, a socket copy is done to transfer its ownership to another thread - or at least another context of execution. It's far better to provide a socket with move semantics, as it's the best way to transfer an object to another context. C++0x makes move constructors and move operator= explicit (by using a rvalue reference). C++98 is akward wrt to the move semantic : the only movable object in the current standard is to be deprecated in the next standard (std::auto_ptr). But anyway, this can be done easily. It also gives a release() function for free (although I'm not sure this should be in the public interface). When real copying is to be used, a weak_socket can be constructed from the socket.

* both TCP servers and UDP servers are just wrappers around other, simple to use classes. A TCP server is made of a polling mechanism and a binded listening socket (the polling can be asynchronous, allowing the implementation of high performance servers in a single thread). This is simple to implement if you have access to both mechanism. It can be a little more cumbersome if you hide all that stuff in a tcp_server class (as Asio and most other network library does).

* naming is primordial for the success of a library: I don't want to hide the fact that I'm handling sockets, but I don't want to accept() incoming connections, as such accept() would necessarily imply an operation which is different from the original accept() in the BSD socket API. Same goes for listen(), select() (which might not even be implemented using select()) and so on. There is some reasearch to do to find clever equivalents that are both concise, clear and different from the original verbs.

* synchronous sockets are not asynchronous sockets: depending on the OS, they are not created using the same system calls and their use is vastly different. A distinction need to be made between UDP and TCP sockets as well, as UDP sockets gives me more informations than TCP sockets. It is possible to create a synchronous socket from an asynchronous one - the inverse is not always true. I should end up with something along the line of :

class stream_socket{ stream_socket(const stream_socket&); // define only stream_socket& operator)(const stream_socket&); // define onlypublic: typedef implementation-defined native_socket_type; typedef implementation-defined boolean_type; stream_socket(); stream_socket(stream_socket&) throw(); // move ctor stream_socket& operator=(stream_socket&) throw(); // move operator= ~stream_socket(); // does nothing is released // properties and query operator boolean_type (); // boolean_type converts to bool weak_socket weak() const; // throws if (!s) // operations void read(...) const; // std::vector ? void write(...) const; // std::vector ? void shutdown_write() const; // = shutdown(SHUT_WR) (man 2 shutdown for further info) void shutdown_read() const; // = shutdown(SHUT_RD) void shutdown() const; // = shutdown(SHUT_RDWR)private: native_socket_type release() throw();};class async_stream_socket{ async_stream_socket(const async_stream_socket&); // define only async_stream_socket& operator)(const async_stream_socket&); // define onlypublic: typedef implementation-defined native_socket_type; typedef implementation-defined boolean_type; async_stream_socket(); async_stream_socket(async_stream_socket&) throw(); // move ctor async_stream_socket& operator=(async_stream_socket&) throw(); // move operator= ~async_stream_socket(); // throws if pending() ? // properties and query operator boolean_type (); // boolean_type converts to bool weak_async_socket weak() const; // throws if (!s) bool pending(); // socket is used in an async operation. Useful? // operations void read(...) const; // std::vector ? void write(...) const; // std::vector ? void shutdown_write() const; // = shutdown(SHUT_WR) (man 2 shutdown for further info) void shutdown_read() const; // = shutdown(SHUT_RD) void shutdown() const; // = shutdown(SHUT_RDWR) weak_socket weak_sync(); // throws if (!s); returns a normal weak_socketprivate: native_socket_type release() throw();};

This is a lot of code to provide only two operations (read and write, which are only partly defined here. Some buffer has to be provided, and I still have to decide whether a std::vector<> would do the trick - in which case this function shall be a template function).

Same goes for UDP sockets (datagram_socket and async_datagram_socket). Now, how do I want to create them? Using endpoints (endpoints and resolvers are two Asio features that I believe are very well designed - at least from a conceptual point of view; I haven't checked the full implementation yet), I can tie an IP address and a port number. Using a listener (name to be changed), I can bind this endpoint to a logical port and create an internal socket. Using a poller, I can use this listener to get new socket instances. So in the end, I never really create them - I get them from the poller (for an UDP server, there is no need to listen from the socket, but a poller can be of interest)

Polling also pose a (slightly limited) software design problem. I have no guarantee that polling will return me only one event, so I must find a way to handle possibly multiple incomming events. Moreover, polling gives me two information: the socket which is to be processed and the event to process (is the socket to be read ? write ?). This information is available from all pollers that are available on any platforms (*nix have epoll (linux), kqueue (BSD, OS X), select (all), /dev/poll (Solaris ; I can ignore that - not my target) ; Windows has select, WSAAsyncSelect). How do I handle these events ? I have two ways :

1/ feed a vector of (socket, event) to the poller. This is quite ugly, might need loads of reallocation if the vector grows, and so on. If I can avoid that, I won't be very sad.

2/ give the poller a tack to execute on the reception of an event. Asio provided the idea of strands, which are (as their name says) "mini-threads". This is not really true. In fact, strands are deferred tasks that are ran when a promise(*) is set (the promise itself is the result of the operation, be it a synchronous or an asynchronous one). If you already have a good knowledge of the upcoming C++0x standard, you can view them as generalized futures : futures only gives you back the promise when strands allows you to do some processing on the promise. Any word play aside, this is a promising solution.

Since (1) looks bad and (2) looks far better, the obvious choice it to implemement (2). For a synchronous poll, this is easy : I just wait for the poll to complete and then I execute my function (which is likely to be a std::function (or std::tr1::function if no C++0x features are available). For asynchonous operations, this is trickier. Windows has completion ports but that only allows me to execute a free function or a static member function, and the select operation is not implemented this way (keep away from WSAAsyncSelect - this is a WTF function that sends a message to a HWND when the operation completes). *nix has no system wide primitive that looks like completion ports so we have to fake them by creating a thread, waiting for the asynchronous function to end, then execute the operation.

In short, asynchronous poll mandates the creation of a short-lived thread in this design. The upcoming standard thread library offers std::thread which provides exactly what we need (I have re-implemented the basic mechanism of std::thread in [ekogen] to compile the library on platforms where it is not yet available, such as g++ prior to version 4.4 and all versions of Visual Studio (std::thread is not part of the tiny part of C++0x that has been implemented in Visual C++ 2010 ; we're looking forward for the next version...).

With such a design, the code for a TCP server shall look like (remember some names are to be changed):

using namespace ekogen::network;struct event_receiver{ listener& m_l; event_receiver(listener& l) : m_l(l) { } // not sure of the prototype yet void operator()(poller& p, const socket& s, const event_type& event) { if (m_l.get_socket() == s) { // add the socket to the poller list poller.add(m_l.incomming().get_socket(), event_type::read | event_type::write); } else { if (event & event_type::read) { s.read(... } else if (event & event_type::write) { s.write(... } } }};int main(){ listener my_listener(endpoint(ipv6_address::loopback, port::any)); poller my_poller; my_poller.add(my_listener.get_socket(), event_type::read); my_poller.wait_for_events(event_receiver(my_listener));}

A TCP server class would just encapsulate a small part of this code. This can still be of interest for simple applications - but then, a tcp_async_server shall be provided, as well as a mechanism to filter the incoming connections and so on.

The code for an async TCP server is quite similar - and the code for the UDP server is not very far way from that (UDP servers does not need to listen() and accept() incoming connections ; you just need to poll the binded socket (and even polling is not really needed, as recvfrom() is a blocking call).

--
(*) don't worry if you're lost with these promise, future and strands ; I will publish something about this very subject in the coming weeks.

## Asio C++ library: it gets nearly everything right

Bur nearly everything doesn't mean everything. For those who believe I'm talking about boost.asio, you're pretty much right as Asio has been incorporated in Boost. However, it exists as a non-Boost library, so I will continue to speak about Asio as Asio, and not boost.asio (there are a few differences, for example the namespace where the declarations are stored, but it's mostly the same thing).

So, Asio is supposed to be a well designed library. When it comes to generic AIO (asynchronous I/O), I tend to agree to that statement. When it comes to the network part, I protest : there are obvious design errors, and they lead to real design issue in th client code.

Let'sbegin by the first, obvious design limitation: the definition of socket types. There are two problems with this one:

* sockets are non-copiable. This is lame: I want to copy my sockets! I can transfer a file descriptor to another thread, but I can't transfer a socket to another thread - unless I store a pointer to it in a shared_ptr<>. Wow. I need to do a dynamic allocation to be able to use a socket in multiple threads?

No, guys. Sockets needs to be copiable. First, they are supposed to be lightweight objects (we're speaking of an object with only a few properties). Second, some well-known server architecture patterns mandates this (you accept the socket in the main thread, and yo pass it to another thread).

If you can't make it copiable, make it movable (that's going to be super-easy with the move constructors in C++1x, but it can be implemented today on th model of auto_ptr<>), or allow for the creation of weak socket (something along the line of weak_ptr<> ; this is bad: no one owns the socket and this is as well a design issue. You shall always know who is owning what).

* bad interface design. Both synchronous ans asynchronous behaviors in the same interface? that's an Error. Either you do synchronous operations (read, write, readfrom, writeto) or you do async operations. There is a good reason for that: it's not the same thing, it's not the same use. Of course, one can mix both types of operations in the same application, using the same socket - in which case he'd better instantiate an async_socket from his socket or the other way round. Two different behaviors in the same interface, this is a clear violation of the single responsibility principle. Bad, bad, bad.

Let's continue with another annoying design issue: symbol names. On most occasions, Asio decided to keep the names that have been used for years in the network programming world in order to mimic a known interface and soften the learning curve. So we have an acceptor class, which accept() stream sockets. But on the other hand, Asio decided to renew the vocabulary of the network programmers by introducing new terms. We no longer gethostbyname(), we resolve a host name.

The latter is correct by all means: you generalize, so you provide a distinct name that explains the generalized concept and is semantically correct. The former is problematic: you use a name with a strong meaning, and you reuse it to do something different - although it's not very different. There is another problem that comes with name reuse : you can't provide an abstract meaning to your class, and that forces you to be very concrete. At the same time, your class is central to the design, and many people uses it. So you have something which is both concrete and stable (per the meaning given by R.C Martin: a stable package/class is a package/class on which many other package/class depends). And this is not a good thing.

I'm sure you all have issues with th design of a library you use. Feel free to share them !

## Managing pipelines in C++

A few days ago, I released version 0.4 of my little security library. This version allows the creation of function pipeline using a simple syntax. If R is the return type of the pipeline and A is its argument type, then

pipeline p = stage(f1) | f2 | f3 | ... | fn;

Will construct a pipeline containing n stages.

The implementation is based on a limited version of boost.function as well as on simple expression templates (because we basically construct a representation of the pipeline function without evaluating it). The first function in the pipeline must be stageified - all the subsequent ones are automatically stageified by using operator|(pipeline_stage, F).

Pipeline stages are a strange beast. The pipeline_stage class has two specialization: the base one, which accept two callable F1 and F2 (functors that inherit std::unary_function<> or function pointers) and the limited one where F2 is nulltype. Using these two specialization I'm able to build an arbitrarly complex pipeline_stage:

// ps == pipeline_stagetypeid(stage(f1)|f2|f3|f4)).name() == typeif(ps,F3>,F4>,F5>).name()

Some code has been added recently to deal with the reconstruction of pipeline stages (stage(f1) constructs ps, so stage(f1) | stage(f2) would naturally construct ps,ps > ; this has been modified so that this expression constructs a ps object).

Version 0.4 has some small issues (does not compiles on Windows ; next version will ; pipeline p = stage(f1) cannot be written, due to the lack of a constructor in pipeline), but it works quite well in practice. I added adapters for the cryptographers and the encoders to enable the construction of encryption/decryption pipelines).

You can download the zlib-licenced code -ekogen-v0.4"]from my French speaking blog (scroll to the bottom up to the "annexes" part).

And if you like reading C++, this library will please you - nothing too advanced, everything can be read easily, although I make heavy use of templates.

Enjoy !

## Encapsulation For Openssl Rsa/Blowfish In C++

Now, that's not a wonderful piece of code, filled with incredible meta-programming snippets. But it's a piece of code that's usable and - more importantly - that can be modified to suit your needs.

So let me introduce you a small part of a large library en devenir. This code encapsulates the blowfish symetric cipher and the RSA asymetric cipher from OpenSSL. As of today (version 0.2), only Linux is supported, but a port to Windows is planned as soon as I get my own PC back. As a bonus, a modern C++ implementation (little endian) of the SHA256 hashing algorithm is provided as well (used together with RSA private encryption, this allows you to sign messages ; which is kind of cool).

If you are interested by the code, just remember the following:
• you're not going to see a lot of comments ; this shall not be needed (my code is not that horrible).
• a large part of the code uses templated policies.
• whenever I can, I play with the standard library. While waiting C++1x, this code uses a small portion of the TR1 (tr1::uint32_t and tr1::uint64_t).
• You finally have the possibility to watch some code of mine in action! (ok, that's not really of interest).
Licensing information is not included yet. You can consider that this code is licensed under some kind of BSD-style licence (that is: do whatever with this code ; just remember I wrote it, but if you want to act like you are the original writer, you are allowed to do that).

Class list:
• ekogen::security::rsa_cryptograph
• ekogen::security::rsa_key
• ekogen::security::rsa_public_key
• ekogen::security::blowfish_cryptograph
• ekogen::security::blowfish_key
• ekogen::security::xor_cryptograph
• ekogen::security::xor_key
• ekogen::security::default_rng
• ekogen::security::xor_rng
• ekogen::security::symetric_cryptograph
• ekogen::security::symetric_key
• ekogen::security::asymetric_cryptograph
• ekogen::security::asymetric_key
• ekogen::security::public_asymetric_key
• ekogen::encoder::base64
• ekogen::encoder::hex
• ekogen::encoder::basic_encoder
Function list
• ekogen::security::sha256(const unsigned char*, std::size_t, std::vector&);
• ekogen::security::sha256(const unsigned char*, std::size_t, E::output_type&, E)
• ekogen::security::sha256(Iterator, Iterator, std::vector&);
• ekogen::security::sha256(Iterator, Iterator, E::output_type&, E)
PDF Documents that explains part of the interface are in directory /doc. The build system is very rudimentary and shall be replaced by a more advanced one in a few days (probably cmake, since it works on all the platforme I target).

Details (in French, sorry) about the code can be found on my blog. For those who don't speak French, google makes a decent work at translating the text.

Happy... something !

# Heading to the Lyon GDC

I finally managed to get in Lyon tonight, just in time for the beginning of the Lyon Game Developper Conference - an event I have waited for month and month. Organisation is not that simple: there are tons of people in Lyon these days, and I have only one hotel night booked (I might be able to book tomorrow night in the same hotel, but after that I'll have to move).

What will I do during this 2 day conference? Well, I will try to get contacts with industry leaders (hopefully, I'll also get some short interviews that will be posted here as podcasts). I will attend some highly technical sessions (the research sessions are looking good), I will spend some time with the game developpers around there.

My only probem is that I don't have a schedule yet - I don't know which session I can attend. Look: I'm supposed to go to the Serious Games Summit on monday. I will do that, of course, but what lectures will I miss? I don't know. That's a bit frustrating because I just can't organize myself. I guess I'll be able to get this information monday morning...

The program (for you):
• As many podcast as I can record
• loads of lecture report
• pictures...
• and, of course, a bit of fun [smile]

So see you tomorrow for the ongoing Lyon GDC report!

## Apologies?

I have been quiet this month (and the one before). It's not that I don't want to do my job here (God knows that I'm happy to work for GameDev.Net) - it's just that my free time has shrinked down to a level I never faced before.

Understand me: even if I am used to work 11h per day, I usually spend half an hour to one hour on the intarweb to read news and post them on gdnet. If I don't have this luxury during the day, I do it when I go back home. But these last weeks are a bit strange for me: I have really no "free" time. In fact, I have some free time (let's say about 1h each day) but I try to spend it with my girlfriend (I'm not sure I should be sorry for that).

I still hope to be able to organize myself to be able to post news daily as I sued to do. I will be able to return to this regular schedule at some point in the future. One thing is sure: I don't give up, and I will return.

For the time being, I'd like to put a big thank on the head of the other staff member who took some time to handle the news (Gaiiden, Melissa, ...) and to the regular users who posted news on our front page. You rock, guys (and girls).

See you later ;)

## Back in the village again!

Dear journal,

I had my share of work and other oddities, and because of these I wasn't able to handle the news as often as I wanted. You have to understand me: it's not that I'm a busy man, but I decided to share more time with my girlfriend (she's soo cuuute), I broke my car engine again (but that's a problem with the latest repair), I had to come back to the south of France, I had to organize my flat a bit (dear journal, do you really think I would have spent more than 1 year in Stuttgart without having bought some small stuff?), and I have now to tackle with new responsibilities in my company (promotion! OMG).

And, to be honnest, I finally bought Oblivion (GotY edition) - because my GPU now allows me to run it. And even if you know that I'm not a hardcore gamer (I'm more the casual guy), damn it, it's Oblivion! Now I am happy because I have all 4 TES games + their extensions + Battlespire. Ego is satisfied.

Ok journal, I have other things to do (you know, life and so on). But I'll come back, I promise. See you soon!

## I be teh slow newzorz

You may have noticed that news posting was a bit chaotic this week - that's because I have a lot to do to return back to France.

Yes, I'm leaving Germany and I'm heading to the sunny Provence (where I'm used to live). Of course, I need to pack everything, and you can imagine that it takes loads of time (what you can't imagine is how much crappy things you buy during a one year course).

So expect to get a more normal situation at the beginning of next week [grin]

## As promised....

Well, see below to read something which is barely related to the title of this post.

My coverage of the GCDC'07 is on the way. It should appear sometimes today, and contains a lot of things. I would like to thank both Drew (that forgave me my slowness) and Felix Kerger (Mirlix on GameDev.Net) who (unexpectedly) helped me during the conference. That was very nice from him.

I met another (French) GameDev.Net guy in Leipzig - but unfortunatly I have lost contact with him (mstly because my small brain have some problem to recall his name; I'm ashamed). That's really unfortunate because we had interesting talks about graphic engines, and I'd like to continue the discussions). So, please, guy, the next time you log on GDnet and read this journal entry, please, please, PM me! (or send me an email - I think I gave you have my business card; I hope).

Speaking of conferences, there is a good chance that I will attend both the Game Connection Lyon (a business related event, the meeting kind; I'll use this opportunity to speak to developers and publishers) and the Lyon GDC. I believe that both events are going to be teh cool.

In my latest post here (yeah, the one from saturday) I promised you a screenshot of the incredible XNA/C# Maze Generator. And this journal post is featuring said screenshot.

I believe it's the first screenshot I even feature in my journal...

But even cooler, I'm posting the code that allows you to play. There is no victory condition, and there is nothing such as a failure. It just display a maze, the minimap, and features you as an orange dot (that's a bit weird, I know... forgot to say that the shot features programmer art). Only on maze is generated for every run of the program - you'll have to quit and relauch to generate another maze. The software runs in windowed 800x600. You can change that in ex_MazeGame\MazeGame.cs - just modify these lines to whatever you want. For the screenshot, I used fullscreen 1680x1050.
  private const int ScreenWidth = 800;  private const int ScreenHeight = 600;  private const bool fullScreen = false;
There is not much polishing - it's really a bare example of what I could do with my Pawn library - whose latest code is also included in the archive. I'm planning to improve everything and to ultimately feature a fully functionnal game (and to include my in-progress D20 lib, which is also excerpted from the C# workshop).

Ok, time for the screeny. Click the image to get the real size one!

And time for the code: 20070910-GDnet_CS_WorkShop.rar!

Note: obviously, you'll need XNA Game Studio Express to build the code. Both the 1.0 and 1.0 refresh are able to build the project.

On a side note, I received a mail from Multi 3D Animation Limited, a 3D animation company located in Hong Kong. I don't know what to do with that, so I decided to give you th link. Feel free to visit them (although I'm sure sure about what to visit here...).

Multi 3D Animation Limited

## OK, I give up...

I mean, this GeForce FX 5600TX is just too lame, and I just can't accept that anymore. So I went to Staurn in the Stuttgart town center and I bought an AGP GeForce 7600 GS (the one by MSI, with 256MB DDR2; see here for the benchmark results). It was cheap, and it's supposed to be good enough - at leat it will help me to wait for the end of the year.

I also decided to buy a Xbox360 pad for my PC (because I plan to write an article about XNA input systems for my blog in a few weeks). I first wanted to get the normal one but it was unavailable - so I bought the cordless controller. Hopefully, I will get some fun with that.

Speaking of XNA, I decided to test my implementation of the C# project 1 in a XNA program (2d, top view). This proved to be tricky - not on the maze part, on the rendering part. I'm writing a series of XNA tutorials for ny blog, so I decided that I should use my own sprite library (pawn) and give it a test. My design is quite effective... for a C++ program. I'm pretty sure that a C# program should NOT be designed this way, but my knowledge of C# is still too limited and disallow me to write something better. Wait, it's not uterly slow. It's just not as fast as it could be.

The maze is implemented as a specific kind of tiled background layer. My library allows me to create a background with an unlimited number of layer (hello mister parralax scrolling). Layers have to inherit the IBackgroundLayer interface and are then free to do whatever they want. I have three implemented types of background layer:
* a "simple image" layer: an image which I directly copy to the position the user specified
* a scrolling image: an image in which you can freely scroll. It's up to the client application to describe the scrolling by specifying the visible area in this image.
* a tiled background: a background which is made of tiles (really?). This is the most interesting one in our case. It only implements how to scroll in the background and the high level rendering operations (ie choice of tiles you want to render and so on). Tile storage is implemented in a IBackgroundLayerTiledStorage interface (which inherit IBackgroundLayerStorage). The library contains a specialized implementation of this interface to load the data from a XML file. I then decided to store the maze in another implementation of this interface to see how it would work.

Well, from a design point of view it works great. From a speed point of view, it works not so bad - but there is so much dumb code executed that I'm sure I can do far better.

To ease the rendering and to limit the number of needed tiles, each cell of the maze is divided in four quadrants - topleft, topright, bottomleft, bottomright. As a result, I only have to deal with 12 tiles (13 if I use my "big rooms" feature while building the maze). Getting the corret tile for a particular quadrant in a particular cell was quite annoying. I finally got everything right (after, say, 1h or 2h of debug... :/).

Then I decided to implement "fog of war". As another background layer. Oh. This is inneficient (as some invisible tiles are drawn twice: once when I render the maze and once when I draw a solid black tile onto them). Given the fact that I just did something very similar (the maze), it only took me one hour to get it running. I also had to mess with the tiles but that was a bit eaier (now thT I had a working scheme).

Implementing the player movement was quite easy, but I had a stupid problem when I tried to update the fog of war w.r.t visited tiles. Well, each cell in the maze have a "bool visited" member - but the cell is a struct, meaning that anytime I got the cell struct from outside the maze, I got a copy of the struct - and not a reference. Well, a struct is a value type in C#. Changing it to a class fixed the problem (but forced me to do a bunch of new allocations, ok, that's not really a problem). Once I got that, everything was working.

I have a perfect maze which is displayed in an XNA program. I find this damn cool, given the fact that I started C# 3 month ago.

Last but not least, I decided to display a minimap of the maze in the top right corner of the screen. It was the easiest part: I just had to specify that the whole bakground was visible and that it should be drawn in a small rectangle in the top right corner. 1 minute later, I had my minimap.

Screenies on monday if you're nice ;)

And now I go back to home ('m again in a cybercafe) - and I'll give a try to these two brand new pieces of hardware.

Cya! (not at home, I mean)

## GameDev.Net's Beta Pick!

Welcome to this new feature!

The goal of GameDev.Net's Beta Pick is to present a beta product that we believe is of interest to you despite the fact that it has not yet reached version 1.0. As you may have seen in the past month, we no longer feature beta products on our front page - except for exceptional cases. The reason for that is that there are tons of beta products, and if we were to feature them all we wouldn't have much room for more interesting news. The new Beta Pick feature is then a cool way to feature a product we like without disturbing the news feed.

The first BP features Horde3D v0.11.0 - a very clever open source 3D engine.

If you want your product to be feature in the Beta Pick, please send a mail to emmanuel@gamedev.net or news@gamedev.net, or send me a PM!

## GCDC day 3 - meetings, meetings, meetings

And that's now time for a short explaination of my 3rd day at the GCDC. And it's going to shock you: I had little time to attend any talk, as it turned out to be a "omg I got tons of people to meet" day.

And all meetings were not equal - although all of them were interesting, as they offered me the opportunity to dwelve into the part of the industry that's quite obscure: the business part.

For example, I got a hour long meeting with Sophie Therrien of the Game Connection Lyon. The GC Lyon is a business-oriented event - something that does not sound extraordinary to you because you are more interested to game development. But once your game is done, what about selling it? And what about pitching your ideas to some publishers in order to get some funding? And guess what, this is the purpose of the Game Connection event: providing a place where developers and publishers can meet and make deals.

Later the same day, I met Matthias Rose, managing director of the GDBC. What's the GDBC? It's the Game Developer Business Center that was created a few weeks ago at Leipzig. The goal of this organisation is to help game developers who want to install their office in Leipzig - by providing them the needed infrastructure and contacts for a low fee, and help them to leverage the other difficulties as well. The GDBC is using the expertise of Maxicom - a company that have done just that for years and for many different industry - and is linked to the GC organisation - and since Leipzig GC has the possibility to become the biggest game related consumer and trade show. I will tell you more later about the GDBC.

I also got the possibility to set up a few interviews - kynogon's features explained, procedural city creation by gamr7 (yeah, that's "gamer's heaven") or explaination of the new IBM MMOG hosting strategy. These will be covered more in a form you'll like. I think.

And finally, I wandered a bit in the GC hall - looking for games that are going to be released. I played The Witcher a bit (and this is going to be a Really Good Game(TM)), got some wiimote fun with Rockstar's Table Tennis and met many other people around there.

All in all, a good, fast-paced day with a lot of interesting output. Watch out for the GCDC coverage report that should be out in a few days - I think you'll be pleased [smile].

## GCDC day 2, panels, panels, panels (and some beer)

Day 2 of the GCDC (yeah, I know, you are all waiting for the real coverage. It's coming, it's coming) was a bit less hard to handle - partly because I wanted to take the time to actually discuss with the game developers, so I decided to drop a few talks.

And everything began really (for me, at least) with Bruce Shelley's talk, "Designing by playing", where he described the methodology used at Ensemble Studio to create games. The basic idea is: first, make a design document and implement a prototype. Then, play the game (often) and notice what's fun and what's not. Add that feature, remove that one, do a minor modification here and here, build another version, play, rince, repeat. IF there are enough people to play the game, chances is that at the end of this process the game will be fun to play. And for sure, it worked well, as the Age series is quite enjoyable. I just throw one figure in: 4000. This is the number of builds for Age of Empire III over a development process of 3 years. With roughly 230 business days per year, that means that the game was built 5 to 5 times per day.

Employees at Ensemble Studio plays a lot [smile].

After lunch, I enjoyed the Engine Panel with Bruce Rogers (Cryptic), Doug Binks (Crytek), John o'Neil (Vicious Cycle) and Mark Rein (Epic). The panel was mostly about how engines makes sense from a business point of view. And while the moderator explicitely stated that the panel should not run into a "buy my engine" commercial it was not difficult to spot the business blah blah from each participant (except Bruce - Cryptic doesn't license its engine, although they use their own one, carefully crafted during the past 7 years). Incidentally, this lead to some very funny discussions - especially during the QA after the panel.

I then took a break (mostly because I had to organize my evening) and I used the time I just gave to me to wander in the corridors, speaking with the exhibitors that were here (Alladin, ATI, IBM, GameStar/Dev and many more). I returned to work when Bruce Shelley and the other founders of Ensemble did their "Age of Empire - a retrospective" keynote. There is not much to say about that - while the history of successfull games is always intersting, this was more a pleasant keynote than a really usefull one (I mean, there is not much to learn from that kind of keynote). But still, it was enjoyable - and I had a great time.

The "European Business Development and Pithcing Panel" was also quite enjoyable. After all, not everything should be about game development - one has to learn how to sell its game to a publisher too. However, the output of this panel was not that big, mostly because the represented publishers stated some obvious truth - "choose your publisher wisely, pitch your game correctly, be sure to double check your contract". There were some gems (don't ask stupid things to your publisher: no, you won't get an advance AND 20% of royalties AND all rights on your IP), but not that many.

And then came the GCDC night - the business-reserved party. Meaning no press. Hum. Fortunately I had the chance to be with a bunch of people from the Game Connection Lyon organization (the GC Lyon is a business event that will take place in Lyon (ah ah ah) right after the GDC Lyon; I will talk to you about that later). I stopped at the all French table for a while (we were about 15 people here, drinking beer, discussing games, exchanging our recipes for making "quiche" and other tasty plates) until I noticed that Vicky Arundel (I love you Vicky) and the other people of Introversion were only a few meters away. These people are just brilliant. They are brilliant game developers and they are brilliant, well, people. I don't know how to explain that exactly, but the few minutes I had with them were really really good. They gained my respect for the rest of my life.

I finally went back to my hotel room, with many good stories in my head - and a lot of alcohol in my blood.

## GCDC day 1 - talks, talks, talks

Hello Everyone,

So the GCDC in Leipzig has begun, and believe me, it's quite good. Speakers are incredible and I have the feeling that quality is going to improve even more on day 2 and 3.

What did I attended on day 1? Well, because of some issue with the registration process (including the fact that press registration is actually done on the 1st floor while normal attendees are using another entrance), the first keynotes were over when I finally got my badge. But I was able to attend Doug Binks and Leigh Davies's talk about "practical multithreading for game performance". Doug revealed some details about the architecture of Crytek's CryEngine2, while Leigh gave very interesting information about how to design a game with multithreading in mind. "Better games through Usability" by Mario Wynards was about including usability in your game design process. That means a lot of usability testing (is that menu clear enough, and so on).

The "Life after WoW: MMO Games of 2008 and beyond" panel was both entertaining and refreshing. Key players in the field discussed what one should expect in coming MMOGs. We had people from Turbine, ZeniMax Online (I tried to get information about what they are doing right now, but that was not possible; damn... :)).

"Procedural texture generation theory and practice" was a talk by Dierk Chaos Ohlerich - from .theprodukt. .theprodukt initially come from the demo-scene, and several years ago they developped a procedural texture creation system which is quite powerfull (some points of it are similar to Allegorithmics's ProFX, but there are still some differences).

Stromfront and game industry veteran Don Glagow gave a talk about "what makes a game next gen". His huge game industry experience (you were too young when he started to make games) proved to be a key aspect of his talk, as he explained us what next-gen is about - it's not about technology, it's about user experience. That was truely The Talk of the Day.

"Interactive ray tracing in games" was amazing - expecially the real-time we had (not to mention the description of the base algorithm). Seing a Q4 map raytraced at 130 fps in a 800x600 window (maybe more) full with reflection and characters) was quite impressive.

And that was the end of the day for me - more precisely, the end of the talks. At this time I began to wander around, asking questions to exhibitors, getting people interested in gamedev.net and so on, orging contacts and so on. I ended the day by a dinner with Fred Hasson (TIGA, UK), Erik Robertson (Nordic Game Program, Sweden), Malte Berhmann (GAME, Germany), Eamon O'Reilly (EACEA, European Commission) as well as many more key European industry players.

I recorded a lot of talks, and made a lot of photos. Some of them might end up here, so stay tuned!

## 4321 posts and a poll result study

I posted 4321 posts before this one. Not very important. Ok, let's consider the other part of the message.

As some of you noticed, there was a poll about the frontpage news (that I have hard time to handle; brain slow; me sick; going to be faster tomorrow).

I'd like to address the main answers:
• Really, everything is ok (26.9%): well, thanks for your support [smile]

• The rhythm is quite slow, please work faster (17.2%): I promise I'll do my best to feed you with even more stuff. However, you have to remember the problem I outlined here. So I ask the following question: do you prefer to have a fast news turn over (2-3 days, ie 10-15 news per day) or do you prefer to have a less fast news turnover (6-8 days, ie 3-5 news per day)?

• Quality of the selection can be improved (16.3%): in case you haven't noticed yet, you can PM me or you can even comment in the journal to tell me what you'd want to see on our frontpage. I made some calls in the past, but I haven't heard any of you [grin]. So, pals, how can we improve the news selection process?

• I'd like to get more industry related news (12.5%): this one is relatively easy, although your vision of what is a industry related news might be different from mine. Mine is: sale figures, studio merges, important deals, market analysis and so on. What's yours?

• News? Where? Is that a planned feature? (9.05%): you know, being able to chose this answer doesn't mean that you had to chose it. Check the front page for more information. If you still don't see the news, visit your favorite oculist.

• Other (18.05%): the 4 last items adds up to less than 1/5 of the vote count. I won't consider them right now, although I note that you'd like to get game-related news. You'd be happy: this is something I'm working on... You'll hear more about that in a near future (read: not before the GCDC; too much things to do)).

comment!

So you'll be consistent with this poll as well...

## I'm the lucky guy!

Deutsche Telekom is suing me for unpaid bills (540EUR). I won't pay the bills. Reason: while it is true that I picked up a phone line some months ago, DT never did their job properly. After two phone calls (the latest has even been ended rather bluntly by the operator who was not able to speak English (maybe he thought this was a joke)), I gave up with them - they never bothered to install a phone plug in my flat, but they never forgot to send me their monthly bills. Consequence: I have never been able to use the phone line for which they want me to pay.

I will face them proudly. I will battle them. Ultimately, I don't expect to win.

Screw them.

## Car is a costly hobby, and new news record

If you ever own a MG ZR, try to NOT breakdown. And if you breakdown, pray to avoid the utterly classical cylinder head gasket problem. That's actually why I was not able to post news yesterday: I had to find a way to overcome my credit card limitation (I can't pay/withdraw more than 770EUR per day when I'm not in France) in order to pay for the repair: 1,397.07EUR. That was a ouch. So I went to France monday morning (I rented a car: I had no way to take the train from and back to Stuttgart in the morning; add 89EUR), withdrew the money in Strasbourg (in France, I'm allowed to withdraw up to 3,000EUR per day; that was easier), came back in Stuttgart, return the rented car, took a taxi to the workshop (add another 24EUR), payed for the bill, and finally I was able to go to work.

That was a hard day.

So I decided to post all the news I wanted to post yesterday this evening - and that sets a new record for the number of news posted in a single day (I mean, since I'm managing news): a good 10 news (I think the previous record was 8 news).

A problem is now that if I push too much news on the frontpage, the older news vanishes quite fast, and that doesn't leave you much than 5-6 days to read them (of course, you can still use the news archive forum, but I suspect that many of you don't visit it very often).

Speaking of that forum, it gives me some interesting numbers about what (I believe) is of interest to you: product releases typically scores in the 1200 views; news about conferences get roughly 300 hits; the classical industry related news will get around 700 hits. Of course, these numbers varies, and sometimes you'll have only 500 views for a particular product (ex: MaPZone 2.6) while an industry news will be read 1000 times (ex: Peter Moore, from MS to EA). Sometimes, a news completely skyrocket to an impressive amount of hits (ex: XNA Game Studio 2.0 this winter? - 3000 hits; Nintendo opens the Wii to independent game developers - 6850 hits).

In the end, that's pretty difficult for me (and for the other members of the team) to find out what you want to know. I know that a news about some ban law will generate traffic; I can also be pretty sure that the announce of a major product will do so too. Part of the problem is that major products are not released in quantities, and game ban laws are a bit boring in the end.

So, guys, what do you want to see in the news? What would be an improvement of the news pipeline in your opinion?

## Surprise!

Richard announced it - so that's no more a suprise. GameDev.Net, together with NVIDIA and Softimage, proudly present you the new GameDev.Net contest, Shade Your World!

Width this contest, you can win a GeForce 8800 GTX, a license to use SOFTIMAGE|XSI Foundation or the overexcellent new book GPU Gems III (you know, the one with the amazing cover).

Your work: build a shader with NVIDIA FX Composer 2.

So, isn't that a cool surprise?

## Shhhhhhh! This is a surprise!

We are preparing something for you, dear comrades. And I'm pretty sure you're going to enjoy it. A lot.

Now, that was probably my shortest journal post.

Official announce in a few days... Or before. That's a surprise too.

In the process of preparing the GCDC, I decided to make use of a promotional offer from VistaPrint and I ordered a set of 250 color business cards (along with two aluminium boxes). It cost me a completely-impossible-to-pay 2.95EUR (or something along the line) for the cards + 16EUR for the boxes. And now, I have a fair offer for all of you: 25% off for your first command at VistaPrint (PM me for more info). Your obligation: none. Your gain: 25% off if you order something. My gain: well, if you order something, it will make my next orders even more interesting [grin]. VistaPrint gain: I really don't know. The thing is that their bizcards are really not expensive at all - the normal price for 500 colorfull is about 35EUR, to which you'll have to add 6 or something EUR to get them delivered into your mailbox. They even have some free stuff sometimes (although it's mostly promotional; for example, you can get 250 free cards but the back will show a line of text to advertise VistaPrint. That's fair, but that does not look very professional).

PS to other staff & mods: I still have the PSD for this file. Just ask, I'll send it.

## New news posts from new news posters!

We have decided to promote four guys in the news team - Morgan Ramsey (better known as, well, Morgan Ramsey), Dan Merritt (better known as DigiDude), Pavel Pod (Pasha_Bigdog) and Brad Leffler (Schmedly).

This shall mean: more news for you! (and consequently, less time to read them as they're goign to vanish pretty quickly from the front page).

I'd like to thanks them all (publicly; I did that in private, but since they decided to devote some time to enhance the community, I think it shall be great if the community thanks them a bit [grin]) and to wish them good luck in their new work!

## #4003

Today's schedule

* posted some news.
* had some mail discussion
* posted some news
* had some mail discussion
* broke the 4000 post barrier!

Hence the title...