Casual Quest

by IainPeregrine
A fast paced, casual, multi player action game with a little RPG touch
ID:287925
 
Resolved
Fixed bug that caused scores to be deleted instead of submitted. Improved score handling.
BYOND Version:N/A
Operating System:Windows 7 Pro 64-bit
Web Browser:Firefox 14.0.1
Applies to:Casual Quest
Status: Resolved (1.35)

This issue has been resolved.
WHY DID IT GET RESET AGAIN?? >:(

PRETTY MUCH EVERYONE WITH A 200 CONSESCUTIVE WAVE SCORE ISN'T ON THE SCOREBOARD ANYMORE.

RIGHT NOW, I HAVE ONLY 5 CONSECUTIVE WAVES ON THE SCOREBOARD, WITH MY 200 RUN OFF THE CHARTS.


I thought that shit was supposed to be fixed :(
That was pretty much our reaction too, without all of the caps locks. It's in the other thread, the one with all of the posts.
In response to Altrez
While I do agree with Altez, D4 does have a good point - this is not a permanent fix, and if anything, will only work until the scoreboard decides to crash itself again. At that point, all us players that play all the time will just lose our scores again.

So... I guess my question is... what now? D4 mentions that it is fairly simple to reset the scoreboard, but to always do that is going to be fairly annoying. Not to mention that we STILL have no idea as to what could be crashing the scoreboard in the first place.

That said - anyone got any ideas as to what we can look for so we could narrow down our scoreboard crashing cause?
I've searched constantly and can't find the source to the error. I found the initial error, but now it seems to be bugging on people who hit wave 200. Is this generally the only cause you all have noticed? Is there any other information you might have available?
In response to Sudzzuds
Like Caution said,it most likely has to do with wave 200. Maybe something regarding the inability to achieve score after 200,something in that code might be messing it up.
In response to CauTi0N
CauTi0N wrote:
I've searched constantly and can't find the source to the error.

Go back to basics. All programs are just Input -> "Magic!" -> Output. The problem is in the "Magic!"; that's where bugs live.

Cut out the magic. Find the spot where scores are sent to the hub, and comment out that line. Replace it with a line that sends a score to the hub on the key "Squirrels" with the high score "999999" and other scores like "999" consecutive waves. That's your "sanity check". If you've isolated the ONLY line that updates the hub, then this should work. If I did my job properly, then there should be only one place where scores are updated, and one place where medals are awarded. This is part of the importance of modularity.

Now you move down a step. Identify the specific message that clears a score when it is sent to the hub. Look it up in the reference, I mean. If I remember correctly, anything that would evaluate as FALSE will clear the scores from a key. So delete the squirrels line and un-comment that score setting line. Now you have to ask "under what circumstances will this line send a blank message to the hub?". Maybe the proc that this line is in simply passes along a value that it was passed as an argument. So now you have to track that argument back to all places it was called from, and ask the same question again.

Keep doing sanity checks, keep working backwards. You won't be able to fix a bug by digging into the middle of the code in random places and trying to sniff it out. You have to think like a computer, but in reverse. Start at the output and work backwards.
In response to CauTi0N
Edit: See the line with the comment in the code box. Is this line present in your version? Bloody stupid nonsense is most easily overlooked. Could have saved me an hour of writing.

I've thought for a while that this error was directly related to customs. D4 will probably remember me asking if this bug has ever effected anyone without a custom, or if it seemed that me being around gave rise to it much more often (because I change people into weird stuff).

I just took another look at the code, which may be out of date with your version, and saw a suspect line. This is the proc in question:
update_hub(){
set waitfor = FALSE
if(!hub_scoring){ return}
if(copytext(ckey, 1, 6) == "guest"){ return}
if(!update_wave && !update_score && !update_waves && !total_score){ return}
var/update_text = {""}
update_text += "Score=[high_score];"
update_text += "Wave=[high_wave];"
update_text += "Consecutive Waves=[high_waves];"
update_text += "Total Score=[num2text(total_score)];"
update_text = "" // <--- This one.
var/result = world.SetScores(key, update_text)
if(result){
update_wave = FALSE
update_score = FALSE
update_waves = FALSE
}
}


This is the only place where world.SetScores() is called. This proc is, in turn, only called in three different places: It is called on all clients when the game has been lost ("Game Over"); It is called on all clients when the world shuts down (to prevent a shut down or reboot from screwing a player out of a high score); it is called on a client when it logs out.

Note the three variables: update_wave/score/waves. These variables exist because BYOND hub scores suck; I'll explain. If a player get a score of 100 and the game sends this to the hub, great! The hub now displays a high score of 100. If a player then gets a score of 50 and sends this to the hub, not great! The hub now displays a high score of 50. So the game has to check the high score before updating, and compare that to the current score. This uses bandwidth, and has the potential to increase lag if lots of players are doing this at the same time. Also, what happens if the hub cannot be contacted temporarily? Any number of hiccups could cause that to happen, in which case scores would be thrown out.

So my solution is to check clients' high scores as they log in, and store these. If the game fails to contact the hub, their "hub_scoring" variable is set to FALSE, and the update_hub() proc will bail out for these clients.

Now that we know if a client is hub_scoring or not, and what its current high score is, we can compare the score they just received against the high score, and determine if we should send a message to the hub. This is done in the award_score() proc:
award_score(var/amount){
total_score += amount
score += amount
if(score > high_score){
high_score = score
update_score = TRUE
}
}


You'll notice that this is one of only two places where the update_score var is set. Here it is set to TRUE only if the current game's score is higher than the client's previous high_score.

The system is supposed to work like this:
  • Client logs in. The hub is contacted. If contact is made then the previously achieved scores are stored on the client, and the var "hub_scoring" is set to TRUE. If contact cannot be made, "hub_scoring" is set to FALSE.
  • Whenever a hero is awarded points during or after a wave the proc award_score() is called with the amount of points. The amount is added to the total_score (more on this later) and score variables. If the client's current score is greater than its high_score, then high_score is set to the current score, and update_score is set to TRUE.
  • At the end of a game (or when the world or the client disappears) update_hub() is called on each client.
    • If the client isn't hub_scoring, return.
    • If update_wave, update_score, update_waves, and total_score are all null, then return. (In other words, don't update unless we need to update).
    • Construct a message using the different high scores and send it to the hub.
    • Clear the three update variables. This tells the game that the hub no longer needs to be updated.


So, what do we know for sure? (Well, almost for sure; you should always do some sanity checks on the things you know "for sure" before proceeding):
  1. We know that hub scores are being cleared.
  2. We know that hub scores can only be cleared by calling SetScores().
  3. We know that our program is the only one calling SetScores() (you can double check this by making sure that we have a hub password, and that the hub entry requires authentication).
  4. We know that SetScores() is only being called in this one place: update_hub().
  5. Take a moment to look at the code and confirm that the SetScores() is always being given a non-null value for update_text, which is composed of four parameters with embedded variables as values.
  6. So we know that in order for hub scores to be cleared, these values have to be null (or at least small, which would cause the player's score to drop near the bottom of the list and appear to be "cleared" away).
  7. We know that in order for this part of the code to be reached, the player must be hub_scoring, which means that the player's previously achieved high score was retrieved and stored successfully. (Check retrieve_scores() and do a search for "hub_scoring" in all files to confirm this for yourself).
  8. We know that one of the four variables {update_wave, update_score, update_waves, total_score} must store a value that evaluates to TRUE in order for this part of the code to be reached.


Consider how if any one of those four variables holds a value that evaluates to TRUE, then all four parameters are sent to the hub. This means that if there is ever a time when a (hub_scoring) client reaches a new highest wave, but that client's high_score holds a value lower than the proper value (or null), then the client's hub scores will be "cleared". Is this possible? The answer is yes, because 1: We've ruled out all other ways that the hub could get cleared; read the list of "what we know" again if I wasn't clear that that is why I was writing it; and 2: We all observe that is is happening (bug reports).

Note, however, that I thought I had put safeguards in place. That section of code is only ever reached if a client is hub_scoring. If a client is hub_scoring, then their high_score was successfully retrieved from the hub. The high_score variable is never set to a lower value than what it currently holds. Therefore, a hub_scoring client will always have a correct high_score value.

The bolded statement is incorrect. I don't know how it can be, but we've proven that scores are being reset, so it must be false.




Even though one of our assumptions is incorrect (or my logic is incorrect), we may be able to plug up this hole another way. The whole "total score" thing was added after the other three scores, and wasn't part of the original system. By removing all parts of the code that deal with total score (comment them out, don't delete them) the bug may go into remission. Total score doesn't work properly, and I've been meaning to remove it from the hub, anyway.
In response to IainPeregrine
Okay.... my brain just blew up and went into another system.

For starters, that line that Iain commented out did look super weird. Correct me if I'm wrong, but that one line pretty much undoes the four lines above it. Mind you, Caution did say that he saw something in the code and corrected it, so perhaps this was it. (Although this begs the question as to how we had a scoreboard to begin with, since that one line means that our scores would have been wiped every time the scoreboard could not be accessed [or something like that?])

The reason why I was asking about the Total Score thing was because I was wondering whether it is possible that the Total Score variable (I'm going to assume it to be some sort of integer variable) was getting overloaded. I did flunk out of Computer Science, but I seem to recall that computer integers are not indefinite. Of course, the Total Score on the hub may not even be an integer variable to begin with, so this may not necessarily apply. It's just that I know that Diclonius has been playing a LOT before the scoreboard crashed, to the point where he had a Total Score that was in the exponential range: 1.~~~~~~e+006 or something like that.
In response to IainPeregrine
IainPeregrine wrote:

So my solution is to check clients' high scores as they log in, and store these. If the game fails to contact the hub, their "hub_scoring" variable is set to FALSE, and the update_hub() proc will bail out for these clients.


What's the case when the new player doesn't yet have a score, or it was cleared out? If it returns null, then you're preventing them from ever getting a new score posted. So long as it returns anything else it's fine though.
In response to Sudzzuds
Sudzzuds wrote:
Okay.... my brain just blew up and went into another system.

For starters, that line that Iain commented out did look super weird. Correct me if I'm wrong, but that one line pretty much undoes the four lines above it. Mind you, Caution did say that he saw something in the code and corrected it, so perhaps this was it. (Although this begs the question as to how we had a scoreboard to begin with, since that one line means that our scores would have been wiped every time the scoreboard could not be accessed [or something like that?])

The reason why I was asking about the Total Score thing was because I was wondering whether it is possible that the Total Score variable (I'm going to assume it to be some sort of integer variable) was getting overloaded. I did flunk out of Computer Science, but I seem to recall that computer integers are not indefinite. Of course, the Total Score on the hub may not even be an integer variable to begin with, so this may not necessarily apply. It's just that I know that Diclonius has been playing a LOT before the scoreboard crashed, to the point where he had a Total Score that was in the exponential range: 1.~~~~~~e+006 or something like that.

That specific line was already taken care of with this latest update. I thought it was the fix, but I guess it wasn't. I've been doing various sets of testing every Friday to try and deduce it and I think I may have a lead, but we'll see where that goes.
In response to CauTi0N
Update on the scoreboard:

I've had to reset my own server quite a few times (with myself on the server at the present time), and I've noticed that my own scores got affected or reset. I'm starting to think that the scoreboard is seriously affected by being on a server when it reboots.
In response to Sudzzuds
This is a very interesting clue. If you find more information please inform me. I may need to do some testing with you or Joram on a private server to find out.
In response to CauTi0N
Page or email me when you want to test and I'll try to accommodate you.
In response to Joram
http://youtu.be/EJUDaQxaa9E

Seeing how I don't know how to embed onto the forum, and that waiting for some time for us to experiment this may take some time, I've decided to try things myself.

It should be noted that far more experimentation is necessary - there are things that my video doesn't cover, so do experiment on this a lot more. Just please understand very well that this may lead to your score being erased.

That said, I don't think this is what causes the scoreboard to crash though. This is more about when Dream Deamon updates the scoreboard. But do keep in mind that I don't have a custom. The lack of score input that is caused from having a custom on will definitely change things.

Even though I manually rebooted the server, I strongly believe a similar effect can most likely be established if the host server has crashed (say, by a D/C from the modem/network, or a power out....) - so I do want some help in following this up.

EDIT: I've decided to test this thoroughly on the client-side as well - suddenly quitting in the middle of a game, and emulating a sudden connection blackout client-side. Neither affects the scoreboard, so this leads me to think that this problem is only caused if something happens server-side.
In response to Sudzzuds
Great scott!
D4RK3 54B3R wrote:
WHY DID IT GET RESET AGAIN?? >:(

PRETTY MUCH EVERYONE WITH A 200 CONSESCUTIVE WAVE SCORE ISN'T ON THE SCOREBOARD ANYMORE.

RIGHT NOW, I HAVE ONLY 5 CONSECUTIVE WAVES ON THE SCOREBOARD, WITH MY 200 RUN OFF THE CHARTS.


I thought that shit was supposed to be fixed :(

Minor warning - as of Nov 7, the scoreboard has crashed (erase scores) once again. Probably happened earlier than that, but I can't pinpoint.
In response to Sudzzuds
In what regard? As in any score is not being posted, or the same issue with the Wave 200?
In response to CauTi0N
In the regard with the following:

a) If you have had a previous score on the scoreboard, merely going onto a server will erase your score from the scoreboard. (speculated - can't prove this yet unless Sef logged in some time last night, because I know for certain that Sef was still on the scoreboard when I posted my last message, but is no longer on the scoreboard when this message is posted)

b) New players will not get their scores recorded onto he scoreboard.

I was just staring at the scoreboard right now... my alternate key is still there. I'm gonna see whether point A is correct or not.

EDIT:

Seems I'm gonna have to correct myself.
http://www.youtube.com/watch?v=ZcG5UwifyXU (I suggest switching to 720p and full screen)

So basically, when the program is supposed to update the scoreboard, it nulls whatever score that is there right now. All new players get their scores null as well. That's assuming that a null score means that our scores get erased.

This does not point out the cause of the issue at hand though - it merely points out the after-effects. Pin-pointing the cause is a tad beyond my scope - even if I did manage to stumble across it, I highly doubt I would be able to replicate it. :(

In response to Sudzzuds
Damn. I thought I figured out the source (in conjunction with an e-mail Joram sent me), but unfortunately that isn't it either. Sudz - does this happen with any key at all?
In response to CauTi0N
CauTi0N wrote:
Damn. I thought I figured out the source (in conjunction with an e-mail Joram sent me), but unfortunately that isn't it either. Sudz - does this happen with any key at all?

I only have 2 keys - and they are both off the scoreboard now. So I can't really answer your question CauTiON. I think though that it is safe to say that if anyone is on the scoreboard now and they even play CQ for one wave, their score will be erased from the scoreboard.

Very good reason why I videoed what I did - seeing how I can't replicate it anymore due to the fact that I have no scores on the scoreboard anymore.
Page: 1 2