Followers 0

# Which approach would be best for checking if an inventory is full in Python?

## 9 posts in this topic

Posted (edited)

Here are 3 versions of a method from my inventory class that adds an item to the given inventory (or increases the items quantity). From a Python perspective, which approach would be best? Each method is followed by a sample of how I would use it in practice. I've been pretty interested in code design/architecture lately and I've been trying to get better at Python, so it may seem like a silly question but I'm just curious what you people think. Currently, I'm using approach #1, but I find it misleading that you could add an item and not actually have an item added. And if there's another approach not listed here that would be good please let me know.

#1 prevent adding item if is_full():
i = next((i for i in self.items if i.tag == item.tag), None) #Duplicate item...
if i is not None:
i.quantity += item.quantity
elif not self.is_full():
self.items.append(item)

#2 throw exception if is_full() and handle outside method:
i = next((i for i in self.items if i.tag == item.tag), None)
if i is not None:
i.quantity += item.quantity
elif not self.is_full():
self.items.append(item)
else:
raise InvetoryFullException("Inventory can only hold 8 items.")

try:
except InvetoryFullException:
pass

#3 check if inventory is_full() outside of method:
i = next((i for i in self.items if i.tag == item.tag), None)
if i is not None:
i.quantity += item.quantity
else:
self.items.append(item)

if not player_inventory.is_full():
player_inventory.items.append(item)

Edited by mrpeed
0

##### Share on other sites
9 hours ago, fastcall22 said:

items = dict()

Makes sense to use a dict actually, not sure why I went with a list.

9 hours ago, fastcall22 said:

@property def full(self): return len(self.items) >= self.max_inventory_size

Curious to why you decided to make this a property?

Also, what's your take on using an exception? As in my second example.

0

##### Share on other sites

Silently ignoring a request is a recipe for making buggy code, so I would strongly suggest you don't do that. Python also recommends that in the "Zen of Python" (type "import this" after the ">>>" prompt). "Explicit is better than implicit."

Making it testable before-hand, or returning "False" if it fails is a simple solution here. For something as simple as a full inventory, it's likely also enough. If you cannot store the item, something else must be done with it, and likely the best place to handle that problem is at the same spot in the code as where you tried (and failed) to insert the item into the inventory. An obvious thing to do is to put the item back where the player found it, for example.

An exception is a stronger failure, it is typically used when you're in real trouble. A file you loaded last time suddenly disappeared for example. The "return False" trick is a valid solution here too, but one level higher, there isn't much you can do about a missing file, so the only thing you can do is again "return False" to the next higher level, and so on, until you are somewhere near the top-level, where you know what files exist, you scratch the missing file, and you pick a new file to load.

When you raise an exception when you find the file missing instead, it does the above in one big step, it repeatedly exits the function, checks for a "catch", and if it doesn't exist, immediately exits that function too, etc, until it finds a "catch" statement that matches, or it reaches the main program (at which point the entire program ends). As such the raise is a substitute for the whole chain of

result = subfunction()
if not result: return False

that you'd have to write otherwise. It's a sort-of super-return.

Exceptions are quite controversial, there are disadvantages to them as well. Since you make big jumps from some innner-inner function back to some much higher function, all the variables that you have created and computations you have done in the functions between "raise" and "catch" are lost. You may not want that.

1

##### Share on other sites
On 14/07/2017 at 5:38 AM, fastcall22 said:

Since the items are referred to by their tag, then it would be easier to use an associative array, such as dict or collections.OrderedDict.  Then, checking if the inventory is full is only a matter of checking the number of tags it has:


items = dict()

def is_full(self):
return len(self.items) >= 8

...etc...

Slight amendment here; I would expect that to be more like:

def __init__():
self.items = dict()

... other methods here, etc ...

Apart from that, I completely agree with this approach, and that the ability to add to the inventory should be checked explicitly with a function rather than handled with an exception. Exceptions are best saved for situations where it's not practical to easily check for the problem or to easily handle the problem where it's discovered.

2

##### Share on other sites
On 7/15/2017 at 6:26 AM, Kylotan said:

