swarm-game / swarm

Resource gathering + programming game
Other
820 stars 51 forks source link

Customizable keybindings #1979

Open xsebek opened 1 week ago

xsebek commented 1 week ago
xsebek commented 3 days ago

It works! 🥳 Add an INI file:

$ cat /Users/xsebek/.config/swarm/config.ini
[keybindings]
debug CESK = Ctrl-u

Print the changed keybindings:

cabal run -O0 swarm -- keybindings --markdown

Keybindings

main

Keybinding Event Name Description
C-q quit Open quit game dialog
F1 view help View Help screen
F2 view robots View Robots screen
F3 view recipes View Recipes screen
F4 view commands View Commands screen
F6 view structures View Structures screen
C-g view goal View scenario goal description
M-h hide robots Hide robots for a few ticks
C-u debug CESK Show active robot CESK machine debugging line

repl

Keybinding Event Name Description
C-c, Esc cancel running program Cancel running base robot program
M-p toggle piloting mode Toggle piloting mode
M-k toggle custom key handling Toggle custom key handling mode

The configuration file is at: /Users/xsebek/.config/swarm/config.ini

xsebek commented 1 day ago

After a lot of shuffling code back and forth, the main game handlers are customizable:


Keybindings

main

Keybinding Event Name Description
Esc (non-customizable key) Close open modal
C-q quit Open quit game dialog
F1 view help View Help screen
F2 view robots View Robots screen
F3 view recipes View Recipes screen
F4 view commands View Commands screen
F5 view messages View Messages screen
F6 view structures View Structures screen
C-g view goal View scenario goal description
M-h hide robots Hide robots for a few ticks
M-d debug CESK Show active robot CESK machine debugging line
C-p pause Pause or unpause the game
C-o run single tick Run game for a single tick
C-x increse TPS Increase game speed by one tick per second
C-z decrease TPS Descrease game speed by one tick per second
M-w focus World Set focus on the World panel
M-e focus Robot Set focus on the Robot panel
M-r focus REPL Set focus on the REPL panel
M-t focus Info Set focus on the Info panel
C-v creative mode Toggle creative mode
C-e world editor Toggle world editor mode
M-, toggle REPL Collapse/Expand REPL panel

repl

Keybinding Event Name Description
C-c, Esc cancel running program Cancel running base robot program
M-p toggle piloting mode Toggle piloting mode
M-k toggle custom key handling Toggle custom key handling mode

world

Keybinding Event Name Description
c view base View the base robot
f show fps Show frames per second
k, Up move view north Scroll world view in the north direction
l, Right move view east Scroll world view in the east direction
j, Down move view south Scroll world view in the south direction
h, Left move view west Scroll world view in the west direction

robot

Keybinding Event Name Description
Enter (non-customizable key) Show entity description
m make entity Make the selected entity
0 show zero inventory entites Show entities with zero count in inventory
; cycle inventory sort Cycle inventory sorting type
: switch inventory direction Switch ascending/descending inventory sort
/ search inventory Start inventory search
xsebek commented 1 day ago

@byorgey @kostmo, While this is not finished yet, I would appreciate it if you could test this out.

The original code could have behaved differently because the conditions allowed events to be handled by subhandlers.

If we really want that behavior, then those handlers have to stay in the old not-as-declarative code. For example, Esc is used everywhere, and I made the mistake of putting it into the main handler. But there could be more obscure bugs or just plain typos that I made.


By the way, this refactoring makes the Controller significantly smaller:

 src/swarm-tui/Swarm/TUI/Controller.hs | 827 ++---------------------------------------------
 27 insertions(+), 800 deletions(-)

It is necessary because the handlers are stored in the Model, which is imported into the Controller, and a cycle would form.

byorgey commented 1 day ago

Just some small initial feeback: so far I'm just trying it out without having looked at the code yet (since that's what players will do). I found swarm keybindings quickly, which told me where the config file should go, but I don't know what format is expected. However, I see you have some todos for documentation and generating an initial .ini file, so maybe you have that under control!

xsebek commented 1 day ago
$ cat /Users/xsebek/.config/swarm/config.ini
[keybindings]
debug CESK = Ctrl-u

@byorgey, exactly. The INI file looks like that, with Event Names as keys and values being parsed by parseBindingList.

I think showing by example will be much clearer than trying to explain the format in detail. 🙂

byorgey commented 1 day ago

I accidentally wrote a keybinding in uppercase, like Ctrl-T, and it turns out this means it parses successfully, with no errors or warnings, but simply does not work --- both Ctrl-t and Ctrl-Shift-t do nothing. I suspect it turns into a keybinding which is impossible to ever see, because Ctrl-Shift-t is not the same as Ctrl-T. Well, I don't know, perhaps it is possible to get Ctrl-T by turning on caps lock and then typing Ctrl-t? In any case it seems like some kind of warning here would be nice.

byorgey commented 1 day ago

I think showing by example will be much clearer than trying to explain the format in detail.

Agreed, I think generating an initial .ini file with all the default keybindings commented out will be perfect.

byorgey commented 19 hours ago

By the way, key shortcuts are shown in two places in the UI: in the bar between the REPL and world panels, and also in the F1 help modal. I think in the F1 modal we should mention something about how to customize keybindings.

byorgey commented 15 hours ago

I just discovered a regression: on main, hitting Esc at the REPL has no effect. With this PR, hitting Esc makes the REPL display ... (as if the base is executing a program) and it's impossible to get back the normal prompt (even with Ctrl-C).