Skip to content

Commit

Permalink
updated the readme and deleted cache
Browse files Browse the repository at this point in the history
  • Loading branch information
victorknox committed Apr 13, 2022
1 parent 212373f commit 63e5904
Show file tree
Hide file tree
Showing 27 changed files with 158 additions and 63 deletions.
29 changes: 21 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Clash-of-Cans
# Clash-of-Clans
A python game similar to clash of clans
Built from scratch in Python using principles of Object Oriented Programming such as Inheritance, Polymorphism, Encapsulation, and Abstraction.

Expand All @@ -7,9 +7,12 @@ To play the game, run
``` python game.py```

- press q to quit the game.
- press w,a,s,d to control the King.
- press p, o, i to spawn barbarians in the spawn points displayed.
- press u to spawn a wallbreaker
- press w,a,s,d to control the Hero(King or Queen).
- press any key from 1 to 9 to spawn troops in the spawn points displayed.
- 1 to 3 spawn barbarians in 3 different spawn points
- 4-6 spawn archers
- 7-9 spawn balloons

- press r to use the rage spell
- press h to use the heal spell

Expand All @@ -19,11 +22,21 @@ To watch the replay of a game, run

# Instructions

- The game starts with a village with few buildings, namely the Townhall, Huts, Cannons and walls surrounding them.
- The objective is to destroy the village using your army, which consists of a King and Troops such as Barbarians and wallbreakers.
- The game starts with a village with few buildings, namely the Townhall, Huts, Cannons, Wizard Towers and walls surrounding them.
- Cannon: defensive building which attacks any troop which is on the ground.
- Wizard Tower: defensive building which can attack even aerial troops like balloons, also does AOE damage.
- The objective is to destroy the village using your army, which consists of a Hero (King or Queen, you can choose!) and Troops such as Barbarians, Archers and Balloons.
- There are three levels in the game, each with more number of defensive buildings.
- Use one of the spawn points to deploy your troops.
- there are two kinds of troops, Barbarians and wallbreakers, barbarians attack any building they come in contact with, wallbreakers blast only walls, and also die in the process.
- The King can be controlled using the WASD keys, use space bar to attack any single building, and use e for an AOE attack which attacks any building within a radius of 3 tiles from the king.
- there are four kinds of troops, Barbarians, Archers, Balloons and WallBreakers
- barbarians attack any building they come in contact with
- wallbreakers blast only walls, and also die in the process.
- archers can attack with a range, like outside of walls
- The Hero can be controlled using the WASD keys, use space bar to use a normal attack and 'e' for a special attack. Player can choose between King and Queen at the beginning of a game.
- King : normal attack is similar to barbarian where he attacks a single building with his sword, special attack is an AOE axe attack which damages buildings around him.
- Queen: normal attack is an AOE attack which deals damage to buildings at a distance in which the Queen is facing, special attack is also an AOE attack with much more range and damage radius, which is executed with a 1 second delay due to its charging up.
- There are two spells:
- rage, which makes your troops and king faster and stronger.
- heal, which heals your troops and king.


Binary file removed __pycache__/Board.cpython-39.pyc
Binary file not shown.
Binary file removed __pycache__/Building.cpython-39.pyc
Binary file not shown.
Binary file removed __pycache__/input.cpython-39.pyc
Binary file not shown.
3 changes: 0 additions & 3 deletions game.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import os
import random
from src.utils import *

def main():

Game()

if __name__ == "__main__":
Expand Down
Binary file removed replays/110320222230.pkl
Binary file not shown.
Binary file removed replays/110320222242.pkl
Binary file not shown.
Binary file removed replays/110320222245.pkl
Binary file not shown.
Binary file removed replays/110320222253.pkl
Binary file not shown.
Binary file removed replays/110320222259.pkl
Binary file not shown.
Binary file removed replays/110320222315.pkl
Binary file not shown.
Binary file removed replays/110320222316.pkl
Binary file not shown.
Binary file removed replays/110320222344.pkl
Binary file not shown.
Binary file removed replays/110320222346.pkl
Binary file not shown.
Binary file removed replays/110320222347.pkl
Binary file not shown.
Binary file removed replays/110320222348.pkl
Binary file not shown.
Binary file removed replays/110320222349.pkl
Binary file not shown.
Binary file removed replays/110320222351.pkl
Binary file not shown.
Binary file removed replays/140320221445.pkl
Binary file not shown.
Binary file removed src/__pycache__/board.cpython-310.pyc
Binary file not shown.
Binary file removed src/__pycache__/building.cpython-310.pyc
Binary file not shown.
Binary file removed src/__pycache__/characters.cpython-310.pyc
Binary file not shown.
Binary file removed src/__pycache__/input.cpython-310.pyc
Binary file not shown.
Binary file removed src/__pycache__/spells.cpython-310.pyc
Binary file not shown.
Binary file removed src/__pycache__/utils.cpython-310.pyc
Binary file not shown.
23 changes: 12 additions & 11 deletions src/board.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ def clear(self):
self.content[2][2] = Fore.YELLOW + 'I' + Fore.RESET
self.content[22][70] = Fore.YELLOW + 'O' + Fore.RESET
self.content[2][70] = Fore.YELLOW + 'P' + Fore.RESET
self.content[22][2] = Fore.YELLOW + 'U' + Fore.RESET


def display(self):
" displays the board "
Expand All @@ -50,22 +48,25 @@ def update(self, buildings, characters):
for character in characters:
self.content[character.y][character.x: character.x + 1] = character.content[0]

# updating king's health bar
self.content[1][self.width-13]='K'
# updating Hero's health bar
self.content[1][self.width-13]='H'
self.content[1][self.width-12]=':'
for i in range(math.floor(characters[0].health/100)):
self.content[1][self.width-11+i]= Fore.CYAN + '■' + Fore.RESET

# updating the troops left
# updating the troops on board
self.content[1][self.width-25]='T'
self.content[1][self.width-24]=':'
self.content[1][self.width-23]= str(21 - len(characters))
self.content[1][self.width-23]= str(len(characters))

# canons attacking enemies
# defensive buildings attacking enemies
for building in buildings:
if(isinstance(building, Cannon)):
building.attack_enemy(characters)

# calling barbarians' automated movement
building.attack_enemy(buildings, characters)
elif(isinstance(building, WizardTower)):
building.attack_enemy(buildings, characters)

# calling all characters' automated movement
for character in characters[1:]:
character.automove(self, buildings)
for i in range(character.ms):
character.automove(self, buildings)
166 changes: 125 additions & 41 deletions src/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import pickle
from time import *
from datetime import datetime
from src.building import *
from src.characters import *
Expand All @@ -9,63 +10,115 @@
import copy


class Game:
class Game():
""" The Game class containing the main game loop, methods for initializing the game and ending the game """
def __init__(self):
def __init__(self,level = 1):
" Initialize the required objects for the game "
self.board = Board()
self.king = King()
self.hero = King()
self.buildings = []
self.characters = []
self.barb_limit = 20
self.barbarian_limit = 6
self.archer_limit = 6
self.balloon_limit = 3
self.barbarians = 0
self.archers = 0
self.balloons = 0
self.boards = []
self.input = input_to()
self.level = level
self.qattack = 0
self.init_game()
self.run_game()

def init_game(self):
" Initialize the game with the village and characters required at the starting point"
# Initialize buildings, this defines the village structure at the beginning of game
self.buildings = [TownHall((40, 12)), Hut((20, 18)), Hut((40, 10)), Hut((20, 15)), Hut((60, 10)), Hut((30, 18)), Hut((40, 18)), Cannon((20, 10)), Cannon((60, 16))]

# Initialize buildings, this defines the village structure at the beginning of game, More buildings are added per level
self.buildings = [TownHall((40, 12)), Hut((20, 18)), Hut((20, 16)), Hut((22, 18)), Hut((22, 16)), Hut((20, 19)), Hut((22, 19)), Cannon((35, 12)), Cannon((60, 16)), WizardTower((20, 10)), WizardTower((47, 12))]
if self.level == 2:
self.buildings.append(WizardTower((60, 12)))
self.buildings.append(Cannon((47, 18)))
if self.level == 3:
self.buildings.append(WizardTower((60, 12)))
self.buildings.append(WizardTower((35, 16)))
self.buildings.append(Cannon((47, 16)))
self.buildings.append(Cannon((22, 14)))

# Initialize walls
for x in range(15, 66):
self.buildings.append(Wall((x, 8)))
self.buildings.append(Wall((x, 20)))
for y in range(8, 21):
self.buildings.append(Wall((15, y)))
self.buildings.append(Wall((65, y)))
# Initialize the King
self.characters = [self.king]

# Initialize the Hero, player gets to choose between King and Queen
if self.level == 1:
while(1):
h = input("Enter k for King, q for Queen: ")
if h == "k":
break
elif h == "q":
self.hero = Queen()
break
else:
print("Incorrect input")
self.characters = [self.hero]
self.board.update(self.buildings, self.characters)


