Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modularising #4

Open
wants to merge 1 commit into
base: feat/mapGen
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pytest = "*"
[packages]
opensimplex = "*"
colorama = "*"
atomicwrites = "*"

[requires]
python_version = "3.8"
26 changes: 25 additions & 1 deletion Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

```
PIPENV_VENV_IN_PROJECT=1
pipenv install
pipenv sync

pipenv run <someCommand>

pipenv shell
```

5 changes: 5 additions & 0 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .actions import Actions
from .entities import Ant, Base, Food
from .field import Field, FieldType
from .gameBoard import GameBoard
from .gameServer import Server
File renamed without changes.
4 changes: 4 additions & 0 deletions entities/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .ant import Ant
from .attackable import Attackable
from .base import Base
from .food import Food
7 changes: 2 additions & 5 deletions main_package/fieldEntities/ant.py → entities/ant.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import main_package.field as field
from main_package.fieldEntities.food import Food
from main_package.interfaces.attackable import Attackable

from .attackable import Attackable
from .food import Food

class Ant(Attackable):

Expand All @@ -14,7 +12,6 @@ def __init__(self, antId: str, playerName: str):
self.attackDamage: int = 1 # the damage the ant inflicts per attack
self._foodUptakeSpeed: int = 2 # how much food the ant acquires per feed action
self.movementEfficiency: int = 2 # TODO how many fields the ant can move before using 1 food, not yet implemented
self.fieldPosition: field.Field = None

def getFoodUptakeValue(self):
"""
Expand Down
File renamed without changes.
4 changes: 1 addition & 3 deletions main_package/fieldEntities/base.py → entities/base.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import main_package.field as field
from main_package.interfaces.attackable import Attackable
from .attackable import Attackable


class Base(Attackable):

def __init__(self, player: str):
Attackable.__init__(self, 100)
self.fieldPosition: field.Field = None
self.player = player
self.health = 100 # placeholder
4 changes: 0 additions & 4 deletions main_package/fieldEntities/food.py → entities/food.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import main_package.field as field

class Food:

def __init__(self, magnitude: int):
self.foodMagnitude = magnitude
self.fieldPosition: field.Field = None

def getFood(self, magnitude) -> int:
if magnitude >= self.foodMagnitude:
returnVal = self.foodMagnitude
self.foodMagnitude = 0
self.fieldPosition.resetToEmpty()
self.fieldPosition = None
return returnVal
else:
self.foodMagnitude -= magnitude
Expand Down
20 changes: 9 additions & 11 deletions main_package/field.py → field.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
import logging
from typing import Tuple

import main_package.fieldEntities.ant as ant
import main_package.fieldEntities.food as food
import main_package.fieldEntities.base as base
from hive import Ant, Base, Food
from colorama import init, Fore

init()
logging.basicConfig(level=logging.INFO)

class FieldTypeEnum(Enum):
class FieldType(Enum):
BASE = Fore.RED + "B"
ANT = Fore.BLUE + "A"
FOOD = Fore.GREEN + "F"
Expand All @@ -27,7 +25,7 @@ class FieldTypeEnum(Enum):
class Field:
log = logging.getLogger(__name__)

def __init__(self, xpos:int, ypos:int, type: FieldTypeEnum):
def __init__(self, xpos:int, ypos:int, type: FieldType):
self.xpos = xpos
self.ypos = ypos
self.emptyType = type
Expand All @@ -45,12 +43,12 @@ def setEntity(self, entity) -> bool:
if self.entity is not None:
self.log.error("Cannot set entity on field that is {} instead of empty".format(self.type))
return False
if isinstance(entity, ant.Ant):
self.type = FieldTypeEnum.ANT
elif isinstance(entity, food.Food):
self.type = FieldTypeEnum.FOOD
elif isinstance(entity, base.Base):
self.type = FieldTypeEnum.BASE
if isinstance(entity, Ant):
self.type = FieldType.ANT
elif isinstance(entity, Food):
self.type = FieldType.FOOD
elif isinstance(entity, Base):
self.type = FieldType.BASE
else:
self.log.error("Entity is of unknown type. Cannot set field type.")
return False
Expand Down
31 changes: 15 additions & 16 deletions main_package/gameBoard.py → gameBoard.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
from typing import Tuple, List, Set
from main_package.fieldEntities.ant import Ant
from main_package.field import *
from main_package.mapGenerator import *
from main_package.fieldEntities.base import Base
from main_package.fieldEntities.food import Food
from main_package.interfaces.attackable import Attackable
from hive.entities import Attackable, Ant, Base, Food
from .field import Field, FieldType
from .mapGenerator import MapGenerator

import logging

logging.basicConfig(level=logging.INFO)


class gameBoard:
class GameBoard:
log = logging.getLogger(__name__)
validForAttack = [FieldTypeEnum.ANT, FieldTypeEnum.BASE]
validForAttack = [FieldType.ANT, FieldType.BASE]

def __init__(self, xdim: int = 50, ydim: int = 40):
"""
Expand Down Expand Up @@ -52,7 +51,7 @@ def createBase(self, xpos: int, ypos: int, player: str) -> bool:

# field where base is placed must be empty
field = self.getField(xpos, ypos)
if field.type != FieldTypeEnum.GRASS:
if field.type != FieldType.GRASS:
logging.error("Base cannot be placed on field that is not grass. Field is {}".format(field.type))
return False

