def ai_rank(c, hmod=1, mxhmod=1): # Gets a card's rank based on its stats out = ((c.card.cost * v.aiMod["c_costMod"]) + ((c.card.attack + c.changes["attack"]) * v.aiMod["c_attackMod"]) + ((c.card.health + c.changes["health"]) * v.aiMod["c_healthMod"] * hmod) + ((c.card.health / (c.card.health + c.changes["health"])) * v.aiMod["c_mxHealthMod"] * mxhmod)) path = pathfind.pathfind(c.tile.pos, (-1, 1), pathfind.get_grid(castle=True)) # Gets card's distance from opponent castle if path != False: while path[-1][0] > 3 and path[-2][0] > 3: path = path[:-1] if len(path) >= c.card.speed + c.changes["speed"] or c.tile.pos[0] + c.tile.range >= 4: out += ((c.card.attack + c.changes["attack"]) * v.aiMod["c_attackMod"]) out += (20 / v.opHealth) * v.aiMod["p_castleMod"] return out
def changes(): """Will implement the list of changes fetched from the game server""" for event in v.networkChanges: if v.online == False and event["type"] == "turn" and len(v.networkChanges) > 1: v.networkChanges.append(v.networkChanges.pop(0)) if event["type"] == "place": pos = event["position"] pos = (3 - pos[0], pos[1]) cunid = event["unid"] for tile in v.tiles: if tile.pos == pos: target = tile card = v.cards[event["id"]] gameItems.add_card(card, tile=target, unid=cunid, player=v.opUnid, renSize=(100, 140), opintro=True) if event["type"] == "move": pos = event["position"] pos = (3 - pos[0], pos[1]) c = None for card in v.gameCards: if card.unid == event["unid"]: c = card if c == None: continue for tile in v.tiles: if tile.pos == pos: path = pathfind.pathfind(c.tile.pos, pos, pathfind.get_grid()) c.tile = tile c.movePath = path if event["type"] == "movable" or "movable" in event.keys(): c = None for card in v.gameCards: if card.unid == event["unid"]: c = card if c == None: continue if event["movable"]: c.moves = 1 else: c.moves = 0 if event["type"] == "damage": for card in v.gameCards: if card.unid == event["unid"]: c = card if event["target"] == v.unid: v.pHealth -= c.card.attack + c.changes["attack"] c.attack("player") else: for card in v.gameCards: if card.unid == event["target"]: t = card c.changes["health"] -= t.card.attack + t.changes["attack"] t.changes["health"] -= c.card.attack + c.changes["attack"] c.attack(t) #c._render((100, 140)) #t._render((100, 140)) if event["type"] == "spell": for card in v.gameCards: if card.unid == event["target"]: target = card if "damage" in event["effects"].keys(): target.changes["health"] -= event["effects"]["damage"] gameItems.Effect(event["animation"], target=target, sheet="assets/images/effects/fireball.png") target._render((100, 140)) if event["type"] == "turn": v.gameTurn = event["turn"] for s in v.gameCards: if s.type == "minion": if v.gameTurn["player"] == v.unid: # If player's turn if s.player == v.unid and s.tile != None: s.next_turn() if v.gameTurn["player"] == v.opUnid: # If opponent's turn if s.player == v.opUnid: s.moves = 1 if v.gameTurn["player"] == v.unid: # If player's turn if len(v.hand) < 4: for card in v.gameDeck: if card.order == 0: card.aniCycle = 1 else: card.order -= 1 v.pturn.cycle = 1 if v.totalMana < 10: v.totalMana += 1 v.pMana = v.totalMana if event["type"] == "stop": v.gameStop = event["reason"] v.networkHalt = True if v.online == False: v.networkChanges.remove(event) return v.networkChanges = []
def update(self): if self.rect.collidepoint(v.mouse_pos): self.hovered = True else: self.hovered = False self.attack = False self.card = None for card in v.gameCards: if card.tile == self: self.card = card if v.dragCard != None: #If card is being dragged if v.dragCard.type == "minion": #If it is a minion card if v.dragCard.tile == None: #If the card is in the player's hand if self.pos[0] < 2: v.availableTiles.add(self) else: #If the card is on the board if self.castle == None: #If this tile isn't a castle tile path = pathfind.pathfind(v.dragCard.tile.pos, self.pos, pathfind.get_grid(skip=[])) a = False for card in v.gameCards: if card.tile == self: if card.player == v.opUnid: a = True path = pathfind.pathfind(v.dragCard.tile.pos, self.pos, pathfind.get_grid(skip=[self])) if path != False and len(path) - 1 <= v.dragCard.moves and v.dragCard.card.speed > 0: v.availableTiles.add(self) if a: self.attack = True if v.dragCard.moves > 0 and v.dragCard.range > 0 and a and abs(v.dragCard.tile.pos[0] - self.pos[0]) <= v.dragCard.range and abs(v.dragCard.tile.pos[1] - self.pos[1]) <= v.dragCard.range: v.availableTiles.add(self) self.attack = True else: #If this tile is a castle tile if self.castle == False: paths = [pathfind.pathfind((v.dragCard.tile.pos[0] + 1, v.dragCard.tile.pos[1]), (self.pos[0] + 1, 0), pathfind.get_grid(skip=[], castle=True)), pathfind.pathfind((v.dragCard.tile.pos[0] + 1, v.dragCard.tile.pos[1]), (self.pos[0] + 1, 1), pathfind.get_grid(skip=[], castle=True)), pathfind.pathfind((v.dragCard.tile.pos[0] + 1, v.dragCard.tile.pos[1]), (self.pos[0] + 1, 2), pathfind.get_grid(skip=[], castle=True))] paths = [p for p in paths if p != False] if len(paths) > 0: path = paths[0] for p in paths: if len(p) < len(path): path = p else: path = False if path != False and len(path) - 1 <= v.dragCard.moves and v.dragCard.card.speed > 0: v.availableTiles.add(self) self.attack = True if v.dragCard.type == "spell": if self.card != None: v.availableTiles.add(self) self.attack = True if v.availableTiles != None: if not self in v.availableTiles: self.hovered = False self.rimage = self.image.copy() if self.card != None: if self.card.player == v.unid: self.rimage.fill((100, 255, 100, 200), special_flags=py.BLEND_RGBA_MULT) else: self.rimage.fill((255, 100, 100, 200), special_flags=py.BLEND_RGBA_MULT) if self.castle != None: if self.attack: self.rimage = self.image.copy() else: self.rimage = py.Surface((0, 0)) if self.hovered: v.hoverTile = self if self.attack: self.rimage.fill((200, 200, 200, 0), special_flags=py.BLEND_RGBA_MAX) else: self.rimage.fill((255, 255, 255, 200)) self.draw()
def ai_action(board, c, targets): bestAction = (None, 0) #print("====", c.card.id, c.tile.pos, "====") for y in range(3): for x in range(-1, 4): curRank = 0 path = pathfind.pathfind((c.tile.pos[0] + 1, c.tile.pos[1]), (x + 1, y), pathfind.get_grid(skip=[(x, y)], castle=True)) #print(">>", (x, y)) if path != False: path = [(p[0]-1, p[1]) for p in path] card = board[y][x] # Card is actually a tile... oops if card != "" or x == -1 or x == 4 and (x, y) != c.tile.pos: if len(path) > 1: while path[-2][0] > 3 or path[-2][0] < -1: path = path[:-1] if x == -1: curRank = [t["rank"] for t in targets if t["card"] == "pCastle"][0] elif x == 4: curRank = [t["rank"] for t in targets if t["card"] == "aiCastle"][0] elif card != "": for t in targets: if t["card"] == card and t["card"].player != 0: curRank += t["rank"] else: curRank = 0 speedDiff = len(path) - c.card.speed + c.changes["speed"] if speedDiff > 0: curRank -= speedDiff * v.aiMod["m_moveDiffMod"] #print("----", curRank, path) if curRank > bestAction[1]: #print("^^^^ overtake") while len(path) > c.card.speed + c.changes["speed"] + 1: path = path[:-1] event = [] if len(path) != 0 and c.card.speed + c.changes["speed"] > 0: if path[-1][0] == -1 or path[-1][0] == 4: while len(path) > 0 and (path[-1][0] < 0 or path[-1][0] > 3): path = path[:-1] if len(path) > 1: event.append({"type": "move", "unid": c.unid, "position": ai_invertCoords(path[-1])}) if len(path) == 0 or path[-1][0] == -1: event.append({"type": "damage", "unid": c.unid, "target": v.unid}) #print("++++ damage castle") else: target = board[path[-1][1]][path[-1][0]] if target != "": if len(path) > 1: event.append({"type": "move", "unid": c.unid, "position": ai_invertCoords(path[-2])}) event.append({"type": "damage", "unid": c.unid, "target": target.unid}) #print("++++ damage", target.unid, target.tile.pos, (path[-1][0], path[-1][1])) if c.range == 0 and target.changes["health"] + target.card.health - (c.card.attack + c.changes["attack"]) <= 0 and c.changes["health"] + c.card.health - (target.card.attack + target.changes["attack"]) > 0: event[-1]["kill"] = True event.append({"type": "move", "unid": c.unid, "position": ai_invertCoords(target.tile.pos)}) else: event.append({"type": "move", "unid": c.unid, "position": ai_invertCoords(path[-1])}) bestAction = (event, curRank) if bestAction[0] != None: bestAction[0][-1]["movable"] = False v.networkChanges.extend(bestAction[0]) #v.networkChanges.append({"type": "movable", "unid": c.unid, "movable": False}) for e in bestAction[0]: if e["type"] == "move": board[ai_invertCoords(e["position"])[1]][ai_invertCoords(e["position"])[0]] = "" if e["type"] == "damage": if "kill" in e.keys(): for y in range(3): for x in range(4): if board[y][x] != "" and board[y][x].unid == e["target"]: board[y][x] = ""
def update(self): self._pre_update() if self.updateDelay != 0: self.updateDelay -= 1 if self.card.health + self.changes["health"] <= 0: if not self.movePath and self.attackTarget == None: if self.updateDelay <= 0: self.kill() if self.schRender: self._render(self.schRenderSize) for event in v.events: # If the card is allowed to be interacted with if v.gameTurn != None and v.gameTurn["player"] == v.unid and self.alive(): # Begin dragging if self.hovered and event.type == py.MOUSEBUTTONDOWN and event.button == 1 and self.player == v.unid: self.drag = True self.dragPoint = (v.mouse_pos[0] - self.rect.x, v.mouse_pos[1] - self.rect.y) v.dragCard = self v.availableTiles = py.sprite.Group() # End Dragging if event.type == py.MOUSEBUTTONUP and event.button == 1 and self.drag: self.drag = False v.dragCard = None v.availableTiles = None self.preCard = [] self.postCard = [] # Card in hand if self.tile == None: if v.pMana >= self.card.cost: for tile in v.tiles: if tile.hovered: self.tile = tile if self.tile != None: v.pMana -= self.card.cost v.networkEvents.append({"type": "place", "id": self.card.id, "position": self.tile.pos, "unid": self.unid}) self._render((100, 140)) for card in v.gameCards: if card.tile == None: if card.order > self.order: card.order -= 1 # Card on board else: if v.hoverTile == None: pass # If a tile is being hovered else: # If the hovered tile isn't the current tile if v.hoverTile != self.tile: # If the hovered tile is attackable if v.hoverTile.attack: if self.range == 0: path = pathfind.pathfind((self.tile.pos[0] + 1, self.tile.pos[1]), (v.hoverTile.pos[0] + 1, v.hoverTile.pos[1]), pathfind.get_grid(skip=[v.hoverTile], castle=True)) path = [(p[0]-1, p[1]) for p in path] self.movePath = path[:-1] while self.movePath[-1][0] > 3 or self.movePath[-1][0] < -1: self.movePath = self.movePath[:-1] if len(path) < 2: print("Bad path length", path, self.movePath) pos = self.movePath[-1] for tile in v.tiles: if tile.pos == pos: self.tile = tile v.networkEvents.append({"type": "move", "unid": self.unid, "position": pos}) self.moves = 0 # If the target is another minion if v.hoverTile.castle == None: target = v.hoverTile.card v.networkEvents.append({"type": "damage", "unid": self.unid, "target": target.unid}) if self.range == 0: self.changes["health"] -= target.card.attack + target.changes["attack"] target.changes["health"] -= self.card.attack + self.changes["attack"] target.updateDelay += 20 self.updateDelay += 20 self.attackTarget = target if self.range == 0 and target.changes["health"] + target.card.health <= 0 and self.changes["health"] + self.card.health > 0: v.networkEvents.append({"type": "move", "unid": self.unid, "position": v.hoverTile.pos}) self.attackWon = True # If the target is a castle else: v.networkEvents.append({"type": "damage", "unid": self.unid, "target": v.opUnid}) v.opHealth -= self.card.attack + self.changes["attack"] self.attackTarget = "enemy" # If the hovered card isn't attackable else: path = pathfind.pathfind(self.tile.pos, v.hoverTile.pos, pathfind.get_grid(skip=[v.hoverTile])) self.movePath = path self.tile = v.hoverTile v.networkEvents.append({"type": "move", "unid": self.unid, "position": self.tile.pos}) self.moves -= len(path) - 1 if self.alive(): if self.moves <= 0: v.networkEvents.append({"type": "movable", "unid": self.unid, "movable": False}) else: v.networkEvents.append({"type": "movable", "unid": self.unid, "movable": True}) if self.tile == None: self._hand_update() else: self.rect = py.Rect((0, 0), (100, 140)) self.rimage = self.image.copy() if self.movePath: # and not (len(self.movePath) <= 1 and self.attackTarget != None) #if not (len(self.movePath) == 1 and self.attackTarget != None): self.move() else: self.rect.center = self.tile.rect.center if self.attackTarget != None: self.attack() if self.moves <= 0: self.rimage.fill((150, 150, 150), special_flags=py.BLEND_MULT) if self.drag and self.tile != None: self.preCard = [] self.postCard = [] if v.hoverTile != None and v.hoverTile != self.tile: if v.hoverTile.castle == None: path = pathfind.pathfind(self.tile.pos, v.hoverTile.pos, pathfind.get_grid(skip=[v.hoverTile])) else: path = pathfind.pathfind((self.tile.pos[0] + 1, self.tile.pos[1]), (v.hoverTile.pos[0] + 1, self.tile.pos[1]), pathfind.get_grid(skip=[v.hoverTile], castle=True)) path = [(p[0]-1, p[1]) for p in path] for i in range(len(path) - 1): arrowRect = py.Rect(0, 0, 100, 100) if path[i + 1][0] > path[i][0]: arrowRect.centery = 130 + path[i][1] * 150 arrowRect.left = 415 + path[i][0] * 150 + 50 rarrow = self.arrow.copy() if path[i + 1][0] < path[i][0]: arrowRect.centery = 130 + path[i][1] * 150 arrowRect.right = 415 + path[i][0] * 150 - 50 rarrow = py.transform.rotate(self.arrow, 180) if path[i + 1][1] > path[i][1]: arrowRect.centerx = 415 + path[i][0] * 150 arrowRect.top = 130 + path[i][1] * 150 + 50 rarrow = py.transform.rotate(self.arrow, -90) if path[i + 1][1] < path[i][1]: arrowRect.centerx = 415 + path[i][0] * 150 arrowRect.bottom = 130 + path[i][1] * 150 - 50 rarrow = py.transform.rotate(self.arrow, 90) self.preCard.append((rarrow, arrowRect)) if v.hoverTile.attack: drect = py.Rect(0, 0, 100, 100) drect.center = v.hoverTile.rect.center self.preCard.append((self.damage, drect)) font = py.font.Font("assets/fonts/Galdeano.ttf", 30) dmg = font.render(str(-self.card.attack), 1, (0, 0, 0)) drect = dmg.get_rect() drect.center = v.hoverTile.rect.center self.preCard.append((dmg, drect)) if v.hoverTile.castle == None and self.range == 0: target = v.hoverTile.card drect = py.Rect(0, 0, 100, 100) drect.center = self.tile.rect.center self.postCard.append((self.damage, drect)) font = py.font.Font("assets/fonts/Galdeano.ttf", 30) dmg = font.render(str(-target.card.attack), 1, (0, 0, 0)) drect = dmg.get_rect() drect.center = self.tile.rect.center self.postCard.append((dmg, drect)) if v.hoverTile == self.tile: self.rarrow = None if v.hoverTile == None: self.rarrow = None if self.opintro: self._opintro() self.draw()