def __doEnemyDebugActions(self, quadrant: Quadrant): if self._gameSettings.debugAddKlingons is True: numKlingons: int = self._gameSettings.debugKlingonCount for x in range(numKlingons): klingon: Klingon = quadrant.addKlingon() self.klingonList.append(klingon) self._gameState.remainingKlingons += numKlingons if self._gameSettings.debugAddCommanders is True: nCommanders: int = self._gameSettings.debugCommanderCount for x in range(nCommanders): commander: Commander = quadrant.addCommander() self.commanderList.append(commander) self._gameState.remainingCommanders += nCommanders if self._gameSettings.debugAddSuperCommanders: nSuperCommanders: int = self._gameSettings.debugSuperCommanderCount for x in range(nSuperCommanders): superCommander: SuperCommander = quadrant.addSuperCommander() self.superCommanderList.append(superCommander) self._gameState.remainingSuperCommanders += nSuperCommanders
def impulse(self, newCoordinates: Coordinates, quadrant: Quadrant, enterprise: Enterprise): """ Args: newCoordinates: The new sector coordinates quadrant: The current quadrant travel was in enterprise: The enterprise sprite """ travelDistance: float = self._computer.computeQuadrantDistance( self._gameState.currentSectorCoordinates, newCoordinates) quadrant.placeEnterprise(enterprise, newCoordinates) self._gameState.currentSectorCoordinates = newCoordinates self.updateTimeAfterImpulseTravel(travelDistance=travelDistance) if self._gameState.energy < self._gameSettings.minimumImpulseEnergy: neededEnergyForImpulseMove = self._gameState.energy else: neededEnergyForImpulseMove = self.computeEnergyForQuadrantTravel( travelDistance=travelDistance) self._gameState.energy = self._gameState.energy - neededEnergyForImpulseMove self._gameState.opTime = travelDistance / 0.095
def _decrementEnemyCount(self, quadrant: Quadrant, enemyName: str): """ Decrement the appropriate enemy count Args: quadrant: A randomly generated quadrant enemyName: The enemy name, 'Klingon', 'Commander', 'SuperCommander' I normally don't like to write dynamically generated codes like this. However, I could not in good conscience duplicate this code three times; I know it is very 'Pythonic', but very high maintenance """ gsPropertyName: str = f'remaining{enemyName}s' qPropertyName: str = f'{enemyName[0].lower()}{enemyName[1:]}s' enemies: Enemies = getattr(quadrant, qPropertyName) for enemy in enemies: quadrant.decrementEnemyCount(enemy) remainingEnemyCount: int = getattr(self._gameState, gsPropertyName) remainingEnemyCount -= 1 assert remainingEnemyCount >= 0, f'{enemyName=} Logic error; Fix it !' setattr(self._gameState, gsPropertyName, remainingEnemyCount) enemyCount: int = len(enemies) if enemyCount > 1: message: str = f'{len(enemies)} {enemyName}s destroyed' else: message = f'{len(enemies)} {enemyName} destroyed' if enemyCount > 0: self.logger.debug(f'{message}') self._messageConsole.displayMessage(message)
def _handleTorpedoHits(self, quadrant: Quadrant): enemies: Enemies = Enemies([]) enemies.extend(quadrant.klingons) enemies.extend(quadrant.commanders) enemies.extend(quadrant.superCommanders) enterprise: Enterprise = quadrant.enterprise for badGuy in enemies: enemy: Enemy = cast(Enemy, badGuy) if enemy.power > 0: expendedTorpedoes: List[ Sprite] = check_for_collision_with_list( sprite=enemy, sprite_list=self._torpedoes) for sprite in expendedTorpedoes: killerTorpedo: PhotonTorpedo = cast(PhotonTorpedo, sprite) self.logger.info(f'{killerTorpedo.id} hit') self.__doExplosion(killerTorpedo) killerTorpedo.remove_from_sprite_lists() self.__damageOrKillEnemy(enterprise, enemy) quadrant.removeDeadEnemies()
def _doDebugActions(self, quadrant: Quadrant): self.__doEnemyDebugActions(quadrant=quadrant) if self._gameSettings.debugAddPlanet is True: quadrant.addPlanet() if self._gameSettings.debugAddStarBase is True: quadrant.addStarBase()
def _doBlockedImpulseMove(self, quadrant: Quadrant, enterpriseCoordinates: Coordinates, results: LineOfSightResponse): """ Handle an impulse move where the Enterprise was blocked by an obstacle Args: quadrant: The current quadrant enterpriseCoordinates: Then enterprise sector coordinates results: The results from the line of sight query """ self._messageConsole.displayMessage(f'Destination is blocked by: {results.obstacle.id}') self._soundMachine.playSound(SoundType.PleaseRepeatRequest) baseGamePiece: BaseGamePiece = cast(BaseGamePiece, results.obstacle) blockerCoordinates: Coordinates = baseGamePiece.gameCoordinates stopEnergy: float = self._gameEngine.computeEnergyWhenBlocked(startSector=enterpriseCoordinates, endSector=blockerCoordinates) self._gameState.energy -= stopEnergy directionData: DirectionData = self._determineCloseCoordinatesToBlockedObject(quadrant=quadrant, targetCoordinates=blockerCoordinates) self.logger.info(f'Move Enterprise to: {directionData.coordinates}') self.__updateQuadrant(quadrant=quadrant, currentCoordinates=enterpriseCoordinates, targetCoordinates=directionData.coordinates) quadrant.enterprise.inMotion = True quadrant.enterpriseCoordinates = directionData.coordinates self._gameEngine.impulse(newCoordinates=directionData.coordinates, quadrant=quadrant, enterprise=quadrant.enterprise) self._soundMachine.playSound(SoundType.EnterpriseBlocked)
def _killEnemy(self, quadrant: Quadrant, enemy: Enemy): """ Remove enemy from board and update the game engine Args: enemy: The "whacked" bad dude """ deadMsg: str = f'Enemy at {enemy.gameCoordinates} destroyed' self._messageConsole.displayMessage(deadMsg) self.logger.info(deadMsg) self._gameEngine.decrementEnemyCount(enemy=enemy) quadrant.decrementEnemyCount(enemy=enemy) sprite: Sprite = cast(Sprite, enemy) sprite.remove_from_sprite_lists()
def __placeMissInQuadrant(self, quadrant: Quadrant, sectorCoordinates: Coordinates, sectorType: SectorType): sector: Sector = quadrant.getSector(sectorCoordinates) sector.type = sectorType
def enterQuadrant(self, quadrant: Quadrant, enterprise): currentSectorCoordinates: Coordinates = self._intelligence.generateSectorCoordinates( ) if self._gameSettings.debugManualPlaceShipInQuadrant is True: currentSectorCoordinates = self._gameSettings.manualSectorCoordinates playerList: SpriteList = SpriteList() playerList.append(enterprise) self._gameState.currentSectorCoordinates = currentSectorCoordinates quadrant.placeEnterprise(enterprise, currentSectorCoordinates) self.playerList = playerList # Don't do this until we have set up the current quadrant self._makeEnemySpriteLists(quadrant=quadrant) self._doDebugActions(quadrant=quadrant)
def __updateQuadrant(self, quadrant: Quadrant, currentCoordinates: Coordinates, targetCoordinates: Coordinates) -> Quadrant: """ Args: quadrant: What we are updating currentCoordinates: Where we are targetCoordinates: Where we are going Returns: The updated input quadrant """ currentSector: Sector = quadrant.getSector(currentCoordinates) targetSector: Sector = quadrant.getSector(targetCoordinates) currentSector.type = SectorType.EMPTY targetSector.type = SectorType.ENTERPRISE targetSector.sprite = currentSector.sprite currentSector.sprite = cast(GamePiece, None) return quadrant
def _checkEnemyMoveIsValid(self, quadrant: Quadrant, targetCoordinates: Coordinates) -> bool: targetSector: Sector = quadrant.getSector(targetCoordinates) if targetSector.type == SectorType.EMPTY: return True else: self._baseEnemyMediatorLogger.info( f'Commander cannot move to sector: {targetCoordinates} occupied by {targetSector.type}' ) return False
def _createGalaxy(self): self.quadrants = [] for y in range(GALAXY_ROWS): quadrantRow: QuadrantRow = QuadrantRow([]) for x in range(GALAXY_COLUMNS): coordinates = Coordinates(x, y) quadrant = Quadrant(coordinates) quadrantRow.append(quadrant) if self._gameSettings.debugAnnounceQuadrantCreation is True: self.logger.debug(f"Created quadrant: ({x},{y})") self.quadrants.append(quadrantRow)
def testGetRandomEmptySector(self): """ """ coordinates: Coordinates = Coordinates(1, 1) quadrant: Quadrant = Quadrant(coordinates=coordinates) sector: Sector = quadrant.getRandomEmptySector() self.assertIsNotNone(sector, "Gotta get a sector back") self.assertEqual(sector.type, SectorType.EMPTY, "sector should be empty") self.logger.info(f'retrieved sector: {sector}')
def _enemyMovedUpdateQuadrant(self, quadrant: Quadrant, enemy: BaseEnemy, newSectorCoordinates: Coordinates, oldSectorCoordinates: Coordinates): """ Args: quadrant: Quadrant to modify enemy: sprite to place in sector newSectorCoordinates: old sector coordinates oldSectorCoordinates: new sector coordinates """ oldSector: Sector = quadrant.getSector( sectorCoordinates=oldSectorCoordinates) oldSector.type = SectorType.EMPTY oldSector.sprite = cast(GamePiece, None) newSector: Sector = quadrant.getSector( sectorCoordinates=newSectorCoordinates) newSector.type = SectorType.COMMANDER newSector.sprite = enemy
def _determineCloseCoordinatesToBlockedObject(self, quadrant: Quadrant, targetCoordinates: Coordinates) -> DirectionData: """ Get Enterprise "Close" coordinates to where it was 'blocked' Args: quadrant: The quadrant we are in targetCoordinates: Returns: """ directionData: DirectionData = self._gameEngine.computeCloseCoordinates(targetCoordinates=targetCoordinates) self.logger.info(f'{directionData=}') while directionData.coordinates.valid() is False or quadrant.isSectorEmpty(sectorCoordinates=directionData.coordinates) is False: directionData = self._gameEngine.computeCloseCoordinates(targetCoordinates=targetCoordinates) self.logger.info(f'Try again: {directionData=}') return directionData
def _doImpulseMove(self, quadrant: Quadrant, enterpriseCoordinates: Coordinates, targetCoordinates: Coordinates): """ Handle impulse move if we are not blocked by any obstacles. Args: quadrant: The current quadrant enterpriseCoordinates: Then enterprise sector coordinates targetCoordinates: Where the player indicated we were moving """ self.__updateQuadrant(quadrant=quadrant, currentCoordinates=enterpriseCoordinates, targetCoordinates=targetCoordinates) quadrant.enterprise.destinationPoint = GamePiece.gamePositionToScreenPosition(gameCoordinates=targetCoordinates) quadrant.enterpriseCoordinates = targetCoordinates quadrant.enterprise.inMotion = True self._gameEngine.impulse(newCoordinates=targetCoordinates, quadrant=quadrant, enterprise=quadrant.enterprise) self._soundMachine.playSound(SoundType.Impulse) if quadrant.klingonCount > 0 or quadrant.commanderCount > 0 or quadrant.superCommanderCount > 0: self._gameState.shipCondition = ShipCondition.Red else: self._gameState.shipCondition = ShipCondition.Green
def testInitialization(self): coordinates: Coordinates = Coordinates(1, 1) quadrant: Quadrant = Quadrant(coordinates=coordinates) self.assertIsNotNone(quadrant, 'Should initialize')
def __removeMissInQuadrant(self, quadrant: Quadrant, sectorCoordinates: Coordinates): sector: Sector = quadrant.getSector(sectorCoordinates) sector.type = SectorType.EMPTY