Slight amendment here; I would expect that to be more like:


def __init__():
self.items = dict()

... other methods here, etc ...

Apart from that, I completely agree with this approach, and that the ability to add to the inventory should be checked explicitly with a function rather than handled with an exception. Exceptions are best saved for situations where it's not practical to easily check for the problem or to easily handle the problem where it's discovered.

Yes, I am initializing that in the __init__ method. And makes sense, I decided to remove the is_full() check from each method and have the inventory size enforced outside of the inventory class. This also removed a lot of clutter from my methods which is good.

I was wondering if you can clarify when to use properties? I tend to avoid them because I feel like they are misleading.

For example,

@property
def full(self):
return len(self.items) >= self.max_inventory_size

Doesn't this hide the fact that this is a method? Would a user not think this a regular variable and possibly try to assign to it? I have other methods labeled get and set throughout my code base that changes behavior within different classes. Would it be misleading to convert those to properties?

Another example, would it be to misleading to make this a next_sprite property?

def get_next_sprite(self):
if self.current_count == self.max_count: #Time to switch sprites...
self.current_count = 0
self.current_sprite = next(self.sprite_reel)
else: #Increment and return the same sprite from last frame...
self.current_count += 1
return self.current_sprite

Edited by mrpeed
0

##### Share on other sites

Properties are intended to hide the fact that they are a method; whether you think that is a good idea or not is up to you. A reasonable middle-ground would be to use a property only where the hidden side-effects make sense in some way. I write entire Python programs without ever defining properties and I'm happy with that. And I see some popular Python packages that use properties in a way I don't agree with, but the world doesn't end. It's up to you.

Examples of 'good' candidates for properties, in my opinion, might be methods that fix up the incoming value on a set-property (e.g. changing a string to a unicode, or an integer to a float), or methods which wrap a more complex comparison (e.g. the 'is_full' concept)

