cosider enemies as threats
This commit is contained in:
@@ -27,7 +27,7 @@ loop1 pos depth acc
|
|||||||
in loop1 sim (depth - 1) acc'
|
in loop1 sim (depth - 1) acc'
|
||||||
|
|
||||||
sim1 :: Pos -> (Int, Pos)
|
sim1 :: Pos -> (Int, Pos)
|
||||||
sim1 pos = (\(val, (_,_, pos, _)) -> (val, pos)) (simulate board1 (0, 100, pos, singleton (0,4)))
|
sim1 pos = (\(val, (_,_, pos, _,_)) -> (val, pos)) (simulate board1 (0, 100, pos, singleton (0,4), empty))
|
||||||
|
|
||||||
board1 :: Board
|
board1 :: Board
|
||||||
board1 = fromList $ fmap fromList
|
board1 = fromList $ fmap fromList
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ dependencies:
|
|||||||
- haskell-src-exts
|
- haskell-src-exts
|
||||||
- vector
|
- vector
|
||||||
- mtl
|
- mtl
|
||||||
|
- time
|
||||||
|
|
||||||
library:
|
library:
|
||||||
source-dirs: src
|
source-dirs: src
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import System.Random
|
|||||||
import Data.Char (digitToInt)
|
import Data.Char (digitToInt)
|
||||||
import Data.List as L
|
import Data.List as L
|
||||||
import qualified Data.Vector as V
|
import qualified Data.Vector as V
|
||||||
|
import Data.Time.Clock.POSIX
|
||||||
|
|
||||||
import BotRunner
|
import BotRunner
|
||||||
import Graph
|
import Graph
|
||||||
@@ -49,6 +50,7 @@ bot readLine writeLine = do
|
|||||||
|
|
||||||
-- game loop
|
-- game loop
|
||||||
forever $ do
|
forever $ do
|
||||||
|
t1 <- getPOSIXTime
|
||||||
input_line <- getLine
|
input_line <- getLine
|
||||||
let entitycount = read input_line :: Int -- the number of entities
|
let entitycount = read input_line :: Int -- the number of entities
|
||||||
|
|
||||||
@@ -71,6 +73,9 @@ bot readLine writeLine = do
|
|||||||
let hero = V.head $ V.filter (\e -> case e of
|
let hero = V.head $ V.filter (\e -> case e of
|
||||||
EHero id _ _ _ -> id == myId
|
EHero id _ _ _ -> id == myId
|
||||||
_ -> False) heroes
|
_ -> False) heroes
|
||||||
|
let enemies = V.filter (\e -> case e of
|
||||||
|
EHero id _ _ _ -> id /= myId
|
||||||
|
_ -> False) heroes
|
||||||
let mines = V.filter (\e -> case e of
|
let mines = V.filter (\e -> case e of
|
||||||
EMine oId _ -> oId /= myId
|
EMine oId _ -> oId /= myId
|
||||||
_ -> False) entities
|
_ -> False) entities
|
||||||
@@ -81,23 +86,26 @@ bot readLine writeLine = do
|
|||||||
EMine oId _ -> oId == myId
|
EMine oId _ -> oId == myId
|
||||||
_ -> False) entities
|
_ -> False) entities
|
||||||
|
|
||||||
let gs = gameState hero $ fmap posFromEntity myMines
|
let gs = gameState hero (fmap posFromEntity myMines) (fmap posFromEntity enemies)
|
||||||
let oldMines = length $ getMines gs
|
let oldMines = length $ getMines gs
|
||||||
let sim = simulate board gs
|
let sim = simulate board gs
|
||||||
let newMines = length $ getMines $ snd sim
|
let newMines = length $ getMines $ snd sim
|
||||||
|
|
||||||
let cmd = if newMines - oldMines > 0
|
let cmd = (\(_,(_,_,pos,_,_)) -> moveToPos pos) sim
|
||||||
then (\(_,(_,_,pos,_)) -> moveToPos pos) sim
|
|
||||||
else case life hero of
|
|
||||||
Just lp -> if lp < 30 then moveToPos minTavernPos else moveToEntity minEMine
|
|
||||||
Nothing -> moveToEntity minEMine
|
|
||||||
|
|
||||||
-- hPrint stderr $ newMines - oldMines
|
-- let cmd = if newMines - oldMines > 0
|
||||||
-- hPrint stderr minEMine
|
-- then (\(_,(_,_,pos,_,_)) -> moveToPos pos) sim
|
||||||
|
-- else case life hero of
|
||||||
|
-- Just lp -> if lp < 30 then moveToPos minTavernPos else moveToEntity minEMine
|
||||||
|
-- Nothing -> moveToEntity minEMine
|
||||||
|
|
||||||
|
t2 <- getPOSIXTime
|
||||||
|
hPrint stderr $ newMines - oldMines
|
||||||
|
hPrint stderr $ round $ 1000 * (t2 - t1)
|
||||||
putStrLn cmd
|
putStrLn cmd
|
||||||
|
|
||||||
getMines :: GameState -> V.Vector Pos
|
getMines :: GameState -> V.Vector Pos
|
||||||
getMines (_,_,_,m) = m
|
getMines (_,_,_,m,_) = m
|
||||||
|
|
||||||
moveToEntity :: Entity -> String
|
moveToEntity :: Entity -> String
|
||||||
moveToEntity e = case e of
|
moveToEntity e = case e of
|
||||||
@@ -116,9 +124,9 @@ posFromEntity :: Entity -> (Int, Int)
|
|||||||
posFromEntity (EHero _ p _ _) = p
|
posFromEntity (EHero _ p _ _) = p
|
||||||
posFromEntity (EMine _ p) = p
|
posFromEntity (EMine _ p) = p
|
||||||
|
|
||||||
gameState :: Entity -> V.Vector Pos -> GameState
|
gameState :: Entity -> V.Vector Pos -> V.Vector Pos -> GameState
|
||||||
gameState (EHero _ pos l g) mines = (g, l, pos, mines)
|
gameState (EHero _ pos l g) mines enemies = (g, l, pos, mines, enemies)
|
||||||
gameState (EMine _ pos) mines = (-1, -1, pos, mines)
|
gameState (EMine _ pos) mines enemies = (-1, -1, pos, mines, enemies)
|
||||||
|
|
||||||
isTavern :: BoardEntity -> Bool
|
isTavern :: BoardEntity -> Bool
|
||||||
isTavern Tavern = True
|
isTavern Tavern = True
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ import Control.Monad.State as S
|
|||||||
import Control.Monad.State.Class
|
import Control.Monad.State.Class
|
||||||
import Data.List as L
|
import Data.List as L
|
||||||
import Simulation.Data
|
import Simulation.Data
|
||||||
|
import Simulation.Lib
|
||||||
|
|
||||||
searchDepth = 9
|
searchDepth = 8
|
||||||
|
|
||||||
-- fromPlayerBoard :: Board -> BoardInternal
|
-- fromPlayerBoard :: Board -> BoardInternal
|
||||||
-- fromPlayerBoard pBoardInternal = fmap (fmap $ fromEnum) asVector
|
-- fromPlayerBoard pBoardInternal = fmap (fmap $ fromEnum) asVector
|
||||||
@@ -24,7 +25,7 @@ simulate :: Board -> GameState -> (Int, GameState)
|
|||||||
simulate board = simulateMove board (-1,-1) searchDepth
|
simulate board = simulateMove board (-1,-1) searchDepth
|
||||||
|
|
||||||
simulateMove :: Board -> Pos -> Int -> GameState -> (Int, GameState)
|
simulateMove :: Board -> Pos -> Int -> GameState -> (Int, GameState)
|
||||||
simulateMove board prevPos depth state@(_,_,pos,_)
|
simulateMove board prevPos depth state@(_,_,pos,_,_)
|
||||||
| depth == 0 =
|
| depth == 0 =
|
||||||
let state' = evalMove board state
|
let state' = evalMove board state
|
||||||
in (evalGameState state', state')
|
in (evalGameState state', state')
|
||||||
@@ -34,37 +35,38 @@ simulateMove board prevPos depth state@(_,_,pos,_)
|
|||||||
-- der Trick: in einem Zug muss die Minenposition zurueckgegeben werden, die Position des Helden
|
-- der Trick: in einem Zug muss die Minenposition zurueckgegeben werden, die Position des Helden
|
||||||
-- aendert sich aber nicht. Im naechsten Zug will der Held dann nicht mehr die Mine erobern.
|
-- aendert sich aber nicht. Im naechsten Zug will der Held dann nicht mehr die Mine erobern.
|
||||||
pos' = if bPos == Tavern || bPos == Mine then prevPos else pos -- move back out of tavern/mine
|
pos' = if bPos == Tavern || bPos == Mine then prevPos else pos -- move back out of tavern/mine
|
||||||
-- pos wird nicht benutzt. Pos ist aber der Wert, der zurueckgegeben werden muss, damit sich der Held in die Taverne bewegt
|
moves = V.filter (posValid board state) $ possibleMoves pos'
|
||||||
moves = filter (posValid board state) $ possibleMoves pos'
|
|
||||||
vals = fmap (\pos'' -> simulateMove board pos' (depth-1) (updatePos pos'' state')) moves
|
vals = fmap (\pos'' -> simulateMove board pos' (depth-1) (updatePos pos'' state')) moves
|
||||||
valsWithOldPos = if depth == searchDepth
|
valsWithOldPos = if depth == searchDepth
|
||||||
then vals -- return position of submove on first level
|
then vals -- return position of submove on first level
|
||||||
else zip (fmap fst vals) $ fmap (updatePos pos . snd) vals -- return starting position otherwise -- pos'
|
else V.zip (fmap fst vals) $ fmap (updatePos pos . snd) vals -- return starting position otherwise -- pos'
|
||||||
in L.maximumBy (\(v1, _) (v2, _) -> compare v1 v2) valsWithOldPos
|
in L.maximumBy (\(v1, _) (v2, _) -> compare v1 v2) valsWithOldPos
|
||||||
|
|
||||||
updatePos :: Pos -> GameState -> GameState
|
updatePos :: Pos -> GameState -> GameState
|
||||||
updatePos pos (gold, life, _, mines) = (gold, life, pos, mines)
|
updatePos pos (gold, life, _, mines, enemies) = (gold, life, pos, mines, enemies)
|
||||||
|
|
||||||
-- update State according to hero position on board
|
-- update State according to hero position on board
|
||||||
-- executed every move
|
-- executed every move
|
||||||
evalMove :: Board -> GameState -> GameState
|
evalMove :: Board -> GameState -> GameState
|
||||||
evalMove board state@(gold, life, pos, mines) = evalDeath evalBuildings
|
evalMove board state@(gold, life, pos, mines, enemies) = evalDeath $ evalEnemies evalBuildings
|
||||||
where
|
where
|
||||||
evalBuildings
|
evalBuildings
|
||||||
| entity == Air = (gold + length mines, thirst life, pos, mines)
|
| entity == Air = (gold + length mines, thirst life, pos, mines, enemies)
|
||||||
| entity == SpawnPoint = (gold + length mines, thirst life, pos, mines)
|
| entity == SpawnPoint = (gold + length mines, thirst life, pos, mines, enemies)
|
||||||
| entity == Tavern =
|
| entity == Tavern =
|
||||||
if gold >= 2 then
|
if gold >= 2 then
|
||||||
( gold + length mines - 2
|
( gold + length mines - 2
|
||||||
, min 100 (life + 50) -- TODO: Check if life is +19
|
, min 100 (life + 50) -- TODO: Check if life is +19
|
||||||
, pos
|
, pos
|
||||||
, mines
|
, mines
|
||||||
|
, enemies
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
( gold + length mines
|
( gold + length mines
|
||||||
, thirst life
|
, thirst life
|
||||||
, pos
|
, pos
|
||||||
, mines
|
, mines
|
||||||
|
, enemies
|
||||||
)
|
)
|
||||||
| entity == Mine =
|
| entity == Mine =
|
||||||
let addMine = pos `V.notElem` mines
|
let addMine = pos `V.notElem` mines
|
||||||
@@ -74,12 +76,18 @@ evalMove board state@(gold, life, pos, mines) = evalDeath evalBuildings
|
|||||||
, if addMine then thirst life - 20 else thirst life
|
, if addMine then thirst life - 20 else thirst life
|
||||||
, pos
|
, pos
|
||||||
, mines'
|
, mines'
|
||||||
|
, enemies
|
||||||
)
|
)
|
||||||
| entity == Wall = state -- should never happen
|
| entity == Wall = state -- should never happen
|
||||||
where
|
where
|
||||||
entity = boardPos board pos
|
entity = boardPos board pos
|
||||||
evalDeath state'@(gold', life', pos', mines')
|
-- TODO: Gegner verliert auch Leben
|
||||||
| life' < 5 = (gold', 100, (0,0), V.empty) -- TODO: starting position is not 0,0 but spawnpoint
|
evalEnemies :: GameState -> GameState
|
||||||
|
evalEnemies state'@(gold', life', pos', mines', enemies')
|
||||||
|
| any (<2) $ fmap (dist pos') enemies' = (gold', life' - 20, pos', mines', enemies')
|
||||||
|
| otherwise = state'
|
||||||
|
evalDeath state'@(gold', life', pos', mines', enemies')
|
||||||
|
| life' < 5 = (gold', 100, (0,0), V.empty, enemies') -- TODO: starting position is not 0,0 but spawnpoint
|
||||||
| otherwise = state'
|
| otherwise = state'
|
||||||
|
|
||||||
thirst life = max 1 (life - 1)
|
thirst life = max 1 (life - 1)
|
||||||
@@ -87,21 +95,21 @@ thirst life = max 1 (life - 1)
|
|||||||
-- retuns the evalutaion of the current move
|
-- retuns the evalutaion of the current move
|
||||||
-- executed if maximum depth is reached
|
-- executed if maximum depth is reached
|
||||||
evalGameState :: GameState -> Int
|
evalGameState :: GameState -> Int
|
||||||
evalGameState (gold, life, _, mines) = gold + (life `div` 10) + length mines * 2
|
evalGameState (gold, life, _, mines, _) = gold + (life `div` 10) + length mines * 2 -- TODO: Warum macht nur mines quatsch?
|
||||||
|
|
||||||
-- get BoardInternalEntity Enum of Pos on BoardInternal
|
-- get BoardInternalEntity Enum of Pos on BoardInternal
|
||||||
boardPos :: Board -> Pos -> BoardEntity
|
boardPos :: Board -> Pos -> BoardEntity
|
||||||
boardPos board (x,y) = (board V.! y) V.! x
|
boardPos board (x,y) = (board V.! y) V.! x
|
||||||
|
|
||||||
posValid :: Board -> GameState -> Pos -> Bool
|
posValid :: Board -> GameState -> Pos -> Bool
|
||||||
posValid board (_, _, _, mines) pos@(x,y) = onBoardInternal && boardPos' /= Wall && pos `notElem` mines
|
posValid board (_, _, _, mines, _) pos@(x,y) = onBoardInternal && boardPos' /= Wall && pos `notElem` mines
|
||||||
where
|
where
|
||||||
size = length board
|
size = length board
|
||||||
boardPos' = boardPos board pos
|
boardPos' = boardPos board pos
|
||||||
onBoardInternal = x >= 0 && x < size && y >= 0 && y < size
|
onBoardInternal = x >= 0 && x < size && y >= 0 && y < size
|
||||||
|
|
||||||
possibleMoves :: Pos -> [Pos]
|
possibleMoves :: Pos -> V.Vector Pos
|
||||||
possibleMoves (x,y) = [ (x+1, y), (x, y+1), (x-1, y), (x, y-1) ]
|
possibleMoves (x,y) = V.fromList [ (x+1, y), (x, y+1), (x-1, y), (x, y-1) ]
|
||||||
|
|
||||||
|
|
||||||
data Tree v = Node v (Tree v) | Leaf v
|
data Tree v = Node v (Tree v) | Leaf v
|
||||||
@@ -10,5 +10,5 @@ type IndexedBoard = V.Vector (Pos, BoardEntity)
|
|||||||
|
|
||||||
type Pos = (Int, Int)
|
type Pos = (Int, Int)
|
||||||
|
|
||||||
-- (gold, life, hero pos, own mines)
|
-- (gold, life, hero pos, own mines, enemies)
|
||||||
type GameState = (Int, Int, Pos, V.Vector Pos)
|
type GameState = (Int, Int, Pos, V.Vector Pos, V.Vector Pos)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ cabal-version: 1.12
|
|||||||
--
|
--
|
||||||
-- see: https://github.com/sol/hpack
|
-- see: https://github.com/sol/hpack
|
||||||
--
|
--
|
||||||
-- hash: a40eac4da8b91ec478d65b8403d0b4c79040e0e5d0ae95d897222ea2c05cb732
|
-- hash: 417e6c9b6226b7bcecca4ed2838a83b02bcb813752e3a15911e72c73db470c74
|
||||||
|
|
||||||
name: stackproject
|
name: stackproject
|
||||||
version: 0.1.0.0
|
version: 0.1.0.0
|
||||||
@@ -51,6 +51,7 @@ library
|
|||||||
, haskell-src-exts
|
, haskell-src-exts
|
||||||
, mtl
|
, mtl
|
||||||
, random
|
, random
|
||||||
|
, time
|
||||||
, vector
|
, vector
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
||||||
@@ -74,6 +75,7 @@ executable stackproject-exe
|
|||||||
, mtl
|
, mtl
|
||||||
, random
|
, random
|
||||||
, stackproject
|
, stackproject
|
||||||
|
, time
|
||||||
, vector
|
, vector
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
||||||
@@ -98,5 +100,6 @@ test-suite stackproject-test
|
|||||||
, mtl
|
, mtl
|
||||||
, random
|
, random
|
||||||
, stackproject
|
, stackproject
|
||||||
|
, time
|
||||||
, vector
|
, vector
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|||||||
Reference in New Issue
Block a user