Keep running the sand falling simulation until the sand stops moving.
(allSand)
| 74 | |
| 75 | |
| 76 | def runHourglassSimulation(allSand): |
| 77 | """Keep running the sand falling simulation until the sand stops |
| 78 | moving.""" |
| 79 | while True: # Keep looping until sand has run out. |
| 80 | random.shuffle(allSand) # Random order of grain simulation. |
| 81 | |
| 82 | sandMovedOnThisStep = False |
| 83 | for i, sand in enumerate(allSand): |
| 84 | if sand[Y] == SCREEN_HEIGHT - 1: |
| 85 | # Sand is on the very bottom, so it won't move: |
| 86 | continue |
| 87 | |
| 88 | # If nothing is under this sand, move it down: |
| 89 | noSandBelow = (sand[X], sand[Y] + 1) not in allSand |
| 90 | noWallBelow = (sand[X], sand[Y] + 1) not in HOURGLASS |
| 91 | canFallDown = noSandBelow and noWallBelow |
| 92 | |
| 93 | if canFallDown: |
| 94 | # Draw the sand in its new position down one space: |
| 95 | bext.goto(sand[X], sand[Y]) |
| 96 | print(' ', end='') # Clear the old position. |
| 97 | bext.goto(sand[X], sand[Y] + 1) |
| 98 | print(SAND, end='') |
| 99 | |
| 100 | # Set the sand in its new position down one space: |
| 101 | allSand[i] = (sand[X], sand[Y] + 1) |
| 102 | sandMovedOnThisStep = True |
| 103 | else: |
| 104 | # Check if the sand can fall to the left: |
| 105 | belowLeft = (sand[X] - 1, sand[Y] + 1) |
| 106 | noSandBelowLeft = belowLeft not in allSand |
| 107 | noWallBelowLeft = belowLeft not in HOURGLASS |
| 108 | left = (sand[X] - 1, sand[Y]) |
| 109 | noWallLeft = left not in HOURGLASS |
| 110 | notOnLeftEdge = sand[X] > 0 |
| 111 | canFallLeft = (noSandBelowLeft and noWallBelowLeft |
| 112 | and noWallLeft and notOnLeftEdge) |
| 113 | |
| 114 | # Check if the sand can fall to the right: |
| 115 | belowRight = (sand[X] + 1, sand[Y] + 1) |
| 116 | noSandBelowRight = belowRight not in allSand |
| 117 | noWallBelowRight = belowRight not in HOURGLASS |
| 118 | right = (sand[X] + 1, sand[Y]) |
| 119 | noWallRight = right not in HOURGLASS |
| 120 | notOnRightEdge = sand[X] < SCREEN_WIDTH - 1 |
| 121 | canFallRight = (noSandBelowRight and noWallBelowRight |
| 122 | and noWallRight and notOnRightEdge) |
| 123 | |
| 124 | # Set the falling direction: |
| 125 | fallingDirection = None |
| 126 | if canFallLeft and not canFallRight: |
| 127 | fallingDirection = -1 # Set the sand to fall left. |
| 128 | elif not canFallLeft and canFallRight: |
| 129 | fallingDirection = 1 # Set the sand to fall right. |
| 130 | elif canFallLeft and canFallRight: |
| 131 | # Both are possible, so randomly set it: |
| 132 | fallingDirection = random.choice((-1, 1)) |
| 133 |