And an example of a 'bad' candidate for properties might be methods that look like getters but which change the object state, e.g. by iterating over some internal collection. (So personally, I wouldn't like a 'next_sprite' property.)

I wouldn't worry about users wrongly thinking they can assign to a property that is read-only; Python code needs to be well-documented to be usable anyway due to the lack of type-checking, so you just need to note such properties accordingly.

1

##### Share on other sites
On 7/17/2017 at 5:13 AM, Kylotan said:

Examples of 'good' candidates for properties, in my opinion, might be methods that fix up the incoming value on a set-property (e.g. changing a string to a unicode, or an integer to a float), or methods which wrap a more complex comparison (e.g. the 'is_full' concept)

If I see no reason for something to be a property over a method should I favor making it a property or a method? For example, I can see no benefit in doing a "full" property over a "is_full() method", other than not having to write (). I can understand if full started as a regular variable and was expanded to a property later, but it wasn't. So in that case what would you say?

0

##### Share on other sites

If you don't want to use properties, then don't. They just exist for convenience, to allow you to create things that act much like regular variables but which require a little extra logic.

0

## Create an account

Register a new account

Followers 0

• ### Similar Content

• By ghonchi
I want to learn game development/modding/make games . But my pc is very old. I don't to where to start & software that will work on this pc.  I don't have money to buy a new pc so this is what I am stuck with. I don't want latest hd graphics type games. I am more than ok with Quake, Half-life, Counter Strike, NOLF, type games or 2d games. Most of the software I see have high system requirements like Unity or Unreal. Please guide me & don't tell me to buy a new pc I cant afford. Also don't tell me that its not possible to develop on these specs. Because these games run smoothly.  Sorry for my English. Thanks

old Pentium 4 1.70 Ghz, 1gb + 512 MB RAM, Windows XP.

Please don't ignore its a matter of life & death for me

• I'm trying to make a game where the characters are randomly generated and retain individual attributes over time. Right now, I'm working on the combat system. I've made it so the roles of "Attacker" and "Defender" will switch between the player character and the NPC they are fighting. Problem is, I'm unsure of how to organize it in an elegant way. All I can think of is doing a bunch of if & else statements every time I need to check. Could you suggest ways of doing this in an elegant way? If there is anything in my code that could be significantly simplified don't be afraid to point that out either.

Here is an example of one of the methods I could use help with. In it, I am taking the int type variable, "overall action score", or OAS, from a tuple, which then helps to determine the force of any attacks that land. On if and else statements, I am checking who is attacking, and calling one of their respective physical attributes.
def forceFinder(self): """ Determines force of strike from OAS and alacrity. """ #subtract attacker OAS from defender OAS force = self._oasTuple[0] - self._oasTuple[1] #exponentially adds to force according to alacrity and #margin between attacker, and defender OAS. for i in range(0, force, 10): force *= 1.10 if Combat._attacker == "pc": force += Combat._pcAttr["alacrity"] * 3 else: force += Combat._npcAttr["alacrity"] * 3 return int(force)

• By Tonya
On Tuesday 25th July from 5:45pm, the Sydney Game Engine Developers will be holding their next Meetup in Ultimo. This month guest speakers Aidan Millott and Paulina Morrison Fell are joining forces to give a talk on Producing an Internal Engine.
Producing engine technology that's shared across 10+ productions is no easy feat. Managing conflicting priorities from multiple games and coordinating shared development of features is only just a flavour of how challenging it can be. In this presentation, Aidan and Paulina share their experiences and techniques used to manage the distributed development of internal projects.
Aidan Millott is an Area Product Owner at Wargaming.net, where he works with internal stakeholders to improve BigWorld, focusing on development of games by small teams. Prior to this, he was an Executive Producer and Studio Manager at Halfbrick studios, where he released 11 games on several platforms.
Paulina Morrison Fell works at Wargaming.net as a Senior Project Manager. She works with the Client Engine team to manage the development of features for game productions, liaising with stakeholders from multiple studios. She has worked in a number of successful startups and bigger companies like Disney, where she has helped launch over 10 games for small platforms.
Agenda for the night is:
5:45pm - Arrive and network (pizza and drinks provided) 6:15pm - Presentation by Aidan and Paulina 7:15pm - Network/Closing There are still spots available and we would love for you to join us for this interesting talk.
RSVP and come along!
In my previous post, I took a look at the various level designs lessons gleaned from Super Mario Bros. 3’s first world. A lot of them naturally dealt with introductory tutorials, but I wanted to take a slightly different approach with this article.

The elegant introduction of new mechanics is still present throughout SMB 3. In this example, the first appearance of a Chain Chomp is marked by two columns that indicate its range and allow the player to safely observe its behaviour.

SMB 3 is filled with great levels, so I decided to pick out a bunch of clever, fun or simply unique moments from the game that originated with its architecture. I skipped over a lot of possible examples trying to keep the list down to 30, but I think I came up with a good collection that complements the original post.

1) World 2 Fortress

It’s a common technique to place falling obstacles side by side on the ceiling so that the player can “narrowly” dodge them while running underneath. Of course once the first hazard is avoided, it’s easy to figure out that the others won’t pose any threat.
In order to sustain tension, the above Thwomps are positioned at different heights, each one closer to the ground than the last. Although it’s still possible run underneath them, the player can’t be sure he’ll make it until he’s all the way through.
It’s also worth noting that the other fortress levels often work to build a similar feeling of suspense (even when they’re actually not any more difficult than the regular stages).

2) World 2-3

The end-level pipe is covered with a mound of Brick Blocks patrolled by a couple of Koopa Troopas. It’s unlikely that the player will choose — or be able — to dispatch the enemies without stomping on them and sending a stray shell rocketing into the bricks. This causes a chain reaction where the shell destroys many of the blocks, but this is far from a randomized event.
Some of the bricks are deliberately turned into Used Blocks when hit, penning the shell inside and ensuring that it clears a path to the exit pipe. The lone brick that survives the destruction also proves to be a Coin Block, rewarding the players that risk activating it.

3) World 2 Quicksand

The Angry Sun doesn’t scroll with the rest of the background, immediately making this level feel unique.
When the player gets past the Tweester, the sun detaches from its static position and begins swooping down on Mario. The entire level is designed with this dodging gameplay in mind as its layout is fairly flat and it doesn’t contain many enemies.

