1 #include "rogueviz.h"
2 
3 /* a sample higher dimensional Sokoban puzzle */
4 
5 namespace rogueviz {
6 
7 namespace crystal_sokoban {
8 
9 vector<string> sokomap = {
10   "########|########|########|########|########|########|########|########",
11   "########|########|## #####|## #####|########|########|########|########",
12   "########|##. ####|# $  ###|##.$####|##. ####|########|########|########",
13   "########|##.#####|# $$@###|##  ####|## #####|########|########|########",
14   "########|########|## #####|## #####|########|########|########|########",
15   "########|########|########|########|########|########|########|########",
16   "########|########|########|########|########|########|########|########",
17   "########|########|########|########|########|########|########|########"
18   };
19 
20 bool on;
21 
22 bool created;
23 
24 vector<cell*> celllist;
25 
26 struct undo_state {
27   vector<eWall> board;
28   cell* where;
29   };
30 
31 vector<undo_state> undos;
32 
current_state()33 undo_state current_state() {
34   undo_state u;
35   u.where = cwt.at;
36   for(cell *c: celllist) u.board.push_back(c->wall);
37   return u;
38   }
39 
40 void sb_hooks();
41 
run_sb()42 void run_sb() {
43   showstartmenu = false;
44   crystal::compass_probability = 0;
45   stop_game();
46   crystal::set_crystal(6);
47   set_variation(eVariation::pure);
48   firstland = specialland = laCanvas;
49   patterns::whichCanvas = 'g';
50   patterns::canvasback = 0x101010;
51   check_cgi();
52   start_game();
53 
54   for(int z=-8; z<8; z++)
55   for(int y=-8; y<8; y++)
56   for(int x=-8; x<8; x++) {
57     crystal::coord co = crystal::c0; co[0] = 2*x; co[1] = 2*y; co[2] = 2*z;
58     cell *c = crystal::get_heptagon_at(co)->c7;
59     setdist(c, 7, c);
60     }
61 
62   for(int z=-8; z<8; z++)
63   for(int y=-8; y<8; y++)
64   for(int x=-8; x<8; x++) {
65     char what;
66     if(x<0 || y<0 || z<0)
67       what = '#';
68     else
69       what = sokomap[y][x*9+z];
70 
71     crystal::coord co = crystal::c0; co[0] = 2*x; co[1] = 2*y; co[2] = 2*z;
72     cell *c = crystal::get_heptagon_at(co)->c7;
73 
74     color_t col;
75     for(int i=0; i<3; i++)
76       part(col, i) = 0x80 + 0x20 * (co[i] - 5);
77 
78     c->landparam = col;
79 
80     if(what == '#')
81       c->wall = waStone;
82     else if(what == '$')
83       c->wall = waCrateCrate;
84     else if(what == '*')
85       c->wall = waCrateOnTarget;
86     else if(what == '.')
87       c->wall = waCrateTarget;
88     else {
89       c->wall = waNone;
90       if(what == '@') {
91         cwt.at = c;
92         centerover = c;
93         }
94       }
95     celllist.push_back(c);
96     }
97   vid.smart_range_detail = ISWEB ? 20 : 1;
98   vid.use_smart_range = 2;
99   undos.push_back(current_state());
100   peace::on = true;
101   }
102 
save_undo()103 void save_undo() {
104   undos.push_back(current_state());
105   }
106 
restore_undo()107 void restore_undo() {
108   undos.pop_back();
109   auto& u = undos.back();
110   cwt.at = u.where;
111   current_display->which_copy = Id;
112   int i = 0;
113   for(cell *c: celllist) c->wall = u.board[i++];
114 
115   undos.pop_back();
116   }
117 
sokomap2()118 bool sokomap2() {
119 
120   if(undos.back().where != cwt.at) save_undo();
121 
122   if(1) {
123     glflush();
124     dynamicval<eGeometry> g(geometry, gEuclidSquare);
125     check_cgi();
126     cgi.require_shapes();
127     initquickqueue();
128 
129     if(1) {
130       auto gm = gmatrix;
131       dynamicval<bool> ww(wmspatial, false);
132       dynamicval<bool> wm(mmspatial, false);
133       dynamicval<shiftmatrix> s1(playerV);
134       dynamicval<transmatrix> s2(current_display->which_copy);
135       dynamicval<shiftmatrix> s3(cwtV, cwtV);
136       dynamicval<array<map<cell*, animation>, ANIMLAYERS>> an(animations);
137       animations[LAYER_SMALL] = {};
138 
139       for(int x=0; x<4; x++)
140       for(int y=0; y<4; y++)
141       for(int z=0; z<4; z++) {
142         crystal::coord co = crystal::c0; co[0] = 2*x+2; co[1] = 2*y+2; co[2] = 2*z+2;
143         cell *c = crystal::get_heptagon_at(co)->c7;
144         drawcell(c, shiftless(euscale(.12,.12) * eupush(3+(vid.xres*1./vid.yres-1)*12, -16) * eupush(z*4.2+x, y) * Id));
145         }
146 
147       gmatrix = gm;
148       }
149 
150     quickqueue();
151     glflush();
152     }
153 
154   check_cgi();
155 
156   return true;
157   }
158 
soko_key(int sym,int uni)159 bool soko_key(int sym, int uni) {
160   if((cmode & sm::NORMAL) && (uni == SDLK_BACKSPACE || uni == 'r') && isize(undos) != 1) {
161     restore_undo();
162     return true;
163     }
164   return false;
165   }
166 
sb_hooks()167 void sb_hooks() {
168   rv_hook(hooks_prestats, 90, sokomap2);
169   rv_hook(hooks_welcome_message, 50, [] () {
170     addMessage(XLAT("Welcome to Crystal Sokoban!"));
171     return true;
172     });
173   rv_hook(hooks_handleKey, 50, soko_key);
174   }
175 
176 auto sbhook = arg::add2("-crystal-sokoban", run_sb);
177 
178 
179 }
180 
181 }