big refactor

This commit is contained in:
Thorn Avery 2019-05-21 22:22:10 +12:00
parent c856496ffc
commit bb439a3169
13 changed files with 334 additions and 202 deletions

View File

@ -1,85 +0,0 @@
module Groups where
import Util
import Types
-- Each factions corresponding Main Character
defCharsFaction :: Faction -> MainCharacter
defCharsFaction Blue = Shinji
defCharsFaction Red = Asuka
defCharsFaction White = Rei
defCharsFaction Green = Misato
defCharsFaction Yellow = Ritsuko
defCharsFaction Black = Gendo
-- Each characters default adjacents
defFrens :: MainCharacter -> [MainCharacter]
defFrens Asuka = [Rei, Shinji, Misato]
defFrens Shinji = [Rei, Gendo, Ritsuko, Misato, Asuka]
defFrens Rei = [Gendo, Shinji, Asuka]
defFrens Misato = [Asuka, Shinji, Ritsuko]
defFrens Ritsuko = [Misato, Shinji, Gendo]
defFrens Gendo = [Rei, Shinji, Ritsuko]
-- Return true if charater is downed
isDowned :: MainCharacter -> Downed -> Bool
isDowned c d = c `elem` d
-- Return true if character is not grouped
isAlone :: MainCharacter -> Groups -> Bool
isAlone c g = curFrens c g == []
-- Return true if X is adjacent to Y
isAdjacent :: MainCharacter -> MainCharacter -> Groups -> Bool
isAdjacent x y g = y `elem` (getAdj x g)
-- All characters a X is adjacent to
getAdj :: MainCharacter -> Groups -> [MainCharacter]
getAdj x g = curFrens x g ++ (foldr (++) [] (adjGroups x g))
-- The characters currently grouped with x
curFrens :: MainCharacter -> Groups -> [MainCharacter]
curFrens x g = filter (/= x) $ charsGroup x g
-- The group that character x belongs to
charsGroup :: MainCharacter -> Groups -> Group
charsGroup x g = head $ filter (\y -> x `elem` y) g
-- The groups a character isnt in
otherGroups :: MainCharacter -> Groups -> Groups
otherGroups x g = filter (\y -> not $ x `elem` y) g
-- The groups a character is adaject to
adjGroups :: MainCharacter -> Groups -> Groups
adjGroups x g = filter (\y -> any (\z -> z `elem` adjFrens) y) (otherGroups x g)
where
adjFrens = uniq $ foldr (++) [] (map defFrens $ charsGroup x g)
-- The groups a group is adjacent to
neighborGroups :: Group -> Groups -> Groups
neighborGroups g gs = uniq . concat $ map (\x -> adjGroups x gs) g
-- Return the groups with C removed from its current group
removeFromGroup :: MainCharacter -> Groups -> Groups
removeFromGroup c g = ( [c] : (groupMinusChar c) : (otherGroups c g) )
where
groupMinusChar x = curFrens x g
-- Return the groups with X grouped with Y
joinGroups :: MainCharacter -> MainCharacter -> Groups -> Groups
joinGroups x y g
| x `elem` curFrens y g = g
| otherwise = (groupX ++ groupY) : (otherGroups x . otherGroups y) g
where
groupX = charsGroup x g
groupY = charsGroup y g
-- Return the Downed with the new character
downChar :: MainCharacter -> Downed -> Downed
downChar c d
| c `elem` d = d
| otherwise = (c : d)
-- Return the Downed minus the chosen character
readyChar :: MainCharacter -> Downed -> Downed
readyChar c d = filter (/= c) d

25
src/Cogs/Cards.hs Normal file
View File

@ -0,0 +1,25 @@
module Cogs.Cards where
-- == Cogs - Cards ==
-- Functions of type :: Arg1... -> BoardState -> a
-- Get information about cards
-- ==
import ComBoard.Types
import Toolbox.Utils
-- Return info for CardSym
getCardInfo :: CardSym -> BoardState -> CardInfo
getCardInfo c bs = snd $ head $ filter (\(s, _) -> s == c) cl
where cl = (bsCardLib bs)
-- Return the Line on CardSym
getCardLine :: CardSym -> BoardState -> String
getCardLine c bs = '"' : (unwrapMaybe (ciLine (getCardInfo c cl))) ++ ['"']
where cl = (bsCardLib bs)
-- Return the Name of CardSym
getCardName :: CardSym -> BoardState -> String
getCardName c bs = (unwrapMaybe (ciName (getCardInfo c cl)))
where cl = (bsCardLib bs)

75
src/Cogs/Groups.hs Normal file
View File

@ -0,0 +1,75 @@
module Cogs.Groups where
-- == Cogs - Groups ==
-- Functions of type :: Arg1... -> BoardState -> a
-- Gets information about groups
-- ====
import ComBoard.Types
import Toolbox.Utils
-- Each factions corresponding Main Character
defCharsFaction :: Faction -> MainCharacter
defCharsFaction Blue = Shinji
defCharsFaction Red = Asuka
defCharsFaction White = Rei
defCharsFaction Green = Misato
defCharsFaction Yellow = Ritsuko
defCharsFaction Black = Gendo
-- Each characters default adjacents
defFrens :: MainCharacter -> [MainCharacter]
defFrens Asuka = [Rei, Shinji, Misato]
defFrens Shinji = [Rei, Gendo, Ritsuko, Misato, Asuka]
defFrens Rei = [Gendo, Shinji, Asuka]
defFrens Misato = [Asuka, Shinji, Ritsuko]
defFrens Ritsuko = [Misato, Shinji, Gendo]
defFrens Gendo = [Rei, Shinji, Ritsuko]
-- Return true if charater is downed
isDowned :: MainCharacter -> BoardState -> Bool
isDowned c bs = c `elem` d
where d = (ntDowned . bsNeoTokyo) bs
-- Return true if character is not grouped
isAlone :: MainCharacter -> BoardState -> Bool
isAlone c bs = curFrens c g == []
where g = (ntGroups . bsNeoTokyo) bs
-- Return true if X is adjacent to Y
isAdjacent :: MainCharacter -> MainCharacter -> BoardState -> Bool
isAdjacent x y bs = y `elem` (getAdj x g)
where g = (ntGroups . bsNeoTokyo) bs
-- All characters a X is adjacent to
getAdj :: MainCharacter -> BoardState -> [MainCharacter]
getAdj x bs = curFrens x g ++ (foldr (++) [] (adjGroups x g))
where g = (ntGroups . bsNeoTokyo) bs
-- The characters currently grouped with x
curFrens :: MainCharacter -> BoardState -> [MainCharacter]
curFrens x bs = filter (/= x) $ charsGroup x g
where g = (ntGroups . bsNeoTokyo) bs
-- The group that character x belongs to
charsGroup :: MainCharacter -> BoardState -> Group
charsGroup x bs = head $ filter (\y -> x `elem` y) g
where g = (ntGroups . bsNeoTokyo) bs
-- The groups a character isnt in
otherGroups :: MainCharacter -> BoardState -> Groups
otherGroups x bs = filter (\y -> not $ x `elem` y) g
where g = (ntGroups . bsNeoTokyo) bs
-- The groups a character is adaject to
adjGroups :: MainCharacter -> BoardState -> Groups
adjGroups x bs = filter (\y -> any (\z -> z `elem` adjFrens) y) (otherGroups x g)
where
adjFrens = uniq $ foldr (++) [] (map defFrens $ charsGroup x g)
g = (ntGroups . bsNeoTokyo) bs
-- The groups a group is adjacent to
neighborGroups :: Group -> BoardState -> Groups
neighborGroups g bs = uniq . concat $ map (\x -> adjGroups x gs) g
where g = (ntGroups . bsNeoTokyo) bs

View File

@ -1,43 +1,35 @@
module Players where
module Cogs.Players where
import Types
-- == Cogs - Players ==
-- Functions of the type :: Arg1... -> BoardState -> a
-- Get information about players
-- ====
import ComBoard.Types
import Util
-- Returns whether CardSym is in PlayerId's hand
isInHand :: CardSym -> PlayerId -> BoardState -> Bool
isInHand c p bs = c `elem` (psHand player)
where
playerLib = (bsPlayerLib bs)
player = snd $ getFirstMatchNS playerLib (matchSnd p)
-- Returns the player info for PlayerId
findPlayer :: PlayerId -> BoardState -> PlayerState
findPlayer p bs = snd $ getFirstMatchNS pl (matchSnd p)
where
pl = (bsPlayerLib bs)
-- Returns the hand of PlayerId
getHand :: PlayerId -> BoardState -> Hand
getHand p bs = psHand (findPlayer p bs)
-- Returns the discard of PlayerId
getDiscard :: PlayerId -> BoardState -> Discard
getDiscard p bs = psDiscard (findPlayer p bs)
-- Returns the name of PlayerId
playerName :: PlayerId -> BoardState -> String
playerName p bs = psPlayerName (findPlayer p bs)
removeFromHand :: PlayerId -> CardSym -> BoardState -> Hand
removeFromHand p c bs = rmFirstMatch (getHand p bs) (== c)
addToDiscard :: PlayerId -> CardSym -> BoardState -> Discard
addToDiscard p c bs = c : (getDiscard p bs)
handToDiscard :: PlayerId -> CardSym -> BoardState -> PlayerState
handToDiscard p c bs = ps
{ psHand = removeFromHand p c bs
, psDiscard = addToDiscard p c bs
}
where
ps = (findPlayer p bs)
adjustDP :: PlayerId -> Integer -> BoardState -> PlayerState
adjustDP p i bs = ps { psDP = (psDP ps) + i }
where
ps = (findPlayer p bs)

View File

