Files
2026-06-07 22:53:58 +08:00

155 lines
4.1 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
local state = runtime.import("state")
local rules = runtime.import("rules")
local ui = runtime.import("ui")
local animation = runtime.import("animation")
---@type RuntimeWidgets
local widgets = runtime.import("runtime_widgets")
local theme = runtime.import("theme")
widgets.configure({
primary = theme.colors.dice_button,
secondary = theme.colors.board_inner,
success = theme.colors.green,
overlay = "#99000000",
surface = theme.colors.top_bar,
surfaceAlt = theme.colors.board_inner,
card = theme.colors.top_bar,
text = theme.colors.text,
muted = theme.colors.muted_text,
progress = theme.colors.green,
transparent = "#00000000"
})
function smoke_test(ctx)
return ctx ~= nil
and ctx.runtimeApiVersion ~= nil
and state.current_player ~= nil
and rules.plan_move ~= nil
and ui.create_board_nodes ~= nil
and animation.move_piece ~= nil
and widgets.dialog ~= nil
end
function init(ctx)
return {
render = { creates = ui.create_board_nodes() },
ui = { creates = ui.create_ui_nodes() },
commands = {}
}
end
local function handle_roll_dice()
if state.phase == "game_over" then
return { commands = { animation.toast("游戏已结束") } }
end
if state.phase ~= "waiting_roll" then
return { commands = { animation.toast("请先完成当前移动") } }
end
state.dice = rules.next_dice()
local movable = rules.movable_pieces()
if #movable == 0 then
local message = state.current_player .. " 无可移动飞机"
if state.dice ~= 6 then
state.current_player = rules.next_player()
end
state.phase = "waiting_roll"
return {
ui = { updates = ui.dice_and_status_updates() },
render = { updates = ui.highlight_updates(rules.all_piece_ids(), false) },
commands = { animation.toast(message) }
}
end
state.phase = "waiting_piece"
return {
ui = { updates = ui.dice_and_status_updates() },
render = { updates = ui.highlight_updates(movable, true) }
}
end
local function handle_piece_tap(piece_id)
if state.phase ~= "waiting_piece" then
return {}
end
local piece = state.pieces[piece_id]
if piece == nil or piece.owner ~= state.current_player or not rules.can_move(piece, state.dice) then
return { commands = { animation.toast("该飞机不能移动") } }
end
local plan = rules.plan_move(piece, state.dice)
state.phase = "animating"
state.selected_piece = piece_id
state.pending_move = plan
return {
ui = { updates = ui.dice_and_status_updates() },
render = { updates = ui.highlight_updates(rules.all_piece_ids(), false) },
commands = { animation.move_piece(piece_id, plan.path) }
}
end
local function handle_move_done()
local plan = state.pending_move
if plan == nil then
state.phase = "waiting_roll"
return { ui = { updates = ui.dice_and_status_updates() } }
end
rules.commit_move(plan)
local moved_piece = state.pieces[plan.piece_id]
local updates = ui.piece_position_updates(plan.captures)
table.insert(updates, ui.piece_position_update(plan.piece_id))
local messages = {}
if #plan.captures > 0 then
table.insert(messages, "撞回 " .. tostring(#plan.captures) .. " 架飞机")
end
if rules.player_finished(moved_piece.owner) then
state.winner = moved_piece.owner
state.phase = "game_over"
table.insert(messages, moved_piece.owner .. " 获胜")
else
if state.dice ~= 6 then
state.current_player = rules.next_player()
else
table.insert(messages, "掷出 6额外回合")
end
state.phase = "waiting_roll"
end
state.selected_piece = nil
state.pending_move = nil
local commands = {}
if #messages > 0 then
commands = { animation.toast(table.concat(messages, "")) }
end
return {
ui = { updates = ui.dice_and_status_updates() },
render = { updates = updates },
commands = commands
}
end
function on_event(event)
if event.handler == "roll_dice" then
return handle_roll_dice()
end
if event.handler == "piece_tap" then
return handle_piece_tap(event.target)
end
if event.handler == "piece_move_done" then
return handle_move_done()
end
return {}
end