]> bicyclesonthemoon.info Git - ott/molpy-up/commitdiff
adopted eternal-flag mode and AI by balthasar_s master
authorPeter Gerwinski <peter.gerwinski@hs-bochum.de>
Wed, 16 May 2018 18:39:12 +0000 (20:39 +0200)
committerPeter Gerwinski <peter.gerwinski@hs-bochum.de>
Wed, 16 May 2018 18:39:12 +0000 (20:39 +0200)
README
assets/lucky.xcf.gz [new file with mode: 0644]
molpyup.py

diff --git a/README b/README
index c4c6600ed4f0356c4af237458056f9f2b6eecaa6..4c4faa4cafcf6b5ebf9611843bedf51ad5bce446 100644 (file)
--- a/README
+++ b/README
@@ -40,12 +40,14 @@ In the game, the following keys can be used:
 
 Some additional key bindings for debugging and/or cheating:
  - Use <ctrl> with <+> or <-> to crank up/down the score.
- - Use <ctrl> with <e> to enable "eternal" mode. No more falling down. ;-)
+ - Use <ctrl> with <e> to enable / disable "eternal" mode. No more falling down. ;-)
+ - Use <ctrl> with <f> for flag-eternal mode. Lose a flag instead of falling down.
  - Use <ctrl> with <f> to get / get rid of a flag.
  - Use <ctrl> with <b> to get / get rid of a beanie.
+ - Use <ctrl> with <i> enable / disable artificial intelligence playing for you.
 
 Thanks to NoMouse and taixzo for the installation instructions!
-Thanks to balthasar_s for testing and debugging!
+Thanks to balthasar_s for testing, debugging, and improving the game!
 Thanks to everyone who reported mustard and kept me up with the Present!
 
 Enjoy!
diff --git a/assets/lucky.xcf.gz b/assets/lucky.xcf.gz
new file mode 100644 (file)
index 0000000..4568546
Binary files /dev/null and b/assets/lucky.xcf.gz differ
index 0c23e80e5bd1b28c6c0b84703eda37d5d4be14f1..481a27b433eb54f49d38a60359a17dc2e6ca7fc1 100644 (file)
@@ -7,7 +7,7 @@
 # Copyright (C) 2018 by Peter Gerwinski <http://www.peter.gerwinski.de>,
 # OTTified in about 120 minutes.
 #
-# edited to add arrow - balthasar_s
+# edited to add arrow, AI, and a flag save mode - balthasar_s
 #
 # This program is Free Software: you can redistribute it and/or modify it
 # under the terms of the GNU General Public License (GNU GPL), version 3,
@@ -40,6 +40,7 @@ from pygame.locals import *
 import sys
 import datetime
 import random
+import math
 
 class MolpyUp:
 
@@ -78,6 +79,7 @@ class MolpyUp:
     scoreEpilogue = 3094
 
     def __init__(self):
+        self.relativeX=0
         self.sx = 553
         self.sy = 395
         self.extrax = self.sx // 16
@@ -87,6 +89,9 @@ class MolpyUp:
         self.clock = pygame.time.Clock()
         self.xmovementmax = 10
         self.eternal = False
