diff --git a/project/game/table.py b/project/game/table.py
index fd7c6bfe..1f12a5f0 100644
--- a/project/game/table.py
+++ b/project/game/table.py
@@ -98,13 +98,17 @@ def init_round(self,
def add_called_meld(self, player_seat, meld):
self.meld_was_called = True
- # when opponent called meld it is means
- # that he discards tile from hand, not from wall
- self.count_of_remaining_tiles += 1
-
- # we will decrease count of remaining tiles after called kan
- # because we had to complement dead wall
- if meld.type == Meld.KAN or meld.type == meld.CHANKAN:
+ # if meld was called from the other player, then we skip one draw from the wall
+ if meld.opened:
+ # but if it's an opened kan, player will get a tile from
+ # a dead wall, so total number of tiles in the wall is the same
+ # as if he just draws a tile
+ if meld.type != Meld.KAN:
+ self.count_of_remaining_tiles += 1
+ else:
+ # can't have a pon or chi from the hand
+ assert meld.type == Meld.KAN or meld.type == meld.CHANKAN
+ # player draws additional tile from the wall in case of closed kan or chankan
self.count_of_remaining_tiles -= 1
self.get_player(player_seat).add_called_meld(meld)
diff --git a/project/game/tests/tests_client.py b/project/game/tests/tests_client.py
index d80d07ea..faaacb67 100644
--- a/project/game/tests/tests_client.py
+++ b/project/game/tests/tests_client.py
@@ -25,7 +25,7 @@ def test_discard_tile(self):
self.assertFalse(tile in client.table.player.tiles)
self.assertEqual(client.table.count_of_remaining_tiles, 69)
- def test_call_meld(self):
+ def test_call_meld_closed_kan(self):
client = Client()
client.table.init_round(0, 0, 0, 0, 0, [0, 0, 0, 0])
@@ -41,13 +41,38 @@ def test_call_meld(self):
meld = Meld()
meld.type = Meld.KAN
# closed kan
+ meld.tiles = [0, 1, 2, 3]
meld.called_tile = None
meld.opened = False
client.table.add_called_meld(0, meld)
self.assertEqual(len(client.player.melds), 2)
- # +1 for called meld
- # -1 for called kan
+ # kan was closed, so -1
+ self.assertEqual(client.table.count_of_remaining_tiles, 70)
+
+ def test_call_meld_kan_from_player(self):
+ client = Client()
+
+ client.table.init_round(0, 0, 0, 0, 0, [0, 0, 0, 0])
+ self.assertEqual(client.table.count_of_remaining_tiles, 70)
+
+ meld = Meld()
+ client.table.add_called_meld(0, meld)
+
+ self.assertEqual(len(client.player.melds), 1)
+ self.assertEqual(client.table.count_of_remaining_tiles, 71)
+
+ client.player.tiles = [0]
+ meld = Meld()
+ meld.type = Meld.KAN
+ # closed kan
+ meld.tiles = [0, 1, 2, 3]
+ meld.called_tile = 0
+ meld.opened = True
+ client.table.add_called_meld(0, meld)
+
+ self.assertEqual(len(client.player.melds), 2)
+ # kan was called from another player, total number of remaining tiles stays the same
self.assertEqual(client.table.count_of_remaining_tiles, 71)
def test_enemy_discard(self):
diff --git a/project/tenhou/decoder.py b/project/tenhou/decoder.py
index e73c85a4..156f3f04 100644
--- a/project/tenhou/decoder.py
+++ b/project/tenhou/decoder.py
@@ -167,7 +167,9 @@ def parse_meld(self, message):
meld = Meld()
meld.who = int(self.get_attribute_content(message, 'who'))
- meld.from_who = data & 0x3
+ # 'from_who' is encoded relative the the 'who', so we want
+ # to convert it to be relative to our player
+ meld.from_who = ((data & 0x3) + meld.who) % 4
if data & 0x4:
self.parse_chi(data, meld)
diff --git a/project/tenhou/tests/tests_decoder.py b/project/tenhou/tests/tests_decoder.py
index 28ace4d3..660750dc 100644
--- a/project/tenhou/tests/tests_decoder.py
+++ b/project/tenhou/tests/tests_decoder.py
@@ -124,7 +124,7 @@ def test_parse_called_opened_kan(self):
meld = decoder.parse_meld('')
self.assertEqual(meld.who, 3)
- self.assertEqual(meld.from_who, 1)
+ self.assertEqual(meld.from_who, 0)
self.assertEqual(meld.type, Meld.KAN)
self.assertEqual(meld.opened, True)
self.assertEqual(meld.tiles, [52, 53, 54, 55])
@@ -174,7 +174,7 @@ def test_parse_who_called_riichi(self):
def test_reconnection_information(self):
message = '