Created
July 27, 2019 21:03
-
-
Save Heimdell/8b5c0d8207ad6896c60d776d6607c177 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Surface exposing (..) | |
import Dict exposing (..) | |
import Maybe exposing (..) | |
type TerrainType | |
= Water | |
| Land | |
type Landmarks | |
= River | |
| Rocks | |
type alias Tile = | |
{ base : TerrainType | |
, height : Int | |
, rain : Int | |
, building : Maybe Building | |
, army : Maybe Army | |
} | |
type Building | |
= CityCenter | |
| Mine | |
| Factory | |
| Farm | |
| Road | |
| Solar | |
| Forest | |
| Fungus | |
type ArmyType | |
= Settler | |
| Patrol | |
| Worker | |
| PsiWorm | |
type alias Army = | |
{ base : ArmyType | |
, steps : Int -- remaining actions for unit | |
, hp : Float | |
, dmg : Float | |
, player : Int | |
} | |
type alias Point = (Int, Int) | |
type alias Surface = | |
{ tiles : Dict Point Tile | |
, focus : Point | |
, locked : Bool -- are we controlling a unit? | |
, turn : Int -- global turn number | |
, ouches : List (Int, Ouch) -- game log | |
} | |
type Ouch | |
= CannotMixArmiesYet | |
| CannotFocusOnNoArmy | |
| ArmyHasNoMovePoints | |
type Msg | |
= ToggleFocus | |
| Move Dir | |
| EndTurn | |
type Dir | |
= L | R | U | D | UL | RD | |
dirToDelta : Dir -> Point | |
dirToDelta dir = case dir of | |
L -> (-1, 0) | |
R -> ( 1, 0) | |
U -> ( 0, 1) | |
D -> ( 0, -1) | |
UL -> (-1, 1) | |
RD -> ( 1, -1) | |
scalar : (Int -> Int -> Int) -> Point -> Point -> Point | |
scalar op (x, y) (x1, y1) = (op x x1, op y y1) | |
ouch : Ouch -> Surface -> Surface | |
ouch msg surface = { surface | ouches = (surface.turn, msg) :: surface.ouches } | |
update : Msg -> Surface -> Surface | |
update msg surface = | |
case msg of | |
ToggleFocus -> | |
if surface.locked then | |
{surface | locked = False} | |
else | |
case currentArmy surface of | |
Just it -> | |
{surface | locked = True} | |
Nothing -> | |
surface | |
|> ouch CannotFocusOnNoArmy | |
Move dir -> | |
if surface.locked then | |
case currentArmy surface of | |
Just army -> | |
moveCurrentArmy dir army surface | |
Nothing -> | |
Debug.todo "Locked, yet no army exists" | |
else | |
{ surface | focus = moveTo dir surface.focus} | |
EndTurn -> | |
surface | |
moveTo : Dir -> Point -> Point | |
moveTo dir = scalar (+) (dirToDelta dir) | |
currentArmy : Surface -> Maybe Army | |
currentArmy surface = armyAt surface.focus surface | |
armyAt : Point -> Surface -> Maybe Army | |
armyAt point surface = | |
surface.tiles | |
|> Dict.get point | |
|> Maybe.andThen .army | |
moveCurrentArmy : Dir -> Army -> Surface -> Surface | |
moveCurrentArmy dir army surface = | |
if canMove army then | |
let dest = moveTo dir surface.focus | |
in case armyAt dest surface of | |
Just dArmy -> | |
if dArmy.player == army.player then | |
surface |> ouch CannotMixArmiesYet | |
else | |
let | |
newArmy = dArmy |> suffer army.dmg | |
armyThatShot = army |> exhaust | |
in surface | |
|> setArmyAt dest newArmy | |
|> setArmyAt surface.focus (Just armyThatShot) | |
Nothing -> | |
surface | |
|> setArmyAt surface.focus Nothing | |
|> setArmyAt dest (Just (exhaust army)) | |
else | |
surface |> ouch ArmyHasNoMovePoints | |
canMove : Army -> Bool | |
canMove army = army.steps > 0 | |
exhaust : Army -> Army | |
exhaust army = { army | steps = army.steps - 1 } | |
suffer : Float -> Army -> Maybe Army | |
suffer dmg army = | |
if army.hp > dmg then | |
Just { army | hp = army.hp - dmg } | |
else | |
Nothing | |
setArmyAt : Point -> Maybe Army -> Surface -> Surface | |
setArmyAt point army surface = | |
{ surface | | |
tiles = | |
surface.tiles | |
|> Dict.update point (Maybe.map <| \tile -> { tile | army = army }) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment