; SPDX-FileCopyrightText: 2023 Jummit
;
; SPDX-License-Identifier: GPL-3.0-or-later
(local {: get-start-cells-for
: get-online-of
: get-cards-on
: is-online
: get-cell} (require :match.info))
(local {: move} (require :move))
(local {: make-state} (require :match.state))
(local {: get-possible-actions} (require :match.actions))
(local {: perform-action} (require :match.action))
(local {: add-cell-action
: add-card-action
: add-slot-action
: remove-cell-actions
: remove-card-actions
: remove-slot-actions} (require :match.interact))
(fn remove-actions [world]
(remove-card-actions world)
(remove-slot-actions world)
(remove-cell-actions world))
(fn card-action [world card action]
(add-card-action card (fn []
(perform-action world action)
(remove-actions world))))
(fn slot-action [world slot action]
(add-slot-action slot (fn []
(perform-action world action)
(remove-actions world))))
(fn player-setup [world]
"System which adds an interface for the player to place online cards
in the setup phase. After all cards are placed the setup action is
performed."
(case world.phase
{:kind :setup : player}
(when (= (. world.players player) :player)
(when (not world.phase.placing)
(let [online (get-online-of world player)
not-placed (. (icollect [_ card (ipairs online)]
(if (not card.circuit-x) card))
1)]
(when (not not-placed)
(let [cards (icollect [_ entity (ipairs world)]
(match entity
{:card {:owner player : kind}
:circuit-x x
:circuit-y y} {: kind
: x
: y}))]
(perform-action world {:kind :setup : player : cards})))
(when not-placed
(set world.phase.placing not-placed)
(move not-placed 110 80)
(set not-placed.card.open true))))
(each [_ {:circuit-x x :circuit-y y &as cell} (ipairs (get-start-cells-for world
player))]
(when (= (length (get-cards-on world x y)) 0)
(add-cell-action world cell
(fn []
(set world.phase.placing.circuit-x x)
(set world.phase.placing.circuit-y y)
(set world.phase.placing nil)
(remove-actions world))))))))
(fn handle-selected-card [world player selected-card]
(case selected-card
(where {: card} (is-online card))
(do
(when selected-card.boosted
(each [_ entity (ipairs world)]
(match entity
{:slot {:owner player :kind :line-boost}}
(slot-action world entity {: player :kind :remove-line-boost}))))
(each [_ action (ipairs (get-possible-actions (make-state world player)))]
(match action
{:kind :move
:from-x selected-card.circuit-x
:from-y selected-card.circuit-y
: to-x
: to-y} (if (. (get-cell world to-x to-y) :cell :core)
(let [slot (. (icollect [_ entity (ipairs world)]
(match entity
{:slot {:owner player
:kind selected-card.card.kind
:used nil}} entity))
1)]
(slot-action world slot
{: player
:x selected-card.circuit-x
:y selected-card.circuit-y
:kind :infiltrate}))
(add-cell-action world
(get-cell world action.to-x
action.to-y)
(fn []
(tset action :player player)
(perform-action world
action)
(remove-actions world)))))))
{:card {:kind :fire-wall}}
(do
(each [_ entity (ipairs world)]
(case entity
(where {: circuit-x : circuit-y : cell}
(and (not cell.core) (not cell.exit-for)
(not (-?> (get-cards-on world circuit-x circuit-y)
(. 1)
(. :card :owner)
(not= player)))))
(add-cell-action world entity
(fn []
(perform-action world
{: player
:kind :fire-wall
:x circuit-x
:y circuit-y})
(remove-actions world))))))
{:card {:kind :404}}
(do
(set world.phase.swapping true)
(each [_ entity (ipairs world)]
(case entity
(where {:card {: owner}}
(and (= owner player) (not entity.captured)
(is-online entity.card)))
(add-card-action entity
(fn []
(each [_ other (ipairs world)]
(case other
(where {:card {: owner}}
(and (= owner player)
(not= entity other)
(not other.captured)
(is-online other.card)))
(card-action world other
{: player
:kind :404
:xa entity.circuit-x
:ya entity.circuit-y
:xb other.circuit-x
:yb other.circuit-y}))))))))
{:card {:kind :virus-check}}
(do
(each [_ entity (ipairs world)]
(case entity
(where {:card {: owner}}
(and (not= owner player) (not entity.captured)
(is-online entity.card)))
(card-action world entity
{: player
:kind :virus-check
:x entity.circuit-x
:y entity.circuit-y}))))
{:card {:kind :line-boost}}
(do
(each [_ entity (ipairs world)]
(case entity
(where {:card {: owner}}
(and (= owner player) (not entity.captured)
(is-online entity.card)))
(card-action world entity
{: player
:kind :line-boost
:x entity.circuit-x
:y entity.circuit-y}))))))
(fn handle-player-turn [world player]
(each [_ entity (ipairs world)]
(match entity
{:card {:owner player} :captured nil} (add-card-action entity
(fn []
(set world.phase.selected-card
entity)
(remove-cell-actions world)))
{:slot {:kind :fire-wall :owner player :used nil}
:circuit-x x
:circuit-y y}
(slot-action world entity {: player :kind :remove-fire-wall : x : y}))))
(fn player-turn [world]
"System which adds interface elements for turn actions when it's the
players turn."
(when (= (. world.players world.phase.player) :player)
(case world.phase
{:kind :turn :swapping true}
nil
{:kind :turn : player : selected-card}
(handle-selected-card world player selected-card)
{:kind :turn : player}
(handle-player-turn world player))))
{: player-turn : player-setup}