10
\$\begingroup\$

At a party, I was introduced to the game LCR. Now it's not a great game as there's no skill but only random chance. But it got me thinking, I could code this, and I made a quick program in R to model the game.

Rules of the game modified from Wikipedia to match how we played:

Each player receives at least 3 chips. Players take it in turn to roll three six-sided dice, each of which is marked with "L", "C", "R" on one side, and a single dot on the three remaining sides. For each "L" or "R" thrown, the player must pass one chip to the player to their left or right, respectively. A "C" indicates a chip to the center (pot). A dot has no effect.

If a player has fewer than three chips left, they are still in the game but their number of chips is the number of dice they roll on their turn, rather than rolling all three. When a player has zero chips, they pass the dice on their turn, but may receive chips from others and take their next turn accordingly. The winner is the last player to put chips into the center.

Contest: write a program in your language of choice that takes input for the number of players and the number of starting chips and simulates a game of LCR, showing the state of the game after each player has rolled.

For example, a game might be output as:

[[[3,3,3,3],0],[[1,4,3,4],0],[[1,4,3,4],0],[[1,4,1,4],2],[[1,4,1,2],4],
[[0,4,1,3],4],[[0,3,2,3],4],[[0,3,0,3],6],[[0,3,1,1],7],[[0,3,1,1],7],
[[2,0,1,1],8],[[2,0,0,1],9],[[2,0,0,0],10],[[0,1,0,0],11],
[[1,0,0,0],11],[[1,0,0,0],11],[[1,0,0,0],11],[[0,0,0,0],12]]

ht: JonathanAllan

The output doesn't have to look exactly like this, but it should be easy to discern the dice roll, how many chips each player has, and how many chips the centre has for each turn.

It's code golf so the shortest code wins.

\$\endgroup\$
  • 3
    \$\begingroup\$ "it should be easy to discern the dice roll" - it's implicit (hence easy to discern) from the chip states, as is the player who rolled, since it's turn based. I'd argue that this example output has everything necessary: [[[3,3,3,3],0],[[1,4,3,4],0],[[1,4,3,4],0],[[1,4,1,4],2],[[1,4,1,2],4],[[0,4,1,3],4],[[0,3,2,3],4],[[0,3,0,3],6],[[0,3,1,1],7],[[0,3,1,1],7],[[2,0,1,1],8],[[2,0,0,1],9],[[2,0,0,0],10],[[0,1,0,0],11],[[1,0,0,0],11],[[1,0,0,0],11],[[1,0,0,0],11],[[0,0,0,0],12]] - is that the case? \$\endgroup\$ – Jonathan Allan Feb 19 at 3:44
  • 1
    \$\begingroup\$ @JonathanAllan, that works for me. \$\endgroup\$ – CT Hall Feb 19 at 3:49
  • 1
    \$\begingroup\$ @KevinCruijssen, good question, I guess I'll allow either way. \$\endgroup\$ – CT Hall Feb 20 at 15:16
  • 1
    \$\begingroup\$ @CTHall In that case I've edited both my answers (Java and 05AB1E) and included both with and without. :) \$\endgroup\$ – Kevin Cruijssen Feb 20 at 17:52
  • 1
    \$\begingroup\$ I almost want to do this on Runic where each instruction pointer acts as a given player. Not sure I can (even ignoring number of players input), but it'd be neat if I could. \$\endgroup\$ – Draco18s Feb 20 at 19:03
4
\$\begingroup\$

Emacs Lisp, 279 bytes

(defmacro n(i)`(incf(nth ,i c)))
(defun f(p s)(g(let((a'(0)))(dotimes(i p)(push s a))(princ a))0 p))
(defun g(c v p)(dotimes(i(min(nth v c)3))(decf(nth v c))(case(random 6)(0(n(mod(1- v)p)))(1(n(mod(1+ v)p)))(2(n p))(t(n v))))(princ c)(or(eq(-sum c)(nth p c))(g c(mod(1+ v)p)p)))

Use this function as (f 4 3).

Better readable version:

(defmacro n (i) `(incf (nth ,i c)))