+        self.eternalFlag = False
+        self.ai = False
+        self.aiDebag = False
         self.imgPlatformSand = [ pygame.image.load("assets/platformSand1.png").convert_alpha(),
                                  pygame.image.load("assets/platformSand2.png").convert_alpha(),
                                  pygame.image.load("assets/platformSand3.png").convert_alpha(),
@@ -171,9 +176,11 @@ class MolpyUp:
         self.hadLucky = False
         self.hadTheEnd = False
         self.raftcastleHasFlag = False
-        self.platforms = [[self.playerx, self.playery + self.sy // 6, self.platformTypeSand, 0, 0]]
+        self.platforms = [[self.playerx, self.playery + self.sy // 6, self.platformTypeSand, 0, 0, -1, False, self.imgPlatformSand[0].get_width()]]
         self.generateInitialPlatforms()
         self.items = []
+        self.aiNextPlatformOk = False
+        self.aiNextPlatform=[self.playerx,self.playery]
         if self.filename:
             self.restoreGame (self.filename)
 
@@ -202,6 +209,7 @@ class MolpyUp:
             file.write("hadTheEnd: " + str(self.hadTheEnd) + "\n")
             file.write("raftcastleHasFlag: " + str(self.raftcastleHasFlag) + "\n")
             file.write("eternal: " + str(self.eternal) + "\n")
+            file.write("eternalFlag: " + str(self.eternalFlag) + "\n")
             file.write("platforms: " + str(self.platforms) + "\n")
             file.write("items: " + str(self.items) + "\n")
 
@@ -241,8 +249,112 @@ class MolpyUp:
             return True
         except FileNotFoundError:
             return False
-
+   
+    def findNextPlatform(self):
+        # bestDistance=float("Inf")
+        # for p in self.platforms:
+            # if not self.jump:
+                # distance = abs(p[0]-self.playerx) * 0.5 - p[1]
+            # else:
+                # distance = abs(p[0]-self.playerx) * 0.5 + abs(p[1]-self.playery)
+                # if p[1]>self.playery:
+                    # distance += 900
+            # if p[2] > self.platformTypeNormal and p[2] <= self.platformTypeFloating:
+                # distance += 290
+            # if p[2] == self.platformTypeBreaking:
+                # distance = float("Inf")
+            # p[6]=distance
+            # if distance<bestDistance:
+                # bestDistance = distance
+                # self.aiNextPlatform=p
+                # self.aiNextPlatformOk = True
+       
+        bestPlatformScore = float("-Inf")
+        actualY=self.playery+self.imgPlayerRightUp.get_height()
+        actualX=self.playerx+self.imgPlayerRightUp.get_width()//2
+        self.aiNextPlatform = self.platforms[0]
+        if self.jump > 0:
+            maxY = actualY - (self.jump * (self.jump+1) // 2)
+            framesUp = self.jump
+        else:
+            maxY = actualY
+            framesUp = 0
+               
+        for p in self.platforms:
+            platformX = p[0] + p[7] //2
+            platformY = p[1]
+            platformScore = 0
+           
+            if (platformY < maxY) or (p[2] == self.platformTypeBreaking):
+                platformScore = float("-Inf")
+                p[6]=platformScore
+                continue
+           
+            distY = actualY - platformY
+            distDown = platformY - maxY
+            distX = abs(platformX-actualX)
+           
+            if self.gravity > 0:
+                framesDown = int(math.floor(math.sqrt(self.gravity * self.gravity + 2 * distDown) - self.gravity))
+            else:
+                framesDown = int(math.floor(math.sqrt(2*distDown)))
+           
+            speedX=9;
+           
+            if p[2] > self.platformTypeNormal and p[2] <= self.platformTypeFloating:
+                if (p[4] and platformX>actualX) or (not p[4] and platformX<actualX):
+                    speedX -= self.extrax // 10
+                else:
+                    speedX += self.extrax // 10
+           
+            platformScore += framesUp + framesDown - distX//speedX
+           
+            if platformX-actualX>2*self.xmovementmax and self.xmovement < 0:
+                platformScore -= (self.xmovementmax-self.xmovement)*(self.xmovementmax-self.xmovement)//4
+            elif actualX-platformX>2*self.xmovementmax and self.xmovement > 0:
+                platformScore -= (-self.xmovementmax-self.xmovement)*(-self.xmovementmax-self.xmovement)//4
+           
+            if platformScore < 0:
+                platformScore = float("-Inf")
+            platformScore *=4
+           
+            if distY>16:
+                platformScore += distY + distX//2
+            else:
+                platformScore += 2*distY - 200 + distX
+           
+            if p[2] > self.platformTypeNormal and p[2] <= self.platformTypeFloating:
+                platformScore -= 50 #100
+            elif p[2] == self.platformTypeLucky:
+                platformScore -= 150
+           
+            if p[5] == self.itemTypeSnake:
+                platformScore -= 150
+            elif p[5] == self.itemTypeFlag and not self.playerCarriesFlag:
+                platformScore += 70
+            elif p[5] == self.itemTypeSandcastle and self.playerCarriesFlag:
+                platformScore += 70
+            elif p[5] == self.itemTypeBeanie and not self.playerWearsBeanie:
+                platformScore += 50
+           
+            p[6] = platformScore
+           
+            if platformScore > bestPlatformScore:
+                bestPlatformScore = platformScore
+                self.aiNextPlatform = p
+                self.aiNextPlatformOk = True
+               
+           
+           
+       
+               
     def updatePlayer(self):
+        if ((not self.jump) and (self.playery > self.aiNextPlatform[1])) or (self.aiNextPlatform[1] - self.cameray > self.sy):
+            self.aiNextPlatformOk = False
+       
+        if not self.aiNextPlatformOk and self.ai:
+            self.findNextPlatform()
+   
         if not self.jump:
             self.playery += self.gravity
             self.gravity += 1
@@ -250,6 +362,7 @@ class MolpyUp:
             self.playery -= self.jump
             self.jump -= 1
         key = pygame.key.get_pressed()
+       
         if key[K_RIGHT]:
             if self.xmovement < self.xmovementmax:
                 self.xmovement += 1
@@ -271,14 +384,42 @@ class MolpyUp:
                 self.speed -= 1
                 self.screen.blit(self.font.render("Speed: " + str(self.speed), -1, (0, 0, 0)), (self.sx // 32, self.sy - self.sy // 12))
         else:
-            if self.xmovement > 0:
-                self.xmovement -= 1
-            elif self.xmovement < 0:
-                self.xmovement += 1
+            if self.ai:
+                actualX=self.playerx+self.imgPlayerRightUp.get_width()//2
+                platformX = self.aiNextPlatform[0] + self.aiNextPlatform[7] //2
+                if self.aiNextPlatform[2] > self.platformTypeNormal and self.aiNextPlatform[2] <= self.platformTypeFloating:
+                    if self.aiNextPlatform[4] == True:
+                        self.relativeX = self.xmovement - self.extrax // 10
+                    else:
+                        self.relativeX = self.xmovement + self.extrax // 10
+                else:
+                    self.relativeX = self.xmovement
+
+                if actualX<platformX -2.5*self.relativeX:
+                    if self.xmovement < self.xmovementmax:
+                        self.xmovement += 1
+                    self.direction = 0
+                elif actualX>platformX -2.5*self.relativeX:
+                    if self.xmovement > -self.xmovementmax:
+                        self.xmovement -= 1
+                    self.direction = 1
+                else:
+                    if self.xmovement > 0:
+                        self.xmovement -= 1
+                    elif self.xmovement < 0:
+                        self.xmovement += 1
+            else:
+                if self.xmovement > 0:
+                    self.xmovement -= 1
+                elif self.xmovement < 0:
+                    self.xmovement += 1
+       
         if self.playerx > self.sx + self.extrax:
             self.playerx = -self.extrax
+            self.aiNextPlatformOk = False
         elif self.playerx < -self.extrax:
             self.playerx = self.sx + self.extrax
+            self.aiNextPlatformOk = False
         self.playerx += self.xmovement
         if self.playery - self.cameray <= self.sy // 3:
             self.cameray -= self.sy // 60
@@ -317,6 +458,8 @@ class MolpyUp:
                         self.screen.blit(self.imgPlayerLeftUp, (self.playerx, self.playery - self.cameray))
                     if self.playerCarriesFlag:
                         self.screen.blit(self.imgFlagRightDown, (self.playerx + 11, self.playery - 10 - self.cameray))
+       
+     
 
     def choosePlatformType(self):
         if self.score >= self.scoreTheEnd:
@@ -348,31 +491,35 @@ class MolpyUp:
             return self.platformTypeBreaking
 
     def generateNewPlatform(self):
+        platform = False
+        platform2 = False
         platformType = self.choosePlatformType()
         if platformType == self.platformTypeTheEnd:
             if not self.hadTheEnd:
-                self.platforms.append([self.sx // 2 - self.imgPlatformTheEnd.get_width() // 2, self.platforms[-1][1] - self.sy // 4, self.platformTypeTheEnd, False, False])
-                self.platforms.append([self.sx // 2 - self.imgPlatformWonTheGame.get_width() // 2, self.platforms[-1][1] - self.sy * 2 // 3, self.platformTypeWonTheGame, False, False])
+                platform2=[self.sx // 2 - self.imgPlatformTheEnd.get_width() // 2, self.platforms[-1][1] - self.sy // 4, self.platformTypeTheEnd, False, False, -1, False, self.imgPlatformTheEnd.get_width()]
+                platform=[self.sx // 2 - self.imgPlatformWonTheGame.get_width() // 2, platform2[1] - self.sy * 2 // 3, self.platformTypeWonTheGame, False, False, -1, False, self.imgPlatformWonTheGame.get_width()]
                 self.hadTheEnd = True
         elif platformType == self.platformTypeWater or platformType == self.platformTypeRaftcastle:
-            self.platforms.append([random.randint(0, self.sx * 7 // 8), self.platforms[-1][1] - self.sy // 8, platformType, False, False])
+            platform=[random.randint(0, self.sx * 7 // 8), self.platforms[-1][1] - self.sy // 8, platformType, False, False, -1, False, self.imgPlatformSand[0].get_width()]
         elif platformType == self.platformTypeLucky:
-            self.platforms.append([0, self.platforms[-1][1] - self.sy // 12, platformType, False, False])
+            platform=[0, self.platforms[-1][1] - self.sy // 12, platformType, False, False, -1, False, self.imgPlatformSand[0].get_width()]
         else:
-            self.platforms.append([random.randint(0, self.sx * 7 // 8), self.platforms[-1][1] - self.sy // 12, platformType, False, False])
+            platform=[random.randint(0, self.sx * 7 // 8), self.platforms[-1][1] - self.sy // 12, platformType, False, False, -1, False, self.imgPlatformSand[0].get_width()]
         if platformType <= self.platformTypeNormal:
             if platformType == self.platformTypeSand:
-                self.platforms[-1][-1] = random.randint(0, len(self.imgPlatformSand) - 1)
+                platform[4] = random.randint(0, len(self.imgPlatformSand) - 1)
             elif platformType == self.platformTypeGrass:
-                self.platforms[-1][-1] = random.randint(0, len(self.imgPlatformGrass) - 1)
+                platform[4] = random.randint(0, len(self.imgPlatformGrass) - 1)
             else:
-                self.platforms[-1][-1] = random.randint(0, len(self.imgPlatformWater) - 1)
-            x = self.platforms[-1][0]
-            y = self.platforms[-1][1]
+                platform[4] = random.randint(0, len(self.imgPlatformWater) - 1)
+            x = platform[0]
+            y = platform[1]
             if platformType == self.platformTypeGrass and self.score > self.scoreSnake and not self.hadSnake:
+                platform[5]=self.itemTypeSnake
                 self.items.append([x - 10, y + 9, self.itemTypeSnake, False])
                 self.hadSnake = True
             elif platformType == self.platformTypeGrass and self.score > self.scorePrickly and not self.hadPrickly:
+                platform[5]=self.itemTypePrickly
                 self.items.append([x + self.imgPlatformSand[0].get_width() // 3, y + 8, self.itemTypePrickly, False])
                 self.hadPrickly = True
             elif self.score > 0:
@@ -381,23 +528,36 @@ class MolpyUp:
                     xx = x + random.randint(0, self.imgPlatformSand[0].get_width() - 40)
                     itemType = random.randint(0,999)
                     if itemType < 50:
+                        platform[5]=self.itemTypeBeanie
                         self.items.append([xx, y + 7, self.itemTypeBeanie, False])
                     elif itemType < 150 and platformType == self.platformTypeSand:
+                        platform[5]=self.itemTypeSandcastle
                         self.items.append([xx, y + 7, self.itemTypeSandcastle, False])
                     elif itemType < 350 and platformType == self.platformTypeSand:
+                        platform[5]=self.itemTypeFlag
                         self.items.append([xx, y + 7, self.itemTypeFlag, False])
                     elif itemType < 950 and platformType == self.platformTypeSand:
+                        platform[5]=self.itemTypePlantSand
                         self.items.append([xx, y + 8, self.itemTypePlantSand, itemType % len(self.imgPlantSand)])
                     elif itemType < 100 and platformType == self.platformTypeGrass:
+                        platform[5]=self.itemTypeFlag
                         self.items.append([xx, y + 6, self.itemTypeFlag, False])
                     elif itemType < 700 and platformType == self.platformTypeGrass:
+                        platform[5]=self.itemTypePlantGrass
                         self.items.append([xx, y + 10, self.itemTypePlantGrass, itemType % len(self.imgPlantGrass)])
                     elif itemType < 850 and platformType == self.platformTypeGrass and self.score > self.scorePrickly:
+                        platform[5]=self.itemTypePrickly
                         self.items.append([xx, y + 8, self.itemTypePrickly, False])
                     elif itemType < 950 and platformType == self.platformTypeGrass and self.score > self.scoreSnake:
+                        platform[5]=self.itemTypeSnake
                         self.items.append([x - 10, y + 9, self.itemTypeSnake, False])
                     else:
+                        platform[5]=self.itemTypeAccelerator
                         self.items.append([xx - 5, y + 10, self.itemTypeAccelerator, False])
+        if platform2 != False:
+            self.platforms.append(platform2)
+        if platform != False:
+            self.platforms.append(platform)
 
     def updatePlatforms(self):
         while self.platforms[0][1] - self.cameray > self.sy + self.sy // 12:
@@ -421,25 +581,27 @@ class MolpyUp:
             player = pygame.Rect(self.playerx + 15, self.playery, self.imgPlayerRightUp.get_width() - 30, self.imgPlayerRightUp.get_height())
             if rect.colliderect(player) and self.gravity and self.playery < (p[1] - self.cameray):
                 if p[2] == self.platformTypeBreaking:
-                    p[-1] = True
+                    p[4] = True
                 else:
                     self.jump = self.sy // 20
+                    self.aiNextPlatformOk = False
                     self.gravity = 0
-                    if p[2] == self.platformTypeLucky and not (self.playerWearsBeanie and self.playerCarriesFlag) and p[-2] <= 0:
+                    if p[2] == self.platformTypeLucky and not (self.playerWearsBeanie and self.playerCarriesFlag) and p[3] <= 0:
+                        self.aiNextPlatformOk = False
                         self.xmovement = self.sx // 20
                         self.direction = 0
                         self.cameray -= self.sy // 12
-                        p[-2] = -1
-                    elif (p[2] == self.platformTypeAfterLucky or p[2] == self.platformTypeCastle or p[2] == self.platformTypeLucky) and self.playerCarriesFlag and not p[-2]:
+                        p[3] = -1
+                    elif (p[2] == self.platformTypeAfterLucky or p[2] == self.platformTypeCastle or p[2] == self.platformTypeLucky) and self.playerCarriesFlag and not p[3]:
                         self.playerCarriesFlag = False
-                        p[-2] = True
+                        p[3] = True
                         self.sandcastles += 1
                     elif p[2] == self.platformTypeRaftcastle and self.playerCarriesFlag and not self.raftcastleHasFlag:
                         self.playerCarriesFlag = False
                         self.raftcastleHasFlag = True
                         self.sandcastles += 1
             if p[2] > self.platformTypeNormal and p[2] <= self.platformTypeFloating:
-                if p[-1]:
+                if p[4]:
                     if p[2] == self.platformTypeAfterLucky:
                         img = self.imgPlatformAfterLucky
                     elif p[2] == self.platformTypeCastle:
@@ -447,35 +609,38 @@ class MolpyUp:
                     else:
                         img = self.imgPlatformGrapevine
                     p[0] += self.extrax // 10
-                    if p[0] + img.get_width() > self.sx + self.extrax:
-                        p[-1] = False
+                    if p[0] + img.get_width() > self.sx:# + self.extrax:
+                        p[4] = False
                 else:
                     p[0] -= self.extrax // 10
                     if p[0] <= 0:
-                        p[-1] = True
+                        p[4] = True
 
+   
+           
+   
     def drawPlatforms(self):
         for p in self.platforms:
             if p[2] == self.platformTypeSand:
-                self.screen.blit(self.imgPlatformSand[p[-1]], (p[0], p[1] - self.cameray))
+                self.screen.blit(self.imgPlatformSand[p[4]], (p[0], p[1] - self.cameray))
             elif p[2] == self.platformTypeGrass:
-                self.screen.blit(self.imgPlatformGrass[p[-1]], (p[0], p[1] - self.cameray))
+                self.screen.blit(self.imgPlatformGrass[p[4]], (p[0], p[1] - self.cameray))
             elif p[2] == self.platformTypeWater:
-                self.screen.blit(self.imgPlatformWater[p[-1]], (p[0], p[1] - self.cameray))
+                self.screen.blit(self.imgPlatformWater[p[4]], (p[0], p[1] - self.cameray))
             elif p[2] == self.platformTypeGrapevine:
                 self.screen.blit(self.imgPlatformGrapevine, (p[0], p[1] - self.cameray))
             elif p[2] == self.platformTypeAfterLucky:
-                if p[-2]:
+                if p[3]:
                     self.screen.blit(self.imgFlagRight, (p[0] + 47, p[1] - 12 - self.cameray))
                 self.screen.blit(self.imgPlatformAfterLucky, (p[0], p[1] - self.cameray))
             elif p[2] == self.platformTypeCastle:
-                if p[-2]:
+                if p[3]:
                     self.screen.blit(self.imgFlagRight, (p[0] + self.imgPlatformCastle.get_width() - 16, p[1] - 4 - self.cameray))
                 self.screen.blit(self.imgPlatformCastle, (p[0], p[1] - self.cameray))
             elif p[2] == self.platformTypeLucky:
-                if p[-2]:
+                if p[3]:
                     self.screen.blit(self.imgPlatformLuckyAttacking, (p[0], p[1] - self.imgPlatformLuckyAttacking.get_height() + self.imgPlatformLuckySleeping.get_height() - self.cameray))
-                    if p[-2] > 0:
+                    if p[3] > 0:
                         self.screen.blit(self.imgFlagRight, (p[0] + self.imgPlatformLuckyAttacking.get_width() - 8, p[1] - 11 - self.cameray))
                 else:
                     self.screen.blit(self.imgPlatformLuckySleeping, (p[0], p[1] - self.cameray))
@@ -484,7 +649,7 @@ class MolpyUp:
                     self.screen.blit(self.imgFlagRight, (p[0] + 50, p[1] - 13 - self.cameray))
                 self.screen.blit(self.imgPlatformRaftcastle, (p[0], p[1] - self.cameray))
             elif p[2] == self.platformTypeBreaking:
-                if not p[-1]:
+                if not p[4]:
                     self.screen.blit(self.imgPlatformBreaking, (p[0], p[1] - self.cameray))
                 else:
                     self.screen.blit(self.imgPlatformBroken, (p[0], p[1] - self.cameray))
@@ -492,6 +657,13 @@ class MolpyUp:
                 self.screen.blit(self.imgPlatformTheEnd, (p[0], p[1] - self.cameray))
             elif p[2] == self.platformTypeWonTheGame:
                 self.screen.blit(self.imgPlatformWonTheGame, (p[0], p[1] - self.cameray))
+            # print (str(p))
+            if self.aiDebag:
+                self.screen.blit(self.font.render(str(p[2])+" "+str(p[5])+" "+str(p[6]), -1, (0, 0x57, 0xaf)), (p[0], p[1] - self.cameray + 16))
+        if self.aiDebag:
+            self.screen.blit(self.imgMolpArrow, (self.aiNextPlatform[0] + (self.imgPlatformSand[0].get_width()-self.imgMolpArrow.get_width())//2, self.aiNextPlatform[1] - self.cameray + 16))
+           
+           
 
     def drawAndUpdateItems(self):
         while self.items and self.items[0][1] - self.cameray > self.sy + self.sy // 12:
@@ -537,6 +709,7 @@ class MolpyUp:
             if not item[-1]:
                 if pygame.Rect(item[0], item[1] - imgItem.get_height(), imgItem.get_width(), imgItem.get_height()).colliderect(pygame.Rect(self.playerx, self.playery, self.imgPlayerRightUp.get_width(), self.imgPlayerRightUp.get_height())):
                     if item[2] == self.itemTypeAccelerator:
+                        self.aiNextPlatformOk = False
                         self.jump = self.sy // 12
                         self.cameray -= self.sy // 12
                         item[-1] = True
@@ -544,6 +717,7 @@ class MolpyUp:
                         self.playerWearsBeanie = True
                         item[-1] = True
                     elif item[2] == self.itemTypeSnake:
+                        self.aiNextPlatformOk = False
                         if self.playerx + self.imgPlayerRightUp.get_width() // 2 < item[0] + self.imgPlatformGrass[0].get_width() // 2:
                             self.xmovement = -self.sx // 30
                             self.direction = 0
@@ -616,9 +790,21 @@ class MolpyUp:
                     key = pygame.key.get_pressed()
                     if key[K_ESCAPE]:
                         sys.exit()
+                    elif key[K_i]:
+                        if pygame.key.get_mods() & KMOD_CTRL:
+                            self.ai = not self.ai
+                            self.aiNextPlatformOk = False
+                    elif key[K_d]:
+                        if pygame.key.get_mods() & KMOD_CTRL:
+                            self.aiDebag = not self.aiDebag
                     elif key[K_e]:
                         if pygame.key.get_mods() & KMOD_CTRL:
                             self.eternal = not self.eternal
+                            self.eternalFlag = False
+                    elif key[K_f]:
+                        if pygame.key.get_mods() & KMOD_CTRL:
+                            self.eternalFlag = not self.eternalFlag
+                            self.eternal = False
                     elif key[K_f]:
                         if pygame.key.get_mods() & KMOD_CTRL:
                             self.playerCarriesFlag = not self.playerCarriesFlag
@@ -640,13 +826,21 @@ class MolpyUp:
             self.screen.blit(self.font.render(str(self.score), -1, (0, 0, 0)), (self.sx // 32, self.sy // 24))
             for i in range(0, self.sandcastles):
                 self.screen.blit(self.imgFlagRight, (self.sx // 32 + 10 * i, self.sy // 8))
+           
+           
             if self.playery - self.cameray > self.sy * 7 // 6:
                 if self.eternal:
                     self.jump = self.gravity
                     self.gravity = 0
+                    self.aiNextPlatformOk = False
+                elif self.eternalFlag and self.sandcastles > 0:
+                    self.sandcastles -= 1
+                    self.jump = self.gravity
+                    self.gravity = 0
+                    self.aiNextPlatformOk = False
                 else:
                     self.showScore()
                     self.reset()
             pygame.display.flip()
 
-MolpyUp().run()
+MolpyUp().run()
\ No newline at end of file