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:


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.

  • 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 '19 at 3:44
  • 1
    \$\begingroup\$ @JonathanAllan, that works for me. \$\endgroup\$ – CT Hall Feb 19 '19 at 3:49
  • 1
    \$\begingroup\$ @KevinCruijssen, good question, I guess I'll allow either way. \$\endgroup\$ – CT Hall Feb 20 '19 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 '19 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 no longer trusts SE Feb 20 '19 at 19:03

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)
   (let ((a '(0)))
     (dotimes (i p)
       (push s a))
     (princ a))

(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)
|improve this answer|||||

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
                             //     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
|improve this answer|||||
  • 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 '19 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 '19 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 '19 at 12:03
  • \$\begingroup\$ Nice trick with the loop comparison decrementing. I might steal that. \$\endgroup\$ – Stackstuck Feb 20 '19 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 '19 at 12:47

Python 2, 159 148 bytes

from random import*
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

|improve this answer|||||
  • \$\begingroup\$ Good attempt, but the code doesn't show the amount of chips in the centre. \$\endgroup\$ – CT Hall Feb 19 '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 '19 at 16:01
  • \$\begingroup\$ that's true. I'll allow it. \$\endgroup\$ – CT Hall Feb 20 '19 at 15:09

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).


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!


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, ...)
|improve this answer|||||
  • \$\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 '19 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 '19 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 '19 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 '19 at 15:01
  • \$\begingroup\$ Ah, okay. Glad I could help. \$\endgroup\$ – Stackstuck Feb 22 '19 at 1:03

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(l=0;l<state[j] && l<3;l++){
public static string a(int[] x){
    var n="|";
    for(l=0;l<x.Length;)n+=x[l++]+" ";
    return n;
|improve this answer|||||
  • \$\begingroup\$ Well, this is my first answer here ever. Please don't eat me. \$\endgroup\$ – Stackstuck Feb 20 '19 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 '19 at 7:10
  • \$\begingroup\$ Okay, that's fixed, output should definitely work. \$\endgroup\$ – Stackstuck Feb 20 '19 at 7:22
  • \$\begingroup\$ ...oh, nope, there's one more error. \$\endgroup\$ – Stackstuck Feb 20 '19 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 '19 at 7:37

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!

//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
//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);}
|improve this answer|||||

Charcoal, 61 bytes


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.


Repeat until nobody has any chips left.


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.


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.


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:


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

|improve this answer|||||
  • \$\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 '19 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 '19 at 1:08

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):


Try it online.

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


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
|improve this answer|||||
  • \$\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 '19 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 '19 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 '19 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 '19 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 '19 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.