-- | Generic binding of keys to commands, procesing macros,-- printing command help. No operation in this module-- involves the 'State' or 'Action' type.moduleGame.LambdaHack.Binding(Binding(..),macroKey,keyHelp,)whereimportqualifiedData.MapasMimportqualifiedData.ListasLimportqualifiedData.SetasSimportGame.LambdaHack.Utils.AssertimportqualifiedGame.LambdaHack.KeyasKimportGame.LambdaHack.Msg-- | Bindings and other information about player commands.dataBindinga=Binding{kcmd::M.Map(K.Key,K.Modifier)(String,Bool,a)-- ^ binding keys to commands,kmacro::M.MapK.KeyK.Key-- ^ macro map,kmajor::[K.Key]-- ^ major, most often used, commands,kdir::[(K.Key,K.Modifier)]-- ^ direction keys for moving and running}-- | Produce the macro map from a macro association list-- taken from the config file. Macros cannot depend on each other.-- The map is fully evaluated to catch errors in macro definitions early.macroKey::[(String,String)]->M.MapK.KeyK.KeymacroKeysection=lettransk=caseK.keyTranslatekofK.Unknowns->assert`failure`("unknown macro key "++s)kt->kttrMacro(from,to)=let!fromTr=transfrom!toTr=transtoiniffromTr==toTrthenassert`failure`("degenerate alias",toTr)else(fromTr,toTr)inM.fromList$L.maptrMacrosectioncoImage::M.MapK.KeyK.Key->K.Key->[K.Key]coImagekmacrok=letdomain=M.keysSetkmacroinifk`S.member`domainthen[]elsek:[from|(from,to)<-M.assocskmacro,to==k]-- | Produce a set of help screens from the key bindings.keyHelp::Bindinga->[Overlay]keyHelpBinding{kcmd,kmacro,kmajor}=letmovBlurb=["Move throughout the level with numerical keypad or","the Vi text editor keys (also known as \"Rogue-like keys\"):",""," 7 8 9 y k u"," \\|/ \\|/"," 4-5-6 h-.-l"," /|\\ /|\\"," 1 2 3 b j n","","Run ahead until anything disturbs you, with SHIFT (or CTRL) and a key.","Press keypad '5' or '.' to skip a turn.","In targeting mode the same keys move the targeting cursor.","","Search, open and attack, by bumping into walls, doors and monsters.","","Press SPACE to see the next page, with the list of major commands."]majorBlurb=["","Commands marked with * take time and are blocked on remote levels.","Press SPACE to see the next page, with the list of minor commands."]minorBlurb=["","For more playing instructions see file PLAYING.md.","Press SPACE to clear the messages and go back to the game."]fmtkh=replicate16' '++k++replicate((15-lengthk)`max`1)' '++h++replicate((41-lengthh)`max`1)' 'fmtss=replicate1' '++s++replicate((71-lengths)`max`1)' 'blank=fmt""""mov=mapfmtsmovBlurbmajor=mapfmtsmajorBlurbminor=mapfmtsminorBlurbkeyCaption=fmt"keys""command"dispk=L.concatMapshow$coImagekmacrokkeysl=[fmt(dispk)(h++iftimedthen"*"else"")|((k,_),(h,timed,_))<-l,h/=""](kcMajor,kcMinor)=L.partition((`elem`kmajor).fst.fst)(M.toAscListkcmd)in[[blank]++mov,[blank]++[keyCaption]++keyskcMajor++major,[blank]++[keyCaption]++keyskcMinor++minor]