Skip to content

Commit

Permalink
Added Queen Hero, Archers and Balloons
Browse files Browse the repository at this point in the history
  • Loading branch information
victorknox committed Apr 13, 2022
1 parent 8d60347 commit 8cb0d83
Showing 1 changed file with 206 additions and 83 deletions.
289 changes: 206 additions & 83 deletions src/characters.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import time
from time import *
from colorama import Fore, Back, Style, init
from numpy import character

init()
size = os.get_terminal_size()
Expand All @@ -9,7 +10,7 @@ class Character:
""" The Character class which stores basic details such as health, position, etc.
also stores basic methods such and unit movement, taking damage attacking the enemy """

def __init__(self, maxhealth, damage, position, ms, icon):
def __init__(self, maxhealth, damage, position, ms, icon, c_range, aoe = 0):
""" The Character class which stores basic details such as health, position, etc."""
self.health = maxhealth
self.maxhealth = maxhealth
Expand All @@ -18,78 +19,150 @@ def __init__(self, maxhealth, damage, position, ms, icon):
self.x = position[0]
self.y = position[1]
self.icon = icon
self.c_range = c_range
self.direction = "r"
self.aoe = aoe
self.aerial = False
self.content = [[Fore.BLUE + icon + Fore.RESET]*1 for tile in range(1)]


def unitmove(self, ip, board):
""" Unit move for any character, checks if the unit can move in the direction it is facing and if it can, moves it. """
if ip == 'w' and board.content[self.y-1][self.x] == ' ':
self.y -= 1
elif ip == 's' and board.content[self.y+1][self.x] == ' ':
self.y += 1
elif ip == 'a' and board.content[self.y][self.x-1] == ' ':
self.x -= 1
elif ip == 'd' and board.content[self.y][self.x+1] == ' ':
self.x += 1
# areal units ignore buildings and walls
if self.aerial:
if ip == 'w':
self.y -= 1
elif ip == 's':
self.y += 1
elif ip == 'a':
self.x -= 1
elif ip == 'd':
self.x += 1
else:
pass
if ip == 'w' and board.content[self.y-1][self.x] == ' ':
self.y -= 1
elif ip == 's' and board.content[self.y+1][self.x] == ' ':
self.y += 1
elif ip == 'a' and board.content[self.y][self.x-1] == ' ':
self.x -= 1
elif ip == 'd' and board.content[self.y][self.x+1] == ' ':
self.x += 1
else:
return -1
return 1

def automove(self, board, buildings):
""" Character automove method, checks for the closest building and moves towards it. """

# search for the closest building
closest = -1

def attack_enemy(self, buildings):
# aerial character movement
flag = False
if self.aerial:
for building in buildings:
if building.damage > 0:
flag = True
break

for building in buildings:
if flag and self.aerial:
if building.damage == 0:
continue
if building.iswall == False:
if closest == -1:
closest = building
else:
if abs(self.x - building.x) + abs(self.y - building.y) < abs(self.x - closest.x) + abs(self.y - closest.y):
closest = building
if closest == -1:
return
dist = self.distance_building(self.x, self.y, closest)
# move towards closest buiding
if dist > self.c_range:
if closest.x > self.x:
self.direction = "r"
self.move(buildings, "d", board)
elif closest.x < self.x:
self.direction = "l"
self.move(buildings, "a", board)
elif closest.y > self.y:
self.direction = "d"
self.move(buildings, "s", board)
elif closest.y < self.y:
self.direction = "u"
self.move(buildings, "w", board)
else:
self.attack_enemy(buildings)

def distance_building(self, x, y, building):
""" returns the distance between the unit and the building """
curr_dist = 10000
for i in range(building.length):
for j in range(building.height):
t = max(abs(x - building.x - i), abs(y - building.y - j))
if t < curr_dist:
curr_dist = t
return curr_dist


