ArcherArcher
Home
Quick Start
Project Introduction
  • 简体中文
  • English
Home
Quick Start
Project Introduction
  • 简体中文
  • English
  • Home
  • Basic Configuration

    • Project Introduction
    • Quick Start
    • FAQ
    • Contact Us
  • Advanced Development

    • Basic Knowledge
    • Basic Framework
    • Script Migration
    • Majsoul Development

      • Tile Names

        • Basic
      • Game Interfaces

        • Basic
      • LQ

        • Basic
      • Action Types

        • Basic
      • Game State

        • Basic
      • Login Event

        • Login Event
        • Advanced - Mahjong Event Login
      • Discard Actions

        • Basics
        • Advanced
      • Chii (Eat)
      • Pon
      • Kong
      • Cancel, Skip
  • Auto Review

    • Automatic Review
  • Tenhou Room

    • Playing in Tenhou Private Room with Mortal Bot
  • RiichiCity

    • Basic

Notes

  • To use this package, you need to enable 【Auto Settings】-> 【Built-in Mode】.
  • In Riichi City, declaring Riichi is not a standalone action; it is embedded in the discard (a discard with a Riichi declaration), so use the Riichi method.
  • Tile names use the same string representation as Majsoul: 1m-9m (man), 1p-9p (pin), 1s-9s (sou), 1z-7z (honors); red fives are 0m / 0p / 0s.

Package Name

  • actions

Import

  • import "github.com/moxcomic/Archer/internal/platform/actions"

Interface Methods

NameParametersReturn ValueNotes
NewRiichiCityActionsNone*actions.RiichiCityActionsRiichi City interface instance

Instance Methods

NameParametersReturn ValueNotes
Discardtile: string, tsumogiri: boolNoneDiscard a tile, tile is the tile name, tsumogiri indicates if it's the last drawn tile
Riichitile: string, tsumogiri: boolNoneDeclare Riichi (a discard with a Riichi declaration), tile is the discarded tile, tsumogiri as above
ChiicalledTile: string, consumed: []stringNoneChii, calledTile is the called tile, consumed are the two hand tiles forming the run
PoncalledTile: string, consumed: []stringNonePon, calledTile is the called tile, consumed are the two hand tiles used for Pon
DaimingkancalledTile: string, consumed: []stringNoneDaimingkan, calledTile is the called tile, consumed are the three hand tiles
Ankantile: stringNoneAnkan, tile is the tile name
Kakantile: stringNoneKakan, tile is the newly added tile name
TsumoNoneNoneTsumo (Self-draw win)
RonNoneNoneRon (Win by discard)
RyukyokuNoneNoneNine Terminal Tiles (abortive draw)
BabeiNoneNoneExecute Babei
CancelNoneNoneCancel or skip (do not call)

Full Example Script

  • Consistent with Majsoul/Tenhou: in the onExecute callback you receive the AI's recommended result and dispatch by action type to the corresponding RiichiCityActions method.
  • For lq.NotifyAIResult, see NotifyAIResult
  • For GetType, see Action Types
package main

import (
	"fmt"
	"math/rand"
	"time"

	"github.com/moxcomic/Archer/internal/platform/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         // Daimingkan
	E_PlayOperation_Kakan          // Kakan
	E_PlayOperation_RiiChi         // Riichi
	E_PlayOperation_Tsumo          // Tsumo
	E_PlayOperation_Ron            // Ron
	E_PlayOperation_JiuZhongJiuPai // Nine Terminal Tiles
	E_PlayOperation_Babei          // Babei
)

func onExecute(result *lq.NotifyAIResult, risk []float64, r, m, f, t float64) {
	if len(result.GetResult()) == 0 {
		return
	}

	onExecuteTarget(result.GetResult()[0], result.GetShanten())
}

func onExecuteTarget(target *lq.AIResult, shanten uint32) {
	action := actions.NewRiichiCityActions()

	// Human-like delay: discard (your own turn, plenty of time) is longer; calls/wins
	// (the server has a response time limit) are shorter to avoid missing the window.
	delay := 250 + rand.Intn(350)
	switch target.GetType() {
	case E_PlayOperation_Discard, E_PlayOperation_RiiChi:
		delay = 700 + rand.Intn(900)
	}
	time.Sleep(time.Millisecond * time.Duration(delay))

	switch target.GetType() {
	case E_PlayOperation_Discard:
		action.Discard(target.GetTile(), target.GetMoqie())
	case E_PlayOperation_RiiChi:
		action.Riichi(target.GetTile(), target.GetMoqie())
	case E_PlayOperation_Chi:
		action.Chii(target.GetTile(), target.GetCombination())
	case E_PlayOperation_Pon:
		action.Pon(target.GetTile(), target.GetCombination())
	case E_PlayOperation_Minkan:
		action.Daimingkan(target.GetTile(), target.GetCombination())
	case E_PlayOperation_Ankan:
		if len(target.GetCombination()) > 0 {
			action.Ankan(target.GetCombination()[0])
		}
	case E_PlayOperation_Kakan:
		action.Kakan(target.GetTile())
	case E_PlayOperation_Tsumo:
		action.Tsumo()
	case E_PlayOperation_Ron:
		action.Ron()
	case E_PlayOperation_JiuZhongJiuPai:
		action.Ryukyoku()
	case E_PlayOperation_Babei:
		action.Babei()
	case E_PlayOperation_None, 321:
		action.Cancel()
	default:
		fmt.Println("RiichiCity: unhandled action type:", target.GetType())
	}
}

Example Code

actions.NewRiichiCityActions().Discard("1m", true)