hyperrogue/rogueviz/crystal-sokoban.cpp

187 lines
4.5 KiB
C++

#include "rogueviz.h"
/* a sample higher dimensional Sokoban puzzle */
namespace rogueviz {
namespace crystal_sokoban {
vector<string> sokomap = {
"########|########|########|########|########|########|########|########",
"########|########|## #####|## #####|########|########|########|########",
"########|##. ####|# $ ###|##.$####|##. ####|########|########|########",
"########|##.#####|# $$@###|## ####|## #####|########|########|########",
"########|########|## #####|## #####|########|########|########|########",
"########|########|########|########|########|########|########|########",
"########|########|########|########|########|########|########|########",
"########|########|########|########|########|########|########|########"
};
bool on;
bool created;
vector<cell*> celllist;
struct undo_state {
vector<eWall> board;
cell* where;
};
vector<undo_state> undos;
undo_state current_state() {
undo_state u;
u.where = cwt.at;
for(cell *c: celllist) u.board.push_back(c->wall);
return u;
}
void sb_hooks();
void run_sb() {
showstartmenu = false;
crystal::compass_probability = 0;
stop_game();
crystal::set_crystal(6);
set_variation(eVariation::pure);
enable_canvas();
patterns::whichCanvas = 'g';
patterns::canvasback = 0x101010;
check_cgi();
start_game();
for(int z=-8; z<8; z++)
for(int y=-8; y<8; y++)
for(int x=-8; x<8; x++) {
crystal::coord co = crystal::c0; co[0] = 2*x; co[1] = 2*y; co[2] = 2*z;
cell *c = crystal::get_heptagon_at(co)->c7;
setdist(c, 7, c);
}
for(int z=-8; z<8; z++)
for(int y=-8; y<8; y++)
for(int x=-8; x<8; x++) {
char what;
if(x<0 || y<0 || z<0)
what = '#';
else
what = sokomap[y][x*9+z];
crystal::coord co = crystal::c0; co[0] = 2*x; co[1] = 2*y; co[2] = 2*z;
cell *c = crystal::get_heptagon_at(co)->c7;
color_t col;
for(int i=0; i<3; i++)
part(col, i) = 0x80 + 0x20 * (co[i] - 5);
c->landparam = col;
if(what == '#')
c->wall = waStone;
else if(what == '$')
c->wall = waCrateCrate;
else if(what == '*')
c->wall = waCrateOnTarget;
else if(what == '.')
c->wall = waCrateTarget;
else {
c->wall = waNone;
if(what == '@') {
cwt.at = c;
centerover = c;
}
}
celllist.push_back(c);
}
vid.smart_range_detail = ISWEB ? 20 : 1;
vid.use_smart_range = 2;
undos.push_back(current_state());
peace::on = true;
sb_hooks();
}
void save_undo() {
undos.push_back(current_state());
}
void restore_undo() {
undos.pop_back();
auto& u = undos.back();
cwt.at = u.where;
current_display->which_copy = Id;
int i = 0;
for(cell *c: celllist) c->wall = u.board[i++];
undos.pop_back();
}
bool sokomap2() {
if(undos.back().where != cwt.at) save_undo();
if(1) {
glflush();
dynamicval<eGeometry> g(geometry, gEuclidSquare);
check_cgi();
cgi.require_shapes();
initquickqueue();
if(1) {
auto gm = gmatrix;
dynamicval<bool> ww(wmspatial, false);
dynamicval<bool> wm(mmspatial, false);
dynamicval<shiftmatrix> s1(playerV);
dynamicval<transmatrix> s2(current_display->which_copy);
dynamicval<shiftmatrix> s3(cwtV, cwtV);
dynamicval<array<map<cell*, animation>, ANIMLAYERS>> an(animations);
animations[LAYER_SMALL] = {};
for(int x=0; x<4; x++)
for(int y=0; y<4; y++)
for(int z=0; z<4; z++) {
crystal::coord co = crystal::c0; co[0] = 2*x+2; co[1] = 2*y+2; co[2] = 2*z+2;
cell *c = crystal::get_heptagon_at(co)->c7;
drawcell(c, shiftless(euscale(.12,.12) * eupush(3+(vid.xres*1./vid.yres-1)*12, -16) * eupush(z*4.2+x, y) * Id));
}
gmatrix = gm;
}
quickqueue();
glflush();
}
check_cgi();
return true;
}
bool soko_key(int sym, int uni) {
if((cmode & sm::NORMAL) && (uni == SDLK_BACKSPACE || uni == 'r') && isize(undos) != 1) {
restore_undo();
return true;
}
return false;
}
void sb_hooks() {
rv_hook(hooks_prestats, 90, sokomap2);
rv_hook(hooks_welcome_message, 50, [] () {
addMessage(XLAT("Welcome to Crystal Sokoban!"));
return true;
});
rv_hook(hooks_handleKey, 50, soko_key);
on_cleanup_or_next([] {
undos.clear();
celllist.clear();
});
}
auto sbhook = arg::add2("-crystal-sokoban", run_sb);
}
}