Initial check in.
This commit is contained in:
214
compiler/compiler.cpp
Normal file
214
compiler/compiler.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user