# [Ink](https://inklestudios.com/ink/), <s>120</s> 119 bytes =f(n) ->g(n,3,2) =g(n,b,s) {n>1:{~{b:b->g(n-1,b-1,s)}|{s:s->g(n-1,b,s-1)}|}f->g(n-1,b,s&&s+1)|{~{b:h|b}|{s:h|s}|h}}->-> Probably still golfable. No online interpreter, sorry. # Ungolfed (mildly reformatted) =f(length) // Define a stitch f, with one parameter which specifies the length of the created string. This is the intended entry point. ->g(length,3,2) // Instantly divert to g, defined below, with some extra parameters =g(length,balls_left,strikes_left) // Define a stitch g, with three parameters. { - length > 1: // If this is not to be the last character in the string // randomly do one of the following: // 1. If balls_left is nonzero, print a b and recurse // 2. If strikes_left is nonzero, print an s and recurse // 3. Do nothing // If we did not divert earlier, print an f and recurse. {~{balls_left:b->g(length-1,balls_left-1,strikes_left)}|{strikes_left:s->g(length-1,balls_left,strikes_left-1)}|}f->g(length-1,balls_left,strikes_left&&strikes_left-1) - else: // Randomly do one of the following // 1. If a ball would result in a walk, print a b, otherwise an h. // 2. If a strike would result in a strikeout, print an s, otherwise an h. // 3. Just print an h. // And finally, halt. {~{balls_left:h|b}|{strikes_left:h|s}|h}}->-> Edit: Saved a byte by finishing with `->->` instead of `->END`.