Read-only archive of the Armageddon Games Forums Archive (2000–2026) · About this archive

15 Puzzle

7 replies · 4,847 views · Started 05 December 2009

This forum is a little sluggish now-a-days so I thought I'd liven it up a bit with a little 15 puzzle I cooked up. 😊

Video: http://www.youtube.com/watch?v=9Xe8DCWKXO4

EDIT: bug fixed.

Unfortunately there's one minor bug to fix before uploading a quest file. Plus I'd much like to draw some better graphics and scale them to fit in the screen better to boot. ( I gladly accept sprite donations! 😛 ..well it's only 15 tiles worth after all, if someone has an inkling for it.)

Since there's no quest file yet I guess I'll post the script as per the norm.

const int PIECE_TILE = 100;

int piece[16];
int selected;
int pm_dir;

ffc script Puzzle15
{
void run()
{
Init15();
while( true )
{
Waitframe();

doControls15();
KeepTime();

RenderBoard15();
if( IsComplete15() )
{
Init15();
}
}
}
}

void MoveSelected15( int dir )
{
if( dir == 0 )
if( selected - 4 < 0 ) selected += 12;
else selected -= 4;
if( dir == 1 )
if( selected + 4 > 15 ) selected -= 12;
else selected += 4;
if( dir == 2 )
if( selected % 4 == 0 ) selected += 3;
else selected -= 1;
if( dir == 3 )
if( selected == 15 || selected == 11 || selected == 7 || selected == 3) selected -= 3;
else selected += 1;
}

void doControls15()
{
if( !paused )
{
if( Link->getPressUp() ) MoveSelected15( 0 );
if( Link->getPressDown() ) MoveSelected15( 1 );
if( Link->getPressLeft() ) MoveSelected15( 2 );
if( Link->getPressRight() ) MoveSelected15( 3 );
if( Link->getPressA() ) MovePiece15();
}

if( Link->getPressStart() )
{
paused = !paused;
}

Link->InputStart = false;
Link->InputUp = false;
Link->InputDown = false;
Link->InputLeft = false;
Link->InputRight = false;

Link->X = 16;
Link->Y = 16;
}

void Init15()
{
InitClock();

piece[15] = 0;
for( int i = 0; i < 15; i++ )
piece[i] = i + 1;

selected = 0;
int loop = 0;
while( loop < 15000 )
{
loop = Randomize15( loop );
}
}

int Randomize15( int loop )
{
int r;
if( piece[0] == 0 ) r = 1 << ( Rand(2) * 2 );
else if( piece[3] == 0 ) r = 2 + ( Rand(2) * 5 );
else if( piece[12] == 0 ) r = 8 + ( Rand(2) * 5 );
else if( piece[15] == 0 ) r = 11 + ( Rand(2) * 3 );
else r = Rand(16);

int v = Move15( r, 1, 4 );
if ( v != -1 && IsInRow15( r, v ) )
{
Swap15( r, v );
}

return loop + 1;
}

void InitClock()
{
global_timer = 0;
seconds = 0;
minutes = 0;
}

int Move15( int i, int x, int y )
{
if( i - x >= 0 )
if( piece[ i - x ] == 0 )
{
pm_dir = 2;
return i - x;
}
if( i + x < 16 )
if( piece[ i + x ] == 0 )
{
pm_dir = 3;
return i + x;
}
if( i - y >= 0 )
if( piece[ i - y ] == 0 )
{
pm_dir = 0;
return i - y;
}
if( i + y < 16 )
if( piece[ i + y ] == 0 )
{
pm_dir = 1;
return i + y;
}
return -1;
}

int Swap15( int p1, int p2 )
{
int tmp = piece[ p1 ];
piece[ p1 ] = piece[ p2 ];
piece[ p2 ] = tmp;
}

bool IsInRow15( int source, int n )
{
if( source < 4 )
{
if( pm_dir > 1 ) return ( n < 4 );
else return ( ( n % 4 ) == source );
}
else if( source < 8 )
{
if( pm_dir > 1 ) return ( n > 3 && n < 8 );
else return ( ( n % 4 ) == ( source - 4 ) );
}
else if( source < 12 )
{
if( pm_dir > 1 ) return ( n > 7 && n < 12 );
else return ( ( n % 4 ) == ( source - 8 ) );
}
else
{
if( pm_dir > 1 ) return ( n > 11 );
else return ( ( n % 4 ) == ( source - 12 ) );
}
return false;
}

void MovePiece15()
{
int v = Move15( selected, 1, 4 );
if ( v != -1 && IsInRow15( selected, v ) )
{
Swap15( selected, v );
return;
}
// No good? Let's try and move up to a whole row then.
v = Move15( selected, 2, 8 );
if ( v != -1 && IsInRow15( selected, v ) )
{
if( pm_dir == 0 ) Swap15( selected - 4, v );
else if( pm_dir == 1 ) Swap15( selected + 4, v );
else if( pm_dir == 2 ) Swap15( selected - 1, v );
else if( pm_dir == 3 ) Swap15( selected + 1, v );
MovePiece15();
return;
}
v = Move15( selected, 3, 12 );
if ( v != -1 && IsInRow15( selected, v ) )
{
if( pm_dir == 0 ) Swap15( selected - 8, v );
else if( pm_dir == 1 ) Swap15( selected + 8, v );
else if( pm_dir == 2 ) Swap15( selected - 2, v );
else if( pm_dir == 3 ) Swap15( selected + 2, v );
MovePiece15();
return;
}
}

int PieceElement( int row, int column )
{
return ( row + ( column * 4 ) );
}

bool IsComplete15()
{
int complete = 0;
if( piece[15] == 0 )
{
for( int j; j < 15; j++ )
if( piece[j] == j + 1 )
complete++;
}
return ( complete == 15 );
}

int getY15( int i )
{
if( i < 4 ) return 0;
else if( i < 8 ) return 1;
else if( i < 12 ) return 2;
return 3;
}

void RenderBoard15()
{
int x_off = 64;
int y_off = 32;

// Draw the border
Screen->Rectangle( 5, x_off-1, y_off-1, x_off + 65, y_off + 65, 15, 1, 0, 0, 0, false, 128 );

for( int i = 0; i < 4; i++ )
for( int j = 0; j < 4; j++ )
Screen->DrawTile( 5, ( i * 16 ) + x_off, ( j * 16 ) + y_off,
PIECE_TILE + piece[ PieceElement( i, j ) ],
1, 1, 0, -1, -1, 0, 0, 0, 0, true, 128 );
// Draw the cursor
Screen->Rectangle( 6, x_off + (( selected % 4 ) * 16), y_off + ( getY15( selected ) * 16 ),
16 + x_off + (( selected % 4 ) * 16), 16 + y_off + ( getY15( selected ) * 16 ),
15, 1, 0, 0, 0, true, 64 );

// Draw the timer
int str[1] = ":";
if( minutes < 10 )
{
Screen->DrawInteger( 6, x_off, 8, 0, 10, 1, -1, -1, 0, 0, 128 );
Screen->DrawInteger( 6, x_off + 8 , 8, 0, 15, 1, -1, -1, minutes, 0, 128 );
}
else Screen->DrawInteger( 6, x_off, 8, 0, 15, 1, -1, -1, minutes, 0, 128 );
if( seconds < 10 )
{
Screen->DrawInteger( 6, x_off + 20, 8, 0, 10, 1, -1, -1, 0, 0, 128 );
Screen->DrawInteger( 6, x_off + 28, 8, 0, 15, 1, -1, -1, seconds, 0, 128 );
}
else Screen->DrawInteger( 6, x_off + 20, 8, 0, 15, 1, -1, -1, seconds, 0, 128 );
if( ( global_timer % 60 ) < 10 )
{
Screen->DrawInteger( 6, x_off + 40, 8, 0, 15, 1, -1, -1, 0, 0, 128 );
Screen->DrawInteger( 6, x_off + 48, 8, 0, 15, 1, -1, -1, global_timer * 1.6, 0, 128 );
}
else Screen->DrawInteger( 6, x_off + 40, 8, 0, 15, 1, -1, -1, global_timer * 1.6, 0, 128 );

Screen->DrawCharacter( 6, x_off + 14, 8, 0, 12, -1, -1, -1, str[0], 64 );
Screen->DrawCharacter( 6, x_off + 35, 8, 0, 12, -1, -1, -1, str[0], 64 );
}

void KeepTime()
{
if( paused ) return;

global_timer++;
if( global_timer >= 60 )
{
seconds++;
global_timer -= 60;
if( seconds >= 60 )
{
minutes++;
seconds -= 60;
}
}
}

edit: what's with the code tags!?

Yep, although I don't think 15 puzzle gets many people exited. I pretty much got bored and wondered how long it would take to script it.

Uses:

- You could have it trigger if link is in water while holding select and presses the B button 20 times.
- Master using it and you can have this?
- As punishment for dying.

Anyway I edited the script. All the parts are there now and it works as it should.

So, you could easily replace the numbers with an image right? This might be fun to try to implement into a quest for a side-quest for a heart piece or something.