Bot for tenhou.net riichi mahjong server written in Python

Overview

Build [Tests coverage]

Bot was tested with Python 3.7+ and PyPy3, we are not supporting Python 2.

What do we have here?

Example of bot game

Mahjong hands calculation

You can find it here: https://github.com/MahjongRepository/mahjong

Mahjong bot

For research purposes we built a simple bot to play riichi mahjong on tenhou.net server.

Here you can read about bot played games statistic: versions history

For developers

How to run it?

  1. pip install -r requirements/lint.txt
  2. Run cd project && python main.py it will connect to the tenhou.net and will play a game.

How to run bot battle with pypy

To make it easier run bot vs bot battles we prepared PyPy3 Docker container.

Run the game locally:

  1. Install Docker
  2. Run make build_docker
  3. Run make GAMES=1 run_battle it will play one game locally. Logs and replays will be stored in bots_battle folder.

Run bots with enabled decision logger (use it only for debug, since it harms performance):

  1. Run make GAMES=1 ARGS=--logs run_battle

Run multiple bots to play one game

  1. Install Docker and Install Docker Compose
  2. Run make build_docker
  3. Put bot configs to project/settings/. By default we are looking for these configs: bot_1_settings.py, bot_2_settings.py, bot_3_settings.py, bot_4_settings.py, bot_5_settings.py. Why 5 settings? Because tenhou doesn't start 2+ game in the custom lobby if you are running only 4 bots.
  4. Run make run_on_tenhou

Configuration instructions

  1. Put your own settings to the project/settings/settings_local.py file. They will override settings from default settings/base.py file.
  2. Also, you can override some default settings with command arguments. Use python main.py -h to check all available commands.

Game reproducer

It can be useful to debug bot errors or strange discards: game reproducer

