Tuesday, March 29, 2011

PK Poll

A lot of people have been vocal about the perceived imbalance in our current PK code, so in the interests of getting a lot of one-click feedback, I've opened a poll (should appear to the right) regarding the matter. Please leave comments below.

April 5, 2011: The results are in!
  • 62% felt that spellcasters need a boost
  • 34% don't PK
  • 31% felt it seems pretty balanced
  • 21% think fighters need to be toned down
  • 18% feel fear is too powerful
  • 12% think guild spells make fighters too strong
This was out of a total of 32 votes.

Although we have no immediate plans to change the fighter/spellcaster dynamic (we have a lot of other changes in the works that need to be finalized before then), we will revisit these results and the comments posted and see if we can adjust accordingly.

Monday, March 28, 2011

Crying and complaining about coding

One of the hardest parts of coding for Dark Risings is the fact that it's derived from code that is over two decades old (Diku was first released in 1990) and, even after transforming into the ROM 2.4b6 codebase (released in 1998), it's been hacked on by twelve years of Dark Risings coders. As much as I hate to say it, the greatest amount of damage to the code has, in fact, been done by the long history of DR coders of varying levels of familiarity with both C and how ROM works.

What's prompted this whiny rant is a problem I discovered while generating a list of all of the scrolls in the game for Sidonie. I'd already done this with wands and staves with the help of a little Perl magic that I wrote, so I expected it to be another straightforward five-minute job. In a sense it was, but upon examining my data dump, I noticed that some scrolls had four spells (some of which are listed as "reserved") and others have blanks where spells should've been. Thinking that my Perl script was defective, I checked the area files themselves, and sure enough, some scrolls have "reserved" and others are just "". What's the difference? Since this sort of ill-defined behavior can lead to major issues (area/pfile corruption, crashes, etc), I started digging and was brought to one particular routine that made me a little crazy.

