Author Topic: clean code  (Read 29055 times)

tuturto

  • Rogueliker
  • ***
  • Posts: 259
  • Karma: +0/-0
    • View Profile
    • pyherc
clean code
« on: August 09, 2012, 04:57:00 AM »
I have been poking around with roguelike development for a bit and started wondering if anyone would know really good examples of cleanly written games. I'm mainly looking for a big picture, not so much single algorithms. You know, how to make system for magical effects that isn't completely hard coded or how to add new actions into game easily.

It would be nice if the game had some other documentation than source code too, but that's not mandatory.

Any suggestions or ideas where to start?
Everyone you will ever meet knows something you don't.
 - Bill Nye

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: clean code
« Reply #1 on: August 09, 2012, 08:30:51 AM »
how to add new actions into game easily.

What means "easily"? Some actions are harder to add than others. The engine can make some things easier to add, but programming a good engine is hard or at least seems to be so in roguelike games. I think the reason is that most hobbyist programmers are unaware of more advanced techniques that would make it easier to handle large scale programs and complex gameplay requirements of a roguelike.

Darren Grey

  • Rogueliker
  • ***
  • Posts: 2027
  • Karma: +0/-0
  • It is pitch black. You are likely to eat someone.
    • View Profile
    • Games of Grey
Re: clean code
« Reply #2 on: August 09, 2012, 08:40:47 AM »
I'm not sure any such game exists, but you could have a look at ToME4, which does a good job of separating things out and has an active modding community that add classes, spells, etc.  It's all in Lua, and is fairly easy to follow, but isn't commented very thoroughly.

kraflab

  • Rogueliker
  • ***
  • Posts: 454
  • Karma: +0/-0
    • View Profile
    • kraflab.com
Re: clean code
« Reply #3 on: August 09, 2012, 10:02:26 AM »
Epilogue is such a game.  So easy to add new abilities or monster interactions that I surprise even myself at times.  Closed source though!  ;)

Quendus

  • Rogueliker
  • ***
  • Posts: 447
  • Karma: +0/-0
  • $@ \in \{1,W\} \times \{1,H\}$
    • View Profile
    • Klein Roguelikes
Re: clean code
« Reply #4 on: August 09, 2012, 10:35:12 AM »
If the hundreds of variants are anything to go on, Angband is such a game. All the C code is very well-commented, all the monster and item definitions are in plaintext files, and it's pretty easy to find which file has which functionality by running a fulltext search on the source directory. The magical effects are "hard coded", but in a very flexible way - for instance a fireball is just a spell that applies fire damage to monsters and floor items in a specific radius of the target square.

Sil is a more recent example of what can be done with the Angband engine.

tuturto

  • Rogueliker
  • ***
  • Posts: 259
  • Karma: +0/-0
    • View Profile
    • pyherc
Re: clean code
« Reply #5 on: August 09, 2012, 03:57:40 PM »
Thanks, I downloaded source for both and started looking around a bit.

On a first glance, Sil isn't quite what I'm after. Code is well commented and nicely structured, but for example describing attack method and applying special hit chance mods (make_attack_normal in melee1.c) has a long switch-case - section, where it is taken care of. If I wanted to add a new attack method, I would have to modify that code, instead of just adding a new class or function and letting the program to know where to find it.

ToME4 looks interesting too, but that takes a bit more poking around to guess what's going on. It's probably closer to what I'm after. In any case, I'll read some more of both sources, it's always interesting.

Krice, by "easily" I meant a system where one wouldn't necessarily have to change existing function / class / what-else-construct to add new functionality, but it would be taken care of in some dynamic way.

kraflab, Epilogue sounds interesting, but can't really source dive that :)
Everyone you will ever meet knows something you don't.
 - Bill Nye

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: clean code
« Reply #6 on: August 10, 2012, 06:05:47 AM »
Krice, by "easily" I meant a system where one wouldn't necessarily have to change existing function / class / what-else-construct to add new functionality, but it would be taken care of in some dynamic way.

This is what "engine" is designed to do. There is no hard coded decisions in the code that handles game objects which means you can simply add new types of game object and the engine takes care of it. However it's not always that simple, because the engine could need new functionality to handle a new type of game object anyway.

tuturto

  • Rogueliker
  • ***
  • Posts: 259
  • Karma: +0/-0
    • View Profile
    • pyherc
Re: clean code
« Reply #7 on: August 10, 2012, 06:38:29 AM »
Yes, and I'm interested seeing how others write that in a way that the new functionality is easy to add and involves minimal amount of editing of old code. If you check melee1.c in Sil's sources, there's code like:

