Allow player choice of different monster species.

parent 1d76695a
......@@ -23,10 +23,14 @@ import Roguestar.Lib.Utility.SiteCriteria
homeBiome :: Species -> WeightedSet Biome
homeBiome RedRecreant = weightedSet [(2,TemperateForest),(2,TemperateClearing),(1,RelaxingPond),(1,CraterInterior)]
homeBiome BlueRecreant = weightedSet [(2,TemperateForest),(2,TemperateClearing),(1,RelaxingPond),(1,CraterInterior)]
homeBiome Anachronid = weightedSet [(5,TropicalForest),(1,TropicalClearing)]
homeBiome TabularMonstrosity = weightedSet [(3,BareMountain),(1,CraterInterior)]
startingEquipmentBySpecies :: Species -> [Tool]
startingEquipmentBySpecies RedRecreant = []
startingEquipmentBySpecies BlueRecreant = []
startingEquipmentBySpecies Anachronid = []
startingEquipmentBySpecies TabularMonstrosity = []
dbCreateStartingPlane :: Creature -> DB PlaneRef
dbCreateStartingPlane creature =
......
......@@ -88,6 +88,8 @@ instance CreatureScore CreatureTrait where
data CreatureSpecial =
Hover
| Teleportation
| TemporalWeb
| ComplexificationMesh
deriving (Eq,Read,Show,Ord)
instance CreatureEndo CreatureSpecial where
......@@ -126,7 +128,7 @@ instance CreatureScore CharacterClass where
-- | Calculator to determine how many ranks a creature has in an ability.
-- Number of aptitude points plus n times number of ability points
figureAbility :: [CreatureTrait] -> Creature -> Integer
figureAbility [] c = 1
figureAbility [] _ = 1
figureAbility traits c = 1 + sum (map (flip rawScore c) traits) `div` List.genericLength traits
creatureAbilityScore :: CreatureAbility -> Creature -> Integer
......
......@@ -181,7 +181,7 @@ rerollStartingSpecies g =
writeTVar (game_message_text g) []
poke g $
do species <- weightedPickM $ unweightedSet all_species
generateInitialPlayerCreature BlueRecreant
generateInitialPlayerCreature species
return species
beginGame :: Game -> IO (Either DBError ())
......
......@@ -25,3 +25,24 @@ speciesInfo RedRecreant = SpeciesData
[Hover,
Teleportation]
speciesInfo BlueRecreant = speciesInfo RedRecreant
speciesInfo Anachronid = SpeciesData
[(Aggression, 3),
(Bulk, 3),
(Caution, 3),
(Dexterity, 10),
(Fortitude, 5),
(Perception, 3),
(Speed, 8)]
[TemporalWeb]
speciesInfo TabularMonstrosity = SpeciesData
[(Aggression, 1),
(Bulk, 15),
(Caution, 1),
(Dexterity, 1),
(Fortitude, 15),
(Perception, 1),
(Speed, 4)]
[Hover,
ComplexificationMesh]
......@@ -8,8 +8,10 @@ module Roguestar.Lib.SpeciesData
data Species =
BlueRecreant
| RedRecreant
| Anachronid
| TabularMonstrosity
deriving (Eq,Ord,Bounded,Enum,Read,Show)
all_species :: [Species]
all_species = [BlueRecreant,RedRecreant] -- [minBound..maxBound]
all_species = [minBound..maxBound]
......@@ -26,7 +26,10 @@ import Control.Arrow (first,second)
--
data Biome = TemperateForest
| TemperateClearing
| TropicalForest
| TropicalClearing
| RelaxingPond
| BareMountain
| CraterInterior
deriving (Read,Show,Eq,Ord,Enum,Bounded)
......@@ -128,6 +131,10 @@ terrainInterpFn :: (Biome,Biome) -> WeightedSet Terrain
terrainInterpFn biomes = case biomes of
(TemperateForest,_) -> weightedSet [(2,Forest),(1,Grass),(1,Dirt)]
(TemperateClearing,_) -> weightedSet [(5,Grass),(3,Dirt)]
(TropicalForest,_) -> weightedSet [(3,Forest),(1,Sand),(1,Water)]
(TropicalClearing,_) -> weightedSet [(3,Grass),(2,Sand),(1,Water)]
(BareMountain,BareMountain) -> weightedSet [(1,RockFace),(1,RockyGround)]
(BareMountain,_) -> weightedSet [(1,RockyGround)]
(RelaxingPond,RelaxingPond) -> weightedSet [(10,Water),(1,RockyGround)]
(RelaxingPond,_) -> weightedSet [(2,Water),(1,Sand)]
(CraterInterior,CraterInterior) -> weightedSet [(1,RockyGround)]
......
......@@ -14,7 +14,7 @@ import Snap.Core
import Snap.Snaplet
import Snap.Util.FileServe
import Snap.Http.Server.Config
import Data.Lens.Template
--import Data.Lens.Template
import Data.Maybe
import qualified Data.List as List
import qualified Data.Map as Map
......@@ -39,7 +39,7 @@ data App = App {
_app_game_state :: GameState,
_globals :: Aeson.Value }
makeLenses [''App]
--makeLenses [''App]
appInit :: SnapletInit App App
appInit = makeSnaplet "roguestar-server-snaplet" "Roguestar Server" Nothing $
......@@ -56,7 +56,6 @@ appInit = makeSnaplet "roguestar-server-snaplet" "Roguestar Server" Nothing $
("/feedback", postFeedback <|> staticTemplate "static/feedback.mustache"),
("/feedback-thanks", staticTemplate "static/feedback-thanks.mustache"),
("/options", options),
("/start", start),
("/version-history", staticTemplate "static/version-history.mustache"),
("", staticTemplate "static/index.mustache")]
config <- liftIO $ getConfiguration default_timeout
......@@ -147,17 +146,6 @@ play =
--("wield",method POST $ wield),
--("unwield",method POST $ unwield)]
resolveAllSnapshots :: Handler App App ()
resolveAllSnapshots =
do g <- getGame
b <- oops $ liftIO $ hasSnapshot g
case b of
True ->
do oops $ liftIO $ popSnapshot g
resolveAllSnapshots
False ->
do return ()
resolveOneSnapshot :: Handler App App ()
resolveOneSnapshot =
do g <- getGame
......@@ -165,9 +153,6 @@ resolveOneSnapshot =
when b $ oops $ liftIO $ popSnapshot g
replay
routeRoguestar :: PlayerState -> [(BS.ByteString,PlayerState -> Handler App App ())] -> Handler App App ()
routeRoguestar ps xs = route $ map (\(bs,f) -> (bs,f ps)) xs
getGameState :: PlayerState -> Handler App App Aeson.Value
getGameState (SpeciesSelectionState Nothing) =
do return $ object [
......@@ -178,8 +163,8 @@ getGameState (SpeciesSelectionState (Just creature)) =
"species" .= show (creature_species creature)
]
]
getGameState (SnapshotEvent snapshot) = getGameStateWhileInPlay
getGameState (PlayerCreatureTurn creature_ref) = getGameStateWhileInPlay
getGameState (SnapshotEvent _) = getGameStateWhileInPlay
getGameState (PlayerCreatureTurn _) = getGameStateWhileInPlay
getGameState (GameOver PlayerIsDead) =
do return $ object [
"player-death" .= True ]
......@@ -187,6 +172,7 @@ getGameState (GameOver PlayerIsVictorious) =
do return $ object [
"player-victory" .= True ]
getGameStateWhileInPlay :: Handler App App Aeson.Value
getGameStateWhileInPlay =
do g <- getGame
map_content <- generateMapContent
......@@ -205,12 +191,12 @@ displayGameState player_state =
do game_state <- getGameState player_state
renderThemedPage "static/play.mustache" game_state
{-
data Inventory = Inventory {
inventory_wielded :: Maybe VisibleObject,
inventory_carried :: [VisibleObject],
inventory_ground :: [VisibleObject] }
{-
collectInventory :: Game -> Handler App App (Either DBError Inventory)
collectInventory g = liftIO $ perceive g $
do visible_objects <- liftM stackVisibleObjects $ visibleObjects (const $ return True)
......@@ -265,6 +251,10 @@ accept _ = pass
move :: Handler App App ()
move = commitBehavior =<< moveBehavior
-- |
-- Determines the correct "Behavior" type for a direction (north/south/east/west) move.
-- This information is either implicit (moving into an enemy is assumed to be attacking)
-- or it can be explicit because the player set a movement type.
moveBehavior :: Handler App App Behavior
moveBehavior =
do g <- getGame
......@@ -273,15 +263,13 @@ moveBehavior =
let facing = fromMaybe (error "Not a valid direction identifier.") $ stringToFacing direction
action <- case mode of
_ | direction == "wait" -> return $ const Wait
"normal" ->
do result <- liftIO $ facingBehavior g facing
case result of
Right x -> return $ const x
"normal" -> liftM const $ oops $ liftIO $ facingBehavior g facing
"step" -> return Step
"attack" -> return Attack
"fire" -> return Fire
"jump" -> return Jump
"turn" -> return TurnInPlace
other -> fail $ "moveBehavior: Didn't recognize: " ++ T.unpack (decodeUtf8 other)
return $ action facing
{-
......@@ -298,6 +286,10 @@ unwield :: Handler App App ()
unwield = commitBehavior Unwield
-}
-- |
-- GET: Offers the player the various game modes they are allowed (such as the tutorial game).
-- POST: Initializes all of the data structures and cookies to start a new game.
--
start :: Handler App App ()
start = on_get <|> on_post
where on_get = method GET $ renderThemedPage "static/start.mustache" (object [])
......@@ -322,7 +314,7 @@ inventoryBehavior f =
commitBehavior :: Behavior -> Handler App App ()
commitBehavior behavior =
do g <- getGame
result <- oops $ liftIO $ behave g behavior
_ <- oops $ liftIO $ behave g behavior
replay
replay :: Handler App App ()
......@@ -369,9 +361,9 @@ getGame =
Nothing -> redirect "/start"
data MapData = MapData {
md_visible_terrain :: Map.Map Position Terrain,
md_visible_objects :: Map.Map Position [VisibleObject],
md_position_info :: (Facing,Position) }
_md_visible_terrain :: Map.Map Position Terrain,
_md_visible_objects :: Map.Map Position [VisibleObject],
_md_position_info :: (Facing,Position) }
generateMapContent :: Handler App App Aeson.Value
generateMapContent =
......@@ -424,7 +416,7 @@ createStatsBlock =
T.concat ["Compass: ",
T.pack $ show $ stats_compass stats]]
data Style = Empty | Strong | Rocky | Icy | Plants | Dusty | Sandy | Wet | DeepWet | Molten | Gloomy | FaintMagic | StrongMagic | StrongDusty | WarpIn | Damage | Active
data Style = Empty | Strong | Rocky | Icy | Plants | Dusty | Sandy | Wet | Molten | Gloomy | FaintMagic | StrongMagic | StrongDusty | WarpIn | Damage | Active | BlueIFF | RedIFF
styleToCSS :: Style -> T.Text
styleToCSS Empty = ""
......@@ -443,6 +435,8 @@ styleToCSS StrongDusty = "B d"
styleToCSS WarpIn = "B warpin"
styleToCSS Damage = "B damage"
styleToCSS Active = "B active"
styleToCSS BlueIFF = "blue"
styleToCSS RedIFF = "red"
class Charcoded a where
codedRepresentation :: PlayerState -> a -> (Char,Style)
......@@ -452,7 +446,7 @@ class Charcoded a where
instance Charcoded a => Charcoded (Maybe a) where
codedRepresentation player_state (Just a) = codedRepresentation player_state a
codedRepresentation player_state Nothing = (' ',Empty)
codedRepresentation _ Nothing = (' ',Empty)
instance Charcoded VisibleObject where
codedRepresentation player_state (VisibleTool { visible_tool = t }) = codedRepresentation player_state t
......@@ -480,8 +474,10 @@ instance Charcoded Tool where
codedRepresentation _ (DeviceTool Sword _) = (')',Strong)
instance Charcoded Species where
codedRepresentation _ RedRecreant = ('r',Strong)
codedRepresentation _ BlueRecreant = ('@',Strong)
codedRepresentation _ RedRecreant = ('r',Strong)
codedRepresentation _ BlueRecreant = ('r',Strong)
codedRepresentation _ Anachronid = ('X',Strong)
codedRepresentation _ TabularMonstrosity = ('m',Strong)
instance Charcoded Terrain where
codedRepresentation _ RockFace = ('#',Rocky)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
<div id="documenttext">
<div id="documenttext" class="roguebox">
<h6 class="quest">A Recreant's Dream</h6>
<h6 class="quest">Crashed!</h6>
<p>Thousands of years ago, on a distant planet, an alien civilization waged war.
They destroyed themselves, but their machines continue to fight over the charred landscape of their homeworld.<p>
<p>You have crash-landed on an alien world, with no supplies and no chance of rescue.</p>
<p>Long after the heroes and causes of this conflict have been forgotten, you roll off an underground assembly line.
Unlike your autonomous brothers, you desire more than a life of endless battle against foes whose only crime is being
programmed with a different IFF transponder code.
Your sensors tell you that there is a portal, somewhere on the planet's surface, that will take you away from this world . . .</p>
<p>You know that, somewhere on the surface of this place, there is a portal that can return you to civilization. Your compass points the way.</p>
<p>But there are others here. Ancient and cold, they watch from the shadows . . .</p>
<form action="/play/reroll" method="post">
<button type="submit">Begin</button>
......
......@@ -2,6 +2,7 @@
width: 1024px;
margin-top: 1em;
margin-bottom: 1em;
overflow: hidden;
}
#menu ul {
......
......@@ -35,6 +35,11 @@ body {
float: right;
}
.left-image {
float: left;
margin: 1em;
}
.help {
font-size: 20px;
}
......
<div id="documenttext">
<div id="documenttext" class="roguebox">
<p>You are a {{{species}}}</p>
<img class="left-image roguebox" src="/static/art/{{species}}.svg"/>
<p>You are a {{species}}</p>
<form action="/play/reroll" method="post">
<p><button type="submit">Reroll</button> a different character.</p>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment