-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathport_object.oz
1489 lines (1459 loc) · 49.4 KB
/
port_object.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
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
functor
import
QTk at 'x-oz://system/wp/QTk.ozf'
Application
OS
Pickle
System
PortDefinitions
AI
AnimatePort
Widget
export
main: MAIN
define
GETDIR = PortDefinitions.getDir
GETINVDIR = PortDefinitions.getInvDir
GETMISSINGDIR = PortDefinitions.getMissingDir
NewPortObject = PortDefinitions.port
NewPortObjectKillable = PortDefinitions.kPort
NewPortObjectMinor = PortDefinitions.mPort
Timer = PortDefinitions.timer
Waiter = PortDefinitions.waiter
ArtificialPlayer = AI.artificialPlayer
GetEnemyAi = AI.getEnemyAi
AnimateTrainer = AnimatePort.trainer
DrawFight = AnimatePort.fight
GetLostScreen = AnimatePort.getLostScreen
GetWelcomeScreen = AnimatePort.getWelcomeScreen
GetWonScreen = AnimatePort.getWonScreen
GetEvolveScreen = AnimatePort.getEvolveScreen
DrawPokeList = Widget.drawPokeList
InitFightTags = Widget.initFightTags
InitPokeTags = Widget.initPokeTags
InitEvolveTags = Widget.initEvolveTags
DrawMap = Widget.drawMap
StarterPokemoz = Widget.starterPokemoz
DrawLost = Widget.drawLost
DrawWon = Widget.drawWon
DrawEvolve = Widget.drawEvolve
MAINPO = Widget.mainPO
KEYS = Widget.keys
PLAYER = Widget.player
WILD = Widget.wild
LISTAI = Widget.listAI
CANVAS = Widget.canvas
TAGS = Widget.tags
ANIMFIRST = Widget.animFirst
MAPID = Widget.mapID
MAPREC = Widget.mapRec
SPEED = Widget.speed
DELAY = Widget.delay
PROBABILITY = Widget.probability
MAXX = Widget.maxX
MAXY = Widget.maxY
AITAGS = Widget.aiTags
% This file will contain all the portObjects' descriptions and code
%%%%%%% MAPRELATED PORTOBJECTS %%%%%%%%%%%%
%@pre: C = coord(x:X y:Y) with X and Y integers
% Init = state(occupied) or state(empty)
% Mapid = Pid of the MapControler
% Ground= {grass,road}
%@post: Returns the Pid of the tile
CreateFight
GetWildling
fun{Tile Init C Mapid Ground}
fun{SignalArrival Trainer Ldir Inv}
case Ldir of nil then nil
[] H|T then
Dir Ack
if Inv then Dir = {GETINVDIR H}
else Dir = {GETDIR H} end
in
if {Send Mapid checkSimple(x:C.x+Dir.x y:C.y+Dir.y $
sig:new(H Trainer Ack))} then
Ack|{SignalArrival Trainer T Inv}
else
Ack = unit
{SignalArrival Trainer T Inv}
end
end
end
proc{WaitList L}
case L of nil then skip
[] H|T then {Wait H} {WaitList T}
end
end
Tid = {Timer}
Tilid = {NewPortObject Init
fun{$ Msg state(State)}
case Msg
of get(X) then
X=State
state(State)
[] getGround(X) then
X=Ground
state(State)
[] leaving then
state(leaving)
[] coming(T Plid Val) then
{Send Tid starttimer(Tilid T arrived(Plid Val))}
state(reserved)
[] coming(T Plid Val B) then %VAL is NOT bound properly!
if State == empty then
B=true
{Send Tid starttimer(Tilid T arrived(Plid Val))}
state(reserved)
else
B=false
state(State)
end
[] arrived(Plid Val) then AckL in
if Ground == grass andthen
{Label Plid} == player then
Wild = {GetWildling}
in
if Wild \= none then
{Send Plid.pid startFight(Wild _)}
end
end
if {Label Plid} == player then
AckL={SignalArrival Plid [up left down right] true}
else
AckL={SignalArrival Plid [{Send Plid.pid getDir($)}] false}
end
thread
{WaitList AckL}%It slows down the whole process but blocks EVERY
%concurrency issue we had!
Val=unit
end
state(occupied(Plid))
[] new(Dir Trainer Ack) then
case State
of occupied(Y) then LblY = {Label Y} Ack2 in
if LblY\={Label Trainer} then
if LblY==player then
if {Send Trainer.poke getFirst($)} \= none then
{Send Y.pid startFight(Trainer Ack2)}
else Ack2 = unit
end
elseif {Send Y.pid getDir($)} == Dir then
if {Send Y.poke getFirst($)} \= none then
{Send Trainer.pid startFight(Y Ack2)}
else Ack2 = unit
end
else Ack2=unit
end
thread
{Wait Ack2} %to be sure that the trainer can't move away
% before being set to fightmode or fightWait
Ack = unit
end
else Ack = unit
end
state(State)
else
% We don't care
Ack = unit
state(State)
end
[] restart then
case State
of occupied(Y) then
if{Label Y} == npc then
{Send Y.pid rmBlock}
else skip
end
else skip
end
state(State)
[] left then
state(empty)
[] init(X) then
state(occupied(X))
end
end}
in
Tilid
end
%
%@post: Returns the pid of the controller (through which every command
% to the tiles passes)
fun{MapController Map}
MapRec
Ground = ground(0:road 1:grass)
fun{CheckEdges X Y}
if X>0 andthen X=<MAXX andthen
Y>0 andthen Y=<MAXY then
true
else
false
end
end
proc{SignalSides L X Y}
case L of nil then skip
[] H|T then
Dx = {GETDIR H}
NewX = X+Dx.x
NewY = Y+Dx.y
in
if{CheckEdges NewX NewY} then
{Send MapRec.NewY.NewX restart}
end
{SignalSides T X Y}
end
end
Mapid = {NewPortObjectMinor
proc{$ Msg}
case Msg
of send(x:X y:Y Sig) then
if{CheckEdges X Y} then
{Send MapRec.Y.X Sig}
end
[] checkSimple(x:X y:Y B sig:Sig) then
if {CheckEdges X Y} then
B=true
{Send MapRec.Y.X Sig}
else
B=false
end
[] movingToNew(X Y dir:Dir B sig:Sig) then
Dx = {GETDIR Dir}
NewX = X+Dx.x
NewY = Y+Dx.y
in
if {CheckEdges NewX NewY} then
B={Send MapRec.NewY.NewX coming(Sig.1 Sig.2 Sig.3 $)}
if B then
{Send MapRec.Y.X leaving}
%Free the AI if their path was blocked!
thread
{Wait Sig.3}
{SignalSides {GETMISSINGDIR Dir} X Y}
if {Label Sig.2}==player then
if NewX == MAXX andthen NewY==MAXY then
{Send Sig.2.poke refill}
{ANIMFIRST}
elseif NewX==MAXX andthen NewY==1 then
{Send MAINPO set(won)}
{GetWonScreen}
end
end
end
end
else B = false
end
[] init(x:X y:Y Plid) then
{Send MapRec.Y.X init(Plid)}
end
end}
in
%better to thread drawmap function
MapRec = {MakeTuple 'mapids' MAXY}
for J in 1..MAXY do
MapRec.J = {MakeTuple 'mapids' MAXX}
for I in 1..MAXX do
MapRec.J.I = {Tile state(empty) coord(x:I y:J) Mapid
Ground.(Map.J.I)}
end
end
MAPREC = MapRec
Mapid
end
%%%%%%%% WILD-POKEMOZ %%%%%%%%
CreatePokemoz CreatePokemozList
fun{RandomName Type}
Names=
pokemoz( grass:grass( %poke("Bulbasoz" "Ivysoz" "Venusoz")
poke("Ozweed" "Kakunoz" "Ozdrill")
poke("Machoz" "Machozman" "Ozchamp")
poke("Rozzozoz" "Roticoz"))
water:water(%poke("Oztirtle" "Wartoztle" "Blastoz")
poke("Zoizoz" "Grozoizoz")
poke("Magiciendoz" "Pytagyroz")
poke("Ozcool" "Ozcruel")
poke("Coincwoz" "Goldoz"))
fire:fire( %poke("Charmandoz" "Charmeleoz" "Charozard")
poke("Vulpoz" "9xOz")
poke("Oz2_0")
poke("Ozachu" "Ozmouse")
poke("Pidgeoz" "Pidgeozoz" "Ozpidgeoz")))
X
in
if Type == grass then X = 3
else X = 4
end
Names.Type.(({OS.rand} mod X)+1)
end
WildlingTrainer
thread WildlingTrainer = wild(poke:{CreatePokemozList nil nil wild}) end
%CreateTrainer Name X0 Y0 Speed Mapid Names Lvls Type}
fun{GetWildling}
fun{Opposite Type}
case Type
of water then grass
[] grass then fire
[] fire then water
end
end
in
if ({OS.rand} mod 100)+1 =< PROBABILITY then
%Calculating lvl
Lvl={FloatToInt {Round {Send PLAYER.poke getAverage($)}}}
R
Ra = {OS.rand} mod 50
if Ra < 35 then R = ~1
elseif Ra < 48 then R = 0
else R = 1
end
Lvl2 = {Max Lvl+R 5}
Lvl3 = {Min Lvl2 10}
%Choosing type
Type = {Send PLAYER.poke getFirstNonDead($)}.type
Type2
Ra2 = {OS.rand} mod 50
if Ra2 < 38 then Type2 = {Opposite {Opposite Type}}
elseif Ra2 < 48 then Type2 = Type
else Type2 = {Opposite Type}
end
%Getting pokemoz
Name = {RandomName Type2} Name2
case Name
of poke(X) then Name2 = X
[] poke(X1 X2) then
if Lvl3<8 then Name2 = X1
else Name2 = X2 end
[] poke(X1 X2 X3) then
if Lvl3<7 then Name2 = X1
elseif Lvl3<9 then Name2 = X2
else Name2 = X3 end
end
Pokemoz={CreatePokemoz Name2 Lvl3 wild}
Ack
in
{Send WildlingTrainer.poke add(Pokemoz Ack)}
{Wait Ack}
WildlingTrainer
else
none
end
end
%%%%%%%%% TRAINER-RELATED PORTOBJECTS %%%%%%%%%
% This portObject will serve as a bridge between the controller
% and the GUI
%@pre : C = pos(x:X y:Y) the start coordinates (X/Y are integers)
% Anid = Pid of animation thread
%@post: Returns the Pid of the trainer
fun{Trainer C Anid Person}
Init = state(C dir:up)
Trid = {NewPortObject Init
fun{$ Msg state(Pos dir:Dir)}
case Msg
of getDir(X) then
X=Dir
state(Pos dir:Dir)
[] getPos(X) then
X=Pos
state(Pos dir:Dir)
[] moveTo(x:X y:Y) then
if Person\=player then
{Send Anid move(Dir normal)}
else
if (Dir == up andthen Y < (MAXY-4) andthen Y>2) orelse
(Dir == down andthen Y < (MAXY-3) andthen Y>3) orelse
(Dir == left andthen X < (MAXX-4) andthen X>2) orelse
(Dir == right andthen X < (MAXX-3) andthen X>3) then
{Send Anid move(Dir special)}
else {Send Anid move(Dir normal)}
end
end
state(pos(x:X y:Y) dir:Dir)
[] turn(NewDir) then
{Send Anid turn(NewDir)}
state(Pos dir:NewDir)
[] reset then
{Send Anid reset(Pos.x Pos.y)}
state(pos(x:MAXX y:MAXY) dir:up)
end
end}
in
Trid
end
proc{BlockAI}
proc{Loop L}
case L of nil then skip
[] H|T then {Send H.pid block} {Loop T}
end
end
in
{Loop LISTAI}
end
proc{ReleaseAI}
proc{Loop L}
case L of nil then skip
[] H|T then {Send H.pid rmBlock} {Loop T}
end
end
in
{Loop LISTAI}
end
proc{ReleaseWaitingAI}
proc{Loop L}
case L of nil then skip
[] H|T then {Send H.pid endFight} {Loop T}
end
end
in
{Loop LISTAI}
end
%@pre : Mapid = the Pid of the mapControler
% Trid = the Pid of the trainer this controller is destined to
%@post: Returns the controler of the trainer
fun{TrainerController Mapid Trid Speed TrainerObj}
AiBool
if TrainerObj.ai\=none then AiBool= (TrainerObj.ai.type==auto)
else AiBool = false end
Wid = {Waiter}
Plid = {NewPortObject state(still nil)
fun{$ Msg state(State FSched)}%FSched = fight-scheduler
case Msg
of getDir(X) then
{Send Trid getDir(X)}
state(State FSched)
[] move(NewDir) then
if State == still then
ActDir = {Send Trid getDir($)}
in
if ActDir == NewDir then
Pos = {Send Trid getPos($)}
Dx = {GETDIR NewDir}
NewX = Pos.x+Dx.x
NewY = Pos.y+Dx.y
Val %will be bound on arrival
ActDel = {DELAY.get}
Sig = coming(Speed*ActDel TrainerObj Val)
in
%Check for boundaries and if the tile is free
%then send arriving signal
if {Send Mapid movingToNew(Pos.x Pos.y dir:NewDir $ sig:Sig)} then
{Send Trid moveTo(x:NewX y:NewY)}
{Send Wid wait(Plid Val arrived)}
{Send Wid wait(Mapid Val send(x:Pos.x y:Pos.y left))}
state(moving FSched)
else
if AiBool then
{Send TrainerObj.ai.pid go(pos:{Send Trid getPos($)}
dir:{Send Trid getDir($)})}
end
state(still FSched)
end
else
{Send Trid turn(NewDir)}
state(still FSched)
end
else
%Neglect info if moving/fighting
state(State FSched)
end
[] startFight(Npc Ack) then %every npc has to be unique
if {Label Npc}\=wild then
{Send Npc.pid waitFight}
end
if State == fighting then
Ack = unit
state(State {Append [Npc] FSched})
else %Then FSched HAS TO BE nil!!
{BlockAI}
{CreateFight TrainerObj Npc}
Ack = unit
state(fighting FSched)
end
[] nextFight then %on fight won
case FSched of nil then
{ReleaseAI}
if AiBool then
{Send TrainerObj.ai.pid go(pos:{Send Trid getPos($)}
dir:{Send Trid getDir($)})}
end
state(still FSched)
[] H|T then
{Delay {DELAY.get}*2}
{CreateFight TrainerObj H}
state(fighting T)
end
[] arrived then
if State == moving then
if AiBool then
{Send TrainerObj.ai.pid go(pos:{Send Trid getPos($)}
dir:{Send Trid getDir($)})}
end
state(still nil)
else
state(State FSched)
end
[] reset(Ack) then %on fight lost
Pos = {Send Trid getPos($)}
in
thread {ReleaseWaitingAI} end
{Send TrainerObj.poke refill}
{Send Mapid send(x:Pos.x y:Pos.y left)}
{Send Mapid init(x:MAXX y:MAXY PLAYER)}
{Send Trid reset}
Ack=unit
state(still nil)
end
end}
in
Plid
end
% Trid = the Pid of the trainer this controller is destined to
%@post: Returns the controler of the trainer
fun{TrainerControllerWithAi Mapid Trid Speed TrainerObj AIid}
Wid = {Waiter}
Plid = {NewPortObject state(still)
fun{$ Msg state(State)}
case Msg
of getDir(X) then
{Send Trid getDir(X)}
state(State)
[] move(NewDir B) then
if State == still then
%ActDir = {Send Trid getDir($)}
Pos = {Send Trid getPos($)}
Dx = {GETDIR NewDir}
NewX = Pos.x+Dx.x
NewY = Pos.y+Dx.y
Val %will be bound on arrival
ActDel = {DELAY.get}
Sig = coming(Speed*ActDel TrainerObj Val)
in
if {Send Mapid movingToNew(Pos.x Pos.y dir:NewDir $ sig:Sig)} then
{Send Trid moveTo(x:NewX y:NewY)}
{Send Wid wait(Plid Val arrived)}
{Send Wid wait(Mapid Val send(x:Pos.x y:Pos.y left))}
B=true
state(moving)
else
B=false
state(still)
end
else
B = false
state(State)
end
[] turn(NewDir B) then
if State == still then
Pos = {Send Trid getPos($)}
Ack
in
{Send Trid turn(NewDir)}
{Send Mapid send(x:Pos.x y:Pos.y arrived(TrainerObj Ack))}
B=true
{Send Wid wait(AIid Ack go)}
state(still)
else
B = false
state(State)
end
[] waitFight then
state(waiting)
[] endFight then
%{Send AIid go}
state(still)
[] rmBlock then
{Send AIid rmBlock}
state(State)
[] block then
{Send AIid block}
state(State)
[] arrived then%should only be bound when everything has been checked
if State == moving then
{Send AIid go}
state(still)
else
state(State)
end
end
end}
in
Plid
end
%%%%%%% FIGHT PORTOBJECTS %%%%%%%%%%%
fun{GetDamage PlayType NpcType Hit} % Hit = player or npc
if PlayType == NpcType then 2
elseif Hit == npc then
case PlayType
of fire then if NpcType==grass then 3 else 1 end
[] grass then if NpcType==water then 3 else 1 end
[] water then if NpcType==fire then 3 else 1 end
end
else
case NpcType
of fire then if PlayType==grass then 3 else 1 end
[] grass then if PlayType==water then 3 else 1 end
[] water then if PlayType==fire then 3 else 1 end
end
end
end
fun {AttackSuccessful Play Npc Attacker}
PlayLvl = {Send Play.pid getLvl($)}
NpcLvl = {Send Npc.pid getLvl($)}
in
case Attacker
of player then
Probability = (6+PlayLvl-NpcLvl)*9
Rand = ({OS.rand} mod 100)+1 % from 1 to 100
in
if Rand =< Probability then true
else false
end
[] npc then
Probability = (6+NpcLvl-PlayLvl)*9
Rand = ({OS.rand} mod 100)+1 % from 1 to 100
in
if Rand =< Probability then true
else false
end
end
end
fun{GetNewPokemoz PokeL}
LivingList = {Send PokeL getAllLiving($)}
Rand = ({OS.rand} mod {Length LivingList}) + 1
in
{List.nth LivingList Rand}
end
fun {RunSuccessful Play Npc} % Npc is a WILD pokemoz guaranteed!!
PlayLvl = {Send Play.pid getLvl($)}
NpcLvl = {Send Npc.pid getLvl($)}
Rand = ({OS.rand} mod 100)+1
in
if Rand =< (6+PlayLvl-NpcLvl)*9+1 then true
else false
end
end
fun {CatchSuccessful Play Npc}
h(act:NpcActH max:NpcMaxH) = {Send Npc.pid getHealth($)}
Rand = ({OS.rand} mod NpcMaxH)+1
Rand2 = ({OS.rand} mod NpcMaxH)+1
in
if Rand >= NpcActH then true
elseif Rand2 >= NpcActH then true
else false end
end
proc{CreateEvoScreens L}
case L of nil then skip
[] (Name1#Name2)|T then Img Text in
Img#Text = {DrawEvolve Name1 Name2}
{Send MAINPO set(evolve)}
{GetEvolveScreen Img Text}
{CreateEvoScreens T}
end
end
fun {FightController PlayObj NpcObj FightAnim Arrows}%PlayL and NpcL are <PokemozList>
AiBool = (PlayObj.ai\=none)
PlayL = PlayObj.poke NpcL=NpcObj.poke
WaitAnim = {Waiter}
proc{OnExit Ack EvoL}
thread
{Wait Ack}
{Send Arrows kill}
if {Label NpcObj}\=wild then
{Send NpcObj.pid endFight}
end
% Evolution
{CreateEvoScreens EvoL}
{Send PlayObj.pid nextFight}
{Send MAINPO set(map)}
end
end
proc{OnBadExit Ack}
%{OnExit Ack}
thread Ack2 in
{Wait Ack}
{Send Arrows kill}
{Send PlayObj.pid reset(Ack2)}
{Wait Ack2}
{GetLostScreen ReleaseAI}
end
end
FirstPlay = {Send PlayL getFirstNonDead($)}
FirstNpc = {Send NpcL getFirst($)}
FightPort = {NewPortObjectKillable
state(player:FirstPlay
enemy:FirstNpc
fighting:false)
fun{$ Msg state(player:Play enemy:Npc fighting:OK)}
case Msg
of run then
if OK then
state(player:Play enemy:Npc fighting:OK)
else
if {Label Npc}\=wild then
{Send FightAnim illRun}
state(player:Play enemy:Npc fighting:OK)
elseif {RunSuccessful Play Npc} then Ack in
{Send FightAnim exit(Ack "You ran away cowardly...")}
{Send WaitAnim wait(NpcL Ack releaseAll)}
{OnExit Ack nil}
state(killed)
else
% Send signal to itself for AI turn = automatic
% attack
{Send FightAnim failRun}
{Send FightPort fightIA}
state(player:Play enemy:Npc fighting:true)
end
end
[] action(X) then X = OK
state(player:Play enemy:Npc fighting:OK)
[] fight then
if OK then
state(player:Play enemy:Npc fighting:OK)
else
NEState Ack
in
if {AttackSuccessful Play Npc player} then
Damage = {GetDamage Play.type Npc.type npc}
in
{Send Npc.pid damage(Damage NEState)}
{Wait NEState}
% ^ to avoid concurrency issues (even if they are
% VERY unlikely)
{Send FightAnim attack(player Ack)}
else
{Send FightAnim attackFail(player Ack)}
NEState = alive
end
if NEState == alive then
{Send WaitAnim wait(FightPort Ack fightIA)}
state(player:Play enemy:Npc fighting:true)
elseif {Send NpcL getState($)} == allDead then Ack EvoL in
{Send FightAnim exit(Ack "You WON!")}
%{Send WaitAnim wait(MAINPO B set(map))}
{Send PlayL shareExp({Send NpcL getAllExp($)} EvoL)}
{OnExit Ack EvoL}
{Send NpcL releaseAll}
state(killed)
else
{Send WaitAnim wait(FightPort Ack switchIA)}
state(player:Play enemy:Npc fighting:true)
end
end
[] fightIA then NTState Ack in
if {AttackSuccessful Play Npc npc} then
Damage = {GetDamage Play.type Npc.type player}
%{Show getting#Damage#damage#Play.type#Npc.type}
in
{Send Play.pid damage(Damage NTState)}
{Wait NTState}%actually not necessary
{Send FightAnim attack(npc Ack)}
else
{Send FightAnim attackFail(npc Ack)}
NTState = alive
end
if NTState == alive then
{Send WaitAnim wait(FightPort Ack endAttack)}
if AiBool then
{Send WaitAnim wait(PlayObj.ai.pid Ack goFight(play:Play npc:Npc))}
end
state(player:Play enemy:Npc fighting:OK)
elseif {Send PlayL getState($)} == allDead then Ack in
{Send FightAnim exit(Ack "You LOST!")}
{Send NpcL refill}
{OnBadExit Ack}
if {Label Npc}==wild then
{Send WaitAnim wait(NpcL Ack releaseAll)}
end
state(killed)
else
proc{FigureLoop Status} B in
thread
{DrawPokeList dead(B)}
if AiBool then
{Send PlayObj.ai.pid change}
end
end
if Status == first then
{Send MAINPO set(pokelist)}
end
if B\=none andthen B\=auto then
{Send FightPort switch(B play)}
elseif B == auto then
NewPkm = {GetNewPokemoz PlayL}
in
{Send FightPort switch(NewPkm play)}
else
{FigureLoop xth}
end
end
in
thread {Wait Ack} {FigureLoop first} end
state(player:Play enemy:Npc fighting:true)
end
[] endAttack then
state(player:Play enemy:Npc fighting:false)
[] switch(NewPkm Next) then %this signal can only be sent
% by a valid button
if NewPkm == Play then
state(player:Play enemy:Npc fighting:OK)
else
Ack={Send FightAnim switch(player NewPkm $)}
in
if Next == ia then
{Send WaitAnim wait(FightPort Ack fightIA)}
else
{Send WaitAnim wait(FightPort Ack endAttack)}
if AiBool then
{Send WaitAnim wait(PlayObj.ai.pid Ack goFight(play:Play npc:Npc))}
end
end
state(player:NewPkm enemy:Npc fighting:true)
end
[] switchIA then
NewNpc = {GetNewPokemoz NpcL} Ack
in
{Send FightAnim switch(npc NewNpc Ack)}
{Send WaitAnim wait(FightPort Ack fightIA)}
state(player:Play enemy:NewNpc fighting:true)
[] catching then
if {Label Npc} \= wild then
{Send FightAnim illCatch(playVsNpc)}
state(player:Play enemy:Npc fighting:OK)
elseif {Send PlayL get($ 6)}\=none then
{Send FightAnim illCatch(playFull)}
state(player:Play enemy:Npc fighting:OK)
elseif {CatchSuccessful PlayL Npc} then Ack in
{Send NpcL captured}
{Send PlayL add(Npc _)}
{Send FightAnim catched(Ack)}
{Send WaitAnim wait(MAINPO Ack set(map))}
{OnExit Ack nil}
state(killed)
else Ack in
{Send FightAnim failCatch(Ack)}
{Send WaitAnim wait(FightPort Ack fightIA)}
state(player:Play enemy:Npc fighting:true)
end
end
end}
in
/*if AiBool then
{Send Play.ai.pid goFight(play:FirstPlay npc:FirstNpc)}
end*/
FightPort
end
%%%%%%% THE EXTERN FUNCTIONS %%%%%%
EXPER = exp(5:5 6:12 7:20 8:30 9:50 10:1000000)
fun{GETTYPE Name}
Grass = ["Bulbasoz" "Ivysoz" "Venusoz" "Ozweed" "Kakunoz" "Ozdrill"
"Zoizoz" "Grozoizoz" "Machoz" "Machozman" "Ozchamp"]
Water = ["Oztirtle" "Wartoztle" "Blastoz" "Rozzozoz" "Roticoz" "Coincwoz"
"Goldoz" "Ozcool" "Ozcruel" "Magiciendoz" "Pytagyroz"]
Fire = ["Charmandoz" "Charmeleoz" "Charozard" "Pidgeoz" "Pidgeozoz"
"Ozpidgeoz" "Ozachu" "Ozmouse" "Vulpoz" "9xOz" "Oz2_0"]
in
if {Member Name Grass} then grass
elseif {Member Name Water} then water
%elseif {Member Name Grass} then fire
else fire
end
end
fun{GetNewName Name OldLvl NewLvl}
fun{GetNext L}
case L of nil then none %should not happen
[] H|T then
if H == Name then T.1
else {GetNext T}
end
end
end
fun{GetNext2 L}
case L of nil then none %should not happen
[] H|T then
if H == Name then T.2.1
else {GetNext2 T}
end
end
end
Three= ["Bulbasoz" "Ivysoz" "Venusoz" "Ozweed" "Kakunoz" "Ozdrill"
"Machoz" "Machozman" "Ozchamp" "Pidgeoz" "Pidgeozoz" "Ozpidgeoz"
"Oztirtle" "Wartoztle" "Blastoz" "Charmandoz" "Charmeleoz"
"Charozard"]
Two = ["Zoizoz" "Grozoizoz" "Magiciendoz" "Pytagyroz" "Rozzozoz"
"Roticoz" "Ozcool" "Ozcruel" "Coincwoz" "Goldoz" "Vulpoz"
"9xOz" "Ozachu" "Ozmouse"]
One = ["Oz2_0"]
in
if {Member Name One} then none
elseif {Member Name Two} then
if OldLvl < 8 andthen NewLvl >= 8 then
{GetNext Two}
else
none
end
else
if OldLvl < 7 andthen NewLvl >= 9 then
{GetNext2 Three}
elseif OldLvl < 7 andthen NewLvl >= 7 then
{GetNext Three}
elseif OldLvl < 9 andthen NewLvl >=9 then
{GetNext Three}
else
none
end
end
end
proc{GetLevel Exp Lvl Ne Le}
if Lvl < 10 andthen Exp >= EXPER.Lvl then
{GetLevel Exp-EXPER.Lvl Lvl+1 Ne Le}
else
Ne = Exp Le = Lvl
end
end
%Function that creates a Pokemoz
fun{CreatePokemoz Name Lvl0 State}
Type = {GETTYPE Name}
HealthMax = 20+(Lvl0-5)*2
ExpMax = EXPER.Lvl0
%Send Kill signal when the wild pokemoz vanishes, trainer is defeated
%or pokemoz is released back into the wild
Pokid = {NewPortObjectKillable state(health:h(act:HealthMax max:HealthMax)
exp:e(act:0 max:ExpMax) lvl:Lvl0)
fun{$ Msg state(health:He exp:Exp lvl:Lvl)}
% released == kill
case Msg
of getHealth(X) then
X=He
state(health:He exp:Exp lvl:Lvl)
[] getExp(X) then
X=Exp
state(health:He exp:Exp lvl:Lvl)
[] getLvl(X) then
X=Lvl
state(health:He exp:Exp lvl:Lvl)
[] addExp(AddExp Evolve) then
%will replenish Health automatically in
%case of evolution and send info in case of
%evolution
NewExp = AddExp+Exp.act
in
if NewExp >= Exp.max then
if Lvl < 10 then NExp NLvl in
{GetLevel NewExp Lvl NExp NLvl}
if Lvl == NLvl then
Evolve = none
state(health:He exp:e(act:NExp max:Exp.max)
lvl:Lvl)
else NMaxH = (NLvl-5)*2 + 20
NewName = {GetNewName Name Lvl NLvl}
in
if NewName\=none then %evolution
Evolve = {CreatePokemoz NewName NLvl player}
{Send Evolve.pid addExp(NExp _)}
state(killed)
else
Evolve = none
state(health:he(act:NMaxH max:NMaxH)
exp:e(act:NExp max:EXPER.NLvl) lvl:NLvl)
end
end
else % if at maxLvl allready
Evolve = none
state(health:He exp:Exp lvl:Lvl)
end
else
Evolve = none
state(health:He exp:e(act:NewExp max:Exp.max)
lvl:Lvl)
end
[] damage(X State) then %State is unbound
NHealth ={Max He.act - X 0}
in
if NHealth == 0 then State = dead
else State = alive end
state(health:he(act:NHealth max:He.max) exp:Exp lvl:Lvl)
[] refill then