mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 14:02:59 +00:00 
			
		
		
		
	loading/saving irregular maps to config and log (and recreate automatically)H
This commit is contained in:
		| @@ -262,6 +262,14 @@ void initConfig() { | |||||||
|   addsaver(nohud, "no-hud", false); |   addsaver(nohud, "no-hud", false); | ||||||
|   addsaver(nofps, "no-fps", false); |   addsaver(nofps, "no-fps", false); | ||||||
|    |    | ||||||
|  |   addsaver(irr::on, "irregular", false); | ||||||
|  |   addsaver(irr::density, "irregular-density", 6); | ||||||
|  |   addsaver(irr::cellcount, "irregular-cellcount", 150); | ||||||
|  |   addsaver(irr::quality, "irregular-quality", .2); | ||||||
|  |   addsaver(irr::place_attempts, "irregular-place", 10); | ||||||
|  |   addsaver(irr::rearrange_max_attempts, "irregular-rearrange-max", 50); | ||||||
|  |   addsaver(irr::rearrange_less, "irregular-rearrangeless", 10); | ||||||
|  |    | ||||||
| #if CAP_SHMUP   | #if CAP_SHMUP   | ||||||
|   shmup::initConfig(); |   shmup::initConfig(); | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -513,9 +513,9 @@ namespace irr { | |||||||
|       /* if(siid == 0) |       /* if(siid == 0) | ||||||
|         for(auto& ma: m.v) ma.first = ma.first * pispin; */ |         for(auto& ma: m.v) ma.first = ma.first * pispin; */ | ||||||
|    |    | ||||||
|       fsh.b.resize(irr::sc); |       fsh.b.resize(irr::cellcount); | ||||||
|  |  | ||||||
|       for(int id=0; id<irr::sc; id++) {       |       for(int id=0; id<irr::cellcount; id++) {       | ||||||
|         auto& vs = irr::cells[id]; |         auto& vs = irr::cells[id]; | ||||||
|  |  | ||||||
|         int cor = isize(vs.vertices); |         int cor = isize(vs.vertices); | ||||||
| @@ -554,10 +554,10 @@ namespace irr { | |||||||
|  |  | ||||||
|       ld sca = fsh.rad0 / shFullFloor.rad0; |       ld sca = fsh.rad0 / shFullFloor.rad0; | ||||||
|        |        | ||||||
|       fsh.b.resize(irr::sc); |       fsh.b.resize(irr::cellcount); | ||||||
|       fsh.shadow.resize(irr::sc);         |       fsh.shadow.resize(irr::cellcount);         | ||||||
|        |        | ||||||
|       for(int i=0; i<irr::sc; i++) {       |       for(int i=0; i<irr::cellcount; i++) {       | ||||||
|         auto& vs = irr::cells[i]; |         auto& vs = irr::cells[i]; | ||||||
|         vector<hyperpoint> cornerlist; |         vector<hyperpoint> cornerlist; | ||||||
|          |          | ||||||
| @@ -580,7 +580,7 @@ namespace irr { | |||||||
|    |    | ||||||
|         for(int k=0; k<SIDEPARS; k++)  |         for(int k=0; k<SIDEPARS; k++)  | ||||||
|           for(int c=0; c<cor; c++) { |           for(int c=0; c<cor; c++) { | ||||||
|             fsh.gpside[k][c].resize(irr::sc); |             fsh.gpside[k][c].resize(irr::cellcount); | ||||||
|             bshape(fsh.gpside[k][c][i], fsh.prio); |             bshape(fsh.gpside[k][c][i], fsh.prio); | ||||||
|             hpcpush(iddspin(&fc, c) * cornerlist[c]); |             hpcpush(iddspin(&fc, c) * cornerlist[c]); | ||||||
|             hpcpush(iddspin(&fc, c) * cornerlist[(c+1)%cor]); |             hpcpush(iddspin(&fc, c) * cornerlist[(c+1)%cor]); | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								hyper.h
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								hyper.h
									
									
									
									
									
								
							| @@ -2551,7 +2551,13 @@ struct hrmap_hyperbolic : hrmap { | |||||||
|  |  | ||||||
| namespace irr {  | namespace irr {  | ||||||
|   extern bool on; |   extern bool on; | ||||||
|  |   extern ld density; | ||||||
|  |   extern ld quality; | ||||||
|  |   extern int cellcount; | ||||||
|   extern ld scale; |   extern ld scale; | ||||||
|  |   extern int place_attempts; | ||||||
|  |   extern int rearrange_max_attempts; | ||||||
|  |   extern int rearrange_less; | ||||||
|   void link_to_base(heptagon *h, heptspin base); |   void link_to_base(heptagon *h, heptspin base); | ||||||
|   void link_start(heptagon *h); |   void link_start(heptagon *h); | ||||||
|   void link_next(heptagon *h, int d); |   void link_next(heptagon *h, int d); | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								init.cpp
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								init.cpp
									
									
									
									
									
								
							| @@ -39,6 +39,7 @@ void initAll() { | |||||||
|   initgraph(); |   initgraph(); | ||||||
| #if CAP_SAVE | #if CAP_SAVE | ||||||
|   loadsave(); |   loadsave(); | ||||||
|  |   if(irr::on) irr::auto_creator(); | ||||||
| #endif | #endif | ||||||
|   start_game(); |   start_game(); | ||||||
|    |    | ||||||
|   | |||||||
							
								
								
									
										116
									
								
								irregular.cpp
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								irregular.cpp
									
									
									
									
									
								
							| @@ -4,9 +4,11 @@ bool on; | |||||||
|  |  | ||||||
| ld density = 6; | ld density = 6; | ||||||
| ld quality = .2; | ld quality = .2; | ||||||
| int rearrange_attempts; | int place_attempts = 10; | ||||||
|  | int rearrange_max_attempts = 50; | ||||||
|  | int rearrange_less = 10; | ||||||
|  |  | ||||||
| int sc; | int cellcount; | ||||||
|  |  | ||||||
| struct cellinfo { | struct cellinfo { | ||||||
|   cell *owner; |   cell *owner; | ||||||
| @@ -92,6 +94,8 @@ hrmap *base; | |||||||
|  |  | ||||||
| bool gridmaking; | bool gridmaking; | ||||||
|  |  | ||||||
|  | int rearrange_index; | ||||||
|  |  | ||||||
| bool step(int delta) { | bool step(int delta) { | ||||||
|  |  | ||||||
|   if(!gridmaking) return false; |   if(!gridmaking) return false; | ||||||
| @@ -108,7 +112,7 @@ bool step(int delta) { | |||||||
|      cells_of_heptagon.clear(); |      cells_of_heptagon.clear(); | ||||||
|      cellindex.clear(); |      cellindex.clear(); | ||||||
|       |       | ||||||
|      if(sc <= isize(all) * 2) { |      if(cellcount <= isize(all) * 2) { | ||||||
|        for(auto h: all) { |        for(auto h: all) { | ||||||
|          cellinfo s; s.patterndir = -1; |          cellinfo s; s.patterndir = -1; | ||||||
|          s.owner = h, s.p = spin(hrand(1000)) * xpush(.01) * C0; |          s.owner = h, s.p = spin(hrand(1000)) * xpush(.01) * C0; | ||||||
| @@ -120,11 +124,11 @@ bool step(int delta) { | |||||||
|       } |       } | ||||||
|       |       | ||||||
|     case 1: { |     case 1: { | ||||||
|       while(isize(cells) < sc) { |       while(isize(cells) < cellcount) { | ||||||
|         if(SDL_GetTicks() > t + 250) { make_cells_of_heptagon(); status[0] = its(isize(cells)) + " cells"; return false; } |         if(SDL_GetTicks() > t + 250) { make_cells_of_heptagon(); status[0] = its(isize(cells)) + " cells"; return false; } | ||||||
|         cellinfo s; s.patterndir = -1; |         cellinfo s; s.patterndir = -1; | ||||||
|         ld bestval = 0; |         ld bestval = 0; | ||||||
|         for(int j=0; j<10; j++) { |         for(int j=0; j<place_attempts; j++) { | ||||||
|           int k = hrand(isize(all)); |           int k = hrand(isize(all)); | ||||||
|           cell *c = all[k]; |           cell *c = all[k]; | ||||||
|           hyperpoint h = randomPointIn(c->type); |           hyperpoint h = randomPointIn(c->type); | ||||||
| @@ -155,7 +159,7 @@ bool step(int delta) { | |||||||
|       int stats[16]; |       int stats[16]; | ||||||
|       for(int k=0; k<16; k++) stats[k] = 0; |       for(int k=0; k<16; k++) stats[k] = 0; | ||||||
|        |        | ||||||
|       for(int i=0; i<sc; i++) { |       for(int i=0; i<cellcount; i++) { | ||||||
|         auto &p1 = cells[i]; |         auto &p1 = cells[i]; | ||||||
|         p1.vertices.clear(); |         p1.vertices.clear(); | ||||||
|         p1.neid.clear(); |         p1.neid.clear(); | ||||||
| @@ -165,7 +169,7 @@ bool step(int delta) { | |||||||
|          |          | ||||||
|         p1.jpoints.clear(); |         p1.jpoints.clear(); | ||||||
|      |      | ||||||
|         for(int j=0; j<sc; j++) { |         for(int j=0; j<cellcount; j++) { | ||||||
|           auto &p2 = cells[j]; |           auto &p2 = cells[j]; | ||||||
|           p1.jpoints.push_back(p1.rpusher * shmup::calc_relative_matrix(p2.owner, p1.owner, p1.p) * p2.p); |           p1.jpoints.push_back(p1.rpusher * shmup::calc_relative_matrix(p2.owner, p1.owner, p1.p) * p2.p); | ||||||
|           } |           } | ||||||
| @@ -173,7 +177,7 @@ bool step(int delta) { | |||||||
|         int j = 0; |         int j = 0; | ||||||
|         if(j == i) j = 1; |         if(j == i) j = 1; | ||||||
|      |      | ||||||
|         for(int k=0; k<sc; k++) if(k != i) { |         for(int k=0; k<cellcount; k++) if(k != i) { | ||||||
|           if(hdist(p1.jpoints[k], C0) < hdist(p1.jpoints[j], C0)) |           if(hdist(p1.jpoints[k], C0) < hdist(p1.jpoints[j], C0)) | ||||||
|             j = k; |             j = k; | ||||||
|           } |           } | ||||||
| @@ -185,7 +189,7 @@ bool step(int delta) { | |||||||
|         do { |         do { | ||||||
|           int best_k = -1; |           int best_k = -1; | ||||||
|           hyperpoint best_h; |           hyperpoint best_h; | ||||||
|           for(int k=0; k<sc; k++) if(k != i && k != j && k != oldj) { |           for(int k=0; k<cellcount; k++) if(k != i && k != j && k != oldj) { | ||||||
|             hyperpoint h = circumscribe(C0, p1.jpoints[j], p1.jpoints[k]); |             hyperpoint h = circumscribe(C0, p1.jpoints[j], p1.jpoints[k]); | ||||||
|             if(h[2] < 0) continue; |             if(h[2] < 0) continue; | ||||||
|             if(!clockwise(t, h)) continue; |             if(!clockwise(t, h)) continue; | ||||||
| @@ -242,9 +246,9 @@ bool step(int delta) { | |||||||
|        |        | ||||||
|       if(errors > 0) status[1] = XLAT("bad cells: %1", its(errors)); else status[1] = " "; |       if(errors > 0) status[1] = XLAT("bad cells: %1", its(errors)); else status[1] = " "; | ||||||
|       if(toobig > 0) status[2] = XLAT("too many edges: %1", its(toobig)); else status[2] = " "; |       if(toobig > 0) status[2] = XLAT("too many edges: %1", its(toobig)); else status[2] = " "; | ||||||
|       if(isize(cells) < sc*3/4) runlevel = 0; |       if(isize(cells) < cellcount*3/4) runlevel = 0; | ||||||
|       else if(isize(cells) < sc) runlevel = 1; |       else if(isize(cells) < cellcount) runlevel = 1; | ||||||
|       else { rearrange_attempts = 20; runlevel++; } |       else { rearrange_index = 0; runlevel++; } | ||||||
|       break; |       break; | ||||||
|       } |       } | ||||||
|      |      | ||||||
| @@ -254,23 +258,29 @@ bool step(int delta) { | |||||||
|       ld minedge = median * quality; |       ld minedge = median * quality; | ||||||
|       status[3] = XLAT("median edge: %1 minimum: %2", fts4(median), fts4(edgelens[0])); |       status[3] = XLAT("median edge: %1 minimum: %2", fts4(median), fts4(edgelens[0])); | ||||||
|       if(edgelens[0] < minedge) { |       if(edgelens[0] < minedge) { | ||||||
|  |         if(rearrange_index >= rearrange_max_attempts) { | ||||||
|  |           runlevel = 0; break; | ||||||
|  |           } | ||||||
|         int tooshort = 0; |         int tooshort = 0; | ||||||
|         for(int i=0; i<isize(cells); i++) { |         for(int i=0; i<isize(cells); i++) { | ||||||
|           auto& p1 = cells[i]; |           auto& p1 = cells[i]; | ||||||
|           using namespace hyperpoint_vec; |           using namespace hyperpoint_vec; | ||||||
|           hyperpoint h = hpxyz(0, 0, 0); |           hyperpoint h = hpxyz(0, 0, 0); | ||||||
|           for(auto v: p1.vertices) h = h + v; |           for(auto v: p1.vertices) h = h + v; | ||||||
|  |            | ||||||
|  |           bool changed = rearrange_index < rearrange_less; | ||||||
|      |      | ||||||
|           for(int j=0; j<isize(p1.vertices); j++) |           for(int j=0; j<isize(p1.vertices); j++) | ||||||
|             if(hdist(p1.vertices[j], p1.vertices[(j+1) % isize(p1.vertices)]) < minedge) { |             if(hdist(p1.vertices[j], p1.vertices[(j+1) % isize(p1.vertices)]) < minedge) { | ||||||
|               tooshort++; |               tooshort++; changed = true; | ||||||
|               h = h + p1.vertices[j] + p1.vertices[(j+1) % isize(p1.vertices)]; |               h = h + p1.vertices[j] + p1.vertices[(j+1) % isize(p1.vertices)]; | ||||||
|               } |               } | ||||||
|           cells[i].p = p1.pusher * normalize(h); |           if(changed) | ||||||
|  |             cells[i].p = p1.pusher * normalize(h); | ||||||
|           } |           } | ||||||
|         status[3] += XLAT(" (edges too short: %1)", its(tooshort)); |         status[3] += XLAT(" (edges too short: %1)", its(tooshort)); | ||||||
|         runlevel = 2; |         runlevel = 2; | ||||||
|         rearrange_attempts--; if(rearrange_attempts < 0) runlevel = 0; |         rearrange_index++; | ||||||
|         break; |         break; | ||||||
|         } |         } | ||||||
|       runlevel++; |       runlevel++; | ||||||
| @@ -281,7 +291,7 @@ bool step(int delta) { | |||||||
|        |        | ||||||
|       int notfound = 0; |       int notfound = 0; | ||||||
|      |      | ||||||
|       for(int i=0; i<sc; i++) { |       for(int i=0; i<cellcount; i++) { | ||||||
|         auto &p1 = cells[i]; |         auto &p1 = cells[i]; | ||||||
|         int N = isize(p1.vertices); |         int N = isize(p1.vertices); | ||||||
|         p1.spin.resize(N); |         p1.spin.resize(N); | ||||||
| @@ -310,7 +320,7 @@ bool step(int delta) { | |||||||
|         } |         } | ||||||
|      |      | ||||||
|       int faredge = 0; |       int faredge = 0; | ||||||
|       for(int i=0; i<sc; i++) { |       for(int i=0; i<cellcount; i++) { | ||||||
|         auto &p1 = cells[i]; |         auto &p1 = cells[i]; | ||||||
|         for(int j: p1.neid) { |         for(int j: p1.neid) { | ||||||
|           auto &p2 = cells[j]; |           auto &p2 = cells[j]; | ||||||
| @@ -363,7 +373,7 @@ ld scale; | |||||||
|  |  | ||||||
| void compute_geometry() { | void compute_geometry() { | ||||||
|   if(irr::on) { |   if(irr::on) { | ||||||
|     scale = sqrt(isize(cells_of_heptagon) * 1. / sc); |     scale = sqrt(isize(cells_of_heptagon) * 1. / cellcount); | ||||||
|     crossf *= scale; |     crossf *= scale; | ||||||
|     hepvdist *= scale; |     hepvdist *= scale; | ||||||
|     rhexf *= scale; |     rhexf *= scale; | ||||||
| @@ -477,6 +487,28 @@ void link_cell(cell *c, int d) { | |||||||
|  |  | ||||||
| eGeometry orig_geometry; | eGeometry orig_geometry; | ||||||
|  |  | ||||||
|  | void start_game_on_created_map() {     | ||||||
|  |   popScreen(); | ||||||
|  |   for(hrmap *& hm : allmaps) if(hm == base) hm = NULL; | ||||||
|  |   stop_game(); | ||||||
|  |   geometry = orig_geometry; | ||||||
|  |   irr::on = true; | ||||||
|  |   nonbitrunc = true; | ||||||
|  |   gp::on = false; | ||||||
|  |   need_reset_geometry = true; | ||||||
|  |   gridmaking = false; | ||||||
|  |   start_game(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | void cancel_map_creation() { | ||||||
|  |   popScreen(); | ||||||
|  |   gridmaking = false; | ||||||
|  |   stop_game(); | ||||||
|  |   geometry = orig_geometry; | ||||||
|  |   need_reset_geometry = true; | ||||||
|  |   start_game(); | ||||||
|  |   } | ||||||
|  |  | ||||||
| void show_gridmaker() { | void show_gridmaker() { | ||||||
|   cmode = sm::SIDE; |   cmode = sm::SIDE; | ||||||
|   gamescreen(0);   |   gamescreen(0);   | ||||||
| @@ -485,12 +517,12 @@ void show_gridmaker() { | |||||||
|   dialog::add_action([] { |   dialog::add_action([] { | ||||||
|     dialog::editNumber(density, 1, 10, .1, 4, "density", ""); |     dialog::editNumber(density, 1, 10, .1, 4, "density", ""); | ||||||
|     dialog::reaction = [] () { |     dialog::reaction = [] () { | ||||||
|       int s = sc; |       int s = cellcount; | ||||||
|       if(density < 1) density = 1; |       if(density < 1) density = 1; | ||||||
|       sc = int(isize(currentmap->allcells()) * density + .5); |       cellcount = int(isize(currentmap->allcells()) * density + .5); | ||||||
|       printf("density = %lf sc = %d\n", double(density), sc); |       printf("density = %lf cellcount = %d\n", double(density), cellcount); | ||||||
|       if(sc > s) runlevel = 1; |       if(cellcount > s) runlevel = 1; | ||||||
|       if(sc < s) runlevel = 0; |       if(cellcount < s) runlevel = 0; | ||||||
|       }; |       }; | ||||||
|     }); |     }); | ||||||
|   dialog::addSelItem(XLAT("min edge to median"), fts(quality), 'q'); |   dialog::addSelItem(XLAT("min edge to median"), fts(quality), 'q'); | ||||||
| @@ -506,27 +538,9 @@ void show_gridmaker() { | |||||||
|     dialog::addInfo(status[i]); |     dialog::addInfo(status[i]); | ||||||
|   dialog::addBreak(100); |   dialog::addBreak(100); | ||||||
|   dialog::addSelItem(XLAT("activate"), XLAT(runlevel == 10 ? "ready" : "wait..."), 'f'); |   dialog::addSelItem(XLAT("activate"), XLAT(runlevel == 10 ? "ready" : "wait..."), 'f'); | ||||||
|   if(runlevel == 10) dialog::add_action([] { |   if(runlevel == 10) dialog::add_action(start_game_on_created_map); | ||||||
|     popScreen(); |  | ||||||
|     for(hrmap *& hm : allmaps) if(hm == base) hm = NULL; |  | ||||||
|     stop_game(); |  | ||||||
|     geometry = orig_geometry; |  | ||||||
|     irr::on = true; |  | ||||||
|     nonbitrunc = true; |  | ||||||
|     gp::on = false; |  | ||||||
|     need_reset_geometry = true; |  | ||||||
|     gridmaking = false; |  | ||||||
|     start_game(); |  | ||||||
|     }); |  | ||||||
|   dialog::addItem(XLAT("cancel"), 'c'); |   dialog::addItem(XLAT("cancel"), 'c'); | ||||||
|   dialog::add_action([] { |   dialog::add_action(cancel_map_creation); | ||||||
|     gridmaking = false; |  | ||||||
|     stop_game(); |  | ||||||
|     geometry = orig_geometry; |  | ||||||
|     need_reset_geometry = true; |  | ||||||
|     start_game(); |  | ||||||
|     popScreen(); |  | ||||||
|     }); |  | ||||||
|   dialog::display(); |   dialog::display(); | ||||||
|   keyhandler = [] (int sym, int uni) { |   keyhandler = [] (int sym, int uni) { | ||||||
|     dialog::handleNavigation(sym, uni); |     dialog::handleNavigation(sym, uni); | ||||||
| @@ -554,13 +568,23 @@ void visual_creator() { | |||||||
|   gp::on = false; |   gp::on = false; | ||||||
|   need_reset_geometry = true; |   need_reset_geometry = true; | ||||||
|   start_game(); |   start_game(); | ||||||
|  |   if(base) delete base; | ||||||
|   base = currentmap;  |   base = currentmap;  | ||||||
|   drawthemap(); |   drawthemap(); | ||||||
|   sc = int(isize(base->allcells()) * density + .5); |   cellcount = int(isize(base->allcells()) * density + .5); | ||||||
|   pushScreen(show_gridmaker); |   pushScreen(show_gridmaker); | ||||||
|   runlevel = 0; |   runlevel = 0; | ||||||
|   gridmaking = true; |   gridmaking = true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | void auto_creator() { | ||||||
|  |   int cc = cellcount; | ||||||
|  |   visual_creator(); | ||||||
|  |   cellcount = cc; density = cc / isize(base->allcells()); | ||||||
|  |   printf("Creating the irregular map automatically...\n"); | ||||||
|  |   while(runlevel < 10) step(1000); | ||||||
|  |   start_game_on_created_map(); | ||||||
|  |   } | ||||||
|    |    | ||||||
| int readArgs() { | int readArgs() { | ||||||
|   using namespace arg; |   using namespace arg; | ||||||
| @@ -577,9 +601,9 @@ int readArgs() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
| unsigned char density_code() { | unsigned char density_code() { | ||||||
|   if(sc < 128) return sc; |   if(cellcount < 128) return cellcount; | ||||||
|   else { |   else { | ||||||
|     int t = 127, a = sc; |     int t = 127, a = cellcount; | ||||||
|     while(a > 127) a = a * 9/10, t++; |     while(a > 127) a = a * 9/10, t++; | ||||||
|     return t; |     return t; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -300,7 +300,7 @@ bool havesave = true; | |||||||
|  |  | ||||||
| #if CAP_SAVE | #if CAP_SAVE | ||||||
| #define MAXBOX 500 | #define MAXBOX 500 | ||||||
| #define POSSCORE 344 // update this when new boxes are added! | #define POSSCORE 346 // update this when new boxes are added! | ||||||
|  |  | ||||||
| struct score { | struct score { | ||||||
|   string ver; |   string ver; | ||||||
| @@ -693,6 +693,9 @@ void applyBoxes() { | |||||||
|   applyBoxBool(gp::on); |   applyBoxBool(gp::on); | ||||||
|   applyBox(gp::param.first); |   applyBox(gp::param.first); | ||||||
|   applyBox(gp::param.second); |   applyBox(gp::param.second); | ||||||
|  |    | ||||||
|  |   applyBoxBool(irr::on); | ||||||
|  |   applyBox(irr::cellcount); | ||||||
|  |  | ||||||
|   if(POSSCORE != boxid) printf("ERROR: %d boxes\n", boxid); |   if(POSSCORE != boxid) printf("ERROR: %d boxes\n", boxid); | ||||||
|   } |   } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue