I'm new to Japanese Mahjong and have trouble calculating the scores. Please help me write a program to calculate it.
Introduction
(aka you can skip this boring part)
Mahjong is a popular tile game in Asia. Different rules have evolved and systematically established in various regions. Japan, being an isolated island state, have its own mahjong variant including rules and scoring.
In Japanese Mahjong, 4 players participate in the game at the same time. They take turn to draw a tile from wall and discard a tile from hand. Occasionally then can take other's discarded tiles for use. Each round 1 of the 4 players will be the dealer. Independent of that, each round may have a winner if he/she can assemble a winning hand. There could be no winners in a round but we don't care about that in this challenge.
When a player become the winner of that round, the change in score is calculated depending on 4 things: (1) Han
and (2) fu
depends on the winning hand, (3) whether the winner is also a dealer, and (4) whether he win by self-draw or from other's discard. The winner get his points by taking the points from the losers. So points lost by all losers added should equal to points gained by winner. Moreover, sometimes only one loser lose his points while the other two don't lose any, and sometimes one of the three losers lose more points. (See below)
Objective
Write a program or function that accepts the 4 parameters mentioned above, and return (1) how many points the winner will gain, and (2-4) how many points each of the three losers will lose.
Details of inputs
Han
: An integer from 1 to 13 inclusive.
Fu
: An integer that is either 25, or an even number from 20 to 130 inclusive. If han
is 1 or 2, fu
is further capped at 110.
dealer or not
: A truthy/falsy value. Though if you are a mahjong lover you can instead accept the winner's seat-wind :-)
self-draw or discard
: A two-state value. Truthy/falsy value will suffice but other reasonable values are acceptable.
Steps of calculating the points gained/lost:
1. Calculate the base score
The base score is calculated based on 2 cases.
1a) Han
≤ 4
If fu
is 25, then keep it as-is. Otherwise round it up to nearest 10.
Then base score is calculated by
base_score = fu×2han+2
And it's capped at 2000 points.
1b) Han
≥ 5
Fu
is not used here. The base score is obtained by direct lookup of han
in the following table:
Han Base score
5 2000
6-7 3000
8-10 4000
11-12 6000
13 8000
2. Calculate the points lost by losers
2a) Dealer wins by self-draw
Each loser pays an amount equal to double of the base score, then rounded up to nearest 100.
2b) Dealer wins by discard
The discarding loser pays an amount equal to 6x the base score, then rounded up to nearest 100. Other two losers don't pay.
2c) Non-dealer wins by self-draw
Dealer (one of the loser) pays an amount equal to double of the base score, then rounded up to nearest 100. The other two losers each pays an amount equal to base score, also rounded up to 100.
2d) Non-dealer wins by discard
The discarding loser pays an amount equal to 4x the base score, then rounded up to 100. Other two losers don't need to pay. Scoring isn't affected by whether the discarding loser is dealer or not.
3. Calculate the points gained by winner
Winner gains the total points lost by the three losers. Not a point less and not a point more.
Example
(Some examples are shamelessly taken/modified from Japanese Wikipedia page of calculating mahjong score)
4 han
24 fu
, dealer win by self-draw
24 fu
rounded up to 30 fu
Base score = 30 × 2 4+2 = 1920
Each loser pays 1920×2 = 3840 => 3900 (rounded)
Winner takes 3900×3 = 11700 points
Output: +11700/-3900/-3900/-3900
3 han
25 fu
, dealer win by discard
25 fu
no need to round up
Base score = 25 × 2 3+2 = 800
Discarding loser pays 800×6 = 4800
Non-discarding loser pays 0 points
Winner takes 4800 points
Output: +4800/-4800/0/0
4 han
40 fu
, non-dealer win by self-draw
40 fu
no need to round up
Base score = 40 × 2 4+2 = 2560 => 2000 (capped)
Dealer pays 2000×2 = 4000
Non-dealer pays 2000
Winner takes 4000+2000×2 = 8000 points
Output: +8000/-4000/-2000/-2000
9 han
50 fu
, non-dealer win by discard
Fu
not used to calculate score
Base score = 4000 (table lookup)
Discarding loser pays 4000×4 = 16000
Non-discarding loser pays 0 points
Winner takes 16000 points
Output: +16000/-16000/0/0
Output
Output 4 numbers: The point that the winner is gaining (as positive number), and the points that each of the three losers is losing (as negative number).
You may output the numbers as 4 individual numerical values in your language's native format, an array/list of numbers, 4 separate strings (or array/list of characters), or a string contatining the numbers that are properly delimited. If you use string, the positive sign is optional but negative sign is mandatory.
The order of the numbers doesn't matter, since they can be inferred from sign and magnitude of the numbers. e.g. 0/-16000/+16000/0 is acceptable.
Format
- Full program or function
- Any reasonable input/output format
- Default rules apply. Standard loopholes forbidden. code-golf so fewest bytes wins.
Notes
- All outputs are guaranteed to be integers, more specifically multiples of 100 in the range [-48000,+48000]
- Rounding is applied only to (1)
fu
and (2) loser's points. It is not applied to base score. - Theoretically winning by self-draw or discard should gain the same points (6x or 4x base points). However due to rounding, this may not be true at low
han
. (See 1st and 2nd test cases)
Test cases
(Also see example)
Inputs Outputs
Han Fu Dealer Self Winner Loser1 Loser2 Loser3
1 22 N Y +1100 -500 -300 -300
1 22 N N +1000 -1000 0 0
3 106 Y N +12000 -12000 0 0
4 20 N Y +5200 -2600 -1300 -1300
4 25 Y N +9600 -9600 0 0
5 88 Y Y +12000 -4000 -4000 -4000
7 25 Y Y +18000 -6000 -6000 -6000
12 64 N N +24000 -24000 0 0
13 130 Y N +48000 -48000 0 0