Introduction
You have been hired by SmallSoft, the world's second-largest producer of tacky video
games, to produce a new video game called Chetyris. Chetyris is a knock-off of the
world-famous Tetris game (with an allusion to Tetris's Russian origin — четыре,
transliterated as chetyre, means four).
In Chetyris, your job as the player is to manage a well that is 10 units wide by 18 units
deep. At the top of the well, pieces of various shapes are dropped into the well. The
pieces are made up of one or more small blocks in various geometric configurations.
For example, here are some of the blocks (in their initial orientation) that will be
dropped, along with their conventional names:
# # # ## ## ##
### ### ### ## ## ## ####
T L J O S Z I
At the start of each game, the well starts out entirely empty. As each piece falls it can
be rotated clockwise or moved horizontally so that every space in the well is filled. If
and when a horizontal row of the well is completely filled with blocks, that row is
vaporized and all of the blocks above fall into the void created by the vaporized row
of blocks. In addition, every time you vaporize a row, you get points. On the other
hand, if a row is covered by one or more pieces before it is completely filled with
blocks, then the unfinished row simply takes up space in the well. The more such
incomplete rows that the player leaves, the higher the pieces stack within the well,
reducing the space in which falling pieces can be manipulated. If the blocks ever
reach the top of the screen, preventing pieces from being dropped, then the game ends.
The game is divided into levels, so that the player can take a rest after each level.
During the first level, the player must complete and vaporize five full rows of blocks
before advancing to the next level. At the second level, the player must complete ten
full rows; on the third level, fifteen full rows, etc. At the end of a level, all remaining
blocks in the well are cleared out, so that each successive level starts with an empty
well.
With each succesive level, gravity increases so that pieces fall faster than during the
previous level, giving the player less time to manipulate the pieces before they come
to rest at the bottom of the well. The game continues (potentially indefinitely) until
the well fills to the top with pieces.
Here is a screen shot of the Chetyris game, showing an S piece coming down:
@ @
@ @
@ @
@ ## @ Next piece:
@ ## @ #
@ @ ###
@ @
@ @
@ @ Score: 0
@ @ Rows left: 5
@ @ Level: 1
@ @
@ @
@ @
@ $ @
@$$ @
@$$$ @
@$$ $$$$ @
@@@@@@@@@@@@
To play the game, the player may hit any of the following keys:
To move the current piece to the left, the left arrow key or 'a' or '4'.
To move the current piece to the right, the right arrow key or 'd' or '6'.
To rotate the piece clockwise, the up arrow key or 'w' or '8'.
To move the current piece down one row (to speed things up), the down arrow
or 's' or '2'.
To move the current piece down as far as it will go (to speed things up more),
the space bar.
To quit the game, 'q' or 'Q'.
The player may hit these keys one or more times to shift the current piece left or right
as it falls into the well. If a piece is falling slowly enough, it is possible to shift a piece
two or more times (e.g. twice to the left) before the piece advances down a single row
in the well.
In addition to the seven classic Tetris shapes shown above, Chetyris has three more
pieces:
The VaporBomb: ##
Once the vapor bomb comes to rest on other blocks in the well or at the bottom of the
well, it will vaporize itself and also obliterate the square of four blocks above the
vapor bomb and the square of four blocks below the vapor bomb. This is the special
action of the VaporBomb. They are sent down occasionally to help the player zap
blocks that are in the way. (See the Game Details section below for more details.)
The FoamBomb: #
Once the foam bomb comes to rest on other blocks in the well or at the bottom of the
well, it will immediately inflate, much like exploding whipped cream, to fill out the
void surrounding and including the landing spot of the foam bomb. This is the special
action of the FoamBomb. This can help to fill hard-to-reach voids in the well. (See the
Game Details section below for more details.)
The CrazyShape: # # ##
The CrazyShape doesn't look all that crazy, but responds in an opposite fashion to the
player's keystrokes. To shift the CrazyShape right, the player must press the left arrow
key, and to shift the CrazyShape left, the player must press the right arrow key. This
can be very confusing during high-speed play. (See the Game Details section below
for more details.)
Game Details
Here is a functional specification for the Chetyris game:
Gameplay Rules
1. There are an unlimited number of levels in the Chetyris game. The first level
number is Level #1 (not level #0).
2. At the start of each level, the well is empty.
3. To complete a given level n, the player must vaporize 5*n rows by filling 5*n
rows full of blocks (all 10 blocks must be filled in a row to vaporize the row).
Once 5*n rows have been vaporized, the well's contents will be cleared, and the
game will prompt the player to start the next level.
The following diagram shows a J piece as it is about to complete, and thus
vaporize, a row. Once the bottom end of the piece settles to rest in position
(2,5), row #5 will be completed and should be vaporized. (Notice the
coordinate system we are using: The first coordinate is the x coordinate, which
grows toward the right; the second is the y coordinate, which grows downward.)
And here is the resulting well, after row 5 has been vaporized:
4. At the start of the game, the first piece will be placed at the top of the well (see
details below) in its default orientation (orientation #0) and then will proceed to
fall a row at a time until it reaches the bottom of the well.
5. The game should provide the player with a different random sequence of pieces
each time the game is played.
6. Once a normal piece (one without a special action) has come to rest at the
bottom of the well or on top of another piece (see details below), the game will
determine if one or more new rows were entirely filled. If a row was entirely
filled then it will be removed from the well, shifting all rows above the
removed row down by one. If more than one row was completed at the same
time, then all these rows will be removed and the rows above will be shifted
down by the number of rows that were removed.
7. Once a special piece (e.g. a VaporBomb) comes to rest, the program will apply
the special action of the piece (e.g. vaporizing blocks above and below the
piece). Next, the program must determine if one†††⁴†㱦⽥㹤ഠ⁴†⁰⁉て†⁷⁴䙩Ɽ†⁴㱨†⽩㹴ഠ⁴†䥷††㰊⁷⽮㸠ൢ⠠⁉Ⱐ⁷䉨⥭㩥†㱴⼬㸠൴੨㱥⽬㹬ഠ਼ 䤾⁷†⁷†ㅳ⁴Ɫ⁹†㵢㍲†㰯 ⽮㹵൭†㵦㘠䉷⁴⁶‾⁴†⡣⁹㱭⽴㹥ਠ⡲㑯ⱷび⤠⥨⁴ 䥬ⱴ㰠⼠㹷੬⁴⁴†⠊㑤ⱥて⥡⁵⁴⁏⁴⸠‣⠰㰠⼊㸹മਠ††ⱥ††㰯 ⽰㹩⸠⥯㰠⼠㹢൬੯ㅣ㑫††ⱬ⁹ †㱬⽤㹹ഠ੩㵮†⡬ㄠてひは⠠ㅡ〠ば⩲⡥䱶ㅯ⥵⥳Ⱐ⁰ㅩづっ⥥
‾⁴⸠⁈⡯㰬⼠㹴൨†††⥷‼⁰⁴†㱢⽫㹳ഠ੩⁷Ɱ†䱭⁴⸠ 䔾†⁰㱰⼠㹴൯ਠ⁴ⱷ†⁶‾⁰⁹⸠⁴㱯⁵⽩㹣൫੬ㅹ㔠†⁷⁴⁴⁴⡳††⥴†㰠⽣㹥൮†⁷‼‾ †䥥†㰠‴⽸㸴ഠⱮ⁸‼⁰†㍲††ⰺ† 㜾 †㱦⽯㹷൩੮Ᵽ†⁵†† 㰠⁴⽨㹩൮ਠㅩ㙴†䤴‴⁵⁷†✣❳✠❥⁰ⱥ††‼†㱥‼⽢㹲ഠਯ⁔䝣⠊†䑥††㰠⼠㸯ാ⥥⸠⁏㰠⽣㹥ഠ਼ㅢ㝲⸠ ⁓ⱥ††⁔⁐††⌯〾㱥†⽐㹩⍲ㄠⰯ‾⁔⌠㈼Ɫ‾⍥㌠ⱆ⁂ ⌼ぢⱲ†⸊⁔㱨⁃⽲㹡ൺ Ⰺ‱⁗⁰⁴㱦⽥㸠൷†Ⱐ⁵Ɽ††㱴‽⼳㸬ഠਖ਼⁷ †Ⱐ⁰⁴㱴⽯㹮ഠਨ‰‼⸾㰊⼠㸯ാㄊ㡉†䥴†††††㰯 ⽘㸽ഴਬ‰†⁰†† 㰊⽩㹮ബਠ⁵⡰⥨ⱡⱘ‽ⰽ‰⁉†㰯 ⽴㹨൩ੳⰬ†⁴⽩⁵††⁷㰠⼊㹢൬੯㱣⽦㸠൴੨ㅥ㤠⁵⁰††‱† ⁴⡨㱳⽬㹯ൣ੫ⱥ†††‼‾††㰯 ⼱㸲മਠ⥷Ⱐ⁰††††㰼†⼯㸾ਊ⁴⁰†㰠⽥㹡⁴ⱡ⁰††⁸†⁷†⁴㱨⽡㹭ਠ⸬†⁴⁴†⁴㰠⁴⼠㹤൩ੲ㉥っ⁰†Ᵽ⁴⁴㱡⽯㹮൴੩⁴†‾⁶†ⁱ†…⁴㰻‼⽢㹲ഠਯ䥮⁴⁰㰠⁸⼠㹲൯㉳ㄠ†⁷ⱳ†㰼†⼯㸾ਊ䥥⁵†‼⡢⸠⸾Ⰽ ††㱴†⽉㸠൰੩⁷††⁰䍰⤠Ɱ⁰†㱴†⽢㹬൯‼† ⸬†㰨‱⼩㸬ഠਨ⸬‱䤩†††††⡳Ⱐ†䉥†㱯⁵⽰㹩䘬䉩⥨ⱡ⁰⁵❥♯㭥☠㭴⁸⁴†❴†㱅⼠㹴൨੯†䘠ⱹ††䉢†⁰㰲†⽴㹨൩ੳ†㉤††㉬㰠⼊㹔൨䅡⡴⥮⁴⡬⤠ⁱ⁹Ɐ††⁴⁴⁴㱳⽲㸠യਾ†
⁶†㱴‵⼬㸲ഩਠ †⁴⁸†⁹㰠†⽵㹮൵ੳ䘠Ⱪ⁷†† ††㱤⁴⽨㹥ഠੰ㉬㉡⁴†䉯†⡲⁵†㰠⽹㹥൲ਠ⤠Ɒ‾⁹䉤❭†㱰⁹⽥㹲ഠ੧‰ ⁰† ⁆⁷⁵㱳⼠㹴൨䉥ⱥ⁴‰ 䉥⁷⁵䉩⁴㱯⽹㸬ഠੴ‰Ⱐ ⁴‾⁄㉰⁵㔠ⴼ‾††㱤⽲㹩ൢ⁹⸠⁹䙯†Ɐ⁵†㩢㰠⼊㹳ൣੲ㱥⼠㸼ൢੲ†䉴Ᵽ⌠Ⱐ⁴⁴†› 㱡⁔⽨㹥ഠੵ⡰㍰ⱥ㍲⤭⁴⁴⡨†⁰⁴㔠‼ 㘾Ⰽ 㱯⽥㹴ഠⱙ‽㍲ⱥ⁔†⁹†㌯‾㐠⥩䤠㱦†⽲㹩൧੨†⁰⁹ⱡ⁴⁘⁙⁵㱬⽥㸠ൡ੮†⡴㍥Ⱳ〠⥤Ⱪ⡰㍬ⱡ㙹⥥Ɽ††⠼㑢Ⱳ㘠⤯⸾㰊‱⼱㸬൙㈰㌠†䙳䉥†‼†⠮†※ⁱ※㰠⽰㹬ൡ⤶Ⱜ″‼⁰⸠䅥⁹⁷䙩䉴⁵㱥†⽣㹯൲੮†⁴‼⡵Ɽ⥮Ⱨ††‴††⡯††⩤⥩㱰⁹⽥㹤ഠ‱†⁵※㕥㔦ⁱ‼⁷⡥ⴠ㉢ⱹⵦ㉩⥶⁰⡡⭥㉳Ⱐ⭯㉬⥬Ɐ⁷㱥⽹㸠൴੨†‼ 䘠䉥㩢㰠⼊㹥മਠ䄠†㕵㕴††⁴Ɫ㰠⼊㹩൳ਠ⁴
⠱
†⤦ⱱ⁵※䘠䉴ⁱ㱵※⼠㸼ൢੲ†⩣㱷†⽢㹹ഠੴ†䅮††㕴㕥†ⱦ㱥⽮㸠ൡਠ‷†Ⱞ†⁵⡭⥥⁰㱬⽤㸠ൡੴ‰†⩥†⸠‼㱢 ⼾㸍ഊਦ⁶⡥⤺…††㱢⼠㸼ൢੲⱨ⁴ⱡ⁴ ⁁⁰㕲㕭⁰㱴
⽥㸮൧ਮ⁐†⁹⠠⥯††⡰⥡⁹♩㭥⁴‡
†㰠†⽤㹩൳ੰ⩴†⸩†㱡†⽳㹨൯ੵ䙬ⱥ††⁴†⁹⁰䙲䉥㱮⽶㹥൮ਠ⁰⁰⡲㍯Ɑ㑰⥴†⡩ †⁰㑥Ⱐ⁰ⱥ㱴⽴㸠൴੨⁅㌠Ⱬ⁷† ㌠⤼㩢㰠⼊㸲മਠ㱇⼠㹤൩ੳ†Ⱐ⁔†㨠㱥⽡㹷൮ਠ㱵⽧㸠ണਠ⁴†⠠㉁ⱬ㕬⤠Ɫ⡯㉣Ⱬ㙳⤠Ᵽ⡭ㅰⱲ㉩⥳Ⱪ⡧ㄠⱰ㍲⥥ⱶ⡯ㅵⱳ㑬⥹Ⱐ⡡ㅬⱬ㕥⥮Ⱐ⁰⡳ㄠⱴ㙨⥡⁴⁶㱥†⼼㹢൲ਠ††††㰯 ⽰㹩‼ 䙡䈠⡡㍭Ⱐ㑢⥯†††㰪⽲㸠യਾ†✠⩤❩ⱥ†††ⱥ䘠䈠††‼ 㰾⁰⽲㹥൶੩⁹″†⁹㱰†⽢㹯ൡੲ†⁴⸾㰊⼠㹮൵੭㉢㑥†䍥††††㨠 㱨⽤㸠൰ੲ䍯Ⱶ††ⱨ…㰠⼠㸯ാ䍥ⱥ†⁴⁵⸠‼‾㰠⽥㹤൩䍴⁴ⱳ†⁹ⱥ†⁴†‼†㰯 ⽰㹩†††⁴ⴻ⁸㱥ⁱ⽵㹯൴㈠㕳䥷 ⁴⁸⁴‼ ⁵⡬㰭⽰㹬ൡⱬ⁴‼㱨⼺㸠഼†††⤠Ⱬ⁴⁴㱥⼠㸼ൢੲ⠠❢†⁶†㰠⼠㸯ാ⁔†⥯䥳⁴†‾㰍⽷㹳ഠੴⱰ††⁖Ɐ⁺‼‾㰍⼠㹁ഠ⁴⁴⁰‾㱲⽯㹷൳ਠ⁰㱯⁺⽥㸠൩੮㈠㙴
‼‾††ⱳ†⁴†⸠⁵䥰†㱴†⽳㹣൯ੲ⁹⁴† †ⱥ‼ ⁁†㱩⽧㸠൲੯䤠ⱡpdate the
rows left display to the right of the well.
8. If, when a new piece is about to be played, that piece will cause the game to
end (because it overlaps with existing blocks in the well), you should still
update the display to show how the piece would fit in the well.
9. When the player completes a level, the game should display the following in
the prompt area of the screen (overwriting other text that may already be there):
"Good job! Press the Enter key to start next level!". Once the player presses the
Enter key, the next level should begin with an empty well and updated score,
rows left, and level number.
10. If the player quits or if the well fills up, the game should display the following
in the prompt area of the screen (overwriting other text that may already be
there): "Game Over! Press the Enter key to exit!" Once the player presses the
Enter key, the program should terminate.
What We Provide You
To help you understand the requirements of this project, we have
provided Windows, macOS, and Linux executables that you can run. If there is a
detail that is not specified explicitly the Game Details, you can use these executables
to determine the intended behavior.
To help you get started, we have provided a skeleton that contains the beginning of a
solution. It contains the following files:
chetyris.cpp
This little file contains the main routine. When we build your solution, we will
ignore any main routine you provide and will use this file instead, so your
program must build correctly with this file. During your program
development, you might want to reduce the size of the well to make the game
take less time when you're testing it.
Game.h and Game.cpp
The Game class manages the game. You are free to make whatever changes
and additions to these files that you like, provided that they build with the
provided chetyris.cpp.
Well.h and Well.cpp
In order for the skeleton code we provided to build, we provided a minimal
class representing the well. You may modify these as you wish.
Piece.h and Piece.cpp
These files are where code related to pieces should go. Also, at the point in the
game where the next piece to be dropped must be chosen, you must call the
chooseRandomPieceType function declared in this header. For example, you
could say
switch (chooseRandomPieceType())
{
case PIECE_I:
... // make the next piece an I piece
break;
case PIECE_L:
... // make the next piece an L piece
break;
...
}