Code
--[[
Score Checker
Score Checker compares the "current", "recentbest",
"creditbest", and "absolutebest" poses, attempting
to identify any violations of basic assumptions.
For example, the score of the "absolutebest" pose
should always be greater than or equal to the score
of any of the other poses. A basic assumption has
been violated if this is not true.
Another assumption is that the score reported by
a pose's GetEnergyScore function should be equal to
the score reported by current.GetEnergyScore after
calling the pose's Restore function.
For example, the code:
local recent_sc = recentbest.GetEnergyScore ()
recentbest.Restore ()
local current_sc = current.GetEnergyScore ()
print ( tostring ( recipe.CompareNumbers ( recent_sc, current_sc ) ) )
should print "true".
For puzzles with filters, it's possible that the
recentbest and absolutebest poses show a score with
filters disabled. The assumption would be that the
pose's GetEnergyScore would match current.GetEnergyScore
either with filters enabled or filters disabled.
Based on testing to date, filters only apply to the
"current" pose. The GetEnergyScore for the other
poses returns the same value regardless of whether
filters are enabled or disabled.
version 1.0 -- 2016/07/22 -- LociOiling
]]--
--
-- Globals
--
Recipe = "Score Checker"
Version = "1.0"
ReVersion = Recipe .. " v." .. Version
poseTable = {
{ "current", current, 0, 0, false, 0, 0, },
{ "recentbest", recentbest, 0, 0, false, 0, 0, },
{ "creditbest", creditbest, 0, 0, false, 0, 0, },
{ "absolutebest", absolutebest, 0, 0, false, 0, 0, },
}
--
-- pose indexes
--
CURRIDX = 1
ABSBIDX = 4
--
-- pose table indexes
--
POSENAME = 1 -- display name for pose
POSETABL = 2 -- actual pose
POSEFILT = 3 -- pose GetEnergyScore with filters
POSENOFL = 4 -- pose GetEnergyScore without filters
POSECOND = 5 -- pose AreConditionsMet - true/false
POSEREFL = 6 -- after pose.Restore, score with filters
POSERENF = 7 -- after pose.Restore, score without filters
function round ( x )--cut all afer 3-rd place
return x - x % 0.001
end
function main ()
print ( ReVersion )
print ( "Puzzle: " .. puzzle.GetName () )
print ( "Track: " .. ui.GetTrackName () )
print ( "--" )
local sscore = current.GetScore ()
print ( "start score = " .. round ( sscore ) )
--
-- collect information for each pose
--
for ii = 1, #poseTable do
--
-- get pose's score with and without filters
--
behavior.SetFiltersDisabled ( false )
poseTable [ ii ] [ POSEFILT ] = poseTable [ ii ] [ POSETABL ].GetEnergyScore ()
behavior.SetFiltersDisabled ( true )
poseTable [ ii ] [ POSENOFL ] = poseTable [ ii ] [ POSETABL ].GetEnergyScore ()
behavior.SetFiltersDisabled ( false )
--
-- get pose's AreConditionsMet value
--
poseTable [ ii ] [ POSECOND ] = poseTable [ ii ] [ POSETABL ].AreConditionsMet ()
--
-- for poses with Restore function, restore and get score with and without filters
--
if ii ~= CURRIDX then
save.Quicksave ( 99 )
behavior.SetFiltersDisabled ( false )
poseTable [ ii ] [ POSETABL ].Restore ()
poseTable [ ii ] [ POSEREFL ] = current.GetEnergyScore ()
behavior.SetFiltersDisabled ( true )
poseTable [ ii ] [ POSETABL ].Restore ()
poseTable [ ii ] [ POSERENF ] = current.GetEnergyScore ()
behavior.SetFiltersDisabled ( false )
save.Quickload ( 99 )
end
end
--
-- print scores for each pose
--
print ( "--" )
print ( "basic scores" )
for ii = 1, #poseTable do
local filtbonus = poseTable [ ii ] [ POSEFILT ] - poseTable [ ii ] [ POSENOFL ]
print ( "pose \""
.. poseTable [ ii ] [ POSENAME ] ..
"\", with filters = "
.. round ( poseTable [ ii ] [ POSEFILT ] ) ..
", without filters = "
.. round ( poseTable [ ii ] [ POSENOFL ] ) ..
", filter bonus = "
.. round ( filtbonus )
)
print ( "pose \""
.. poseTable [ ii ] [ POSENAME ] ..
"\", conditions met = "
.. tostring ( poseTable [ ii ] [ POSECOND ] )
)
if ii ~= CURRIDX then
local reflbonus = poseTable [ ii ] [ POSEREFL ] - poseTable [ ii ] [ POSERENF ]
print ( "restored pose \""
.. poseTable [ ii ] [ POSENAME ] ..
"\", with filters = "
.. round ( poseTable [ ii ] [ POSEREFL ] ) ..
", without filters = "
.. round ( poseTable [ ii ] [ POSERENF ] ) ..
", filter bonus = "
.. round ( reflbonus )
)
end
end
--
-- check each pose before and after restore
--
print ( "--" )
print ( "Restore() results" )
local restfail = 0
for ii = 1, #poseTable do
if ii ~= CURRIDX then
if poseTable [ ii ] [ POSEFILT ] ~= poseTable [ ii ] [ POSEREFL ]
and poseTable [ ii ] [ POSEFILT ] ~= poseTable [ ii ] [ POSERENF ] then
print ( "pose \""
.. poseTable [ ii ] [ POSENAME ] ..
"\", GetEnergyScore = "
.. round ( poseTable [ ii ] [ POSEFILT ] ) ..
", does not match restored score with filters = "
.. round ( poseTable [ ii ] [ POSEREFL ] ) ..
", or without filters = "
.. round ( poseTable [ ii ] [ POSERENF ] )
)
restfail = restfail + 1
end
end
end
print ( "Restore() mismatches = " .. restfail )
--
-- check absolutebest against the others
--
print ( "--" )
print ( "absolutebest results" )
local absbfail = 0
for ii = 1, #poseTable do
if ii ~= ABSBIDX then
if poseTable [ ii ] [ POSEFILT ] > poseTable [ ABSBIDX ] [ POSEFILT ]
or poseTable [ ii ] [ POSENOFL ] > poseTable [ ii ] [ POSEFILT ] then
print ( "pose \""
.. poseTable [ ii ] [ POSENAME ] ..
"\", GetEnergyScore with filters= "
.. round ( poseTable [ ii ] [ POSEFILT ] ) ..
" or without filters = "
.. round ( poseTable [ ii ] [ POSENOFL ] ) ..
" greater than absolutebest score = "
.. round ( poseTable [ ABSBIDX ] [ POSEFILT ] )
)
absbfail = absbfail + 1
end
end
end
print ( "absolutebest mismatches = " .. absbfail )
--
-- exit thru the gift shoppe
--
cleanup ()
end
function cleanup ( error )
--
-- optionally, do not loop if cleanup causes an error
-- (any loop here is automatically terminated after a few iterations, however)
--
if CLEANUPENTRY ~= nil then
return
end
CLEANUPENTRY = true
print ( "---" )
local reason
local start, stop, line, msg
if error == nil then
reason = "complete"
else
--
-- model 120 - civilized error reporting,
-- thanks to Bruno K. and Jean-Bob
--
start, stop, line, msg = error:find ( ":(%d+):%s()" )
if msg ~= nil then
error = error:sub ( msg, #error )
end
if error:find ( "Cancelled" ) ~= nil then
reason = "cancelled"
else
reason = "error"
end
end
--
-- model 100 - print recipe name, puzzle, track, time, score, and gain
--
print ( ReVersion .. " " .. reason )
print ( "Puzzle: " .. puzzle.GetName () )
print ( "Track: " .. ui.GetTrackName () )
if reason == "error" then
print ( "Unexpected error detected" )
print ( "Error line: " .. line )
print ( "Error: \"" .. error .. "\"" )
end
--
-- model 130 - reset clash importance, clear selections, restore structures, etc.
--
--[[
--
-- it's possible to crash the cleanup routine
--
print ( "call unimplemented function = " .. nonesuch () )
]]--
end
-- main call
xpcall ( main, cleanup )
--end of script