<h1 id="quick-peek-at-some-places-in-code">Quick peek at some places in code</h1>
<p><code>Main.hs</code> has our <code>Main</code> module definition. It was generated by <code>Stack</code> when we started. In the end of the <code>main</code> function, it calls <code>run</code> function, which is defined in <code>Run.hs</code> file. This is the place where we can see overall flow of the program in one glance.</p>
<pre><code>run :: RIO App ()
run = do
  choice &lt;- showMainMenu
  case choice of
    StarNewGame -&gt; do
      logDebug &quot;New game starting...&quot;
      logDebug &quot;Rolling new character...&quot;
      player &lt;- liftIO $ evalRandIO rollNewCharacter
      displayNewCharacter player
      logDebug &quot;Selecting starting gear...&quot;
      gear &lt;- selectStartingGear $ playerGear player
      logDebug &quot;Preparing game...&quot;
      game &lt;- liftIO $ evalRandIO $ startGame player gear
      logDebug &quot;Dealing first card...&quot;
      finishedGame &lt;- playGame game
      logDebug &quot;Displaying game over...&quot;
      displayGameOver finishedGame

    ExitGame -&gt;
      return ()</code></pre>
<p>Another interesting module is <code>Types</code>. Here you can find how player, items, monsters and such are represented.</p>
<p>Third and biggest module is <code>UserInterface</code>, which contains functions to display game status to player and ask their input.</p>
<p>So, what does our <code>run</code> function do? Lets have a look:</p>
<ul>
<li><code>choice &lt;- showMainMenu</code>
<ul>
<li>show main menu and ask for player input</li>
</ul></li>
<li><code>case choice of</code>
<ul>
<li>depending on the choice, continue with game logic or exit the function</li>
</ul></li>
<li><code>player &lt;- liftIO $ evalRandIO rollNewCharacter</code>
<ul>
<li>roll a new character</li>
<li><code>evalRandIO</code> indicates we're dealing with random numbers</li>
</ul></li>
<li><code>displayNewCharacter player</code>
<ul>
<li>display the new character on screen</li>
</ul></li>
<li><code>gear &lt;- selectStartingGear $ playerGear player</code>
<ul>
<li>select starting gear</li>
</ul></li>
<li><code>game &lt;- liftIO $ evalRandIO $ startGame player gear</code>
<ul>
<li>shuffle the deck and set up the game</li>
<li>again using random numbers here</li>
</ul></li>
<li><code>finishedGame &lt;- playGame game</code>
<ul>
<li>play game until we're done</li>
</ul></li>
<li><code>displayGameOver finishedGame</code>
<ul>
<li>display game over screen</li>
</ul></li>
</ul>
<h1 id="word-about-input-and-output">Word about input and output</h1>
<p>One of the features of Haskell I like is the ability to show which functions are pure (always returning same output with given set of inputs and not having any side effects). In our program, every function that returns <code>RIO a b</code> has access to input and output. In addition to that, it also has access to system wide configuration (which we don't use much here) and logging functions.</p>
<p>To write on the screen, we use <code>putStrLn</code> and reading a user input <code>readLine</code>. Since they're designed to work with <code>IO</code> instead of <code>RIO a b</code>, we have to use <code>liftIO</code>. But all that is technical details that we won't worry now.</p>
<p><code>App</code> is our configuration. We aren't directly using it, so it's safe to ignore for now.</p>
<h1 id="showing-main-menu">Showing main menu</h1>
<p><code>showMainMenu</code> function will print out the menu and then call <code>mainMenuInput</code>. <code>mainMenuInput</code> will read input, validate that it's either <code>1</code> or <code>2</code> and return respectively <code>StarNewGame</code> or <code>ExitGame</code>. In case user enters something else, <code>mainMenuInput</code> will recurse until user enters valid input.</p>
<pre><code>-- | Display main menu
showMainMenu :: RIO App MainMenuChoice
showMainMenu = do
  logDebug &quot;Displaying main menu&quot;
  liftIO $ putStrLn &quot;\n\n&quot;
  liftIO $ putStrLn &quot;Treasure Dungeon&quot;
  liftIO $ putStrLn &quot;****************&quot;
  liftIO $ putStrLn &quot;&quot;
  liftIO $ putStrLn &quot;1. Start a new game&quot;
  liftIO $ putStrLn &quot;2. Quit&quot;
  mainMenuInput

mainMenuInput :: RIO App MainMenuChoice
mainMenuInput = do
  i &lt;- liftIO getLine
  case i of
    &quot;1&quot; -&gt; return StarNewGame
    &quot;2&quot; -&gt; return ExitGame
      _ -&gt; do
            logDebug $ displayShow $ &quot;Incorrect menu choice: &quot; &lt;&gt; i
            liftIO $ putStrLn &quot;Please select 1 or 2&quot;
            mainMenuInput</code></pre>
<p>You might wonder, why <code>mainMenuInput</code> can keep calling itself without filling the stack? That's because Haskell doesn't use stack in the same sense as many other programming languages. Haskell compiler is also smart enough to notice that call to <code>mainMenuInput</code> is last operation of the <code>mainMenuInput</code>, there is no work to be done after the call, and thus can optimize things even more. I don't know all the dirty details how this has been implemented and how things work behind the curtains.</p>
<h1 id="rolling-new-character">Rolling new character</h1>
<p><code>player &lt;- liftIO $ evalRandIO rollNewCharacter</code> rolls a new character, but what exactly is going on here? <code>rollNewChacter</code> has following signature: <code>rollNewCharacter :: (RandomGen g) =&gt; Rand g Player</code>. It doesn't take any parameters and returns <code>Rand g Player</code>, where <code>g</code> implements <code>RandomGen</code>. So, it's <code>Rand</code> monad that returns <code>Player</code>. In order to get the result of the computation, we call <code>evalRandIO</code> that uses global random number generator to compute. And since it's an <code>IO</code> operation, we need <code>liftIO</code>. It's bit confusing at first, so don't worry if you don't get all the details. The main point is that we're doing computation with random numbers.</p>
<p>Implementation is not too complex:</p>
<pre><code>rollNewCharacter :: (RandomGen g) =&gt; Rand g Player
rollNewCharacter = do
  str &lt;- dice 3
  dex &lt;- dice 3
  mind &lt;- dice 3
  maxHp &lt;- dice 4
  return $ Player
    { playerStrength  = MkStrength str
    , playerDexterity = MkDexterity dex
    , playerMind      = MkMind mind
    , playerHP        = MkHP maxHp
    , playerMaxHP     = MkHP maxHp
    , playerGear      = [ ]
    }</code></pre>
<p>This rolls three six sided dice for each attribute and 4 for hit points. The values are then used to create <code>Player</code> record that is returned.</p>
<p><code>dice</code> is implemented as following:</p>
<pre><code>dice :: (RandomGen g) =&gt; Natural -&gt; Rand g Natural
dice n = do
  rolls &lt;- getRandomRs (1, 6)
  let roll = sum $ take (fromIntegral n) rolls
  return $ fromInteger roll</code></pre>
<p>Again, we're using <code>Rand</code> monad for random number generation. <code>getRandomRs</code> supplies us an infinite list of numbers between <code>1</code> and <code>6</code>. Then we use <code>take</code> to some of them and <code>sum</code> to add them together. <code>fromIntegral n</code> is needed, because <code>take</code> doesn't operate on <code>Natural</code> type, but <code>Int</code>. I wanted to use <code>Natural</code> though, because that ensures that the parameter <code>n</code> will always be <code>0</code> or more.</p>
<h1 id="in-closing">In closing</h1>
<p>Now we have a basic layout for our program and know how to roll a character with random stats. Next time we'll finally look into getting some gear on them. The code for the game is available at my <a href="https://codeberg.org/Tuula/treasure-dungeon/">codeberg repository</a>.</p>
<p>ad astra!</p>
