Jimboom7 / AlphaJong

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

I'd like to make a suggestion about the bot's strategy. #45

Closed dioarame closed 2 years ago

dioarame commented 2 years ago

1.

For example, if you have a starting hand, such as 24478m2p247s12z, the bot preferentially throws away the z-tiles. This is an efficient approach, but it's like giving up a hand that can be safe later in a real game or a hand that can be Yaku. (especially in the case of double east double south or our wind tile is only 1 in start hand.)

The method of making efficiency-oriented cards is effective in low tiers, but it is seen as reducing the number of cases that can be won with a rather low defense in the Gold-Jade section. (In particular, Damaten after middle stage of game and Richie of other players)

I don't have an exact idea how to deal with this, but I hope you see it as an approach that can be referred to for future development.

2.

I wonder how BOT predicts the loss composition after another player declares a call. For example, if there is a player who calls 999s / 999p, it is generally expected to be a Terminal or Honor in each set and is wary of creating a risk card to compensate for it. (Determine if it is possible to throw away tiles such as 23/78 mps and z-tiles.)

Sometimes, however, BOT tends to cut its teeth too boldly, which seems to be less careful after another player's call raises the Danger Level.

After this process, BOT takes the Fold strategy in quite a few cases. However, since ztiles that can be considered safety pads have already been discarded without damaging their hands in connection with No. 1, they are often deducted from No-ten even if they are not directly Ron.

3.

Judgment of offense and defense is an important issue in Mahjong. However, the bot raises his hand with 1,000 points and shows aggressive behavior despite Oya's statistical announcement of Richie with an average of 5,200 points. In some cases, this can be passed safely, but in many cases, it results in a loss of points. In particular, it often appears when it first has two wind tiles or 5,6,7z, so it immediately calls.

I didn't come up with an idea to deal with direct technology related to development, but as a person who loves this project, I wrote a long opinion. I hope this opinion will be helpful for future development.

dioarame commented 2 years ago

Oh, and I don't know if you guys will check, but I have another idea. I think it would be good if Tenpai, BOT raises the expected score of the complete hand with Tsumo or Ron.

ex. Max : nn Fu nn Han, 0000 Min : nn Fu nn Han, 0000

I think this can be useful with the Help mode that can be checked at present.

It is good for AI to respond to the other person's Richie or many calls, but I think it is also a great direction for players to consider.

dioarame commented 2 years ago

As in Image, Bot Accept Call to make ready hand. But as we know, there is 9m in hand - this mean, if accepted call our hand would be 'No Yaku.' -

In addition, BOT overall showed good performance but showed incomprehensible behavior in some games. (Especially in games of East 2 / South 1 / South 3)

I attached Paipu link, if you need to check - please see it. https://mahjongsoul.game.yo-star.com/?paipu=jkjpls-zwsv3586-1935-6gff-fnhh-dmkmpquxpmyv_a830397198_2 (Sadly, Webpage was refrashed, so I couldn't copy Log of Bot.)

Jimboom7 commented 2 years ago

As you may have noticed I worked on a new version in the "experimental" branch that should improve some of your concerns.

In addition, BOT seems to have a lower rate of choosing Fold than in the past.

I am not sure what version you used, but this should not happen anymore in the latest version (See PR #46 ). It is now stable and I would be glad if you try it out and report any bugs or problems you find,

dioarame commented 2 years ago

I used https://github.com/Jimboom7/AlphaJong/issues/42 script. I'll try you're WIP version and report bugs or problems if I find.

Thanks for reply and hope you well!

yangruihan commented 2 years ago

I used #42 script. I'll try you're WIP version and report bugs or problems if I find.

Thanks for reply and hope you well!

If you need "help" mode, you can use this script, at this brach . It is based on the computing logic of the latest experimental branch, I will try to keep it consistent with the branch logic as soon as possible.

Thanks. ;-)

dioarame commented 2 years ago

I checked with 3 games and few recognition was found.

I think this might be difficult to decision because chitoitsu is need some luck. https://mahjongsoul.game.yo-star.com/?paipu=jkjpls-z2423869-z163-6de5-gbkm-mrotqpujowvy_a830397198_2 [East 1]

But with Tenpai for chitoitsu, Bot has some chance to select or waiting good tiles... like 1/9 Tiles and Yaku tiles. I know it is not formula, just suggestion for waiting good waiting.

(But I know, in upper game We were Oya and early stage Oya's Richie is pressure to other player's hand.)

2.

3.

  1. is not a problem. In my sense, BOT's Defense algorithm is quite good than before. (By the way, There were an accident in other game - loss point by Turn 4 : Mangan Damaten ... Well, Top class player also cannot dodge either I think :) )

