Gentoo Archives: gentoo-commits

From: Sergey Torokhov <torokhov-s-a@××××××.ru>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/proj/guru:dev commit in: games-board/rmahjong/files/, games-board/rmahjong/
Date: Sun, 25 Oct 2020 12:36:45
Message-Id: 1603629357.ef556bcba0d3fb3451d080cdf0ce559c00ad6c72.SergeyTorokhov@gentoo
1 commit: ef556bcba0d3fb3451d080cdf0ce559c00ad6c72
2 Author: Sergey Torokhov <torokhov-s-a <AT> yandex <DOT> ru>
3 AuthorDate: Sun Oct 25 12:28:08 2020 +0000
4 Commit: Sergey Torokhov <torokhov-s-a <AT> yandex <DOT> ru>
5 CommitDate: Sun Oct 25 12:35:57 2020 +0000
6 URL: https://gitweb.gentoo.org/repo/proj/guru.git/commit/?id=ef556bcb
7
8 games-board/rmahjong: new package
9
10 This is attempt python3 "final" porting the game
11 by means of additional patches to initial py3 port.
12
13 The game is playable for me at "single player + 3 bots".
14 Network game process is not tested.
15
16 Menu icon for desktop entry is fetched from Kmahjongg project.
17
18 Signed-off-by: Sergey Torokhov <torokhov-s-a <AT> yandex.ru>
19
20 games-board/rmahjong/Manifest | 2 +
21 .../files/rmahjong-0.4_fix_python3_compat.patch | 87 +++++++
22 .../rmahjong/files/rmahjong-0.4_fix_tests.patch | 282 +++++++++++++++++++++
23 games-board/rmahjong/metadata.xml | 18 ++
24 games-board/rmahjong/rmahjong-0.4_p20201013.ebuild | 83 ++++++
25 5 files changed, 472 insertions(+)
26
27 diff --git a/games-board/rmahjong/Manifest b/games-board/rmahjong/Manifest
28 new file mode 100644
29 index 00000000..624f607c
30 --- /dev/null
31 +++ b/games-board/rmahjong/Manifest
32 @@ -0,0 +1,2 @@
33 +DIST kmahjongg_rmahjong.png 3816 BLAKE2B 8029e6c3f4eddff9d3593ad7d5615860cd3b9d9bc4b067145e2d191b8fec00f934f3752adec32db11eb7f3e31eba7d4586a2c2f005de4ded8555ec73a4f2f81f SHA512 49cb371b1260aa23bb7b341247047cf7abc59487fd75cc365c2c6f77588af7a83dfed73d7fc1845edcedb8a9b6810ac39dbecff065c3799e3fcc7195df84e67c
34 +DIST rmahjong-0.4_p20201013.tar.gz 1399540 BLAKE2B 9dd1c40fea7c2d93e33a7bea0e1b66912eb547c64b45bbeadd95e4234380786551005cec8bf5edc1a7e8b135e5a66b2af80b4f22d257e14aa7068ff9959cee64 SHA512 9eface62972abe37753c380af713e168d39e23f6031af08d735467669b2dd0cbe5dec40eb9e750fff675a054791a58cfad710266229c966d94c190990f63c466
35
36 diff --git a/games-board/rmahjong/files/rmahjong-0.4_fix_python3_compat.patch b/games-board/rmahjong/files/rmahjong-0.4_fix_python3_compat.patch
37 new file mode 100644
38 index 00000000..d6ad5893
39 --- /dev/null
40 +++ b/games-board/rmahjong/files/rmahjong-0.4_fix_python3_compat.patch
41 @@ -0,0 +1,87 @@
42 +diff --git a/client/client.py b/client/client.py
43 +--- a/client/client.py
44 ++++ b/client/client.py
45 +@@ -138,10 +138,10 @@ class Mahjong:
46 +
47 + def init_player_boxes(self, names, player_winds, score):
48 + self.player_boxes = [
49 +- PlayerBox((50, 700), names[0], player_winds[0], int(score[0]), direction_up, (0,-80)),
50 +- PlayerBox((954, 50), names[1], player_winds[1], int(score[1]), direction_left, (-210, 0)),
51 +- PlayerBox((700, 0), names[2], player_winds[2], int(score[2]), direction_up, (0,80)),
52 +- PlayerBox((0, 50), names[3], player_winds[3], int(score[3]), direction_right, (80,0)) ]
53 ++ PlayerBox((50, 700), names[0], player_winds[0], int(float(score[0])), direction_up, (0,-80)),
54 ++ PlayerBox((954, 50), names[1], player_winds[1], int(float(score[1])), direction_left, (-210, 0)),
55 ++ PlayerBox((700, 0), names[2], player_winds[2], int(float(score[2])), direction_up, (0,80)),
56 ++ PlayerBox((0, 50), names[3], player_winds[3], int(float(score[3])), direction_right, (80,0)) ]
57 + for widget in self.player_boxes:
58 + self.gui.add_widget(widget)
59 +
60 +diff --git a/client/states.py b/client/states.py
61 +--- a/client/states.py
62 ++++ b/client/states.py
63 +@@ -555,8 +555,8 @@ class ScoreState(RoundPreparingState):
64 + results = []
65 + for wind in winds:
66 + name = (self.mahjong.get_player_name(wind))
67 +- score = (int(self.message[wind + "_score"]))
68 +- payment = (int(self.message[wind + "_payment"]))
69 ++ score = (int(float(self.message[wind + "_score"])))
70 ++ payment = (int(float(self.message[wind + "_payment"])))
71 + results.append((name, score, payment))
72 + results.sort(key = lambda r: r[1], reverse = True)
73 + return results
74 +diff --git a/client/tilepainter.py b/client/tilepainter.py
75 +--- a/client/tilepainter.py
76 ++++ b/client/tilepainter.py
77 +@@ -89,7 +89,7 @@ class TilePainter:
78 + img = self.tile_images[name]
79 + w = img.get_width()
80 + h = img.get_height()
81 +- screen.blit(pygame.transform.smoothscale(img, (w/4, h/4)), position)
82 ++ screen.blit(pygame.transform.smoothscale(img, (w//4, h//4)), position)
83 +
84 + def draw_tile_list(self, screen, position, tile_names, space = 0):
85 + for i, tile_name in enumerate(tile_names):
86 +diff --git a/server/botengine.py b/server/botengine.py
87 +index 03623f9..b128135 100644
88 +--- a/server/botengine.py
89 ++++ b/server/botengine.py
90 +@@ -71,7 +71,7 @@ class BotEngine():
91 +
92 + def get_tiles(self, blocking = False):
93 + if self._is_next_line() or blocking:
94 +- return map(Tile, (self._read_line().strip().split()))
95 ++ return [*map(Tile, (self._read_line().strip().split()))]
96 + else:
97 + return None
98 +
99 +diff --git a/server/eval.py b/server/eval.py
100 +index 042ee54..dc7e463 100644
101 +--- a/server/eval.py
102 ++++ b/server/eval.py
103 +@@ -19,6 +19,7 @@ from tile import Pon, Chi
104 + from tile import red_dragon, white_dragon, green_dragon, dragons
105 + from tile import bamboos, chars, pins, all_tiles, honors
106 + from copy import copy
107 ++import functools
108 +
109 + def is_hand_open(sets):
110 + for set in sets:
111 +@@ -274,7 +275,7 @@ def eval_sets(pair, sets, round_wind, player_wind, last_tile, wintype):
112 + # Other hands
113 + for name, fn in score_functions:
114 + score = fn(pair, sets)
115 +- if score > 0:
116 ++ if score:
117 + result.append((name, score))
118 +
119 + # Pinfu
120 +@@ -304,7 +305,7 @@ def eval_sets(pair, sets, round_wind, player_wind, last_tile, wintype):
121 +
122 +
123 + def sum_over_sets(sets, fn):
124 +- return reduce(lambda a, s: fn(s) + a, sets, 0)
125 ++ return functools.reduce(lambda a, s: fn(s) + a, sets, 0)
126 +
127 + def for_all_tiles_in_sets(sets, fn):
128 + return for_all_sets(sets, lambda s: s.all_tiles(fn))
129
130 diff --git a/games-board/rmahjong/files/rmahjong-0.4_fix_tests.patch b/games-board/rmahjong/files/rmahjong-0.4_fix_tests.patch
131 new file mode 100644
132 index 00000000..7926e714
133 --- /dev/null
134 +++ b/games-board/rmahjong/files/rmahjong-0.4_fix_tests.patch
135 @@ -0,0 +1,282 @@
136 +diff --git a/server/test.py b/server/test.py
137 +--- a/server/test.py
138 ++++ b/server/test.py
139 +@@ -25,7 +25,7 @@ from botengine import BotEngine
140 +
141 +
142 + def tiles(strs):
143 +- return map(Tile, strs)
144 ++ return [*map(Tile, strs)]
145 +
146 +
147 + def chi(tile_name):
148 +@@ -156,52 +156,52 @@ class EvalHandTestCase(TestCase):
149 + hand, sets, r = h
150 + score = count_of_tiles_yaku(tiles(hand), sets, [], Tile("XX"), Tile("XX"), "Ron")
151 + yaku = find_tiles_yaku(tiles(hand), sets, [], Tile("XX"), Tile("XX"), "Ron")
152 +- self.assert_(score == r, "Hand %i returned score %i %s hand=%s" % (hand_id, score, yaku, hand))
153 ++ self.assertTrue(score == r, "Hand %i returned score %i %s hand=%s" % (hand_id, score, yaku, hand))
154 +
155 + hand = [ "WE", "C2", "C3", "C4", "WN", "WN", "WN", "DR", "B9", "DR", "B8", "B7", "WE", "WE" ]
156 + sets = []
157 +- self.assertEquals(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WN"), "Ron"), 2)
158 +- self.assertEquals(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WN"), "Tsumo"), 3)
159 +- self.assertEquals(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WE"), "Ron"), 2)
160 +- self.assertEquals(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WS"), "Ron"), 1)
161 ++ self.assertEqual(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WN"), "Ron"), 2)
162 ++ self.assertEqual(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WN"), "Tsumo"), 3)
163 ++ self.assertEqual(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WE"), "Ron"), 2)
164 ++ self.assertEqual(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WS"), "Ron"), 1)
165 + hand = [ "WE", "DW", "DW", "DW", "C4", "C2", "C3", "DR", "B9", "DR", "B8", "B7", "WE", "WE" ]
166 +- self.assertEquals(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WS"), "Ron"), 2)
167 ++ self.assertEqual(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WS"), "Ron"), 2)
168 + hand,sets = ([ "C4", "C5", "C6", "C7", "B7", "B8", "B9", "P2", "P3", "P4", "C4"], [kan("WS")])
169 +- self.assertEquals(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WS"), "Ron"), 1)
170 ++ self.assertEqual(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WS"), "Ron"), 1)
171 + hand,sets = ([ "C4", "C5", "C6", "C7", "B7", "B8", "B9", "P2", "P3", "P4", "C4"], [ckan("WS")])
172 +- self.assertEquals(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WS"), "Ron"), 1)
173 ++ self.assertEqual(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WS"), "Ron"), 1)
174 +
175 + hand = [ "WN", "B9", "B6", "WN", "B4", "B8", "B5", "B7"]
176 + sets = [chi("B1"), chi("P5")]
177 +- self.assertEquals(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WW"), "Ron"), 1)
178 +- self.assertEquals(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WW"), "Tsumo"), 1)
179 ++ self.assertEqual(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WW"), "Ron"), 1)
180 ++ self.assertEqual(count_of_tiles_yaku(tiles(hand), sets, [], Tile("WE"), Tile("WW"), "Tsumo"), 1)
181 +
182 + def test_basic_payment(self):
183 +- self.assert_(compute_payment(2, 40, "Ron", Tile("WN")) == ("", 2600))
184 +- self.assert_(compute_payment(2, 40, "Ron", Tile("WE")) == ("", 3900))
185 +- self.assertEquals(compute_payment(2, 40, "Tsumo", Tile("WN")), ("", (700,1300)))
186 +- self.assertEquals(compute_payment(2, 40, "Tsumo", Tile("WE")), ("", (1300, 0)))
187 ++ self.assertTrue(compute_payment(2, 40, "Ron", Tile("WN")) == ("", 2600))
188 ++ self.assertTrue(compute_payment(2, 40, "Ron", Tile("WE")) == ("", 3900))
189 ++ self.assertEqual(compute_payment(2, 40, "Tsumo", Tile("WN")), ("", (700,1300)))
190 ++ self.assertEqual(compute_payment(2, 40, "Tsumo", Tile("WE")), ("", (1300, 0)))
191 +
192 +- self.assert_(compute_payment(1, 40, "Ron", Tile("WN")) == ("", 1300))
193 +- self.assert_(compute_payment(1, 40, "Ron", Tile("WE")) == ("", 2000))
194 +- self.assertEquals(compute_payment(1, 40, "Tsumo", Tile("WN")), ("", (400, 700)))
195 +- self.assertEquals(compute_payment(1, 40, "Tsumo", Tile("WE")), ("", (700, 0)))
196 ++ self.assertTrue(compute_payment(1, 40, "Ron", Tile("WN")) == ("", 1300))
197 ++ self.assertTrue(compute_payment(1, 40, "Ron", Tile("WE")) == ("", 2000))
198 ++ self.assertEqual(compute_payment(1, 40, "Tsumo", Tile("WN")), ("", (400, 700)))
199 ++ self.assertEqual(compute_payment(1, 40, "Tsumo", Tile("WE")), ("", (700, 0)))
200 +
201 +- self.assertEquals(compute_payment(4, 20, "Tsumo", Tile("WN")), ("", (1300, 2600)))
202 +- self.assertEquals(compute_payment(4, 20, "Tsumo", Tile("WE")), ("", (2600, 0)))
203 ++ self.assertEqual(compute_payment(4, 20, "Tsumo", Tile("WN")), ("", (1300, 2600)))
204 ++ self.assertEqual(compute_payment(4, 20, "Tsumo", Tile("WE")), ("", (2600, 0)))
205 +
206 +- self.assertEquals(compute_payment(3, 20, "Tsumo", Tile("WN")), ("", (700, 1300)))
207 +- self.assertEquals(compute_payment(3, 20, "Tsumo", Tile("WE")), ("", (1300, 0)))
208 ++ self.assertEqual(compute_payment(3, 20, "Tsumo", Tile("WN")), ("", (700, 1300)))
209 ++ self.assertEqual(compute_payment(3, 20, "Tsumo", Tile("WE")), ("", (1300, 0)))
210 +
211 +- self.assertEquals(compute_payment(5, 40, "Ron", Tile("WN")), ("Mangan", 8000))
212 +- self.assertEquals(compute_payment(5, 40, "Ron", Tile("WE")), ("Mangan", 12000))
213 +- self.assertEquals(compute_payment(5, 40, "Tsumo", Tile("WN")), ("Mangan", (2000, 4000)))
214 +- self.assertEquals(compute_payment(5, 40, "Tsumo", Tile("WE")), ("Mangan", (4000, 0)))
215 ++ self.assertEqual(compute_payment(5, 40, "Ron", Tile("WN")), ("Mangan", 8000))
216 ++ self.assertEqual(compute_payment(5, 40, "Ron", Tile("WE")), ("Mangan", 12000))
217 ++ self.assertEqual(compute_payment(5, 40, "Tsumo", Tile("WN")), ("Mangan", (2000, 4000)))
218 ++ self.assertEqual(compute_payment(5, 40, "Tsumo", Tile("WE")), ("Mangan", (4000, 0)))
219 +
220 +- self.assertEquals(compute_payment(13, 40, "Ron", Tile("WN")), ("Yakuman", 32000))
221 +- self.assertEquals(compute_payment(13, 40, "Ron", Tile("WE")), ("Yakuman", 48000))
222 +- self.assertEquals(compute_payment(13, 40, "Tsumo", Tile("WN")), ("Yakuman", (8000, 16000)))
223 +- self.assertEquals(compute_payment(13, 40, "Tsumo", Tile("WE")), ("Yakuman", (16000, 0)))
224 ++ self.assertEqual(compute_payment(13, 40, "Ron", Tile("WN")), ("Yakuman", 32000))
225 ++ self.assertEqual(compute_payment(13, 40, "Ron", Tile("WE")), ("Yakuman", 48000))
226 ++ self.assertEqual(compute_payment(13, 40, "Tsumo", Tile("WN")), ("Yakuman", (8000, 16000)))
227 ++ self.assertEqual(compute_payment(13, 40, "Tsumo", Tile("WE")), ("Yakuman", (16000, 0)))
228 +
229 + def test_tenpai(self):
230 + hands = (([ "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "P1", "P1", "P1", "WN"], [], True, ["WN"]),
231 +@@ -215,10 +215,10 @@ class EvalHandTestCase(TestCase):
232 + ([ "P1", "P2", "P3", "DR", "DR", "DR", "B7", "B9", "WN", "WN"], [ pon("P1") ], True, ["B8"]))
233 +
234 + for h, sets, tenpai, w in hands:
235 +- self.assertEquals(hand_in_tenpai(tiles(h), sets), tenpai)
236 ++ self.assertEqual(hand_in_tenpai(tiles(h), sets), tenpai)
237 + waiting = [ t.name for t in find_waiting_tiles(tiles(h), sets) ]
238 + waiting.sort()
239 +- self.assertEquals(waiting, w)
240 ++ self.assertEqual(waiting, w)
241 +
242 + def test_riichi(self):
243 + hands = (([ "P5", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "P1", "P1", "P1", "WN"], [], True),
244 +@@ -229,7 +229,7 @@ class EvalHandTestCase(TestCase):
245 + ([ "P4", "P4", "P4", "C6", "C4", "C5", "B7", "B6", "B8", "B8", "DR" ], [ ckan("WE") ], True),
246 + ([ "P4", "P4", "C6", "P3", "C5", "B7", "B6", "P1", "DR", "B8", "DR" ], [ ckan("WE") ], False))
247 + for h, sets, riichi in hands:
248 +- self.assertEquals(riichi_test(tiles(h), sets), riichi, [h,sets])
249 ++ self.assertEqual(riichi_test(tiles(h), sets), riichi, [h,sets])
250 +
251 + def test_singlewait(self):
252 + # Last tile in the list comes last
253 +@@ -242,21 +242,21 @@ class EvalHandTestCase(TestCase):
254 + ([ "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "P1", "P1", "P3", "P1", "P2"], [], True),
255 + ([ "B1", "B2", "B3", "C8", "C8", "C8", "DW", "DW", "DW", "P4", "P4", "P1", "P2", "P3"], [], True))
256 + for h, sets, singlewait in hands:
257 +- self.assertEquals(check_single_waiting(tiles(h), sets), singlewait)
258 ++ self.assertEqual(check_single_waiting(tiles(h), sets), singlewait)
259 +
260 +
261 + def test_score(self):
262 + hand = [ "WN", "B9", "B6", "WN", "B4", "B8", "B5", "B7"]
263 + sets = [chi("B1"), chi("P5")]
264 + payment, scores, minipoints = compute_score(tiles(hand), sets, "Ron", ([], [ Tile("B7") ]), [], Tile("WE"), Tile("WW"))
265 +- self.assertEquals(payment, ('', 2000))
266 +- self.assertEquals(minipoints, 30)
267 ++ self.assertEqual(payment, ('', 2000))
268 ++ self.assertEqual(minipoints, 30)
269 +
270 + hand = [ "C2", "C2", "C4", "C4", "C7", "C7", "B6", "B8", "B8", "C1", "C1", "WS", "WS", "B6"]
271 + sets = []
272 + payment, scores, minipoints = compute_score(tiles(hand), sets, "Ron", ([ Tile("C7") ], [ Tile("B5") ]), [], Tile("WS"), Tile("WW"))
273 +- self.assertEquals(payment, ('', 6400))
274 +- self.assertEquals(minipoints, 25)
275 ++ self.assertEqual(payment, ('', 6400))
276 ++ self.assertEqual(minipoints, 25)
277 +
278 +
279 + class BotEngineTestCase(TestCase):
280 +@@ -272,9 +272,9 @@ class BotEngineTestCase(TestCase):
281 + e.set_wall(4 * all_tiles)
282 + e.question_discard()
283 + action = e.get_string()
284 +- self.assert_(action == "Discard")
285 ++ self.assertTrue(action == "Discard")
286 + tile = e.get_tile()
287 +- self.assert_(tile in h)
288 ++ self.assertTrue(tile in h)
289 + finally:
290 + e.shutdown()
291 +
292 +@@ -289,9 +289,9 @@ class BotEngineTestCase(TestCase):
293 + e.set_wall(4 * all_tiles)
294 + e.question_discard()
295 + action = e.get_string()
296 +- self.assert_(action == "Discard")
297 ++ self.assertTrue(action == "Discard")
298 + tile = e.get_tile()
299 +- self.assert_(tile in h)
300 ++ self.assertTrue(tile in h)
301 + finally:
302 + e.shutdown()
303 +
304 +@@ -308,7 +308,7 @@ class BotEngineTestCase(TestCase):
305 + e.set_sets(sets)
306 + e.question_yaku()
307 + score = e.get_int()
308 +- self.assert_(score == r, "Hand %i returned score %i" % (hand_id, score))
309 ++ self.assertTrue(score == r, "Hand %i returned score %i" % (hand_id, score))
310 +
311 + finally:
312 + e.shutdown()
313 +@@ -324,23 +324,23 @@ class BotEngineTestCase(TestCase):
314 + e.set_round_wind(Tile("WE"))
315 + e.set_player_wind(Tile("WN"))
316 + e.question_yaku()
317 +- self.assertEquals(e.get_int(), 2)
318 ++ self.assertEqual(e.get_int(), 2)
319 +
320 + e.set_round_wind(Tile("WE"))
321 + e.set_player_wind(Tile("WE"))
322 + e.question_yaku()
323 +- self.assertEquals(e.get_int(), 2)
324 ++ self.assertEqual(e.get_int(), 2)
325 +
326 + e.set_round_wind(Tile("WE"))
327 + e.set_player_wind(Tile("WS"))
328 + e.question_yaku()
329 +- self.assertEquals(e.get_int(), 1)
330 ++ self.assertEqual(e.get_int(), 1)
331 +
332 + e.set_sets([ pon("DW") ])
333 + e.set_round_wind(Tile("WE"))
334 + e.set_player_wind(Tile("WS"))
335 + e.question_yaku()
336 +- self.assertEquals(e.get_int(), 2)
337 ++ self.assertEqual(e.get_int(), 2)
338 +
339 + finally:
340 + e.shutdown()
341 +@@ -357,7 +357,7 @@ class BotEngineTestCase(TestCase):
342 + e.set_wall(wall)
343 + e.question_discard_tiles()
344 + tile_list = e.get_tiles()
345 +- self.assertEquals(tile_list, [Tile("B1"), Tile("B1"), Tile("B1")])
346 ++ self.assertEqual(tile_list, [Tile("B1"), Tile("B1"), Tile("B1")])
347 + finally:
348 + e.shutdown()
349 +
350 +@@ -373,7 +373,7 @@ class BotEngineTestCase(TestCase):
351 + e.set_wall(wall)
352 + e.question_discard_tiles()
353 + tile_list = e.get_tiles()
354 +- self.assertEquals(tile_list, [Tile("DR")])
355 ++ self.assertEqual(tile_list, [Tile("DR")])
356 + finally:
357 + e.shutdown()
358 +
359 +@@ -394,12 +394,12 @@ class BotEngineTestCase(TestCase):
360 + e.set_wall(wall)
361 + e.question_discard_tiles()
362 + tile_list = e.get_tiles()
363 +- self.assertEquals(tile_list, [Tile("P4")])
364 ++ self.assertEqual(tile_list, [Tile("P4")])
365 + h = tiles([ "C8", "C8", "C2", "C2", "C3", "C3", "B2", "B2", "B4", "B4", "P1", "P4", "B5", "B5" ])
366 + e.set_hand(h)
367 + e.question_discard_tiles()
368 + tile_list = e.get_tiles()
369 +- self.assertEquals(tile_list, [Tile("P1")])
370 ++ self.assertEqual(tile_list, [Tile("P1")])
371 +
372 + wall = 3 * all_tiles
373 + wall.remove(Tile("WW"))
374 +@@ -411,7 +411,7 @@ class BotEngineTestCase(TestCase):
375 + e.set_hand(h)
376 + e.question_discard_tiles()
377 + tile_list = e.get_tiles()
378 +- self.assertEquals(tile_list, [Tile("C9")])
379 ++ self.assertEqual(tile_list, [Tile("C9")])
380 +
381 + finally:
382 + e.shutdown()
383 +@@ -429,18 +429,18 @@ class BotEngineTestCase(TestCase):
384 + e.question_discard()
385 +
386 + action = e.get_string()
387 +- self.assert_(action == "Kan")
388 ++ self.assertTrue(action == "Kan")
389 + tile = e.get_tile()
390 +- self.assertEquals(tile, Tile("P9"))
391 ++ self.assertEqual(tile, Tile("P9"))
392 +
393 + h = tiles([ "C1", "C2", "C3", "P9", "B1", "B1", "B1", "P1", "P3", "DR", "DR" ])
394 + e.set_hand(h)
395 + e.set_sets([pon("P9")])
396 + e.question_discard()
397 + action = e.get_string()
398 +- self.assert_(action == "Kan")
399 ++ self.assertTrue(action == "Kan")
400 + tile = e.get_tile()
401 +- self.assertEquals(tile, Tile("P9"))
402 ++ self.assertEqual(tile, Tile("P9"))
403 +
404 +
405 + h = tiles([ "C1", "C2", "C3", "P9", "P9", "P9", "P9", "P7", "P8", "P1", "P3", "DR", "DR", "C5" ])
406 +@@ -448,9 +448,9 @@ class BotEngineTestCase(TestCase):
407 + e.set_sets([])
408 + e.question_discard()
409 + action = e.get_string()
410 +- self.assert_(action == "Discard")
411 ++ self.assertTrue(action == "Discard")
412 + tile = e.get_tile()
413 +- self.assertEquals(tile, Tile("C5"))
414 ++ self.assertEqual(tile, Tile("C5"))
415 +
416 + finally:
417 + e.shutdown()
418
419 diff --git a/games-board/rmahjong/metadata.xml b/games-board/rmahjong/metadata.xml
420 new file mode 100644
421 index 00000000..97c7f078
422 --- /dev/null
423 +++ b/games-board/rmahjong/metadata.xml
424 @@ -0,0 +1,18 @@
425 +<?xml version="1.0" encoding="UTF-8"?>
426 +<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
427 +<pkgmetadata>
428 + <maintainer type="person">
429 + <email>torokhov-s-a@××××××.ru</email>
430 + <name>Sergey Torokhov</name>
431 + </maintainer>
432 + <longdescription>
433 + Riichi Mahjong is the Japanese variant to the Chinese game for four players.
434 + RMahjong is the computer implementation of this game.
435 +
436 + RMahjong allows you to play the game over a network,
437 + missing players can be replaced by computer players.
438 + </longdescription>
439 + <upstream>
440 + <remote-id type="github">spirali/rmahjong</remote-id>
441 + </upstream>
442 +</pkgmetadata>
443
444 diff --git a/games-board/rmahjong/rmahjong-0.4_p20201013.ebuild b/games-board/rmahjong/rmahjong-0.4_p20201013.ebuild
445 new file mode 100644
446 index 00000000..28f4c28e
447 --- /dev/null
448 +++ b/games-board/rmahjong/rmahjong-0.4_p20201013.ebuild
449 @@ -0,0 +1,83 @@
450 +# Copyright 1999-2020 Gentoo Authors
451 +# Distributed under the terms of the GNU General Public License v2
452 +
453 +EAPI=7
454 +
455 +PYTHON_COMPAT=( python3_{6,7,8,9} )
456 +
457 +inherit desktop python-single-r1 xdg
458 +
459 +# Tarball from initial py3 port branch:
460 +# https://github.com/spirali/rmahjong/tree/py3
461 +# At least "Furiten", "Red fives" rules aren't implemented.
462 +PKG_sha="119704b581e3358ecb2764bd8e208ea5b24e7695"
463 +
464 +DESCRIPTION="Riichi Mahjong, the Japanese variant of the Chinese game Mahjong for 4 players"
465 +HOMEPAGE="https://github.com/spirali/rmahjong"
466 +
467 +# PNG icon is taken from Kmahjongg project (GPL-2), renamed to avoid pkgs conflicts
468 +SRC_URI="
469 + https://github.com/spirali/${PN}/archive/${PKG_sha}.tar.gz -> ${P}.tar.gz
470 + https://github.com/KDE/kmahjongg/raw/master/icons/48-apps-kmahjongg.png -> kmahjongg_${PN}.png"
471 +
472 +LICENSE="GPL-2"
473 +SLOT="0"
474 +KEYWORDS="~amd64 ~x86"
475 +
476 +IUSE="test"
477 +RESTRICT="!test? ( test )"
478 +REQUIRED_USE="${PYTHON_REQUIRED_USE}"
479 +
480 +S="${WORKDIR}/${PN}-${PKG_sha}"
481 +
482 +RDEPEND="
483 + ${PYTHON_DEPS}
484 + dev-python/pygame[X,opengl]
485 + $(python_gen_cond_dep '
486 + dev-python/pygame[${PYTHON_MULTI_USEDEP}]
487 + dev-python/pyopengl[${PYTHON_MULTI_USEDEP}]
488 + ')
489 +"
490 +DEPEND="test? ( dev-python/unittest2 )"
491 +
492 +PATCHES=(
493 + "${FILESDIR}/${PN}-0.4_fix_python3_compat.patch"
494 + "${FILESDIR}/${PN}-0.4_fix_tests.patch"
495 +)
496 +
497 +src_prepare(){
498 + default
499 +
500 + # Disable logging as application log into directory where user access is denied
501 + sed -i "/logging.basicConfig/d" "${S}/client/client.py" || die
502 + sed -i "/logging.basicConfig/d" "${S}/server/server.py" || die
503 + sed -i "/logging.info/d" "${S}/server/server.py" || die
504 +
505 + echo $'#!/bin/sh\ncd '"$(python_get_sitedir)/${PN}"' && ./start.sh' > "${S}/rmahjong"
506 +}
507 +
508 +src_compile() {
509 + # Build bots
510 + cd "${S}/bot/" && emake
511 +}
512 +
513 +src_test() {
514 + cd "${S}/server/" && python3 test.py
515 +}
516 +
517 +src_install() {
518 + insinto "$(python_get_sitedir)/${PN}"
519 + doins -r {client/,server/,start.sh}
520 + fperms 755 $(python_get_sitedir)/${PN}/start.sh
521 + fperms 755 $(python_get_sitedir)/${PN}/server/run_server.sh
522 +
523 + insinto "$(python_get_sitedir)/${PN}/bot"
524 + doins "bot/bot"
525 + fperms 755 $(python_get_sitedir)/${PN}/bot/bot
526 +
527 + python_optimize "${D}/$(python_get_sitedir)/${PN}/"{client,server}/*.py
528 +
529 + dobin "rmahjong"
530 + doicon -s 48 "${DISTDIR}/kmahjongg_${PN}.png"
531 + make_desktop_entry "${PN}" "RMahjong" "kmahjongg_${PN}.png" "Game;BoardGame;" || die "Failed making desktop entry!"
532 +}