Universität Ulm, Fakultät für Mathematik und Wirtschaftswissenschaften, SAI

SS 99 || Ferienprojekt zu Allgemeine Informatik II || Puzzle Library

MODULE RemotePuzzlePlayers


(* Edit RemotePuzzl.rm instead of this file which has been generated
   by genrem at Mon Jul 26 15:20:58 MET DST 1999
*)

MODULE RemotePuzzlePlayers;

   IMPORT ChessClocks, Messages, Objects, PersistentObjects, Puzzle,
      PuzzlePlayers, RelatedEvents, RemoteObjects, Services, Streams;

   TYPE
      Player = POINTER TO PlayerRec;
      PlayerRec = RECORD (PuzzlePlayers.PlayerRec) END;

   TYPE
      Message = POINTER TO MessageRec;
      MessageRec = RECORD (Messages.MessageRec) END;

   TYPE
      MakeMoveMessage = POINTER TO MakeMoveMessageRec;
      MakeMoveMessageRec =
         RECORD
            (MessageRec)
            situation: Puzzle.Situation; (* IN via COPY *)
            clock: ChessClocks.ChessClock; (* IN via REF *)
            game: Services.Object; (* IN via REF *)
            move: Puzzle.Move; (* OUT via COPY *)
         END;
   VAR
      makeMoveMessageType: Services.Type;

   TYPE
      AcceptMessage = POINTER TO AcceptMessageRec;
      AcceptMessageRec =
         RECORD
            (MessageRec)
            game: Services.Object; (* IN via REF *)
         END;
   VAR
      acceptMessageType: Services.Type;

   TYPE
      GameOverMessage = POINTER TO GameOverMessageRec;
      GameOverMessageRec =
         RECORD
            (MessageRec)
            game: Services.Object; (* IN via REF *)
         END;
   VAR
      gameOverMessageType: Services.Type;

   VAR
      if: PuzzlePlayers.Interface; (* of PuzzlePlayers *)
      type: Services.Type; (* of RemotePuzzlePlayers.Player *)

   PROCEDURE CreateMakeMoveMessage(VAR object: PersistentObjects.Object);
      VAR msg: MakeMoveMessage;
   BEGIN
      NEW(msg);
      PersistentObjects.Init(msg, makeMoveMessageType);
      Messages.Init(msg);
      object := msg;
   END CreateMakeMoveMessage;

   PROCEDURE WriteMakeMoveMessage(s: Streams.Stream;
                                  msg: PersistentObjects.Object) : BOOLEAN;
   BEGIN
      WITH msg: MakeMoveMessage DO
         IF msg.processed THEN
            RETURN PersistentObjects.Write(s, msg.move)
         ELSE
            RETURN PersistentObjects.Write(s, msg.situation) &
                   RemoteObjects.Export(s, msg.clock) &
                   RemoteObjects.Export(s, msg.game)
         END;
      END;
   END WriteMakeMoveMessage;

   PROCEDURE ReadMakeMoveMessage(s: Streams.Stream;
                                 msg: PersistentObjects.Object) : BOOLEAN;
   BEGIN
      WITH msg: MakeMoveMessage DO
         IF msg.processed THEN
            RETURN PersistentObjects.Read(s, msg.move)
         ELSE
            RETURN PersistentObjects.Read(s, msg.situation) &
                   RemoteObjects.Import(s, msg.clock) &
                   RemoteObjects.Import(s, msg.game)
         END;
      END;
   END ReadMakeMoveMessage;

   PROCEDURE CreateAcceptMessage(VAR object: PersistentObjects.Object);
      VAR msg: AcceptMessage;
   BEGIN
      NEW(msg);
      PersistentObjects.Init(msg, acceptMessageType);
      Messages.Init(msg);
      object := msg;
   END CreateAcceptMessage;

   PROCEDURE WriteAcceptMessage(s: Streams.Stream;
                                msg: PersistentObjects.Object) : BOOLEAN;
   BEGIN
      WITH msg: AcceptMessage DO
         IF msg.processed THEN
            RETURN TRUE
         ELSE
            RETURN RemoteObjects.Export(s, msg.game)
         END;
      END;
   END WriteAcceptMessage;

   PROCEDURE ReadAcceptMessage(s: Streams.Stream;
                               msg: PersistentObjects.Object) : BOOLEAN;
   BEGIN
      WITH msg: AcceptMessage DO
         IF msg.processed THEN
            RETURN TRUE
         ELSE
            RETURN RemoteObjects.Import(s, msg.game)
         END;
      END;
   END ReadAcceptMessage;

   PROCEDURE CreateGameOverMessage(VAR object: PersistentObjects.Object);
      VAR msg: GameOverMessage;
   BEGIN
      NEW(msg);
      PersistentObjects.Init(msg, gameOverMessageType);
      Messages.Init(msg);
      object := msg;
   END CreateGameOverMessage;

   PROCEDURE WriteGameOverMessage(s: Streams.Stream;
                                  msg: PersistentObjects.Object) : BOOLEAN;
   BEGIN
      WITH msg: GameOverMessage DO
         IF msg.processed THEN
            RETURN TRUE
         ELSE
            RETURN RemoteObjects.Export(s, msg.game)
         END;
      END;
   END WriteGameOverMessage;

   PROCEDURE ReadGameOverMessage(s: Streams.Stream;
                                 msg: PersistentObjects.Object) : BOOLEAN;
   BEGIN
      WITH msg: GameOverMessage DO
         IF msg.processed THEN
            RETURN TRUE
         ELSE
            RETURN RemoteObjects.Import(s, msg.game)
         END;
      END;
   END ReadGameOverMessage;

   PROCEDURE Handler(object: Messages.Object; VAR msg: Messages.Message);
      VAR
         oldQueue, newQueue: RelatedEvents.Queue;
   BEGIN
      IF ~(msg IS Message) THEN RETURN END;
      WITH object: PuzzlePlayers.Player DO
         RelatedEvents.QueueEvents(object);
         RelatedEvents.GetQueue(object, oldQueue);
         msg.processed := TRUE;
         IF msg IS MakeMoveMessage THEN
            WITH msg: MakeMoveMessage DO
               msg.done := PuzzlePlayers.MakeMove(object, msg.situation, msg.clock, msg.game, msg.move);
            END;
         ELSIF msg IS AcceptMessage THEN
            WITH msg: AcceptMessage DO
               msg.done := PuzzlePlayers.Accept(object, msg.game);
            END;
         ELSIF msg IS GameOverMessage THEN
            WITH msg: GameOverMessage DO
               PuzzlePlayers.GameOver(object, msg.game);
               msg.done := TRUE;
            END;
         END;
         RelatedEvents.GetQueue(object, newQueue);
         RelatedEvents.AppendQueue(msg.errors, newQueue);
         RelatedEvents.AppendQueue(object, oldQueue);
      END;
   END Handler;

   PROCEDURE MakeMove(player: PuzzlePlayers.Player;
                      situation: Puzzle.Situation;
                      clock: ChessClocks.ChessClock;
                      game: Services.Object;
                      VAR move: Puzzle.Move) : BOOLEAN;
      VAR msg: MakeMoveMessage; queue: RelatedEvents.Queue;
   BEGIN
      CreateMakeMoveMessage(msg);
      msg.situation := situation;
      msg.clock := clock;
      msg.game := game;
      Messages.Send(player, msg);
      move := msg.move;
      RelatedEvents.GetQueue(msg.errors, queue);
      RelatedEvents.AppendQueue(player, queue);
      RETURN msg.done
   END MakeMove;

   PROCEDURE Accept(player: PuzzlePlayers.Player;
                    game: Services.Object) : BOOLEAN;
      VAR msg: AcceptMessage; queue: RelatedEvents.Queue;
   BEGIN
      CreateAcceptMessage(msg);
      msg.game := game;
      Messages.Send(player, msg);
      RelatedEvents.GetQueue(msg.errors, queue);
      RelatedEvents.AppendQueue(player, queue);
      RETURN msg.done
   END Accept;

   PROCEDURE GameOver(player: PuzzlePlayers.Player;
                      game: Services.Object);
      VAR msg: GameOverMessage; queue: RelatedEvents.Queue;
   BEGIN
      CreateGameOverMessage(msg);
      msg.game := game;
      Messages.Send(player, msg);
      RelatedEvents.GetQueue(msg.errors, queue);
      RelatedEvents.AppendQueue(player, queue);
   END GameOver;

   PROCEDURE InitPO(VAR type: Services.Type;
                    name, baseName: ARRAY OF CHAR;
                    create: PersistentObjects.CreateProc;
                    read: PersistentObjects.ReadProc;
                    write: PersistentObjects.WriteProc);
      VAR if: PersistentObjects.Interface;
   BEGIN
      NEW(if);
      if.create := create; if.read := read; if.write := write;
      if.createAndRead := NIL;
      PersistentObjects.RegisterType(type, name, baseName, if);
   END InitPO;

   PROCEDURE ^ CreateProxy(VAR object: Services.Object;
                           params: PersistentObjects.Object);

   PROCEDURE InitIFs;
      VAR
         msgtype: Services.Type;
         remoteObjIf: RemoteObjects.Interface;
         baseType: Services.Type;
   BEGIN
      NEW(if);
      if.makeMove := MakeMove;
      if.accept := Accept;
      if.gameOver := GameOver;
      PersistentObjects.RegisterType(msgtype,
         "RemotePuzzlePlayers.Message", "Messages.Message", NIL);
      InitPO(makeMoveMessageType, "RemotePuzzlePlayers.MakeMoveMessage", "RemotePuzzlePlayers.Message",
             CreateMakeMoveMessage, ReadMakeMoveMessage, WriteMakeMoveMessage);
      InitPO(acceptMessageType, "RemotePuzzlePlayers.AcceptMessage", "RemotePuzzlePlayers.Message",
             CreateAcceptMessage, ReadAcceptMessage, WriteAcceptMessage);
      InitPO(gameOverMessageType, "RemotePuzzlePlayers.GameOverMessage", "RemotePuzzlePlayers.Message",
             CreateGameOverMessage, ReadGameOverMessage, WriteGameOverMessage);
      Services.CreateType(type,
         "RemotePuzzlePlayers.Player", "PuzzlePlayers.Player");

      Services.SeekType("PuzzlePlayers.Player", baseType);
      ASSERT(baseType # NIL);
      NEW(remoteObjIf);
      remoteObjIf.getParams := NIL;
      remoteObjIf.createProxy := CreateProxy;
      remoteObjIf.msgHandler := Handler;
      RemoteObjects.Register(baseType, remoteObjIf, RemoteObjects.parallel);
   END InitIFs;


   PROCEDURE CreateProxy(VAR object: Services.Object;
			 params: PersistentObjects.Object);
      VAR p: Player;
   BEGIN
      NEW(p);
      Services.Init(p, type);
      PuzzlePlayers.Init(p, if);
      RelatedEvents.QueueEvents(p);
      object := p;
   END CreateProxy;
   
BEGIN
   InitIFs;
END RemotePuzzlePlayers.

SS 99 || Ferienprojekt zu Allgemeine Informatik II || Puzzle Library

Andreas Borchert, 26. Juli 1999