Jimboom7 / AlphaJong

A Mahjong AI for Mahjong Soul
GNU General Public License v3.0
395 stars 56 forks source link

Suggestion for 3 player mahjong strategy #30

Closed woonchoi closed 2 years ago

woonchoi commented 2 years ago

First of all, I would like to thank you for your outstanding project.

I tested the script on a 3 player mahjong and found some problems and strategic errors.

1. AI call pon west wind when seat wind is south. (maybe problem in getSeatWind function, 3 player mahjong need another function for it)

function getSeatWind(player) {
    return ((4 + localPosition2Seat(player) - view.DesktopMgr.Inst.index_ju) % 4) + 1;
}

2. Basically, 3 player mahjong is very aggresive. so AI need another strategy for it.

3. AI didn't send AboltiveDrawCall when hand is really bad.

3. The offense and defense judgment should be a little more clear.

It is worth considering that the strategy taken by AI changes to some extent depending on the turn by using dynamic parameters rather than static parameters.

when tilesLeft > 30, AI more concentrate on offense. (High YAKU_VALUE, DORA_VALUE.) when someone riichi, AI fold quickly (FOLD_CONSTANT decrease) etc..

Jimboom7 commented 2 years ago

Thank you for these detailed suggestions. The 3 player AI is currently 99% percent based on the 4 player AI. I only added the most important "fixes" like being able to call Kita, but that's it - because I personally have no clue of 3 player mahjong and the differences in strategy. Your points sound logical, but without knowledge of the mode I don't feel like I could implement most of them really well. It would require rewriting most of the AI logic (maybe even completely splitting the 4 player and 3 player AI). But this is an open source project, so maybe others will pick up this task. I'll just fix some obvious bugs or smaller problems myself:

  1. AI call pon west wind when seat wind is south. (maybe problem in getSeatWind function, 3 player mahjong need another function for it)

I think I tested this extensively even in 3 player mode, but maybe it's still buggy. I'll investigate it further and fix it if necessary. EDIT: The function is working as intended, tested it in east and south round for multiple positions.

  1. Basically, 3 player mahjong is very aggresive. so AI need another strategy for it.

As I mentioned, this is not trivial, it requires to rewrite a huge part of the code and you also need good knowledge of 3 player mahjong which I don't have. The kita problem seems very simple, so maybe I'll fix that myself.

  1. AI didn't send AboltiveDrawCall when hand is really bad.

Thanks for pointing this out, the parantheses are indeed missing. Checking for multiple pairs of honor tiles also makes sense, even in 4 player mode.

  1. The offense and defense judgment should be a little more clear. when tilesLeft > 30, AI more concentrate on offense. (High YAKU_VALUE, DORA_VALUE.) when someone riichi, AI fold quickly (FOLD_CONSTANT decrease)

The AI will already play more aggressively early and when someone calls riichi fold quickly. But the default parameters are optimized for 4 player mode, and also the logic behind it. This is also something which I can't fix without better knowledge of 3 player mahjong.

woonchoi commented 2 years ago

The getSeatWind function should be called in this form when in three player mode.

function getSeatWind(player) {
    if (getNumberOfPlayers() == 3) {
        return ((3 + localPosition2Seat(player) - view.DesktopMgr.Inst.index_ju) % 3) + 1;
    }
    else {
        return ((4 + localPosition2Seat(player) - view.DesktopMgr.Inst.index_ju) % 4) + 1;
    }
}

AI determines the existence of wind tiles yaku based on the location of their seats. I was able to correct this function like this and eliminate the error of calling the wrong wind tile in the three player mode.

EDIT: When sitting in the west wind in three player mode, the debug string is printed as follows:

4p|19m12468p567s127z||||342z|5z1m2p|133z|0,0,0|4|1|44

cbrt729 commented 2 years ago

Thanks for the 1.3.0 update! Push/fold decisions are dramatically improved than before!

I report the similar problem as mentioned above about seat wind. In the case below, discarding 6p makes the hand to be tenpai but the AI discarded 4s. From the debug string the AI appears to recognize the north is its own wind and the current hand has no yaku. The woonchoi's solution works fine for me to fix it.

220521

##### OWN TURN #####
Debug String: 2z|236p23440s55z4p|333z|||9m8s7z9p9s5p|9m2s6z3s3p1s|11s17z3p6z|0,0,0|4|2|33
Right Player Tenpai Chance: 4.2%, Expected Hand Value: 8610
Left Player Tenpai Chance: 2.4%, Expected Hand Value: 8000
Strategy: General
Would fold this hand above 437.38 danger for 4s discard.
Tile Priorities:
Overall: Value Open: <7321> Closed Value: <7321> Riichi Value: <10714> Shanten: <1>
🀓: 4s: Priority: <784.541> Efficiency: <0.180> Yaku Open: <0.086> Yaku Closed: <0.086> Dora: <3.892> Waits: <1.797> Danger: <8.61> 2
🀑: 2s: Priority: <598.638> Efficiency: <0.140> Yaku Open: <0.088> Yaku Closed: <0.094> Dora: <3.998> Waits: <1.402> Danger: <0.66>
Discard: 4s

And I found the following codes use half the number of the wall tiles as a constant. The starting wall is 70 tiles in the 4 player mode but 55 in the 3 player mode. It seems to be better to switch this constant to 27.5 from 35 in the 3 player mode to prevent early fold.

https://github.com/Jimboom7/AlphaJong/blob/0150d275434c92b091667f303ae66ecfde4c5fab/src/utils.js#L698 https://github.com/Jimboom7/AlphaJong/blob/1a4d5e2f0b7d8e12a65465f7ee7667ebe921b5a4/src/ai_offense.js#L206