Skip to content


Folders and files

Last commit message
Last commit date

Latest commit



17 Commits

Repository files navigation

Copyright (C) 2009 Riad Wahby <>

TriHs is a Tetris-like game implemented in Haskell using Gtk2Hs, using
the Cairo vector graphics library bindings.


To build TriHs, you will need the Glasgow Haskell Compiler.  In
addition, make sure you have the following Haskell libraries installed:

  - Graphics.UI.Gtk
      aka Gtk2Hs.  I've tested it against v0.10.1

  - Graphics.Rendering.Cairo
      part of Gtk2Hs, but sometimes distributed separately
      if you build Gtk2Hs, be sure that the Cairo bindings get built too!

  - Control.Concurrent
      I use an MVar to hold the game state.  I could have used an IOVar, but
      there might be some crazy crap I decide to pull later involving MVars.

Once you have these, just type "make."


The following keys are defined:

  - Alt-q / Ctrl-q / "Quit" button
      Quit the game
  - Ctrl-p
      Pause the game
  - Ctrl-s
      Toggle shadows on/off (using this makes you a cheater!)
  - Ctrl-1
      Begin new 1-player game
  - Ctrl-2
      Begin new 2-player game

Player 1 controls:
  - a - move left
  - d - move right
  - s - move down
  - q - instant drop (hard)
  - e - rotate clockwise
  - w - rotate counterclockwise
  - f - swap opponent's next brick (2 player game only)

Player 2 controls:
  - p - move left
  - ] - move right
  - [ - move down
  - - - instant drop (hard)
  - = - rotate clockwise
  - 0 - rotate counterclockwise
  - o - swap opponent's next brick (2 player game only)

Player 2 alt controls:
  - Left, Right, Down arrows - move as directed
  - Up arrow - rotate CCW
  - XF86Forward - rotate CW
  - XF86Back - Instant drop
  - / - swap opponent's next brick (2 player game only)

The alt controls are only there because they are really convenient on my
Thinkpad T61 keyboard.  It should be relatively self-explanatory how to
change the keybindings; see the "handleButtonPress" function in the Main
module (TriHs.hs).


The code for TriHs is split into three pieces: TriHsPieces,
TriHsDrawing, and the Main module.

TriHsPieces contains only pure code that defines the game datatypes and
piece and state transforms.  This is where the game-specific (non-UI)
definitions live.

TriHsDrawing contains all the Cairo-related code.  This is where the
canvas redraw callbacks and board, piece, and block drawing functions
live.  Basically, everything in the Render monad lives here.

Main contains impure (IO Monad) code for dealing with the user
interface, including creating the windows, handling events, updating
mutable state, et cetera.

In principle, this separation should make it relatively easy to rip the
whole front end (Gtk2Hs+Cairo) off of the back end and build a new one
with another toolkit, or to swap out Cairo for OpenGL.

The only front end-specific blemishes in TriHsPieces are the
"HandlerId", "DrawingArea", and "Label" data in TetrisGameState.  To
really separate these, TetrisGameState should either be defined in Main
or wrapped in another datatype that is defined in Main.  However, it
seemed to me that this would muddy up the code for essentially no gain.


Yes, it's not pretty.  I care more about implementing interesting
extensions to the Tetris rules than I do about making a beautiful UI.
Unfortunately, this means there's no fancy game over screen or the
like.  Feel free to make things prettier if you care; it should be
pretty simple.


TriHs is free software.  It comes without any warranty, to to the extent
permitted by applicable law.  You can redistribute it and/or modify it
under the terms of the Do What The Fuck You Want To Public License,
Version 2, as published by Sam Hocevar.  See the COPYING file or for more details


Tetris game in Haskell using Gtk2Hs/Cairo.







No releases published


No packages published