4) World 2-4

The top-left corner of the level’s starting position shows a narrow gap plugged up with a bunch of Brick Blocks. This draw the players attention and guides him to discover that he can fly and smash through the entire column without losing any elevation.
Once at the top of the platform — which contains a neat-looking enclosed pool — the player is given a chance to discover another fun continuous-flight mechanic: bumping a horizontal line of Brick Blocks that all dispense coins.

5) World 2 Pyramid

These tight tunnels are filled with one-off brick walls. Although it’s possible to destroy them with Raccoon Mario’s spin-attack, the plethora of Buzzy Beetles ensures that the player has many chances to use the enemies in order to carve a path through the level.

6) World 3-2

This is an example of an interesting Starman mechanic: the Wooden Block dispenses the invincibility powerup, and if Mario is invincible while bumping certain other “?” Blocks, they will also release Starmen instead of coins.
Although quite challenging to time, this allows the player to blaze through the level instead of following the more exploratory route.

7) World 3-3

In addition to changing Brick Blocks into collectible coins, the P-Switch can also be used to make level traversal much easier. In this case, rows of coins are turned into platforms that allow Mario to avoid various hazards lurking below. These makeshift bridges carry on to the end-level pipe and provide a much safer route if the player is quick enough to take advantage of them.
The end-level pipe is also interesting as it’s not located on the very right edge of the map, but instead roughly 2 screens to its left. If the player travels past the pipe, he’ll discover a secret 1-Up Mushroom.
This is a great example of making something feel novel by enforcing a certain pattern (end-level pipes are always on the right side of the map) and then simply breaking it (the end-level pipe is now closer to the middle).

8) World 3 Fortress 1

This hallway with numerous doorways introduces large-scale branching and looping design. Most doors drop Mario into a pool of water, but two have unique destinations: a bonus coin room, and the actual path to the level’s end.
Since working out which doors lead to where is a matter of trial and error, it’s easy for the player to start feeling a little tense as the timer continues to tick down.

9) World 3-4

Perhaps the greatest slide in all of SMB 3; not only does it let Mario barrel through a bunch of Goombas, but it can also launch him over a lake and onto higher ground. It’s almost like a Sonic the Hedgehog segment, albeit not quite as thrilling.
If the player misses the jump, there are also a couple of invisible “?” Blocks over the lake that create an alternative path to the top.

10) World 3-8

In this level Mario is constantly harassed by Boss Basses while the whole map dips in and out of water. Thankfully the stage also contains a few Beanstalks that allow the player to climb up and “ride out the storm.”
This is notable as these elements were all encountered in previous levels, but an entirely new dynamic was introduced by putting them together.

11) World 4-1

Probably the most beloved of SMB 3’s worlds, Giant Land features unusually large enemies and objects. Despite their size, most of them behave the same way as their smaller counterparts (although there are a few differences such as not being able to destroy giant Brick Blocks with a spin-attack).
Giant Land levels actually mix large objects and enemies with the regular-sized versions, but it’s the behemoths that are the ones remembered. The sense of wonder they evoke is similar to the “Honey, I Shrunk the Kids” effect, and it works so well because the player had 3 previous worlds (and perhaps other Mario games as well) to get used to the standardized dimensions. When most everything is suddenly blown up — regardless of actual impact on gameplay — it leaves quite an impression.

12) World 4-3

This is a small but notable example of difficulty ramping and an alternative use of objects.
Wooden Blocks are usually a boon to Mario as they stop enemies and occasionally dispense powerups. However, in this case they make navigating the triangular platforms much more difficult. Instead of providing a reward, the blocks stop Mario’s jump and actually push him back, sending him skidding towards a bottomless pit.

13) World 4-4

Air bubbles emanating from the pipe indicate a water current that’s impossible to pass without the somewhat rare Frog Suit. This is actually one of the few areas a Raccoon Mario can’t reach, and its end-point is a neat bonus room with two P-Switches.
This is unusual as P-Switches are typically limited to 1 per level, but there there are 2 of them here (side by side, no less). This is possible as the 2 P-Switches actually serve 2 different functions: one changes a wall of bricks into coins, while the other summons a wall of previously invisible/non-collidable Silver Coins.

