Qbasic Snake

5 views
Skip to first unread message

Josephina

unread,
Aug 3, 2024, 3:21:32 PM8/3/24
to maiworkdowno

Nibbles, also known by the source code's file name NIBBLES.BAS, is a variant of the snake video game concept used to demonstrate the QBasic programming language. Nibbles was written in QBasic by Rick Raddatz, who later went on to create small businesses such as Xiosoft and Bizpad.[citation needed]

The game's objective is to navigate a virtual snake through a walled space while consuming numbers (from 1 through 9) along the way. The player must avoid colliding with walls, other snakes or their own snake. Since the length of the snake increases with each number consumed, the game increases in difficulty over time. After the last number has been eaten, the player progresses to the next level, with more complex obstacles and increased speed. There is a multiplayer mode which allows a second player to control a second snake by using a different set of keys on the same keyboard.[1]

Nibbles was included with MS-DOS version 5.0 and above. Written in QBasic, it is one of the programs included as a demonstration of that programming language.[1] The QBasic game uses the standard 80x25 text screen to emulate an 80x50 grid by making clever use of foreground and background colors, and the ANSI characters for full blocks and half-height blocks. Microsoft's 24kB QBasic version was copyrighted in 1990. Because of MS-DOS's prevalence at that time, it was available on almost every IBM PC compatible in the early 1990s.

Do you remember MS-DOS? Do you remember that it came withan interpreted programming language? From MS-DOS 5 onwards,it came with not Python, not Javascript or R or Matlab,but a dialectof BASIC. ButI think most people, especially most people my age whowere children at the height of the MS-DOS era, rememberit for the games, the two sample programs that came with it, namelyGorillasand Nibbles (their name for Snake).

It looks a little less impressive in such a small little emulationwindow, but of course at the time it took the entire screen of anentire CRT monitor, and was the best technology available for meto interact with.

Nibbles was a sample game designed for you to learn to program as wellas having fun with. True to its time, it had a little set-up interfacewhere you answered questions in a very basic prompt-and-respond TUIbefore you couldstart playing:

Code browsers are great, and this interface is a solid reminder thatsubroutines are a very early form of modules, especially given thatin QBasic, these subroutines could contain their ownsub-subroutinesusing the more traditionalGOSUB command.

First off, wesee some mutable global variables, a big no-no by modern standards,but can you really blame them when their scope is no larger than thatof a small modern class, where the fields would be effectively globalwithin the context of an instance?

But also, to my pleasant surprise, there were also some globalconstants,and they are marked as such, withthe CONST keyword. In fact, as we see inmultipleplaces,QBasic is actually strongly typed, sometimes even usingthesigils,for which the BASIC family is infamous.

Or, of course, maybe duck-typing was seen as too difficult orinefficient to implement. But in that case, why did they havewhat I imagine would be an equally difficult compromise measure,alphabetically-based typedefaulting.

To be fair, for a long time I had no idea what DEFINT evenmeant, but DEFINT A-Z certainly seemed like an appropriately mysteriousand even badass way to start a subroutine, a magical invocation, coveringthe ends of the alphabet to start off each page of code.

So what did I do with this? I added more action keys. I addedkeys to speed up and slow down gameplay on command, so that ifyou pressed the arrow in the direction the snake was currentlygoing, instead of doing nothing, it sped up the snake. Pressingthe opposite direction of where you were going would then slowit down. And then, I wrote new levels, using the existing levelscodeas a baseline.

Basically, Snake (or nibbles) was an popular PC game back in the 80s where you control a Snake and attempt to eat 10 digits or fruit. As you eat, your snake gets longer, and if you crash into a yourself, a wall, other player, you die. I used to play the Qbasic version a lot back in the day, and me and one of my lab partners had fun competing

I have TapeWorm, but the graphics are lame, and in the later levels, your snake becomes invisible, which makes hitting the targets excruciatingly frustrating. Surround doesn't really seem to have a decent 1-player mode, nor do you have targets or obstacles to navigate. Are there any other decent games I can try?

But what I really enjoyed about the original Qbasic Nibbles, and the classic PC snake games, was the exploring aspect of collecting the randomly distributed apples, numbers, whatever and watching the snake grow. Then in two player mode, you have the option of working together or competing. Sure you could try to annihilate your opponent, but the primary objective was to collect numerals. Just like in games like Mario Brothers, Joust, and Balloon Fight, with 2-player Snake / Nibbles, you have the option of working together or competing just based on play style.

After consuming a number, the snake grows longer. It dies if it runs into the walls or into its own tail, which grows pretty long after several helpings of numbers. The higher levels feature more walls, therefore, navigating them is more difficult. The game has a two-player mode as well as the standard single-player.

In this project, you will develop a version of Snake, a famous early computer game widely cloned and reproduced. (Fun fact: Snake in QBASIC was the first computer game Malte played as a child, and Snake was also on his first mobile phone, a Nokia 3310.)

Important Note: There are Testing and Debugging sections at the end of the handout. Make sure you read through these before attempting to implement any part of the project, so that you can run tests and productively debug your code.

We know that the game board will have certain dimensions, and may contain walls. Our snake game will support user-provided levels, so the board dimensions may be different every time. We will also need to access and update the board based on arrow key inputs from the user.

So, what are some important details about the game board that we need to store? Additionally, what data structure(s) can we use to represent the board itself? Think on these questions before reading through our explanation of the struct that we give you in the stencil!

Important Note: This project leaves deliberately leaves you some design freedom in how you represent your snake. You can use the snake struct, or you can choose another way to store the information in memory (but think about which memory lifetimes, and thus memory segments, are appropriate).

In the board struct provided in the stencil, the cells field is defined as an array of integers. This means that each cell on the board will have an integer representing what type of cell it is (i.e., a wall, an empty cell, a food cell, or a snake cell). We would like our game implementation to support cells that have multiple properties, so we use bit flags within an integer value to represent the states.

Now that we have our main three structs defined, we need to initialize all of them before we can run our game. First, take a look at the function initialize_default_board (in game_setup.c). You do not need to modify this function.

Purpose: Initializes a board_t struct to contain a default board with 10 rows and 20 columns. The snake is initialized at the 3rd row down and 3rd column from the left. You do not need to modify this function.

You may notice that the return value of initialize_default_board is a value of type board_init_status_t. This type represents possible error codes for errors that could occur during board initialization.

Task: Your task is to implement initialize_game, which should initialize all the fields of the game struct provided as a pointer argument named game. For now, to initialize the board field, call the initialize_default_board function given in the stencil. This will automatically fill in all the fields of the board_t as well as initialize the respective field of the game_t struct. You will also want to set the return value to the value returned from initialize_default_board.

Now, at the end of the main function, uncomment the last line that calls end_game(&game). This function is responsible for freeing all the resources used up by our program, as well as stopping the renderer upon completion of our game. Click on the dropdown for more information.

You should pass tests 1 and 2 at this point! This means that you should be able to see a board with 10 rows and 20 columns, with walls around the edges, and a snake initialised at the third row down and third column from the left. The snake should not move.

Now that you have defined a way to represent the snake in our game, you can use your representation (as well as the game struct and board struct) to begin implementing the update function in game.c. First, you will need to write the functionality that allows your snake to move while on the board.

Note: In most versions of Snake, the snake initially moves to the right. Make sure that you replicate this convention and that your snake starts moving right when the game is initialized!

Note: So far, we have been using the default board to run your game, but later on, you will need to handle custom boards, which may or may not have internal walls that your snake can crash into.

Aside: For both Part 1 and Part 2 of this project, try playing the Google Maps version of Snake to figure out how to handle any edge cases you come up with! This will also be useful when trying to pass any of our tests that test for specific edge cases.

In this representation of a custom board, the board is represented by a looooong string that contains exactly one character for every cell on the board. For example, an 80x24 board (a typical terminal size, which goes back to the 1970s) would look like this:

c80f0f1006
Reply all
Reply to author
Forward
0 new messages