Sutda Game
Code Battle
한글로 보기

Game Rules

Read the strategy guide
Check the rules of the game, fill in the functions below, select your opponent and press the start button to start the game.
You and your opponent will each receive 2 cards (Hwatu card), and it is a game where you win or lose with a combination of 2 cards.
There are 20 cards in total, and there are two pairs of cards that represent the numbers 1 to 10. It is assumed that the cards consist of numbers 1 to 10 and numbers 11 to 20 so that only the numbers can be distinguished. For example, 15 is the second card meaning 5.
You get money when the game starts, you get 2 cards and 1 opponent card at the start of the round, and you have to choose raise or call or die on each turn.
"raise" is an action that raises table money, "call" is an action that accepts only the amount of money raised by the opponent and ends the round and confirms the win or lose, and "die" is an action that gives up the opponent's card check and pays only the basic money(1) before giving up the round.

My Code (JavaScript)

Opponents

Online battles are played between signed-in members. Sign in to join.
If you or the opponent's screen is not visible, the communication speed will be slower.
TURN
ME
-
VS
OP
-
ROUND
ME
0
+0
OP
0
+0
GAME
WIN
0
LOSE
0

Game Log

Recent logs are displayed at the top.

When to fold and when to call

In Sutda you cannot choose your hand. The cards come at random, and all you decide is whether to bet, call, or fold. That narrows strategy down to one question: when do you fold? And folding costs 1 too. Below are three ways to fold and the score each one actually produced.

1. Call whatever is on the table (the default sample)

This is what the default code on this page does. It bets 1 when it goes first, and otherwise calls exactly what the opponent bet. It never looks at its own hand. The rank table for all 20 cards sits further down this page and this code never uses it.

LEVEL 1 roughly even LEVEL 2·3 mostly loses

Against LEVEL 1 it is even, because that opponent also bets only 1 and never folds, so a round moves just 1 either way. But LEVEL 2 and LEVEL 3 raise hard when they hold a strong hand. Calling without looking at your hand keeps feeding those big bets.

2. Fold when the hand is weak

Score the two cards and fold below 5-kkut. That throws away about half of all hands. The scoring rule is copied straight from the rank table further down this page.

var my_money = 0;

function onGameStart() {}

function onRoundStart(data) {
	// my_money arrives only when a round starts. Track it yourself within a round.
	my_money = data.my_money;
}

// The score of two cards, copied from the rank table below.
// The kkut tiebreak rule is left out to keep it short.
function getPoint(c1, c2) {
	var n1 = c1 > 10 ? c1 - 10 : c1;
	var n2 = c2 > 10 ? c2 - 10 : c2;

	if ((c1 === 3 && c2 === 8) || (c1 === 8 && c2 === 3)) { return 30000; }
	if ((c1 === 1 && c2 === 8) || (c1 === 8 && c2 === 1)) { return 20000; }
	if ((c1 === 1 && c2 === 3) || (c1 === 3 && c2 === 1)) { return 10000; }
	if (n1 === n2) { return n1 * 1000; }
	return ((c1 + c2) % 10) * 100;
}

function onTurnStart(data) {
	var point = getPoint(data.my_cards[0], data.my_cards[1]);
	var bet = data.op_turn_result;
	var result;

	if (point < 500) {
		// Fold below 5-kkut. That throws away about half of all hands.
		result = {action: "die", money: 1};
	} else if (bet === null) {
		result = my_money >= 2
			? {action: "raise", money: 1}
			: {action: "die", money: 1};
	} else if (bet.money > my_money) {
		result = {action: "die", money: 1};
	} else {
		result = {action: "call", money: bet.money};
	}
	my_money -= result.money;
	return result;
}

function onRoundEnd() {}
function onGameEnd() {}

LEVEL 1 loses every game LEVEL 2 has the edge LEVEL 3 roughly even

LEVEL 2 and LEVEL 3 flip. Dropping weak hands when they raise hard removes the big losses. And yet it loses every game to the simplest opponent, LEVEL 1 — the only one of the three that computes neither odds nor bet sizes. This is the strangest point in the game.

3. Count the fact that folding also costs 1

LEVEL 1 bets only 1 and never folds. Calling that 1 costs 1, and folding costs 1. They are the same. Folding saves nothing and only throws away a chance to win, so if there is any chance at all, calling is better. The rule for what counts as a weak hand stays exactly as it was in 2. Only one condition goes in front of it.

op_turn_result.money == 1 Fold costs 1, call costs 1. Same, so call.
op_turn_result.money == 20 Fold costs 1, call costs 20. Different, so drop the weak hand.
var my_money = 0;

function onGameStart() {}

function onRoundStart(data) {
	// my_money arrives only when a round starts. Track it yourself within a round.
	my_money = data.my_money;
}

// The score of two cards, copied from the rank table below.
// The kkut tiebreak rule is left out to keep it short.
function getPoint(c1, c2) {
	var n1 = c1 > 10 ? c1 - 10 : c1;
	var n2 = c2 > 10 ? c2 - 10 : c2;

	if ((c1 === 3 && c2 === 8) || (c1 === 8 && c2 === 3)) { return 30000; }
	if ((c1 === 1 && c2 === 8) || (c1 === 8 && c2 === 1)) { return 20000; }
	if ((c1 === 1 && c2 === 3) || (c1 === 3 && c2 === 1)) { return 10000; }
	if (n1 === n2) { return n1 * 1000; }
	return ((c1 + c2) % 10) * 100;
}

function onTurnStart(data) {
	var point = getPoint(data.my_cards[0], data.my_cards[1]);
	var bet = data.op_turn_result;
	var result;

	if (bet === null) {
		// I am first. Folding costs 1 and betting costs 1, so even a weak hand bets.
		result = my_money >= 2
			? {action: "raise", money: 1}
			: {action: "die", money: 1};
	} else if (bet.money > my_money) {
		// You cannot pay more money than you have.
		result = {action: "die", money: 1};
	} else if (bet.money <= 1) {
		// Calling costs what folding costs. Folding saves nothing here, so call.
		result = {action: "call", money: bet.money};
	} else if (point >= 500) {
		result = {action: "call", money: bet.money};
	} else {
		// The bet now costs more than folding. Only from here do I drop weak hands.
		result = {action: "die", money: 1};
	}
	my_money -= result.money;
	return result;
}

function onRoundEnd() {}
function onGameEnd() {}

LEVEL 1 roughly even LEVEL 2 has the edge LEVEL 3 roughly even

LEVEL 1 comes back from a total loss to even, and the LEVEL 2 and LEVEL 3 scores stay where they were. The weak-hand line is still 5-kkut. The only change is that folding is now compared against what is on the table. Folding is not free, and it does not always cost the same either.

4. Your turn from here

The three above leave two things untouched. One is the opponent's first card: onTurnStart hands you data.op_card, so one of their cards is visible. Count which of the remaining cards would beat your hand and you have your odds — that is what LEVEL 2 does. The other is the amount. All three above always bet 1. Betting big on a strong hand earns more, and betting big on a weak one can make the opponent fold — but if they don't, you lose that much more. Paste the code above into the editor and start changing it here.

How a battle runs

  • Code battle is a battle between your code and opponent's code, and the language is JAVASCRIPT.
  • Fill in the code, select the opponent (LEVEL1, LEVEL2, LEVEL3, Online opponent) and then press the game start button will start the match.
  • 1 game consists of a maximum of 200 rounds and the game ends if either you or your opponent runs out of money while the round is repeated. And, 1 round consists of several turns. On each turn, you can "raise" to raise table money and pass it to your opponent's turn, or you can "call" or "die" to finish the round.
  • OnGameStart and onGameEnd functions are called at the beginning and end of the game, onRoundStart and onRoundEnd functions are called at the beginning and end of each round, and onTurnStart is called on each turn. onGameStart => onRoundStart => onTurnStart => onRoundEnd => onGameEnd. You can implement your own logic in each function.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
OrderGroupNameRemarks
1Gwang-ttaeng3 and 8 gwang-ttaengWhen two cards are 3 and 8. Sutda's strongest combination.
2Gwang-ttaeng1 and 8 gwang-ttaengWhen two cards are 1 and 8.
3Gwang-ttaeng1 and 3 gwang-ttaengWhen two cards are 1 and 3.
4Ttaeng10 ttaengWhen two cards are 10 and 20.
5Ttaeng9 ttaengWhen two cards are 9 and 19.
6Ttaeng8 ttaengWhen two cards are 8 and 18.
7Ttaeng7 ttaengWhen two cards are 7 and 17.
8Ttaeng6 ttaengWhen two cards are 6 and 16.
9Ttaeng5 ttaengWhen two cards are 5 and 15.
10Ttaeng4 ttaengWhen two cards are 4 and 14.
11Ttaeng3 ttaengWhen two cards are 3 and 13.
12Ttaeng2 ttaengWhen two cards are 2 and 12.
13Ttaeng1 ttaengWhen two cards are 1 and 11.
14Kkeus9 kkeusWhen the "units" number of the sum of two card is 9. (Ex: 5 and 14, or 3 and 6). If it's the same, compare the big cards. (Ex: ['5' and 4] < [3 and '6'])
15Kkeus8 kkeusWhen the "units" number of the sum of two card is 8. (Ex: 5 and 13, or 6 and 2)
16Kkeus7 kkeusWhen the "units" number of the sum of two card is 7. (Ex: 2 and 15, or 3 and 4)
17Kkeus6 kkeusWhen the "units" number of the sum of two card is 6. (Ex: 5 and 11, or 1 and 5)
18Kkeus5 kkeusWhen the "units" number of the sum of two card is 5. (Ex: 2 and 13, or 3 and 2)
19Kkeus4 kkeusWhen the "units" number of the sum of two card is 4. (Ex: 4 and 10, or 1 and 3)
20Kkeus3 kkeusWhen the "units" number of the sum of two card is 3. (Ex: 1 and 12, or 2 and 1)
21Kkeus2 kkeusWhen the "units" number of the sum of two card is 2. (Ex: 2 and 10, or 3 and 9)
22Kkeus1 kkeusWhen the "units" number of the sum of two card is 1. (Ex: 1 and 10, or 5 and 6)
23Kkeus0 kkeusWhen the "units" number of the sum of two card is 0. (Ex: 1 and 9, or 3 and 7)

Sutda has five hooks and no onTurnEnd. onTurnStart must return an object with action and money, where action is one of raise, call, or die. You cannot call on the first turn. The code in 2 and 3 above contains all five hooks, so it runs as-is when pasted in.

Also, my_money arrives only when a round starts. You have to subtract what you bet within a round yourself, or you will bet more than you hold and be disqualified. Folding costs 1 too, so if you bet down to your last coin you cannot even fold on the next turn. Disqualification looks like an ordinary loss on screen, which makes it hard to find.

Scores were measured over 150 games per opponent, and a test in the repository re-checks them against the real rule engine every time. One game runs up to 200 rounds. Here "loses every game" means a win rate of 3% or below, "mostly loses" 15% or below, "roughly even" 20-80%, and "has the edge" 50% or above. While measuring with 60 games, the LEVEL 2 win rate of method 3 moved between 53% and 67%; since the line for the edge is 50%, the count went up to 150.