14) World 4-6

This level is actually split into 2 nearly identical maps, with a single door joining them together. The main difference between the 2 areas is that the first contains large enemies, while the second contains regular enemies.
The effect makes the door feel like a gateway to the “normal” part of the game, in turn accentuating the surreal, alternate-universe nature of Giant Land. All this is also achieved with no extra art resources, and it comes across as quite unique since it’s never repeated in any other levels.

15) World 5-2

Mario enters this level by falling down a narrow, walled-off tunnel. While descending, the player is shown a pipe and some blocks that inform him of an area he can’t yet reach.
As the tunnel ends, a couple of platforms pop into view that — if the player is fast enough — can be used to break Mario’s fall. The platforms are Jump Blocks and their bounciness makes this a somewhat tense exercise, but successfully landing on them allows the player to get up to the pipe Mario just passed.
If the player misses the platforms, though, he won’t lose a life. Instead, he’ll continue falling while collecting a few extra coins, and eventually take a slightly harder, alternative route to the level’s end.

16) World 5-3

The only level in the game where Mario can get a hold of the famous Kuribo’s Shoe. Although the powerup is fairly easy to miss — it disappears if the Goomba riding it is stomped or shot with a fireball — a helpful row of blocks allows Mario to bump it from below. This catapults the Goomba out of the shoe and lets the player take it for himself.
Further on in the level Mario encounters a variety of enemies and obstacles that are usually harmful to touch. However, if he’s riding the shoe, Mario will be able to perform various hazardous tasks such as walking across Munchers and stomping Piranha Plants! This extremely satisfying twist stems from flipping a bunch of rules on their heads, and in the process it greatly empowers the player.
It also feels all the more special as the shoe is only encountered in this one stage.

17) World 6-1

The first ice level contains a secret door in the sky that can only be reached by a flying Mario. The door leads to an icy room filled with Brick Blocks clogging a corridor, and a small passage just above them.
Although Mario can use the spin-attack to get past the bricks, the upper path contains a P-Switch that can turn all the blocks into coins. Since only a super version of Mario can fly up to this room, the player must use a running slide to get through the narrow passage and reach the P-Switch.
Once the P-Switch is hit, the cramped quarters make backtracking to the coins somewhat difficult (especially since the game always slides Mario to the right if he gets stuck under a block). However, the newly encountered ice provides less friction, which in turn makes sliding much easier. This relatively small difference is elegantly used to create a layout that would be frustrating (if not impossible) in other worlds.

18) World 6-5

This is perhaps the most puzzle-ish level in the entire game, and it requires very specific knowledge to properly traverse.
Here’s how the level is completed:
Mario must first turn into Raccoon Mario if he’s not already capable of flight. This is made fairly easy by a small room that can be entered from a pipe at the beginning or end of the map. This room contains a powerup-dispensing “?” Block that respawns every time it’s visited. Once Mario has the ability to fly, he must clear the ground of Buster Beetles and Ice Blocks to create a runway. However, he must not kill the Koopa Troopa while doing this. Next, Mario must stomp the Koopa Troopa, pick up its shell, and quickly fly to the upper-right corner of the map before the turtle wakes up. Finally, the player must toss the shell into some blocks and Nipper Plants. This is the only way to take out the Nipper Plants and open up a path to the end-level pipe. The reason for all these steps is that the Nipper Plants cannot be stomped, and their surroundings prevent Mario from spin-attacking them. It’s also impossible to get up to this part of the map with a Fire Mario, or to bring along an Ice Block as Raccoon Mario cannot carry them while flying. Finally, even if the player decides to “sacrifice” a hit to the Nipper Plants, he’ll instantly shrink and be unable to break the Brick Blocks that wall off the end-level pipe.
The only way to reach the exit is to use a turtle shell, and this whole chain of events shows how a group of relatively simple objects and enemies can be combined to create a very complex obstacle.

19) World 6-6

