util

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 6, 2022 License: MIT Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const (
	RonPointRiichiHiIppatsu = 5172.0 // 基准
	RonPointRiichiIppatsu   = 7445.0
	//RonPointHonitsu         = 6603.0
	//RonPointToitoi          = 7300.0
	RonPointOtherNaki = 3000.0 // *fixed
	// TODO: 考虑双东的影响
	RonPointDama = 4536.0
)

子家荣和点数均值 参考:「統計学」のマージャン戦術 亲家按 x1.5 算 TODO: 剩余 dora 数对失点的影响

View Source
const (
	WallSafeTypeDoubleNoChance = iota // 只输单骑对碰
	WallSafeTypeNoChance              // 单骑对碰边张坎张
	WallSafeTypeDoubleOneChance
	WallSafeTypeMixedOneChance // 对于456来说,一半 double,一半不是 double
	WallSafeTypeOneChance
)
View Source
const (
	// https://en.wikipedia.org/wiki/Japanese_Mahjong_yaku
	// Special criteria
	YakuRiichi int = iota
	YakuChiitoi

	// Yaku based on luck
	YakuTsumo
	//YakuIppatsu
	//YakuHaitei
	//YakuHoutei
	//YakuRinshan
	//YakuChankan
	YakuDaburii

	// Yaku based on sequences
	YakuPinfu
	YakuRyanpeikou
	YakuIipeikou
	YakuSanshokuDoujun // *
	YakuIttsuu         // *

	// Yaku based on triplets and/or quads
	YakuToitoi
	YakuSanAnkou
	YakuSanshokuDoukou
	YakuSanKantsu

	// Yaku based on terminal or honor tiles
	YakuTanyao
	YakuYakuhai
	YakuChanta    // * 必须有顺子
	YakuJunchan   // * 必须有顺子
	YakuHonroutou // 七对也算
	YakuShousangen

	// Yaku based on suits
	YakuHonitsu  // *
	YakuChinitsu // *

	// Yakuman
	//YakuKokushi
	//YakuKokushi13
	YakuSuuAnkou
	YakuSuuAnkouTanki
	YakuDaisangen
	YakuShousuushii
	YakuDaisuushii
	YakuTsuuiisou
	YakuChinroutou
	YakuRyuuiisou
	YakuChuuren
	YakuChuuren9
	YakuSuuKantsu

	// 古役
	YakuShiiaruraotai
	YakuUumensai
	YakuSanrenkou
	YakuIsshokusanjun

	// 古役役满
	YakuDaisuurin
	YakuDaisharin
	YakuDaichikurin
	YakuDaichisei
)

Variables

View Source
var (
	// TileTypeTable [需要判断危险度的牌号(0-8)][是否有对应的现物(0-1或0-3)]
	// 123789: 无现物,有现物
	// 4: 无17现物,无1有7,有1无7,有17
	// 56: 同上
	TileTypeTable = [][]tileType{
		{tileTypeNoSuji19, tileTypeSuji19},
		{tileTypeNoSuji28, tileTypeSuji28},
		{tileTypeNoSuji37, tileTypeSuji37},
		{tileTypeNoSuji46, tileTypeHalfSuji46B, tileTypeHalfSuji46A, tileTypeDoubleSuji46},
		{tileTypeNoSuji5, tileTypeHalfSuji5, tileTypeHalfSuji5, tileTypeDoubleSuji5},
		{tileTypeNoSuji46, tileTypeHalfSuji46A, tileTypeHalfSuji46B, tileTypeDoubleSuji46},
		{tileTypeNoSuji37, tileTypeSuji37},
		{tileTypeNoSuji28, tileTypeSuji28},
		{tileTypeNoSuji19, tileTypeSuji19},
	}
	// [是否为役牌(0-1)][剩余数-1]
	HonorTileType = [][]tileType{
		{tileTypeOtakazeLeft1, tileTypeOtakazeLeft2, tileTypeOtakazeLeft3, tileTypeOtakazeLeft3},
		{tileTypeYakuHaiLeft1, tileTypeYakuHaiLeft2, tileTypeYakuHaiLeft3, tileTypeYakuHaiLeft3},
	}
)
View Source
var FixedDoraRiskRateMulti = []float64{
	14.9 / 12.8 * 78 / 58,
	15.0 / 13.1 * 78 / 58,
	12.1 / 9.5 * 75 / 56,
	10.3 / 8.6 * 75 / 54,
	8.9 / 7.4 * 77 / 53,

	9.7 / 7.4 * 81 / 60,
	8.9 / 7.2 * 81 / 60,
	10.4 / 7.9 * 81 / 60,
	8.0 / 5.5 * 75 / 56,
	5.5 / 3.9 * 81 / 56,
	3.5 / 1.8 * 92 / 58,
	4.1 / 2.2 * 88 / 62,
	4.1 / 2.3 * 88 / 62,

	5.2 / 4.6 * 96 / 67,
	2.9 / 1.9 * 96 / 67,
	1.1 / 0.3 * 96 / 67,
	5.1 / 4.0 * 92 / 56,
	3.0 / 1.8 * 92 / 56,
	0.8 / 0.2 * 92 / 56,
}

考虑失点的综合值(参考第9巡的数据)

View Source
var Mahjong = [...]string{
	"1m", "2m", "3m", "4m", "5m", "6m", "7m", "8m", "9m",
	"1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p",
	"1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s",
	"1z", "2z", "3z", "4z", "5z", "6z", "7z",
}
View Source
var MahjongU = [...]string{
	"1M", "2M", "3M", "4M", "5M", "6M", "7M", "8M", "9M",
	"1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p",
	"1S", "2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S",
	"1Z", "2Z", "3Z", "4Z", "5Z", "6Z", "7Z",
}
View Source
var MahjongZH = [...]string{
	"1万", "2万", "3万", "4万", "5万", "6万", "7万", "8万", "9万",
	"1饼", "2饼", "3饼", "4饼", "5饼", "6饼", "7饼", "8饼", "9饼",
	"1索", "2索", "3索", "4索", "5索", "6索", "7索", "8索", "9索",
	"东", "南", "西", "北", "白", "发", "中",
}
View Source
var MaxTurns = len(RiskRate) - 1
View Source
var OldNakiYakuHanMap = _yakuHanMap{
	YakuShiiaruraotai: 1,
	YakuUumensai:      2,
	YakuSanrenkou:     2,
	YakuIsshokusanjun: 2,
}
View Source
var OldYakuHanMap = _yakuHanMap{
	YakuUumensai:      2,
	YakuSanrenkou:     2,
	YakuIsshokusanjun: 3,
}
View Source
var OldYakuNameMap = map[int]string{
	YakuShiiaruraotai: "十二落抬",
	YakuUumensai:      "五门齐",
	YakuSanrenkou:     "三连刻",
	YakuIsshokusanjun: "一色三顺",

	YakuDaisuurin:   "大数邻",
	YakuDaisharin:   "大车轮",
	YakuDaichikurin: "大竹林",
	YakuDaichisei:   "大七星",
}
View Source
var OldYakumanTimesMap = map[int]int{
	YakuDaisuurin:   1,
	YakuDaisharin:   1,
	YakuDaichikurin: 1,
	YakuDaichisei:   1,
}
View Source
var RiskRate = [][]float64{
	{},
	{5.7, 5.7, 5.8, 4.7, 3.4, 2.5, 2.5, 3.1, 5.6, 3.8, 1.8, 0.8, 2.6, 2.1, 1.2, 0.5, 2.4, 1.4, 1.2},
	{6.6, 6.9, 6.3, 5.2, 4.0, 3.5, 3.5, 4.1, 5.3, 3.5, 1.9, 0.8, 2.6, 2.3, 1.2, 0.5, 2.7, 1.3, 0.4},
	{7.7, 8.0, 6.7, 5.8, 4.6, 4.3, 4.1, 4.9, 5.2, 3.6, 1.8, 1.6, 2.0, 2.4, 1.2, 0.3, 2.6, 1.2, 0.3},
	{8.5, 8.9, 7.1, 6.2, 5.1, 4.8, 4.7, 5.6, 5.2, 3.8, 1.7, 1.6, 2.0, 2.6, 1.1, 0.2, 2.6, 1.2, 0.2},
	{9.4, 9.7, 7.5, 6.7, 5.5, 5.3, 5.1, 6.0, 5.3, 3.7, 1.7, 1.7, 2.0, 2.9, 1.2, 0.2, 2.8, 1.2, 0.2},
	{10.2, 10.5, 7.9, 7.1, 5.9, 5.8, 5.6, 6.4, 5.2, 3.7, 1.7, 1.8, 2.0, 3.2, 1.3, 0.2, 2.9, 1.3, 0.2},
	{11.0, 11.3, 8.4, 7.5, 6.3, 6.3, 6.1, 6.8, 5.3, 3.7, 1.7, 2.0, 2.1, 3.6, 1.4, 0.2, 3.2, 1.4, 0.2},
	{11.9, 12.2, 8.9, 8.0, 6.8, 6.9, 6.6, 7.4, 5.3, 3.8, 1.7, 2.1, 2.2, 4.0, 1.6, 0.2, 3.5, 1.6, 0.2},
	{12.8, 13.1, 9.5, 8.6, 7.4, 7.4, 7.2, 7.9, 5.5, 3.9, 1.8, 2.2, 2.3, 4.6, 1.9, 0.3, 4.0, 1.8, 0.2},
	{13.8, 14.1, 10.1, 9.2, 8.0, 8.0, 7.8, 8.5, 5.6, 4.0, 1.9, 2.4, 2.4, 5.3, 2.2, 0.3, 4.6, 2.1, 0.3},
	{14.9, 15.1, 10.8, 9.9, 8.7, 8.7, 8.5, 9.2, 5.7, 4.2, 2.0, 2.5, 2.6, 6.0, 2.6, 0.4, 5.1, 2.5, 0.3},
	{16.0, 16.3, 11.6, 10.6, 9.4, 9.4, 9.2, 9.9, 6.0, 4.4, 2.2, 2.7, 2.7, 6.8, 3.1, 0.4, 5.1, 2.5, 0.3},
	{17.2, 17.5, 12.4, 11.4, 10.2, 10.2, 10.0, 10.6, 6.2, 4.6, 2.4, 3.0, 3.0, 7.8, 3.7, 0.5, 6.6, 3.7, 0.5},
	{18.5, 18.8, 13.3, 12.3, 11.1, 11.0, 10.9, 11.4, 6.6, 4.9, 2.7, 3.2, 3.1, 8.8, 4.4, 0.7, 7.4, 4.4, 0.6},
	{19.9, 20.1, 14.3, 13.3, 12.0, 11.9, 11.8, 12.3, 7.0, 5.3, 3.0, 3.4, 3.4, 9.9, 5.2, 0.8, 8.4, 5.3, 0.8},
	{21.3, 21.7, 15.4, 14.3, 13.1, 12.9, 12.8, 13.3, 7.4, 5.7, 3.3, 3.7, 3.6, 11.2, 6.2, 1.0, 9.4, 6.5, 0.9},
	{22.9, 23.2, 16.6, 15.4, 14.2, 14.0, 13.8, 14.4, 8.0, 6.1, 3.6, 3.9, 3.9, 12.4, 7.3, 1.3, 10.5, 7.7, 1.2},
	{24.7, 24.9, 17.9, 16.7, 15.4, 15.2, 15.0, 15.6, 8.5, 6.6, 4.0, 4.3, 4.2, 13.9, 8.5, 1.7, 11.8, 9.4, 1.6},
	{27.5, 27.8, 20.4, 19.1, 17.8, 17.5, 17.5, 17.5, 9.8, 7.4, 5.0, 5.1, 5.1, 18.1, 12.1, 2.8, 14.7, 12.6, 2.1},
}

[巡目][类型]

View Source
var YakuNameMap = map[int]string{

	YakuRiichi:  "立直",
	YakuChiitoi: "七对",

	YakuTsumo: "自摸",

	YakuDaburii: "w立",

	YakuPinfu:          "平和",
	YakuRyanpeikou:     "两杯口",
	YakuIipeikou:       "一杯口",
	YakuSanshokuDoujun: "三色",
	YakuIttsuu:         "一通",

	YakuToitoi:         "对对",
	YakuSanAnkou:       "三暗刻",
	YakuSanshokuDoukou: "三色同刻",
	YakuSanKantsu:      "三杠子",

	YakuTanyao:     "断幺",
	YakuYakuhai:    "役牌",
	YakuChanta:     "混全",
	YakuJunchan:    "纯全",
	YakuHonroutou:  "混老头",
	YakuShousangen: "小三元",

	YakuHonitsu:  "混一色",
	YakuChinitsu: "清一色",

	YakuSuuAnkou:      "四暗刻",
	YakuSuuAnkouTanki: "四暗刻单骑",
	YakuDaisangen:     "大三元",
	YakuShousuushii:   "小四喜",
	YakuDaisuushii:    "大四喜",
	YakuTsuuiisou:     "字一色",
	YakuChinroutou:    "清老头",
	YakuRyuuiisou:     "绿一色",
	YakuChuuren:       "九莲",
	YakuChuuren9:      "纯正九莲",
	YakuSuuKantsu:     "四杠子",
}
View Source
var YaochuTiles = [...]int{0, 8, 9, 17, 18, 26, 27, 28, 29, 30, 31, 32, 33}

