Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
moxcomic committed Jun 27, 2024
1 parent a9cdc01 commit 297e312
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 1 deletion.
6 changes: 5 additions & 1 deletion lesson/Navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@

第四课: 优化出牌操作 | Lesson Four: Optimizing Discard Details

[简体中文](./lesson_four/LESSON_FOUR_CN.md) | [English](./lesson_four/LESSON_FOUR_EN.md)
[简体中文](./lesson_four/LESSON_FOUR_CN.md) | [English](./lesson_four/LESSON_FOUR_EN.md)

第五课: 吃 | Lesson Five: Chii (Eat)

[简体中文](./lesson_five/LESSON_FIVE_CN.md) | [English](./lesson_five/LESSON_FIVE_EN.md)
112 changes: 112 additions & 0 deletions lesson/lesson_five/LESSON_FIVE_CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
## 第五课: 吃

`Archer`已经为大家封装好了一系列牌桌操作方法, 他们位于`github.com/moxcomic/Archer/actions`包内`(该包为Archer内置包, 并未公开, 无法在Github查看)`

## 函数详情

```go
package actions

import "sync"

type MajsoulActions struct{}

var (
inst *MajsoulActions
once = sync.OnceFunc(func() {
inst = &MajsoulActions{}
})
)

func NewMajsoulActions() *MajsoulActions {
once()

return inst
}

func (self *MajsoulActions) Join(roomID int, roomType int) {}
func (self *MajsoulActions) ReJoin() {}
func (self *MajsoulActions) CancelJoin() {}
func (self *MajsoulActions) Confirm() {}
func (self *MajsoulActions) BackToHome() {}
func (self *MajsoulActions) Huansanzhang() {}
func (self *MajsoulActions) Babei() {}
func (self *MajsoulActions) Discard(tile string, tsumogiri bool) {}
func (self *MajsoulActions) Riichi(tile string, tsumogiri bool) {}
func (self *MajsoulActions) Chii(tile0 string, tile1 string) {}
func (self *MajsoulActions) Pon(tile0 string, tile1 string) {}
func (self *MajsoulActions) Daimingkan(tile string) {}
func (self *MajsoulActions) Kakan(tile string) {}
func (self *MajsoulActions) Ankan(tile string) {}
func (self *MajsoulActions) Ryukyoku() {}
func (self *MajsoulActions) Tsumo() {}
func (self *MajsoulActions) Ron() {}
func (self *MajsoulActions) Cancel() {}
func (self *MajsoulActions) ComeBack() {}
```

## 牌代码

`Archer`的牌按照天凤牌代码进行记牌

```
m: 萬
p: 筒
s: 索
z: 字
例如: 1m 表示 一萬
东南西北白發中: 1234567 z
```



## 思路解析

由上方信息我们可以知道,如果你想要出牌就可以调用`Chii(tile0 string, tile1 string)`接口方法,其中`tile0``tile1`为要进行吃的选项牌(`tile按照上方牌代码`), 这里我们以一个最小化的示例进行演示:

```go
package main

import (
"github.com/moxcomic/Archer/actions"
"github.com/moxcomic/lq"
)

const (
E_PlayOperation_None = iota
E_PlayOperation_Discard // 弃牌
E_PlayOperation_Chi //
E_PlayOperation_Pon //
E_PlayOperation_Ankan // 暗杠
E_PlayOperation_Minkan // 明杠
E_PlayOperation_Kakan // 加杠
E_PlayOperation_RiiChi // 立直
E_PlayOperation_Tsumo // 自摸
E_PlayOperation_Ron //
E_PlayOperation_JiuZhongJiuPai // 九种九牌
E_PlayOperation_Babei // 拔北
E_PlayOperation_HuanSanZhang // 换三张
E_PlayOperation_DingQue // 定缺
E_PlayOperation_Reveal
E_PlayOperation_Unveil
E_PlayOperation_LockTile
E_PlayOperation_Revealliqi
)

func onExecute(result *lq.NotifyAIResult, risk []float64, r, m, f, t float64) {
if result.GetResult()[0].GetType() == E_PlayOperation_Chi {
if len(result.GetResult()[0].GetCombination()) != 2 {
fmt.Println("无法获取【吃】选项")
return
}

actions.NewMajsoulActions().Chii(result.GetResult()[0].GetCombination()[0], result.GetResult()[0].GetCombination()[1])
}
}
```

上方的例子我们以最简单的方式执行了出牌, 当AI有动作时就会调用`onExecute`方法, 而`result`里就存放着AI的推荐操作, 这是一个数组, 第`1`个代表AI的推荐操作, 所以这里我们使用了`result.GetResult()[0]`, 注意, 在程序里第`1`个是从`0`开始的;