Expand Down Expand Up @@ -130,15 +129,15 @@ def createAnt(self, xpos: int, ypos: int, antId: str, player: str) -> bool:
# placement checks
placementDesitnation: Field = self.getField(xpos, ypos)
neighbouring_fields: List[Field] = self.getNeighbouringFields(placementDesitnation)
if not any(f.type == FieldTypeEnum.BASE for f in neighbouring_fields):
if not any(f.type == FieldType.BASE for f in neighbouring_fields):
self.log.error("Invalid Placement, no adjacent base")
return False
elif placementDesitnation.type is not FieldTypeEnum.GRASS:
elif placementDesitnation.type is not FieldType.GRASS:
self.log.error("Invalid Placement, field not grass")
return False

# check if player owns base near which they want to place ant
base: Base = next(filter(lambda x: x.type == FieldTypeEnum.BASE, neighbouring_fields)).entity
base: Base = next(filter(lambda x: x.type == FieldType.BASE, neighbouring_fields)).entity
if base.player != player:
self.log.error("Player {} does not own the adjacent base".format(player))
return False
Expand All @@ -159,7 +158,7 @@ def moveAnt(self, antId: str, xpos: int, ypos: int) -> bool:
ant = self.ants[antId]
# determine valid fields for movement
fields = self.getNeighbouringFields(ant.fieldPosition)
validFields = filter(lambda x: x.type != FieldTypeEnum.ROCK, fields)
validFields = filter(lambda x: x.type != FieldType.ROCK, fields)

# is movement valid ?
fieldToMoveTo: Field = None
Expand Down Expand Up @@ -192,7 +191,7 @@ def attack(self, antId: str, xpos: int, ypos: int) -> bool:
if fieldToAttack not in neighbouringFields:
self.log.error("The field {} is not in range of ant {}".format((xpos, ypos), antId))
return False
if fieldToAttack.type not in gameBoard.validForAttack:
if fieldToAttack.type not in GameBoard.validForAttack:
self.log.error("The field {} is not a valid attack target for ant {}".format((xpos, ypos), antId))
return False
target: Attackable = fieldToAttack.entity # TODO: might need "attackable" interface later
Expand Down Expand Up @@ -234,7 +233,7 @@ def getBase(self, playerName: str) -> Base or None:

def createFood(self, xpos: int, ypos: int, magnitude: int) -> bool:
targetField = self.getField(xpos, ypos)
if targetField is None or targetField.type is not FieldTypeEnum.GRASS:
if targetField is None or targetField.type is not FieldType.GRASS:
self.log.error("Invalid target ({},{}) for placing food.".format(xpos, ypos))
return False
if magnitude <= 0 or magnitude != magnitude: # test for negative or nan
Expand All @@ -256,7 +255,7 @@ def feed(self, antId: str, targetXpos: int, targetYpos: int) -> bool:
self.log.error("Ant with id {} is not in range of targeted field ({},{})".format(antId, targetXpos, targetYpos))
return False
# check if field is food
if targetField.type != FieldTypeEnum.FOOD:
if targetField.type != FieldType.FOOD:
self.log.error("Ant with id {} tried to feed on a non food field ({},{})".format(antId,targetXpos,targetYpos))
return False
# ants have a food capacity and feeding speed value
Expand Down
3 changes: 1 addition & 2 deletions main_package/gameServer.py → gameServer.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import json
import uuid

from main_package.actions import Actions

from .actions import Actions

class Server:

Expand Down
4 changes: 2 additions & 2 deletions main_package/main.py → main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from main_package.gameBoard import gameBoard
from .world import GameBoard
import sys

if __name__ == '__main__':
print(sys.path)
server = gameBoard()
server = GameBoard()
print(server.getBoardString())
Empty file.
Empty file.
22 changes: 11 additions & 11 deletions main_package/mapGenerator.py → mapGenerator.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from main_package.field import *
from .field import Field, FieldType
from opensimplex import OpenSimplex

class MapGenerator:
Expand Down Expand Up @@ -30,30 +30,30 @@ def __init__(self, width: int, height: int):
self.noiseGenerator = OpenSimplex()
self.map = self.createMap()

def getTerrain(self, elevation: int, moisture: int) -> FieldTypeEnum:
def getTerrain(self, elevation: int, moisture: int) -> FieldType:
e = elevation * 100 # elevation [0, 100]
m = moisture * 100 # moisture [0, 100]

if (e < self.waterMaxElevation / 3):
return FieldTypeEnum.DEEP_WATER
return FieldType.DEEP_WATER
if (e < self.waterMaxElevation):
return FieldTypeEnum.WATER
return FieldType.WATER
if (e < self.waterMaxElevation + self.sandMaxElevation):
return FieldTypeEnum.SAND
return FieldType.SAND

if (e > self.rockMinElevation):
return FieldTypeEnum.ROCK
return FieldType.ROCK
if (e > self.rockMinElevation - self.sandMaxElevation):
return FieldTypeEnum.TALL_GRASS
return FieldType.TALL_GRASS

if (m < self.grassMinMoisture):
return FieldTypeEnum.DRY_GRASS
return FieldType.DRY_GRASS
if (e < self.forestMaxElevation and m > self.forestMinMoisture and m < self.forestMaxMoisture):
return FieldTypeEnum.FOREST
return FieldType.FOREST
if (e > self.tallGrassMinElevation and m > self.tallGrassMinMoisture):
return FieldTypeEnum.TALL_GRASS
return FieldType.TALL_GRASS

return FieldTypeEnum.GRASS
return FieldType.GRASS

def createMap(self):
map = []
Expand Down
File renamed without changes.
Loading