4
\$\begingroup\$

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 , so the shortest answer in bytes will win. Good luck!

Thanks to Jonathan Allan for providing a better explanation for the Winning Conditions

asked Feb 3 at 18:13
\$\endgroup\$
5
  • \$\begingroup\$ Is the color used only for see who win? \$\endgroup\$ Commented 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\$ Commented 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\$ Commented 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\$ Commented 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\$ Commented Feb 9 at 0:39

3 Answers 3

4
+100
\$\begingroup\$

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 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 x with value V played 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 y with value v for the computer.

  • We set the winning variable w to \0ドル\$, \1ドル\$ or \2ドル\$ with:

    w = (x + 2 * y) % 3 // test by element
     || 2 * (V < v) | V > v // test by value
    

    Try the element formula online!

  • We print the output for this round.

Finally, if this is not a tie:

  • We add the winning card z to the relevant winning cards array a[]:

    (a = h[--w]).push(z = w ? y : x)
    
  • We check whether there exists 2 other cards x, y in a[] 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, z are 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.

answered Feb 8 at 18:16
\$\endgroup\$
5
  • 1
    \$\begingroup\$ Great attempt! You earned the bounty that was put in place. \$\endgroup\$ Commented Feb 9 at 0:28
  • 1
    \$\begingroup\$ @WeirdGlyphs Thank you for the clarifications. I've updated my answer accordingly. \$\endgroup\$ Commented 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\$ Commented 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\$ Commented 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\$ Commented Feb 9 at 11:27
1
\$\begingroup\$

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
answered Feb 9 at 9:37
\$\endgroup\$
1
\$\begingroup\$

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:

  • u and v are constants (u is also used as the checking boolean at the end of a round in order to check if the game is finished)
  • h is the hand (5 cards chosen randomly with r()), a and b are the winning piles for Player 1 and 2, A and B are the number of cards in each pile, and the other variables are used as temporary values
  • o() 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 using R() until the value is a positive number, and z() modifies u if 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 a and b
answered Feb 7 at 16:21
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.