Cheep-Cheeps are usually encountered in large bodies of water, but in this level they can also be found in small, one-tile-wide cavities. It’s a unique occurrence, but executed very well.
The Cheep-Cheeps never miss their jumps — even when their starting and ending points are placed at different elevations — and their aerial acrobatics are fun to interact with and observe.

20) World 6-7

This autoscrolling level is filled with Donut Lifts that crumble and fall under Mario’s weight. The player can actually risk riding them as they fall to collect columns of coins and still jump off before it’s too late. In fact, this very technique is required to exit the level.
Midway through the stage, the player can also obtain a Fire Flower. The level is easier to traverse with Raccoon Mario’s glide ability, but the Fire Flower allows Mario to melt a bunch of frozen coins at the end of the stage (a similar mechanic is later used with frozen Munchers).

21) World 6-8

The plethora of Ice Blocks and rows of enemies found in this level allow the player to set off numerous chain reactions that take out his foes in a single move.
The cascading effect of tossing shells/blocks is always fun, and it provides extra points/1-Ups while clearing the path ahead.

22) World 6 Fortress 3

When Mario enters the penultimate room in this fortress, he finds himself dropping past a door near the ceiling. As Mario falls, multiple Boos surround him and the background begins to scroll down.
This creates a unique and pretty tense situation as the player is forced to dodge the incoming Boos while waiting for the exit to descend.

23) World 7-1

The ability to loop around the edges of the screen was a staple of the original Mario Bros., and it’s also used at various points in SMB 3. In this case, it teases the player with a coin-filled room.
Although it’s possible to get close to the room’s entry-pipe by looping around the screen, Mario cannot jump into it. Instead, he must drop to the thin horizontal pipe below, build up his P meter, and finally soar up and fly into the entry-pipe from below.

24) World 7-2

If the player falls into the above ditch, he’ll quickly discover that it’s impossible to jump back out. Consequently, this will lead him to enter the pipe at its bottom. It’s a preferable choice to simply falling into a bottomless pit, but there’s a catch: like with so many later levels, this seemingly innocuous mechanic (entering a pipe) results in a hazardous situation.
When Mario emerges on the other side, he’ll find himself floating underwater above a bottomless pit. To make matters worse, the pipe itself will spew out air bubbles that will push him ever closer to his death. It’s not too difficult to escape the current, but it’s a somewhat unexpected challenge that requires quick reflexes.

25) World 7-5

Although the above jump is possible, it’s quite tricky. Most players will not reach the ledge, and when they try to jump back up, they’ll bump into a bunch of invisible “?” Blocks (the blocks are only collidable when hit from the bottom).
This technique is used in numerous levels, and although it slows down the player and forces him to backtrack, the unveiled “?” Blocks serve as helpful bridges the second time around.

26) World 7 Fortress 1

This unique fortress lacks any enemies and is another great example of a puzzle-oriented level.
Its first room is constructed almost entirely out of Brick Blocks, with a single door on the far right. The door leads to an empty hallway (which is a little creepy due to the absence of Hot Foot, Stretch and Roto-Disc enemies despite the presence of objects they’re usually attached to), and another door that deposits the player in a lava room.
The lava room contains a “?” Block that spawns a powerup and is bordered by a wall. The wall is mostly there to prevent a Mushroom (if that’s what the “?” releases) from escaping Mario’s reach. This is vital as the room is a dead-end and the player needs a super version of Mario to complete the level.
Once the powerup is collected, the player has to backtrack to the beginning of the stage and smash some of the Brick Blocks positioned above his head. One of these Brick Blocks will turn out to contain a P-Switch, and when the switch is pressed, all of the bricks in the room will turn into coins.
It’s easy to let Mario’s momentum slide him off of the P-Switch, or simply to jump and grab at the plethora of coins, but restraint is required to make progress; if the player falls through the newly materialized coins, he’ll simply find another door that leads back to the empty hallway.
Instead, when the P-Switch is hit, an invisible door will appear close to it (so even if the player misses it, he’ll know about it’s presence). The hidden door leads to a secret room and a Tanooki Suit, and eventually back to the empty hallway. The lack of enemies in the level makes it easy to do all this backtracking without losing the suit, and its flight ability needs to be used in this section in order to reach the hidden exit pipe on the ceiling.

