forked from IreneeMichel/MagicCardBattle
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathCreature.py
419 lines (394 loc) · 17.9 KB
/
Creature.py
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
import pygame
from copy import copy
from functools import partial
from Sprites import Animation,Sprite,Attach_to_Creature
#,Mark
import random
from types import MethodType,FunctionType
#from Spell import Multiplier
from Card import Card
wound_img = pygame.transform.scale(pygame.image.load("gameAnimationImages/damage.png"),(300,260))
wound_img.set_colorkey((0,0,0))
class Creature() :
def __init__(self,origin,card,player) :
if hasattr(player,"verbose") and player.verbose>4 : print " Creature __init__ ",card.name," from ",player.name
# origin is usually a cardInHand
#print "creature init",card.name
self.card=card
self.is_dead = False
self.max_pv = self.pv=card.pv
self.att=card.att
self.name=card.name
self.bonus=[copy(b) for b in card.bonus]
for b in self.bonus :
b.owner=self
self.player=player
self.game = player.game
self.ready=False
self.starcost=card.starcost
player.army.append(self)
#print "army apres add",player,[(c,c.name) for c in player.army]
self.marks={} # ligne temproraire
if self.pv==0 :
# it is a spell
#print "creature",self,self.name,"de",self.player.name," bonus=",self.bonus
for m in player.army :
if m.max_pv>0 :
for b in m.bonus :
b.spellLaunched(self)
for m in player.adv.army :
for b in m.bonus :
b.otherSpellLaunched(self)
#print "owner2",self.bonus[0].owner
player.launch(self,card.bonus[0])
else :
self.marks={}
self.id=self.game.getId()
if isinstance(origin,Creature) :
self.is_invocation=True
else :
self.is_invocation=False
for b in reversed(self.bonus) :
#print "after invoc ",b
b.afterInvocation(self)
for m in player.army :
if m is not self :
for b in m.bonus :
b.additionalBonus(self)
for m in player.adv.army :
if m.pv > 0 :
for b in m.bonus :
b.otherMonsterCreation(self)
if len(player.army)>9 and "choix1"!=self.name and "choix2"!=self.name :
player.sacrify()
def beginTurn(self) :
#if isinstance(self,AnimatedCreature) : print "normal begin turn de ",self.name
self.ready=True
def getInlineDescription(self):
return self.name +" ("+str(self.att)+" "+str(self.pv)+' '.join(
[b.getInlineDescription() for b in self.bonus]) +" )"
def endTurn(self):
for p in reversed(self.bonus): # pour bien remettre les choses en place
p.endturn(self)
def combatAnim(self,target) :
self.combat(target)
def combat(self,target) :
from Player import Computer0
#if not isinstance(target.player,Computer0) : print "combat de base",self,"attaque ",target
self.ready=False
for b in self.bonus :
b.beforeCombat(self,target)
if target != self :
for b in target.bonus :
b.beforeCombat(self,target)
self.combatSequence(target)
self.afterCombat(target)
target.afterCombat(self)
def afterCombat(self,adv) :
#from Player import Player
#if not isinstance(adv,Player) : print "aftercombat basic",self.name
#if self.pv <1 :
for b in reversed(self.bonus) :
b.afterCombat(self,adv)
def combatSequence(self,target) :
self.attack(target)
target.defend(self)
def attack(self,target) :
damage=self.att
for b in self.bonus :
damage=b.modifyDamage(self,damage,target)
target.sufferDamage(damage)
def defend(self,target) :
#print "defend normal"
self.attack(target)
def sufferDamage(self,damage) :
self.sufferDamageAnimation(damage)
self.pv-=damage
if self.pv <1 and self.pv+damage>0 :
#"print " die due to damage"
self.die()
def sufferDamageAnimation(self,damage) :
pass
def updateImage(self) :
pass
def addMark(self,name,pos="center",typ="external",level=1,size=0,value=0) :
if "-simu" not in self.player.name :
print "fatal error Mark playing",self.name
raise "toto"
self.marks[name]=[value]
def removeMark(self,name,level=1) :
if name in self.marks :
del self.marks[name]
def hasMark(self,name) :
return (name in self.marks)
def die(self):
self.pv=0
if self.is_dead == False :
self.is_dead = True
if self.max_pv>0 :
for b in self.bonus:
b.death(self)
for m in self.player.army :
if m.max_pv>0 and m is not self :
for b in m.bonus:
b.otherDeath(self)
for m in self.player.adv.army :
if m.max_pv>0 and m is not self :
for b in m.bonus:
b.enemyDeath(self)
# dans la simu le monstre sera dans l armee donc il faut que le remove soit apres le launch de agonie
if self in self.player.army :
self.player.army.remove(self)
else :
pass
# spells are removed from army
#if self.max_pv<1 :
#print "Strange : creature",self,self.name," not in army ?"
#print self.player,self.player.name," army was : ",self.player.army,[c.name for c in self.player.army]
#b=0/0
def castSpellAnimation(self) :
pass
def copy_methods(self, klass, *methods):
"""Copy methods from `klass` into this object.
"""
for method in methods:
self.copy_method(klass, method)
def takePlace(self,add=0):
#print " takePlace de creature=pass"
pass
class CreatureCopy(Creature) :
def __init__(self,original,player) :
for i in dir(original) :
if i not in ("sufferDamageAnimation","takePlace","castSpellAnimation","combatAnim","appear","die","addMark","removeMark","updateImage") and i[0]!= "_":
if callable(getattr(original,i)) :
m1=getattr(original,i)
f=FunctionType(m1.func_code,globals(),closure=m1.func_closure)
m=MethodType(f,self)
setattr(self,i,m)
else :
setattr(self,i,copy(getattr(original,i)))
self.player=player # difference importante avec l original : game et player
self.game=player.game
self.bonus=[copy(b) for b in original.bonus]
for b in self.bonus :
b.owner=self
#class AnimatedSpell(Sprite,Spell):
# def __init__(self,origin,card,player) :
# if not hasattr(card,"image") :
# name=card.name.replace(" ","_")
# card.image = pygame.image.load(name+".png")
# Sprite.__init__(self,origin,pygame.transform.scale(card.image,(136, 200)))
# # self.player=player
# effect=partial(self.appear,*(origin,card,player)) # creature appears only then
# #destination=self.getPlace(add=1)
# phase0 = (destination,30, self.size,effect)
# Animation(origin,[phase0])
# #self.game.all_animations.add(self)
# #self.game.animation_runing = True
# #self.anim_num = 0
# #player.army.add(self)
# def attack(self,creature) :
# #self.setPosition(origin.center)
# Spell.__init__(self,origin,card,player)
# player.hand.remove(origin)
# #print "init animated creature done"
class AnimatedCreature(Sprite,Creature) :
def __init__(self,origin,card,player,simultaneous=1) :
#print "animated creature init ",card.name,origin,card
# creature is init only after effect
if not hasattr(card,"image") :
name=card.name.replace(" ","_")
try :
card.image = pygame.image.load("Cards/"+name+".png")
except :
import glob
lina=glob.glob("*"+name+"*.png")+glob.glob("*/*"+name+"*.png")
if lina :
card.image = pygame.image.load(lina[0])
else :
screen_info = pygame.display.Info() #Required to set a good resolution for the game screen
height,width = screen_info.current_h, screen_info.current_w
print "image manquante ,name=",name
card.image = card.createImage(True)
pygame.image.save(card.image,name+".png")
card.image = pygame.image.load(name+".png")
pygame.display.set_mode((width,height))
Sprite.__init__(self,origin,pygame.transform.scale(card.image,(136, 200)))
self.game=player.game
self.player=player
self.index = len(player.army)+simultaneous-1
self.graphism = copy(card.image)
self.name=card.name # ligne utile pour debug de getplace
player.orderArmy(add=simultaneous)
effect=partial(self.appear,*(origin,card,player)) # creature appears only then
if card.pv>0 :
destination=self.getPlace(add=simultaneous)
else :
destination=[800,450]
phase0 = (destination,10, self.size,effect)
Animation(origin,[phase0])
self.all_effects = {}
#self.game.all_animations.add(self)
#self.game.animation_runing = True
#self.anim_num = 0
#player.army.add(self)
def appear(self,origin,card,player) :
#print "appear",origin,card
if origin in player.hand :
player.hand.remove(origin) # remove avant creature sinon le getchoice de la simulation l oublie
self.setPosition(origin.center)
Creature.__init__(self,origin,card,player)
player.orderArmy(add=0)
#print "init animated creature done"
def castSpellAnimation(self) :#print "launch from",origin," army is ",self.army
sp=Sprite(self,"gameAnimationImages/boule_energie_bleue.png",[20,20])
phase0=(self.getPosition(),8,[250,250],None)
Animation(sp,[phase0],True)
def sufferDamageAnimation(self,damage) :
#Sprite(sprite,"gameAnimationImages/stone.png")
phase1 = (self.center,5,[4.*damage]*2,self.updateImage)
Animation(Sprite(self,wound_img),[phase1],True)
def updateImage(self):
#print "UPDATE_IMG"
# pas sur d avoir une card ici
# le graphism a une taille connue, l image peut etre reduite
self.graphism = copy(self.card.image)
wound=self.max_pv - self.pv
if not "wound" in self.marks :
if wound :
self.marks["wound"]=[0,wound_img,"random",wound,"multiple"]
else :
self.marks["wound"][3]=wound
self.child=[]
#print " update",self.name,"with",self.marks.keys()
for i,o in self.marks.items() :
#print "update mark",i,o
value,image,position,level,typ=o
lx,ly=image.get_size()
if typ=="external" :
sx,sy=self.size
else :
sx,sy=self.graphism.get_size()
#print " creature size is ",self.size
nb=[1,level][typ=="multiple"]
#print "nb",nb,":",level,typ
for i in range(nb) :
if position=="random" :
pos_mod=(random.random()*(sx*1.-lx)+sx*0.0,random.random()*(sy*1.-ly)+sy*0.)
elif position=="center" : # ce serait mieux de faire ce calcul dans addMark
pos_mod=(sx/2.-lx/2.,sy/2.-ly/2.)
#print "center, pos_mod",pos_mod
elif position=="sw" : # ce serait mieux de faire ce calcul dans addMark
pos_mod=(sx*0.3-lx/2.,sy*0.9-ly/2.)
#print "sw, pos_mod",pos_mod
elif position=="se" : # ce serait mieux de faire ce calcul dans addMark
pos_mod=(sx*0.7-lx/2.,sy*0.9-ly/2.)
elif position=="s" : # ce serait mieux de faire ce calcul dans addMark
pos_mod=(sx*0.5-lx/2.,sy*0.9-ly/2.)
#print "se, pos_mod",pos_mod
else :
pos_mod=position
if typ=="external" :
#print "external"
self.child.append(Attach_to_Creature(self,image,pos_mod))
else :
#print " blit de mark ",image,position," sur ",self.name
self.graphism.blit(image,pos_mod)
if typ=="number" :
font = pygame.font.SysFont("Calibri Bold",46)
text = font.render("+"*(level>0)+str(level),False,(0,0,0))
self.graphism.blit(text,(pos_mod[0]+lx/2-20,pos_mod[1]+ly/2-15))
self.image = pygame.transform.scale(self.graphism,self.size)
def addMark(self,name,pos="center",typ="external",level=1,size=0,value=0) :
# a mark is list of an origin (string or instance), an image (or list of) (string or image), a position on card
# image and position are string
#print "add Mark"
#print " addMark , creature ",self.name," has ",self.marks.keys()," and we add ",name
if not (name in self.marks) :
#effect = eval(tipe)(self,eff_img,pos,level)
if typ=="power" :
nbpo=len([1 for m in self.marks.values() if m[4]=="power"])
pos=(187.-5.5*len(name),167*2.+(4-nbpo)*20*2.)
image=pygame.Surface((10+11*len(name),30))
image.fill((60,60,100))
font = pygame.font.SysFont("Calibri Bold",30)
text = font.render(name,False,(0,0,0))
image.blit(text,(5,10))
else :
fname=name
if not "." in name :
fname=name+".png"
try :
image=pygame.image.load("gameAnimationImages/"+fname)
except :
try :
image=pygame.image.load(fname)
except :
import glob
u=glob.glob("*/"+fname)
if u :
image=pygame.image.load(u[0])
else :
print "Mark : */"+fname," not found"
raise
if size :
image = pygame.transform.scale(image,size)
#image.convert_alpha()
image.set_colorkey((0,0,0))
self.marks[name]=[value,image,pos,level,typ]
# self.game.temporary_sprites.add(effect)
# self.all_effects[name]=effect
else :
# == "Mark":
self.marks[name][3] += level
#print " addMark , creature ",self.name," has ",self.marks.keys()
self.updateImage()
#if name in marks
#self.marks.append((name,origin,image,position))
#self.graphism.blit(image,position)
def removeMark(self,name,level=0) :
if not name in self.marks :
print "removeMark : fatal error : name",name," not in marks ",self.marks.keys()," of creature ",self.name,self
return
if level :
#print " level ->",self.marks[name][2],"-",level
self.marks[name][3]-=level
if self.marks[name][3]==0 or not level :
del self.marks[name]
#print " removeMark ",name,", creature ",self.name," now has ",self.marks.keys()
self.updateImage()
#def imageEffect(self,(name,image_name,size),pos=(0,0),tipe="Attach_to_Creature",level=0):
#def destroyEffect(self,name,lv=0):
# print name," destroyed from ",self
def combatAnim(self,target):
#print "combat de base pour animated creature"
if target is not self :
phase1 = (target.center,10, None,partial(self.combat,*(target,)))
phase2=(self.center,10,None,None)
animated_sprite=self
for b in self.bonus :
animated_sprite=b.attackAnimationSprite(animated_sprite)
a=Animation(animated_sprite,[phase1]+[phase2]*(animated_sprite==self),animated_sprite!=self)
a.phase_time = 2 # l attaque ne fait plus que 9/10 du trajet
else :
self.combat(target)
def die(self):
self.kill()
Creature.die(self)
self.player.orderArmy()
if self.all_effects:
for e in reversed(self.all_effects.keys()):
self.game.temporary_sprites.remove(self.all_effects[e])
def getPlace(self,add=0):
# add is to prepare the add or remove of a card
nb=len([m for m in self.player.army if m.pv>0])
x = self.game.width/2 + (80*(self.index*2 - nb-add+1)*self.game.width)/1600
#print self.name," getPlace ",self.index,"/(",len(self.player.army),"+",add,") x=",x
y=self.player.army.position_y
return (x,y)
def takePlace(self,add=0):
#print " take place de",self,self.name
Animation(self,[(self.getPlace(add),3, self.size,None)])
#def initAnimation(self):
# pass
#print "init_animation with no effect"