svarlet
Hi all,
Let’s assume we are all coding a poker game as a purely functional library (=> no processes at this stage). If you don’t feel comfortable with poker, any other familiar multiplayer game will do.
How would you model it?
How would you design user interactions?
How would you validate user actions?
Thanks
Trending in Questions
Hello!
Suppose you are building workflow (order / task / payment) processing system with the following requirements:
Each workflow con...
New
Hey guys,
I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly
Do you guys have any suggestions what is the best prac...
New
Kia ora,
We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
Hello,
I’m developing a online persistent chat system (what’s app) like using elixir/dynamodb/aws for a mobile app(flutter).
The diffic...
New
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
Other Trending Topics
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
There are three potential reasons for members of this forum to have a look at https://vutuv.de
You are tired or annoyed of LinkedIn.
Yo...
New
ICal is a library for interacting with iCalendar data. It parses iCalendars into typed Elixir structs via ICal.from_ics, and can prepare ...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #ai
- #phoenix_html
- #elixirconf-us
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
peerreynders
So at some point will there be processes? In that case, have you already had a look at The Erlangelist: To spawn, or not to spawn?. It looks at bridge for the purposes of the article - though as it uses processes it may not address your exact concerns (I also don’t recall any validations).
svarlet
Yes, read it again this morning. It’s blackjack not bridge!
It’s interesting but taking many shortcuts, notably regarding validations. I wonder how he would handle validation of user actions. In BlackJack, there are few possible moves and they are not complex, therefore there is not much to validate. This is my problem with his example.
Once you put your finger into verifying that every user action is possible and authorised, your code becomes a mess. For example, in a game where players select a card from their hand:
when Player P select card C in game G
→ has G started?
→ is G still playable (not game over) ?
→ does G have the min number of players?
→ does P own card C?
→ has P already selected a card before C?
…
That’s what just happened to me on a side project. Therefore I’m starting to think either:
Of course, the second action is not acceptable.
kokolegorille
This might help You
peerreynders
Of course it is blackjack - serves me right for posting before my first coffee in the morning.
Well, Saša Jurić already mentions
:gen_statemand there is even the concept of communicating finite-state machines. However rather than coding the validation as an FSM straight away, it may make more sense to capture it in a state diagram first. With the states clearly identified a “purely functional implementation” could break the validation process into two phases:svarlet
Interesting and thorough example but there it seems the author is using processes for everything and letting them crash when an unauthorised action happens.
Unfortunately, that is not what I’m curious about here.
kokolegorille
The game logic is separated from genserver in the example
Qqwy
So to first do note something about structuring with processes: In multiplayer games, there usually is something the player can interact with directly/frequently, and other things that the player only interacts with sporadically (or not at all).
For a game like poker, every table/round is nearly completely isolated: The dealt cards and player actions in one game do not at all matter for another game that is happening at the same time.
And now for the ṕurely functional library’:
One round of poker should definitely be its own, purely functional piece of logic. I think it works very well as a finite state machine. Building a finite state machine in a functional language is not that difficult (However, I personally think it is easier in a strongly typed functional language because you are forced to be more explicit in the different states, how/which transitions (can) happen, and that all states are handled when reading out something from the state machine).
The state machine should make sure that only actions that are allowed at this time can be performed; So ‘player 3’ is not allowed to bet/raise/call until ‘player 2’ has done so. Matching a ‘user’ to ‘player 3 in this round’ is something that should probably exist outside of the state machine, though.
I’d personally strongly advise to separate the state machine from the GenServer that runs it as a process. This both makes it easier to test the thing, as well as making it more explicit where the boundaries of logic vs. communications are.
I have not used
:gen_statembefore (But I did dabble with the older:gen_fsmwhich I did not particularly like), but I’d advise to just build the state machine and the transitioning logic myself, rather than using a leaky abstraction layer on top of it.svarlet
@Qqwy I agree with everything you said. This is where I would appreciate a type system with algebraic data types. Without it, I feel a bit overwhelmed by the number of repetitions in the production code (validate this, validate that, …), and by the number of tests to write as well. So for one bit of game logic, I end up writing tons of validation code. It is currently mixed in the actual logic and that looks messy. That’s why I thought of an FSM to reject obviously impossible actions (like starting a game when it has already started). However, it won’t help with finer grain issues like “player 3 is trying to play before player 2” or “player A is playing a card that he doesn’t own”.
Not sure I’m making progress here.
OvermindDL1
As a state blob that I pass around. I do exactly this in the languages I’ve implemented in Elixir, just passing around an
envstruct, threading it through every function.Well in purely functional you cannot get user input other than before your code runs, so I’d do it via the repl with them calling the function with the current state along with their action as a kind of ‘event input’.
In reality you need some way to get user actions at runtime, a Haskell IO monad can do that functionally (by blackboxing using input and pretending it has been there since the start even if it has not) or via event passing between purely functional processes or so.
Depends entirely on what you want to validate, but you’d do it in that above process function.
This is not actually that hard. Given a language with Sum types (or tagged tuples on the BEAM) I’d just have each action be part of that sum type that they pass in with the state, and via simple pattern matching you only handle what is valid for a given state/event mix. With matchers it is trivial to just work on the valid actions and crash on the invalid (with perhaps a single wrapper to give pretty errors).
Likewise, I just implemented an FSM on gen_server anytime I needed a FSM, just by pattern matching states and such.
svarlet
@OvermindDL1 so instead of drowning in validations, you would just code the happy path and crash for all players of this party?