improved CA simulator

This commit is contained in:
Zeno Rogue 2019-12-07 11:12:46 +01:00
parent 0b385dd7f4
commit 17cd694952
4 changed files with 36 additions and 18 deletions

View File

@ -3239,13 +3239,23 @@ namespace prairie {
EX namespace ca { EX namespace ca {
EX ld prob = .2; EX ld prob = .2;
string carule[8][2]; static const int MAX_NEIGHBOR = 60; /* may be larger than MAX_EDGE due to mineadj */
string carule[MAX_NEIGHBOR][2];
EX eWall wlive = waFloorA;
// you can also do -mineadj
EX string fillup(string s) {
while(isize(s) < MAX_NEIGHBOR) s += '0';
return s;
}
EX void init() { EX void init() {
// hexagonal variant of Game of Life, as suggested by Wikipedia // hexagonal variant of Game of Life, as suggested by Wikipedia
for(int i=0; i<8; i++) for(int i=0; i<MAX_NEIGHBOR; i++)
carule[i][0] = "00100000", carule[i][0] = fillup("00100"),
carule[i][1] = "00011000"; carule[i][1] = fillup("00011");
} }
#if CAP_COMMANDLINE #if CAP_COMMANDLINE
@ -3255,22 +3265,25 @@ EX namespace ca {
shift(); prob = argf(); shift(); prob = argf();
return 0; return 0;
} }
if(argis("-calive")) {
shift(); wlive = eWall(argi());
return 0;
}
if(args()[0] != '-') return 1; if(args()[0] != '-') return 1;
if(args()[1] != 'c') return 1; if(args()[1] != 'c') return 1;
int livedead = args()[2] - '0'; int livedead = args()[2] - '0';
if(livedead < 0 || livedead > 1) return 1; if(livedead < 0 || livedead > 1) return 1;
int nei = -1; int nei = -1;
if(args()[3]) { if(args()[3]) {
nei = args()[3] - '0'; nei = atoi(argcs()+3);
if(nei < 0 || nei > 7) return 1; if(nei < 0 || nei >= MAX_NEIGHBOR) return 1;
if(args()[4]) return 1;
} }
shift(); shift();
string s = args(); s += "00000000"; string s = args();
if(nei == -1) for(int i=0; i<8; i++) if(nei == -1) for(int i=0; i<MAX_NEIGHBOR; i++)
carule[i][livedead] = s; carule[i][livedead] = fillup(s);
else else
carule[nei][livedead] = s; carule[nei][livedead] = fillup(s);
return 0; return 0;
} }
@ -3282,20 +3295,23 @@ EX namespace ca {
vector<cell*>& allcells = currentmap->allcells(); vector<cell*>& allcells = currentmap->allcells();
int dcs = isize(allcells); int dcs = isize(allcells);
std::vector<bool> willlive(dcs); std::vector<bool> willlive(dcs);
int old = 0, xold = 0;
for(int i=0; i<dcs; i++) { for(int i=0; i<dcs; i++) {
cell *c = allcells[i]; cell *c = allcells[i];
if(c->land != laCA) return; if(c->land != laCA) return;
int nei = 0, live = 0; int nei = 0, live = 0;
forCellEx(c2, c) if(c2->land == laCA) { for(cell *c2: adj_minefield_cells(c)) {
nei++; if(c2->wall == waFloorA) live++; nei++; if(c2->wall == wlive) live++;
} }
int welive = 0; if(c->wall == waFloorA) welive++; int welive = 0; if(c->wall == wlive) welive++;
willlive[i] = carule[nei][welive][live] == '1'; willlive[i] = carule[nei][welive][live] == '1';
old += welive, xold += live;
} }
for(int i=0; i<dcs; i++) { for(int i=0; i<dcs; i++) {
cell *c = allcells[i]; cell *c = allcells[i];
c->wall = willlive[i] ? waFloorA : waNone; c->wall = willlive[i] ? wlive : waNone;
} }
println(hlog, tie(dcs, old, xold));
} }
EX } EX }

View File

@ -750,7 +750,7 @@ EX void showEuclideanMenu() {
}); });
} }
if(specialland == laMinefield && geometry_has_alt_mine_rule()) { if(among(specialland, laMinefield, laCA) && geometry_has_alt_mine_rule()) {
dialog::addSelItem(XLAT("mine adjacency rule"), XLAT(mine_adjacency_rule ? "vertex" : WDIM == 3 ? "face" : "edge"), 'M'); dialog::addSelItem(XLAT("mine adjacency rule"), XLAT(mine_adjacency_rule ? "vertex" : WDIM == 3 ? "face" : "edge"), 'M');
dialog::add_action([] { dialog::add_action([] {
stop_game(); stop_game();

View File

@ -706,8 +706,10 @@ EX string generateHelpForLand(eLand l) {
s += "\n\n" + XLAT(lv.msg); s += "\n\n" + XLAT(lv.msg);
#if !ISMOBILE #if !ISMOBILE
if(l == laCA) if(l == laCA) {
s += XLAT("\n\nOption -mineadj 1 can be added for Moore neighborhoods.");
s += XLAT("\n\nHint: use 'm' to toggle cells quickly"); s += XLAT("\n\nHint: use 'm' to toggle cells quickly");
}
#endif #endif
return s; return s;

View File

@ -981,7 +981,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
case laCA: case laCA:
if(fargen) if(fargen)
c->wall = (hrand(1000000) < ca::prob * 1000000) ? waFloorA : waNone; c->wall = (hrand(1000000) < ca::prob * 1000000) ? ca::wlive : waNone;
break; break;
case laLivefjord: case laLivefjord: