Temple of The Roguelike Forums
Announcements => Traditional Roguelikes (Turn Based) => Topic started by: getter77 on December 07, 2016, 12:59:36 PM
-
There it is~
https://github.com/ChaosForge/doomrl
-
Also rebranded from DoomRL to DRL. Hopefully that'll keep ZeniMax at bay...
-
Also rebranded from DoomRL to DRL. Hopefully that'll keep ZeniMax at bay...
What, so you do have problems with IP?
-
Got a pretty interesting reply on reddit in relation to the timing of the release and the real motives behind it. People were wondering if it was a means of promoting the Jupiter Hell kickstarter or something like that so this is pretty informative:
The C&D was targeted at the website, not the game. Hence I realized that if I push it OS now, I can still push it in it's original state. Even if I have to change it later as a result of a game-targeted C&D, the original source, and hence the original game will still be out there somewhere. You can't stop the signal :P
Source https://www.reddit.com/r/roguelikes/comments/5gve4x/doomrl_goes_open_source/dawactd/?context=3
-
I did look at the source code briefly. It's cool that pascal is so object-oriented these days. However I disliked the low amount of comments and they were something like "todo" or some random funny lines. People, learn how to properly comment your source code! It's important. My rule is always comment as if I was some day going to open source the project (which means write comments mainly for other people that possibly don't have skills to read the source code itself). This source code is kind of readable and not that bad, but still it makes a big difference to explain in plain words what each section of code (how large sections are explained is a personal preference) is supposed to do. And also at the beginning of each source file there should be a short summary of what is the purpose of that source file.
-
They say that even better is not to have any comments at all -- that is, the code should be self-explaining. If you don't know/remember what the code does, you need to refactor. I know it's too idealistic for the real life programming, but I often stumble upon totally unnecessary comments like this:
int counter = 0; // this counts occurrences of the value in a collection
Wouldn't it be better to just name the variable 'numberOfValueOccurrences'?
I also hate this type of comments:
a = 1; // assign the value '1' to the 'a' variable
What is the purpose of that? Everybody can see that we are assigning to the variable. Even a non-programmer would probably understand this. For some reason, though, people seem to like this kind of commenting the code. Maybe they just misinterpret the principle of comprehensive commenting.
Sorry for this terrible offtopic ;).
-
a = 1; // assign the value '1' to the 'a' variable
Huh, I remember writing stuff for my colleagues. I needed to comment every line of code, that student on the exam could just read comments if professor would ask for explaination how his code works. This led to really weird comments, like
animals = ['dog', 'cat', 'bird'] #create new list
for animal in animals: #loops throught every element of list
print animal #prints element of list
-
I've always thought that good design is more important and more readable than any amount of well-documented bad code but even then I set myself a goal of commenting every class and public or protected method in Javelin - which, thankfully Java IDEs help you do very well and the tooling can generate stand-alone documentation too. Right now though I'm working on a big redesign and changing a lot of my previous code and the sheer amount of work leads me to completely ignoring all the comment warnings on my screen. I plan on getting back to documentation once the work is done, but not before I produce a testing/alpha release.
In the end it will always be more important to create and test your code and get stuff done than to comment everything you're doing along the way - and that could even be counter-productive. This current redesign I've been working on has gone through several iterations even this week - if I were to stop to comment properly on all the things I ended up throwing away it would have just been wasted effort, not to mention I might be more tempted to keep them instead of discarding it and always be striving for the best design.
I'd like to hear what are comments worth to other devs but to me they're always much more of a "can I pass this value as null here' or "does calling this method automatically triggers this other update routine or should I call it manually" and in this sense it is nice to have well commented code but it isn't the end of the world if there is no comment on a function: a person should always be able to go in and write the comment themselves - sure it will take 5 minutes away from what they were originally doing but not more than that unless you're writing big cryptic functions that don't follow any of the standards of modern programming. This one I've come across when creating a small patch for DCSS a couple of days ago is not the worst example out there but it comes to mind due to being "not short", returning several values at once via address pointers instead of separating concerns and having a ton of special cases that are not intuitive at all https://github.com/crawl/crawl/blob/24d37aaa1f410fe53df520af77736b379ba67c61/crawl-ref/source/mon-info.cc#L1323
Meanwhile something like this can be documented by anyone at any time in a minute or so and arguably doesn't even need a comment at all unless you're trying to be thorough https://github.com/crawl/crawl/blob/24d37aaa1f410fe53df520af77736b379ba67c61/crawl-ref/source/mon-info.cc#L1647
Finally, if Javelin was closed source, as DoomRL originally was, I am not sure how much code commenting I'd be doing at all. Probably some, for my own benefit - like just annotate the answer in a comment whenever I have to stop and look at the code about some detail. I must admit though that my major goal with documentation is that if someone ever checks out the project he will find it as friendly as possible and have that be a nudge in the right direction of getting people to join in the effort and also set the same standard if someone does come along for the ride.
-
They say that even better is not to have any comments at all -- that is, the code should be self-explaining.
They say shit. Yes the code should be readable, but it's not the point. It's still more readable if you explain what the next section of code is doing. It's easier to read that one (preferably) line of comment than read through the source code. Even more than that not all people code the same way. Some programmers have let's say strange ways to do things. In that case it's even more important to write good comments. Some of the examples of bad comments were those you provided, but they have nothing to do with good commenting.
-
They say shit. Yes the code should be readable, but it's not the point. It's still more readable if you explain what the next section of code is doing. It's easier to read that one (preferably) line of comment than read through the source code. Even more than that not all people code the same way. Some programmers have let's say strange ways to do things. In that case it's even more important to write good comments.
No, if you work in a group, you should all code the same way. That's why Java is far better than Perl in big projects, by the way. Comments may help you to read the code, but will not make it much better when you need to modify it -- you'll still have to fully understand that piece of the code, right? Here's an example:
i--; // go to the next object
The original line was 'i++', a programmer has changed it to 'i--', but forgot to update the comment. This is a very simple operation, so it is unlikely that anybody gets fooled by this errorneous comment, but it's not difficult to imagine a similar situation with much more complicated code and an outdated, misleading comment. I've seen hundreds of such cases in the production code.
-
Comments may help you to read the code, but will not make it much better when you need to modify it
Yes it will, because you don't have to read through the entire source code to figure it out. But comments are mainly for reading the source code. So what?
similar situation with much more complicated code and an outdated, misleading comment. I've seen hundreds of such cases in the production code.
That is when we are talking about bad comments. Why do you keep giving those examples? Allow me to demostrate a good comment. One example is a summary at the beginning of a source file. It's so much easier to read it than read the source code that you may or may not be able to understand fast. I've started to write summary myself only recently, but it's something I highly recommend.
//Teemu
//flypack.h - Copyright 2008-2016 Paul K. Pekkarinen (paulkp@mbnet.fi)
//Desc: Datatype to contain data of a flying object with the object handle itself,
//direction of trajectory and attempted distance.
#ifndef FLYPACK_H
#define FLYPACK_H
class Game_Object;
class GO_Creature;
class Level;
class Flight_Package
{
private:
...
For summary I've added 'Desc:' so you can find all summaries with that and find out what the source code is doing file by file.
-
Comments may help you to read the code, but will not make it much better when you need to modify it
You're wrong here: a comment is as much of a contract as an interface (in the programmatic sense). If the comment says that "this method will never return a null result" it sure is helping you change the code because if you start returning nulls then you're 99% likely to cause segmentation faults or null pointer exceptions somewhere else. The same goes with any other information in the comment.
Another example: if there is a slow cloning function and the comment says it's a a deep-clone operation, you're probably not going to make the mistake to rewrite it as a faster but shallow-clone operation - unless, of course, you're willing to change all the other affected areas of the code as well since this is a pretty big change in any project that benefits from cloning. In this way the comment is as important and helpful as the return type of the function or it's parameters signature.
-
Functions should be commented to describe what their overall point is. Otherwise buggy code won't make any sense to anyone. Even if the code is written in a very readable way it's no good if you make mistakes in the code iself.
But let's be realistic, in pet projects like these built up over many years both the code and the comments are likely to be heavily flawed. We should only be surprised by the fact that there are comments at all ;)
-
Here is another example of how I would comment code. This is again from Teemu. When you comment like this you don't have to read the code, only comments, to find out what the code is doing.
void T_Command::Show_Keyboard_Code(int x, int y)
{
//construct key and command names to char buffer 'ot' to display it
char ot[16];
int p=0;
const char ac=cmd_data[cmd].actual_key;
//get the letter of keycode and add possible ~ or ^ index before it
//for alt+ or ctrl+ commands
SDL_Keycode k=cmd_data[cmd].key_code;
const int mk=cmd_data[cmd].mod_key_code;
if (mk==kmCtrl) ot[p++]='^';
else if (mk==kmAlt) ot[p++]='~';
//save the position of letter in 'ot' for possible lowercase change
int sp=p;
//handle special cases to get shorter key names than SDL2 has
switch (k)
{
case SDLK_ESCAPE: p+=sprintf(ot+p, "Esc"); break;
default:
{
if (ac!=0) ot[p++]=ac;
else p+=sprintf(ot+p, "%s", SDL_GetKeyName(k));
}
break;
}
//lowercase SDL keyname for letters (which for some reason are uppercase in SDL2)
if (k>=SDLK_a && k<=SDLK_z)
{
//..but only if it's a lowercase command (shift not pressed)
if (mk==kmNone) ot[sp]=(char)tolower(ot[sp]);
}
ot[p]=0;
//draw the underline between letter and command name
const int xa=n_str->Get_Line_Width(ot);
const int w=64-xa;
const int fw=n_str->Font_Width();
const int fh=n_str->Font_Height();
SDL_Color scol=t_gui->guitheme.Get_Window_Border_Color();
const int px=(x*fw)+xa;
const int py=(y*fh)+fh;
for (int t=0; t<w; t+=3)
t_gui->Draw_Shape(shape::Filled_Rectangle, px+t, py-5, 1, 1, scol);
//show debug commands in green
if (Is_Debug_Command()) n_str->Set_Color(cEmerald_Green);
else t_gui->Set_Font_Color(geWindow_Font);
//show letter and command name
n_str->Write_To(x, y, ot);
n_str->Write_To(x+5, y, cmd_data[cmd].command_name);
}
-
This is terrible in my opinion. I don't often bother writing in-line comments, only function comments. if I were working on your code I'd start by changing this to:
/*
* Handles the information from #cmd_data, turns in into a proper letter and associated command and prints it.
*
* Receives x and y coordinates for printing on screen.
*/
void T_Command::Show_Keyboard_Code(int x, int y){
constructkeyandcommands();
handlemodifiers();
int lowercasecheck=p;
handlesdlshortkeys();
handlesdllowerkeys();
drawunderline(); //this and below should go to UI code instead
showdebug();
print();
}
Of course this is only a quick adaptation and I didn't consider problems with parameters and such and some of those functions could be merged into a single one if relevant, like handlesdl*. I would also then comment those functions as with the one above if I thought they would be used a lot.
Also from a code design point of view this function is taking way too many responsibilities. I would have totally separate functions to handle the input and others to print it for example. This is clearly a breach of controller/view responsibilities if you're into that sort of stuff.
Sorry if I'm being harsh - other than my personal style preferences your code seems pretty OK and better documented than usual. I've seen way worse code in my lifetime! But that's what happens when you post code and expect other's programmers to react honestly to it ;D
My main point here is, regarding comments: don't write comments when you can instead create a new function that is easier to read, more cohesive and easier to be re-utilized elsewhere. I hardly allow any functions to be longer than a screen-worth of lines when I write code. Sure, changing context makes functions somewhat expensive to process but I doubt it's gonna have any impact on a RL, especially a turn-based one - and if it does I'm pretty sure you can tell your compiler to inline these functions somehow.
EDIT there is an inline keyword for that http://www.cplusplus.com/articles/2LywvCM9/
-
Sorry if I'm being harsh - other than my personal style preferences
Who the fuck writes code like you just did? Are you seriously calling a function every time you do something? Do you have any idea what it's doing under the hood (well, other than the compiler trying to optimize away things like that some idiot is writing).
-
Who the fuck writes code like you just did?
Anyone who thinks readability is important, I guess? :D
Do you have any idea what it's doing under the hood (well, other than the compiler trying to optimize away things like that some idiot is writing).
Yes, I have! Which is why I touched on the subject in my post and why it isn't a big deal!
I was going to apologize for using the word "terrible" since that is not exactly what I meant but you're handling this so poorly I won't even bother ::) you need to be a little more open-minded if you're posting your code in a thread where people are discussing coding style! There will always be someone out there who doesn't like your approach... You could even use this as a learning opportunity instead of swearing at the replies.... (just an idea)
In honor of the D**mRL this thread is created for I've went in and found a function that looks a lot like my example, except with a few conditionals added in ;D Also if you look at that entire file there's like 2 or 3 functions that don't fit inside a screen-worth of height... even when they grow a little bigger it's not much more than that... https://github.com/ChaosForge/doomrl/blob/master/src/dflevel.pas#L212
Are you learning yet? ;D
-
Are you learning yet? ;D
No. You will learn some day I hope. Let's just say that the way you are using member functions in not very -functional-. Even in C++ functional approach is good in a limited way, mostly using parameters as generic structure (rather than return values). Splitting up everything in thousands of small functions is inefficient, harder to read in fact when you have to jump around reading all those small functions and also harder to debug. As you probably will find out sooner or later, it will also become a nightmare to manage the source code when it's getting to large scale.
-
Are you learning yet? ;D
No.
Aw that's a shame :D
the way you are using member functions in not very -functional
The word you're looking for is "procedural". C++ isn't a functional language (LISP is fun though - I like it, but I wouldn't use it to write a roguelike). About "procedural" though: I sure hope my code isn't like that, I mean it's almost 2017 not 1960 ;D
Splitting up everything in thousands of small functions is inefficient, harder to read
You're still ignoring my first reply to your code sample? ::) I'd rather take a page from D**mRL code than yours on this. I've worked with the style you're describing a lot (for example when writing patches for DCSS) and I know for a fact which of those I want in my own codebase.
"Smaller functions are hard to read". You sound kinda desperate now, don't you? I mean, if your code has files with thousands and thousands of lines then I'm sure it's hard to find a small function inside those but if you're properly organizing your code in relation to the responsability of each module and regarding high-cohesion, low-coupling directives then how is it possible small functions are harder to read and debug? Especially if you're using an IDE that visually indexes all of those function for you and makes jumping through stack frames while debugging super simple.
As you probably will find out sooner or later, it will also become a nightmare to manage the source code when it's getting to large scale.
As I've said I've worked with large codebases in both styles and I know for a fact that having long functions is more often than not a big pain in the ass to refactor, reutilize and alter without having to spend hours on it or causing unexpected side effects all over the code - especially when the function that handles user input takes screen coordinates (https://cdn.meme.am/instances/500x/66411344.jpg) as mandatory parameters... If that is the best one you found to show us how good of a programmer you are I shudder to think of the rest. The inline comments were nice though...
-
At least one of the people here doesn't release software, so.
-
The word you're looking for is "procedural". C++ isn't a functional language (LISP is fun though - I like it, but I wouldn't use it to write a roguelike). About "procedural" though: I sure hope my code isn't like that, I mean it's almost 2017 not 1960 ;D
I guess it goes like this most of the time. When I started programming in C++ about 11 years ago I also wrote lots of methods without parameters, because you get excited about the class scope. But as time has passed it starts to shift towards functional (or also known as procedural in real world terms) styles, which is sort of funny discovery if you think about it. Of course some people never evolve, they stay at the same place, repeating the same mistakes over again. What you actually want to do with classes is minimize the number of member functions and even use outside functions in generic style especially when they don't have side effects (pure functions).
-
At least one of the people here doesn't release software, so.
;D Case closed.
-
functional (or also known as procedural in real world terms) styles
The reason you can't use "functional" in this case even in"fantasy world" terms is because functional is a whole different programming paradigm, as opposed to the imperative approach used in procedural languages like C and C++ and most other popular and common languages, from Jave to C# to Python to Ruby to BASH. It's a common mistake though since it's easy to think "it has functions then it must be functional". - I've made this mistake myself more than once. Doesn't change the fact it's wrong though.
as time has passed it starts to shift
I think as with all things in life there is a balance to be found. You surely don't want functions having too many parameters (especially in a language where there are no optional parameters) and handling more than one responsibility when you could use different objects and methods for that instead. You also don't want code where you have several classes with only one method spread around dozens of files (unless they're very utility-like as with Comparator implementations).
Learning what good func procedural code is and what good object-oriented code is will let you choose the best approach for each problem, even in a single codebase. The same way you don't want to be using CGI to produce webpages when you can use a template system instead (like PHP and so many other template solutions for almost every conceivable language out there) or even a CMS like Wordpress .
Also, a disclaimer since this seems to be dying down for now: I don't claim I don't produce shitty code. I sure do! Time constraints, being tired, having to work with old code or previous implementations, etc or just plain making bad decisions will always lead to shitty code from time to time. I could easily find files that do not follow my own advice to post here. I'm just saying this before someone calls me a hypocrite or something ::) I do try to produce code that is in alignment with what I consider to be good practices but I don't always succeed.
-
It's a common mistake though since it's easy to think "it has functions then it must be functional".
Well, now that you mentioned, yes, it is. Remember, C++ is a multi-paradigm language.
Also, a disclaimer since this seems to be dying down for now: I don't claim I don't produce shitty code. I sure do!
Also good to remember that release rate and code quality are two different things. Game programmers for sure are notorious for writing quite bad code. The amount of bugs can be a telltale sign of bad programming. My approach is famous "zero bugs release". I think current release version of Teemu did have one bug (+couple of potential bugs), but that's how it is sometimes. But the current dev version is actually even better in code quality. You'll see it soon.
-
Coding arguments remind me of the old days of rgrd... What language do you think is best, guys? ;)
-
C++ is a multi-paradigm language.
My approach is famous "zero bugs release".
You're rich, man. Show me your declarative C++ code and keep thinking your code has zero bugs. Meanwhile I'll be hanging out with my very real honest girlfriend Angeline Jolie and balling with my 0% fake home boy Kanye.
Darren I'm not sure if your question is troll bait or not but I think that could be a good discussion, considering this thread has been derailed from the very start ;D which ones do you use for your 7DRLs? Did you ever change languages for them along the way and if so why?
-
Darren I'm not sure if your question is troll bait or not but I think that could be a good discussion,
It was a joke. Coding styles and language choices are personal things, and arguments over them are a pointless waste of time.
Arguing with Krice is often quite futile too :P
-
Coding styles and language choices are personal things, and arguments over them are a pointless waste of time.
You could say that about anything. What is even worth discussing, then? Where I'm from there's a saying that goes " anything is worth it if you got enough soul". Wisdom is found on unexpected places and I don't see discussion about something that is directly related to my hobbies and interests as waste of time. I guess as long as no one's hurt and we're all being polite then discussing these very topics is probably the reason why this forum came into existence to begin with?
Arguing with Krice is often quite futile too :P
I noticed that. One can always hope that more constructive fellas will join in on the conversation at some point though or take something away from reading it.
-
Darren I'm not sure if your question is troll bait or not but I think that could be a good discussion,
It was a joke. Coding styles and language choices are personal things, and arguments over them are a pointless waste of time.
Arguing with Krice is often quite futile too :P
int i, j, k in that order. Anything else is heresy and has direct, negative empirical results for code performance.
-
direct, negative empirical results for code performance.
You are wrong and I'm triggered - anyone with an inch of brain in their skulls knows this is nothing compared to not properly using camel case to name functions, parameters and variables!!
-
direct, negative empirical results for code performance.
You are wrong and I'm triggered - anyone with an inch of brain in their skulls knows this is nothing compared to not properly using camel case to name functions, parameters and variables!!
War may or may not be declared on the basis of first letter capitalization.