From 3131b1c464d073f5b92dfe3d29ba92f8bd813e5d Mon Sep 17 00:00:00 2001 From: anon Date: Fri, 8 Dec 2023 12:55:39 +0100 Subject: [PATCH] init --- Makefile | 12 ++++++ main.hs | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 Makefile create mode 100644 main.hs diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..09ba6f5 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +.PHONY: run + +OUT := main + +main: main.hs + ghc -o ${OUT} main.hs + +run: main + ./${OUT} + +clean: + -rm ${OUT} diff --git a/main.hs b/main.hs new file mode 100644 index 0000000..22baaf2 --- /dev/null +++ b/main.hs @@ -0,0 +1,127 @@ +import System.IO +import Data.Char +import System.Console.ANSI +import System.Random +import Control.Monad.IO.Class +import System.Random.Shuffle + +target_words = + [ "mutate" + , "dubbed" + , "repair" + , "rugrat" + , "system" + , "human" + , "defend" + , "stream" + , "wagons" + , "subtle" + , "carved" + ] + +garbage = "$@#`|:=;_-<>()[]{}%+*^/\\!?'\"" + +solution_index = 3 +table_size = 32 +entry_width = 12 +starting_lifes = 4 + + +likeness :: Eq a => [a] -> [a] -> Int +likeness [] _ = 0 +likeness _ [] = 0 +likeness (g:gx) (l:lx) = (if g == l then 1 else 0) + (likeness gx lx) + +fake_hex' :: String -> String +fake_hex' s + | len < 4 = fake_hex' ("0" ++ s) + | len == 4 = "0x" ++ s + where len = length s +fake_hex :: Int -> String +fake_hex i + | len < 4 = fake_hex' ("0" ++ (show i)) + | len > 4 = fake_hex (mod i 10000) + | len == 4 = fake_hex' (show i) + where len = length (show i) + +garbage_char :: IO Char +garbage_char = do + rindex <- randomIO :: IO Int + return $ garbage !! (mod rindex (length garbage)) + +garbage_entry' :: Int -> [IO Char] -> [IO Char] +garbage_entry' i s + | i > 0 = [garbage_char] ++ (garbage_entry' (i - 1) s) + | otherwise = s + +garbage_entry :: [IO Char] +garbage_entry = garbage_entry' entry_width [] + +litter_entry :: String -> IO String +litter_entry e + | (length e) < entry_width = do a <- garbage_char + litter_entry (e ++ [a]) + | otherwise = return e + +litter_entries :: [String] -> IO [String] +litter_entries l + | (length l) < table_size = do a <- sequence garbage_entry; litter_entries (l ++ [a]) + | otherwise = do a <- sequence garbage_entry; return l + +render_entry :: Int -> String -> String +render_entry i w = + (fake_hex i) ++ " " ++ w + +render_odd, render_even, render_entries :: Int -> [String] -> String +render_odd i [] = "" +render_odd i (l:ls) = + (render_entry i l) ++ " " ++ (render_even (i + 1) ls) +render_even i [] = "" +render_even i (l:ls) = + (render_entry i l) ++ "\n" ++ (render_odd (i + 1) ls) +render_entries i l = + render_odd i l + +print_console :: [String] -> IO () +print_console l = do + rng <- newStdGen + start <- randomIO :: IO Int + entries <- litter_entries target_words + entries <- (mapM litter_entry entries) + putStr $ render_entries start (shuffle' entries (length entries) rng) + +print_lifes' :: Int -> IO () +print_lifes' i + | i > 0 = do putStr " #"; print_lifes' (i - 1) + | otherwise = putStrLn "" + + +print_lifes :: Int -> IO () +print_lifes i = do + putStr "Attempts remaining:" + print_lifes' i + +game_cycle :: Int -> IO () +game_cycle i = do + putStrLn "Password Required" + putStrLn "" + print_lifes i + putStrLn "" + print_console target_words + putStr "$:" + hFlush stdout + guess_index <- readLn :: IO Int + let guess = target_words !! (guess_index - 1) + let solution = target_words !! solution_index + print $ ">" ++ (map toUpper guess) + if guess == solution then + print "I'm in!" + else do + print ">Entry denied." + print $ ">Likeness=" ++ show (likeness guess solution) + game_cycle (i - 1) + +main :: IO () +main = do + setSGR [SetConsoleIntensity BoldIntensity, SetColor Foreground Dull Yellow] + game_cycle starting_lifes