From eb450921dab3afae83bf833a3cd9dea2b2c51e8e Mon Sep 17 00:00:00 2001
From: unknown <ingenzivany@gmail.com>
Date: Wed, 8 Dec 2021 23:15:47 +0100
Subject: [PATCH] Finished the Turn-By-Turn Implementation

---
 .gitignore        |   1 +
 Input.oz          |  18 ++--
 Main.oz           | 223 ++++++++++++++++++++++++++++++++++++++++++++--
 Makefile          |  21 ++++-
 Player000Basic.oz |  22 ++++-
 Player001Basic.oz |  38 ++++++++
 PlayerManager.oz  |   8 +-
 statement.pdf     | Bin 191731 -> 206558 bytes
 8 files changed, 303 insertions(+), 28 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 Player001Basic.oz

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ce5ed96
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+./*.ozf
\ No newline at end of file
diff --git a/Input.oz b/Input.oz
index 3e676eb..69711ff 100644
--- a/Input.oz
+++ b/Input.oz
@@ -4,7 +4,7 @@ export
     nRow:NRow
     nColumn:NColumn
     map:Map
-    nbPlayer:NbPlayer
+    nbPlayer:NbPlayers
     players:Players
     colors:Colors
     thinkMin:ThinkMin
@@ -25,7 +25,7 @@ define
     NRow
     NColumn
     Map
-    NbPlayer
+    NbPlayers
     Players
     Colors
     ThinkMin
@@ -52,17 +52,17 @@ in
    
     NRow = 5
     NColumn = 10
-    Map = [[0 0 0 0 0 0 0 0 0 0]
-    [0 0 0 0 0 0 0 0 0 0]
-    [0 0 0 1 1 0 0 0 0 0]
-    [0 0 1 1 0 0 1 0 0 0]
-    [0 0 0 0 0 0 0 0 0 0]]
+    Map =  [[0 0 0 0 0 0 0 0 0 0]
+            [0 0 0 0 0 0 0 0 0 0]
+            [0 0 0 0 0 0 0 0 0 0]
+            [0 0 0 0 0 0 1 0 0 0]
+            [0 0 0 0 0 0 0 0 0 0]]
 
 %%%% Players description %%%%
 
     NbPlayers = 2
-    Players = [player1 player2]
-    Colors = [red blue]
+    Players = [player000basic player001basic]
+    Colors = [green black]
   
 %%%% Surface time/turns %%%%
 
diff --git a/Main.oz b/Main.oz
index fb43455..8cd15b2 100644
--- a/Main.oz
+++ b/Main.oz
@@ -3,16 +3,223 @@ import
     GUI
     Input
     PlayerManager
+    System
 define
     %% TODO
+    GUI_PORT = {GUI.portWindow}
+    PlayersList
+
+    %% Players  : List of players
+    %% Colors   : List of colors
+    %% AccID    : Init ID number to give to players
+    fun {InitPlayers Players Colors AccID}
+        case Players#Colors 
+        of nil#nil then nil
+        [] (Player|OtherPlayers)#(Color|OtherColors) then 
+            player( 
+                    port:{PlayerManager.playerGenerator Player Color AccID}
+                    nbSurface: 0 %% All the players start underwater
+                  )|{InitPlayers OtherPlayers OtherColors AccID+1}
+        end
+    end
+
+    %% L        : List to visit
+    %% F        : Function for visiting
+    proc {VisitList L F}
+        case L of nil then skip
+        [] H|T then {F H} {VisitList T F}
+        end 
+    end
+    
+    fun {ModifyOnlyCurrent Players Current F}
+        {List.Map Players fun{$ Player} if Player==Current then {F Player} else Player end end}
+    end
+
+    %% NextPlayers      : The next players to play
+    %% CurrentIndex     : The index of the next player
+    %% Indicate Next    : Unbound variable for the turn
+    fun {TurnByTurn1 Players CurrentIndex Next} 
+        CurrentPlayer={List.nth Players CurrentIndex}
+        fun{IncrNbSurface Player} player(port:Player.port nbSurface:Player.nbSurface+1) end
+    in
+        if CurrentPlayer.nbSurface > 0 andthen CurrentPlayer.nbSurface < Input.turnSurface then 
+            Next = 9
+            {ModifyOnlyCurrent Players CurrentPlayer IncrNbSurface}
+        else
+            Next = 2 Players
+        end 
+    end
+
+    %% NextPlayers      : The next players to play
+    %% CurrentIndex     : The index of the next player
+    fun {TurnByTurn2 Players CurrentIndex}
+        CurrentPlayer={List.nth Players CurrentIndex}
+        fun{SetNbSurfaceZero Player} 
+            {Send Player.port dive}
+            player(port:Player.port nbSurface:0)
+        end
+    in
+        if CurrentPlayer.nbSurface == Input.turnSurface then
+            {ModifyOnlyCurrent Players CurrentPlayer SetNbSurfaceZero}
+        else
+            Players
+        end
+    end
+
+    %% Players          : List of players cell
+    %% Msg              : The message to broadcast
+    proc {Broadcast Players Msg}
+        case Players of nil then skip
+        [] Player|OtherPlayers then
+            {Send Player.port Msg}
+        end
+    end
+
+    proc {ManageMineExplosion Players Id Position}
+        {List.forAll Players    proc{$ Player} Resp in
+                                    {Send Player.port sayMineExplode(Id Position Resp)}
+                                    {Wait Resp}
+                                    case Resp of null then skip
+                                    else {Broadcast Players Resp} end
+                                end}
+    end
+
+    proc {ManageMissileExplosion Players Id Position}
+        {List.forAll Players    proc{$ Player} Resp in
+                                    {Send Player.port sayMissileExplode(Id Position Resp)}
+                                    {Wait Resp}
+                                    case Resp of null then skip
+                                    else {Broadcast Players Resp} end
+                                end}
+    end
+
+
+    proc{ManagingDroneFiring Players SenderPlayer Drone}
+        {List.forAll Players proc{$ Player} ID Resp in
+                                    {Send Player.port sayPassingDrone(Drone ID Resp)}
+                                    {Send SenderPlayer.port Resp}
+                                end}
+    end
+
+    proc{ManagingSonarFiring Players SenderPlayer}
+        {List.forAll Players proc{$ Player} ID Resp in
+            {Send Player.port sayPassingSonar(ID Resp)}
+            {Send SenderPlayer.port Resp} end}
+    end
+
+    fun {TurnByTurn345 Players CurrentIndex Next}
+        CurrentPlayer={List.nth Players CurrentIndex}
+        ID Pos Direction NewPlayers
+        fun{SetNbSurfaceOne Player} player(port:Player.port nbSurface:1) end
+    in
+        {Send CurrentPlayer.port move(ID Pos Direction)}
+        {Wait ID} {Wait Pos} {Wait Direction}
+        case Direction 
+        of surface then 
+            NewPlayers={ModifyOnlyCurrent Players CurrentPlayer SetNbSurfaceOne}
+            {Broadcast NewPlayers saySurface(ID)}       {Send GUI_PORT surface(ID)}
+            Next=9 NewPlayers
+        [] east then 
+            {Broadcast Players sayMove(ID Direction)}   {Send GUI_PORT movePlayer(ID pt(x:Pos.x y:Pos.y+1))}
+            Next=6 Players
+        [] west then 
+            {Broadcast Players sayMove(ID Direction)}   {Send GUI_PORT movePlayer(ID pt(x:Pos.x y:Pos.y-1))}
+            Next=6 Players
+        [] north then
+            {Broadcast Players sayMove(ID Direction)}   {Send GUI_PORT movePlayer(ID pt(x:Pos.x-1 y:Pos.y))}
+            Next=6 Players
+        [] south then
+            {Broadcast Players sayMove(ID Direction)}   {Send GUI_PORT movePlayer(ID pt(x:Pos.x+1 y:Pos.y))}
+            Next=6 Players
+        else
+            Next=6 Players
+        end
+    end
+
+    proc {TurnByTurn6 Players CurrentIndex}
+        CurrentPlayer=Players.CurrentIndex
+        ID KindItem 
+    in 
+        {Send CurrentPlayer.port chargeItem(ID KindItem)}
+        {Wait ID} {Wait KindItem}
+        case KindItem of null then skip
+        else 
+            {Broadcast Players sayCharged(ID KindItem)}
+        end
+    end
+
+    proc {TurnByTurn78 Players CurrentIndex}
+        CurrentPlayer=Players.CurrentIndex
+        ID KindFire
+    in 
+        {Send CurrentPlayer.port fireItem(ID KindFire)}
+        {Wait ID} {Wait KindFire}
+        case KindFire of null then skip
+        [] mine(Position) then Id Mine in 
+            {Send GUI_PORT putItem(ID Position)}    {Broadcast Players sayMinePlace(ID)}
+            {Send CurrentPlayer.port fireMine(Id Mine)}
+            case Mine of null then skip %% To Be Studied
+            else 
+                {Send GUI_PORT explosion(Id Position)} 
+                {ManageMineExplosion Id Players Position}
+            end
+        [] missile(Position) then 
+            {ManageMissileExplosion ID Players Position}
+        [] drone(U V) then 
+            {Send GUI_PORT drone(ID KindFire)}
+            {ManagingDroneFiring Players CurrentPlayer KindFire}
+        [] sonar then 
+            {Send GUI_PORT sonar(ID)}
+            {ManagingSonarFiring Players CurrentPlayer}
+        end
+    end
+
+    proc {TurnByTurn Players CurrentIndex}
+        NewPlayers1 NewPlayers2 NewPlayers3
+        Next1 Next345
+    in
+        %% 1.
+        NewPlayers1 = {TurnByTurn1 Players CurrentIndex Next1}
+        if Next1==2 then
+            %% 2.
+            NewPlayers2 = {TurnByTurn2 NewPlayers1 CurrentIndex}
+            %% 345.
+            NewPlayers3 = {TurnByTurn345 NewPlayers2 CurrentIndex Next345}
+            if Next345==6 then 
+                %% 6.
+                {TurnByTurn6 NewPlayers3 CurrentIndex}
+                %% 78.
+                {TurnByTurn78 NewPlayers3 CurrentIndex}
+                %% 9.
+                {TurnByTurn NewPlayers3 (CurrentIndex mod Input.nbPlayer)+1}
+            else
+                %% 9.
+                {TurnByTurn NewPlayers1 (CurrentIndex mod Input.nbPlayer)+1}
+            end
+        else
+            %% 9.
+            {TurnByTurn NewPlayers1 (CurrentIndex mod Input.nbPlayer)+1}
+        end        
+    end
 in
-    %%  1.  Create the port for the GUI and launch its interface
-    %%  2.  Create the port for every player using the PlayerManager.
-    %%  3.  Choose its initial point for every player.
-    %%  4.  Choose game mode and launch the game.
+    %%1. 
+    {Send GUI_PORT buildWindow}
+
+    %%2. Create Port for Every Player
+    PlayersList={InitPlayers Input.players Input.colors 1}
 
-    %% TODO: implement the controllers:
-    %%   - Turn-by-turn
-    %%   - Simultaneous
+    %%3. Ask Init Point and tell players to dive
+    {VisitList  PlayersList
+                proc{$ Player} 
+                    ID Pos 
+                in
+                    {Send Player.port initPosition(ID Pos)}
+                    {Send GUI_PORT initPlayer(ID Pos)}
+                    {Send Player.port dive}
+                end}
 
-end
\ No newline at end of file
+    %%4. Launch the game 
+    if Input.isTurnByTurn then 
+        {TurnByTurn PlayersList 1}
+    end
+end
diff --git a/Makefile b/Makefile
index f562d29..32d61a5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,22 @@
 # ----------------------------
-# group nb XXX
-# noma1 : name1 surname1
-# noma2 : name2 surname2
+# group nb 20
+# noma1 : Ingenzi Vany			80461900
+# noma2 : Hirwa Mihigo Olyvia 	02701900
 # ----------------------------
 
 # TODO complete the header with your group number, your noma's and full names
 
-# TODO write your makefile here
\ No newline at end of file
+# TODO write your makefile here
+OZFILES=$(wildcard ./*.oz)
+OZEXEC=$(OZFILES:.oz=.ozf)
+
+%.ozf:%.oz
+	@ozc -c $^
+
+.PHONY: runMain
+
+runMain: $(OZEXEC)
+	@ozengine ./Main.ozf
+
+clean: 
+	@rm -f $(OZEXEC)
\ No newline at end of file
diff --git a/Player000Basic.oz b/Player000Basic.oz
index b286e89..9405dbd 100644
--- a/Player000Basic.oz
+++ b/Player000Basic.oz
@@ -1,6 +1,7 @@
 functor
 import
-Input 
+    Input 
+    OS
 export
    portPlayer:StartPlayer
 define
@@ -10,15 +11,28 @@ in
     fun{StartPlayer Color ID}
         Stream
         Port 
+        RandomX = ({OS.rand} mod Input.nRow)    + 1
+        RandomY = ({OS.rand} mod Input.nColumn) + 1
     in
         {NewPort Stream Port}
         thread
-            {TreatStream Stream}
+            {TreatStream Stream '#'(id:id(id:ID color:Color name:name) 
+                                    pos:pt(x:RandomX y:RandomY)
+                                    items:'#'(missile:0 sonar:0 drone:0 mine:0)) 
+            }
+
         end
         Port
     end
 
-    proc{TreatStream Stream} %% TODO: you may add as many argument as needed
-        %% TODO: complete 
+    proc{TreatStream Stream State}
+        case Stream 
+        of initPosition(ID Pos)|T then 
+            ID  = State.id 
+            Pos = State.pos
+            {TreatStream Stream State}
+        else 
+            {TreatStream Stream State}
+        end
     end
 end
\ No newline at end of file
diff --git a/Player001Basic.oz b/Player001Basic.oz
new file mode 100644
index 0000000..680d134
--- /dev/null
+++ b/Player001Basic.oz
@@ -0,0 +1,38 @@
+functor
+import
+    Input 
+    OS
+    System
+export
+   portPlayer:StartPlayer
+define
+    StartPlayer
+    TreatStream
+in
+    fun{StartPlayer Color ID}
+        Stream
+        Port 
+        RandomX = ({OS.rand} mod Input.nRow)    + 1
+        RandomY = ({OS.rand} mod Input.nColumn) + 1
+    in
+        {NewPort Stream Port}
+        thread
+            {TreatStream Stream '#'(id:id(id:ID color:Color name:name) 
+                                    pos:pt(x:RandomX y:RandomY)) 
+            }
+
+        end
+        Port
+    end
+
+    proc{TreatStream Stream State}
+        case Stream 
+        of initPosition(ID Pos)|T then 
+            ID  = State.id 
+            Pos = State.pos
+            {TreatStream Stream State}
+        else 
+            {TreatStream Stream State}
+        end
+    end
+end
\ No newline at end of file
diff --git a/PlayerManager.oz b/PlayerManager.oz
index 43be76d..1520935 100644
--- a/PlayerManager.oz
+++ b/PlayerManager.oz
@@ -1,7 +1,7 @@
 functor
 import
    Player000Basic
-   ...
+   Player001Basic
 export
    playerGenerator:PlayerGenerator
 define
@@ -9,8 +9,10 @@ define
 in
    fun{PlayerGenerator Kind Color ID}
       case Kind
-      of player000basic then {Player000basic.portPlayer Color ID}
-      ...
+      of player000basic then 
+         {Player000Basic.portPlayer Color ID}
+      [] player001basic then 
+         {Player001Basic.portPlayer Color ID}
       end
    end 
 end
\ No newline at end of file
diff --git a/statement.pdf b/statement.pdf
index 64f699deeb8c23e5c75dc5aac8dc26a7d9b5e51f..04d93ec0b294548addb2d5cd89d695da778f89b7 100644
GIT binary patch
delta 14700
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

delta 13
Vcmcb2mgn<L?uHh|Eli)^001*D2Ppsm

-- 
GitLab