diff --git a/hyper.h b/hyper.h index d30bcae1..fe827a5b 100644 --- a/hyper.h +++ b/hyper.h @@ -674,6 +674,7 @@ string XLAT(string x); // translate the sentence x string XLATN(string x); // translate the sentence x string cts(char c); // character to string string its(int i); // int to string +string itsh8(int i); // int to string (8 hex digits) // a random integer from [0..i), generated by the game's main generator // we want the same world to be generated if the seed is the same. For this purpose, @@ -4652,6 +4653,23 @@ template void print(hstream& hs, const C& c, con template void println(hstream& hs, const CS&... cs) { print(hs, cs...); hs.write_char('\n'); } +inline string spaced(int i) { return its(i); } +inline string spaced(color_t col) { return itsh8(col); } +inline string spaced(const string& s) { return s; } +inline string spaced(ld x) { return fts(x, 10); } +template string spaced_of(T a[], int q) { string s = spaced(a[0]); for(int i=1; i string spaced(const array& a) { return spaced_of(&a[0], isize(a)); } +template string spaced(const C& c, const C1& c1, const CS&... cs) { return spaced(c) + " " + spaced(c1, cs...); } + +bool scan(fhstream& hs, int&); +bool scan(fhstream& hs, ld&); +bool scan(fhstream& hs, string&); +bool scan(fhstream& hs, color_t& c); +template bool scan(fhstream& hs, C& c, C1& c1, CS&... cs) { return scan(hs, c) && scan(hs, c1, cs...); } + +string scanline(fhstream& hs); +template T scan(fhstream& hs) { T t {}; scan(hs, t); return t; } + // copied from: https://stackoverflow.com/questions/16387354/template-tuple-calling-a-function-on-each-element namespace detail @@ -4681,6 +4699,7 @@ void for_each_in_tuple(std::tuple const& t, F f) inline void print(hstream& hs, const string& s) { hs.write_chars(s.c_str(), isize(s)); } inline void print(hstream& hs, int i) { print(hs, its(i)); } inline void print(hstream& hs, ld x) { print(hs, fts(x)); } +inline void print(hstream& hs, color_t col) { print(hs, itsh8(col)); } template void print(hstream& hs, const walker& w) { print(hs, "[", w.at, "/", w.spin, "/", w.mirrored, "]"); } diff --git a/irregular.cpp b/irregular.cpp index 61df385a..01c1c4b6 100644 --- a/irregular.cpp +++ b/irregular.cpp @@ -812,36 +812,35 @@ void start_game_on_created_map() { } bool save_map(const string& fname) { - FILE *f = fopen(fname.c_str(), "wt"); - if(!f) return false; + fhstream f(fname, "wt"); + if(!f.f) return false; auto& all = base->allcells(); int origcells = 0; for(cellinfo& ci: cells) if(ci.generation == 0) origcells++; - fprintf(f, "%d %d %d\n", geometry, isize(all), origcells); + println(f, spaced(int(geometry), isize(all), origcells)); for(auto h: all) { origcells = 0; for(auto i: cells_of_heptagon[h->master]) if(cells[i].generation == 0) origcells++; - fprintf(f, "%d\n", origcells); + println(f, origcells); for(auto i: cells_of_heptagon[h->master]) if(cells[i].generation == 0) { auto &ci = cells[i]; - fprintf(f, "%lf %lf %lf\n", double(ci.p[0]), double(ci.p[1]), double(ci.p[GDIM])); + println(f, spaced(ci.p[0], ci.p[1], ci.p[GDIM])); } } - fclose(f); return true; } bool load_map(const string &fname) { - FILE *f = fopen(fname.c_str(), "rt"); - if(!f) return false; + fhstream f(fname, "rt"); + if(!f.f) return false; auto& all = base->allcells(); int g, sa; - ignore(fscanf(f, "%d %d %d\n", &g, &sa, &cellcount)); + scan(f, g, sa, cellcount); if(sa != isize(all) || g != geometry) { printf("bad parameters\n"); addMessage(XLAT("bad format or bad map geometry")); return false; } density = cellcount * 1. / isize(all); @@ -849,20 +848,19 @@ bool load_map(const string &fname) { for(auto h: all) { int q = 0; - ignore(fscanf(f, "%d\n", &q)); + scan(f, q); if(q < 0 || q > cellcount) { runlevel = 0; return false; } while(q--) { cells.emplace_back(); cellinfo& s = cells.back(); s.patterndir = -1; double a, b, c; - ignore(fscanf(f, "%lf%lf%lf", &a, &b, &c)); + scan(f, a, b, c); s.p = hpxyz(a, b, c); for(auto c0: all) s.relmatrices[c0] = calc_relative_matrix(c0, h, s.p); s.owner = h; } } - fclose(f); make_cells_of_heptagon(); runlevel = 2; diff --git a/mapeditor.cpp b/mapeditor.cpp index 58c1108f..34fe4a35 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -1622,19 +1622,13 @@ namespace mapeditor { if(uni == COLORKEY) dsCur->color = colortouse; } - void writeHyperpoint(FILE *f, hyperpoint h) { - for(int i=0; i= 0xA0A0) { int tg, wp; int nt; - hr::ignore(fscanf(f, "%d%d%d%d\n", &tg, &nt, &wp, &patterns::subpattern_flags)); + scan(f, tg, nt, wp, patterns::subpattern_flags); patterns::whichPattern = patterns::ePattern(wp); set_geometry(eGeometry(tg)); set_variation(eVariation(nt)); @@ -1670,9 +1664,10 @@ namespace mapeditor { } while(true) { - int i, j, l, sym, rots, color, siz; - err = fscanf(f, "%d%d%d%d%d%x%d", &i, &j, &l, &sym, &rots, &color, &siz); - if(i == -1 || err < 6) break; + int i, j, l, sym, rots, siz; + color_t color; + if(!scan(f, i, j, l, sym, rots, color, siz)) break; + if(i == -1) break; if(siz < 0 || siz > 1000) break; if(i >= 4) { @@ -1683,19 +1678,18 @@ namespace mapeditor { initShape(i, j); usershapelayer& ds(usershapes[i][j]->d[l]); - if(VERNUM_HEX >= 0xA608) { double z; err = fscanf(f, "%lf", &z); ds.zlevel = z; } + if(vernum >= 0xA608) scan(f, ds.zlevel); ds.shift = readHyperpoint(f); ds.spin = readHyperpoint(f); ds.list.clear(); for(int i=0; i= 0xA0A0) - fprintf(f, "%d %d %d %d\n", geometry, int(variation), patterns::whichPattern, patterns::subpattern_flags); + println(f, spaced(geometry, int(variation), patterns::whichPattern, patterns::subpattern_flags)); for(int i=0; id[l].list)) { usershapelayer& ds(us->d[l]); - fprintf(f, "\n%d %d %d %d %d %6x %d\n", - i, usp.first, l, ds.sym, ds.rots, ds.color, int(isize(ds.list))); - fprintf(f, "\n%lf", double(ds.zlevel)); + println(f, spaced(i, usp.first, l, ds.sym, ds.rots, ds.color, int(isize(ds.list)))); + print(f, spaced(ds.zlevel), " "); writeHyperpoint(f, ds.shift); writeHyperpoint(f, ds.spin); - fprintf(f,"\n"); + println(f); for(int i=0; id[l].list)) { usershapelayer& ds(us->d[l]); - printf("// %d %d %d [%06X %lf]\n", i, usp.first, l, ds.color, double(ds.zlevel)); - printf(" ID, %d, %d, ", us->d[l].rots, us->d[l].sym?2:1); + println(hlog, spaced("//", i, usp.first, l, "[", ds.color, double(ds.zlevel), "]")); + print(hlog, " ID, ", us->d[l].rots, ", ", us->d[l].sym?2:1, ", "); for(int i=0; id[l].list); i++) { - for(int d=0; dd[l].list[i][d])); - printf(" "); + for(int d=0; dd[l].list[i][d]), ", "); + print(hlog, " "); } - printf("\n"); + println(hlog); } } } diff --git a/netgen.cpp b/netgen.cpp index 132df5fa..55b6031d 100644 --- a/netgen.cpp +++ b/netgen.cpp @@ -134,28 +134,25 @@ namespace hr { namespace netgen { void loadData() { - FILE *f = fopen("papermodeldata.txt", "rt"); - if(!f) return; + fhstream f("papermodeldata.txt", "rt"); + if(!f.f) return; - int err = fscanf(f, "%d %d %d %d %d %d %d %lf %d\n\n", - &CELLS, &SX, &SY, &PX, &PY, &SCALE, &BASE, &el, &created); - if(err != 9) { fclose(f); return; } + if(!scan(f, CELLS, SX, SY, PX, PY, SCALE, BASE, el, created)) return; loaded = true; - if(!created) { fclose(f); return; } + if(!created) return; - for(int i=0; i