Consider the following code, straight out of the Dark Risings source:
/*
* Lookup a skill by name.
*/
int skill_lookup( const char *name )
{
int sn;

for ( sn = 0; sn < MAX_SKILL; sn++ )
{

if( skill_table[ sn ].name == NULL )
break;

if( strcasecmp( name, skill_table[ sn ].name ) == 0 )
return sn;

/*
if ( skill_table[sn].name == NULL )
break;
if ( LOWER(name[0]) == LOWER(skill_table[sn].name[0])
&& !str_prefix( name, skill_table[sn].name ) )
return sn;
*/
}
...
For whatever reason, a past coder decided it best to comment out the stock bits of this subroutine, presumably to force the subroutine to match the whole skill/spell name instead of allowing abbreviation (which can cause issues when you have spells like "lightning bolt" versus "lightning breath").

This sort of thing drives me crazy for many reasons, but here's one.

The stock version of the code was smart; it first checked the first character of the argument against the first character of the entry under examination in the master skill table. Since there's a very large chance that those first characters won't match when ripping through all 298 skills, you wind up not having to incur the overhead associated with a full-on subroutine call for the majority of the misses. This makes the whole process of finding a skill and returning its associated skill number much faster.

Perhaps I am more mindful of the benefit of these tiny performance benefits since I write very computationally intensive scientific code, where one poorly written line of code can add days or weeks onto compute time, for a living. And perhaps there really is no appreciable speed benefit to not preserving this preliminary first-character check when matching strings on modern hardware. However, I see little reason to pull it out outright since it is a smart way of handling these sorts of lookups.

Furthermore, the str_prefix routine (provided with ROM) was replaced with strcasecmp, which is intrinsic to string.h. However, whoever did this code change must have been extremely unfamiliar with ROM's internals (or perhaps extremely tired), because ROM provides str_cmp, its own equivalent to strcasecmp which is used extensively (and I mean extensively) throughout the code.

If strcasecmp and str_cmp serve the same purpose, why do both exist? As it turns out, strcasecmp is indeed included in string.h, but it is not ANSI C (although it is POSIX 2001). POSIX didn't exist back when Diku was first released (and neither did GCC or glibc for that matter), so it's likely that the str_cmp routine was written into the code decades ago. Providing this routine made the code more portable by not having to rely on special extensions that only existed in specific proprietary compilers. It was also tailored specifically to the needs of the code.

For the sake of consistency and portability, str_cmp (which is probably a little faster than strcasecmp) has been used exclusively in ROM's source. Unfortunately, DR's code has become rife with a sloppy mix of strcasecmp and str_cmp, forfeiting the benefits of portability while gaining literally nothing. As DR coders have touched the code, they've left these marks across it without really considering what the implications may have been.

True, since strcasecmp is now POSIX, it is unlikely that Dark Risings will ever be run on a system without it (e.g., DR compiles on HP-UX 11i, which predates POSIX 2001), but this is only an innocuous example. This sort of messy work, where one feature is implemented many times because various coders were ignorant of their predecessors' work, are all over the DR source, and it drives me a little nuts. I could go through and change all those strcasecmps to str_cmp, but to do so would require quite a bit of testing and would open the doors to new bugs. When it comes down to spending time cleaning up code which will not introduce any new features to the game or spending time adding new features while leaving the existing problems as they are, I find myself always choosing the latter.

Nobody cares if our code reads like garbage as long as that garbage is transparent to the players and imms, so I guess I'll have to take out my frustrations on this blog. It probably doesn't help that I spend my entire day at work cleaning up garbage FORTRAN.

Monday, March 14, 2011

Game Mechanics Q&A

A while ago we answered a number of questions about the rumors that surround game mechanics. They've recently expired off of the ideas board, so someone asked us to make them permanent somehow. Here they are.

Q: Does dex factor into the CLEAR command working?
A: No. It's just a flat % chance.

Q: Is it possible for second attack (or third attack, fourth attack, etc.) to go up without using practices?
A: It is possible if you have first used rage, though we don't quite remember if rage will work this way for all the attacks. We'll figure it out when we get to those helpfiles.

Q: Do stats have any effect on how successful you are at learning trades?
A: No.

Q: Does intelligence help you land spells?
A: With the sole exception of the forget spell, no. For now.

Q: Is blind mental, and does that mean orcs and ogres are vulnerable to the spell?
A: Blind is not mental. It is magic. Races that resist magic resist blind, but it should be noted that the resist bonus for this type of spell is small.

Q: Does wisdom help you resist spells?
A: Wisdom has nothing to do with resisting spells. The vast majority of spells only check the victim's saves and racial adjustments (resist/vuln).

Q: Does having high saves help you land spells?
A: No. The caster's saves have nothing to do landing spells.

Q: Does constitution help you push?
A: No, but strength does.

Q: Should we bother with armor class (AC)?
A: At level 50, I would say not. Basically, in order for you to get the minimum AC necessary for it to be useful, you would need many thousands (like better than -5000) of AC. This is because the game is built around the idea of 8 hitroll being awesome. As soon as awesome hitroll got moved from around 8 to around 80, AC became an irrelevant stat, because nobody can possibly get the huge AC needed for it to matter.

AC is useful at low levels though, because you will be fighting mobs who have such low hitrolls that your AC will actually do something for you. Casting your armor/shield/stoneskin spells while levelling will help you a lot.

This is something we may consider opening the door to changing in the future.

Q: Does dexterity help you land melee blows?
A: Dex does not help you land melee blows. It does factor into your AC, but see the previous question for an explanation as to why this winds up having no effect.

Q: What is dexterity useful for?
A: Dexterity is most useful for landing (and defending against) dirt kick, and for defending against barbarian skills.

Q: What are the bonuses to two-handed weapons?
A: You get a bonus to parry while wielding polearms, spears, and staffs. Typically, two-handed weapons have higher stats than ordinary weapons since they get extra points for builders to allot.

Q: How does dispel magic work?
A: The first check is a flat saves check. If the victim makes his saves check, the caster sees "You failed." If the dispel is landed, each affect on the victim is checked. Essentially, the effectiveness of this second check depends on the level of the affects on the victim. If the level of all affects on the victim are too high to dispel, the caster will see "Spell failed." However, this also indicates that a high-level spell affect had its level lowered, making it easier to dispel in subsequent casts. Each spell affect is independently checked of the others, so it casting a weaker spell on a victim first won't help you dispel other affects.

Q: Is there a 'cap' at which point having more saves, hitroll, and damroll is pointless? If so, what is it?
A: There is no cap on hit/dam. More is always better. It's a little more complicated for saves. Check out this post; there's a bullet called "There is no cap for hit, dam, or saves" which provides a more detailed answer.

Q: How much difference does having the weapon skill you're defending against make?
A: None. There was a myth that if you were skilled in the type of weapon your opponent was using, that you would get a bonus to parry, but although that is an interesting concept, it isn't true.

Q: Does intelligence/wisdom affect mana regeneration?
A: Yes and yes.

Q: Does constitution affect hp regeneration?
A: Yes.

Q: What is the difference between enhanced damage and critical strike?
A: They're completely different skills. Critical strike is pretty rare, even at 100%, but when it does work, it adds a lot more damage to a hit. Enhanced damage at 100% adds a small amount of extra damage to every successful hit.

Q: What are the real effects of having the sharp and vorpal flags on weapons?
A: Sharp is awesome. It gives a significant chance of doing more than double damage. Vorpal literally does nothing. This is subject to change in the future.

Q: What is the chance of shattering someone's shield?
A: Although we are going to be answering a lot of questions about how things work, we don't want to get into specifics about exact chances or formulas, etc. There is -a- chance that it will work, providing the shield isn't unbreakable.

Q: Does the fear spell remove one extra attack?
A: No. It cripples second attack and outright removes third, fourth, and fifth attack. It doesn't affect extra attacks granted by spells such as haste.

Q: What about web, how does it work?
A: Web prevents the victim from moving or fleeing until the web is broken. Strength and dexterity impact a victim's ability to break free.

Q: Do templar maledictions cast at a higher level and land at a lower level?
A: No. However, judgment does have a higher chance of landing than regular maledictions (such as curse, blind, etc.). This was done to balance the penalty templars suffer in not being able to cast specific maledictions.

Q: How does chaotic dispersal compare to dispel magic?
A: There are chances that CD will cast at a much higher level, making it much more effective than a regular dispel. There is also a chance that it will dispel the caster.

Q: Wild summon is supposed to have the chance of doing something great if it works. What's the extra affect?
A: There are two affects. One very significant one is that the victim does not know he is being summoned. The other is that there is a small chance that the summoned person will be blinded during the summon.

Q: What's the purpose of giving constitution to adrenaline rush?
A: Adrenaline rush, like haste, slows down hp regeneration. Since higher con helps hp regen faster, I would say the Con boost is there to balance out the haste penalty to hp regeneration.

Q: Does energy drain have the same chance of landing as blind?
A: Yes.

Q: What is the minimum recommended saves for blended classes?
A: Saves requirements for blended classes are determined by how much mana a class gets per level. If you're getting about 10 mana when you level, you're considered a magic class as far as saves go. If you're getting about 5, then you have the saves requirements of a fighter class. Simple as that.

Q: Do some races/classes cast at higher or lower levels?
A: With the exception of a very few spells, no. Everyone casts spells at his level. One related thing of note: spell affects diminish over time. For example, when I cast curse on myself, I get -7 to hit and +7 to saves, and the affect is at level 60. As the spell ticks down though, its level decreases in addition to its duration, making it easier to dispel.

Sunday, March 13, 2011

More Player Stats

The Dark Risings census and other miscellaneous stats on our official webpage are a bit out of date, and since team admin is in the process of renovating that site, I figured I should generate some new stats. Since the new site isn't ready to go yet, I'll upload them here for the time being.

Guild Statistics

  • Of all of the mortals, only 5.03% are guilded. However, of all level 50 characters, 9.64% are guilded. This number should ideally be higher, as we like people to be involved in guilds.
  • Of all guilded mortals the three most populous guilds are Dawning (23%), Gypsy (20%), and Covenance (17%).
  • The most exclusive guilds are Inferno (10%), Arcaenum (13%), and Vermillion (15%).
  • Interestingly, these least populous guilds are designed to be the most exclusive as well. That is, they aren't necessarily the least popular

General Census

  • Of all characters, 75.7% are male, 22.5% are female, and 1.9% are neither
  • Of level 50's, 77.8% are male, 20.9% are female, and 1.2% are neither
  • Of all characters who aren't level 50 yet, 73.4% are male, 24.1% are female, and 2.5% are neither
  • Does this mean girls are bigger quitters than guys?

Werecreature Stats

  • Of all mortal characters, 13.8% are werecreatures
  • Of all level 50 characters, 20.9% are werecreatures (an impressive fraction!)
  • Of all werecreature characters who haven't hit level 50 yet, over half (55%) haven't even gotten to level 30--that is, they don't even know that they're werecreatures yet
  • Of all mortal characters, 5.8% are werecreatures who haven't hit level 30 yet

Highest play times at level 50

 1.      Sintar 6239
2. Adi 4087
3. Tiea 3972
4. Ravindra 3489
5. Mellyrnna 3133
6. Zyggi 2609
7. Yuneo 2459
8. Sutherland 2376
9. Argban 2164
10. Donovan 2024
11. Divinicus 1863
12. Sagoth 1734
13. Brunne 1707
14. Senara 1634
15. Shadowmoon 1615
16. Xanaphia 1613
17. Vaanderun 1606
18. Maaz 1597
19. Rehanea 1571
20. Parisa 1559
Dilaver 1553
Tamlin 1541
Zerikial 1517
Amenia 1495
Kamille 1453
Cailet 1425
Madelaine 1417
Flocrian 1370
Lena 1368
Akemi 1361

Most experience at level 50

 1.  Shadowmoon 3872186
2. Xilokerym 3600337
3. Reilyn 3520363
4. Macainay 3480307
5. Azael 3480293
6. Lasrael 3432018
7. Avidician 3404568
8. Prechu 3220008
9. Madarchod 3192000
10. Radys 3108133
11. Xukuth 3108062
12. Econicue 3000404
13. Derevoc 2904153
14. Hager 2772372
15. Finn 2688013
16. Xianthian 2604451
17. Virstrel 2464235
18. Rakkashavas 2400338
19. Errol 2376025
20. Kenthur 2340123
Lastur 2300064
Anglameil 2208000
Varongril 2200100
Zachariah 2184014
Farris 2112000
Greleil 2080124
Orazbahgn 2024272
Drackion 2024145
Beranon 2024031
Salvatori 2016263