local state = runtime.import("state") local rules = runtime.import("rules") local ui = runtime.import("ui") local animation = runtime.import("animation") local i18n = runtime.import("i18n") ---@type RuntimeWidgets local widgets = runtime.import("runtime_widgets") local theme = runtime.import("theme") widgets.configure({ primary = theme.colors.dice_button, secondary = theme.colors.board, success = theme.colors.blue, overlay = "#99000000", surface = theme.colors.top_bar, surfaceAlt = theme.colors.board, card = theme.colors.top_bar, text = theme.colors.text, muted = "#ffcbd5e1", progress = theme.colors.blue, transparent = "#00000000" }) function smoke_test(ctx) i18n.configure(ctx) return ctx ~= nil and ctx.runtimeApiVersion ~= nil and state.current_player ~= nil and rules.next_player ~= nil and ui.create_board_nodes ~= nil and animation.move_piece ~= nil and widgets.dialog ~= nil end function init(ctx) i18n.configure(ctx) return { render = { creates = ui.create_board_nodes() }, ui = { creates = ui.create_ui_nodes() }, commands = {} } end local function handle_roll_dice() if state.phase ~= "waiting_roll" then return { commands = { animation.toast(i18n.t("toast.move_first")) } } end state.dice = rules.next_dice() local movable = rules.movable_pieces() if #movable == 0 then state.current_player = rules.next_player() state.phase = "waiting_roll" return { ui = { updates = ui.dice_and_turn_updates(state.dice, state.current_player) }, render = { updates = ui.highlight_updates(rules.all_piece_ids(), false) }, commands = { animation.toast(i18n.t("toast.no_movable_piece")) } } end state.phase = "waiting_piece" return { ui = { updates = ui.dice_update(state.dice) }, render = { updates = ui.highlight_updates(movable, true) }, commands = { animation.play_sound("dice") } } 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(i18n.t("toast.invalid_piece")) } } end local path = rules.calculate_path(piece, state.dice) rules.apply_move(piece, state.dice) state.phase = "animating" state.selected_piece = piece_id return { render = { updates = ui.highlight_updates(rules.all_piece_ids(), false) }, commands = { animation.move_piece(piece_id, path) } } end local function handle_move_done() if state.dice ~= 6 then state.current_player = rules.next_player() end state.phase = "waiting_roll" state.selected_piece = nil return { ui = { updates = ui.turn_update(state.current_player) } } 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