Building a roguelike in F# from scratch - Multi Key Commands

in #programming7 years ago

Introduction

Recursion really is a thing of beauty :)

I have updated the player command generator so it will handle commands that take multiple key presses. The working commands are now:

  • W - Up
  • A - Left
  • S - Down
  • D - Right
  • Space - Idle
  • O + [WASD] - Open the door in that direction
  • C + [WASD] - Close the door in that direction

Reading the keyboard

The change to implement this was so simple in the end. There is a new function called handleKeyPress, this handles all the building. It is called initially with a None command builder.

  • If W,A,S,D or Space are pressed it calls selectActorCommand, which you saw last time.
  • If O or C are pressed it calls back into itself with the related builder. Next time if W,A,S or D are pressed it will build the Open or Close command in that direction.
let selectCommand validator operation direction actorId level =
    level 
        |> validator direction actorId 
        |> bind (fun l -> operation direction actorId l)

let private selectActorCommand direction actorId level =
    resultOrElse {
        return! selectCommand isValidMove buildMoveActorCommand direction actorId level
        return! selectCommand canOpenDoor buildOpenDoorCommand direction actorId level
        return! (invalidCommand level)
    }

let rec handleKeyPress activeBuilder actorId =
    let workingBuilder = 
        match activeBuilder with
        | Some builder -> builder
        | None -> selectActorCommand

    match Console.ReadKey().Key with
    | ConsoleKey.O -> handleKeyPress (Some buildOpenDoorCommand) actorId
    | ConsoleKey.C -> handleKeyPress (Some buildCloseDoorCommand) actorId
    | ConsoleKey.W -> workingBuilder north actorId
    | ConsoleKey.A -> workingBuilder west actorId
    | ConsoleKey.S -> workingBuilder south actorId
    | ConsoleKey.D -> workingBuilder east actorId
    | ConsoleKey.Spacebar -> idleCommand
    | _ -> invalidCommand

let getPlayerCommand actorId = handleKeyPress None actorId

The only issue at the moment is termination if the player holders down O or C, that should not be an issue as this should be tail call recursive. If this proves to be incorrect I will need to revisit it. Good enough for now.

Summary

Short one today, but nice simple change that gives a lot of power for very little work. Most of it already existed just needed moving around a bit :)

And for those who have only just found the series, here is the story so far for Building a roguelike in F# from scratch :

Finally the GitHub Repo

Feel free to ask questions and happy coding :)

Woz

Sort:  

Congratulations @woz.software! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of comments

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

Coin Marketplace

STEEM 0.17
TRX 0.15
JST 0.028
BTC 60526.80
ETH 2335.69
USDT 1.00
SBD 2.53