{"author_link":"\/users\/steinuil","author_name":"steinuil","author_uid":"steinuil","comments":[],"epoch":1665198721,"event":"LD51","format":"md","ldjam_node_id":309513,"likes":8,"metadata":{"p_key":"169072","p_author":"steinuil","p_authorkey":"1249063","p_urlkey":"396832","p_title":"A functional game","p_cat":"LDJam ","p_event":"LD51","p_time":"1665198721","p_likes":"8","p_comments":"0","p_status":"WAYBACK","us_key":"1249063","us_name":"steinuil","us_username":"steinuil","event_start":"1664496000","event_key":"114","event_name":"Ludum Dare 51"},"node":{"_collation":{"body_sanitizer":"TextUtils::SanitizeHTML via existing importer","event":"LD51","removed_author":false},"_superparent":296586,"_trust":1,"author":249063,"body":"Yes your game may function, but is it *functional*? I wrote [our game](https:\/\/ldjam.com\/events\/ludum-dare\/51\/10-doujins-per-second) in MonoGame and F# -- a *mostly* functional programming language -- and I did it *mostly* using pure functions and following a sketch of [The Elm Architecture](https:\/\/guide.elm-lang.org\/architecture\/).\n\nOk, *maybe* the view function is effectful because encoding your .Draw calls in a discriminated union feels like too much, even for me, and *maybe* I left a few bits of extremely mutable state in there because I couldn't be bothered to include them in the state type, but I think I did better than the last time.\n\nSo, we *do* have a GameStateMachine union this time. It defines all the states that the game could be in:\n\n```fsharp\ntype GameStateMachine =\n    | SplashScreen of int\n    | Menu\n    | Intro of int\n    | Day of int * DayState\n    | Interim of int\n    | EndScreen\n    | Credits of int\n```\n\nAll this state is held in a mutable `state` variable. There's no real enforcement of read\/write permissions in the methods, but .Update is the only one that was allowed to actually write to any of the variables while .Draw could only read.\n\nBoth of these functions are just very big [pattern](https:\/\/github.com\/steinuil\/TenDoujinsPerSecond\/blob\/7eb59ffb6756d174a31aebfe4d3bb8fccd4eb63e\/Program.fs#L333) [matches](https:\/\/github.com\/steinuil\/TenDoujinsPerSecond\/blob\/7eb59ffb6756d174a31aebfe4d3bb8fccd4eb63e\/Program.fs#L627) on the state variable. `.Update` is supposed to be a function that takes a `GameStateMachine` and returns the next `GameStateMachine` (in practice it updates it in place) and `.Draw` takes a `GameStateMachine` and issues side effects to the MonoGame APIs.\n\nWhy is this relevant, you ask? Well, I think having such a simple architecture enables for fast prototyping and few bugs. We had some friends playtest our game for the first time just an hour and a half before the submission deadline and it was surprisingly bug-free! Except for the intended level of jank, that is. In fact, the only actual bug I've found so far was due to the few bits of mutable state I left in because I was strapped for time.\n\nThere's this ethos of *making invalid states unrepresentable* in typed functional programming, and that goes a long way in solving logic bugs in your game. Do give it a try if you're into functional programming and are working in an engine that lets you write code in a language with discriminated unions\/variants\/whatever you wanna call them. It just works!","comments":1,"comments-timestamp":"2022-10-08T06:17:30Z","created":"2022-10-08T02:43:33Z","files":[],"files-timestamp":0,"id":309513,"love":8,"love-timestamp":"2022-10-08T12:14:12Z","meta":[],"modified":"2022-10-08T12:14:12Z","name":"A functional game","node-timestamp":"2022-10-08T03:12:01Z","parent":303667,"parents":[1,5,9,296586,303667],"path":"\/events\/ludum-dare\/51\/10-doujins-per-second\/a-functional-game","published":"2022-10-08T03:12:01Z","scope":"public","slug":"a-functional-game","subsubtype":"","subtype":"","type":"post","version":964602},"node_metadata":{"n_key":"309513","n_urlkey":"396832","n_parent":"303667","n_path":"\/events\/ludum-dare\/51\/10-doujins-per-second\/a-functional-game","n_slug":"a-functional-game","n_type":"post","n_subtype":"","n_subsubtype":"","n_author":"249063","n_created":"1665197013","n_modified":"1665231252","n_version":"964602","n_status":"WAYBACK"},"source_url":"https:\/\/ldjam.com\/events\/ludum-dare\/51\/10-doujins-per-second\/a-functional-game","text":"Yes your game may function, but is it *functional*? I wrote [our game](https:\/\/ldjam.com\/events\/ludum-dare\/51\/10-doujins-per-second) in MonoGame and F# -- a *mostly* functional programming language -- and I did it *mostly* using pure functions and following a sketch of [The Elm Architecture](https:\/\/guide.elm-lang.org\/architecture\/).\n\nOk, *maybe* the view function is effectful because encoding your .Draw calls in a discriminated union feels like too much, even for me, and *maybe* I left a few bits of extremely mutable state in there because I couldn't be bothered to include them in the state type, but I think I did better than the last time.\n\nSo, we *do* have a GameStateMachine union this time. It defines all the states that the game could be in:\n\n```fsharp\ntype GameStateMachine =\n    | SplashScreen of int\n    | Menu\n    | Intro of int\n    | Day of int * DayState\n    | Interim of int\n    | EndScreen\n    | Credits of int\n```\n\nAll this state is held in a mutable `state` variable. There's no real enforcement of read\/write permissions in the methods, but .Update is the only one that was allowed to actually write to any of the variables while .Draw could only read.\n\nBoth of these functions are just very big [pattern](https:\/\/github.com\/steinuil\/TenDoujinsPerSecond\/blob\/7eb59ffb6756d174a31aebfe4d3bb8fccd4eb63e\/Program.fs#L333) [matches](https:\/\/github.com\/steinuil\/TenDoujinsPerSecond\/blob\/7eb59ffb6756d174a31aebfe4d3bb8fccd4eb63e\/Program.fs#L627) on the state variable. `.Update` is supposed to be a function that takes a `GameStateMachine` and returns the next `GameStateMachine` (in practice it updates it in place) and `.Draw` takes a `GameStateMachine` and issues side effects to the MonoGame APIs.\n\nWhy is this relevant, you ask? Well, I think having such a simple architecture enables for fast prototyping and few bugs. We had some friends playtest our game for the first time just an hour and a half before the submission deadline and it was surprisingly bug-free! Except for the intended level of jank, that is. In fact, the only actual bug I've found so far was due to the few bits of mutable state I left in because I was strapped for time.\n\nThere's this ethos of *making invalid states unrepresentable* in typed functional programming, and that goes a long way in solving logic bugs in your game. Do give it a try if you're into functional programming and are working in an engine that lets you write code in a language with discriminated unions\/variants\/whatever you wanna call them. It just works!","title":"A functional game","wayback_source":[]}