(defun f(p s)
  (g
   (let ((a '(0)))
     (dotimes (i p)
       (push s a))
     (princ a))
   0
   p))

(defun g (c v p)
  (dotimes (i (min (nth v c) 3))
    (decf (nth v c))
    (case (random 6)
      (0 (n (mod (1- v) p)))
      (1 (n (mod (1+ v) p)))
      (2 (n p))
      (t (n v))))
    (princ c)
    (or (eq (-sum c) (nth p c))
    (g c (mod (1+ v) p) p)))

Output example:

(3 3 3 3 0)(1 4 3 4 0)(2 2 4 4 0)(2 2 2 5 1)(4 2 2 3 1)(2 2 2 4 2)(2 1 3 4 2)(2 2 0 4 4)(2 2 0 4 4)(1 2 0 4 5)(2 1 0 4 5)(2 1 0 4 5)(2 1 1 3 5)(0 1 1 3 7)(1 0 1 3 7)(1 0 1 3 7)(1 0 3 1 7)(1 0 3 1 7)(1 0 3 1 7)(1 1 2 1 7)(1 1 3 0 7)(0 1 3 0 8)(1 0 3 0 8)(1 1 1 1 8)(1 1 2 0 8)(0 1 2 1 8)(0 1 2 1 8)(0 1 1 1 9)(0 1 1 1 9)(0 1 1 1 9)(0 1 1 1 9)(0 1 1 1 9)(0 1 1 0 10)(0 1 1 0 10)(0 0 1 0 11)(0 0 1 0 11)(0 0 1 0 11)(0 0 1 0 11)(0 0 1 0 11)(0 0 0 0 12)
\$\endgroup\$
3
\$\begingroup\$

Java 8, 281 277 275 274 253 bytes

Version which outputs the same state when a turn player has 0 chips left:

p->n->{java.util.Arrays A=null;int c[]=new int[p],i=0,t,r,s=1,u,f=9;for(A.fill(c,n);s>0;f=0,System.out.print(A.toString(c)))for(t=c[++i%p],t=t>3?3:t;t-->f;r*=Math.random(),c[i%p]-=1-r/3,s=c[u=(i+r-1+p)%p]+=1-r&1-r/4,c[u]=s<0?0:s,s=A.stream(c).sum())r=6;}

Starts with the third player in the array.

Try it online.

Version which skips players with 0 chips left (274 bytes):

p->n->{java.util.Arrays A=null;int c[]=new int[p],i=p,t,r,s=1,u,f=9;for(A.fill(c,n);s>0;f=0,System.out.print(A.toString(c))){for(t=c[i%p],t=t>3?3:t;t-->f;r*=Math.random(),c[i%p]-=1-r/3,s=c[u=(i+r-1+p)%p]+=1-r&1-r/4,c[u]=s<0?0:s)r=6;for(s=A.stream(c).sum();s>0&c[++i%p]<1;);}}

Starts at the first player in the array.

Try it online.

-7 bytes thanks to @OlivierGrégoire.

Explanation (of the second version):

p->n->{                      // Method with two integer parameters and no return-type
  java.util.Arrays A=null;   //  Create a static Arrays-object to save bytes
  int c[]=new int[p],        //  Integer-array with chips of each player (0 by default)
      i=p,                   //  Index integer, starting at the amount of players
      t,                     //  Temp integer to roll 3 dice
      r,                     //  Temp integer for the dice-result
      s=1,u,                 //  Temp integers (and `s` is also the total-sum integer)
      f=9;                   //  Flag integer, starting at a single digit above 3
  for(A.fill(c,n);           //  Give each player in the array the chips
      s>0                    //  Loop as long as the total-sum is not 0 yet
      ;                      //    After every iteration:
       f=0,                  //     Set the flag to 0
       System.out.print(A.toString(c))){
                             //     Print the current state
    for(t=c[i%p],            //   Set `t` to the current player's chips
        t=t>3?3:t;           //   If this is larger than 3: set it to 3 instead
        t-->f                //   Loop that many times (1, 2, or 3)
                             //   (the flag is used to skip this loop the first iteration,
                             //   so we can print the initial state)
        ;                    //     After every iteration:
         r*=Math.random(),   //      Roll the dice in the range [0,5]
         c[i%p]-=r<3?        //      If the dice-roll is 0, 1 or 2:
                  1          //       Remove a chip from this player
                 :0,         //      Else: Leave the chip-amount the same
         s=c[u=(i+r-1+p)%p]  //      If the dice-roll is 0, go to the player left
                             //      If the dice-roll is 2, go to the player right
             +=1-r&1-r/4,    //       And add a chip to this player
         c[u]=s<0?0:s)       //      Change negative amount of chips to 0
      r=6;                   //    Reset the dice-roll to 6 so we can roll again
    for(s=A.stream(c).sum(); //   Calculate the total sum of the chips of the players
        s>0&                 //   If this sum is larger than 0:
         c[++i%p]<1;);}}     //    Determine the next player in line with at least 1 chip
\$\endgroup\$
  • 1
    \$\begingroup\$ Could leave my upvote without a (tiny) golf :D s=0;for(int C:c)s+=C; (21 bytes) can be replaced by s=A.stream(c).sum(); (20 bytes) \$\endgroup\$ – Olivier Grégoire Feb 20 at 11:06
  • \$\begingroup\$ Also, not sure if entirely ok: c[i%p]-=r<3?1:0c[i%p]-=1-r/3. This would save 2 bytes. \$\endgroup\$ – Olivier Grégoire Feb 20 at 11:11
  • 1
    \$\begingroup\$ @OlivierGrégoire Ah, smart way of re-using the A from java.util.Arrays. :D And by putting it in the loop to save on the semi-colon it's -2 bytes. And 1-r/3 is indeed correct (see here). Thanks. \$\endgroup\$ – Kevin Cruijssen Feb 20 at 12:03
  • \$\begingroup\$ Nice trick with the loop comparison decrementing. I might steal that. \$\endgroup\$ – Stackstuck Feb 20 at 12:14
  • 1
    \$\begingroup\$ Ignore my previous deleted comment: my truth table was off. This is the fixed one: s=c[u=(i+r-1+p)%p]+=1-r&1-r/4 (saves 2 bytes, compared to s=c[u=(i+r%2*2-1+p)%p]+=r<2?1:0) \$\endgroup\$ – Olivier Grégoire Feb 20 at 12:47
2
\$\begingroup\$

Python 2, 159 148 bytes

from random import*
n,c=input()
g=[c]*n;i=0
while sum(g):exec"r=randrange(6);g[i]-=1;g[i-[0,1,~-n][max(0,r-3)]]+=r>0;"*min(3,g[i]);i=(i+1)%n;print g

Try it online!

Prints all players chips after every roll

\$\endgroup\$
  • \$\begingroup\$ Good attempt, but the code doesn't show the amount of chips in the centre. \$\endgroup\$ – CT Hall Feb 19 at 15:41
  • 3
    \$\begingroup\$ @CTHall The chips in the center is always equal to n*c - sum(players). If I need to explicitly write it out, I will \$\endgroup\$ – TFeld Feb 19 at 16:01
  • \$\begingroup\$ that's true. I'll allow it. \$\endgroup\$ – CT Hall Feb 20 at 15:09
2
\$\begingroup\$

Jelly, 39 bytes

+2 to fix repetition behaviour (¡ must be preceded by a nilad so «3Ḣ$ -> ⁸FḢ«3)

If we can define the output lists to be rotated to have the chips belonging to the player who acted previously at the left we can do away with the right-most 6 bytes for 33 bytes (however, in my opinion, it is somewhat awkward to read that).

ẋµ’1¦‘.,2ŻX¤¦$¹Ø.X¤?⁸FḢ«3¤¡ṙ1µSпṙ"JC$$

A dyadic Link accepting chips-per-player on the left and number-of-players on the right which yields a list of players chip counts as at the start of the game and after each turn (including turns where 0 chips forces a pass).

Try it online!

How?

Each player in turn, up to three times, depending on their chip count, flips a coin. When a player flips heads they do nothing but if they flip tails they then roll a three sided die losing a chip to L, C or R. (Note that 0 flips when a player has 0 chips is equivalent to passing.)
This is repeated until the sum of the players chips is 0.
The implementation rotates the players left by one place each turn and then rotates the resulting states back to all be aligned as if they were not.

ẋµ’1¦‘.,2ŻX¤¦$¹Ø.X¤?⁸«3Ḣ¤¡ṙ1µSпṙ"JC$$ - Link: chipsPerPlayer, C; numberOfPlayers, P
ẋ                                      - repeat C P times (making a list of P Cs)
                              п       - collect up results in a list while...
                             S         - ...п condition: sum (while players have chips)
 µ                          µ          - ...п do: the monadic chain:
                         ¡             -   repeat...
                        ¤              -   ...¡ number of times: nilad and link(s) as a nilad:
                    ⁸                  -     chain's left argument (the chip list)
                     «3                -     minimum with three (vectorises)
                       Ḣ               -     head -- i.e. min(left-most player's chips, 3)
                   ?                   -   ...¡ action: if...
                  ¤                    -     ...? clause: nilad and link(s) as a nilad:
               Ø.                      -       the list [0,1]
                 X                     -       random choice (0 is falsey while 1 is truthy)
             $                         -     ...? then: last two links as a monad:
    ¦                                  -       sparsely apply...
   1                                   -       ...¦ to indices: one (the left-most)
  ’                                    -       ...¦ action: decrement (player lost a chip)
            ¦                          -       sparsely apply...
           ¤                           -       ...¦ to indices: nilad and link(s) as a nilad:
      .,2                              -         literal pair of literals .5 and two = [.5,2]
         Ż                             -         prepend a zero = [0,0.5,2]
          X                            -         random choice
                                       -         -- Note application to index .5 is a no-op
                                       -                 index 0 is the right-most entry (L) 
                                       -                 index 2 is the second entry (R) 
                          ṙ1           -   rotate the list left by one for the next п loop
                                     $ - last two links as a monad:
                                    $  -   last two links as a monad:
                                  J    -     range of length -- i.e. [1,2,3,...,turns+1]
                                   C   -     complement = 1-x        [0,-1,-2,...,-turns]
                                 "     -   zipped-appliction of:
                                ṙ      -     rotate left by
                                       -   -- i.e. rotate 1st left by 0, 2nd left by -1, ...)
\$\endgroup\$
  • \$\begingroup\$ I'm a bit impressed as to how people code in these languages that look like line noise. :) But then I only know a couple of languages kinda, so maybe with more experience it'll come. \$\endgroup\$ – CT Hall Feb 20 at 18:21
  • 2
    \$\begingroup\$ You could check out the tutorial at the wiki, it's pretty good. Once I post the code breakdown you will hopefully follow what I've done... \$\endgroup\$ – Jonathan Allan Feb 20 at 18:23
  • \$\begingroup\$ ...this is subtly incorrect behavior, though? Per spec, you need to roll all three dice, not just one coin flip. Unless the description is in error and the code is fine. \$\endgroup\$ – Stackstuck Feb 21 at 12:58
  • \$\begingroup\$ @Stackstuck - the description overview is slightly misleading, the coin is flipped each time; I shall fix it - thanks. FWIW the code breakdown description is right - the coin flip branching, Ø.X¤?, is nested inside the repeat-up-to-3-times instruction, ⁸«3Ḣ¤¡. \$\endgroup\$ – Jonathan Allan Feb 21 at 15:01
  • \$\begingroup\$ Ah, okay. Glad I could help. \$\endgroup\$ – Stackstuck Feb 22 at 1:03
1
\$\begingroup\$

C#, 356?+13? Bytes

Requires using System; for a total of +13 bytes to the code shown below, if I'm required to count that. Otherwise just plonk it in any class and call L(players, starting chips);.

static int i,j,k,l;public static void L(int p,int s){var r=new Random();var x=new int[p];for(i=0;i<p;i++)x[i]=s;
for(i=0;i<s*p;){for(j=0;j<p;j++){for(l=0;l<x[j]&l<3;l++){k=r.Next(-1,5);if(k<2){if(k==0){x[j]--;i++;}else{x[(p+j+k)%p]++;x[j]--;}}}Console.Write(a(x)+i);}}}public static string a(int[] x){var n="|";for(l=0;l<x.Length;)n+=x[l++]+" ";
return n;}

Sample output for a 2,2 game:

|1 3 0|2 2 0|1 3 0|1 3 0|0 4 0|0 3 1|0 3 1|2 1 1|1 2 1|1 2 1|0 3 1|0 3 1|0 3 1|1 1 2|1 1 2|1 1 2|0 2 2|1 1 2|0 1 3|1 0 3|0 1 3|0 1 3|0 1 3|1 0 3|1 0 3|1 0 3|0 1 3|1 0 3|0 1 3|0 0 4

Less golfed version:

using System;
//class omitted.
static int i,j,k,l;
public static void LCR(int pl, int sc){
var r=new Random();
var state = new int[pl];
for(i=0;i<pl;i++)state[i]=sc;
for(i=0;i<sc*pl;){
    for(j=0;j<pl;j++){
        for(l=0;l<state[j] && l<3;l++){
            k=r.Next(-1,5);
            if(k<2){
                if(k==0){state[j]--;i++;}else{state[(pl+j+k)%pl]++;state[j]--;}
            }
        }
        Console.Write(a(state)+i);
    }
}
}
public static string a(int[] x){
    var n="|";
    for(l=0;l<x.Length;)n+=x[l++]+" ";
    return n;
}
\$\endgroup\$
  • \$\begingroup\$ Well, this is my first answer here ever. Please don't eat me. \$\endgroup\$ – Stackstuck Feb 20 at 6:53
  • \$\begingroup\$ Ah, drat. I got my array printing behavior confused with Java. I'll just be...right back with a revision. \$\endgroup\$ – Stackstuck Feb 20 at 7:10
  • \$\begingroup\$ Okay, that's fixed, output should definitely work. \$\endgroup\$ – Stackstuck Feb 20 at 7:22
  • \$\begingroup\$ ...oh, nope, there's one more error. \$\endgroup\$ – Stackstuck Feb 20 at 7:29
  • \$\begingroup\$ People saying modulo when the behavior is actually remainder should...not do that. There, I'm 90% sure this works now. \$\endgroup\$ – Stackstuck Feb 20 at 7:37
1
\$\begingroup\$

C# (Visual C# Interactive Compiler), 201 199 bytes

n=>m=>{var r=new Random();var j=Enumerable.Repeat(n,m).ToList();for(int i=0;j.Any(c=>c>0);i++,Print(j))for(int k=0,x=r.Next(6);k++<Math.Min(j[i%m],3);j[((x<1?-1:1)+i+m)%m]+=x<2?1:0,j[i%m]-=x<3?1:0);}

Try it online!

startingChips=>playerNum=>{
//Instantiate a new random number generator
var rng = new Random();
//Create a list of chips
var players = Enumerable.Repeat(startingChips, playerNum ).ToList();
//Loop as long any player still has chips
for(int turnNum = 0;players.Any(c=>c>0);
//And print the result every iteration
i++,Print(j))
//Get a random number within the range of 0-5 and loop for...
for(int k = 0,randomNum = rng.Next(6);
//either 3 or the amount of chips we have, whichever is smaller
k++<Math.Min(players[turnNum % playerNum ],3);
//Increment either the right player if the random number is 1, else increment the right player if it is 0
players[((randomNum<1?-1:1)+ turnNum + playerNum ) % playerNum ]+=x<2?1:0,
//Decrement current player if the die roll is under 3
players[ turnNum % playerNum ]-=x<3?1:0);}
\$\endgroup\$
1
\$\begingroup\$

Charcoal, 61 bytes

≔⁰ηWΣθ«≔Eθ⭆⌊⟦κ׳⁼λη⟧‽⁶ιUMθ⁻⁺⁺κ№§ι⊕λ3№§ι⊖λ5LΦ§ιλ›μ2≔﹪⊕ηLθη⟦⪫θ,

Try it online! Link is to verbose version of code. Alternates between outputting the dice rolls and chips left (neither the initial number of chips nor the number of chips in the centre are included in the output). Explanation:

≔⁰η

Start with the first player.

WΣθ«

Repeat until nobody has any chips left.

≔Eθ⭆⌊⟦κ׳⁼λη⟧‽⁶ι

Roll up to three dice for the current player. These dice are labelled 0-5, where 0-2 represent the dot, 3 is pass to left, 4 is to centre, 5 is to right.

UMθ⁻⁺⁺κ№§ι⊕λ3№§ι⊖λ5LΦ§ιλ›μ2

Add the number of chips the player on the right passed left and the number of chips the player on the left passed right, but subtract the number of chips the player themselves passed on.

≔﹪⊕ηLθη

Advance to the next player.

⟦⪫θ,

Output the the new numbers of chips held by the players.

It's actually simpler for everyone to roll their dice simultaneously, which can be done in 50 bytes, including printing the dice rolls as well as the chips left:

WΣθ«≔Eθ⭆⌊⟦κ³⟧‽⁶ιUMθ⁻⁺⁺κ№§ι⊕λ3№§ι⊖λ5LΦ§ιλ›μ2⟦⪫ι,⪫θ,

Try it online! Link is to verbose version of code.

\$\endgroup\$
  • \$\begingroup\$ I'm not sure, but it doesn't seem as if it accounts for the number of chips held after each role, not each round. \$\endgroup\$ – CT Hall Feb 26 at 19:36
  • \$\begingroup\$ @CTHall Oh, you mean each player rolls individually, and then the numbers of chips are updated? Sorry, I overlooked that. I'll update my answer as soon as I have the time. \$\endgroup\$ – Neil Feb 27 at 1:08
1
\$\begingroup\$

Runic Enchantments, 825 bytes

non-competing (see below)

  \y̤y̤y̤y̤y̤y̤\ >>y4J  4J  4J"|3,3,3|0"akq$ 1I     9?;w ;'69w/
  \      D     \72B͍\74B͍\76B͍           \'|$m1-:$9=?/92';w\
m1-$]1JR0Tm1)3*?02B͍6'RA:2)bb+*?:2=d*?1=4*?1J2?1J2?1JF
      \  \'|$;                             \74B\76B͍\4X8B͍9
