Is this usage of the dynamic keyword an indicator of a design fault?
I believe your question is more aimed at a what, where, and when to use the dynamic keyword more than a design philosophy. It just so happens that a good explanation exists here: https://cloudncode.blog/2016/07/12/c-dynamic-keyword-what-why-when/
The short and easy from the link:


There is no compile-time type checking, this means that unless you have 100% confidence in your unit tests (cough) you are running a risk.
The dynamic keyword uses more CPU cycles than your old fashioned statically typed code due to the additional runtime overhead, if performance is important to your project (it normally is) don’t use dynamic.
Common mistakes include returning anonymous types wrapped in the dynamic keyword in public methods. Anonymous types are specific to an assembly, returning them across assembly (via the public methods) will throw an error, even though simple testing will catch this, you now have a public method which you can use only from specific places and that’s just bad design.
It’s a slippery slope, inexperienced developers itching to write something new and trying their best to avoid more classes (this is not necessarily limited to the inexperienced) will start using dynamic more and more if they see it in code, usually I would do a code analysis check for dynamic / add it in code review.


In my personal opinion - These functions are accepting rather simple data types (bool, int). It's more cumbersome on the CPU/Hardware to have a dynamic used than to just use function overloading to accomplish the same task without the needed stress. It is true that this may eliminate the need of type checking but you run a very large risk if these functions are used in uncontrolled events.
Also, your confidence in the data being entered for MakeChoice() or any of the other dynamic parameter functions or functions using dynamic has to be as accurate as the sun coming up tomorrow. Otherwise, you may get runtime errors.
Let me know if this helps - thanks.