Skip to content

Instantly share code, notes, and snippets.

@Heimdell
Created July 27, 2019 21:03
Show Gist options
  • Save Heimdell/8b5c0d8207ad6896c60d776d6607c177 to your computer and use it in GitHub Desktop.
Save Heimdell/8b5c0d8207ad6896c60d776d6607c177 to your computer and use it in GitHub Desktop.
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