Permalink
Browse files

Divide into two modules

  • Loading branch information...
1 parent ea4079f commit 1a4eebe96fd41bc094b1d25b3ab9879e756e13bb @jaspervdj committed Sep 7, 2010
Showing with 113 additions and 98 deletions.
  1. +4 −0 .gitignore
  2. +10 −98 Main.hs
  3. +99 −0 PlanetWars.hs
View
@@ -0,0 +1,4 @@
+dist/
+*.o
+*.hi
+*.swp
View
108 Main.hs
@@ -1,90 +1,18 @@
module Main where
-import Data.List (isPrefixOf, intercalate, maximumBy, minimumBy)
-import Control.Applicative ((<$>))
-import Data.Monoid (Monoid, mempty, mappend)
-import System.IO
-import Data.IntMap (IntMap)
+import Data.List (maximumBy, minimumBy)
import qualified Data.IntMap as IM
import Data.Ord (comparing)
-data Planet = Planet
- { planetId :: Int
- , planetOwner :: Int
- , planetShips :: Int
- , planetGrowthRate :: Int
- , planetX :: Double
- , planetY :: Double
- } deriving (Show)
+import PlanetWars
-data Fleet = Fleet
- { fleetOwner :: Int
- , fleetShips :: Int
- , fleetSource :: Int
- , fleetDestination :: Int
- , fleetTripLength :: Int
- , fleetTurnsRemaining :: Int
- } deriving (Show)
-
-data GameState = GameState
- { gameStatePlanets :: IntMap Planet
- , gameStateFleets :: [Fleet]
- } deriving (Show)
-
-instance Monoid GameState where
- mempty = GameState mempty mempty
- mappend (GameState p1 f1) (GameState p2 f2) =
- GameState (p1 `mappend` p2) (f1 `mappend` f2)
-
-buildGameState :: GameState -> String -> GameState
-buildGameState state string = case words string of
- ("P" : xs) ->
- let planet = Planet planetId'
- (read $ xs !! 2)
- (read $ xs !! 3)
- (read $ xs !! 5)
- (read $ xs !! 0)
- (read $ xs !! 1)
- in state { gameStatePlanets = IM.insert planetId' planet
- (gameStatePlanets state)
- }
- ("F" : xs) ->
- let fleet = Fleet (read $ xs !! 0)
- (read $ xs !! 1)
- (read $ xs !! 2)
- (read $ xs !! 3)
- (read $ xs !! 4)
- (read $ xs !! 5)
- in state { gameStateFleets = fleet : gameStateFleets state
- }
- _ -> state
- where
- planetId' = IM.size $ gameStatePlanets state
-
-issueOrder :: Handle -- ^ Handle to write to
- -> Int -- ^ Source planet
- -> Int -- ^ Destination planet
- -> Int -- ^ Number of ships
- -> IO () -- ^ Result
-issueOrder handle source destination number = do
- hPutStrLn handle $ intercalate " " $ map show [source, destination, number]
- hFlush handle
-
-finnishTurn :: Handle -- ^ Handle to write to
- -> IO () -- ^ Result
-finnishTurn handle = do
- hPutStrLn handle "go"
- hFlush handle
-
-doTurn :: Handle -- ^ Handle to write to
- -> GameState -- ^ Game state
- -> IO ()
-doTurn handle state = do
- if (null $ gameStateFleets state)
- -- Simple ai
- then issueOrder handle (planetId strongest) (planetId weakest) ships
- -- If we have a fleet in flight, just do nothing
- else return ()
+doTurn :: GameState -- ^ Game state
+ -> [Order] -- ^ Orders
+doTurn state = if (null $ gameStateFleets state)
+ -- Simple ai
+ then [Order (planetId strongest) (planetId weakest) ships]
+ -- If we have a fleet in flight, just do nothing
+ else []
where
strongest = maximumBy (comparing planetShips)
$ filter ((== 1) . planetOwner)
@@ -94,21 +22,5 @@ doTurn handle state = do
$ map snd $ IM.toList $ gameStatePlanets state
ships = planetShips strongest `div` 2
-runGame :: Handle -> GameState -> IO ()
-runGame handle state = do
- line <- takeWhile (/= '#') <$> hGetLine handle
- if "go" `isPrefixOf` line
- -- Go Go Go!
- then do
- doTurn stdout state
- finnishTurn stdout
- runGame handle mempty
- -- Keep building map
- else runGame handle (buildGameState state line)
- return ()
-
main :: IO ()
-main = do
- let handle = stdin
- hSetBuffering stdin NoBuffering
- runGame stdin mempty
+main = bot doTurn
View
@@ -0,0 +1,99 @@
+module PlanetWars
+ ( Planet (..)
+ , Fleet (..)
+ , Order (..)
+ , GameState (..)
+ , bot
+ ) where
+
+import Control.Applicative ((<$>))
+import Data.List (intercalate, isPrefixOf)
+import Data.Monoid (Monoid, mempty, mappend)
+import System.IO
+import Data.IntMap (IntMap)
+import qualified Data.IntMap as IM
+
+data Planet = Planet
+ { planetId :: Int
+ , planetOwner :: Int
+ , planetShips :: Int
+ , planetGrowthRate :: Int
+ , planetX :: Double
+ , planetY :: Double
+ } deriving (Show)
+
+data Fleet = Fleet
+ { fleetOwner :: Int
+ , fleetShips :: Int
+ , fleetSource :: Int
+ , fleetDestination :: Int
+ , fleetTripLength :: Int
+ , fleetTurnsRemaining :: Int
+ } deriving (Show)
+
+data Order = Order
+ { orderSource :: Int
+ , orderDestination :: Int
+ , orderShips :: Int
+ } deriving (Show)
+
+data GameState = GameState
+ { gameStatePlanets :: IntMap Planet
+ , gameStateFleets :: [Fleet]
+ } deriving (Show)
+
+instance Monoid GameState where
+ mempty = GameState mempty mempty
+ mappend (GameState p1 f1) (GameState p2 f2) =
+ GameState (p1 `mappend` p2) (f1 `mappend` f2)
+
+issueOrder :: Order -> IO ()
+issueOrder (Order source destination ships) =
+ putStrLn $ intercalate " " $ map show [source, destination, ships]
+
+finnishTurn :: IO () -- ^ Result
+finnishTurn = do
+ putStrLn "go"
+ hFlush stdout
+
+buildGameState :: GameState -> String -> GameState
+buildGameState state string = case words string of
+ ("P" : xs) ->
+ let planet = Planet planetId'
+ (read $ xs !! 2)
+ (read $ xs !! 3)
+ (read $ xs !! 5)
+ (read $ xs !! 0)
+ (read $ xs !! 1)
+ in state { gameStatePlanets = IM.insert planetId' planet
+ (gameStatePlanets state)
+ }
+ ("F" : xs) ->
+ let fleet = Fleet (read $ xs !! 0)
+ (read $ xs !! 1)
+ (read $ xs !! 2)
+ (read $ xs !! 3)
+ (read $ xs !! 4)
+ (read $ xs !! 5)
+ in state { gameStateFleets = fleet : gameStateFleets state
+ }
+ _ -> state
+ where
+ planetId' = IM.size $ gameStatePlanets state
+
+bot :: (GameState -> [Order])
+ -> IO ()
+bot f = do
+ hSetBuffering stdin NoBuffering
+ loop mempty
+ where
+ loop state = do
+ line <- takeWhile (/= '#') <$> hGetLine stdin
+ if "go" `isPrefixOf` line
+ -- Go Go Go!
+ then do
+ mapM_ issueOrder $ f state
+ finnishTurn
+ loop mempty
+ -- Keep building map
+ else loop (buildGameState state line)

0 comments on commit 1a4eebe

Please sign in to comment.