@ -1,14 +1,12 @@
module Cards where
module ComBoard.Cards where
import Types
import Util
-- == Comboard - Cards ==
-- Hardcoded values for Cards
-- ====
getCardInfo :: CardSym -> CardLib -> CardInfo
getCardInfo c cl = snd $ head $ filter (\(s, _) -> s == c) cl
getCardLine :: CardSym -> CardLib -> String
getCardLine c cl = '"' : (unwrapMaybe (ciLine (getCardInfo c cl))) ++ ['"']
import ComBoard.Types
-- List of all CardSyms and respective Information
gCardLib :: CardLib
gCardLib =
[ (S01_Shinji, ciS01_Shinji)
@ -19,6 +17,10 @@ gCardLib =
, (S06_Gendo, ciS06_Gendo)
]
-- ==
-- Individual Card Info
-- ==
ciS01_Shinji :: CardInfo
ciS01_Shinji = CardInfo
{ ciName = "3rd Child - Shinji Ikari"

View File

@ -1,7 +1,11 @@
module Init where
module ComBoard.Init where
import Types
import Cards
-- == ComBoard Init ==
-- Initial State for ComBoard
-- ====
import ComBoard.Types
import ComBoard.Cards
initBS :: BoardState
initBS = BoardState

View File

@ -1,4 +1,8 @@
module Print where
module ComBoard.Printer where
-- == ComBoard - Printer ==
-- Prints the state of the ComBoard
-- ====
import Types
import Groups

View File

@ -1,66 +1,22 @@
module Types where
module ComBoard.Types where
-- == ComBoard - Types ==
-- Data Types for the BoardState
-- ====
-- Board piece names
data MainCharacter = Shinji | Asuka | Rei | Misato | Ritsuko | Gendo deriving (Show, Eq)
data MainEva = UnitZero | UnitOne | UnitTwo deriving (Show, Eq)
data Angel = Sachiel | Shamshel | Ramiel | Gaghiel | Israfel | Sandalphon | Matariel | Sahaquiel | Ireul | Leliel | Bardiel | Zeruel | Arael | Armisael | Kaworu | Man | Lilith | Adam
-- Card Pool symbols
data CardSym = S01_Shinji | S02_Asuka | S03_Rei | S04_Misato | S05_Ritsuko | S06_Gendo deriving (Show, Eq)
-- TODO
-- * Create worker functions for the Card Stack
-- work into playing line
-- Card types
type CardLib = [(CardSym, CardInfo)]
type Downed = [MainCharacter]
type PutCards = [(Either MainCharacter MainEva, CardSym)]
type ActiveLine = Maybe LineMeta
data LineMeta = LineMeta
{ cmCardSym :: CardSym
, cmOwner :: PlayerId
, cmTarget :: MainCharacter
, cmLineMark :: LineMark
}
data NeoTokyo = NeoTokyo
{ ntGroups :: Groups
, ntEvas :: Evas
, ntAngels :: Angels
, ntPutCards :: PutCards
, ntDowned :: Downed
}
type Evas = [MainEva]
type Group = [MainCharacter]
type Groups = [Group]
type Angels = [Angel]
data BoardState = BoardState
{ bsNeoTokyo :: NeoTokyo
, bsPlayerLib :: PlayerLib
, bsActivePlayers :: ActivePlayers
, bsPriorityPlayer :: PriorityPlayer
, bsActiveLine :: ActiveLine
, bsCardLib :: CardLib
, bsGameLog :: GameLog
}
type PlayerLib = [(PlayerId, PlayerState)]
type ActivePlayers = [PlayerId]
type PriorityPlayer = PlayerId
type PlayerId = Integer
data PlayerState = PlayerState
{ psPlayerName :: PlayerName
, psHand :: Hand
, psDeck :: Deck
, psDiscard :: Discard
, psDP :: Integer
} deriving (Show, Eq)
type PlayerName = String
type Hand = [CardSym]
type Deck = [CardSym]
type Discard = [CardSym]
type GameLog = [GameMessage]
type GameMessage = Either GameLine GameError
type GameLine = String
type GameError = String
data Faction = Blue | Red | White | Green | Yellow | Black deriving (Show)
data TypeSym = Character | Eva | Angel | Drama | Put | Intstrumentality deriving (Show, Eq)
data Trait = Other | Reaction | Male | Female | Weapon deriving (Show)
@ -68,7 +24,6 @@ type Traits = [Trait]
data Mark = Circle | Triangle deriving (Show)
type LineMark = (Mark, Faction)
type LineMarks = [LineMark]
data CardInfo = CardInfo
{ ciName :: String
, ciFaction :: Faction
@ -83,3 +38,54 @@ data CardInfo = CardInfo
, ciNextInst :: Maybe CardSym
} deriving (Show)
-- Player types
type PlayerLib = [(PlayerId, PlayerState)]
type PlayerId = Integer
type PlayerName = String
data PlayerState = PlayerState
{ psPlayerName :: PlayerName
, psHand :: Hand
, psDeck :: Deck
, psDiscard :: Discard
, psDP :: Integer
} deriving (Show, Eq)
-- NeoTokyo types
data NeoTokyo = NeoTokyo
{ ntGroups :: Groups
, ntEvas :: Evas
, ntAngels :: Angels
, ntPutCards :: PutCards
, ntDowned :: Downed
}
type Evas = [MainEva]
type Group = [MainCharacter]
type Groups = [Group]
type Angels = [Angel]
type Downed = [MainCharacter]
type PutCards = [(Either MainCharacter MainEva, CardSym)]
-- Game types
type ActivePlayers = [PlayerId]
type PriorityPlayer = PlayerId
type ActiveLine = Maybe LineMeta
type GameLog = [GameMessage]
type GameMessage = Either GameLine GameError
type GameLine = String
type GameError = String
data LineMeta = LineMeta
{ cmCardSym :: CardSym
, cmOwner :: PlayerId
, cmTarget :: MainCharacter
, cmLineMark :: LineMark
}
data BoardState = BoardState
{ bsNeoTokyo :: NeoTokyo
, bsPlayerLib :: PlayerLib
, bsActivePlayers :: ActivePlayers
, bsPriorityPlayer :: PriorityPlayer
, bsActiveLine :: ActiveLine
, bsCardLib :: CardLib
, bsGameLog :: GameLog
}

30
src/Leads/ComBoard.hs Normal file
View File

@ -0,0 +1,30 @@
module Leads.ComBoard where
-- == Leads - ComBoard ==
-- Functions of type :: Arg1... -> BoardState -> BoardState
-- Sets state for the ComBoard
-- ====
import ComBoard.Types
import Cogs.Players
-- Sets the groups in NeoTokyo
setGroups :: Groups -> BoardState -> BoardState
setGroups gs bs = bs
{ bsNeoTokyo = (bsNeoTokyo bs) { nsGroups = gs } }
-- Sets the downed in NeoTokyo
setDowned :: Downed -> BoardState -> BoardState
setDowned d bs = bs
{ bsNeoTokyo = (bsNeoTokyo bs) { ntDowned = d } }
-- Sets the player lib
setPlayerLib :: PlayerLib -> BoardState -> BoardState
setPlayerLib pl bs = bs { bsPlayerLib = pl }
-- Sets a players state
setPlayer :: PlayerId -> PlayerState -> BoardState -> BoardState
setPlayer pi ps bs = setPlayerLib $ map
(\(pid,state) -> if (pid == pi) then ps else state) pl
where
pl = (bsPlayerLib bs)

View File

@ -1,35 +1,13 @@
module Connect where
module Leads.Groups where
import Types
import Groups
import Players
-- == Leads - Groups ==
-- Functions of type :: Arg1... -> BoardState -> BoardState
-- Changes state of groups
-- IDEAS
-- * Bank of bool function, boardstate affection pairs
-- One global, one per player
-- used as a list of restrictions for whether you can play a card.
-- * Further, make it a list of restrictions, for going in timing order.
-- makes for better log messages.
import ComBoard.Types
import Cogs.Groups
--conAnnounceLine :: PlayerId -> CardSym -> MainCharacter -> BoardState -> BoardState
--conAnnounceLine p l t oldBoardState
-- | not $ PlayerId `elem` (bsPlayerLib oldBoardState) = oldBoardState
-- { bsGameLog = (bsGameLog oldBoardState)
-- ++ [ Right ("Player " ++ show PlayerId ++ " is not in the game") ]
-- }
-- | not $ isInHand l p oldBoardState = oldBoardState
-- { bsGameLog = (bsGameLog oldBoardState)
-- ++ [ Right (show CardSym ++ " is not in " ++ (playerName p) ++ "'s hand" ]
-- }
-- | otherwise = oldBoardState
-- { bsGameLog = (bsGameLog oldBoardState)
-- ++ [ Left (playerName p oldBoardState) ++ " announced " ++ (getCardLine l) ++ ", moved to active" ]
-- , bsCardStack
-- TODO
-- * manipulate the card stack after writing it
-- Passes state for X to hurt Y
-- X hurts Y
conHurt :: MainCharacter -> MainCharacter -> BoardState -> BoardState
conHurt charX charY oldBoardState
| not $ isAdjacent charX charY oldGroups = oldBoardState
@ -55,7 +33,7 @@ conHurt charX charY oldBoardState
oldGroups = (ntGroups . bsNeoTokyo) oldBoardState
oldPut = (ntPutCards . bsNeoTokyo) oldBoardState
-- Passes state for X to attract Y
-- X attracts Y
conAttract :: MainCharacter -> MainCharacter -> BoardState -> BoardState
conAttract charX charY oldBoardState
| not $ isAdjacent charX charY oldGroups = oldBoardState

41
src/Leads/Groups.hs Normal file
View File

@ -0,0 +1,41 @@
module Leads.Groups where
-- == Leads - Groups ==
-- Functions of the type :: Arg1... -> BoardState -> BoardState
-- Changes state of groups
-- ====
import Leads.ComBoard
import ComBoard.Types
import Toolbox.Utils
-- Return the groups with C removed from its current group
removeFromGroup :: MainCharacter -> BoardState -> BoardState
removeFromGroup c bs = setGroups ( [c] : (groupMinusChar c) : (otherGroups c g) ) bs
where
groupMinusChar x = curFrens x g
g = (ntGroups . bsNeoTokyo) bs
-- Return the groups with X grouped with Y
joinGroups :: MainCharacter -> MainCharacter -> BoardState -> BoardState
joinGroups x y bs
| x `elem` curFrens y g = bs
| otherwise = setGroups ((groupX ++ groupY) : (otherGroups x . otherGroups y) g) bs
where
g = (ntGroups . bsNeoTokyo) bs
groupX = charsGroup x g
groupY = charsGroup y g
-- Return the Downed with the new character
downChar :: MainCharacter -> BoardState -> BoardState
downChar c bs
| c `elem` d = bs
| otherwise = setDowned (c : d) bs
where
d = (ntDowned . bsNeoTokyo) bs
-- Return the Downed minus the chosen character
readyChar :: MainCharacter -> BoardState -> BoardState
readyChar c bs = setDowned (filter (/= c) d) bs
where
d = (ntDowned . bsNeoTokyo) bs

44
src/Leads/Players.hs Normal file
View File

@ -0,0 +1,44 @@
module Leads.Players here
-- == Leads - Players ==
-- Functions of type :: Arg1... -> BoardState -> BoardState
-- Changes state of players
-- ====
import ComBoard.Types
import Toolbox.Utils
-- Non Lead : Filter CardSym from hand
removeFromHand' :: CardSym -> Hand -> Hand
removeFromHand' c h = rmFirstMatch h (==c)
-- Remove CardSym from PlayerId's hand
removeFromHand :: PlayerId -> CardSym -> BoardState -> BoardState
removeFromHand p c bs = setHand p (removeFromHand' c h) bs
where
h = (getHand p)
-- Non Lead : Add CardSym to discard
addToDiscard' :: CardSym -> Discard -> Discard
addToDiscard c d = (c:d)
-- Add CardSym to PlayerId's discard
addToDiscard :: PlayerId -> CardSym -> BoardState -> BoardState
addToDiscard p c bs = setDiscard p (addToDiscard' c d) bs
where
d = (getDiscard p bs)
-- Move CardSym from PlayerId's hand to their discard
handToDiscard :: PlayerId -> CardSym -> BoardState -> BoardState
handToDiscard p c bs = (setHand p nh) . (setDiscard p nd) $ bs
where
nh = removeFromHand' p c bs
nd = addToDiscard' p c bs
-- Change PlayreId's current DP by i
adjustDP :: PlayerId -> Integer -> BoardState -> BoardState
adjustDP p i bs = setPlayer p (ps = ps { psDP = (i + dp) } )
where
ps = (findPlayer p bs)
dp = (psDp ps)

View File

@ -1,28 +1,44 @@
module Util where
module Toolbox.Utils where
-- == Toolbox - Utils ==
-- Non-project specific utility functions
-- ====
-- Check if theres a respective entry in a list
elemSnd :: (Eq a) => a -> [(a,b)] -> Bool
elemSnd a l = any (\(x,_) -> x == a) l
-- Check if target matches entry
matchSnd :: (Eq a) => a -> (a,b) -> Bool
matchSnd t (a,_) = a == t
-- Return first matching item from list
-- WARNING: will error if not found in list
getFirstMatchNS :: [a] -> (a -> Bool) -> a
getFirstMatchNS l f = unwrapMaybe (getFirstMatch l f)
-- Forcefully unwrap a Maybe
-- WARNING: will error if given Nothing
unwrapMaybe :: Maybe a -> a
unwrapMaybe (Just a) = a
unwrapMaybe _ = error "Brutal Present: Unwrapped Nothing"
-- Remove first match in list
-- Passes untouched if none match
rmFirstMatch :: [a] -> (a -> Bool) -> [a]
rmFirstMatch [] _ = []
rmFirstMatch (l:ls) f
| f l = ls
| otherwise = (l : rmFirstMatch ls f)
-- Return Left value
-- WARNING: will error if given Right
unwrapLeft :: Either a b -> a
unwrapLeft (Left x) = x
unwrapLeft (Right _) = error "Not a Left value"
-- Return Right value
-- WARNING: will error if given Left
unwrapRight :: Either a b -> b
unwrapRight (Right x) = x
unwrapRight (Left _) = error "Not a Right value"