Skip to content

UnoActions ​

UNO 插件自定义的 Action 类型与工厂函数。

概述 ​

UNO 插件在引擎通用 Action(PLAY_CARD / DRAW_CARD / END_TURN / PASS)之外,新增两个专属 Action:

Action 类型常量用途
CHOOSE_COLORCHOOSE_COLOR_ACTION玩家为刚打出的 Wild 牌指定颜色
UNO_FLIP_INITIALUNO_FLIP_INITIAL_ACTION游戏开始时翻出初始弃牌

UNO 还复用引擎内置的 PLAY_CARD_ACTION / DRAW_CARD_ACTION / END_TURN_ACTION,由 UnoPlugin 注册对应的 ActionHandler。

常量 ​

名称类型值
CHOOSE_COLOR_ACTION'CHOOSE_COLOR' (as const)玩家选色 Action 类型
UNO_FLIP_INITIAL_ACTION'UNO_FLIP_INITIAL' (as const)翻初始弃牌 Action 类型

类型 ​

ChooseColorPayload ​

ts
interface ChooseColorPayload {
  color: UnoColorChoice
}

CHOOSE_COLOR 的负载:玩家选择的颜色(必须是实色 red / yellow / green / blue,不能是 'wild')。

ChooseColorAction ​

ts
type ChooseColorAction = Action<typeof CHOOSE_COLOR_ACTION, ChooseColorPayload>

UnoFlipInitialAction ​

ts
type UnoFlipInitialAction = Action<typeof UNO_FLIP_INITIAL_ACTION, Record<string, never>>

无负载、无发起玩家的系统动作。

工厂函数 ​

createChooseColorAction() ​

ts
function createChooseColorAction(
  playerId: string,
  color: UnoColorChoice
): ChooseColorAction

创建 CHOOSE_COLOR Action。

参数 ​

名称类型说明
playerIdstring指定颜色的玩家 ID(即刚打出 Wild 牌的玩家)
colorUnoColorChoice玩家选择的目标颜色

返回值 ​

ChooseColorAction

示例 ​

ts
import { createChooseColorAction } from 'decklet/uno'

const action = createChooseColorAction('p1', 'red')
// { type: 'CHOOSE_COLOR', playerId: 'p1', payload: { color: 'red' } }

createUnoFlipInitialAction() ​

ts
function createUnoFlipInitialAction(): UnoFlipInitialAction

创建 UNO_FLIP_INITIAL Action。

参数 ​

无。

返回值 ​

UnoFlipInitialAction:无 playerId、无有效 payload 的系统动作。

行为 ​

由 handleGameStarted 在发完初始手牌后派发,从牌堆顶翻牌直到出现数字牌,该数字牌作为初始弃牌并决定起始颜色;非数字牌通过"移到弃牌堆再移回牌堆底部"的往返轮转至牌堆底,避免功能牌 / Wild 牌成为起始弃牌。

示例 ​

ts
import { createUnoFlipInitialAction } from 'decklet/uno'

const action = createUnoFlipInitialAction()
// { type: 'UNO_FLIP_INITIAL', payload: {} }

UNO 复用的基础 Action ​

UNO 出牌、抽牌、结束回合均通过引擎通用 Action 完成,由 UnoPlugin.actions 注册对应 ActionHandler:

Action 类型常量UNO 中的用途工厂函数
PLAY_CARDPLAY_CARD_ACTION玩家出一张牌到弃牌堆createPlayCardAction(playerId, cardIds)
DRAW_CARDDRAW_CARD_ACTION玩家从牌堆抽牌(初始发牌、罚抽、无牌可出时抽牌)createDrawCardAction(playerId, count)
END_TURNEND_TURN_ACTION结束当前玩家回合,推进到下家createEndTurnAction(playerId)
PASSPASS_ACTION玩家主动过牌(UNO 一般通过抽牌代替)createPassAction(playerId)

PLAY_CARD 在 UNO 中的特殊行为 ​

UnoPlugin 注册的 playCardHandler(ActionHandler<PlayCardAction>):

  1. 校验 playerId 与 cardIds(恰一张),取出卡牌并移入 弃牌堆。
  2. 发出引擎通用 CARD_PLAYED 与 UNO 专属 UNO_CARD_PLAYED 事件。
  3. 实色牌额外更新 UNO_VAR_CURRENT_COLOR 并发出 UNO_COLOR_CHANGED(reason='play');Wild 牌不在此更新颜色,留待 CHOOSE_COLOR 处理。

回合推进与胜负判定不在该 handler 完成,而是交由 handleCardPlayed 在 CARD_PLAYED 事件回调中根据卡牌类型派发对应 Effect。

示例:完整出牌 + 选色流程 ​

ts
import {
  GameEngine,
  TurnPlugin,
  DrawPlugin,
  createPlayCardAction,
  createDrawCardAction,
  createEndTurnAction
} from 'decklet'
import {
  UnoPlugin,
  createChooseColorAction,
  CHOOSE_COLOR_ACTION,
  UNO_VAR_PENDING_COLOR,
  isPendingColorChoice
} from 'decklet/uno'

const engine = new GameEngine()
engine.use(TurnPlugin).use(DrawPlugin).use(UnoPlugin)
engine.createGame({
  players: [
    { id: 'p1', name: 'Alice', seat: 1 },
    { id: 'p2', name: 'Bob', seat: 2 }
  ]
})
engine.start()

const state = engine.getState()
const currentId = state.currentPlayerId!

// 1) 出一张 Wild 牌
const wildCardId = /* 当前玩家手中的 wild 牌 id */ '<wildCardId>'
engine.dispatch(createPlayCardAction(currentId, [wildCardId]))

// 2) 此时 isPendingColorChoice === true,需提交 CHOOSE_COLOR
if (isPendingColorChoice(engine.getState())) {
  engine.dispatch(createChooseColorAction(currentId, 'red'))
}

// 3) 选色完成后,handleColorChosen 自动派发 END_TURN 推进回合
console.log('next player:', engine.getState().currentPlayerId)

注意事项 ​

  • CHOOSE_COLOR_ACTION 仅在 UNO_VAR_PENDING_COLOR === true 时合法(由 chooseColorValidRule 校验)。
  • UNO_FLIP_INITIAL_ACTION 是系统动作,由插件内部派发,外部通常不需要直接调用。
  • payload.color 必须是 UnoColorChoice(实色),不能传 'wild'——isUnoColorChoice 类型守卫会拒绝。