m1-$]1JR0Tm1)3*?04B͍6'RA:2)bb+*?:2=d*?1=4*?1J2?1J2?1JF
      \  \',$;                             \76B\72B͍\4X8B͍4
m1-$]1JR0Tm1)3*?06B͍6'RA:2)bb+*?:2=d*?1=4*?1J2?1J2?1JF
 /J1  /  \',$;                        /0\  \72B\74B͍\4X8B͍'
 \                                    T;UL $kaL   \     ;

Try it online!

This is, effectively, an incomplete answer, but it was by far the more interesting part of that answer. See the non-competing section below.

Not that this code was not, itself, a pain to create, but it was more interesting than trying to write the code that would produce this code as output (similarly, trying to compress it without messing up the timing and having to deal with continuously updating the Branch target locations is a nightmare: there are 4 separate locations that are teleported to, three of which are each referenced four times, the last one referenced three times).

Explanation

  \      \ >>y4J  4J  4J"|3,3,3|0"akq$     9?
  \      D     \72B͍\74B͍\76B͍           

This section starts everything off, prints the initial token values for each player (and the pot in the middle) and spawns IPs that will keep track of each player. The 4J creates these pointers, with a starting mana value equal to the player's chips (plus 1). The right hand remainder of these lines deals with printing the pot and checking if the last turn happened. The 9? skips over a chunk of termination code so that the IP wraps around, hits the D, causing it to pass over the first player's T, getting the ball rolling.

