summaryrefslogtreecommitdiffstats
path: root/examples/life
diff options
context:
space:
mode:
Diffstat (limited to 'examples/life')
-rw-r--r--examples/life/life.cpp136
-rw-r--r--examples/life/life.doc27
-rw-r--r--examples/life/life.h58
-rw-r--r--examples/life/life.pro13
-rw-r--r--examples/life/lifedlg.cpp162
-rw-r--r--examples/life/lifedlg.h64
-rw-r--r--examples/life/main.cpp44
-rw-r--r--examples/life/patterns.cpp383
8 files changed, 887 insertions, 0 deletions
diff --git a/examples/life/life.cpp b/examples/life/life.cpp
new file mode 100644
index 0000000..24379e6
--- /dev/null
+++ b/examples/life/life.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include "life.h"
+
+#include <qpainter.h>
+#include <qdrawutil.h>
+#include <qcheckbox.h>
+#include <qevent.h>
+#include <qapplication.h>
+
+// The main game of life widget
+
+LifeWidget::LifeWidget( int s, QWidget *parent, const char *name )
+ : QFrame( parent, name )
+{
+ SCALE = s;
+
+ maxi = maxj = 50;
+ setMinimumSize( MINSIZE * SCALE + 2 * BORDER,
+ MINSIZE * SCALE + 2 * BORDER );
+ setMaximumSize( MAXSIZE * SCALE + 2 * BORDER,
+ MAXSIZE * SCALE + 2 * BORDER );
+ setSizeIncrement( SCALE, SCALE);
+
+ clear();
+ resize( maxi * SCALE + 2 * BORDER , maxj * SCALE + 2 * BORDER );
+
+}
+
+
+void LifeWidget::clear()
+{
+ current = 0;
+ for ( int t = 0; t < 2; t++ )
+ for ( int i = 0; i < MAXSIZE + 2; i++ )
+ for ( int j = 0; j < MAXSIZE + 2; j++ )
+ cells[t][i][j] = FALSE;
+
+ repaint();
+}
+
+
+// We assume that the size will never be beyond the maximum size set
+// this is not in general TRUE, but in practice it's good enough for
+// this program
+
+void LifeWidget::resizeEvent( QResizeEvent * e )
+{
+ maxi = (e->size().width() - 2 * BORDER) / SCALE;
+ maxj = (e->size().height() - 2 * BORDER) / SCALE;
+}
+
+
+void LifeWidget::setPoint( int i, int j )
+{
+ if ( i < 1 || i > maxi || j < 1 || j > maxi )
+ return;
+ cells[current][i][j] = TRUE;
+ repaint( index2pos(i), index2pos(j), SCALE, SCALE, FALSE );
+}
+
+
+void LifeWidget::mouseHandle( const QPoint &pos )
+{
+ int i = pos2index( pos.x() );
+ int j = pos2index( pos.y() );
+ setPoint( i, j );
+}
+
+
+void LifeWidget::mouseMoveEvent( QMouseEvent *e )
+{
+ mouseHandle( e->pos() );
+}
+
+
+void LifeWidget::mousePressEvent( QMouseEvent *e )
+{
+ if ( e->button() == QMouseEvent::LeftButton )
+ mouseHandle( e->pos() );
+}
+
+
+void LifeWidget::nextGeneration()
+{
+ for ( int i = 1; i <= MAXSIZE; i++ ) {
+ for ( int j = 1; j <= MAXSIZE; j++ ) {
+ int t = cells[current][i - 1][j - 1]
+ + cells[current][i - 1][j]
+ + cells[current][i - 1][j + 1]
+ + cells[current][i][j - 1]
+ + cells[current][i][j + 1]
+ + cells[current][i + 1][j - 1]
+ + cells[current][i + 1][j]
+ + cells[current][i + 1][j + 1];
+
+ cells[!current][i][j] = ( t == 3 ||
+ t == 2 && cells[current][i][j] );
+ }
+ }
+ current = !current;
+ repaint( FALSE ); // repaint without erase
+}
+
+
+void LifeWidget::paintEvent( QPaintEvent * e )
+{
+ int starti = pos2index( e->rect().left() );
+ int stopi = pos2index( e->rect().right() );
+ int startj = pos2index( e->rect().top() );
+ int stopj = pos2index( e->rect().bottom() );
+
+ if (stopi > maxi)
+ stopi = maxi;
+ if (stopj > maxj)
+ stopj = maxj;
+
+ QPainter paint( this );
+ for ( int i = starti; i <= stopi; i++ ) {
+ for ( int j = startj; j <= stopj; j++ ) {
+ if ( cells[current][i][j] )
+ qDrawShadePanel( &paint, index2pos( i ), index2pos( j ),
+ SCALE - 1, SCALE - 1, colorGroup() );
+ else if ( cells[!current][i][j] )
+ erase(index2pos( i ), index2pos( j ), SCALE - 1, SCALE - 1);
+ }
+ }
+ drawFrame( &paint );
+}
diff --git a/examples/life/life.doc b/examples/life/life.doc
new file mode 100644
index 0000000..cd935cf
--- /dev/null
+++ b/examples/life/life.doc
@@ -0,0 +1,27 @@
+/*
+*/
+/*! \page life-example.html
+
+ \ingroup examples
+ \title Conway's Game of Life
+
+
+ <hr>
+
+ Header file:
+
+ \include life/life.h
+
+ <hr>
+
+ Implementation:
+
+ \include life/life.cpp
+
+ <hr>
+
+ Main:
+
+ \include life/main.cpp
+*/
+
diff --git a/examples/life/life.h b/examples/life/life.h
new file mode 100644
index 0000000..a66a3d1
--- /dev/null
+++ b/examples/life/life.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef LIFE_H
+#define LIFE_H
+
+#include <qframe.h>
+
+
+class LifeWidget : public QFrame
+{
+ Q_OBJECT
+public:
+ LifeWidget( int s = 10, QWidget *parent = 0, const char *name = 0 );
+
+ void setPoint( int i, int j );
+
+ int maxCol() { return maxi; }
+ int maxRow() { return maxj; }
+
+public slots:
+ void nextGeneration();
+ void clear();
+
+protected:
+ virtual void paintEvent( QPaintEvent * );
+ virtual void mouseMoveEvent( QMouseEvent * );
+ virtual void mousePressEvent( QMouseEvent * );
+ virtual void resizeEvent( QResizeEvent * );
+ void mouseHandle( const QPoint &pos );
+
+private:
+ enum { MAXSIZE = 50, MINSIZE = 10, BORDER = 5 };
+
+ bool cells[2][MAXSIZE + 2][MAXSIZE + 2];
+ int current;
+ int maxi, maxj;
+
+ int pos2index( int x )
+ {
+ return ( x - BORDER ) / SCALE + 1;
+ }
+ int index2pos( int i )
+ {
+ return ( i - 1 ) * SCALE + BORDER;
+ }
+
+ int SCALE;
+};
+
+
+#endif // LIFE_H
diff --git a/examples/life/life.pro b/examples/life/life.pro
new file mode 100644
index 0000000..cc9d22f
--- /dev/null
+++ b/examples/life/life.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = life
+
+CONFIG += qt warn_on release
+DEPENDPATH = ../../include
+
+REQUIRES = medium-config
+
+HEADERS = life.h \
+ lifedlg.h
+SOURCES = life.cpp \
+ lifedlg.cpp \
+ main.cpp
diff --git a/examples/life/lifedlg.cpp b/examples/life/lifedlg.cpp
new file mode 100644
index 0000000..a27f456
--- /dev/null
+++ b/examples/life/lifedlg.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include "lifedlg.h"
+#include <qapplication.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qslider.h>
+#include <qcombobox.h>
+#include <qdatetime.h>
+#include <stdlib.h>
+
+#include "patterns.cpp"
+
+
+// A simple timer which has a pause and a setSpeed slot
+
+LifeTimer::LifeTimer( QWidget *parent ) : QTimer( parent ), interval( 500 )
+{
+ start( interval );
+}
+
+
+void LifeTimer::pause( bool stopIt )
+{
+ if ( stopIt )
+ stop();
+ else
+ start( interval );
+}
+
+
+void LifeTimer::setSpeed( int speed )
+{
+ interval = MAXSPEED - speed;
+ if ( isActive() )
+ changeInterval( interval );
+}
+
+
+// A top-level container widget to organize the others
+
+LifeDialog::LifeDialog( int scale, QWidget * parent, const char * name )
+ : QWidget( parent, name )
+{
+ qb = new QPushButton( "Quit!", this );
+ cb = new QComboBox( this, "comboBox" );
+ life = new LifeWidget(scale, this);
+ life->move( SIDEBORDER, TOPBORDER );
+
+
+ connect( qb, SIGNAL(clicked()), qApp, SLOT(quit()) );
+ qb->setGeometry( SIDEBORDER, SIDEBORDER, qb->sizeHint().width(), 25 );
+ timer = new LifeTimer( this );
+
+ connect( timer, SIGNAL(timeout()), life, SLOT(nextGeneration()) );
+ pb = new QPushButton( "Pause", this );
+ pb->setToggleButton( TRUE );
+ connect( pb, SIGNAL(toggled(bool)), timer, SLOT(pause(bool)) );
+ pb->resize( pb->sizeHint().width(), 25 );
+ pb->move( width() - SIDEBORDER - pb->width(), SIDEBORDER );
+
+ sp = new QLabel( "Speed:", this );
+ sp->adjustSize();
+ sp->move( SIDEBORDER, 45 );
+ scroll = new QSlider( 0, LifeTimer::MAXSPEED, 50,
+ LifeTimer::MAXSPEED / 2,
+ QSlider::Horizontal, this );
+ connect( scroll, SIGNAL(valueChanged(int)),
+ timer, SLOT(setSpeed(int)) );
+
+ scroll->move( sp->width() + 2 * SIDEBORDER, 45 );
+ scroll->resize( 200, 15 );
+
+ life->setFrameStyle( QFrame::Panel | QFrame::Sunken );
+ life->show();
+
+ srand( QTime(0,0,0).msecsTo(QTime::currentTime()) );
+ int sel = rand() % NPATS;
+ getPattern( sel );
+
+ cb->move( 2*SIDEBORDER + qb->width(), SIDEBORDER);
+ cb->insertItem( "Glider Gun " );
+ cb->insertItem( "Figure Eight " );
+ cb->insertItem( "Pulsar " );
+ cb->insertItem( "Barber Pole P2 " );
+ cb->insertItem( "Achim P5 " );
+ cb->insertItem( "Hertz P4 " );
+ cb->insertItem( "Tumbler " );
+ cb->insertItem( "Pulse1 P4" );
+ cb->insertItem( "Shining Flower P5 " );
+ cb->insertItem( "Pulse2 P6 " );
+ cb->insertItem( "Pinwheel, Clock P4 " );
+ cb->insertItem( "Pentadecatholon " );
+ cb->insertItem( "Piston " );
+ cb->insertItem( "Piston2 " );
+ cb->insertItem( "Switch Engine " );
+ cb->insertItem( "Gears (Gear, Flywheel, Blinker) " );
+ cb->insertItem( "Turbine8 " );
+ cb->insertItem( "P16 " );
+ cb->insertItem( "Puffer " );
+ cb->insertItem( "Escort " );
+ cb->insertItem( "Dart Speed 1/3 " );
+ cb->insertItem( "Period 4 Speed 1/2 " );
+ cb->insertItem( "Another Period 4 Speed 1/2 " );
+ cb->insertItem( "Smallest Known Period 3 Spaceship Speed 1/3 " );
+ cb->insertItem( "Turtle Speed 1/3 " );
+ cb->insertItem( "Smallest Known Period 5 Speed 2/5 " );
+ cb->insertItem( "Sym Puffer " );
+ cb->insertItem( "], Near Ship, Pi Heptomino " );
+ cb->insertItem( "R Pentomino " );
+ cb->setAutoResize( FALSE );
+ cb->setCurrentItem( sel );
+ cb->show();
+ connect( cb, SIGNAL(activated(int)), SLOT(getPattern(int)) );
+
+ QSize s;
+ s = life->minimumSize();
+ setMinimumSize( s.width() + 2 * SIDEBORDER,
+ s.height() + TOPBORDER + SIDEBORDER );
+ s = life->maximumSize();
+ setMaximumSize( s.width() + 2 * SIDEBORDER,
+ s.height() + TOPBORDER + SIDEBORDER );
+ s = life->sizeIncrement();
+ setSizeIncrement( s.width(), s.height() );
+
+ resize( QMIN(512, qApp->desktop()->width()),
+ QMIN(480, qApp->desktop()->height()) );
+}
+
+
+void LifeDialog::resizeEvent( QResizeEvent * e )
+{
+ life->resize( e->size() - QSize( 2 * SIDEBORDER, TOPBORDER + SIDEBORDER ));
+ pb->move( e->size().width() - SIDEBORDER - pb->width(), SIDEBORDER );
+ scroll->resize( e->size().width() - sp->width() - 3 * SIDEBORDER,
+ scroll->height() );
+ cb->resize( width() - 4*SIDEBORDER - qb->width() - pb->width() , 25 );
+}
+
+
+// Adapted from xlock, see pattern.cpp for copyright info.
+
+void LifeDialog::getPattern( int pat )
+{
+ life->clear();
+ int i = pat % NPATS;
+ int col;
+ int * patptr = &patterns[i][0];
+ while ( (col = *patptr++) != 127 ) {
+ int row = *patptr++;
+ col += life->maxCol() / 2;
+ row += life->maxRow() / 2;
+ life->setPoint( col, row );
+ }
+}
diff --git a/examples/life/lifedlg.h b/examples/life/lifedlg.h
new file mode 100644
index 0000000..e26e6ea
--- /dev/null
+++ b/examples/life/lifedlg.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef LIFEDLG_H
+#define LIFEDLG_H
+
+#include <qtimer.h>
+#include <qwidget.h>
+
+class QSlider;
+class QPushButton;
+class QLabel;
+class QComboBox;
+
+#include "life.h"
+
+
+class LifeTimer : public QTimer
+{
+ Q_OBJECT
+public:
+ LifeTimer( QWidget *parent );
+ enum { MAXSPEED = 1000 };
+
+public slots:
+ void setSpeed( int speed );
+ void pause( bool );
+
+private:
+ int interval;
+};
+
+
+class LifeDialog : public QWidget
+{
+ Q_OBJECT
+public:
+ LifeDialog( int scale = 10, QWidget *parent = 0, const char *name = 0 );
+public slots:
+ void getPattern( int );
+
+protected:
+ virtual void resizeEvent( QResizeEvent * e );
+
+private:
+ enum { TOPBORDER = 70, SIDEBORDER = 10 };
+
+ LifeWidget *life;
+ QPushButton *qb;
+ LifeTimer *timer;
+ QPushButton *pb;
+ QComboBox *cb;
+ QLabel *sp;
+ QSlider *scroll;
+};
+
+
+#endif // LIFEDLG_H
diff --git a/examples/life/main.cpp b/examples/life/main.cpp
new file mode 100644
index 0000000..3ee785e
--- /dev/null
+++ b/examples/life/main.cpp
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include "lifedlg.h"
+#include <qapplication.h>
+#include <stdlib.h>
+
+void usage()
+{
+ qWarning( "Usage: life [-scale scale]" );
+}
+
+int main( int argc, char **argv )
+{
+ QApplication a( argc, argv );
+
+ int scale = 10;
+
+ for ( int i = 1; i < argc; i++ ){
+ QString arg = argv[i];
+ if ( arg == "-scale" )
+ scale = atoi( argv[++i] );
+ else {
+ usage();
+ exit(1);
+ }
+ }
+
+ if ( scale < 2 )
+ scale = 2;
+
+ LifeDialog *life = new LifeDialog( scale );
+ a.setMainWidget( life );
+ life->setCaption("Qt Example - Life");
+ life->show();
+
+ return a.exec();
+}
diff --git a/examples/life/patterns.cpp b/examples/life/patterns.cpp
new file mode 100644
index 0000000..01c3bc2
--- /dev/null
+++ b/examples/life/patterns.cpp
@@ -0,0 +1,383 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+/****************************************************************************
+ *
+ * Patterns for life. Adapted from xlock; original copyright notice below.
+ *
+ * Copyright (c) 1988-91 by Patrick J. Naughton.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * This file is provided AS IS with no warranties of any kind. The author
+ * shall have no liability with respect to the infringement of copyrights,
+ * trade secrets or any patents by this file or any part thereof. In no
+ * event will the author be liable for any lost revenue or profits or
+ * other special, indirect and consequential damages.
+ *****************************************************************************/
+
+//#include <qglobal.h>
+
+
+#define NUMPTS 63
+/* Patterns have < NUMPTS pts (and should have a size of <= 32x32,
+ the Gun is an exception) */
+static int patterns[][2 * NUMPTS + 1] = {
+ { /* GLIDER GUN */
+ 6, -4,
+ 5, -3, 6, -3,
+ -6, -2, -5, -2, 8, -2, 9, -2, 16, -2,
+ -7, -1, 8, -1, 9, -1, 10, -1, 16, -1, 17, -1,
+ -18, 0, -17, 0, -8, 0, 8, 0, 9, 1,
+ -17, 1, -8, 1, 5, 1, 6, 1,
+ -8, 2, 6, 2,
+ -7, 3,
+ -6, 4, -5, 4,
+ 127
+ },
+ { /* FIGURE EIGHT */
+ -3, -3, -2, -3, -1, -3,
+ -3, -2, -2, -2, -1, -2,
+ -3, -1, -2, -1, -1, -1,
+ 0, 0, 1, 0, 2, 0,
+ 0, 1, 1, 1, 2, 1,
+ 0, 2, 1, 2, 2, 2,
+ 127
+ },
+ { /* PULSAR */
+ -2, -1, -1, -1, 0, -1, 1, -1, 2, -1,
+ -2, 0, 2, 0,
+ 127
+ },
+ { /* BARBER POLE P2 */
+ -6, -6, -5, -6,
+ -6, -5, -4, -5,
+ -4, -3, -2, -3,
+ -2, -1, 0, -1,
+ 0, 1, 2, 1,
+ 2, 3, 4, 3,
+ 5, 4,
+ 4, 5, 5, 5,
+ 127
+ },
+ { /* ACHIM P5 */
+ -6, -6, -5, -6,
+ -6, -5,
+ -4, -4,
+ -4, -3, -2, -3,
+ -2, -1, 0, -1,
+ 0, 1, 2, 1,
+ 2, 3, 3, 3,
+ 5, 4,
+ 4, 5, 5, 5,
+ 127
+ },
+ { /* HERTZ P4 */
+ -2, -5, -1, -5,
+ -2, -4, -1, -4,
+ -7, -2, -6, -2, -2, -2, -1, -2, 0, -2, 1, -2, 5, -2, 6, -2,
+ -7, -1, -5, -1, -3, -1, 2, -1, 4, -1, 6, -1,
+ -5, 0, -3, 0, -2, 0, 2, 0, 4, 0,
+ -7, 1, -5, 1, -3, 1, 2, 1, 4, 1, 6, 1,
+ -7, 2, -6, 2, -2, 2, -1, 2, 0, 2, 1, 2, 5, 2, 6, 2,
+ -2, 4, -1, 4,
+ -2, 5, -1, 5,
+ 127
+ },
+ { /* TUMBLER */
+ -2, -3, -1, -3, 1, -3, 2, -3,
+ -2, -2, -1, -2, 1, -2, 2, -2,
+ -1, -1, 1, -1,
+ -3, 0, -1, 0, 1, 0, 3, 0,
+ -3, 1, -1, 1, 1, 1, 3, 1,
+ -3, 2, -2, 2, 2, 2, 3, 2,
+ 127
+ },
+ { /* PULSE1 P4*/
+ 0, -3, 1, -3,
+ -2, -2, 0, -2,
+ -3, -1, 3, -1,
+ -2, 0, 2, 0, 3, 0,
+ 0, 2, 2, 2,
+ 1, 3,
+ 127
+ },
+ { /* SHINING FLOWER P5 */
+ -1, -4, 0, -4,
+ -2, -3, 1, -3,
+ -3, -2, 2, -2,
+ -4, -1, 3, -1,
+ -4, 0, 3, 0,
+ -3, 1, 2, 1,
+ -2, 2, 1, 2,
+ -1, 3, 0, 3,
+ 127
+ },
+ { /* PULSE2 P6 */
+ 0, -4, 1, -4,
+ -4, -3, -3, -3, -1, -3,
+ -4, -2, -3, -2, 0, -2, 3, -2,
+ 1, -1, 3, -1,
+ 2, 0,
+ 1, 2, 2, 2,
+ 1, 3, 2, 3,
+ 127
+ },
+ { /* PINWHEEL, CLOCK P4 */
+ -2, -6, -1, -6,
+ -2, -5, -1, -5,
+ -2, -3, -1, -3, 0, -3, 1, -3,
+ -3, -2, -1, -2, 2, -2, 4, -2, 5, -2,
+ -3, -1, 1, -1, 2, -1, 4, -1, 5, -1,
+ -6, 0, -5, 0, -3, 0, 0, 0, 2, 0,
+ -6, 1, -5, 1, -3, 1, 2, 1,
+ -2, 2, -1, 2, 0, 2, 1, 2,
+ 0, 4, 1, 4,
+ 0, 5, 1, 5,
+ 127
+ },
+ { /* PENTADECATHOLON */
+ -5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0,
+ 127
+ },
+ { /* PISTON */
+ 1, -3, 2, -3,
+ 0, -2,
+ -10, -1, -1, -1,
+ -11, 0, -10, 0, -1, 0, 9, 0, 10, 0,
+ -1, 1, 9, 1,
+ 0, 2,
+ 1, 3, 2, 3,
+ 127
+ },
+ { /* PISTON2 */
+ -3, -5,
+ -14, -4, -13, -4, -4, -4, -3, -4, 13, -4, 14, -4,
+ -14, -3, -13, -3, -5, -3, -4, -3, 13, -3, 14, -3,
+ -4, -2, -3, -2, 0, -2, 1, -2,
+ -4, 2, -3, 2, 0, 2, 1, 2,
+ -14, 3, -13, 3, -5, 3, -4, 3, 13, 3, 14, 3,
+ -14, 4, -13, 4, -4, 4, -3, 4, 13, 4, 14, 4,
+ -3, 5,
+ 127
+ },
+ { /* SWITCH ENGINE */
+ -12, -3, -10, -3,
+ -13, -2,
+ -12, -1, -9, -1,
+ -10, 0, -9, 0, -8, 0,
+ 13, 2, 14, 2,
+ 13, 3,
+ 127
+ },
+ { /* GEARS (gear, flywheel, blinker) */
+ -1, -4,
+ -1, -3, 1, -3,
+ -3, -2,
+ 2, -1, 3, -1,
+ -4, 0, -3, 0,
+ 2, 1,
+ -2, 2, 0, 2,
+ 0, 3,
+
+ 5, 3,
+ 3, 4, 4, 4,
+ 5, 5, 6, 5,
+ 4, 6,
+
+ 8, 0,
+ 8, 1,
+ 8, 2,
+ 127
+ },
+ { /* TURBINE8 */
+ -4, -4, -3, -4, -2, -4, -1, -4, 0, -4, 1, -4, 3, -4, 4, -4,
+ -4, -3, -3, -3, -2, -3, -1, -3, 0, -3, 1, -3, 3, -3, 4, -3,
+ 3, -2, 4, -2,
+ -4, -1, -3, -1, 3, -1, 4, -1,
+ -4, 0, -3, 0, 3, 0, 4, 0,
+ -4, 1, -3, 1, 3, 1, 4, 1,
+ -4, 2, -3, 2,
+ -4, 3, -3, 3, -1, 3, 0, 3, 1, 3, 2, 3, 3, 3, 4, 3,
+ -4, 4, -3, 4, -1, 4, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4,
+ 127
+ },
+ { /* P16 */
+ -3, -6, 1, -6, 2, -6,
+ -3, -5, 0, -5, 3, -5,
+ 3, -4,
+ -5, -3, -4, -3, 1, -3, 2, -3, 5, -3, 6, -3,
+ -6, -2, -3, -2,
+ -6, -1, -3, -1,
+ -5, 0, 5, 0,
+ 3, 1, 6, 1,
+ 3, 2, 6, 2,
+ -6, 3, -5, 3, -2, 3, -1, 3, 4, 3, 5, 3,
+ -3, 4,
+ -3, 5, 0, 5, 3, 5,
+ -2, 6, -1, 6, 3, 6,
+ 127
+ },
+ { /* PUFFER */
+ 1, -9,
+ 2, -8,
+ -2, -7, 2, -7,
+ -1, -6, 0, -6, 1, -6, 2, -6,
+ -2, -2,
+ -1, -1, 0, -1,
+ 0, 0,
+ 0, 1,
+ -1, 2,
+ 1, 5,
+ 2, 6,
+ -2, 7, 2, 7,
+ -1, 8, 0, 8, 1, 8, 2, 8,
+ 127
+ },
+ { /* ESCORT */
+ 3, -8,
+ 4, -7,
+ -2, -6, 4, -6,
+ -1, -5, 0, -5, 1, -5, 2, -5, 3, -5, 4, -5,
+ -5, -1, -4, -1, -3, -1, -2, -1, -1, -1, 0, -1,
+ 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, 6, -1,
+ -6, 0, 6, 0,
+ 6, 1,
+ 5, 2,
+ 3, 4,
+ 4, 5,
+ -2, 6, 4, 6,
+ -1, 7, 0, 7, 1, 7, 2, 7, 3, 7, 4, 7,
+ 127
+ },
+ { /* DART SPEED 1/3 */
+ 3, -7,
+ 2, -6, 4, -6,
+ 1, -5, 2, -5,
+ 4, -4,
+ 0, -3, 4, -3,
+ -3, -2, 0, -2,
+ -4, -1, -2, -1, 1, -1, 2, -1, 3, -1, 4, -1,
+ -5, 0, -2, 0,
+ -4, 1, -2, 1, 1, 1, 2, 1, 3, 1, 4, 1,
+ -3, 2, 0, 2,
+ 0, 3, 4, 3,
+ 4, 4,
+ 1, 5, 2, 5,
+ 2, 6, 4, 6,
+ 3, 7,
+ 127
+ },
+ { /* PERIOD 4 SPEED 1/2 */
+ -3, -5,
+ -4, -4, -3, -4, -2, -4, -1, -4, 0, -4,
+ -5, -3, -4, -3, 0, -3, 1, -3, 3, -3,
+ -4, -2, 4, -2,
+ -3, -1, -2, -1, 1, -1, 3, -1,
+ -3, 1, -2, 1, 1, 1, 3, 1,
+ -4, 2, 4, 2,
+ -5, 3, -4, 3, 0, 3, 1, 3, 3, 3,
+ -4, 4, -3, 4, -2, 4, -1, 4, 0, 4,
+ -3, 5,
+ 127
+ },
+ { /* ANOTHER PERIOD 4 SPEED 1/2 */
+ -4, -7, -3, -7, -1, -7, 0, -7, 1, -7, 2, -7, 3, -7, 4, -7,
+ -5, -6, -4, -6, -3, -6, -2, -6, 5, -6,
+ -6, -5, -5, -5,
+ -5, -4, 5, -4,
+ -4, -3, -3, -3, -2, -3, 0, -3,
+ -2, -2,
+ -2, -1,
+ -1, 0,
+ -2, 1,
+ -2, 2,
+ -4, 3, -3, 3, -2, 3, 0, 3,
+ -5, 4, 5, 4,
+ -6, 5, -5, 5,
+ -5, 6, -4, 6, -3, 6, -2, 6, 5, 6,
+ -4, 7, -3, 7, -1, 7, 0, 7, 1, 7, 2, 7, 3, 7, 4, 7,
+ 127
+ },
+ { /* SMALLEST KNOWN PERIOD 3 SPACESHIP SPEED 1/3 */
+ 0, -8,
+ -1, -7, 1, -7,
+ -1, -6, 1, -6,
+ -1, -5,
+ -2, -3, -1, -3,
+ -1, -2, 1, -2,
+ -2, -1, 0, -1,
+ -2, 0, -1, 0, 0, 0,
+ -1, 2, 1, 2,
+ -1, 3, 0, 3,
+ 0, 4,
+ 0, 5, 2, 5,
+ 0, 6, 2, 6,
+ 1, 7,
+ 127
+ },
+ { /* TURTLE SPEED 1/3 */
+ -4, -5, -3, -5, -2, -5, 6, -5,
+ -4, -4, -3, -4, 0, -4, 2, -4, 3, -4, 5, -4, 6, -4,
+ -2, -3, -1, -3, 0, -3, 5, -3,
+ -4, -2, -1, -2, 1, -2, 5, -2,
+ -5, -1, 0, -1, 5, -1,
+ -5, 0, 0, 0, 5, 0,
+ -4, 1, -1, 1, 1, 1, 5, 1,
+ -2, 2, -1, 2, 0, 2, 5, 2,
+ -4, 3, -3, 3, 0, 3, 2, 3, 3, 3, 5, 3, 6, 3,
+ -4, 4, -3, 4, -2, 4, 6, 4,
+ 127
+ },
+ { /* SMALLEST KNOWN PERIOD 5 SPEED 2/5 */
+ 1, -7, 3, -7,
+ -2, -6, 3, -6,
+ -3, -5, -2, -5, -1, -5, 4, -5,
+ -4, -4, -2, -4,
+ -5, -3, -4, -3, -1, -3, 0, -3, 5, -3,
+ -4, -2, -3, -2, 0, -2, 1, -2, 2, -2, 3, -2, 4, -2,
+ -4, 2, -3, 2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2,
+ -5, 3, -4, 3, -1, 3, 0, 3, 5, 3,
+ -4, 4, -2, 4,
+ -3, 5, -2, 5, -1, 5, 4, 5,
+ -2, 6, 3, 6,
+ 1, 7, 3, 7,
+ 127
+ },
+ { /* SYM PUFFER */
+ 1, -4, 2, -4, 3, -4, 4, -4,
+ 0, -3, 4, -3,
+ 4, -2,
+ -4, -1, -3, -1, 0, -1, 3, -1,
+ -4, 0, -3, 0, -2, 0,
+ -4, 1, -3, 1, 0, 1, 3, 1,
+ 4, 2,
+ 0, 3, 4, 3,
+ 1, 4, 2, 4, 3, 4, 4, 4,
+ 127
+ },
+ { /* ], NEAR SHIP, PI HEPTOMINO */
+ -2, -1, -1, -1, 0, -1,
+ 1, 0,
+ -2, 1, -1, 1, 0, 1,
+ 127
+ },
+ { /* R PENTOMINO */
+ 0, -1, 1, -1,
+ -1, 0, 0, 0,
+ 0, 1,
+ 127
+ }
+};
+
+#define NPATS (sizeof patterns / sizeof patterns[0])