Code: [Select]
/* Describe the attack method, apply special hit chance mods. */
switch (method)
{
case RBM_HIT:
{
        ...
}
case RBM_TOUCH:
{
act = "touches you";

// ignores armor
prt_percent = 0;

// can't do criticals
no_crit = TRUE;

break;
}

case RBM_PUNCH:
{
act = "punches you";
do_stun = 1;

// stopped by armor
prt_percent = 100;

break;
}

case RBM_KICK:
{
act = "kicks you";
do_stun = 1;

// stopped by armor
prt_percent = 100;

break;
}

which works and is easy enough to edit. But if you wanted to add something new, you would have to add it to that select-case - section, instead of just coding it as a stand alone unit and telling the system to use it.

Or if somebody would want to make a variant, which works pretty much the same as the original system, but kicks (for some reason) are not stopped by armour. In the example, this would be achieved by editing original code. When new version of original code is released, the variant has to merge the two codebases so that they have new functionality of the original plus their changes.

However, if the stuff that variant does differently was written in own location and the engine was told to use that one instead of the original, merging would most likely be much easier.
Everyone you will ever meet knows something you don't.
 - Bill Nye

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: clean code
« Reply #8 on: August 10, 2012, 09:03:46 AM »
That switch-case code could be easily transformed to data-driven style by creating a datatype for attack styles with information contained in that class, then operated through verbose public interface. That way in optimal case when a new attack type is added all you have to do is edit one class or just add a new data entry for it.

Sil's code is definitely the old school C style with linear approach to coding. It's not bad I guess, but I like data-driven style: data types with public interface, because it "always" works in the source code no matter where it's used.

With datatype all that code would be replaced by this:
Code: [Select]
act=method.Get_Action_String();
prt_percent=method.Get_Protection_Percent();
do_crit=method.Is_Critical_Hit();
do_stun=method.Is_Stunning();

And new stuff would be added to method class.

ps. Also if you need stuff like do_stun only once, you can remove assign to a variable and use it directly:
Code: [Select]
if (method.Is_Stunning())
{
  //do stuff
}
« Last Edit: August 10, 2012, 09:41:33 AM by Krice »

tuturto

  • Rogueliker
  • ***
  • Posts: 259
  • Karma: +0/-0
    • View Profile
    • pyherc
Re: clean code
« Reply #9 on: August 10, 2012, 03:20:42 PM »
Yes, that is somewhat more what I'm after. Would still push stunning to be an entity of its own (either class or function). Poisoning and stunning are just status effects after all that have slightly different behaviour, so it might make sense to model them like that.

Maybe I should try some java-based games, since it's object oriented language. Might have more luck there than with pure C.
Everyone you will ever meet knows something you don't.
 - Bill Nye

XLambda

  • Rogueliker
  • ***
  • Posts: 208
  • Karma: +0/-0
    • MSN Messenger - tau_iota@live.de
    • View Profile
    • The Weird Rogue
Re: clean code
« Reply #10 on: August 10, 2012, 05:54:46 PM »
Yes, that is somewhat more what I'm after. Would still push stunning to be an entity of its own (either class or function). Poisoning and stunning are just status effects after all that have slightly different behaviour, so it might make sense to model them like that.

Maybe I should try some java-based games, since it's object oriented language. Might have more luck there than with pure C.

No kidding. I mean, C still has its purposes (it's important for OS and embedded systems), but it's generally harder to use than OOP languages. (Despite whatever Torvalds says. :p) It's not so bad at small sizes, but big projects really suffer from it.
« Last Edit: August 10, 2012, 06:05:29 PM by XLambda »

tuturto

  • Rogueliker
  • ***
  • Posts: 259
  • Karma: +0/-0
    • View Profile
    • pyherc
Re: clean code
« Reply #11 on: August 13, 2012, 12:29:14 PM »
It's been interesting to read loads and loads of source code written by others.

I came across blog of Trystan and he seems to be quite tidy code. I only found two 7DRLs by him though. Would anyone happen to know if he has written more of them or even a full blown roguelike?
Everyone you will ever meet knows something you don't.
 - Bill Nye

Leaf

  • Rogueliker
  • ***
  • Posts: 64
  • Karma: +0/-0
    • View Profile
    • Email
Re: clean code
« Reply #12 on: August 14, 2012, 05:34:40 PM »
I think the cleanest way to implement a game like this would be to use an OO language to build an engine with an event-driven paradigm around various interfaces.  Perhaps with some sort of compositional object model to get rid of the boilerplating problem.

Java and C# would do it pretty well.  C++ would do it but might get messy.  Old procedural languages like C, forget it. :3

TheCreator

  • Rogueliker
  • ***
  • Posts: 370
  • Karma: +0/-0
    • View Profile
    • Fame
    • Email
Re: clean code
« Reply #13 on: August 15, 2012, 07:16:59 AM »
Java and C# would do it pretty well.  C++ would do it but might get messy.  Old procedural languages like C, forget it. :3

When the programmer is dumb, it will get messy no matter which language is used. But I agree on procedural languages, they're history :).
Fame (Untitled) - my game. Everything is a roguelike.

tuturto

  • Rogueliker
  • ***
  • Posts: 259
  • Karma: +0/-0
    • View Profile
    • pyherc
Re: clean code
« Reply #14 on: August 15, 2012, 12:44:49 PM »
I think the cleanest way to implement a game like this would be to use an OO language to build an engine with an event-driven paradigm around various interfaces.  Perhaps with some sort of compositional object model to get rid of the boilerplating problem.

That is quite high level, could you elaborate it a bit?

On another note, I have been reading through Trystan's blog and he seems to have good ideas about developing roguelikes (and software in general). Maybe I'll get code for his roguelike tutorial later today and have a look at there too.
Everyone you will ever meet knows something you don't.
 - Bill Nye