enhanced train&build logic

This commit is contained in:
weiss
2020-04-13 06:17:40 +02:00
parent 4fcf4219a8
commit 3014d916e8

View File

@@ -3,13 +3,15 @@ module Main where
-- mines only on side -- mines only on side
-- build giants -- build giants
-- Pattern match filed wei keine eigenes gebaeude -- Pattern match filed wei keine eigenes gebaeude
-- aber warum nur 2 minen und dann stopp? -- letzte Mine wird nciht aufgelevelt?
import Prelude import Prelude
import Control.Monad.State (State, gets, modify_, runState) import Control.Monad.State (State, gets, modify_, runState)
import Control.MonadZero (guard) import Control.MonadZero (guard)
import Data.Array (any, filter, foldl, head, length, reverse, sortBy) import Data.Array (any, filter, foldl, head, length, reverse, sort, sortBy)
import Data.DateTime (time)
import Data.Foldable (sum)
import Data.Maybe (Maybe(..), fromJust) import Data.Maybe (Maybe(..), fromJust)
import Data.Tuple (fst, snd) import Data.Tuple (fst, snd)
import Effect (Effect) import Effect (Effect)
@@ -94,22 +96,35 @@ loop' = do
buildAll :: State GameState String buildAll :: State GameState String
buildAll = do buildAll = do
sites <- gets _.sites sites <- gets _.sites
units <- gets _.units
let buildingsCnt = length $ friendlySites sites let buildingsCnt = length $ friendlySites sites
let minesCnt = length $ friendlyMines sites let noTowerBuildingsCnt = length $ filter (not isTower) $ friendlySites sites
if minesCnt < 3 let mines = length $ maxLvlFriendlyMines sites
if mines < 4 -- TODO: letzte Mine muss auch ganz ausgebaut werden
then buildMines then buildMines
else if buildingsCnt < 5 else if noTowerBuildingsCnt < 5
then case head $ nearFreeSites (queen units) sites of then buildBarracks
Just site -> do else if buildingsCnt < 8 || (minTowerRange sites) < 300
let typ = if not $ hasArcherBarrack sites then 1 then if buildingsCnt < 8 then buildTowers
else if not $ hasKnightsBarrack sites then 0 else refreshTowers
else 2 else if noTowerBuildingsCnt < 6
pure $ build site typ then buildBarracks
Nothing -> refreshTowers
else if buildingsCnt < 8
then buildTowers
else refreshTowers else refreshTowers
where
minTowerRange sites = case head $ sort $ map (\t -> t.param2) $ filter (isTower) $ friendlySites sites of
Just t -> t
Nothing -> 0
buildBarracks :: State GameState String
buildBarracks = do
sites <- gets _.sites
units <- gets _.units
case head $ nearFreeSites (queen units) sites of
Just site -> do
let typ = --if not $ hasArcherBarrack sites then 1
if not $ hasKnightsBarrack sites then 0
else 2
pure $ build site typ
Nothing -> refreshTowers
buildTowers :: State GameState String buildTowers :: State GameState String
buildTowers = do buildTowers = do
@@ -123,7 +138,6 @@ buildTowers = do
refreshTowers :: State GameState String refreshTowers :: State GameState String
refreshTowers = do refreshTowers = do
towers <-friendlyTowersByAttraction towers <-friendlyTowersByAttraction
case head towers of case head towers of
Just site -> do Just site -> do
touched <- gets _.touchedSite touched <- gets _.touchedSite
@@ -143,6 +157,7 @@ buildMines :: State GameState String
buildMines = do buildMines = do
units <- gets _.units units <- gets _.units
sites <- gets _.sites sites <- gets _.sites
leftSide <- gets _.leftSide
case head $ nearNonEmptyMines (queen units) sites of case head $ nearNonEmptyMines (queen units) sites of
Just site -> do Just site -> do
touched <- gets _.touchedSite touched <- gets _.touchedSite
@@ -180,15 +195,16 @@ trainAll = do
sites <- gets _.sites sites <- gets _.sites
units <- gets _.units units <- gets _.units
let ownArchers = ownMinions units let ownGiants = filter isGiant $ ownMinions units
let barrack =if gold > 140 let trainGiants = length (enemyTowers sites) > 2 && length ownGiants < 3
then let barrack = if not trainGiants
if length ownArchers < 4 && length (enemyKnights units) /= 0 then knightBarracks sites
then archerBarrack sites else if gold > 140 then
else if length (enemyTowers sites) > 2 --knightBarracks sites
then giantBarrack sites
else -- if length ownArchers < 4 && length (enemyKnights units) /= 0
knightBarrack sites -- then archerBarrack sites
giantBarrack sites
else [] else []
pure $ foldl siteToIds "TRAIN" barrack pure $ foldl siteToIds "TRAIN" barrack
where where
@@ -201,7 +217,7 @@ trainAll = do
Nothing -> [] Nothing -> []
giantBarrack sites = case head $ giantBarracks sites of giantBarrack sites = case head $ giantBarracks sites of
Just barrack -> [barrack] Just barrack -> [barrack]
Nothing -> [] Nothing -> knightBarracks sites
build :: forall e. { id :: Int | e } -> Int -> String build :: forall e. { id :: Int | e } -> Int -> String
build s typ = "BUILD " <> show s.id <> " BARRACKS-" <> t build s typ = "BUILD " <> show s.id <> " BARRACKS-" <> t
@@ -230,6 +246,9 @@ friendlySites = filter (\s -> s.owner == 0)
friendlyMines :: Array Site -> Array Site friendlyMines :: Array Site -> Array Site
friendlyMines sites = filter (\s -> s.structureType == 0) $ friendlySites sites friendlyMines sites = filter (\s -> s.structureType == 0) $ friendlySites sites
maxLvlFriendlyMines :: Array Site -> Array Site
maxLvlFriendlyMines sites = filter (\s -> s.lvl >= s.maxMineSize) $ friendlyMines sites
enemyTowers :: Array Site -> Array Site enemyTowers :: Array Site -> Array Site
enemyTowers = filter isEnemy <<< filter isTower enemyTowers = filter isEnemy <<< filter isTower
@@ -246,8 +265,8 @@ friendlyTowersByAttraction = do
sites <- gets _.sites sites <- gets _.sites
units <- gets _.units units <- gets _.units
let q = queen units let q = queen units
pure $ reverse $ sortBy (\t1 t2 -> compare (attraction t1 q) (attraction t2 q)) (friendlyTowers sites) pure $ sortBy (\t1 t2 -> compare (attraction t1 q) (attraction t2 q)) (friendlyTowers sites)
where attraction t q = t.param1 - dist t q where attraction t q = t.param1 + dist t q
nearSites :: forall a. { x :: Int, y :: Int | a } -> Array Site -> Array Site nearSites :: forall a. { x :: Int, y :: Int | a } -> Array Site -> Array Site
nearSites minion sites = sortBy (compareSiteDist minion) sites nearSites minion sites = sortBy (compareSiteDist minion) sites