factory-lang/Main.hs

128 lines
4.4 KiB
Haskell
Raw Normal View History

2021-05-19 20:15:40 +00:00
module Main where
2021-05-23 22:03:17 +00:00
-- TODO:
-- arithmetic
-- I/O
2021-05-19 20:15:40 +00:00
import Data.List
2021-05-25 13:00:17 +00:00
import System.Environment
import System.Exit
2021-05-23 22:03:17 +00:00
import Element
2021-05-25 13:00:17 +00:00
import Types
import Dirty
2021-05-19 20:15:40 +00:00
main :: IO ()
main = do
2021-05-25 13:00:17 +00:00
args <- getArgs
if length args < 1
then die "No filename provided."
else run $ args !! 0
run :: String -> IO ()
run inputFile = do
input <- readFile inputFile
2021-05-19 20:15:40 +00:00
let internalFactory = stringsToFactory $ lines input
2021-05-23 22:03:17 +00:00
interpretLoop internalFactory [ Element
0
2021-05-25 13:00:17 +00:00
(fst $ entryPointLocation internalFactory)
2021-05-23 22:03:17 +00:00
(snd $ entryPointLocation internalFactory)]
2021-05-19 20:15:40 +00:00
interpretLoop :: Factory -> [Element] -> IO ()
interpretLoop f es = do
let elements = stepInterpret f es
2021-05-23 22:03:17 +00:00
printFactory f elements
2021-05-19 20:15:40 +00:00
a <- getChar
2021-05-25 13:00:17 +00:00
case a of
'q' -> return ()
_ -> interpretLoop f elements
2021-05-19 20:15:40 +00:00
stringsToFactory :: [[Char]] -> [[Tile]]
2021-05-23 22:03:17 +00:00
stringsToFactory [] = []
stringsToFactory s = map (map charToTile) s
2021-05-19 20:15:40 +00:00
tupAdd :: (Num a, Num b) => (a, b) -> (a, b) -> (a, b)
tupAdd (a, b) (c, d) = (a + c, b + d)
entryPointLocation :: Factory -> (Int, Int)
entryPointLocation [] = error "Couldn't find an entrypoint (E)."
entryPointLocation (l:ls) = case index of
Nothing -> tupAdd (0, 1) (entryPointLocation ls)
Just x -> (x, 0)
where index = elemIndex Entrypoint l
oobCheck :: Factory -> Element -> Bool
oobCheck f e = yPos e >= length f
|| xPos e >= length (f !! yPos e)
2021-05-28 10:06:03 +00:00
singleton :: a -> [a]
singleton a = [a]
2021-05-19 20:15:40 +00:00
-- custom hashmap thingy, but uses lists so it's slow on large things (luckily this is small)
2021-05-28 10:06:03 +00:00
tileActionMap :: Tile -> [(Tile, Element -> [Element])] -> (Element -> [Element])
tileActionMap _ [] = singleton
2021-05-19 20:15:40 +00:00
tileActionMap tile (pair:rest)
| tile == fst pair = snd pair
| otherwise = tileActionMap tile rest
2021-05-23 22:03:17 +00:00
-- TODO: make this safe, aka boundary check
2021-05-28 10:06:03 +00:00
spitOut :: Direction -> Factory -> Element -> Element
spitOut dir f elem = case dir of
East -> spitOutEast f elem
South -> spitOutSouth f elem
West -> spitOutWest f elem
North -> spitOutNorth f elem
-- AAAAAAAA
spitOutEast :: Factory -> Element -> Element
spitOutEast f elem
2021-05-23 22:03:17 +00:00
| (f !! yPos elem) !! (xPos elem + 1) == Track East = incXPos elem
| (f !! (yPos elem + 1)) !! xPos elem == Track South = incYPos elem
| (f !! yPos elem) !! (xPos elem - 1) == Track West = decXPos elem
| (f !! (yPos elem - 1)) !! xPos elem == Track North = decYPos elem
2021-05-28 10:06:03 +00:00
spitOutSouth :: Factory -> Element -> Element
spitOutSouth f elem
| (f !! (yPos elem + 1)) !! xPos elem == Track South = incYPos elem
| (f !! yPos elem) !! (xPos elem - 1) == Track West = decXPos elem
| (f !! (yPos elem - 1)) !! xPos elem == Track North = decYPos elem
| (f !! yPos elem) !! (xPos elem + 1) == Track East = incXPos elem
spitOutWest :: Factory -> Element -> Element
spitOutWest f elem
| (f !! yPos elem) !! (xPos elem - 1) == Track West = decXPos elem
| (f !! (yPos elem - 1)) !! xPos elem == Track North = decYPos elem
| (f !! yPos elem) !! (xPos elem + 1) == Track East = incXPos elem
| (f !! (yPos elem + 1)) !! xPos elem == Track South = incYPos elem
spitOutNorth :: Factory -> Element -> Element
spitOutNorth f elem
| (f !! (yPos elem - 1)) !! xPos elem == Track North = decYPos elem
| (f !! yPos elem) !! (xPos elem + 1) == Track East = incXPos elem
| (f !! (yPos elem + 1)) !! xPos elem == Track South = incYPos elem
| (f !! yPos elem) !! (xPos elem - 1) == Track West = decXPos elem
duplicate :: Element -> [Element]
duplicate e = [e, e]
update :: Factory -> Element -> [Element]
2021-05-19 20:15:40 +00:00
update f e = if oobCheck f e then error "Element out of bounds check failed!"
2021-05-23 22:03:17 +00:00
else tileActionMap t tileActions e
2021-05-19 20:15:40 +00:00
where t = (f !! yPos e) !! xPos e
2021-05-28 10:06:03 +00:00
tileActions = [ (Track East, singleton . incXPos)
, (Track West, singleton . decXPos)
, (Track South, singleton . incYPos)
, (Track North, singleton . decYPos)
, (Modifier Increment, singleton . incVal . spitOut East f)
, (Modifier Decrement, singleton . decVal . spitOut East f)
, (Special Duplicate, dupFunc)
, (Entrypoint, singleton . spitOut East f)
2021-05-19 20:15:40 +00:00
]
2021-05-28 10:06:03 +00:00
dupFunc :: Element -> [Element]
dupFunc elem = [ spitOut East f elem
, spitOut South f elem
]
2021-05-19 20:15:40 +00:00
stepInterpret :: Factory -> [Element] -> [Element]
2021-05-28 10:06:03 +00:00
stepInterpret f = concat . map (update f)