Game Rules
Read the strategy guideOpponents
TURN
ROUND
GAME
Game Log
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.
| Order | Group | Name | Remarks |
|---|---|---|---|
| 1 | Gwang-ttaeng | 3 and 8 gwang-ttaeng | When two cards are 3 and 8. Sutda's strongest combination. |
| 2 | Gwang-ttaeng | 1 and 8 gwang-ttaeng | When two cards are 1 and 8. |
| 3 | Gwang-ttaeng | 1 and 3 gwang-ttaeng | When two cards are 1 and 3. |
| 4 | Ttaeng | 10 ttaeng | When two cards are 10 and 20. |
| 5 | Ttaeng | 9 ttaeng | When two cards are 9 and 19. |
| 6 | Ttaeng | 8 ttaeng | When two cards are 8 and 18. |
| 7 | Ttaeng | 7 ttaeng | When two cards are 7 and 17. |
| 8 | Ttaeng | 6 ttaeng | When two cards are 6 and 16. |
| 9 | Ttaeng | 5 ttaeng | When two cards are 5 and 15. |
| 10 | Ttaeng | 4 ttaeng | When two cards are 4 and 14. |
| 11 | Ttaeng | 3 ttaeng | When two cards are 3 and 13. |
| 12 | Ttaeng | 2 ttaeng | When two cards are 2 and 12. |
| 13 | Ttaeng | 1 ttaeng | When two cards are 1 and 11. |
| 14 | Kkeus | 9 kkeus | When 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']) |
| 15 | Kkeus | 8 kkeus | When the "units" number of the sum of two card is 8. (Ex: 5 and 13, or 6 and 2) |
| 16 | Kkeus | 7 kkeus | When the "units" number of the sum of two card is 7. (Ex: 2 and 15, or 3 and 4) |
| 17 | Kkeus | 6 kkeus | When the "units" number of the sum of two card is 6. (Ex: 5 and 11, or 1 and 5) |
| 18 | Kkeus | 5 kkeus | When the "units" number of the sum of two card is 5. (Ex: 2 and 13, or 3 and 2) |
| 19 | Kkeus | 4 kkeus | When the "units" number of the sum of two card is 4. (Ex: 4 and 10, or 1 and 3) |
| 20 | Kkeus | 3 kkeus | When the "units" number of the sum of two card is 3. (Ex: 1 and 12, or 2 and 1) |
| 21 | Kkeus | 2 kkeus | When the "units" number of the sum of two card is 2. (Ex: 2 and 10, or 3 and 9) |
| 22 | Kkeus | 1 kkeus | When the "units" number of the sum of two card is 1. (Ex: 1 and 10, or 5 and 6) |
| 23 | Kkeus | 0 kkeus | When 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.