Functions

func BrightYarrowPrint

func BrightYarrowPrint(text string)

func BrightYarrowPrintf

func BrightYarrowPrintf(format string, texts ...interface{})

func ByteAtStr

func ByteAtStr(b byte, s string) int

func CalcPointRon

func CalcPointRon(han int, fu int, yakumanTimes int, isParent bool) (point int)

番数 符数 役满倍数 是否为亲家 返回荣和点数

func CalcPointTsumo

func CalcPointTsumo(han int, fu int, yakumanTimes int, isParent bool) (childPoint int, parentPoint int)

番数 符数 役满倍数 是否为亲家 返回自摸时的子家支付点数和亲家支付点数

func CalcPointTsumoSum

func CalcPointTsumoSum(han int, fu int, yakumanTimes int, isParent bool) int

番数 符数 役满倍数 是否为亲家 返回自摸时的点数

func CalcTenpaiRate

func CalcTenpaiRate(melds []*model.Meld, discardTiles []int, meldDiscardsAt []int) float64

没有立直时,根据玩家的副露、手切来判断其听牌率 (0-100) TODO: 传入 *model.PlayerInfo

func CalcYakuHan

func CalcYakuHan(yakuTypes []int, isNaki bool) (cntHan int)

计算 yakuTypes(非役满) 累积的番数

func CalcYakumanTimes

func CalcYakumanTimes(yakuTypes []int, isNaki bool) (times int)

计算役满倍数

func CalculateAgariRateOfEachTile

func CalculateAgariRateOfEachTile(waits Waits, playerInfo *model.PlayerInfo) map[int]float64

计算各张待牌的和率 剩余为 0 则和率为 0

func CalculateAvgAgariRate

func CalculateAvgAgariRate(waits Waits, playerInfo *model.PlayerInfo) float64

计算平均和率

func CalculateLeftNoSujiTiles

func CalculateLeftNoSujiTiles(safeTiles34 []bool, leftTiles34 []int) (leftNoSujiTiles []int)

计算剩余的无筋 123789 牌 总计 18 种。剩余无筋牌数量越少,该无筋牌越危险

func CalculateMeld

func CalculateMeld(playerInfo *model.PlayerInfo, calledTile int, isRedFive bool, allowChi bool) (minShanten int, results Hand14AnalysisResultList, incShantenResults Hand14AnalysisResultList)

计算鸣牌下的何切分析 calledTile 他家出的牌,尝试鸣这张牌 isRedFive 这张牌是否为赤5 allowChi 是否允许吃这张牌

func CalculateShanten

func CalculateShanten(tiles34 []int) int

根据手牌计算向听数(不考虑国士) 3k+1 和 3k+2 张牌都行

func CalculateShantenOfChiitoi

func CalculateShantenOfChiitoi(tiles34 []int) int

参考 http://ara.moo.jp/mjhmr/shanten.htm 七对子向听数 = 6-对子数+max(0,7-种类数)

func CalculateShantenOfNormal

func CalculateShantenOfNormal(tiles34 []int, countOfTiles int) int

根据手牌计算一般型(不考虑七对国士)的向听数 3k+1 和 3k+2 张牌都行

func CalculateShantenWithImproves14

func CalculateShantenWithImproves14(playerInfo *model.PlayerInfo) (shanten int, results Hand14AnalysisResultList, incShantenResults Hand14AnalysisResultList)

CalculateShantenWithImproves14 3k+2 张牌,计算向听数、进张、改良、向听倒退等

func CatPrint

func CatPrint()

func ChiCongPrint

func ChiCongPrint(text string)

func ChiCongPrintf

func ChiCongPrintf(format string, texts ...interface{})

func CityLightPrint

func CityLightPrint(text string)

func CityLightPrintf

func CityLightPrintf(format string, texts ...interface{})

func CountOfTiles34

func CountOfTiles34(tiles34 []int) (count int)

计算手牌枚数

func CountPairsOfTiles34

func CountPairsOfTiles34(tiles34 []int) (count int)

计算手牌对子数

func EggBluePrint

func EggBluePrint(text string)

func EggBluePrintf

func EggBluePrintf(format string, texts ...interface{})

func Equal

func Equal(a, b float64) bool

func GetTenpaiRate3

func GetTenpaiRate3(rate4 float64) (rate3 float64)

用四麻的数据近似得到三麻的数据 更加精确的数据见 https://shikkaku.com/data_sanma_20

func GradualChangePrint

func GradualChangePrint(text string)

func InDelta

func InDelta(a, b, delta float64) bool

func InInts

func InInts(e int, arr []int) bool

func InStrings

func InStrings(e string, arr []string) bool

func InitLeftTiles34

func InitLeftTiles34() []int

func InitLeftTiles34WithTiles34

func InitLeftTiles34WithTiles34(tiles34 []int) []int

根据传入的牌,返回移除这些牌后剩余的牌

func IsAgari

func IsAgari(tiles34 []int) bool

3k+2 张牌,是否和牌(不检测国士无双)

func LightGreenishBluePrint

func LightGreenishBluePrint(text string)

func LightGreenishBluePrintf

func LightGreenishBluePrintf(format string, texts ...interface{})

func Lower

func Lower(c byte) byte

func MaxInt

func MaxInt(a, b int) int

func MinInt

func MinInt(a, b int) int

func MintLeafPrint

func MintLeafPrint(text string)

func MintLeafPrintf

func MintLeafPrintf(format string, texts ...interface{})

func MustParseHumanTilesWithMelds

func MustParseHumanTilesWithMelds(humanTilesWithMelds string) *model.PlayerInfo

func MustStrToTile34

func MustStrToTile34(humanTile string) int

调试用

func MustStrToTiles

func MustStrToTiles(humanTiles string) []int

调试用

func MustStrToTiles34

func MustStrToTiles34(humanTiles string) []int

调试用

func NumberToChineseShanten

func NumberToChineseShanten(num int) string

-1=和了,0=和牌,1=一向听,……

func OrangevillePrint

func OrangevillePrint(text string)

func OrangevillePrintf

func OrangevillePrintf(format string, texts ...interface{})

func OutsideTiles

func OutsideTiles(tile int) (outsideTiles []int)

计算外侧牌

func ParseHumanTilesWithMelds

func ParseHumanTilesWithMelds(humanTilesWithMelds string) (playerInfo *model.PlayerInfo, err error)

func RandomAddTile

func RandomAddTile(tiles34 []int)

随机补充一张牌

func RonPointOtherNakiWithDora

func RonPointOtherNakiWithDora(doraCount int) (point float64)

简单地判断子家副露者的打点 dora point han 0 3000 1-3 1 4200 2-4 2 5880 3-5 3 8232 4-6 4 10000 5-7 5 13000 6-8 亲家按 x1.5 算 TODO: 暗杠对打点的提升?

func SetConsiderOldYaku

func SetConsiderOldYaku(b bool)

func ShantenTrueColorChinese