m1-$]1JR0Tm1)3*?02B͍6'R2:2)bb+*?:2=d*?1=4*?1J2?1J2?1JF
      \  \'|$;                             \74B\76B͍\4X8B͍9

These two lines (and the following four that are near duplicates) handle a single die roll for a single player (see this for 3 rolls per player, its quite wide, and effectively just a 3x duplication of each player row).

T handles holding the IP until the previous player completes their turn, printing their current token pool, spawning an IP with 1J, which passes over the next player's T perpendicularly, then printing either a | or , (for output formatting) before terminating.

The remainder is then these sections:

          m1)3*?   6'R2:2)                           .
                02B͍       bb+*?                   1JF
                               :2=d*?         1J2?
                                     1=4*?1J2?

In order:

  • check to see if the IP has more than 1 mana (if not, return to T)
  • Generate a random number 0-5
  • Compare with >2, =2, =1. True: skip to next section on same line
  • Each false drops down a line (in the above depiction) and executes instructions until it hops back up a line (each 2? skips the previous line's code block)
  • Each 1J spawns an IP that either adds 1 to another player or adds 1 to the pot (the subsequent line contains 3 branch instructions: the player above, the player below, and the pot).

The IP then wraps around back to the left where it prints its current mana value (minus 1), clears the stack of any remaining junk, and returns to the T to wait.

The third player's turn passing also includes a second IP generated to output the size of the pot, check the pot to see if it has 9 tokens in it, and if so, terminate.

                                  .          ;w;'69w/        //cause termination
                                  \'|$m1-:$9=?/92';w\        //print and check pot
                                                    9
                                                    4
                                                    '
                                  /0\               ;
                                  T;UL.$kaL...\             //print newline and wait

The sequence in the top left, \y̤y̤y̤y̤y̤y̤\ delays the 3rd -> 1st player execution long enough for the pot to be checked and printed (note that the ̤ blend in in the code block, but display just fine inline). Removed from golfy 825 byte version due to not-forking and just wrapping around the width of the program.

Termination involves replacing the 3 T instructions with a terminator ;.

Non-competing

I accomplished the goal I set out in this comment, so even though it does not actually conform to spec (not taking any input), but the best parts of the challenge presented are here. Its just that the 'meta-golf' needed for a "real" answer is not as fun (read: a complete nightmare). First the code presented here would need to be golfed as much as possible, identifying the per-player segments, and then encoded inside a larger program that would take input, construct this program as a string (via a kolmogorov complexity exercise), and then run Eval on it.

The end result would be far, far less interesting to create and showcase.

825 byte version. Despite the remaining regions of empty space, it is probably about as golfed as it can get.

\$\endgroup\$
1
\$\begingroup\$

05AB1E (legacy), 58 50 49 52 bytes

Version which outputs the same state when a turn player has 0 chips left (50 49 52 bytes):

и[=ÐO_#¾è3‚Ws\F5ÝΩ©3‹iε¾¹%NQ-}®≠iε®<¾+¹%NQ+}}}}D0›*¼

Try it online.

Version which skips players with 0 chips left (58 57 60 bytes):

и[=DO_#[D¾èDĀ#\¼}3‚Ws\F5ÝΩ©3‹iε¾¹%NQ-}®≠iε®<¾+¹%NQ+}}}}D0›*¼

Try it online.

Both +3 bytes by using the legacy version, because the new 05AB1E version has a weird bug. It should work with Ws\ (push minimum without popping; swap; discard list) replaced with ß (pop list and push minimum) and 0› (check if larger than 0) replaced with d (check if non-negative / larger than or equal to 0) in the new version, but for some reason the list order is changed after the trailing ¼!.. :S (and the new version is also extremely slow and times out after 60 sec before finishing the result.. >.>)

The first input is the amount of players, second input the amount of chips per player.

Explanation (of the second version):

и                    # Create a list with a size of the (first) implicit input,
                     # filled with the second (implicit) input
[                    # Start an infinite loop:
 =                   #  Print the list with trailing newline, without popping the list
 DO_#                #  If the total amount of chips is 0: stop the infinite loop
 [                   #  Start an inner infinite loop:
  D¾è                #   Get the chips of the I'th player (I is 0 by default)
     D               #   Duplicate this
      Ā#             #   If it is NOT 0: stop the inner infinite loop
        \            #   Remove the duplicated chips for the next iteration
         ¼           #   And increase I by 1
 }                   #  After the inner infinite loop:
 3‚Ws\               #  If the amount of chips is larger than 3: use 3 instead
      F              #  Loop that many times:
       5ÝΩ           #   Roll a random dice in the range [0,5]
       ©3‹i          #   If the dice-roll is 0, 1, or 2:
           ε¾¹%NQ-}  #    Remove a chip from the I'th player
           ®≠i       #    If the dice-roll is NOT 1:
              ε®<¾+  #     Go to the player left if 0; or right if 2
              ¹%NQ+} #     And increase that player's chips by 1
      }}}            #  Close both if-statements and the loop
         D0›*        #  Make any negative amount of chips 0
             ¼       #  Increase I by 1
