mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 22:12:59 +00:00 
			
		
		
		
	rogueviz:: added random walk
This commit is contained in:
		
							
								
								
									
										238
									
								
								rogueviz/random-walk.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								rogueviz/random-walk.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,238 @@ | ||||
| #include "rogueviz.h" | ||||
| #include <iostream> | ||||
| #include <thread> | ||||
|  | ||||
| namespace rogueviz { | ||||
|  | ||||
| namespace rwalk { | ||||
|  | ||||
| struct line { | ||||
|   hyperpoint a; | ||||
|   hyperpoint b; | ||||
|   color_t col; | ||||
|   int timestamp; | ||||
|   }; | ||||
|  | ||||
| struct rwalker { | ||||
|   cell *at; | ||||
|   transmatrix ori; | ||||
|   transmatrix T; | ||||
|   color_t col; | ||||
|   int simulated; | ||||
|   }; | ||||
|  | ||||
| map<cell*, vector<line> > drawn; | ||||
|  | ||||
| vector<rwalker> walkers; | ||||
|  | ||||
| ld total_time; | ||||
|  | ||||
| bool draw_rwalk(cell *c, const shiftmatrix& V) { | ||||
|  | ||||
|   vid.linewidth *= 3; | ||||
|   for(auto p: drawn[c]) if(p.timestamp <= total_time) | ||||
|     queueline(V * p.a, V * p.b, p.col, 0); | ||||
|   vid.linewidth /= 3; | ||||
|  | ||||
|   return false; | ||||
|   } | ||||
|  | ||||
| bool do_walkers; | ||||
|  | ||||
| bool in_video; | ||||
|  | ||||
| ld sim_speed = 5; | ||||
|  | ||||
| int branch_each = 50000; | ||||
|  | ||||
| ld step_size = 0.02; | ||||
|  | ||||
| bool advance_walkers(int delta) { | ||||
|   if(!do_walkers) return false; | ||||
|  | ||||
|   if(walkers.empty()) { | ||||
|     walkers.emplace_back(rwalker{currentmap->gamestart(), Id, Id, 0xFFFFFFFF, 0}); | ||||
|     } | ||||
|    | ||||
|   if(in_video) { | ||||
|     ld t = history::phase / (isize(history::v) - 1); | ||||
|     total_time = walkers[0].simulated * t; | ||||
|     } | ||||
|   else { | ||||
|     total_time += delta * sim_speed; | ||||
|     } | ||||
|  | ||||
|   for(int i=0; i<isize(walkers); i++) { | ||||
|     if(heptdistance(walkers[i].at, centerover) > 7) | ||||
|       continue; | ||||
|     while(walkers[i].simulated < total_time) { | ||||
|       walkers[i].simulated++; | ||||
|       if(rand() % branch_each == 0) { | ||||
|         walkers.push_back(walkers[i]); | ||||
|         walkers.back().col = hrandpos() | 0x808080FF; | ||||
|         walkers[i].col = hrandpos() | 0x808080FF; | ||||
|         } | ||||
|       auto& w = walkers[i]; | ||||
|       hyperpoint h = tC0(w.T); | ||||
|       if(WDIM == 2) { | ||||
|         w.T = w.T * xspinpush(randd() * 2 * M_PI, step_size); | ||||
|         } | ||||
|       else { | ||||
|         hyperpoint dir = random_spin() * xtangent(step_size); | ||||
|         apply_parallel_transport(w.T, w.ori, dir);         | ||||
|         } | ||||
|       fixmatrix(w.T); | ||||
|       hyperpoint h1 = tC0(w.T); | ||||
|       drawn[w.at].emplace_back(line{h, h1, w.col, w.simulated}); | ||||
|       virtualRebase(w.at, w.T); | ||||
|       w.simulated++; | ||||
|       } | ||||
|     } | ||||
|   // centerover = walkers[0].at; | ||||
|   // View = inverse(walkers[0].T); | ||||
|   // setdist(centerover, 0, nullptr); | ||||
|   return false; | ||||
|   } | ||||
|  | ||||
| int args() { | ||||
|   using namespace arg; | ||||
|             | ||||
|   if(0) ; | ||||
|   else if(argis("-rwalk")) { | ||||
|     do_walkers = true; | ||||
|     } | ||||
|   else if(argis("-rwparam")) { | ||||
|     shift_arg_formula(sim_speed); | ||||
|     shift_arg_formula(step_size); | ||||
|     shift(); branch_each = argi(); | ||||
|     } | ||||
|   else if(argis("-rwalk-off")) { | ||||
|     do_walkers = false; | ||||
|     } | ||||
|  | ||||
|   else return 1; | ||||
|   return 0; | ||||
|   } | ||||
|  | ||||
| bool pres_handleKey(int sym, int uni) { | ||||
|   if((cmode & sm::NORMAL)) | ||||
|     if(sym == 'x') { | ||||
|       return true; | ||||
|       } | ||||
|   return false; | ||||
|   } | ||||
|  | ||||
| void show() { | ||||
|   cmode = sm::SIDE | sm::MAYDARK; | ||||
|   gamescreen(0); | ||||
|   dialog::init(XLAT("random walk"), 0xFFFFFFFF, 150, 0); | ||||
|  | ||||
|   dialog::addSelItem("step size", fts(step_size), 'd'); | ||||
|   dialog::add_action([]() { | ||||
|     dialog::editNumber(step_size, 1e-3, 10, 0.1, 1e-2, "step size", ""); | ||||
|     dialog::scaleLog(); | ||||
|     }); | ||||
|  | ||||
|   dialog::addSelItem("steps per millisecond", fts(sim_speed), 'v'); | ||||
|   dialog::add_action([]() { | ||||
|     dialog::editNumber(sim_speed, 0, 10, 0.1, 5, "steps per millisecond", ""); | ||||
|     }); | ||||
|  | ||||
|   dialog::addSelItem("steps per branch", its(branch_each), 'b'); | ||||
|   dialog::add_action([]() { | ||||
|     dialog::editNumber(branch_each, 100, 1000000, 0.1, 50000, "steps per branch", ""); | ||||
|     dialog::scaleLog(); | ||||
|     }); | ||||
|  | ||||
|   dialog::addBoolItem("create an animation", in_video, 'a'); | ||||
|   dialog::add_action([]() { | ||||
|     in_video = !in_video; | ||||
|     if(!in_video) { | ||||
|       total_time = walkers[0].simulated; | ||||
|       history::on = false; | ||||
|       } | ||||
|     if(in_video) { | ||||
|       history::create(currentmap->gamestart(), walkers[0].at, walkers[0].T); | ||||
|       models::rotation = rand() % 360; | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|   dialog::addBack(); | ||||
|   dialog::display();     | ||||
|   } | ||||
|  | ||||
| void o_key(o_funcs& v) { | ||||
|   if(do_walkers) v.push_back(named_dialog("random walk", show)); | ||||
|   } | ||||
|  | ||||
| string cap = "non-Euclidean random walk/"; | ||||
|  | ||||
| void rw_slide(vector<tour::slide>& v, string title, string desc, reaction_t t) { | ||||
|   using namespace tour; | ||||
|   v.push_back( | ||||
|     tour::slide{cap + title, 18, LEGAL::NONE | QUICKGEO, desc,  | ||||
|     | ||||
|   [t] (presmode mode) { | ||||
|     setCanvas(mode, '0'); | ||||
|  | ||||
|     if(mode == pmStart) { | ||||
|       stop_game(); | ||||
|       start_game(); | ||||
|       do_walkers = true; | ||||
|       } | ||||
|  | ||||
|     if(mode == pmStop) { | ||||
|       do_walkers = false; | ||||
|       } | ||||
|     }} | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|  | ||||
| auto msc =  | ||||
|   addHook(hooks_args, 100, args) | ||||
| + addHook(hooks_drawcell, 100, draw_rwalk) | ||||
| + addHook(shmup::hooks_turn, 100, advance_walkers) | ||||
| + addHook(hooks_handleKey, 0, pres_handleKey) | ||||
| + addHook(hooks_o_key, 80, o_key) | ||||
| + addHook(hooks_clearmemory, 40, [] () { | ||||
|     drawn.clear(); | ||||
|     walkers.clear(); | ||||
|     }) | ||||
| + addHook(rvtour::hooks_build_rvtour, 180, [] (vector<tour::slide>& v) { | ||||
|   v.push_back(tour::slide{ | ||||
|     cap+"random walk visualization", 10, tour::LEGAL::NONE | tour::QUICKSKIP, | ||||
|     "Here we see random walk in various geometries.\n" | ||||
|     , | ||||
|     [] (tour::presmode mode) {} | ||||
|     }); | ||||
|   rw_slide(v, "Euclidean plane", "In Euclidean plane, the random walk always returns to the neighborhood of the starting point with probability 1.", [] { | ||||
|     set_geometry(gEuclid); | ||||
|     set_variation(eVariation::pure); | ||||
|     sim_speed = 5; | ||||
|     branch_each = 0; | ||||
|     step_size = 0.02; | ||||
|     }); | ||||
|   rw_slide(v, "Euclidean 3-space",  | ||||
|     "However, in Euclidean 3-space, it does not return.", [] { | ||||
|     set_geometry(gCubeTiling); | ||||
|     set_variation(eVariation::pure); | ||||
|     sim_speed = 5; | ||||
|     branch_each = 0; | ||||
|     step_size = 0.02; | ||||
|     }); | ||||
|   rw_slide(v, "Hyperbolic geometry", "In H2, it does not return, even if we branch from time to time.", [] { | ||||
|     set_geometry(gNormal); | ||||
|     set_variation(eVariation::bitruncated); | ||||
|     sim_speed = 5; | ||||
|     branch_each = 50000; | ||||
|     step_size = 0.02; | ||||
|     }); | ||||
|   /* it works in other geometries too -- exercise left for the reader */ | ||||
|   }); | ||||
|  | ||||
| // {4,5} : 10 6 works | ||||
|  | ||||
| } | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue