Merge branch 'master' of git.epichack.com:barak/tim-the-enchanter
This commit is contained in:
commit
a8564ccb0c
5 changed files with 647 additions and 103 deletions
30
LICENSE
Normal file
30
LICENSE
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
Copyright (c) 2013, Barak Michener
|
||||
|
||||
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 Barak Michener 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.
|
||||
2
Setup.hs
Normal file
2
Setup.hs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
import Distribution.Simple
|
||||
main = defaultMain
|
||||
274
Tim.hs
Normal file
274
Tim.hs
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
{-# LANGUAGE NoMonomorphismRestriction #-}
|
||||
{-# LANGUAGE ConstraintKinds #-}
|
||||
{-# LANGUAGE DoAndIfThenElse #-}
|
||||
|
||||
import qualified Numeric.Probability.Distribution as Dist
|
||||
import Numeric.Probability.Distribution as Probs
|
||||
--import Control.Monad (liftM2, replicateM, ap)
|
||||
--import Control.Monad (ap)
|
||||
import Control.Monad.Parallel (replicateM)
|
||||
import Control.Monad (replicateM, ap)
|
||||
import Data.List (permutations, isPrefixOf)
|
||||
import Data.List.Split (splitOn)
|
||||
import qualified Numeric.Probability.Random as Rnd
|
||||
import Numeric.Probability.Trace (Trace)
|
||||
|
||||
type Prob = Double
|
||||
type Dist a = Dist.T Prob a
|
||||
|
||||
data Side = Good | Evil
|
||||
deriving (Show, Eq, Ord)
|
||||
|
||||
otherSide Good = Evil
|
||||
otherSide Evil = Good
|
||||
|
||||
data Role = Role { roleName :: String
|
||||
, roleSide :: Side }
|
||||
deriving (Show, Eq, Ord)
|
||||
|
||||
type Deal = [Role]
|
||||
|
||||
good1 = Role "G1" Good
|
||||
good2 = Role "G2" Good
|
||||
good3 = Role "G3" Good
|
||||
good4 = Role "G4" Good
|
||||
good5 = Role "G5" Good
|
||||
good6 = Role "G6" Good
|
||||
bad1 = Role "E1" Evil
|
||||
bad2 = Role "E2" Evil
|
||||
bad3 = Role "E3" Evil
|
||||
bad4 = Role "E4" Evil
|
||||
|
||||
defaultGame :: Deal
|
||||
defaultGame = [good1, good2, good3, bad1, bad2,
|
||||
good4, bad3, good5, good6, bad4 ]
|
||||
|
||||
gameSize n = take n defaultGame
|
||||
|
||||
allDecks n = permutations $ take n defaultGame
|
||||
|
||||
|
||||
bernoulli :: Double -> Dist Bool
|
||||
bernoulli x = fromFreqs [(True, x), (False, (1 - x))]
|
||||
|
||||
deals :: Int -> Dist Deal
|
||||
deals = Dist.uniform . allDecks
|
||||
|
||||
stateSpace :: Int -> Dist Game
|
||||
stateSpace nPlayers = return Game `ap`
|
||||
deals nPlayers `ap` -- trueRoles
|
||||
bernoulli 0.5 `ap`
|
||||
makeVoteDucks `ap`
|
||||
makeProposalIgnorance `ap`
|
||||
makeProposalDucks `ap`
|
||||
makeDecay
|
||||
|
||||
--`ap` -- ladyWillLie
|
||||
--playerBeliefVar (1 / 3.0) nPlayers
|
||||
|
||||
data Game = Game { trueRoles :: Deal
|
||||
, ladyWillLie :: Bool
|
||||
, willDuckOnRound :: [Bool]
|
||||
, proposalIgnorant :: Double
|
||||
, proposalDucks :: Double
|
||||
, decay :: Double
|
||||
}
|
||||
deriving (Show, Eq, Ord)
|
||||
|
||||
|
||||
|
||||
beliefVar :: Double -> Dist Double
|
||||
beliefVar precision = Dist.uniform [0.0, precision..1.0]
|
||||
|
||||
playerBeliefVar :: Double -> Int -> Dist [Double]
|
||||
playerBeliefVar precision n_players = constraint ?=<< var
|
||||
where var = Control.Monad.replicateM n_players $ beliefVar precision
|
||||
constraint in_var =
|
||||
sum in_var == (sum $ Prelude.map (\x -> if roleSide x == Good then 1.0 else 0.0) $ gameSize n_players)
|
||||
|
||||
makeVoteDucks = mapM bernoulli [0.8, 0.6, 0.4]
|
||||
makeProposalIgnorance = certainly 0.8
|
||||
makeProposalDucks = certainly 0.8
|
||||
makeDecay = certainly 0.8
|
||||
|
||||
isGood :: Int -> Game -> Bool
|
||||
isGood player game = roleSide (trueRoles game !! player) == Good
|
||||
isEvil player game = roleSide (trueRoles game !! player) == Evil
|
||||
|
||||
playerNisRole :: Int -> String -> Dist.Event Game
|
||||
playerNisRole n name game = roleName (trueRoles game !! n) == name
|
||||
|
||||
seePlayerN n role dist = playerNisRole n role ?=<< dist
|
||||
|
||||
playerNisSide :: Int -> Side -> Dist.Event Game
|
||||
playerNisSide n side game = getSide n game == side
|
||||
|
||||
-- trustLevel n game = tableTrust game !! n
|
||||
|
||||
playerSeesPlayerAndClaims :: Int -> Int -> Side -> Dist.Event Game
|
||||
playerSeesPlayerAndClaims p1 p2 claim game =
|
||||
if isGood p1 game
|
||||
then playerNisSide p2 claim game
|
||||
else if not (ladyWillLie game) then playerNisSide p2 claim game
|
||||
else playerNisSide p2 (otherSide claim) game
|
||||
|
||||
getSide x game = roleSide (trueRoles game !! x)
|
||||
|
||||
getRoundIgnorance round game = proposalIgnorant game * (decay game ** (round - 1)) > 0.5
|
||||
|
||||
getProposalDucks round game = proposalDucks game * (decay game ** (round - 1)) > 0.5
|
||||
|
||||
|
||||
teamIsGood [] game = True
|
||||
teamIsGood (x:xs) game = getSide x game == Good && (teamIsGood xs game)
|
||||
|
||||
doProposal team votes round game =
|
||||
foldl (||) False $ Prelude.map (proposalConstraints game) $ zip [0,1..] votes
|
||||
where
|
||||
proposalConstraints game (player, vote) =
|
||||
if vote == 1 then
|
||||
if getSide player game == Good then
|
||||
if teamIsGood team game then True
|
||||
else if getRoundIgnorance round game then True
|
||||
else False
|
||||
else
|
||||
if not (teamIsGood team game) then True
|
||||
else if getProposalDucks round game then True
|
||||
else False
|
||||
else
|
||||
if getSide player game == Good then
|
||||
if not (teamIsGood team game) then True
|
||||
else if getRoundIgnorance round game then True
|
||||
else False
|
||||
else
|
||||
if teamIsGood team game then True
|
||||
else if getProposalDucks round game then True
|
||||
else False
|
||||
|
||||
|
||||
|
||||
-- doVote :: [Int] -> Int -> Dist.Event Game
|
||||
doVote team successes round game =
|
||||
foldl (||) False $ Prelude.map (makeConstraints game) $ [(successes, x) | x <- permutations team]
|
||||
where
|
||||
makeConstraints game (0, []) = True
|
||||
makeConstraints game (0, (x:xs)) = getSide x game == Evil && (makeConstraints game (0,xs))
|
||||
makeConstraints game (n, (x:xs)) = (getSide x game == Good || (ducks round game && (getSide x game == Evil))) && (makeConstraints game ((n - 1), xs))
|
||||
ducks round game = if round > 2 then False else ((willDuckOnRound game) !! round)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
assertOnGame x game = x ?=<< game
|
||||
|
||||
assertions = [(doVote [0, 2] 1 1), (playerSeesPlayerAndClaims 0 1 Evil)]
|
||||
|
||||
applyAssertions = foldl (\x y -> (assertOnGame y x))
|
||||
|
||||
|
||||
dropNth i list = (take i list) ++ (drop (i+1) (list))
|
||||
{-seePlayerN n role dist = do-}
|
||||
{-val <- dist-}
|
||||
{-Dist.filter (playerNisRole n role) val-}
|
||||
{-return val-}
|
||||
|
||||
--main = putStrLn $ show (seePlayerN 0 good1 deals)
|
||||
|
||||
playerReport n dist =
|
||||
"Player " ++ show n ++ ":\n" ++
|
||||
" Is Good: " ++ show (playerNisSide n Good ?? dist) ++ "\n" ++
|
||||
" Is Evil: " ++ show (playerNisSide n Evil ?? dist) ++ "\n"
|
||||
|
||||
ladyLoop nPlayers stateSpace assertions command ls =
|
||||
let continueLoop = mainLoop nPlayers stateSpace assertions ls in
|
||||
let args = splitOn " " command in
|
||||
if length args < 4 then do
|
||||
putStrLn $ show args
|
||||
continueLoop
|
||||
else do
|
||||
putStrLn "Got it"
|
||||
let arg1 = read (args !! 1) :: Int
|
||||
let arg2 = read (args !! 2) :: Int
|
||||
let arg3 = if (read (args !! 3) :: Int) == 1 then Good else Evil
|
||||
mainLoop nPlayers stateSpace (assertions ++ [(playerSeesPlayerAndClaims arg1 arg2 arg3)]) (ls ++ [command])
|
||||
|
||||
assertLoop nPlayers stateSpace assertions command ls =
|
||||
let continueLoop = mainLoop nPlayers stateSpace assertions ls in
|
||||
let args = splitOn " " command in
|
||||
if length args < 3 then do
|
||||
putStrLn $ show args
|
||||
continueLoop
|
||||
else do
|
||||
putStrLn "Got it"
|
||||
let arg1 = read (args !! 1) :: Int
|
||||
let arg2 = read (args !! 2) :: Int
|
||||
let side = if arg2 == 0 then Evil else Good in
|
||||
mainLoop nPlayers stateSpace (assertions ++ [(playerNisSide arg1 side)]) (ls ++ [command])
|
||||
|
||||
propLoop nPlayers stateSpace assertions command ls =
|
||||
let continueLoop = mainLoop nPlayers stateSpace assertions ls in
|
||||
let args = splitOn " " command in
|
||||
if length args < 4 then do
|
||||
putStrLn $ show args
|
||||
continueLoop
|
||||
else do
|
||||
putStrLn "Got it"
|
||||
let arg1 = Prelude.map (\x -> (read x :: Int)) $ drop 1 $ splitOn "" (args !! 1)
|
||||
let arg2 = Prelude.map (\x -> (read x :: Int)) $ drop 1 $ splitOn "" (args !! 2)
|
||||
let arg3 = read (args !! 3) :: Double
|
||||
putStrLn $ show arg1
|
||||
putStrLn $ show arg2
|
||||
mainLoop nPlayers stateSpace (assertions ++ [(doProposal arg1 arg2 (arg3 - 1))]) (ls ++ [command])
|
||||
|
||||
voteLoop nPlayers stateSpace assertions command ls =
|
||||
let continueLoop = mainLoop nPlayers stateSpace assertions ls in
|
||||
let args = splitOn " " command in
|
||||
if length args < 4 then do
|
||||
putStrLn $ show args
|
||||
continueLoop
|
||||
else do
|
||||
putStrLn "Got it"
|
||||
let arg1 = Prelude.map (\x -> (read x :: Int)) $ drop 1 $ splitOn "" (args !! 1)
|
||||
let arg2 = read (args !! 2) :: Int
|
||||
let arg3 = read (args !! 3) :: Int
|
||||
putStrLn $ show arg1
|
||||
putStrLn $ show arg2
|
||||
mainLoop nPlayers stateSpace (assertions ++ [(doVote arg1 arg2 (arg3 - 1))]) (ls ++ [command])
|
||||
|
||||
mainLoop nPlayers stateSpace assertions ls = do
|
||||
let continueLoop = mainLoop nPlayers stateSpace assertions ls
|
||||
putStrLn $ "Tim " ++ show nPlayers ++ "> "
|
||||
command <- getLine
|
||||
if command == "quit"
|
||||
then return ()
|
||||
else if isPrefixOf "lol" command then
|
||||
ladyLoop nPlayers stateSpace assertions command ls
|
||||
else if isPrefixOf "ass" command then
|
||||
assertLoop nPlayers stateSpace assertions command ls
|
||||
else if isPrefixOf "ls" command then do
|
||||
putStrLn $ foldl (\x y -> x ++ (show $ fst y) ++ ": " ++ (snd y) ++ "\n") "" $ zip [0,1..] ls
|
||||
continueLoop
|
||||
else if isPrefixOf "deass" command then do
|
||||
let args = splitOn " " command
|
||||
let arg1 = read (args !! 1) :: Int
|
||||
mainLoop nPlayers stateSpace (dropNth arg1 assertions) (dropNth arg1 ls)
|
||||
else if isPrefixOf "vot" command then
|
||||
voteLoop nPlayers stateSpace assertions command ls
|
||||
else if isPrefixOf "pro" command then
|
||||
propLoop nPlayers stateSpace assertions command ls
|
||||
else if command == "eval" then do
|
||||
trace <- Control.Monad.Parallel.replicateM 100 (Rnd.run $ Rnd.pick $ applyAssertions stateSpace assertions)
|
||||
let traceDist = Dist.uniform trace
|
||||
putStrLn $ foldl (++) "" $ Prelude.map (flip playerReport traceDist) [0..(nPlayers - 1)]
|
||||
continueLoop
|
||||
else do
|
||||
putStrLn "Unknown"
|
||||
continueLoop
|
||||
|
||||
main = do
|
||||
putStrLn "N players? "
|
||||
players <- getLine
|
||||
let nplayers = read players :: Int
|
||||
mainLoop nplayers (stateSpace nplayers) [] []
|
||||
|
||||
22
tim-the-enchanter.cabal
Normal file
22
tim-the-enchanter.cabal
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
-- Initial tim-the-enchanter.cabal generated by cabal init. For further
|
||||
-- documentation, see http://haskell.org/cabal/users-guide/
|
||||
|
||||
name: tim-the-enchanter
|
||||
version: 0.1.0.0
|
||||
-- synopsis:
|
||||
-- description:
|
||||
license: BSD3
|
||||
license-file: LICENSE
|
||||
author: Barak Michener
|
||||
maintainer: me@barakmich.com
|
||||
-- copyright:
|
||||
category: Game
|
||||
build-type: Simple
|
||||
cabal-version: >=1.8
|
||||
|
||||
executable tim-the-enchanter
|
||||
-- main-is:
|
||||
Main-is: Tim.hs
|
||||
ghc-options: -O3 -threaded -rtsopts
|
||||
-- other-modules:
|
||||
build-depends: base ==4.6.*, probability, monad-parallel, split
|
||||
422
tim.py
422
tim.py
|
|
@ -3,138 +3,354 @@ import functools
|
|||
import itertools
|
||||
from collections import defaultdict as dd
|
||||
import pprint
|
||||
import numpy
|
||||
|
||||
|
||||
def ResistanceGame(n_players):
|
||||
full_set = [("G1", True), ("G2", True), ("G3", True), ("E1", False), ("E2", False),
|
||||
("G4", True), ("E3", False), ("G5", True), ("G6", True), ("E4", False)]
|
||||
return full_set[:n_players]
|
||||
full_set = [("G1", True), ("G2", True), ("G3", True),
|
||||
("E1", False), ("E2", False), ("G4", True),
|
||||
("E3", False), ("G5", True), ("G6", True), ("E4", False)]
|
||||
return full_set[:n_players]
|
||||
|
||||
|
||||
def BuildNbyNBeliefMatrix(id, n_players):
|
||||
all_vars = []
|
||||
matrix = []
|
||||
for player_id in range(n_players):
|
||||
vec = mc.Uniform("%d_trust_%d" % (id, player_id),
|
||||
0.0, 1.0,
|
||||
trace=True,
|
||||
size=n_players,
|
||||
value=(numpy.ones(n_players) * (1.0 / n_players)))
|
||||
matrix.append(vec)
|
||||
all_vars.append(vec)
|
||||
|
||||
# Enforce that there's only one role for each player.
|
||||
for i, player_vec in enumerate(matrix):
|
||||
@mc.potential
|
||||
def obs_one_role(player_vec=player_vec):
|
||||
return mc.distributions.normal_like(
|
||||
sum(player_vec),
|
||||
1.0,
|
||||
100)
|
||||
all_vars.append(obs_one_role)
|
||||
|
||||
# Enforce that there's only one player per role.
|
||||
for i in range(n_players):
|
||||
@mc.potential
|
||||
def obs_one_per_role(matrix=matrix):
|
||||
return mc.distributions.normal_like(
|
||||
sum([vec[i] for vec in matrix]),
|
||||
1.0,
|
||||
100)
|
||||
all_vars.append(obs_one_per_role)
|
||||
|
||||
return matrix, all_vars
|
||||
|
||||
|
||||
class Player(object):
|
||||
''' Representing all that the player is and knows '''
|
||||
def __init__(self, id, game):
|
||||
self.id = id
|
||||
self.game = game
|
||||
self.all_vars = []
|
||||
self.build_belief_matrix()
|
||||
|
||||
def side(self):
|
||||
return self.side_var
|
||||
|
||||
def role(self):
|
||||
return self.role_var
|
||||
|
||||
def build_belief_matrix(self):
|
||||
self.matrix, self.all_vars = \
|
||||
BuildNbyNBeliefMatrix(self.id, self.game.n_players)
|
||||
|
||||
# Enforce that the player completely knows her own role.
|
||||
@mc.potential
|
||||
def knows(deck_var=self.game.deck_var, matrix=self.matrix):
|
||||
role_id = self.game.player_role_for_deck_var(deck_var, self.id)
|
||||
return mc.distributions.normal_like(
|
||||
matrix[self.id][role_id],
|
||||
1.0,
|
||||
100)
|
||||
self.all_vars.append(knows)
|
||||
|
||||
def get_role_belief_for(self, player_id, role_id):
|
||||
return self.matrix[player_id][role_id]
|
||||
|
||||
|
||||
class DeceptionGame(object):
|
||||
def __init__(self, player_array):
|
||||
self.player_array = player_array
|
||||
self.all_permutations = list(itertools.permutations(player_array))
|
||||
self.deck_var = mc.DiscreteUniform("deal", 0, len(self.all_permutations) - 1)
|
||||
self.n_players = len(player_array)
|
||||
self.model = None
|
||||
def __init__(self, player_array):
|
||||
self.player_array = player_array
|
||||
self.all_permutations = list(itertools.permutations(player_array))
|
||||
self.deck_var = mc.DiscreteUniform("deal", 0,
|
||||
len(self.all_permutations) - 1)
|
||||
self.n_players = len(player_array)
|
||||
self.model = None
|
||||
|
||||
self.player_side_vars = []
|
||||
self.player_role_vars = []
|
||||
self.role_ids = {}
|
||||
self.role_side = {}
|
||||
|
||||
self.player_alliance_vars = []
|
||||
self.player_role_vars = []
|
||||
self.role_ids = {}
|
||||
self.role_alliance = {}
|
||||
i = 0
|
||||
i = 0
|
||||
|
||||
for card in player_array:
|
||||
role, good = card
|
||||
self.role_ids[role] = i
|
||||
self.role_alliance[i] = good
|
||||
i += 1
|
||||
for card in player_array:
|
||||
role, good = card
|
||||
self.role_ids[role] = i
|
||||
self.role_side[i] = good
|
||||
i += 1
|
||||
|
||||
def player_alliance(x, role):
|
||||
return self.role_alliance[role]
|
||||
def player_side(x, role):
|
||||
if self.role_side[role]:
|
||||
return True
|
||||
return False
|
||||
|
||||
def player_role(x, deck_var = self.deck_var):
|
||||
role_str = self.all_permutations[deck_var][x][0]
|
||||
return self.role_ids[role_str]
|
||||
def player_role(x, deck_var=self.deck_var):
|
||||
role_str = self.all_permutations[deck_var][x][0]
|
||||
return int(self.role_ids[role_str])
|
||||
|
||||
for x in range(self.n_players):
|
||||
role = mc.Deterministic(eval = functools.partial(player_role, x),
|
||||
name = "player_role_%d" % x,
|
||||
parents = { "deck_var" : self.deck_var },
|
||||
doc = "Who is player %d?" % x,
|
||||
dtype = str,
|
||||
trace = True,
|
||||
plot = False)
|
||||
self.player_role_vars.append(role)
|
||||
self.players = []
|
||||
|
||||
alliance = mc.Deterministic(eval = functools.partial(player_alliance, x),
|
||||
name = "player_alliance_%d" % x,
|
||||
parents = { "role" : role},
|
||||
doc = "Is player %d good?" % x,
|
||||
dtype = bool,
|
||||
trace = True,
|
||||
plot = False)
|
||||
for x in range(self.n_players):
|
||||
role = mc.Deterministic(eval=functools.partial(player_role, x),
|
||||
name="player_role_%d" % x,
|
||||
parents={"deck_var": self.deck_var},
|
||||
doc="Who is player %d?" % x,
|
||||
dtype=int,
|
||||
trace=True,
|
||||
plot=False)
|
||||
self.player_role_vars.append(role)
|
||||
|
||||
self.player_alliance_vars.append(alliance)
|
||||
side = mc.Deterministic(eval=functools.partial(
|
||||
player_side, x),
|
||||
name="player_side_%d" % x,
|
||||
parents={"role": role},
|
||||
doc="Is player %d good?" % x,
|
||||
dtype=bool,
|
||||
trace=True,
|
||||
plot=False)
|
||||
|
||||
self.observations = []
|
||||
self.tid = 0
|
||||
self.player_side_vars.append(side)
|
||||
#self.players.append(Player(x, self))
|
||||
|
||||
def add_known_alliance(self, player_id, is_good):
|
||||
transaction = []
|
||||
obs = mc.Bernoulli("player_seen_tid%d" % self.tid,
|
||||
self.player_alliance_vars[player_id],
|
||||
value = is_good,
|
||||
observed = True)
|
||||
transaction.append(obs)
|
||||
self.observations.append(transaction)
|
||||
self.tid += 1
|
||||
self.lady_will_duck = mc.Bernoulli("lady_will_duck", 0.5)
|
||||
self.team_duck = [None] * 5
|
||||
self.team_duck[0] = mc.Bernoulli("team_duck_1", 0.8)
|
||||
self.team_duck[1] = mc.Bernoulli("team_duck_2", 0.6)
|
||||
self.team_duck[2] = mc.Bernoulli("team_duck_3", 0.4)
|
||||
self.team_duck[3] = mc.Bernoulli("team_duck_4", 0.2)
|
||||
self.team_duck[4] = mc.Bernoulli("team_duck_5", 0.0)
|
||||
|
||||
def add_known_role(self, player_id, role_str):
|
||||
transaction = []
|
||||
obs = mc.Bernoulli("player_seen_role_tid%d" % self.tid,
|
||||
self.player_role_vars[player_id],
|
||||
value = self.role_ids[role_str],
|
||||
observed = True)
|
||||
transaction.append(obs)
|
||||
self.observations.append(transaction)
|
||||
self.tid += 1
|
||||
self.observations = []
|
||||
self.tid = 0
|
||||
|
||||
def get_role_id_for(self, name):
|
||||
return self.role_ids[name]
|
||||
|
||||
def eval(self, length=40000):
|
||||
mcmc = mc.MCMC(self._build_model_list())
|
||||
mcmc.sample(length, 2000)
|
||||
self.model = mcmc
|
||||
def role_id_is_good(self, role_id):
|
||||
return self.role_side[role_id]
|
||||
|
||||
def report(self):
|
||||
if self.model is None:
|
||||
self.eval()
|
||||
out = []
|
||||
for i in range(self.n_players):
|
||||
out.append(self.get_player_data(i))
|
||||
return out
|
||||
def player_good_for_deck_var(self, index, player):
|
||||
return self.all_permutations[index][player][1]
|
||||
|
||||
def get_player_data(self, i):
|
||||
out = {}
|
||||
role_key = "player_role_%d" % i
|
||||
alliance_key = "player_alliance_%d" % i
|
||||
def player_role_for_deck_var(self, index, player):
|
||||
return self.get_role_id_for(self.all_permutations[index][player][0])
|
||||
|
||||
temp_role = self._aggregate(list(self.model.trace(role_key)))
|
||||
out["role"] = {}
|
||||
for k, v in temp_role.iteritems():
|
||||
out["role"][self.player_array[int(k)][0]] = v
|
||||
out["alliance"] = self._aggregate(list(self.model.trace(alliance_key)))
|
||||
return out
|
||||
def player_sees_player_and_claims(self, player_view, player_give, claim):
|
||||
transaction = []
|
||||
total_len = len(self.all_permutations)
|
||||
for i in range(len(self.all_permutations)):
|
||||
self.deck_var.value = (5119 * i) % total_len
|
||||
try:
|
||||
@mc.potential
|
||||
def claims(deck_var=self.deck_var, will_duck=self.lady_will_duck):
|
||||
if self.player_good_for_deck_var(deck_var, player_view) or will_duck:
|
||||
if self.player_good_for_deck_var(deck_var, player_give) == claim:
|
||||
return 0.0
|
||||
else:
|
||||
return -numpy.inf
|
||||
else:
|
||||
if self.player_good_for_deck_var(deck_var, player_give) == claim:
|
||||
return -numpy.inf
|
||||
else:
|
||||
return 0.0
|
||||
|
||||
def _aggregate(self, l):
|
||||
out = dd(float)
|
||||
size = len(l) * 1.0
|
||||
for x in l:
|
||||
out[x] += 1 / size
|
||||
return dict(out)
|
||||
return -numpy.inf
|
||||
except mc.ZeroProbability:
|
||||
continue
|
||||
|
||||
transaction.append(claims)
|
||||
self.observations.append(transaction)
|
||||
self.tid += 1
|
||||
|
||||
def print_report(self):
|
||||
pp = pprint.PrettyPrinter(indent = 4)
|
||||
pp.pprint(self.report())
|
||||
def add_known_side(self, player_id, is_good):
|
||||
transaction = []
|
||||
total_len = len(self.all_permutations)
|
||||
for i in range(len(self.all_permutations)):
|
||||
self.deck_var.value = (5119 * i) % total_len
|
||||
try:
|
||||
@mc.potential
|
||||
def obs(deck_var=self.deck_var):
|
||||
x = float(self.player_good_for_deck_var(deck_var, player_id)) - \
|
||||
float(is_good)
|
||||
return mc.distributions.normal_like(x, 0.0, 10000)
|
||||
except mc.ZeroProbability:
|
||||
continue
|
||||
break
|
||||
|
||||
def _build_model_list(self):
|
||||
out = []
|
||||
out.append(self.deck_var)
|
||||
out.extend(self.player_alliance_vars[:])
|
||||
out.extend(self.player_role_vars[:])
|
||||
flattened = [item for transaction in self.observations for item in transaction]
|
||||
out.extend(flattened[:])
|
||||
return list(set(out))
|
||||
transaction.append(obs)
|
||||
self.observations.append(transaction)
|
||||
self.tid += 1
|
||||
|
||||
def add_known_role(self, player_id, role_str):
|
||||
transaction = []
|
||||
known_role_id = self.get_role_id_for(role_str)
|
||||
total_len = len(self.all_permutations)
|
||||
for i in range(len(self.all_permutations)):
|
||||
self.deck_var.value = (5119 * i) % total_len
|
||||
try:
|
||||
@mc.potential
|
||||
def role(deck_var=self.deck_var):
|
||||
x = self.player_role_for_deck_var(deck_var, player_id) \
|
||||
- known_role_id
|
||||
return mc.distributions.normal_like(x, 0.0, 10000)
|
||||
|
||||
except mc.ZeroProbability:
|
||||
continue
|
||||
break
|
||||
|
||||
transaction.append(role)
|
||||
self.observations.append(transaction)
|
||||
self.tid += 1
|
||||
|
||||
def build_team(self, team, votes, required_success):
|
||||
transaction = []
|
||||
|
||||
for voter in range(self.n_players):
|
||||
total_len = len(self.all_permutations)
|
||||
for i in range(len(self.all_permutations)):
|
||||
self.deck_var.value = (5119 * i) % total_len
|
||||
try:
|
||||
@mc.potential
|
||||
def build_team(deck_var=self.deck_var):
|
||||
voter_is_good = self.player_good_for_deck_var(deck_var, voter)
|
||||
if voter_is_good:
|
||||
return mc.distributions.normal_like(x - n_successes, 0.0, 1000)
|
||||
else:
|
||||
return mc.distributions.normal_like(x - required_success, len(team) -
|
||||
team_votes.name = "voter_%d_tid%d" % (voter, self.tid)
|
||||
|
||||
except mc.ZeroProbability:
|
||||
continue
|
||||
break
|
||||
|
||||
transaction.append(team_votes)
|
||||
self.observations.append(transaction)
|
||||
self.tid += 1
|
||||
def team_and_successes(self, team, n_successes, mandatory, r):
|
||||
transaction = []
|
||||
|
||||
total_len = len(self.all_permutations)
|
||||
for i in range(len(self.all_permutations)):
|
||||
self.deck_var.value = (5119 * i) % total_len
|
||||
try:
|
||||
@mc.potential
|
||||
def team_votes(deck_var=self.deck_var, team_duck=self.team_duck[r - 1]):
|
||||
team_allegience = [self.player_good_for_deck_var(deck_var, x)
|
||||
for x in team]
|
||||
for i, al in enumerate(team_allegience):
|
||||
if al is True:
|
||||
continue
|
||||
else:
|
||||
if not mandatory and team_duck:
|
||||
print "Ducking"
|
||||
team_allegience[i] = True
|
||||
|
||||
x = sum([float(x) for x in team_allegience])
|
||||
return mc.distributions.normal_like(x - n_successes, 0.0, 1000)
|
||||
team_votes.name = "team_votes_tid%d" % self.tid
|
||||
|
||||
except mc.ZeroProbability:
|
||||
continue
|
||||
break
|
||||
|
||||
transaction.append(team_votes)
|
||||
self.observations.append(transaction)
|
||||
self.tid += 1
|
||||
|
||||
def eval(self, length=60000, burn=30):
|
||||
mcmc = mc.MCMC(self._build_model_list())
|
||||
mcmc.sample(length, burn)
|
||||
self.model = mcmc
|
||||
|
||||
def eval_model_sans_players(self, length=40000, burn=0):
|
||||
mcmc = mc.MCMC(self._build_restricted_model_list())
|
||||
#mcmc.use_step_method(mc.DiscreteMetropolis, self.deck_var, proposal_distribution='Prior')
|
||||
mcmc.sample(length, burn, tune_throughout=False)
|
||||
|
||||
def report(self):
|
||||
if self.model is None:
|
||||
self.eval()
|
||||
out = []
|
||||
for i in range(self.n_players):
|
||||
out.append(self.get_player_data(i))
|
||||
return out
|
||||
|
||||
def get_player_data(self, i):
|
||||
out = {}
|
||||
role_key = "player_role_%d" % i
|
||||
side_key = "player_side_%d" % i
|
||||
|
||||
temp_role = self._aggregate(list(self.model.trace(role_key)))
|
||||
out["role"] = {}
|
||||
for k, v in temp_role.iteritems():
|
||||
out["role"][self.player_array[int(k)][0]] = v
|
||||
out["side"] = self._aggregate(list(self.model.trace(side_key)))
|
||||
return out
|
||||
|
||||
def _aggregate(self, l):
|
||||
out = dd(float)
|
||||
size = len(l) * 1.0
|
||||
for x in l:
|
||||
out[x] += 1 / size
|
||||
return dict(out)
|
||||
|
||||
def print_report(self):
|
||||
pp = pprint.PrettyPrinter(indent=4)
|
||||
pp.pprint(self.report())
|
||||
|
||||
def _build_restricted_model_list(self):
|
||||
out = []
|
||||
out.append(self.deck_var)
|
||||
out.extend(self.player_side_vars[:])
|
||||
out.extend(self.player_role_vars[:])
|
||||
return out
|
||||
|
||||
def _build_model_list(self):
|
||||
out = []
|
||||
out.append(self.deck_var)
|
||||
out.append(self.lady_will_duck)
|
||||
out.extend(self.player_side_vars[:])
|
||||
out.extend(self.player_role_vars[:])
|
||||
for duck in self.team_duck:
|
||||
out.append(duck)
|
||||
for player in self.players:
|
||||
out.extend(player.all_vars[:])
|
||||
flattened = [item for transaction in self.observations
|
||||
for item in transaction]
|
||||
out.extend(flattened[:])
|
||||
return list(set(out))
|
||||
|
||||
|
||||
base_game = DeceptionGame(ResistanceGame(5))
|
||||
base_game.eval(10000)
|
||||
base_game.add_known_role(0, "G1")
|
||||
base_game.add_known_alliance(1, False)
|
||||
#base_game.add_known_role(0, "G1")
|
||||
base_game.build_team([0, 1, 2], [1, 0, 1, 1, 0], 1)
|
||||
base_game.team_and_successes([0, 1, 2], 2, 1, False)
|
||||
#base_game.team_and_successes([0, 1, 2], 2, 2, False)
|
||||
#base_game.player_sees_player_and_claims(0, 1, False)
|
||||
#base_game.add_known_side(1, False)
|
||||
base_game.eval()
|
||||
|
||||
base_game.print_report()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue