g | x | w | all
Bytes Lang Time Link
345JavaScript V8250208T181607ZArnauld
614C gcc250207T162136ZWeird Gl
449APLNARS250209T093728ZRosario

JavaScript (V8), 345 bytes

Expects an array of user inputs. Displays lists of cards as comma-separated strings and uses 0/1/2 for the winner.

a=>a.some(n=>print([...h.map(a=>a.map(g=n=>E[n%3]+"YORBGP"[n/3%6|0]+(v=n/18|0))),n--,g(x=H[n],H[n]=c(c[x]=c)),g(R(V=v)),w=(x+2*y)%3||2*(V<v)|V>v].join`
`)|w&&(a=h[--w]).push(z=w?y:x)*a.some(x=>a.some(y=>(F=i=>new Set(g(x)[i]+g(y)[i]+g(z)[i]).size)(1)>2&F(0))),h=[[],[],H=[...E="FWS00"].map(c=_=>c[(R=_=>y=Math.random()*198+36|0)()]?c():c[y]=y)])

Try it online!

Or try this hacked version for a more readable output.

Functions and variables

The helper function R returns a random card in \$[36\dots233]\$ and saves it in the global variable y:

R = _ => y = Math.random() * 198 + 36 | 0

The encoding scheme is as follows:

The recursive helper function c returns a random card for the player, using its own underlying object to make sure that no duplicate card is selected within the player's hand:

c = _ => c[R()] ? c() : c[y] = y

The helper function g converts a card index into its textual representation and saves its value in the global variable v:

g = n => E[n % 3] + "YORBGP"[n / 3 % 6 | 0] + (v = n / 18 | 0)

where E = "FWS00" (we obviously only need "FWS", but E is used elsewhere to build an array of 5 entries).

h[] is an array containing:

H is an alias for h[2].

Main algorithm

For each round:

Finally, if this is not a tie:

C (gcc), 715 685 632 627 620 614 bytes

#define y(x);}x(n,l)int*l;{
#define P;printf(
u,v=11,h[5],a[99],b[99],A,B,i,j,k,I,J,K;o(n){P"%c%c%d","FWS"[n/u],"ROYGBP"[n/v%6],n%v+2)y(O)for(i=0 P i<n?","+!i:" \n")-2;)o(l[i++])y(R)k=n?R(n-1,l+1),k^*l?k:-1:rand()%198;}r(n){for(h[n]=-1;R(5,h),h[n]<0;h[n]=k)u=66 y(z)for(i=n;i--;)for(I=l[j=i]/v;J=l[j]/v,K=l[n-1]/v,j++<n;)u*=I%6==J%6|I%6==K%6|J%6==K%6||(K=K/6-J/6)|(J=I/6-J/6)&&!J|J==K|!K;}main(w){for(srand(&w);i<5;)r(i++);for(;u;z(B,b)){j=h[J=getchar(R(0))-49];K=j%v-k%v;I=j/u^k/u?j/u-(k/u+2)%3?1:-1:(K>0)-(K<0);O(A,a);O(B,b);O(5,h)P"%d\n",J+1);o(j)P"\n");o(k)P"\n%d\n",I);I>0?a[A++]=j:I?b[B++]=k:0;r(J);z(A,a);}}

Try it online!

-53 -58 -65 -71 bytes thanks to ceilingcat, really nice :)

This C version was written in order to check that the challenge was able to be solved even without using a modern programming language. This was pretty fun to make actually, since it was my first answer written in C. This answer was originally posted in order to announce a bounty for the first sub 500-bytes answer (Awarded to Arnauld for his JavaScript anwser).

A small explanation of this code:

APL(NARS), 449 chars

r←h;g;p;l;m;x;t;a;s;d;w
l←≢m←,(0..2)∘.,(0..5)∘.,2..12⋄a←0
t←m[x←?l]⋄m[x]←m[r←?l]⋄m[r]←t⋄→2×⍳l≥a+←1⋄g←p←⍬⋄r←1+i←1⋄d←{⍵≡⍬:''⋄{'FSW'[1+1⊃⍵],'YORBGP'[1+2⊃⍵],⍕3⊃⍵}¨⍵}⋄w←{⍬≡s←⍵:0⋄∨/{k←⍵⋄0=+/q←{⍵[1]=k}¨s:0⋄3≤≢∪{2⊃⍵}¨q/s}¨0 1 2}⋄x←m[i..i+4]⋄i+←5
⎕←d x⋄a←⍎⍞⋄→0×⍳∼a∊⍳5⋄⎕←d(s t)←x[a],m[i]⋄→0×⍳l<i+←1⋄x←x[a∼⍨⍳5]⋄→6×⍳∼t[1]=3∣1+s[1]
g,←⊂s⋄⎕←1
⎕←d g⋄⎕←d p⋄→9×⍳w g⋄→0×⍳w p⋄x,←m[i]⋄→0×⍳l<i+←1⋄→3
→8×⍳∼s[1]=3∣1+t[1]
p,←⊂t⋄⎕←2⋄→5
→4×⍳s[3]>t[3]⋄→7×⍳s[3]<t[3]⋄⎕←0⋄→5
r←1

//24+34+180+81+10+50+19+13+35+3=449 At end the h function return 1 if operator wins, 2 if PC wins. It is possible there is some error. test:

  h
 FY2 FO8 WR10 FP11 FO9 
1
 FY2 FG2 
0


 FO8 WR10 FP11 FO9 FY8 
2
 WR10 SG10 
2

 SG10 
 FO8 FP11 FO9 FY8 WY11 
3
 FO9 SP10 
1
 FO9 
 SG10 
 FO8 FP11 FY8 WY11 FO4 
4
 WY11 SB6 
2
 FO9 
 SG10 SB6 
 FO8 FP11 FY8 FO4 WP8 
5
 WP8 FY3 
1
 FO9 WP8 
 SG10 SB6 
 FO8 FP11 FY8 FO4 FR8 
1
 FO8 WO2 
2
 FO9 WP8 
 SG10 SB6 WO2 
 FP11 FY8 FO4 FR8 WO5 
2
 FY8 WG7 
2
 FO9 WP8 
 SG10 SB6 WO2 WG7 
 FP11 FO4 FR8 WO5 SB10 
3
 FR8 SO8 
1
 FO9 WP8 FR8 
 SG10 SB6 WO2 WG7 
 FP11 FO4 WO5 SB10 FO11 
4
 SB10 WR11 
1
 FO9 WP8 FR8 SB10 
 SG10 SB6 WO2 WG7 
 FP11 FO4 WO5 FO11 WB6 
5
 WB6 SP5 
2
 FO9 WP8 FR8 SB10 
 SG10 SB6 WO2 WG7 SP5 
2