\$\endgroup\$
  • \$\begingroup\$ I'm not sure it is working correctly. It seems players can gain chips on their turn which shouldn't happen. \$\endgroup\$ – CT Hall Mar 8 at 3:53
  • \$\begingroup\$ @CTHall Are you sure? In which of the four TIO versions did you see this? I only checked the last (legacy version which skips players with 0 chips), but the only time it increases a player is when another player is at turn. Here is that last one with added debug-line so you can see which (0-indexed) player is at turn. \$\endgroup\$ – Kevin Cruijssen Mar 8 at 7:39
  • 1
    \$\begingroup\$ The legacy ones seem to be correct, but the nonlegacy seems to have the error I mentioned. \$\endgroup\$ – CT Hall Mar 8 at 14:41
  • \$\begingroup\$ @CTHall Ah, you're indeed right. I see a line [2, 3, 3, 3] followed by [2, 2, 2, 6].. :S I'll see if I can find the cause and fix it. If not, I can always delete it and only use the legacy, since it outputs a lot more anyway.. The new version is pretty slow with complex loops for some reason.. >.> \$\endgroup\$ – Kevin Cruijssen Mar 8 at 16:55
  • \$\begingroup\$ @CTHall I've been able to pinpoint the issue, but unable to fix it. For some reason the order of the list get changed right after increasing the global counter_variable.. I tried to reproduce the issue in a simpler example, but am unable to. It has something to do with the nested if-statements and maps inside the infinite loop, but it's definitely weird.. Anyway, I've removed that version and now only the legacy (and faster) version remains, which works as intended. \$\endgroup\$ – Kevin Cruijssen Mar 8 at 18:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.