27) World 7-7

This is a unique implementation of the Starman powerup as the player is actually forced to use it in order to complete the level.
The invincibility afforded by the Starman allows Mario to run across the flat row of Munchers, periodically hitting “?” Blocks in order to snag another Starman. Of course the distance between the “?” Blocks keeps increasing as the level goes on, and this creates a sense of tension as Mario is forced to continuously rush forward while recharging the temporary powerup.

28) World 8 Tank Brigade, World 8 Navy, and World 8 Airforce

The auto-scrolling “military” levels are one of the defining features of SMB 3, and they do a good job of making the player feel like he’s plowing through an entire army.
They also play off of each other quite well:
The tanks in the first wave have animating treads that — when combined with the auto-scrolling nature of the level — make it seem like they’re slowly approaching Mario. The tanks are completely stationary, but the constant forward-push of the scrolling is a neat trick that makes ’em appear mobile. The second wave consists of battleships and a “rising tide” mechanic that has the whole map continuously dipping up and down. It’s another simple trick, but it does a great job of making the level feel as if it were a battle taking place on the open seas. Finally, the airship wave drastically increases the auto-scrolling speed, jarring the player from the ponderous pace of the previous waves and throwing him into a hectic chase atop floating platforms.
29) World 8 Hand Trap 1

Although the Hand Trap levels are somewhat random and optional, the first one is notable for its gauntlet of mini-bosses. It contains no regular enemies, just the numerous variants of the Hammer Bros., and ends with a single chest instead of a Goal Panel/boss fight.

30) World 8 Bowser's Castle

The treacherous last level contains various hazards, but it’s main notable point is the final confrontation with Bowser.
Although it’s possible to dispatch him with the Hammer Suit, the traditional approach is to let Bowser stomp through the the bricked floor. It’s a very intuitive mechanic as it’s demonstrated for the player throughout the fight, but what really makes it interesting is how it contrasts Mario’s own abilities.
Throughout the entire game, Mario destroys bricks by hitting them from below. Bowser, on the other hand, is capable of exactly the opposite maneuver: smashing blocks by stomping down on them.

Despite this list being a top 30, it is not thorough (for example, a cool concept never mentioned is the P-Switch in World 4 Fortress 2 that outlines an invisible door with a bunch of silver coin). Taking what’s here, though, it becomes quite evident that much of SMB 3’s uniqueness comes from conditioning the player, and then pulling the rug out from underneath him. This isn’t as bad as it sounds as these “twists” are often optional and give the player time to adjust.
They’re also part of a larger design choice that seems to be SMB 3’s main focus: variety.
Beyond the clever architecture, one-time mechanics/dynamics, unique art assets, etc., the overall flow of the levels shows the importance of this goal. Even when the Worlds are themed — such as Ice Land — each of their consecutive stages use different tilesets and gameplay. The standard level is accompanied by multi-directional auto-scrollers, tense fortresses, sluggish underwater stages, battle arenas, one-off themed levels, labyrinth maps, bonus shops, airships, minigames, etc. Simply put, SMB 3 pulls out all the stops in trying to create a constantly stimulating experience that never feels repetitive.
I’d like to take a closer look at how all this variety is stitched together, so for my final post I’ll focus on SMB 3’s “meta” aspects and how they tie-into the overall level design.

Note: This article was originally published on the author's blog, and is reproduced here with kind permission.

• This game started as a practice project. It's the classic game of Snake, but with a twist: you have to control two snakes at once, they score points separately, but in the end you get the lower score of the two (so you have to balance).
You have two things to collect, one gives you point depending on the length, the other gives no points at all, but increases the length, so you need to find the balance here as well.

On the "client" side, I use p5.js and jQuery,It has a highscore feature (which turned out quite difficult for me): on the server side that's node.js and MongoDB. I'm a beginner in programming,but I've learned a lot from this and it was quite fun so far.

What do you think about this game? How to improve it? Is there something you would do differently?
You can check it out here: http://serpents.ga

• 28
• 13
• 11
• 31
• 20