Icon representing a recipe

Recipe: Wiggle Lock Check v 2.0

created by brow42

Profile


Name
Wiggle Lock Check v 2.0
ID
39029
Shared with
Public
Parent
None
Children
None
Created on
March 17, 2012 at 19:02 PM UTC
Updated on
March 17, 2012 at 19:02 PM UTC
Description

Pulls each segment against known locked segments and checks for a small change in score. Now with dialog.

Best for


Code


--[[ * Wiggle Lock Check * Original Author: Brow42 2/29/2012 * Version 1.0 -- Puzzle 522b * This performs a test for 'wiggle lock' as suggested by Rav3n, but * automated here. For each segment that you want to test, that * should *not* be locked, it draws a strength 10 band to a segment that * is *known* to be locked. After a wiggle, the score will be almost * exactly identical to what the score would have been if no band * had been made, if the segment is 'wiggle locked'. At the end, a list * of wiggle locked segments is printed. * * Strength 10 bands can make wiggle run a long time, so you can manual * cancel each wiggle with 'space' after about 2 seconds. If you cancel * too soon, though, that segment will show up as wiggle locked. * * Version 1.1 3/15/2012 * * Changed defaults for 529 * * Version 2.0 3/17/2012 * * Changed to use a dialog interface --]] -- ================================== Begin New Dialog Library Functions -- Add a wall of text from a table function dialog.AddLabels(d,msg) -- need to manually pass in # of existing autolabels nlabels = #d._Order -- unique starting index if type(msg) == 'string' then msg = { msg } end for i = 1,#msg do d['autolabel'..tostring(i+nlabels)] = dialog.AddLabel(msg[i]) end end -- Create but don't display a wall of text and 1 or 2 buttons function dialog.CreateMessageBox(msg,title,buttontext1,buttontext0) title = title or '' local d = dialog.CreateDialog(title) dialog.AddLabels(d,msg) buttontext1 = buttontext1 or 'Ok' d.button = dialog.AddButton(buttontext1,1) if buttontext0 ~= nil then d.button0 = dialog.AddButton(buttontext0,0) end return d end -- Display a dialog box function dialog.ShowMessageBox(msg,title,buttontext1,buttontext0) return dialog.Show(dialog.CreateMessageBox(msg,title,buttontext1,buttontext0)) end function ErrorMessage(msg) print('Error',msg) dialog.ShowMessageBox(msg,'Error') end function ParseRangeString(str) local n = structure.GetCount() local tab, r = {}, {} for i in string.gfind(str,'-?%d+') do i = tonumber(i) local j = math.abs(i) if j < 1 or j > n then ErrorMessage(string.format('Segment id %d is out of range 1 - %d',j,n)) return false end if i < 0 then if #r == 0 then ErrorMessage('Unexpected 2nd half of range without first half') return false end tab[#tab+1] = { r[1], -i } r = {} else if #r > 0 then tab[#tab+1] = r end r = { i } end end if #r > 0 then tab[#tab+1] = r end return true, tab end -- ================================== Begin Main (Dialog) d = dialog.CreateMessageBox( { 'This creates a band between segments you specify', 'and a known-locked segment. If it moves the same as', 'when there is no band, it\'s wiggle-locked.', 'Puzzle should be relaxed. Watch output window.', 'Remeber, you can can cancel wiggles after 2 seconds.', '' }, 'Wiggle Lock Check 2.0','Check','Exit') d.locked = dialog.AddTextbox('Locked Segment #:','') dialog.AddLabels(d,{ 'If score changes more than this, it\'s not locked.', 'Smaller is more accurate here, but puzzle must be', 'relaxed to less than this.',''} ) d.fuzz = dialog.AddTextbox('Max Change:','1.0') dialog.AddLabels(d,'Enter segments to test as #s or #-# ranges') d.range = dialog.AddTextbox('Test Segments:','') repeat rc = dialog.Show(d) if rc == 0 then break end rc2, ranges = ParseRangeString(d.range.value) fuzz = tonumber(d.fuzz.value) or 0 bandseg = tonumber(d.locked.value) or 0 if fuzz <= 0 then ErrorMessage('Max Score Change should be a small positive number') rc2 = false end if bandseg < 1 or bandseg > structure.GetCount() then ErrorMessage('Locked Segment # out of range') rc2 = false end if #ranges == 0 then ErrorMessage('Missing list of segment (ranges) to test.') rc2 = false end until rc2 == true if rc == 0 then print('Recipe canceled.') return end -- ================================== Begin Main (work) str = 10.0 zerolist = {} -- list of locked segments printed at the end score = current.GetScore() print(puzzle.GetName()) print(string.format('Relaxing to %f...',fuzz/10)) band.DeleteAll() while true do structure.WiggleAll(1) newscore = current.GetScore() print('Relaxing:',newscore-score) if math.abs(newscore-score) < fuzz /10 then break end score = newscore end print('Remember, you can quit any wiggle after 2 seconds.') save.Quicksave(100) structure.WiggleAll(1) delta_bandless = current.GetScore() - score print('bandless',delta_bandless) save.Quickload(100) print() print('Seg Change') for iBlock = 1, #ranges do teststart, testend = ranges[iBlock][1], ranges[iBlock][2] or ranges[iBlock][1] if teststart > testend then teststart,testend = testend,teststart end for iSeg = teststart,testend do band.DeleteAll() rc = band.AddBetweenSegments(iSeg,bandseg) if rc == 0 then print(string.format('Error making band %d - %d (too close?)',iSeg,bandseg)) else band.SetStrength(rc,str) band.SetGoalLength(rc,0.001) structure.WiggleAll(1) delta = current.GetScore() - score if math.abs(delta) < fuzz then table.insert(zerolist,iSeg) end -- this test is based on the fact that wiggle is deterministic -- if delta == delta_bandless then table.insert(zerolist,iSeg) end print(iSeg,delta) end save.Quickload(100) end end if #zerolist > 0 then table.sort(zerolist) print('Locked Segs:',table.concat(zerolist,' ')) else print('No locked segments found.') end

Comments