Thanks for Good project again, and I anticipate with end WIP stage of project! And I hope my opinion is help to improve BOT's performance.

ms860309 commented 2 years ago

1. It looks like robots prefer chiitoitsu to toitoi. 2. The experimental version is broken in 3 player mode.

Jimboom7 commented 2 years ago

@dioarame Are you sure you used the correct version? Because I checked the replays which you linked and when I let the bot make a decision in that state it was different from your discards. For example this one:

https://mahjongsoul.game.yo-star.com/?paipu=jkjpls-z2423869-z163-6de5-gbkm-mrotqpujowvy_a830397198_2 [East 1] But with Tenpai for chitoitsu, Bot has some chance to select or waiting good tiles... like 1/9 Tiles and Yaku tiles.

When I try it the bot kept the South Wind and discarded a number tile, which is good.

Same thing about 2 (3444m12589p137s4z): When I try it the bot wants to discard 4z. But this example is without context of the whole game, so there could be other reasons why it chooses to discard 3m for you (like danger for example).

https://mahjongsoul.game.yo-star.com/?paipu=jkjpls-zwsv3586-1935-6gff-fnhh-dmkmpquxpmyv_a830397198_2 [East 2]

I also got different discards there, the bot did not discard manzu when I tried it (In fact, the 6m that was discarded by you is considered the worst discard by the bot).

@ms860309 Thank you for your feedback! I will see if I can improve the chiitoitsu/toitoi decision. 3 player mode is actually broken right now, I totally forgot to test that. Will fix it soon!

dioarame commented 2 years ago

image

I updated WIP version almost 8 hours ago like above, but I'll check and re-install script. Because I also think it's weird discard than before.

woonchoi commented 2 years ago

Thank you for the improvement of the wonderful project.

When I tested the new version of AI, I could see some problems.

  1. AI is really good at defending. But when someone does Riichi, they tend to give up their tenpai state too easily. This means a significant reduction in win rate.

The users of Gold tier tend to push it too hard when someone does Riichi, and in this process, the number of safe tiles increases. I think AI should try to make Tenpai in the new safety tile even if it goes to the full fold state.

  1. Sometimes AI makes excessive calls. For example, a call without closed yaku is typical. If open yaku cannot be closed yaku (if tsumotile does not come in properly), AI flounder in no yaku.

  2. In the shouldRiichi function, I wonder if that part is the correct code.

    // Hand already has high value and enough yaku (line 762)
    if (tilePrio.yaku.closed >= 1 && tilePrio.score.riichi > 5000 + (RIICHI * 1000) + (tilePrio.waits * 500)) {
        log("Decline Riichi because of high value hand with enough yaku.");
        return false;
    }

As I think, the code below needs to be modified like this to work as intended.

    // Hand already has high value and enough yaku (line 762)
    if (tilePrio.yaku.closed >= 1 && tilePrio.score.closed > 5000 + (RIICHI * 1000) + (tilePrio.waits * 500)) {
        log("Decline Riichi because of high value hand with enough yaku.");
        return false;
    }

At the same time, I think this should be improved when AI start calculating the score properly.

    // Last Place (in last game)? -> Yolo
    if (isLastGame() && getDistanceToLast() > 0) {
        log("Accept Riichi because of last place in last game.");
        return true;
    }

I think it should be set to play Riichi when we secure a score to avoid 4th place. (I'm not sure if it's possible, but I hope it's possible.)

  1. 3 player mode should be calculated by missing one person. so, in the score calculation part should be modified as below.
function calculateScore(player, han, fu = 30) {
    var discount = 0;

    if (getNumberOfPlayers() == 3) {
        discount = 1;
    }

    var score = (fu * Math.pow(2, 2 + han) * (4 - discount));

    if (han > 4) {
        score = 8000 - (discount * 2000);
    }

    if (han > 5) {
        score = 8000 + ((han - 5) * 4000 - (discount * 2000));
    }
    if (han > 6) {
        score = 12000 + ((han - 6) * 2000 - (discount * 3000));
    }
    if (han > 8) {
        score = 16000 + ((han - 8) * 2666 - (discount * 4000));
    }
    if (han > 11) {
        score = 24000 + ((han - 11) * 4000 - (discount * 6000));
    }
    if (han >= 13) {
        score = 32000 - (discount * 8000);
    }

    if (getSeatWind(player) == 1) { //Is Dealer
        score *= 1.5;
    }

    return score;
}

Below is a feature proposal.

  1. It would be great if a function that sets parameters differently in 3 player mode is added.

  2. Additionally, it would be nice if there is an additional button that allows humans to determine the current state of AI. For example

    • Auto mode(AI determines attack and defense based on current situation)
    • General(When selected, the AI will determine the Discard tile according to the General rule when it arrives at the next OwnTurn.)
    • Fold(Force entry into the Fold Discard state.)

I think it will be useful when a person wants to decide on the judgment of attack and defense. Especially, it would be good to use Discard tile when showing it in GUI patches.

Thank you for always working on a good project :D

dioarame commented 2 years ago

I found wrong decision of bot's action.

Log

OWN TURN

userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 Debug String: 8p|123789m67899p89s1z|||||275z5m24s3m8s13p|1s441z12p11s6z8s|372z8p2z29m4p1s3p|18p8m89s54m5p6m3s3p|0,0,0,0|2|1|28 userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 Shimocha Tenpai Chance: 7.6%, Expected Hand Value: 2578 userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 Toimen Tenpai Chance: 7.6%, Expected Hand Value: 2578 userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 Kamicha Tenpai Chance: 9.2%, Expected Hand Value: 3951 userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 Strategy: General userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 Would fold this hand above 1786.09 danger. userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 Tile Priorities: userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 Overall: Value Open: <6726> Closed Value: <8946> Riichi Value: <15200> Shanten: <0> userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 1z: Priority: <2008.122> Efficiency: <0.225> Yaku Open: <1.507> Yaku Closed: <2.744> Dora: <2.251> Waits: <4.498> Danger: <17.22> userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 6p: Priority: <174.503> Efficiency: <0.040> Yaku Open: <0.585> Yaku Closed: <0.909> Dora: <1.909> Waits: <0.791> Danger: <32.88> userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 9s: Priority: <109.198> Efficiency: <0.027> Yaku Open: <0.304> Yaku Closed: <0.597> Dora: <2.219> Waits: <0.548> Danger: <6.14> userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 ["1z"] userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 Decline Riichi because of high value hand with enough yaku. userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 Riichi declined! userscript.html?name=AlphaJong.user.js&id=928ad15b-d66b-4a59-97ba-8934f6b56f4d:1373 Discard: 1z

As you see in Log, Bot declined Riichi because of enough Yaku. But, it was wrong - Hand has no Yaku, just Dora's value. -

So I think, Bot should calculate hand value like this. - Yaku Han + Number of Dora's = Hand's Total value - It means, If we have Yaku Han with Dora, Bot could choose Damaten or Riichi.

In summary, it seems that Yaku and Dora need to be separated in BOT's operation.

Jimboom7 commented 2 years ago

Version 1.3.0 is now released and should fix most of the problems and suggestions propsed here:

For example, if you have a starting hand, such as 24478m2p247s12z, the bot preferentially throws away the z-tiles. This is an efficient approach, but it's like giving up a hand that can be safe later in a real game or a hand that can be Yaku. (especially in the case of double east double south or our wind tile is only 1 in start hand.)

There is a new parameter called KEEP_SAFETILE to keep at least 1 honor tile (until 1 shanten). The bot also tries to Sakigiri a bit, by raising the SAKIGIRI parameter you can increase the effect.

I wonder how BOT predicts the loss composition after another player declares a call. For example, if there is a player who calls 999s / 999p, it is generally expected to be a Terminal or Honor in each set and is wary of creating a risk card to compensate for it.

The bot is now trying to predict the opponents yaku when the hand is open.

Judgment of offense and defense is an important issue in Mahjong. However, the bot raises his hand with 1,000 points and shows aggressive behavior despite Oya's statistical announcement of Richie with an average of 5,200 points.

The bot now calculates the expected values for the own and the opponents hand and should make better push/fold decisions with that information.

The users of Gold tier tend to push it too hard when someone does Riichi, and in this process, the number of safe tiles increases. I think AI should try to make Tenpai in the new safety tile even if it goes to the full fold state.

The AI will now check what level the current room is (like bronze, silver, gold etc) and will fold later in lower ranked rooms.

As you see in Log, Bot declined Riichi because of enough Yaku. But, it was wrong - Hand has no Yaku, just Dora's value. - So I think, Bot should calculate hand value like this. - Yaku Han + Number of Dora's = Hand's Total value - It means, If we have Yaku Han with Dora, Bot could choose Damaten or Riichi. In summary, it seems that Yaku and Dora need to be separated in BOT's operation.

This is not a problem with separating the Yaku/Dora value. Those values are separated. In you case the problem was that the Yaku was calculated incorrectly, it expects the hand to have 1 or 2 open yaku which is wrong. I think it's related to Chanta or Junchan, I noted it down and will try to improve it in the future.

@woonchoi Some of your suggestions are implemented now, but I haven't touched the 3 player specific parts yet. I did not forget about them, it's on my TODO list.