From a7a3dfbfc2a9dae3b779fbf3cee8000a36d7ab35 Mon Sep 17 00:00:00 2001
From: Jesse Paroz
Date: Sat, 12 Nov 2016 21:15:14 +1000
Subject: [PATCH 01/22] Add skeleton for Haskell starter package
runGame.bat is rather simplified compared to runGame.sh, mostly as I
have no real knowledge of batch scripting, and no Windows machine on
which to test. I don't think it should be too complicated to port for
someone more knowledgeable though.
---
airesources/Haskell/LICENSE | 30 +++++++++++++++++
airesources/Haskell/Setup.hs | 2 ++
airesources/Haskell/halite-haskell.cabal | 25 ++++++++++++++
airesources/Haskell/lib/Halite.hs | 1 +
airesources/Haskell/lib/Halite/Networking.hs | 1 +
airesources/Haskell/runGame.bat | 3 ++
airesources/Haskell/runGame.sh | 12 +++++++
airesources/Haskell/src/MyBot.hs | 3 ++
airesources/Haskell/src/RandomBot.hs | 3 ++
airesources/Haskell/stack.yaml | 35 ++++++++++++++++++++
10 files changed, 115 insertions(+)
create mode 100644 airesources/Haskell/LICENSE
create mode 100644 airesources/Haskell/Setup.hs
create mode 100644 airesources/Haskell/halite-haskell.cabal
create mode 100644 airesources/Haskell/lib/Halite.hs
create mode 100644 airesources/Haskell/lib/Halite/Networking.hs
create mode 100644 airesources/Haskell/runGame.bat
create mode 100755 airesources/Haskell/runGame.sh
create mode 100644 airesources/Haskell/src/MyBot.hs
create mode 100644 airesources/Haskell/src/RandomBot.hs
create mode 100644 airesources/Haskell/stack.yaml
diff --git a/airesources/Haskell/LICENSE b/airesources/Haskell/LICENSE
new file mode 100644
index 000000000..3cd48fe71
--- /dev/null
+++ b/airesources/Haskell/LICENSE
@@ -0,0 +1,30 @@
+Copyright Jesse Paroz (c) 2016
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * Neither the name of Jesse Paroz nor the names of other
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/airesources/Haskell/Setup.hs b/airesources/Haskell/Setup.hs
new file mode 100644
index 000000000..9a994af67
--- /dev/null
+++ b/airesources/Haskell/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/airesources/Haskell/halite-haskell.cabal b/airesources/Haskell/halite-haskell.cabal
new file mode 100644
index 000000000..09b20b37f
--- /dev/null
+++ b/airesources/Haskell/halite-haskell.cabal
@@ -0,0 +1,25 @@
+name: halite-haskell
+version: 0.1.0.0
+synopsis: Halite starter pack for Haskell
+author: Jesse Paroz
+maintainer: jesse.paroz@gmail.com
+build-type: Simple
+cabal-version: >=1.10
+
+library
+ hs-source-dirs: lib
+ exposed-modules: Halite, Halite.Networking
+ default-language: Haskell2010
+ build-depends: base >= 4.7 && < 5
+
+executable MyBot
+ hs-source-dirs: src
+ main-is: MyBot.hs
+ default-language: Haskell2010
+ build-depends: base >= 4.7 && < 5
+
+executable RandomBot
+ hs-source-dirs: src
+ main-is: RandomBot.hs
+ default-language: Haskell2010
+ build-depends: base >= 4.7 && < 5
diff --git a/airesources/Haskell/lib/Halite.hs b/airesources/Haskell/lib/Halite.hs
new file mode 100644
index 000000000..96835ffab
--- /dev/null
+++ b/airesources/Haskell/lib/Halite.hs
@@ -0,0 +1 @@
+module Halite where
diff --git a/airesources/Haskell/lib/Halite/Networking.hs b/airesources/Haskell/lib/Halite/Networking.hs
new file mode 100644
index 000000000..939b2cece
--- /dev/null
+++ b/airesources/Haskell/lib/Halite/Networking.hs
@@ -0,0 +1 @@
+module Halite.Networking where
diff --git a/airesources/Haskell/runGame.bat b/airesources/Haskell/runGame.bat
new file mode 100644
index 000000000..d3df1b1ea
--- /dev/null
+++ b/airesources/Haskell/runGame.bat
@@ -0,0 +1,3 @@
+cabal configure
+cabal build
+.\halite.exe -d "30 30" "dist/build/MyBot/MyBot" "dist/build/RandomBot/RandomBot"
diff --git a/airesources/Haskell/runGame.sh b/airesources/Haskell/runGame.sh
new file mode 100755
index 000000000..396e2aa8e
--- /dev/null
+++ b/airesources/Haskell/runGame.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+if hash stack 2>/dev/null; then
+ stack build
+ build="$(stack path --dist-dir)/build"
+else
+ cabal configure
+ cabal build
+ build="./dist/build"
+fi
+
+./halite -d "30 30" "$build/MyBot/MyBot" "$build/RandomBot/RandomBot"
diff --git a/airesources/Haskell/src/MyBot.hs b/airesources/Haskell/src/MyBot.hs
new file mode 100644
index 000000000..a4531e1a4
--- /dev/null
+++ b/airesources/Haskell/src/MyBot.hs
@@ -0,0 +1,3 @@
+module Main where
+
+main = putStrLn "hullo from MyBot"
diff --git a/airesources/Haskell/src/RandomBot.hs b/airesources/Haskell/src/RandomBot.hs
new file mode 100644
index 000000000..300cc63cf
--- /dev/null
+++ b/airesources/Haskell/src/RandomBot.hs
@@ -0,0 +1,3 @@
+module Main where
+
+main = main
diff --git a/airesources/Haskell/stack.yaml b/airesources/Haskell/stack.yaml
new file mode 100644
index 000000000..7a275c54c
--- /dev/null
+++ b/airesources/Haskell/stack.yaml
@@ -0,0 +1,35 @@
+# This file was automatically generated by stack init
+# For more information, see: http://docs.haskellstack.org/en/stable/yaml_configuration/
+
+# Specifies the GHC version and set of packages available (e.g., lts-3.5, nightly-2015-09-21, ghc-7.10.2)
+resolver: lts-7.8
+
+# Local packages, usually specified by relative directory name
+packages:
+- '.'
+# Packages to be pulled from upstream that are not in the resolver (e.g., acme-missiles-0.3)
+extra-deps: []
+
+# Override default flag values for local packages and extra-deps
+flags: {}
+
+# Extra package databases containing global packages
+extra-package-dbs: []
+
+# Control whether we use the GHC we find on the path
+# system-ghc: true
+
+# Require a specific version of stack, using version ranges
+# require-stack-version: -any # Default
+# require-stack-version: >= 1.0.0
+
+# Override the architecture used by stack, especially useful on Windows
+# arch: i386
+# arch: x86_64
+
+# Extra directories used by stack for building
+# extra-include-dirs: [/path/to/dir]
+# extra-lib-dirs: [/path/to/dir]
+
+# Allow a newer minor version of GHC than the snapshot specifies
+# compiler-check: newer-minor
From ebe864417cb424fdd500870fb0f47cbc2a750711 Mon Sep 17 00:00:00 2001
From: Jesse Paroz
Date: Sat, 12 Nov 2016 23:12:26 +1000
Subject: [PATCH 02/22] Haskell: Implement types and stub functions
---
airesources/Haskell/halite-haskell.cabal | 2 +-
airesources/Haskell/lib/Halite.hs | 3 ++
airesources/Haskell/lib/Halite/Networking.hs | 32 +++++++++++++++-
airesources/Haskell/lib/Halite/Types.hs | 40 ++++++++++++++++++++
4 files changed, 75 insertions(+), 2 deletions(-)
create mode 100644 airesources/Haskell/lib/Halite/Types.hs
diff --git a/airesources/Haskell/halite-haskell.cabal b/airesources/Haskell/halite-haskell.cabal
index 09b20b37f..6a865f605 100644
--- a/airesources/Haskell/halite-haskell.cabal
+++ b/airesources/Haskell/halite-haskell.cabal
@@ -8,7 +8,7 @@ cabal-version: >=1.10
library
hs-source-dirs: lib
- exposed-modules: Halite, Halite.Networking
+ exposed-modules: Halite, Halite.Networking, Halite.Types
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
diff --git a/airesources/Haskell/lib/Halite.hs b/airesources/Haskell/lib/Halite.hs
index 96835ffab..ed601c1ed 100644
--- a/airesources/Haskell/lib/Halite.hs
+++ b/airesources/Haskell/lib/Halite.hs
@@ -1 +1,4 @@
module Halite where
+
+import Halite.Types
+import Halite.Networking
diff --git a/airesources/Haskell/lib/Halite/Networking.hs b/airesources/Haskell/lib/Halite/Networking.hs
index 939b2cece..ebf331162 100644
--- a/airesources/Haskell/lib/Halite/Networking.hs
+++ b/airesources/Haskell/lib/Halite/Networking.hs
@@ -1 +1,31 @@
-module Halite.Networking where
+module Halite.Networking
+ ( getInit
+ , sendInit
+ , getFrame
+ , sendMoves
+ ) where
+
+import Halite.Types
+
+getInit :: IO (ID, Map)
+getInit = do
+ userID <- read <$> getLine
+ [w, h] <- map read . words <$> getLine
+ prod <- parseProductionMap (w, h) <$> getLine
+ mapc <- parseMapContents (w, h) prod <$> getLine
+ return (userID, Map w h mapc)
+
+sendInit :: String -> IO ()
+sendInit = undefined
+
+getFrame :: IO Map
+getFrame = undefined
+
+sendMoves :: [Move] -> IO ()
+sendMoves = undefined
+
+parseProductionMap :: (Int, Int) -> String -> [[Int]]
+parseProductionMap = undefined
+
+parseMapContents :: (Int, Int) -> [[Int]] -> String -> [[Site]]
+parseMapContents = undefined
diff --git a/airesources/Haskell/lib/Halite/Types.hs b/airesources/Haskell/lib/Halite/Types.hs
new file mode 100644
index 000000000..d5492df47
--- /dev/null
+++ b/airesources/Haskell/lib/Halite/Types.hs
@@ -0,0 +1,40 @@
+module Halite.Types
+ ( Direction(..)
+ , Map(..)
+ , Location(..)
+ , Site(..)
+ , Move(..)
+ , ID
+ ) where
+
+data Direction
+ = Still
+ | North
+ | East
+ | South
+ | West
+ deriving (Show, Eq, Ord, Enum)
+
+data Location = Location
+ { locX :: Int
+ , locY :: Int
+ } deriving (Show, Eq)
+
+data Site = Site
+ { siteOwner :: Int
+ , siteStrength :: Int
+ , siteProduction :: Int
+ } deriving (Show, Eq)
+
+data Move = Move
+ { moveLocation :: Location
+ , moveDirection :: Direction
+ } deriving (Show, Eq)
+
+data Map = Map
+ { mapWidth :: Int
+ , mapHeight :: Int
+ , mapContents :: [[Site]]
+ } deriving (Show, Eq)
+
+type ID = Int
From 2f16d1f2203b8da997dc840b8016cb504f6525c4 Mon Sep 17 00:00:00 2001
From: Jesse Paroz
Date: Sun, 13 Nov 2016 01:21:06 +1000
Subject: [PATCH 03/22] Implement rest of starter pack (untested!)
---
airesources/Haskell/lib/Halite/Networking.hs | 42 +++++++++++++++-----
1 file changed, 31 insertions(+), 11 deletions(-)
diff --git a/airesources/Haskell/lib/Halite/Networking.hs b/airesources/Haskell/lib/Halite/Networking.hs
index ebf331162..6d9a92b0d 100644
--- a/airesources/Haskell/lib/Halite/Networking.hs
+++ b/airesources/Haskell/lib/Halite/Networking.hs
@@ -2,7 +2,7 @@ module Halite.Networking
( getInit
, sendInit
, getFrame
- , sendMoves
+ , sendFrame
) where
import Halite.Types
@@ -11,21 +11,41 @@ getInit :: IO (ID, Map)
getInit = do
userID <- read <$> getLine
[w, h] <- map read . words <$> getLine
- prod <- parseProductionMap (w, h) <$> getLine
+ prod <- map read . words <$> getLine
mapc <- parseMapContents (w, h) prod <$> getLine
return (userID, Map w h mapc)
sendInit :: String -> IO ()
-sendInit = undefined
+sendInit = putStrLn
-getFrame :: IO Map
-getFrame = undefined
+getFrame :: Map -> IO Map
+getFrame (Map w h cont) =
+ Map w h . parseMapContents (w, h) (getProds cont) <$> getLine
-sendMoves :: [Move] -> IO ()
-sendMoves = undefined
+sendFrame :: [Move] -> IO ()
+sendFrame = putStrLn . unwords . map showMove
-parseProductionMap :: (Int, Int) -> String -> [[Int]]
-parseProductionMap = undefined
-parseMapContents :: (Int, Int) -> [[Int]] -> String -> [[Site]]
-parseMapContents = undefined
+parseMapContents :: (Int, Int) -> [Int] -> String -> [[Site]]
+parseMapContents (w, h) pds s = splitEvery w $ zipWith3 Site ons sts pds
+ where
+ (owners, sts) = splitMapContents (read <$> words s) (w * h)
+ ons = stretch owners
+ stretch (x:y:ys) = replicate x y ++ stretch ys
+ stretch [] = []
+
+splitMapContents :: [Int] -> Int -> ([Int], [Int])
+splitMapContents xs area = splitAt (length xs - area) xs
+
+splitEvery :: Int -> [a] -> [[a]]
+splitEvery _ [] = []
+splitEvery n xs = first : splitEvery n rest
+ where
+ (first, rest) = splitAt n xs
+
+getProds :: [[Site]] -> [Int]
+getProds = map siteProduction . concat
+
+showMove :: Move -> String
+showMove (Move (Location x y) d) =
+ show x ++ " " ++ show y ++ " " ++ show (fromEnum d)
From 605683c5a470d8dbe3342bbf1319a9cb8c95cc34 Mon Sep 17 00:00:00 2001
From: Jesse Paroz
Date: Sun, 13 Nov 2016 03:51:51 +1000
Subject: [PATCH 04/22] Complete Haskell starter package and examples
---
airesources/Haskell/halite-haskell.cabal | 4 +++
airesources/Haskell/lib/Halite.hs | 5 +++-
airesources/Haskell/lib/Halite/Networking.hs | 17 ++++++++----
airesources/Haskell/lib/Halite/Types.hs | 11 +++-----
airesources/Haskell/src/MyBot.hs | 27 +++++++++++++++++++-
airesources/Haskell/src/RandomBot.hs | 27 +++++++++++++++++++-
6 files changed, 76 insertions(+), 15 deletions(-)
diff --git a/airesources/Haskell/halite-haskell.cabal b/airesources/Haskell/halite-haskell.cabal
index 6a865f605..d970e681e 100644
--- a/airesources/Haskell/halite-haskell.cabal
+++ b/airesources/Haskell/halite-haskell.cabal
@@ -17,9 +17,13 @@ executable MyBot
main-is: MyBot.hs
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
+ , halite-haskell
+ , random
executable RandomBot
hs-source-dirs: src
main-is: RandomBot.hs
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
+ , halite-haskell
+ , random
diff --git a/airesources/Haskell/lib/Halite.hs b/airesources/Haskell/lib/Halite.hs
index ed601c1ed..02655875d 100644
--- a/airesources/Haskell/lib/Halite.hs
+++ b/airesources/Haskell/lib/Halite.hs
@@ -1,4 +1,7 @@
-module Halite where
+module Halite
+ ( module Halite.Types
+ , module Halite.Networking
+ ) where
import Halite.Types
import Halite.Networking
diff --git a/airesources/Haskell/lib/Halite/Networking.hs b/airesources/Haskell/lib/Halite/Networking.hs
index 6d9a92b0d..beb56e32e 100644
--- a/airesources/Haskell/lib/Halite/Networking.hs
+++ b/airesources/Haskell/lib/Halite/Networking.hs
@@ -6,6 +6,8 @@ module Halite.Networking
) where
import Halite.Types
+import Data.List (zipWith5)
+import System.IO (hFlush, stdout)
getInit :: IO (ID, Map)
getInit = do
@@ -16,23 +18,28 @@ getInit = do
return (userID, Map w h mapc)
sendInit :: String -> IO ()
-sendInit = putStrLn
+sendInit s = putStrLn s >> hFlush stdout
getFrame :: Map -> IO Map
getFrame (Map w h cont) =
Map w h . parseMapContents (w, h) (getProds cont) <$> getLine
+sendFrame' :: [Move] -> IO ()
+sendFrame' = putStrLn . unwords . map showMove
+
sendFrame :: [Move] -> IO ()
-sendFrame = putStrLn . unwords . map showMove
+sendFrame s = sendFrame' s >> hFlush stdout
parseMapContents :: (Int, Int) -> [Int] -> String -> [[Site]]
-parseMapContents (w, h) pds s = splitEvery w $ zipWith3 Site ons sts pds
+parseMapContents (w, h) pds s = splitEvery w $ zipWith5 Site ons sts pds xs ys
where
(owners, sts) = splitMapContents (read <$> words s) (w * h)
ons = stretch owners
- stretch (x:y:ys) = replicate x y ++ stretch ys
+ stretch (a:b:bs) = replicate a b ++ stretch bs
stretch [] = []
+ xs = concat $ replicate h [0..w - 1]
+ ys = concatMap (replicate w) [0..h - 1]
splitMapContents :: [Int] -> Int -> ([Int], [Int])
splitMapContents xs area = splitAt (length xs - area) xs
@@ -47,5 +54,5 @@ getProds :: [[Site]] -> [Int]
getProds = map siteProduction . concat
showMove :: Move -> String
-showMove (Move (Location x y) d) =
+showMove (Move x y d) =
show x ++ " " ++ show y ++ " " ++ show (fromEnum d)
diff --git a/airesources/Haskell/lib/Halite/Types.hs b/airesources/Haskell/lib/Halite/Types.hs
index d5492df47..9c1a2033c 100644
--- a/airesources/Haskell/lib/Halite/Types.hs
+++ b/airesources/Haskell/lib/Halite/Types.hs
@@ -1,7 +1,6 @@
module Halite.Types
( Direction(..)
, Map(..)
- , Location(..)
, Site(..)
, Move(..)
, ID
@@ -15,19 +14,17 @@ data Direction
| West
deriving (Show, Eq, Ord, Enum)
-data Location = Location
- { locX :: Int
- , locY :: Int
- } deriving (Show, Eq)
-
data Site = Site
{ siteOwner :: Int
, siteStrength :: Int
, siteProduction :: Int
+ , siteX :: Int
+ , siteY :: Int
} deriving (Show, Eq)
data Move = Move
- { moveLocation :: Location
+ { moveX :: Int
+ , moveY :: Int
, moveDirection :: Direction
} deriving (Show, Eq)
diff --git a/airesources/Haskell/src/MyBot.hs b/airesources/Haskell/src/MyBot.hs
index a4531e1a4..5a48eaad5 100644
--- a/airesources/Haskell/src/MyBot.hs
+++ b/airesources/Haskell/src/MyBot.hs
@@ -1,3 +1,28 @@
module Main where
-main = putStrLn "hullo from MyBot"
+import Halite
+import System.Random (randomRs, getStdGen, StdGen)
+
+main :: IO ()
+main = do
+ (myID, gameMap) <- getInit
+ sendInit "MyHaskellBot"
+ dirs <- randomDirections <$> getStdGen
+ loop myID gameMap dirs
+
+loop :: ID -> Map -> [Direction] -> IO ()
+loop myID gameMap dirs = do
+ gameMap' <- getFrame gameMap
+ let sites = concat $ mapContents gameMap'
+ moves = assignMoves myID sites dirs
+ dirs' = drop (length moves) dirs
+ sendFrame moves
+ loop myID gameMap' dirs'
+
+assignMoves :: ID -> [Site] -> [Direction] -> [Move]
+assignMoves myID sites = zipWith3 Move (map siteX sites') (map siteY sites')
+ where
+ sites' = filter (\s -> siteOwner s == myID) sites
+
+randomDirections :: StdGen -> [Direction]
+randomDirections g = toEnum <$> randomRs (0, 4) g
diff --git a/airesources/Haskell/src/RandomBot.hs b/airesources/Haskell/src/RandomBot.hs
index 300cc63cf..a76d0bd1e 100644
--- a/airesources/Haskell/src/RandomBot.hs
+++ b/airesources/Haskell/src/RandomBot.hs
@@ -1,3 +1,28 @@
module Main where
-main = main
+import Halite
+import System.Random (randomRs, getStdGen, StdGen)
+
+main :: IO ()
+main = do
+ (myID, gameMap) <- getInit
+ sendInit "RandomHaskellBot"
+ dirs <- randomDirections <$> getStdGen
+ loop myID gameMap dirs
+
+loop :: ID -> Map -> [Direction] -> IO ()
+loop myID gameMap dirs = do
+ gameMap' <- getFrame gameMap
+ let sites = concat $ mapContents gameMap'
+ moves = assignMoves myID sites dirs
+ dirs' = drop (length moves) dirs
+ sendFrame moves
+ loop myID gameMap' dirs'
+
+assignMoves :: ID -> [Site] -> [Direction] -> [Move]
+assignMoves myID sites = zipWith3 Move (map siteX sites') (map siteY sites')
+ where
+ sites' = filter (\s -> siteOwner s == myID) sites
+
+randomDirections :: StdGen -> [Direction]
+randomDirections g = toEnum <$> randomRs (0, 4) g
From a017346f3812ce7770366361030b93ae32d191e3 Mon Sep 17 00:00:00 2001
From: Jesse Paroz
Date: Sun, 13 Nov 2016 03:57:28 +1000
Subject: [PATCH 05/22] Haskell: Remove erroneous LICENSE file
---
airesources/Haskell/LICENSE | 30 ------------------------------
1 file changed, 30 deletions(-)
delete mode 100644 airesources/Haskell/LICENSE
diff --git a/airesources/Haskell/LICENSE b/airesources/Haskell/LICENSE
deleted file mode 100644
index 3cd48fe71..000000000
--- a/airesources/Haskell/LICENSE
+++ /dev/null
@@ -1,30 +0,0 @@
-Copyright Jesse Paroz (c) 2016
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
-
- * Neither the name of Jesse Paroz nor the names of other
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
From 15845d29b813dd0d95b35af321704da7fcbe2d60 Mon Sep 17 00:00:00 2001
From: Josef Vonasek
Date: Mon, 14 Nov 2016 13:52:21 -0500
Subject: [PATCH 06/22] I have provided the src/ scripts with new interface,
hopefuly more convenient for the user.
---
.gitignore | 3 ++
airesources/Haskell/halite-haskell.cabal | 5 ++-
airesources/Haskell/lib/Halite.hs | 8 ++--
airesources/Haskell/lib/Halite/Classes.hs | 12 ++++++
airesources/Haskell/lib/Halite/Networking.hs | 28 +++++++++++---
airesources/Haskell/lib/Halite/Types.hs | 33 +++++++++++++++--
airesources/Haskell/src/MyBot.hs | 39 ++++++++++----------
airesources/Haskell/src/RandomBot.hs | 39 ++++++++++----------
8 files changed, 112 insertions(+), 55 deletions(-)
create mode 100644 airesources/Haskell/lib/Halite/Classes.hs
diff --git a/.gitignore b/.gitignore
index 189a8098c..9680c76bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -372,3 +372,6 @@ google*.html
screenlog.*
*.dll
+
+node_modules
+/dist
diff --git a/airesources/Haskell/halite-haskell.cabal b/airesources/Haskell/halite-haskell.cabal
index d970e681e..17743ff1b 100644
--- a/airesources/Haskell/halite-haskell.cabal
+++ b/airesources/Haskell/halite-haskell.cabal
@@ -2,15 +2,18 @@ name: halite-haskell
version: 0.1.0.0
synopsis: Halite starter pack for Haskell
author: Jesse Paroz
+ , Josef Vonasek
maintainer: jesse.paroz@gmail.com
+ , j.f.vonasek@gmail.com
build-type: Simple
cabal-version: >=1.10
library
hs-source-dirs: lib
- exposed-modules: Halite, Halite.Networking, Halite.Types
+ exposed-modules: Halite, Halite.Networking, Halite.Types, Halite.Classes
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
+ , random
executable MyBot
hs-source-dirs: src
diff --git a/airesources/Haskell/lib/Halite.hs b/airesources/Haskell/lib/Halite.hs
index 02655875d..4aa9ae102 100644
--- a/airesources/Haskell/lib/Halite.hs
+++ b/airesources/Haskell/lib/Halite.hs
@@ -1,7 +1,7 @@
module Halite
- ( module Halite.Types
- , module Halite.Networking
+ ( module M
) where
-import Halite.Types
-import Halite.Networking
+import Halite.Networking as M
+import Halite.Classes as M
+import Halite.Types as M
diff --git a/airesources/Haskell/lib/Halite/Classes.hs b/airesources/Haskell/lib/Halite/Classes.hs
new file mode 100644
index 000000000..1ec68aebd
--- /dev/null
+++ b/airesources/Haskell/lib/Halite/Classes.hs
@@ -0,0 +1,12 @@
+module Halite.Classes
+ ( RandomReader(..)
+ ) where
+
+-- use type classes to manage side effects for your algorithm function
+-- if you want to add your custom side effect just create a new class
+-- class Monad m => MyCustomSideEffect m where ...
+-- and change type signature of your algorithm to
+-- algorithm :: (MyCustomSideEffect m, RandomReader m) => .... -> m [Move]
+
+class Monad m => RandomReader m where
+ rand :: Int -> m Int
diff --git a/airesources/Haskell/lib/Halite/Networking.hs b/airesources/Haskell/lib/Halite/Networking.hs
index beb56e32e..faf619bd4 100644
--- a/airesources/Haskell/lib/Halite/Networking.hs
+++ b/airesources/Haskell/lib/Halite/Networking.hs
@@ -1,14 +1,29 @@
module Halite.Networking
- ( getInit
- , sendInit
- , getFrame
- , sendFrame
+ ( communicate
) where
import Halite.Types
import Data.List (zipWith5)
+import System.Random (getStdGen)
import System.IO (hFlush, stdout)
+communicate
+ :: Monad m
+ => String
+ -> (ID -> Map -> m [Move])
+ -> a -> (m [Move] -> a -> ([Move], a))
+ -> IO ()
+communicate name algorithm input runMonad = do
+ (myID, gameMap) <- getInit
+ sendInit name
+ loop (algorithm myID) gameMap input runMonad
+
+loop algorithm gameMap input runMonad = do
+ gameMap' <- getFrame gameMap
+ let (moves, input') = runMonad (algorithm gameMap') input
+ sendFrame moves
+ loop algorithm gameMap' input' runMonad
+
getInit :: IO (ID, Map)
getInit = do
userID <- read <$> getLine
@@ -32,7 +47,7 @@ sendFrame s = sendFrame' s >> hFlush stdout
parseMapContents :: (Int, Int) -> [Int] -> String -> [[Site]]
-parseMapContents (w, h) pds s = splitEvery w $ zipWith5 Site ons sts pds xs ys
+parseMapContents (w, h) pds s = splitEvery w $ zipWith5 Site ons sts pds locations
where
(owners, sts) = splitMapContents (read <$> words s) (w * h)
ons = stretch owners
@@ -40,6 +55,7 @@ parseMapContents (w, h) pds s = splitEvery w $ zipWith5 Site ons sts pds xs ys
stretch [] = []
xs = concat $ replicate h [0..w - 1]
ys = concatMap (replicate w) [0..h - 1]
+ locations = zipWith Location xs ys
splitMapContents :: [Int] -> Int -> ([Int], [Int])
splitMapContents xs area = splitAt (length xs - area) xs
@@ -54,5 +70,5 @@ getProds :: [[Site]] -> [Int]
getProds = map siteProduction . concat
showMove :: Move -> String
-showMove (Move x y d) =
+showMove (Move (Location x y) d) =
show x ++ " " ++ show y ++ " " ++ show (fromEnum d)
diff --git a/airesources/Haskell/lib/Halite/Types.hs b/airesources/Haskell/lib/Halite/Types.hs
index 9c1a2033c..dca6313cd 100644
--- a/airesources/Haskell/lib/Halite/Types.hs
+++ b/airesources/Haskell/lib/Halite/Types.hs
@@ -1,11 +1,19 @@
+{-# LANGUAGE DeriveFunctor, DeriveAnyClass #-}
+
module Halite.Types
( Direction(..)
+ , Location(..)
, Map(..)
, Site(..)
, Move(..)
, ID
+ , Effects(runEffects)
+ , Test(runTest)
) where
+import System.Random (StdGen, randomR)
+import Halite.Classes
+
data Direction
= Still
| North
@@ -14,17 +22,20 @@ data Direction
| West
deriving (Show, Eq, Ord, Enum)
+data Location = Location
+ { posX :: Int
+ , posY :: Int
+ } deriving (Show, Eq)
+
data Site = Site
{ siteOwner :: Int
, siteStrength :: Int
, siteProduction :: Int
- , siteX :: Int
- , siteY :: Int
+ , siteLocation :: Location
} deriving (Show, Eq)
data Move = Move
- { moveX :: Int
- , moveY :: Int
+ { movelocation :: Location
, moveDirection :: Direction
} deriving (Show, Eq)
@@ -35,3 +46,17 @@ data Map = Map
} deriving (Show, Eq)
type ID = Int
+
+-- these two monads allow you to use side effects in your algorithm
+
+data Effects a = Effects {runEffects :: StdGen -> (a, StdGen)}
+ deriving (Functor, Applicative, Monad)
+
+instance RandomReader Effects where
+ rand i = Effects $ randomR (0, i)
+
+data Test a = Test {runTest :: [Int] -> (a, [Int])}
+ deriving (Functor, Applicative, Monad)
+
+instance RandomReader Test where
+ rand i = Test $ \(x:xs) -> (mod x i, xs)
diff --git a/airesources/Haskell/src/MyBot.hs b/airesources/Haskell/src/MyBot.hs
index 5a48eaad5..feef45f65 100644
--- a/airesources/Haskell/src/MyBot.hs
+++ b/airesources/Haskell/src/MyBot.hs
@@ -1,28 +1,27 @@
module Main where
+import System.Random (getStdGen)
import Halite
-import System.Random (randomRs, getStdGen, StdGen)
main :: IO ()
-main = do
- (myID, gameMap) <- getInit
- sendInit "MyHaskellBot"
- dirs <- randomDirections <$> getStdGen
- loop myID gameMap dirs
+main = communicate name algorithm runEffects <$> getStdGen
-loop :: ID -> Map -> [Direction] -> IO ()
-loop myID gameMap dirs = do
- gameMap' <- getFrame gameMap
- let sites = concat $ mapContents gameMap'
- moves = assignMoves myID sites dirs
- dirs' = drop (length moves) dirs
- sendFrame moves
- loop myID gameMap' dirs'
+name = "Awesome Haskell Bot"
-assignMoves :: ID -> [Site] -> [Direction] -> [Move]
-assignMoves myID sites = zipWith3 Move (map siteX sites') (map siteY sites')
- where
- sites' = filter (\s -> siteOwner s == myID) sites
+algorithm :: RandomReader m => ID -> Map -> m [Move]
+algorithm me g@(GameMap width height sites) =
+ randomMoves
+ [Location x y | x <- [1..width], y <- [1..height]] $
+ fmap (isMy me) sites
-randomDirections :: StdGen -> [Direction]
-randomDirections g = toEnum <$> randomRs (0, 4) g
+randomMoves :: RandomReader m => [Location] -> [Bool] -> m [Move]
+randomMoves l = traverse randMove . filter' l
+ where
+ filter' :: [a] -> [Bool] -> [a]
+ filter' [] [] = []
+ filter' (a:as) (True:bs) = a : filter' as bs
+ filter' (_:as) (False:bs) = filter' as bs
+ randMove :: RandomReader r => Location -> r Move
+ randMove location = do
+ direction <- toEnum <$> randR 5
+ return $ Move location direction
diff --git a/airesources/Haskell/src/RandomBot.hs b/airesources/Haskell/src/RandomBot.hs
index a76d0bd1e..feef45f65 100644
--- a/airesources/Haskell/src/RandomBot.hs
+++ b/airesources/Haskell/src/RandomBot.hs
@@ -1,28 +1,27 @@
module Main where
+import System.Random (getStdGen)
import Halite
-import System.Random (randomRs, getStdGen, StdGen)
main :: IO ()
-main = do
- (myID, gameMap) <- getInit
- sendInit "RandomHaskellBot"
- dirs <- randomDirections <$> getStdGen
- loop myID gameMap dirs
+main = communicate name algorithm runEffects <$> getStdGen
-loop :: ID -> Map -> [Direction] -> IO ()
-loop myID gameMap dirs = do
- gameMap' <- getFrame gameMap
- let sites = concat $ mapContents gameMap'
- moves = assignMoves myID sites dirs
- dirs' = drop (length moves) dirs
- sendFrame moves
- loop myID gameMap' dirs'
+name = "Awesome Haskell Bot"
-assignMoves :: ID -> [Site] -> [Direction] -> [Move]
-assignMoves myID sites = zipWith3 Move (map siteX sites') (map siteY sites')
- where
- sites' = filter (\s -> siteOwner s == myID) sites
+algorithm :: RandomReader m => ID -> Map -> m [Move]
+algorithm me g@(GameMap width height sites) =
+ randomMoves
+ [Location x y | x <- [1..width], y <- [1..height]] $
+ fmap (isMy me) sites
-randomDirections :: StdGen -> [Direction]
-randomDirections g = toEnum <$> randomRs (0, 4) g
+randomMoves :: RandomReader m => [Location] -> [Bool] -> m [Move]
+randomMoves l = traverse randMove . filter' l
+ where
+ filter' :: [a] -> [Bool] -> [a]
+ filter' [] [] = []
+ filter' (a:as) (True:bs) = a : filter' as bs
+ filter' (_:as) (False:bs) = filter' as bs
+ randMove :: RandomReader r => Location -> r Move
+ randMove location = do
+ direction <- toEnum <$> randR 5
+ return $ Move location direction
From 36a3dacc5b2219dabed0540fb98b454f72a2ed28 Mon Sep 17 00:00:00 2001
From: Jesse Paroz
Date: Tue, 15 Nov 2016 13:45:23 +1000
Subject: [PATCH 07/22] Fix typos and simple copy-paste type errors
---
airesources/Haskell/lib/Halite/Networking.hs | 4 ++--
airesources/Haskell/src/MyBot.hs | 13 +++++++++----
airesources/Haskell/src/RandomBot.hs | 13 +++++++++----
3 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/airesources/Haskell/lib/Halite/Networking.hs b/airesources/Haskell/lib/Halite/Networking.hs
index faf619bd4..07685883e 100644
--- a/airesources/Haskell/lib/Halite/Networking.hs
+++ b/airesources/Haskell/lib/Halite/Networking.hs
@@ -3,7 +3,7 @@ module Halite.Networking
) where
import Halite.Types
-import Data.List (zipWith5)
+import Data.List (zipWith4)
import System.Random (getStdGen)
import System.IO (hFlush, stdout)
@@ -47,7 +47,7 @@ sendFrame s = sendFrame' s >> hFlush stdout
parseMapContents :: (Int, Int) -> [Int] -> String -> [[Site]]
-parseMapContents (w, h) pds s = splitEvery w $ zipWith5 Site ons sts pds locations
+parseMapContents (w, h) pds s = splitEvery w $ zipWith4 Site ons sts pds locations
where
(owners, sts) = splitMapContents (read <$> words s) (w * h)
ons = stretch owners
diff --git a/airesources/Haskell/src/MyBot.hs b/airesources/Haskell/src/MyBot.hs
index feef45f65..879349f38 100644
--- a/airesources/Haskell/src/MyBot.hs
+++ b/airesources/Haskell/src/MyBot.hs
@@ -4,15 +4,17 @@ import System.Random (getStdGen)
import Halite
main :: IO ()
-main = communicate name algorithm runEffects <$> getStdGen
+main = do
+ input <- getStdGen
+ communicate name algorithm input runEffects
name = "Awesome Haskell Bot"
algorithm :: RandomReader m => ID -> Map -> m [Move]
-algorithm me g@(GameMap width height sites) =
+algorithm me (Map width height sites) =
randomMoves
[Location x y | x <- [1..width], y <- [1..height]] $
- fmap (isMy me) sites
+ fmap (ownedBy me) (concat sites)
randomMoves :: RandomReader m => [Location] -> [Bool] -> m [Move]
randomMoves l = traverse randMove . filter' l
@@ -23,5 +25,8 @@ randomMoves l = traverse randMove . filter' l
filter' (_:as) (False:bs) = filter' as bs
randMove :: RandomReader r => Location -> r Move
randMove location = do
- direction <- toEnum <$> randR 5
+ direction <- toEnum <$> rand 5
return $ Move location direction
+
+ownedBy :: ID -> Site -> Bool
+ownedBy userID site = siteOwner site == userID
diff --git a/airesources/Haskell/src/RandomBot.hs b/airesources/Haskell/src/RandomBot.hs
index feef45f65..879349f38 100644
--- a/airesources/Haskell/src/RandomBot.hs
+++ b/airesources/Haskell/src/RandomBot.hs
@@ -4,15 +4,17 @@ import System.Random (getStdGen)
import Halite
main :: IO ()
-main = communicate name algorithm runEffects <$> getStdGen
+main = do
+ input <- getStdGen
+ communicate name algorithm input runEffects
name = "Awesome Haskell Bot"
algorithm :: RandomReader m => ID -> Map -> m [Move]
-algorithm me g@(GameMap width height sites) =
+algorithm me (Map width height sites) =
randomMoves
[Location x y | x <- [1..width], y <- [1..height]] $
- fmap (isMy me) sites
+ fmap (ownedBy me) (concat sites)
randomMoves :: RandomReader m => [Location] -> [Bool] -> m [Move]
randomMoves l = traverse randMove . filter' l
@@ -23,5 +25,8 @@ randomMoves l = traverse randMove . filter' l
filter' (_:as) (False:bs) = filter' as bs
randMove :: RandomReader r => Location -> r Move
randMove location = do
- direction <- toEnum <$> randR 5
+ direction <- toEnum <$> rand 5
return $ Move location direction
+
+ownedBy :: ID -> Site -> Bool
+ownedBy userID site = siteOwner site == userID
From e66ad3dbef700abbc1478c9ecf27abd8b04809b4 Mon Sep 17 00:00:00 2001
From: Jesse Paroz
Date: Tue, 15 Nov 2016 14:58:00 +1000
Subject: [PATCH 08/22] Added manual instances for Effects and Test
---
airesources/Haskell/lib/Halite/Types.hs | 30 ++++++++++++++++++++-----
airesources/Haskell/src/MyBot.hs | 2 +-
airesources/Haskell/src/RandomBot.hs | 2 +-
3 files changed, 27 insertions(+), 7 deletions(-)
diff --git a/airesources/Haskell/lib/Halite/Types.hs b/airesources/Haskell/lib/Halite/Types.hs
index dca6313cd..67a74ff67 100644
--- a/airesources/Haskell/lib/Halite/Types.hs
+++ b/airesources/Haskell/lib/Halite/Types.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE DeriveFunctor, DeriveAnyClass #-}
+{-# LANGUAGE DeriveFunctor #-}
module Halite.Types
( Direction(..)
@@ -7,10 +7,12 @@ module Halite.Types
, Site(..)
, Move(..)
, ID
- , Effects(runEffects)
- , Test(runTest)
+ , Effects(..)
+ , Test(..)
) where
+
+import Control.Monad (ap)
import System.Random (StdGen, randomR)
import Halite.Classes
@@ -50,13 +52,31 @@ type ID = Int
-- these two monads allow you to use side effects in your algorithm
data Effects a = Effects {runEffects :: StdGen -> (a, StdGen)}
- deriving (Functor, Applicative, Monad)
+ deriving (Functor)
+
+instance Applicative Effects where
+ pure x = Effects (\y -> (x, y))
+ (<*>) = ap
+
+instance Monad Effects where
+ m >>= k = Effects $ \s ->
+ let (a, s') = runEffects m s
+ in runEffects (k a) s'
instance RandomReader Effects where
rand i = Effects $ randomR (0, i)
data Test a = Test {runTest :: [Int] -> (a, [Int])}
- deriving (Functor, Applicative, Monad)
+ deriving (Functor)
+
+instance Applicative Test where
+ pure x = Test (\y -> (x, y))
+ (<*>) = ap
+
+instance Monad Test where
+ m >>= k = Test $ \s ->
+ let (a, s') = runTest m s
+ in runTest (k a) s'
instance RandomReader Test where
rand i = Test $ \(x:xs) -> (mod x i, xs)
diff --git a/airesources/Haskell/src/MyBot.hs b/airesources/Haskell/src/MyBot.hs
index 879349f38..0d3a5d3b9 100644
--- a/airesources/Haskell/src/MyBot.hs
+++ b/airesources/Haskell/src/MyBot.hs
@@ -25,7 +25,7 @@ randomMoves l = traverse randMove . filter' l
filter' (_:as) (False:bs) = filter' as bs
randMove :: RandomReader r => Location -> r Move
randMove location = do
- direction <- toEnum <$> rand 5
+ direction <- toEnum <$> rand 4
return $ Move location direction
ownedBy :: ID -> Site -> Bool
diff --git a/airesources/Haskell/src/RandomBot.hs b/airesources/Haskell/src/RandomBot.hs
index 879349f38..0d3a5d3b9 100644
--- a/airesources/Haskell/src/RandomBot.hs
+++ b/airesources/Haskell/src/RandomBot.hs
@@ -25,7 +25,7 @@ randomMoves l = traverse randMove . filter' l
filter' (_:as) (False:bs) = filter' as bs
randMove :: RandomReader r => Location -> r Move
randMove location = do
- direction <- toEnum <$> rand 5
+ direction <- toEnum <$> rand 4
return $ Move location direction
ownedBy :: ID -> Site -> Bool
From 8518f87b7fdc3fa0fa98394d7599571ebe68f813 Mon Sep 17 00:00:00 2001
From: Jesse Paroz
Date: Tue, 15 Nov 2016 15:02:50 +1000
Subject: [PATCH 09/22] Improve showMove definition
---
airesources/Haskell/lib/Halite/Networking.hs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/airesources/Haskell/lib/Halite/Networking.hs b/airesources/Haskell/lib/Halite/Networking.hs
index 07685883e..b9b3213d8 100644
--- a/airesources/Haskell/lib/Halite/Networking.hs
+++ b/airesources/Haskell/lib/Halite/Networking.hs
@@ -70,5 +70,4 @@ getProds :: [[Site]] -> [Int]
getProds = map siteProduction . concat
showMove :: Move -> String
-showMove (Move (Location x y) d) =
- show x ++ " " ++ show y ++ " " ++ show (fromEnum d)
+showMove (Move (Location x y) d) = unwords $ map show [x, y, fromEnum d]
From e9a9d96a31fd0a17af92348d0e7516260f1fcc33 Mon Sep 17 00:00:00 2001
From: Jesse Paroz
Date: Tue, 15 Nov 2016 15:31:15 +1000
Subject: [PATCH 10/22] Fix bug, should start indexing from 0
Also renamed variables in parseMapContents to aid readability
---
airesources/Haskell/lib/Halite/Networking.hs | 11 ++++++-----
airesources/Haskell/src/MyBot.hs | 2 +-
airesources/Haskell/src/RandomBot.hs | 2 +-
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/airesources/Haskell/lib/Halite/Networking.hs b/airesources/Haskell/lib/Halite/Networking.hs
index b9b3213d8..418172f65 100644
--- a/airesources/Haskell/lib/Halite/Networking.hs
+++ b/airesources/Haskell/lib/Halite/Networking.hs
@@ -47,14 +47,15 @@ sendFrame s = sendFrame' s >> hFlush stdout
parseMapContents :: (Int, Int) -> [Int] -> String -> [[Site]]
-parseMapContents (w, h) pds s = splitEvery w $ zipWith4 Site ons sts pds locations
+parseMapContents (w, h) productions s =
+ splitEvery w $ zipWith4 Site owners strengths productions locations
where
- (owners, sts) = splitMapContents (read <$> words s) (w * h)
- ons = stretch owners
+ (owners', strengths) = splitMapContents (read <$> words s) (w * h)
+ owners = stretch owners'
stretch (a:b:bs) = replicate a b ++ stretch bs
stretch [] = []
- xs = concat $ replicate h [0..w - 1]
- ys = concatMap (replicate w) [0..h - 1]
+ xs = concat $ replicate h [0 .. w - 1]
+ ys = concatMap (replicate w) [0 .. h - 1]
locations = zipWith Location xs ys
splitMapContents :: [Int] -> Int -> ([Int], [Int])
diff --git a/airesources/Haskell/src/MyBot.hs b/airesources/Haskell/src/MyBot.hs
index 0d3a5d3b9..bc7c0d770 100644
--- a/airesources/Haskell/src/MyBot.hs
+++ b/airesources/Haskell/src/MyBot.hs
@@ -13,7 +13,7 @@ name = "Awesome Haskell Bot"
algorithm :: RandomReader m => ID -> Map -> m [Move]
algorithm me (Map width height sites) =
randomMoves
- [Location x y | x <- [1..width], y <- [1..height]] $
+ [Location x y | x <- [0..width-1], y <- [0..height-1]] $
fmap (ownedBy me) (concat sites)
randomMoves :: RandomReader m => [Location] -> [Bool] -> m [Move]
diff --git a/airesources/Haskell/src/RandomBot.hs b/airesources/Haskell/src/RandomBot.hs
index 0d3a5d3b9..bc7c0d770 100644
--- a/airesources/Haskell/src/RandomBot.hs
+++ b/airesources/Haskell/src/RandomBot.hs
@@ -13,7 +13,7 @@ name = "Awesome Haskell Bot"
algorithm :: RandomReader m => ID -> Map -> m [Move]
algorithm me (Map width height sites) =
randomMoves
- [Location x y | x <- [1..width], y <- [1..height]] $
+ [Location x y | x <- [0..width-1], y <- [0..height-1]] $
fmap (ownedBy me) (concat sites)
randomMoves :: RandomReader m => [Location] -> [Bool] -> m [Move]
From bce63b1a254dd17e6f97e5c3cc38f6cd1eda300b Mon Sep 17 00:00:00 2001
From: Josef Vonasek
Date: Tue, 15 Nov 2016 01:33:09 -0500
Subject: [PATCH 11/22] Fixed typecheck errors.
---
airesources/Haskell/.gitignore | 1 +
airesources/Haskell/lib/Halite/Networking.hs | 9 +++++----
airesources/Haskell/src/MyBot.hs | 19 ++++++-------------
airesources/Haskell/src/RandomBot.hs | 19 ++++++-------------
4 files changed, 18 insertions(+), 30 deletions(-)
create mode 100644 airesources/Haskell/.gitignore
diff --git a/airesources/Haskell/.gitignore b/airesources/Haskell/.gitignore
new file mode 100644
index 000000000..3a5b47571
--- /dev/null
+++ b/airesources/Haskell/.gitignore
@@ -0,0 +1 @@
+.stack-work/
diff --git a/airesources/Haskell/lib/Halite/Networking.hs b/airesources/Haskell/lib/Halite/Networking.hs
index faf619bd4..8287cdb30 100644
--- a/airesources/Haskell/lib/Halite/Networking.hs
+++ b/airesources/Haskell/lib/Halite/Networking.hs
@@ -3,7 +3,7 @@ module Halite.Networking
) where
import Halite.Types
-import Data.List (zipWith5)
+import Data.List (zipWith4)
import System.Random (getStdGen)
import System.IO (hFlush, stdout)
@@ -11,9 +11,10 @@ communicate
:: Monad m
=> String
-> (ID -> Map -> m [Move])
- -> a -> (m [Move] -> a -> ([Move], a))
+ -> (m [Move] -> a -> ([Move], a))
+ -> a
-> IO ()
-communicate name algorithm input runMonad = do
+communicate name algorithm runMonad input = do
(myID, gameMap) <- getInit
sendInit name
loop (algorithm myID) gameMap input runMonad
@@ -47,7 +48,7 @@ sendFrame s = sendFrame' s >> hFlush stdout
parseMapContents :: (Int, Int) -> [Int] -> String -> [[Site]]
-parseMapContents (w, h) pds s = splitEvery w $ zipWith5 Site ons sts pds locations
+parseMapContents (w, h) pds s = splitEvery w $ zipWith4 Site ons sts pds locations
where
(owners, sts) = splitMapContents (read <$> words s) (w * h)
ons = stretch owners
diff --git a/airesources/Haskell/src/MyBot.hs b/airesources/Haskell/src/MyBot.hs
index feef45f65..534983b14 100644
--- a/airesources/Haskell/src/MyBot.hs
+++ b/airesources/Haskell/src/MyBot.hs
@@ -4,24 +4,17 @@ import System.Random (getStdGen)
import Halite
main :: IO ()
-main = communicate name algorithm runEffects <$> getStdGen
+main = getStdGen >>= communicate name algorithm runEffects
name = "Awesome Haskell Bot"
algorithm :: RandomReader m => ID -> Map -> m [Move]
-algorithm me g@(GameMap width height sites) =
- randomMoves
- [Location x y | x <- [1..width], y <- [1..height]] $
- fmap (isMy me) sites
+algorithm me g@(Map width height sites) =
+ randomMoves $ filter ( \s -> siteOwner s == me ) (concat sites)
-randomMoves :: RandomReader m => [Location] -> [Bool] -> m [Move]
-randomMoves l = traverse randMove . filter' l
+randomMoves :: RandomReader m => [Site] -> m [Move]
+randomMoves = traverse $ randMove . siteLocation
where
- filter' :: [a] -> [Bool] -> [a]
- filter' [] [] = []
- filter' (a:as) (True:bs) = a : filter' as bs
- filter' (_:as) (False:bs) = filter' as bs
- randMove :: RandomReader r => Location -> r Move
randMove location = do
- direction <- toEnum <$> randR 5
+ direction <- toEnum <$> rand 5
return $ Move location direction
diff --git a/airesources/Haskell/src/RandomBot.hs b/airesources/Haskell/src/RandomBot.hs
index feef45f65..534983b14 100644
--- a/airesources/Haskell/src/RandomBot.hs
+++ b/airesources/Haskell/src/RandomBot.hs
@@ -4,24 +4,17 @@ import System.Random (getStdGen)
import Halite
main :: IO ()
-main = communicate name algorithm runEffects <$> getStdGen
+main = getStdGen >>= communicate name algorithm runEffects
name = "Awesome Haskell Bot"
algorithm :: RandomReader m => ID -> Map -> m [Move]
-algorithm me g@(GameMap width height sites) =
- randomMoves
- [Location x y | x <- [1..width], y <- [1..height]] $
- fmap (isMy me) sites
+algorithm me g@(Map width height sites) =
+ randomMoves $ filter ( \s -> siteOwner s == me ) (concat sites)
-randomMoves :: RandomReader m => [Location] -> [Bool] -> m [Move]
-randomMoves l = traverse randMove . filter' l
+randomMoves :: RandomReader m => [Site] -> m [Move]
+randomMoves = traverse $ randMove . siteLocation
where
- filter' :: [a] -> [Bool] -> [a]
- filter' [] [] = []
- filter' (a:as) (True:bs) = a : filter' as bs
- filter' (_:as) (False:bs) = filter' as bs
- randMove :: RandomReader r => Location -> r Move
randMove location = do
- direction <- toEnum <$> randR 5
+ direction <- toEnum <$> rand 5
return $ Move location direction
From 9327aa8c45c4bfa5c000b5d24aed96cb16d91125 Mon Sep 17 00:00:00 2001
From: Jesse Paroz
Date: Tue, 15 Nov 2016 16:32:08 +1000
Subject: [PATCH 12/22] Fix incorrectly generating locations in algorithm
A list comprehension generates almost the right list, but in the wrong
order. The way the list was used, the order must correspond to the order
of Bools in the second list, or else you end up with nonsense moves,
sending requests for unowned sites to move.
I changed it to use the more precise method used in the library
function, but probably a neater way to do things would be to simply
filter the list of sites based on owner, then map `siteLocation` over
the resulting list.
---
airesources/Haskell/src/MyBot.hs | 6 +++++-
airesources/Haskell/src/RandomBot.hs | 6 +++++-
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/airesources/Haskell/src/MyBot.hs b/airesources/Haskell/src/MyBot.hs
index bc7c0d770..7a4db05f8 100644
--- a/airesources/Haskell/src/MyBot.hs
+++ b/airesources/Haskell/src/MyBot.hs
@@ -13,8 +13,12 @@ name = "Awesome Haskell Bot"
algorithm :: RandomReader m => ID -> Map -> m [Move]
algorithm me (Map width height sites) =
randomMoves
- [Location x y | x <- [0..width-1], y <- [0..height-1]] $
+ locations $
fmap (ownedBy me) (concat sites)
+ where
+ xs = concat $ replicate height [0 .. width - 1]
+ ys = concatMap (replicate width) [0 .. height - 1]
+ locations = zipWith Location xs ys
randomMoves :: RandomReader m => [Location] -> [Bool] -> m [Move]
randomMoves l = traverse randMove . filter' l
diff --git a/airesources/Haskell/src/RandomBot.hs b/airesources/Haskell/src/RandomBot.hs
index bc7c0d770..7a4db05f8 100644
--- a/airesources/Haskell/src/RandomBot.hs
+++ b/airesources/Haskell/src/RandomBot.hs
@@ -13,8 +13,12 @@ name = "Awesome Haskell Bot"
algorithm :: RandomReader m => ID -> Map -> m [Move]
algorithm me (Map width height sites) =
randomMoves
- [Location x y | x <- [0..width-1], y <- [0..height-1]] $
+ locations $
fmap (ownedBy me) (concat sites)
+ where
+ xs = concat $ replicate height [0 .. width - 1]
+ ys = concatMap (replicate width) [0 .. height - 1]
+ locations = zipWith Location xs ys
randomMoves :: RandomReader m => [Location] -> [Bool] -> m [Move]
randomMoves l = traverse randMove . filter' l
From bdd1480ee6acf78970475880f9059f2e48e9f9d7 Mon Sep 17 00:00:00 2001
From: Josef Vonasek
Date: Wed, 16 Nov 2016 05:03:13 -0500
Subject: [PATCH 13/22] Few tweaks.
---
airesources/Haskell/.gitignore | 2 ++
airesources/Haskell/lib/Halite/Networking.hs | 14 ++++-----
airesources/Haskell/lib/Halite/Types.hs | 30 ++++++++++++++++----
airesources/Haskell/src/MyBot.hs | 2 +-
airesources/Haskell/src/RandomBot.hs | 4 +--
5 files changed, 37 insertions(+), 15 deletions(-)
diff --git a/airesources/Haskell/.gitignore b/airesources/Haskell/.gitignore
index 3a5b47571..24047bee7 100644
--- a/airesources/Haskell/.gitignore
+++ b/airesources/Haskell/.gitignore
@@ -1 +1,3 @@
.stack-work/
+halite.exe
+halite
diff --git a/airesources/Haskell/lib/Halite/Networking.hs b/airesources/Haskell/lib/Halite/Networking.hs
index 8287cdb30..6e409896d 100644
--- a/airesources/Haskell/lib/Halite/Networking.hs
+++ b/airesources/Haskell/lib/Halite/Networking.hs
@@ -48,14 +48,15 @@ sendFrame s = sendFrame' s >> hFlush stdout
parseMapContents :: (Int, Int) -> [Int] -> String -> [[Site]]
-parseMapContents (w, h) pds s = splitEvery w $ zipWith4 Site ons sts pds locations
+parseMapContents (w, h) productions s =
+ splitEvery w $ zipWith4 Site owners strengths productions locations
where
- (owners, sts) = splitMapContents (read <$> words s) (w * h)
- ons = stretch owners
+ (owners', strengths) = splitMapContents (read <$> words s) (w * h)
+ owners = stretch owners'
stretch (a:b:bs) = replicate a b ++ stretch bs
stretch [] = []
- xs = concat $ replicate h [0..w - 1]
- ys = concatMap (replicate w) [0..h - 1]
+ xs = concat $ replicate h [0 .. w - 1]
+ ys = concatMap (replicate w) [0 .. h - 1]
locations = zipWith Location xs ys
splitMapContents :: [Int] -> Int -> ([Int], [Int])
@@ -71,5 +72,4 @@ getProds :: [[Site]] -> [Int]
getProds = map siteProduction . concat
showMove :: Move -> String
-showMove (Move (Location x y) d) =
- show x ++ " " ++ show y ++ " " ++ show (fromEnum d)
+showMove (Move (Location x y) d) = unwords $ map show [x, y, fromEnum d]
diff --git a/airesources/Haskell/lib/Halite/Types.hs b/airesources/Haskell/lib/Halite/Types.hs
index dca6313cd..b4cf10224 100644
--- a/airesources/Haskell/lib/Halite/Types.hs
+++ b/airesources/Haskell/lib/Halite/Types.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE DeriveFunctor, DeriveAnyClass #-}
+{-# LANGUAGE DeriveFunctor #-}
module Halite.Types
( Direction(..)
@@ -7,10 +7,12 @@ module Halite.Types
, Site(..)
, Move(..)
, ID
- , Effects(runEffects)
+ , Effects(runEffects) -- you don't want to export constructor
, Test(runTest)
) where
+
+import Control.Monad (ap)
import System.Random (StdGen, randomR)
import Halite.Classes
@@ -50,13 +52,31 @@ type ID = Int
-- these two monads allow you to use side effects in your algorithm
data Effects a = Effects {runEffects :: StdGen -> (a, StdGen)}
- deriving (Functor, Applicative, Monad)
+ deriving (Functor)
+
+instance Applicative Effects where
+ pure x = Effects (\y -> (x, y))
+ (<*>) = ap
+
+instance Monad Effects where
+ m >>= k = Effects $ \s ->
+ let (a, s') = runEffects m s
+ in runEffects (k a) s'
instance RandomReader Effects where
- rand i = Effects $ randomR (0, i)
+ rand i = Effects $ randomR (0, i-1)
data Test a = Test {runTest :: [Int] -> (a, [Int])}
- deriving (Functor, Applicative, Monad)
+ deriving (Functor)
+
+instance Applicative Test where
+ pure x = Test (\y -> (x, y))
+ (<*>) = ap
+
+instance Monad Test where
+ m >>= k = Test $ \s ->
+ let (a, s') = runTest m s
+ in runTest (k a) s'
instance RandomReader Test where
rand i = Test $ \(x:xs) -> (mod x i, xs)
diff --git a/airesources/Haskell/src/MyBot.hs b/airesources/Haskell/src/MyBot.hs
index 534983b14..035661b8e 100644
--- a/airesources/Haskell/src/MyBot.hs
+++ b/airesources/Haskell/src/MyBot.hs
@@ -10,7 +10,7 @@ name = "Awesome Haskell Bot"
algorithm :: RandomReader m => ID -> Map -> m [Move]
algorithm me g@(Map width height sites) =
- randomMoves $ filter ( \s -> siteOwner s == me ) (concat sites)
+ randomMoves $ filter ((== me) . siteOwner) (concat sites)
randomMoves :: RandomReader m => [Site] -> m [Move]
randomMoves = traverse $ randMove . siteLocation
diff --git a/airesources/Haskell/src/RandomBot.hs b/airesources/Haskell/src/RandomBot.hs
index 534983b14..ddb2546ca 100644
--- a/airesources/Haskell/src/RandomBot.hs
+++ b/airesources/Haskell/src/RandomBot.hs
@@ -6,11 +6,11 @@ import Halite
main :: IO ()
main = getStdGen >>= communicate name algorithm runEffects
-name = "Awesome Haskell Bot"
+name = "Random Haskell Bot"
algorithm :: RandomReader m => ID -> Map -> m [Move]
algorithm me g@(Map width height sites) =
- randomMoves $ filter ( \s -> siteOwner s == me ) (concat sites)
+ randomMoves $ filter ((== me) . siteOwner) (concat sites)
randomMoves :: RandomReader m => [Site] -> m [Move]
randomMoves = traverse $ randMove . siteLocation
From fa8a99db83b4966112a42e74604ad85230431f5c Mon Sep 17 00:00:00 2001
From: Josef Vonasek
Date: Wed, 16 Nov 2016 05:05:34 -0500
Subject: [PATCH 14/22] New module Halite.Logic
---
airesources/Haskell/halite-haskell.cabal | 2 +-
airesources/Haskell/lib/Halite.hs | 1 +
airesources/Haskell/lib/Halite/Logic.hs | 47 ++++++++++++++++++++++++
3 files changed, 49 insertions(+), 1 deletion(-)
create mode 100644 airesources/Haskell/lib/Halite/Logic.hs
diff --git a/airesources/Haskell/halite-haskell.cabal b/airesources/Haskell/halite-haskell.cabal
index 17743ff1b..6bf201a6f 100644
--- a/airesources/Haskell/halite-haskell.cabal
+++ b/airesources/Haskell/halite-haskell.cabal
@@ -10,7 +10,7 @@ cabal-version: >=1.10
library
hs-source-dirs: lib
- exposed-modules: Halite, Halite.Networking, Halite.Types, Halite.Classes
+ exposed-modules: Halite, Halite.Networking, Halite.Types, Halite.Classes, Halite.Logic
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
, random
diff --git a/airesources/Haskell/lib/Halite.hs b/airesources/Haskell/lib/Halite.hs
index 4aa9ae102..8259c46e9 100644
--- a/airesources/Haskell/lib/Halite.hs
+++ b/airesources/Haskell/lib/Halite.hs
@@ -5,3 +5,4 @@ module Halite
import Halite.Networking as M
import Halite.Classes as M
import Halite.Types as M
+import Halite.Logic as M
diff --git a/airesources/Haskell/lib/Halite/Logic.hs b/airesources/Haskell/lib/Halite/Logic.hs
new file mode 100644
index 000000000..9346df261
--- /dev/null
+++ b/airesources/Haskell/lib/Halite/Logic.hs
@@ -0,0 +1,47 @@
+module Halite.Logic
+ ( toLocation
+ , distance
+ , angle
+ , moveToLocation
+ , site
+ ) where
+
+import Halite.Types
+
+toLocation :: Map -> (Int, Int) -> Location
+toLocation (Map width height _) (x, y) =
+ Location (mod x width) (mod y height)
+
+distance :: Map -> Location -> Location -> Int
+distance (Map width height _) (Location x1 y1) (Location x2 y2) =
+ (x2 - x1) `mod` width + (y2 - y1) `mod` height
+
+angle :: Map -> Location -> Location -> Double
+angle (Map width height _) (Location x1 y1) (Location x2 y2) =
+ atan2 (fromIntegral $ foo dx width) (fromIntegral $ foo dy height)
+ where
+ dx = x2 - x1
+ dy = y2 - y1
+ foo a b
+ | a > b - a = a - b
+ | -a > b + a = a + b
+ | otherwise = a
+
+moveToLocation :: Map -> Move -> Location
+moveToLocation _ (Move location Still) = location
+moveToLocation (Map width height _) (Move (Location x y) dir) = case dir of
+ North -> if y == 0
+ then Location x (height -1)
+ else Location x (y +1)
+ South -> if y == height -1
+ then Location x 0
+ else Location x (y -1)
+ West -> if x == 0
+ then Location (width -1) y
+ else Location (x +1) y
+ East -> if x == width -1
+ then Location 0 y
+ else Location (x +1) y
+
+site :: Map -> Location -> Site
+site (Map _ _ sites) (Location x y) = sites !! y !! x
From 2771e19d9c9f902e137dc16f5723ce1c1c3ec1bc Mon Sep 17 00:00:00 2001
From: Josef Vonasek
Date: Wed, 16 Nov 2016 07:10:22 -0500
Subject: [PATCH 15/22] Resolved conflicts.
---
airesources/Haskell/src/MyBot.hs | 3 +++
airesources/Haskell/src/RandomBot.hs | 3 +++
2 files changed, 6 insertions(+)
diff --git a/airesources/Haskell/src/MyBot.hs b/airesources/Haskell/src/MyBot.hs
index 035661b8e..73465149a 100644
--- a/airesources/Haskell/src/MyBot.hs
+++ b/airesources/Haskell/src/MyBot.hs
@@ -18,3 +18,6 @@ randomMoves = traverse $ randMove . siteLocation
randMove location = do
direction <- toEnum <$> rand 5
return $ Move location direction
+
+ownedBy :: ID -> Site -> Bool
+ownedBy userID site = siteOwner site == userID
diff --git a/airesources/Haskell/src/RandomBot.hs b/airesources/Haskell/src/RandomBot.hs
index ddb2546ca..6937f260b 100644
--- a/airesources/Haskell/src/RandomBot.hs
+++ b/airesources/Haskell/src/RandomBot.hs
@@ -18,3 +18,6 @@ randomMoves = traverse $ randMove . siteLocation
randMove location = do
direction <- toEnum <$> rand 5
return $ Move location direction
+
+ownedBy :: ID -> Site -> Bool
+ownedBy userID site = siteOwner site == userID
From 9d9a4f2a9f87cf88795f64ff128eb6074c7d805c Mon Sep 17 00:00:00 2001
From: Michael Truell
Date: Sat, 19 Nov 2016 12:05:36 -0500
Subject: [PATCH 16/22] Add ghc to sandbox
---
worker/Dockerfile | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/worker/Dockerfile b/worker/Dockerfile
index d2e2b2bfc..3fe35283a 100644
--- a/worker/Dockerfile
+++ b/worker/Dockerfile
@@ -8,12 +8,16 @@ RUN apt-get install -y curl
RUN apt-get install -y libstdc++6
RUN apt-get install -y gcc
RUN apt-get install -y g++
+
RUN apt-get install -y python3 python3-pip python3-dev python3-numpy
+
RUN curl -sSf https://static.rust-lang.org/rustup.sh | sh
+
RUN apt-get install -y python-software-properties
RUN apt-get install -y software-properties-common
RUN apt-get install -y openjdk-8-jdk
+
RUN apt-get install -y scala
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
@@ -25,3 +29,5 @@ RUN apt-get install -y ruby
RUN gem install bundler
RUN apt-get install -y golang
+
+RUN apt-get install -y ghc
From 022fda8bac00e511fab7d43a99b7aba80eb143d9 Mon Sep 17 00:00:00 2001
From: Michael Truell
Date: Sat, 19 Nov 2016 12:17:12 -0500
Subject: [PATCH 17/22] Add stack to sandbox
---
worker/Dockerfile | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/worker/Dockerfile b/worker/Dockerfile
index 3fe35283a..9720aaf81 100644
--- a/worker/Dockerfile
+++ b/worker/Dockerfile
@@ -30,4 +30,5 @@ RUN gem install bundler
RUN apt-get install -y golang
-RUN apt-get install -y ghc
+RUN curl -sSL https://get.haskellstack.org/ | sh
+RUN stack setup
From 63ea5a2e9347d1a297adf27ee71a2bb446b05dd8 Mon Sep 17 00:00:00 2001
From: Michael Truell
Date: Sat, 19 Nov 2016 12:24:24 -0500
Subject: [PATCH 18/22] Stack debugging
---
worker/Dockerfile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/worker/Dockerfile b/worker/Dockerfile
index 9720aaf81..3aa4ac262 100644
--- a/worker/Dockerfile
+++ b/worker/Dockerfile
@@ -31,4 +31,6 @@ RUN gem install bundler
RUN apt-get install -y golang
RUN curl -sSL https://get.haskellstack.org/ | sh
+RUN stack update
+RUN stack upgrade
RUN stack setup
From 12f69b06ac545ff9f5c8d4e8c6f4d4de2eb39011 Mon Sep 17 00:00:00 2001
From: Michael Truell
Date: Sat, 19 Nov 2016 12:27:41 -0500
Subject: [PATCH 19/22] Add to website
---
website/advanced_game_server.php | 8 ++++++--
website/archiveStarterPackages.sh | 4 +++-
website/downloads.php | 3 ++-
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/website/advanced_game_server.php b/website/advanced_game_server.php
index 2d5ddd42f..275ac101f 100644
--- a/website/advanced_game_server.php
+++ b/website/advanced_game_server.php
@@ -39,10 +39,11 @@
Python - .py
C++ - .cpp and .h(pp)
C# - .cs
+ Go - .go
+ Haskell - .hs
Rust - .toml (for your Cargo.toml) and .rs (for your Rust source)
Scala - .scala
Ruby - .rb
- Go - .go
@@ -52,6 +53,7 @@
Java - javac 1.8.0_111
C++ - g++ 4.84
C# - mcs 4.6.1.0
+ Haskell - ghc 8.0.1
Rust - rustc 1.10.0
Scala - scalac 2.10.4
@@ -60,6 +62,7 @@
The following build automators are used:
+ - Haskell - stack 1.2.0
- Rust - cargo 0.11.0
@@ -71,10 +74,11 @@
Python 3.4.3
C++ 11
C# 6.0
+ Go 1.6
+ Haskell 8.0.1
Rust 1.10
Scala 2.10.4
Ruby 2.3.1
- Go 1.6
diff --git a/website/archiveStarterPackages.sh b/website/archiveStarterPackages.sh
index 624bf5461..daa383956 100755
--- a/website/archiveStarterPackages.sh
+++ b/website/archiveStarterPackages.sh
@@ -4,7 +4,7 @@ cd ../airesources/
rm -r *-Starter-Package
-mkdir Halite-Python-Starter-Package Halite-Java-Starter-Package Halite-C++-Starter-Package Halite-Rust-Starter-Package Halite-C#-Starter-Package Halite-Scala-Starter-Package Halite-Ruby-Starter-Package Halite-Go-Starter-Package
+mkdir Halite-Python-Starter-Package Halite-Java-Starter-Package Halite-C++-Starter-Package Halite-Rust-Starter-Package Halite-C#-Starter-Package Halite-Scala-Starter-Package Halite-Ruby-Starter-Package Halite-Go-Starter-Package Halite-Haskell-Starter-Package
cp -r Python/* Halite-Python-Starter-Package/
cp -r Java/* Halite-Java-Starter-Package/
@@ -14,6 +14,7 @@ cp -r Java/* Halite-Scala-Starter-Package/
cp -r CSharp/* Halite-C#-Starter-Package/
cp -r Ruby/* Halite-Ruby-Starter-Package/
cp -r Go/* Halite-Go-Starter-Package/
+cp -r Haskell/* Halite-Haskell-Starter-Package/
cp -r Scala/* Halite-Scala-Starter-Package/
rm Halite-Scala-Starter-Package/MyBot.java
@@ -26,6 +27,7 @@ zip -r Halite-C#-Starter-Package.zip Halite-C#-Starter-Package/
zip -r Halite-Scala-Starter-Package.zip Halite-Scala-Starter-Package/
zip -r Halite-Ruby-Starter-Package.zip Halite-Ruby-Starter-Package/
zip -r Halite-Go-Starter-Package.zip Halite-Go-Starter-Package/
+zip -r Halite-Haskell-Starter-Package.zip Halite-Haskell-Starter-Package/
mkdir -p ../website/downloads/starterpackages
mv *.zip ../website/downloads/starterpackages
diff --git a/website/downloads.php b/website/downloads.php
index b92d80982..e472d09fc 100644
--- a/website/downloads.php
+++ b/website/downloads.php
@@ -27,10 +27,11 @@
Community Packages
From 75866a52b6b629a879ef34d66cc3f4e62b2922fe Mon Sep 17 00:00:00 2001
From: Michael Truell
Date: Mon, 21 Nov 2016 19:20:59 -0500
Subject: [PATCH 20/22] Add cabal
---
worker/Dockerfile | 14 ++++++++++++++
worker/compiler.py | 4 ++--
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/worker/Dockerfile b/worker/Dockerfile
index 1ebd43ad0..759e1fba2 100644
--- a/worker/Dockerfile
+++ b/worker/Dockerfile
@@ -37,3 +37,17 @@ RUN curl -sL https://deb.nodesource.com/setup_7.x | bash -
RUN apt-get install -y nodejs
RUN apt-get install -y ocaml
+
+RUN echo 'deb http://ppa.launchpad.net/hvr/ghc/ubuntu trusty main' > /etc/apt/sources.list.d/ghc.list && \
+ echo 'deb http://download.fpcomplete.com/debian/jessie stable main'| tee /etc/apt/sources.list.d/fpco.list && \
+ # hvr keys
+ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F6F88286 && \
+ # fpco keys
+ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C5705533DA4F78D8664B5DC0575159689BEFB442 && \
+ apt-get update && \
+ apt-get install -y --no-install-recommends cabal-install-1.24 ghc-8.0.1 happy-1.19.5 alex-3.1.7 \
+ stack zlib1g-dev libtinfo-dev libsqlite3-0 libsqlite3-dev ca-certificates g++ git && \
+ rm -rf /var/lib/apt/lists/*
+
+ENV PATH /root/.cabal/bin:/root/.local/bin:/opt/cabal/1.24/bin:/opt/ghc/8.0.1/bin:/opt/happy/1.19.5/bin:/opt/alex/3.1.7/bin:$PATH
+
diff --git a/worker/compiler.py b/worker/compiler.py
index c4291abc3..75a1acbdb 100644
--- a/worker/compiler.py
+++ b/worker/compiler.py
@@ -254,7 +254,7 @@ def compile(self, bot_dir, globs, errors, timelimit):
"D" : [["dmd", "-O", "-inline", "-release", "-noboundscheck", "-of" + BOT]],
"Groovy" : [["groovyc"],
["jar", "cfe", BOT + ".jar", BOT]],
- "Haskell" : [["ghc", "--make", BOT + ".hs", "-O", "-v0"]],
+ "Haskell" : [["cabal", "configure"], ["cabal", "build"]],
"Java" : [["javac", "-encoding", "UTF-8", "-J-Xmx%sm" % (MEMORY_LIMIT)]],
"Lisp" : [['sbcl', '--dynamic-space-size', str(MEMORY_LIMIT), '--script', BOT + '.lisp']],
"OCaml" : [["ocamlbuild -lib unix", BOT + ".native"]],
@@ -342,7 +342,7 @@ def compile(self, bot_dir, globs, errors, timelimit):
[(["*.groovy"], ExternalCompiler(comp_args["Groovy"][0])),
(["*.class"], ExternalCompiler(comp_args["Groovy"][1]))]
),
- Language("Haskell", BOT, "MyBot.hs",
+ Language("Haskell", "src/"+BOT, "src/MyBot.hs",
"./MyBot +RTS -M" + str(MEMORY_LIMIT) + "m",
[BOT],
[([""], ExternalCompiler(comp_args["Haskell"][0]))]
From e5c35d37b1d01c64fbdf5c2aa4e3902bd7cecc55 Mon Sep 17 00:00:00 2001
From: Josef
Date: Thu, 24 Nov 2016 02:09:20 -0500
Subject: [PATCH 21/22] Deleted two useless lines.
---
airesources/Haskell/src/MyBot.hs | 2 --
1 file changed, 2 deletions(-)
diff --git a/airesources/Haskell/src/MyBot.hs b/airesources/Haskell/src/MyBot.hs
index 73465149a..18819a812 100644
--- a/airesources/Haskell/src/MyBot.hs
+++ b/airesources/Haskell/src/MyBot.hs
@@ -19,5 +19,3 @@ randomMoves = traverse $ randMove . siteLocation
direction <- toEnum <$> rand 5
return $ Move location direction
-ownedBy :: ID -> Site -> Bool
-ownedBy userID site = siteOwner site == userID
From 1c9200b5aca4187e87a80d2505c782786ee87f81 Mon Sep 17 00:00:00 2001
From: Josef
Date: Thu, 24 Nov 2016 02:10:21 -0500
Subject: [PATCH 22/22] Deleted two useless lines.
---
airesources/Haskell/src/RandomBot.hs | 3 ---
1 file changed, 3 deletions(-)
diff --git a/airesources/Haskell/src/RandomBot.hs b/airesources/Haskell/src/RandomBot.hs
index 6937f260b..ddb2546ca 100644
--- a/airesources/Haskell/src/RandomBot.hs
+++ b/airesources/Haskell/src/RandomBot.hs
@@ -18,6 +18,3 @@ randomMoves = traverse $ randMove . siteLocation
randMove location = do
direction <- toEnum <$> rand 5
return $ Move location direction
-
-ownedBy :: ID -> Site -> Bool
-ownedBy userID site = siteOwner site == userID