From d73d97ac6f72ed8779c635538d5fcfb9a8d737c6 Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Tue, 2 May 2017 12:02:58 +0200 Subject: [PATCH 01/32] Finished Wrath --- code/experiments/chasmGen.py | 19 +++++++++++-------- main.py | 16 +++++++++++----- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/code/experiments/chasmGen.py b/code/experiments/chasmGen.py index 1bed76e..eb9171f 100644 --- a/code/experiments/chasmGen.py +++ b/code/experiments/chasmGen.py @@ -194,9 +194,19 @@ def unblockTunnels(): myMap[x][y].chasm = False myMap[x][y].fg = colors.lighter_grey myMap[x][y].bg = colors.darker_sepia + +def checkMap(): + for x in range(MAP_WIDTH): + for y in range(MAP_HEIGHT): + if myMap[x][y].chasm: + myMap[x][y].fg = colors.dark_grey + myMap[x][y].bg = colors.black + else: + myMap[x][y].fg = colors.lighter_grey + myMap[x][y].bg = colors.dark_sepia def makeMap(): - global myMap, baseMap, rooms, roomTiles, tunnelTiles, unchasmable, firstX, firstY, lastX, lastY + global myMap, rooms, roomTiles, tunnelTiles, unchasmable, firstX, firstY, lastX, lastY myMap = [[Tile(blocked = True, x = x, y = y) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. rooms = [] @@ -217,8 +227,6 @@ def makeMap(): removeFromEmptyTiles(0, y) myMap[MAP_WIDTH - 1][y].setIndestructible() removeFromEmptyTiles(MAP_WIDTH - 1, y) - - baseMap = list(copy.deepcopy(myMap)) for r in range(30): w = randint(6, 10) @@ -266,11 +274,6 @@ def makeMap(): unblockTunnels() myMap = [[]] -baseMap = [[]] - - -maps = [myMap, baseMap] -mapIndex = 0 def countNeighbours(mapToUse, startX, startY, stopAtFirst = False): count = 0 diff --git a/main.py b/main.py index d8803c1..955513f 100644 --- a/main.py +++ b/main.py @@ -19,7 +19,7 @@ import code.dunbranches as dBr import code.dilledShelve as shelve from code.dunbranches import gluttonyDungeon -from code.custom_except import UnusableMethodException +from code.custom_except import * from music import playWavSound from multiprocessing import freeze_support, current_process @@ -3850,8 +3850,8 @@ def getInput(): for x in range(MAP_WIDTH): for y in range(MAP_HEIGHT): try: - if not myMap[x][y].block_sight: #DO NOT REMOVE THIS CHECK. Unless you'd like to see what would happen if the game was running on an actual toaster. - myMap[x][y].explored = True + #if not myMap[x][y].block_sight: #DO NOT REMOVE THIS CHECK. Unless you'd like to see what would happen if the game was running on an actual toaster. + myMap[x][y].explored = True except: pass for spell in spells: @@ -4698,7 +4698,7 @@ def applyBurn(target, chance = 70): buff.removeBuff() message('The ' + target.name + "'s ice melts away.") -def monsterArmageddon(monsterName ,monsterX, monsterY, radius = 4, damage = 40, selfHit = True): +def monsterArmageddon(monsterName, monsterX, monsterY, radius = 4, damage = 40, selfHit = True): radmax = radius + 2 message(monsterName.capitalize() + ' recites an arcane formula and explodes !', colors.red) global explodingTile @@ -4711,6 +4711,8 @@ def monsterArmageddon(monsterName ,monsterX, monsterY, radius = 4, damage = 40, if tileDistance(monsterX, monsterY, x, y) <= radius and not myMap[x][y].unbreakable: myMap[x][y].blocked = False myMap[x][y].block_sight = False + myMap[x][y].wall = False + myMap[x][y].applyGroundProperties() if x in range (1, MAP_WIDTH-1) and y in range (1,MAP_HEIGHT - 1): explodingTiles.append((x,y)) for obj in objects: @@ -5651,7 +5653,7 @@ def unblockTunnels(): elif not myMap[x][y].secretWall: myMap[x][y].applyGroundProperties() -def makeMap(generateChasm = False): +def makeMap(generateChasm = True): global myMap, stairs, objects, upStairs, bossDungeonsAppeared, color_dark_wall, color_light_wall, color_dark_ground, color_light_ground, color_dark_gravel, color_light_gravel, townStairs, gluttonyStairs, stairs, upStairs, nemesisList, roomTiles, tunnelTiles, unchasmable nemesis = None @@ -6168,6 +6170,10 @@ def takeTurn(self): self.flurryCooldown = 21 else: boss.Fighter.attack(player) + elif boss.distanceTo(player) <= 4: + if self.explodeCooldown <= 0: + monsterArmageddon('Wrath', boss.x, boss.y, 4, 30, False) + self.explodeCooldown = 31 elif self.chargeCooldown <= 0 and not self.charging: self.defineChargePath(player) self.chargeCooldown = 16 From df627cb096876a189583ed1189ca9cba59a4a68c Mon Sep 17 00:00:00 2001 From: Edern76 Date: Tue, 2 May 2017 12:03:30 +0200 Subject: [PATCH 02/32] Tried adding threading --- main.py | 121 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 93 insertions(+), 28 deletions(-) diff --git a/main.py b/main.py index d8803c1..51f3458 100644 --- a/main.py +++ b/main.py @@ -174,6 +174,8 @@ def __init__(self, name, width, height, type = 'noType'): bossDungeonsAppeared = {'gluttony': False, 'greed' : False} lastHitter = None nemesisList = [] +mobsToCalculate = [] +mustCalculate = False currentMusic = 'No_Music.wav' # - Spells - @@ -189,6 +191,8 @@ def __init__(self, name, width, height, type = 'noType'): RESURECTABLE_CORPSES = ["darksoul", "ogre"] BASE_HUNGER = 500 + + # - Spells - #_____________ CONSTANTS __________________ @@ -983,7 +987,7 @@ def actuallySteal(initiator, amountStolen): def castAstarPath(caster = None, monsterTarget = None): global FOV_recompute - (goalX, goalY) = targetTile(unlimited=True) + (goalX, goalY) = targetAnyTile(startX = player.x, startY = player.y) if targetTile == 'cancelled': return 'cancelled' else: @@ -2110,16 +2114,29 @@ def acidify(self, cooldown = 6): self.acidifiedCooldown = cooldown curArmor = self.armor - self.baseArmor self.baseArmor = -curArmor + +class Pathfinder(threading.Thread): + def __init__(self, mob, goalX, goalY): + threading.Thread.__init__(self) + self.mob = mob + self.goalX = goalX + self.goalY = goalY + + def run(self): + self.mob.astarPath = astarPath(self.mob.x, self.mob.y, self.goalX, self.goalY) class BasicMonster: #Basic monsters' AI + def __init__(self): + self.selectedTarget = None + def takeTurn(self): + global mustCalculate monster = self.owner targets = [] - selectedTarget = None priorityTargetFound = False monsterVisibleTiles = tdl.map.quick_fov(x = monster.x, y = monster.y,callback = isVisibleTile , fov = FOV_ALGO, radius = SIGHT_RADIUS, lightWalls = FOV_LIGHT_WALLS) if not 'frozen' in convertBuffsToNames(self.owner.Fighter) and monster.distanceTo(player) <= 15: - print(monster.name + " is less than 15 tiles to player.") + #print(monster.name + " is less than 15 tiles to player.") for object in objects: if (object.x, object.y) in monsterVisibleTiles and (object == player or (object.AI and object.AI.__class__.__name__ == "FriendlyMonster" and object.AI.friendlyTowards == player)): targets.append(object) @@ -2127,50 +2144,77 @@ def takeTurn(self): print(monster.name.capitalize() + " can target", end=" ") if targets: for loop in range (len(targets)): + pass print(targets[loop].name.capitalize() + ", ", sep ="", end ="") else: + pass print("absolutely nothing but nothingness.", end ="") - print() if targets: if player in targets: #Target player in priority - selectedTarget = player - del targets[targets.index(player)] + self.selectedTarget = player + print("PLAYER IN TARGETS") + print(self.selectedTarget) + targets.remove(targets.index(player)) if monster.distanceTo(player) < 2: priorityTargetFound = True if not priorityTargetFound: for enemyIndex in range(len(targets)): enemy = targets[enemyIndex] if monster.distanceTo(enemy) < 2: - selectedTarget = enemy + self.selectedTarget = enemy else: - if selectedTarget == None or monster.distanceTo(selectedTarget) > monster.distanceTo(enemy): - selectedTarget = enemy - if selectedTarget is not None: - if monster.distanceTo(selectedTarget) < 2: - monster.Fighter.attack(selectedTarget) + if self.selectedTarget == None or monster.distanceTo(self.selectedTarget) > monster.distanceTo(enemy): + self.selectedTarget = enemy + if self.selectedTarget is not None: + if monster.distanceTo(self.selectedTarget) < 2: + monster.Fighter.attack(self.selectedTarget) #else: - #state = monster.moveAstar(selectedTarget.x, selectedTarget.y, fallback = False) + #state = monster.moveAstar(self.selectedTarget.x, self.selectedTarget.y, fallback = False) #if state == "fail": - # diagState = checkDiagonals(monster, selectedTarget) + # diagState = checkDiagonals(monster, self.selectedTarget) # if diagState is None: - # monster.moveTowards(selectedTarget.x, selectedTarget.y) - #monster.moveOnAstarPath(goal = selectedTarget) + # monster.moveTowards(self.selectedTarget.x, self.selectedTarget.y) + #monster.moveOnAstarPath(goal = self.selectedTarget) #elif (monster.x, monster.y) in visibleTiles and monster.distanceTo(player) >= 2: #monster.moveAstar(player.x, player.y) else: - if not 'frozen' in convertBuffsToNames(monster.Fighter) and monster.distanceTo(player) >= 2: - pathState = "complete" - diagPathState = None - if monster.astarPath: - pathState = monster.moveAstar() - elif not monster.astarPath or pathState == "fail": - if monster.distanceTo(player) <= 15 and not (monster.x == player.x and monster.y == player.y): - diagPathState = checkDiagonals(monster, player) - elif diagPathState is None or monster.distanceTo(player) > 15: - monster.move(randint(-1, 1), randint(-1, 1)) #wandering + print("TRYING TO MOVE") + self.tryMove() + elif not 'frozen' in convertBuffsToNames(self.owner.Fighter): monster.move(randint(-1, 1), randint(-1, 1)) #wandering + + def tryMove(self): + global mustCalculate + monster = self.owner + if not 'frozen' in convertBuffsToNames(monster.Fighter) and monster.distanceTo(player) >= 2: + pathState = "complete" + diagPathState = None + if monster.astarPath: + print("Found astarPath") + if not monster.astarPath[0].blocked: + print("Not blocked") + (x, y) = monster.astarPath[0] + monster.move(x,y) + else: + print("Blocked") + if self.selectedTarget: + print("Recalculating") + mustCalculate = True + mobsToCalculate.append(monster) + else: + monster.move(randint(-1, 1), randint(-1, 1)) #wandering + + elif not monster.astarPath or pathState == "fail": + if self.selectedTarget: + print("Trying to calculate") + mustCalculate = True + mobsToCalculate.append(monster) + else: + print("No target") + monster.move(randint(-1, 1), randint(-1, 1)) #wandering + class Charger: def __init__(self): @@ -4855,7 +4899,7 @@ def __init__(self, blocked, x, y, block_sight = None, acid = False, acidCooldown self.dark_fg = colors.black self.DARK_BG = (0, 0, 16) self.dark_bg = (0, 0, 16) - self.moveCost = moveCost + self.moveCost = moveCost def neighbors(self): x = self.x @@ -8451,6 +8495,9 @@ def playGame(): quitGame('Player pressed escape', True) FOV_recompute = True #So as to avoid the blackscreen bug no matter which key we press if gameState == 'playing' and playerAction != 'didnt-take-turn': + global mobsToCalculate + global mustCalculate + mobsToCalculate = [] for object in objects: if object.AI: try: @@ -8470,7 +8517,25 @@ def playGame(): print(object.name) print("============================================") print("============================================") - + while mustCalculate: + print("Calculating") + pathfinders = [] + mustCalculate = False + print(len(mobsToCalculate)) + for mob in mobsToCalculate: + newPathfinder = Pathfinder(mob, mob.AI.selectedTarget.x, mob.AI.selectedTarget.y) + pathfinder.append(newPathfinder) + + for pathfind in pathfinders: + pathfind.start() + for pathfind in pathfinders: + pathfind.join() + + for mob in mobsToCalculate: + mob.AI.tryMove() + + + if object.Fighter and object.Fighter.baseShootCooldown > 0 and object.Fighter is not None: object.Fighter.curShootCooldown -= 1 From 24c4716eecbed4aadcbaaf263af6607c2dc17e42 Mon Sep 17 00:00:00 2001 From: Edern76 Date: Tue, 2 May 2017 17:28:05 +0200 Subject: [PATCH 03/32] Added Astar threading, and fixed window closing Also added lot of swearing to compensate developper's lost mental sanity. --- main.py | 119 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 104 insertions(+), 15 deletions(-) diff --git a/main.py b/main.py index 51f3458..1b3b6f8 100644 --- a/main.py +++ b/main.py @@ -1715,6 +1715,18 @@ def move(self, dx, dy): elif self == player: return 'didnt-take-turn' + def moveTo(self, otherX, otherY): + if self.Fighter and 'frozen' in convertBuffsToNames(self.Fighter): + pass + elif not isBlocked(otherX, otherY) or self.ghost: + self.x = int(otherX) + self.y = int(otherY) + else: + if self.Player and self.Fighter and 'confused' in convertBuffsToNames(self.Fighter): + message('You bump into a wall !') + elif self == player: + return 'didnt-take-turn' + def draw(self): if (self.x, self.y) in visibleTiles or REVEL: con.draw_char(self.x, self.y, self.char, self.color, bg=None) @@ -2127,13 +2139,28 @@ def run(self): class BasicMonster: #Basic monsters' AI def __init__(self): - self.selectedTarget = None + self.selectedTarget = None + self.dumbCounter = 0 + self.failCounter = 0 + self.didRecalcThisTurn = False + for loop in range(10): + print("!!!!!!!! SETTING TARGET TO NONE !!!!!!!!") + print() + + def setFuckingTarget(self, target): + self.selectedTarget = target def takeTurn(self): global mustCalculate monster = self.owner targets = [] + self.selectedTarget = None + self.setFuckingTarget(None) + self.dumbCounter = 0 + self.failCounter = 0 + self.didRecalcThisTurn = False priorityTargetFound = False + monsterVisibleTiles = tdl.map.quick_fov(x = monster.x, y = monster.y,callback = isVisibleTile , fov = FOV_ALGO, radius = SIGHT_RADIUS, lightWalls = FOV_LIGHT_WALLS) if not 'frozen' in convertBuffsToNames(self.owner.Fighter) and monster.distanceTo(player) <= 15: #print(monster.name + " is less than 15 tiles to player.") @@ -2154,18 +2181,29 @@ def takeTurn(self): self.selectedTarget = player print("PLAYER IN TARGETS") print(self.selectedTarget) - targets.remove(targets.index(player)) + try: + targets.remove(targets.index(player)) + except: + print("================ERROR==================") + for target in targets: + print(target.name) + print("=======================================") if monster.distanceTo(player) < 2: priorityTargetFound = True + print("BEFORE PRIORITY : {}".format(self.selectedTarget.name)) if not priorityTargetFound: for enemyIndex in range(len(targets)): enemy = targets[enemyIndex] if monster.distanceTo(enemy) < 2: + print("PRIORITIZING ENEMY {}".format(enemy.name)) self.selectedTarget = enemy else: if self.selectedTarget == None or monster.distanceTo(self.selectedTarget) > monster.distanceTo(enemy): self.selectedTarget = enemy + else: + print("NO PRIORITY, TARGET IS {}".format(self.selectedTarget.name)) if self.selectedTarget is not None: + print("SELECTED TARGET IS NOT NONE") if monster.distanceTo(self.selectedTarget) < 2: monster.Fighter.attack(self.selectedTarget) #else: @@ -2178,8 +2216,11 @@ def takeTurn(self): #elif (monster.x, monster.y) in visibleTiles and monster.distanceTo(player) >= 2: #monster.moveAstar(player.x, player.y) + else: + print("TRYING TO MOVE") + self.tryMove() else: - print("TRYING TO MOVE") + print("No target, still trying to move") self.tryMove() elif not 'frozen' in convertBuffsToNames(self.owner.Fighter): @@ -2189,31 +2230,64 @@ def tryMove(self): global mustCalculate monster = self.owner if not 'frozen' in convertBuffsToNames(monster.Fighter) and monster.distanceTo(player) >= 2: - pathState = "complete" + print("IN TRYMOVE BLOCK") + print("SELECTED TARGET : {}".format(self.selectedTarget)) + pathState = "fail" diagPathState = None - if monster.astarPath: + forceRecalculate = False + if monster.astarPath and ((not self.selectedTarget) or self.didRecalcThisTurn): print("Found astarPath") - if not monster.astarPath[0].blocked: + potentialX = int(monster.astarPath[0].x) + potentialY = int(monster.astarPath[0].y) + ''' + if monster.distanceToCoords(potentialX, potentialY) > monster.distanceToCoords(int(self.selectedTarget.x), int(self.selectedTarget.y)): + if self.dumbCounter < 1: + self.dumbCounter += 1 + forceRecalculate = True + else: + message("{} was too dumb to try to find a new path.".format(monster.name)) + ''' + + if not monster.astarPath[0].blocked and not forceRecalculate: print("Not blocked") - (x, y) = monster.astarPath[0] - monster.move(x,y) + print("ASTARX {} | ASTARY {}".format(monster.astarPath[0].x, monster.astarPath[0].y)) + x = int(monster.astarPath[0].x) + y = int(monster.astarPath[0].y) + if x == monster.x and y == monster.y: + print("Next step is identical to monster current position") + if len(monster.astarPath) > 1: + x = int(monster.astarPath[1].x) + y = int(monster.astarPath[1].y) + else: + print("Astar path is way too short") + print(monster.astarPath) + monster.moveTo(x, y) + monster.astarPath.remove(monster.astarPath[0]) + else: print("Blocked") - if self.selectedTarget: + if self.selectedTarget and self.failCounter < 3: print("Recalculating") + self.didRecalcThisTurn = True + self.failCounter += 1 mustCalculate = True mobsToCalculate.append(monster) else: + message("{} has a dumb expression on its face.".format(monster.name)) monster.move(randint(-1, 1), randint(-1, 1)) #wandering elif not monster.astarPath or pathState == "fail": - if self.selectedTarget: + if self.selectedTarget and self.failCounter < 3: print("Trying to calculate") mustCalculate = True + self.didRecalcThisTurn = True + self.failCounter += 1 mobsToCalculate.append(monster) else: print("No target") - monster.move(randint(-1, 1), randint(-1, 1)) #wandering + monster.move(randint(-1, 1), randint(-1, 1)) #wandering + if self.failCounter >= 3: + message("{} has a dumb expression on its face.".format(monster.name)) class Charger: @@ -3800,6 +3874,7 @@ def quitGame(message, backToMainMenu = False): if backToMainMenu: mainMenu() else: + stopProcess() raise SystemExit(str(message)) def stopProcess(): @@ -4673,8 +4748,14 @@ def isVisibleTile(x, y): return True def isBlocked(x, y): #With this function, making a check such as myMap[x][y].blocked is deprecated and should not be used anymore outside of this function (or FOV related stuff), since the latter does exactly the same job in addition to checking for blocking objects. - if myMap[x][y].blocked: - return True #If the Tile is already set as blocking, there's no point in making further checks + try: + if myMap[x][y].blocked: + return True #If the Tile is already set as blocking, there's no point in making further checks + except IndexError: + traceback.print_exc() + print("X : {} | Y : {}".format(x,y)) + quitGame("Quitted due to error") + for object in objects: try: #As all statements starting with this, ignore PyDev warning. However, please note that objects refers to the list of objects that we created and IS NOT defined by default in any library used (so don't call it out of the blue), contrary to object. @@ -5165,6 +5246,12 @@ def refreshEmptyTiles(): for y in range(MAP_HEIGHT): if not myMap[x][y].blocked: emptyTiles.append((x,y)) + +def updateTileCoords(): + for x in range(MAP_WIDTH): + for y in range(MAP_HEIGHT): + myMap[x][y].x = int(x) + myMap[x][y].y = int(y) def doStep(oldMap): newMap = list(deepcopy(baseMap)) @@ -5539,9 +5626,10 @@ def generateCave(): placeObjects(room, True) else: placeObjects(room, False) + updateTileCoords() print("DONE") - gameState = 'dead' + #gameState = 'dead' #What the hell ? ROOM_MAX_SIZE = 10 @@ -5904,6 +5992,7 @@ def makeMap(generateChasm = False): global gluttonyStairs print('Wrong branch for gluttony stairs') gluttonyStairs = None + updateTileCoords() def makeBossLevel(): global myMap, objects, upStairs, rooms, numberRooms @@ -8524,7 +8613,7 @@ def playGame(): print(len(mobsToCalculate)) for mob in mobsToCalculate: newPathfinder = Pathfinder(mob, mob.AI.selectedTarget.x, mob.AI.selectedTarget.y) - pathfinder.append(newPathfinder) + pathfinders.append(newPathfinder) for pathfind in pathfinders: pathfind.start() From 98e65da6989d6d51d6985236d6866e7a26a3883b Mon Sep 17 00:00:00 2001 From: Edern76 Date: Tue, 2 May 2017 17:42:36 +0200 Subject: [PATCH 04/32] Made so the game freezes less longer when mobs are trying to path through clogged corridors --- main.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index 04dc775..7c679cc 100644 --- a/main.py +++ b/main.py @@ -192,6 +192,7 @@ def __init__(self, name, width, height, type = 'noType'): BASE_HUNGER = 500 +MAX_ASTAR_FAILS = 2 # - Spells - #_____________ CONSTANTS __________________ @@ -241,6 +242,8 @@ def __init__(self, name, width, height, type = 'noType'): currentBranch = dBr.mainDungeon #Setting this to None causes errors. It doesn't matter tough, since this gets updated on loading or starting a game. dungeonLevel = 1 + + def findCurrentDir(): if getattr(sys, 'frozen', False): datadir = os.path.dirname(sys.executable) @@ -2266,7 +2269,7 @@ def tryMove(self): else: print("Blocked") - if self.selectedTarget and self.failCounter < 3: + if self.selectedTarget and self.failCounter < MAX_ASTAR_FAILS: print("Recalculating") self.didRecalcThisTurn = True self.failCounter += 1 @@ -2277,7 +2280,7 @@ def tryMove(self): monster.move(randint(-1, 1), randint(-1, 1)) #wandering elif not monster.astarPath or pathState == "fail": - if self.selectedTarget and self.failCounter < 3: + if self.selectedTarget and self.failCounter < MAX_ASTAR_FAILS: print("Trying to calculate") mustCalculate = True self.didRecalcThisTurn = True @@ -2286,7 +2289,7 @@ def tryMove(self): else: print("No target") monster.move(randint(-1, 1), randint(-1, 1)) #wandering - if self.failCounter >= 3: + if self.failCounter >= MAX_ASTAR_FAILS: message("{} has a dumb expression on its face.".format(monster.name)) From 9d955fd00e46c3d36b501868b9846c233c8aa2ce Mon Sep 17 00:00:00 2001 From: Edern76 Date: Tue, 2 May 2017 17:45:55 +0200 Subject: [PATCH 05/32] Lessened even more the freezes --- main.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main.py b/main.py index 7c679cc..66d0c0f 100644 --- a/main.py +++ b/main.py @@ -192,7 +192,7 @@ def __init__(self, name, width, height, type = 'noType'): BASE_HUNGER = 500 -MAX_ASTAR_FAILS = 2 +MAX_ASTAR_FAILS = 1 #Possibly unstable at 1 (but best performance), if you get weird results with Astar (aside from freezing) try bumping this number up a LITTLE bit (3 is already way overkill) # - Spells - #_____________ CONSTANTS __________________ @@ -2269,7 +2269,7 @@ def tryMove(self): else: print("Blocked") - if self.selectedTarget and self.failCounter < MAX_ASTAR_FAILS: + if self.selectedTarget and self.failCounter <= MAX_ASTAR_FAILS: print("Recalculating") self.didRecalcThisTurn = True self.failCounter += 1 @@ -2280,7 +2280,7 @@ def tryMove(self): monster.move(randint(-1, 1), randint(-1, 1)) #wandering elif not monster.astarPath or pathState == "fail": - if self.selectedTarget and self.failCounter < MAX_ASTAR_FAILS: + if self.selectedTarget and self.failCounter <= MAX_ASTAR_FAILS: print("Trying to calculate") mustCalculate = True self.didRecalcThisTurn = True @@ -2289,7 +2289,7 @@ def tryMove(self): else: print("No target") monster.move(randint(-1, 1), randint(-1, 1)) #wandering - if self.failCounter >= MAX_ASTAR_FAILS: + if self.failCounter > MAX_ASTAR_FAILS: message("{} has a dumb expression on its face.".format(monster.name)) From 70a6ba6d38b4a8bb621a4a1ee44f6847d5b6b5ea Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Tue, 2 May 2017 20:13:14 +0200 Subject: [PATCH 06/32] Chasm generation is now working --- code/experiments/chasmGen.py | 151 +++++++---------------------------- main.py | 13 +-- 2 files changed, 33 insertions(+), 131 deletions(-) diff --git a/code/experiments/chasmGen.py b/code/experiments/chasmGen.py index eb9171f..38f3d0f 100644 --- a/code/experiments/chasmGen.py +++ b/code/experiments/chasmGen.py @@ -18,12 +18,6 @@ rooms = [] roomTiles = [] tunnelTiles = [] -visuTiles = [] -visuEdges = [] -confTiles = [] -dispEmpty = False -dispDebug = True -state = "base" unchasmable = [] lastX = 0 lastY = 0 @@ -78,77 +72,6 @@ def returnOtherOwners(self, base): newList.remove(base) return newList - -class Room: - def __init__(self, tiles, borders = []): - self.tiles = tiles - self.borders = borders - rooms.append(self) - self.contestedTiles = [] - self.collidingRooms = [] - self.connectedRooms = [] - self.protect = False - self.mainRoom = False - self.reachableFromMainRoom = False - - def remove(self): - for (x,y) in self.tiles: - closeTile(x, y, myMap) - rooms.remove(self) - del self - - def claimTile(self, x, y): - if (x,y) in self.tiles or (x,y) in self.borders: - conflict = myMap[x][y].addOwner(self) - if conflict: - print("CONFLICT") - self.contestedTiles.append((x,y)) - for contester in conflict: - if not contester in self.collidingRooms: - self.collidingRooms.append(contester) - else: - raise IllegalTileInvasion("At {} {}".format(x, y)) - - def claimBorders(self): - for (x, y) in self.borders: - self.claimTile(x, y) - - def mergeWith(self, other, arbitraryTiles = []): - self.protect = True - if not other.protect: - if self in self.collidingRooms: - self.collidingRooms.remove(self) - print("REMOVED SELF FROM COLLROOMS") - for (x,y) in other.tiles: - if not (x,y) in self.tiles: - self.tiles.append((x,y)) - - for (x,y) in arbitraryTiles: - if not (x,y) in self.tiles: - self.tiles.append((x,y)) - - for (x,y) in other.borders: - if not (x,y) in self.borders: - self.borders.append((x,y)) - - if other in rooms: - rooms.remove(other) - else: - print("Other room not in rooms") - if other in self.collidingRooms: - self.collidingRooms.remove(other) - else: - print("Other room not in colliding rooms") - del other - else: - print("OTHER ROOM IS FUCKING PROTECTED, DO NOT MERGE") - - def setReachable(self): - if not self.reachableFromMainRoom: - self.reachableFromMainRoom = True - for room in self.connectedRooms: - room.setReachable() - class Rectangle: def __init__(self, x, y, w, h): @@ -186,14 +109,14 @@ def createVerticalTunnel(y1, y2, x): myMap[x][y].blocked = False tunnelTiles.append((x, y)) -def unblockTunnels(): - global myMap, tunnelTiles, roomTiles +def unblockTunnels(mapToUse, roomTiles, tunnelTiles, unchasmable): for x in range(MAP_WIDTH): for y in range(MAP_HEIGHT): - if myMap[x][y].chasm and ((x, y) in unchasmable or ((x,y) in tunnelTiles and not (x, y) in roomTiles)): - myMap[x][y].chasm = False - myMap[x][y].fg = colors.lighter_grey - myMap[x][y].bg = colors.darker_sepia + if mapToUse[x][y].chasm and ((x, y) in unchasmable or ((x,y) in tunnelTiles and not (x, y) in roomTiles)): + mapToUse[x][y].chasm = False + mapToUse[x][y].fg = colors.lighter_grey + mapToUse[x][y].bg = colors.darker_sepia + return mapToUse def checkMap(): for x in range(MAP_WIDTH): @@ -204,6 +127,18 @@ def checkMap(): else: myMap[x][y].fg = colors.lighter_grey myMap[x][y].bg = colors.dark_sepia + +def createChasms(mapToUse, roomTiles, tunnelTiles, unchasmable): + for x in range(1, MAP_WIDTH - 1): + for y in range(1, MAP_HEIGHT - 1): + if randint(0, 100) < CHANCE_TO_START_ALIVE: + #mapToUse[x][y].fg = colors.lighter_grey + #mapToUse[x][y].bg = colors.dark_sepia + mapToUse[x][y].chasm = False + for loop in range(STEPS_NUMBER): + mapToUse = doStep(mapToUse) + newMap = unblockTunnels(mapToUse, roomTiles, tunnelTiles, unchasmable) + return newMap def makeMap(): global myMap, rooms, roomTiles, tunnelTiles, unchasmable, firstX, firstY, lastX, lastY @@ -216,17 +151,13 @@ def makeMap(): for x in range(MAP_WIDTH): myMap[x][0].setIndestructible() - removeFromEmptyTiles(x,0) myMap[x][MAP_HEIGHT - 1].setIndestructible() - removeFromEmptyTiles(x, MAP_HEIGHT - 1) for y in range(MAP_HEIGHT): if not myMap[x][y].blocked and not (x,y) in emptyTiles: emptyTiles.append((x,y)) for y in range(MAP_HEIGHT): myMap[0][y].setIndestructible() - removeFromEmptyTiles(0, y) myMap[MAP_WIDTH - 1][y].setIndestructible() - removeFromEmptyTiles(MAP_WIDTH - 1, y) for r in range(30): w = randint(6, 10) @@ -263,6 +194,8 @@ def makeMap(): for y in range(lastCreatedRoom.y1 + 1, lastCreatedRoom.y2): unchasmable.append((x, y)) + myMap = createChasms(myMap, roomTiles, tunnelTiles, unchasmable) + ''' for x in range(1, MAP_WIDTH - 1): for y in range(1, MAP_HEIGHT - 1): if randint(0, 100) < CHANCE_TO_START_ALIVE: @@ -272,6 +205,7 @@ def makeMap(): for loop in range(STEPS_NUMBER): myMap = doStep(myMap) unblockTunnels() + ''' myMap = [[]] @@ -293,26 +227,6 @@ def countNeighbours(mapToUse, startX, startY, stopAtFirst = False): if stopAtFirst and found: break return count -def removeFromEmptyTiles(x, y): - if (x,y) in emptyTiles: - emptyTiles.remove((x,y)) - -def openTile(x, y, mapToUse): - if mapToUse[x][y].open() and not (x,y) in emptyTiles: - #emptyTiles.append((x,y)) - pass - -def closeTile(x, y, mapToUse): - mapToUse[x][y].close() - #removeFromEmptyTiles(x,y) - -def refreshEmptyTiles(): - global emptyTiles - emptyTiles = [] - for x in range(MAP_WIDTH): - for y in range(MAP_HEIGHT): - if not myMap[x][y].blocked: - emptyTiles.append((x,y)) def doStep(oldMap): newMap = list(copy.deepcopy(oldMap)) @@ -321,31 +235,24 @@ def doStep(oldMap): neighbours = countNeighbours(oldMap, x, y) if not oldMap[x][y].chasm: if neighbours < DEATH_LIMIT: - newMap[x][y].fg = colors.dark_grey - newMap[x][y].bg = colors.black + #newMap[x][y].fg = colors.dark_grey + #newMap[x][y].bg = colors.black newMap[x][y].chasm = True else: - newMap[x][y].fg = colors.lighter_grey - newMap[x][y].bg = colors.dark_sepia + #newMap[x][y].fg = colors.lighter_grey + #newMap[x][y].bg = colors.dark_sepia newMap[x][y].chasm = False else: if neighbours > BIRTH_LIMIT: - newMap[x][y].fg = colors.lighter_grey - newMap[x][y].bg = colors.dark_sepia + #newMap[x][y].fg = colors.lighter_grey + #newMap[x][y].bg = colors.dark_sepia newMap[x][y].chasm = False else: - newMap[x][y].fg = colors.dark_grey - newMap[x][y].bg = colors.black + #newMap[x][y].fg = colors.dark_grey + #newMap[x][y].bg = colors.black newMap[x][y].chasm = True return newMap -def drawCentered(cons = root , y = 1, text = "Lorem Ipsum", fg = None, bg = None): - xCentered = (WIDTH - len(text))//2 - cons.draw_str(xCentered, y, text, fg, bg) - - - - def update(mapToUse): root.clear() try: diff --git a/main.py b/main.py index 66d0c0f..71b1dda 100644 --- a/main.py +++ b/main.py @@ -22,6 +22,7 @@ from code.custom_except import * from music import playWavSound from multiprocessing import freeze_support, current_process +import code.experiments.chasmGen as chasmGen activeProcess = [] @@ -3972,8 +3973,8 @@ def getInput(): for x in range(MAP_WIDTH): for y in range(MAP_HEIGHT): try: - #if not myMap[x][y].block_sight: #DO NOT REMOVE THIS CHECK. Unless you'd like to see what would happen if the game was running on an actual toaster. - myMap[x][y].explored = True + if not myMap[x][y].block_sight: #DO NOT REMOVE THIS CHECK. Unless you'd like to see what would happen if the game was running on an actual toaster. + myMap[x][y].explored = True except: pass for spell in spells: @@ -5897,13 +5898,7 @@ def makeMap(generateChasm = True): unchasmable.append((x, y)) if generateChasm: - for x in range(1, MAP_WIDTH - 1): - for y in range(1, MAP_HEIGHT - 1): - if randint(0, 100) < CHANCE_TO_START_ALIVE_CHASM: - myMap[x][y].chasm = False - for loop in range(STEPS_NUMBER): - myMap = doChasmStep(myMap) - unblockTunnels() + myMap = chasmGen.createChasms(myMap, roomTiles, tunnelTiles, unchasmable) checkMap() if nemesis is not None: From 1006fff03f8c460d1c1278ae8fd37b3ff06f2cca Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Tue, 2 May 2017 20:29:28 +0200 Subject: [PATCH 07/32] Explosions don't remove chasms anymore --- main.py | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/main.py b/main.py index 71b1dda..cf3117e 100644 --- a/main.py +++ b/main.py @@ -5028,21 +5028,38 @@ def applyChasmProperties(self): self.dark_bg = (0, 0, 16) def applyGroundProperties(self, explode = False): - if not self.secretWall or explode: - gravelChoice = randint(0, 5) - self.blocked = False - self.block_sight = False - if gravelChoice == 0: - self.character = chr(177) - elif gravelChoice == 1: - self.character = chr(176) - else: - self.character = None - self.fg = color_light_gravel - self.bg = color_light_ground - self.dark_fg = color_dark_gravel - self.dark_bg = color_dark_ground - self.wall = False + if explode: + if not self.chasm: + gravelChoice = randint(0, 5) + self.blocked = False + self.block_sight = False + if gravelChoice == 0: + self.character = chr(177) + elif gravelChoice == 1: + self.character = chr(176) + else: + self.character = None + self.fg = color_light_gravel + self.bg = color_light_ground + self.dark_fg = color_dark_gravel + self.dark_bg = color_dark_ground + self.wall = False + else: + if not self.secretWall: + gravelChoice = randint(0, 5) + self.blocked = False + self.block_sight = False + if gravelChoice == 0: + self.character = chr(177) + elif gravelChoice == 1: + self.character = chr(176) + else: + self.character = None + self.fg = color_light_gravel + self.bg = color_light_ground + self.dark_fg = color_dark_gravel + self.dark_bg = color_dark_ground + self.wall = False def setUnbreakable(self): self.blocked = True @@ -5658,8 +5675,6 @@ def checkMap(): for y in range(MAP_HEIGHT): if myMap[x][y].wall: myMap[x][y].applyWallProperties() - if myMap[x][y].chasm: - myMap[x][y].dark_fg = colors.black elif myMap[x][y].chasm and not myMap[x][y].secretWall: myMap[x][y].applyChasmProperties() myMap[x][y].wall = False From 29cebb7d93d00792028b225f4ce71f5160621304 Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Wed, 3 May 2017 20:13:57 +0200 Subject: [PATCH 08/32] Moved chasmGen module out of experiments --- code/{experiments => }/chasmGen.py | 0 main.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename code/{experiments => }/chasmGen.py (100%) diff --git a/code/experiments/chasmGen.py b/code/chasmGen.py similarity index 100% rename from code/experiments/chasmGen.py rename to code/chasmGen.py diff --git a/main.py b/main.py index cf3117e..b87f27c 100644 --- a/main.py +++ b/main.py @@ -22,7 +22,7 @@ from code.custom_except import * from music import playWavSound from multiprocessing import freeze_support, current_process -import code.experiments.chasmGen as chasmGen +import code.chasmGen as chasmGen activeProcess = [] From 0c871ceac3154af6ac0dd02f53ab430b8080dc80 Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Wed, 3 May 2017 20:43:02 +0200 Subject: [PATCH 09/32] Monsters now don't walk on chasms, objects don't spawn on chasms, stairs can't appear in rooms with chasms --- main.py | 89 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 27 deletions(-) diff --git a/main.py b/main.py index b87f27c..152e8ec 100644 --- a/main.py +++ b/main.py @@ -1588,7 +1588,7 @@ def enterName(race): def heuristic(sourceX, sourceY, targetX, targetY): return abs(sourceX - targetX) + abs(sourceY - targetY) -def astarPath(startX, startY, goalX, goalY): +def astarPath(startX, startY, goalX, goalY, flying = False): start = myMap[startX][startY] goal = myMap[goalX][goalY] frontier = [(start, 0)] @@ -1614,19 +1614,22 @@ def astarPath(startX, startY, goalX, goalY): break for next in current.neighbors(): print('neighbor:', next.x, next.y) - if not isBlocked(next.x, next.y) or next == goal: - newCost = costSoFar[current] + myMap[next.x][next.y].moveCost - if next not in costSoFar or newCost < costSoFar[next]: - costSoFar[next] = newCost - heurCost = heuristic(next.x, next.y, goal.x, goal.y) - priority = newCost + heurCost - print('next:', next.x, next.y, ' prio = G + H', ' G=', newCost, ' H=', heurCost) - frontier.append((next, priority)) - cameFrom[next] = current - elif next in costSoFar: - print('next was already explored') + if flying or not myMap[next.x][next.y].chasm: + if not isBlocked(next.x, next.y) or next == goal: + newCost = costSoFar[current] + myMap[next.x][next.y].moveCost + if next not in costSoFar or newCost < costSoFar[next]: + costSoFar[next] = newCost + heurCost = heuristic(next.x, next.y, goal.x, goal.y) + priority = newCost + heurCost + print('next:', next.x, next.y, ' prio = G + H', ' G=', newCost, ' H=', heurCost) + frontier.append((next, priority)) + cameFrom[next] = current + elif next in costSoFar: + print('next was already explored') + else: + print('next is blocked') else: - print('next is blocked') + print('next is chasm') current = goal path = [goal] @@ -1662,7 +1665,7 @@ def __init__(self, nemesisObject, branch, level): class GameObject: "A generic object, represented by a character" - def __init__(self, x, y, char, name, color = colors.white, blocks = False, Fighter = None, AI = None, Player = None, Ghost = False, Item = None, alwaysVisible = False, darkColor = None, Equipment = None, pName = None, Essence = None, socialComp = None, shopComp = None, questList = []): + def __init__(self, x, y, char, name, color = colors.white, blocks = False, Fighter = None, AI = None, Player = None, Ghost = False, flying = False, Item = None, alwaysVisible = False, darkColor = None, Equipment = None, pName = None, Essence = None, socialComp = None, shopComp = None, questList = []): self.x = x self.y = y self.char = char @@ -1675,6 +1678,7 @@ def __init__(self, x, y, char, name, color = colors.white, blocks = False, Fight self.Item = Item self.alwaysVisible = alwaysVisible self.darkColor = darkColor + self.flying = flying if self.Fighter: #let the fighter component know who owns it self.Fighter.owner = self self.AI = AI @@ -2228,7 +2232,12 @@ def takeTurn(self): self.tryMove() elif not 'frozen' in convertBuffsToNames(self.owner.Fighter): - monster.move(randint(-1, 1), randint(-1, 1)) #wandering + dx, dy = randint(-1, 1), randint(-1, 1) + x, y = self.owner.x + dx, self.owner.y + dy + print('wandering, chasm:', myMap[x][y].chasm) + if self.owner.flying or not myMap[x][y].chasm: + print('moving') + monster.move(dx, dy) #wandering def tryMove(self): global mustCalculate @@ -5805,8 +5814,7 @@ def unblockTunnels(): myMap[x][y].applyGroundProperties() def makeMap(generateChasm = True): - global myMap, stairs, objects, upStairs, bossDungeonsAppeared, color_dark_wall, color_light_wall, color_dark_ground, color_light_ground, color_dark_gravel, color_light_gravel, townStairs, gluttonyStairs, stairs, upStairs, nemesisList, roomTiles, tunnelTiles, unchasmable - + global myMap, stairs, objects, upStairs, bossDungeonsAppeared, color_dark_wall, color_light_wall, color_dark_ground, color_light_ground, color_dark_gravel, color_light_gravel, townStairs, gluttonyStairs, stairs, upStairs, nemesisList, roomTiles, tunnelTiles, unchasmable, rooms nemesis = None found = checkFile('meta.bak', absMetaDirPath) @@ -5898,10 +5906,6 @@ def makeMap(generateChasm = True): else: createVerticalTunnel(previous_y, new_y, previous_x) createHorizontalTunnel(previous_x, new_x, new_y) - if r == 0: - placeObjects(newRoom, first = True) - else: - placeObjects(newRoom) rooms.append(newRoom) numberRooms += 1 secretRoom() @@ -5916,6 +5920,13 @@ def makeMap(generateChasm = True): myMap = chasmGen.createChasms(myMap, roomTiles, tunnelTiles, unchasmable) checkMap() + r = 0 + for room in rooms: + if r == 0: + placeObjects(room, True) + else: + placeObjects(room) + if nemesis is not None: randRoom = randint(0, len(rooms) - 1) room = rooms[randRoom] @@ -5936,13 +5947,21 @@ def makeMap(generateChasm = True): while not createdStairs: randRoom = randint(0, len(rooms) - 1) room = rooms[randRoom] + chasmedRoom = False + for x in range(room.x1 + 1, room.x2): + for y in range(room.y1 + 1, room.y2): + if myMap[x][y].chasm: + chasmedRoom = True + break + if chasmedRoom: + break (x, y) = room.center() wrongCentre = False for object in objects: if object.x == x and object.y == y: wrongCentre = True break - if not wrongCentre: + if not wrongCentre and not chasmedRoom: global gluttonyStairs gluttonyStairs = GameObject(x, y, '>', 'stairs to Gluttony', branch.lightStairsColor, alwaysVisible = True, darkColor = branch.darkStairsColor) objects.append(gluttonyStairs) @@ -5956,13 +5975,21 @@ def makeMap(generateChasm = True): while not createdStairs: randRoom = randint(0, len(rooms) - 1) room = rooms[randRoom] + chasmedRoom = False + for x in range(room.x1 + 1, room.x2): + for y in range(room.y1 + 1, room.y2): + if myMap[x][y].chasm: + chasmedRoom = True + break + if chasmedRoom: + break (x, y) = room.center() wrongCentre = False for object in objects: if object.x == x and object.y == y: wrongCentre = True break - if not wrongCentre: + if not wrongCentre and not chasmedRoom: global greedStairs greedStairs = GameObject(x, y, '>', 'stairs to Greed', branch.lightStairsColor, alwaysVisible = True, darkColor = branch.darkStairsColor) objects.append(greedStairs) @@ -5980,13 +6007,21 @@ def makeMap(generateChasm = True): while not createdStairs: randRoom = randint(0, len(rooms) - 1) room = rooms[randRoom] - (x, y) = room.center() + chasmedRoom = False + for x in range(room.x1 + 1, room.x2): + for y in range(room.y1 + 1, room.y2): + if myMap[x][y].chasm: + chasmedRoom = True + break + if chasmedRoom: + break wrongCentre = False for object in objects: if object.x == x and object.y == y: wrongCentre = True break - if not wrongCentre: + (x, y) = room.center() + if not wrongCentre and not chasmedRoom: global townStairs townStairs = GameObject(x, y, '>', 'glowing portal', branch.lightStairsColor, alwaysVisible = True, darkColor = branch.darkStairsColor) objects.append(townStairs) @@ -6879,7 +6914,7 @@ def placeObjects(room, first = False): (x,y) = room.tiles[randint(0, len(room.tiles) - 1)] - if not isBlocked(x, y) and (x, y) != (player.x, player.y): + if not isBlocked(x, y) and (x, y) != (player.x, player.y) and not myMap[x][y].chasm: monsterChoice = randomChoice(monsterChances) if monsterChoice == 'darksoul': monster = createDarksoul(x, y) @@ -6960,7 +6995,7 @@ def placeObjects(room, first = False): elif type(room) is CaveRoom: (x,y) = room.tiles[randint(0, len(room.tiles) - 1)] item = None - if not isBlocked(x, y): + if not isBlocked(x, y) and not myMap[x][y].chasm: itemChoice = randomChoice(itemChances) if itemChoice == 'potion': potionChoice = randomChoice(potionChances) From e5082f87e818e980f793c34ea4d87f78feae6194 Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Wed, 3 May 2017 21:16:32 +0200 Subject: [PATCH 10/32] Made falling a thing --- main.py | 90 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 69 insertions(+), 21 deletions(-) diff --git a/main.py b/main.py index 152e8ec..9d63070 100644 --- a/main.py +++ b/main.py @@ -4345,6 +4345,12 @@ def moveOrAttack(dx, dy): if not 'confused' in convertBuffsToNames(player.Fighter): x = player.x + dx y = player.y + dy + if myMap[x][y].chasm: + temporaryBox('You fall deeper into the dungeon...') + if dungeonLevel + 1 in currentBranch.bossLevels: + nextLevel(boss = True, fall = True) + else: + nextLevel(fall = True) else: possibleDirections = [(1, 1), (1,0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1), (0, 1)] index = randint(0, len(possibleDirections) - 1) @@ -5038,7 +5044,7 @@ def applyChasmProperties(self): def applyGroundProperties(self, explode = False): if explode: - if not self.chasm: + if not self.chasm or self.wall: gravelChoice = randint(0, 5) self.blocked = False self.block_sight = False @@ -5053,6 +5059,7 @@ def applyGroundProperties(self, explode = False): self.dark_fg = color_dark_gravel self.dark_bg = color_dark_ground self.wall = False + self.chasm = False else: if not self.secretWall: gravelChoice = randint(0, 5) @@ -5516,7 +5523,7 @@ def createPassage(roomA, roomB, tileA, tileB): -def generateCave(): +def generateCave(fall = False): global myMap, baseMap, mapToDisp, maps, visuTiles, state, visuEdges, confTiles, rooms, curRoomIndex, stairs, objects, upStairs, bossDungeonsAppeared, color_dark_wall, color_light_wall, color_dark_ground, color_light_ground, color_dark_gravel, color_light_gravel, townStairs, gluttonyStairs, stairs, upStairs, nemesisList myMap = [[Tile(blocked=False, x = x, y = y, block_sight=False) for y in range(MAP_HEIGHT)] for x in range(MAP_WIDTH)] visuTiles = [] @@ -5643,8 +5650,9 @@ def generateCave(): refreshEmptyTiles() checkMap() (pX, pY) = rooms[0].tiles[randint(0, len(rooms[0].tiles) - 1)] - player.x = pX - player.y = pY + if not fall: + player.x = pX + player.y = pY upStairs = GameObject(pX, pY, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor) objects.append(upStairs) upStairs.sendToBack() @@ -5658,6 +5666,14 @@ def generateCave(): placeObjects(room, True) else: placeObjects(room, False) + + if fall: + fallen = False + while not fallen: + x, y = randint(1, MAP_WIDTH - 1), randint(1, MAP_HEIGHT - 1) + if not myMap[x][y].chasm and not isBlocked(x, y): + player.x, player.y = x, y + fallen = True updateTileCoords() print("DONE") @@ -5813,7 +5829,7 @@ def unblockTunnels(): elif not myMap[x][y].secretWall: myMap[x][y].applyGroundProperties() -def makeMap(generateChasm = True): +def makeMap(generateChasm = True, fall = False): global myMap, stairs, objects, upStairs, bossDungeonsAppeared, color_dark_wall, color_light_wall, color_dark_ground, color_light_ground, color_dark_gravel, color_light_gravel, townStairs, gluttonyStairs, stairs, upStairs, nemesisList, roomTiles, tunnelTiles, unchasmable, rooms nemesis = None @@ -5889,8 +5905,9 @@ def makeMap(generateChasm = True): (new_x, new_y) = newRoom.center() if numberRooms == 0: - player.x = new_x - player.y = new_y + if not fall: + player.x = new_x + player.y = new_y for x in range(newRoom.x1 + 1, newRoom.x2): for y in range(newRoom.y1 + 1, newRoom.y2): unchasmable.append((x, y)) @@ -6042,9 +6059,17 @@ def makeMap(generateChasm = True): global gluttonyStairs print('Wrong branch for gluttony stairs') gluttonyStairs = None + + if fall: + fallen = False + while not fallen: + x, y = randint(1, MAP_WIDTH - 1), randint(1, MAP_HEIGHT - 1) + if not myMap[x][y].chasm and not isBlocked(x, y): + player.x, player.y = x, y + fallen = True updateTileCoords() -def makeBossLevel(): +def makeBossLevel(fall = False): global myMap, objects, upStairs, rooms, numberRooms myMap = [[Tile(True, x = x, y = y, wall = True) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. objects = [player] @@ -6072,10 +6097,12 @@ def makeBossLevel(): if not intersection: createRoom(newRoom) (new_x, new_y) = newRoom.center() + (previous_x, previous_y) = newRoom.center() if numberRooms == 0: - player.x = new_x - player.y = new_y + if not fall: + player.x = new_x + player.y = new_y if dungeonLevel > 1: upStairs = GameObject(new_x, new_y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor) objects.append(upStairs) @@ -6116,8 +6143,16 @@ def makeBossLevel(): (previous_x, previous_y) = bossRoom.center() rooms.append(bossRoom) numberRooms += 1 + + if fall: + fallen = False + while not fallen: + x, y = randint(1, MAP_WIDTH - 1), randint(1, MAP_HEIGHT - 1) + if not myMap[x][y].chasm and not isBlocked(x, y): + player.x, player.y = x, y + fallen = True -def makeHiddenTown(): +def makeHiddenTown(fall = False): global myMap, objects, upStairs, rooms, numberRooms myMap = [[Tile(True, wall = True) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. objects = [player] @@ -6133,8 +6168,17 @@ def makeHiddenTown(): newRoom = Rectangle(10, 10, 20, 10) createRoom(newRoom) - (player.x, player.y) = newRoom.center() - upStairs = GameObject(int(player.x), int(player.y), '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor) + x, y = newRoom.center() + if not fall: + player.x, player.y = x, y + else: + fallen = False + while not fallen: + x, y = randint(1, MAP_WIDTH - 1), randint(1, MAP_HEIGHT - 1) + if not myMap[x][y].chasm and not isBlocked(x, y): + player.x, player.y = x, y + fallen = True + upStairs = GameObject(x, y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor) objects.append(upStairs) upStairs.sendToBack() @@ -8102,7 +8146,10 @@ def chat(): def GetNamesUnderLookCursor(): tile = myMap[lookCursor.x][lookCursor.y] - tileDisp = 'Chasm: ' + str(tile.chasm) + if tile.secretWall: + tileDisp = 'Something is off with this wall' + else: + tileDisp = None names = [obj for obj in objects if obj.x == lookCursor.x and obj.y == lookCursor.y and (obj.x, obj.y in visibleTiles) and obj != lookCursor] for loop in range(len(names)): @@ -8117,7 +8164,8 @@ def GetNamesUnderLookCursor(): else: displayName = names[loop].name names[loop] = displayName - names.insert(0, tileDisp) + if tileDisp is not None: + names.insert(0, tileDisp) names = ', '.join(names) return names.capitalize() @@ -8520,7 +8568,7 @@ def loadLevel(level, save = True, branch = currentBranch): if level == townBrLevel and branch.name == 'Main': townStairs = objects[xfile["townStairsIndex"]] if dungeonLevel == greedBrLevel and currentBranch.name == 'Main': - greedStairs = objects[file["greedStairsIndex"]] + greedStairs = objects[xfile["greedStairsIndex"]] message("You climb the stairs") print("Loaded level " + str(level)) @@ -8529,7 +8577,7 @@ def loadLevel(level, save = True, branch = currentBranch): currentBranch = branch initializeFOV() -def nextLevel(boss = False, changeBranch = None, fixedMap = None): +def nextLevel(boss = False, changeBranch = None, fixedMap = None, fall = False): global dungeonLevel, currentBranch, currentMusic if boss: currentMusic = 'Hoxton_Princess.wav' @@ -8582,15 +8630,15 @@ def nextLevel(boss = False, changeBranch = None, fixedMap = None): if not boss: if currentBranch.fixedMap is None: if currentBranch.genType == 'dungeon': - makeMap() + makeMap(fall = fall) elif currentBranch.genType == 'cave': - generateCave() + generateCave(fall = fall) elif currentBranch.fixedMap == 'town': - makeHiddenTown() + makeHiddenTown(fall = fall) else: raise ValueError('Current branch fixedMap attribute is invalid ({})'.format(currentBranch.fixedMap)) else: - makeBossLevel() + makeBossLevel(fall = fall) print("Created a new level") print("After try except block") if hiroshimanNumber == 1 and not hiroshimanHasAppeared: From 23fa13b23df6fb6067c591b091dfd29ea7a22220 Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Wed, 3 May 2017 22:28:23 +0200 Subject: [PATCH 11/32] Started implementing wrath's dungeon --- code/dunbranches.py | 5 +- code/holeGen.py | 228 ++++++++++++++++++++++++++++++++++++++++++++ main.py | 161 +++++++++++++++++++++---------- 3 files changed, 342 insertions(+), 52 deletions(-) create mode 100644 code/holeGen.py diff --git a/code/dunbranches.py b/code/dunbranches.py index a14eb0e..841d37a 100644 --- a/code/dunbranches.py +++ b/code/dunbranches.py @@ -10,7 +10,7 @@ def __init__(self, shortName, name = None, maxDepth = 99999, branchesFrom = None weaponChances = {'sword': 25, 'axe': 25, 'hammer': 25, 'mace': 25}, foodChances = {'bread' : 500, 'herbs' : 501, 'rMeat' : 300, 'pie' : 200, 'pasta' : 200, 'meat' : 100, 'hBaguette' : 10}, # TO-DO : Add dumb stuff here with very low chances of spawning (maybe more on Gluttony's branch ?) and dumb effects, aka easter eggs. color_dark_wall = colors.darkest_grey, color_light_wall = colors.darker_grey, color_dark_ground = colors.darkest_sepia, color_dark_gravel = (27, 20, 0), - color_light_ground = colors.darker_sepia, color_light_gravel = (50, 37, 0), bossLevels = [3, 6], bossNames = {'High Inquisitor': 3, 'Gluttony': 6}, fixedMap = None, genType = 'dungeon'): + color_light_ground = colors.darker_sepia, color_light_gravel = (50, 37, 0), bossLevels = [3, 6], bossNames = {'High Inquisitor': 3, 'Gluttony': 6}, fixedMap = None, genType = 'dungeon', genFeatures = ['chasms']): """ A branch of the dungeon. Please note that the main dungeon is also considered as a branch. @type shortName: str @@ -50,13 +50,16 @@ def __init__(self, shortName, name = None, maxDepth = 99999, branchesFrom = None self.bossNames = bossNames self.fixedMap = fixedMap self.genType = genType + self.genFeatures = genFeatures mainDungeon = Branch(shortName = "main", name = "Main", branchesTo = None) gluttonyDungeon = Branch(shortName = "glutt", name = "Gluttony Dungeon", maxDepth = 5, branchesFrom = (mainDungeon, 1), lightStairsColor = colors.desaturated_chartreuse, darkStairsColor = colors.darkest_chartreuse, monsterChances = {'darksoul': 400, 'ogre': 200, 'starveling': 250, 'cultist': 150}, itemChances = {'potion': 360, 'scroll': 20, 'weapon': 20, 'shield': 100, 'food': 500}, bossLevels = [5], bossNames = {'Gluttony': 5}) hiddenTown = Branch(shortName = 'town',name = "Hidden Refuge", maxDepth = 1, branchesFrom = (mainDungeon, 1),lightStairsColor = colors.azure, darkStairsColor = colors.darker_azure, fixedMap = 'town') greedDungeon = Branch(shortName = 'greed', name = 'Greed Cavern', maxDepth = 5, branchesFrom= (mainDungeon, 2), lightStairsColor = colors.yellow, darkStairsColor = colors.darker_yellow, genType = 'cave', monsterChances = {'darksoul': 400, 'ogre': 100, 'snake': 10, 'cultist': 150, 'greedyFiend' : 200}, color_light_wall = colors.darker_yellow, color_dark_wall = colors.darkest_yellow, color_light_ground = colors.darker_sepia, color_dark_ground = colors.darkest_sepia, itemChances = {'potion': 100, 'scroll': 150, 'weapon': 50, 'shield': 50, 'food': 90, 'money' : 300}) +wrathDungeon = Branch(shortName = "wrath", name = "Wrath Lair", maxDepth = 5, branchesFrom = (mainDungeon, 2), lightStairsColor = colors.desaturated_red, darkStairsColor = colors.darkest_red, monsterChances = {'darksoul': 400, 'ogre': 400, 'cultist': 200}, itemChances = {'potion': 360, 'scroll': 20, 'weapon': 400, 'shield': 20, 'food': 200}, bossLevels = [5], bossNames = {'Wrath': 5}, genFeatures = ['holes'], color_light_wall = colors.darker_orange, color_dark_wall = colors.darkest_orange) mainDungeon.branchesTo.append((gluttonyDungeon, 1)) mainDungeon.branchesTo.append((hiddenTown, 1)) mainDungeon.branchesTo.append((greedDungeon, 2)) +mainDungeon.branchesTo.append((wrathDungeon, 2)) \ No newline at end of file diff --git a/code/holeGen.py b/code/holeGen.py new file mode 100644 index 0000000..9468a89 --- /dev/null +++ b/code/holeGen.py @@ -0,0 +1,228 @@ +import tdl, colors, copy, pdb, traceback, os, sys, time +from random import * +from custom_except import * + + +WIDTH, HEIGHT, LIMIT = 150, 80, 20 +MAP_WIDTH, MAP_HEIGHT = 140, 60 +MID_MAP_WIDTH, MID_MAP_HEIGHT = MAP_WIDTH//2, MAP_HEIGHT//2 +MID_WIDTH, MID_HEIGHT = int(WIDTH/2), int(HEIGHT/2) + +CHANCE_TO_START_ALIVE = 65 +DEATH_LIMIT = 3 +BIRTH_LIMIT = 4 +STEPS_NUMBER = 2 +MIN_ROOM_SIZE = 6 + +rooms = [] +lastX = 0 +lastY = 0 +firstX = 0 +firstY = 0 + +curRoomIndex = 0 + +sys.setrecursionlimit(3000) + +if __name__ == '__main__': + root = tdl.init(WIDTH, HEIGHT, 'Dementia') + +class Tile: + def __init__(self, blocked, x, y): + self.blocked = blocked + self.x = x + self.y = y + self.indestructible = False + self.belongsTo = [] + self.fg = colors.lighter_grey + self.bg = colors.dark_sepia + self.hole = True + + def setIndestructible(self): + self.blocked = True + self.indestructible = True + self.hole = False + + def open(self): + if not self.indestructible: + self.blocked = False + return True + else: + return False + + def close(self): + if not self.blocked: + self.blocked = True + + def addOwner(self, toAdd): + if not toAdd in self.belongsTo: + if self.belongsTo: + otherOwners = list(self.belongsTo) + else: + otherOwners = [] + self.belongsTo.append(toAdd) + print(otherOwners) + return otherOwners + + def returnOtherOwners(self, base): + newList = list(self.belongsTo) + newList.remove(base) + return newList + + +class Rectangle: + def __init__(self, x, y, w, h): + self.x1 = x + self.y1 = y + self.x2 = x + w + self.y2 = y + h + self.tiles = [] + + def center(self): + center_x = (self.x1 + self.x2) // 2 + center_y = (self.y1 + self.y2) // 2 + return (center_x, center_y) + + def intersect(self, other): + return (self.x1 <= other.x2 and self.x2 >= other.x1 and + self.y1 <= other.y2 and self.y2 >= other.y1) + +def createRoom(room): + global myMap, roomTiles + for x in range(room.x1 + 1, room.x2): + for y in range(room.y1 + 1, room.y2): + myMap[x][y].blocked = False + +def createHorizontalTunnel(x1, x2, y): + global myMap, tunnelTiles + for x in range(min(x1, x2), max(x1, x2) + 1): + myMap[x][y].blocked = False + +def createVerticalTunnel(y1, y2, x): + global myMap, tunnelTiles + for y in range(min(y1, y2), max(y1, y2) + 1): + myMap[x][y].blocked = False + +def checkMap(): + global myMap + for x in range(MAP_WIDTH): + for y in range(MAP_HEIGHT): + if myMap[x][y].hole and not myMap[x][y].indestructible: + myMap[x][y].blocked = False + +def createHoles(mapToUse): + for x in range(1, MAP_WIDTH - 1): + for y in range(1, MAP_HEIGHT - 1): + if randint(0, 100) < CHANCE_TO_START_ALIVE: + mapToUse[x][y].hole = False + for loop in range(STEPS_NUMBER): + mapToUse = doStep(mapToUse) + + return mapToUse + +def makeMap(): + global myMap, rooms, firstX, firstY, lastX, lastY + + myMap = [[Tile(blocked = True, x = x, y = y) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. + rooms = [] + roomTiles = [] + tunnelTiles = [] + numberRooms = 0 + + for x in range(MAP_WIDTH): + myMap[x][0].setIndestructible() + myMap[x][MAP_HEIGHT - 1].setIndestructible() + for y in range(MAP_HEIGHT): + myMap[0][y].setIndestructible() + myMap[MAP_WIDTH - 1][y].setIndestructible() + + for r in range(30): + w = randint(6, 10) + h = randint(6, 10) + x = randint(0, MAP_WIDTH-w-1) + y = randint(0, MAP_HEIGHT-h-1) + newRoom = Rectangle(x, y, w, h) + intersection = False + for otherRoom in rooms: + if newRoom.intersect(otherRoom): + intersection = True + break + if not intersection: + createRoom(newRoom) + lastCreatedRoom = newRoom + (new_x, new_y) = newRoom.center() + if numberRooms != 0: + (previous_x, previous_y) = rooms[numberRooms-1].center() + if randint(0, 1): + createHorizontalTunnel(previous_x, new_x, previous_y) + createVerticalTunnel(previous_y, new_y, new_x) + else: + createVerticalTunnel(previous_y, new_y, previous_x) + createHorizontalTunnel(previous_x, new_x, new_y) + else: + firstX, firstY = new_x, new_y + rooms.append(newRoom) + numberRooms += 1 + lastX, lastY = new_x, new_y + + myMap = createHoles(myMap) + checkMap() + +myMap = [[]] + +def countNeighbours(mapToUse, startX, startY): + count = 0 + found = False + for x in range(-1, 2): + for y in range(-1, 2): + if x == 0 and y == 0: + continue + else: + otherX = startX + x + otherY = startY + y + if not mapToUse[otherX][otherY].hole: + count += 1 + return count + +def doStep(oldMap): + newMap = list(copy.deepcopy(oldMap)) + for x in range(1, MAP_WIDTH - 1): + for y in range(1, MAP_HEIGHT - 1): + neighbours = countNeighbours(oldMap, x, y) + if not oldMap[x][y].hole: + if neighbours < DEATH_LIMIT: + newMap[x][y].hole = True + else: + newMap[x][y].hole = False + else: + if neighbours > BIRTH_LIMIT: + newMap[x][y].hole = False + else: + newMap[x][y].hole = True + return newMap + +def update(mapToUse): + root.clear() + try: + for x in range(MAP_WIDTH): + for y in range(MAP_HEIGHT): + if mapToUse[x][y].blocked: + root.draw_char(x, y, char = '#', fg = mapToUse[x][y].fg, bg = mapToUse[x][y].bg) + else: + root.draw_char(x, y, char = None, fg = mapToUse[x][y].fg, bg = mapToUse[x][y].bg) + if (x, y) == (firstX, firstY): + root.draw_char(x, y, char = 'X', fg = colors.red, bg = mapToUse[x][y].bg) + if (x, y) == (lastX, lastY): + root.draw_char(x, y, char = 'X', fg = colors.green, bg = mapToUse[x][y].bg) + + except IndexError: + traceback.print_exc() + os._exit(-1) + + tdl.flush() + +if __name__ == '__main__': + makeMap() + while not tdl.event.is_window_closed(): + update(myMap) + diff --git a/main.py b/main.py index 9d63070..231023e 100644 --- a/main.py +++ b/main.py @@ -23,6 +23,7 @@ from music import playWavSound from multiprocessing import freeze_support, current_process import code.chasmGen as chasmGen +import code.holeGen as holeGen activeProcess = [] @@ -172,7 +173,7 @@ def __init__(self, name, width, height, type = 'noType'): boss_FOV_recompute = True BOSS_FOV_ALGO = 'BASIC' BOSS_SIGHT_RADIUS = 20 -bossDungeonsAppeared = {'gluttony': False, 'greed' : False} +bossDungeonsAppeared = {'gluttony': False, 'greed' : False, 'wrath': False} lastHitter = None nemesisList = [] mobsToCalculate = [] @@ -235,6 +236,7 @@ def __init__(self, name, width, height, type = 'noType'): gluttonyStairs = None townStairs = None greedStairs = None +wrathStairs = None ######## hiroshimanHasAppeared = False highCultistHasAppeared = False @@ -4189,6 +4191,18 @@ def getInput(): nextLevel(boss, changeBranch = dBr.greedDungeon) else: message("You're too tired to climb down the stairs right now") + elif wrathStairs is not None and wrathStairs.x == player.x and wrathStairs.y == player.y: + if stairCooldown == 0: + global stairCooldown + temporaryBox('Loading...') + stairCooldown = 2 + boss = False + if DEBUG: + message("Stair cooldown set to {}".format(stairCooldown), colors.purple) + nextLevel(boss, changeBranch = dBr.wrathDungeon) + else: + message("You're too tired to climb down the stairs right now") + return None elif userInput.keychar.upper() == 'I': choseOrQuit = False while not choseOrQuit: @@ -4953,7 +4967,7 @@ def explode(): unchasmable = [] class Tile: - def __init__(self, blocked, x, y, block_sight = None, acid = False, acidCooldown = 5, character = None, fg = None, bg = None, dark_fg = None, dark_bg = None, chasm = False, wall = False, moveCost = 1): + def __init__(self, blocked, x, y, block_sight = None, acid = False, acidCooldown = 5, character = None, fg = None, bg = None, dark_fg = None, dark_bg = None, chasm = False, wall = False, hole = False, moveCost = 1): self.blocked = blocked self.explored = False self.unbreakable = False @@ -4968,6 +4982,7 @@ def __init__(self, blocked, x, y, block_sight = None, acid = False, acidCooldown self.DARK_BG = dark_bg self.wall = wall self.chasm = chasm + self.hole = hole self.x = x self.y = y self.secretWall = False @@ -5311,33 +5326,6 @@ def doStep(oldMap): openTile(x, y, newMap) return newMap -def doChasmStep(oldMap): - newMap = list(deepcopy(oldMap)) - for x in range(1, MAP_WIDTH - 1): - for y in range(1, MAP_HEIGHT - 1): - neighbours = countNeighbours(oldMap, x, y, searchBlock=False, searchChasm= True) - if not oldMap[x][y].chasm: - if neighbours < DEATH_LIMIT: - newMap[x][y].chasm = True - #newMap[x][y].applyChasmProperties() - else: - newMap[x][y].chasm = False - #if myMap[x][y].wall: - # myMap[x][y].applyWallProperties() - #elif not myMap[x][y].secretWall: - # newMap[x][y].applyGroundProperties() - else: - if neighbours > BIRTH_LIMIT: - newMap[x][y].chasm = False - #if myMap[x][y].wall: - # myMap[x][y].applyWallProperties() - #elif not myMap[x][y].secretWall: - # newMap[x][y].applyGroundProperties() - else: - newMap[x][y].chasm = True - #newMap[x][y].applyChasmProperties() - return newMap - def updateReachLists(): global reachableRooms, unreachableRooms reachableRooms = [] @@ -5524,7 +5512,7 @@ def createPassage(roomA, roomB, tileA, tileB): def generateCave(fall = False): - global myMap, baseMap, mapToDisp, maps, visuTiles, state, visuEdges, confTiles, rooms, curRoomIndex, stairs, objects, upStairs, bossDungeonsAppeared, color_dark_wall, color_light_wall, color_dark_ground, color_light_ground, color_dark_gravel, color_light_gravel, townStairs, gluttonyStairs, stairs, upStairs, nemesisList + global myMap, baseMap, mapToDisp, maps, visuTiles, state, visuEdges, confTiles, rooms, curRoomIndex, stairs, objects, upStairs, bossDungeonsAppeared, color_dark_wall, color_light_wall, color_dark_ground, color_light_ground, color_dark_gravel, color_light_gravel, townStairs, gluttonyStairs, stairs, upStairs, nemesisList, wrathStairs myMap = [[Tile(blocked=False, x = x, y = y, block_sight=False) for y in range(MAP_HEIGHT)] for x in range(MAP_WIDTH)] visuTiles = [] visuEdges = [] @@ -5538,6 +5526,7 @@ def generateCave(fall = False): upStairs = None gluttonyStairs = None townStairs = None + wrathStairs = None color_dark_wall = currentBranch.color_dark_wall color_light_wall = currentBranch.color_light_wall @@ -5698,7 +5687,13 @@ def createRoom(room): def checkMap(): for x in range(MAP_WIDTH): for y in range(MAP_HEIGHT): - if myMap[x][y].wall: + if myMap[x][y].hole and not myMap[x][y].unbreakable: + myMap[x][y].wall = False + if myMap[x][y].chasm: + myMap[x][y].applyChasmProperties() + else: + myMap[x][y].applyGroundProperties() + elif myMap[x][y].wall: myMap[x][y].applyWallProperties() elif myMap[x][y].chasm and not myMap[x][y].secretWall: myMap[x][y].applyChasmProperties() @@ -5818,19 +5813,8 @@ def checkFile(file, folder): break return False -def unblockTunnels(): - global myMap, tunnelTiles, roomTiles - for x in range(MAP_WIDTH): - for y in range(MAP_HEIGHT): - if myMap[x][y].chasm and ((x, y) in unchasmable or ((x,y) in tunnelTiles and not (x, y) in roomTiles)): - myMap[x][y].chasm = False - if myMap[x][y].wall and not myMap[x][y].secretWall: - myMap[x][y].applyWallProperties() - elif not myMap[x][y].secretWall: - myMap[x][y].applyGroundProperties() - -def makeMap(generateChasm = True, fall = False): - global myMap, stairs, objects, upStairs, bossDungeonsAppeared, color_dark_wall, color_light_wall, color_dark_ground, color_light_ground, color_dark_gravel, color_light_gravel, townStairs, gluttonyStairs, stairs, upStairs, nemesisList, roomTiles, tunnelTiles, unchasmable, rooms +def makeMap(generateChasm = True, generateHole = False, fall = False): + global myMap, stairs, objects, upStairs, bossDungeonsAppeared, color_dark_wall, color_light_wall, color_dark_ground, color_light_ground, color_dark_gravel, color_light_gravel, townStairs, gluttonyStairs, stairs, upStairs, nemesisList, roomTiles, tunnelTiles, unchasmable, rooms, wrathStairs nemesis = None found = checkFile('meta.bak', absMetaDirPath) @@ -5863,6 +5847,7 @@ def makeMap(generateChasm = True, fall = False): upStairs = None gluttonyStairs = None townStairs = None + wrathStairs = None color_dark_wall = currentBranch.color_dark_wall color_light_wall = currentBranch.color_light_wall @@ -5872,7 +5857,7 @@ def makeMap(generateChasm = True, fall = False): color_light_gravel = currentBranch.color_light_gravel - myMap = [[Tile(True, x = x, y = y, wall = True, chasm = generateChasm) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. + myMap = [[Tile(True, x = x, y = y, wall = True, chasm = generateChasm, hole = generateHole) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. rooms = [] roomTiles = [] @@ -5935,6 +5920,8 @@ def makeMap(generateChasm = True, fall = False): if generateChasm: myMap = chasmGen.createChasms(myMap, roomTiles, tunnelTiles, unchasmable) + if generateHole: + myMap = holeGen.createHoles(myMap) checkMap() r = 0 @@ -6018,7 +6005,7 @@ def makeMap(generateChasm = True, fall = False): global greedStairs print('No greed stairs on this level') greedStairs = None - if branch == dBr.hiddenTown: + elif branch == dBr.hiddenTown: if dungeonLevel == level: createdStairs = False while not createdStairs: @@ -6049,7 +6036,34 @@ def makeMap(generateChasm = True, fall = False): global townStairs print('No town stairs on this level') townStairs = None - + elif branch == dBr.wrathDungeon: + if dungeonLevel == level and not bossDungeonsAppeared['wrath']: + createdStairs = False + while not createdStairs: + randRoom = randint(0, len(rooms) - 1) + room = rooms[randRoom] + chasmedRoom = False + for x in range(room.x1 + 1, room.x2): + for y in range(room.y1 + 1, room.y2): + if myMap[x][y].chasm: + chasmedRoom = True + break + if chasmedRoom: + break + (x, y) = room.center() + wrongCentre = False + for object in objects: + if object.x == x and object.y == y: + wrongCentre = True + break + if not wrongCentre and not chasmedRoom: + global wrathStairs + wrathStairs = GameObject(x, y, '>', 'stairs to Wrath', branch.lightStairsColor, alwaysVisible = True, darkColor = branch.darkStairsColor) + objects.append(wrathStairs) + wrathStairs.sendToBack() + bossDungeonsAppeared['wrath'] = True + createdStairs = True + print('created wraths stairs at ' + str(x) + ', ' + str(y)) if not dBr.hiddenTown in branches: global townStairs @@ -6059,6 +6073,10 @@ def makeMap(generateChasm = True, fall = False): global gluttonyStairs print('Wrong branch for gluttony stairs') gluttonyStairs = None + if not dBr.wrathDungeon in branches: + global wrathStairs + print('Wrong branch for wrath stairs') + wrathStairs = None if fall: fallen = False @@ -8350,6 +8368,7 @@ def saveGame(): gluttBrLevel = dBr.gluttonyDungeon.origDepth townBrLevel = dBr.hiddenTown.origDepth greedBrLevel = dBr.greedDungeon.origDepth + wrathBrLevel = dBr.wrathDungeon.origDepth if dungeonLevel == gluttBrLevel and currentBranch.name == 'Main': try: file["gluttStairsIndex"] = objects.index(gluttonyStairs) @@ -8382,6 +8401,17 @@ def saveGame(): print('Details : {}'.format(error.args)) print('==============================') pass + if dungeonLevel == wrathBrLevel and currentBranch.name == 'Main': + try: + file["wrathStairsIndex"] = objects.index(wrathStairs) + print('SAVED FUCKING wrath STAIRS AT INDEX {}'.format(objects.index(wrathStairs))) + except Exception as error: + print("===========WARNING============") + print("Couldn't save wrath stairs") + print('Error : {}'.format(type(error))) + print('Details : {}'.format(error.args)) + print('==============================') + pass file.close() #mapFile = open(absPicklePath, 'wb') @@ -8394,7 +8424,7 @@ def newGame(): DEBUG = False REVEL = False deleteSaves() - bossDungeonsAppeared = {'gluttony': False, 'greed': False} + bossDungeonsAppeared = {'gluttony': False, 'greed': False, 'wrath': False} gameMsgs = [] objects = [player] logMsgs = [] @@ -8438,7 +8468,7 @@ def newGame(): highCultistHasAppeared = False #Make so more high cultists can spawn at lower levels (still only one by floor though) def loadGame(): - global objects, inventory, gameMsgs, gameState, player, dungeonLevel, myMap, equipmentList, stairs, upStairs, hiroshimanNumber, currentBranch, gluttonyStairs, logMsgs, townStairs, greedStairs + global objects, inventory, gameMsgs, gameState, player, dungeonLevel, myMap, equipmentList, stairs, upStairs, hiroshimanNumber, currentBranch, gluttonyStairs, logMsgs, townStairs, greedStairs, wrathStairs #myMap = [[Tile(True) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] @@ -8462,12 +8492,15 @@ def loadGame(): gluttBrLevel = dBr.gluttonyDungeon.origDepth townBrLevel = dBr.hiddenTown.origDepth greedBrLevel = dBr.greedDungeon.origDepth + wrathBrLevel = dBr.wrathDungeon.origDepth if dungeonLevel == gluttBrLevel and currentBranch.name == 'Main': gluttonyStairs = objects[file["gluttStairsIndex"]] if dungeonLevel == townBrLevel and currentBranch.name == 'Main': townStairs = objects[file["townStairsIndex"]] if dungeonLevel == greedBrLevel and currentBranch.name == 'Main': greedStairs = objects[file["greedStairsIndex"]] + if dungeonLevel == wrathBrLevel and currentBranch.name == 'Main': + greedStairs = objects[file["wrathStairsIndex"]] #mapFile = open(absPicklePath, "rb") #myMap = pickle.load(mapFile) #mapFile.close() @@ -8496,6 +8529,7 @@ def saveLevel(level = dungeonLevel): gluttBrLevel = dBr.gluttonyDungeon.origDepth townBrLevel = dBr.hiddenTown.origDepth greedBrLevel = dBr.greedDungeon.origDepth + wrathBrLevel = dBr.wrathDungeon.origDepth if dungeonLevel == gluttBrLevel and currentBranch.name == 'Main': try: mapFile["gluttStairsIndex"] = objects.index(gluttonyStairs) @@ -8528,6 +8562,21 @@ def saveLevel(level = dungeonLevel): print('Details : {}'.format(error.args)) print('==============================') pass + if dungeonLevel == wrathBrLevel and currentBranch.name == 'Main': + try: + mapFile["wrathStairsIndex"] = objects.index(wrathStairs) + print('SAVED FUCKING wrath STAIRS AT INDEX {}'.format(objects.index(wrathStairs))) + except Exception as error: + print("===========WARNING============") + print("Couldn't save wrath stairs") + print('Error : {}'.format(type(error))) + print('Details : {}'.format(error.args)) + print('==============================') + pass + else: + print("DIDNT SAVE wrath STAIRS") + print("DungeonLevel : {} / WrathLevel : {}".format(dungeonLevel, wrathBrLevel)) + print('Current branch : {}'.format(currentBranch.name)) mapFile["yunowork"] = "SCREW THIS" print("Saved level at " + mapFilePath) mapFile.sync() @@ -8537,7 +8586,7 @@ def saveLevel(level = dungeonLevel): return "completed" def loadLevel(level, save = True, branch = currentBranch): - global objects, player, myMap, stairs, dungeonLevel, gluttonyStairs, townStairs, currentBranch + global objects, player, myMap, stairs, dungeonLevel, gluttonyStairs, townStairs, currentBranch, wrathStairs, greedStairs if save: try: saveLevel(dungeonLevel) @@ -8560,6 +8609,7 @@ def loadLevel(level, save = True, branch = currentBranch): gluttBrLevel = dBr.gluttonyDungeon.origDepth townBrLevel = dBr.hiddenTown.origDepth greedBrLevel = dBr.greedDungeon.origDepth + wrathBrLevel = dBr.wrathDungeon.origDepth if level == gluttBrLevel and branch.name == 'Main': print("Branch name is {} and gluttony stairs appear in branch Main. Moreover, we are at level {} and they appear at level {}. Therefore we are loading them and NOTHING SHOULD GO FUCKING WRONG.".format(branch.name, level, gluttBrLevel)) gluttonyStairs = objects[xfile["gluttStairsIndex"]] @@ -8569,6 +8619,8 @@ def loadLevel(level, save = True, branch = currentBranch): townStairs = objects[xfile["townStairsIndex"]] if dungeonLevel == greedBrLevel and currentBranch.name == 'Main': greedStairs = objects[xfile["greedStairsIndex"]] + if dungeonLevel == wrathBrLevel and currentBranch.name == 'Main': + wrathStairs = objects[xfile['wrathStairsIndex']] message("You climb the stairs") print("Loaded level " + str(level)) @@ -8627,10 +8679,17 @@ def nextLevel(boss = False, changeBranch = None, fixedMap = None, fall = False): objects = tempObjects player = tempPlayer stairs = tempStairs + chasmGeneration = False + holeGeneration = False if not boss: if currentBranch.fixedMap is None: + for feature in currentBranch.genFeatures: + if feature == 'chasms': + chasmGeneration = True + if feature == 'holes': + holeGeneration = True if currentBranch.genType == 'dungeon': - makeMap(fall = fall) + makeMap(generateChasm=chasmGeneration, generateHole=holeGeneration, fall = fall) elif currentBranch.genType == 'cave': generateCave(fall = fall) elif currentBranch.fixedMap == 'town': From 6826a4a4a0c3ab7dc0fae17fdc45cab514e68b38 Mon Sep 17 00:00:00 2001 From: Edern76 Date: Thu, 4 May 2017 18:10:03 +0200 Subject: [PATCH 12/32] Greedy fiends now drop part of what they stole to player --- main.py | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/main.py b/main.py index 66d0c0f..c2a6471 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,5 @@ -import colors, math, textwrap, time, os, sys, code, gzip, pathlib, traceback, ffmpy, pdb, copy, queue #Code is not unused. Importing it allows us to import the rest of our custom modules in the code package. +import colors, math, textwrap, time, os, sys, code, gzip, pathlib, traceback, ffmpy, pdb, copy, queue, random #Code is not unused. Importing it allows us to import the rest of our custom modules in the code package. import tdlib as tdl import code.dialog as dial import music as mus @@ -978,6 +978,10 @@ def stealMoneyAndDamage(initiator, target, amount): # To call, add to attackFunctions : "lambda ini, target : stealMoneyAndDamage(ini, target, [ENTER_DESIRED_AMOUNT_HERE])" def actuallySteal(initiator, amountStolen): target.Player.money -= amountStolen + addCoef = round(random.uniform(0, 0.8), 3) + toAdd = int(amountStolen * addCoef) + print("To add = {} (coef = {})".format(toAdd, addCoef)) + initiator.lootFunction[0].Item.amount += toAdd message("{} has stolen {} of your gold pieces !".format(initiator.owner.name.capitalize(), amountStolen), colors.red) leftToSteal = int(amount) if target.Player.money >= leftToSteal: @@ -1587,7 +1591,7 @@ def enterName(race): def heuristic(sourceX, sourceY, targetX, targetY): return abs(sourceX - targetX) + abs(sourceY - targetY) -def astarPath(startX, startY, goalX, goalY): +def astarPath(startX, startY, goalX, goalY, silent = True): start = myMap[startX][startY] goal = myMap[goalX][goalY] frontier = [(start, 0)] @@ -1607,38 +1611,49 @@ def astarPath(startX, startY, goalX, goalY): frontier.remove((prioTile, lastPrio)) current = prioTile - print('tile:', prioTile.x, prioTile.y, ' prio:', lastPrio) + if not silent: + print('tile:', prioTile.x, prioTile.y, ' prio:', lastPrio) if current == goal: - print('arrived to goal') + if not silent: + print('arrived to goal') break for next in current.neighbors(): - print('neighbor:', next.x, next.y) + if not silent: + print('neighbor:', next.x, next.y) if not isBlocked(next.x, next.y) or next == goal: newCost = costSoFar[current] + myMap[next.x][next.y].moveCost if next not in costSoFar or newCost < costSoFar[next]: costSoFar[next] = newCost heurCost = heuristic(next.x, next.y, goal.x, goal.y) priority = newCost + heurCost - print('next:', next.x, next.y, ' prio = G + H', ' G=', newCost, ' H=', heurCost) + if not silent: + print('next:', next.x, next.y, ' prio = G + H', ' G=', newCost, ' H=', heurCost) frontier.append((next, priority)) cameFrom[next] = current elif next in costSoFar: - print('next was already explored') + if not silent: + print('next was already explored') else: - print('next is blocked') + if not silent: + print('next is blocked') current = goal path = [goal] - print('start:', startX, startY, ' goal:', goalX, goalY) + if not silent: + print('start:', startX, startY, ' goal:', goalX, goalY) while current != start: former = current - print('former:', former.x, former.y) + if not silent: + print('former:', former.x, former.y) current = cameFrom[former] - print('current:', current.x, current.y) + if not silent: + print('current:', current.x, current.y) path.append(current) - print('not reversed path:', path) + if not silent: + print('not reversed path:', path) path.reverse() - print('reversed path:', path) + if not silent: + print('reversed path:', path) return path def closestMonster(max_range): @@ -6744,7 +6759,8 @@ def createGreedyFiend(x, y, friendly = False, corpse = False): deathType = monsterDeath monName = "greedy fiend" color = colors.dark_orange - lootOnDeath = None + money = GameObject(x = None, y = None, char = '$', name = 'gold piece', color = colors.gold, Item=Money(0), blocks = False, pName = 'gold pieces') + lootOnDeath = [money] else: monName = "YOU_SHOULDNT_SEE_THIS" deathType = zombieDeath @@ -6754,7 +6770,7 @@ def createGreedyFiend(x, y, friendly = False, corpse = False): AI_component = BasicMonster() else: AI_component = FriendlyMonster(friendlyTowards = player) - fighterComponent = Fighter(hp=20, armor=2, power=1, xp = 30, deathFunction = deathType, accuracy = 30, evasion = 20, lootFunction=lootOnDeath, lootRate=[15], attackFunctions= [lambda ini, target : stealMoneyAndDamage(ini, target, 300)], noDirectDamage = True) + fighterComponent = Fighter(hp=20, armor=2, power=1, xp = 30, deathFunction = deathType, accuracy = 30, evasion = 20, lootFunction=lootOnDeath, lootRate=[100], attackFunctions= [lambda ini, target : stealMoneyAndDamage(ini, target, 300)], noDirectDamage = True) monster = GameObject(x, y, char = 'f', color = color, name = monName, blocks = True, Fighter=fighterComponent, AI = AI_component) return monster else: @@ -7322,7 +7338,8 @@ def monsterDeath(monster): for item in monster.Fighter.lootFunction: loot = randint(1, 100) if loot <= monster.Fighter.lootRate[itemIndex]: - lootItem(item, monster.x, monster.y) + if not item.Item.stackable or item.Item.amount > 0: + lootItem(item, monster.x, monster.y) itemIndex += 1 monster.char = '%' From 377d63ae9545dd8645a8f90972ac061da61e8c2e Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Thu, 4 May 2017 22:07:07 +0200 Subject: [PATCH 13/32] Modified wrath dungeon and started temple generation --- code/dunbranches.py | 2 +- code/experiments/templeGen.py | 310 ++++++++++++++++++++++++++++++++++ main.py | 27 +-- 3 files changed, 327 insertions(+), 12 deletions(-) create mode 100644 code/experiments/templeGen.py diff --git a/code/dunbranches.py b/code/dunbranches.py index 841d37a..114c352 100644 --- a/code/dunbranches.py +++ b/code/dunbranches.py @@ -56,7 +56,7 @@ def __init__(self, shortName, name = None, maxDepth = 99999, branchesFrom = None gluttonyDungeon = Branch(shortName = "glutt", name = "Gluttony Dungeon", maxDepth = 5, branchesFrom = (mainDungeon, 1), lightStairsColor = colors.desaturated_chartreuse, darkStairsColor = colors.darkest_chartreuse, monsterChances = {'darksoul': 400, 'ogre': 200, 'starveling': 250, 'cultist': 150}, itemChances = {'potion': 360, 'scroll': 20, 'weapon': 20, 'shield': 100, 'food': 500}, bossLevels = [5], bossNames = {'Gluttony': 5}) hiddenTown = Branch(shortName = 'town',name = "Hidden Refuge", maxDepth = 1, branchesFrom = (mainDungeon, 1),lightStairsColor = colors.azure, darkStairsColor = colors.darker_azure, fixedMap = 'town') greedDungeon = Branch(shortName = 'greed', name = 'Greed Cavern', maxDepth = 5, branchesFrom= (mainDungeon, 2), lightStairsColor = colors.yellow, darkStairsColor = colors.darker_yellow, genType = 'cave', monsterChances = {'darksoul': 400, 'ogre': 100, 'snake': 10, 'cultist': 150, 'greedyFiend' : 200}, color_light_wall = colors.darker_yellow, color_dark_wall = colors.darkest_yellow, color_light_ground = colors.darker_sepia, color_dark_ground = colors.darkest_sepia, itemChances = {'potion': 100, 'scroll': 150, 'weapon': 50, 'shield': 50, 'food': 90, 'money' : 300}) -wrathDungeon = Branch(shortName = "wrath", name = "Wrath Lair", maxDepth = 5, branchesFrom = (mainDungeon, 2), lightStairsColor = colors.desaturated_red, darkStairsColor = colors.darkest_red, monsterChances = {'darksoul': 400, 'ogre': 400, 'cultist': 200}, itemChances = {'potion': 360, 'scroll': 20, 'weapon': 400, 'shield': 20, 'food': 200}, bossLevels = [5], bossNames = {'Wrath': 5}, genFeatures = ['holes'], color_light_wall = colors.darker_orange, color_dark_wall = colors.darkest_orange) +wrathDungeon = Branch(shortName = "wrath", name = "Wrath Lair", maxDepth = 5, branchesFrom = (mainDungeon, 2), lightStairsColor = colors.dark_red, darkStairsColor = colors.darkest_red, monsterChances = {'darksoul': 400, 'ogre': 400, 'cultist': 200}, itemChances = {'potion': 360, 'scroll': 20, 'weapon': 400, 'shield': 20, 'food': 200}, bossLevels = [5], bossNames = {'Wrath': 5}, genFeatures = ['holes']) mainDungeon.branchesTo.append((gluttonyDungeon, 1)) mainDungeon.branchesTo.append((hiddenTown, 1)) diff --git a/code/experiments/templeGen.py b/code/experiments/templeGen.py new file mode 100644 index 0000000..5467617 --- /dev/null +++ b/code/experiments/templeGen.py @@ -0,0 +1,310 @@ +import tdl, colors, copy, pdb, traceback, os, sys, time +from random import * +from custom_except import * + + +WIDTH, HEIGHT, LIMIT = 150, 80, 20 +MAP_WIDTH, MAP_HEIGHT = 140, 60 +MID_MAP_WIDTH, MID_MAP_HEIGHT = MAP_WIDTH//2, MAP_HEIGHT//2 +MID_WIDTH, MID_HEIGHT = int(WIDTH/2), int(HEIGHT/2) + +CHANCE_TO_START_ALIVE = 65 +DEATH_LIMIT = 3 +BIRTH_LIMIT = 4 +STEPS_NUMBER = 2 +MIN_ROOM_SIZE = 6 + +rooms = [] +lastX = 0 +lastY = 0 +firstX = 0 +firstY = 0 + +curRoomIndex = 0 + +sys.setrecursionlimit(3000) + +if __name__ == '__main__': + root = tdl.init(WIDTH, HEIGHT, 'Dementia') + +class Tile: + def __init__(self, blocked, x, y, char = '#'): + self.blocked = blocked + self.x = x + self.y = y + self.char = char + self.indestructible = False + self.belongsTo = [] + self.fg = colors.lighter_grey + self.bg = colors.grey + self.pillar = False + + def setIndestructible(self): + self.blocked = True + self.indestructible = True + +class Rectangle: + def __init__(self, x, y, w, h): + self.x1 = x + self.y1 = y + self.x2 = x + w + self.y2 = y + h + self.tiles = [] + + def center(self): + center_x = (self.x1 + self.x2) // 2 + center_y = (self.y1 + self.y2) // 2 + return (center_x, center_y) + + def intersect(self, other): + return (self.x1 <= other.x2 and self.x2 >= other.x1 and + self.y1 <= other.y2 and self.y2 >= other.y1) + +def findNeighbours(mapToUse, startX, startY, stopAtFirst = False, cross = False): + found = False + for x in range(-1, 2): + for y in range(-1, 2): + if x == 0 and y == 0: + continue + else: + notCorner = not ((x==1 and y==1) or (x==1 and y==-1) or (x==-1 and y==-1) or (x==-1 and y==1)) + if not cross or notCorner: + otherX = startX + x + otherY = startY + y + if mapToUse[otherX][otherY].blocked: + found = True + if stopAtFirst: + break + if stopAtFirst and found: + break + return found + +def createRoom(room): + global myMap + for x in range(room.x1 + 1, room.x2): + for y in range(room.y1 + 1, room.y2): + myMap[x][y].blocked = False + myMap[x][y].char = None + centerPillar = randint(0, 2) + if centerPillar != 0: + myMap[room.x1 + 2][room.y1 + 2].pillar = True + myMap[room.x1 + 2][room.y1 + 2].char = 'o' + myMap[room.x1 + 2][room.y2 - 2].pillar = True + myMap[room.x1 + 2][room.y2 - 2].char = 'o' + myMap[room.x2 - 2][room.y1 + 2].pillar = True + myMap[room.x2 - 2][room.y1 + 2].char = 'o' + myMap[room.x2 - 2][room.y2 - 2].pillar = True + myMap[room.x2 - 2][room.y2 - 2].char = 'o' + else: + x, y = room.center() + myMap[x][y].pillar = True + myMap[x][y].char = 'o' + +def createHorizontalTunnel(x1, x2, y, big = False): + global myMap + for x in range(min(x1, x2), max(x1, x2) + 1): + myMap[x][y].blocked = False + if myMap[x][y].char == '#': + myMap[x][y].char = None + if big: + #pillar = 0 + for x in range(min(x1, x2) - 1, max(x1, x2) + 2): + myMap[x][y + 1].blocked = False + if myMap[x][y + 1].char == '#': + myMap[x][y + 1].char = None + myMap[x][y - 1].blocked = False + if myMap[x][y - 1].char == '#': + myMap[x][y - 1].char = None + #if pillar == 2: + # if findNeighbours(myMap, x, y - 1, True, True) and findNeighbours(myMap, x, y + 1, True, True): + # myMap[x][y - 1].pillar = True + # myMap[x][y - 1].char = 'o' + # myMap[x][y + 1].pillar = True + # myMap[x][y + 1].char = 'o' + # pillar = 0 + #else: + # pillar += 1 + +def createVerticalTunnel(y1, y2, x, big = False): + global myMap + for y in range(min(y1, y2), max(y1, y2) + 1): + myMap[x][y].blocked = False + if myMap[x][y].char == '#': + myMap[x][y].char = None + if big: + #pillar = 0 + for y in range(min(y1, y2) - 1, max(y1, y2) + 2): + myMap[x - 1][y].blocked = False + if myMap[x - 1][y].char == '#': + myMap[x - 1][y].char = None + myMap[x + 1][y].blocked = False + if myMap[x + 1][y].char == '#': + myMap[x + 1][y].char = None + #if pillar == 2: + # if findNeighbours(myMap, x - 1, y, True, True) and findNeighbours(myMap, x + 1, y, True, True): + # myMap[x - 1][y].pillar = True + # myMap[x - 1][y].char = 'o' + # myMap[x + 1][y].pillar = True + # myMap[x + 1][y].char = 'o' + # pillar = 0 + #else: + # pillar += 1 + +def secretRoomTest(startingX, endX, startingY, endY): + for x in range(startingX, endX): + for y in range(startingY, endY): + if not myMap[x][y].blocked: + if x >= 10 and x <= MAP_WIDTH - 10 and y >= 10 and y <= MAP_HEIGHT -10: + if myMap[x + 1][y].blocked: #right of the current tile + intersect = False + for indexX in range(9): + for indexY in range(9): + if not myMap[x + 1 + indexX][y - 4 + indexY].blocked: + intersect = True + break + if not intersect: + print("right") + return x + 1, y - 4, x + 1, y + if myMap[x - 1][y].blocked: #left + intersect = False + for indexX in range(9): + for indexY in range(9): + if not myMap[x - 1 - indexX][y - 4 + indexY].blocked: + intersect = True + break + if not intersect: + print("left") + return x - 9, y - 4, x - 1, y + if myMap[x][y + 1].blocked: #under + intersect = False + for indexX in range(9): + for indexY in range(9): + if not myMap[x - 4 + indexX][y + 1 + indexY].blocked: + intersect = True + break + if not intersect: + print("under") + return x - 4, y + 1, x, y + 1 + if myMap[x][y - 1].blocked: #above + intersect = False + for indexX in range(9): + for indexY in range(9): + if not myMap[x - 4 + indexX][y - 1 - indexY].blocked: + intersect = True + break + if not intersect: + print("above") + return x - 4, y - 9, x, y - 1 + +def secretRoom(): + global myMap + quarter = randint(1, 4) + if quarter == 1: + minX = 1 + maxX = MID_MAP_WIDTH + minY = 1 + maxY = MID_MAP_HEIGHT + if quarter == 2: + minX = MID_MAP_WIDTH + 1 + maxX = MAP_WIDTH + minY = 1 + maxY = MID_MAP_HEIGHT + if quarter == 3: + minX = 1 + maxX = MID_MAP_WIDTH + minY = MID_MAP_HEIGHT + 1 + maxY = MAP_HEIGHT + if quarter == 4: + minX = MID_MAP_WIDTH + 1 + maxX = MAP_WIDTH + minY = MID_MAP_HEIGHT + 1 + maxY = MAP_HEIGHT + [x, y, entryX, entryY] = secretRoomTest(minX, maxX, minY, maxY) + if not (x == 'cancelled' or y == 'cancelled' or entryX == 'cancelled' or entryY == 'cancelled'): + secretRoom = Rectangle(x, y, 8, 8) + createRoom(secretRoom) + myMap[entryX][entryY].blocked = False + myMap[entryX][entryY].char = '#' + myMap[entryX][entryY].fg = colors.red + myMap[x][y].blocked = False + print("created secret room at x ", entryX, " y ", entryY, " in quarter ", quarter) + +def checkMap(): + global myMap + for x in range(MAP_WIDTH): + for y in range(MAP_HEIGHT): + if myMap[x][y].hole and not myMap[x][y].indestructible: + myMap[x][y].blocked = False + +def makeMap(): + global myMap, rooms, firstX, firstY, lastX, lastY + + myMap = [[Tile(blocked = True, x = x, y = y) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. + rooms = [] + numberRooms = 0 + + for x in range(MAP_WIDTH): + myMap[x][0].setIndestructible() + myMap[x][MAP_HEIGHT - 1].setIndestructible() + for y in range(MAP_HEIGHT): + myMap[0][y].setIndestructible() + myMap[MAP_WIDTH - 1][y].setIndestructible() + + for r in range(30): + w = randint(10, 16) + h = randint(10, 16) + x = randint(0, MAP_WIDTH-w-1) + y = randint(0, MAP_HEIGHT-h-1) + newRoom = Rectangle(x, y, w, h) + intersection = False + for otherRoom in rooms: + if newRoom.intersect(otherRoom): + intersection = True + break + if not intersection: + createRoom(newRoom) + lastCreatedRoom = newRoom + (new_x, new_y) = newRoom.center() + if numberRooms != 0: + (previous_x, previous_y) = rooms[numberRooms-1].center() + bigTunnel = randint(0, 4) + big = bigTunnel == 0 + if randint(0, 1): + createHorizontalTunnel(previous_x, new_x, previous_y, big) + createVerticalTunnel(previous_y, new_y, new_x, big) + else: + createVerticalTunnel(previous_y, new_y, previous_x, big) + createHorizontalTunnel(previous_x, new_x, new_y, big) + else: + firstX, firstY = new_x, new_y + rooms.append(newRoom) + numberRooms += 1 + lastX, lastY = new_x, new_y + + secretRoom() + #checkMap() + +myMap = [[]] + +def update(mapToUse): + root.clear() + try: + for x in range(MAP_WIDTH): + for y in range(MAP_HEIGHT): + root.draw_char(x, y, char = mapToUse[x][y].char, fg = mapToUse[x][y].fg, bg = mapToUse[x][y].bg) + if (x, y) == (firstX, firstY): + root.draw_char(x, y, char = 'X', fg = colors.red, bg = mapToUse[x][y].bg) + if (x, y) == (lastX, lastY): + root.draw_char(x, y, char = 'X', fg = colors.green, bg = mapToUse[x][y].bg) + + except IndexError: + traceback.print_exc() + os._exit(-1) + + tdl.flush() + +if __name__ == '__main__': + makeMap() + while not tdl.event.is_window_closed(): + update(myMap) + diff --git a/main.py b/main.py index cabbe46..df684f3 100644 --- a/main.py +++ b/main.py @@ -6104,9 +6104,9 @@ def makeMap(generateChasm = True, generateHole = False, fall = False): fallen = True updateTileCoords() -def makeBossLevel(fall = False): +def makeBossLevel(fall = False, generateHole=False): global myMap, objects, upStairs, rooms, numberRooms - myMap = [[Tile(True, x = x, y = y, wall = True) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. + myMap = [[Tile(True, x = x, y = y, wall = True, hole = generateHole) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. objects = [player] rooms = [] numberRooms = 0 @@ -6178,6 +6178,9 @@ def makeBossLevel(fall = False): (previous_x, previous_y) = bossRoom.center() rooms.append(bossRoom) numberRooms += 1 + if generateHole: + myMap = holeGen.createHoles(myMap) + checkMap() if fall: fallen = False @@ -7218,11 +7221,13 @@ def getAllWeights(object): def checkLoad(): load = getAllWeights(player) - burdened = Buff('burdened', colors.yellow, 99999, showCooldown=False) if load > player.Player.maxWeight: + burdened = Buff('burdened', colors.yellow, 99999, showCooldown=False) burdened.applyBuff(player) - if load < player.Player.maxWeight and 'burdened' in convertBuffsToNames(player.Fighter): - burdened.removeBuff() + if load <= player.Player.maxWeight and 'burdened' in convertBuffsToNames(player.Fighter): + for buff in player.Fighter.buffList: + if buff.name == 'burdened': + buff.removeBuff() def lootItem(object, x, y): objects.append(object) @@ -8700,13 +8705,13 @@ def nextLevel(boss = False, changeBranch = None, fixedMap = None, fall = False): stairs = tempStairs chasmGeneration = False holeGeneration = False + for feature in currentBranch.genFeatures: + if feature == 'chasms': + chasmGeneration = True + if feature == 'holes': + holeGeneration = True if not boss: if currentBranch.fixedMap is None: - for feature in currentBranch.genFeatures: - if feature == 'chasms': - chasmGeneration = True - if feature == 'holes': - holeGeneration = True if currentBranch.genType == 'dungeon': makeMap(generateChasm=chasmGeneration, generateHole=holeGeneration, fall = fall) elif currentBranch.genType == 'cave': @@ -8716,7 +8721,7 @@ def nextLevel(boss = False, changeBranch = None, fixedMap = None, fall = False): else: raise ValueError('Current branch fixedMap attribute is invalid ({})'.format(currentBranch.fixedMap)) else: - makeBossLevel(fall = fall) + makeBossLevel(fall = fall, generateHole = holeGeneration) print("Created a new level") print("After try except block") if hiroshimanNumber == 1 and not hiroshimanHasAppeared: From f9a35e6d863ec7ed8fe54f4121c13738d651c41e Mon Sep 17 00:00:00 2001 From: Edern76 Date: Tue, 9 May 2017 10:43:50 +0200 Subject: [PATCH 14/32] Tried fixing falling into non existent chasms --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index df684f3..5f98a0e 100644 --- a/main.py +++ b/main.py @@ -4376,7 +4376,7 @@ def moveOrAttack(dx, dy): if not 'confused' in convertBuffsToNames(player.Fighter): x = player.x + dx y = player.y + dy - if myMap[x][y].chasm: + if myMap[x][y].chasm and not myMap[x][y].wall: temporaryBox('You fall deeper into the dungeon...') if dungeonLevel + 1 in currentBranch.bossLevels: nextLevel(boss = True, fall = True) From 28b25477787ec8a8d51184101764c910bcc256f6 Mon Sep 17 00:00:00 2001 From: Edern76 Date: Tue, 9 May 2017 11:38:28 +0200 Subject: [PATCH 15/32] Added teleport spell and unfucked spell cooldowns --- main.py | 84 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/main.py b/main.py index 5f98a0e..c2f2808 100644 --- a/main.py +++ b/main.py @@ -1010,6 +1010,20 @@ def castAstarPath(caster = None, monsterTarget = None): Update() return +def castTeleportTo(caster = None, monsterTarget = None): + global FOV_recompute + (goalX, goalY) = targetAnyTile(startX = player.x, startY = player.y) + if targetTile == 'cancelled': + return 'cancelled' + else: + if not myMap[goalX][goalY].blocked and not myMap[goalX][goalY].chasm: + player.x = goalX + player.y = goalY + return + else: + message("Cannot teleport there !", colors.red) + return 'cancelled' + fireball = Spell(ressourceCost = 7, cooldown = 5, useFunction = castFireball, name = "Fireball", ressource = 'MP', type = 'Magic', magicLevel = 1, arg1 = 1, arg2 = 12, arg3 = 4) heal = Spell(ressourceCost = 15, cooldown = 12, useFunction = castHeal, name = 'Heal self', ressource = 'MP', type = 'Magic', magicLevel = 2, arg1 = 20) @@ -1019,12 +1033,13 @@ def castAstarPath(caster = None, monsterTarget = None): confuse = Spell(ressourceCost = 5, cooldown = 4, useFunction = castConfuse, name = 'Confusion', ressource = 'MP', type = 'Magic', magicLevel = 1) ice = Spell(ressourceCost = 9, cooldown = 5, useFunction = castFreeze, name = 'Ice bolt', ressource = 'MP', type = 'Magic', magicLevel = 2) ressurect = Spell(ressourceCost = 10, cooldown = 15, useFunction=castRessurect, name = "Dark ressurection", ressource = 'MP', type = "Occult", arg1 = 4) -placeTag = Spell(ressourceCost = 0, cooldown = 0, useFunction=castPlaceTag, name = 'DEBUG : Place tag', ressource = 'MP', type = 'Occult') -drawRect = Spell(ressourceCost = 0, cooldown = 0, useFunction=castDrawRectangle, name = 'DEBUG : Draw Rectangle', ressource = 'MP', type = 'Occult') +placeTag = Spell(ressourceCost = 0, cooldown = 1, useFunction=castPlaceTag, name = 'DEBUG : Place tag', ressource = 'MP', type = 'Occult') +drawRect = Spell(ressourceCost = 0, cooldown = 1, useFunction=castDrawRectangle, name = 'DEBUG : Draw Rectangle', ressource = 'MP', type = 'Occult') envenom = Spell(ressourceCost= 3, cooldown = 20, useFunction=castEnvenom, name = 'Envenom weapons', ressource='MP', type = 'Racial') -drawAstarPath = Spell(ressourceCost = 0, cooldown = 0, useFunction=castAstarPath, name = 'DEBUG : Draw A* path', ressource = 'MP', type = 'Occult') +drawAstarPath = Spell(ressourceCost = 0, cooldown = 1, useFunction=castAstarPath, name = 'DEBUG : Draw A* path', ressource = 'MP', type = 'Occult') +teleport = Spell(ressourceCost = 0, cooldown = 1, useFunction=castTeleportTo, name = 'DEBUG : Teleport', ressource = 'HP', type = 'Occult') -spells.extend([fireball, heal, darkPact, enrage, lightning, confuse, ice, ressurect, placeTag, drawRect, drawAstarPath]) +spells.extend([fireball, heal, darkPact, enrage, lightning, confuse, ice, ressurect, placeTag, drawRect, drawAstarPath, teleport]) #_____________SPELLS_____________ #______________CHARACTER GENERATION____________ @@ -8791,31 +8806,11 @@ def playGame(): print(object.name) print("============================================") print("============================================") - while mustCalculate: - print("Calculating") - pathfinders = [] - mustCalculate = False - print(len(mobsToCalculate)) - for mob in mobsToCalculate: - newPathfinder = Pathfinder(mob, mob.AI.selectedTarget.x, mob.AI.selectedTarget.y) - pathfinders.append(newPathfinder) - - for pathfind in pathfinders: - pathfind.start() - for pathfind in pathfinders: - pathfind.join() - - for mob in mobsToCalculate: - mob.AI.tryMove() - - - - if object.Fighter and object.Fighter.baseShootCooldown > 0 and object.Fighter is not None: object.Fighter.curShootCooldown -= 1 if object.Fighter and object.Fighter.baseLandCooldown > 0 and object.Fighter is not None: object.Fighter.curLandCooldown -= 1 - + if object.Fighter and object.Fighter.spellsOnCooldown and object.Fighter is not None: try: for spell in object.Fighter.spellsOnCooldown: @@ -8827,8 +8822,14 @@ def playGame(): object.Fighter.knownSpells.append(spell) if object == player: message(spell.name + " is now ready.") - except: + except Exception as error: + traceback.print_exc() + message("OMG SPELLS NOT WORKING SEE CONSOLE", colors.red) continue + else: + if object.Fighter: + print("{} has no spell on cooldown".format(object.name)) + if object.Fighter and object.Fighter.MP < object.Fighter.maxMP and object.Fighter is not None: object.Fighter.MPRegenCountdown -= 1 if object.Fighter.MPRegenCountdown < 0: @@ -8842,7 +8843,7 @@ def playGame(): else: object.Fighter.MPRegenCountdown = 10 object.Fighter.MP += 1 - + if object.Player is not None: if NATURAL_REGEN: monsterInSight = False @@ -8857,7 +8858,7 @@ def playGame(): if player.Fighter.healCountdown == 0: player.Fighter.heal(1) player.Fighter.healCountdown= 25 - player.Player.vitality - + if object.Player and object.Player.race == 'Werewolf': def shapeshift(fighter, fromWolf = False, fromHuman = True): if fromWolf: @@ -8866,7 +8867,7 @@ def shapeshift(fighter, fromWolf = False, fromHuman = True): if fromHuman: player.Player.shapeshift = 'wolf' object.Player.shapeshifted = True - + human = Buff('human', colors.lightest_yellow, cooldown = player.Player.human, showBuff = False, applyFunction = lambda fighter: setFighterStatsBack(fighter), removeFunction = lambda fighter: shapeshift(fighter)) wolf = Buff('in wolf form', colors.amber, cooldown = player.Player.wolf, applyFunction = lambda fighter: modifyFighterStats(fighter, str = 5, dex = 3, vit = 4, will = -5), removeFunction = lambda fighter: shapeshift(fighter, fromHuman=False, fromWolf=True)) if object.Player.shapeshifted: @@ -8906,7 +8907,26 @@ def shapeshift(fighter, fromWolf = False, fromHuman = True): if object.Fighter and object.Fighter is not None: for buff in object.Fighter.buffList: buff.passTurn() - + + + while mustCalculate: + print("Calculating") + pathfinders = [] + mustCalculate = False + print(len(mobsToCalculate)) + for mob in mobsToCalculate: + newPathfinder = Pathfinder(mob, mob.AI.selectedTarget.x, mob.AI.selectedTarget.y) + pathfinders.append(newPathfinder) + + for pathfind in pathfinders: + pathfind.start() + for pathfind in pathfinders: + pathfind.join() + + for mob in mobsToCalculate: + mob.AI.tryMove() + + for x in range(MAP_WIDTH): for y in range(MAP_HEIGHT): if myMap[x][y].acid: @@ -8951,7 +8971,9 @@ def shapeshift(fighter, fromWolf = False, fromHuman = True): prevStatus = player.Player.hungerStatus player.Player.hungerStatus = "full" if prevStatus != "full": - message("You feel way less hungry") + message("You feel way less hungry") + + actions = 1 if player.Player.speed == 'fast' and randint(1, 100) <= player.Player.speedChance: From 3e4551d69cb126036b64b51a503811ee8b9cca72 Mon Sep 17 00:00:00 2001 From: Edern76 Date: Tue, 9 May 2017 11:59:47 +0200 Subject: [PATCH 16/32] Started working on spellgeneration --- code/nameGen.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/code/nameGen.py b/code/nameGen.py index 053555e..e5c555d 100644 --- a/code/nameGen.py +++ b/code/nameGen.py @@ -1,6 +1,42 @@ from random import randint from code.constants import * +class SpellTemplate: + def __init__(self): + self.type = None + self.targeting = None + self.zone = None + self.eff1 = None + self.eff2 = None + self.eff3 = None + +class NumberedEffect: + def __init__(self, name, amount): + self.name = name + self.amount = amount + +class DoubleNumberedEffect: + def __init__(self, name, initAmount, doubleAmount): + self.name = name + self.initAmount = initAmount + self.doubleAmount = doubleAmount + + +class BetterList(list): + def __init__(self): + list.__init__() + def removeFrom(self, element): + ind = self.index(element) + self.remove(self[ind]) + + +def createSpell(): + typeList = ["Attack", "Buff", "Heal", "Mixed"] + targetList = ["Select", "Self", "Closest", "Farthest"] + zoneList = ["SingleTile", "Cross", "AOE"] + + attackList = [""] + def humanLike(length = randint(6, 12)): #Generates pronouncable, human sounding like names (in theory) From 4f904541f599dac03228933aa3b61750008b5012 Mon Sep 17 00:00:00 2001 From: Edern76 Date: Wed, 10 May 2017 13:25:00 +0200 Subject: [PATCH 17/32] Moved spell generation to its own module and continued working on it Why I didn't do this right from the start is beyond me. --- code/nameGen.py | 29 +++++++++++++++++++---------- code/spellGen.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 code/spellGen.py diff --git a/code/nameGen.py b/code/nameGen.py index e5c555d..759705e 100644 --- a/code/nameGen.py +++ b/code/nameGen.py @@ -1,5 +1,6 @@ from random import randint from code.constants import * +from nameGen import BetterList class SpellTemplate: def __init__(self): @@ -16,26 +17,34 @@ def __init__(self, name, amount): self.amount = amount class DoubleNumberedEffect: - def __init__(self, name, initAmount, doubleAmount): + def __init__(self, name, initAmount, overtimeAmount): self.name = name self.initAmount = initAmount - self.doubleAmount = doubleAmount + self.overtimeAmount = overtimeAmount - class BetterList(list): - def __init__(self): - list.__init__() + def __init__(self, *args): + super(BetterList, self).__init__(args[0]) + def removeFrom(self, element): ind = self.index(element) self.remove(self[ind]) + + def randFrom(self): + ind = randint(0, len(self) - 1) + return self[ind] -def createSpell(): - typeList = ["Attack", "Buff", "Heal", "Mixed"] - targetList = ["Select", "Self", "Closest", "Farthest"] - zoneList = ["SingleTile", "Cross", "AOE"] +def createEffect(): + typeList = BetterList("Attack", "Buff", "Heal") + targetList = BetterList("Select", "Self", "Closest", "Farthest") + zoneList = BetterList("SingleTile", "Cross", "AOE") + + attackList = BetterList("Fire", "Physical", "Poison") + buffList = BetterList("Hunger", "AttackUp") + healList = BetterList("HP", "MP", "CureFire", "CurePoison") + - attackList = [""] def humanLike(length = randint(6, 12)): diff --git a/code/spellGen.py b/code/spellGen.py new file mode 100644 index 0000000..7f02085 --- /dev/null +++ b/code/spellGen.py @@ -0,0 +1,45 @@ +from random import randint +from code.constants import * + +class SpellTemplate: + def __init__(self): + self.type = None + self.targeting = None + self.zone = None + self.eff1 = None + self.eff2 = None + self.eff3 = None + +class NumberedEffect: + def __init__(self, name, amount): + self.name = name + self.amount = amount + +class DoubleNumberedEffect: + def __init__(self, name, initAmount, overtimeAmount): + self.name = name + self.initAmount = initAmount + self.overtimeAmount = overtimeAmount + +class BetterList(list): + def __init__(self, *args): + super(BetterList, self).__init__(args[0]) + + def removeFrom(self, element): + ind = self.index(element) + self.remove(self[ind]) + + def randFrom(self): + ind = randint(0, len(self) - 1) + return self[ind] + + +def createEffect(): + typeList = BetterList("Attack", "Buff", "Heal") + targetList = BetterList("Select", "Self", "Closest", "Farthest") + zoneList = BetterList("SingleTile", "Cross", "AOE") + + attackList = BetterList("Fire", "Physical", "Poison") + buffList = BetterList("Hunger", "AttackUp") + healList = BetterList("HP", "MP", "CureFire", "CurePoison") + \ No newline at end of file From f076678c2946e0136c0cf7a32d3d0d80db2d9ee1 Mon Sep 17 00:00:00 2001 From: Edern76 Date: Wed, 10 May 2017 16:01:06 +0200 Subject: [PATCH 18/32] Actually removed spell gen from nameGen module --- code/nameGen.py | 46 ---------------------------------------------- code/spellGen.py | 1 + 2 files changed, 1 insertion(+), 46 deletions(-) diff --git a/code/nameGen.py b/code/nameGen.py index 759705e..317b780 100644 --- a/code/nameGen.py +++ b/code/nameGen.py @@ -1,51 +1,5 @@ from random import randint from code.constants import * -from nameGen import BetterList - -class SpellTemplate: - def __init__(self): - self.type = None - self.targeting = None - self.zone = None - self.eff1 = None - self.eff2 = None - self.eff3 = None - -class NumberedEffect: - def __init__(self, name, amount): - self.name = name - self.amount = amount - -class DoubleNumberedEffect: - def __init__(self, name, initAmount, overtimeAmount): - self.name = name - self.initAmount = initAmount - self.overtimeAmount = overtimeAmount - -class BetterList(list): - def __init__(self, *args): - super(BetterList, self).__init__(args[0]) - - def removeFrom(self, element): - ind = self.index(element) - self.remove(self[ind]) - - def randFrom(self): - ind = randint(0, len(self) - 1) - return self[ind] - - -def createEffect(): - typeList = BetterList("Attack", "Buff", "Heal") - targetList = BetterList("Select", "Self", "Closest", "Farthest") - zoneList = BetterList("SingleTile", "Cross", "AOE") - - attackList = BetterList("Fire", "Physical", "Poison") - buffList = BetterList("Hunger", "AttackUp") - healList = BetterList("HP", "MP", "CureFire", "CurePoison") - - - def humanLike(length = randint(6, 12)): #Generates pronouncable, human sounding like names (in theory) diff --git a/code/spellGen.py b/code/spellGen.py index 7f02085..d316bd1 100644 --- a/code/spellGen.py +++ b/code/spellGen.py @@ -42,4 +42,5 @@ def createEffect(): attackList = BetterList("Fire", "Physical", "Poison") buffList = BetterList("Hunger", "AttackUp") healList = BetterList("HP", "MP", "CureFire", "CurePoison") + \ No newline at end of file From 833440034b049b8b7b04835c4dc6d324195625d2 Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Thu, 11 May 2017 20:03:43 +0200 Subject: [PATCH 19/32] Started identify system --- main.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index c2f2808..8987422 100644 --- a/main.py +++ b/main.py @@ -1736,6 +1736,16 @@ def __init__(self, x, y, char, name, color = colors.white, blocks = False, Fight self.socialComp = socialComp self.shopComp = shopComp self.questList = questList + + @property + def name(self): + if self.Item: + if self.Item.identified: + return self.name + else: + return self.Item.unIDName + else: + return self.name def moveTowards(self, target_x, target_y): dx = target_x - self.x @@ -3018,7 +3028,7 @@ def absorb(self): player.Player.speedChance += boost class Item: - def __init__(self, useFunction = None, arg1 = None, arg2 = None, arg3 = None, stackable = False, amount = 1, weight = 0, description = 'Placeholder.', pic = 'trollMace.xp', itemtype = None): + def __init__(self, useFunction = None, arg1 = None, arg2 = None, arg3 = None, stackable = False, amount = 1, weight = 0, description = 'Placeholder.', pic = 'trollMace.xp', itemtype = None, identified = True, unIDName = 'Unidentified'): self.useFunction = useFunction self.arg1 = arg1 self.arg2 = arg2 @@ -3029,7 +3039,18 @@ def __init__(self, useFunction = None, arg1 = None, arg2 = None, arg3 = None, s self.description = description self.pic = pic self.type = itemtype - + self.identified = identified + self.unIDName = unIDName + + def identify(self): + self.identified = True + for object in objects: + if object.Item.unIDName == self.unIDName: + object.Item.identified = True + for object in inventory: + if object.Item.unIDName == self.unIDName: + object.Item.identified = True + def pickUp(self, silent = False, inObjects = True): if not self.stackable: #if len(inventory)>=26: From 8a8024a5c830c92f84afbcb905331904dd21f954 Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Thu, 11 May 2017 22:24:42 +0200 Subject: [PATCH 20/32] Continued Identifying system Almost done, need to modify item pic and description --- main.py | 126 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 92 insertions(+), 34 deletions(-) diff --git a/main.py b/main.py index 8987422..d8255c7 100644 --- a/main.py +++ b/main.py @@ -226,6 +226,7 @@ def __init__(self, name, width, height, type = 'noType'): FOV_recompute = True inventory = [] #Player inventory equipmentList = [] #Player equipment +identifiedItems = [] activeSounds = [] spells = [] #List of all spells in the game @@ -1705,7 +1706,7 @@ def __init__(self, x, y, char, name, color = colors.white, blocks = False, Fight self.char = char self.color = color self.blocks = blocks - self.name = name + self.trueName = name self.Fighter = Fighter self.Player = Player self.ghost = Ghost @@ -1731,8 +1732,7 @@ def __init__(self, x, y, char, name, color = colors.white, blocks = False, Fight self.astarPath = [] self.lastTargetX = None self.lastTargetY = None - self.pluralName = pName - self.pName = self.pluralName + self.pName = pName self.socialComp = socialComp self.shopComp = shopComp self.questList = questList @@ -1741,11 +1741,21 @@ def __init__(self, x, y, char, name, color = colors.white, blocks = False, Fight def name(self): if self.Item: if self.Item.identified: - return self.name + return self.trueName else: return self.Item.unIDName else: - return self.name + return self.trueName + + @property + def pluralName(self): + if self.Item: + if self.Item.identified: + return self.pName + else: + return self.Item.unIDpName + else: + return self.pName def moveTowards(self, target_x, target_y): dx = target_x - self.x @@ -3028,7 +3038,7 @@ def absorb(self): player.Player.speedChance += boost class Item: - def __init__(self, useFunction = None, arg1 = None, arg2 = None, arg3 = None, stackable = False, amount = 1, weight = 0, description = 'Placeholder.', pic = 'trollMace.xp', itemtype = None, identified = True, unIDName = 'Unidentified'): + def __init__(self, useFunction = None, arg1 = None, arg2 = None, arg3 = None, stackable = False, amount = 1, weight = 0, description = 'Placeholder.', pic = 'trollMace.xp', itemtype = None, identified = True, unIDName = 'Unidentified', unIDpName = 'UnidentifiedS'): self.useFunction = useFunction self.arg1 = arg1 self.arg2 = arg2 @@ -3041,15 +3051,20 @@ def __init__(self, useFunction = None, arg1 = None, arg2 = None, arg3 = None, s self.type = itemtype self.identified = identified self.unIDName = unIDName + self.unIDpName = unIDpName def identify(self): + global identifiedItems self.identified = True + identifiedItems.append(self.unIDName) for object in objects: - if object.Item.unIDName == self.unIDName: - object.Item.identified = True + if object.Item: + if object.Item.unIDName == self.unIDName: + object.Item.identified = True for object in inventory: - if object.Item.unIDName == self.unIDName: - object.Item.identified = True + if object.Item: + if object.Item.unIDName == self.unIDName: + object.Item.identified = True def pickUp(self, silent = False, inObjects = True): if not self.stackable: @@ -3105,6 +3120,7 @@ def use(self): if equipping == 'didnt-take-turn' or equipping == 'cancelled': return 'didnt-take-turn' else: + self.identify() return if self.useFunction is None: message('The ' + self.owner.name + ' cannot be used !') @@ -3120,7 +3136,7 @@ def use(self): self.amount = 0 if self.amount == 0: inventory.remove(self.owner) - + self.identify() else: return 'cancelled' elif self.arg2 is None and self.arg1 is not None: @@ -3133,6 +3149,7 @@ def use(self): self.amount = 0 if self.amount == 0: inventory.remove(self.owner) + self.identify() else: return 'cancelled' elif self.arg3 is None and self.arg2 is not None: @@ -3145,6 +3162,7 @@ def use(self): self.amount = 0 if self.amount == 0: inventory.remove(self.owner) + self.identify() else: return 'cancelled' elif self.arg3 is not None: @@ -3157,6 +3175,7 @@ def use(self): self.amount = 0 if self.amount == 0: inventory.remove(self.owner) + self.identify() else: return 'cancelled' @@ -3747,8 +3766,8 @@ def formatName(self): raise NotEqualToExpectedValueException('ItemComp is different from the Item component of the actual object') ''' if self.stock > 1: - if o.pName: - name = str(self.stock) + ' ' + o.pName + if o.pluralName: + name = str(self.stock) + ' ' + o.pluralName else: name = str(self.stock) + ' ' + o.name + 's' else: @@ -5703,6 +5722,7 @@ def generateCave(fall = False): stairs = GameObject(sX, sY, '>', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor) objects.append(stairs) stairs.sendToBack() + applyIdentification() for room in rooms: if room == rooms[0]: placeObjects(room, True) @@ -5977,6 +5997,7 @@ def makeMap(generateChasm = True, generateHole = False, fall = False): myMap = holeGen.createHoles(myMap) checkMap() + applyIdentification() r = 0 for room in rooms: if r == 0: @@ -6321,7 +6342,7 @@ def basicBossDeath(monster): monster.color = colors.dark_red monster.blocks = False monster.AI = None - monster.name = 'remains of ' + monster.name + monster.trueName = 'remains of ' + monster.name monster.Fighter = None monster.sendToBack() createEndRooms() @@ -6331,7 +6352,7 @@ def fatDeath(monster): global deathX, deathY monster.char = '%' monster.color = colors.dark_red - monster.name = 'some mangled fat' + monster.trueName = 'some mangled fat' monster.blocks = False monster.AI = None monster.Fighter = None @@ -6433,7 +6454,7 @@ def gluttonysDeath(monster): monster.color = colors.dark_red monster.blocks = False monster.AI = None - monster.name = 'remains of ' + monster.name + monster.trueName = 'remains of ' + monster.name monster.Fighter = None monster.sendToBack() for object in objects: @@ -6606,6 +6627,11 @@ def placeBoss(name, x, y): #_____________ BOSS FIGHT __________________ #_____________ ROOM POPULATION + ITEMS GENERATION_______________ +potionIdentify = {} +scrollIdentify = {} +colorDict = {'blue': colors.blue, 'red': colors.red, 'violet': colors.violet} +nameDict = ['Ewaz', 'Vuzin', 'Armuz', 'Gowid', 'Ansuz', 'Juman', 'Ji', 'Morwen'] + def createSword(x, y): name = 'sword' pic = 'shortSword.xp' @@ -6810,27 +6836,48 @@ def createWeapon(x, y): def createScroll(x, y): scrollChances = currentBranch.scrollChances scrollChoice = randomChoice(scrollChances) + unIdentifiedName = 'scroll of ' + scrollIdentify[scrollChoice] + pName = unIdentifiedName = 'scrolls of ' + scrollIdentify[scrollChoice] + identified = False + if unIdentifiedName in identifiedItems: + identified = True if scrollChoice == 'lightning': - scroll = GameObject(x, y, '~', 'scroll of lightning bolt', colors.light_yellow, Item = Item(useFunction = castLightning, weight = 0.3, stackable = True), blocks = False, pName = 'scrolls of lightning bolt') + scroll = GameObject(x, y, '~', 'scroll of lightning bolt', colors.light_yellow, Item = Item(useFunction = castLightning, weight = 0.3, stackable = True, unIDName=unIdentifiedName, identified=identified, unIDpName=pName), blocks = False, pName = 'scrolls of lightning bolt') elif scrollChoice == 'confuse': - scroll = GameObject(x, y, '~', 'scroll of confusion', colors.light_yellow, Item = Item(useFunction = castConfuse, weight = 0.3, stackable = True), blocks = False, pName = 'scrolls of confusion') + scroll = GameObject(x, y, '~', 'scroll of confusion', colors.light_yellow, Item = Item(useFunction = castConfuse, weight = 0.3, stackable = True, unIDName=unIdentifiedName, identified=identified, unIDpName=pName), blocks = False, pName = 'scrolls of confusion') elif scrollChoice == 'fireball': fireballChances = {'lesser': 20, 'normal': 50, 'greater': 20} fireballChoice = randomChoice(fireballChances) if fireballChoice == 'lesser': - scroll = GameObject(x, y, '~', 'scroll of lesser fireball', colors.light_yellow, Item = Item(castFireball, 2, 12, weight = 0.3, stackable = True), blocks = False, pName = 'scrolls of lesser fireball') + scroll = GameObject(x, y, '~', 'scroll of lesser fireball', colors.light_yellow, Item = Item(castFireball, 2, 12, weight = 0.3, stackable = True, unIDName=unIdentifiedName, identified=identified, unIDpName=pName), blocks = False, pName = 'scrolls of lesser fireball') elif fireballChoice == 'normal': - scroll = GameObject(x, y, '~', 'scroll of fireball', colors.light_yellow, Item = Item(castFireball, weight = 0.3, stackable = True), blocks = False, pName = 'scrolls of fireball') + scroll = GameObject(x, y, '~', 'scroll of fireball', colors.light_yellow, Item = Item(castFireball, weight = 0.3, stackable = True, unIDName=unIdentifiedName, identified=identified, unIDpName=pName), blocks = False, pName = 'scrolls of fireball') elif fireballChoice == 'greater': - scroll = GameObject(x, y, '~', 'scroll of greater fireball', colors.light_yellow, Item = Item(castFireball, 4, 48, weight = 0.3, stackable = True), blocks = False, pName = 'scrolls of greater fireball') + scroll = GameObject(x, y, '~', 'scroll of greater fireball', colors.light_yellow, Item = Item(castFireball, 4, 48, weight = 0.3, stackable = True, unIDName=unIdentifiedName, identified=identified, unIDpName=pName), blocks = False, pName = 'scrolls of greater fireball') elif scrollChoice == 'armageddon': - scroll = GameObject(x, y, '~', 'scroll of armageddon', colors.red, Item = Item(castArmageddon, weight = 0.3, stackable = True), blocks = False, pName = 'scrolls of armageddon') + scroll = GameObject(x, y, '~', 'scroll of armageddon', colors.red, Item = Item(castArmageddon, weight = 0.3, stackable = True, unIDName=unIdentifiedName, identified=identified, unIDpName=pName), blocks = False, pName = 'scrolls of armageddon') elif scrollChoice == 'ice': - scroll = GameObject(x, y, '~', 'scroll of ice bolt', colors.light_cyan, Item = Item(castFreeze, weight = 0.3, stackable = True, amount = randint(1, 3)), blocks = False, pName = 'scrolls of ice bolt') + scroll = GameObject(x, y, '~', 'scroll of ice bolt', colors.light_cyan, Item = Item(castFreeze, weight = 0.3, stackable = True, amount = randint(1, 3), unIDName=unIdentifiedName, identified=identified, unIDpName=pName), blocks = False, pName = 'scrolls of ice bolt') elif scrollChoice == 'none': scroll = None return scroll +def createPotion(x, y): + potionChances = currentBranch.potionChances + potionChoice = randomChoice(potionChances) + name, color = potionIdentify[potionChoice] + unIdentifiedName = name + ' potion' + pName = name + ' potions' + identified = False + if unIdentifiedName in identifiedItems: + identified = True + if potionChoice == 'heal': + potion = GameObject(x, y, '!', 'healing potion', color, Item = Item(useFunction = castHeal, weight = 0.4, stackable=True, amount = randint(1, 2), pic = "redpotion.xp", description = "A slighly bubbling red beverage that stimulates cell growth when ingested, which allows for wounds to heal signifcantly faster. However, it also notably increases risk of cancer, but if you're in a situation where you have to drink such a potion, this is probably one of the least of your worries.", unIDName=unIdentifiedName, identified=identified, unIDpName=pName), blocks = False) + if potionChoice == 'mana': + potion = GameObject(x, y, '!', 'mana regeneration potion', color, Item = Item(useFunction = castRegenMana, arg1 = 10, weight = 0.4, stackable = True, pic = "smokybluepotion.xp", description = "The blueish smokes emanating from this potion scared more than one novice mage, but it actually tastes quite good and has no other short-term effect other than replenishing your life-force. However, the [PLACEHOLDER WORLD (the 'normal' one, not Realm of Madness) NAME]'s Guild of Alchemists is still debating about whether or not it causes detrimental long-term effects.", unIDName=unIdentifiedName, identified=identified, unIDpName=pName), blocks = False) + + return potion + def createSpellbook(x, y): spellbookChances = currentBranch.spellbookChances spellbookChoice = randomChoice(spellbookChances) @@ -7117,11 +7164,7 @@ def placeObjects(room, first = False): if not isBlocked(x, y) and not myMap[x][y].chasm: itemChoice = randomChoice(itemChances) if itemChoice == 'potion': - potionChoice = randomChoice(potionChances) - if potionChoice == 'heal': - item = GameObject(x, y, '!', 'healing potion', colors.violet, Item = Item(useFunction = castHeal, weight = 0.4, stackable=True, amount = randint(1, 2), pic = "redpotion.xp", description = "A slighly bubbling red beverage that stimulates cell growth when ingested, which allows for wounds to heal signifcantly faster. However, it also notably increases risk of cancer, but if you're in a situation where you have to drink such a potion, this is probably one of the least of your worries."), blocks = False) - if potionChoice == 'mana': - item = GameObject(x, y, '!', 'mana regeneration potion', colors.blue, Item = Item(useFunction = castRegenMana, arg1 = 10, weight = 0.4, stackable = True, pic = "smokybluepotion.xp", description = "The blueish smokes emanating from this potion scared more than one novice mage, but it actually tastes quite good and has no other short-term effect other than replenishing your life-force. However, the [PLACEHOLDER WORLD (the 'normal' one, not Realm of Madness) NAME]'s Guild of Alchemists is still debating about whether or not it causes detrimental long-term effects."), blocks = False) + item = createPotion(x, y) elif itemChoice == 'scroll': item = createScroll(x, y) elif itemChoice == 'none': @@ -7208,6 +7251,21 @@ def pieDebuff(amount, text): if 'highCultist' in monsterChances.keys(): print('Reverting high cultist chances to previous value (current : {} / previous : {})'.format(monsterChances['highCultist'], previousHighCultistChances)) monsterChances['highCultist'] = previousHighCultistChances + +def applyIdentification(): + global potionIdentify, scrollIdentify, colorDict, nameDict + + for potion, u in currentBranch.potionChances.items(): + if not potion in potionIdentify: + colorName, color = choice(list(colorDict.items())) + del colorDict[colorName] + potionIdentify[potion] = (colorName, color) + + for scroll, u in currentBranch.scrollChances.items(): + if not scroll in scrollIdentify: + name = nameDict.pop(randint(0, len(nameDict) - 1)) + scrollIdentify[scroll] = name + #_____________ ROOM POPULATION + ITEMS GENERATION_______________ #_____________ EQUIPMENT ________________ @@ -7273,7 +7331,7 @@ def lootItem(object, x, y): if object.Item and object.Item.amount <= 1: message('A ' + object.name + ' falls from the dead body!', colors.dark_sky) elif object.Item: - message(str(object.Item.amount) + ' ' + object.pName + ' fall from the dead body!', colors.dark_sky) + message(str(object.Item.amount) + ' ' + object.pluralName + ' fall from the dead body!', colors.dark_sky) else: message('A ' + object.name + ' falls from the dead body!', colors.dark_sky) @@ -7488,15 +7546,14 @@ def monsterDeath(monster): for item in monster.Fighter.lootFunction: loot = randint(1, 100) if loot <= monster.Fighter.lootRate[itemIndex]: - if not item.Item.stackable or item.Item.amount > 0: - lootItem(item, monster.x, monster.y) + lootItem(item, monster.x, monster.y) itemIndex += 1 monster.char = '%' monster.color = colors.dark_red monster.blocks = False monster.AI = None - monster.name = 'remains of ' + monster.name + monster.trueName = 'remains of ' + monster.name monster.Fighter = None monster.sendToBack() @@ -7508,7 +7565,7 @@ def zombieDeath(monster): monster.color = Ellipsis monster.blocks = False monster.AI = None - monster.name = None + monster.trueName = None monster.Fighter = None #_____________ GUI _______________ @@ -8479,7 +8536,7 @@ def saveGame(): #mapFile.close() def newGame(): - global objects, inventory, gameMsgs, gameState, player, dungeonLevel, gameMsgs, equipmentList, currentBranch, bossDungeonsAppeared, DEBUG, REVEL, logMsgs, tilesInRange, tilesinPath, tilesInRect, menuWindows, explodingTiles, hiroshimanNumber, FOV_recompute + global objects, inventory, gameMsgs, gameState, player, dungeonLevel, gameMsgs, identifiedItems, equipmentList, currentBranch, bossDungeonsAppeared, DEBUG, REVEL, logMsgs, tilesInRange, tilesinPath, tilesInRect, menuWindows, explodingTiles, hiroshimanNumber, FOV_recompute DEBUG = False REVEL = False @@ -8502,6 +8559,7 @@ def newGame(): inventory = [] equipmentList = [] + identifiedItems = [] FOV_recompute = True initializeFOV() From ef1313184e8738977821000f32bd9a8c618af09d Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Fri, 12 May 2017 20:24:45 +0200 Subject: [PATCH 21/32] Finished identify system --- assets/ascii/violetpotion.xp | Bin 0 -> 196 bytes main.py | 29 +++++++++++++++++++---------- 2 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 assets/ascii/violetpotion.xp diff --git a/assets/ascii/violetpotion.xp b/assets/ascii/violetpotion.xp new file mode 100644 index 0000000000000000000000000000000000000000..926931b197f4bffdb0853ba18707ffc03b75235e GIT binary patch literal 196 zcmV;#06YI5iwFP!000003;X~7|9?gX1_n+b<^f^_1{ffnr4PhF@r4v_3(hMSoTJ@1qgz<~djihF@0L3Z yn0`ZqF2V)za9M=w@w2d{2x9$9iM{w;Kx}%(mO3eM0sj1p%{Bm_ZR6cY1ONbjWLbd# literal 0 HcmV?d00001 diff --git a/main.py b/main.py index d8255c7..aff7e11 100644 --- a/main.py +++ b/main.py @@ -3038,7 +3038,7 @@ def absorb(self): player.Player.speedChance += boost class Item: - def __init__(self, useFunction = None, arg1 = None, arg2 = None, arg3 = None, stackable = False, amount = 1, weight = 0, description = 'Placeholder.', pic = 'trollMace.xp', itemtype = None, identified = True, unIDName = 'Unidentified', unIDpName = 'UnidentifiedS'): + def __init__(self, useFunction = None, arg1 = None, arg2 = None, arg3 = None, stackable = False, amount = 1, weight = 0, description = 'Placeholder.', pic = 'trollMace.xp', itemtype = None, identified = True, unIDName = 'Unidentified', unIDpName = 'UnidentifiedS', unIDdesc='Unidentified placeholder.'): self.useFunction = useFunction self.arg1 = arg1 self.arg2 = arg2 @@ -3046,12 +3046,20 @@ def __init__(self, useFunction = None, arg1 = None, arg2 = None, arg3 = None, s self.stackable = stackable self.amount = amount self.weight = weight - self.description = description + self.desc = description self.pic = pic self.type = itemtype self.identified = identified self.unIDName = unIDName self.unIDpName = unIDpName + self.unIDdesc = unIDdesc + + @property + def description(self): + if self.identified: + return self.desc + else: + return self.unIDdesc def identify(self): global identifiedItems @@ -6629,7 +6637,7 @@ def placeBoss(name, x, y): #_____________ ROOM POPULATION + ITEMS GENERATION_______________ potionIdentify = {} scrollIdentify = {} -colorDict = {'blue': colors.blue, 'red': colors.red, 'violet': colors.violet} +colorDict = {'blue': (colors.blue, 'smokybluepotion.xp', 'The blueish smokes emanating from this potion is not very reassuring about what effects it could bring.'), 'red': (colors.red, 'redpotion.xp', 'A slighly bubbling red beverage.'), 'violet': (colors.violet, 'violetpotion.xp', 'A slighly bubbling violet beverage.')} nameDict = ['Ewaz', 'Vuzin', 'Armuz', 'Gowid', 'Ansuz', 'Juman', 'Ji', 'Morwen'] def createSword(x, y): @@ -6837,7 +6845,7 @@ def createScroll(x, y): scrollChances = currentBranch.scrollChances scrollChoice = randomChoice(scrollChances) unIdentifiedName = 'scroll of ' + scrollIdentify[scrollChoice] - pName = unIdentifiedName = 'scrolls of ' + scrollIdentify[scrollChoice] + pName = 'scrolls of ' + scrollIdentify[scrollChoice] identified = False if unIdentifiedName in identifiedItems: identified = True @@ -6865,16 +6873,16 @@ def createScroll(x, y): def createPotion(x, y): potionChances = currentBranch.potionChances potionChoice = randomChoice(potionChances) - name, color = potionIdentify[potionChoice] + name, color, pic, desc = potionIdentify[potionChoice] unIdentifiedName = name + ' potion' pName = name + ' potions' identified = False if unIdentifiedName in identifiedItems: identified = True if potionChoice == 'heal': - potion = GameObject(x, y, '!', 'healing potion', color, Item = Item(useFunction = castHeal, weight = 0.4, stackable=True, amount = randint(1, 2), pic = "redpotion.xp", description = "A slighly bubbling red beverage that stimulates cell growth when ingested, which allows for wounds to heal signifcantly faster. However, it also notably increases risk of cancer, but if you're in a situation where you have to drink such a potion, this is probably one of the least of your worries.", unIDName=unIdentifiedName, identified=identified, unIDpName=pName), blocks = False) + potion = GameObject(x, y, '!', 'healing potion', color, Item = Item(useFunction = castHeal, weight = 0.4, stackable=True, amount = randint(1, 2), pic = pic, description = "A potion that stimulates cell growth when ingested, which allows for wounds to heal signifcantly faster. However, it also notably increases risk of cancer, but if you're in a situation where you have to drink such a potion, this is probably one of the least of your worries.", unIDName=unIdentifiedName, identified=identified, unIDpName=pName, unIDdesc = desc), blocks = False) if potionChoice == 'mana': - potion = GameObject(x, y, '!', 'mana regeneration potion', color, Item = Item(useFunction = castRegenMana, arg1 = 10, weight = 0.4, stackable = True, pic = "smokybluepotion.xp", description = "The blueish smokes emanating from this potion scared more than one novice mage, but it actually tastes quite good and has no other short-term effect other than replenishing your life-force. However, the [PLACEHOLDER WORLD (the 'normal' one, not Realm of Madness) NAME]'s Guild of Alchemists is still debating about whether or not it causes detrimental long-term effects.", unIDName=unIdentifiedName, identified=identified, unIDpName=pName), blocks = False) + potion = GameObject(x, y, '!', 'mana regeneration potion', color, Item = Item(useFunction = castRegenMana, arg1 = 10, weight = 0.4, stackable = True, pic = pic, description = "The awkward look of this potion scared more than one novice mage, but it actually tastes quite good and has no other short-term effect other than replenishing your life-force. However, the [PLACEHOLDER WORLD (the 'normal' one, not Realm of Madness) NAME]'s Guild of Alchemists is still debating about whether or not it causes detrimental long-term effects.", unIDName=unIdentifiedName, identified=identified, unIDpName=pName, unIDdesc = desc), blocks = False) return potion @@ -7255,11 +7263,12 @@ def pieDebuff(amount, text): def applyIdentification(): global potionIdentify, scrollIdentify, colorDict, nameDict - for potion, u in currentBranch.potionChances.items(): + for potion in currentBranch.potionChances.keys(): if not potion in potionIdentify: - colorName, color = choice(list(colorDict.items())) + colorName, colorPicDesc = choice(list(colorDict.items())) + color, pic, desc = colorPicDesc del colorDict[colorName] - potionIdentify[potion] = (colorName, color) + potionIdentify[potion] = (colorName, color, pic, desc) for scroll, u in currentBranch.scrollChances.items(): if not scroll in scrollIdentify: From 6b975d082f4673a01874cb5d6456431b7829aa9c Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Fri, 12 May 2017 21:02:30 +0200 Subject: [PATCH 22/32] Started making AIs cleaner --- main.py | 157 +++++++++++++++----------------------------------------- 1 file changed, 40 insertions(+), 117 deletions(-) diff --git a/main.py b/main.py index aff7e11..c860fbc 100644 --- a/main.py +++ b/main.py @@ -2199,28 +2199,18 @@ def __init__(self, mob, goalX, goalY): def run(self): self.mob.astarPath = astarPath(self.mob.x, self.mob.y, self.goalX, self.goalY) -class BasicMonster: #Basic monsters' AI +class TargetSelector: def __init__(self): self.selectedTarget = None - self.dumbCounter = 0 - self.failCounter = 0 - self.didRecalcThisTurn = False - for loop in range(10): - print("!!!!!!!! SETTING TARGET TO NONE !!!!!!!!") - print() - + def setFuckingTarget(self, target): self.selectedTarget = target - - def takeTurn(self): - global mustCalculate + + def selectTarget(self): monster = self.owner targets = [] self.selectedTarget = None self.setFuckingTarget(None) - self.dumbCounter = 0 - self.failCounter = 0 - self.didRecalcThisTurn = False priorityTargetFound = False monsterVisibleTiles = tdl.map.quick_fov(x = monster.x, y = monster.y,callback = isVisibleTile , fov = FOV_ALGO, radius = SIGHT_RADIUS, lightWalls = FOV_LIGHT_WALLS) @@ -2264,20 +2254,30 @@ def takeTurn(self): self.selectedTarget = enemy else: print("NO PRIORITY, TARGET IS {}".format(self.selectedTarget.name)) + +class BasicMonster(TargetSelector): #Basic monsters' AI + def __init__(self): + TargetSelector.__init__(self) + self.dumbCounter = 0 + self.failCounter = 0 + self.didRecalcThisTurn = False + + def takeTurn(self): + self.takeBasicTurn() + + def takeBasicTurn(self): + global mustCalculate + monster = self.owner + self.dumbCounter = 0 + self.failCounter = 0 + self.didRecalcThisTurn = False + + if not 'frozen' in convertBuffsToNames(self.owner.Fighter) and monster.distanceTo(player) <= 15: + self.selectTarget() if self.selectedTarget is not None: print("SELECTED TARGET IS NOT NONE") if monster.distanceTo(self.selectedTarget) < 2: monster.Fighter.attack(self.selectedTarget) - #else: - #state = monster.moveAstar(self.selectedTarget.x, self.selectedTarget.y, fallback = False) - #if state == "fail": - # diagState = checkDiagonals(monster, self.selectedTarget) - # if diagState is None: - # monster.moveTowards(self.selectedTarget.x, self.selectedTarget.y) - #monster.moveOnAstarPath(goal = self.selectedTarget) - - #elif (monster.x, monster.y) in visibleTiles and monster.distanceTo(player) >= 2: - #monster.moveAstar(player.x, player.y) else: print("TRYING TO MOVE") self.tryMove() @@ -2478,68 +2478,15 @@ def charge(self): FOV_recompute = True self.charging = False -class FastMonster: +class FastMonster(BasicMonster): def __init__(self, speed): + BasicMonster.__init__(self) self.speed = speed def takeTurn(self): - monster = self.owner for loop in range(self.speed): - targets = [] - selectedTarget = None - priorityTargetFound = False - monsterVisibleTiles = tdl.map.quick_fov(x = monster.x, y = monster.y,callback = isVisibleTile , fov = FOV_ALGO, radius = SIGHT_RADIUS, lightWalls = FOV_LIGHT_WALLS) - if not 'frozen' in convertBuffsToNames(self.owner.Fighter) and monster.distanceTo(player) <= 15: - print(monster.name + " is less than 15 tiles to player.") - for object in objects: - if (object.x, object.y) in monsterVisibleTiles and (object == player or (object.AI and object.AI.__class__.__name__ == "FriendlyMonster" and object.AI.friendlyTowards == player)): - targets.append(object) - if DEBUG: - print(monster.name.capitalize() + " can target", end=" ") - if targets: - for loop in range (len(targets)): - print(targets[loop].name.capitalize() + ", ", sep ="", end ="") - else: - print("absolutely nothing but nothingness.", end ="") - print() - if targets: - if player in targets: #Target player in priority - selectedTarget = player - del targets[targets.index(player)] - if monster.distanceTo(player) < 2: - priorityTargetFound = True - if not priorityTargetFound: - for enemyIndex in range(len(targets)): - enemy = targets[enemyIndex] - if monster.distanceTo(enemy) < 2: - selectedTarget = enemy - else: - if selectedTarget == None or monster.distanceTo(selectedTarget) > monster.distanceTo(enemy): - selectedTarget = enemy - if selectedTarget is not None: - if monster.distanceTo(selectedTarget) < 2: - monster.Fighter.attack(selectedTarget) - else: - state = monster.moveAstar(selectedTarget.x, selectedTarget.y, fallback = False) - if state == "fail": - diagState = checkDiagonals(monster, selectedTarget) - if diagState is None: - monster.moveTowards(selectedTarget.x, selectedTarget.y) - #elif (monster.x, monster.y) in visibleTiles and monster.distanceTo(player) >= 2: - #monster.moveAstar(player.x, player.y) - else: - if not 'frozen' in convertBuffsToNames(monster.Fighter) and monster.distanceTo(player) >= 2: - pathState = "complete" - diagPathState = None - if monster.astarPath: - pathState = monster.moveAstar() - elif not monster.astarPath or pathState == "fail": - if monster.distanceTo(player) <= 15 and not (monster.x == player.x and monster.y == player.y): - diagPathState = checkDiagonals(monster, player) - elif diagPathState is None or monster.distanceTo(player) > 15: - monster.move(randint(-1, 1), randint(-1, 1)) #wandering - elif not 'frozen' in convertBuffsToNames(self.owner.Fighter): - monster.move(randint(-1, 1), randint(-1, 1)) #wandering + self.takeBasicTurn() #for some reason when moving only one tile it won't attack as a second action + class Fleeing: def takeTurn(self): monster = self.owner @@ -2555,43 +2502,19 @@ def takeTurn(self): if state == "fail": monster.moveTowards(bestX, bestY) -class hostileStationnary: +class HostileStationnary(TargetSelector): + def __init__(self): + TargetSelector.__init__(self) + def takeTurn(self): monster = self.owner - targets = [] - selectedTarget = None - priorityTargetFound = False if not 'frozen' in convertBuffsToNames(self.owner.Fighter): - for object in objects: - if (object.x, object.y) in visibleTiles and (object == player or (object.AI and object.AI.__class__.__name__ == "FriendlyMonster" and object.AI.friendlyTowards == player)): - targets.append(object) - if DEBUG: - print(monster.name.capitalize() + " can target", end=" ") - if targets: - for loop in range (len(targets)): - print(targets[loop].name.capitalize() + ", ", sep ="", end ="") - else: - print("absolutely nothing but nothingness.", end ="") - print() - if targets: - if player in targets: #Target player in priority - selectedTarget = player - del targets[targets.index(player)] - if monster.distanceTo(player) < 2: - priorityTargetFound = True - if not priorityTargetFound: - for enemyIndex in range(len(targets)): - enemy = targets[enemyIndex] - if monster.distanceTo(enemy) < 2: - selectedTarget = enemy - else: - if selectedTarget == None or monster.distanceTo(selectedTarget) > monster.distanceTo(enemy): - selectedTarget = enemy - if selectedTarget is not None: - if monster.distanceTo(selectedTarget) < 2: - monster.Fighter.attack(selectedTarget) + self.selectTarget() + if self.selectedTarget is not None: + if monster.distanceTo(self.selectedTarget) < 2: + monster.Fighter.attack(self.selectedTarget) -class immobile(): +class Immobile: def takeTurn(self): monster = self.owner return @@ -2613,7 +2536,7 @@ def __init__(self, old_AI, numberTurns=CONFUSE_NUMBER_TURNS): self.numberTurns = numberTurns def takeTurn(self): - if self.old_AI.__class__.__name__ != 'hostileStationnary' and self.old_AI.__class__.__name__ != 'immobile': + if self.old_AI.__class__.__name__ != 'HostileStationnary' and self.old_AI.__class__.__name__ != 'Immobile': if self.numberTurns > 0: self.owner.move(randint(-1, 1), randint(-1, 1)) self.numberTurns -= 1 @@ -6369,7 +6292,7 @@ def fatDeath(monster): def createFat(x, y): fatFighterComponent = Fighter(hp = 5, armor = 0, power = 1, xp = 0, deathFunction=fatDeath, accuracy= 0, evasion=1) - fat_AI_component = immobile() + fat_AI_component = Immobile() fat = GameObject(x, y, char = '#', color = colors.dark_lime, name = "Gluttony's fat", blocks = True, Fighter = fatFighterComponent, AI = fat_AI_component) objects.append(fat) @@ -6466,7 +6389,7 @@ def gluttonysDeath(monster): monster.Fighter = None monster.sendToBack() for object in objects: - if object.name == "Gluttony's fat": #or (object.AI and (object.AI.__class__.__name__ == "immobile")): + if object.name == "Gluttony's fat": #or (object.AI and (object.AI.__class__.__name__ == "Immobile")): object.Fighter.hp = 0 fatDeath(object) createEndRooms() From 706c8de0219032e961b603b0a85ef7878dc77923 Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Fri, 12 May 2017 22:17:28 +0200 Subject: [PATCH 23/32] Started making stairs cleaner --- code/dunbranches.py | 1 + main.py | 145 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 134 insertions(+), 12 deletions(-) diff --git a/code/dunbranches.py b/code/dunbranches.py index 114c352..07e2cc0 100644 --- a/code/dunbranches.py +++ b/code/dunbranches.py @@ -51,6 +51,7 @@ def __init__(self, shortName, name = None, maxDepth = 99999, branchesFrom = None self.fixedMap = fixedMap self.genType = genType self.genFeatures = genFeatures + self.appeared = False mainDungeon = Branch(shortName = "main", name = "Main", branchesTo = None) gluttonyDungeon = Branch(shortName = "glutt", name = "Gluttony Dungeon", maxDepth = 5, branchesFrom = (mainDungeon, 1), lightStairsColor = colors.desaturated_chartreuse, darkStairsColor = colors.darkest_chartreuse, monsterChances = {'darksoul': 400, 'ogre': 200, 'starveling': 250, 'cultist': 150}, itemChances = {'potion': 360, 'scroll': 20, 'weapon': 20, 'shield': 100, 'food': 500}, bossLevels = [5], bossNames = {'Gluttony': 5}) diff --git a/main.py b/main.py index c860fbc..69557d6 100644 --- a/main.py +++ b/main.py @@ -1698,9 +1698,62 @@ def __init__(self, nemesisObject, branch, level): self.branch = branch self.level = level +class Stairs: + def __init__(self, climb = 'down', branchesFrom = dBr.mainDungeon, branchesTo = dBr.mainDungeon): + self.climb = climb + self.branchesFrom = branchesFrom + self.branchesTo = branchesTo + if self.branchesFrom != self.branchesTo: + self.changeBranch = self.branchesTo + else: + self.changeBranch = None + + def climbStairs(self): + if stairCooldown == 0: + if self.climb == 'down': + global stairCooldown, currentBranch + temporaryBox('Loading...') + stairCooldown = 2 + boss = False + if dungeonLevel + 1 in currentBranch.bossLevels and self.changeBranch is None: + boss = True + if DEBUG: + message("Stair cooldown set to {}".format(stairCooldown), colors.purple) + nextLevel(boss, changeBranch=self.changeBranch) + elif self.climb == 'up': + if dungeonLevel > 1 or currentBranch.name != 'Main': + print(currentBranch.name) + if stairCooldown == 0: + global stairCooldown, dungeonLevel + temporaryBox('Loading...') + saveLevel(dungeonLevel) + chosen = False + stairCooldown = 2 + if DEBUG: + message("Stair cooldown set to {}".format(stairCooldown), colors.purple) + if dungeonLevel == 1 and currentBranch.name != 'Main': + if not chosen: + chosen = True + print('Returning to origin branch') + loadLevel(currentBranch.origDepth, save = False, branch = currentBranch.origBranch) + else: + print('WHY THE HECK IS THE CODE EXECUTING THIS FFS ?') + else: + if not chosen: + chosen = True + toLoad = dungeonLevel - 1 + loadLevel(toLoad, save = False) + else: + print('Chosen was equal to true. If the code ever goes here, I fucking hate all of this.') + else: + message("You're too tired to climb the stairs right now") + return None + else: + message("You're too tired to climb down the stairs right now") + class GameObject: "A generic object, represented by a character" - def __init__(self, x, y, char, name, color = colors.white, blocks = False, Fighter = None, AI = None, Player = None, Ghost = False, flying = False, Item = None, alwaysVisible = False, darkColor = None, Equipment = None, pName = None, Essence = None, socialComp = None, shopComp = None, questList = []): + def __init__(self, x, y, char, name, color = colors.white, blocks = False, Fighter = None, AI = None, Player = None, Ghost = False, flying = False, Item = None, alwaysVisible = False, darkColor = None, Equipment = None, pName = None, Essence = None, socialComp = None, shopComp = None, questList = [], Stairs = None): self.x = x self.y = y self.char = char @@ -1729,6 +1782,9 @@ def __init__(self, x, y, char, name, color = colors.white, blocks = False, Fight self.Essence = Essence if self.Essence: self.Essence.owner = self + self.Stairs = Stairs + if self.Stairs: + self.Stairs.owner = self self.astarPath = [] self.lastTargetX = None self.lastTargetY = None @@ -4116,6 +4172,19 @@ def getInput(): elif userInput.keychar.upper() == '<': print('You pressed the freaking climb up key') + for object in objects: + if object.x == player.x and object.y == player.y and not object == player: + print('{} object is a the same place as the player.'.format(object.name)) + if object.Stairs: + print('object has a stairs component') + if object.Stairs.climb == 'up': + print('stairs are to climb up') + object.Stairs.climbStairs() + else: + print('stairs are to climb down but you want to go up') + else: + print('object has no stairs component') + ''' if dungeonLevel > 1 or currentBranch.name != 'Main': #saveLevel(dungeonLevel) if upStairs.x == player.x and upStairs.y == player.y: @@ -4145,8 +4214,22 @@ def getInput(): else: message("You're too tired to climb the stairs right now") return None + ''' FOV_recompute = True elif userInput.keychar.upper() == '>': + for object in objects: + if object.x == player.x and object.y == player.y and not object == player: + print('{} object is a the same place as the player.'.format(object.name)) + if object.Stairs: + print('object has a stairs component') + if object.Stairs.climb == 'down': + print('stairs are to go down') + object.Stairs.climbStairs() + else: + print('stairs are to climb up but you want to go down') + else: + print('object has no stairs component') + ''' if stairs is not None and stairs.x == player.x and stairs.y == player.y: if stairCooldown == 0: global stairCooldown @@ -4206,6 +4289,7 @@ def getInput(): else: message("You're too tired to climb down the stairs right now") return None + ''' elif userInput.keychar.upper() == 'I': choseOrQuit = False while not choseOrQuit: @@ -5645,12 +5729,12 @@ def generateCave(fall = False): if not fall: player.x = pX player.y = pY - upStairs = GameObject(pX, pY, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor) + upStairs = GameObject(pX, pY, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs = Stairs(climb='up')) objects.append(upStairs) upStairs.sendToBack() stairsRoom = rooms[randint(1, len(rooms) - 1)] (sX, sY) = stairsRoom.tiles[randint(0, len(stairsRoom.tiles) - 1)] - stairs = GameObject(sX, sY, '>', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor) + stairs = GameObject(sX, sY, '>', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs = Stairs(climb='down', branchesFrom=currentBranch, branchesTo=currentBranch)) objects.append(stairs) stairs.sendToBack() applyIdentification() @@ -5901,7 +5985,7 @@ def makeMap(generateChasm = True, generateHole = False, fall = False): for y in range(newRoom.y1 + 1, newRoom.y2): unchasmable.append((x, y)) if dungeonLevel > 1 or currentBranch.name != 'Main': - upStairs = GameObject(new_x, new_y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor) + upStairs = GameObject(new_x, new_y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs=Stairs(climb='up')) objects.append(upStairs) upStairs.sendToBack() else: @@ -5915,7 +5999,7 @@ def makeMap(generateChasm = True, generateHole = False, fall = False): rooms.append(newRoom) numberRooms += 1 secretRoom() - stairs = GameObject(new_x, new_y, '>', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor) + stairs = GameObject(new_x, new_y, '>', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs=Stairs('down', currentBranch, currentBranch)) objects.append(stairs) stairs.sendToBack() for x in range(lastCreatedRoom.x1 + 1, lastCreatedRoom.x2): @@ -5950,6 +6034,34 @@ def makeMap(generateChasm = True, generateHole = False, fall = False): branches = [] for (branch, level) in currentBranch.branchesTo: branches.append(branch) + if dungeonLevel == level and not branch.appeared: + createdStairs = False + while not createdStairs: + randRoom = randint(0, len(rooms) - 1) + room = rooms[randRoom] + chasmedRoom = False + for x in range(room.x1 + 1, room.x2): + for y in range(room.y1 + 1, room.y2): + if myMap[x][y].chasm: + chasmedRoom = True + break + if chasmedRoom: + break + (x, y) = room.center() + wrongCentre = False + for object in objects: + if object.x == x and object.y == y: + wrongCentre = True + break + if not wrongCentre and not chasmedRoom: + newStairs = GameObject(x, y, '>', 'stairs to ' + branch.name, branch.lightStairsColor, alwaysVisible = True, darkColor = branch.darkStairsColor, Stairs=Stairs('down', currentBranch, branch)) + objects.append(newStairs) + newStairs.sendToBack() + branch.appeared = True + createdStairs = True + print('created {} stairs at {}, {}'.format(branch.shortName, str(x), str(y))) + + ''' if branch == dBr.gluttonyDungeon: if dungeonLevel == level and not bossDungeonsAppeared['gluttony']: createdStairs = False @@ -6069,6 +6181,7 @@ def makeMap(generateChasm = True, generateHole = False, fall = False): bossDungeonsAppeared['wrath'] = True createdStairs = True print('created wraths stairs at ' + str(x) + ', ' + str(y)) + ''' if not dBr.hiddenTown in branches: global townStairs @@ -6127,7 +6240,7 @@ def makeBossLevel(fall = False, generateHole=False): player.x = new_x player.y = new_y if dungeonLevel > 1: - upStairs = GameObject(new_x, new_y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor) + upStairs = GameObject(new_x, new_y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs = Stairs(climb='up')) objects.append(upStairs) upStairs.sendToBack() else: @@ -6180,7 +6293,7 @@ def makeBossLevel(fall = False, generateHole=False): def makeHiddenTown(fall = False): global myMap, objects, upStairs, rooms, numberRooms - myMap = [[Tile(True, wall = True) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. + myMap = [[Tile(True, wall = True, x = x, y = y) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. objects = [player] rooms = [] numberRooms = 0 @@ -6204,7 +6317,7 @@ def makeHiddenTown(fall = False): if not myMap[x][y].chasm and not isBlocked(x, y): player.x, player.y = x, y fallen = True - upStairs = GameObject(x, y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor) + upStairs = GameObject(x, y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs = Stairs(climb='up')) objects.append(upStairs) upStairs.sendToBack() @@ -6248,7 +6361,7 @@ def createEndRooms(): createHorizontalTunnel(previous_x, new_x, new_y) rooms.append(newRoom) numberRooms += 1 - stairs = GameObject(new_x, new_y, '>', 'stairs', colors.white, alwaysVisible = True, darkColor = colors.dark_grey) + stairs = GameObject(new_x, new_y, '>', 'stairs', colors.white, alwaysVisible = True, darkColor = colors.dark_grey, Stairs=Stairs(climb='down')) objects.append(stairs) stairs.sendToBack() @@ -8410,6 +8523,10 @@ def saveGame(): file["logMsgs"] = logMsgs file["gameState"] = gameState file["hiroshimanNumber"] = hiroshimanNumber + file['potionIdentify'] = potionIdentify + file['scrollIdentify'] = scrollIdentify + file['colorDict'] = colorDict + file['nameDict'] = nameDict if dungeonLevel > 1 or currentBranch.name != 'Main': print(currentBranch.name) print(currentBranch.shortName) @@ -8518,9 +8635,9 @@ def newGame(): highCultistHasAppeared = False #Make so more high cultists can spawn at lower levels (still only one by floor though) def loadGame(): - global objects, inventory, gameMsgs, gameState, player, dungeonLevel, myMap, equipmentList, stairs, upStairs, hiroshimanNumber, currentBranch, gluttonyStairs, logMsgs, townStairs, greedStairs, wrathStairs - + global FOV_recompute, objects, inventory, gameMsgs, gameState, player, dungeonLevel, myMap, equipmentList, stairs, upStairs, hiroshimanNumber, currentBranch, gluttonyStairs, logMsgs, townStairs, greedStairs, wrathStairs, potionIdentify, scrollIdentify, nameDict, colorDict + FOV_recompute = True #myMap = [[Tile(True) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] file = shelve.open(absFilePath, "r") dungeonLevel = file["dungeonLevel"] @@ -8536,6 +8653,10 @@ def loadGame(): gameState = file["gameState"] logMsgs = file["logMsgs"] hiroshimanNumber = file["hiroshimanNumber"] + potionIdentify = file['potionIdentify'] + scrollIdentify = file['scrollIdentify'] + colorDict = file['colorDict'] + nameDict = file['nameDict'] if dungeonLevel > 1 or currentBranch.name != 'Main': print(currentBranch.name) upStairs = objects[file["upStairsIndex"]] @@ -8679,7 +8800,7 @@ def loadLevel(level, save = True, branch = currentBranch): currentBranch = branch initializeFOV() -def nextLevel(boss = False, changeBranch = None, fixedMap = None, fall = False): +def nextLevel(boss = False, changeBranch = None, fall = False): global dungeonLevel, currentBranch, currentMusic if boss: currentMusic = 'Hoxton_Princess.wav' From 66451a40fe65aa8c5f9cea3600298cc87ee50e0a Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Sat, 13 May 2017 11:45:45 +0200 Subject: [PATCH 24/32] Continued cleaning stairs A problem is occurring right now where loading level does not place the player a the good coordinates. --- main.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/main.py b/main.py index 69557d6..af18a23 100644 --- a/main.py +++ b/main.py @@ -8515,8 +8515,8 @@ def saveGame(): print("Saved myMap_level{}".format(dungeonLevel)) file["objects_level{}".format(dungeonLevel)] = objects file["playerIndex"] = objects.index(player) - if currentBranch.shortName != 'town': - file["stairsIndex"] = objects.index(stairs) + #if currentBranch.shortName != 'town': + # file["stairsIndex"] = objects.index(stairs) file["inventory"] = inventory file["equipmentList"] = equipmentList file["gameMsgs"] = gameMsgs @@ -8527,6 +8527,8 @@ def saveGame(): file['scrollIdentify'] = scrollIdentify file['colorDict'] = colorDict file['nameDict'] = nameDict + + ''' if dungeonLevel > 1 or currentBranch.name != 'Main': print(currentBranch.name) print(currentBranch.shortName) @@ -8578,6 +8580,7 @@ def saveGame(): print('Details : {}'.format(error.args)) print('==============================') pass + ''' file.close() #mapFile = open(absPicklePath, 'wb') @@ -8590,7 +8593,7 @@ def newGame(): DEBUG = False REVEL = False deleteSaves() - bossDungeonsAppeared = {'gluttony': False, 'greed': False, 'wrath': False} + #bossDungeonsAppeared = {'gluttony': False, 'greed': False, 'wrath': False} gameMsgs = [] objects = [player] logMsgs = [] @@ -8645,8 +8648,8 @@ def loadGame(): myMap = file["myMap_level{}".format(dungeonLevel)] objects = file["objects_level{}".format(dungeonLevel)] player = objects[file["playerIndex"]] - if currentBranch.shortName != 'town': - stairs = objects[file["stairsIndex"]] + #if currentBranch.shortName != 'town': + # stairs = objects[file["stairsIndex"]] inventory = file["inventory"] equipmentList = file["equipmentList"] gameMsgs = file["gameMsgs"] @@ -8657,6 +8660,8 @@ def loadGame(): scrollIdentify = file['scrollIdentify'] colorDict = file['colorDict'] nameDict = file['nameDict'] + + ''' if dungeonLevel > 1 or currentBranch.name != 'Main': print(currentBranch.name) upStairs = objects[file["upStairsIndex"]] @@ -8675,6 +8680,7 @@ def loadGame(): #mapFile = open(absPicklePath, "rb") #myMap = pickle.load(mapFile) #mapFile.close() + ''' def saveLevel(level = dungeonLevel): #if not os.path.exists(absDirPath): @@ -8692,6 +8698,7 @@ def saveLevel(level = dungeonLevel): mapFile["myMap"] = myMap mapFile["objects"] = objects mapFile["playerIndex"] = objects.index(player) + ''' if currentBranch.shortName != 'town': mapFile["stairsIndex"] = objects.index(stairs) if (level > 1 or currentBranch.name != 'Main') and upStairs in objects: @@ -8748,6 +8755,7 @@ def saveLevel(level = dungeonLevel): print("DIDNT SAVE wrath STAIRS") print("DungeonLevel : {} / WrathLevel : {}".format(dungeonLevel, wrathBrLevel)) print('Current branch : {}'.format(currentBranch.name)) + ''' mapFile["yunowork"] = "SCREW THIS" print("Saved level at " + mapFilePath) mapFile.sync() @@ -8772,6 +8780,7 @@ def loadLevel(level, save = True, branch = currentBranch): player.x = int(tempPlayer.x) player.y = int(tempPlayer.y) objects[xfile["playerIndex"]] = player + ''' if branch.shortName != 'town': stairs = objects[xfile["stairsIndex"]] if level > 1 or branch.name != 'Main': @@ -8792,7 +8801,8 @@ def loadLevel(level, save = True, branch = currentBranch): greedStairs = objects[xfile["greedStairsIndex"]] if dungeonLevel == wrathBrLevel and currentBranch.name == 'Main': wrathStairs = objects[xfile['wrathStairsIndex']] - + ''' + message("You climb the stairs") print("Loaded level " + str(level)) xfile.close() From 6903b4e13cd43b0c38f5c21e437121143e0831cd Mon Sep 17 00:00:00 2001 From: Edern76 Date: Sat, 13 May 2017 19:32:37 +0200 Subject: [PATCH 25/32] Tried doing some work --- code/spellGen.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/code/spellGen.py b/code/spellGen.py index d316bd1..658cccb 100644 --- a/code/spellGen.py +++ b/code/spellGen.py @@ -1,6 +1,8 @@ +import copy from random import randint from code.constants import * + class SpellTemplate: def __init__(self): self.type = None @@ -33,14 +35,23 @@ def randFrom(self): ind = randint(0, len(self) - 1) return self[ind] +baseTypeList = BetterList("Attack", "Buff", "Heal") +baseTargetList = BetterList("Select", "Self", "Closest", "Farthest") +baseZoneList = BetterList("SingleTile", "Cross", "AOE") + +baseAttackList = BetterList("Fire", "Physical", "Poison") +baseBuffList = BetterList("Hunger", "AttackUp") +baseHealList = BetterList("HP", "MP", "CureFire", "CurePoison") + def createEffect(): - typeList = BetterList("Attack", "Buff", "Heal") - targetList = BetterList("Select", "Self", "Closest", "Farthest") - zoneList = BetterList("SingleTile", "Cross", "AOE") + typeList = copy.copy(baseTypeList) + targetList = copy.copy(baseTargetList) + zoneList = copy.copy(baseZoneList) + + attackList = copy.copy(baseAttackList) + buffList = copy.copy(baseBuffList) + healList = copy.copy(baseHealList) - attackList = BetterList("Fire", "Physical", "Poison") - buffList = BetterList("Hunger", "AttackUp") - healList = BetterList("HP", "MP", "CureFire", "CurePoison") \ No newline at end of file From f9e3860e31760dbe12e7d50c0e47e0563b862762 Mon Sep 17 00:00:00 2001 From: Malan-Tai Date: Sat, 13 May 2017 21:51:05 +0200 Subject: [PATCH 26/32] Stairs now load the good level*, leftover skillpoints are now saved * but still load the player at his last location in the level, even if he jumped into a chasm --- main.py | 79 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/main.py b/main.py index af18a23..8308198 100644 --- a/main.py +++ b/main.py @@ -1742,7 +1742,7 @@ def climbStairs(self): if not chosen: chosen = True toLoad = dungeonLevel - 1 - loadLevel(toLoad, save = False) + loadLevel(toLoad, save = False, branch=currentBranch) else: print('Chosen was equal to true. If the code ever goes here, I fucking hate all of this.') else: @@ -2779,6 +2779,7 @@ def __init__(self, name, strength, dexterity, vitality, willpower, load, race, c for trait in self.allTraits: if trait.type == 'trait': self.traits.append(trait) + self.skillpoints = 0 self.essences = {'Gluttony': 0, 'Wrath': 0, 'Lust': 0, 'Pride': 0, 'Envy': 0, 'Greed': 0, 'Sloth': 0} @@ -4098,7 +4099,8 @@ def getInput(): displayLog(50) elif userInput.keychar == 'C': displayCharacter() - + elif userInput.keychar == 's': + levelUpScreen(newSkillpoints = False) elif userInput.keychar == 'd' and gameState == 'playing': chosenItem = inventoryMenu('Press the key next to an item to drop it, or press any other key to cancel.') if chosenItem is not None: @@ -4579,9 +4581,11 @@ def shoot(): message('You have no ranged weapon equipped.') return 'didnt-take-turn' -def levelUpScreen(skillpoint = 3): +def levelUpScreen(newSkillpoints = True, skillpoint = 3): global menuWindows, FOV_recompute quitted = False + if newSkillpoints: + player.Player.skillpoints += skillpoint if menuWindows: for mWindow in menuWindows: mWindow.clear() @@ -4629,6 +4633,8 @@ def levelUpScreen(skillpoint = 3): window.draw_char(0, lMax, chr(192)) window.draw_char(kMax, lMax, chr(217)) + window.draw_str(1, 1, 'Skillpoints left: ' + str(player.Player.skillpoints), fg = colors.green) + counter1 = 0 counter2 = 0 groupCounter2 = 0 @@ -4693,19 +4699,19 @@ def levelUpScreen(skillpoint = 3): index = len(prevList) - 1 elif key.keychar.upper() == 'ENTER': skill = player.Player.skills[index] - if skill.selectable and skill.amount < 5 and skillpoint > 0: + if skill.selectable and skill.amount < 5 and player.Player.skillpoints > 0: skill.selected = True if not skill in notConfirmed: notConfirmed[skill] = skill.amount skill.amount += 1 - skillpoint -= 1 + player.Player.skillpoints -= 1 for newSkill in skill.allowsSelection: newSkill.selectable = True elif key.keychar.upper() == 'BACKSPACE': skill = player.Player.skills[index] if skill in notConfirmed and skill.amount > notConfirmed[skill]: skill.amount -= 1 - skillpoint += 1 + player.Player.skillpoints += 1 if skill.amount == notConfirmed[skill]: del notConfirmed[skill] if skill.amount <= 0: @@ -5729,7 +5735,13 @@ def generateCave(fall = False): if not fall: player.x = pX player.y = pY - upStairs = GameObject(pX, pY, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs = Stairs(climb='up')) + if dungeonLevel > 1: + formerBranch = currentBranch + elif currentBranch.name != 'Main': + formerBranch = currentBranch.origBranch + else: + formerBranch = None + upStairs = GameObject(pX, pY, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs = Stairs(climb='up', branchesFrom=formerBranch, branchesTo=currentBranch)) objects.append(upStairs) upStairs.sendToBack() stairsRoom = rooms[randint(1, len(rooms) - 1)] @@ -5985,7 +5997,11 @@ def makeMap(generateChasm = True, generateHole = False, fall = False): for y in range(newRoom.y1 + 1, newRoom.y2): unchasmable.append((x, y)) if dungeonLevel > 1 or currentBranch.name != 'Main': - upStairs = GameObject(new_x, new_y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs=Stairs(climb='up')) + if dungeonLevel > 1: + formerBranch = currentBranch + elif currentBranch.name != 'Main': + formerBranch = currentBranch.origBranch + upStairs = GameObject(new_x, new_y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs=Stairs(climb='up', branchesFrom=formerBranch, branchesTo=currentBranch)) objects.append(upStairs) upStairs.sendToBack() else: @@ -6240,7 +6256,7 @@ def makeBossLevel(fall = False, generateHole=False): player.x = new_x player.y = new_y if dungeonLevel > 1: - upStairs = GameObject(new_x, new_y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs = Stairs(climb='up')) + upStairs = GameObject(new_x, new_y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs = Stairs(climb='up', branchesFrom=currentBranch, branchesTo=currentBranch)) objects.append(upStairs) upStairs.sendToBack() else: @@ -6317,7 +6333,7 @@ def makeHiddenTown(fall = False): if not myMap[x][y].chasm and not isBlocked(x, y): player.x, player.y = x, y fallen = True - upStairs = GameObject(x, y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs = Stairs(climb='up')) + upStairs = GameObject(x, y, '<', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs = Stairs(climb='up', branchesFrom=dBr.mainDungeon, branchesTo=dBr.hiddenTown)) objects.append(upStairs) upStairs.sendToBack() @@ -6361,7 +6377,7 @@ def createEndRooms(): createHorizontalTunnel(previous_x, new_x, new_y) rooms.append(newRoom) numberRooms += 1 - stairs = GameObject(new_x, new_y, '>', 'stairs', colors.white, alwaysVisible = True, darkColor = colors.dark_grey, Stairs=Stairs(climb='down')) + stairs = GameObject(new_x, new_y, '>', 'stairs', currentBranch.lightStairsColor, alwaysVisible = True, darkColor = currentBranch.darkStairsColor, Stairs=Stairs(climb='down', branchesFrom=currentBranch, branchesTo=currentBranch)) objects.append(stairs) stairs.sendToBack() @@ -7978,10 +7994,11 @@ def displayControl(x, y, control, description): displayControl(1, 15, 'Space', 'Pick up object') displayControl(1, 17, 'c', 'Chat with NPC') displayControl(1, 19, 'C', 'Display character informations') - displayControl(1, 21, 'l', 'Enter look mode') - displayControl(1, 23, 'L', 'Display message log') - displayControl(1, 25, '>', 'Climb up stairs') - displayControl(1, 27, '<', 'Climb down stairs') + displayControl(1, 21, 's', 'Open skills and level up menu') + displayControl(1, 23, 'l', 'Enter look mode') + displayControl(1, 25, 'L', 'Display message log') + displayControl(1, 27, '>', 'Climb up stairs') + displayControl(1, 29, '<', 'Climb down stairs') x = MID_WIDTH - int(width/2) y = MID_CON_HEIGHT - int(height/2) root.blit(window, x, y, width, height, 0, 0) @@ -8764,8 +8781,21 @@ def saveLevel(level = dungeonLevel): return "completed" -def loadLevel(level, save = True, branch = currentBranch): +def loadLevel(level, save = True, branch = currentBranch, fall = False, fromStairs = True): global objects, player, myMap, stairs, dungeonLevel, gluttonyStairs, townStairs, currentBranch, wrathStairs, greedStairs + ''' + if fall: + fromStairs = False + if currentBranch != branch: + changeBranch = True + climbing = 'change' + else: + if level > dungeonLevel: + climbing = 'down' + else: + climbing = 'up' + changeBranch = False + ''' if save: try: saveLevel(dungeonLevel) @@ -8777,8 +8807,19 @@ def loadLevel(level, save = True, branch = currentBranch): myMap = xfile["myMap"] objects = xfile["objects"] tempPlayer = objects[xfile["playerIndex"]] - player.x = int(tempPlayer.x) - player.y = int(tempPlayer.y) + #if fromStairs: + # for object in objects: + # if object.Stairs: + # if (object.Stairs.climb == 'up' and climbing == 'down' and object.Stairs.branchesFrom == currentBranch) or (object.Stairs.climb == 'down' and climbing == 'up' and object.Stairs.branchesTo == currentBranch): # or (changeBranch and object.Stairs.climb == 'down' and object.Stairs.branchesTo == branch): + # player.x, player.y = object.x, object.y + if not fall: + player.x = int(tempPlayer.x) + player.y = int(tempPlayer.y) + else: + x, y = 1, 1 + while isBlocked(x, y) or myMap[x][y].chasm: + x, y = randint(0, MAP_WIDTH), randint(0, MAP_HEIGHT) + player.x, player.y = x, y objects[xfile["playerIndex"]] = player ''' if branch.shortName != 'town': @@ -8846,7 +8887,7 @@ def nextLevel(boss = False, changeBranch = None, fall = False): tempStairs = stairs print("Before try/except block") try: - loadLevel(dungeonLevel, save = False, branch = changeBranch) + loadLevel(dungeonLevel, save = False, branch = changeBranch, fall = fall) print("Loaded existing level {}".format(dungeonLevel)) except Exception as error: global myMap, objects, player, stairs From 2a04cd5bd466e26e25af6a22438db124dffd9bd3 Mon Sep 17 00:00:00 2001 From: Edern76 Date: Sun, 14 May 2017 16:40:21 +0200 Subject: [PATCH 27/32] Lost sanity WHY. ARE. THE. STAIRS TO OTHER BRANCHES. NO. LONGER. SPAWNING. --- main.py | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index 8308198..f4a546b 100644 --- a/main.py +++ b/main.py @@ -4116,9 +4116,17 @@ def getInput(): return 'didnt-take-turn' else: if chosenSpell.magicLevel > player.Player.getTrait(searchedType = 'skill', name = 'Magic ').amount: + ''' FOV_recompute = True message('Your arcane knowledge is not high enough to cast ' + chosenSpell.name + '.') return 'didnt-take-turn' + ''' + action = chosenSpell.cast(caster = player) + if action == 'cancelled': + FOV_recompute = True + return 'didnt-take-turn' + else: + return else: action = chosenSpell.cast(caster = player) if action == 'cancelled': @@ -5913,6 +5921,15 @@ def checkFile(file, folder): break return False +def removeAllChasms(): + ''' + For when they are truly making you lose your sanity and you want to erase all trace of the existence of every single of these fuckers because they are preventing you from testing what you want to test + And then after hours of banging your head against the nearest wall you realize that chasms were never the cause of your problem. FML. + ''' + for x in range(MAP_WIDTH): + for y in range(MAP_HEIGHT): + myMap[x][y].chasm = False + def makeMap(generateChasm = True, generateHole = False, fall = False): global myMap, stairs, objects, upStairs, bossDungeonsAppeared, color_dark_wall, color_light_wall, color_dark_ground, color_light_ground, color_dark_gravel, color_light_gravel, townStairs, gluttonyStairs, stairs, upStairs, nemesisList, roomTiles, tunnelTiles, unchasmable, rooms, wrathStairs nemesis = None @@ -5958,7 +5975,7 @@ def makeMap(generateChasm = True, generateHole = False, fall = False): myMap = [[Tile(True, x = x, y = y, wall = True, chasm = generateChasm, hole = generateHole) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. - + removeAllChasms() #Erase this when no longer needed rooms = [] roomTiles = [] tunnelTiles = [] @@ -6021,34 +6038,52 @@ def makeMap(generateChasm = True, generateHole = False, fall = False): for x in range(lastCreatedRoom.x1 + 1, lastCreatedRoom.x2): for y in range(lastCreatedRoom.y1 + 1, lastCreatedRoom.y2): unchasmable.append((x, y)) + print("BEFORE CHASM") if generateChasm: - myMap = chasmGen.createChasms(myMap, roomTiles, tunnelTiles, unchasmable) + #NOTE : RESTORE THIS AFTER TRAILER + #myMap = chasmGen.createChasms(myMap, roomTiles, tunnelTiles, unchasmable) + pass + print("PASSING") if generateHole: myMap = holeGen.createHoles(myMap) + print("AFTER CHASM") checkMap() - + print("PREPING IDENTIFIYING") applyIdentification() + print("DONE IDING") r = 0 + roomCounter = 0 for room in rooms: + roomCounter += 1 + print("ROOMS LENGTH = {} AND SWE ARE AT THE {}TH TIME PLACING FREAKING OBJECTS".format(len(rooms), roomCounter)) if r == 0: placeObjects(room, True) else: placeObjects(room) + print("DONE ITEMS") + if nemesis is not None: randRoom = randint(0, len(rooms) - 1) + print("DONE NEM RAND") room = rooms[randRoom] + print("DONE NEM ROOM") x = randint(room.x1 + 1, room.x2) y = randint(room.y1 + 1, room.y2) + print("DONE NEM COORDS") nemesisMonster = nemesis.nemesisObject + print("DONE NEM") nemesisMonster.x = x nemesisMonster.y = y + print("DONE NEM POS") objects.append(nemesisMonster) print('created nemesis', nemesisMonster.name, x, y) + print("DONE NEMESIS") branches = [] for (branch, level) in currentBranch.branchesTo: + print("IN BRANCH LEVEL LOOP") branches.append(branch) if dungeonLevel == level and not branch.appeared: createdStairs = False @@ -7132,13 +7167,18 @@ def placeObjects(room, first = False): monsterChances['ogre'] -= 50 monsterChances['highCultist'] = 50 + monCount = 0 for i in range(numMonsters): + monCount += 1 + print("{}th ITERATION OF MONSTER LOOP WTF IS THIS FREEZING WHY DID REMOVING CHASMS MAKE THIS BREAK".format(monCount)) if type(room) is Rectangle: + print("THIS IS A RECTANGE") x = randint(room.x1+1, room.x2-1) y = randint(room.y1+1, room.y2-1) elif type(room) is CaveRoom: (x,y) = room.tiles[randint(0, len(room.tiles) - 1)] - + print("THIS IS A CAVE") + print("X : {} | Y : {}".format(x,y)) if not isBlocked(x, y) and (x, y) != (player.x, player.y) and not myMap[x][y].chasm: monsterChoice = randomChoice(monsterChances) @@ -7209,38 +7249,55 @@ def placeObjects(room, first = False): else: monster = None + else: + if isBlocked(x, y): + print("IT IS BLOCKEEED") if monster != 'cancelled' and monster != None: objects.append(monster) num_items = randint(0, MAX_ROOM_ITEMS) + itemCount = 0 for i in range(num_items): + itemCount += 1 + print("{}th ITERATION OF ITEM LOOP".format(itemCount)) if type(room) is Rectangle: x = randint(room.x1+1, room.x2-1) y = randint(room.y1+1, room.y2-1) + print("ITEM ROOM IS RECTANGLE") elif type(room) is CaveRoom: (x,y) = room.tiles[randint(0, len(room.tiles) - 1)] + print("ITEM ROOM IS CAVE") item = None if not isBlocked(x, y) and not myMap[x][y].chasm: itemChoice = randomChoice(itemChances) + print("DONE RANDOM") if itemChoice == 'potion': item = createPotion(x, y) + print("POT") elif itemChoice == 'scroll': item = createScroll(x, y) + print("SCR") elif itemChoice == 'none': item = None + print("NO") elif itemChoice == 'weapon': item = createWeapon(x, y) + print("WEP") elif itemChoice == 'money': item = GameObject(x, y, char = '$', name = 'gold piece', color = colors.gold, Item=Money(randint(15, 30)), blocks = False, pName = 'gold pieces') + print("MON") elif itemChoice == 'shield': equipmentComponent = Equipment(slot = 'one handed', type = 'shield', armorBonus=3) item = GameObject(x, y, '[', 'shield', colors.darker_orange, Equipment=equipmentComponent, Item=Item(weight = 3.0, pic = 'shield.xp')) + print("SHI") elif itemChoice == 'spellbook': item = createSpellbook(x, y) + print("SPELL") elif itemChoice == "food": foodChances = currentBranch.foodChances foodChoice = randomChoice(foodChances) + print("FOOD") if foodChoice == 'bread': item = GameObject(x, y, ',', "slice of bread", colors.yellow, Item = Item(useFunction=satiateHunger, arg1 = 20, arg2 = "a slice of bread", weight = 0.2, stackable=True, amount = randint(1, 5), description = "This has probably been lying on the ground for ages, but you'll have to deal with it if you don't want to starve.", itemtype = 'food'), blocks = False, pName = "slices of bread") elif foodChoice == 'herbs': @@ -7298,7 +7355,9 @@ def pieDebuff(amount, text): item = None else: item = None - if item is not None: + + if item is not None: + print("ITEM NOT NONE") objects.append(item) item.sendToBack() @@ -7311,6 +7370,16 @@ def pieDebuff(amount, text): if 'highCultist' in monsterChances.keys(): print('Reverting high cultist chances to previous value (current : {} / previous : {})'.format(monsterChances['highCultist'], previousHighCultistChances)) monsterChances['highCultist'] = previousHighCultistChances + else: + print("COULDNT DO ITEM BECAUSE REASONS") + if isBlocked(x, y): + print("ITEM IS BLOCKEEED") + else: + print("WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAT") + print("CONTINUING FUCKING LOOP BECAUSE WE ARE NOT SUPPOSED TO FREEZE THE WHOLE FUCKING PROGRAM") + continue + print("THIS SHOULD NOT DISPLAY") + return 'I-am-fucking-done-with-this' def applyIdentification(): global potionIdentify, scrollIdentify, colorDict, nameDict From 8631e8e42c8894e1b59841aeaaf45bc7b15b2b93 Mon Sep 17 00:00:00 2001 From: Edern76 Date: Sun, 14 May 2017 17:17:31 +0200 Subject: [PATCH 28/32] Restored chasms and fixed rare crash related to equipment --- main.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/main.py b/main.py index f4a546b..af83dc8 100644 --- a/main.py +++ b/main.py @@ -3425,6 +3425,14 @@ def __init__(self, slot, type, powerBonus=0, armorBonus=0, maxHP_Bonus=0, accura self.meleeWeapon = meleeWeapon self.slow = slow self.enchant = enchant + + def updateState(self): + if self.owner in equipmentList: + print("EQUIPPED") + self.isEquipped = True + else: + print("NOT EQUIPPED") + self.isEquipped = False @property def powerBonus(self): @@ -3539,6 +3547,7 @@ def willpowerBonus(self): return self.baseWillpowerBonus def toggleEquip(self): + self.updateState() if self.isEquipped: self.unequip() else: @@ -5975,7 +5984,7 @@ def makeMap(generateChasm = True, generateHole = False, fall = False): myMap = [[Tile(True, x = x, y = y, wall = True, chasm = generateChasm, hole = generateHole) for y in range(MAP_HEIGHT)]for x in range(MAP_WIDTH)] #Creates a rectangle of blocking tiles from the Tile class, aka walls. Each tile is accessed by myMap[x][y], where x and y are the coordinates of the tile. - removeAllChasms() #Erase this when no longer needed + #removeAllChasms() rooms = [] roomTiles = [] tunnelTiles = [] @@ -6041,10 +6050,7 @@ def makeMap(generateChasm = True, generateHole = False, fall = False): print("BEFORE CHASM") if generateChasm: - #NOTE : RESTORE THIS AFTER TRAILER - #myMap = chasmGen.createChasms(myMap, roomTiles, tunnelTiles, unchasmable) - pass - print("PASSING") + myMap = chasmGen.createChasms(myMap, roomTiles, tunnelTiles, unchasmable) if generateHole: myMap = holeGen.createHoles(myMap) print("AFTER CHASM") @@ -8350,8 +8356,9 @@ def chat(): NPC.shopComp.browse() break elif state != 'QUEST0': - NPC.questList[0].take() - tree.currentScreen = NPC.questList[0].screenGive + #NPC.questList[0].take() + #tree.currentScreen = NPC.questList[0].screenGive + pass con.clear() dialLength = len(tree.currentScreen.dialogText) - 1 ty = (CON_HEIGHT // 2) - (dialLength // 2) From 93941746593055f25513680b7f02a5a4b40c8f9a Mon Sep 17 00:00:00 2001 From: Edern76 Date: Sun, 14 May 2017 17:18:54 +0200 Subject: [PATCH 29/32] Added another command for "learn all spells" So as you don't have to revel all the map when you want to cheat in some spells --- main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main.py b/main.py index af83dc8..e681671 100644 --- a/main.py +++ b/main.py @@ -4025,6 +4025,8 @@ def getInput(): FOV_recompute = True elif userInput.keychar.upper() == "F6" and DEBUG and not tdl.event.isWindowClosed(): player.Fighter.xp += 1000 + for spell in spells: + learnSpell(spell) FOV_recompute = True return 'didnt-take-turn' elif userInput.keychar.upper() == 'F7' and DEBUG and not tdl.event.isWindowClosed(): From 4aa69009f16a1fad1cf32b2a04173fc6a6b0343f Mon Sep 17 00:00:00 2001 From: Edern76 Date: Sun, 14 May 2017 17:27:35 +0200 Subject: [PATCH 30/32] Nerfed hunger (maybe a bit too much) --- main.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/main.py b/main.py index e681671..74a5fa9 100644 --- a/main.py +++ b/main.py @@ -192,7 +192,7 @@ def __init__(self, name, width, height, type = 'noType'): RESURECTABLE_CORPSES = ["darksoul", "ogre"] -BASE_HUNGER = 500 +BASE_HUNGER = 1500 MAX_ASTAR_FAILS = 1 #Possibly unstable at 1 (but best performance), if you get weird results with Astar (aside from freezing) try bumping this number up a LITTLE bit (3 is already way overkill) @@ -3856,7 +3856,7 @@ def badPieEffect(): if dice > 40: vomit() else: - satiateHunger(randint(30, 80)) + satiateHunger(randint(50, 200)) if dice > 70: message("This had a very strange aftertaste...", colors.red) poisoned = Buff('poisoned', colors.purple, cooldown=randint(5, 10), continuousFunction=lambda fighter: randomDamage('poison', fighter, chance = 100, minDamage=1, maxDamage=10)) @@ -3865,10 +3865,10 @@ def badPieEffect(): badPie = GameObject(None, None, ',', "awful pie", colors.dark_fuchsia, Item = Item(useFunction = lambda : badPieEffect(), weight = 0.4, stackable=True, amount = 1, description = "This pie looks barely edible. Whoever baked it deserves the title of the worst baker of all this world.", itemtype = 'food'), blocks = False, pName = "awful pies") # TO-DO : Once we find the name of the world, change description badPieChoice = ShopChoice(gObject = badPie, price = 100, stock = 20) -salad = GameObject(None, None, ',', "'herb salad", colors.green, Item = Item(useFunction = lambda : satiateHunger(40, 'the herb salad'), weight = 0.05, stackable=True, amount = 1, description = "A salad made out of the herbs that grow all arount this place. Oddly enough, this looks like it won't make you die of poisoning as soon as you eat it.", itemtype = 'food'), blocks = False, pName = "herb salads") +salad = GameObject(None, None, ',', "'herb salad", colors.green, Item = Item(useFunction = lambda : satiateHunger(100, 'the herb salad'), weight = 0.05, stackable=True, amount = 1, description = "A salad made out of the herbs that grow all arount this place. Oddly enough, this looks like it won't make you die of poisoning as soon as you eat it.", itemtype = 'food'), blocks = False, pName = "herb salads") saladChoice = ShopChoice(gObject = salad, price = 120, stock = 10) -bread = GameObject(None, None, ',', "slice of bread", colors.yellow, Item = Item(useFunction= lambda : satiateHunger(20, 'the slice of bread'), weight = 0.2, stackable=True, amount = 1, description = "This has probably been lying on the ground for ages, but you'll have to deal with it if you don't want to starve.", itemtype = 'food'), blocks = False, pName = "slices of bread") +bread = GameObject(None, None, ',', "slice of bread", colors.yellow, Item = Item(useFunction= lambda : satiateHunger(50, 'the slice of bread'), weight = 0.2, stackable=True, amount = 1, description = "This has probably been lying on the ground for ages, but you'll have to deal with it if you don't want to starve.", itemtype = 'food'), blocks = False, pName = "slices of bread") breadChoice = ShopChoice(gObject = bread, price = 40, stock = 5) #The amount of stock will make sense once we have a restock system implemented (you have to bake more bread to get more, and since the NPC cannot leave the town because monsters there are limited ressources, so you can't bake a lot of it in one go) cSwordEquip = Equipment(slot = 'one handed', type = 'light weapon', powerBonus = 2, criticalBonus = 1, meleeWeapon = True) @@ -7307,9 +7307,9 @@ def placeObjects(room, first = False): foodChoice = randomChoice(foodChances) print("FOOD") if foodChoice == 'bread': - item = GameObject(x, y, ',', "slice of bread", colors.yellow, Item = Item(useFunction=satiateHunger, arg1 = 20, arg2 = "a slice of bread", weight = 0.2, stackable=True, amount = randint(1, 5), description = "This has probably been lying on the ground for ages, but you'll have to deal with it if you don't want to starve.", itemtype = 'food'), blocks = False, pName = "slices of bread") + item = GameObject(x, y, ',', "slice of bread", colors.yellow, Item = Item(useFunction=satiateHunger, arg1 = 50, arg2 = "a slice of bread", weight = 0.2, stackable=True, amount = randint(1, 5), description = "This has probably been lying on the ground for ages, but you'll have to deal with it if you don't want to starve.", itemtype = 'food'), blocks = False, pName = "slices of bread") elif foodChoice == 'herbs': - item = GameObject(x, y, ',', "'edible' herb", colors.darker_lime, Item = Item(useFunction=satiateHunger, arg1 = 10, arg2 = "some weird looking herb", weight = 0.05, stackable=True, amount = randint(1, 8), description = "An oddly shapen herb, which looks 'slightly' withered. Your empty stomach makes you think this is comestible, but you're not sure about this.", itemtype = 'food'), blocks = False, pName = "'edible' herbs") + item = GameObject(x, y, ',', "'edible' herb", colors.darker_lime, Item = Item(useFunction=satiateHunger, arg1 = 30, arg2 = "some weird looking herb", weight = 0.05, stackable=True, amount = randint(1, 8), description = "An oddly shapen herb, which looks 'slightly' withered. Your empty stomach makes you think this is comestible, but you're not sure about this.", itemtype = 'food'), blocks = False, pName = "'edible' herbs") elif foodChoice == 'rMeat': def rMeatDebuff(amount, text): if not 'poisoned' in convertBuffsToNames(player.Fighter): @@ -7325,7 +7325,7 @@ def rMeatDebuff(amount, text): message("You really don't want to take the risk of being in worse condition than you currently are.", colors.red) return 'cancelled' - item = GameObject(x, y, ',', "piece of rancid meat", colors.light_crimson, Item = Item(useFunction=lambda: rMeatDebuff(150, 'a chunk of rancid meat'), weight = 0.4, stackable=True, amount = 1, description = "'Rancid' is not the most appropriate term to describe the state of this chunk of meat, 'half-putrefacted' would be closer to the reality. Eating this is probably not a good idea", itemtype = 'food'), blocks = False, pName = "pieces of rancid meat") + item = GameObject(x, y, ',', "piece of rancid meat", colors.light_crimson, Item = Item(useFunction=lambda: rMeatDebuff(400, 'a chunk of rancid meat'), weight = 0.4, stackable=True, amount = 1, description = "'Rancid' is not the most appropriate term to describe the state of this chunk of meat, 'half-putrefacted' would be closer to the reality. Eating this is probably not a good idea", itemtype = 'food'), blocks = False, pName = "pieces of rancid meat") elif foodChoice == 'pie': def pieDebuff(amount, text): pieChoices = {'noDebuff' : 20, 'poison' : 20, 'freeze' : 20, 'burn' : 20, 'confuse' : 20} @@ -7352,13 +7352,13 @@ def pieDebuff(amount, text): else: message("This didn't taste as bad as you'd expect.") - item = GameObject(x, y, ',', "strange pie", colors.fuchsia, Item = Item(useFunction= lambda : pieDebuff(randint(100, 200), 'the pie'), weight = 0.4, stackable=True, amount = 1, description = "This looks like a pie of some sort, but for some reason it doesn't look appetizing at all. Should fill your stomach for a little while though. Wait, is that a worm you saw inside ?", itemtype = 'food'), blocks = False, pName = "strange pies") + item = GameObject(x, y, ',', "strange pie", colors.fuchsia, Item = Item(useFunction= lambda : pieDebuff(randint(200, 350), 'the pie'), weight = 0.4, stackable=True, amount = 1, description = "This looks like a pie of some sort, but for some reason it doesn't look appetizing at all. Should fill your stomach for a little while though. Wait, is that a worm you saw inside ?", itemtype = 'food'), blocks = False, pName = "strange pies") elif foodChoice == 'pasta': - item = GameObject(x, y, ',', "'plate' of pasta", colors.light_yellow, Item = Item(useFunction=satiateHunger, arg1 = 50, arg2 = "the pasta", weight = 0.3, stackable=True, amount = randint(1, 4), description = "If you exclude the fact that the 'plate' is inexistent, and therefore the pasta are spilled on the floor, this actually looks delicious.", itemtype = 'food'), blocks = False, pName = "'plates' of pasta") + item = GameObject(x, y, ',', "'plate' of pasta", colors.light_yellow, Item = Item(useFunction=satiateHunger, arg1 = 150, arg2 = "the pasta", weight = 0.3, stackable=True, amount = randint(1, 4), description = "If you exclude the fact that the 'plate' is inexistent, and therefore the pasta are spilled on the floor, this actually looks delicious.", itemtype = 'food'), blocks = False, pName = "'plates' of pasta") elif foodChoice == 'meat': - item = GameObject(x, y, ',', "piece of cooked meat", colors.red, Item = Item(useFunction=satiateHunger, arg1 = 300, arg2 = "a chunk of edible meat (at last !)", weight = 0.4, stackable=True, amount = 1, description = "A perfectly fine-looking grilled steak. Yummy !", itemtype = 'food'), blocks = False, pName = "cooked pieces of meat") + item = GameObject(x, y, ',', "piece of cooked meat", colors.red, Item = Item(useFunction=satiateHunger, arg1 = 650, arg2 = "a chunk of edible meat (at last !)", weight = 0.4, stackable=True, amount = 1, description = "A perfectly fine-looking grilled steak. Yummy !", itemtype = 'food'), blocks = False, pName = "cooked pieces of meat") elif foodChoice == 'hBaguette': - item = GameObject(x, y, ',', "holy baguette", colors.white, Item = Item(useFunction=satiateHunger, arg1 = 500, arg2 = "le holy baguette", weight = 0.4, stackable=True, amount = 1, description = "HON HON HON ! Dis iz going to be le most goodest meal you iz gonna have in years !", itemtype = 'food'), blocks = False, pName = "holy baguettes") #Easter-egg. You'll maybe want to tone down its spawn rate by a little bit. TO-DO : Add a funny effect when eating this. TO-DO : Make this illuminate the adjacent tiles (when and if we implement lighting) + item = GameObject(x, y, ',', "holy baguette", colors.white, Item = Item(useFunction=satiateHunger, arg1 = 1500, arg2 = "le holy baguette", weight = 0.4, stackable=True, amount = 1, description = "HON HON HON ! Dis iz going to be le most goodest meal you iz gonna have in years !", itemtype = 'food'), blocks = False, pName = "holy baguettes") #Easter-egg. You'll maybe want to tone down its spawn rate by a little bit. TO-DO : Add a funny effect when eating this. TO-DO : Make this illuminate the adjacent tiles (when and if we implement lighting) else: item = None else: From b377c8f54be9d8f0e741bcafa34ec1494a013bb6 Mon Sep 17 00:00:00 2001 From: Edern76 Date: Sun, 14 May 2017 17:31:29 +0200 Subject: [PATCH 31/32] Added quick next level key --- main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index 74a5fa9..fc845b3 100644 --- a/main.py +++ b/main.py @@ -3993,7 +3993,8 @@ def getInput(): return 'didnt-take-turn' ''' elif userInput.keychar.upper() == 'F2' and gameState != 'looking': - player.Fighter.takeDamage(1, 'debug damage') + #player.Fighter.takeDamage(1, 'debug damage') + nextLevel() FOV_recompute = True return 'didnt-take-turn' elif userInput.keychar.upper() == 'F1': From 75f6c588f11031f1c6010d2007a38c28df84f7f5 Mon Sep 17 00:00:00 2001 From: Edern76 Date: Sun, 14 May 2017 17:48:54 +0200 Subject: [PATCH 32/32] Fixed stairs to branches not appearing after first game on the same session --- code/dunbranches.py | 9 +++++++++ main.py | 4 +++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/code/dunbranches.py b/code/dunbranches.py index 07e2cc0..494140a 100644 --- a/code/dunbranches.py +++ b/code/dunbranches.py @@ -1,5 +1,7 @@ import colors +branches = [] + class Branch: def __init__(self, shortName, name = None, maxDepth = 99999, branchesFrom = None, branchesTo = None, lightStairsColor = colors.white, darkStairsColor = colors.dark_gray, monsterChances = {'darksoul': 600, 'ogre': 200, 'snake': 50, 'cultist': 150, 'highCultist' : 0}, @@ -52,6 +54,8 @@ def __init__(self, shortName, name = None, maxDepth = 99999, branchesFrom = None self.genType = genType self.genFeatures = genFeatures self.appeared = False + + branches.append(self) mainDungeon = Branch(shortName = "main", name = "Main", branchesTo = None) gluttonyDungeon = Branch(shortName = "glutt", name = "Gluttony Dungeon", maxDepth = 5, branchesFrom = (mainDungeon, 1), lightStairsColor = colors.desaturated_chartreuse, darkStairsColor = colors.darkest_chartreuse, monsterChances = {'darksoul': 400, 'ogre': 200, 'starveling': 250, 'cultist': 150}, itemChances = {'potion': 360, 'scroll': 20, 'weapon': 20, 'shield': 100, 'food': 500}, bossLevels = [5], bossNames = {'Gluttony': 5}) @@ -63,4 +67,9 @@ def __init__(self, shortName, name = None, maxDepth = 99999, branchesFrom = None mainDungeon.branchesTo.append((hiddenTown, 1)) mainDungeon.branchesTo.append((greedDungeon, 2)) mainDungeon.branchesTo.append((wrathDungeon, 2)) + +def reinitializeBranches(): + for branch in branches: + print("Reinitializing {}".format(branch.name)) + branch.appeared = False \ No newline at end of file diff --git a/main.py b/main.py index fc845b3..e3b37d6 100644 --- a/main.py +++ b/main.py @@ -8689,7 +8689,8 @@ def newGame(): DEBUG = False REVEL = False deleteSaves() - #bossDungeonsAppeared = {'gluttony': False, 'greed': False, 'wrath': False} + bossDungeonsAppeared = {'gluttony': False, 'greed': False, 'wrath': False} + dBr.reinitializeBranches() gameMsgs = [] objects = [player] logMsgs = [] @@ -8700,6 +8701,7 @@ def newGame(): menuWindows = [] hiroshimanNumber = 0 FOV_recompute = True + currentBranch = dBr.mainDungeon dungeonLevel = 1 makeMap()