├── .gitignore ├── res ├── btn.bmp ├── blue.bmp ├── click.wav ├── laser.wav ├── nova.bmp ├── nova.ttf ├── rain.bmp ├── tile.bmp ├── title.bmp ├── whizz.wav ├── applause.wav ├── betwarr.bmp ├── closed.bmp ├── cursor.bmp ├── glasbk2.wav ├── large-A1.bmp ├── large-A2.bmp ├── large-A3.bmp ├── large-A4.bmp ├── large-A5.bmp ├── large-A6.bmp ├── large-B1.bmp ├── large-B2.bmp ├── large-B3.bmp ├── large-B4.bmp ├── large-B5.bmp ├── large-B6.bmp ├── large-C1.bmp ├── large-C2.bmp ├── large-C3.bmp ├── large-C4.bmp ├── large-C5.bmp ├── large-C6.bmp ├── large-D1.bmp ├── large-D2.bmp ├── large-D3.bmp ├── large-D4.bmp ├── large-D5.bmp ├── large-D6.bmp ├── large-E1.bmp ├── large-E2.bmp ├── large-E3.bmp ├── large-E4.bmp ├── large-E5.bmp ├── large-E6.bmp ├── large-F1.bmp ├── large-F2.bmp ├── large-F3.bmp ├── large-F4.bmp ├── large-F5.bmp ├── large-F6.bmp ├── laudcn2.ttf ├── luximb.ttf ├── marble1.bmp ├── small-a1.bmp ├── small-a2.bmp ├── small-a3.bmp ├── small-a4.bmp ├── small-a5.bmp ├── small-a6.bmp ├── small-b1.bmp ├── small-b2.bmp ├── small-b3.bmp ├── small-b4.bmp ├── small-b5.bmp ├── small-b6.bmp ├── small-c1.bmp ├── small-c2.bmp ├── small-c3.bmp ├── small-c4.bmp ├── small-c5.bmp ├── small-c6.bmp ├── small-d1.bmp ├── small-d2.bmp ├── small-d3.bmp ├── small-d4.bmp ├── small-d5.bmp ├── small-d6.bmp ├── small-e1.bmp ├── small-e2.bmp ├── small-e3.bmp ├── small-e4.bmp ├── small-e5.bmp ├── small-e6.bmp ├── small-f1.bmp ├── small-f2.bmp ├── small-f3.bmp ├── small-f4.bmp ├── small-f5.bmp ├── small-f6.bmp ├── verthint.bmp ├── flatokbtn.bmp ├── hint-near.bmp ├── hint-side.bmp ├── hint-tile.bmp ├── horposhint.bmp ├── opensquare.bmp ├── redpattern.bmp ├── darkpattern.bmp ├── greenpattern.bmp ├── hornearhint.bmp ├── build.sh ├── horbetweenhint.bmp ├── messages.txt ├── messages_ru.txt ├── rules.txt ├── rules_ru.txt └── resources.descr ├── einstein.res ├── README ├── descr.h ├── options.h ├── opensave.h ├── main.h ├── visitor.h ├── mkres ├── msgformatter.h ├── msgformatter.cpp ├── format.cpp ├── format.h ├── exceptions.h ├── Makefile ├── streams.h ├── messages.h ├── convert.h ├── unicode.h ├── streams.cpp ├── convert.cpp ├── lexal.h ├── compressor.h ├── buffer.cpp ├── buffer.h ├── table.h ├── main.cpp ├── compressor.cpp ├── lexal.cpp └── messages.cpp ├── exceptions.h ├── sound.h ├── storage.h ├── README.md ├── tablestorage.h ├── regstorage.h ├── storage.cpp ├── font.h ├── topscores.h ├── streams.h ├── iconset.h ├── horhints.h ├── verthints.h ├── random.h ├── tokenizer.h ├── puzzle.h ├── tablestorage.cpp ├── convert.h ├── formatter.h ├── game.h ├── unicode.h ├── streams.cpp ├── sound.cpp ├── convert.cpp ├── i18n.h ├── utils.h ├── lexal.h ├── messages.h ├── Makefile.win ├── tokenizer.cpp ├── iconset.cpp ├── screen.h ├── puzgen.h ├── buffer.cpp ├── Makefile.macosx ├── Makefile ├── buffer.h ├── table.h ├── main.cpp ├── main.cpp.orig ├── options.cpp ├── font.cpp ├── conf.h ├── messages.cpp ├── regstorage.cpp ├── verthints.cpp ├── random.cpp ├── topscores.cpp ├── formatter.cpp ├── horhints.cpp ├── puzzle.cpp ├── menu.cpp └── lexal.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | einstein 3 | mkres/*.o 4 | mkres/mkres 5 | 6 | -------------------------------------------------------------------------------- /res/btn.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/btn.bmp -------------------------------------------------------------------------------- /einstein.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/einstein.res -------------------------------------------------------------------------------- /res/blue.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/blue.bmp -------------------------------------------------------------------------------- /res/click.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/click.wav -------------------------------------------------------------------------------- /res/laser.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/laser.wav -------------------------------------------------------------------------------- /res/nova.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/nova.bmp -------------------------------------------------------------------------------- /res/nova.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/nova.ttf -------------------------------------------------------------------------------- /res/rain.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/rain.bmp -------------------------------------------------------------------------------- /res/tile.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/tile.bmp -------------------------------------------------------------------------------- /res/title.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/title.bmp -------------------------------------------------------------------------------- /res/whizz.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/whizz.wav -------------------------------------------------------------------------------- /res/applause.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/applause.wav -------------------------------------------------------------------------------- /res/betwarr.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/betwarr.bmp -------------------------------------------------------------------------------- /res/closed.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/closed.bmp -------------------------------------------------------------------------------- /res/cursor.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/cursor.bmp -------------------------------------------------------------------------------- /res/glasbk2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/glasbk2.wav -------------------------------------------------------------------------------- /res/large-A1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-A1.bmp -------------------------------------------------------------------------------- /res/large-A2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-A2.bmp -------------------------------------------------------------------------------- /res/large-A3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-A3.bmp -------------------------------------------------------------------------------- /res/large-A4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-A4.bmp -------------------------------------------------------------------------------- /res/large-A5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-A5.bmp -------------------------------------------------------------------------------- /res/large-A6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-A6.bmp -------------------------------------------------------------------------------- /res/large-B1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-B1.bmp -------------------------------------------------------------------------------- /res/large-B2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-B2.bmp -------------------------------------------------------------------------------- /res/large-B3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-B3.bmp -------------------------------------------------------------------------------- /res/large-B4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-B4.bmp -------------------------------------------------------------------------------- /res/large-B5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-B5.bmp -------------------------------------------------------------------------------- /res/large-B6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-B6.bmp -------------------------------------------------------------------------------- /res/large-C1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-C1.bmp -------------------------------------------------------------------------------- /res/large-C2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-C2.bmp -------------------------------------------------------------------------------- /res/large-C3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-C3.bmp -------------------------------------------------------------------------------- /res/large-C4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-C4.bmp -------------------------------------------------------------------------------- /res/large-C5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-C5.bmp -------------------------------------------------------------------------------- /res/large-C6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-C6.bmp -------------------------------------------------------------------------------- /res/large-D1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-D1.bmp -------------------------------------------------------------------------------- /res/large-D2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-D2.bmp -------------------------------------------------------------------------------- /res/large-D3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-D3.bmp -------------------------------------------------------------------------------- /res/large-D4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-D4.bmp -------------------------------------------------------------------------------- /res/large-D5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-D5.bmp -------------------------------------------------------------------------------- /res/large-D6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-D6.bmp -------------------------------------------------------------------------------- /res/large-E1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-E1.bmp -------------------------------------------------------------------------------- /res/large-E2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-E2.bmp -------------------------------------------------------------------------------- /res/large-E3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-E3.bmp -------------------------------------------------------------------------------- /res/large-E4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-E4.bmp -------------------------------------------------------------------------------- /res/large-E5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-E5.bmp -------------------------------------------------------------------------------- /res/large-E6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-E6.bmp -------------------------------------------------------------------------------- /res/large-F1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-F1.bmp -------------------------------------------------------------------------------- /res/large-F2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-F2.bmp -------------------------------------------------------------------------------- /res/large-F3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-F3.bmp -------------------------------------------------------------------------------- /res/large-F4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-F4.bmp -------------------------------------------------------------------------------- /res/large-F5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-F5.bmp -------------------------------------------------------------------------------- /res/large-F6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/large-F6.bmp -------------------------------------------------------------------------------- /res/laudcn2.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/laudcn2.ttf -------------------------------------------------------------------------------- /res/luximb.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/luximb.ttf -------------------------------------------------------------------------------- /res/marble1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/marble1.bmp -------------------------------------------------------------------------------- /res/small-a1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-a1.bmp -------------------------------------------------------------------------------- /res/small-a2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-a2.bmp -------------------------------------------------------------------------------- /res/small-a3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-a3.bmp -------------------------------------------------------------------------------- /res/small-a4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-a4.bmp -------------------------------------------------------------------------------- /res/small-a5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-a5.bmp -------------------------------------------------------------------------------- /res/small-a6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-a6.bmp -------------------------------------------------------------------------------- /res/small-b1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-b1.bmp -------------------------------------------------------------------------------- /res/small-b2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-b2.bmp -------------------------------------------------------------------------------- /res/small-b3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-b3.bmp -------------------------------------------------------------------------------- /res/small-b4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-b4.bmp -------------------------------------------------------------------------------- /res/small-b5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-b5.bmp -------------------------------------------------------------------------------- /res/small-b6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-b6.bmp -------------------------------------------------------------------------------- /res/small-c1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-c1.bmp -------------------------------------------------------------------------------- /res/small-c2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-c2.bmp -------------------------------------------------------------------------------- /res/small-c3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-c3.bmp -------------------------------------------------------------------------------- /res/small-c4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-c4.bmp -------------------------------------------------------------------------------- /res/small-c5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-c5.bmp -------------------------------------------------------------------------------- /res/small-c6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-c6.bmp -------------------------------------------------------------------------------- /res/small-d1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-d1.bmp -------------------------------------------------------------------------------- /res/small-d2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-d2.bmp -------------------------------------------------------------------------------- /res/small-d3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-d3.bmp -------------------------------------------------------------------------------- /res/small-d4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-d4.bmp -------------------------------------------------------------------------------- /res/small-d5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-d5.bmp -------------------------------------------------------------------------------- /res/small-d6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-d6.bmp -------------------------------------------------------------------------------- /res/small-e1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-e1.bmp -------------------------------------------------------------------------------- /res/small-e2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-e2.bmp -------------------------------------------------------------------------------- /res/small-e3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-e3.bmp -------------------------------------------------------------------------------- /res/small-e4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-e4.bmp -------------------------------------------------------------------------------- /res/small-e5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-e5.bmp -------------------------------------------------------------------------------- /res/small-e6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-e6.bmp -------------------------------------------------------------------------------- /res/small-f1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-f1.bmp -------------------------------------------------------------------------------- /res/small-f2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-f2.bmp -------------------------------------------------------------------------------- /res/small-f3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-f3.bmp -------------------------------------------------------------------------------- /res/small-f4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-f4.bmp -------------------------------------------------------------------------------- /res/small-f5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-f5.bmp -------------------------------------------------------------------------------- /res/small-f6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/small-f6.bmp -------------------------------------------------------------------------------- /res/verthint.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/verthint.bmp -------------------------------------------------------------------------------- /res/flatokbtn.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/flatokbtn.bmp -------------------------------------------------------------------------------- /res/hint-near.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/hint-near.bmp -------------------------------------------------------------------------------- /res/hint-side.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/hint-side.bmp -------------------------------------------------------------------------------- /res/hint-tile.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/hint-tile.bmp -------------------------------------------------------------------------------- /res/horposhint.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/horposhint.bmp -------------------------------------------------------------------------------- /res/opensquare.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/opensquare.bmp -------------------------------------------------------------------------------- /res/redpattern.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/redpattern.bmp -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | To build and install einstein edit Makefile and run `make install` as root. 3 | 4 | -------------------------------------------------------------------------------- /res/darkpattern.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/darkpattern.bmp -------------------------------------------------------------------------------- /res/greenpattern.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/greenpattern.bmp -------------------------------------------------------------------------------- /res/hornearhint.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/hornearhint.bmp -------------------------------------------------------------------------------- /res/build.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | ../mkres/mkres --source resources.descr --output einstein.res 4 | 5 | -------------------------------------------------------------------------------- /res/horbetweenhint.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lksj/einstein-puzzle/HEAD/res/horbetweenhint.bmp -------------------------------------------------------------------------------- /descr.h: -------------------------------------------------------------------------------- 1 | #ifndef __DESCR_H__ 2 | #define __DESCR_H__ 3 | 4 | 5 | #include "widgets.h" 6 | 7 | 8 | void showDescription(Area *parentArea); 9 | 10 | 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /options.h: -------------------------------------------------------------------------------- 1 | #ifndef __OPTIONS_H__ 2 | #define __OPTIONS_H__ 3 | 4 | 5 | #include "widgets.h" 6 | 7 | 8 | 9 | void showOptionsWindow(Area *area); 10 | 11 | 12 | #endif 13 | 14 | -------------------------------------------------------------------------------- /opensave.h: -------------------------------------------------------------------------------- 1 | #ifndef __OPENSAVE_H__ 2 | #define __OPENSAVE_H__ 3 | 4 | 5 | #include "widgets.h" 6 | #include "game.h" 7 | 8 | 9 | 10 | bool saveGame(Area *parentArea, Game *game); 11 | Game* loadGame(Area *parentArea); 12 | 13 | 14 | 15 | #endif 16 | 17 | -------------------------------------------------------------------------------- /main.h: -------------------------------------------------------------------------------- 1 | #ifndef __MAIN_H__ 2 | #define __MAIN_H__ 3 | 4 | #include "exceptions.h" 5 | #include "screen.h" 6 | #include "resources.h" 7 | #include "random.h" 8 | 9 | 10 | extern Screen screen; 11 | extern Random rndGen; 12 | 13 | void menu(); 14 | 15 | #endif 16 | 17 | -------------------------------------------------------------------------------- /visitor.h: -------------------------------------------------------------------------------- 1 | #ifndef __VISITOR_H__ 2 | #define __VISITOR_H__ 3 | 4 | 5 | /// Abstract visitor 6 | template 7 | class Visitor 8 | { 9 | public: 10 | virtual ~Visitor() { }; 11 | 12 | /// Called at every visit 13 | virtual void onVisit(T &t) = 0; 14 | }; 15 | 16 | 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /mkres/msgformatter.h: -------------------------------------------------------------------------------- 1 | #ifndef __MSG_FORMATTER_H__ 2 | #define __MSG_FORMATTER_H__ 3 | 4 | 5 | #include "format.h" 6 | 7 | 8 | class MsgFormatter: public Formatter 9 | { 10 | public: 11 | MsgFormatter(); 12 | virtual void format(const std::wstring &fileName, Buffer &output); 13 | }; 14 | 15 | 16 | #endif 17 | 18 | -------------------------------------------------------------------------------- /mkres/msgformatter.cpp: -------------------------------------------------------------------------------- 1 | #include "msgformatter.h" 2 | #include "table.h" 3 | #include "unicode.h" 4 | #include "messages.h" 5 | 6 | 7 | MsgFormatter::MsgFormatter() 8 | { 9 | } 10 | 11 | void MsgFormatter::format(const std::wstring &fileName, Buffer &output) 12 | { 13 | Table table(toMbcs(fileName)); 14 | Messages msg; 15 | for (Table::Iterator i = table.begin(); i != table.end(); i++) { 16 | msg.add((*i).first, (*i).second->asString()); 17 | } 18 | msg.save(output); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /exceptions.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXCEPTIONS_H__ 2 | #define __EXCEPTIONS_H__ 3 | 4 | 5 | #include 6 | #include 7 | 8 | 9 | class Exception 10 | { 11 | private: 12 | std::wstring message; 13 | 14 | public: 15 | Exception(const std::wstring& msg) { message = msg; /*std::cout << msg << std::endl;*/ }; 16 | virtual ~Exception() { }; 17 | 18 | public: 19 | const std::wstring& getMessage() const { return message; }; 20 | }; 21 | 22 | 23 | #endif 24 | 25 | -------------------------------------------------------------------------------- /mkres/format.cpp: -------------------------------------------------------------------------------- 1 | #include "format.h" 2 | #include "msgformatter.h" 3 | 4 | 5 | FormatRegistry formatRegistry; 6 | 7 | 8 | FormatRegistry::FormatRegistry() 9 | { 10 | formatters[L"messages"] = new MsgFormatter(); 11 | } 12 | 13 | 14 | FormatRegistry::~FormatRegistry() 15 | { 16 | for (FormattersMap::iterator i = formatters.begin(); 17 | i != formatters.end(); i++) 18 | delete (*i).second; 19 | } 20 | 21 | 22 | Formatter* FormatRegistry::get(const std::wstring &name) 23 | { 24 | return formatters[name]; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /sound.h: -------------------------------------------------------------------------------- 1 | #ifndef __SOUND_H__ 2 | #define __SOUND_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | class Sound 11 | { 12 | private: 13 | bool disabled; 14 | 15 | typedef std::map ChunkMap; 16 | ChunkMap chunkCache; 17 | 18 | bool enableFx; 19 | float volume; 20 | 21 | public: 22 | Sound(); 23 | ~Sound(); 24 | 25 | public: 26 | void play(const std::wstring &name); 27 | void setVolume(float volume); 28 | }; 29 | 30 | 31 | extern Sound *sound; 32 | 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /storage.h: -------------------------------------------------------------------------------- 1 | #ifndef __STORAGE_H__ 2 | #define __STORAGE_H__ 3 | 4 | 5 | #include 6 | 7 | 8 | class Storage 9 | { 10 | public: 11 | virtual ~Storage() { }; 12 | 13 | public: 14 | virtual int get(const std::wstring &name, int dflt) = 0; 15 | virtual std::wstring get(const std::wstring &name, 16 | const std::wstring &dflt) = 0; 17 | virtual void set(const std::wstring &name, int value) = 0; 18 | virtual void set(const std::wstring &name, const std::wstring &value) = 0; 19 | virtual void flush() = 0; 20 | }; 21 | 22 | 23 | Storage* getStorage(); 24 | 25 | 26 | #endif 27 | 28 | -------------------------------------------------------------------------------- /mkres/format.h: -------------------------------------------------------------------------------- 1 | #ifndef __FORMAT_H__ 2 | #define __FORMAT_H__ 3 | 4 | 5 | #include 6 | #include "buffer.h" 7 | 8 | 9 | class Formatter 10 | { 11 | public: 12 | virtual ~Formatter() { }; 13 | virtual void format(const std::wstring &fileName, Buffer &output) = 0; 14 | }; 15 | 16 | 17 | class FormatRegistry 18 | { 19 | private: 20 | typedef std::map FormattersMap; 21 | FormattersMap formatters; 22 | 23 | public: 24 | FormatRegistry(); 25 | ~FormatRegistry(); 26 | 27 | public: 28 | Formatter* get(const std::wstring &name); 29 | }; 30 | 31 | 32 | extern FormatRegistry formatRegistry; 33 | 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # einstein-puzzle 2 | Einstein puzzle is a free cross-platform open source remake of old DOS game Sherlock which was inspired by Albert Einstein's puzzle. Einstein said that only those with an intelligence quotient of 98 percentile and higher should be able to solve it. The game goal is to open all cards in square of 6x6 cards. For this, a number of hints describing relations between card positions are given. Use them to find the correct layout. Einstein 2.0 features sound support, full internalization, Russian localization, reengineered resource subsystem to allow custom graphics themes and in-game rules browser. Previously, the project was located on http://games.flowix.com/en/index.html Now this resource available only through http://web.archive.org 3 | -------------------------------------------------------------------------------- /tablestorage.h: -------------------------------------------------------------------------------- 1 | #ifndef __TABLESTORAGE_H__ 2 | #define __TABLESTORAGE_H__ 3 | 4 | 5 | #include "storage.h" 6 | #include "table.h" 7 | 8 | 9 | class TableStorage: public Storage 10 | { 11 | private: 12 | Table table; 13 | 14 | public: 15 | TableStorage(); 16 | virtual ~TableStorage(); 17 | 18 | public: 19 | virtual int get(const std::wstring &name, int dflt); 20 | virtual std::wstring get(const std::wstring &name, 21 | const std::wstring &dflt); 22 | virtual void set(const std::wstring &name, int value); 23 | virtual void set(const std::wstring &name, const std::wstring &value); 24 | virtual void flush(); 25 | 26 | private: 27 | std::wstring getFileName(); 28 | }; 29 | 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /mkres/exceptions.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXCEPTIONS_H__ 2 | #define __EXCEPTIONS_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | /// Basic exception class 11 | class Exception: public std::exception 12 | { 13 | private: 14 | std::wstring message; 15 | 16 | public: 17 | /// Create exception 18 | /// \param msg message text 19 | Exception(const std::wstring& msg) throw() { message = msg; }; 20 | virtual ~Exception() throw() { }; 21 | 22 | public: 23 | /// Get error message. 24 | virtual const std::wstring& getMessage() const throw() { return message; }; 25 | 26 | /// Inherited way of receiving error messags 27 | virtual const char* what() const throw() { return "Exception"; }; 28 | }; 29 | 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /regstorage.h: -------------------------------------------------------------------------------- 1 | #ifndef __REGSTORAGE_H__ 2 | #define __REGSTORAGE_H__ 3 | #ifdef WIN32 // Win32 only 4 | 5 | 6 | #include 7 | #include "storage.h" 8 | 9 | 10 | class RegistryStorage: public Storage 11 | { 12 | private: 13 | HKEY globalKey; 14 | HKEY userKey; 15 | 16 | public: 17 | RegistryStorage(); 18 | virtual ~RegistryStorage(); 19 | 20 | public: 21 | virtual int get(const std::wstring &name, int dflt) ; 22 | virtual std::wstring get(const std::wstring &name, 23 | const std::wstring &dflt); 24 | virtual void set(const std::wstring &name, int value); 25 | virtual void set(const std::wstring &name, const std::wstring &value); 26 | virtual void flush() { }; 27 | }; 28 | 29 | 30 | #endif 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /storage.cpp: -------------------------------------------------------------------------------- 1 | #include "storage.h" 2 | 3 | #ifndef WIN32 4 | #include "tablestorage.h" 5 | #else 6 | #include "regstorage.h" 7 | #endif 8 | 9 | 10 | class StorageHolder 11 | { 12 | private: 13 | Storage *storage; 14 | 15 | public: 16 | StorageHolder(); 17 | ~StorageHolder(); 18 | 19 | public: 20 | Storage* getStorage() { return storage; }; 21 | }; 22 | 23 | 24 | StorageHolder::StorageHolder() 25 | { 26 | #ifndef WIN32 27 | storage = new TableStorage(); 28 | #else 29 | storage = new RegistryStorage(); 30 | #endif 31 | } 32 | 33 | 34 | StorageHolder::~StorageHolder() 35 | { 36 | if (storage) 37 | delete storage; 38 | } 39 | 40 | 41 | static StorageHolder storageHolder; 42 | 43 | 44 | Storage* getStorage() 45 | { 46 | return storageHolder.getStorage(); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /font.h: -------------------------------------------------------------------------------- 1 | #ifndef __FONT_H__ 2 | #define __FONT_H__ 3 | 4 | 5 | #include 6 | #include 7 | 8 | 9 | class Font 10 | { 11 | private: 12 | TTF_Font *font; 13 | void *data; 14 | 15 | public: 16 | Font(const std::wstring &name, int ptsize); 17 | ~Font(); 18 | 19 | public: 20 | void draw(SDL_Surface *s, int x, int y, int r, int g, int b, 21 | bool shadow, const std::wstring &text); 22 | void draw(int x, int y, int r, int g, int b, bool shadow, 23 | const std::wstring &text); 24 | int getWidth(const std::wstring &text); 25 | int getWidth(wchar_t ch); 26 | int getHeight(const std::wstring &text); 27 | void getSize(const std::wstring &text, int &width, int &height); 28 | }; 29 | 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /mkres/Makefile: -------------------------------------------------------------------------------- 1 | OPTIMIZE=-O6 2 | CFLAGS=-Wall $(OPTIMIZE) 3 | LNFLAGS=-lz 4 | 5 | TARGET=mkres 6 | SOURCES=main.cpp compressor.cpp unicode.cpp streams.cpp table.cpp \ 7 | lexal.cpp convert.cpp buffer.cpp format.cpp messages.cpp \ 8 | msgformatter.cpp 9 | HEADERS=compressor.h unicode.h streams.h lexal.h convert.h table.h \ 10 | buffer.h format.h messages.h msgformatter.h 11 | OBJECTS=main.o compressor.o unicode.o streams.o lexal.o table.o \ 12 | convert.o buffer.o format.o messages.o msgformatter.o 13 | 14 | .cpp.o: 15 | $(CXX) -c $(CFLAGS) $< 16 | 17 | all: $(TARGET) 18 | 19 | depend: 20 | @makedepend $(SOURCES) 2> /dev/null 21 | 22 | $(TARGET): $(OBJECTS) 23 | $(CXX) $(LNFLAGS) $(OBJECTS) -o $(TARGET) $(LIBS) 24 | 25 | clean: 26 | rm -f $(OBJECTS) $(TARGET) core 27 | 28 | # DO NOT DELETE THIS LINE -- make depend depends on it. 29 | 30 | -------------------------------------------------------------------------------- /topscores.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOPSCORES_H__ 2 | #define __TOPSCORES_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include "widgets.h" 8 | 9 | 10 | #define MAX_SCORES 10 11 | 12 | 13 | class TopScores 14 | { 15 | public: 16 | typedef struct { 17 | std::wstring name; 18 | int score; 19 | } Entry; 20 | typedef std::list ScoresList; 21 | 22 | private: 23 | ScoresList scores; 24 | bool modifed; 25 | 26 | public: 27 | TopScores(); 28 | ~TopScores(); 29 | 30 | public: 31 | int add(const std::wstring &name, int scores); 32 | void save(); 33 | ScoresList& getScores(); 34 | int getMaxScore(); 35 | bool isFull() { return scores.size() >= MAX_SCORES; }; 36 | }; 37 | 38 | 39 | void showScoresWindow(Area *area, TopScores *scores, int highlightPos=-1); 40 | std::wstring enterNameDialog(Area *area); 41 | 42 | 43 | #endif 44 | 45 | -------------------------------------------------------------------------------- /streams.h: -------------------------------------------------------------------------------- 1 | #ifndef __STREAMS_H__ 2 | #define __STREAMS_H__ 3 | 4 | 5 | #include 6 | #include 7 | 8 | 9 | /// Read utf-8 file and convert it to wide characters 10 | class UtfStreamReader 11 | { 12 | private: 13 | /// Pointer to file stream 14 | std::ifstream *stream; 15 | 16 | /// Push back buffet 17 | std::list backBuf; 18 | 19 | public: 20 | /// Create utf-8 stream reader. 21 | /// \param stream pointer to file stream. 22 | UtfStreamReader(std::ifstream *stream); 23 | 24 | /// Destructor 25 | ~UtfStreamReader(); 26 | 27 | public: 28 | /// Read next unicode character. 29 | wchar_t getNextChar(); 30 | 31 | /// Push back character. 32 | /// \param ch character to push back 33 | void ungetChar(wchar_t ch); 34 | 35 | /// Check if end of file reached. 36 | bool isEof(); 37 | }; 38 | 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /mkres/streams.h: -------------------------------------------------------------------------------- 1 | #ifndef __STREAMS_H__ 2 | #define __STREAMS_H__ 3 | 4 | 5 | #include 6 | #include 7 | 8 | 9 | /// Read utf-8 file and convert it to wide characters 10 | class UtfStreamReader 11 | { 12 | private: 13 | /// Pointer to file stream 14 | std::ifstream *stream; 15 | 16 | /// Push back buffet 17 | std::list backBuf; 18 | 19 | public: 20 | /// Create utf-8 stream reader. 21 | /// \param stream pointer to file stream. 22 | UtfStreamReader(std::ifstream *stream); 23 | 24 | /// Destructor 25 | ~UtfStreamReader(); 26 | 27 | public: 28 | /// Read next unicode character. 29 | wchar_t getNextChar(); 30 | 31 | /// Push back character. 32 | /// \param ch character to push back 33 | void ungetChar(wchar_t ch); 34 | 35 | /// Check if end of file reached. 36 | bool isEof(); 37 | }; 38 | 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /iconset.h: -------------------------------------------------------------------------------- 1 | #ifndef __ICONSET_H__ 2 | #define __ICONSET_H__ 3 | 4 | 5 | #include 6 | 7 | 8 | class IconSet 9 | { 10 | private: 11 | SDL_Surface *smallIcons[6][6][2]; 12 | SDL_Surface *largeIcons[6][6][2]; 13 | SDL_Surface *emptyFieldIcon, *emptyHintIcon, *nearHintIcon[2]; 14 | SDL_Surface *sideHintIcon[2], *betweenArrow[2]; 15 | 16 | public: 17 | IconSet(); 18 | virtual ~IconSet(); 19 | 20 | public: 21 | SDL_Surface* getLargeIcon(int row, int num, bool highlighted); 22 | SDL_Surface* getSmallIcon(int row, int num, bool highlighted); 23 | SDL_Surface* getEmptyFieldIcon() { return emptyFieldIcon; }; 24 | SDL_Surface* getEmptyHintIcon() { return emptyHintIcon; }; 25 | SDL_Surface* getNearHintIcon(bool h) { return nearHintIcon[h ? 1 : 0]; }; 26 | SDL_Surface* getSideHintIcon(bool h) { return sideHintIcon[h ? 1 : 0]; }; 27 | SDL_Surface* getBetweenArrow(bool h) { return betweenArrow[h ? 1 : 0]; }; 28 | }; 29 | 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /horhints.h: -------------------------------------------------------------------------------- 1 | #ifndef __HORHINTS_H__ 2 | #define __HORHINTS_H__ 3 | 4 | 5 | #include 6 | #include "iconset.h" 7 | #include "puzgen.h" 8 | #include "widgets.h" 9 | 10 | 11 | 12 | class HorHints: public Widget 13 | { 14 | private: 15 | IconSet &iconSet; 16 | typedef std::vector RulesArr; 17 | RulesArr rules; 18 | RulesArr excludedRules; 19 | std::vector numbersArr; 20 | bool showExcluded; 21 | int highlighted; 22 | 23 | public: 24 | HorHints(IconSet &is, Rules &rules); 25 | HorHints(IconSet &is, Rules &rules, std::istream &stream); 26 | 27 | public: 28 | virtual void draw(); 29 | void drawCell(int col, int row, bool addToUpdate=true); 30 | virtual bool onMouseButtonDown(int button, int x, int y); 31 | void toggleExcluded(); 32 | int getRuleNo(int x, int y); 33 | virtual bool onMouseMove(int x, int y); 34 | bool isActive(int ruleNo); 35 | void save(std::ostream &stream); 36 | void reset(Rules &rules); 37 | }; 38 | 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /verthints.h: -------------------------------------------------------------------------------- 1 | #ifndef __VERTHINTS_H__ 2 | #define __VERTHINTS_H__ 3 | 4 | 5 | #include 6 | #include "iconset.h" 7 | #include "puzgen.h" 8 | #include "widgets.h" 9 | 10 | 11 | 12 | class VertHints: public Widget 13 | { 14 | private: 15 | IconSet &iconSet; 16 | typedef std::vector RulesArr; 17 | RulesArr rules; 18 | RulesArr excludedRules; 19 | std::vector numbersArr; 20 | bool showExcluded; 21 | int highlighted; 22 | 23 | public: 24 | VertHints(IconSet &is, Rules &rules); 25 | VertHints(IconSet &is, Rules &rules, std::istream &stream); 26 | 27 | public: 28 | virtual void draw(); 29 | void drawCell(int col, bool addToUpdate=true); 30 | virtual bool onMouseButtonDown(int button, int x, int y); 31 | void toggleExcluded(); 32 | int getRuleNo(int x, int y); 33 | virtual bool onMouseMove(int x, int y); 34 | bool isActive(int ruleNo); 35 | void save(std::ostream &stream); 36 | void reset(Rules &rules); 37 | }; 38 | 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /res/messages.txt: -------------------------------------------------------------------------------- 1 | rules = "Game Rules" 2 | close = "Close" 3 | next = "Next" 4 | prev = "Prev" 5 | ok = "OK" 6 | cancel = "Cancel" 7 | fullscreen = "Run in fullscreen mode" 8 | niceCursor = "Nice cursor" 9 | options = "Options" 10 | newGame = "Start New Game" 11 | loadGame = "Load Game" 12 | topScores = "Hall Of Fame" 13 | about = "About" 14 | exit = "Exit" 15 | einsteinPuzzle = "Einstein Puzzle" 16 | version = "version 2.0" 17 | copyright = "Copyright (c) 2003-2005 Flowix Games" 18 | anonymous = "Anonymous" 19 | enterName = "Enter your name:" 20 | empty = "-- Empty Slot --" 21 | enterGame = "Enter game name:" 22 | saveError = "Error saving game" 23 | saveGame = "Save Game" 24 | paused = "GAME PAUSED" 25 | won = "CONGRATULATIONS, YOU HAVE WON!" 26 | startNew = "New game" 27 | tryAgain = "Try again" 28 | loose = "YOU HAVE LOST" 29 | iddqd = "IT IS NOT DOOM, LUKE!" 30 | pause = "Pause" 31 | switch = "Switch" 32 | save = "Save" 33 | help = "Help" 34 | loading = "Loading.... Please wait...." 35 | einsteinFlowix = "Einstein puzzle by Flowix Games" 36 | enableSound = "Enable sound" 37 | expired = "This beta is expired. Please download update from http://games.flowix.com" 38 | volume = "Volume:" 39 | 40 | -------------------------------------------------------------------------------- /res/messages_ru.txt: -------------------------------------------------------------------------------- 1 | rules = "Правила игры" 2 | close = "Закрыть" 3 | next = "Вперед" 4 | prev = "Назад" 5 | ok = "OK" 6 | cancel = "Отмена" 7 | fullscreen = "Полноэкранный режим" 8 | niceCursor = "Симпатичный курсор" 9 | options = "Настройки" 10 | newGame = "Начать игру" 11 | loadGame = "Загрузить игру" 12 | topScores = "Доска почета" 13 | about = "Об авторах" 14 | exit = "Выход" 15 | einsteinPuzzle = "Головоломка Эйнштейна" 16 | version = "версия 2.0" 17 | copyright = "Copyright (c) 2003-2005 Flowix Games" 18 | anonymous = "Аноним" 19 | enterName = "Введите ваше имя:" 20 | empty = "-- Пусто --" 21 | enterGame = "Название игры:" 22 | saveError = "Ошибка сохранения игры" 23 | saveGame = "Сохранить игру" 24 | paused = "ИГРА ПРИОСТАНОВЛЕНА" 25 | won = "ПОЗДРАВЛЯЮ! ВЫ ВЫЙГРАЛИ!!!" 26 | startNew = "Новая игра" 27 | tryAgain = "Эта же" 28 | loose = "ВЫ ПРОИГРАЛИ" 29 | iddqd = "ЭТО ВАМ НЕ ДУМ КАКОЙ-НИБУДЬ!" 30 | pause = "Пауза" 31 | switch = "Скрытые" 32 | save = "Сохранить" 33 | help = "Справка" 34 | loading = "Загружается.... Пожалуйста ждите...." 35 | einsteinFlowix = "Головоломка Эйнштейна от Flowix Games" 36 | enableSound = "Включить звуки" 37 | expired = "Эта бета-версия устарела. Скачайте новую с http://games.flowix.com" 38 | volume = "Громкость:" 39 | -------------------------------------------------------------------------------- /random.h: -------------------------------------------------------------------------------- 1 | #ifndef __RANDOM_H__ 2 | #define __RANDOM_H__ 3 | 4 | 5 | 6 | class Random 7 | { 8 | private: 9 | #define RAND_N 624 10 | unsigned long mt[RAND_N]; /* the array for the state vector */ 11 | int mti; /* mti==RAND_N+1 means mt[RAND_N] is not initialized */ 12 | 13 | public: 14 | Random(); 15 | Random(unsigned long int seed); 16 | Random(int keys[], int length); 17 | ~Random(); 18 | 19 | public: 20 | /* generates a random number on [0,0xffffffff]-interval */ 21 | unsigned long int genInt32(); 22 | /* generates a random number on [0,0x7fffffff]-interval */ 23 | long int genInt31(); 24 | /* generates a random number on [0,1]-real-interval */ 25 | double genReal1(); 26 | /* generates a random number on [0,1)-real-interval */ 27 | double genReal2(); 28 | /* generates a random number on (0,1)-real-interval */ 29 | double genReal3(); 30 | /* generates a random number on [0,1) with 53-bit resolution*/ 31 | double genReal53(); 32 | /* generate integer random number on [0, range) int interval */ 33 | int genInt(int range); 34 | 35 | private: 36 | void initLong(unsigned long int s); 37 | }; 38 | 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /tokenizer.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOKENIZER_H__ 2 | #define __TOKENIZER_H__ 3 | 4 | 5 | #include 6 | #include 7 | 8 | 9 | class Tokenizer; 10 | 11 | 12 | class Token 13 | { 14 | friend class Tokenizer; 15 | 16 | public: 17 | enum Type { 18 | Word, 19 | Para, 20 | Eof 21 | }; 22 | 23 | private: 24 | Type type; 25 | std::wstring content; 26 | 27 | private: 28 | Token(Type type) { this->type = type; }; 29 | Token(Type type, const std::wstring &content): content(content) { 30 | this->type = type; 31 | } 32 | 33 | public: 34 | Type getType() const { return type; }; 35 | const std::wstring& getContent() const { return content; }; 36 | std::wstring toString() const; 37 | }; 38 | 39 | 40 | class Tokenizer 41 | { 42 | private: 43 | std::wstring text; 44 | int currentPos; 45 | std::list stack; 46 | 47 | public: 48 | Tokenizer(const std::wstring &s): text(s) { currentPos = 0; }; 49 | 50 | public: 51 | Token getNextToken(); 52 | void unget(const Token &token); 53 | bool isFinished(); 54 | 55 | private: 56 | bool skipSpaces(bool notSearch); 57 | }; 58 | 59 | 60 | #endif 61 | 62 | -------------------------------------------------------------------------------- /puzzle.h: -------------------------------------------------------------------------------- 1 | #ifndef __PUZZLE_H__ 2 | #define __PUZZLE_H__ 3 | 4 | 5 | #include "iconset.h" 6 | #include "puzgen.h" 7 | #include "widgets.h" 8 | 9 | 10 | class Puzzle: public Widget 11 | { 12 | private: 13 | Possibilities *possib; 14 | IconSet &iconSet; 15 | bool valid; 16 | bool win; 17 | SolvedPuzzle &solved; 18 | int hCol, hRow; 19 | int subHNo; 20 | Command *winCommand, *failCommand; 21 | 22 | public: 23 | Puzzle(IconSet &is, SolvedPuzzle &solved, Possibilities *possib); 24 | virtual ~Puzzle(); 25 | 26 | public: 27 | virtual void draw(); 28 | void drawRow(int row, bool addToUpdate=true); 29 | void drawCell(int col, int row, bool addToUpdate=true); 30 | Possibilities* getPossibilities() { return possib; }; 31 | virtual bool onMouseButtonDown(int button, int x, int y); 32 | bool isValid() const { return valid; }; 33 | bool victory() const { return win; }; 34 | void onFail(); 35 | void onVictory(); 36 | bool getCellNo(int x, int y, int &col, int &row, int &subNo); 37 | virtual bool onMouseMove(int x, int y); 38 | void setCommands(Command *winCommand, Command *failCommand); 39 | void reset(); 40 | }; 41 | 42 | 43 | #endif 44 | 45 | -------------------------------------------------------------------------------- /mkres/messages.h: -------------------------------------------------------------------------------- 1 | #ifndef __MESSAGES_H__ 2 | #define __MESSAGES_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include "buffer.h" 9 | 10 | 11 | class MsgCommand 12 | { 13 | public: 14 | virtual ~MsgCommand() { }; 15 | 16 | public: 17 | virtual std::wstring toString() = 0; 18 | virtual int write(Buffer &buffer) = 0; 19 | }; 20 | 21 | 22 | class Message 23 | { 24 | private: 25 | typedef std::list Commands; 26 | Commands commands; 27 | 28 | public: 29 | Message(const std::wstring &msg); 30 | ~Message(); 31 | int save(Buffer &buffer); 32 | }; 33 | 34 | 35 | class Messages 36 | { 37 | private: 38 | typedef struct { 39 | int offset; 40 | Message *message; 41 | } MsgEntry; 42 | typedef std::map MsgMap; 43 | MsgMap messages; 44 | 45 | public: 46 | Messages(); 47 | ~Messages(); 48 | 49 | public: 50 | void add(const std::wstring &key, const std::wstring &msg); 51 | void save(Buffer &buffer); 52 | 53 | private: 54 | int writeHeader(Buffer &buffer); 55 | int writeMessages(Buffer &buffer, int offset); 56 | int writeDirectory(Buffer &buffer); 57 | }; 58 | 59 | 60 | #endif 61 | 62 | -------------------------------------------------------------------------------- /tablestorage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "tablestorage.h" 5 | #include "unicode.h" 6 | #include "exceptions.h" 7 | 8 | 9 | TableStorage::TableStorage() 10 | { 11 | try { 12 | table = Table(toMbcs(getFileName())); 13 | } catch (Exception &e) { 14 | std::cerr << e.getMessage() << std::endl; 15 | } catch (...) { 16 | std::cerr << "Unknown config file error" << std::endl; 17 | } 18 | } 19 | 20 | TableStorage::~TableStorage() 21 | { 22 | flush(); 23 | } 24 | 25 | std::wstring TableStorage::getFileName() 26 | { 27 | #ifndef WIN32 28 | return std::wstring(fromMbcs(getenv("HOME"))) + L"/.einstein/einsteinrc"; 29 | #else 30 | return L"einstein.cfg"; 31 | #endif 32 | } 33 | 34 | int TableStorage::get(const std::wstring &name, int dflt) 35 | { 36 | return table.getInt(name, dflt); 37 | } 38 | 39 | std::wstring TableStorage::get(const std::wstring &name, 40 | const std::wstring &dflt) 41 | { 42 | return table.getString(name, dflt); 43 | } 44 | 45 | void TableStorage::set(const std::wstring &name, int value) 46 | { 47 | table.setInt(name, value); 48 | } 49 | 50 | void TableStorage::set(const std::wstring &name, const std::wstring &value) 51 | { 52 | table.setString(name, value); 53 | } 54 | 55 | void TableStorage::flush() 56 | { 57 | table.save(getFileName()); 58 | } 59 | 60 | -------------------------------------------------------------------------------- /convert.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONVERT_H__ 2 | #define __CONVERT_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "exceptions.h" 11 | #include "unicode.h" 12 | 13 | 14 | /// Convert value to string 15 | /// \param x value 16 | template 17 | inline std::wstring toString(const T &x) 18 | { 19 | #ifndef WIN32 20 | std::wostringstream o; 21 | if (! (o << x)) 22 | throw Exception(L"Can't convert " + fromMbcs(typeid(x).name()) 23 | + L" to string"); 24 | return o.str(); 25 | #else // Mingw doesn't support std::wostringstream yet :-( 26 | std::ostringstream o; 27 | if (! (o << x)) 28 | throw Exception(L"Can't convert " + fromMbcs(typeid(x).name()) 29 | + L" to string"); 30 | return fromMbcs(o.str()); 31 | #endif 32 | } 33 | 34 | 35 | /// Convert string to lower case. 36 | std::wstring toLowerCase(const std::wstring &s); 37 | 38 | /// Convert string to upper case 39 | std::wstring toUpperCase(const std::wstring &s); 40 | 41 | /// Convert integer to string. 42 | std::wstring numToStr(int num); 43 | 44 | /// Convert unsigned integer to string. 45 | std::wstring numToStr(unsigned int num); 46 | 47 | /// Convert string to integer 48 | int strToInt(const std::wstring &str); 49 | 50 | /// Conver string to double 51 | double strToDouble(const std::wstring &str); 52 | 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /mkres/convert.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONVERT_H__ 2 | #define __CONVERT_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "exceptions.h" 10 | #include "unicode.h" 11 | #include 12 | 13 | /// Convert value to string 14 | /// \param x value 15 | template 16 | inline std::wstring toString(const T &x) 17 | { 18 | #ifndef WIN32 19 | std::wostringstream o; 20 | if (! (o << x)) 21 | throw Exception(L"Can't convert " + fromMbcs(typeid(x).name()) 22 | + L" to string"); 23 | return o.str(); 24 | #else // Mingw doesn't support std::wostringstream yet :-( 25 | std::ostringstream o; 26 | if (! (o << x)) 27 | throw Exception(L"Can't convert " + fromMbcs(typeid(x).name()) 28 | + L" to string"); 29 | return fromMbcs(o.str()); 30 | #endif 31 | } 32 | 33 | 34 | /// Convert string to lower case. 35 | std::wstring toLowerCase(const std::wstring &s); 36 | 37 | /// Convert string to upper case 38 | std::wstring toUpperCase(const std::wstring &s); 39 | 40 | /// Convert integer to string. 41 | std::wstring numToStr(int num); 42 | 43 | /// Convert unsigned integer to string. 44 | std::wstring numToStr(unsigned int num); 45 | 46 | /// Convert string to integer 47 | int strToInt(const std::wstring &str); 48 | 49 | /// Conver string to double 50 | double strToDouble(const std::wstring &str); 51 | 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /formatter.h: -------------------------------------------------------------------------------- 1 | #ifndef __FORMATTER_H__ 2 | #define __FORMATTER_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | class ArgValue; 11 | 12 | 13 | /// Localized message formatter 14 | class Formatter 15 | { 16 | public: 17 | typedef enum { 18 | EMPTY_CMD = 0, 19 | TEXT_COMMAND, 20 | INT_ARG, 21 | STRING_ARG, 22 | DOUBLE_ARG, 23 | FLOAT_ARG 24 | } CmdType; 25 | 26 | typedef struct 27 | { 28 | CmdType type; 29 | void *data; 30 | } Command; 31 | 32 | private: 33 | int commandsCnt; 34 | int argsCnt; 35 | 36 | Command *commands; 37 | 38 | CmdType *args; 39 | 40 | public: 41 | /// Create localized message from message buffer. 42 | /// \param data buffer contained message file 43 | /// \param offset offset to message from buffer start 44 | Formatter(unsigned char *data, int offset); 45 | ~Formatter(); 46 | 47 | public: 48 | /// Get message text. 49 | std::wstring getMessage() const; 50 | 51 | /// Fromat message 52 | /// \param ap list of arguments 53 | std::wstring format(va_list ap) const; 54 | 55 | private: 56 | std::wstring format(std::vector &argValues) const; 57 | }; 58 | 59 | 60 | 61 | 62 | #endif 63 | 64 | -------------------------------------------------------------------------------- /game.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAME_H__ 2 | #define __GAME_H__ 3 | 4 | 5 | #include 6 | #include "puzgen.h" 7 | #include "verthints.h" 8 | #include "horhints.h" 9 | #include "puzzle.h" 10 | 11 | 12 | 13 | class Watch; 14 | 15 | 16 | 17 | class Game 18 | { 19 | private: 20 | SolvedPuzzle solvedPuzzle; 21 | Rules rules; 22 | Possibilities *possibilities; 23 | VertHints *verHints; 24 | HorHints *horHints; 25 | IconSet iconSet; 26 | Puzzle *puzzle; 27 | Watch *watch; 28 | bool hinted; 29 | SolvedPuzzle savedSolvedPuzzle; 30 | Rules savedRules; 31 | 32 | public: 33 | Game(); 34 | Game(std::istream &stream); 35 | ~Game(); 36 | 37 | public: 38 | SolvedPuzzle& getSolvedPuzzle() { return solvedPuzzle; }; 39 | Rules& getRules() { return rules; }; 40 | Possibilities* getPossibilities() { return possibilities; }; 41 | VertHints* getVerHints() { return verHints; }; 42 | HorHints* getHorHints() { return horHints; }; 43 | void save(std::ostream &stream); 44 | void run(); 45 | bool isHinted() { return hinted; }; 46 | void setHinted() { hinted = true; }; 47 | void restart(); 48 | void newGame(); 49 | 50 | private: 51 | void deleteRules(); 52 | void pleaseWait(); 53 | void genPuzzle(); 54 | void resetVisuals(); 55 | }; 56 | 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /unicode.h: -------------------------------------------------------------------------------- 1 | #ifndef __UNICODE_H__ 2 | #define __UNICODE_H__ 3 | 4 | 5 | /// \file unicode.h 6 | /// Definition of UNICODE handling rotinues. 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | /// Convert unicode string to multibyte string in UTF-8 encoding 14 | /// \param str string in unicode 15 | std::string toUtf8(const std::wstring &str); 16 | 17 | /// Convert multibyte string in UTF-8 encoding to unicode string 18 | /// \param str string in UTF-8 encoding 19 | std::wstring fromUtf8(const std::string &str); 20 | 21 | /// Convert multibyte string in UTF-8 encoding to unicode string 22 | /// \param str string in UTF-8 encoding 23 | /// \param len string length in bytes 24 | std::wstring fromUtf8(const char *str, int len); 25 | 26 | /// Convert unicode string to multibyte string in system default encoding 27 | /// \param str string in unicode 28 | std::string toMbcs(const std::wstring &str); 29 | 30 | /// Convert unicode string to multibyte string in system default encoding 31 | /// \param str string in unicode 32 | std::wstring fromMbcs(const std::string &str); 33 | 34 | /// Convert unicode string to default multibyte encoding 35 | /// and write it to stream. 36 | /// \param stream stream 37 | /// \param str string to output 38 | std::ostream& operator << (std::ostream &stream, const std::wstring &str); 39 | 40 | /// Returns length of UTF-8 character in bytes by first UTF-8 character byte. 41 | /// \param c first byte of UTF-8 character. 42 | int getUtf8Length(unsigned char c); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /mkres/unicode.h: -------------------------------------------------------------------------------- 1 | #ifndef __UNICODE_H__ 2 | #define __UNICODE_H__ 3 | 4 | 5 | /// \file unicode.h 6 | /// Definition of UNICODE handling rotinues. 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | /// Convert unicode string to multibyte string in UTF-8 encoding 14 | /// \param str string in unicode 15 | std::string toUtf8(const std::wstring &str); 16 | 17 | /// Convert multibyte string in UTF-8 encoding to unicode string 18 | /// \param str string in UTF-8 encoding 19 | std::wstring fromUtf8(const std::string &str); 20 | 21 | /// Convert multibyte string in UTF-8 encoding to unicode string 22 | /// \param str string in UTF-8 encoding 23 | /// \param len string length in bytes 24 | std::wstring fromUtf8(const char *str, int len); 25 | 26 | /// Convert unicode string to multibyte string in system default encoding 27 | /// \param str string in unicode 28 | std::string toMbcs(const std::wstring &str); 29 | 30 | /// Convert unicode string to multibyte string in system default encoding 31 | /// \param str string in unicode 32 | std::wstring fromMbcs(const std::string &str); 33 | 34 | /// Convert unicode string to default multibyte encoding 35 | /// and write it to stream. 36 | /// \param stream stream 37 | /// \param str string to output 38 | std::ostream& operator << (std::ostream &stream, const std::wstring &str); 39 | 40 | /// Returns length of UTF-8 character in bytes by first UTF-8 character byte. 41 | /// \param c first byte of UTF-8 character. 42 | int getUtf8Length(unsigned char c); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /streams.cpp: -------------------------------------------------------------------------------- 1 | #include "streams.h" 2 | #include "exceptions.h" 3 | #include "unicode.h" 4 | 5 | 6 | UtfStreamReader::UtfStreamReader(std::ifstream *s) 7 | { 8 | stream = s; 9 | } 10 | 11 | UtfStreamReader::~UtfStreamReader() 12 | { 13 | } 14 | 15 | // This function is very slow because of poor fromUtf8 function design 16 | wchar_t UtfStreamReader::getNextChar() 17 | { 18 | unsigned char buf[10]; 19 | 20 | if (0 < backBuf.size()) { 21 | wchar_t wc = backBuf.front(); 22 | backBuf.pop_front(); 23 | return wc; 24 | } 25 | 26 | if (! stream->good()) 27 | throw Exception(L"Error reading from stream 1"); 28 | 29 | int sz = stream->readsome((char*)buf, 1); 30 | if (1 != sz) 31 | throw Exception(L"Error reading from stream 2"); 32 | int size = getUtf8Length(buf[0]); 33 | if (size > 1) { 34 | sz = stream->readsome((char*)buf + 1, size - 1); 35 | if (size - 1 != sz) 36 | throw Exception(L"Error reading from stream 3"); 37 | } 38 | buf[size] = 0; 39 | std::string s((char*)buf); 40 | std::wstring ws(fromUtf8(s)); 41 | if (1 != ws.length()) 42 | throw Exception(L"Error converting UTF-8 character to wide character"); 43 | return ws[0]; 44 | } 45 | 46 | void UtfStreamReader::ungetChar(wchar_t ch) 47 | { 48 | backBuf.push_back(ch); 49 | } 50 | 51 | bool UtfStreamReader::isEof() 52 | { 53 | if (stream->eof()) 54 | return true; // FIXME: it doesn't work. why? 55 | return EOF == stream->peek(); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /mkres/streams.cpp: -------------------------------------------------------------------------------- 1 | #include "streams.h" 2 | #include "exceptions.h" 3 | #include "unicode.h" 4 | 5 | 6 | UtfStreamReader::UtfStreamReader(std::ifstream *s) 7 | { 8 | stream = s; 9 | } 10 | 11 | UtfStreamReader::~UtfStreamReader() 12 | { 13 | } 14 | 15 | // This function is very slow because of poor fromUtf8 function design 16 | wchar_t UtfStreamReader::getNextChar() 17 | { 18 | unsigned char buf[10]; 19 | 20 | if (0 < backBuf.size()) { 21 | wchar_t wc = backBuf.front(); 22 | backBuf.pop_front(); 23 | return wc; 24 | } 25 | 26 | if (! stream->good()) 27 | throw Exception(L"Error reading from stream 1"); 28 | 29 | int sz = stream->readsome((char*)buf, 1); 30 | if (1 != sz) 31 | throw Exception(L"Error reading from stream 2"); 32 | int size = getUtf8Length(buf[0]); 33 | if (size > 1) { 34 | sz = stream->readsome((char*)buf + 1, size - 1); 35 | if (size - 1 != sz) 36 | throw Exception(L"Error reading from stream 3"); 37 | } 38 | buf[size] = 0; 39 | std::string s((char*)buf); 40 | std::wstring ws(fromUtf8(s)); 41 | if (1 != ws.length()) 42 | throw Exception(L"Error converting UTF-8 character to wide character"); 43 | return ws[0]; 44 | } 45 | 46 | void UtfStreamReader::ungetChar(wchar_t ch) 47 | { 48 | backBuf.push_back(ch); 49 | } 50 | 51 | bool UtfStreamReader::isEof() 52 | { 53 | if (stream->eof()) 54 | return true; // FIXME: it doesn't work. why? 55 | return EOF == stream->peek(); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /sound.cpp: -------------------------------------------------------------------------------- 1 | #include "sound.h" 2 | 3 | #include 4 | #include 5 | #include "resources.h" 6 | 7 | 8 | Sound *sound; 9 | 10 | 11 | Sound::Sound() 12 | { 13 | int audio_rate = 22050; 14 | Uint16 audio_format = AUDIO_S16; /* 16-bit stereo */ 15 | int audio_channels = 2; 16 | int audio_buffers = 1024; 17 | disabled = Mix_OpenAudio(audio_rate, audio_format, audio_channels, 18 | audio_buffers); 19 | if (disabled) 20 | std::cout << "Audio is disabled" << std::endl; 21 | } 22 | 23 | Sound::~Sound() 24 | { 25 | if (! disabled) 26 | Mix_CloseAudio(); 27 | for (ChunkMap::iterator i = chunkCache.begin(); i != chunkCache.end(); i++) 28 | Mix_FreeChunk((*i).second); 29 | Mix_CloseAudio(); 30 | } 31 | 32 | 33 | void Sound::play(const std::wstring &name) 34 | { 35 | if (disabled || (! enableFx)) 36 | return; 37 | 38 | Mix_Chunk *chunk = NULL; 39 | 40 | ChunkMap::iterator i = chunkCache.find(name); 41 | if (i != chunkCache.end()) 42 | chunk = (*i).second; 43 | else { 44 | ResDataHolder data(name); 45 | chunk = Mix_LoadWAV_RW(SDL_RWFromMem(data.getData(), data.getSize()), 46 | 0); 47 | chunkCache[name] = chunk; 48 | } 49 | 50 | if (chunk) { 51 | Mix_VolumeChunk(chunk, (int)(volume * 128.0f)); 52 | Mix_PlayChannel(-1, chunk, 0); 53 | } 54 | SDL_PumpEvents(); 55 | } 56 | 57 | void Sound::setVolume(float v) 58 | { 59 | volume = v; 60 | enableFx = 0.01 < volume; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /convert.cpp: -------------------------------------------------------------------------------- 1 | #include "convert.h" 2 | 3 | std::wstring toLowerCase(const std::wstring &s) 4 | { 5 | std::wstring res; 6 | 7 | int len = s.length(); 8 | for (int i = 0; i < len; i++) 9 | res += (wchar_t)towlower(s[i]); 10 | 11 | return res; 12 | } 13 | 14 | std::wstring toUpperCase(const std::wstring &s) 15 | { 16 | std::wstring res; 17 | 18 | int len = s.length(); 19 | for (int i = 0; i < len; i++) 20 | res += (wchar_t)towupper(s[i]); 21 | 22 | return res; 23 | } 24 | 25 | std::wstring numToStr(int num) 26 | { 27 | wchar_t buf[30]; 28 | #ifdef WIN32 29 | swprintf(buf, L"%i", num); 30 | #else 31 | swprintf(buf, 29, L"%i", num); 32 | #endif 33 | buf[29] = 0; 34 | return std::wstring(buf); 35 | } 36 | 37 | std::wstring numToStr(unsigned int num) 38 | { 39 | wchar_t buf[30]; 40 | #ifdef WIN32 41 | swprintf(buf, L"%u", num); 42 | #else 43 | swprintf(buf, 29, L"%i", num); 44 | #endif 45 | buf[29] = 0; 46 | return std::wstring(buf); 47 | } 48 | 49 | int strToInt(const std::wstring &str) 50 | { 51 | int n; 52 | wchar_t *endptr; 53 | 54 | n = wcstol(str.c_str(), &endptr, 10); 55 | if ((! str.c_str()[0]) || (endptr[0])) 56 | throw Exception(L"Invalid integer '" + str + L"'"); 57 | return n; 58 | } 59 | 60 | double strToDouble(const std::wstring &str) 61 | { 62 | double n; 63 | wchar_t *endptr; 64 | 65 | n = wcstod(str.c_str(), &endptr); 66 | if ((! str.c_str()[0]) || (endptr[0])) 67 | throw Exception(L"Invalid double '" + str + L"'"); 68 | return n; 69 | } 70 | -------------------------------------------------------------------------------- /i18n.h: -------------------------------------------------------------------------------- 1 | #ifndef __I18N_H__ 2 | #define __I18N_H__ 3 | 4 | 5 | /// \file i18n.h 6 | /// Locale related functions 7 | 8 | 9 | #include 10 | 11 | 12 | /// Description of current locale 13 | class Locale 14 | { 15 | private: 16 | std::wstring language; 17 | std::wstring country; 18 | std::wstring encoding; 19 | 20 | public: 21 | /// Load locale 22 | Locale(); 23 | 24 | /// Copy constructor 25 | Locale(const Locale &locale); 26 | 27 | public: 28 | /// Get current country. 29 | const std::wstring& getCountry() const { return country; }; 30 | 31 | /// Get current language. 32 | const std::wstring& getLanguage() const { return language; }; 33 | 34 | /// Get current encoding. 35 | const std::wstring& getEncoding() const { return encoding; }; 36 | 37 | private: 38 | void parseLocale(const std::wstring &name); 39 | }; 40 | 41 | 42 | // split file name to file name, extension, language name and country 43 | // for exmaple, "story_ru_RU.txt" shoud be splited to 44 | // name="story", extension="txt", language="ru", country="RU" 45 | void splitFileName(const std::wstring &fileName, std::wstring &name, 46 | std::wstring &ext, std::wstring &lang, std::wstring &country); 47 | 48 | // calculate relevance score between language, country and 49 | // current locale 50 | int getScore(const std::wstring &lang, const std::wstring &country, 51 | const Locale &locale); 52 | 53 | 54 | extern Locale locale; 55 | 56 | 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /mkres/convert.cpp: -------------------------------------------------------------------------------- 1 | #include "convert.h" 2 | 3 | std::wstring toLowerCase(const std::wstring &s) 4 | { 5 | std::wstring res; 6 | 7 | int len = s.length(); 8 | for (int i = 0; i < len; i++) 9 | res += (wchar_t)towlower(s[i]); 10 | 11 | return res; 12 | } 13 | 14 | std::wstring toUpperCase(const std::wstring &s) 15 | { 16 | std::wstring res; 17 | 18 | int len = s.length(); 19 | for (int i = 0; i < len; i++) 20 | res += (wchar_t)towupper(s[i]); 21 | 22 | return res; 23 | } 24 | 25 | std::wstring numToStr(int num) 26 | { 27 | wchar_t buf[30]; 28 | #ifdef WIN32 29 | swprintf(buf, L"%i", num); 30 | #else 31 | swprintf(buf, 29, L"%i", num); 32 | #endif 33 | buf[29] = 0; 34 | return std::wstring(buf); 35 | } 36 | 37 | std::wstring numToStr(unsigned int num) 38 | { 39 | wchar_t buf[30]; 40 | #ifdef WIN32 41 | swprintf(buf, L"%u", num); 42 | #else 43 | swprintf(buf, 29, L"%i", num); 44 | #endif 45 | buf[29] = 0; 46 | return std::wstring(buf); 47 | } 48 | 49 | int strToInt(const std::wstring &str) 50 | { 51 | int n; 52 | wchar_t *endptr; 53 | 54 | n = wcstol(str.c_str(), &endptr, 10); 55 | if ((! str.c_str()[0]) || (endptr[0])) 56 | throw Exception(L"Invalid integer '" + str + L"'"); 57 | return n; 58 | } 59 | 60 | double strToDouble(const std::wstring &str) 61 | { 62 | double n; 63 | wchar_t *endptr; 64 | 65 | n = wcstod(str.c_str(), &endptr); 66 | if ((! str.c_str()[0]) || (endptr[0])) 67 | throw Exception(L"Invalid double '" + str + L"'"); 68 | return n; 69 | } 70 | -------------------------------------------------------------------------------- /utils.h: -------------------------------------------------------------------------------- 1 | #ifndef __UTILS_H__ 2 | #define __UTILS_H__ 3 | 4 | #include 5 | #include 6 | #ifdef WIN32 7 | #include 8 | #endif 9 | #include 10 | #include "resources.h" 11 | #include "widgets.h" 12 | 13 | 14 | 15 | SDL_Surface* loadImage(const std::wstring &name, bool transparent=false); 16 | SDL_Surface* adjustBrightness(SDL_Surface *image, double k, bool transparent=false); 17 | int gettimeofday(struct timeval* tp); 18 | void drawWallpaper(const std::wstring &name); 19 | void showWindow(Area *area, const std::wstring &fileName); 20 | bool isInRect(int evX, int evY, int x, int y, int w, int h); 21 | std::wstring numToStr(int no); 22 | void adjustBrightness(SDL_Surface *image, int x, int y, double k); 23 | std::wstring secToStr(int time); 24 | void showMessageWindow(Area *area, const std::wstring &pattern, 25 | int width, int height, Font *font, int r, int g, int b, 26 | const std::wstring &msg); 27 | int getCornerPixel(SDL_Surface *surface); 28 | void getPixel(SDL_Surface *surface, int x, int y, 29 | Uint8 *r, Uint8 *g, Uint8 *b); 30 | void setPixel(SDL_Surface *s, int x, int y, int r, int g, int b); 31 | void drawBevel(SDL_Surface *s, int left, int top, int width, int height, 32 | bool raised, int size); 33 | void ensureDirExists(const std::wstring &fileName); 34 | int readInt(std::istream &stream); 35 | std::wstring readString(std::istream &stream); 36 | void writeInt(std::ostream &stream, int value); 37 | void writeString(std::ostream &stream, const std::wstring &value); 38 | 39 | /// Read 4-bytes integer from memory. 40 | int readInt(unsigned char *buffer); 41 | 42 | 43 | #endif 44 | 45 | -------------------------------------------------------------------------------- /lexal.h: -------------------------------------------------------------------------------- 1 | #ifndef __LEXAL_H__ 2 | #define __LEXAL_H__ 3 | 4 | 5 | #include "streams.h" 6 | 7 | 8 | class Lexeme 9 | { 10 | public: 11 | typedef enum Type { 12 | String, 13 | Integer, 14 | Float, 15 | Ident, 16 | Symbol, 17 | Eof 18 | }; 19 | 20 | private: 21 | int line; 22 | int pos; 23 | Type type; 24 | std::wstring content; 25 | 26 | public: 27 | Lexeme() { }; 28 | Lexeme(Type type, const std::wstring &content, int line, int pos); 29 | ~Lexeme() { }; 30 | 31 | public: 32 | const Type getType() const { return type; }; 33 | const std::wstring getContent() const { return content; }; 34 | std::wstring getPosStr() const; 35 | int getLine() const { return line; }; 36 | int getPos() const { return pos; }; 37 | }; 38 | 39 | 40 | class Lexal 41 | { 42 | private: 43 | UtfStreamReader &reader; 44 | int line; 45 | int pos; 46 | 47 | public: 48 | Lexal(UtfStreamReader &reader); 49 | ~Lexal() { }; 50 | 51 | public: 52 | Lexeme getNext(); 53 | static std::wstring posToStr(int line, int pos); 54 | 55 | private: 56 | void skipSpaces(); 57 | void skipToLineEnd(); 58 | void skipMultilineComment(int startLine, int startPos); 59 | Lexeme readIdent(int startLine, int startPos, wchar_t first); 60 | Lexeme readNumber(int startLine, int startPos, wchar_t first); 61 | Lexeme readString(int startLine, int startPos, wchar_t quote); 62 | }; 63 | 64 | 65 | #endif 66 | 67 | -------------------------------------------------------------------------------- /mkres/lexal.h: -------------------------------------------------------------------------------- 1 | #ifndef __LEXAL_H__ 2 | #define __LEXAL_H__ 3 | 4 | 5 | #include "streams.h" 6 | 7 | 8 | class Lexeme 9 | { 10 | public: 11 | typedef enum Type { 12 | String, 13 | Integer, 14 | Float, 15 | Ident, 16 | Symbol, 17 | Eof 18 | }; 19 | 20 | private: 21 | int line; 22 | int pos; 23 | Type type; 24 | std::wstring content; 25 | 26 | public: 27 | Lexeme() { }; 28 | Lexeme(Type type, const std::wstring &content, int line, int pos); 29 | ~Lexeme() { }; 30 | 31 | public: 32 | const Type getType() const { return type; }; 33 | const std::wstring getContent() const { return content; }; 34 | std::wstring getPosStr() const; 35 | int getLine() const { return line; }; 36 | int getPos() const { return pos; }; 37 | }; 38 | 39 | 40 | class Lexal 41 | { 42 | private: 43 | UtfStreamReader &reader; 44 | int line; 45 | int pos; 46 | 47 | public: 48 | Lexal(UtfStreamReader &reader); 49 | ~Lexal() { }; 50 | 51 | public: 52 | Lexeme getNext(); 53 | static std::wstring posToStr(int line, int pos); 54 | 55 | private: 56 | void skipSpaces(); 57 | void skipToLineEnd(); 58 | void skipMultilineComment(int startLine, int startPos); 59 | Lexeme readIdent(int startLine, int startPos, wchar_t first); 60 | Lexeme readNumber(int startLine, int startPos, wchar_t first); 61 | Lexeme readString(int startLine, int startPos, wchar_t quote); 62 | }; 63 | 64 | 65 | #endif 66 | 67 | -------------------------------------------------------------------------------- /messages.h: -------------------------------------------------------------------------------- 1 | #ifndef __MESSAGES_H__ 2 | #define __MESSAGES_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | class Resource; 11 | class Formatter; 12 | class Buffer; 13 | 14 | 15 | /// Localized messages formatter 16 | class Messages 17 | { 18 | private: 19 | typedef struct { 20 | int score; 21 | Formatter *message; 22 | } ScoredStr; 23 | typedef std::map StrMap; 24 | StrMap messages; 25 | 26 | public: 27 | /// Create empty messages table. 28 | Messages(); 29 | ~Messages(); 30 | 31 | public: 32 | /// Load message tables from resources. 33 | void load(); 34 | 35 | /// Get simple text string 36 | /// \param key message key 37 | std::wstring getMessage(const std::wstring &key) const; 38 | 39 | /// Shorter alias for getMessage 40 | /// \param key message key 41 | std::wstring operator [](const std::wstring &key) const { 42 | return getMessage(key); 43 | }; 44 | 45 | /// Format message 46 | /// \param key message key 47 | std::wstring format(const wchar_t *key, ...) const; 48 | 49 | /// Shorter alias for format 50 | /// \param key message key 51 | std::wstring operator ()(const wchar_t *key, ...) const; 52 | 53 | /// Load messages from resource 54 | /// \param res resource 55 | void loadFromResource(Resource *res, Buffer *buffer); 56 | 57 | private: 58 | void loadBundle(int score, unsigned char *data, size_t size); 59 | std::wstring format(const wchar_t *key, va_list ap) const; 60 | }; 61 | 62 | 63 | extern Messages msg; 64 | 65 | 66 | #endif 67 | 68 | -------------------------------------------------------------------------------- /Makefile.win: -------------------------------------------------------------------------------- 1 | OPTIMIZE=-O3 #-march=pentium4 -mfpmath=sse -fomit-frame-pointer -funroll-loops 2 | DEBUG=#-ggdb 3 | CXXFLAGS=-Wall $(OPTIMIZE) $(DEBUG) -Ic:/mingw/include/sdl -mwindows 4 | LNFLAGS=-lmingw32 -lSDLmain -mwindows 5 | LIBS=-lmingw32 -lSDLmain -lSDL_ttf -lSDL -lfreetype -lz -lSDL_mixer 6 | 7 | TARGET=einstein 8 | 9 | SOURCES=puzgen.cpp main.cpp screen.cpp resources.cpp utils.cpp game.cpp \ 10 | widgets.cpp iconset.cpp puzzle.cpp rules.cpp \ 11 | verthins.cpp random.cpp horhints.cpp menu.cpp font.cpp \ 12 | conf.cpp storage.cpp tablestorage.cpp regstorage.cpp \ 13 | topscores.cpp opensave.cpp descr.cpp options.cpp messages.cpp \ 14 | formatter.cpp buffer.cpp unicode.cpp convert.cpp table.cpp \ 15 | i18n.cpp lexal.cpp streams.cpp tokenizer.cpp sound.cpp 16 | OBJECTS=puzgen.o main.o screen.o resources.o utils.o game.o \ 17 | widgets.o iconset.o puzzle.o rules.o verthints.o random.o \ 18 | horhints.o menu.o font.o conf.o storage.o options.o \ 19 | tablestorage.o regstorage.o topscores.o opensave.o descr.o \ 20 | messages.o formatter.o buffer.o unicode.o convert.o table.o \ 21 | i18n.o lexal.o streams.o tokenizer.o sound.o 22 | HEADERS=screen.h main.h exceptions.h resources.h utils.h \ 23 | widgets.h iconset.h puzzle.h verthints.h random.h horhints.h \ 24 | font.h conf.h storage.h tablestorage.h regstorage.h \ 25 | topscores.h opensave.h game.h descr.h options.h messages.h \ 26 | foramtter.h buffer.h visitor.h unicode.h convert.h table.h \ 27 | i18n.h lexal.h streams.h tokenizer.h sound.h 28 | 29 | .cpp.o: 30 | $(CXX) $(CXXFLAGS) -c $< 31 | 32 | all: $(TARGET) 33 | 34 | 35 | $(TARGET): $(OBJECTS) 36 | $(CXX) $(LNFLAGS) $(OBJECTS) $(LIBS) -o $(TARGET) 37 | 38 | clean: 39 | del $(TARGET).exe 40 | del *.o 41 | 42 | depend: 43 | @makedepend $(SOURCES) 2> /dev/null 44 | 45 | run: $(TARGET) 46 | ./$(TARGET) 47 | 48 | # DO NOT DELETE 49 | 50 | -------------------------------------------------------------------------------- /tokenizer.cpp: -------------------------------------------------------------------------------- 1 | #include "tokenizer.h" 2 | 3 | #include 4 | 5 | 6 | std::wstring Token::toString() const 7 | { 8 | if (Word == type) 9 | return L"Word: '" + content + L"'"; 10 | else if (Para == type) 11 | return L"Para"; 12 | else if (Eof == type) 13 | return L"Eof"; 14 | else 15 | return L"Unknown"; 16 | } 17 | 18 | 19 | static bool wisspace(wchar_t ch) 20 | { 21 | //std::cout << "'" << ch << "' " << ((int)ch) << " " << L'\n' << std::endl; 22 | return (L' ' == ch) || (L'\n' == ch) || (L'\r' == ch) 23 | || (L'\t' == ch) || (L'\f' == ch) || (L'\v' == ch); 24 | } 25 | 26 | 27 | bool Tokenizer::skipSpaces(bool notSearch) 28 | { 29 | int len = text.length(); 30 | bool foundDoubleReturn = false; 31 | while ((len > currentPos) && wisspace(text[currentPos])) { 32 | currentPos++; 33 | if ((! notSearch) && (L'\n' == text[currentPos - 1]) 34 | && (currentPos < len) && (L'\n' == text[currentPos])) 35 | notSearch = foundDoubleReturn = true; 36 | } 37 | return foundDoubleReturn; 38 | } 39 | 40 | 41 | Token Tokenizer::getNextToken() 42 | { 43 | if (0 < stack.size()) { 44 | Token t(*stack.begin()); 45 | stack.pop_front(); 46 | return t; 47 | } 48 | int len = text.length(); 49 | if (skipSpaces(! currentPos) && (currentPos < len)) 50 | return Token(Token::Para); 51 | if (currentPos >= len) 52 | return Token(Token::Eof); 53 | int wordStart = currentPos; 54 | while ((len > currentPos) && (! wisspace(text[currentPos]))) 55 | currentPos++; 56 | return Token(Token::Word, text.substr(wordStart, currentPos - wordStart)); 57 | } 58 | 59 | 60 | void Tokenizer::unget(const Token &token) 61 | { 62 | stack.push_back(token); 63 | } 64 | 65 | 66 | bool Tokenizer::isFinished() 67 | { 68 | if (0 < stack.size()) 69 | return false; 70 | return currentPos >= (int)text.length(); 71 | } 72 | 73 | -------------------------------------------------------------------------------- /iconset.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "iconset.h" 3 | #include "utils.h" 4 | 5 | 6 | IconSet::IconSet() 7 | { 8 | std::wstring buf = L"xy.bmp"; 9 | 10 | for (int i = 0; i < 6; i++) 11 | for (int j = 0; j < 6; j++) { 12 | buf[1] = L'1' + j; 13 | buf[0] = L'a' + i; 14 | smallIcons[i][j][0] = loadImage(buf); 15 | smallIcons[i][j][1] = adjustBrightness(smallIcons[i][j][0], 1.5, false); 16 | buf[0] = L'A' + i; 17 | largeIcons[i][j][0] = loadImage(buf); 18 | largeIcons[i][j][1] = adjustBrightness(largeIcons[i][j][0], 1.5, false); 19 | } 20 | emptyFieldIcon = loadImage(L"tile.bmp"); 21 | emptyHintIcon = loadImage(L"hint-tile.bmp"); 22 | nearHintIcon[0] = loadImage(L"hint-near.bmp"); 23 | nearHintIcon[1] = adjustBrightness(nearHintIcon[0], 1.5, false); 24 | sideHintIcon[0] = loadImage(L"hint-side.bmp"); 25 | sideHintIcon[1] = adjustBrightness(sideHintIcon[0], 1.5, false); 26 | betweenArrow[0] = loadImage(L"betwarr.bmp", true); 27 | betweenArrow[1] = adjustBrightness(betweenArrow[0], 1.5, false); 28 | } 29 | 30 | IconSet::~IconSet() 31 | { 32 | for (int i = 0; i < 6; i++) 33 | for (int j = 0; j < 6; j++) 34 | for (int k = 0; k < 2; k++) { 35 | SDL_FreeSurface(smallIcons[i][j][k]); 36 | SDL_FreeSurface(largeIcons[i][j][k]); 37 | } 38 | SDL_FreeSurface(emptyFieldIcon); 39 | SDL_FreeSurface(emptyHintIcon); 40 | SDL_FreeSurface(nearHintIcon[0]); 41 | SDL_FreeSurface(nearHintIcon[1]); 42 | SDL_FreeSurface(sideHintIcon[0]); 43 | SDL_FreeSurface(sideHintIcon[1]); 44 | SDL_FreeSurface(betweenArrow[0]); 45 | SDL_FreeSurface(betweenArrow[1]); 46 | } 47 | 48 | SDL_Surface* IconSet::getLargeIcon(int row, int num, bool h) 49 | { 50 | return largeIcons[row][num-1][h ? 1 : 0]; 51 | } 52 | 53 | SDL_Surface* IconSet::getSmallIcon(int row, int num, bool h) 54 | { 55 | return smallIcons[row][num-1][h ? 1 : 0]; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /res/rules.txt: -------------------------------------------------------------------------------- 1 | rulesText = " 2 | 3 | The game goal is to open all cards in square of 6x6 cards. When 4 | every card is open, field looks like this: 5 | 6 | $opensquare.bmp$ 7 | 8 | Every row of square contains cards of one type only. For example, 9 | first row contains arabic digits, second - letters, third - rome digits, 10 | fouths - dices, fifth - geometric figures, sixs - mathematic symbols. 11 | 12 | Use logic and open cards with method of exclusion. If card doesn't 13 | opened, cell contains every possible cards. For example, 14 | 15 | $closed.bmp$ 16 | 17 | means that this cell may contain every rome digit with exception of 18 | III (because card with III image is absent). To open card click on 19 | small image with left mouse button. To exclude card click with right 20 | mouse button. 21 | 22 | Use tips to solve this puzzle. There is two types of tips: 23 | horizontal and vertical. Vertical tips located at screen bottom. 24 | For example, vertical tip 25 | 26 | $verthint.bmp$ 27 | 28 | means that letter 'B' and '+' sign located in the same column. 29 | 30 | Horizontal tips located at the right side of the puzzle square. 31 | There is few type of horizontal tips. First type of horizontal 32 | tip says that two cards located at neighbour columns, but it is 33 | unknown, which one is at the right side and thich is at the left: 34 | 35 | $hornearhint.bmp$ 36 | 37 | Second tip type means that one cards is at the left of another. 38 | It says nothing about distance between that cards. They may be 39 | neighbour columns or at the opposite sides of puzzle field: 40 | 41 | $horposhint.bmp$ 42 | 43 | The last type of tip means that one card is located between 44 | two another cards: 45 | 46 | $horbetweenhint.bmp$ 47 | 48 | All three cards must be located in neighbour columns, central 49 | card is always between other two, but it is unknown, which card is located 50 | at the right side and which at the left. 51 | 52 | If you no longer need some tip, remove it by right mouse button click. 53 | You can always see removed tips by pressing 'Switch' button. 54 | 55 | 56 | " 57 | 58 | -------------------------------------------------------------------------------- /mkres/compressor.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMPRESSOR_H__ 2 | #define __COMPRESSOR_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "format.h" 10 | 11 | 12 | 13 | class Entry 14 | { 15 | public: 16 | std::wstring name; 17 | int realSize; 18 | int offset; 19 | int packedSize; 20 | int comprLevel; 21 | std::wstring group; 22 | std::wstring fileName; 23 | Formatter *formatter; 24 | 25 | public: 26 | Entry(const std::wstring &n, int level, const std::wstring &grp, 27 | const std::wstring &fn, Formatter *frmt): 28 | name(n), group(grp), fileName(fn) 29 | 30 | { 31 | comprLevel = level; 32 | offset = packedSize = realSize = 0; 33 | formatter = frmt; 34 | }; 35 | }; 36 | 37 | 38 | class ResourceCompressor 39 | { 40 | private: 41 | typedef std::list Entries; 42 | Entries entries; 43 | int priority; 44 | Buffer unpackedBuffer, packedBuffer; 45 | std::ostream *stream; 46 | bool dontDeleteStream; 47 | 48 | public: 49 | ResourceCompressor(); 50 | ~ResourceCompressor(); 51 | 52 | public: 53 | void add(const Entry &entry) { entries.push_back(entry); } 54 | void setPriority(int p) { priority = p; }; 55 | void compress(const std::string &outputFile, bool verbose); 56 | void printDeps(const std::string &outputFile, 57 | const std::string &sourceFile); 58 | 59 | private: 60 | void adjustBuffers(int fileSize); 61 | int writeHeader(); 62 | void compressEntry(Entry &entry, int &offset); 63 | void showEntryStat(Entry &entry); 64 | void writeFooter(int &offset); 65 | void openStream(const std::string &outputFile); 66 | void closeStream(); 67 | void readData(const std::wstring &fileName); 68 | void runFormatter(Formatter *formatter, const std::wstring &fileName); 69 | }; 70 | 71 | 72 | #endif 73 | 74 | -------------------------------------------------------------------------------- /screen.h: -------------------------------------------------------------------------------- 1 | #ifndef __SCREEN_H__ 2 | #define __SCREEN_H__ 3 | 4 | 5 | #include "SDL/SDL.h" 6 | #include 7 | #include 8 | 9 | 10 | class VideoMode 11 | { 12 | private: 13 | int width; 14 | int height; 15 | int bpp; 16 | bool fullScreen; 17 | 18 | public: 19 | VideoMode(int w, int h, int bpp, bool fullscreen) 20 | { 21 | width = w; 22 | height = h; 23 | this->bpp = bpp; 24 | this->fullScreen = fullscreen; 25 | } 26 | 27 | public: 28 | int getWidth() const { return width; }; 29 | int getHeight() const { return height; }; 30 | int getBpp() const { return bpp; }; 31 | bool isFullScreen() const { return fullScreen; }; 32 | }; 33 | 34 | 35 | class Screen 36 | { 37 | private: 38 | SDL_Surface *screen; 39 | bool fullScreen; 40 | SDL_Surface *mouseImage; 41 | SDL_Surface *mouseSave; 42 | std::list regions; 43 | bool mouseVisible; 44 | SDL_Rect *regionsList; 45 | int maxRegionsList; 46 | int saveX, saveY; 47 | bool niceCursor; 48 | SDL_Cursor *cursor, *emptyCursor; 49 | 50 | public: 51 | Screen(); 52 | ~Screen(); 53 | 54 | public: 55 | const VideoMode getVideoMode() const; 56 | int getWidth() const; 57 | int getHeight() const; 58 | void setMode(const VideoMode& mode); 59 | std::vector getFullScreenModes() const; 60 | void centerMouse(); 61 | void setMouseImage(SDL_Surface *image); 62 | void hideMouse(); 63 | void showMouse(); 64 | void updateMouse(); 65 | void flush(); 66 | void addRegionToUpdate(int x, int y, int w, int h); 67 | void setPixel(int x, int y, int r, int g, int b); 68 | SDL_Surface* getSurface() { return screen; }; 69 | void draw(int x, int y, SDL_Surface *surface); 70 | void setCursor(bool nice); 71 | void initCursors(); 72 | void doneCursors(); 73 | SDL_Surface* createSubimage(int x, int y, int width, int height); 74 | }; 75 | 76 | 77 | #endif 78 | 79 | -------------------------------------------------------------------------------- /puzgen.h: -------------------------------------------------------------------------------- 1 | #ifndef __PUZGEN_H__ 2 | #define __PUZGEN_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include "iconset.h" 9 | 10 | 11 | #define PUZZLE_SIZE 6 12 | 13 | 14 | typedef short SolvedPuzzle[PUZZLE_SIZE][PUZZLE_SIZE]; 15 | 16 | 17 | class Possibilities 18 | { 19 | private: 20 | short pos[PUZZLE_SIZE][PUZZLE_SIZE][PUZZLE_SIZE]; 21 | 22 | public: 23 | Possibilities(); 24 | Possibilities(std::istream &stream); 25 | 26 | public: 27 | void exclude(int col, int row, int element); 28 | void set(int col, int row, int element); 29 | bool isPossible(int col, int row, int element); 30 | bool isDefined(int col, int row); 31 | int getDefined(int col, int row); 32 | int getPosition(int row, int element); 33 | bool isSolved(); 34 | void print(); 35 | bool isValid(SolvedPuzzle &puzzle); 36 | void makePossible(int col, int row, int element); 37 | void save(std::ostream &stream); 38 | void reset(); 39 | void checkSingles(int row); 40 | }; 41 | 42 | 43 | class Rule 44 | { 45 | public: 46 | typedef enum { 47 | SHOW_VERT, 48 | SHOW_HORIZ, 49 | SHOW_NOTHING 50 | } ShowOptions; 51 | 52 | public: 53 | virtual ~Rule() { }; 54 | 55 | public: 56 | virtual std::wstring getAsText() = 0; 57 | virtual bool apply(Possibilities &pos) = 0; 58 | virtual bool applyOnStart() { return false; }; 59 | virtual ShowOptions getShowOpts() { return SHOW_NOTHING; }; 60 | virtual void draw(int x, int y, IconSet &iconSet, bool highlight) = 0; 61 | virtual void save(std::ostream &stream) = 0; 62 | }; 63 | 64 | 65 | typedef std::list Rules; 66 | 67 | 68 | void genPuzzle(SolvedPuzzle &puzzle, Rules &rules); 69 | void openInitial(Possibilities &possib, Rules &rules); 70 | Rule* genRule(SolvedPuzzle &puzzle); 71 | void getHintsQty(Rules &rules, int &vert, int &horiz); 72 | Rule* getRule(Rules &rules, int no); 73 | 74 | void savePuzzle(SolvedPuzzle &puzzle, std::ostream &stream); 75 | void loadPuzzle(SolvedPuzzle &puzzle, std::istream &stream); 76 | void saveRules(Rules &rules, std::ostream &stream); 77 | void loadRules(Rules &rules, std::istream &stream); 78 | 79 | 80 | #endif 81 | 82 | -------------------------------------------------------------------------------- /buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "buffer.h" 2 | #include 3 | #include "exceptions.h" 4 | #include "unicode.h" 5 | 6 | 7 | Buffer::Buffer(int sz, int alloc) 8 | { 9 | allocated = alloc; 10 | size = sz; 11 | if (size > allocated) 12 | allocated = size; 13 | if (allocated < 1024) 14 | allocated = 1024; 15 | data = malloc(allocated); 16 | if (! data) 17 | throw Exception(L"Error allocating memory for Buffer"); 18 | } 19 | 20 | Buffer::~Buffer() 21 | { 22 | free(data); 23 | } 24 | 25 | void Buffer::setSize(size_t sz) 26 | { 27 | if (sz > allocated) { 28 | int newAl = allocated + sz + 1024; 29 | void *d = realloc(data, newAl); 30 | if (! d) 31 | throw Exception(L"Error expanding buffer memory"); 32 | data = d; 33 | allocated = newAl; 34 | } 35 | 36 | size = sz; 37 | } 38 | 39 | size_t Buffer::getSize() 40 | { 41 | return size; 42 | } 43 | 44 | size_t Buffer::getAllocated() 45 | { 46 | return allocated; 47 | } 48 | 49 | void* Buffer::getData() 50 | { 51 | return data; 52 | } 53 | 54 | 55 | void Buffer::gotoPos(int offset) 56 | { 57 | currentPos = offset; 58 | } 59 | 60 | 61 | size_t Buffer::putData(const unsigned char *d, size_t length) 62 | { 63 | if (size < currentPos + length) 64 | setSize(currentPos + length); 65 | memcpy((unsigned char*)data + currentPos, d, length); 66 | currentPos += length; 67 | return length; 68 | } 69 | 70 | 71 | size_t Buffer::putInteger(int v) 72 | { 73 | unsigned char b[4]; 74 | int i, ib; 75 | 76 | for (i = 0; i < 4; i++) { 77 | ib = v & 0xFF; 78 | v = v >> 8; 79 | b[i] = ib; 80 | } 81 | 82 | return putData(b, 4); 83 | } 84 | 85 | 86 | size_t Buffer::putUtf8(const std::wstring &string) 87 | { 88 | std::string s(toUtf8(string)); 89 | putInteger(s.length()); 90 | putData((const unsigned char*)s.c_str(), s.length()); 91 | return 4 + s.length(); 92 | } 93 | 94 | 95 | size_t Buffer::putByte(unsigned char value) 96 | { 97 | if (size < (size_t)currentPos + 1) 98 | setSize(currentPos + 1); 99 | ((unsigned char*)data)[currentPos] = value; 100 | currentPos++; 101 | return 1; 102 | } 103 | 104 | 105 | -------------------------------------------------------------------------------- /mkres/buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "buffer.h" 2 | #include 3 | #include "exceptions.h" 4 | #include "unicode.h" 5 | 6 | 7 | Buffer::Buffer(int sz, int alloc) 8 | { 9 | allocated = alloc; 10 | size = sz; 11 | if (size > allocated) 12 | allocated = size; 13 | if (allocated < 1024) 14 | allocated = 1024; 15 | data = malloc(allocated); 16 | if (! data) 17 | throw Exception(L"Error allocating memory for Buffer"); 18 | } 19 | 20 | Buffer::~Buffer() 21 | { 22 | free(data); 23 | } 24 | 25 | void Buffer::setSize(size_t sz) 26 | { 27 | if (sz > allocated) { 28 | int newAl = allocated + sz + 1024; 29 | void *d = realloc(data, newAl); 30 | if (! d) 31 | throw Exception(L"Error expanding buffer memory"); 32 | data = d; 33 | allocated = newAl; 34 | } 35 | 36 | size = sz; 37 | } 38 | 39 | size_t Buffer::getSize() 40 | { 41 | return size; 42 | } 43 | 44 | size_t Buffer::getAllocated() 45 | { 46 | return allocated; 47 | } 48 | 49 | void* Buffer::getData() 50 | { 51 | return data; 52 | } 53 | 54 | 55 | void Buffer::gotoPos(int offset) 56 | { 57 | currentPos = offset; 58 | } 59 | 60 | 61 | size_t Buffer::putData(const unsigned char *d, size_t length) 62 | { 63 | if (size < currentPos + length) 64 | setSize(currentPos + length); 65 | memcpy((unsigned char*)data + currentPos, d, length); 66 | currentPos += length; 67 | return length; 68 | } 69 | 70 | 71 | size_t Buffer::putInteger(int v) 72 | { 73 | unsigned char b[4]; 74 | int i, ib; 75 | 76 | for (i = 0; i < 4; i++) { 77 | ib = v & 0xFF; 78 | v = v >> 8; 79 | b[i] = ib; 80 | } 81 | 82 | return putData(b, 4); 83 | } 84 | 85 | 86 | size_t Buffer::putUtf8(const std::wstring &string) 87 | { 88 | std::string s(toUtf8(string)); 89 | putInteger(s.length()); 90 | putData((const unsigned char*)s.c_str(), s.length()); 91 | return 4 + s.length(); 92 | } 93 | 94 | 95 | size_t Buffer::putByte(unsigned char value) 96 | { 97 | if (size < (size_t)currentPos + 1) 98 | setSize(currentPos + 1); 99 | ((unsigned char*)data)[currentPos] = value; 100 | currentPos++; 101 | return 1; 102 | } 103 | 104 | 105 | -------------------------------------------------------------------------------- /Makefile.macosx: -------------------------------------------------------------------------------- 1 | ######################################## 2 | # 3 | # build parameters 4 | # 5 | ######################################## 6 | 7 | # installation prefix 8 | PREFIX=/usr/local 9 | 10 | ######################################## 11 | # 12 | # do not modify rest of this file 13 | # 14 | ######################################## 15 | 16 | OPTIMIZE=#-O6 -march=pentium4 -mfpmath=sse -fomit-frame-pointer -funroll-loops 17 | PROFILER=#-pg 18 | DEBUG=-ggdb 19 | CXXFLAGS=-pipe -Wall $(OPTIMIZE) $(DEBUG) -I/Library/Frameworks/SDL.framework/Headers/ -I/Library/Frameworks/SDL_ttf.framework/Headers/ -I/Library/Frameworks/SDL_mixer.framework/Headers/ -DPREFIX=L\"$(PREFIX)\" $(PROFILER) 20 | LNFLAGS=-pipe -framework Cocoa -framework SDL_ttf -framework SDL -framework SDL_mixer -lSDLmain -lz $(PROFILER) 21 | 22 | TARGET=einstein 23 | 24 | SOURCES=puzgen.cpp main.cpp screen.cpp resources.cpp utils.cpp game.cpp \ 25 | widgets.cpp iconset.cpp puzzle.cpp rules.cpp \ 26 | verthins.cpp random.cpp horhints.cpp menu.cpp font.cpp \ 27 | conf.cpp storage.cpp tablestorage.cpp regstorage.cpp \ 28 | topscores.cpp opensave.cpp descr.cpp options.cpp messages.cpp \ 29 | formatter.cpp buffer.cpp unicode.cpp convert.cpp table.cpp \ 30 | i18n.cpp lexal.cpp streams.cpp tokenizer.cpp sound.cpp 31 | OBJECTS=puzgen.o main.o screen.o resources.o utils.o game.o \ 32 | widgets.o iconset.o puzzle.o rules.o verthints.o random.o \ 33 | horhints.o menu.o font.o conf.o storage.o options.o \ 34 | tablestorage.o regstorage.o topscores.o opensave.o descr.o \ 35 | messages.o formatter.o buffer.o unicode.o convert.o table.o \ 36 | i18n.o lexal.o streams.o tokenizer.o sound.o 37 | HEADERS=screen.h main.h exceptions.h resources.h utils.h \ 38 | widgets.h iconset.h puzzle.h verthints.h random.h horhints.h \ 39 | font.h conf.h storage.h tablestorage.h regstorage.h \ 40 | topscores.h opensave.h game.h descr.h options.h messages.h \ 41 | foramtter.h buffer.h visitor.h unicode.h convert.h table.h \ 42 | i18n.h lexal.h streams.h tokenizer.h sound.h 43 | 44 | .cpp.o: 45 | $(CXX) $(CXXFLAGS) -c $< 46 | 47 | all: $(TARGET) 48 | 49 | 50 | $(TARGET): $(OBJECTS) 51 | $(CXX) $(LNFLAGS) $(OBJECTS) -o $(TARGET) 52 | 53 | clean: 54 | rm -f $(OBJECTS) core* *core $(TARGET) *~ 55 | 56 | depend: 57 | @makedepend $(SOURCES) 2> /dev/null 58 | 59 | run: $(TARGET) 60 | ./$(TARGET) 61 | 62 | # DO NOT DELETE 63 | 64 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ######################################## 2 | # 3 | # build parameters 4 | # 5 | ######################################## 6 | 7 | # installation prefix 8 | PREFIX=/usr/local 9 | 10 | ######################################## 11 | # 12 | # do not modify rest of this file 13 | # 14 | ######################################## 15 | 16 | OPTIMIZE=#-O6 -march=pentium4 -mfpmath=sse -fomit-frame-pointer -funroll-loops 17 | PROFILER=#-pg 18 | DEBUG=#-ggdb 19 | CXXFLAGS=-pipe -Wall $(OPTIMIZE) $(DEBUG) `sdl-config --cflags` -DPREFIX=L\"$(PREFIX)\" $(PROFILER) 20 | LNFLAGS=-pipe -lSDL_ttf -lfreetype `sdl-config --libs` -lz -lSDL_mixer $(PROFILER) 21 | INSTALL=install 22 | 23 | TARGET=einstein 24 | 25 | SOURCES=puzgen.cpp main.cpp screen.cpp resources.cpp utils.cpp game.cpp \ 26 | widgets.cpp iconset.cpp puzzle.cpp rules.cpp \ 27 | verthins.cpp random.cpp horhints.cpp menu.cpp font.cpp \ 28 | conf.cpp storage.cpp tablestorage.cpp regstorage.cpp \ 29 | topscores.cpp opensave.cpp descr.cpp options.cpp messages.cpp \ 30 | formatter.cpp buffer.cpp unicode.cpp convert.cpp table.cpp \ 31 | i18n.cpp lexal.cpp streams.cpp tokenizer.cpp sound.cpp 32 | OBJECTS=puzgen.o main.o screen.o resources.o utils.o game.o \ 33 | widgets.o iconset.o puzzle.o rules.o verthints.o random.o \ 34 | horhints.o menu.o font.o conf.o storage.o options.o \ 35 | tablestorage.o regstorage.o topscores.o opensave.o descr.o \ 36 | messages.o formatter.o buffer.o unicode.o convert.o table.o \ 37 | i18n.o lexal.o streams.o tokenizer.o sound.o 38 | HEADERS=screen.h main.h exceptions.h resources.h utils.h \ 39 | widgets.h iconset.h puzzle.h verthints.h random.h horhints.h \ 40 | font.h conf.h storage.h tablestorage.h regstorage.h \ 41 | topscores.h opensave.h game.h descr.h options.h messages.h \ 42 | foramtter.h buffer.h visitor.h unicode.h convert.h table.h \ 43 | i18n.h lexal.h streams.h tokenizer.h sound.h 44 | 45 | .cpp.o: 46 | $(CXX) $(CXXFLAGS) -c $< 47 | 48 | all: $(TARGET) 49 | 50 | 51 | $(TARGET): $(OBJECTS) 52 | $(CXX) $(LNFLAGS) $(OBJECTS) -o $(TARGET) 53 | 54 | clean: 55 | rm -f $(OBJECTS) core* *core $(TARGET) *~ 56 | 57 | depend: 58 | @makedepend $(SOURCES) 2> /dev/null 59 | 60 | run: $(TARGET) 61 | ./$(TARGET) 62 | 63 | install: $(TARGET) 64 | $(INSTALL) -s -D $(TARGET) $(PREFIX)/bin/$(TARGET) 65 | $(INSTALL) -D einstein.res $(PREFIX)/share/einstein/res/einstein.res 66 | 67 | # DO NOT DELETE THIS LINE -- make depend depends on it. 68 | 69 | -------------------------------------------------------------------------------- /buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUFFER_H__ 2 | #define __BUFFER_H__ 3 | 4 | 5 | #include 6 | #include 7 | 8 | 9 | /// Dynamic growing buffer 10 | class Buffer 11 | { 12 | private: 13 | size_t size; 14 | size_t allocated; 15 | void *data; 16 | int currentPos; 17 | 18 | public: 19 | /// Create buffer 20 | /// \param size initial size of buffer 21 | /// \param allocated bytes to allocate 22 | Buffer(int size=0, int allocated=1024); 23 | 24 | ~Buffer(); 25 | 26 | public: 27 | /// Set buffer size, expands memory if needed 28 | /// \param size new size 29 | void setSize(size_t size); 30 | 31 | /// Get current size of buffer 32 | size_t getSize(); 33 | 34 | /// Get actual bytes used by buffer 35 | size_t getAllocated(); 36 | 37 | /// Get pointer to data 38 | void* getData(); 39 | 40 | public: 41 | /// Move pointer to specified position. 42 | /// \param offset offset from buffer start 43 | void gotoPos(int offset); 44 | 45 | /// Add data to buffer and advance current position by data length. 46 | /// Grow buffer if needed. 47 | /// \param data pointer to data 48 | /// \param length data size. 49 | size_t putData(const unsigned char *data, size_t length); 50 | 51 | /// Add data to buffer and advance current position by data length. 52 | /// Grow buffer if needed. 53 | /// \param data pointer to data 54 | /// \param length data size. 55 | size_t putData(const char *data, size_t length) { 56 | return putData((const unsigned char*)data, length); 57 | }; 58 | 59 | /// Add integer to buffer and advance current position by 4. 60 | /// Grow buffer if needed. 61 | /// \param value value to add. 62 | size_t putInteger(int value); 63 | 64 | /// Add string to buffer encoded in UTF-8 and advance current 65 | /// position by string length. String stored prefixed by 66 | /// string length. 67 | /// Grow buffer if needed. 68 | /// \param string value to add. 69 | size_t putUtf8(const std::wstring &string); 70 | 71 | /// Add byte to buffer and advance current position by 1. 72 | /// Grow buffer if needed. 73 | /// \param value value to add. 74 | size_t putByte(unsigned char value); 75 | }; 76 | 77 | 78 | #endif 79 | 80 | -------------------------------------------------------------------------------- /mkres/buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUFFER_H__ 2 | #define __BUFFER_H__ 3 | 4 | 5 | #include 6 | #include 7 | 8 | 9 | /// Dynamic growing buffer 10 | class Buffer 11 | { 12 | private: 13 | size_t size; 14 | size_t allocated; 15 | void *data; 16 | int currentPos; 17 | 18 | public: 19 | /// Create buffer 20 | /// \param size initial size of buffer 21 | /// \param allocated bytes to allocate 22 | Buffer(int size=0, int allocated=1024); 23 | 24 | ~Buffer(); 25 | 26 | public: 27 | /// Set buffer size, expands memory if needed 28 | /// \param size new size 29 | void setSize(size_t size); 30 | 31 | /// Get current size of buffer 32 | size_t getSize(); 33 | 34 | /// Get actual bytes used by buffer 35 | size_t getAllocated(); 36 | 37 | /// Get pointer to data 38 | void* getData(); 39 | 40 | public: 41 | /// Move pointer to specified position. 42 | /// \param offset offset from buffer start 43 | void gotoPos(int offset); 44 | 45 | /// Add data to buffer and advance current position by data length. 46 | /// Grow buffer if needed. 47 | /// \param data pointer to data 48 | /// \param length data size. 49 | size_t putData(const unsigned char *data, size_t length); 50 | 51 | /// Add data to buffer and advance current position by data length. 52 | /// Grow buffer if needed. 53 | /// \param data pointer to data 54 | /// \param length data size. 55 | size_t putData(const char *data, size_t length) { 56 | return putData((const unsigned char*)data, length); 57 | }; 58 | 59 | /// Add integer to buffer and advance current position by 4. 60 | /// Grow buffer if needed. 61 | /// \param value value to add. 62 | size_t putInteger(int value); 63 | 64 | /// Add string to buffer encoded in UTF-8 and advance current 65 | /// position by string length. String stored prefixed by 66 | /// string length. 67 | /// Grow buffer if needed. 68 | /// \param string value to add. 69 | size_t putUtf8(const std::wstring &string); 70 | 71 | /// Add byte to buffer and advance current position by 1. 72 | /// Grow buffer if needed. 73 | /// \param value value to add. 74 | size_t putByte(unsigned char value); 75 | }; 76 | 77 | 78 | #endif 79 | 80 | -------------------------------------------------------------------------------- /res/rules_ru.txt: -------------------------------------------------------------------------------- 1 | rulesText = " 2 | 3 | Правила игры очень простые: надо открыть все фишки в квадрате 4 | 6x6 фишек. После того как все фишки будут открыты, 5 | квадрат будет выглядить следующим образом: 6 | 7 | $opensquare.bmp$ 8 | 9 | В каждой строке квадрата находятся фишки одного типа. Например, 10 | в первой строке квадрата находятся арабские цифры, 11 | во второй - латинские буквы, в третьей - римские цифры, 12 | в четвертой - игральные кости, в пятой - геометрические фигуры, 13 | в шестой - математические символы. 14 | 15 | Открывать фишки надо методом исключения. Когда фишка не 16 | открыта на ее месте показываются все возможные варианты. 17 | Например, изображение 18 | 19 | $closed.bmp$ 20 | 21 | обозначает что в данном месте могут находится любые римские 22 | цифры кроме III (квадратик с изображением III отсутствует). 23 | Чтобы открыть фишку надо нажать на ее уменьшенное изображение 24 | левой кнопкой мыши, чтобы исключить фишку - нажмите на ней 25 | правой кнопкой мыши. 26 | 27 | Для того, чтобы решить головоломку нужно использовать подсказки. 28 | Подсказки бывают двух типов: вертикальные и горизонтальные. 29 | Вертикальные подсказки находятся внизу экрана и выглядят так: 30 | 31 | $verthint.bmp$ 32 | 33 | Такая подсказка обозначает что буква 'B' и знак '+' находятся 34 | в одной колонке, при этом не важно, какой из этих символов находится 35 | выше, а какой - ниже. 36 | 37 | Горизонтальные подсказки расположены в правой части экрана. 38 | Они делятся на несколько типов. Самая простая подсказка говорит 39 | о том что две фишки находятся в соседних колонках, при этом не 40 | известно, какая из фишек находится левее а какая правее: 41 | 42 | $hornearhint.bmp$ 43 | 44 | Подсказка следующего типа говорит о том что одна фишка 45 | находится в колонке левее другой. Эта подсказка ничего 46 | не говорит о том на каком расстоянии друг от друга находятся фишки. 47 | Они могут оказаться как в соседних колонках так и находится 48 | на значительном расстоянии друг от друга: 49 | 50 | $horposhint.bmp$ 51 | 52 | Последний тип подсказки указывает что одна фишка находится между 53 | двумя другими: 54 | 55 | $horbetweenhint.bmp$ 56 | 57 | Все три фишки всегда находятся в соседних колонках, фишка 58 | указанная в центре всегда находится между двумя другими, но какая 59 | фишка правее центральной а какая левее - неизвестно. 60 | 61 | Использованные подсказки удобно удалять пользуясь правой кнопкой мыши. 62 | Удаленные подсказки можно посмотреть нажав на кнопку 'Скрытые'. 63 | Повторное нажатие на эту кнопку снова покажет неудаленные подсказки. 64 | 65 | " 66 | -------------------------------------------------------------------------------- /table.h: -------------------------------------------------------------------------------- 1 | #ifndef __TABLE_H__ 2 | #define __TABLE_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include "lexal.h" 8 | 9 | 10 | class Table; 11 | 12 | 13 | class Value 14 | { 15 | public: 16 | typedef enum Type { 17 | Integer, 18 | Double, 19 | String, 20 | Table 21 | }; 22 | 23 | public: 24 | virtual ~Value() { }; 25 | 26 | public: 27 | virtual ::Table* asTable() const = 0; 28 | virtual Type getType() const = 0; 29 | virtual int asInt() const = 0; 30 | virtual double asDouble() const = 0; 31 | virtual std::wstring asString() const = 0; 32 | virtual Value* clone() const = 0; 33 | }; 34 | 35 | 36 | class Table 37 | { 38 | public: 39 | typedef std::map ValuesMap; 40 | typedef ValuesMap::const_iterator Iterator; 41 | 42 | private: 43 | ValuesMap fields; 44 | int lastArrayIndex; 45 | 46 | public: 47 | Table(); 48 | Table(const Table &table); 49 | Table(const std::string &fileName); 50 | Table(Lexal &lexal, int startLine, int startPos); 51 | ~Table(); 52 | 53 | public: 54 | Table& operator = (const Table &table); 55 | std::wstring toString() const; 56 | std::wstring toString(bool printBraces, bool butify, int ident) const; 57 | bool isArray() const; 58 | void save(const std::wstring &fileName) const; 59 | 60 | public: 61 | Iterator begin() const { return fields.begin(); }; 62 | Iterator end() const { return fields.end(); }; 63 | bool hasKey(const std::wstring &key) const; 64 | Value::Type getType(const std::wstring &key) const; 65 | std::wstring getString(const std::wstring &key, const std::wstring &dflt = L"") const; 66 | int getInt(const std::wstring &key, int dflt=0) const; 67 | double getDouble(const std::wstring &key, double dflt=0) const; 68 | Table* getTable(const std::wstring &key, Table *dflt=NULL) const; 69 | void setString(const std::wstring &key, const std::wstring &value); 70 | void setInt(const std::wstring &key, int value); 71 | void setDouble(const std::wstring &key, double value); 72 | void setTable(const std::wstring &key, Table *value); 73 | 74 | private: 75 | void parse(Lexal &lexal, bool needBracket, int startLine, int startPos); 76 | void addArrayElement(Lexal &lexal, const Lexeme &lexeme); 77 | void addValuePair(Lexal &lexal, const std::wstring &name); 78 | void setValue(const std::wstring &key, Value *value); 79 | }; 80 | 81 | 82 | 83 | #endif 84 | 85 | -------------------------------------------------------------------------------- /mkres/table.h: -------------------------------------------------------------------------------- 1 | #ifndef __TABLE_H__ 2 | #define __TABLE_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include "lexal.h" 8 | 9 | 10 | class Table; 11 | 12 | 13 | class Value 14 | { 15 | public: 16 | typedef enum Type { 17 | Integer, 18 | Double, 19 | String, 20 | Table 21 | }; 22 | 23 | public: 24 | virtual ~Value() { }; 25 | 26 | public: 27 | virtual ::Table* asTable() const = 0; 28 | virtual Type getType() const = 0; 29 | virtual int asInt() const = 0; 30 | virtual double asDouble() const = 0; 31 | virtual std::wstring asString() const = 0; 32 | virtual Value* clone() const = 0; 33 | }; 34 | 35 | 36 | class Table 37 | { 38 | public: 39 | typedef std::map ValuesMap; 40 | typedef ValuesMap::const_iterator Iterator; 41 | 42 | private: 43 | ValuesMap fields; 44 | int lastArrayIndex; 45 | 46 | public: 47 | Table(); 48 | Table(const Table &table); 49 | Table(const std::string &fileName); 50 | Table(Lexal &lexal, int startLine, int startPos); 51 | ~Table(); 52 | 53 | public: 54 | Table& operator = (const Table &table); 55 | std::wstring toString() const; 56 | std::wstring toString(bool printBraces, bool butify, int ident) const; 57 | bool isArray() const; 58 | void save(const std::wstring &fileName) const; 59 | 60 | public: 61 | Iterator begin() const { return fields.begin(); }; 62 | Iterator end() const { return fields.end(); }; 63 | bool hasKey(const std::wstring &key) const; 64 | Value::Type getType(const std::wstring &key) const; 65 | std::wstring getString(const std::wstring &key, const std::wstring &dflt = L"") const; 66 | int getInt(const std::wstring &key, int dflt=0) const; 67 | double getDouble(const std::wstring &key, double dflt=0) const; 68 | Table* getTable(const std::wstring &key, Table *dflt=NULL) const; 69 | void setString(const std::wstring &key, const std::wstring &value); 70 | void setInt(const std::wstring &key, int value); 71 | void setDouble(const std::wstring &key, double value); 72 | void setTable(const std::wstring &key, Table *value); 73 | 74 | private: 75 | void parse(Lexal &lexal, bool needBracket, int startLine, int startPos); 76 | void addArrayElement(Lexal &lexal, const Lexeme &lexeme); 77 | void addValuePair(Lexal &lexal, const std::wstring &name); 78 | void setValue(const std::wstring &key, Value *value); 79 | }; 80 | 81 | 82 | 83 | #endif 84 | 85 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "main.h" 7 | #include "utils.h" 8 | #include "storage.h" 9 | #include "unicode.h" 10 | #include "messages.h" 11 | #include "sound.h" 12 | 13 | 14 | Screen screen; 15 | Random rndGen; 16 | 17 | 18 | static void initScreen() 19 | { 20 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) 21 | throw Exception(std::wstring(L"Error initializing SDL: ") + 22 | fromMbcs(SDL_GetError())); 23 | atexit(SDL_Quit); 24 | if (TTF_Init()) 25 | throw Exception(L"Error initializing font engine"); 26 | screen.setMode(VideoMode(800, 600, 24, 27 | getStorage()->get(L"fullscreen", 1) != 0)); 28 | screen.initCursors(); 29 | 30 | SDL_Surface *mouse = loadImage(L"cursor.bmp"); 31 | SDL_SetColorKey(mouse, SDL_SRCCOLORKEY, SDL_MapRGB(mouse->format, 0, 0, 0)); 32 | screen.setMouseImage(mouse); 33 | SDL_FreeSurface(mouse); 34 | SDL_WM_SetCaption("Einstein", NULL); 35 | 36 | #ifdef __APPLE__ 37 | screen.setCursor(false); 38 | #else 39 | screen.setCursor(getStorage()->get(L"niceCursor", 1)); 40 | #endif 41 | } 42 | 43 | static void initAudio() 44 | { 45 | sound = new Sound(); 46 | sound->setVolume((float)getStorage()->get(L"volume", 20) / 100.0f); 47 | } 48 | 49 | 50 | #ifdef __APPLE__ 51 | static std::wstring getResourcesPath(const std::wstring& path) 52 | { 53 | int idx = path.find_last_of(L'/'); 54 | return path.substr(0, idx) + L"/../../"; 55 | } 56 | #endif 57 | 58 | static void loadResources(const std::wstring &selfPath) 59 | { 60 | StringList dirs; 61 | #ifdef WIN32 62 | dirs.push_back(getStorage()->get(L"path", L"") + L"\\res"); 63 | #else 64 | #ifdef __APPLE__ 65 | dirs.push_back(getResourcesPath(selfPath)); 66 | #else 67 | dirs.push_back("/usr" L"/share/einstein/res"); 68 | dirs.push_back(fromMbcs(getenv("HOME")) + L"/.einstein/res"); 69 | #endif 70 | #endif 71 | dirs.push_back(L"res"); 72 | dirs.push_back(L"."); 73 | resources = new ResourcesCollection(dirs); 74 | msg.load(); 75 | } 76 | 77 | 78 | /*static void checkBetaExpire() 79 | { 80 | if (1124832535L + 60L*60L*24L*40L < time(NULL)) { 81 | Font font(L"laudcn2.ttf", 16); 82 | Area area; 83 | showMessageWindow(&area, L"darkpattern.bmp", 84 | 700, 100, &font, 255,255,255, 85 | msg(L"expired")); 86 | } 87 | }*/ 88 | 89 | 90 | 91 | int main(int argc, char *argv[]) 92 | { 93 | #ifndef WIN32 94 | ensureDirExists(fromMbcs(getenv("HOME")) + std::wstring(L"/.einstein")); 95 | #endif 96 | 97 | try { 98 | loadResources(fromUtf8(argv[0])); 99 | initScreen(); 100 | initAudio(); 101 | // checkBetaExpire(); 102 | menu(); 103 | getStorage()->flush(); 104 | } catch (Exception &e) { 105 | std::cerr << L"ERROR: " << e.getMessage() << std::endl; 106 | } catch (...) { 107 | std::cerr << L"ERROR: Unknown exception" << std::endl; 108 | } 109 | screen.doneCursors(); 110 | 111 | return 0; 112 | } 113 | 114 | -------------------------------------------------------------------------------- /main.cpp.orig: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "main.h" 7 | #include "utils.h" 8 | #include "storage.h" 9 | #include "unicode.h" 10 | #include "messages.h" 11 | #include "sound.h" 12 | 13 | 14 | Screen screen; 15 | Random rndGen; 16 | 17 | 18 | static void initScreen() 19 | { 20 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) 21 | throw Exception(std::wstring(L"Error initializing SDL: ") + 22 | fromMbcs(SDL_GetError())); 23 | atexit(SDL_Quit); 24 | if (TTF_Init()) 25 | throw Exception(L"Error initializing font engine"); 26 | screen.setMode(VideoMode(800, 600, 24, 27 | getStorage()->get(L"fullscreen", 1) != 0)); 28 | screen.initCursors(); 29 | 30 | SDL_Surface *mouse = loadImage(L"cursor.bmp"); 31 | SDL_SetColorKey(mouse, SDL_SRCCOLORKEY, SDL_MapRGB(mouse->format, 0, 0, 0)); 32 | screen.setMouseImage(mouse); 33 | SDL_FreeSurface(mouse); 34 | SDL_WM_SetCaption("Einstein", NULL); 35 | 36 | #ifdef __APPLE__ 37 | screen.setCursor(false); 38 | #else 39 | screen.setCursor(getStorage()->get(L"niceCursor", 1)); 40 | #endif 41 | } 42 | 43 | static void initAudio() 44 | { 45 | sound = new Sound(); 46 | sound->setVolume((float)getStorage()->get(L"volume", 20) / 100.0f); 47 | } 48 | 49 | 50 | #ifdef __APPLE__ 51 | static std::wstring getResourcesPath(const std::wstring& path) 52 | { 53 | int idx = path.find_last_of(L'/'); 54 | return path.substr(0, idx) + L"/../../"; 55 | } 56 | #endif 57 | 58 | static void loadResources(const std::wstring &selfPath) 59 | { 60 | StringList dirs; 61 | #ifdef WIN32 62 | dirs.push_back(getStorage()->get(L"path", L"") + L"\\res"); 63 | #else 64 | #ifdef __APPLE__ 65 | dirs.push_back(getResourcesPath(selfPath)); 66 | #else 67 | dirs.push_back(PREFIX L"/share/einstein/res"); 68 | dirs.push_back(fromMbcs(getenv("HOME")) + L"/.einstein/res"); 69 | #endif 70 | #endif 71 | dirs.push_back(L"res"); 72 | dirs.push_back(L"."); 73 | resources = new ResourcesCollection(dirs); 74 | msg.load(); 75 | } 76 | 77 | 78 | /*static void checkBetaExpire() 79 | { 80 | if (1124832535L + 60L*60L*24L*40L < time(NULL)) { 81 | Font font(L"laudcn2.ttf", 16); 82 | Area area; 83 | showMessageWindow(&area, L"darkpattern.bmp", 84 | 700, 100, &font, 255,255,255, 85 | msg(L"expired")); 86 | } 87 | }*/ 88 | 89 | 90 | 91 | int main(int argc, char *argv[]) 92 | { 93 | #ifndef WIN32 94 | ensureDirExists(fromMbcs(getenv("HOME")) + std::wstring(L"/.einstein")); 95 | #endif 96 | 97 | try { 98 | loadResources(fromUtf8(argv[0])); 99 | initScreen(); 100 | initAudio(); 101 | // checkBetaExpire(); 102 | menu(); 103 | getStorage()->flush(); 104 | } catch (Exception &e) { 105 | std::cerr << L"ERROR: " << e.getMessage() << std::endl; 106 | } catch (...) { 107 | std::cerr << L"ERROR: Unknown exception" << std::endl; 108 | } 109 | screen.doneCursors(); 110 | 111 | return 0; 112 | } 113 | 114 | -------------------------------------------------------------------------------- /options.cpp: -------------------------------------------------------------------------------- 1 | #include "options.h" 2 | #include "storage.h" 3 | #include "main.h" 4 | #include "messages.h" 5 | #include "sound.h" 6 | 7 | 8 | class OptionsChangedCommand: public Command 9 | { 10 | private: 11 | bool &fullscreen; 12 | bool &niceCursor; 13 | float &volume; 14 | Area *area; 15 | 16 | public: 17 | OptionsChangedCommand(Area *a, bool &fs, bool &ns, float &v): 18 | fullscreen(fs), niceCursor(ns), volume(v) { 19 | area = a; 20 | }; 21 | 22 | virtual void doAction() { 23 | bool oldFullscreen = (getStorage()->get(L"fullscreen", 1) != 0); 24 | bool oldCursor = (getStorage()->get(L"niceCursor", 1) != 0); 25 | float oldVolume = (float)getStorage()->get(L"volume", 20) / 100.0f; 26 | if (fullscreen != oldFullscreen) { 27 | getStorage()->set(L"fullscreen", fullscreen); 28 | screen.setMode(VideoMode(800, 600, 24, fullscreen)); 29 | } 30 | #ifndef __APPLE__ 31 | if (niceCursor != oldCursor) { 32 | getStorage()->set(L"niceCursor", niceCursor); 33 | screen.setCursor(niceCursor); 34 | } 35 | #endif 36 | if (volume != oldVolume) { 37 | getStorage()->set(L"volume", (int)(volume * 100.0f)); 38 | sound->setVolume(volume); 39 | } 40 | getStorage()->flush(); 41 | area->finishEventLoop(); 42 | }; 43 | }; 44 | 45 | 46 | #define LABEL(y, s) \ 47 | area.add(new Label(&font, 300, y, 300, 20, Label::ALIGN_LEFT, \ 48 | Label::ALIGN_MIDDLE, 255,255,255, msg(s))); 49 | #define CHECKBOX(y, var) \ 50 | area.add(new Checkbox(265, y, 20, 20, &font, 255,255,255, L"blue.bmp", \ 51 | var)); 52 | #define OPTION(y, s, var) LABEL(y, s) CHECKBOX(y, var) 53 | 54 | void showOptionsWindow(Area *parentArea) 55 | { 56 | Font titleFont(L"nova.ttf", 26); 57 | Font font(L"laudcn2.ttf", 14); 58 | 59 | bool fullscreen = (getStorage()->get(L"fullscreen", 1) != 0); 60 | bool niceCursor = (getStorage()->get(L"niceCursor", 1) != 0); 61 | float volume = ((float)getStorage()->get(L"volume", 20)) / 100.0f; 62 | 63 | Area area; 64 | 65 | area.add(parentArea); 66 | area.add(new Window(250, 170, 300, 260, L"blue.bmp")); 67 | area.add(new Label(&titleFont, 250, 175, 300, 40, Label::ALIGN_CENTER, 68 | Label::ALIGN_MIDDLE, 255,255,0, msg(L"options"))); 69 | OPTION(260, L"fullscreen", fullscreen); 70 | #ifndef __APPLE__ 71 | OPTION(280, L"niceCursor", niceCursor); 72 | #endif 73 | 74 | area.add(new Label(&font, 265, 330, 300, 20, Label::ALIGN_LEFT, 75 | Label::ALIGN_MIDDLE, 255,255,255, msg(L"volume"))); 76 | area.add(new Slider(360, 332, 160, 16, volume)); 77 | 78 | ExitCommand exitCmd(area); 79 | OptionsChangedCommand okCmd(&area, fullscreen, niceCursor, volume); 80 | area.add(new Button(315, 390, 85, 25, &font, 255,255,0, L"blue.bmp", 81 | msg(L"ok"), &okCmd)); 82 | area.add(new Button(405, 390, 85, 25, &font, 255,255,0, L"blue.bmp", 83 | msg(L"cancel"), &exitCmd)); 84 | area.add(new KeyAccel(SDLK_ESCAPE, &exitCmd)); 85 | area.add(new KeyAccel(SDLK_RETURN, &okCmd)); 86 | area.run(); 87 | } 88 | 89 | -------------------------------------------------------------------------------- /font.cpp: -------------------------------------------------------------------------------- 1 | #include "font.h" 2 | #include "main.h" 3 | #include "utils.h" 4 | #include "unicode.h" 5 | 6 | 7 | static Uint16 *convBuf = NULL; 8 | static size_t bufSize = 0; 9 | 10 | 11 | static Uint16 *strToUint16(const std::wstring &text) 12 | { 13 | const wchar_t *str = text.c_str(); 14 | if ((! str) || (sizeof(wchar_t) == sizeof(Uint16))) 15 | return (Uint16*)str; 16 | else { 17 | size_t len = wcslen(str); 18 | if (! convBuf) { 19 | size_t sz = len * 2 + 1; 20 | convBuf = (Uint16*)malloc(sizeof(Uint16) * sz); 21 | bufSize = sz; 22 | } else 23 | if (bufSize < len + 1) { 24 | size_t sz = len * 2 + 1; 25 | convBuf = (Uint16*)realloc(convBuf, sizeof(Uint16) * sz); 26 | // I should check if it is NULL, but I'm too lazy today 27 | bufSize = sz; 28 | } 29 | for (unsigned int i = 0; i <= len; i++) 30 | convBuf[i] = (Uint16)str[i]; 31 | return convBuf; 32 | } 33 | } 34 | 35 | 36 | 37 | Font::Font(const std::wstring &name, int ptsize) 38 | { 39 | int size; 40 | 41 | data = resources->getRef(name, size); 42 | if (! data) 43 | throw Exception(name + L" not found"); 44 | SDL_RWops *op = SDL_RWFromMem(data, size); 45 | font = TTF_OpenFontRW(op, 1, ptsize); 46 | 47 | if (! font) 48 | throw Exception(L"Error loading font " + name); 49 | } 50 | 51 | 52 | Font::~Font() 53 | { 54 | TTF_CloseFont(font); 55 | resources->delRef(data); 56 | } 57 | 58 | 59 | void Font::draw(SDL_Surface *s, int x, int y, int r, int g, int b, 60 | bool shadow, const std::wstring &text) 61 | { 62 | if (text.length() < 1) 63 | return; 64 | 65 | Uint16 *str = strToUint16(text); 66 | 67 | if (shadow) { 68 | SDL_Color color = { 1, 1, 1, 1 }; 69 | SDL_Surface *surface = TTF_RenderUNICODE_Blended(font, str, color); 70 | SDL_Rect src = { 0, 0, surface->w, surface->h }; 71 | SDL_Rect dst = { x+1, y+1, surface->w, surface->h }; 72 | SDL_BlitSurface(surface, &src, s, &dst); 73 | SDL_FreeSurface(surface); 74 | } 75 | SDL_Color color = { r, g, b, 0 }; 76 | SDL_Surface *surface = TTF_RenderUNICODE_Blended(font, str, color); 77 | SDL_Rect src = { 0, 0, surface->w, surface->h }; 78 | SDL_Rect dst = { x, y, surface->w, surface->h }; 79 | SDL_BlitSurface(surface, &src, s, &dst); 80 | SDL_FreeSurface(surface); 81 | } 82 | 83 | void Font::draw(int x, int y, int r, int g, int b, bool shadow, 84 | const std::wstring &text) 85 | { 86 | draw(screen.getSurface(), x, y, r,g,b, shadow, text); 87 | } 88 | 89 | int Font::getWidth(const std::wstring &text) 90 | { 91 | int w, h; 92 | Uint16 *str = strToUint16(text); 93 | TTF_SizeUNICODE(font, str, &w, &h); 94 | return w; 95 | } 96 | 97 | int Font::getWidth(wchar_t ch) 98 | { 99 | int minx, maxx, miny, maxy, advance; 100 | TTF_GlyphMetrics(font, (Uint16)ch, &minx, &maxx, &miny, &maxy, &advance); 101 | return advance; 102 | } 103 | 104 | int Font::getHeight(const std::wstring &text) 105 | { 106 | int w, h; 107 | Uint16 *str = strToUint16(text); 108 | TTF_SizeUNICODE(font, str, &w, &h); 109 | return h; 110 | } 111 | 112 | void Font::getSize(const std::wstring &text, int &width, int &height) 113 | { 114 | Uint16 *str = strToUint16(text); 115 | TTF_SizeUNICODE(font, str, &width, &height); 116 | } 117 | 118 | -------------------------------------------------------------------------------- /conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Configuration file parser 3 | * Copyright (c) 2002 Alexander Babichev 4 | */ 5 | 6 | #ifndef __CONF_H__ 7 | #define __CONF_H__ 8 | 9 | struct _STable; 10 | typedef struct _STable* HTable; 11 | struct _STableIterator; 12 | typedef struct _STableIterator* HTableIterator; 13 | 14 | #define TYPE_INT 1 15 | #define TYPE_STRING 2 16 | #define TYPE_FLOAT 3 17 | #define TYPE_TABLE 4 18 | 19 | /* create empty table */ 20 | HTable table_create(); 21 | 22 | /* read table from file */ 23 | HTable table_read(const char *filename); 24 | 25 | /* free table */ 26 | void table_free(HTable table); 27 | 28 | /* get table iterator positioned before table start */ 29 | HTableIterator table_get_iter(HTable table); 30 | 31 | /* free table iterator */ 32 | void table_free_iter(HTableIterator iterator); 33 | 34 | /* move iterator. return 1 on success */ 35 | int table_iter_next(HTableIterator iterator); 36 | 37 | /* get name of table field */ 38 | char* table_iter_get_name(HTableIterator iterator); 39 | 40 | /* get type of table field */ 41 | int table_iter_get_type(HTableIterator iterator); 42 | 43 | /* get current table field as newly allocated string */ 44 | char* table_iter_get_str(HTableIterator iterator, int *err); 45 | 46 | /* get current table field as static string valid till next iterator operation */ 47 | char* table_iter_get_strs(HTableIterator iterator, int *err); 48 | 49 | /* get current table field as int */ 50 | int table_iter_get_int(HTableIterator iterator, int *err); 51 | 52 | /* get current table field as double */ 53 | double table_iter_get_double(HTableIterator iterator, int *err); 54 | 55 | /* get current table field as table */ 56 | HTable table_iter_get_table(HTableIterator iterator, int *err); 57 | 58 | /* return 0 if field not exists in table */ 59 | int table_is_field_exists(HTable table, char *name); 60 | 61 | /* get type of table field or -1 if field not exists */ 62 | int table_get_field_type(HTable table, char *field); 63 | 64 | /* get table field as newly allocated string */ 65 | char* table_get_str(HTable table, char *field, char *dflt, int *err); 66 | 67 | /* get table field as static string */ 68 | char* table_get_strs(HTable table, char *field, char *dflt, int *err); 69 | 70 | /* get table field as int */ 71 | int table_get_int(HTable table, char *field, int dflt, int *err); 72 | 73 | /* get table field as double */ 74 | double table_get_double(HTable table, char *field, double dflt, int *err); 75 | 76 | /* get table field as table */ 77 | HTable table_get_table(HTable table, char *field, HTable dflt, int *err); 78 | 79 | /* print table to new allocated string */ 80 | char* table_to_str(HTable table, int print_braces, int butify, int spaces); 81 | 82 | /* set table field as string */ 83 | int table_set_str(HTable table, const char *field, const char *val); 84 | 85 | /* set table field as int */ 86 | int table_set_int(HTable table, const char *field, int val); 87 | 88 | /* set table field as double */ 89 | int table_set_double(HTable table, const char *field, double val); 90 | 91 | /* set table field as table */ 92 | int table_set_table(HTable table, const char *field, HTable val); 93 | 94 | /* append string field to table */ 95 | int table_append_str(HTable table, const char *val); 96 | 97 | /* append int field to table */ 98 | int table_append_int(HTable table, int val); 99 | 100 | /* append double field to table */ 101 | int table_append_double(HTable table, double val); 102 | 103 | /* append tablee field to table */ 104 | int table_append_table(HTable table, HTable val); 105 | 106 | #endif 107 | 108 | -------------------------------------------------------------------------------- /messages.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "messages.h" 4 | #include "formatter.h" 5 | #include "resources.h" 6 | #include "exceptions.h" 7 | #include "buffer.h" 8 | #include "utils.h" 9 | #include "unicode.h" 10 | 11 | 12 | Messages msg; 13 | 14 | 15 | Messages::Messages() 16 | { 17 | } 18 | 19 | Messages::~Messages() 20 | { 21 | } 22 | 23 | class ResVisitor: public Visitor 24 | { 25 | private: 26 | Messages &messages; 27 | Buffer *buffer; 28 | 29 | public: 30 | ResVisitor(Messages &m, Buffer *b): messages(m) { buffer = b; }; 31 | 32 | virtual void onVisit(Resource *&r) { 33 | messages.loadFromResource(r, buffer); 34 | } 35 | }; 36 | 37 | void Messages::load() 38 | { 39 | Buffer buffer; 40 | ResVisitor loader(*this, &buffer); 41 | resources->forEachInGroup(L"messages", loader); 42 | } 43 | 44 | void Messages::loadFromResource(Resource *res, Buffer *buffer) 45 | { 46 | if (! res) return; 47 | 48 | int cnt = res->getVariantsCount(); 49 | for (int i = 0; i < cnt; i++) { 50 | ResVariant *var = res->getVariant(i); 51 | if (var) { 52 | try { 53 | int score = var->getI18nScore(); 54 | var->getData(*buffer); 55 | loadBundle(score, (unsigned char*)buffer->getData(), 56 | buffer->getSize()); 57 | } catch (Exception &e) { 58 | std::cerr << std::wstring(L"Error loading text bundle " + 59 | res->getName() + L": " + e.getMessage()); 60 | } 61 | } 62 | } 63 | } 64 | 65 | std::wstring Messages::getMessage(const std::wstring &key) const 66 | { 67 | StrMap::const_iterator i = messages.find(key); 68 | if (i != messages.end()) 69 | return (*i).second.message->getMessage(); 70 | else 71 | return key; 72 | } 73 | 74 | std::wstring Messages::format(const wchar_t *key, va_list ap) const 75 | { 76 | std::wstring s; 77 | StrMap::const_iterator i = messages.find(key); 78 | if (i != messages.end()) 79 | s = (*i).second.message->format(ap); 80 | else 81 | s = key; 82 | return s; 83 | } 84 | 85 | std::wstring Messages::format(const wchar_t *key, ...) const 86 | { 87 | va_list ap; 88 | va_start(ap, key); 89 | std::wstring s = format(key, ap); 90 | va_end(ap); 91 | return s; 92 | } 93 | 94 | std::wstring Messages::operator ()(const wchar_t *key, ...) const 95 | { 96 | va_list ap; 97 | va_start(ap, key); 98 | std::wstring s = format(key, ap); 99 | va_end(ap); 100 | return s; 101 | } 102 | 103 | void Messages::loadBundle(int score, unsigned char *data, size_t size) 104 | { 105 | if ((data[0] != 'C') || (data[1] != 'M') || (data[2] != 'F')) 106 | throw Exception(L"Invalid format of message file"); 107 | if (readInt(data + 3) != 1) 108 | throw Exception(L"Unknown version of message file"); 109 | 110 | int offset = readInt(data + size - 4); 111 | int cnt = readInt(data + offset); 112 | offset += 4; 113 | 114 | for (int i = 0; i < cnt; i++) { 115 | int sz = readInt(data + offset); 116 | offset += 4; 117 | if (sz > 0) { 118 | std::wstring name(fromUtf8((char*)data + offset, sz)); 119 | int msgOffset = readInt(data + offset + sz); 120 | StrMap::iterator i = messages.find(name); 121 | if (i == messages.end()) { 122 | ScoredStr ss = { score, new Formatter(data, msgOffset) }; 123 | messages[name] = ss; 124 | } else { 125 | ScoredStr &ss = (*i).second; 126 | if (ss.score <= score) { 127 | ss.score = score; 128 | ss.message = new Formatter(data, msgOffset); 129 | } 130 | } 131 | } 132 | offset += sz + 4; 133 | } 134 | } 135 | 136 | -------------------------------------------------------------------------------- /regstorage.cpp: -------------------------------------------------------------------------------- 1 | #ifdef WIN32 // Win32 only 2 | #include "regstorage.h" 3 | #include "unicode.h" 4 | 5 | 6 | RegistryStorage::RegistryStorage() 7 | { 8 | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 9 | "SOFTWARE\\Flowix Games\\Einstein\\2.0", 10 | 0, KEY_READ, &globalKey)) 11 | globalKey = NULL; 12 | if (RegOpenKeyEx(HKEY_CURRENT_USER, 13 | "SOFTWARE\\Flowix Games\\Einstein\\2.0", 14 | 0, KEY_READ | KEY_WRITE, &userKey)) 15 | { 16 | if (RegCreateKeyEx(HKEY_CURRENT_USER, 17 | "SOFTWARE\\Flowix Games\\Einstein\\2.0", 0, NULL, 18 | REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, 19 | NULL, &userKey, NULL)) 20 | userKey = NULL; 21 | } 22 | } 23 | 24 | RegistryStorage::~RegistryStorage() 25 | { 26 | if (globalKey) 27 | RegCloseKey(globalKey); 28 | if (userKey) 29 | RegCloseKey(userKey); 30 | } 31 | 32 | int RegistryStorage::get(const std::wstring &name, int dflt) 33 | { 34 | std::string uname(toUtf8(name)); 35 | 36 | if (globalKey) { 37 | DWORD data; 38 | DWORD size = sizeof(data); 39 | DWORD type; 40 | if (! RegQueryValueEx(globalKey, uname.c_str(), NULL, &type, 41 | (BYTE*)&data, &size)) 42 | if (type == REG_DWORD) 43 | return data; 44 | } 45 | 46 | if (userKey) { 47 | DWORD data; 48 | DWORD size = sizeof(data); 49 | DWORD type; 50 | if (! RegQueryValueEx(userKey, uname.c_str(), NULL, &type, 51 | (BYTE*)&data, &size)) 52 | if (type == REG_DWORD) 53 | return data; 54 | } 55 | 56 | return dflt; 57 | } 58 | 59 | std::wstring RegistryStorage::get(const std::wstring &name, const std::wstring &dflt) 60 | { 61 | std::string uname(toUtf8(name)); 62 | 63 | if (globalKey) { 64 | DWORD size = 0; 65 | DWORD type; 66 | if (! RegQueryValueEx(globalKey, uname.c_str(), NULL, &type, 67 | NULL, &size)) 68 | { 69 | if ((type == REG_SZ) && (size > 0)) { 70 | char *data = new char[size + 1]; 71 | if (! RegQueryValueEx(globalKey, uname.c_str(), NULL, &type, 72 | (BYTE*)data, &size)) 73 | { 74 | std::wstring s(fromUtf8(data)); 75 | delete[] data; 76 | return s; 77 | } 78 | delete[] data; 79 | } else 80 | return L""; 81 | } 82 | } 83 | 84 | if (userKey) { 85 | DWORD size = 0; 86 | DWORD type; 87 | if (! RegQueryValueEx(userKey, uname.c_str(), NULL, &type, 88 | NULL, &size)) 89 | { 90 | if ((type == REG_SZ) && (size > 0)) { 91 | char *data = new char[size]; 92 | if (! RegQueryValueEx(userKey, uname.c_str(), NULL, &type, 93 | (BYTE*)data, &size)) 94 | { 95 | std::wstring s(fromUtf8(data)); 96 | delete[] data; 97 | return s; 98 | } 99 | delete[] data; 100 | } else 101 | return L""; 102 | } 103 | } 104 | 105 | return dflt; 106 | } 107 | 108 | void RegistryStorage::set(const std::wstring &name, int value) 109 | { 110 | std::string uname(toUtf8(name)); 111 | 112 | if (userKey) { 113 | DWORD data = value; 114 | RegSetValueEx(userKey, uname.c_str(), 0, REG_DWORD, 115 | (BYTE*)&data, sizeof(data)); 116 | } 117 | } 118 | 119 | void RegistryStorage::set(const std::wstring &name, const std::wstring &value) 120 | { 121 | std::string uname(toUtf8(name)); 122 | std::string uval(toUtf8(value)); 123 | 124 | if (userKey) 125 | RegSetValueEx(userKey, uname.c_str(), 0, REG_SZ, 126 | (BYTE*)uval.c_str(), (uval.length() + 1) * sizeof(char)); 127 | } 128 | 129 | 130 | #endif 131 | 132 | -------------------------------------------------------------------------------- /mkres/main.cpp: -------------------------------------------------------------------------------- 1 | #include "compressor.h" 2 | #include "exceptions.h" 3 | #include "unicode.h" 4 | #include "table.h" 5 | #include 6 | 7 | static std::string sourceFile, outputFile; 8 | static bool verbose = false; 9 | static bool showDeps = false; 10 | 11 | 12 | static void printHelp(int terminate) 13 | { 14 | std::cerr << "USAGE:" << std::endl; 15 | std::cerr << " mkres [options]" << std::endl; 16 | std::cerr << "OPTIONS:" << std::endl; 17 | std::cerr << " --verbose print more messages" << std::endl; 18 | std::cerr << " --deps print make(1) dependencies" << std::endl; 19 | std::cerr << " --source read source file" << std::endl; 20 | std::cerr << " --output write result to file" << std::endl; 21 | std::cerr << " --version show version number" << std::endl; 22 | std::cerr << " --help this help screen" << std::endl; 23 | if (terminate >= 0) 24 | exit(terminate); 25 | } 26 | 27 | 28 | static void printVersion(int terminate) 29 | { 30 | std::cout << "Resource File Compressor" << std::endl; 31 | std::cout << "Version 1.2" << std::endl; 32 | std::cout << "Copyright (c) 2003-2005 Alexander Babichev" << std::endl; 33 | if (terminate >= 0) 34 | exit(terminate); 35 | } 36 | 37 | 38 | static void parseArgs(int argc, char *argv[]) 39 | { 40 | int i; 41 | 42 | if (argc == 1) 43 | printHelp(0); 44 | 45 | for (i = 1; i < argc; i++) { 46 | if (! argv[i]) 47 | continue; 48 | if ((! strcmp(argv[i], "--source")) && (i < argc - 1)) 49 | sourceFile = std::string(argv[++i]); 50 | else if ((! strcmp(argv[i], "--output")) && (i < argc - 1)) 51 | outputFile = std::string(argv[++i]); 52 | else if (! strcmp(argv[i], "--help")) 53 | printHelp(0); 54 | else if (! strcmp(argv[i], "--version")) 55 | printVersion(0); 56 | else if (! strcmp(argv[i], "--verbose")) 57 | verbose = true; 58 | else if (! strcmp(argv[i], "--deps")) 59 | showDeps = true; 60 | else { 61 | std::cerr << "Invalid option '" << argv[i] << "'" << std::endl; 62 | printHelp(1); 63 | } 64 | } 65 | 66 | if (! sourceFile.length()) { 67 | std::cerr << "Source file not specified" << std::endl; 68 | exit(1); 69 | } 70 | 71 | if (! outputFile.length()) { 72 | std::cerr << "Output file not specified" << std::endl; 73 | exit(1); 74 | } 75 | } 76 | 77 | 78 | static ResourceCompressor compressor; 79 | 80 | 81 | static void parseFile(const std::string &fileName) 82 | { 83 | Table table(fileName); 84 | 85 | compressor.setPriority(table.getInt(L"priority", 1000)); 86 | 87 | Table *res = table.getTable(L"resources"); 88 | if (res) { 89 | for (Table::Iterator i = res->begin(); i != res->end(); i++) { 90 | Value *value = (*i).second; 91 | if ((! value) || (! (Value::Table == value->getType()))) 92 | throw Exception(L"Invalid resource entry"); 93 | Table *t = value->asTable(); 94 | const std::wstring &name = t->getString(L"name"); 95 | if (0 >= name.length()) 96 | throw Exception(L"Unnamed resource entry"); 97 | const std::wstring &format = t->getString(L"format"); 98 | Formatter *formatter = formatRegistry.get(format); 99 | if ((0 < format.length()) && (! formatter)) 100 | throw Exception(L"Unknown format '" + format + L"'"); 101 | compressor.add(Entry(name, t->getInt(L"compr", 9), 102 | t->getString(L"group", L""), 103 | t->getString(L"file", name), formatter)); 104 | } 105 | } 106 | } 107 | 108 | 109 | 110 | int main(int argc, char *argv[]) 111 | { 112 | int res = 0; 113 | //lua_State *lua = NULL; 114 | parseArgs(argc, argv); 115 | 116 | try { 117 | parseFile(sourceFile); 118 | if (! showDeps) 119 | compressor.compress(outputFile, verbose); 120 | else 121 | compressor.printDeps(outputFile, sourceFile); 122 | } catch (Exception &e) { 123 | std::cerr << e.getMessage() << std::endl; 124 | res = 1; 125 | } catch (std::string &s) { 126 | std::cerr << s << std::endl; 127 | res = 1; 128 | } catch (...) { 129 | std::cerr << L"Error: unknown exception" << std::endl; 130 | res = 1; 131 | } 132 | 133 | /* if (lua) { 134 | lua_setgcthreshold(lua, 0); 135 | lua_close(lua); 136 | }*/ 137 | 138 | return res; 139 | } 140 | 141 | -------------------------------------------------------------------------------- /res/resources.descr: -------------------------------------------------------------------------------- 1 | priority = 100 2 | 3 | resources = { 4 | { name = "cursor.bmp" } 5 | { name = "rain.bmp" } 6 | { name = "tile.bmp" } 7 | { name = "hint-tile.bmp" } 8 | { name = "a1.bmp", file="small-a1.bmp" } 9 | { name = "a2.bmp", file="small-a2.bmp" } 10 | { name = "a3.bmp", file="small-a3.bmp" } 11 | { name = "a4.bmp", file="small-a4.bmp" } 12 | { name = "a5.bmp", file="small-a5.bmp" } 13 | { name = "a6.bmp", file="small-a6.bmp" } 14 | { name = "A1.bmp", file="large-A1.bmp" } 15 | { name = "A2.bmp", file="large-A2.bmp" } 16 | { name = "A3.bmp", file="large-A3.bmp" } 17 | { name = "A4.bmp", file="large-A4.bmp" } 18 | { name = "A5.bmp", file="large-A5.bmp" } 19 | { name = "A6.bmp", file="large-A6.bmp" } 20 | { name = "b1.bmp", file="small-b1.bmp" } 21 | { name = "b2.bmp", file="small-b2.bmp" } 22 | { name = "b3.bmp", file="small-b3.bmp" } 23 | { name = "b4.bmp", file="small-b4.bmp" } 24 | { name = "b5.bmp", file="small-b5.bmp" } 25 | { name = "b6.bmp", file="small-b6.bmp" } 26 | { name = "B1.bmp", file="large-B1.bmp" } 27 | { name = "B2.bmp", file="large-B2.bmp" } 28 | { name = "B3.bmp", file="large-B3.bmp" } 29 | { name = "B4.bmp", file="large-B4.bmp" } 30 | { name = "B5.bmp", file="large-B5.bmp" } 31 | { name = "B6.bmp", file="large-B6.bmp" } 32 | { name = "c1.bmp", file="small-c1.bmp" } 33 | { name = "c2.bmp", file="small-c2.bmp" } 34 | { name = "c3.bmp", file="small-c3.bmp" } 35 | { name = "c4.bmp", file="small-c4.bmp" } 36 | { name = "c5.bmp", file="small-c5.bmp" } 37 | { name = "c6.bmp", file="small-c6.bmp" } 38 | { name = "C1.bmp", file="large-C1.bmp" } 39 | { name = "C2.bmp", file="large-C2.bmp" } 40 | { name = "C3.bmp", file="large-C3.bmp" } 41 | { name = "C4.bmp", file="large-C4.bmp" } 42 | { name = "C5.bmp", file="large-C5.bmp" } 43 | { name = "C6.bmp", file="large-C6.bmp" } 44 | { name = "d1.bmp", file="small-d1.bmp" } 45 | { name = "d2.bmp", file="small-d2.bmp" } 46 | { name = "d3.bmp", file="small-d3.bmp" } 47 | { name = "d4.bmp", file="small-d4.bmp" } 48 | { name = "d5.bmp", file="small-d5.bmp" } 49 | { name = "d6.bmp", file="small-d6.bmp" } 50 | { name = "D1.bmp", file="large-D1.bmp" } 51 | { name = "D2.bmp", file="large-D2.bmp" } 52 | { name = "D3.bmp", file="large-D3.bmp" } 53 | { name = "D4.bmp", file="large-D4.bmp" } 54 | { name = "D5.bmp", file="large-D5.bmp" } 55 | { name = "D6.bmp", file="large-D6.bmp" } 56 | { name = "e1.bmp", file="small-e1.bmp" } 57 | { name = "e2.bmp", file="small-e2.bmp" } 58 | { name = "e3.bmp", file="small-e3.bmp" } 59 | { name = "e4.bmp", file="small-e4.bmp" } 60 | { name = "e5.bmp", file="small-e5.bmp" } 61 | { name = "e6.bmp", file="small-e6.bmp" } 62 | { name = "E1.bmp", file="large-E1.bmp" } 63 | { name = "E2.bmp", file="large-E2.bmp" } 64 | { name = "E3.bmp", file="large-E3.bmp" } 65 | { name = "E4.bmp", file="large-E4.bmp" } 66 | { name = "E5.bmp", file="large-E5.bmp" } 67 | { name = "E6.bmp", file="large-E6.bmp" } 68 | { name = "f1.bmp", file="small-f1.bmp" } 69 | { name = "f2.bmp", file="small-f2.bmp" } 70 | { name = "f3.bmp", file="small-f3.bmp" } 71 | { name = "f4.bmp", file="small-f4.bmp" } 72 | { name = "f5.bmp", file="small-f5.bmp" } 73 | { name = "f6.bmp", file="small-f6.bmp" } 74 | { name = "F1.bmp", file="large-F1.bmp" } 75 | { name = "F2.bmp", file="large-F2.bmp" } 76 | { name = "F3.bmp", file="large-F3.bmp" } 77 | { name = "F4.bmp", file="large-F4.bmp" } 78 | { name = "F5.bmp", file="large-F5.bmp" } 79 | { name = "F6.bmp", file="large-F6.bmp" } 80 | { name = "opensquare.bmp" } 81 | { name = "closed.bmp" } 82 | { name = "verthint.bmp" } 83 | { name = "hornearhint.bmp" } 84 | { name = "horposhint.bmp" } 85 | { name = "horbetweenhint.bmp" } 86 | { name = "hint-near.bmp" } 87 | { name = "hint-side.bmp" } 88 | { name = "betwarr.bmp" } 89 | { name = "title.bmp" } 90 | { name = "marble1.bmp" } 91 | { name = "blue.bmp" } 92 | { name = "luximb.ttf" } 93 | { name = "redpattern.bmp" } 94 | { name = "greenpattern.bmp" } 95 | { name = "darkpattern.bmp" } 96 | { name = "nova.bmp" } 97 | { name = "nova.ttf" } 98 | { name = "laudcn2.ttf" } 99 | { name = "btn.bmp" } 100 | { name = "rules.txt", format = "messages" group = "messages" } 101 | { name = "rules_ru.txt", format = "messages" group = "messages" } 102 | { name = "messages.txt", format = "messages" group = "messages" } 103 | { name = "messages_ru.txt", format = "messages" group = "messages" } 104 | { name = "click.wav" } 105 | { name = "applause.wav" } 106 | { name = "glasbk2.wav" } 107 | { name = "laser.wav" } 108 | { name = "whizz.wav" } 109 | } 110 | -------------------------------------------------------------------------------- /verthints.cpp: -------------------------------------------------------------------------------- 1 | #include "verthints.h" 2 | #include "main.h" 3 | #include "utils.h" 4 | #include "puzgen.h" 5 | #include "sound.h" 6 | 7 | 8 | #define TILE_NUM 15 9 | #define TILE_GAP 4 10 | #define TILE_X 12 11 | #define TILE_Y 495 12 | #define TILE_WIDTH 48 13 | #define TILE_HEIGHT 48 14 | 15 | 16 | VertHints::VertHints(IconSet &is, Rules &r): iconSet(is) 17 | { 18 | reset(r); 19 | } 20 | 21 | 22 | VertHints::VertHints(IconSet &is, Rules &rl, std::istream &stream): iconSet(is) 23 | { 24 | int qty = readInt(stream); 25 | 26 | for (int i = 0; i < qty; i++) { 27 | int no = readInt(stream); 28 | numbersArr.push_back(no); 29 | Rule *r = getRule(rl, no); 30 | int excluded = readInt(stream); 31 | if (excluded) { 32 | excludedRules.push_back(r); 33 | rules.push_back(NULL); 34 | } else { 35 | excludedRules.push_back(NULL); 36 | rules.push_back(r); 37 | } 38 | } 39 | 40 | showExcluded = readInt(stream); 41 | 42 | int x, y; 43 | SDL_GetMouseState(&x, &y); 44 | highlighted = getRuleNo(x, y); 45 | } 46 | 47 | void VertHints::reset(Rules &r) 48 | { 49 | rules.clear(); 50 | excludedRules.clear(); 51 | numbersArr.clear(); 52 | 53 | int no = 0; 54 | for (Rules::iterator i = r.begin(); i != r.end(); i++) { 55 | Rule *rule = *i; 56 | if (rule->getShowOpts() == Rule::SHOW_VERT) { 57 | rules.push_back(rule); 58 | excludedRules.push_back(NULL); 59 | numbersArr.push_back(no); 60 | } 61 | no++; 62 | } 63 | 64 | showExcluded = false; 65 | 66 | int x, y; 67 | SDL_GetMouseState(&x, &y); 68 | highlighted = getRuleNo(x, y); 69 | } 70 | 71 | void VertHints::draw() 72 | { 73 | for (int i = 0; i < TILE_NUM; i++) 74 | drawCell(i, true); 75 | } 76 | 77 | 78 | void VertHints::drawCell(int col, bool addToUpdate) 79 | { 80 | int x = TILE_X + col * (TILE_WIDTH + TILE_GAP); 81 | int y = TILE_Y; 82 | 83 | Rule *r = NULL; 84 | if (col < (int)rules.size()) { 85 | if (showExcluded) 86 | r = excludedRules[col]; 87 | else 88 | r = rules[col]; 89 | } 90 | if (r) 91 | r->draw(x, y, iconSet, highlighted == col); 92 | else { 93 | screen.draw(x, y, iconSet.getEmptyHintIcon()); 94 | screen.draw(x, y + TILE_HEIGHT, iconSet.getEmptyHintIcon()); 95 | } 96 | 97 | if (addToUpdate) 98 | screen.addRegionToUpdate(x, y, TILE_WIDTH, TILE_HEIGHT*2); 99 | } 100 | 101 | 102 | bool VertHints::onMouseButtonDown(int button, int x, int y) 103 | { 104 | if (button != 3) 105 | return false; 106 | 107 | int no = getRuleNo(x, y); 108 | if (no < 0) return false; 109 | 110 | if (no < (int)rules.size()) { 111 | if (showExcluded) { 112 | Rule *r = excludedRules[no]; 113 | if (r) { 114 | sound->play(L"whizz.wav"); 115 | rules[no] = r; 116 | excludedRules[no] = NULL; 117 | drawCell(no); 118 | } 119 | } else { 120 | Rule *r = rules[no]; 121 | if (r) { 122 | sound->play(L"whizz.wav"); 123 | rules[no] = NULL; 124 | excludedRules[no] = r; 125 | drawCell(no); 126 | } 127 | } 128 | } 129 | 130 | return true; 131 | } 132 | 133 | 134 | void VertHints::toggleExcluded() 135 | { 136 | showExcluded = !showExcluded; 137 | draw(); 138 | } 139 | 140 | 141 | bool VertHints::onMouseMove(int x, int y) 142 | { 143 | int no = getRuleNo(x, y); 144 | 145 | if (no != highlighted) { 146 | int old = highlighted; 147 | highlighted = no; 148 | if (isActive(old)) 149 | drawCell(old); 150 | if (isActive(no)) 151 | drawCell(no); 152 | } 153 | 154 | return false; 155 | } 156 | 157 | 158 | int VertHints::getRuleNo(int x, int y) 159 | { 160 | if (! isInRect(x, y, TILE_X, TILE_Y, (TILE_WIDTH + TILE_GAP) * TILE_NUM, 161 | TILE_HEIGHT * 2)) 162 | return -1; 163 | 164 | x = x - TILE_X; 165 | y = y - TILE_Y; 166 | 167 | int no = x / (TILE_WIDTH + TILE_GAP); 168 | if (no * (TILE_WIDTH + TILE_GAP) + TILE_WIDTH < x) 169 | return -1; 170 | 171 | return no; 172 | } 173 | 174 | bool VertHints::isActive(int ruleNo) 175 | { 176 | if ((ruleNo < 0) || (ruleNo >= (int)rules.size())) 177 | return false; 178 | Rule *r = showExcluded ? excludedRules[ruleNo] : rules[ruleNo]; 179 | return r != NULL; 180 | } 181 | 182 | 183 | void VertHints::save(std::ostream &stream) 184 | { 185 | int cnt = numbersArr.size(); 186 | writeInt(stream, cnt); 187 | for (int i = 0; i < cnt; i++) { 188 | writeInt(stream, numbersArr[i]); 189 | writeInt(stream, rules[i] ? 0 : 1); 190 | } 191 | writeInt(stream, showExcluded ? 1 : 0); 192 | } 193 | 194 | -------------------------------------------------------------------------------- /random.cpp: -------------------------------------------------------------------------------- 1 | #include "random.h" 2 | #include "utils.h" 3 | 4 | /* Period parameters */ 5 | #define M 397 6 | #define MATRIX_A 0x9908b0dfUL /* constant vector a */ 7 | #define UPPER_MASK 0x80000000UL /* most significant w-r bits */ 8 | #define LOWER_MASK 0x7fffffffUL /* least significant r bits */ 9 | 10 | 11 | Random::Random() 12 | { 13 | mti = RAND_N+1; /* mti==RAND_N+1 means mt[RAND_N] is not initialized */ 14 | struct timeval tv; 15 | gettimeofday(&tv); 16 | unsigned long long int s = tv.tv_sec * 1000000 + tv.tv_usec; 17 | initLong(s); 18 | } 19 | 20 | Random::Random(unsigned long int seed) 21 | { 22 | mti = RAND_N+1; /* mti==RAND_N+1 means mt[RAND_N] is not initialized */ 23 | initLong(seed); 24 | } 25 | 26 | 27 | /* initialize by an array with array-length */ 28 | /* init_key is the array for initializing keys */ 29 | /* key_length is its length */ 30 | Random::Random(int init_key[], int key_length) 31 | { 32 | mti = RAND_N+1; /* mti==RAND_N+1 means mt[RAND_N] is not initialized */ 33 | 34 | int i, j, k; 35 | initLong(19650218UL); 36 | i=1; j=0; 37 | k = (RAND_N>key_length ? RAND_N : key_length); 38 | for (; k; k--) { 39 | mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) 40 | + init_key[j] + j; /* non linear */ 41 | mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 42 | i++; j++; 43 | if (i>=RAND_N) { mt[0] = mt[RAND_N-1]; i=1; } 44 | if (j>=key_length) j=0; 45 | } 46 | for (k=RAND_N-1; k; k--) { 47 | mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) 48 | - i; /* non linear */ 49 | mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 50 | i++; 51 | if (i>=RAND_N) { mt[0] = mt[RAND_N-1]; i=1; } 52 | } 53 | 54 | mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 55 | } 56 | 57 | 58 | 59 | Random::~Random() 60 | { 61 | } 62 | 63 | /* initializes mt[RAND_N] with a seed */ 64 | void Random::initLong(unsigned long s) 65 | { 66 | mt[0]= s & 0xffffffffUL; 67 | for (mti=1; mti> 30)) + mti); 70 | /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ 71 | /* In the previous versions, MSBs of the seed affect */ 72 | /* only MSBs of the array mt[]. */ 73 | /* 2002/01/09 modified by Makoto Matsumoto */ 74 | mt[mti] &= 0xffffffffUL; 75 | /* for >32 bit machines */ 76 | } 77 | } 78 | 79 | 80 | /* generates a random number on [0,0xffffffff]-interval */ 81 | unsigned long Random::genInt32(void) 82 | { 83 | unsigned long y; 84 | static unsigned long mag01[2]={0x0UL, MATRIX_A}; 85 | /* mag01[x] = x * MATRIX_A for x=0,1 */ 86 | 87 | if (mti >= RAND_N) { /* generate N words at one time */ 88 | int kk; 89 | 90 | if (mti == RAND_N+1) /* if init_genrand() has not been called, */ 91 | initLong(5489UL); /* a default initial seed is used */ 92 | 93 | for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; 96 | } 97 | for (;kk> 1) ^ mag01[y & 0x1UL]; 100 | } 101 | y = (mt[RAND_N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); 102 | mt[RAND_N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; 103 | 104 | mti = 0; 105 | } 106 | 107 | y = mt[mti++]; 108 | 109 | /* Tempering */ 110 | y ^= (y >> 11); 111 | y ^= (y << 7) & 0x9d2c5680UL; 112 | y ^= (y << 15) & 0xefc60000UL; 113 | y ^= (y >> 18); 114 | 115 | return y; 116 | } 117 | 118 | /* generates a random number on [0,0x7fffffff]-interval */ 119 | long Random::genInt31() 120 | { 121 | return (long)(genInt32()>>1); 122 | } 123 | 124 | /* generates a random number on [0,1]-real-interval */ 125 | double Random::genReal1(void) 126 | { 127 | return genInt32()*(1.0/4294967295.0); 128 | /* divided by 2^32-1 */ 129 | } 130 | 131 | /* generates a random number on [0,1)-real-interval */ 132 | double Random::genReal2() 133 | { 134 | return genInt32()*(1.0/4294967296.0); 135 | /* divided by 2^32 */ 136 | } 137 | 138 | /* generates a random number on (0,1)-real-interval */ 139 | double Random::genReal3(void) 140 | { 141 | return (((double)genInt32()) + 0.5)*(1.0/4294967296.0); 142 | /* divided by 2^32 */ 143 | } 144 | 145 | /* generates a random number on [0,1) with 53-bit resolution*/ 146 | double Random::genReal53(void) 147 | { 148 | unsigned long a=genInt32()>>5, b=genInt32()>>6; 149 | return(a*67108864.0+b)*(1.0/9007199254740992.0); 150 | } 151 | 152 | /* generate integer random number on [0, range) int interval */ 153 | int Random::genInt(int range) 154 | { 155 | int v = (int)(genReal2() * range); 156 | if (v == range) printf("ooops!\n"); 157 | return v; 158 | } 159 | 160 | -------------------------------------------------------------------------------- /topscores.cpp: -------------------------------------------------------------------------------- 1 | #include "topscores.h" 2 | #include "storage.h" 3 | #include "utils.h" 4 | #include "font.h" 5 | #include "convert.h" 6 | #include "messages.h" 7 | 8 | 9 | TopScores::TopScores() 10 | { 11 | Storage *storage = getStorage(); 12 | 13 | for (int i = 0; i < MAX_SCORES; i++) { 14 | int score = storage->get(L"top_score_" + toString(i), -1); 15 | if (score < 0) 16 | break; 17 | std::wstring name = storage->get(L"top_name_" + toString(i), L""); 18 | add(name, score); 19 | } 20 | 21 | modifed = false; 22 | } 23 | 24 | 25 | TopScores::~TopScores() 26 | { 27 | save(); 28 | } 29 | 30 | int TopScores::add(const std::wstring &name, int score) 31 | { 32 | if (score >= getMaxScore() || (scores.size() < 1)) { 33 | if (! isFull()) { 34 | Entry e = { name, score }; 35 | scores.push_back(e); 36 | modifed = true; 37 | return scores.size() - 1; 38 | } 39 | return -1; 40 | } 41 | 42 | int pos = 0; 43 | for (ScoresList::iterator i = scores.begin(); i != scores.end(); i++) { 44 | Entry &e = *i; 45 | if (e.score > score) { 46 | Entry ne = { name, score }; 47 | scores.insert(i, ne); 48 | modifed = true; 49 | break; 50 | } 51 | pos++; 52 | } 53 | 54 | while (scores.size() > MAX_SCORES) { 55 | modifed = true; 56 | scores.erase(--scores.end()); 57 | } 58 | 59 | return modifed ? pos : -1; 60 | } 61 | 62 | void TopScores::save() 63 | { 64 | if (! modifed) 65 | return; 66 | 67 | Storage *storage = getStorage(); 68 | int no = 0; 69 | 70 | for (ScoresList::iterator i = scores.begin(); i != scores.end(); i++) { 71 | Entry &e = *i; 72 | storage->set(L"top_name_" + toString(no), e.name); 73 | storage->set(L"top_score_" + toString(no), e.score); 74 | no++; 75 | } 76 | 77 | storage->flush(); 78 | modifed = false; 79 | } 80 | 81 | TopScores::ScoresList& TopScores::getScores() 82 | { 83 | return scores; 84 | } 85 | 86 | int TopScores::getMaxScore() 87 | { 88 | if (scores.size() < 1) 89 | return -1; 90 | ScoresList::iterator i = scores.end(); 91 | i--; 92 | return (*i).score; 93 | } 94 | 95 | 96 | class ScoresWindow: public Window 97 | { 98 | public: 99 | ScoresWindow(int x, int y, TopScores *scores, int highlight); 100 | }; 101 | 102 | 103 | ScoresWindow::ScoresWindow(int x, int y, TopScores *scores, int highlight): 104 | Window(x, y, 320, 350, L"blue.bmp") 105 | { 106 | Font titleFont(L"nova.ttf", 26); 107 | Font entryFont(L"laudcn2.ttf", 14); 108 | Font timeFont(L"luximb.ttf", 14); 109 | 110 | std::wstring txt = msg(L"topScores"); 111 | int w = titleFont.getWidth(txt); 112 | titleFont.draw(background, (320 - w) / 2, 15, 255,255,0, true, txt); 113 | 114 | TopScores::ScoresList &list = scores->getScores(); 115 | int no = 1; 116 | int pos = 70; 117 | for (TopScores::ScoresList::iterator i = list.begin(); 118 | i != list.end(); i++) 119 | { 120 | TopScores::Entry &e = *i; 121 | std::wstring s(toString(no) + L"."); 122 | int w = entryFont.getWidth(s); 123 | int c = ((no - 1) == highlight) ? 0 : 255; 124 | entryFont.draw(background, 30 - w, pos, 255,255,c, true, s); 125 | SDL_Rect rect = { 40, pos-20, 180, 40 }; 126 | SDL_SetClipRect(background, &rect); 127 | entryFont.draw(background, 40, pos, 255,255,c, true, e.name); 128 | SDL_SetClipRect(background, NULL); 129 | s = secToStr(e.score); 130 | w = timeFont.getWidth(s); 131 | timeFont.draw(background, 305-w, pos, 255,255,c, true, s); 132 | pos += 20; 133 | no++; 134 | } 135 | } 136 | 137 | 138 | void showScoresWindow(Area *parentArea, TopScores *scores, int highlight) 139 | { 140 | Area area; 141 | 142 | Font font(L"laudcn2.ttf", 16); 143 | area.add(parentArea); 144 | area.add(new ScoresWindow(240, 125, scores, highlight)); 145 | ExitCommand exitCmd(area); 146 | area.add(new Button(348, 430, 90, 25, &font, 255,255,0, L"blue.bmp", 147 | msg(L"ok"), &exitCmd)); 148 | area.add(new KeyAccel(SDLK_ESCAPE, &exitCmd)); 149 | area.run(); 150 | } 151 | 152 | 153 | std::wstring enterNameDialog(Area *parentArea) 154 | { 155 | Area area; 156 | 157 | Font font(L"laudcn2.ttf", 16); 158 | area.add(parentArea); 159 | area.add(new Window(170, 280, 460, 100, L"blue.bmp")); 160 | Storage *storage = getStorage(); 161 | std::wstring name = storage->get(L"lastName", msg(L"anonymous")); 162 | area.add(new Label(&font, 180, 300, 255,255,0, msg(L"enterName"))); 163 | area.add(new InputField(350, 300, 270, 26, L"blue.bmp", name, 20, 164 | 255,255,0, &font)); 165 | ExitCommand exitCmd(area); 166 | area.add(new Button(348, 340, 90, 25, &font, 255,255,0, L"blue.bmp", 167 | msg(L"ok"), &exitCmd)); 168 | area.add(new KeyAccel(SDLK_ESCAPE, &exitCmd)); 169 | area.add(new KeyAccel(SDLK_RETURN, &exitCmd)); 170 | area.run(); 171 | storage->set(L"lastName", name); 172 | return name; 173 | } 174 | 175 | 176 | -------------------------------------------------------------------------------- /formatter.cpp: -------------------------------------------------------------------------------- 1 | #include "formatter.h" 2 | #include "utils.h" 3 | #include "convert.h" 4 | 5 | 6 | #define ADD_ARG(t) \ 7 | commands[commandsCnt].type = t; \ 8 | argNo = readInt(data + offset); \ 9 | if (argNo > maxArg) \ 10 | maxArg = argNo; \ 11 | commands[commandsCnt].data = (void*)argNo; \ 12 | commandsCnt++; 13 | 14 | Formatter::Formatter(unsigned char *data, int offset) 15 | { 16 | int cnt = readInt(data + offset); 17 | if (! cnt) { 18 | commandsCnt = argsCnt = 0; 19 | commands = NULL; 20 | args = NULL; 21 | } 22 | 23 | offset += 4; 24 | commands = new Command[cnt]; 25 | commandsCnt = 0; 26 | 27 | int maxArg = 0, argNo; 28 | 29 | for (int i = 0; i < cnt; i++) { 30 | int type = data[offset]; 31 | offset++; 32 | int size = readInt(data + offset); 33 | offset += 4; 34 | switch (type) { 35 | case 1: 36 | commands[commandsCnt].type = TEXT_COMMAND; 37 | commands[commandsCnt].data = new std::wstring( 38 | fromUtf8((char*)data + offset, size)); 39 | commandsCnt++; 40 | break; 41 | 42 | case 2: ADD_ARG(INT_ARG); break; 43 | case 3: ADD_ARG(STRING_ARG); break; 44 | case 4: ADD_ARG(FLOAT_ARG); break; 45 | case 5: ADD_ARG(DOUBLE_ARG); break; 46 | } 47 | offset += size; 48 | } 49 | 50 | argsCnt = maxArg; 51 | if (! argsCnt) 52 | args = NULL; 53 | else { 54 | args = new CmdType[argsCnt]; 55 | memset(args, 0, sizeof(CmdType) * argsCnt); 56 | for (int i = 0; i < commandsCnt; i++) { 57 | Command &c = commands[i]; 58 | if ((c.type == INT_ARG) || (c.type == STRING_ARG) || 59 | (c.type == FLOAT_ARG) || (c.type == DOUBLE_ARG)) 60 | { 61 | long no = (long)c.data; 62 | args[no - 1] = c.type; 63 | } 64 | } 65 | } 66 | } 67 | 68 | Formatter::~Formatter() 69 | { 70 | for (int i = 0; i < commandsCnt; i++) 71 | if (TEXT_COMMAND == commands[i].type) 72 | delete (std::wstring*)(commands[i].data); 73 | if (commands) 74 | delete[] commands; 75 | if (args) 76 | delete[] args; 77 | } 78 | 79 | std::wstring Formatter::getMessage() const 80 | { 81 | std::wstring s; 82 | 83 | for (int i = 0; i < commandsCnt; i++) 84 | if (TEXT_COMMAND == commands[i].type) 85 | s += *(std::wstring*)(commands[i].data); 86 | return s; 87 | } 88 | 89 | 90 | class ArgValue 91 | { 92 | public: 93 | virtual ~ArgValue() { }; 94 | virtual std::wstring format(Formatter::Command *command) = 0; 95 | }; 96 | 97 | template 98 | class TemplatedArgValue: public ArgValue 99 | { 100 | private: 101 | T value; 102 | 103 | public: 104 | TemplatedArgValue(const T &v) { value = v; }; 105 | virtual std::wstring format(Formatter::Command *command) { 106 | return toString(value); 107 | }; 108 | }; 109 | 110 | class StrArgValue: public ArgValue 111 | { 112 | private: 113 | std::wstring value; 114 | 115 | public: 116 | StrArgValue(const std::wstring &v): value(v) { }; 117 | virtual std::wstring format(Formatter::Command *command) { 118 | return value; 119 | }; 120 | }; 121 | 122 | 123 | std::wstring Formatter::format(std::vector &argValues) const 124 | { 125 | std::wstring s; 126 | long no; 127 | 128 | for (int i = 0; i < commandsCnt; i++) { 129 | Command *cmd = &commands[i]; 130 | 131 | switch (cmd->type) { 132 | case TEXT_COMMAND: 133 | s += *(std::wstring*)(cmd->data); 134 | break; 135 | 136 | case STRING_ARG: 137 | case INT_ARG: 138 | no = (long)cmd->data - 1; 139 | if (no < (long)argValues.size()) 140 | s += argValues[no]->format(cmd); 141 | break; 142 | 143 | default: ; 144 | } 145 | } 146 | 147 | return s; 148 | } 149 | 150 | std::wstring Formatter::format(va_list ap) const 151 | { 152 | if (! argsCnt) 153 | return getMessage(); 154 | 155 | std::vector argValues; 156 | 157 | for (int i = 0; i < argsCnt; i++) { 158 | switch (args[i]) { 159 | case INT_ARG: 160 | argValues.push_back(new TemplatedArgValue 161 | (va_arg(ap, int))); 162 | break; 163 | case STRING_ARG: 164 | argValues.push_back(new StrArgValue(va_arg(ap, wchar_t*))); 165 | break; 166 | case DOUBLE_ARG: 167 | argValues.push_back(new TemplatedArgValue 168 | (va_arg(ap, double))); 169 | break; 170 | case FLOAT_ARG: 171 | argValues.push_back(new TemplatedArgValue 172 | ((float)va_arg(ap, double))); 173 | break; 174 | default: 175 | i = argsCnt; 176 | } 177 | } 178 | 179 | std::wstring s = format(argValues); 180 | 181 | for (std::vector::iterator i = argValues.begin(); 182 | i != argValues.end(); i++) 183 | delete *i; 184 | 185 | return s; 186 | } 187 | 188 | -------------------------------------------------------------------------------- /horhints.cpp: -------------------------------------------------------------------------------- 1 | #include "horhints.h" 2 | #include "main.h" 3 | #include "utils.h" 4 | #include "sound.h" 5 | 6 | 7 | #define HINTS_COLS 3 8 | #define HINTS_ROWS 8 9 | #define TILE_GAP_X 4 10 | #define TILE_GAP_Y 4 11 | #define TILE_X 348 12 | #define TILE_Y 68 13 | #define TILE_WIDTH 48 14 | #define TILE_HEIGHT 48 15 | 16 | 17 | HorHints::HorHints(IconSet &is, Rules &r): iconSet(is) 18 | { 19 | reset(r); 20 | } 21 | 22 | 23 | HorHints::HorHints(IconSet &is, Rules &rl, std::istream &stream): iconSet(is) 24 | { 25 | int qty = readInt(stream); 26 | 27 | for (int i = 0; i < qty; i++) { 28 | int no = readInt(stream); 29 | numbersArr.push_back(no); 30 | Rule *r = getRule(rl, no); 31 | int excluded = readInt(stream); 32 | if (excluded) { 33 | excludedRules.push_back(r); 34 | rules.push_back(NULL); 35 | } else { 36 | excludedRules.push_back(NULL); 37 | rules.push_back(r); 38 | } 39 | } 40 | 41 | showExcluded = readInt(stream); 42 | 43 | int x, y; 44 | SDL_GetMouseState(&x, &y); 45 | highlighted = getRuleNo(x, y); 46 | } 47 | 48 | 49 | void HorHints::reset(Rules &r) 50 | { 51 | rules.clear(); 52 | excludedRules.clear(); 53 | numbersArr.clear(); 54 | 55 | int no = 0; 56 | for (Rules::iterator i = r.begin(); i != r.end(); i++) { 57 | Rule *rule = *i; 58 | if (rule->getShowOpts() == Rule::SHOW_HORIZ) { 59 | rules.push_back(rule); 60 | excludedRules.push_back(NULL); 61 | numbersArr.push_back(no); 62 | } 63 | no++; 64 | } 65 | 66 | showExcluded = false; 67 | 68 | int x, y; 69 | SDL_GetMouseState(&x, &y); 70 | highlighted = getRuleNo(x, y); 71 | } 72 | 73 | void HorHints::draw() 74 | { 75 | for (int i = 0; i < HINTS_ROWS; i++) 76 | for (int j = 0; j < HINTS_COLS; j++) 77 | drawCell(j, i, true); 78 | } 79 | 80 | void HorHints::drawCell(int col, int row, bool addToUpdate) 81 | { 82 | int x = TILE_X + col * (TILE_WIDTH*3 + TILE_GAP_X); 83 | int y = TILE_Y + row * (TILE_HEIGHT + TILE_GAP_Y); 84 | 85 | Rule *r = NULL; 86 | int no = row * HINTS_COLS + col; 87 | if (no < (int)rules.size()) 88 | if (showExcluded) 89 | r = excludedRules[no]; 90 | else 91 | r = rules[no]; 92 | if (r) 93 | r->draw(x, y, iconSet, no == highlighted); 94 | else 95 | for (int i = 0; i < 3; i++) 96 | screen.draw(x + TILE_HEIGHT*i, y, iconSet.getEmptyHintIcon()); 97 | 98 | if (addToUpdate) 99 | screen.addRegionToUpdate(x, y, TILE_WIDTH*3, TILE_HEIGHT); 100 | } 101 | 102 | 103 | bool HorHints::onMouseButtonDown(int button, int x, int y) 104 | { 105 | if (button != 3) 106 | return false; 107 | 108 | int no = getRuleNo(x, y); 109 | if (no < 0) return false; 110 | int row = no / HINTS_COLS; 111 | int col = no - row * HINTS_COLS; 112 | 113 | if (showExcluded) { 114 | Rule *r = excludedRules[no]; 115 | if (r) { 116 | sound->play(L"whizz.wav"); 117 | rules[no] = r; 118 | excludedRules[no] = NULL; 119 | drawCell(col, row); 120 | } 121 | } else { 122 | Rule *r = rules[no]; 123 | if (r) { 124 | sound->play(L"whizz.wav"); 125 | rules[no] = NULL; 126 | excludedRules[no] = r; 127 | drawCell(col, row); 128 | } 129 | } 130 | 131 | return true; 132 | } 133 | 134 | 135 | void HorHints::toggleExcluded() 136 | { 137 | showExcluded = !showExcluded; 138 | draw(); 139 | } 140 | 141 | 142 | bool HorHints::onMouseMove(int x, int y) 143 | { 144 | int no = getRuleNo(x, y); 145 | 146 | if (no != highlighted) { 147 | int old = highlighted; 148 | highlighted = no; 149 | if (isActive(old)) { 150 | int row = old / HINTS_COLS; 151 | int col = old - row * HINTS_COLS; 152 | drawCell(col, row); 153 | } 154 | if (isActive(no)) { 155 | int row = no / HINTS_COLS; 156 | int col = no - row * HINTS_COLS; 157 | drawCell(col, row); 158 | } 159 | } 160 | 161 | return false; 162 | } 163 | 164 | 165 | int HorHints::getRuleNo(int x, int y) 166 | { 167 | if (! isInRect(x, y, TILE_X, TILE_Y, (TILE_WIDTH*3 + TILE_GAP_X) * HINTS_COLS, 168 | (TILE_HEIGHT + TILE_GAP_Y) * HINTS_ROWS)) 169 | return -1; 170 | 171 | x = x - TILE_X; 172 | y = y - TILE_Y; 173 | 174 | int col = x / (TILE_WIDTH*3 + TILE_GAP_X); 175 | if (col * (TILE_WIDTH*3 + TILE_GAP_X) + TILE_WIDTH*3 < x) 176 | return -1; 177 | int row = y / (TILE_HEIGHT + TILE_GAP_Y); 178 | if (row * (TILE_HEIGHT + TILE_GAP_Y) + TILE_HEIGHT < y) 179 | return -1; 180 | 181 | int no = row * HINTS_COLS + col; 182 | if (no >= (int)rules.size()) 183 | return -1; 184 | 185 | return no; 186 | } 187 | 188 | bool HorHints::isActive(int ruleNo) 189 | { 190 | if ((ruleNo < 0) || (ruleNo >= (int)rules.size())) 191 | return false; 192 | Rule *r = showExcluded ? excludedRules[ruleNo] : rules[ruleNo]; 193 | return r != NULL; 194 | } 195 | 196 | 197 | void HorHints::save(std::ostream &stream) 198 | { 199 | int cnt = numbersArr.size(); 200 | writeInt(stream, cnt); 201 | for (int i = 0; i < cnt; i++) { 202 | writeInt(stream, numbersArr[i]); 203 | writeInt(stream, rules[i] ? 0 : 1); 204 | } 205 | writeInt(stream, showExcluded ? 1 : 0); 206 | } 207 | 208 | -------------------------------------------------------------------------------- /puzzle.cpp: -------------------------------------------------------------------------------- 1 | #include "puzzle.h" 2 | #include "main.h" 3 | #include "utils.h" 4 | #include "sound.h" 5 | 6 | 7 | #define FIELD_OFFSET_X 12 8 | #define FIELD_OFFSET_Y 68 9 | #define FIELD_GAP_X 4 10 | #define FIELD_GAP_Y 4 11 | #define FIELD_TILE_WIDTH 48 12 | #define FIELD_TILE_HEIGHT 48 13 | 14 | 15 | Puzzle::Puzzle(IconSet &is, SolvedPuzzle &s, Possibilities *p): 16 | iconSet(is), solved(s) 17 | { 18 | possib = p; 19 | 20 | reset(); 21 | } 22 | 23 | 24 | Puzzle::~Puzzle() 25 | { 26 | } 27 | 28 | void Puzzle::reset() 29 | { 30 | valid = true; 31 | win = false; 32 | 33 | int x, y; 34 | SDL_GetMouseState(&x, &y); 35 | getCellNo(x, y, hCol, hRow, subHNo); 36 | } 37 | 38 | void Puzzle::draw() 39 | { 40 | for (int i = 0; i < PUZZLE_SIZE; i++) 41 | for (int j = 0; j < PUZZLE_SIZE; j++) 42 | drawCell(i, j, true); 43 | } 44 | 45 | void Puzzle::drawCell(int col, int row, bool addToUpdate) 46 | { 47 | int posX = FIELD_OFFSET_X + col * (FIELD_TILE_WIDTH + FIELD_GAP_X); 48 | int posY = FIELD_OFFSET_Y + row * (FIELD_TILE_HEIGHT + FIELD_GAP_Y); 49 | 50 | if (possib->isDefined(col, row)) { 51 | int element = possib->getDefined(col, row); 52 | if (element > 0) 53 | screen.draw(posX, posY, iconSet.getLargeIcon(row, element, 54 | (hCol == col) && (hRow == row))); 55 | } else { 56 | screen.draw(posX, posY, iconSet.getEmptyFieldIcon()); 57 | int x = posX; 58 | int y = posY + (FIELD_TILE_HEIGHT / 6); 59 | for (int i = 0; i < 6; i++) { 60 | if (possib->isPossible(col, row, i + 1)) 61 | screen.draw(x, y, iconSet.getSmallIcon(row, i + 1, 62 | (hCol == col) && (hRow == row) && (i + 1 == subHNo))); 63 | if (i == 2) { 64 | x = posX; 65 | y += (FIELD_TILE_HEIGHT / 3); 66 | } else 67 | x += (FIELD_TILE_WIDTH / 3); 68 | } 69 | } 70 | if (addToUpdate) 71 | screen.addRegionToUpdate(posX, posY, FIELD_TILE_WIDTH, 72 | FIELD_TILE_HEIGHT); 73 | } 74 | 75 | 76 | void Puzzle::drawRow(int row, bool addToUpdate) 77 | { 78 | for (int i = 0; i < PUZZLE_SIZE; i++) 79 | drawCell(i, row, addToUpdate); 80 | } 81 | 82 | 83 | bool Puzzle::onMouseButtonDown(int button, int x, int y) 84 | { 85 | int col, row, element; 86 | 87 | if (! getCellNo(x, y, col, row, element)) 88 | return false; 89 | 90 | if (! possib->isDefined(col, row)) { 91 | /*if (button == 3) { 92 | for (int i = 1; i <= PUZZLE_SIZE; i++) 93 | possib->makePossible(col, row, i); 94 | drawCell(col, row); 95 | } 96 | } else {*/ 97 | if (element == -1) 98 | return false; 99 | if (button == 1) { 100 | if (possib->isPossible(col, row, element)) { 101 | possib->set(col, row, element); 102 | sound->play(L"laser.wav"); 103 | } 104 | } else if (button == 3) { 105 | if (possib->isPossible(col, row, element)) { 106 | possib->exclude(col, row, element); 107 | sound->play(L"whizz.wav"); 108 | } 109 | /*else 110 | possib->makePossible(col, row, element);*/ 111 | } 112 | drawRow(row); 113 | } 114 | 115 | bool valid = possib->isValid(solved); 116 | if (! valid) 117 | onFail(); 118 | else 119 | if (possib->isSolved() && valid) 120 | onVictory(); 121 | 122 | return true; 123 | } 124 | 125 | 126 | void Puzzle::onFail() 127 | { 128 | if (failCommand) 129 | failCommand->doAction(); 130 | } 131 | 132 | 133 | void Puzzle::onVictory() 134 | { 135 | if (winCommand) 136 | winCommand->doAction(); 137 | } 138 | 139 | bool Puzzle::getCellNo(int x, int y, int &col, int &row, int &subNo) 140 | { 141 | col = row = subNo = -1; 142 | 143 | if (! isInRect(x, y, FIELD_OFFSET_X, FIELD_OFFSET_Y, 144 | (FIELD_TILE_WIDTH + FIELD_GAP_X) * PUZZLE_SIZE, 145 | (FIELD_TILE_HEIGHT + FIELD_GAP_Y) * PUZZLE_SIZE)) 146 | return false; 147 | 148 | x = x - FIELD_OFFSET_X; 149 | y = y - FIELD_OFFSET_Y; 150 | 151 | col = x / (FIELD_TILE_WIDTH + FIELD_GAP_X); 152 | if (col * (FIELD_TILE_WIDTH + FIELD_GAP_X) + FIELD_TILE_WIDTH < x) 153 | return false; 154 | row = y / (FIELD_TILE_HEIGHT + FIELD_GAP_Y); 155 | if (row * (FIELD_TILE_HEIGHT + FIELD_GAP_Y) + FIELD_TILE_HEIGHT < y) 156 | return false; 157 | 158 | x = x - col * (FIELD_TILE_WIDTH + FIELD_GAP_X); 159 | y = y - row * (FIELD_TILE_HEIGHT + FIELD_GAP_Y) 160 | - FIELD_TILE_HEIGHT / 6; 161 | if ((y < 0) || (y >= (FIELD_TILE_HEIGHT / 3) * 2)) 162 | return true; 163 | int cCol = x / (FIELD_TILE_WIDTH / 3); 164 | if (cCol >= 3) { 165 | col = row = -1; 166 | return false; 167 | } 168 | int cRow = y / (FIELD_TILE_HEIGHT / 3); 169 | subNo = cRow * 3 + cCol + 1; 170 | 171 | return true; 172 | } 173 | 174 | bool Puzzle::onMouseMove(int x, int y) 175 | { 176 | int oldCol = hCol; 177 | int oldRow = hRow; 178 | int oldElement = subHNo; 179 | 180 | getCellNo(x, y, hCol, hRow, subHNo); 181 | if ((hCol != oldCol) || (hRow != oldRow) || (subHNo != oldElement)) { 182 | if ((oldCol != -1) && (oldRow != -1)) 183 | drawCell(oldCol, oldRow); 184 | if ((hCol != -1) && (hRow != -1)) 185 | drawCell(hCol, hRow); 186 | } 187 | 188 | return false; 189 | } 190 | 191 | void Puzzle::setCommands(Command *win, Command *fail) 192 | { 193 | winCommand = win; 194 | failCommand = fail; 195 | } 196 | 197 | -------------------------------------------------------------------------------- /menu.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "main.h" 3 | #include "utils.h" 4 | #include "widgets.h" 5 | #include "topscores.h" 6 | #include "opensave.h" 7 | #include "game.h" 8 | #include "descr.h" 9 | #include "options.h" 10 | #include "messages.h" 11 | 12 | 13 | 14 | class MenuBackground: public Widget 15 | { 16 | public: 17 | virtual void draw(); 18 | }; 19 | 20 | 21 | void MenuBackground::draw() 22 | { 23 | SDL_Surface *title = loadImage(L"nova.bmp"); 24 | screen.draw(0, 0, title); 25 | SDL_FreeSurface(title); 26 | Font font(L"nova.ttf", 28); 27 | std::wstring s(msg(L"einsteinFlowix")); 28 | int width = font.getWidth(s); 29 | font.draw((screen.getWidth() - width) / 2, 30, 255,255,255, true, s); 30 | Font urlFont(L"luximb.ttf", 16); 31 | s = L"http://games.flowix.com"; 32 | width = urlFont.getWidth(s); 33 | urlFont.draw((screen.getWidth() - width) / 2, 60, 255,255,0, true, s); 34 | screen.addRegionToUpdate(0, 0, screen.getWidth(), screen.getHeight()); 35 | } 36 | 37 | 38 | 39 | class NewGameCommand: public Command 40 | { 41 | private: 42 | Area *area; 43 | 44 | public: 45 | NewGameCommand(Area *a) { area = a; }; 46 | 47 | virtual void doAction() { 48 | Game game; 49 | game.run(); 50 | area->updateMouse(); 51 | area->draw(); 52 | }; 53 | }; 54 | 55 | 56 | class LoadGameCommand: public Command 57 | { 58 | private: 59 | Area *area; 60 | 61 | public: 62 | LoadGameCommand(Area *a) { area = a; }; 63 | 64 | virtual void doAction() { 65 | Game *game = loadGame(area); 66 | if (game) { 67 | game->run(); 68 | delete game; 69 | } 70 | area->updateMouse(); 71 | area->draw(); 72 | }; 73 | }; 74 | 75 | 76 | 77 | class TopScoresCommand: public Command 78 | { 79 | private: 80 | Area *area; 81 | 82 | public: 83 | TopScoresCommand(Area *a) { area = a; }; 84 | 85 | virtual void doAction() { 86 | TopScores scores; 87 | showScoresWindow(area, &scores); 88 | area->updateMouse(); 89 | area->draw(); 90 | }; 91 | }; 92 | 93 | 94 | class RulesCommand: public Command 95 | { 96 | private: 97 | Area *area; 98 | 99 | public: 100 | RulesCommand(Area *a) { area = a; }; 101 | 102 | virtual void doAction() { 103 | showDescription(area); 104 | area->updateMouse(); 105 | area->draw(); 106 | }; 107 | }; 108 | 109 | 110 | class OptionsCommand: public Command 111 | { 112 | private: 113 | Area *area; 114 | 115 | public: 116 | OptionsCommand(Area *a) { area = a; }; 117 | 118 | virtual void doAction() { 119 | showOptionsWindow(area); 120 | area->updateMouse(); 121 | area->draw(); 122 | }; 123 | }; 124 | 125 | 126 | class AboutCommand: public Command 127 | { 128 | private: 129 | Area *parentArea; 130 | 131 | public: 132 | AboutCommand(Area *a) { parentArea = a; }; 133 | 134 | virtual void doAction() { 135 | Area area; 136 | Font titleFont(L"nova.ttf", 26); 137 | Font font(L"laudcn2.ttf", 14); 138 | Font urlFont(L"luximb.ttf", 16); 139 | 140 | #define LABEL(pos, c, f, text) area.add(new Label(&f, 220, pos, 360, 20, \ 141 | Label::ALIGN_CENTER, Label::ALIGN_MIDDLE, 255,255,c, text)); 142 | area.add(parentArea); 143 | area.add(new Window(220, 160, 360, 280, L"blue.bmp")); 144 | area.add(new Label(&titleFont, 250, 165, 300, 40, Label::ALIGN_CENTER, 145 | Label::ALIGN_MIDDLE, 255,255,0, msg(L"about"))); 146 | LABEL(240, 255, font, msg(L"einsteinPuzzle")) 147 | LABEL(260, 255, font, msg(L"version")) 148 | LABEL(280, 255, font, msg(L"copyright")) 149 | LABEL(330, 0, urlFont, L"http://games.flowix.com") 150 | #undef LABEL 151 | ExitCommand exitCmd(area); 152 | area.add(new Button(360, 400, 80, 25, &font, 255,255,0, L"blue.bmp", 153 | msg(L"ok"), &exitCmd)); 154 | area.add(new KeyAccel(SDLK_ESCAPE, &exitCmd)); 155 | area.add(new KeyAccel(SDLK_RETURN, &exitCmd)); 156 | area.run(); 157 | 158 | parentArea->updateMouse(); 159 | parentArea->draw(); 160 | }; 161 | }; 162 | 163 | 164 | static Button* menuButton(int y, Font *font, const std::wstring &text, 165 | Command *cmd=NULL) 166 | { 167 | return new Button(550, y, 220, 30, font, 0,240,240, 30,255,255, text, cmd); 168 | } 169 | 170 | 171 | void menu() 172 | { 173 | Area area; 174 | Font font(L"laudcn2.ttf", 20); 175 | 176 | area.add(new MenuBackground()); 177 | area.draw(); 178 | 179 | NewGameCommand newGameCmd(&area); 180 | area.add(menuButton(340, &font, msg(L"newGame"), &newGameCmd)); 181 | LoadGameCommand loadGameCmd(&area); 182 | area.add(menuButton(370, &font, msg(L"loadGame"), &loadGameCmd)); 183 | TopScoresCommand topScoresCmd(&area); 184 | area.add(menuButton(400, &font, msg(L"topScores"), &topScoresCmd)); 185 | RulesCommand rulesCmd(&area); 186 | area.add(menuButton(430, &font, msg(L"rules"), &rulesCmd)); 187 | OptionsCommand optionsCmd(&area); 188 | area.add(menuButton(460, &font, msg(L"options"), &optionsCmd)); 189 | AboutCommand aboutCmd(&area); 190 | area.add(menuButton(490, &font, msg(L"about"), &aboutCmd)); 191 | ExitCommand exitMenuCmd(area); 192 | area.add(menuButton(520, &font, msg(L"exit"), &exitMenuCmd)); 193 | area.add(new KeyAccel(SDLK_ESCAPE, &exitMenuCmd)); 194 | 195 | area.draw(); 196 | screen.addRegionToUpdate(0, 0, screen.getWidth(), screen.getHeight()); 197 | screen.flush(); 198 | 199 | area.run(); 200 | } 201 | 202 | -------------------------------------------------------------------------------- /mkres/compressor.cpp: -------------------------------------------------------------------------------- 1 | #include "compressor.h" 2 | #include 3 | #include "convert.h" 4 | #include "exceptions.h" 5 | #include 6 | 7 | ResourceCompressor::ResourceCompressor() 8 | { 9 | priority = 1000; 10 | } 11 | 12 | ResourceCompressor::~ResourceCompressor() 13 | { 14 | } 15 | 16 | 17 | void ResourceCompressor::adjustBuffers(int fileSize) 18 | { 19 | int maxComprSize = (int)((fileSize + 100.0) * 2.1); 20 | if (maxComprSize < 1024) 21 | maxComprSize = 1024; 22 | unpackedBuffer.setSize(fileSize); 23 | packedBuffer.setSize(maxComprSize); 24 | } 25 | 26 | 27 | static int writeInt(std::ostream *stream, int v) 28 | { 29 | unsigned char b[4]; 30 | int i, ib; 31 | 32 | for (i = 0; i < 4; i++) { 33 | ib = v & 0xFF; 34 | v = v >> 8; 35 | b[i] = ib; 36 | } 37 | 38 | stream->write((char*)&b, 4); 39 | 40 | return 4; 41 | } 42 | 43 | 44 | static int writeString(std::ostream *stream, const std::wstring &value) 45 | { 46 | std::string v(toUtf8(value)); 47 | int len = v.length() + 1; 48 | stream->write(v.c_str(), len); 49 | return len; 50 | } 51 | 52 | 53 | int ResourceCompressor::writeHeader() 54 | { 55 | int offset = writeString(stream, L"CRF"); 56 | offset += writeInt(stream, 2); 57 | offset += writeInt(stream, 1); 58 | offset += writeInt(stream, priority); 59 | return offset; 60 | } 61 | 62 | 63 | void ResourceCompressor::showEntryStat(Entry &entry) 64 | { 65 | std::cerr << entry.name << " before: " << entry.realSize << 66 | ", after: " << entry.packedSize << ", ratio: " << 67 | (100.0 / entry.realSize) * entry.packedSize << "%" << std::endl; 68 | } 69 | 70 | void ResourceCompressor::openStream(const std::string &outputFile) 71 | { 72 | if ((outputFile.length()) && (outputFile != "-")) { 73 | dontDeleteStream = false; 74 | std::ofstream *s = new std::ofstream(); 75 | stream = s; 76 | s->open(outputFile.c_str(), std::ios::out | std::ios::binary); 77 | if (stream->fail()) { 78 | delete stream; 79 | throw std::string("Can't open output file"); 80 | } 81 | } else { 82 | dontDeleteStream = true; 83 | stream = &std::cout; 84 | } 85 | } 86 | 87 | void ResourceCompressor::closeStream() 88 | { 89 | if (! dontDeleteStream) 90 | delete stream; 91 | } 92 | 93 | void ResourceCompressor::compress(const std::string &outputFile, bool verbose) 94 | { 95 | openStream(outputFile); 96 | 97 | int offset = writeHeader(); 98 | for (Entries::iterator i = entries.begin(); i != entries.end(); i++) { 99 | Entry &e = *i; 100 | compressEntry(e, offset); 101 | if (verbose) 102 | showEntryStat(e); 103 | } 104 | writeFooter(offset); 105 | 106 | closeStream(); 107 | } 108 | 109 | void ResourceCompressor::printDeps(const std::string &outputFile, 110 | const std::string &sourceFile) 111 | { 112 | std::cout << std::endl << outputFile << ": " << sourceFile << " "; 113 | 114 | int width = outputFile.length() + sourceFile.length() + 3; 115 | 116 | for (Entries::iterator i = entries.begin(); i != entries.end(); i++) { 117 | Entry &e = *i; 118 | std::cout << " "; 119 | int len = e.fileName.length() + 1; 120 | if (len + width > 77) { 121 | std::cout << "\\" << std::endl << "\t"; 122 | width = 7; 123 | } 124 | std::cout << e.fileName; 125 | width += len; 126 | } 127 | 128 | std::cout << std::endl; 129 | } 130 | 131 | 132 | void ResourceCompressor::writeFooter(int &offset) 133 | { 134 | int start = offset; 135 | 136 | for (Entries::iterator i = entries.begin(); i != entries.end(); i++) { 137 | Entry &e = *i; 138 | offset += writeString(stream, e.name); 139 | offset += writeInt(stream, e.realSize); 140 | offset += writeInt(stream, e.offset); 141 | offset += writeInt(stream, e.packedSize); 142 | offset += writeInt(stream, e.comprLevel); 143 | offset += writeString(stream, e.group); 144 | } 145 | 146 | offset += writeInt(stream, start); 147 | offset += writeInt(stream, entries.size()); 148 | } 149 | 150 | 151 | static int pack(char *in, int inSize, char *out, int maxOutSize, int level) 152 | { 153 | if (! level) { 154 | if (inSize) 155 | memcpy(out, in, inSize); 156 | return inSize; 157 | } else { 158 | z_stream zs; 159 | memset(&zs, 0, sizeof(z_stream)); 160 | zs.next_in = (Bytef*)in; 161 | zs.avail_in = inSize; 162 | zs.next_out = (Bytef*)out; 163 | zs.avail_out = maxOutSize; 164 | 165 | if (deflateInit(&zs, level) != Z_OK) 166 | throw std::string("Can't init compressor"); 167 | if (deflate(&zs, Z_FINISH) != Z_STREAM_END) 168 | throw std::string("Error compressing data"); 169 | if (deflateEnd(&zs) != Z_OK) 170 | throw std::string("Error finishing compressor"); 171 | 172 | return zs.total_out; 173 | } 174 | } 175 | 176 | 177 | void ResourceCompressor::readData(const std::wstring &fileName) 178 | { 179 | std::ifstream ifs(toMbcs(fileName).c_str(), 180 | std::ios::in | std::ios::binary); 181 | if (ifs.fail()) 182 | throw Exception(L"Error opening file '" + fileName + L"'"); 183 | 184 | ifs.seekg(0, std::ios::end); 185 | int realSize = ifs.tellg(); 186 | unpackedBuffer.setSize(realSize); 187 | ifs.seekg(0, std::ios::beg); 188 | if (realSize <= 0) 189 | throw Exception(L"File '" + fileName + L"' has invalid size"); 190 | 191 | ifs.read((char*)unpackedBuffer.getData(), realSize); 192 | if (ifs.fail() || (ifs.gcount() != realSize)) 193 | throw Exception(L"Error reading from file '" + fileName + L"'"); 194 | ifs.close(); 195 | 196 | } 197 | 198 | void ResourceCompressor::runFormatter(Formatter *formatter, 199 | const std::wstring &fileName) 200 | { 201 | unpackedBuffer.setSize(0); 202 | unpackedBuffer.gotoPos(0); 203 | formatter->format(fileName, unpackedBuffer); 204 | } 205 | 206 | void ResourceCompressor::compressEntry(Entry &entry, int &offset) 207 | { 208 | entry.offset = offset; 209 | 210 | if (! entry.formatter) 211 | readData(entry.fileName); 212 | else 213 | runFormatter(entry.formatter, entry.fileName); 214 | entry.realSize = unpackedBuffer.getSize(); 215 | adjustBuffers(entry.realSize); 216 | 217 | entry.packedSize = pack((char*)unpackedBuffer.getData(), entry.realSize, 218 | (char*)packedBuffer.getData(), packedBuffer.getSize(), 219 | entry.comprLevel); 220 | stream->write((char*)packedBuffer.getData(), entry.packedSize); 221 | 222 | offset += entry.packedSize; 223 | } 224 | 225 | 226 | 227 | -------------------------------------------------------------------------------- /lexal.cpp: -------------------------------------------------------------------------------- 1 | #include "lexal.h" 2 | #include "convert.h" 3 | 4 | 5 | Lexeme::Lexeme(Type t, const std::wstring &cont, int line, int pos) 6 | { 7 | type = t; 8 | content = cont; 9 | this->line = line; 10 | this->pos = pos; 11 | } 12 | 13 | std::wstring Lexeme::getPosStr() const 14 | { 15 | return Lexal::posToStr(line, pos); 16 | } 17 | 18 | 19 | 20 | Lexal::Lexal(UtfStreamReader &rdr): reader(rdr) 21 | { 22 | line = 1; 23 | pos = 0; 24 | } 25 | 26 | 27 | static bool isIdentStart(wchar_t ch) { 28 | return ((L'a' <= ch) && (L'z' >= ch)) || ((L'A' <= ch) && (L'Z' >= ch)) 29 | || (L'_' == ch); 30 | } 31 | 32 | static bool isIdentCont(wchar_t ch) { 33 | return ((L'a' <= ch) && (L'z' >= ch)) || ((L'A' <= ch) && (L'Z' >= ch)) 34 | || (L'_' == ch) || (L'.' == ch) || ((L'0' <= ch) && (L'9' >= ch)); 35 | } 36 | 37 | static bool isWhiteSpace(wchar_t ch) { 38 | return (L' ' == ch) || (L'\t' == ch) || (L'\n' == ch) || (L'\r' == ch); 39 | } 40 | 41 | static bool isDigit(wchar_t ch) { 42 | return (L'0' <= ch) && (L'9' >= ch); 43 | } 44 | 45 | static bool isSymbol(wchar_t ch) { 46 | return (L'{' == ch) || (L'}' == ch) || (L',' == ch) || (L'=' == ch) 47 | || (L';' == ch); 48 | } 49 | 50 | static bool isQuote(wchar_t ch) { 51 | return (L'\'' == ch) || (L'"' == ch); 52 | } 53 | 54 | 55 | std::wstring Lexal::posToStr(int line, int pos) 56 | { 57 | return L"(" + toString(line) + L":" + toString(pos) + L")"; 58 | } 59 | 60 | 61 | Lexeme Lexal::getNext() 62 | { 63 | skipSpaces(); 64 | if (reader.isEof()) 65 | return Lexeme(Lexeme::Eof, L"", line, pos); 66 | 67 | int startLine = line; 68 | int startPos = pos; 69 | 70 | wchar_t ch = reader.getNextChar(); 71 | pos++; 72 | 73 | if (isIdentStart(ch)) 74 | return readIdent(startLine, startPos, ch); 75 | else if (isDigit(ch)) 76 | return readNumber(startLine, startPos, ch); 77 | else if (isQuote(ch)) 78 | return readString(startLine, startPos, ch); 79 | else if (isSymbol(ch)) 80 | return Lexeme(Lexeme::Symbol, toString(ch), startLine, startPos); 81 | 82 | throw Exception(L"Invalid character at "+ posToStr(startLine, startPos)); 83 | } 84 | 85 | 86 | Lexeme Lexal::readString(int startLine, int startPos, wchar_t quote) 87 | { 88 | std::wstring str; 89 | bool closed = false; 90 | 91 | while (! reader.isEof()) { 92 | wchar_t ch = reader.getNextChar(); 93 | pos++; 94 | if ('\n' == ch) { 95 | line++; 96 | pos = 0; 97 | } else if ('\\' == ch) { 98 | if (! reader.isEof()) { 99 | wchar_t nextCh = reader.getNextChar(); 100 | if (isWhiteSpace(nextCh)) 101 | throw Exception(L"Invalid escape sequence at " + 102 | posToStr(line, pos)); 103 | pos++; 104 | switch (nextCh) { 105 | case L'\t': str += L'\t'; break; 106 | case L'\n': str += L'\n'; break; 107 | case L'\r': str += L'\r'; break; 108 | default: 109 | str += nextCh; 110 | } 111 | } 112 | } else if (quote == ch) { 113 | closed = true; 114 | break; 115 | } else 116 | str += ch; 117 | } 118 | 119 | if (! closed) 120 | throw Exception(L"String at " + posToStr(startLine, startPos) 121 | + L" doesn't closed"); 122 | 123 | return Lexeme(Lexeme::String, str, startLine, startPos); 124 | } 125 | 126 | Lexeme Lexal::readNumber(int startLine, int startPos, wchar_t first) 127 | { 128 | std::wstring number; 129 | number += first; 130 | Lexeme::Type type = Lexeme::Integer; 131 | 132 | while (! reader.isEof()) { 133 | wchar_t ch = reader.getNextChar(); 134 | pos++; 135 | if (isDigit(ch)) 136 | number += ch; 137 | else if (L'.' == ch) { 138 | if (Lexeme::Integer == type) { 139 | type = Lexeme::Float; 140 | number += ch; 141 | } else 142 | throw Exception(L"To many dots in number at " + 143 | posToStr(line, pos)); 144 | } else if ((! isSymbol(ch)) && (! isWhiteSpace(ch))) 145 | throw Exception(L"invalid number at " + posToStr(line, pos)); 146 | else { 147 | pos--; 148 | reader.ungetChar(ch); 149 | break; 150 | } 151 | } 152 | 153 | if (L'.' == number[number.length() - 1]) 154 | throw Exception(L"Missing digit after dot at " + posToStr(line, pos)); 155 | 156 | return Lexeme(type, number, startLine, startPos); 157 | } 158 | 159 | Lexeme Lexal::readIdent(int startLine, int startPos, wchar_t first) 160 | { 161 | std::wstring ident; 162 | ident += first; 163 | 164 | while (! reader.isEof()) { 165 | wchar_t ch = reader.getNextChar(); 166 | if (! isIdentCont(ch)) { 167 | reader.ungetChar(ch); 168 | break; 169 | } 170 | ident += ch; 171 | pos++; 172 | } 173 | 174 | return Lexeme(Lexeme::Ident, ident, startLine, startPos); 175 | } 176 | 177 | 178 | void Lexal::skipToLineEnd() 179 | { 180 | while (! reader.isEof()) { 181 | wchar_t ch = reader.getNextChar(); 182 | pos++; 183 | if ('\n' == ch) { 184 | pos = 0; 185 | line++; 186 | return; 187 | } 188 | } 189 | } 190 | 191 | 192 | void Lexal::skipMultilineComment(int startLine, int startPos) 193 | { 194 | while (! reader.isEof()) { 195 | wchar_t ch = reader.getNextChar(); 196 | pos++; 197 | if ('\n' == ch) { 198 | pos = 0; 199 | line++; 200 | } else if (('*' == ch) && (! reader.isEof())) { 201 | wchar_t nextCh = reader.getNextChar(); 202 | if ('/' != nextCh) 203 | reader.ungetChar(nextCh); 204 | } 205 | } 206 | throw Exception(L"Remark started at " + posToStr(startLine, startPos) 207 | + L" is not closed"); 208 | } 209 | 210 | 211 | void Lexal::skipSpaces() 212 | { 213 | while (! reader.isEof()) { 214 | wchar_t ch = reader.getNextChar(); 215 | pos++; 216 | if (! isWhiteSpace(ch)) { 217 | if ('#' == ch) 218 | skipToLineEnd(); 219 | else { 220 | bool finish = false; 221 | if (('/' == ch) && (! reader.isEof())) { 222 | wchar_t nextCh = reader.getNextChar(); 223 | pos++; 224 | if ('/' == nextCh) 225 | skipToLineEnd(); 226 | else if ('*' == nextCh) 227 | skipMultilineComment(line, pos); 228 | else { 229 | pos--; 230 | reader.ungetChar(nextCh); 231 | finish = true; 232 | } 233 | } else 234 | finish = true; 235 | if (finish) { 236 | pos--; 237 | reader.ungetChar(ch); 238 | return; 239 | } 240 | } 241 | } else 242 | if ('\n' == ch) { 243 | pos = 0; 244 | line++; 245 | } 246 | } 247 | } 248 | 249 | -------------------------------------------------------------------------------- /mkres/lexal.cpp: -------------------------------------------------------------------------------- 1 | #include "lexal.h" 2 | #include "convert.h" 3 | 4 | 5 | Lexeme::Lexeme(Type t, const std::wstring &cont, int line, int pos) 6 | { 7 | type = t; 8 | content = cont; 9 | this->line = line; 10 | this->pos = pos; 11 | } 12 | 13 | std::wstring Lexeme::getPosStr() const 14 | { 15 | return Lexal::posToStr(line, pos); 16 | } 17 | 18 | 19 | 20 | Lexal::Lexal(UtfStreamReader &rdr): reader(rdr) 21 | { 22 | line = 1; 23 | pos = 0; 24 | } 25 | 26 | 27 | static bool isIdentStart(wchar_t ch) { 28 | return ((L'a' <= ch) && (L'z' >= ch)) || ((L'A' <= ch) && (L'Z' >= ch)) 29 | || (L'_' == ch); 30 | } 31 | 32 | static bool isIdentCont(wchar_t ch) { 33 | return ((L'a' <= ch) && (L'z' >= ch)) || ((L'A' <= ch) && (L'Z' >= ch)) 34 | || (L'_' == ch) || (L'.' == ch) || ((L'0' <= ch) && (L'9' >= ch)); 35 | } 36 | 37 | static bool isWhiteSpace(wchar_t ch) { 38 | return (L' ' == ch) || (L'\t' == ch) || (L'\n' == ch) || (L'\r' == ch); 39 | } 40 | 41 | static bool isDigit(wchar_t ch) { 42 | return (L'0' <= ch) && (L'9' >= ch); 43 | } 44 | 45 | static bool isSymbol(wchar_t ch) { 46 | return (L'{' == ch) || (L'}' == ch) || (L',' == ch) || (L'=' == ch) 47 | || (L';' == ch); 48 | } 49 | 50 | static bool isQuote(wchar_t ch) { 51 | return (L'\'' == ch) || (L'"' == ch); 52 | } 53 | 54 | 55 | std::wstring Lexal::posToStr(int line, int pos) 56 | { 57 | return L"(" + toString(line) + L":" + toString(pos) + L")"; 58 | } 59 | 60 | 61 | Lexeme Lexal::getNext() 62 | { 63 | skipSpaces(); 64 | if (reader.isEof()) 65 | return Lexeme(Lexeme::Eof, L"", line, pos); 66 | 67 | int startLine = line; 68 | int startPos = pos; 69 | 70 | wchar_t ch = reader.getNextChar(); 71 | pos++; 72 | 73 | if (isIdentStart(ch)) 74 | return readIdent(startLine, startPos, ch); 75 | else if (isDigit(ch)) 76 | return readNumber(startLine, startPos, ch); 77 | else if (isQuote(ch)) 78 | return readString(startLine, startPos, ch); 79 | else if (isSymbol(ch)) 80 | return Lexeme(Lexeme::Symbol, toString(ch), startLine, startPos); 81 | 82 | throw Exception(L"Invalid character at "+ posToStr(startLine, startPos)); 83 | } 84 | 85 | 86 | Lexeme Lexal::readString(int startLine, int startPos, wchar_t quote) 87 | { 88 | std::wstring str; 89 | bool closed = false; 90 | 91 | while (! reader.isEof()) { 92 | wchar_t ch = reader.getNextChar(); 93 | pos++; 94 | if ('\n' == ch) { 95 | line++; 96 | pos = 0; 97 | str += ch; 98 | } else if ('\\' == ch) { 99 | if (! reader.isEof()) { 100 | wchar_t nextCh = reader.getNextChar(); 101 | if (isWhiteSpace(nextCh)) 102 | throw Exception(L"Invalid escape sequence at " + 103 | posToStr(line, pos)); 104 | pos++; 105 | switch (nextCh) { 106 | case L'\t': str += L'\t'; break; 107 | case L'\n': str += L'\n'; break; 108 | case L'\r': str += L'\r'; break; 109 | default: 110 | str += nextCh; 111 | } 112 | } 113 | } else if (quote == ch) { 114 | closed = true; 115 | break; 116 | } else 117 | str += ch; 118 | } 119 | 120 | if (! closed) 121 | throw Exception(L"String at " + posToStr(startLine, startPos) 122 | + L" doesn't closed"); 123 | 124 | return Lexeme(Lexeme::String, str, startLine, startPos); 125 | } 126 | 127 | Lexeme Lexal::readNumber(int startLine, int startPos, wchar_t first) 128 | { 129 | std::wstring number; 130 | number += first; 131 | Lexeme::Type type = Lexeme::Integer; 132 | 133 | while (! reader.isEof()) { 134 | wchar_t ch = reader.getNextChar(); 135 | pos++; 136 | if (isDigit(ch)) 137 | number += ch; 138 | else if (L'.' == ch) { 139 | if (Lexeme::Integer == type) { 140 | type = Lexeme::Float; 141 | number += ch; 142 | } else 143 | throw Exception(L"To many dots in number at " + 144 | posToStr(line, pos)); 145 | } else if ((! isSymbol(ch)) && (! isWhiteSpace(ch))) 146 | throw Exception(L"invalid number at " + posToStr(line, pos)); 147 | else { 148 | pos--; 149 | reader.ungetChar(ch); 150 | break; 151 | } 152 | } 153 | 154 | if (L'.' == number[number.length() - 1]) 155 | throw Exception(L"Missing digit after dot at " + posToStr(line, pos)); 156 | 157 | return Lexeme(type, number, startLine, startPos); 158 | } 159 | 160 | Lexeme Lexal::readIdent(int startLine, int startPos, wchar_t first) 161 | { 162 | std::wstring ident; 163 | ident += first; 164 | 165 | while (! reader.isEof()) { 166 | wchar_t ch = reader.getNextChar(); 167 | if (! isIdentCont(ch)) { 168 | reader.ungetChar(ch); 169 | break; 170 | } 171 | ident += ch; 172 | pos++; 173 | } 174 | 175 | return Lexeme(Lexeme::Ident, ident, startLine, startPos); 176 | } 177 | 178 | 179 | void Lexal::skipToLineEnd() 180 | { 181 | while (! reader.isEof()) { 182 | wchar_t ch = reader.getNextChar(); 183 | pos++; 184 | if ('\n' == ch) { 185 | pos = 0; 186 | line++; 187 | return; 188 | } 189 | } 190 | } 191 | 192 | 193 | void Lexal::skipMultilineComment(int startLine, int startPos) 194 | { 195 | while (! reader.isEof()) { 196 | wchar_t ch = reader.getNextChar(); 197 | pos++; 198 | if ('\n' == ch) { 199 | pos = 0; 200 | line++; 201 | } else if (('*' == ch) && (! reader.isEof())) { 202 | wchar_t nextCh = reader.getNextChar(); 203 | if ('/' != nextCh) 204 | reader.ungetChar(nextCh); 205 | } 206 | } 207 | throw Exception(L"Remark started at " + posToStr(startLine, startPos) 208 | + L" is not closed"); 209 | } 210 | 211 | 212 | void Lexal::skipSpaces() 213 | { 214 | while (! reader.isEof()) { 215 | wchar_t ch = reader.getNextChar(); 216 | pos++; 217 | if (! isWhiteSpace(ch)) { 218 | if ('#' == ch) 219 | skipToLineEnd(); 220 | else { 221 | bool finish = false; 222 | if (('/' == ch) && (! reader.isEof())) { 223 | wchar_t nextCh = reader.getNextChar(); 224 | pos++; 225 | if ('/' == nextCh) 226 | skipToLineEnd(); 227 | else if ('*' == nextCh) 228 | skipMultilineComment(line, pos); 229 | else { 230 | pos--; 231 | reader.ungetChar(nextCh); 232 | finish = true; 233 | } 234 | } else 235 | finish = true; 236 | if (finish) { 237 | pos--; 238 | reader.ungetChar(ch); 239 | return; 240 | } 241 | } 242 | } else 243 | if ('\n' == ch) { 244 | pos = 0; 245 | line++; 246 | } 247 | } 248 | } 249 | 250 | -------------------------------------------------------------------------------- /mkres/messages.cpp: -------------------------------------------------------------------------------- 1 | #include "messages.h" 2 | 3 | #include 4 | #include 5 | #include "convert.h" 6 | #include "unicode.h" 7 | 8 | 9 | class TextCommand: public MsgCommand 10 | { 11 | private: 12 | std::wstring text; 13 | 14 | public: 15 | TextCommand(const std::wstring &s): text(s) { }; 16 | 17 | virtual std::wstring toString() { 18 | return L"text: '" + text + L"'"; 19 | } 20 | 21 | virtual int write(Buffer &buffer) { 22 | int sz = buffer.putByte(1); 23 | //sz += writeInt(stream, text.length()); 24 | sz += buffer.putUtf8(text); 25 | return sz; 26 | } 27 | }; 28 | 29 | class ArgCommand: public MsgCommand 30 | { 31 | protected: 32 | int argNo; 33 | 34 | public: 35 | ArgCommand(int no) { argNo = no; }; 36 | }; 37 | 38 | 39 | class IntArgCommand: public ArgCommand 40 | { 41 | public: 42 | IntArgCommand(int no): ArgCommand(no) { }; 43 | 44 | virtual std::wstring toString() { 45 | return L"int_arg " + ::toString(argNo); 46 | } 47 | 48 | virtual int write(Buffer &buffer) { 49 | int sz = buffer.putByte(2); 50 | sz += buffer.putInteger(4); 51 | sz += buffer.putInteger(argNo); 52 | return sz; 53 | } 54 | }; 55 | 56 | 57 | class StrArgCommand: public ArgCommand 58 | { 59 | public: 60 | StrArgCommand(int no): ArgCommand(no) { }; 61 | virtual std::wstring toString() { 62 | return L"str_arg " + ::toString(argNo); 63 | } 64 | 65 | virtual int write(Buffer &buffer) { 66 | int sz = buffer.putByte(3); 67 | sz += buffer.putInteger(4); 68 | sz += buffer.putInteger(argNo); 69 | return sz; 70 | } 71 | }; 72 | 73 | 74 | class FloatArgCommand: public ArgCommand 75 | { 76 | public: 77 | FloatArgCommand(int no): ArgCommand(no) { }; 78 | 79 | virtual std::wstring toString() { 80 | return L"float_arg " + ::toString(argNo); 81 | } 82 | 83 | virtual int write(Buffer &buffer) { 84 | int sz = buffer.putByte(4); 85 | sz += buffer.putInteger(4); 86 | sz += buffer.putInteger(argNo); 87 | return sz; 88 | } 89 | }; 90 | 91 | 92 | class DoubleArgCommand: public ArgCommand 93 | { 94 | public: 95 | DoubleArgCommand(int no): ArgCommand(no) { }; 96 | 97 | virtual std::wstring toString() { 98 | return L"float_arg " + ::toString(argNo); 99 | } 100 | 101 | virtual int write(Buffer &buffer) { 102 | int sz = buffer.putByte(5); 103 | sz += buffer.putInteger(4); 104 | sz += buffer.putInteger(argNo); 105 | return sz; 106 | } 107 | }; 108 | 109 | 110 | ////////////////////////////////////////////////////////////////////////// 111 | // 112 | // Message 113 | // 114 | ////////////////////////////////////////////////////////////////////////// 115 | 116 | 117 | Message::Message(const std::wstring &msg) 118 | { 119 | int len = msg.length(); 120 | std::wstring str; 121 | int i = 0; 122 | bool numbersUsed = false; 123 | int currentArg = 1; 124 | 125 | while (i < len) { 126 | wchar_t ch = msg[i]; 127 | if ((L'%' == ch) && (i != len - 1)) { 128 | ch = msg[++i]; 129 | if (L'%' != ch) { 130 | if (str.length()) { 131 | commands.push_back(new TextCommand(str)); 132 | str.clear(); 133 | } 134 | while ((ch >= L'0') && (ch <= L'9') && (i < len)) { // read arg no 135 | str += ch; 136 | ch = msg[++i]; 137 | } 138 | if (i == len) 139 | throw Exception(L"Escape sequence is not finished"); 140 | if (L'$' == ch) { // skeep $ sign 141 | ch = msg[++i]; 142 | if (i == len) 143 | throw Exception(L"Escape sequence is not finished"); 144 | } 145 | int argNo; 146 | if (str.length()) { 147 | argNo = strToInt(str); 148 | str.clear(); 149 | numbersUsed = true; 150 | } else { 151 | if (numbersUsed) 152 | throw Exception(L"Can't use unnumbered arguments" 153 | L" if numbered was used before"); 154 | argNo = currentArg++; 155 | } 156 | if (argNo <= 0) 157 | throw Exception(L"Invalid argument number"); 158 | MsgCommand *cmd; 159 | switch (ch) { 160 | case L'd': 161 | case L'i': cmd = new IntArgCommand(argNo); break; 162 | case L's': cmd = new StrArgCommand(argNo); break; 163 | case L'f': cmd = new FloatArgCommand(argNo); break; 164 | case L'e': cmd = new DoubleArgCommand(argNo); break; 165 | default: 166 | throw Exception(std::wstring(L"Format string '%") 167 | + ch + std::wstring(L"' is not supported")); 168 | } 169 | commands.push_back(cmd); 170 | } else 171 | str += ch; 172 | } else 173 | str += ch; 174 | i++; 175 | } 176 | 177 | if (str.length()) 178 | commands.push_back(new TextCommand(str)); 179 | } 180 | 181 | 182 | Message::~Message() 183 | { 184 | for (Commands::iterator i = commands.begin(); i != commands.end(); i++) 185 | delete *i; 186 | } 187 | 188 | int Message::save(Buffer &buffer) 189 | { 190 | int sz = buffer.putInteger(commands.size()); 191 | for (Commands::iterator i = commands.begin(); i != commands.end(); i++) { 192 | MsgCommand *cmd = *i; 193 | sz += cmd->write(buffer); 194 | } 195 | return sz; 196 | } 197 | 198 | ////////////////////////////////////////////////////////////////////////// 199 | // 200 | // Messages 201 | // 202 | ////////////////////////////////////////////////////////////////////////// 203 | 204 | Messages::Messages() 205 | { 206 | } 207 | 208 | Messages::~Messages() 209 | { 210 | for (MsgMap::iterator i = messages.begin(); i != messages.end(); i++) 211 | delete (*i).second.message; 212 | } 213 | 214 | void Messages::add(const std::wstring &key, const std::wstring &msg) 215 | { 216 | Message *message = new Message(msg); 217 | 218 | MsgMap::iterator iter = messages.find(key); 219 | if (iter != messages.end()) { 220 | std::cerr << L"Warning: message '" << key << L"' already exists" 221 | << std::endl; 222 | delete (*iter).second.message; 223 | } 224 | 225 | MsgEntry entry = { 0, message }; 226 | messages[key] = entry; 227 | } 228 | 229 | int Messages::writeHeader(Buffer &buffer) 230 | { 231 | buffer.putData("CMF", 3); 232 | int offset = 3; 233 | offset += buffer.putInteger(1); 234 | offset += buffer.putInteger(0); 235 | return offset; 236 | } 237 | 238 | int Messages::writeMessages(Buffer &buffer, int offset) 239 | { 240 | for (MsgMap::iterator i = messages.begin(); i != messages.end(); i++) { 241 | MsgEntry &e = (*i).second; 242 | e.offset = offset; 243 | offset += e.message->save(buffer); 244 | } 245 | return offset; 246 | } 247 | 248 | int Messages::writeDirectory(Buffer &buffer) 249 | { 250 | int offset = buffer.putInteger(messages.size()); 251 | for (MsgMap::iterator i = messages.begin(); i != messages.end(); i++) { 252 | const std::wstring &name = (*i).first; 253 | offset += buffer.putUtf8(name); 254 | offset += buffer.putInteger((*i).second.offset); 255 | } 256 | return offset; 257 | } 258 | 259 | void Messages::save(Buffer &buffer) 260 | { 261 | int offset = writeHeader(buffer); 262 | offset = writeMessages(buffer, offset); 263 | int headerStart = offset; 264 | writeDirectory(buffer); 265 | buffer.putInteger(headerStart); 266 | } 267 | 268 | --------------------------------------------------------------------------------