[Kc] Perl 'Expert' Quiz of the Week #23

Garrett Goebel garrett at scriptpro.com
Thu Sep 9 08:41:44 CDT 2004

IMPORTANT: Please do not post solutions, hints, or other spoilers
        until at least 60 hours after the date of this message.

IMPORTANTE: Por favor, no enviis soluciones, pistas, o cualquier otra
        cosa que pueda echar a perder la resolucin del problema hasta
        que hayan pasado por lo menos 60 horas desde el envo de este
        mensaje. Gracias.

WICHTIG: Bitte schicken Sie keine Lsungen, Tipps oder Hinweise fr
        diese Aufgabe vor Ablauf von 60 Stunden nach dem Datum dieser
        Mail. Danke.

VNIMANIE: Pozhalujsta ne shlite reshenija, nameki na reshenija, i
        voobshe lyubye podskazki v techenie po krajnej mere 60 chasov
        ot daty etogo soobshenija.  Spasibo.

Qing3 Zhu4Yi4: Qing3 Ning2 Deng3Dao4 Jie1Dao4 Ben3 Xin4Xi2 Zhi1Hou4 60
        Xiao3Shi2, Zai4 Fa1Biao3 Jie3Da2, Ti2Shi4, Huo4 Qi2Ta1 Hui4
        Xie4Lou4 Da2An4 De5 Jian4Yi4.  Xie4Xie4.


The aim this fortnight is to write a tetris game -- a problem that should be
both fun to write and fun to use.

The problem is split into three milestones. Each milestone adds
functionality to the game to the point where we can play each other across
the internet.

Write a single-user tetris game.

Tetris is a simple graphical game that can be implemented on almost any
interface, from a text display to a full-blown three dimensional graphical

A game grid is 10 spaces wide and 20 spaces high. Gravity pulls random
blocks toward the bottom of the grid until the bottom surface of any portion
of the block touches another block or the bottom of the game grid.

Gravity pulls blocks downward at a rate starting at one space per second
(we'll call that the 'gravity-period'.

The player can alter the way the block drops in four ways:
- Move left: The player can move the dropping block one space to the left
- Move right: The player can move the dropping block one space to the right
- Move down: The player can move the dropping block one space down
- Rotate: The player can rotate the block clockwise 90 degrees
   (optionally you may also allow an anti-clockwise rotate)

The player is not limited to the number of actions they take in each
gravity-period by anything other than the speed of the interface.

There are seven block shapes that fall:

    ##   @@  %%   ***  &&&  ++++  $$$
    ##  @@    %%  *      &         $

Once the block reaches ground-level another gravity-period elapses before it
is cemented in place. This allows the player to move the block left or right
at the last moment, as shown below. The '#' block is moved:

        4|&&        |  |&&        |
        3|& ##      |  |&##       |
        2|& ##      |  |&##       |
        1+----------+  +----------+

Each time a complete horizonal row in the grid is completed, its contents
disappear and the contents of the rows above it drop down to fill the
vacated spaces. The example below shows a block landing and completing row
2.  One gravity-period later, row 2 has disappeared, and rows 3 and 4 have
dropped down one space:

        4|&&        |  |          |
        3|&##    &  |  |&&        |
        2|&##++++&&&|  |&##    &  |
        1|++++  ++++|  |++++  ++++|
         +----------+  +----------+

After each 10 complete rows are deleted in this way, the difficulty level
increases.  Difficulty level $n's gravity-period is (1 /
1.3**($n-1)) seconds. Each completed row scores the user $c * $n where $c is
the number of blocks removed at a single time (in the default grid, that
would be 10 times the number of rows removed as there are 10 columns).

The aim of the game is to successfully place as many blocks as possible
before one of the blocks touches the top of the grid. Here's a game that's
finished -- you'll note that the top '%' block touches the top of the grid:

        20|     %    |
        19|    %%    |
        18|    %     |
        17|    +     |
        16|    +     |
        15|    +     |
        14|    +     |
        13|   &&     |
        12|   &      |
        11|   &      |
        10|   +      |
         9|   +      |
         8|   +      |
         7|   +      |
         6|   &      |
         5|   &      |
         4|  &&      |
         3| ##       |
         2| ##       |
         1|++++      |

The player scores one point for each unit of the perimeter of the dropped
shape that touches a previously dropped block or the edge of the grid. In
the example game below, the '&' block was dropped onto a blank grid and
scored 5 points.  Then the '$' block was then dropped and scored 3 points:
two points for its two contacts with the '&' block and one point for its
contact with the bottom of the grid:

          4|   $      |
          3|& $$      |
          2|&&&$      |

You may choose to use any reasonable interface that you want.  It will be
interesting to see solutions in ncurses, tk or anything else. (Note that
I'll be testing it on MacOS-X and RedHat linux)

The interface should show the entire game grid and should also show which
block will drop next.

Any of the above options can be changed except the block shapes. You can
allow users to change the gravity-period or the grid size.
However, the defaults are as above.

The default action keys should be:

        Z - left
        X - right
        / - down
        ' - rotate

If you have extra time, you may want to implement some of the following
extensions to the project:

Allow two-user game play

In this version of the quiz you will allow a second user to select which
block will drop next. This selection will be from three randomly selected
blocks and should be selected using the 1, 2 and 3 keys. These three pieces
should be displayed in the interface.

Should the second player not select a block before it is needed, one should
be selected at random from the three choices.

Write a split engine/interface tetris game

In this version of the quiz the interface should be split from the engine.
Two interfaces should be able to link to a given engine, one for each
player.  (Optionally, extra interfaces may connect but only to view the
game, not play)

The interface should connect to the engine via a network socket.

The command set should be standardised so your interface can plug into my
engine or vice versa.

The client will send the server commands on each keypress:


A second client (for player 2) can send:


to indicate the selected piece. In the split game (where the two players are
using different clients) there is no requirement for player 1 to see the
three options given to player 2 until one becomes the 'next block'.

The server will send the client diffs of the game board. The following
change would be transmitted as:

        D03 D02 B03#B02#

  4|&&        |  |&&        |
  3|& ##      |  |&##       |
  2|& ##      |  |&##       |
  1+----------+  +----------+

The format of the message string is:

        ($col,$row,$piece) =~ /([A-J])(\d\d)([\Q#@%*&+$\E])/


Screenshot of original tetris:


History of tetris (from Atari's point of view -- there was a court


Javascript Implementation of the game if you've never played it:


-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.pm.org/pipermail/kc/attachments/20040909/4f5b59d5/attachment.htm

More information about the kc mailing list