def check_win(self):
def check_loss(self):
# Declare it a loss if all the characters on the board are dead
win = True
loss = True
for character in self.characters:
if(character.health > 0):
win = False
if(win):
loss = False
if(loss):
print("Defeat!")
self.save_game()
exit()

def check_loss(self):
def check_win(self):
# Declare it a win if all the buildings on the board are destroyed.
loss = True
win = True
for building in self.buildings:
if(building.iswall == False):
if(building.health > 0):
loss = False
if(loss):
print("Victory!")
self.save_game()
exit()
win = False
if(win):
return 1
else:
return 0

def end_game(self):
# check if the game is over
self.check_win()
"""Checks if the round or game is over, if the round is won, player proceeds to next round."""

self.check_loss()
# if previous round is won, move to next round
if self.check_win() == 1:
if self.level <= 2:
print("Victory!\n Next Round")
sleep(3)
self.level += 1
self.board = Board()
self.buildings = []
self.characters = []
self.barbarian_limit = 6
self.archer_limit = 6
self.balloon_limit = 3
self.barbarians = 0
self.archers = 0
self.balloons = 0
self.boards = []
self.hero.health = self.hero.maxhealth
self.input = input_to()
self.init_game()
self.run_game()

else:
print("You have won the game!")
exit()


def save_game(self):
# save the game to a pickle file, which contains all the instances of the board and characters
Expand Down Expand Up @@ -93,30 +146,61 @@ def run_game(self):
self.save_game()
exit()

# King moves
# Hero moves
if(ip == 's' or 'w' or 'a' or 'd'):
self.king.move(ip, self.board)
self.hero.move(ip, self.board)

# King attacks the building in front of him
# Hero attacks the building in front of them
if(ip == ' '):
self.king.attack_enemy(self.buildings)
self.hero.attack_enemy(self.buildings)

# Hero uses the special attack

# In case of the queens attack, there's a time delay before the attack is executed
if(self.qattack >= time() - 1):
self.hero.special_attack(self.buildings)
self.qattack = 0

# King uses the axe attack
if (ip == 'e'):
self.king.axe_attack(self.buildings)

# spawn a barbarian at the respective spawn point
if (ip == 'p' or 'i' or 'o' or 'u'):
# spawn points are (2, 2), (22, 70), (2, 70) and (22, 2) (last one spawns a wallbreaker)
if(len(self.characters ) < self.barb_limit + 1):
if(ip == 'i'):
self.characters.append(Barbarian((2, 2)))
if(ip == 'o'):
self.characters.append(Barbarian((70, 22)))
if(ip == 'p'):
self.characters.append(Barbarian((70, 2)))
if(ip == 'u'):
self.characters.append(Wallbreaker((2, 22)))
if isinstance(self.hero, King):
self.hero.special_attack(self.buildings)
elif isinstance(self.hero, Queen) and self.qattack == 0:
self.qattack = time()

# spawn a troop at the respective spawn point
if (ip == '1' or '2' or '3' or '4' or '5' or '6' or '7' or '8' or '9'):
# spawn points are (2, 2), (70, 22), (70, 2), they can be accessed through the numbers 1 to 9
p1 = (2, 2)
p2 = (70, 22)
p3 = (70, 2)
if(len(self.characters ) <= self.barbarian_limit + self.archer_limit + self.balloon_limit):
if(ip == '1' and self.barbarians < self.barbarian_limit):
self.characters.append(Barbarian(p1))
self.barbarians += 1
if(ip == '2' and self.barbarians < self.barbarian_limit):
self.characters.append(Barbarian(p2))
self.barbarians += 1
if(ip == '3' and self.barbarians < self.barbarian_limit):
self.characters.append(Barbarian(p3))
self.barbarians += 1
if(ip == '4' and self.archers < self.archer_limit):
self.characters.append(Archer(p1))
self.archers += 1
if(ip == '5' and self.archers < self.archer_limit):
self.characters.append(Archer(p2))
self.archers += 1
if(ip == '6' and self.archers < self.archer_limit):
self.characters.append(Archer(p3))
self.archers += 1
if(ip == '7' and self.balloons < self.balloon_limit):
self.characters.append(Baloon(p1))
self.balloons += 1
if(ip == '8' and self.balloons < self.balloon_limit):
self.characters.append(Baloon(p2))
self.balloons += 1
if(ip == '9' and self.balloons < self.balloon_limit):
self.characters.append(Baloon(p3))
self.balloons += 1
else:
pass

Expand Down

0 comments on commit 63e5904

Please sign in to comment.