; SPDX-FileCopyrightText: 2023 Jummit
;
; SPDX-License-Identifier: GPL-3.0-or-later
(local {: is-online} (require :match.info))
(local {: view} (require :fennel))
(fn make-state [world player]
"Analyses the world and returns a view of the game state for the
given player. The structure contains the terminal, online and captured
cards, and some information about the cells:
{:online [{:kind :virus :x 1 :y 2 :mine true :boosted true}]
:terminals {:line-boost true true :404 true}]
:captured [{:kind :virus :mine true}
:cells [{:x 1 :y 1 :fire-wall :enemies :exit :mine}]]}
This function exists so AIs or players don't accidentally access
information that they shouldn't have, and to structure the data
so it is easier to use."
{:terminals (collect [_ entity (ipairs world)]
(case entity
(where {:card {: owner : kind}}
(and (not (is-online entity.card)) (= owner player)))
(values kind true)))
:captured (icollect [_ entity (ipairs world)]
(case entity
{:card {: owner : kind} :captured true}
{:mine (= player owner) :kind (when (= player owner) kind)}))
:online (icollect [_ entity (ipairs world)]
(case entity
{:card {: owner : kind} :circuit-x x :circuit-y y :captured nil}
{: x : y :mine (= player owner) : kind :boosted entity.boosted}))
:cells (icollect [_ entity (ipairs world)]
(case entity
(where {:circuit-x x :circuit-y y} entity.cell)
{: x
: y
:fire-wall (match entity.cell.fire-walled player :mine nil nil _ :enemies)
:exit (match entity.cell.exit-for player :mine nil nil _ :enemies)}))})
(fn enemies [mine]
(case mine
:mine
:enemies
:enemies
:mine))
(fn invert-state [state]
"Returns the board state flipped, as the opponent sees it."
{:cells (icollect [_ {: x : y : fire-wall : exit} (ipairs state.cells)]
{: x : y :fire-wall (enemies fire-wall) :exit (enemies exit)})
:online (icollect [_ {: x : y : mine : boosted} (ipairs state.online)]
{: x : y :mine (not mine) : boosted})
:captured (icollect [_ {: mine : kind} (ipairs state.captured)]
{:mine (not mine) : kind})
:terminals {}})
{: make-state : invert-state}