Comments
  • Occassionally printing infinite empty 'GET:' after player calls Riichi

    Occassionally printing infinite empty 'GET:' after player calls Riichi

    Hi Nihisil,

    thank you so much for developing this repo, when I used it to play an online match(with my little dumb AI), it seems encountered a bug described in the title, here are some logs:

    2017-01-17 16:50:33 DEBUG: Send: <Z />
    2017-01-17 16:50:33 DEBUG: Send: <NEXTREADY />
    2017-01-17 16:50:35 DEBUG: Get: <INIT seed="3,0,0,2,5,82" ten="350,158,334,158" oya="1" hai="119,77,68,116,4,37,71,74,73,90,64,66,132"/> <U/> 
    2017-01-17 16:50:35 INFO: Round: 3, Honba: 0, Dora Indicators: [82]
    2017-01-17 16:50:35 INFO: Players: [NoName (35,000), 上野あいみ (33,400), no_D (15,800), 紅稀 (15,800)]
    2017-01-17 16:50:35 INFO: Dealer: no_D (15,800)
    2017-01-17 16:50:35 INFO: Round  wind: East
    2017-01-17 16:50:35 INFO: Player wind: North
    2017-01-17 16:50:41 DEBUG: Get: <E114/> 
    2017-01-17 16:50:42 DEBUG: Get: <N who="2" m="44139" /> 
    2017-01-17 16:50:42 INFO: Meld: pon, who 2
    2017-01-17 16:50:44 DEBUG: Get: <F3/> <W/> 
    2017-01-17 16:50:46 DEBUG: Get: <G121/> <T54/> 
    2017-01-17 16:50:47 INFO: Hand: 2m158899p1125s337z
    2017-01-17 16:50:47 DEBUG: Send: <D p="132"/>
    2017-01-17 16:50:47 INFO: Remaining tiles: 67
    2017-01-17 16:50:48 DEBUG: Send: <Z />
    2017-01-17 16:50:48 DEBUG: Get: <D132/> <U/> 
    2017-01-17 16:50:49 DEBUG: Get: <E123/> <V/> 
    2017-01-17 16:50:53 DEBUG: Get: <F60/> 
    2017-01-17 16:50:58 DEBUG: Get: <W/> 
    2017-01-17 16:50:59 DEBUG: Get: <G124/> <T63/> 
    2017-01-17 16:51:00 INFO: Hand: 2m1578899p1125s33z
    2017-01-17 16:51:00 DEBUG: Send: <D p="37"/>
    2017-01-17 16:51:00 INFO: Remaining tiles: 63
    2017-01-17 16:51:01 DEBUG: Get: <D37/> <U/> 
    2017-01-17 16:51:02 DEBUG: Get: <E34/> <V/> 
    2017-01-17 16:51:03 DEBUG: Send: <Z />
    2017-01-17 16:51:03 DEBUG: Get: <F135/> <W/> 
    2017-01-17 16:51:08 DEBUG: Get: <G133/> <T81/> 
    2017-01-17 16:51:09 INFO: Hand: 2m578899p11235s33z
    2017-01-17 16:51:09 DEBUG: Send: <D p="4"/>
    2017-01-17 16:51:09 INFO: Remaining tiles: 59
    2017-01-17 16:51:10 DEBUG: Get: <D4/> 
    2017-01-17 16:51:11 DEBUG: Get: <U/> 
    2017-01-17 16:51:12 DEBUG: Get: <E32/> <V/> 
    2017-01-17 16:51:13 DEBUG: Get: <F127/> <W/> 
    2017-01-17 16:51:16 DEBUG: Get: <G107/> <T16/> 
    2017-01-17 16:51:17 INFO: Hand: 5m578899p11235s33z
    2017-01-17 16:51:17 DEBUG: Send: <D p="16"/>
    2017-01-17 16:51:17 INFO: Remaining tiles: 55
    2017-01-17 16:51:18 DEBUG: Send: <Z />
    2017-01-17 16:51:18 DEBUG: Get: <D16/> <U/> 
    2017-01-17 16:51:20 DEBUG: Get: <E98/> <V/> 
    2017-01-17 16:51:22 DEBUG: Get: <F101/> 
    2017-01-17 16:51:23 DEBUG: Get: <W/> 
    2017-01-17 16:51:24 DEBUG: Get: <G36/> <T91/> 
    2017-01-17 16:51:25 INFO: Hand: 578899p112355s33z
    2017-01-17 16:51:25 DEBUG: Send: <D p="54"/>
    2017-01-17 16:51:25 INFO: Remaining tiles: 51
    2017-01-17 16:51:26 DEBUG: Get: <D54/> <U/> 
    2017-01-17 16:51:27 DEBUG: Get: <E131/> <V/> 
    2017-01-17 16:51:31 DEBUG: Get: <F27/> 
    2017-01-17 16:51:33 DEBUG: Send: <Z />
    2017-01-17 16:51:33 DEBUG: Get: <W/> 
    2017-01-17 16:51:34 DEBUG: Get: <g118 t="1"/> 
    2017-01-17 16:51:35 DEBUG: Send: <N />
    2017-01-17 16:51:36 DEBUG: Get: <T31/> 
    2017-01-17 16:51:37 INFO: Hand: 8m78899p112355s33z
    2017-01-17 16:51:37 DEBUG: Send: <D p="31"/>
    2017-01-17 16:51:37 INFO: Remaining tiles: 47
    2017-01-17 16:51:38 DEBUG: Get: <D31/> <U/> 
    2017-01-17 16:51:39 DEBUG: Get: <E106/> <V/> 
    2017-01-17 16:51:41 DEBUG: Get: <F129/> <W/> 
    2017-01-17 16:51:44 DEBUG: Get: <g130/> <T41/> 
    2017-01-17 16:51:45 INFO: Hand: 278899p112355s33z
    2017-01-17 16:51:45 DEBUG: Send: <D p="41"/>
    2017-01-17 16:51:45 INFO: Remaining tiles: 43
    2017-01-17 16:51:46 DEBUG: Get: <D41/> <U/> 
    2017-01-17 16:51:48 DEBUG: Send: <Z />
    2017-01-17 16:51:48 DEBUG: Get: <E0/> <V/> 
    2017-01-17 16:51:50 DEBUG: Get: <F83/> <W/> 
    2017-01-17 16:51:52 DEBUG: Get: <g109/> <T65/> 
    2017-01-17 16:51:53 INFO: Hand: 788899p112355s33z
    2017-01-17 16:51:53 DEBUG: Send: <D p="63"/>
    2017-01-17 16:51:53 INFO: Remaining tiles: 39
    2017-01-17 16:51:54 DEBUG: Get: <D63/> 
    2017-01-17 16:51:58 DEBUG: Get: <U/> 
    2017-01-17 16:51:59 DEBUG: Get: <e1/> <V/> 
    2017-01-17 16:52:00 DEBUG: Get: <f35/> 
    2017-01-17 16:52:03 DEBUG: Send: <Z />
    2017-01-17 16:52:03 DEBUG: Get: <W/> 
    2017-01-17 16:52:04 DEBUG: Get: <g96/> <T89 t="32"/> 
    2017-01-17 16:52:05 INFO: Hand: 88899p1123555s33z
    2017-01-17 16:52:05 DEBUG: Send: <REACH hai="64" />
    2017-01-17 16:52:07 DEBUG: Send: <D p="64"/>
    2017-01-17 16:52:07 INFO: Remaining tiles: 35
    2017-01-17 16:52:08 DEBUG: Get: <REACH who="0" step="1"/> 
    2017-01-17 16:52:09 DEBUG: Get: 
    2017-01-17 16:52:10 DEBUG: Get: 
    2017-01-17 16:52:11 DEBUG: Get: 
    2017-01-17 16:52:12 DEBUG: Get: 
    2017-01-17 16:52:13 DEBUG: Get: 
    2017-01-17 16:52:14 DEBUG: Get: 
    2017-01-17 16:52:15 DEBUG: Get: 
    2017-01-17 16:52:16 DEBUG: Get: 
    2017-01-17 16:52:17 DEBUG: Get: 
    2017-01-17 16:52:18 DEBUG: Send: <Z />
    2017-01-17 16:52:18 DEBUG: Get: 
    2017-01-17 16:52:19 DEBUG: Get: 
    2017-01-17 16:52:20 DEBUG: Get: 
    2017-01-17 16:52:21 DEBUG: Get: 
    2017-01-17 16:52:22 DEBUG: Get: 
    2017-01-17 16:52:23 DEBUG: Get: 
    2017-01-17 16:52:24 DEBUG: Get: 
    2017-01-17 16:52:25 DEBUG: Get: 
    2017-01-17 16:52:26 DEBUG: Get: 
    2017-01-17 16:52:27 DEBUG: Get: 
    2017-01-17 16:52:28 DEBUG: Get: 
    2017-01-17 16:52:29 DEBUG: Get: 
    2017-01-17 16:52:30 DEBUG: Get: 
    2017-01-17 16:52:31 DEBUG: Get: 
    2017-01-17 16:52:32 DEBUG: Get: 
    2017-01-17 16:52:33 DEBUG: Send: <Z />
    Exception in thread Thread-1:
    Traceback (most recent call last):
      File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
        self.run()
      File "/usr/lib/python3.4/threading.py", line 868, in run
        self._target(*self._args, **self._kwargs)
      File "/home/hao/mahjong/tenhou-python-bot/project/tenhou/client.py", line 304, in send_request
        self._send_message('<Z />')
      File "/home/hao/mahjong/tenhou-python-bot/project/tenhou/client.py", line 280, in _send_message
        self.socket.sendall(message.encode())
    BrokenPipeError: [Errno 32] Broken pipe
    
    2017-01-17 16:52:33 DEBUG: Get: 
    2017-01-17 16:52:34 DEBUG: Get: 
    2017-01-17 16:52:35 DEBUG: Get: 
    2017-01-17 16:52:36 DEBUG: Get: 
    2017-01-17 16:52:37 DEBUG: Get: 
    2017-01-17 16:52:38 DEBUG: Get: 
    2017-01-17 16:52:39 DEBUG: Get: 
    2017-01-17 16:52:40 DEBUG: Get: 
    2017-01-17 16:52:41 DEBUG: Get: 
    2017-01-17 16:52:42 DEBUG: Get: 
    2017-01-17 16:52:43 DEBUG: Get: 
    2017-01-17 16:52:44 DEBUG: Get: 
    2017-01-17 16:52:45 DEBUG: Get: 
    2017-01-17 16:52:46 DEBUG: Get: 
    2017-01-17 16:52:47 DEBUG: Get: 
    2017-01-17 16:52:48 DEBUG: Get: 
    2017-01-17 16:52:49 DEBUG: Get: 
    2017-01-17 16:52:50 DEBUG: Get: 
    2017-01-17 16:52:51 DEBUG: Get: 
    2017-01-17 16:52:52 DEBUG: Get: 
    2017-01-17 16:52:53 DEBUG: Get: 
    2017-01-17 16:52:54 DEBUG: Get: 
    2017-01-17 16:52:55 DEBUG: Get: 
    2017-01-17 16:52:56 DEBUG: Get: 
    2017-01-17 16:52:57 DEBUG: Get: 
    2017-01-17 16:52:58 DEBUG: Get: 
    2017-01-17 16:52:59 DEBUG: Get: 
    2017-01-17 16:53:00 DEBUG: Get: 
    2017-01-17 16:53:01 DEBUG: Get: 
    2017-01-17 16:53:02 DEBUG: Get: 
    2017-01-17 16:53:03 DEBUG: Get: 
    2017-01-17 16:53:04 DEBUG: Get: 
    2017-01-17 16:53:05 DEBUG: Get: 
    2017-01-17 16:53:06 DEBUG: Get: 
    2017-01-17 16:53:07 DEBUG: Get: 
    2017-01-17 16:53:08 DEBUG: Get: 
    2017-01-17 16:53:09 DEBUG: Get: 
    2017-01-17 16:53:10 DEBUG: Get: 
    2017-01-17 16:53:11 DEBUG: Get: 
    2017-01-17 16:53:12 DEBUG: Get: 
    2017-01-17 16:53:13 DEBUG: Get: 
    2017-01-17 16:53:14 DEBUG: Get: 
    2017-01-17 16:53:15 DEBUG: Get: 
    2017-01-17 16:53:16 DEBUG: Get: 
    2017-01-17 16:53:17 DEBUG: Get: 
    2017-01-17 16:53:18 DEBUG: Get: 
    2017-01-17 16:53:19 DEBUG: Get: 
    2017-01-17 16:53:20 DEBUG: Get: 
    2017-01-17 16:53:21 DEBUG: Get: 
    2017-01-17 16:53:22 DEBUG: Get: 
    2017-01-17 16:53:23 DEBUG: Get: 
    2017-01-17 16:53:24 DEBUG: Get: 
    2017-01-17 16:53:25 DEBUG: Get: 
    2017-01-17 16:53:26 DEBUG: Get: 
    2017-01-17 16:53:27 DEBUG: Get: 
    2017-01-17 16:53:28 DEBUG: Get: 
    2017-01-17 16:53:29 DEBUG: Get: 
    2017-01-17 16:53:30 DEBUG: Get: 
    2017-01-17 16:53:31 DEBUG: Get: 
    2017-01-17 16:53:32 DEBUG: Get: 
    2017-01-17 16:53:33 DEBUG: Get: 
    2017-01-17 16:53:34 DEBUG: Get: 
    2017-01-17 16:53:35 DEBUG: Get: 
    2017-01-17 16:53:36 DEBUG: Get: 
    2017-01-17 16:53:37 DEBUG: Get: 
    2017-01-17 16:53:38 DEBUG: Get: 
    2017-01-17 16:53:39 DEBUG: Get: 
    2017-01-17 16:53:40 DEBUG: Get: 
    2017-01-17 16:53:41 DEBUG: Get: 
    2017-01-17 16:53:42 DEBUG: Get: 
    2017-01-17 16:53:43 DEBUG: Get: 
    2017-01-17 16:53:44 DEBUG: Get: 
    2017-01-17 16:53:45 DEBUG: Get: 
    
    opened by 0xsuu 9
  • AI crashes when calling chankan

    AI crashes when calling chankan

    2017-07-03 00:26:23 INFO: Hand: 23m55z + 8s [888s, 456m, 999s]
    2017-07-03 00:26:24 DEBUG: Send: <N type="5" hai="103" />
    2017-07-03 00:26:24 INFO: We called a kan set!
    2017-07-03 00:26:25 DEBUG: Get: <N who="0" m="38515" /> <T51/> 
    2017-07-03 00:26:25 INFO: Meld: Type: chankan, Tiles: 8888s [100, 101, 102, 103] by 0
    2017-07-03 00:26:25 INFO: Hand: 23m8s55z + 4p [888s, 456m, 999s]
    2017-07-03 00:26:26 ERROR: Unexpected exception
    Traceback (most recent call last):
      File "/mnt/d/programming/wsl/tenhou-python-bot-0.2.7/project/tenhou/main.py", line 24, in connect_and_play
        client.start_game()
      File "/mnt/d/programming/wsl/tenhou-python-bot-0.2.7/project/tenhou/client.py", line 277, in start_game
        discarded_tile = self.player.discard_tile()
      File "/mnt/d/programming/wsl/tenhou-python-bot-0.2.7/project/mahjong/player.py", line 157, in discard_tile
        tile_to_discard = self.ai.discard_tile()
      File "/mnt/d/programming/wsl/tenhou-python-bot-0.2.7/project/mahjong/ai/main.py", line 60, in discard_tile
        selected_tile = self.process_discard_options_and_select_tile_to_discard(results, shanten)
      File "/mnt/d/programming/wsl/tenhou-python-bot-0.2.7/project/mahjong/ai/main.py", line 96, in process_discard_options_and_select_tile_to_discard
        return self.chose_tile_to_discard(results)
      File "/mnt/d/programming/wsl/tenhou-python-bot-0.2.7/project/mahjong/ai/main.py", line 211, in chose_tile_to_discard
        temp_tile = results[0]
    IndexError: list index out of range
    2017-07-03 00:26:26 INFO: Ending the game...
    2017-07-03 00:26:26 ERROR: Game was ended without success
    

    Version is 0.2.7.

    Here is the link of full log file.
    https://app.box.com/s/zj8tos4qcdjcy5f3d4iolacz9dtiz88u

    bug kan 
    opened by 0xrgb 7
  • Very slow desicion

    Very slow desicion

    Бот на сервере думал 43 секунды над тем брать ли 5м в открытие. Тенха дисконектнула по таймауту из игры.

    Локально у меня это решение за 16 секунд обрабатывается, что тоже очень много и больше доступного таймера. Возможно это как-то малой кровью ускорить.

    Вопроизвести: python reproducer.py --log 2020102209gm-0009-0000-f4494785 --player Kaavi --wind 1 --honba 0 --tile 5m --action enemy_discard

    image

    performance 
    opened by Nihisil 5
  • Fail to connect if AI takes a long time to load(~3s).

    Fail to connect if AI takes a long time to load(~3s).

    In Tenhou client, if the overhead of AI takes approximately longer than 3s, then it'll show some socket timeout messages, the fix should be trivial.

    Many thanks.

    Edit: Sample output:

    2017-03-06 11:19:40 INFO: Bot AI enabled: True
    2017-03-06 11:19:52 DEBUG: Send: <HELO name="NoName" tid="f0" sx="M" />
    2017-03-06 11:19:52 DEBUG: Get: 
    2017-03-06 11:19:52 DEBUG: Send: <BYE />
    2017-03-06 11:19:52 INFO: End of the game
    
    bug 
    opened by 0xsuu 5
  • Error while run mahjong.py

    Error while run mahjong.py

    I run the mahjong.py and this came out, please help! pygame 1.9.4 Hello from the pygame community. https://www.pygame.org/contribute.html Traceback (most recent call last): File "E:/Mahjong-Dynasty-master/mahjong.py", line 12, in jeu_mahjong = mahjong_board(graphics) File "E:\Mahjong-Dynasty-master\src\game.py", line 82, in init self.refresh_mur_gfx() File "E:\Mahjong-Dynasty-master\src\game.py", line 128, in refresh_mur_gfx x, y, angle = fgx_pos_iterateur.next() AttributeError: 'generator' object has no attribute 'next'

    opened by NozomiWyane 3
  • INFO prints dan instead of score

    INFO prints dan instead of score

    2017-06-22 17:20:01 INFO: Round: 3, Honba: 1, Dora Indicators: [73]
    2017-06-22 17:20:01 INFO: Players: [isi1017 (61,400), 辺銀堂 (25,500), ToukaBot (13,100), にこぷり麻雀道. (2級)]
    2017-06-22 17:20:01 INFO: Dealer: 辺銀堂 (25,500)
    2017-06-22 17:20:01 INFO: Round  wind: East
    2017-06-22 17:20:01 INFO: Player wind: West
    

    Here is the link of full log file. https://app.box.com/s/futa0t1619l1g848trmeihzq8as0lv20

    bug 
    opened by 0xrgb 3
  • Bot crashed when calling kan set

    Bot crashed when calling kan set

    2017-06-22 13:45:12 INFO: Meld: Type: pon, Tiles: 555s [88, 90, 91] by 0
    2017-06-22 13:45:12 INFO: With hand: 34m455666p + 5s [345m, 555s]
    2017-06-22 13:45:12 INFO: Discard tile after called meld: 4p
    2017-06-22 13:45:12 DEBUG: Send: <D p="48"/>
    2017-06-22 13:45:13 DEBUG: Get: <D48/> <U/> 
    2017-06-22 13:45:16 DEBUG: Get: <e47/> <V/> 
    2017-06-22 13:45:20 DEBUG: Send: <Z />
    2017-06-22 13:45:21 DEBUG: Get: <f59 t="3"/> 
    2017-06-22 13:45:21 DEBUG: Send: <N type="2" />
    2017-06-22 13:45:21 INFO: We called a kan set!
    2017-06-22 13:45:22 DEBUG: Get: <N who="0" m="15106" /> <T45/> 
    2017-06-22 13:45:22 ERROR: Unexpected exception
    Traceback (most recent call last):
      File "/_github/tenhou-python-bot-0.2.6/project/tenhou/main.py", line 21, in connect_and_play
        client.start_game()
      File "/_github/tenhou-python-bot-0.2.6/project/tenhou/client.py", line 316, in start_game
        self.table.add_called_meld(meld.who, meld)
      File "/_github/tenhou-python-bot-0.2.6/project/mahjong/table.py", line 75, in add_called_meld
        self.get_player(player_seat).add_called_meld(meld)
      File "/_github/tenhou-python-bot-0.2.6/project/mahjong/player.py", line 214, in add_called_meld
        self.tiles.remove(meld.called_tile)
    ValueError: list.remove(x): x not in list
    2017-06-22 13:45:22 INFO: Ending the game...
    2017-06-22 13:45:22 ERROR: Game was ended without success
    

    Here is the log.

    bug kan 
    opened by 0xrgb 3
  • Not optimal discard?

    Not optimal discard?

    Возможно кинуть 9м тут является вариантом получше, но это не точно. Надо разобраться.

    Воспроизвести: python reproducer.py --log 2020102009gm-0001-7994-5e2f46c0 --player Kaavi --wind 3 --honba 1 --tile 5m --action draw

    image

    question? 
    opened by Nihisil 2
  • Change encounter and melding logic, add data analysis stuffs

    Change encounter and melding logic, add data analysis stuffs

    Hi Alex! I am really interested in this project and appreciate it a lot for works that have done. Now I have forked it, tweaked it a little bit, added some data analysis stuffs like data cleaning and visualization, and now I am running several bots to collect more data. I am looking forward to cooperate with you more.

    The changes I have made to this bot is mainly based on a book called 科学する麻雀. It's my favorite mahjong book.

    Several changes I have made to the bot are:

    • Play game according to several different states: Preparing, Proactive Goodshape, Proactive Badshape, Reactive Goodshape, Reactive Badshape, Defence.
    • Switch strategy to tanyao or yakuhai only if (dora >=1) or (shanten <= 2) or (is_dealer). I find the bot calling melds too much and several tweaks are based on this.
    • Improve tanyao condition judgement. If there are 2 or more terminal lugs(13, 12, 23 without 4, or stuffs like that), tanyao strategy won't be activated.
    • Improve yakuhai melding judgement by disallowing calling melds before yakuhai pon is called. In previous version it calls melds a lot before yakuhai pon and that's not good.

    Now the bot calls melds much less often than before and that results in better defence and more riichi.

    Now I am collecting more data to make better analysis and see where it can improve. I have collected about 100 games and 900 hands but that's not enough at all for data analysis.

    Any suggestions are appreciated.

    opened by jakehsiao 2
  • Is there a way to see whether a discarded tile from an opponent player is changed tile or not?

    Is there a way to see whether a discarded tile from an opponent player is changed tile or not?

    Hi, thanks for your effort in this project. I have a question about possibility of telling whether a tile is a changed tile or not.

    The definition of a changed tile: if the tile a player discards has existed in his hand, it is called a "changed tile"; if the tile a player discards is the one he just draws, it is NOT a "changed tile". I believe this information is important for mahjong players. When playing mahjong face to face, we always pay attention to players who changed their hands.

    In mjlog, we can easily get this information since all tiles (including those in the hands of opponent players) are visible; however, is it possible to get this information while playing real games?

    Thanks very much.

    opened by josephchenhk 2
  • [Question/Need help] How to watch a game based on python-socket communication with tenhou.net

    [Question/Need help] How to watch a game based on python-socket communication with tenhou.net

    Hi developer @Nihisil , I'm very interested in your AI developed. I'm mostly interested in the socket communication part that allows the AI to play game automatically through sending text messages. So I'm now currently learning your code and developing a program to watch a tenhou game and print out the results. But I meet some problems.

    By clicking into a tenhou game link obtained from tenhou.net/0/wg in my browser, and press F12, I saw the message sent in order to start watching a game: image So after I connected by socket and got authenticated (this part is same as your code), I sent <WG id="8DAC0C1A" tw=0 />, but I got no reply at all. At this stage if a sent a message requesting for a game (copied from your code), I could get reply and start a game. So I'm doubting whether I sent the correct message.

    Later on I compared other messages my browser sent with your code's, and I found some differences: The Login message: image image Your code has an extra tid="f0"

    The alive message when hanging around in lobby: image image The numbers within the messages are different.

    Since both messages work for sure, I wonder how you found out the correct message to send, and why you did not choose the same message as the browser version. (Note, most other messages sent are the same)

    I'm a beginner to socket, and I'm purely coding for fun and learning. I would appreciate it very much if you could give me some hints and guidance!

    opened by 17876zjc 7
  • [Question] Why and when socket connections was automatically?

    [Question] Why and when socket connections was automatically?

    Question

    I use this repository in our Mahjong AI Project and plays mahjong game (game_type is 9, hanchan ari-ari), but sometimes game was ended unsuccessfully with the log "We are getting empty messages from socket. Probably socket connection was closed". I'm not sure why and when this happened?

    opened by nara-ryoya 2
  • Crash [Live dora tiles can't be less than 0]

    Crash [Live dora tiles can't be less than 0]

    Bots played on commit: https://github.com/MahjongRepository/tenhou-python-bot/commit/1e4d477bf470c8a9024b4ad553ab47125b914903

    Seed to reproduce:

    15996451505448234089
    
    2020-11-24_03_16_38.log-Traceback (most recent call last):
    2020-11-24_03_16_38.log-  File "bots_battle.py", line 47, in main
    2020-11-24_03_16_38.log-    manager.play_game()
    2020-11-24_03_16_38.log-  File "/app/game/bots_battle/game_manager.py", line 105, in play_game
    2020-11-24_03_16_38.log-    results = self.play_round()
    2020-11-24_03_16_38.log-  File "/app/game/bots_battle/game_manager.py", line 435, in play_round
    2020-11-24_03_16_38.log-    meld, discard_option = other_client.player.try_to_call_meld(tile, is_kamicha_discard)
    2020-11-24_03_16_38.log-  File "/app/game/player.py", line 240, in try_to_call_meld
    2020-11-24_03_16_38.log-    return self.ai.try_to_call_meld(tile, is_kamicha_discard)
    2020-11-24_03_16_38.log-  File "/app/game/ai/main.py", line 126, in try_to_call_meld
    2020-11-24_03_16_38.log-    meld, discard_option = self.current_strategy.try_to_call_meld(tile_136, is_kamicha_discard, tiles_136)
    2020-11-24_03_16_38.log-  File "/app/game/ai/strategies/main.py", line 184, in try_to_call_meld
    2020-11-24_03_16_38.log-    chosen_meld_dict = self._find_best_meld_to_open(tile, possible_melds, new_tiles, closed_hand, tile)
    2020-11-24_03_16_38.log-  File "/app/game/ai/strategies/main.py", line 405, in _find_best_meld_to_open
    2020-11-24_03_16_38.log-    selected_tile = self.player.ai.hand_builder.choose_tile_to_discard(after_meld=True)
    2020-11-24_03_16_38.log-  File "/app/game/ai/hand_builder.py", line 47, in choose_tile_to_discard
    2020-11-24_03_16_38.log-    discard_options, threatening_players = self.player.ai.defence.mark_tiles_danger_for_threats(discard_options)
    2020-11-24_03_16_38.log-  File "/app/game/ai/defence/main.py", line 482, in mark_tiles_danger_for_threats
    2020-11-24_03_16_38.log-    discard_options = self.calculate_danger_borders(discard_options, threatening_player, threatening_players)
    2020-11-24_03_16_38.log-  File "/app/game/ai/defence/main.py", line 206, in calculate_danger_borders
    2020-11-24_03_16_38.log-    threatening_player_hand_cost = threatening_player.get_assumed_hand_cost(tile_136)
    2020-11-24_03_16_38.log-  File "/app/game/ai/defence/enemy_analyzer.py", line 161, in get_assumed_hand_cost
    2020-11-24_03_16_38.log-    return self._calculate_assumed_hand_cost_for_riichi(tile_136)
    2020-11-24_03_16_38.log-  File "/app/game/ai/defence/enemy_analyzer.py", line 272, in _calculate_assumed_hand_cost_for_riichi
    2020-11-24_03_16_38.log-    assert live_dora_tiles >= 0, "Live dora tiles can't be less than 0"
    2020-11-24_03_16_38.log-AssertionError: Live dora tiles can't be less than 0
    
    bug battle 
    opened by Nihisil 1
  • Don't consider suji traps when calling riichi on dora (except for 1 or 9 maybe)

    Don't consider suji traps when calling riichi on dora (except for 1 or 9 maybe)

    Боты сейчас активно ричуют в залом, но они не учитывают, что залом на дору фактически не работает. Поэтому для ожиданий на дору в логике кидать риичи или даматенить лучше не учитывать залом вообще, или учитывать его только при риичи на 1 или 9.

    enhancement 
    opened by bogachev-pa 0
  • Additional riichi/damaten rules

    Additional riichi/damaten rules

    Есть еще такая мысль, если противник ричует, то, если даматеним на тайлы, не безопасные против него, то ричуем встречку. Мб кроме случаев, когда ждем в танки на плохой вэйт. Можно будет это продумать.

    idea 
    opened by bogachev-pa 0
Releases(v0.5.1)
  • v0.5.1(Dec 16, 2020)

  • v0.5.0(Nov 29, 2020)

  • v0.4.0(Feb 26, 2019)

    For this version, we did a lot of improvements (162 commits in total) in hand building and meld calling. The bot is building hand very well now and the next step is to build a smart defence mechanism.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.2(Oct 7, 2017)

  • v0.3.1(Sep 30, 2017)

    • Fix players sorting (it is sorting by first position as a second attribute now)
    • Remove " " from log name
    • Tsumogiri tile when it is possible
    • Resurrect statistics sender
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Sep 25, 2017)

    • Hand calculations code were was to the separate project, so you had to run pip install -r requirements.txt to install this package (https://github.com/MahjongRepository/mahjong)
    • AI structure was refactored and now it is easy to implement your own AI. You can find details here: https://github.com/MahjongRepository/tenhou-python-bot#implement-your-own-ai
    Source code(tar.gz)
    Source code(zip)
  • v0.2.8(Jul 22, 2017)

  • v0.2.7(Jun 22, 2017)

    • Fix an issue with crash after called kan set (#32)
    • Fix wrong scores displaying for player with scores = 0 (#33)
    • Minor fixes in bot logger formatter
    Source code(tar.gz)
    Source code(zip)
  • v0.2.6(Jun 21, 2017)

    • Add round reproducer (check readme for details)
    • Fix an issue with crash after called kan
    • Fix an issue with called meld wrong log messages (#31)
    Source code(tar.gz)
    Source code(zip)
  • v0.2.5(Apr 15, 2017)

    Features:

    • Add logic to call closed kan, chankan and opened kan
    • Handle unexpected errors and store stack trace to the log
    • Try to push riichi (with a good wait) against threatening players
    • Remove analytics code from the project
    • Remove local game runner code from the project

    Bugs fixes:

    • Improve the way to open hand and fix different bugs related to it
    • Fix a bug related to crash when tempai without riichi
    • Improve honitsu discard detection
    • Fix a bug with overwriting safe tile danger value by more dangerous tile
    Source code(tar.gz)
    Source code(zip)
  • v0.2.4(Apr 11, 2017)

    Features:

    • Total refactoring of discards system
    • Minor improvements of rounds reproducer
    • Try to push with expensive (with 3+ doras) 1 shanten hand against threatening players
    • Try to save more valuable tiles in hand even if they have less remaining tiles
    • Try to grab as much yakuhai pons as possible
    • Correctly handle atodzuke opened yakuhai hands
    • Improve defence against multiple honitsu players
    • Improve honitsu discards detection

    Bugs fixes:

    • Don't add chankan to the players melds (because we already added a pon)
    • Fix a bug with wrong hand estimation in defence mode
    • Fix a bug with wrong detection of safe tiles
    • Fix a bug with wrong honitsu detection
    • Exclude aka dora from waiting for hand estimation, because it affected on hand cost
    Source code(tar.gz)
    Source code(zip)
  • v0.2.3(Apr 8, 2017)

    New features:

    • After started game bot will parse game rules (aka dora and open tanyao) and it will change it's play logic based on these rules
    • Discards system were refactored for better support of defence logic. It will consume more resources now, but will give more opportunity to the careful playing
    • Detect enemy's honitsu hands and fold against them
    • Parse and store to a log a message about new achieved rank
    • Add replay reproducer. We need it to be able reproduce round from the tenhou log and debug bot's decisions
    • First try to fold only with 100% safe tiles against multiple players, and if there is no 100% safe tiles try to find common suji tiles to fold
    • Mark dora as a dangerous tile to discard when defence with suji

    Bugs fixes:

    • Fix a bug when bot didn't riichi for with penchan waiting
    • Fix a bug with not counting our bot discards as safe tiles against other players in riichi
    • Fix a bug with wrong is_tempai flag after discarding tiles
    • Fix a crash after called chankan
    • Fix an issue with wrong counting of remaining tiles in the wall
    • Check should bot go to the defence mode just after called riichi, not after first draw. It will affect open hand suggestions
    Source code(tar.gz)
    Source code(zip)
  • v0.2.2(Mar 21, 2017)

    • Improve defence strategy with Kabe technique
    • Improve defence strategy with Suji technique
    • Remove beautifulsoup4 dependency. It should speed up a bot a little bit
    • Various minor fixes in local games runner
    • Fix an issue with bot discards and revealed tiles cache
    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(Mar 17, 2017)

    Bot AI improvements:

    • In defence mode try to discard not needed safe tiles first
    • If there is no not needed tiles, try to discard safe tiles that will do less harm to the hand state
    • Don't call a riichi for a pair wait (except chitoitsu). This wait can be easily improved

    Local games improvements:

    • Don't allow to call ron when furiten
    • Support multiple ron for local games
    • Support abortive retakes for local games
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Mar 16, 2017)

    • Store information about was tile discarded from hand or it was tsumogiri. It will be helpful for future discard analyzation
    • Implement simple defence mode. Discard gembutsu tiles after other player riichi if our hand is cheap or not ready
    • Heavy refactoring of Client, Table and Player classes. It will allow to build next features with less efforts :)
    Source code(tar.gz)
    Source code(zip)
  • v0.1.1(Mar 8, 2017)

    • Add the mode to detect game type dynamically based on bot rank and rate
    • Fix and issue with socket initialization and resources loading
    • Handle KeyboardInterrupt exception on Ctrl + C
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Mar 6, 2017)

    • Was added basic support for open hands. Bot will open hand if it will improve hand shanten number. And it has different open hand strategies: Tanyao, Honitsu, Yakuhai.
    • Each discard tile has "value" from now. For example dora would be more valuable, than usual tile, or 5 is more valuable than 1. Bot will try to discard not valuable tiles first.
    • For "remaining tiles" we will not count discarded tiles or tiles from open sets. So, bot will try to avoid "dead" waits.
    • Local game runner was significantly improved. It supports more mahjong aspects and allows to save local games in tenhou.net log format. So, you can view it with standard tenhou log viewer.
    • Add analytics package. It contains scripts to download phoenix replays and load them to the memory. Later I will analyze phoenix replays for different mahjong situations (like suji traps and etc.)
    Source code(tar.gz)
    Source code(zip)
  • v0.0.5(Jun 29, 2016)

  • v0.0.4(Jun 24, 2016)

  • v0.0.3(Jun 21, 2016)

    • Allow to set settings from command arguments. Use python main.py -h for details
    • Support login to the lobby
    • Support is_tournament mode. In this mode bot will connect to the lobby and will wait while game is started.
    Source code(tar.gz)
    Source code(zip)
  • v0.0.2(May 23, 2016)

  • v0.0.1(May 23, 2016)

    Bot can only collects tiles and calls riichi. It doesn't know about dora, yaku or defence, but all main features for playing on tenhou.net were implemented. In the next release I will improve bot strategy.

    Source code(tar.gz)
    Source code(zip)
The Research PACS on AWS solution facilitates researchers' access medical images stored in the clinical PACS in a secure and seamless manner

Research PACS on AWS Challenge to solve Solution presentation Deploy the solution Further reading Releases License Challenge to solve The rise of new

AWS Samples 23 Sep 09, 2022
A bot can play all variants, but standard are abit weak, so if you need strongest you can change fsf instead of stockfish_14_Dev

MAINTAINERS Drdisrespect1 and drrespectable lichess-bot Engine communication code taken from https://github.com/ShailChoksi/lichess-bot by ShailChoksi

RPNS Nimsilu 1 Dec 12, 2021
Reddit bot that uses sentiment analysis

Reddit Bot Project 2: Neural Network Boogaloo Reddit bot that uses sentiment analysis from NLTK.VADER WIP_WIP_WIP_WIP_WIP_WIP Link to test subreddit:

TpK 1 Oct 24, 2021
A muti pairs martingle trading bot for Binance exchange.

multi_pairs_martingle_bot English Documentation A muti pairs martingle trading bot for Binance exchange. Configuration { "platform": "binance_futur

51bitquant 62 Nov 16, 2022
VideoMergeDcBot1 - Video Merge Dc Bot for telegram

VIDEO MERGE BOT An Telegram Bot Demo 👉 @VideoMergeDcBot To Merge multiple Video

Selfie SD 2 Feb 04, 2022
Ethereum transactions and wallet information for people you follow on Twitter.

ethFollowing Ethereum transactions and wallet information for people you follow on Twitter. Set up Setup python environment (requires python 3.8): vir

Brian Donohue 2 Dec 28, 2021
Web-music-bot - A telegram bot which get a *site Url* and sends all songs contain in the Url to telegram

web music bot this is a telegram bot which get a site Url and sends all songs co

Arya Shabane 4 Apr 02, 2022
Django3 web app that renders OpenWeather API data ☁️☁️

nz-weather For a live build, visit - https://brandonru.pythonanywhere.com/ NZ Openweather API data rendered using Django3 and requests ☀️ Local Run In

Brandon Ru 1 Oct 17, 2021
A Telegram bot that can stream Telegram files to users over HTTP

AK-FILE-TO-LINK-BOT A Telegram bot that can stream Telegram files to users over HTTP. Setup Install dependencies (see requirements.txt), configure env

3 Dec 29, 2021
AKShare is an elegant and simple financial data interface library for Python, built for human beings

AKShare is an elegant and simple financial data interface library for Python, built for human beings

AKFamily 5.8k Dec 30, 2022
A Discord Tool which checks for valid tokens and adds them to a server

Discord-Server-Botter A Discord Tool which checks for valid tokens and adds them to a server Usage Choice 1 is for checking tokens Choice 2 is for add

Bless 3 Jul 01, 2022
The Most Simple yet Powerful and Advanced Google Colab Notebook for Zip, Unzip, Tar, UnTar, RaR, UnRaR Files in Google Drive

The Most Simple yet Powerful and Advanced Google Colab Notebook for Zip, Unzip, Tar, UnTar, RaR, UnRaR Files in Google Drive

Dr.Caduceus 15 Aug 16, 2022
A discord bot to assist you when playing phasmophobia.

phasbot A discord bot to assist you when playing phasmophobia. Add phasbot to your server here! Bot Commands ?help - shows commands ?info [ghost name]

1 Dec 22, 2021
We propose the adversarial blur attack (ABA) against visual object tracking.

ABA We propose the adversarial blur attack (ABA) against visual object tracking. The ICCV link: https://arxiv.org/abs/2107.12085 and, https://openacce

Qing Guo 13 Dec 01, 2022
SickNerd aims to slowly enumerate Google Dorks via the googlesearch API then requests found pages for metadata

CLI tool for making Google Dorking a passive recon experience. With the ability to fetch and filter dorks from GHDB.

Jake Wnuk 21 Jan 02, 2023
Telegram chats reader with python

Telegram chat reader Программа полностью сливает чаты телеграм в базу данных PostgreSQL. Для использования нужен развернутый сервер постгрес и телегра

Anton 4 Dec 24, 2021
[Multithreading] [Proxy - auto & infile]

Discord-Token-Generator-AutoCheck [Multithreading] [Proxy - auto & infile] How to install? pip install -r requirements.txt run generator.py with pytho

Chakeaw__ 3 Oct 17, 2021
Clipboard-watcher - Keep an eye on the apps that are using your clipboard

clipboard-watcher This repository contains the code of an experiment, in order t

Gonçalo Valério 48 Oct 13, 2022
A telegram bot script for generating session string using pyrogram and telethon on Telegram bot

String-session-Bot Telegram Bot to generate Pyrogram and Telethon String Session. A star ⭐ from you means a lot to us! Usage Deploy to Heroku Tap on a

Wahyusaputra 8 Oct 28, 2022
Elon Muschioso is a Telegram bot that you can use to manage your computer from the phone.

elon Elon Muschioso is a Telegram bot that you can use to manage your computer from the phone. what does it do? Elon Muschio makes a connection from y

4 Feb 28, 2022