I have a program (no doubt pretty grotty - I'm still messing around
learning Haskell) which causes GHC (4.04.19990916) to produce an
executable which coredumps.

The source is attached (and is quite small).

I'm using a GHC binary package from Debian GNU/Linux, binary package
version 4.04.19990916-0slink1 built by Michael Weber
<[EMAIL PROTECTED]>.  As soon as I get it to compile
I'll try a compiler installation I built myself.

-davenant:stalk> make XHCFLAGS=-dcore-lint
ghc -syslib posix -syslib exts -syslib misc -dcore-lint -c XSM.hs
ghc: module version changed to 1; reason: no old .hi file
ghc -syslib posix -syslib exts -syslib misc -dcore-lint -c server.hs
ghc: module version changed to 1; reason: no old .hi file
ghc -syslib posix -syslib exts -syslib misc -dcore-lint -o nettlestalk server.o XSM.o
-davenant:stalk> ./nettlestalk 
foo
Segmentation fault (core dumped)
-davenant:stalk> gcc -v
Reading specs from /usr/lib/gcc-lib/i486-linux/egcs-2.91.66/specs
gcc version egcs-2.91.66 Debian GNU/Linux (egcs-1.1.2 release)
-davenant:stalk> dpkg -l 'ghc*' 'libc6*' 'gcc*'
Desired=Unknown/Install/Remove/Purge
| Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed
|/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
||/ Name            Version        Description
+++-===============-==============-============================================
ii  ghc4            4.04.19990916- GHC - the Glasgow Haskell Compilation system
un  ghc4-doc        <none>         (no description available)
ii  ghc4-libsrc     4.04.19990916- Library Sources of GHC - the Glasgow Haskell
ii  libc6           2.1.1-12       GNU C Library: Shared libraries and timezone
ii  libc6-dbg       2.1.1-12       GNU C Library: Libraries with debugging symb
ii  libc6-dev       2.1.1-12       GNU C Library: Development libraries and hea
pn  libc6-doc       <none>         (no description available)
ii  libc6-pic       2.1.1-12       GNU C Library: PIC archive library
ii  libc6-prof      2.1.1-12       GNU C Library: Profiling libraries.
un  libc6.1         <none>         (no description available)
ii  gcc             2.91.66-2      The GNU (EGCS) C compiler.
ii  gcc-doc         2.95.1-2       Documentation for the GNU compilers (gcc, go
pn  gcc-docs        <none>         (no description available)
pn  gcc-i386-gnu    <none>         (no description available)
pn  gcc-m68k-linux  <none>         (no description available)
un  gcc-m68k-palmos <none>         (no description available)
un  gcc-ss          <none>         (no description available)
pn  gccchecker      <none>         (no description available)
-davenant:stalk> uname -av
Linux davenant 2.2.12 #4 Sun Sep 19 23:27:21 BST 1999 i586 unknown
-davenant:stalk> 

Ian.

-- X-war (Warcraft/Starcraft/C&C-alike) server prototype

-- Copyright (C)1999 Ian Jackson <[EMAIL PROTECTED]>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2, or (at your option)
-- any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software Foundation,
-- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
--
-- $Id: server.hs,v 1.7 1999/12/05 16:29:04 ian Exp $

import Int
import FiniteMap
import IOExts

import XSM

type UnitID = Int32
type Coord = Int
type HitPoints = Int
type PlayerNum = Int
type Interval = Int {-ms-}

data Orders =   OrdersNone |
                OrdersAttack UnitID |
                OrdersMove { ordmvx, ordmvy::Int }
instance Show Orders where
        showsPrec _ OrdersNone = ("None"++)
        showsPrec _ (OrdersAttack v) = ("Attack "++).(shows v)
        showsPrec _ (OrdersMove x y) = ("Move "++).(shows x).(" "++).(shows y)

data UnitBase = UnitBase {
                ubpn :: PlayerNum,
                ubx, uby :: Coord,
                ubhp :: HitPoints,
                ubcloak :: Bool,
                uborders :: Orders
        }

instance Show UnitBase where
        showsPrec _ (UnitBase pn x y hp cloak orders) = (
                        ("UnitBase { ubpn="++) . (shows pn) .
                        (", ubx="++) . (shows x) .
                        (", uby="++) . (shows y) .
                        (", ubhp="++) . (shows hp) .
                        (", ubcloak="++) . (shows cloak) .
                        (", uborders="++) . (shows orders) .
                        (" }++"++)
                )

data Unit = Unit UnitID UnitBase UnitType
instance Show Unit where
        showsPrec _ (Unit ui ub ut) =
                ("u#"++) . (shows ui) . (": "++) . (shows ub) . (" "++) . (shows ut)
                                
data UnitType = Marine
instance Show UnitType where
        showsPrec _ ut = ((utName ut)++)

utName          Marine  = "Marine"
initHP          Marine  = 100
notifReUnitType ub ut o = []            -- defaults from here onwards
isDetector      _       = False

data Visibility = VisNone | VisNormal | VisDetect
instance Show Visibility where
        showsPrec _ VisNone = ('-':)
        showsPrec _ VisNormal = ('o':)
        showsPrec _ VisDetect = ('*':)

data Player = Player {
                plpn :: PlayerNum,
                plname :: String,
                plvis :: [[Visibility]],
                plshvis :: [PlayerNum] -- players we share vision with
        }
instance Show Player where
        showsPrec _ pl = (
                        ("p#"++) . (shows $ plpn pl) . (": name=\""++) .
                        ((plname pl) ++) . ("\" vis="++) . (shows $ plvis pl) .
                        (" shvis="++) . (shows $ plshvis pl)
                )
emptyPlayer pn xsz ysz = Player {
                plpn = pn,
                plname = ("player "++(show pn)),
                plvis = replicate ysz (replicate xsz VisNormal),
                plshvis = [pn]
        }

data GameState = GameState {
                gsnextuid :: UnitID,
                gsu :: FiniteMap UnitID Unit,
                gspl :: [Player]
        }
instance Show GameState where
        showsPrec _ gs = (
                        ("nextuid="++) . (shows (gsnextuid gs)) .
                        (" players="++) . (shows (gspl gs)) .
                        (" nunits="++) . (shows (sizeFM (gsu gs))) .
                        (foldr (\ (ui,u) o ->
                                o . ("\n "++) . (shows u)
                                ) id (fmToList (gsu gs)))
                )
emptyGameState nplayers xsz ysz = GameState {
                gsnextuid=1,
                gsu=emptyFM,
                gspl= [ emptyPlayer p xsz ysz | p <- [1..nplayers] ]
}

-- Game Monad

type CallBack = (Interval, GM ())

data GameContext = GameContext GameState [CallBack] [Notification]
instance Show GameContext where
        showsPrec _ (GameContext gs cbs notifs) =
                        ("gamestate: "++) . (shows gs) .
                        ("\ncallbacks: "++) . (shows (map callbackint cbs)) . ("\n"++) 
.
                        (shownotifs notifs)
                where
                        callbackint (i,acts) = i
                        shownotifs [] = id
                        shownotifs (n:ns) = (shows n) . ("\n"++) . (shownotifs ns)

type GM rt = PureSM GameContext rt

runGM :: GameState -> [CallBack] -> GM rt -> (rt, GameContext)
runGM s0 cb0 acts = runPureSM (GameContext s0 cb0 []) acts

readGM :: GM GameState
readGM = do
        GameContext gs _ _ <- readXSM
        return gs

updateGM :: (GameState -> GameState) -> GM ()
updateGM stf = updateXSM xstf
        where xstf (GameContext gs cbs nfs) = GameContext (stf gs) cbs nfs

setGM :: GameState -> GM ()
setGM ngs = updateGM stf
        where stf _ = ngs

afterGM :: Interval -> GM () -> GM ()
afterGM iv acts = do updateXSM xstf where
        xstf (GameContext gs cbs nfs) = GameContext gs ncbs nfs
                        where ncbs = insertCallBack cbs (iv,acts)
        insertCallBack [] new = [new]
        insertCallBack existings new
                        | firsti < newi = [first] ++ insertCallBack rest new
                        | firsti >= newi = [new] ++ existings
                where
                        (first:rest) = existings
                        (firsti,_) = first
                        (newi,_) = new

notifyGM :: [Notification] -> GM ()
notifyGM news = updateXSM xstf
        where xstf (GameContext gs cbs olds) = GameContext gs cbs (olds++news)

-- Notifications

data NotifProp =        NPropUnitID UnitID |
                        NPropOrders Orders |
                        NPropPlayer PlayerNum |
                        NPropLocation Coord Coord |
                        NPropHP HitPoints |
                        NPropCloak Bool
instance Show NotifProp where
        showsPrec _ (NPropUnitID v) = ("UnitID "++).(shows v)
        showsPrec _ (NPropOrders v) = ("Orders "++).(shows v)
        showsPrec _ (NPropPlayer v) = ("Player "++).(shows v)
        showsPrec _ (NPropLocation x y) = ("Location "++).(shows x).(" "++).(shows y)
        showsPrec _ (NPropHP v) = ("HP "++).(shows v)
        showsPrec _ (NPropCloak v) = ("Cloak "++).(shows v)

data Notification = Notification PlayerNum NotifType [NotifProp]
instance Show Notification where
        showsPrec _ (Notification pn nt nps) = head . showprops . tail
                where   head = ("(Notification "++).(shows pn).(" "++).(shows nt)
                        showprops = foldl addsp id nps
                        tail = (")"++)
                        addsp orgshows p = orgshows.(" ("++).(shows p).(")"++)

data NotifType = NotifUnit
instance Show NotifType where
        showsPrec _ NotifUnit = ("Unit"++)

notifyReUnit u = do
        gs <- readGM
        notifyGM $ notifsReUnit u gs

notifsReUnit :: Unit -> GameState -> [Notification]
notifsReUnit u@(Unit ui ub ut) gs = concatMap n1 (gspl gs)
        where   n1 pl = let tpn = plpn pl
                        in nr1  tpn u gs
                                (plvis pl !! uby ub !! ubx ub)
                                (ubcloak ub)
                                (tpn == (ubpn ub))
                nr1 pn u gs VisNone _ False = []
                nr1 pn u gs VisNormal True False = []
                nr1 pn u@(Unit ui ub ut) gs _ _ own = [n]
                        where   unitnotifs =    [NPropUnitID ui] ++
                                                (nbase ub own) ++
                                                (notifReUnitType ub ut own)
                                n =             Notification pn NotifUnit unitnotifs
                nbase ub True =         (nbase ub False) ++
                                        [NPropOrders (uborders ub)]
                nbase ub False = [      NPropPlayer (ubpn ub),
                                        NPropLocation (ubx ub) (uby ub),
                                        NPropHP (ubhp ub),
                                        NPropCloak (ubcloak ub)         ]

-- General unit handling stuff

readUnit :: UnitID -> GM Unit
readUnit ui = do
        gs <- readGM
        return $ lookupWithDefaultFM (gsu gs) undefined ui

-- unitUpdateVisibility :: Unit -> GM ()
-- unitUpdateVisibility u@(_ ub _) = do
--      gs <- readGM
--      mapM [ findPlayer pn | pn <- ubpn ub  gs

setUnit :: Unit -> GM ()
setUnit u@(Unit ui _ _) = do
        updateGM $ \gs -> gs { gsu = addToFM (gsu gs) ui u }
        notifyReUnit u
--      unitUpdateVisibility u

updateUnit :: UnitID -> (Unit -> GameState -> Unit) -> GM ()
updateUnit ui stf = do
        gs <- readGM
        u <- readUnit ui
        setUnit (stf u gs)

-- Specific stuff

newUnitID :: GM UnitID
newUnitID = do
        gs <- readGM
        let ui = gsnextuid gs in do
                let iu gs = gs { gsnextuid = ui+1 } in updateGM iu
                return (trace ("allocated unit ID "++(show ui)++"\n") ui)

registerUnit :: PlayerNum -> Coord -> Coord -> UnitType -> GM UnitID
registerUnit pn x y ut = do
        ui <- newUnitID
        setUnit $ Unit ui (UnitBase pn x y (initHP ut) False OrdersNone) ut
        return ui

theGame = do
        m1 <- registerUnit 1 1 1 Marine
        m2 <- registerUnit 2 2 2 Marine
        return (m1,m2)

startGame = emptyGameState 2 5 5
        
dumpGM_dbg gs = do
        inXSM $ putStr $ "game state: "++(show gs)++"\n"

main :: IO ()
main = do
                putStr "foo\n"
                putStr (show r)
        where
                r = runGM startGame [] theGame
-- Extra State Monad

-- Copyright (C)1999 Ian Jackson <[EMAIL PROTECTED]>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2, or (at your option)
-- any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software Foundation,
-- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
--
-- $Id: XSM.hs,v 1.3 1999/12/05 16:29:04 ian Exp $

module XSM (
        XSM(), inXSM, runXSM, readXSM, updateXSM,
        NullMonad(), runNullMonad,
        PureSM, runPureSM
) where

data XSM st bm rt = XSM (st -> bm (rt,st))

instance Monad bm => Monad (XSM st bm) where
        XSM c1 >>= fc2 =
                XSM (\s0 -> do -- in the bm monad
                        (rv1,s1) <- (c1 s0)
                        let XSM c2 = (fc2 rv1) in (c2 s1)
                )
        return rv =     XSM (\s0 -> return (rv, s0))

inXSM :: Monad bm => bm rv -> XSM st bm rv
inXSM ba = XSM (\s0 -> do
                rv <- ba
                return (rv,s0))

runXSM :: Monad bm => st -> XSM st bm rt -> bm rt
runXSM s0 (XSM acts) = do
        (rv,st) <- acts s0
        return rv

readXSM :: Monad bm => XSM st bm st
readXSM = XSM (\s0 -> return (s0, s0))

updateXSM :: Monad bm => (st -> st) -> XSM st bm ()
updateXSM tf = XSM (\s0 -> return ((), tf s0))

data NullMonad rt = NullMonad rt
instance Monad NullMonad where
        return rv = NullMonad rv
        NullMonad v1 >>= fc2 = fc2 v1

runNullMonad :: NullMonad rt -> rt
runNullMonad (NullMonad rv) = rv

type PureSM st rt = XSM st NullMonad rt

runPureSM :: st -> PureSM st rt -> (rt,st)
runPureSM s0 (XSM stf) = runNullMonad (stf s0)

Reply via email to