## 注意

这里只是一个简单的示例代码, 并没有考虑什么要思考几秒、等待几秒的操作,如果你真按照这样写那么会得到一个秒出牌的程序,我们不推荐你这样做, 因为人类需要思考而不是牌还没看见就被吃走了。
110 changes: 110 additions & 0 deletions lesson/lesson_five/LESSON_FIVE_EN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
## Lesson 5: Chii (Eat)

`Archer` has encapsulated a series of table operation methods for you, which are located in the `github.com/moxcomic/Archer/actions` package (this package is built into Archer and is not publicly available, so it cannot be viewed on Github).

### Function Details

```go
package actions

import "sync"

type MajsoulActions struct{}

var (
inst *MajsoulActions
once = sync.OnceFunc(func() {
inst = &MajsoulActions{}
})
)

func NewMajsoulActions() *MajsoulActions {
once()
return inst
}

func (self *MajsoulActions) Join(roomID int, roomType int) {}
func (self *MajsoulActions) ReJoin() {}
func (self *MajsoulActions) CancelJoin() {}
func (self *MajsoulActions) Confirm() {}
func (self *MajsoulActions) BackToHome() {}
func (self *MajsoulActions) Huansanzhang() {}
func (self *MajsoulActions) Babei() {}
func (self *MajsoulActions) Discard(tile string, tsumogiri bool) {}
func (self *MajsoulActions) Riichi(tile string, tsumogiri bool) {}
func (self *MajsoulActions) Chii(tile0 string, tile1 string) {}
func (self *MajsoulActions) Pon(tile0 string, tile1 string) {}
func (self *MajsoulActions) Daimingkan(tile string) {}
func (self *MajsoulActions) Kakan(tile string) {}
func (self *MajsoulActions) Ankan(tile string) {}
func (self *MajsoulActions) Ryukyoku() {}
func (self *MajsoulActions) Tsumo() {}
func (self *MajsoulActions) Ron() {}
func (self *MajsoulActions) Cancel() {}
func (self *MajsoulActions) ComeBack() {}
```

### Tile Codes

`Archer` uses Tenhou tile codes for notation:

```
m: Man (characters)
p: Pin (dots)
s: Sou (bamboo)
z: Honor tiles (winds and dragons)
For example: 1m means one Man
East, South, West, North, White, Green, Red: 1234567 z
```

### Thought Process

From the above information, we know that if you want to perform a Chii (eat), you can call the `Chii(tile0 string, tile1 string)` method, where `tile0` and `tile1` are the tiles to be eaten (following the tile codes mentioned above). Here, we demonstrate with a minimal example:

```go
package main

import (
"fmt"
"github.com/moxcomic/Archer/actions"
"github.com/moxcomic/lq"
)

const (
E_PlayOperation_None = iota
E_PlayOperation_Discard // Discard
E_PlayOperation_Chi // Chii
E_PlayOperation_Pon // Pon
E_PlayOperation_Ankan // Ankan
E_PlayOperation_Minkan // Daiminkan
E_PlayOperation_Kakan // Kakan
E_PlayOperation_RiiChi // Riichi
E_PlayOperation_Tsumo // Tsumo
E_PlayOperation_Ron // Ron
E_PlayOperation_JiuZhongJiuPai // JiuZhongJiuPai
E_PlayOperation_Babei // Babei
E_PlayOperation_HuanSanZhang // Huansanzhang
E_PlayOperation_DingQue // Dingque
E_PlayOperation_Reveal
E_PlayOperation_Unveil
E_PlayOperation_LockTile
E_PlayOperation_Revealliqi
)

func onExecute(result *lq.NotifyAIResult, risk []float64, r, m, f, t float64) {
if result.GetResult()[0].GetType() == E_PlayOperation_Chi {
if len(result.GetResult()[0].GetCombination()) != 2 {
fmt.Println("Unable to get Chii options")
return
}

actions.NewMajsoulActions().Chii(result.GetResult()[0].GetCombination()[0], result.GetResult()[0].GetCombination()[1])
}
}
```

In the example above, we executed a Chii action in the simplest way. When the AI has an action, it will call the `onExecute` method, and `result` contains the AI's recommended operations. This is an array, and the first element represents the AI's recommended operation, so we use `result.GetResult()[0]`. Note that in the program, the first element starts from `0`.

### Note

This is just a simple example and does not consider operations that require a few seconds of thinking or waiting. If you write the program this way, you will get a program that discards tiles instantly. We do not recommend doing this because humans need to think, not have tiles eaten immediately upon seeing them.

0 comments on commit 297e312

Please sign in to comment.