1. Not sure... probably less than 500K
2. Current project is 10K, probably will be more like 15K when done. 1K of those are comments, and 2K are blank.
3. Don't know
4. Don't know
5. I'd say <10K is fun size, <100K is small, <500K is medium, <1M is big, past that is monster.
In general, I consider more lines of code to be a negative side effect of adding functionality
That is, the less the better, up to the point that you start sacrificing readability to save lines.
A related statistic is comments. I generally consider self-documenting code to be the best of all, but a lot of things aren't so straightforward so I add a line of comment explaining why I'm doing something. Or a big block comment explaining what I'm about to do with a lot of lines of code. And if I have a brilliant idea how to solve a complex problem in relatively few lines of code, it's perfectly fine if it takes more lines of commentary to explain what's happening than the actual code it's talking about.
Here's a good example function of pushing the boundary between "less is more" and "OMG what have I done"
void SpriteSystemYSort()
{
Sprite *sprite = gSpriteActiveListHead;
Sprite *activeListTail;
if (sprite == NULL || sprite->next == NULL)
return; // No sorting to be done unless there's more than one sprite
// Start from the tail of the list, for minimal insert time if the order hasn't changed since last frame
while(sprite->next)
sprite = sprite->next;
// Rebuild the active list in Y sorted order. Start by adding the first sprite, to save a couple null checks in the loop
gSpriteActiveListHead = activeListTail = sprite;
sprite = sprite->prev;
gSpriteActiveListHead->prev = gSpriteActiveListHead->next = NULL;
while(sprite)
{
Sprite *prev = sprite->prev;
Sprite *insert = gSpriteActiveListHead;
while(insert != NULL && insert->pos.y > sprite->pos.y)
insert = insert->next;
if (insert == NULL)
sprite->prev = activeListTail, sprite->next = NULL, activeListTail->next = sprite, activeListTail = sprite;
else if (insert == gSpriteActiveListHead)
sprite->prev = NULL, sprite->next = gSpriteActiveListHead, gSpriteActiveListHead->prev = sprite, gSpriteActiveListHead = sprite;
else
sprite->prev = insert->prev, sprite->next = insert, insert->prev->next = sprite, insert->prev = sprite;
sprite = prev;
}
}
Specifically those 3 long multi-statement lines. On the one hand, they'd be more readable if I separated them into multiple lines. But on the other hand, they're run-of-the-mlll linked list operations, which most programmers should be familiar with. And this way, you can clearly see the whole loop (and even the whole function) at once, which makes following the flow of execution easier.
Another interesting point of this function is "design time optimization". I could have gone with a fancy sorting algorithm because insertion sort is technically O(n2) complexity, except that I know most of the time sprites won't change order between frames. So if I iterate through the list backward when choosing who to insert, and forward when inserting them, the new list will be built up from tail to head, inserting each sprite right at the head of the list, making the whole thing linear time.