--
--	game-objects.occ -- game objects
--	Copyright (C) 2004 Fred Barnes <frmb@kent.ac.uk>
--
--	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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
--

#INCLUDE "config.inc"
#INCLUDE "types.inc"
#USE "game-utils"

#INCLUDE "course.module"


--{{{  PROC triv.object (VAL []BYTE name, VAL INT ilocn, SHARED CT.GAMECTRL! to.game)
PROC triv.object (VAL []BYTE name, VAL INT ilocn, SHARED CT.GAMECTRL! to.game)
  CT.OBJECT? in:
  CT.OBJECT! link:
  SHARED CT.ROOMLINK! room:
  INITIAL BOOL placed IS FALSE:
  MOBILE []BYTE msg:
  MOBILE []BYTE desc:
  BOOL got.desc:
  INT damage, health:
  BOOL ok:
  SEQ
    in, link := MOBILE CT.OBJECT
    damage := 0       -- damage inflicted
    health := 0       -- health given
    ok := TRUE

    MOBILE []MOBILE []BYTE odesclines:
    [256]BYTE fname:
    INT flen:
    INT sline:
    SEQ
      flen := 0
      buffer.set.string (fname, flen, ##BASEPATH)
      buffer.set.string (fname, flen, name)
      buffer.set.string (fname, flen, ".odesc")

      file.readlines ([fname FOR flen], got.desc, odesclines)

      sline := -1
      --{{{  iterate over lines for description and other settings
      IF
        got.desc
          SEQ i = 0 FOR SIZE odesclines
            INITIAL MOBILE []BYTE thisline IS odesclines[i]:
            SEQ
              IF
                (SIZE thisline) > 3
                  BOOL v.ok:
                  SEQ
                    IF
                      [thisline FOR 3] = "+d "
                        damage, v.ok := parse.int ([thisline FROM 3])
                      [thisline FOR 3] = "+h "
                        health, v.ok := parse.int ([thisline FROM 3])
                      sline < 0
                        SEQ
                          sline := i
                          desc := thisline
                      TRUE
                        SKIP
                    -- if we failed to parse anything, tuff..
                TRUE
                  SKIP
        TRUE
          ok := FALSE
      --}}}

      IF
        (NOT ok) OR (sline < 0)
          desc := ""
        TRUE
          SKIP

    -- file.rdescline (name, ".odesc", got.desc, desc)

    IF
      ok
        --{{{  get room and place
        SEQ
          CHAN SHARED CT.ROOMLINK! c:
          PAR
            util.getroom (2, ilocn, to.game, c!, placed)
            c ? room
          IF
            placed
              -- place client-end in room
              CLAIM room
                room[in] ! new.object; name; link
            TRUE
              SKIP
        --}}}
      TRUE
        SKIP
    IF
      ok
        --{{{  main-loop
        INITIAL BOOL running IS placed:
        WHILE running
          PRI ALT
            in[in] ? CASE
              die
                running := FALSE
              get.name
                in[out] ! name; name
              examine
                IF
                  got.desc
                    in[out] ! name; CLONE desc
                  TRUE
                    in[out] ! name; "trivial object"
              MOBILE []BYTE act:
              support.action; act
                IF
                  act = "get"
                    in[out] ! yes
                  TRUE
                    in[out] ! no
              get.damage
                in[out] ! damage; damage
              get.health
                in[out] ! health; health
        --}}}
      TRUE
        SKIP
:
--}}}
--{{{  PROC door.object (VAL []BYTE name, VAL INT ilocn, VAL INT itarget, SHARED CT.GAMECTRL! to.game)
PROC door.object (VAL []BYTE name, VAL INT ilocn, VAL INT itarget, SHARED CT.GAMECTRL! to.game)
  CT.OBJECT? in:
  CT.OBJECT! link:
  MOBILE []BYTE desc:
  BOOL got.desc:
  INITIAL BOOL placed IS FALSE:
  SHARED CT.ROOMLINK! room:
  INITIAL BOOL got.target IS FALSE:
  SHARED CT.ROOMLINK! target:
  SEQ
    in, link := MOBILE CT.OBJECT

    file.rdescline (name, ".odesc", got.desc, desc)

    --{{{  get rooms and place
    CHAN SHARED CT.ROOMLINK! c:
    PAR
      util.getroom (2, ilocn, to.game, c!, placed)
      c ? room
    CHAN SHARED CT.ROOMLINK! c:
    PAR
      util.getroom (2, itarget, to.game, c!, got.target)
      c ? target
    IF
      (NOT got.target) OR (NOT placed)
        SKIP
      TRUE
        CLAIM room
          room[in] ! new.object; name; link
    --}}}
    INITIAL BOOL running IS (placed AND got.target):
    WHILE running
      PRI ALT
        in[in] ? CASE
          die
            running := FALSE
          get.name
            in[out] ! name; name
          examine
            IF
              got.desc
                in[out] ! name; CLONE desc
              TRUE
                in[out] ! name; "door object"
          MOBILE []BYTE act:
          support.action; act
            IF
              act = "cliuse"
                in[out] ! yes
              TRUE
                in[out] ! no
          CT.CLIENT! cli:
          MOBILE []BYTE cname:
          use.client; cname; cli
            SEQ
              -- send a message to the client
              cli[s.in] ! genmsg; "the gateway transports you to another part of the game"
              -- transport client to target
              CLAIM target
                target[in] ! new.client; cname; cli
:
--}}}
--{{{  PROC dispenser.object (VAL []BYTE name, gives, VAL INT ilocn, SHARED CT.GAMECTRL! to.game)
PROC dispenser.object (VAL []BYTE name, gives, VAL INT ilocn, SHARED CT.GAMECTRL! to.game)
  CT.OBJECT? in:
  CT.OBJECT! link:
  MOBILE []BYTE desc:
  BOOL got.desc:
  INITIAL BOOL placed IS FALSE:
  SHARED CT.ROOMLINK! room:
  SEQ
    in, link := MOBILE CT.OBJECT

    file.rdescline (name, ".odesc", got.desc, desc)

    --{{{  get rooms and place
    CHAN SHARED CT.ROOMLINK! c:
    PAR
      util.getroom (2, ilocn, to.game, c!, placed)
      c ? room
    IF
      NOT placed
        SKIP
      TRUE
        CLAIM room
          room[in] ! new.object; name; link
    --}}}
    INITIAL BOOL running IS placed:
    WHILE running
      PRI ALT
        in[in] ? CASE
          die
            running := FALSE
          get.name
            in[out] ! name; name
          examine
            IF
              got.desc
                in[out] ! name; CLONE desc
              TRUE
                in[out] ! name; "dispenser object"
          MOBILE []BYTE act:
          support.action; act
            IF
              act = "use"
                in[out] ! yes
              TRUE
                in[out] ! no
          use
            SEQ
              -- produce a photocopy (or whatever we're told to dispense)
              FORK triv.object (gives, ilocn, to.game)
:
--}}}
--{{{  PROC linc.terminal (VAL INT ilocn, SHARED CT.GAMECTRL! to.game, SHARED CT.LINCLINK! to.linc)
PROC linc.terminal (VAL INT ilocn, SHARED CT.GAMECTRL! to.game, SHARED CT.LINCLINK! to.linc)
  CT.OBJECT? in:
  CT.OBJECT! link:
  MOBILE []BYTE desc:
  BOOL got.desc:
  INITIAL BOOL placed IS FALSE:
  SHARED CT.ROOMLINK! room:
  SEQ
    in, link := MOBILE CT.OBJECT

    file.rdescline ("linc-terminal", ".odesc", got.desc, desc)

    --{{{  get rooms and place
    CHAN SHARED CT.ROOMLINK! c:
    PAR
      util.getroom (2, ilocn, to.game, c!, placed)
      c ? room
    IF
      NOT placed
        SKIP
      TRUE
        CLAIM room
          room[in] ! new.object; "linc-terminal"; link
    --}}}
    INITIAL BOOL running IS placed:
    WHILE running
      PRI ALT
        in[in] ? CASE
          die
            running := FALSE
          get.name
            in[out] ! name; "linc-terminal"
          examine
            IF
              got.desc
                in[out] ! name; CLONE desc
              TRUE
                in[out] ! name; "a linc terminal"
          MOBILE []BYTE act:
          support.action; act
            IF
              act = "cliuse"
                in[out] ! yes
              TRUE
                in[out] ! no
          CT.CLIENT! cli:
          MOBILE []BYTE cname:
          use.client; cname; cli
            SEQ
              -- transport to LINC
              CLAIM to.linc
                to.linc[in] ! new.client; cname; cli; ilocn
:
--}}}
--{{{  PROC object.creator (SHARED CT.GAMECTRL! to.game)
--
--  dynamically, and randomly, create objects
--
PROC object.creator (SHARED CT.GAMECTRL! to.game)
  TIMER tim:
  INT t, seed:
  INT nrooms:
  INT check.nrooms:
  SEQ
    tim ? t
    seed := (t >> 2) + 1
    check.nrooms := 0
    WHILE TRUE
      INT rand:
      SEQ
        rand, seed := random (10, seed)
        t := t PLUS ((rand + 10) * 5000000)
        tim ? AFTER t
        IF
          check.nrooms = 0
            SEQ
              CLAIM to.game
                SEQ
                  to.game[in] ! get.n.rooms
                  to.game[out] ? CASE n.rooms; nrooms
              check.nrooms := 10
          TRUE
            SKIP

        INT room, objnum:
        MOBILE []BYTE objname:
        SEQ
          room, seed := random (nrooms, seed)
          objnum, seed := random (3, seed)

          CASE objnum
            0
              objname := "bread"
            1
              objname := "cookies"
            2
              objname := "ribena"

          FORK triv.object (objname, room, to.game)

:
--}}}



