-
Notifications
You must be signed in to change notification settings - Fork 0
/
Simultaneous.oz
368 lines (355 loc) · 13.8 KB
/
Simultaneous.oz
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
functor
import
Input
OS System
export
simultaneous:Simultaneous
winner:Winner
define
PlayerAtPosition ItemAtPosition
PlayerWithID
UpdatePlayers UpdateItems
SendAll
SpawnGhost SpawnPacman
MoveGhost MovePacman
KilledByGhost KillGhost
CollectPoint CollectBonus
SpawnPoint SpawnBonus
Simultaneous
TreatStream
PacmanPlayer GhostPlayer
Winner
in
proc{PacmanPlayer MapPort PlayerPort IsAlive LivesLeft}
{System.show livesLeft(LivesLeft)}
if LivesLeft==0 then skip
else ID P HasSurvived in
if IsAlive then
{Send PlayerPort move(ID P)} {Wait ID} {Wait P}
if {Or ID==null P==null} then {PacmanPlayer MapPort PlayerPort false LivesLeft-1} % Killed
else
{Delay Input.thinkMin+({OS.rand} mod (Input.thinkMax-Input.thinkMin))}
{Send MapPort movePacman(ID P HasSurvived)} {Wait HasSurvived} % Alive
end
else
{Delay Input.respawnTimePacman}
{Send PlayerPort spawn(ID P)} {Wait ID} {Wait P}
if {Or ID==null P==null} then {PacmanPlayer MapPort PlayerPort false LivesLeft-1} % Killed
else {Send MapPort spawnPacman(ID P HasSurvived)} {Wait HasSurvived} % Spawned
end
end
if HasSurvived==null then {PacmanPlayer MapPort PlayerPort false LivesLeft-1}
elseif HasSurvived then {PacmanPlayer MapPort PlayerPort true LivesLeft}
else {PacmanPlayer MapPort PlayerPort false LivesLeft-1}
end
end
end
proc{GhostPlayer MapPort PlayerPort IsAlive KillThread}
fun{IsThreadKilled Timeout}
X in
thread {Delay Timeout} X=unit end
if {Record.waitOr KillThread#X}==1 then true
else false
end
end
proc{Local IsAlive}
if {IsThreadKilled 10} then skip % Stop this ghost
else ID P HasSurvived in
if IsAlive then
{Send PlayerPort move(ID P)} {Wait ID} {Wait P}
if {Or ID==null P==null} then {Local false} % Killed
else {Delay Input.thinkMin+({OS.rand} mod (Input.thinkMax-Input.thinkMin))} {Send MapPort moveGhost(ID P HasSurvived)} {Wait HasSurvived} % Alive
end
else
{Delay Input.respawnTimeGhost}
{Send PlayerPort spawn(ID P)} {Wait ID} {Wait P}
if {Or ID==null P==null} then {Local false} % Failed to spawn
else {Send MapPort spawnGhost(ID P HasSurvived)} {Wait HasSurvived} % Spawned
end
end
if HasSurvived==null then {Local false}
else {Local HasSurvived}
end
end
end
in
{Local IsAlive}
end
proc{TreatStream Stream MapPort WindowPort Pacmans Ghosts Mode Points Bonus}
{System.show 'MapServer: '#Stream.1}
case Stream
of nil then skip
[] spawnPacman(ID P HasSurvived)|T then
RT={SpawnPacman ID P WindowPort Pacmans Ghosts Mode} in
case RT
of pacmans(NewPacmans)#ghosts(NewGhosts)#HasSurvivedRT then
HasSurvived=HasSurvivedRT
{TreatStream T MapPort WindowPort NewPacmans NewGhosts Mode Points Bonus}
end
[] spawnGhost(ID P HasSurvived)|T then
RT={SpawnGhost ID P WindowPort Pacmans Ghosts Mode} in
case RT
of pacmans(NewPacmans)#ghosts(NewGhosts)#HasSurvivedRT then
HasSurvived=HasSurvivedRT
{TreatStream T MapPort WindowPort NewPacmans NewGhosts Mode Points Bonus}
end
[] movePacman(ID P HasSurvived)|T then
if {PlayerWithID ID Pacmans}.3==null then % Invalid move need to respawn if actual pos==null
{System.show invalidPacmanMoveCatched(ID)}
HasSurvived=null
{TreatStream T MapPort WindowPort Pacmans Ghosts Mode Points Bonus}
else
RT={MovePacman ID P MapPort WindowPort Pacmans Ghosts Mode Points Bonus} in
case RT
of pacmans(NewPacmans)#ghosts(NewGhosts)#mode(NewMode)#points(NewPoints)#bonus(NewBonus)#HasSurvivedRT then
HasSurvived=HasSurvivedRT
{TreatStream T MapPort WindowPort NewPacmans NewGhosts NewMode NewPoints NewBonus}
end
end
[] moveGhost(ID P HasSurvived)|T then
if {PlayerWithID ID Ghosts}.3==null then % Invalid move need to respawn if actual pos==null
{System.show invalidGhostMoveCatched(ID)}
HasSurvived=null
{TreatStream T MapPort WindowPort Pacmans Ghosts Mode Points Bonus}
else
RT={MoveGhost ID P MapPort WindowPort Pacmans Ghosts Mode Points Bonus} in
case RT
of pacmans(NewPacmans)#ghosts(NewGhosts)#mode(NewMode)#points(NewPoints)#bonus(NewBonus)#HasSurvivedRT then
HasSurvived=HasSurvivedRT
{TreatStream T MapPort WindowPort NewPacmans NewGhosts NewMode NewPoints NewBonus}
end
end
[] spawnBonus(P)|T then
RT={SpawnBonus P MapPort WindowPort Pacmans Ghosts Mode Bonus} in
case RT
of mode(NewMode)#bonus(NewBonus) then
{TreatStream T MapPort WindowPort Pacmans Ghosts NewMode Points NewBonus}
end
[] spawnPoint(P)|T then
RT={SpawnPoint P MapPort WindowPort Pacmans Ghosts Points} in
case RT
of points(NewPoints) then
{TreatStream T MapPort WindowPort Pacmans Ghosts Mode NewPoints Bonus}
end
[] setMode(M)|T then
{Send WindowPort setMode(M)}
{SendAll Pacmans setMode(M)}
{SendAll Ghosts setMode(M)}
{TreatStream T MapPort WindowPort Pacmans Ghosts M Points Bonus}
else
{System.show 'MapServer: Incompatible message: '#Stream.1}
end
end
fun{SpawnPacman ID Position WindowPort Pacmans Ghosts Mode}
Ghost={PlayerAtPosition Position Ghosts}
Pacman={PlayerWithID ID Pacmans}
in
if Mode==classic andthen Ghost\=null then % Killed by ghost
{KilledByGhost WindowPort Pacman Ghost Ghosts}
pacmans({UpdatePlayers Pacmans ID null})#ghosts(Ghosts)#false
elseif Mode==hunt andthen Ghost\=null then % Kill a ghost
{KillGhost WindowPort Pacman Ghost Pacmans}
pacmans({UpdatePlayers Pacmans ID Position})#ghosts({UpdatePlayers Ghosts Ghost.1 null})#true
else % Spawn
{Send WindowPort spawnPacman(ID Position)}
{SendAll Ghosts pacmanPos(ID Position)}
pacmans({UpdatePlayers Pacmans ID Position})#ghosts(Ghosts)#true
end
end
fun{SpawnGhost ID Position WindowPort Pacmans Ghosts Mode}
Pacman={PlayerAtPosition Position Pacmans}
Ghost={PlayerWithID ID Ghosts}
in
if Mode==classic andthen Pacman\=null then % Kill a pacman
{KilledByGhost WindowPort Pacman Ghost Ghosts}
pacmans({UpdatePlayers Pacmans Pacman.1 null})#ghosts({UpdatePlayers Ghosts ID Position})#true
elseif Mode==hunt andthen Pacman\=null then % Killed by a pacman
{KillGhost WindowPort Pacman Ghost Pacmans}
pacmans(Pacmans)#ghosts({UpdatePlayers Ghosts ID null})#false
else % Spawn
{Send WindowPort spawnGhost(ID Position)}
{SendAll Pacmans ghostPos(ID Position)}
pacmans(Pacmans)#ghosts({UpdatePlayers Ghosts ID Position})#true
end
end
fun{MovePacman ID Position MapPort WindowPort Pacmans Ghosts Mode Points Bonus}
Ghost={PlayerAtPosition Position Ghosts}
Pacman={PlayerWithID ID Pacmans}
ItemPoints={ItemAtPosition Position Points}
ItemBonus={ItemAtPosition Position Bonus}
in
{Send WindowPort movePacman(ID Position)}
{SendAll Ghosts pacmanPos(ID Position)}
if Mode==classic andthen Ghost\=null then % Kill by a ghost
{KilledByGhost WindowPort Pacman Ghost Ghosts}
pacmans({UpdatePlayers Pacmans ID null})#ghosts(Ghosts)#mode(Mode)#points(Points)#bonus(Bonus)#false
elseif Mode==hunt andthen Ghost\=null then % Kill a ghost
{KillGhost WindowPort Pacman Ghost Pacmans}
pacmans({UpdatePlayers Pacmans ID Position})#ghosts({UpdatePlayers Ghosts Ghost.1 null})#mode(Mode)#points(Points)#bonus(Bonus)#true
elseif ItemPoints\=null then % Collect a point
{CollectPoint MapPort WindowPort Position Pacman Pacmans}
pacmans({UpdatePlayers Pacmans ID Position})#ghosts(Ghosts)#mode(Mode)#points({UpdateItems Points Position disable})#bonus(Bonus)#true
elseif ItemBonus\=null then % Collect a bonus
{CollectBonus MapPort WindowPort Position Pacmans Ghosts}
pacmans({UpdatePlayers Pacmans ID Position})#ghosts(Ghosts)#mode(hunt)#points(Points)#bonus({UpdateItems Bonus Position disable})#true
else % Nothing to do
pacmans({UpdatePlayers Pacmans ID Position})#ghosts(Ghosts)#mode(Mode)#points(Points)#bonus(Bonus)#true
end
end
fun{MoveGhost ID Position MapPort WindowPort Pacmans Ghosts Mode Points Bonus}
Pacman={PlayerAtPosition Position Pacmans}
Ghost={PlayerWithID ID Ghosts}
in
{Send WindowPort moveGhost(ID Position)}
{SendAll Pacmans ghostPos(ID Position)}
if Mode==classic andthen Pacman\=null then % Kill a pacman
{KilledByGhost WindowPort Pacman Ghost Ghosts}
pacmans({UpdatePlayers Pacmans Pacman.1 null})#ghosts({UpdatePlayers Ghosts ID Position})#mode(Mode)#points(Points)#bonus(Bonus)#true
elseif Mode==hunt andthen Pacman\=null then % Killed by a pacman
{KillGhost WindowPort Pacman Ghost Pacmans}
pacmans(Pacmans)#ghosts({UpdatePlayers Ghosts ID null})#mode(Mode)#points(Points)#bonus(Bonus)#false
else % Nothing to do
pacmans(Pacmans)#ghosts({UpdatePlayers Ghosts ID Position})#mode(Mode)#points(Points)#bonus(Bonus)#true
end
end
fun{SpawnBonus Position MapPort WindowPort Pacmans Ghosts Mode Bonus}
Pacman={PlayerAtPosition Position Pacmans}
Ghost={PlayerAtPosition Position Ghosts} % Display ghost on same position on top of bonus
in
if Pacman\=null then % Collect a bonus
{CollectBonus MapPort WindowPort Position Pacmans Ghosts}
mode(hunt)#bonus(Bonus)
else % Spawn a bonus
{Send WindowPort spawnBonus(Position)}
{SendAll Pacmans bonusSpawn(Position)}
if Ghost\=null then {Send WindowPort moveGhost(Ghost.1 Ghost.3)} end
mode(Mode)#bonus({UpdateItems Bonus Position enable})
end
end
fun{SpawnPoint Position MapPort WindowPort Pacmans Ghosts Points}
Pacman={PlayerAtPosition Position Pacmans}
Ghost={PlayerAtPosition Position Ghosts}
in
if Pacman\=null then % Collect a Point
{CollectPoint MapPort WindowPort Position Pacman Pacmans}
points(Points)
else % Spawn a Point
{Send WindowPort spawnPoint(Position)}
{SendAll Pacmans pointSpawn(Position)}
if Ghost\=null then {Send WindowPort moveGhost(Ghost.1 Ghost.3)} end % Reprint Ghost above the new point
points({UpdateItems Points Position enable})
end
end
proc{KilledByGhost WindowPort Pacman Ghost Ghosts}
NewLife NewScore in
{Send Pacman.2 gotKilled(_ NewLife NewScore)} {Wait NewLife} {Wait NewScore}
{Send Ghost.2 killPacman(Pacman.1)}
{Send WindowPort hidePacman(Pacman.1)}
{Send WindowPort lifeUpdate(Pacman.1 NewLife)}
{Send WindowPort scoreUpdate(Pacman.1 NewScore)}
{SendAll Ghosts deathPacman(Pacman.1)}
end
proc{KillGhost WindowPort Pacman Ghost Pacmans}
NewScore in
{Send Ghost.2 gotKilled()}
{Send Pacman.2 killGhost(Ghost.1 _ NewScore)} {Wait NewScore}
{Send WindowPort hideGhost(Ghost.1)}
{Send WindowPort scoreUpdate(Pacman.1 NewScore)}
{SendAll Pacmans deathGhost(Ghost.1)}
end
proc{CollectPoint MapPort WindowPort Position Pacman Pacmans}
NewScore in
{Send Pacman.2 addPoint(Input.rewardPoint _ NewScore)} {Wait NewScore}
{Send WindowPort scoreUpdate(Pacman.1 NewScore)}
{Send WindowPort hidePoint(Position)}
{SendAll Pacmans pointRemoved(Position)}
thread {Delay Input.respawnTimePoint} {Send MapPort spawnPoint(Position)} end
end
proc{CollectBonus MapPort WindowPort Position Pacmans Ghosts}
{Send WindowPort hideBonus(Position)}
{Send WindowPort setMode(hunt)}
{SendAll Pacmans bonusRemoved(Position)}
{SendAll Pacmans setMode(hunt)}
{SendAll Ghosts setMode(hunt)}
thread {Delay Input.huntTime} {Send MapPort setMode(classic)} end
thread {Delay Input.respawnTimeBonus} {Send MapPort spawnBonus(Position)} end
end
fun{PlayerAtPosition Position Players}
case Players
of nil then null
[] H|_ andthen H.3==Position then H
else {PlayerAtPosition Position Players.2}
end
end
fun{ItemAtPosition Position Items}
case Items
of nil then null
[] H|_ andthen H.1==Position andthen H.2==enable then H
else {ItemAtPosition Position Items.2}
end
end
fun{PlayerWithID ID Players}
case Players
of nil then null
[] H|_ andthen H.1==ID then H
else {PlayerWithID ID Players.2}
end
end
fun{UpdatePlayers Players ID Position}
case Players
of nil then nil
[] H|T andthen H.1==ID then ID#H.2#Position|T
else Players.1|{UpdatePlayers Players.2 ID Position}
end
end
fun{UpdateItems Items Position State}
case Items
of nil then nil
[] H|T andthen H.1==Position then Position#State|T
else Items.1|{UpdateItems Items.2 Position State}
end
end
proc{SendAll Players Msg}
case Players
of nil then skip
[] H|T then {Send H.2 Msg} {SendAll T Msg}
end
end
proc{Simultaneous WindowPort Pacmans Ghosts Points Bonus}
fun{CreateMapPort}
local Stream MapPort={NewPort Stream} in
thread {TreatStream Stream MapPort WindowPort Pacmans Ghosts classic Points Bonus} end
MapPort
end
end
fun{BestPacman Pacmans Best}
case Pacmans
of nil then Best
[] H|T andthen Best==null then {BestPacman T H}
[] H|T andthen {GetScore H}>{GetScore Best} then {BestPacman T H}
else {BestPacman Pacmans.2 Best}
end
end
fun{GetScore Pacman}
NewScore in
{Send Pacman.2 addPoint(0 _ NewScore)} {Wait NewScore}
NewScore
end
MapPort={CreateMapPort}
StatesAgents={Record.make statesAgents {List.number 1 Input.nbPacman 1}}
KillThread
in
for I in 1..Input.nbPacman do
thread {PacmanPlayer MapPort {Nth Pacmans I}.2 true Input.nbLives} StatesAgents.I=unit end
end
for I in 1..Input.nbGhost do
thread {GhostPlayer MapPort {Nth Ghosts I}.2 true KillThread} end
end
% Wait end of all pacmans then kill ghosts agents
for I in 1..Input.nbPacman do
{Wait StatesAgents.I}
end
KillThread=unit
Winner={BestPacman Pacmans null}
end
end