func ShantenTrueColorChinese(num int)

func SourLemonPrint

func SourLemonPrint(text string)

func SourLemonPrintf

func SourLemonPrintf(format string, texts ...interface{})

func StrToTile34

func StrToTile34(humanTile string) (tile34 int, isRedFive bool, err error)

e.g. "3m" => 2 可以接收赤5,如 0p

func StrToTiles

func StrToTiles(humanTiles string) (tiles []int, numRedFives []int, err error)

e.g. "11122z" => [27, 27, 27, 28, 28]

func StrToTiles34

func StrToTiles34(humanTiles string) (tiles34 []int, numRedFives []int, err error)

e.g. "224m 24p" => [0, 2, 0, 1, 0, ..., 1, 0, 1, ...] 也可以传入不含空格的手牌,如 "224m24p" 可以接收赤5,如 0p

func Tile34ToStr

func Tile34ToStr(tile34 int) string

func Tiles34ToStr

func Tiles34ToStr(tiles34 []int) (humanTiles string)

func Tiles34ToStrWithBracket

func Tiles34ToStrWithBracket(tiles34 []int) string

func Tiles34ToTiles

func Tiles34ToTiles(tiles34 []int) (tiles []int)

func TilesToMahjongZH

func TilesToMahjongZH(tiles []int) (words []string)

func TilesToMahjongZHInterface

func TilesToMahjongZHInterface(tiles []int) (words []interface{})

func TilesToStr

func TilesToStr(tiles []int) (humanTiles string)

e.g. [9, 11, 27] => "13p 1z"

func TilesToStrWithBracket

func TilesToStrWithBracket(tiles []int) string

e.g. [9, 11, 27] => "[13p 1z]"

func TilesToTiles34

func TilesToTiles34(tiles []int) (tiles34 []int)

func Upper

func Upper(c byte) byte

func YakuTypesToStr

func YakuTypesToStr(yakuTypes []int) string

func YakuTypesWithDoraToStr

func YakuTypesWithDoraToStr(yakuTypes map[int]struct{}, numDora int) string

Types

type DivideResult

type DivideResult struct {
	PairTile          int   // 雀头牌
	KotsuTiles        []int // 刻子牌(注意 len(KotsuTiles) 为自摸时的暗刻数,荣和时的暗刻数需要另加逻辑判断)
	ShuntsuFirstTiles []int // 顺子牌的第一张(如 678s 的 6s)

	// 由于生成 winTable 的代码是不考虑具体是什么牌的,
	// 所以只能判断如七对子、九莲宝灯、一气通贯、两杯口、一杯口等和「形状」有关的役,
	// 像国士无双、断幺、全带、三色、绿一色等,和具体的牌/位置有关的役是判断不出的,需要另加逻辑判断
	IsChiitoi       bool // 七对子
	IsChuurenPoutou bool // 九莲宝灯
	IsIttsuu        bool // 一气通贯(注意:未考虑副露!)
	IsRyanpeikou    bool // 两杯口(IsRyanpeikou == true 时 IsIipeikou == false)
	IsIipeikou      bool // 一杯口
}

3k+2 张牌的某种拆解结果

func DivideTiles34

func DivideTiles34(tiles34 []int) (divideResults []*DivideResult)

3k+2 张牌,返回所有可能的拆解,没有拆解表示未和牌(不检测国士无双) http://hp.vector.co.jp/authors/VA046927/mjscore/mjalgorism.html http://hp.vector.co.jp/authors/VA046927/mjscore/AgariIndex.java

func (*DivideResult) String

func (d *DivideResult) String() string

调试用

type Hand13AnalysisResult

