feat: lucha libre torneo
This commit is contained in:
105
lucha-libre-torneo/LuchaLibreTorneo.hs
Normal file
105
lucha-libre-torneo/LuchaLibreTorneo.hs
Normal file
@@ -0,0 +1,105 @@
|
||||
module Main where
|
||||
|
||||
import Control.Concurrent.Async (mapConcurrently)
|
||||
import Control.Monad (replicateM)
|
||||
import Data.Either
|
||||
import Data.Random.Normal (normalIO)
|
||||
import Debug.Trace
|
||||
import Text.Printf
|
||||
|
||||
type Card = [Int]
|
||||
|
||||
data Side = A | B
|
||||
deriving (Show, Eq)
|
||||
|
||||
type Statistics = ((Float, Float), Float, Int)
|
||||
|
||||
sides = [A, B]
|
||||
|
||||
data State = State { turn :: Int, aCards :: [Card], bCards :: [Card], lastWinner :: Side, temp :: [Card] }
|
||||
deriving (Show)
|
||||
|
||||
data Parameters = Parameters { beginningSide :: Side, fields :: Int, cardsPerSide :: Int }
|
||||
deriving (Show)
|
||||
|
||||
maxIndex xs = head $ filter ((== maximum xs) . (xs !!)) [0..]
|
||||
|
||||
point :: IO Int
|
||||
point = abs . truncate . (100 *) <$> (normalIO :: IO Float)
|
||||
|
||||
initialState :: Parameters -> IO State
|
||||
initialState parameters =
|
||||
State 0 <$> cards <*> cards <*> pure (beginningSide parameters) <*> pure []
|
||||
where card = replicateM (fields parameters) point
|
||||
cards = replicateM (cardsPerSide parameters) card
|
||||
|
||||
runGame :: State -> Either State (Side, Int)
|
||||
runGame state =
|
||||
if turn state >= 1000 then Left state else
|
||||
case (aCards state, bCards state) of
|
||||
([], _) -> Right (A, turn state)
|
||||
(_, []) -> Right (B, turn state)
|
||||
(a:ac, b:bc) ->
|
||||
let
|
||||
lastWinnersFirstCard = case lastWinner state of
|
||||
A -> a
|
||||
B -> b
|
||||
-- the last winning player picks the field of his card which is best
|
||||
bestField = maxIndex lastWinnersFirstCard
|
||||
in
|
||||
-- trace ("maxIndex of " ++ show lastWinnersFirstCard ++ " is " ++ show bestField) $
|
||||
-- trace ("Side " ++ show (lastWinner state) ++ " asking for " ++ show bestField) $
|
||||
runGame $ case compare (a !! bestField) (b !! bestField) of
|
||||
GT ->
|
||||
-- trace "A won" $
|
||||
state
|
||||
{ turn = succ $ turn state
|
||||
, aCards = ac ++ temp state ++ [a, b]
|
||||
, bCards = bc
|
||||
, lastWinner = A
|
||||
, temp = []
|
||||
}
|
||||
LT ->
|
||||
-- trace "B won" $
|
||||
state
|
||||
{ turn = succ $ turn state
|
||||
, aCards = ac
|
||||
, bCards = bc ++ temp state ++ [a, b]
|
||||
, lastWinner = B
|
||||
, temp = []
|
||||
}
|
||||
EQ ->
|
||||
state
|
||||
{ turn = succ $ turn state
|
||||
, aCards = ac
|
||||
, bCards = bc
|
||||
, lastWinner = lastWinner state
|
||||
, temp = [a, b]
|
||||
}
|
||||
|
||||
average :: [Either State (Side, Int)] -> Statistics
|
||||
average results =
|
||||
( (winningQuota A, winningQuota B)
|
||||
, quota $ sum $ map snd $ rights results -- average
|
||||
, length $ lefts results
|
||||
)
|
||||
where
|
||||
quota x = fromIntegral x / fromIntegral (length results)
|
||||
winningQuota side = quota $ length $ filter ((== side) . fst) (rights results)
|
||||
|
||||
allTheStats :: Int -> [Int] -> [Int] -> IO [(Parameters, Statistics)]
|
||||
allTheStats games possibleFields possibleCardsPerSide =
|
||||
mapConcurrently averageGame allTheGames
|
||||
where allTheGames = Parameters <$> [A, B] <*> possibleFields <*> possibleCardsPerSide
|
||||
averageGame parameters = (,) parameters . average <$> replicateM games (runGame <$> initialState parameters)
|
||||
|
||||
renderStats :: (Parameters, Statistics) -> String
|
||||
renderStats (parameters, ((winsA, winsB), turns, loops)) = printf "(begin %s fields %4d cards %4d) A %.2f B %.2f Turns %3.1f Loops %d" (show $ beginningSide parameters) (fields parameters) (cardsPerSide parameters) winsA winsB turns loops
|
||||
|
||||
main = do
|
||||
stats <- allTheStats 100 [6] [1..20]
|
||||
mapM_ (putStrLn . renderStats) stats
|
||||
|
||||
-- how many turns do games need on average
|
||||
-- is any of that influenced by the number of fields, the number of cards per side and who began (initial lastWinner)
|
||||
--
|
||||
3
lucha-libre-torneo/Readme.md
Normal file
3
lucha-libre-torneo/Readme.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Lucha Libre Torneo
|
||||
|
||||
Simulating a card game using Haskell.
|
||||
Reference in New Issue
Block a user