Part 1 is available here.
Card-Jitsu was a mini card-game based on Rock, Paper, Scissors available on the children MMO game Club Penguin. A lot of footage of this game is available online, and may be useful if you want to know what the actual game looks like. However, you obviously don't need to know the rules in order to publish an answer. I will describe a short modified version of the rules that you will have to implement for this challenge. This second part is completely independent from the first one, so you don't need to complete Part 1 in order to write an answer for Part 2. However, Part 1 is easier to complete and explains with more details the Winning Conditions used for the end of the game, so it might be useful to check it out.
If you have any doubt about these rules, please ask about it in the comments section.
Cards (<!> Different from Part 1)
A card in Card-Jitsu is composed of three attributes:
- An element, either Fire (F), Water (W) or Snow (S)
- A color, either Yellow (Y), Orange (O), Red (R), Blue (B), Green (G) or Purple (P)
- A value between 2 and 12 inclusive
You will display a Card-Jitsu card as the concatenation between the letter representing its element, the letter representing its color, and its value (e.g., FB9 for a Blue Fire card with value 9). All possible values (198 cards in total (3x6x11)) can be combined in order to create a valid card, and all valid cards can be generated randomly in the game with equal probability.
Game Loop and I/O
Input: Multiple inputs between 1 and 5 inclusive.
Output: Direct printing to STDOUT, a string or any similar data type.
Player 1 will be controlled by the user, while Player 2 will be controlled by the computer. At the start of the game, Player 1 will receive a hand of five random cards. This hand must never contain any duplicate at any time during the game (e.g., The hand cannot contain two copies of WR4). Only Player 1 has a hand, Player 2 will play randomly without any restriction.
The game will have multiple rounds. At the start of each round, you will display the cards won by Player 1, the cards won by Player 2 (see Winning Conditions for more) and the current hand of Player 1. Player 1 will then input a number between 1 and 5 in order to select the card they want to play. You are allowed to receive every input at the beginning. It will then display the card chosen by Player 1, the card chosen by Player 2, which will be a random valid card (no extra condition, this can be any card), and will then display 1 if Player 1 won this round, -1 or 2 if Player 2 won (choose one or the other), or 0 in case of a tie. It will then start a new round by adding a new card to Player 1's hand. As previously stated, only one copy of each card is allowed in the hand.
A single round will be displayed like this:
[FO5,WG6,WY9] <- Cards won by Player 1
[SY4] <- Cards won by Player 2
[SG10,FB4,SR9,WY7,FO8] <- Player 1's hand
2 <- User input (Between 1 and 5)
FB4 <- Card chosen by Player 1 (The 2nd card in their hand)
SY6 <- Card chosen by Player 2 (Random)
1 <- Player 1 won this round (Fire beats Snow)
You must follow this output format, with a line break separating each section of the output. However, you are allowed to display lists of cards however you want, as long as it is consistent and coherent. For example, SG10 FB4 SR9 WY7 FO8, [SG10, FB4, SR9, WY7, FO8] and {SG10/FB4/SR9/WY7/FO8} are all valid ways to display a list of cards. If you have any doubt, please ask about it in the comments. The hand will always have 5 cards. However, the winning pile for Player 1 and 2 can, in theory, have an infinite amount of cards. In order to simplify this for languages without easy access to dynamic memory allocation, a winning pile must be able to contain at least 99 cards without problem. You can of course exploit that for your own program.
Winning Conditions
In order to determine who won a specific round, you will have to compare the two cards chosen by Player 1 and 2 and follow these rules:
- If the elements are different, Fire beats Snow, Snow beats Water, and Water beats Fire
- If the elements are the same, but the cards have different values, the highest value wins
- Otherwise, it's a tie, no one wins this round
If one of the two players wins a round, the card they played will be added to their winning pile. The winning pile can contain multiple copies of the same card and can contain cards that are also in Player 1's hand. Only the hand itself must have no duplicate. If there exists a set of three cards of differing colors within the pile that either (a) all have the same element or (b) all have differing elements, the player wins the whole game and the program/function stops. A valid set of three cards must have cards with different colors every single time, with no exception.
In other words, the elements and values are used in order to determine who wins a round, while the elements and the colors are used in order to determine who wins the whole game.
Example
Here's a full example showing one possible outcome:
[]
[]
[SG10,FB4,SP9,WY7,FO8]
2
FB4
IY6
1 <- First round ends here
[FB4] <- Second round starts here
[]
[SG10,SP9,WY7,FO8,WR2]
3
WY7
WB8
2
[FB4]
[WB8]
[SG10,SP9,FO8,WR2,FY5]
1
SG10
WG10
1
[FB4,SG10]
[WB8]
[SP9,FO8,WR2,FY5,WG7]
5
WG7
WY4
1
[FB4,SG10,WG7]
[WB8]
[SP9,FO8,WR2,FY5,FB3]
3
WR2
WG2
0
[FB4,SG10,WG7]
[WB8]
[SP9,FO8,FY5,FB3,WR7]
1
SR9
WO10
1 <- Player 1 won the entire game (FB4,-,WG7,SR9)
This is code-golf, so the shortest answer in bytes will win. Good luck!
Thanks to Jonathan Allan for providing a better explanation for the Winning Conditions
-
\$\begingroup\$ Is the color used only for see who win? \$\endgroup\$Rosario– Rosario2025年02月08日 19:44:30 +00:00Commented Feb 8 at 19:44
-
\$\begingroup\$ "Otherwise, it's a tie, no one wins this round" that means the 2 card gamed are discarded? \$\endgroup\$Rosario– Rosario2025年02月08日 19:53:25 +00:00Commented Feb 8 at 19:53
-
\$\begingroup\$ Are we supposed to internally maintain a hand of 5 cards for the computer as well, or can we just draw a random card each time it plays? (I assumed the former, although I believe that's a non-observable requirement). Also, may the same card be drawn several times during the same game or is it definitely removed from the deck? \$\endgroup\$Arnauld– Arnauld2025年02月08日 22:32:41 +00:00Commented Feb 8 at 22:32
-
1\$\begingroup\$ @Rosario The color is only used when checking if someone won the entire game or not, this is its only purpose. After a round, no matter what, Player 1 looses the card they played from their hand and gains a new random card that isn't already in their hand (In the original game, same thing for Player 2, but I decided than managing Player 2's hand was maybe a bit too hard). In case of a tie, the only thing that changes is that no one gets a card added to their winning pile. So yeah, they are basically discarded, though they can still be generated randomly for the next round. \$\endgroup\$Weird Glyphs– Weird Glyphs2025年02月09日 00:34:04 +00:00Commented Feb 9 at 0:34
-
1\$\begingroup\$ @Arnauld It was actually the latter (no extra requirement, just a random card, this was done in order to simplify the rules and also because it would be non-verifiable otherwise). The same card can be drawn several times, the only requirement is for Player 1 to not have any duplicate in their hand. \$\endgroup\$Weird Glyphs– Weird Glyphs2025年02月09日 00:39:31 +00:00Commented Feb 9 at 0:39
3 Answers 3
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)])
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 element is \$n \bmod 3\$
- the color is \$\lfloor n/3\rfloor \bmod 6\$
- the value is \$\lfloor n/18\rfloor\$
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:
- at index 0: the winning cards of player 1 (initially empty)
- at index 1: the winning cards of player 2 (initially empty)
- at index 2: the hand of player 1 (always filled with 5 distinct card indices)
H is an alias for h[2].
Main algorithm
For each round:
We pick the card
xwith valueVplayed by the player.The selected card is freed by doing
c[x] = c.We replace it in the player's hand with a new random card.
We pick a random card
ywith valuevfor the computer.We set the winning variable
wto \0ドル\$, \1ドル\$ or \2ドル\$ with:w = (x + 2 * y) % 3 // test by element || 2 * (V < v) | V > v // test by valueWe print the output for this round.
Finally, if this is not a tie:
We add the winning card
zto the relevant winning cards arraya[]:(a = h[--w]).push(z = w ? y : x)We check whether there exists 2 other cards
x,yina[]so that(x,y,z)meets the conditions for winning the whole game:a.some(x => // for each card x in a[]: a.some(y => // for each card y in a[]: ( F = i => // F is a helper function taking i: new Set( // build a set by splitting this string: g(x)[i] + // either the element or the color of x g(y)[i] + // either the element or the color of y g(z)[i] // either the element or the color of z ).size // return the size of the set )(1) > 2 // invoke F for the color (must be 3) & F(0) // invoke F for the element (must be odd) ) // end of inner some() ) // end of outer some()(we don't have to do anything to make sure that
x,y,zare distinct because we can't get 3 distinct colors if they're not anyway)If the above test succeeds, it triggers the top-level
some()of the main function and stops the execution.
-
1\$\begingroup\$ Great attempt! You earned the bounty that was put in place. \$\endgroup\$Weird Glyphs– Weird Glyphs2025年02月09日 00:28:08 +00:00Commented Feb 9 at 0:28
-
1\$\begingroup\$ @WeirdGlyphs Thank you for the clarifications. I've updated my answer accordingly. \$\endgroup\$Arnauld– Arnauld2025年02月09日 09:40:41 +00:00Commented Feb 9 at 9:40
-
\$\begingroup\$ It seems to me the card WG8 is both in a buffer and in the hand in the end of tio try program output WO2,FO6,SG7,SG10,SO12 FP11,FG11,SG11,WG8 SP4,FB9,SB9,WG8,FP8 2 FB9 SO6 2 \$\endgroup\$Rosario– Rosario2025年02月09日 11:14:30 +00:00Commented Feb 9 at 11:14
-
1\$\begingroup\$ @Rosario According to WeirdGlyphs clarifications, this may indeed happen: The same card can be drawn several times, the only requirement is for Player 1 to not have any duplicate in their hand. \$\endgroup\$Arnauld– Arnauld2025年02月09日 11:17:59 +00:00Commented Feb 9 at 11:17
-
1\$\begingroup\$ @Rosario I can confirm that this is indeed valid, I will probably modify the rules in order to make it obvious that this is allowed and expected. \$\endgroup\$Weird Glyphs– Weird Glyphs2025年02月09日 11:27:08 +00:00Commented Feb 9 at 11:27
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×ばつ⍳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×ばつ⍳∼a∊⍳5⋄⎕←d(s t)←x[a],m[i×ばつ⍳l<i+←1⋄x←x[a×ばつ⍳∼t[1]=3∣1+s[1]
g,←⊂s⋄⎕←1
⎕←d g⋄⎕←d p×ばつ⍳w g×ばつ⍳w p⋄x,←m[i×ばつ⍳l<i×ばつ⍳∼s[1]=3∣1+t[1]
p×ばつ⍳s[3]&g×ばつ⍳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
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);}}
(削除) -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:
uandvare constants (uis also used as the checking boolean at the end of a round in order to check if the game is finished)his the hand (5 cards chosen randomly withr()),aandbare the winning piles for Player 1 and 2,AandBare the number of cards in each pile, and the other variables are used as temporary valueso()prints a single card,O()prints a list of cards,R()generates a random card and checks recursively if the card is contained within l, adds -1 to the list otherwise,r()chooses a new random card for the hand, added at position n, by usingR()until the value is a positive number, andz()modifiesuif the game is finished- The main program retrieves the two cards chosen by each player, calculates the winner for this round, prints the required lines, adds a new card to the hand, and checks if the game is finished using both
aandb