def attack_enemy(self, buildings, wall = 0):
""" Attack enemy method, checks if the unit can attack the enemy and if it can, attacks it. """
a_range = self.c_range
if wall == 1:
a_range = 1
for building in buildings:
if wall == 0:
if building.iswall == True:
continue
if self.direction == "r":
if(self.x + 1 == building.x and self.y <= building.y + building.height - 1 and self.y >= building.y):
building.attacked(self.damage)
if(self.x + a_range >= building.x and self.y <= building.y + building.height - 1 and self.y >= building.y):
building.attacked(self.damage, buildings)
elif self.direction == "l":
if(self.x - 1 == building.x + building.length - 1 and self.y <= building.y + building.height - 1 and self.y >= building.y):
building.attacked(self.damage)
if(self.x - a_range <= building.x + building.length - 1 and self.y <= building.y + building.height - 1 and self.y >= building.y):
building.attacked(self.damage, buildings)
elif self.direction == "u":
if(self.y - 1 == building.y + building.height - 1 and self.x <= building.x + building.length - 1 and self.x >= building.x):
building.attacked(self.damage)
if(self.y - a_range <= building.y + building.height - 1 and self.x <= building.x + building.length - 1 and self.x >= building.x):
building.attacked(self.damage, buildings)
elif self.direction == "d":
if(self.y + 1 == building.y and self.x <= building.x + building.length - 1 and self.x >= building.x):
building.attacked(self.damage)
if(self.y + a_range >= building.y and self.x <= building.x + building.length - 1 and self.x >= building.x):
building.attacked(self.damage, buildings)

def attacked(self, damage):

def attacked(self, damage, characters):
""" receives damage and updates the health accordingly """
self.health -= damage
if self.health <= 0:
self.destroy()
self.destroy(characters)
elif self.health <= self.maxhealth/4:
self.update_color(Fore.WHITE)
elif self.health <= self.maxhealth/2:
self.update_color(Fore.CYAN)
else:
self.update_color(Fore.BLUE)

def move(self, buildings, ip, board):
""" Character move method, checks if the character can move in the direction it is facing and if it can, moves it. """
val = self.unitmove(ip, board)
if val == -1:
self.attack_enemy(buildings, 1)

def destroy(self):
def destroy(self, characters):
""" removes the unit from the board """
self.content = [['' + Fore.RESET]*1 for tile in range(1)]
self.x = -1
self.y = -1
try:
characters.remove(self)
except:
pass


def update_color(self, color):
""" updates the color of the unit """
self.content = [[color + self.icon + Fore.RESET]*1 for tile in range(1)]



class King(Character):
""" King class, inherits from Character class """

def __init__(self):
""" initialize the king with basic details """
health = 1000
damage = 30
position = (1, 1)
ms = 1
icon = '┼'
super().__init__(health, damage, position, ms, icon)

class Hero(Character):
""" Hero class, inherits from Character class. """
def move(self, ip, board):
""" King move method, checks if the king can move in the direction it is facing and if it can, moves it. """
""" Hero move method, checks if the hero can move in the direction it is facing and if it can, moves it. """
if ip == 'w':
self.direction = "u"
elif ip == 's':
Expand All @@ -103,64 +176,113 @@ def move(self, ip, board):
self.unitmove(ip, board)
ms -= 1

def axe_attack(self, buildings):
def attack_enemy(self, buildings):
""" Attack enemy method, checks if the unit can attack the enemy and if it can, attacks it. """
x = self.x
y = self.y
if self.direction == "r":
x += self.c_range
elif self.direction == "l":
x -= self.c_range
elif self.direction == "u":
y -= self.c_range
elif self.direction == "d":
y += self.c_range

for building in buildings:
dist = self.distance_building(x,y,building)
if dist <= self.aoe:
building.attacked(self.damage, buildings)

class King(Hero):
""" King class, inherits from Character and Hero class """

def __init__(self):
""" initialize the king with basic details """
health = 1000
damage = 30
position = (1, 1)
ms = 1
c_range = 1
aoe = 0
icon = '┼'
super().__init__(health, damage, position, ms, icon, c_range, aoe)

def special_attack(self, buildings):
""" Axe attack method, attacks any building withing the radius of the attack range. """
attack_range = 3
for building in buildings:
for i in range(-attack_range, attack_range):
for j in range(-attack_range, attack_range):
if(self.x + i <= building.x + building.length - 1 and self.x + i >= building.x):
if(self.y + j <= building.y + building.height - 1 and self.y + j >= building.y):
building.attacked(self.damage)
building.attacked(self.damage, buildings)

class Queen(Hero):
""" Queen class, inherits from Character and Hero class """
def __init__(self):
""" initialize the queen with basic details """
health = 1000
damage = 20
position = (1, 1)
ms = 1
c_range = 8
aoe = 2
icon = 'q'
super().__init__(health, damage, position, ms, icon, c_range, aoe)

def special_attack(self, buildings):
""" Eagle arrow method, attacks in a range with AOE damage. """
self.c_range = 16
self.aoe = 4
self.attack_enemy(buildings)
self.c_range = 8
self.aoe = 2

class Barbarian(Character):
""" Barbarian class, inherits from Character class """

def __init__(self, position):
""" initialize the barbarian with basic details """
health = 300
damage = 1
damage = 2
ms = 1
icon = '¥'
super().__init__(health, damage, position, ms, icon)

def automove(self, board, buildings):
""" Barbarian automove method, checks for the closest building and moves towards it. """
c_range = 1
super().__init__(health, damage, position, ms, icon, c_range)

# search for the closest building
closest = -1

class Archer(Character):
""" Archer class, inherits from Character class """

def __init__(self, position):
""" initialize the archer with basic details """
health = 150
damage = 1
ms = 2
c_range = 5
icon = '⚔'
super().__init__(health, damage, position, ms, icon, c_range)


class Baloon(Character):
""" Baloon class, inherits from Character class """

def __init__(self, position):
""" initialize the baloon with basic details """
health = 300
damage = 4
ms = 2
c_range = 0
icon = 'o'
super().__init__(health, damage, position, ms, icon, c_range)
self.aerial = True

def attack_enemy(self, buildings):
for building in buildings:
if building.iswall == False:
if closest == -1:
closest = building
else:
if abs(self.x - building.x) + abs(self.y - building.y) < abs(self.x - closest.x) + abs(self.y - closest.y):
closest = building

# move towards closest buiding
if closest.x > self.x:
self.direction = "r"
self.move("d", board)
elif closest.x < self.x:
self.direction = "l"
self.move("a", board)
elif closest.y > self.y:
self.direction = "d"
self.move("s", board)
elif closest.y < self.y:
self.direction = "u"
self.move("w", board)
else:
pass
self.attack_enemy(buildings)
if self.distance_building(self.x, self.y, building) <= self.c_range:
building.attacked(self.damage, buildings)

def move(self, ip, board):
""" Barbarian move method, checks if the barbarian can move in the direction it is facing and if it can, moves it. """
ms = self.ms
while(ms > 0):
self.unitmove(ip, board)
ms -= 1

class Wallbreaker(Character):
""" Wallbreaker class, inherits from Character class """
Expand Down Expand Up @@ -199,16 +321,16 @@ def automove(self, board, buildings):
# move towards closest wall
if closest.x > self.x:
self.direction = "r"
self.move("d", board)
self.move(buildings, "d", board)
elif closest.x < self.x:
self.direction = "l"
self.move("a", board)
self.move(buildings, "a", board)
elif closest.y > self.y:
self.direction = "d"
self.move("s", board)
self.move(buildings, "s", board)
elif closest.y < self.y:
self.direction = "u"
self.move("w", board)
self.move(buildings, "w", board)
else:
pass
for building in buildings:
Expand All @@ -223,3 +345,4 @@ def move(self, ip, board):
while(ms > 0):
self.unitmove(ip, board)
ms -= 1

0 comments on commit 8cb0d83

Please sign in to comment.