type Hand13AnalysisResult struct {
	// 原手牌
	Tiles34 []int

	// 剩余牌
	LeftTiles34 []int

	// 是否已鸣牌(非门清状态)
	// 用于判断是否无役等
	IsNaki bool

	// 向听数
	Shanten int

	// 进张
	// 考虑了剩余枚数
	// 若某个进张牌 4 枚都可见,则该进张的 value 值为 0
	Waits Waits

	// 默听时的进张
	DamaWaits Waits

	// map[进张牌]向听前进后的(最大)进张数
	NextShantenWaitsCountMap map[int]int

	// 向听前进后的(最大)进张数的加权均值
	AvgNextShantenWaitsCount float64

	// 综合了进张与向听前进后进张的评分
	MixedWaitsScore float64

	// 改良:摸到这张牌虽不能让向听数前进,但可以让进张变多
	// len(Improves) 即为改良的牌的种数
	Improves Improves

	// 改良情况数,这里计算的是有多少种使进张增加的摸牌-切牌方式
	ImproveWayCount int

	// 摸到非进张牌时的进张数的加权均值(非改良+改良。对于非改良牌,其进张数为 Waits.AllCount())
	// 这里只考虑一巡的改良均值
	// TODO: 在考虑改良的情况下,如何计算向听前进所需要的摸牌次数的期望值?蒙特卡罗方法?
	AvgImproveWaitsCount float64

	// 听牌时的手牌和率
	// TODO: 未听牌时的和率?
	AvgAgariRate float64

	// 振听可能率(一向听和听牌时)
	FuritenRate float64

	// 役种
	YakuTypes map[int]struct{}

	// (鸣牌时)是否片听
	IsPartWait bool

	// 宝牌个数(手牌+副露)
	DoraCount int

	// 非立直状态下的打点期望(副露或默听)
	DamaPoint float64

	// 立直状态下的打点期望
	RiichiPoint float64

	// 局收支
	MixedRoundPoint float64
}

3k+1 张手牌的分析结果

func CalculateShantenWithImproves13

func CalculateShantenWithImproves13(playerInfo *model.PlayerInfo) (r *Hand13AnalysisResult)

CalculateShantenWithImproves13 3k+1 张牌,计算向听数、进张、改良等(考虑了剩余枚数)

func (*Hand13AnalysisResult) String

func (r *Hand13AnalysisResult) String() string

调试用

type Hand14AnalysisResult

type Hand14AnalysisResult struct {
	// 需要切的牌
	DiscardTile int

	// 切的是否为宝牌
	IsDiscardDoraTile bool

	// 切的牌的价值(宝牌或宝牌周边)
	DiscardTileValue tileValue

	// 切牌后的手牌分析结果
	Result13 *Hand13AnalysisResult

	DiscardHonorTileRisk int

	// 剩余可以摸的牌数
	LeftDrawTilesCount int

	// 副露信息(没有副露就是 nil)
	// 比如用 23m 吃了牌,OpenTiles 就是 [1,2]
	OpenTiles []int
	// contains filtered or unexported fields
}

func (*Hand14AnalysisResult) String

func (r *Hand14AnalysisResult) String() string

type Hand14AnalysisResultList

type Hand14AnalysisResultList []*Hand14AnalysisResult

func (Hand14AnalysisResultList) Sort

func (l Hand14AnalysisResultList) Sort(improveFirst bool)

按照特定规则排序 若 improveFirst 为 true,则优先按照 AvgImproveWaitsCount 排序(对于三向听及以上来说)

type Improves

type Improves map[int]Waits

map[改良牌]进张(选择进张数最大的)

type PointResult

type PointResult struct {
	Point      int
	FixedPoint float64 // 和牌时的期望点数
	// contains filtered or unexported fields
}

func CalcAvgPoint

func CalcAvgPoint(playerInfo model.PlayerInfo, waits Waits) (avgPoint float64, pointResults []*PointResult)

已听牌,根据 playerInfo 提供的信息计算加权和率后的平均点数 无役时返回 0 有役时返回平均点数(立直时考虑自摸、一发和里宝)和各种侍牌下的对应点数

func CalcAvgRiichiPoint

func CalcAvgRiichiPoint(playerInfo model.PlayerInfo, waits Waits) (avgRiichiPoint float64, pointResults []*PointResult)

计算立直时的平均点数(考虑自摸、一发和里宝)和各种侍牌下的对应点数 已鸣牌时返回 0 TODO: 剩余不到 4 张无法立直 TODO: 不足 1000 点无法立直

func CalcPoint

func CalcPoint(playerInfo *model.PlayerInfo) (result *PointResult)

已和牌,计算自摸或荣和时的点数(不考虑里宝、一发等情况) 无役时返回的点数为 0(和率也为 0) 调用前请设置 IsTsumo WinTile

type RiskTiles34

type RiskTiles34 []float64

func CalculateRiskTiles34

func CalculateRiskTiles34(turns int, safeTiles34 []bool, leftTiles34 []int, doraTiles []int, roundWindTile int, playerWindTile int) (risk34 RiskTiles34)

根据巡目(对于对手而言)、现物、立直后通过的牌、NC、Dora,来计算基础铳率 至于早外、OC 和读牌交给后续的计算 turns: 巡目,这里是对于对手而言的,也就是该玩家舍牌的次数 safeTiles34: 现物及立直后通过的牌 leftTiles34: 各个牌在山中剩余的枚数 roundWindTile: 场风 playerWindTile: 自风

func (RiskTiles34) FixWithEarlyOutside

func (l RiskTiles34) FixWithEarlyOutside(discardTiles []int) RiskTiles34

对 5 巡前的外侧牌的危险度进行调整 粗略调整为 *0.4(参考:科学する麻雀)

func (RiskTiles34) FixWithGlobalMulti

func (l RiskTiles34) FixWithGlobalMulti(multi float64) RiskTiles34

func (RiskTiles34) FixWithPoint

func (l RiskTiles34) FixWithPoint(ronPoint float64) RiskTiles34

根据副露情况对危险度进行修正

type Waits

type Waits map[int]int

进张 map[进张牌]剩余数

func CalculateShantenAndWaits13

func CalculateShantenAndWaits13(tiles34 []int, leftTiles34 []int) (shanten int, waits Waits)

3k+1 张牌,计算向听数、进张(考虑了剩余枚数),不计算改良

func (Waits) AllCount

func (w Waits) AllCount() (count int)

func (Waits) AvailableTiles

func (w Waits) AvailableTiles() []int

剩余数不为零的进张

func (Waits) Equals

func (w Waits) Equals(w1 Waits) bool

func (Waits) ParseIndex

func (w Waits) ParseIndex() (allCount int, indexes []int)

func (Waits) String

func (w Waits) String() string

type WallSafeTile

type WallSafeTile struct {
	Tile34   int
	SafeType int
}

type WallSafeTileList

type WallSafeTileList []WallSafeTile

func CalcDNCSafeTiles

func CalcDNCSafeTiles(leftTiles34 []int) (dncSafeTiles WallSafeTileList)

根据剩余牌 leftTiles34 中的某些牌是否为 0(壁),来判断哪些牌较为安全(Double No Chance:只输单骑、双碰)

func CalcDNCSafeTilesWithDiscards

func CalcDNCSafeTilesWithDiscards(leftTiles34 []int, safeTiles34 []bool) (dncSafeTiles WallSafeTileList)

根据剩余牌 leftTiles34 中的某些牌是否为 0(壁),来判断哪些牌较为安全(Double No Chance:只输单骑、双碰) 这里加上现物,相比 CalcDNCSafeTiles 可以得到更加精确的结果 注:虽然说在 4 为现物的情况下,1 也可以认为是只输单骑、双碰的,但这不在壁的讨论范围内,故不考虑这种情况

func CalcNCSafeTiles

func CalcNCSafeTiles(leftTiles34 []int) (ncSafeTiles WallSafeTileList)

根据剩余牌 leftTiles34 中的某些牌是否为 0(壁),来判断哪些牌较为安全(No Chance:不输两面)

func CalcOCSafeTiles

func CalcOCSafeTiles(leftTiles34 []int) (ocSafeTiles WallSafeTileList)

根据剩余牌 leftTiles34 中的某些牌是否为 1(薄壁),来判断哪些牌较为安全(One Chance:早巡大概率不输两面)

func CalcWallTiles

func CalcWallTiles(leftTiles34 []int) (safeTiles WallSafeTileList)

func (WallSafeTileList) FilterWithHands

func (l WallSafeTileList) FilterWithHands(handsTiles34 []int) WallSafeTileList

func (WallSafeTileList) String

func (l WallSafeTileList) String() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL