Hi everyone, we found an intermittent error in our game that I'm having a difficult time reproducing. I've isolated the code where it happens and I see what the error is, but I cannot determine why it is happening.
I ran about 500 iterations of the test this morning and it passes every time. At this point I really need a second pair of eyes to look over my logic and tell me what I could be potentially doing wrong.
Here is the code:
type tile_type
letter$ as string
count as integer
points as integer
specOp as integer
specOpPlace as integer
tileID as integer
tileTextID as integer
pointTextID as integer
y# as float
x# as float
tileOnBoard as integer
depth as integer
switchFlag as integer
wphaFlag as integer
endtype
setPrintSize(2)
do
inc iter
dim playerHand[9] as tile_type
playerHand[0].count = 7
playerHand[1].letter$ = "E"
playerHand[1].specOp = 0
playerHand[2].letter$ = "L"
playerHand[2].specOp = 0
playerHand[3].letter$ = "U"
playerHand[3].specOp = 0
playerHand[4].letter$ = "L"
playerHand[4].specOp = 0
playerHand[5].letter$ = "E"
playerHand[5].specOp = 0
playerHand[6].letter$ = "I"
playerHand[6].specOp = 0
playerHand[7].letter$ = "A"
playerHand[7].specOp = 0
newHand$ = "7E0L0V0L0E0I0A0"
newHandSize = val(mid(newHand$ , 1 , 1))
dim tempHand[newHandSize] as tile_type
letterPlace = 0
for i = 1 to newHandSize
inc letterPlace , 2
tempHand[i].letter$ = mid(newHand$ , letterPlace , 1)
tempHand[i].specOp = val(mid(newHand$ , letterPlace+1 , 1))
next i
`trying to catch any potential errors
if playerHand[0].count <> newHandSize
WriteErrorLog("FATAL ERROR in switch - playerHand[0].count = " + str(playerHand[0].count) + " newHandSize = " + str(newHandSize) , 1 , 1 , 0 , 0)
WriteErrorLog(" newHand$ = " + newHand$ , 1 , 1 , 0 , 0)
WriteErrorLog(" current hand" , 1 , 1 , 0 , 0)
for phErr = 1 to playerHand[0].count
WriteErrorLog(" ltr = " + playerHand[phErr].letter$ + " specOp = " + str(playerHand[phErr].specOp) , 1 , 1 , 0 , 0)
next phErr
WriteErrorLog("FATAL ERROR - shutting down", 1 , 1 , 1 , 1)
endif
`determine the letter to remove
for i = 1 to playerHand[0].count
for j = 1 to newHandSize
if playerHand[i].letter$ = tempHand[j].letter$ and playerHand[i].specOp = tempHand[j].specOp and playerHand[i].switchFlag = 0 and tempHand[j].switchFlag = 0
playerHand[i].switchFlag = 1
tempHand[j].switchFlag = 1
EXIT
endif
next j
next i
`old letter
letterIndexToRemove = 0
for i = 1 to playerHand[0].count
if playerHand[i].switchFlag = 0
letterIndexToRemove = i
EXIT
endif
next i
`new letter
letterIndexToAdd = 0
for i = 1 to newHandSize
if tempHand[i].switchFlag = 0
letterIndexToAdd = i
EXIT
endif
next i
sync()
print("iterations = " + str(iter))
print(" newLetter = " + tempHand[letterIndexToAdd].letter$ + " letterIndexToAdd = " + str(letterIndexToAdd))
print(" old letter = " + playerHand[letterIndexToRemove].letter$ + " letterIndexToRemove = " + str(letterIndexToRemove))
sync()
sleep(500)
if letterIndexToRemove = 0 or letterIndexToAdd = 0
WriteErrorLog("FATAL ERROR in switch - letterIndexToRemove = " + str(letterIndexToRemove) + " letterIndexToAdd = " + str(letterIndexToAdd) + " - playerHand[0].count = " + str(playerHand[0].count) + " newHandSize = " + str(newHandSize) , 1 , 1 , 0 , 0)
WriteErrorLog(" newLetter = " + tempHand[letterIndexToAdd].letter$ , 1 , 1 , 0 , 0)
WriteErrorLog(" old letter = " + playerHand[letterIndexToRemove].letter$ , 1 , 1 , 0 , 0)
WriteErrorLog(" newHand$ = " + newHand$ , 1 , 1 , 0 , 0)
WriteErrorLog(" current hand" , 1 , 1 , 0 , 0)
for phErr = 1 to playerHand[0].count
WriteErrorLog(" ltr = " + playerHand[phErr].letter$ + " specOp = " + str(playerHand[phErr].specOp) + " switch flag = " + str(playerHand[phErr].switchFlag) , 1 , 1 , 0 , 0)
next phErr
WriteErrorLog(" new hand" , 1 , 1 , 0 , 0)
for phErr = 1 to newHandSize
WriteErrorLog(" ltr = " + tempHand[phErr].letter$ + " specOp = " + str(tempHand[phErr].specOp) + " switch flag = " + str(tempHand[phErr].switchFlag) , 1 , 1 , 0 , 0)
next phErr
WriteErrorLog("FATAL ERROR - shutting down", 1 , 1 , 1 , 1)
endif
undim playerHand[]
undim tempHand[]
loop
END
function WriteErrorLog(sText$ , iToggleTimeStamp , iAppend , iWarn , iFatal)
if iWARN_ALL = 1 or iWarn = 1
if iDEBUG_ON = 1
Message("Error written to log! - " + sText$)
elseif iFatal = 1
Message("FATAL ERROR - Please send us a support request through the game if possible. If not please send an email to support@wordspionage.com with details on the error you've experienced.")
endif
endif
fileID = OpenToWrite(gUser$+"_error_log.csv" , iAppend)
if iToggleTimeStamp = 1
sText$ = GetCurrentDate() + " " + GetCurrentTime() + ": " + sText$
endif
WriteLine(fileID , sText$)
CloseFile(fileID)
if iFatal = 1
ClearScreen()
Render()
img = GetImage(0,0,100,100)
SaveImage(img , "errorscreen.png")
t0 = GetMilliseconds()
SetPrintSize(8)
repeat
Print("")
Print("")
Print("FATAL ERROR")
Sync()
until GetMilliseconds() - t0 > 90000 or GetPointerPressed() = 1 or GetRawKeyPressed(27) = 1
END
endif
endfunction
`
Here is the error log confirming the test data that I use above (which passes), but as can be seen in the error log, it actually failed.
2013-12-16 20:14:37: FATAL ERROR in switch - letterIndexToRemove = 2 letterIndexToAdd = 0 - playerHand[0].count = 7 newHandSize = 7
2013-12-16 20:14:37: newLetter =
2013-12-16 20:14:37: old letter = L
2013-12-16 20:14:37: newHand$ = 7E0L0V0L0E0I0A0
2013-12-16 20:14:37: current hand
2013-12-16 20:14:37: ltr = E specOp = 0 switch flag = 1
2013-12-16 20:14:37: ltr = L specOp = 0 switch flag = 0
2013-12-16 20:14:37: ltr = U specOp = 0 switch flag = 0
2013-12-16 20:14:37: ltr = L specOp = 0 switch flag = 0
2013-12-16 20:14:37: ltr = E specOp = 0 switch flag = 0
2013-12-16 20:14:37: ltr = I specOp = 0 switch flag = 0
2013-12-16 20:14:37: ltr = A specOp = 0 switch flag = 0
2013-12-16 20:14:37: new hand
2013-12-16 20:14:37: ltr = E specOp = 0 switch flag = 1
2013-12-16 20:14:37: ltr = L specOp = 0 switch flag = 1
2013-12-16 20:14:37: ltr = V specOp = 0 switch flag = 1
2013-12-16 20:14:37: ltr = L specOp = 0 switch flag = 1
2013-12-16 20:14:37: ltr = E specOp = 0 switch flag = 1
2013-12-16 20:14:37: ltr = I specOp = 0 switch flag = 1
2013-12-16 20:14:37: ltr = A specOp = 0 switch flag = 1
2013-12-16 20:14:37: FATAL ERROR - shutting down
We can see that for some reason only the first element in playerHand[] gets marked with the switch flag, while every element in tempHand[] gets marked with the switch flag.
It is like the comparison of the letter$ element is comparing empty strings, or somehow passing, but even then it doesn't make much sense because the array element for playerHand[].switchFlag would also have to be 0 for each tempHand[] element to get flagged...
It's just really odd and I can't see what is up.
All suggestions welcome.
Thank you!