Files
android_app/compiler/compiler.cpp
2013-04-21 23:46:09 +04:00

215 lines
3.6 KiB
C++

#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <list>
#include <string>
#include <functional>
//
// Describes one single puzzle.
//
class puzzle
{
protected:
int width;
int height;
typedef std::vector<char> content_type;
content_type content;
enum symbols {
empty = 0,
wall,
box,
hole,
box_in_hole,
worker
};
public:
puzzle()
: width(0)
, height(0)
{}
void load( const std::string& name )
{
std::cout << "Loading " << name << "..." << std::flush;
std::ifstream is( name );
std::stringstream ss;
//
// Read line by line and calculate width and hight.
//
std::string line;
while ( std::getline( is, line ) )
{
ss << line << std::endl;
width = std::max( width, (int)line.length() );
++height;
}
//
// Encode puzzle.
//
std::cout << "encoding..." << std::flush;
content.resize(width*height);
content_type::iterator it = content.begin();
while ( std::getline( ss, line ) )
{
for ( char c : line )
{
switch ( c )
{
case ' ':
*it++ = empty;
break;
case '#':
*it++ = wall;
break;
case '$':
*it++ = box;
break;
case '.':
*it++ = hole;
break;
case '*':
*it++ = box_in_hole;
break;
case '@':
*it++ = worker;
break;
default:
throw std::runtime_error(
std::string("Unexpected symbol '" )+c+"' found." );
}
}
for ( int i=0; i < width - line.length(); ++i)
*it++ = empty;
}
std::cout << "done" << std::endl;
}
int size()
{
return 2+width*height;
}
void encode( std::ostream& os )
{
if ( width > height )
encode_as_is(os);
else
encode_rotated(os);
}
private:
void encode_as_is( std::ostream& os )
{
os << (char)width;
os << (char)height;
for ( char c : content )
os << c;
}
void encode_rotated( std::ostream& os )
{
std::cout << "rotating." << std::endl;
os << (char)height;
os << (char)width;
for ( int i = 0; i < width; ++i )
for ( int j = 0; j < height; ++j )
os << content[ j*width+i ];
}
};
//
// Describes catalog of puzzles.
//
class catalog
{
protected:
typedef std::list<puzzle*> puzzles_type;
puzzles_type puzzles;
typedef int i32;
typedef i32 offset_type;
typedef i32 count_type;
public:
void push( puzzle * p )
{
puzzles.push_back( p );
}
void compile( std::ostream& os )
{
std::cout << "Compiling." << std::endl;
encode( os,(count_type)puzzles.size());
offset_type bgn = sizeof(count_type)+puzzles.size()*sizeof(offset_type);
std::cout << "Table ... ";
for ( puzzle * p : puzzles )
{
encode(os,bgn);
bgn += p->size();
}
std::cout << "done." << std::endl;
std::cout << "Puzzles...";
for ( puzzle * p : puzzles )
{
p->encode(os);
}
std::cout << "done." << std::endl;
}
protected:
template <class I>
void encode( std::ostream& os, I i)
{
if ( sizeof(i) == 1 )
os << (char)i;
else if ( sizeof(i) == 2 )
{
os << (char)(i&0xff);
os << (char)(i>>8&0xff);
}
else if ( sizeof(i) == 4 )
{
os << (char)(i&0xff);
os << (char)(i>>8&0xff);
os << (char)(i>>16&0xff);
os << (char)(i>>24&0xff);
}
}
};
int main( void )
try
{
catalog c;
for ( int i = 1; i <= 90; ++i )
{
std::stringstream ss;
ss << "screen_" << i << ".sokoban";
puzzle * p = new puzzle;
p->load( ss.str());
c.push( p );
}
std::ofstream os( "puzzles.bin", std::ios::binary );
c.compile( os );
return 0;
}
catch ( const std::exception& e )
{
std::cout << "std::exception: " << e.what() << std::endl;
}
catch ( ... )
{
std::cout << "unknown exception." << std::endl;
}