]> bicyclesonthemoon.info Git - ott/molpy-up/commitdiff
merged both games into one
authorb <rowerynaksiezycu@gmail.com>
Sat, 28 Mar 2026 06:34:16 +0000 (07:34 +0100)
committerb <rowerynaksiezycu@gmail.com>
Sat, 28 Mar 2026 06:34:16 +0000 (07:34 +0100)
README
molpydown.py [deleted file]
molpyup.py

diff --git a/README b/README
index fea59baf61b8efceb7f63e4bc73897051f0902dc..8a50b9d9420625eefc412f0cbc4a25c2cc4d8136 100644 (file)
--- a/README
+++ b/README
@@ -45,6 +45,7 @@ Some additional key bindings for debugging and/or cheating:
  - 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.
+ - Use <ctrl> with <m> to switch between "Molpy Up!" and "Molpy Down!" games.
 
 Thanks to NoMouse and taixzo for the installation instructions!
 Thanks to balthasar_s for testing, debugging, and improving the game!
diff --git a/molpydown.py b/molpydown.py
deleted file mode 100644 (file)
index 1aec662..0000000
+++ /dev/null
@@ -1,907 +0,0 @@
-# -*- coding: utf-8 -*-
-# Molpy Down!
-#
-# Based on Max00355's version of DoodleJump, <https://github.com/Max00355/DoodleJump>
-# Copyright (C) 2015 by Frankie Primerano,
-# written in 120 minutes, see <https://www.reddit.com/r/gamedev/comments/3umhuq/doodle_jump_created_in_120_minutes_with_python/>.
-#
-# Copyright (C) 2018 by Peter Gerwinski <http://www.peter.gerwinski.de>,
-# OTTified in about 120 minutes.
-#
-# Copyright (C) 2018, 2026 by Balthasar SzczepaƄski
-# add arrow, AI, flag save mode,
-# remove off-screen space,
-# gmae mode messages,
-# some optimisation
-# Change into Molpy Down game!
-#
-# 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,
-# as published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program, see the file LICENSE.  If not, see
-# <http://www.gnu.org/licenses/>.
-#
-# The player figure "Molpy" is
-# Copyright (C) 2013 by BlitzGirl, see user "BlitzGirl" at <http://forums.xkcd.com>,
-# released under conditions compatible with both the GNU GPL v3 and the
-# CC BY-NC 2.5 license (see below).
-#
-# All other artwork used by this program is based on xkcd 1190 "Time",
-# Copyright (C) 2013 by Randall Munroe, see <http://xkcd.com/1190>,
-# released under the Creative Commonns Attribution-NonCommercial Generic License,
-# version 2.5 (CC BY-NC 2.5), see <https://creativecommons.org/licenses/by-nc/2.5/>.
-#
-# In particular, the contents of the directory "assets"
-# is NOT subject to the GNU GPL.
-
-import pygame
-from pygame.locals import *
-import sys
-import datetime
-import random
-import math
-
-class MolpyUp:
-
-    platformTypeSand       =  0
-    platformTypeGrass      =  1
-    platformTypeNormal     = platformTypeGrass
-    platformTypeGrapevine  =  2
-    platformTypeAfterLucky =  3
-    platformTypeCastle     =  4
-    platformTypeWater      =  5
-    platformTypeRaftcastle =  6
-    platformTypeFloating   = platformTypeRaftcastle
-    platformTypeLucky      =  7
-    platformTypeBreaking   =  8
-    platformTypeTheEnd     =  9
-    platformTypeWonTheGame = 10
-    platformTypeFrame1     = 11
-
-    itemTypeAccelerator = 0
-    itemTypeBeanie      = 1
-    itemTypeSnake       = 2
-    itemTypePrickly     = 3
-    itemTypeSandcastle  = 4
-    itemTypeFlag        = 5
-    itemTypePlantSand   = 6
-    itemTypePlantGrass  = 7
-
-    scoreSnake      = 1738
-    scorePrickly    = 2015
-    scoreGrass      = 2193
-    scoreAfterLucky = 2315
-    scoreCastle     = 2825
-    scoreLucky      = 2976
-    scoreRaftcastle = 3031
-    scoreWater      = 3043
-    scoreTheEnd     = 3089
-    scoreEpilogue   = 3094
-
-    def __init__(self):
-        self.relativeX=0
-        self.sx = 553
-        self.sy = 395
-        self.extrax = self.sx // 16
-        self.screen = pygame.display.set_mode((self.sx, self.sy))
-        pygame.font.init()
-        self.font = pygame.font.SysFont("xkcd,sans", 25)
-        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(),
-                                         pygame.image.load("assets/platformSand4.png").convert_alpha() ]
-        self.imgPlatformGrass        = [ pygame.image.load("assets/platformGrass1.png").convert_alpha(),
-                                         pygame.image.load("assets/platformGrass2.png").convert_alpha(),
-                                         pygame.image.load("assets/platformGrass3.png").convert_alpha(),
-                                         pygame.image.load("assets/platformGrass1f.png").convert_alpha(),
-                                         pygame.image.load("assets/platformGrass2f.png").convert_alpha(),
-                                         pygame.image.load("assets/platformGrass3f.png").convert_alpha() ]
-        self.imgPlatformWater        = [ pygame.image.load("assets/platformWater1.png").convert_alpha(),
-                                         pygame.image.load("assets/platformWater2.png").convert_alpha(),
-                                         pygame.image.load("assets/platformWater1f.png").convert_alpha(),
-                                         pygame.image.load("assets/platformWater2f.png").convert_alpha() ]
-        self.imgPlatformAfterLucky     = pygame.image.load("assets/platformAfterLucky.png").convert_alpha()
-        self.imgPlatformCastle         = pygame.image.load("assets/platformCastle.png").convert_alpha()
-        self.imgPlatformLuckySleeping  = pygame.image.load("assets/platformLuckySleeping.png").convert_alpha()
-        self.imgPlatformLuckyAttacking = pygame.image.load("assets/platformLuckyAttacking.png").convert_alpha()
-        self.imgPlatformRaftcastle     = pygame.image.load("assets/platformRaftcastle.png").convert_alpha()
-        self.imgPlatformGrapevine      = pygame.image.load("assets/platformGrapevine.png").convert_alpha()
-        self.imgPlatformBreaking       = pygame.image.load("assets/platformBreaking.png").convert_alpha()
-        self.imgPlatformBroken         = pygame.image.load("assets/platformBroken.png").convert_alpha()
-        self.imgPlatformTheEnd         = pygame.image.load("assets/platformTheEnd.png").convert_alpha()
-        self.imgPlatformWonTheGame     = pygame.image.load("assets/platformWonTheGame.png").convert_alpha()
-        self.imgPlatformFrame1         = pygame.image.load("assets/platformFrame1.png").convert_alpha()
-        self.imgPlayerRightUp          = pygame.image.load("assets/playerRightUp.png").convert_alpha()
-        self.imgPlayerRightDown        = pygame.image.load("assets/playerRightDown.png").convert_alpha()
-        self.imgPlayerLeftUp           = pygame.image.load("assets/playerLeftUp.png").convert_alpha()
-        self.imgPlayerLeftDown         = pygame.image.load("assets/playerLeftDown.png").convert_alpha()
-        self.imgPlayerRightUpBeanie    = pygame.image.load("assets/playerRightUpBeanie.png").convert_alpha()
-        self.imgPlayerRightDownBeanie  = pygame.image.load("assets/playerRightDownBeanie.png").convert_alpha()
-        self.imgPlayerLeftUpBeanie     = pygame.image.load("assets/playerLeftUpBeanie.png").convert_alpha()
-        self.imgPlayerLeftDownBeanie   = pygame.image.load("assets/playerLeftDownBeanie.png").convert_alpha()
-        self.imgAccelerator            = pygame.image.load("assets/accelerator.png").convert_alpha()
-        self.imgAcceleratorUsed        = pygame.image.load("assets/acceleratorUsed.png").convert_alpha()
-        self.imgBeanie                 = pygame.image.load("assets/beanie.png").convert_alpha()
-        self.imgSnake                  = pygame.image.load("assets/snake.png").convert_alpha()
-        self.imgSnakeLeft              = pygame.image.load("assets/snakeLeft.png").convert_alpha()
-        self.imgSnakeRight             = pygame.image.load("assets/snakeRight.png").convert_alpha()
-        self.imgPrickly                = pygame.image.load("assets/prickly.png").convert_alpha()
-        self.imgPricklyCurled          = pygame.image.load("assets/pricklyCurled.png").convert_alpha()
-        self.imgSandcastle             = pygame.image.load("assets/sandcastle.png").convert_alpha()
-        self.imgFlagLeft               = pygame.image.load("assets/flagLeft.png").convert_alpha()
-        self.imgFlagLeftDown           = pygame.image.load("assets/flagLeftDown.png").convert_alpha()
-        self.imgFlagRight              = pygame.image.load("assets/flagRight.png").convert_alpha()
-        self.imgFlagRightDown          = pygame.image.load("assets/flagRightDown.png").convert_alpha()
-        self.imgPlantSand            = [ pygame.image.load("assets/plantSand1.png").convert_alpha(),
-                                         pygame.image.load("assets/plantSand2.png").convert_alpha(),
-                                         pygame.image.load("assets/plantSand3.png").convert_alpha(),
-                                         pygame.image.load("assets/plantSand4.png").convert_alpha(),
-                                         pygame.image.load("assets/plantSand5.png").convert_alpha() ]
-        self.imgPlantGrass           = [ pygame.image.load("assets/plantGrass1.png").convert_alpha(),
-                                         pygame.image.load("assets/plantGrass2.png").convert_alpha(),
-                                         pygame.image.load("assets/plantGrass3.png").convert_alpha(),
-                                         pygame.image.load("assets/plantGrass4.png").convert_alpha(),
-                                         pygame.image.load("assets/plantGrass5.png").convert_alpha(),
-                                         pygame.image.load("assets/plantGrass6.png").convert_alpha(),
-                                         pygame.image.load("assets/plantGrass7.png").convert_alpha(),
-                                         pygame.image.load("assets/plantGrass8.png").convert_alpha(),
-                                         pygame.image.load("assets/plantGrass9.png").convert_alpha(),
-                                         pygame.image.load("assets/plantGrass10.png").convert_alpha(),
-                                         pygame.image.load("assets/plantGrass11.png").convert_alpha() ]
-        self.imgMolpArrow              = pygame.image.load("assets/molpArrow.png").convert_alpha()
-        self.playerHeight = self.imgPlayerRightUp.get_height()
-        # self.playerHalfHeight = self.playerHeight // 2
-        self.playerWidth = self.imgPlayerRightUp.get_width()
-        self.playerHalfWidth = self.playerWidth // 2
-        self.platformSpeed = self.extrax // 10
-        self.platformHeight = [
-            self.imgPlatformSand[0].get_height(),
-            self.imgPlatformGrass[0].get_height(),
-            self.imgPlatformGrapevine.get_height(),
-            self.imgPlatformAfterLucky.get_height(),
-            self.imgPlatformCastle.get_height(),
-            self.imgPlatformWater[0].get_height(),
-            self.imgPlatformRaftcastle.get_height(),
-            self.imgPlatformLuckySleeping.get_height(),
-            self.imgPlatformBreaking.get_height(),
-            self.imgPlatformTheEnd.get_height(),
-            self.imgPlatformWonTheGame.get_height(),
-            self.imgPlatformFrame1.get_height()
-        ]
-        self.platformWidth = [
-            self.imgPlatformSand[0].get_width(),
-            self.imgPlatformGrass[0].get_width(),
-            self.imgPlatformGrapevine.get_width(),
-            self.imgPlatformAfterLucky.get_width(),
-            self.imgPlatformCastle.get_width(),
-            self.imgPlatformWater[0].get_width(),
-            self.imgPlatformRaftcastle.get_width(),
-            self.imgPlatformLuckySleeping.get_width(),
-            self.imgPlatformBreaking.get_width(),
-            self.imgPlatformTheEnd.get_width(),
-            self.imgPlatformWonTheGame.get_width(),
-            self.imgPlatformFrame1.get_width()
-        ]
-        self.dropLimit = 25
-        if self.dropLimit >= self.platformHeight[self.platformTypeSand] + self.playerHeight:
-            self.dropLimit = self.platformHeight[self.platformTypeSand] + self.playerHeight - 1
-        self.showArrow = True
-        
-    def reset(self):
-        self.cameray = 0
-        self.score = self.scoreEpilogue
-        self.sandcastles = 0
-        self.speed = 30
-        self.modeText = ''
-        self.playerx = self.sx // 2 - self.playerHalfWidth
-        self.playery = self.sy * 3 // 4
-        self.direction = 0
-        self.jump = 0
-        self.gravity = 0
-        self.xmovement = 0
-        self.playerWearsBeanie = False
-        self.playerCarriesFlag = False
-        self.hadSnake = False
-        self.hadPrickly = False
-        self.hadAfterLucky = False
-        self.hadCastle = False
-        self.hadLucky = False
-        self.hadTheEnd = False
-        self.raftcastleHasFlag = False
-        self.generateInitialPlatforms()
-        self.items = []
-        self.aiNextPlatformOk = False
-        self.aiNextPlatform=[self.playerx,self.playery]
-        self.oops = False
-        self.pause = False
-        if self.filename:
-            self.restoreGame (self.filename)
-
-    def saveGame(self):
-        self.filename = datetime.datetime.now().strftime("%Y%m%d-%H%M%S.molpyup")
-        with open(self.filename, "w") as file:
-            file.write("MolpyUp!\n")
-            file.write("cameray: " + str(self.cameray) + "\n")
-            file.write("score: " + str(self.score) + "\n")
-            file.write("sandcastles: " + str(self.sandcastles) + "\n")
-            file.write("speed: " + str(self.speed) + "\n")
-            file.write("showArrow: " + str(self.showArrow) + "\n")
-            file.write("playerx: " + str(self.playerx) + "\n")
-            file.write("playery: " + str(self.playery) + "\n")
-            file.write("direction: " + str(self.direction) + "\n")
-            file.write("jump: " + str(self.jump) + "\n")
-            file.write("gravity: " + str(self.gravity) + "\n")
-            file.write("xmovement: " + str(self.xmovement) + "\n")
-            file.write("playerWearsBeanie: " + str(self.playerWearsBeanie) + "\n")
-            file.write("playerCarriesFlag: " + str(self.playerCarriesFlag) + "\n")
-            file.write("hadSnake: " + str(self.hadSnake) + "\n")
-            file.write("hadPrickly: " + str(self.hadPrickly) + "\n")
-            file.write("hadAfterLucky: " + str(self.hadAfterLucky) + "\n")
-            file.write("hadCastle: " + str(self.hadCastle) + "\n")
-            file.write("hadLucky: " + str(self.hadLucky) + "\n")
-            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")
-
-    def readVariable(self, line, name, var):
-        if line.startswith(name + ": "):
-            return eval (line[len(name) + 2:])
-        else:
-            return var
-
-    def restoreGame(self, filename):
-        try:
-            with open(filename, "r") as file:
-                lines = file.readlines()
-            for line in lines:
-                self.cameray = self.readVariable(line, "cameray", self.cameray)
-                self.score = self.readVariable(line, "score", self.score)
-                self.sandcastles = self.readVariable(line, "sandcastles", self.sandcastles)
-                self.speed = self.readVariable(line, "speed", self.speed)
-                self.showArrow = self.readVariable(line, "showArrow", self.showArrow)
-                self.playerx = self.readVariable(line, "playerx", self.playerx)
-                self.playery = self.readVariable(line, "playery", self.playery)
-                self.direction = self.readVariable(line, "direction", self.direction)
-                self.jump = self.readVariable(line, "jump", self.jump)
-                self.gravity = self.readVariable(line, "gravity", self.gravity)
-                self.xmovement = self.readVariable(line, "xmovement", self.xmovement)
-                self.playerWearsBeanie = self.readVariable(line, "playerWearsBeanie", self.playerWearsBeanie)
-                self.playerCarriesFlag = self.readVariable(line, "playerCarriesFlag", self.playerCarriesFlag)
-                self.hadSnake = self.readVariable(line, "hadSnake", self.hadSnake)
-                self.hadPrickly = self.readVariable(line, "hadPrickly", self.hadPrickly)
-                self.hadAfterLucky = self.readVariable(line, "hadAfterLucky", self.hadAfterLucky)
-                self.hadCastle = self.readVariable(line, "hadCastle", self.hadCastle)
-                self.hadLucky = self.readVariable(line, "hadLucky", self.hadLucky)
-                self.hadTheEnd = self.readVariable(line, "hadTheEnd", self.hadTheEnd)
-                self.raftcastleHasFlag = self.readVariable(line, "raftcastleHasFlag", self.raftcastleHasFlag)
-                self.platforms = self.readVariable(line, "platforms", self.platforms)
-                self.items = self.readVariable(line, "items", self.items)
-            return True
-        except FileNotFoundError:
-            return False
-
-    def findNextPlatform(self):
-        bestPlatformScore = float("-Inf")
-        actualY = self.playery + self.playerHeight
-        actualX = self.playerx + self.playerHalfWidth
-        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.platformSpeed
-                else:
-                    speedX += self.platformSpeed
-           
-            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
-            if self.gravity < self.dropLimit:
-                self.gravity += 1
-        else:
-            self.playery -= self.jump
-            self.jump -= 1
-            
-        if self.playery - self.cameray > self.sy * 7 // 6:
-            if self.eternal or (self.eternalFlag and self.sandcastles > 0):
-                if self.eternalFlag:
-                    self.sandcastles -= 1
-                self.jump = self.gravity
-                self.gravity = 0
-                self.aiNextPlatformOk = False
-                self.playery = self.cameray + self.sy + self.playerHeight
-            else:
-                self.oops = True
-        
-        key = pygame.key.get_pressed()
-        
-        xdir = 0;
-        actualX = self.playerx + self.playerHalfWidth
-        if key[K_RIGHT]:
-            xdir = 1
-            self.modeText = ''
-        elif key[K_LEFT]:
-            xdir = -1
-            self.modeText = ''
-        elif key[K_PLUS] or key[K_KP_PLUS]:
-            if pygame.key.get_mods() & KMOD_CTRL:
-                self.score += 10
-                self.modeText = "Score +10: " + str(self.score)
-            else:
-                self.speed += 1
-                self.modeText = "Speed: " + str(self.speed)
-        elif key[K_MINUS] or key[K_KP_MINUS]:
-            if pygame.key.get_mods() & KMOD_CTRL:
-                self.score -= 10
-                self.modeText = "Score -10: " + str(self.score)
-            else:
-                self.speed -= 1
-                self.modeText = "Speed: " + str(self.speed)
-        elif self.ai:
-            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.platformSpeed
-                else:
-                    self.relativeX = self.xmovement + self.platformSpeed
-            else:
-                self.relativeX = self.xmovement
-
-            if actualX < platformX - 2.5 * self.relativeX:
-                xdir = 1
-            elif actualX > platformX - 2.5 * self.relativeX:
-                xdir = -1
-        
-        if xdir > 0:
-            if self.xmovement < self.xmovementmax:
-                self.xmovement += 1
-            elif self.xmovement > self.xmovementmax:
-                self.xmovement -= 1
-            self.direction = 0
-        elif xdir < 0:
-            if self.xmovement > -self.xmovementmax:
-                self.xmovement -= 1
-            elif self.xmovement < -self.xmovementmax:
-                self.xmovement += 1
-            self.direction = 1
-        elif self.xmovement > 0:
-            self.xmovement -= 1
-        elif self.xmovement < 0:
-            self.xmovement += 1
-        
-        self.playerx += self.xmovement
-        actualX += self.xmovement
-        
-        while actualX < 0:
-            self.playerx += self.sx
-            actualX += self.sx
-            self.aiNextPlatformOk = False
-        while actualX >= self.sx:
-            self.playerx -= self.sx
-            actualX -= self.sx
-            self.aiNextPlatformOk = False
-        
-        if self.playery - self.cameray >= self.sy // 3:
-            if self.jump:
-                self.cameray += self.sy // 120
-            else:
-                self.cameray += self.sy // 180
-
-        drawX = self.playerx % self.sx
-        if drawX > self.sx - self.playerWidth:
-            drawX = [drawX, drawX - self.sx]
-        else:
-            drawX = [drawX]
-        drawY = self.playery - self.cameray
-        
-        for x in drawX:
-            if (drawY + self.playerHeight) < 0:
-                if self.showArrow:
-                    self.screen.blit(self.imgMolpArrow, (x, 2))
-            else:
-                if not self.direction:
-                    if self.jump:
-                        if self.playerWearsBeanie:
-                            self.screen.blit(self.imgPlayerRightDownBeanie, (x, drawY))
-                        else:
-                            self.screen.blit(self.imgPlayerRightDown, (x, drawY))
-                        if self.playerCarriesFlag:
-                            self.screen.blit(self.imgFlagLeft, (x + 24, drawY - 10))
-                    else:
-                        if self.playerWearsBeanie:
-                            self.screen.blit(self.imgPlayerRightUpBeanie, (x, drawY))
-                        else:
-                            self.screen.blit(self.imgPlayerRightUp, (x, drawY))
-                        if self.playerCarriesFlag:
-                            self.screen.blit(self.imgFlagLeftDown, (x + 22, drawY - 10))
-                else:
-                    if self.jump:
-                        if self.playerWearsBeanie:
-                            self.screen.blit(self.imgPlayerLeftDownBeanie, (x, drawY))
-                        else:
-                            self.screen.blit(self.imgPlayerLeftDown, (x, drawY))
-                        if self.playerCarriesFlag:
-                            self.screen.blit(self.imgFlagRight, (x + 13, drawY - 10))
-                    else:
-                        if self.playerWearsBeanie:
-                            self.screen.blit(self.imgPlayerLeftUpBeanie, (x, drawY))
-                        else:
-                            self.screen.blit(self.imgPlayerLeftUp, (x, drawY))
-                        if self.playerCarriesFlag:
-                            self.screen.blit(self.imgFlagRightDown, (x + 11, drawY - 10))
-
-    def choosePlatformType(self):
-        platformType = random.randint(0, 999)
-        if self.score > self.scoreWater:
-            if platformType < 900:
-                return self.platformTypeWater
-            else:
-                return self.platformTypeRaftcastle
-        elif platformType < 800:
-            if platformType < 1000 * self.score // self.scoreGrass:
-                if self.score <= self.scoreLucky and not self.hadLucky:
-                    self.hadLucky = True
-                    return self.platformTypeLucky
-                elif self.score <= self.scoreCastle and not self.hadCastle:
-                    self.hadCastle = True
-                    return self.platformTypeCastle
-                elif self.score <= self.scoreAfterLucky and not self.hadAfterLucky:
-                    self.hadAfterLucky = True
-                    return self.platformTypeAfterLucky
-                else:
-                    return self.platformTypeGrass
-            else:
-                return self.platformTypeSand
-        elif platformType < 900:
-            return self.platformTypeGrapevine
-        else:
-            return self.platformTypeBreaking
-
-    def generateNewPlatform(self):
-        platform = False
-        platformType = self.choosePlatformType()
-        w = self.platformWidth[platformType]
-        h = self.platformHeight[platformType]
-        if platformType == self.platformTypeWater or platformType == self.platformTypeRaftcastle:
-            x = random.randint(0, self.sx - w)
-            y = self.platforms[-1][1] + self.sy // 6
-        elif platformType == self.platformTypeLucky:
-            x = 0
-            y = self.platforms[-1][1] + self.sy // 12
-        else:
-            x = random.randint(0, self.sx - self.w)
-            y = self.platforms[-1][1] + self.sy // 9,
-        platform = [x, y, platformType, False, False, -1, 0, w, h]
-        if platformType <= self.platformTypeNormal:
-            if platformType == self.platformTypeSand:
-                platform[4] = random.randint(0, len(self.imgPlatformSand) - 1)
-            elif platformType == self.platformTypeGrass:
-                platform[4] = random.randint(0, len(self.imgPlatformGrass) - 1)
-            else:
-                platform[4] = random.randint(0, len(self.imgPlatformWater) - 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:
-                check = random.randint(0, 999)
-                if check > 800:
-                    xx = x + random.randint(0, w - 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 platform != False:
-            self.platforms.append(platform)
-
-    def updatePlatforms(self):
-        while True:
-            if len(self.platforms) < 1:
-                return
-            if self.platforms[-1][1] - self.cameray < self.sy * 7 // 6:
-                self.generateNewPlatform()
-                if self.score > 1:
-                    self.score -= 1
-                continue
-            if self.platforms[0][1] - self.cameray < - self.platformHeight[self.platformTypeSand] - self.sy // 6:
-                self.platforms.pop(0)
-                continue
-            break
-        colX = self.playerx % self.sx
-        player = pygame.Rect(colX + 15, self.playery, self.playerWidth - 30, self.playerHeight)
-        if colX > self.sx - self.playerWidth:
-            player2 = pygame.Rect(colX - self.sx + 15, self.playery, self.playerWidth - 30, self.playerHeight)
-        else:
-            player2 = False
-        for p in self.platforms:
-            rect = pygame.Rect(p[0], p[1], p[7], p[8])
-            collision = rect.colliderect(player)
-            if player2:          
-                collision = rect.colliderect(player2) or collision
-            if collision and self.gravity:
-                if p[2] == self.platformTypeBreaking:
-                    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[3] <= 0:
-                        self.aiNextPlatformOk = False
-                        self.xmovement = self.sx // 20
-                        self.direction = 0
-                        self.cameray -= self.sy // 12
-                        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[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[4]:
-                    p[0] += self.platformSpeed
-                    if p[0] + p[7] >= self.sx:# + self.extrax:
-                        p[4] = False
-                else:
-                    p[0] -= self.platformSpeed
-                    if p[0] <= 0:
-                        p[4] = True
-
-    def drawPlatforms(self):
-        for p in self.platforms:
-            if p[2] == self.platformTypeSand:
-                self.screen.blit(self.imgPlatformSand[p[4]], (p[0], p[1] - self.cameray))
-            elif p[2] == self.platformTypeGrass:
-                self.screen.blit(self.imgPlatformGrass[p[4]], (p[0], p[1] - self.cameray))
-            elif p[2] == self.platformTypeWater:
-                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[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[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[3]:
-                    self.screen.blit(self.imgPlatformLuckyAttacking, (p[0], p[1] - self.imgPlatformLuckyAttacking.get_height() + self.imgPlatformLuckySleeping.get_height() - self.cameray))
-                    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))
-            elif p[2] == self.platformTypeRaftcastle:
-                if self.raftcastleHasFlag:
-                    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[4]:
-                    self.screen.blit(self.imgPlatformBreaking, (p[0], p[1] - self.cameray))
-                else:
-                    self.screen.blit(self.imgPlatformBroken, (p[0], p[1] - self.cameray))
-            elif p[2] == self.platformTypeTheEnd:
-                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))
-            if self.aiDebag:
-                self.screen.blit(self.font.render(str(p[2])+" "+str(p[5])+" "+str(p[6]), -1, (0, 0x57, 0xaf) if self.ai else (0xbb, 0x66, 0x22)), (p[0], p[1] - self.cameray + 16))
-        if self.aiDebag:
-            self.screen.blit(self.imgMolpArrow, (self.aiNextPlatform[0] + (self.platformWidth[self.platformTypeSand]-self.playerWidth)//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:
-            self.items.pop(0)
-        for item in self.items:
-            if item[2] == self.itemTypeAccelerator:
-                if item[-1]:
-                    imgItem = self.imgAcceleratorUsed
-                else:
-                    imgItem = self.imgAccelerator
-            elif item[2] == self.itemTypeBeanie:
-                if not item[-1]:
-                    imgItem = self.imgBeanie
-                else:
-                    imgItem = None
-            elif item[2] == self.itemTypeSnake:
-                if item[-1] == -1:
-                    imgItem = self.imgSnakeLeft
-                elif item[-1] == 1:
-                    imgItem = self.imgSnakeRight
-                else:
-                    imgItem = self.imgSnake
-            elif item[2] == self.itemTypePrickly:
-                if not item[-1]:
-                    imgItem = self.imgPrickly
-                else:
-                    imgItem = self.imgPricklyCurled
-            elif item[2] == self.itemTypeSandcastle:
-                imgItem = self.imgSandcastle
-                if item[-1]:
-                    self.screen.blit(self.imgFlagRight, (item[0] + 4, item[1] - imgItem.get_height() + 2 - self.imgFlagRight.get_height() - self.cameray))
-            elif item[2] == self.itemTypeFlag:
-                if not item[-1]:
-                    imgItem = self.imgFlagRight
-                else:
-                    imgItem = None
-            elif item[2] == self.itemTypePlantSand:
-                imgItem = self.imgPlantSand[item[-1]]
-            elif item[2] == self.itemTypePlantGrass:
-                imgItem = self.imgPlantGrass[item[-1]]
-            if imgItem:
-                self.screen.blit(imgItem, (item[0], item[1] - imgItem.get_height() - self.cameray))
-            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
-                    elif item[2] == self.itemTypeBeanie and not self.playerWearsBeanie:
-                        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
-                            self.cameray -= self.sy // 12
-                            item[-1] = -1
-                        else:
-                            self.xmovement = self.sx // 30
-                            self.direction = 0
-                            self.cameray -= self.sy // 12
-                            item[-1] = 1
-                    elif item[2] == self.itemTypePrickly:
-                        item[-1] = True
-                    elif item[2] == self.itemTypeSandcastle and self.playerCarriesFlag:
-                        self.playerCarriesFlag = False
-                        item[-1] = True
-                        self.sandcastles += 1
-                    elif item[2] == self.itemTypeFlag and not self.playerCarriesFlag:
-                        self.playerCarriesFlag = True
-                        item[-1] = True
-
-    def generateInitialPlatforms(self):
-        self.platforms = [
-            [
-                self.sx // 2 - self.platformWidth[self.platformTypeWonTheGame] // 2,
-                self.playery - self.sy // 2,
-                self.platformTypeWonTheGame, False, False, -1, 0,
-                self.platformWidth[self.platformTypeWonTheGame],
-                self.platformHeight[self.platformTypeWonTheGame]
-            ], [
-                self.sx // 2 - self.platformWidth[self.platformTypeTheEnd] // 2,
-                self.playery + self.sy // 6,
-                self.platformTypeTheEnd, False, False, -1, 0,
-                self.platformWidth[self.platformTypeTheEnd],
-                self.platformHeight[self.platformTypeTheEnd]
-            ]
-        ]
-        while self.platforms[-1][1] < self.sy * 10 // 6:
-            self.generateNewPlatform()
-
-    def drawGrid(self):
-        for x in range(80):
-            pygame.draw.line(self.screen, (222,222,222), (x * 12, 0), (x * 12, self.sy))
-            pygame.draw.line(self.screen, (222,222,222), (0, x * 12), (self.sx, x * 12))
-
-    def waitForIt(self, its):
-        run = False
-        while not run:
-            self.clock.tick(self.speed)
-            event = pygame.event.poll()
-            if event.type == KEYDOWN:
-                key = pygame.key.get_pressed()
-                if key[K_ESCAPE]:
-                    sys.exit()
-                for it in its:
-                    if key[it]:
-                        return it
-
-    def showScore(self):
-        line1 = self.font.render("Press ENTER to restart,", -1, (0, 0, 0))
-        line2 = self.font.render("ESC to quit.", -1, (0, 0, 0))
-        w = max(line1.get_width(), line2.get_width())
-        h = line1.get_height() + line2.get_height()
-        dx = 10
-        dy = 5
-        pygame.draw.rect(self.screen, (255,255,255), ((self.sx - w) // 2 - dx, (self.sy - h) // 2 - dy, w + 2 * dx, h + 2 * dy))
-        pygame.draw.rect(self.screen, (0,0,0), ((self.sx - w) // 2 - dx, (self.sy - h) // 2 - dy, w + 2 * dx, h + 2 * dy), 3)
-        self.screen.blit(line1, ((self.sx - line1.get_width()) // 2, self.sy // 2 - line1.get_height()))
-        self.screen.blit(line2, ((self.sx - line2.get_width()) // 2, self.sy // 2))
-        pygame.display.flip()
-        self.waitForIt([K_RETURN])
-
-    def run(self):
-        if len(sys.argv) > 1:
-            self.filename = sys.argv[1]
-        else:
-            self.filename = None
-        self.reset()
-        while True:
-            self.screen.fill((255,255,255))
-            self.clock.tick(self.speed)
-            for event in pygame.event.get():
-                if event.type == QUIT:
-                    sys.exit()
-                elif event.type == KEYDOWN:
-                    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
-                            self.modeText = "AI " + ('enabled' if self.ai else 'disabled')
-                    elif key[K_d]:
-                        if pygame.key.get_mods() & KMOD_CTRL:
-                            self.aiDebag = not self.aiDebag
-                            self.modeText = "AI debug " + ('enabled' if self.aiDebag else 'disabled')
-                    elif key[K_e]:
-                        if pygame.key.get_mods() & KMOD_CTRL:
-                            self.eternal = not self.eternal
-                            self.eternalFlag = False
-                            self.modeText = "Eternal mode " + ('enabled' if self.eternal else 'disabled')
-                    elif key[K_g]:
-                        if pygame.key.get_mods() & KMOD_CTRL:
-                            self.eternalFlag = not self.eternalFlag
-                            self.eternal = False
-                            self.modeText = "Eternal (flag) mode " + ('enabled' if self.eternalFlag else 'disabled')
-                    elif key[K_f]:
-                        if pygame.key.get_mods() & KMOD_CTRL:
-                            self.playerCarriesFlag = not self.playerCarriesFlag
-                            self.modeText = "Flag " + ('added' if self.playerCarriesFlag else 'removed')
-                    elif key[K_b]:
-                        if pygame.key.get_mods() & KMOD_CTRL:
-                            self.playerWearsBeanie = not self.playerWearsBeanie
-                            self.modeText = "Beanie " + ('added' if self.playerWearsBeanie else 'removed')
-                    elif key[K_SPACE]:
-                        self.modeText = "Wait for it."
-                        self.pause = True
-                    elif key[K_s]:
-                        self.saveGame()
-                        self.modeText = "Saved"
-                    elif key[K_a]:
-                        self.showArrow = not self.showArrow
-                        self.modeText = "Arrow " + ('enabled' if self.showArrow else 'disabled')
-            self.drawGrid()
-            self.drawPlatforms()
-            self.drawAndUpdateItems()
-            self.updatePlayer()
-            self.updatePlatforms()
-            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.modeText != '':
-                self.screen.blit(self.font.render(self.modeText, -1, (0, 0, 0)), (self.sx // 32, self.sy - self.sy // 12))
-            
-            if self.oops:
-                self.showScore()
-                self.reset()
-            pygame.display.flip()
-            
-            if self.pause:
-                self.modeText = "RUN!"
-                while self.waitForIt([K_SPACE, K_s]) == K_s:
-                    self.saveGame()
-                    self.modeText = "Saved"
-                self.pause = False
-
-MolpyUp().run()
index 9e934baa6d9942329943444c5cc73b01af917374..4f33eaf32fdbf81587fbd136c8abd70d5ee0a407 100644 (file)
@@ -11,8 +11,9 @@
 # Copyright (C) 2018, 2026 by Balthasar SzczepaƄski
 # add arrow, AI, flag save mode,
 # remove off-screen space,
-# gmae mode messages,
+# game mode messages,
 # some optimisation
+# Molpy Down mode!
 #
 # 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,
@@ -62,6 +63,7 @@ class MolpyUp:
     platformTypeBreaking   =  8
     platformTypeTheEnd     =  9
     platformTypeWonTheGame = 10
+    platformTypeFrame1     = 11
 
     itemTypeAccelerator = 0
     itemTypeBeanie      = 1
@@ -83,7 +85,8 @@ class MolpyUp:
     scoreTheEnd     = 3089
     scoreEpilogue   = 3094
 
-    def __init__(self):
+    def __init__(self, molpyDown = False):
+        self.molpyDown = molpyDown
         self.relativeX=0
         self.sx = 553
         self.sy = 395
@@ -121,6 +124,7 @@ class MolpyUp:
         self.imgPlatformBroken         = pygame.image.load("assets/platformBroken.png").convert_alpha()
         self.imgPlatformTheEnd         = pygame.image.load("assets/platformTheEnd.png").convert_alpha()
         self.imgPlatformWonTheGame     = pygame.image.load("assets/platformWonTheGame.png").convert_alpha()
+        self.imgPlatformFrame1         = pygame.image.load("assets/platformFrame1.png").convert_alpha()
         self.imgPlayerRightUp          = pygame.image.load("assets/playerRightUp.png").convert_alpha()
         self.imgPlayerRightDown        = pygame.image.load("assets/playerRightDown.png").convert_alpha()
         self.imgPlayerLeftUp           = pygame.image.load("assets/playerLeftUp.png").convert_alpha()
@@ -160,7 +164,6 @@ class MolpyUp:
                                          pygame.image.load("assets/plantGrass11.png").convert_alpha() ]
         self.imgMolpArrow              = pygame.image.load("assets/molpArrow.png").convert_alpha()
         self.playerHeight = self.imgPlayerRightUp.get_height()
-        # self.playerHalfHeight = self.playerHeight // 2
         self.playerWidth = self.imgPlayerRightUp.get_width()
         self.playerHalfWidth = self.playerWidth // 2
         self.platformSpeed = self.extrax // 10
@@ -175,7 +178,8 @@ class MolpyUp:
             self.imgPlatformLuckySleeping.get_height(),
             self.imgPlatformBreaking.get_height(),
             self.imgPlatformTheEnd.get_height(),
-            self.imgPlatformWonTheGame.get_height()
+            self.imgPlatformWonTheGame.get_height(),
+            self.imgPlatformFrame1.get_height()
         ]
         self.platformWidth = [
             self.imgPlatformSand[0].get_width(),
@@ -188,7 +192,8 @@ class MolpyUp:
             self.imgPlatformLuckySleeping.get_width(),
             self.imgPlatformBreaking.get_width(),
             self.imgPlatformTheEnd.get_width(),
-            self.imgPlatformWonTheGame.get_width()
+            self.imgPlatformWonTheGame.get_width(),
+            self.imgPlatformFrame1.get_width()
         ]
         self.dropLimit = 25
         if self.dropLimit >= self.platformHeight[self.platformTypeSand] + self.playerHeight:
@@ -197,7 +202,7 @@ class MolpyUp:
         
     def reset(self):
         self.cameray = 0
-        self.score = 0
+        self.score = self.scoreEpilogue if self.molpyDown else 0
         self.sandcastles = 0
         self.speed = 30
         self.modeText = ''
@@ -216,7 +221,6 @@ class MolpyUp:
         self.hadLucky = False
         self.hadTheEnd = False
         self.raftcastleHasFlag = False
-        self.platforms = [[self.playerx, self.playery + self.sy // 6, self.platformTypeSand, 0, 0, -1, 0, self.platformWidth[self.platformTypeSand], self.platformHeight[self.platformTypeSand]]]
         self.generateInitialPlatforms()
         self.items = []
         self.aiNextPlatformOk = False
@@ -230,6 +234,7 @@ class MolpyUp:
         self.filename = datetime.datetime.now().strftime("%Y%m%d-%H%M%S.molpyup")
         with open(self.filename, "w") as file:
             file.write("MolpyUp!\n")
+            file.write("molpyDown: " + str(self.molpyDown) + "\n")
             file.write("cameray: " + str(self.cameray) + "\n")
             file.write("score: " + str(self.score) + "\n")
             file.write("sandcastles: " + str(self.sandcastles) + "\n")
@@ -266,6 +271,7 @@ class MolpyUp:
             with open(filename, "r") as file:
                 lines = file.readlines()
             for line in lines:
+                self.molpyDown = self.readVariable(line, "molpyDown", self.molpyDown)
                 self.cameray = self.readVariable(line, "cameray", self.cameray)
                 self.score = self.readVariable(line, "score", self.score)
                 self.sandcastles = self.readVariable(line, "sandcastles", self.sandcastles)
@@ -462,8 +468,15 @@ class MolpyUp:
             actualX -= self.sx
             self.aiNextPlatformOk = False
         
-        if self.playery - self.cameray <= self.sy // 3:
-            self.cameray -= self.sy // 60
+        if self.molpyDown:
+            if self.playery - self.cameray >= self.sy // 3:
+                if self.jump:
+                    self.cameray += self.sy // 120
+                else:
+                    self.cameray += self.sy // 180
+        else:
+            if self.playery - self.cameray <= self.sy // 3:
+                self.cameray -= self.sy // 60
 
         drawX = self.playerx % self.sx
         if drawX > self.sx - self.playerWidth:
@@ -509,60 +522,96 @@ class MolpyUp:
                             self.screen.blit(self.imgFlagRightDown, (x + 11, drawY - 10))
 
     def choosePlatformType(self):
-        if self.score >= self.scoreTheEnd:
-            return self.platformTypeTheEnd
         platformType = random.randint(0, 999)
-        if self.score > self.scoreWater:
-            if platformType < 900:
-                return self.platformTypeWater
-            else:
-                return self.platformTypeRaftcastle
-        elif platformType < 800:
-            if platformType < 1000 * self.score // self.scoreGrass:
-                if self.score > self.scoreAfterLucky and not self.hadAfterLucky:
-                    self.hadAfterLucky = True
-                    return self.platformTypeAfterLucky
-                elif self.score > self.scoreCastle and not self.hadCastle:
-                    self.hadCastle = True
-                    return self.platformTypeCastle
-                elif self.score > self.scoreLucky and not self.hadLucky:
-                    self.hadLucky = True
-                    return self.platformTypeLucky
+        if self.molpyDown:
+            if self.score <= 1:
+                return self.platformTypeFrame1
+            elif self.score > self.scoreWater:
+                if platformType < 900:
+                    return self.platformTypeWater
+                else:
+                    return self.platformTypeRaftcastle
+            elif platformType < 800:
+                if platformType < 1000 * self.score // self.scoreGrass:
+                    if self.score <= self.scoreLucky and not self.hadLucky:
+                        self.hadLucky = True
+                        return self.platformTypeLucky
+                    elif self.score <= self.scoreCastle and not self.hadCastle:
+                        self.hadCastle = True
+                        return self.platformTypeCastle
+                    elif self.score <= self.scoreAfterLucky and not self.hadAfterLucky:
+                        self.hadAfterLucky = True
+                        return self.platformTypeAfterLucky
+                    else:
+                        return self.platformTypeGrass
                 else:
-                    return self.platformTypeGrass
+                    return self.platformTypeSand
+            elif platformType < 900:
+                return self.platformTypeGrapevine
             else:
-                return self.platformTypeSand
-        elif platformType < 900:
-            return self.platformTypeGrapevine
+                return self.platformTypeBreaking
         else:
-            return self.platformTypeBreaking
+            if self.score >= self.scoreTheEnd:
+                return self.platformTypeTheEnd
+            platformType = random.randint(0, 999)
+            if self.score > self.scoreWater:
+                if platformType < 900:
+                    return self.platformTypeWater
+                else:
+                    return self.platformTypeRaftcastle
+            elif platformType < 800:
+                if platformType < 1000 * self.score // self.scoreGrass:
+                    if self.score > self.scoreAfterLucky and not self.hadAfterLucky:
+                        self.hadAfterLucky = True
+                        return self.platformTypeAfterLucky
+                    elif self.score > self.scoreCastle and not self.hadCastle:
+                        self.hadCastle = True
+                        return self.platformTypeCastle
+                    elif self.score > self.scoreLucky and not self.hadLucky:
+                        self.hadLucky = True
+                        return self.platformTypeLucky
+                    else:
+                        return self.platformTypeGrass
+                else:
+                    return self.platformTypeSand
+            elif platformType < 900:
+                return self.platformTypeGrapevine
+            else:
+                return self.platformTypeBreaking
 
     def generateNewPlatform(self):
         platform = False
+        item = False
         platformType = self.choosePlatformType()
         w = self.platformWidth[platformType]
         h = self.platformHeight[platformType]
-        if platformType == self.platformTypeTheEnd:
+        if platformType == self.platformTypeFrame1:
             if self.hadTheEnd:
                 return
-            elif platform[-1][2] == self.platformTypeTheEnd:
+            x = 0
+            y = self.sy * 2 // 3
+        elif platformType == self.platformTypeTheEnd:
+            if self.hadTheEnd:
+                return
+            elif self.platforms[-1][2] == self.platformTypeTheEnd:
                 self.hadTheEnd = True
                 platformType = platformWonTheGame
                 w = self.platformWidth[platformType]
                 h = self.platformHeight[platformType]
-                y = self.platforms[-1][1] - self.sy * 2 // 3
+                y = self.sy * 2 // 3
             else:
-                y = self.platforms[-1][1] - self.sy // 4
+                y = self.sy // 4
             x = self.sx // 2 - w // 2
         elif platformType == self.platformTypeWater or platformType == self.platformTypeRaftcastle:
             x = random.randint(0, self.sx - w)
-            y = self.platforms[-1][1] - self.sy // 8
+            y = self.sy // 6 if self.molpyDown else self.sy // 8
         elif platformType == self.platformTypeLucky:
             x = 0
-            y = self.platforms[-1][1] - self.sy // 12
+            y = self.sy // 9 if self.molpyDown else self.sy // 12
         else:
             x = random.randint(0, self.sx - w)
-            y = self.platforms[-1][1] - self.sy // 9
+            y = self.sy // 9 if self.molpyDown else self.sy // 12
+        y = self.platforms[0][1] + y if self.molpyDown else self.platforms[-1][1] - y
         platform = [x, y, platformType, False, False, -1, 0, w, h]
         if platformType <= self.platformTypeNormal:
             if platformType == self.platformTypeSand:
@@ -572,12 +621,10 @@ class MolpyUp:
             else:
                 platform[4] = random.randint(0, len(self.imgPlatformWater) - 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])
+                item = [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])
+                item = [x + self.imgPlatformSand[0].get_width() // 3, y + 8, self.itemTypePrickly, False]
                 self.hadPrickly = True
             elif self.score > 0:
                 check = random.randint(0, 999)
@@ -585,45 +632,56 @@ class MolpyUp:
                     xx = x + random.randint(0, w - 40)
                     itemType = random.randint(0,999)
                     if itemType < 50:
-                        platform[5]=self.itemTypeBeanie
-                        self.items.append([xx, y + 7, self.itemTypeBeanie, False])
+                        item = [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])
+                        item = [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])
+                        item = [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)])
+                        item = [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])
+                        item = [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)])
+                        item = [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])
+                        item = [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])
+                        item = [x - 10, y + 9, self.itemTypeSnake, False]
                     else:
-                        platform[5]=self.itemTypeAccelerator
-                        self.items.append([xx - 5, y + 10, self.itemTypeAccelerator, False])
+                        item = [xx - 5, y + 10, self.itemTypeAccelerator, False]
+        if item != False:
+            platform[5] = item[2]
+            if self.molpyDown:
+                self.items.insert(0, item)
+            else:
+                self.items.append(item)
         if platform != False:
-            self.platforms.append(platform)
+            if self.molpyDown:
+                self.platforms.insert(0, platform)
+            else:
+                self.platforms.append(platform)
 
     def updatePlatforms(self):
         while True:
             if len(self.platforms) < 1:
                 return
-            if self.platforms[0][1] - self.cameray <= self.sy + self.sy // 12:
+            if self.molpyDown:
+                if self.platforms[0][1] - self.cameray < self.sy * 7 // 6:
+                    self.generateNewPlatform()
+                    if self.score > 1:
+                        self.score -= 1
+                    continue
+                if self.platforms[-1][1] - self.cameray < - self.platformHeight[self.platformTypeSand] - self.sy // 6:
+                    self.platforms.pop()
+                    continue
                 break
-            self.generateNewPlatform()
-            self.platforms.pop(0)
-            if self.score < self.scoreEpilogue:
-                self.score += 1
+            else:
+                if self.platforms[0][1] - self.cameray <= self.sy + self.sy // 12:
+                    break
+                self.generateNewPlatform()
+                self.platforms.pop(0)
+                if self.score < self.scoreEpilogue:
+                    self.score += 1
         colX = self.playerx % self.sx
         player = pygame.Rect(colX + 15, self.playery, self.playerWidth - 30, self.playerHeight)
         if colX > self.sx - self.playerWidth:
@@ -633,9 +691,9 @@ class MolpyUp:
         for p in self.platforms:
             rect = pygame.Rect(p[0], p[1], p[7], p[8])
             collision = rect.colliderect(player)
-            if player2:          
+            if player2 != False:
                 collision = rect.colliderect(player2) or collision
-            if collision and self.gravity and self.playery < (p[1] - self.cameray):
+            if collision and self.gravity:
                 if p[2] == self.platformTypeBreaking:
                     p[4] = True
                 else:
@@ -707,11 +765,15 @@ class MolpyUp:
             if self.aiDebag:
                 self.screen.blit(self.font.render(str(p[2])+" "+str(p[5])+" "+str(p[6]), -1, (0, 0x57, 0xaf) if self.ai else (0xbb, 0x66, 0x22)), (p[0], p[1] - self.cameray + 16))
         if self.aiDebag:
-            self.screen.blit(self.imgMolpArrow, (self.aiNextPlatform[0] + (self.platformWidth[self.platformTypeSand]-self.playerWidth)//2, self.aiNextPlatform[1] - self.cameray + 16))
+            self.screen.blit(self.imgMolpArrow, (self.aiNextPlatform[0] + (p[7]-self.playerWidth)//2, self.aiNextPlatform[1] - self.cameray + self.aiNextPlatform[8]))
 
     def drawAndUpdateItems(self):
-        while self.items and self.items[0][1] - self.cameray > self.sy + self.sy // 12:
-            self.items.pop(0)
+        if self.molpyDown:
+            while self.items and self.items[-1][1] - self.cameray < - self.sy // 6:
+                self.items.pop()
+        else:
+            while self.items and self.items[0][1] - self.cameray > self.sy + self.sy // 12:
+                self.items.pop(0)
         for item in self.items:
             if item[2] == self.itemTypeAccelerator:
                 if item[-1]:
@@ -783,8 +845,34 @@ class MolpyUp:
                         item[-1] = True
 
     def generateInitialPlatforms(self):
-        while self.platforms[-1][1] > - self.sy // 6:
-            self.generateNewPlatform()
+        if self.molpyDown:
+            self.platforms = [
+                [
+                    self.sx // 2 - self.platformWidth[self.platformTypeTheEnd] // 2,
+                    self.playery + self.sy // 6,
+                    self.platformTypeTheEnd, False, False, -1, 0,
+                    self.platformWidth[self.platformTypeTheEnd],
+                    self.platformHeight[self.platformTypeTheEnd]
+                ], [
+                    self.sx // 2 - self.platformWidth[self.platformTypeWonTheGame] // 2,
+                    self.playery - self.sy // 2,
+                    self.platformTypeWonTheGame, False, False, -1, 0,
+                    self.platformWidth[self.platformTypeWonTheGame],
+                    self.platformHeight[self.platformTypeWonTheGame]
+                ]
+            ]
+            while self.platforms[0][1] < self.sy * 10 // 6:
+                self.generateNewPlatform()
+        else:
+            self.platforms = [[
+                self.playerx,
+                self.playery + self.sy // 6,
+                self.platformTypeSand, False, False, -1, 0,
+                self.platformWidth[self.platformTypeSand],
+                self.platformHeight[self.platformTypeSand]
+            ]]
+            while self.platforms[-1][1] > - self.sy // 6:
+                self.generateNewPlatform()
 
     def drawGrid(self):
         for x in range(80):
@@ -861,6 +949,15 @@ class MolpyUp:
                         if pygame.key.get_mods() & KMOD_CTRL:
                             self.playerWearsBeanie = not self.playerWearsBeanie
                             self.modeText = "Beanie " + ('added' if self.playerWearsBeanie else 'removed')
+                    elif key[K_m]:
+                        if pygame.key.get_mods() & KMOD_CTRL:
+                            self.molpyDown = not self.molpyDown
+                            self.modeText = "Molpy " + ('Down!' if self.molpyDown else 'Up!')
+                            self.hadTheEnd = False
+                            for p in self.platforms:
+                                if p[2] == (self.platformTypeFrame1 if self.molpyDown else self.platformTypeWonTheGame):
+                                    self.hadTheEnd = True
+                                    break
                     elif key[K_SPACE]:
                         self.modeText = "Wait for it."
                         self.pause = True